UNPKG

zonder

Version:

Ergonomic multi-chain indexing framework with dual runtime support for Ponder and Envio.

91 lines (90 loc) 2.99 kB
import { factory } from 'ponder'; import { resolveStartBlock } from '../zonder/resolveStartBlock.js'; export function buildChains(chains) { return Object.fromEntries(Object.entries(chains).map(([chainName, chain]) => { const rpcKey = `PONDER_RPC_URL_${chain.id}`; const rpcValue = process.env[rpcKey]; if (!rpcValue) { throw new Error(`${rpcKey} is not set`); } const rpc = rpcValue.split(','); if (rpc.length === 0) { throw new Error(`${rpcKey} is empty`); } rpc.forEach((r) => { try { new URL(r); } catch (e) { throw new Error(`${rpcKey} contains invalid URL: "${r}"`); } }); return [ chainName, { id: chain.id, rpc, }, ]; })); } export function buildContractChainAddressConfig(config, chainName, contract) { const { factoryDeployed, addresses } = config; const address = addresses[chainName][contract]; const factoryConfig = factoryDeployed?.[contract]; if (!!address && !!factoryConfig) { throw new Error(`Contract ${String(contract)} is configured both as a singleton and a factory on chain ${String(chainName)}`); } if (address) { return { address }; } if (factoryConfig) { const { event, parameter, deployedBy } = factoryConfig; const factoryAddress = addresses[chainName][deployedBy]; if (!factoryAddress) { // Factory not configured on this chain - factory-deployed contract can't exist here return null; } return { address: factory({ address: factoryAddress, event, parameter, }), }; } // Contract not configured on this chain - this is acceptable return null; } export function buildContractConfig(config, contract) { const { chains, contracts, startBlocks } = config; const ponderChain = Object.fromEntries(Object.entries(chains) .map(([chainName]) => { const addressConfig = buildContractChainAddressConfig(config, chainName, contract); if (!addressConfig) { // Contract not configured on this chain, skip it return null; } return [ chainName, { ...addressConfig, startBlock: resolveStartBlock(startBlocks, chainName, String(contract)), }, ]; }) .filter((entry) => entry !== null)); return { abi: contracts[contract], chain: ponderChain, }; } export function buildConfig(config) { return { chains: buildChains(config.chains), contracts: Object.fromEntries(Object.keys(config.contracts).map((contract) => [ contract, buildContractConfig(config, contract), ])), }; }