import { createAction } from '@reduxjs/toolkit' export interface Call { address: string callData: string gasRequired?: number } const ADDRESS_REGEX = /^0x[a-fA-F0-9]{40}$/ const LOWER_HEX_REGEX = /^0x[a-f0-9]*$/ export function toCallKey(call: Call): string { if (!ADDRESS_REGEX.test(call.address)) { throw new Error(`Invalid address: ${call.address}`) } if (!LOWER_HEX_REGEX.test(call.callData)) { throw new Error(`Invalid hex: ${call.callData}`) } let key = `${call.address}-${call.callData}` if (call.gasRequired) { if (!Number.isSafeInteger(call.gasRequired)) { throw new Error(`Invalid number: ${call.gasRequired}`) } key += `-${call.gasRequired}` } return key } export function parseCallKey(callKey: string): Call { const pcs = callKey.split('-') if (![2, 3].includes(pcs.length)) { throw new Error(`Invalid call key: ${callKey}`) } return { address: pcs[0], callData: pcs[1], ...(pcs[2] ? { gasRequired: Number.parseInt(pcs[2]) } : {}), } } export interface ListenerOptions { // how often this data should be fetched, by default 1 readonly blocksPerFetch?: number } export const addMulticallListeners = createAction<{ chainId: number; calls: Call[]; options?: ListenerOptions }>( 'gmulticall/addMulticallListeners' ) export const removeMulticallListeners = createAction<{ chainId: number; calls: Call[]; options?: ListenerOptions }>( 'gmulticall/removeMulticallListeners' ) export const fetchingMulticallResults = createAction<{ chainId: number; calls: Call[]; fetchingBlockNumber: number }>( 'gmulticall/fetchingMulticallResults' ) export const errorFetchingMulticallResults = createAction<{ chainId: number calls: Call[] fetchingBlockNumber: number }>('gmulticall/errorFetchingMulticallResults') export const updateMulticallResults = createAction<{ chainId: number blockNumber: number results: { [callKey: string]: string | null } }>('gmulticall/updateMulticallResults')