This repository has been archived by the owner on Mar 15, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
near: add ability to backfill, refactor common code
- Loading branch information
Showing
4 changed files
with
178 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { sleep } from '@wormhole-foundation/wormhole-monitor-common'; | ||
import { INITIAL_DEPLOYMENT_BLOCK_BY_CHAIN } from '@wormhole-foundation/wormhole-monitor-common/src/consts'; | ||
import axios from 'axios'; | ||
import { connect } from 'near-api-js'; | ||
import { Provider } from 'near-api-js/lib/providers'; | ||
import { BlockResult } from 'near-api-js/lib/providers/provider'; | ||
import { NEAR_CONTRACT } from '../src/consts'; | ||
import { storeVaasByBlock } from '../src/databases/utils'; | ||
import { | ||
NearExplorerTransactionRequestParams, | ||
NearExplorerTransactionResponse, | ||
} from '../src/types/near'; | ||
import { NearWatcher } from '../src/watchers/NearWatcher'; | ||
|
||
// This script exists because NEAR RPC nodes do not support querying blocks older than 5 epochs | ||
// (~2.5 days): https://docs.near.org/api/rpc/setup#querying-historical-data. This script fetches | ||
// all transactions for the core bridge contract from the NEAR Explorer backend API and then uses | ||
// the archival RPC node to backfill messages in the given range. | ||
|
||
const BATCH_SIZE = 1000; | ||
const NEAR_ARCHIVE_RPC = 'https://archival-rpc.mainnet.near.org'; | ||
const NEAR_EXPLORER_TRANSACTION_URL = | ||
'https://backend-mainnet-1713.onrender.com/trpc/transaction.listByAccountId'; | ||
|
||
const getArchivalRpcProvider = async (): Promise<Provider> => { | ||
const connection = await connect({ nodeUrl: NEAR_ARCHIVE_RPC, networkId: 'mainnet' }); | ||
const provider = connection.connection.provider; | ||
|
||
// sleep for 100ms between each request (do not parallelize calls with Promise.all) | ||
for (const propName of Object.getOwnPropertyNames(Object.getPrototypeOf(provider))) { | ||
if (typeof (provider as any)[propName] === 'function') { | ||
(provider as any)[propName] = async (...args: any[]) => { | ||
await sleep(100); // respect rate limits: 600req/min | ||
return (provider as any)[propName](...args); | ||
}; | ||
} | ||
} | ||
|
||
return provider; | ||
}; | ||
|
||
const getExplorerTransactionsUrl = (timestamp: number, batchSize: number): string => { | ||
const params: NearExplorerTransactionRequestParams = { | ||
accountId: NEAR_CONTRACT, | ||
limit: batchSize, | ||
cursor: { | ||
timestamp, | ||
indexInChunk: 0, | ||
}, | ||
}; | ||
return `${NEAR_EXPLORER_TRANSACTION_URL}?batch=1&input={"0":${JSON.stringify(params)}}`; | ||
}; | ||
|
||
const backfillNear = async (fromBlock: number, toBlock: number): Promise<void> => { | ||
const watcher = new NearWatcher(); | ||
fromBlock = Math.max(fromBlock, Number(INITIAL_DEPLOYMENT_BLOCK_BY_CHAIN[watcher.chain] ?? 0)); | ||
if (fromBlock > toBlock) return; | ||
|
||
// use archival rpc to fetch specified transactions | ||
const provider = await getArchivalRpcProvider(); | ||
|
||
// fetch all transactions for core bridge contract from explorer: | ||
// https://github.com/near/near-explorer/blob/beead42ba2a91ad8d2ac3323c29b1148186eec98/backend/src/router/transaction/list.ts#L127 | ||
const timestamp = (await provider.block(toBlock)).header.timestamp; | ||
const transactions = ( | ||
(await axios.get(getExplorerTransactionsUrl(timestamp, BATCH_SIZE))) | ||
.data as NearExplorerTransactionResponse | ||
)[0].result.data.items.filter((tx) => tx.status === 'success'); | ||
|
||
// filter out transactions that are not in the given block range | ||
const blocks: BlockResult[] = []; | ||
const blockHashes = [...new Set(transactions.map((tx) => tx.blockHash))]; | ||
blockHashes.forEach(async (hash) => { | ||
const block = await provider.block(hash); | ||
if (block.header.height >= fromBlock && block.header.height <= toBlock) { | ||
blocks.push(block); | ||
} | ||
}); | ||
|
||
watcher.provider = provider; | ||
const vaasByBlock = await watcher.getMessagesFromBlockResults(blocks); | ||
await storeVaasByBlock(watcher.chain, vaasByBlock); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// https://nomicon.io/Standards/EventsFormat | ||
export type EventLog = { | ||
event: string; | ||
standard: string; | ||
data?: unknown; | ||
version?: string; // this is supposed to exist but is missing in WH logs | ||
}; | ||
|
||
export type WormholePublishEventLog = { | ||
standard: 'wormhole'; | ||
event: 'publish'; | ||
data: string; | ||
nonce: number; | ||
emitter: string; | ||
seq: number; | ||
block: number; | ||
}; | ||
|
||
export const isWormholePublishEventLog = (log: EventLog): log is WormholePublishEventLog => { | ||
return log.standard === 'wormhole' && log.event === 'publish'; | ||
}; | ||
|
||
export type NearExplorerTransactionResponse = { | ||
id: string | null; | ||
result: { | ||
type: string; | ||
data: { | ||
items: NearExplorerTransaction[]; | ||
}; | ||
}; | ||
}[]; | ||
|
||
export type NearExplorerTransaction = { | ||
hash: string; | ||
signerId: string; | ||
receiverId: string; | ||
blockHash: string; | ||
blockTimestamp: number; | ||
actions: { | ||
kind: string; | ||
args: { | ||
methodName: string; | ||
args: string; | ||
gas: number; | ||
deposit: string; | ||
}; | ||
}[]; | ||
status: string; | ||
}; | ||
|
||
export type NearExplorerTransactionRequestParams = { | ||
accountId: string; | ||
limit: number; | ||
cursor?: { | ||
timestamp: number; // paginate with timestamp | ||
indexInChunk: number; | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters