-
Notifications
You must be signed in to change notification settings - Fork 203
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
perf: load withdrawal tx history by priority #2128
Changes from 23 commits
4588f8c
fb8e92f
57d4a29
b153022
565ad23
edcd366
5992894
fc97519
e9c8f56
b158c14
a33a55f
92e66ec
924e0a4
e15683a
75d9823
3941f7b
6067f9c
43a9f82
aeaa9a9
33b2240
b45452b
57ef6b9
7bcda1f
82c13c1
751be46
8ec6b17
a7deab2
5cbb81c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,8 +2,6 @@ import { Provider, BlockTag } from '@ethersproject/providers' | |
import { Erc20Bridger, EventArgs } from '@arbitrum/sdk' | ||
import { WithdrawalInitiatedEvent } from '@arbitrum/sdk/dist/lib/abi/L2ArbitrumGateway' | ||
|
||
import { getNonce } from '../AddressUtils' | ||
|
||
function dedupeEvents( | ||
events: (EventArgs<WithdrawalInitiatedEvent> & { | ||
txHash: string | ||
|
@@ -12,6 +10,15 @@ function dedupeEvents( | |
return [...new Map(events.map(item => [item.txHash, item])).values()] | ||
} | ||
|
||
export type FetchTokenWithdrawalsFromEventLogsParams = { | ||
sender?: string | ||
receiver?: string | ||
fromBlock: BlockTag | ||
toBlock: BlockTag | ||
l2Provider: Provider | ||
l2GatewayAddresses?: string[] | ||
} | ||
|
||
/** | ||
* Fetches initiated token withdrawals from event logs in range of [fromBlock, toBlock]. | ||
* | ||
|
@@ -30,22 +37,13 @@ export async function fetchTokenWithdrawalsFromEventLogs({ | |
toBlock, | ||
l2Provider, | ||
l2GatewayAddresses = [] | ||
}: { | ||
sender?: string | ||
receiver?: string | ||
fromBlock: BlockTag | ||
toBlock: BlockTag | ||
l2Provider: Provider | ||
l2GatewayAddresses?: string[] | ||
}) { | ||
Comment on lines
-33
to
-40
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. extracted into type |
||
}: FetchTokenWithdrawalsFromEventLogsParams) { | ||
const erc20Bridger = await Erc20Bridger.fromProvider(l2Provider) | ||
const promises: ReturnType<Erc20Bridger['getWithdrawalEvents']>[] = [] | ||
|
||
const senderNonce = await getNonce(sender, { provider: l2Provider }) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. moved to |
||
|
||
l2GatewayAddresses.forEach(gatewayAddress => { | ||
// funds sent by this address | ||
if (sender && senderNonce > 0) { | ||
if (sender) { | ||
promises.push( | ||
erc20Bridger.getWithdrawalEvents( | ||
l2Provider, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
import { constants } from 'ethers' | ||
import { Provider, BlockTag } from '@ethersproject/providers' | ||
import { Erc20Bridger, getArbitrumNetwork } from '@arbitrum/sdk' | ||
|
||
import { | ||
fetchTokenWithdrawalsFromEventLogs, | ||
FetchTokenWithdrawalsFromEventLogsParams | ||
} from './fetchTokenWithdrawalsFromEventLogs' | ||
import { getNonce } from '../AddressUtils' | ||
import { fetchL2Gateways } from '../fetchL2Gateways' | ||
|
||
function wait(ms: number) { | ||
return new Promise(resolve => setTimeout(resolve, ms)) | ||
} | ||
|
||
async function getGateways(provider: Provider): Promise<{ | ||
standardGateway: string | ||
wethGateway: string | ||
customGateway: string | ||
otherGateways: string[] | ||
}> { | ||
const network = await getArbitrumNetwork(provider) | ||
|
||
const standardGateway = network.tokenBridge?.childErc20Gateway | ||
const customGateway = network.tokenBridge?.childCustomGateway | ||
const wethGateway = network.tokenBridge?.childWethGateway | ||
const otherGateways = await fetchL2Gateways(provider) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Outside the scope of the current PR, but since it touches this code, we might want to rename The function can be called There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will be taken up in next PR. |
||
|
||
return { | ||
standardGateway: standardGateway ?? constants.AddressZero, | ||
wethGateway: wethGateway ?? constants.AddressZero, | ||
customGateway: customGateway ?? constants.AddressZero, | ||
otherGateways | ||
} | ||
} | ||
|
||
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T | ||
brtkx marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
type TokenWithdrawalQuery = { | ||
params: FetchTokenWithdrawalsFromEventLogsParams | ||
priority: number | ||
} | ||
|
||
export type FetchTokenWithdrawalsFromEventLogsSequentiallyParams = { | ||
sender?: string | ||
receiver?: string | ||
provider: Provider | ||
fromBlock?: BlockTag | ||
toBlock?: BlockTag | ||
/** | ||
* How long to delay in-between queries of different priority. | ||
*/ | ||
delayMs?: number | ||
} | ||
|
||
export type FetchTokenWithdrawalsFromEventLogsSequentiallyResult = | ||
UnwrapPromise<ReturnType<Erc20Bridger['getWithdrawalEvents']>> | ||
|
||
export async function fetchTokenWithdrawalsFromEventLogsSequentially({ | ||
sender, | ||
receiver, | ||
provider, | ||
fromBlock = 0, | ||
toBlock = 'latest', | ||
delayMs = 2_000 | ||
}: FetchTokenWithdrawalsFromEventLogsSequentiallyParams): Promise<FetchTokenWithdrawalsFromEventLogsSequentiallyResult> { | ||
// keep track of priority; increment as queries are added | ||
let priority = 0 | ||
// keep track of queries | ||
const queries: TokenWithdrawalQuery[] = [] | ||
|
||
// helper function to reuse common params | ||
function buildQueryParams({ | ||
sender, | ||
receiver, | ||
gateways = [] | ||
}: { | ||
sender?: string | ||
receiver?: string | ||
gateways?: string[] | ||
}): TokenWithdrawalQuery['params'] { | ||
return { | ||
sender, | ||
receiver, | ||
fromBlock, | ||
toBlock, | ||
l2Provider: provider, | ||
l2GatewayAddresses: gateways | ||
} | ||
} | ||
|
||
// for sanitizing, adding queries and incrementing priority | ||
function addQuery(params: TokenWithdrawalQuery['params']) { | ||
const gateways = params.l2GatewayAddresses ?? [] | ||
const gatewaysSanitized = gateways.filter(g => g !== constants.AddressZero) | ||
|
||
if (gatewaysSanitized.length === 0) { | ||
return | ||
} | ||
|
||
queries.push({ | ||
params: { ...params, l2GatewayAddresses: gatewaysSanitized }, | ||
priority: ++priority | ||
}) | ||
} | ||
|
||
const gateways = await getGateways(provider) | ||
const senderNonce = await getNonce(sender, { provider }) | ||
|
||
// sender queries; only add if nonce > 0 | ||
if (senderNonce > 0) { | ||
addQuery(buildQueryParams({ sender, gateways: [gateways.standardGateway] })) | ||
addQuery(buildQueryParams({ sender, gateways: [gateways.wethGateway] })) | ||
addQuery(buildQueryParams({ sender, gateways: [gateways.customGateway] })) | ||
addQuery(buildQueryParams({ sender, gateways: gateways.otherGateways })) | ||
} | ||
|
||
// receiver queries | ||
addQuery(buildQueryParams({ receiver, gateways: [gateways.standardGateway] })) | ||
addQuery(buildQueryParams({ receiver, gateways: [gateways.wethGateway] })) | ||
addQuery(buildQueryParams({ receiver, gateways: [gateways.customGateway] })) | ||
addQuery(buildQueryParams({ receiver, gateways: gateways.otherGateways })) | ||
|
||
// for iterating through all priorities in the while loop below | ||
let currentPriority = 1 | ||
|
||
// final result | ||
const result: FetchTokenWithdrawalsFromEventLogsSequentiallyResult = [] | ||
|
||
while (currentPriority <= priority) { | ||
const currentPriorityQueries = queries.filter( | ||
query => query.priority === currentPriority | ||
) | ||
|
||
const currentPriorityResults = await Promise.all( | ||
currentPriorityQueries.map(query => | ||
fetchTokenWithdrawalsFromEventLogs(query.params) | ||
) | ||
) | ||
|
||
currentPriorityResults.forEach(r => { | ||
result.push(...r) | ||
}) | ||
|
||
await wait(delayMs) | ||
|
||
currentPriority++ | ||
} | ||
|
||
return result | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this function will now be used only to keep track of custom custom gateways