import { timeoutFetch } from 'zutils/utils/net.util' import { retry } from 'zutils/utils/promise.util' const DEFAULT_TIMEOUT = 30000 const request = async (url: string, options: any) => { options.timeout = options.timeout || DEFAULT_TIMEOUT return timeoutFetch(url, options, options.timeout) } const requestChain = async (rpc: string, method: string, params: any) => { const data = { id: Date.now(), jsonrpc: '2.0', method, params, } return request(rpc, { method: 'POST', headers: { 'Content-Type': 'application/json; charset=utf-8', }, body: JSON.stringify(data), }).then(res => res.json()) } export const ethBlockNumber = async (rpc: string) => { return requestChain(rpc, 'eth_blockNumber', []) } export const retryEthBlockNumber = async (rpc: string) => { const res = await retry(() => ethBlockNumber(rpc), { maxRetries: 3, whitelistErrors: [] }) if (res.error) { throw new Error(res.error.message) } return res } export const retryEthGetBlockByNumber = async (rpc: string, blockNumber: string, all = true) => { const res = await retry(() => ethGetBlockByNumber(rpc, blockNumber, all), { maxRetries: 3, whitelistErrors: [] }) if (res.error) { throw new Error(res.error.message) } return res } export const ethGetBlockByNumber = async (rpc: string, blockNumber: string, all = true) => { return requestChain(rpc, 'eth_getBlockByNumber', [blockNumber, all]) } export const ethGetLogs = async (rpc: string, params: any) => { return requestChain(rpc, 'eth_getLogs', params) } export const _batchEthBlocks = async (rpc: string, blockNumber: number, amount: number) => { let batch = [] for (let i = 0; i < amount; i++) { batch.push({ jsonrpc: '2.0', method: 'eth_getBlockByNumber', params: ['0x' + (blockNumber + i).toString(16), true], id: blockNumber + i, }) } return request(rpc, { method: 'POST', headers: { 'Content-Type': 'application/json; charset=utf-8', }, body: JSON.stringify(batch), }).then(res => res.json()) } export const batchEthBlocks = async (rpc: string, blockNumbers: number[]) => { let batch = [] for (let blockNum of blockNumbers) { batch.push({ jsonrpc: '2.0', method: 'eth_getBlockByNumber', params: ['0x' + blockNum.toString(16), true], id: blockNum, }) } return request(rpc, { method: 'POST', headers: { 'Content-Type': 'application/json; charset=utf-8', }, body: JSON.stringify(batch), }).then(res => res.json()) } export const batchEthLogs = async (rpc: string, params: any) => { return request(rpc, { method: 'POST', headers: { 'Content-Type': 'application/json; charset=utf-8', }, body: JSON.stringify(params), }).then(res => res.json()) }