Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 46 additions & 2 deletions codegenerator/cli/npm/envio/src/TestIndexer.res
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,20 @@ type testIndexerState = {
mutable processChanges: array<unknown>,
}

// Cast Internal.entity back to DynamicContractRegistry.t
external castFromDcRegistry: Internal.entity => InternalTable.DynamicContractRegistry.t =
"%identity"

// Convert DynamicContractRegistry.t to Internal.indexingContract
let toIndexingContract = (
dc: InternalTable.DynamicContractRegistry.t,
): Internal.indexingContract => {
address: dc.contractAddress,
contractName: dc.contractName,
startBlock: dc.registeringEventBlockNumber,
registrationBlock: Some(dc.registeringEventBlockNumber),
}

let handleLoadByIds = (
state: testIndexerState,
~tableName: string,
Expand Down Expand Up @@ -220,6 +234,7 @@ let handleWriteBatch = (
let makeInitialState = (
~config: Config.t,
~processConfigChains: Js.Dict.t<chainConfig>,
~dynamicContractsByChain: dict<array<Internal.indexingContract>>,
): Persistence.initialState => {
let chainKeys = processConfigChains->Js.Dict.keys
let chains = chainKeys->Array.map(chainIdStr => {
Expand All @@ -231,6 +246,10 @@ let makeInitialState = (
}

let processChainConfig = processConfigChains->Js.Dict.unsafeGet(chainIdStr)
let dynamicContracts =
dynamicContractsByChain
->Js.Dict.get(chainIdStr)
->Option.getWithDefault([])
{
Persistence.id: chainId,
startBlock: processChainConfig.startBlock,
Expand All @@ -241,7 +260,7 @@ let makeInitialState = (
numEventsProcessed: 0,
firstEventBlockNumber: None,
timestampCaughtUpToHeadOrEndblock: None,
dynamicContracts: [],
dynamicContracts,
}
})

Expand Down Expand Up @@ -344,8 +363,33 @@ let makeCreateTestIndexer = (
// Reset processChanges for this run
state.processChanges = []

// Extract dynamic contracts from state.entities for each chain
let dynamicContractsByChain: dict<array<Internal.indexingContract>> = Js.Dict.empty()
switch state.entities->Js.Dict.get(InternalTable.DynamicContractRegistry.name) {
| Some(dcDict) =>
dcDict
->Js.Dict.values
->Array.forEach(entity => {
let dc = entity->castFromDcRegistry
let chainIdStr = dc.chainId->Int.toString
let contracts = switch dynamicContractsByChain->Js.Dict.get(chainIdStr) {
| Some(arr) => arr
| None =>
let arr = []
dynamicContractsByChain->Js.Dict.set(chainIdStr, arr)
arr
}
contracts->Array.push(dc->toIndexingContract)->ignore
})
| None => ()
}

// Create initialState from processConfig chains
let initialState = makeInitialState(~config, ~processConfigChains=chains)
let initialState = makeInitialState(
~config,
~processConfigChains=chains,
~dynamicContractsByChain,
)

Promise.make((resolve, reject) => {
// Include initialState in workerData
Expand Down
2 changes: 0 additions & 2 deletions codegenerator/cli/npm/envio/src/sources/EvmChain.res
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ let makeSources = (
| Some(endpointUrl) => [
HyperSyncSource.make({
chain,
contracts,
endpointUrl,
allEventSignatures,
eventRouter,
Expand All @@ -78,7 +77,6 @@ let makeSources = (
RpcSource.make({
chain,
sourceFor,
contracts,
syncConfig: getSyncConfig(syncConfig->Option.getWithDefault({})),
url,
eventRouter,
Expand Down
2 changes: 0 additions & 2 deletions codegenerator/cli/npm/envio/src/sources/HyperSyncSource.res
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@ let memoGetSelectionConfig = (~chain) => {
}

type options = {
contracts: array<Internal.evmContractConfig>,
chain: ChainMap.Chain.t,
endpointUrl: string,
allEventSignatures: array<string>,
Expand All @@ -160,7 +159,6 @@ type options = {

let make = (
{
contracts,
chain,
endpointUrl,
allEventSignatures,
Expand Down
153 changes: 72 additions & 81 deletions codegenerator/cli/npm/envio/src/sources/RpcSource.res
Original file line number Diff line number Diff line change
Expand Up @@ -468,23 +468,13 @@ type options = {
syncConfig: Config.sourceSync,
url: string,
chain: ChainMap.Chain.t,
contracts: array<Internal.evmContractConfig>,
eventRouter: EventRouter.t<Internal.evmEventConfig>,
allEventSignatures: array<string>,
lowercaseAddresses: bool,
}

let make = (
{
sourceFor,
syncConfig,
url,
chain,
contracts,
eventRouter,
allEventSignatures,
lowercaseAddresses,
}: options,
{sourceFor, syncConfig, url, chain, eventRouter, allEventSignatures, lowercaseAddresses}: options,
): t => {
let urlHost = switch sanitizeUrl(url) {
| None =>
Expand Down Expand Up @@ -688,81 +678,82 @@ let make = (
)
}

let parsedQueueItems = await logs
->Array.zip(parsedEvents)
->Array.keepMap(((
log: Ethers.log,
maybeDecodedEvent: Js.Nullable.t<HyperSyncClient.Decoder.decodedEvent>,
)) => {
let topic0 = log.topics[0]->Option.getWithDefault("0x0"->EvmTypes.Hex.fromStringUnsafe)
let routedAddress = if lowercaseAddresses {
log.address->Address.Evm.fromAddressLowercaseOrThrow
} else {
log.address
}
let parsedQueueItems =
await logs
->Array.zip(parsedEvents)
->Array.keepMap(((
log: Ethers.log,
maybeDecodedEvent: Js.Nullable.t<HyperSyncClient.Decoder.decodedEvent>,
)) => {
let topic0 = log.topics[0]->Option.getWithDefault("0x0"->EvmTypes.Hex.fromStringUnsafe)
let routedAddress = if lowercaseAddresses {
log.address->Address.Evm.fromAddressLowercaseOrThrow
} else {
log.address
}

switch eventRouter->EventRouter.get(
~tag=EventRouter.getEvmEventId(
~sighash=topic0->EvmTypes.Hex.toString,
~topicCount=log.topics->Array.length,
),
~indexingContracts,
~contractAddress=routedAddress,
~blockNumber=log.blockNumber,
) {
| None => None
| Some(eventConfig) =>
switch maybeDecodedEvent {
| Js.Nullable.Value(decoded) =>
Some(
(
async () => {
let (block, transaction) = try await Promise.all2((
log->getEventBlockOrThrow,
log->getEventTransactionOrThrow(
~transactionSchema=eventConfig.transactionSchema,
),
)) catch {
| exn =>
raise(
Source.GetItemsError(
FailedGettingFieldSelection({
message: "Failed getting selected fields. Please double-check your RPC provider returns correct data.",
exn,
blockNumber: log.blockNumber,
logIndex: log.logIndex,
}),
switch eventRouter->EventRouter.get(
~tag=EventRouter.getEvmEventId(
~sighash=topic0->EvmTypes.Hex.toString,
~topicCount=log.topics->Array.length,
),
~indexingContracts,
~contractAddress=routedAddress,
~blockNumber=log.blockNumber,
) {
| None => None
| Some(eventConfig) =>
switch maybeDecodedEvent {
| Js.Nullable.Value(decoded) =>
Some(
(
async () => {
let (block, transaction) = try await Promise.all2((
log->getEventBlockOrThrow,
log->getEventTransactionOrThrow(
~transactionSchema=eventConfig.transactionSchema,
),
)
}
)) catch {
| exn =>
raise(
Source.GetItemsError(
FailedGettingFieldSelection({
message: "Failed getting selected fields. Please double-check your RPC provider returns correct data.",
exn,
blockNumber: log.blockNumber,
logIndex: log.logIndex,
}),
),
)
}

Internal.Event({
eventConfig: (eventConfig :> Internal.eventConfig),
timestamp: block.timestamp,
blockNumber: block.number,
chain,
logIndex: log.logIndex,
event: {
chainId: chain->ChainMap.Chain.toChainId,
params: decoded->eventConfig.convertHyperSyncEventArgs,
transaction,
block: block->(
Utils.magic: Ethers.JsonRpcProvider.block => Internal.eventBlock
),
srcAddress: routedAddress,
Internal.Event({
eventConfig: (eventConfig :> Internal.eventConfig),
timestamp: block.timestamp,
blockNumber: block.number,
chain,
logIndex: log.logIndex,
}->Internal.fromGenericEvent,
})
}
)(),
)
| Js.Nullable.Null
| Js.Nullable.Undefined =>
None
event: {
chainId: chain->ChainMap.Chain.toChainId,
params: decoded->eventConfig.convertHyperSyncEventArgs,
transaction,
block: block->(
Utils.magic: Ethers.JsonRpcProvider.block => Internal.eventBlock
),
srcAddress: routedAddress,
logIndex: log.logIndex,
}->Internal.fromGenericEvent,
})
}
)(),
)
| Js.Nullable.Null
| Js.Nullable.Undefined =>
None
}
}
}
})
->Promise.all
})
->Promise.all

let optFirstBlockParent = await firstBlockParentPromise

Expand Down
Original file line number Diff line number Diff line change
@@ -1,47 +1,23 @@
# yaml-language-server: $schema=./node_modules/envio/evm.schema.json
name: Factory Contract
description: Example indexer for indexing factory-deployed contracts
name: envio-indexer
description: Envio Indexer showcase for the Factory Contract feature
contracts:
- name: UniswapV3Factory
events:
- event: PoolCreated(address indexed token0, address indexed token1, uint24 indexed fee, int24 tickSpacing, address pool)
- name: UniswapV3Pool
events:
- event: Swap(address indexed sender, address indexed recipient, int256 amount0, int256 amount1, uint160 sqrtPriceX96, uint128 liquidity, int24 tick)

chains:
- id: 1 # Ethereum Mainnet
start_block: 0
contracts:
- name: UniswapV3Factory
address:
- 0x1F98431c8aD98523631AE4a59f267346ea31F984
- name: UniswapV3Pool
- id: 130 # Unichain Mainnet
start_block: 0
contracts:
- name: UniswapV3Factory
address:
- 0x1F98400000000000000000000000000000000003
- name: UniswapV3Pool
- id: 42161 # Arbitrum Mainnet
start_block: 0
contracts:
- name: UniswapV3Factory
address:
- 0x1F98431c8aD98523631AE4a59f267346ea31F984
- name: UniswapV3Pool
- id: 10 # Optimism Mainnet
start_block: 0
contracts:
- name: UniswapV3Factory
address:
- 0x1F98431c8aD98523631AE4a59f267346ea31F984
- name: UniswapV3Pool
- id: 8453 # Base Mainnet
start_block: 0
contracts:
- name: UniswapV3Factory
address:
- 0x33128a8fC17869897dcE68Ed026d694621f6FDfD
- name: UniswapV3Pool
Loading
Loading