├── .cursor
└── rules
│ ├── rescript-rule.mdc
│ └── rescript.mdc
├── .github
├── Dockerfile
├── Dockerfile.typescript
├── ISSUE_TEMPLATE
│ └── bug_report.md
├── changelog.json
└── workflows
│ ├── build_and_test.yml
│ ├── cache-clean-guide.md
│ ├── codegen_diff.yml
│ ├── release.yml
│ ├── templates_integration_test.yml
│ └── update_codegen_on_main.yaml
├── .gitignore
├── .vscode
└── settings.json
├── CONTRIBUTING.md
├── README.md
├── codegenerator
├── .gitignore
├── Cargo.lock
├── Cargo.toml
├── cli
│ ├── .idea
│ │ ├── .gitignore
│ │ ├── codegenerator.iml
│ │ ├── modules.xml
│ │ └── vcs.xml
│ ├── Cargo.toml
│ ├── CommandLineHelp.md
│ ├── Makefile
│ ├── README.md
│ ├── npm
│ │ ├── envio
│ │ │ ├── .gitignore
│ │ │ ├── bin.js
│ │ │ ├── evm.schema.json
│ │ │ ├── fuel.schema.json
│ │ │ ├── index.d.ts
│ │ │ ├── index.js
│ │ │ ├── local-bin.mjs
│ │ │ ├── package.json
│ │ │ ├── package.json.tmpl
│ │ │ ├── rescript.json
│ │ │ └── src
│ │ │ │ ├── Address.gen.ts
│ │ │ │ ├── Address.res
│ │ │ │ ├── ChainMap.res
│ │ │ │ ├── ChainMap.resi
│ │ │ │ ├── Envio.gen.ts
│ │ │ │ ├── Envio.res
│ │ │ │ ├── ErrorHandling.res
│ │ │ │ ├── EventUtils.res
│ │ │ │ ├── EvmTypes.res
│ │ │ │ ├── FetchState.res
│ │ │ │ ├── Hasura.res
│ │ │ │ ├── Internal.gen.ts
│ │ │ │ ├── Internal.res
│ │ │ │ ├── LazyLoader.res
│ │ │ │ ├── LoadManager.res
│ │ │ │ ├── LogSelection.res
│ │ │ │ ├── Logging.res
│ │ │ │ ├── Persistence.res
│ │ │ │ ├── PgStorage.res
│ │ │ │ ├── Prometheus.res
│ │ │ │ ├── ReorgDetection.res
│ │ │ │ ├── Throttler.res
│ │ │ │ ├── Throttler.resi
│ │ │ │ ├── Time.res
│ │ │ │ ├── TopicFilter.res
│ │ │ │ ├── Types.ts
│ │ │ │ ├── Utils.res
│ │ │ │ ├── bindings
│ │ │ │ ├── BigDecimal.gen.ts
│ │ │ │ ├── BigDecimal.res
│ │ │ │ ├── BigInt.res
│ │ │ │ ├── Ethers.gen.ts
│ │ │ │ ├── Ethers.res
│ │ │ │ ├── Express.res
│ │ │ │ ├── Hrtime.res
│ │ │ │ ├── Hrtime.resi
│ │ │ │ ├── NodeJs.res
│ │ │ │ ├── Pino.gen.ts
│ │ │ │ ├── Pino.res
│ │ │ │ ├── Postgres.res
│ │ │ │ ├── PromClient.res
│ │ │ │ ├── Promise.res
│ │ │ │ ├── SDSL.res
│ │ │ │ └── Viem.res
│ │ │ │ ├── db
│ │ │ │ ├── EntityHistory.res
│ │ │ │ ├── Schema.res
│ │ │ │ └── Table.res
│ │ │ │ ├── sources
│ │ │ │ ├── Fuel.res
│ │ │ │ ├── HyperFuel.res
│ │ │ │ ├── HyperFuel.resi
│ │ │ │ ├── HyperFuelClient.res
│ │ │ │ ├── HyperSync.res
│ │ │ │ ├── HyperSync.resi
│ │ │ │ ├── HyperSyncClient.gen.ts
│ │ │ │ ├── HyperSyncClient.res
│ │ │ │ ├── HyperSyncJsonApi.res
│ │ │ │ ├── Rpc.res
│ │ │ │ ├── Source.res
│ │ │ │ ├── SourceManager.res
│ │ │ │ ├── SourceManager.resi
│ │ │ │ └── vendored-fuel-abi-coder.js
│ │ │ │ └── vendored
│ │ │ │ ├── Rest.res
│ │ │ │ └── Rest.resi
│ │ └── package.json.tmpl
│ ├── src
│ │ ├── cli_args
│ │ │ ├── clap_definitions.rs
│ │ │ ├── init_config.rs
│ │ │ ├── interactive_init
│ │ │ │ ├── evm_prompts.rs
│ │ │ │ ├── fuel_prompts.rs
│ │ │ │ ├── inquire_helpers.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── shared_prompts.rs
│ │ │ │ └── validation.rs
│ │ │ └── mod.rs
│ │ ├── commands.rs
│ │ ├── config_parsing
│ │ │ ├── chain_helpers.rs
│ │ │ ├── contract_import
│ │ │ │ ├── converters.rs
│ │ │ │ └── mod.rs
│ │ │ ├── entity_parsing.rs
│ │ │ ├── event_parsing.rs
│ │ │ ├── graph_migration
│ │ │ │ └── mod.rs
│ │ │ ├── human_config.rs
│ │ │ ├── hypersync_endpoints.rs
│ │ │ ├── mod.rs
│ │ │ ├── postgres_types.rs
│ │ │ ├── system_config.rs
│ │ │ └── validation.rs
│ │ ├── constants.rs
│ │ ├── evm
│ │ │ ├── abi.rs
│ │ │ ├── address.rs
│ │ │ └── mod.rs
│ │ ├── executor
│ │ │ ├── codegen.rs
│ │ │ ├── dev.rs
│ │ │ ├── init.rs
│ │ │ ├── local.rs
│ │ │ └── mod.rs
│ │ ├── fuel
│ │ │ ├── abi.rs
│ │ │ ├── address.rs
│ │ │ └── mod.rs
│ │ ├── hbs_templating
│ │ │ ├── codegen_templates.rs
│ │ │ ├── contract_import_templates.rs
│ │ │ ├── hbs_dir_generator.rs
│ │ │ ├── init_templates.rs
│ │ │ └── mod.rs
│ │ ├── lib.rs
│ │ ├── main.rs
│ │ ├── persisted_state
│ │ │ ├── db.rs
│ │ │ ├── hash_string.rs
│ │ │ └── mod.rs
│ │ ├── project_paths
│ │ │ ├── handler_paths.rs
│ │ │ ├── mod.rs
│ │ │ └── path_utils.rs
│ │ ├── rescript_types.rs
│ │ ├── scripts
│ │ │ ├── mod.rs
│ │ │ └── print_missing_networks.rs
│ │ ├── service_health.rs
│ │ ├── template_dirs.rs
│ │ └── utils
│ │ │ ├── file_system.rs
│ │ │ ├── mod.rs
│ │ │ ├── normalized_list.rs
│ │ │ ├── text.rs
│ │ │ └── unique_hashmap.rs
│ ├── tarpaulin.toml
│ ├── templates
│ │ ├── dynamic
│ │ │ ├── codegen
│ │ │ │ ├── index.d.ts.hbs
│ │ │ │ ├── package.json.hbs
│ │ │ │ ├── persisted_state.envio.json.hbs
│ │ │ │ └── src
│ │ │ │ │ ├── ConfigYAML.res.hbs
│ │ │ │ │ ├── ContextEnv.res.hbs
│ │ │ │ │ ├── Handlers.res.hbs
│ │ │ │ │ ├── Path.res.hbs
│ │ │ │ │ ├── RegisterHandlers.res.hbs
│ │ │ │ │ ├── TestHelpers.res.hbs
│ │ │ │ │ ├── TestHelpers_MockDb.res.hbs
│ │ │ │ │ ├── Types.res.hbs
│ │ │ │ │ ├── Types.ts.hbs
│ │ │ │ │ └── db
│ │ │ │ │ ├── Entities.res.hbs
│ │ │ │ │ └── Enums.res.hbs
│ │ │ ├── contract_import_templates
│ │ │ │ ├── javascript
│ │ │ │ │ ├── src
│ │ │ │ │ │ └── EventHandlers.js.hbs
│ │ │ │ │ └── test
│ │ │ │ │ │ └── Test.js.hbs
│ │ │ │ ├── rescript
│ │ │ │ │ ├── src
│ │ │ │ │ │ └── EventHandlers.res.hbs
│ │ │ │ │ └── test
│ │ │ │ │ │ └── Test.res.hbs
│ │ │ │ ├── shared
│ │ │ │ │ ├── .env.hbs
│ │ │ │ │ └── schema.graphql.hbs
│ │ │ │ └── typescript
│ │ │ │ │ ├── src
│ │ │ │ │ └── EventHandlers.ts.hbs
│ │ │ │ │ └── test
│ │ │ │ │ └── Test.ts.hbs
│ │ │ ├── init_templates
│ │ │ │ └── shared
│ │ │ │ │ ├── .env.hbs
│ │ │ │ │ └── package.json.hbs
│ │ │ └── subgraph_migration_templates
│ │ │ │ ├── javascript
│ │ │ │ └── src
│ │ │ │ │ └── EventHandlers.js.hbs
│ │ │ │ ├── rescript
│ │ │ │ └── src
│ │ │ │ │ └── EventHandlers.res.hbs
│ │ │ │ └── typescript
│ │ │ │ └── src
│ │ │ │ └── EventHandlers.ts.hbs
│ │ └── static
│ │ │ ├── blank_template
│ │ │ ├── javascript
│ │ │ │ └── .gitkeep
│ │ │ ├── rescript
│ │ │ │ ├── rescript.json
│ │ │ │ └── test
│ │ │ │ │ └── Test.res
│ │ │ ├── shared
│ │ │ │ ├── .env.example
│ │ │ │ ├── .gitignore
│ │ │ │ └── README.md
│ │ │ └── typescript
│ │ │ │ └── tsconfig.json
│ │ │ ├── codegen
│ │ │ ├── .gitignore
│ │ │ ├── .npmrc
│ │ │ ├── LICENSE.md
│ │ │ ├── docker-compose.yaml
│ │ │ ├── index.js
│ │ │ ├── rescript.json
│ │ │ └── src
│ │ │ │ ├── Benchmark.res
│ │ │ │ ├── Config.res
│ │ │ │ ├── Env.res
│ │ │ │ ├── EventProcessing.res
│ │ │ │ ├── EventRouter.res
│ │ │ │ ├── GqlDbCustomTypes.res
│ │ │ │ ├── IO.res
│ │ │ │ ├── InMemoryStore.res
│ │ │ │ ├── InMemoryTable.res
│ │ │ │ ├── Index.res
│ │ │ │ ├── Js.shim.ts
│ │ │ │ ├── LoadLayer.res
│ │ │ │ ├── LoadLayer.resi
│ │ │ │ ├── PersistedState.res
│ │ │ │ ├── TableIndices.res
│ │ │ │ ├── TestHelpers_MockAddresses.res
│ │ │ │ ├── UserContext.res
│ │ │ │ ├── bindings
│ │ │ │ ├── Dotenv.res
│ │ │ │ ├── Ethers.gen.ts
│ │ │ │ ├── Lodash.res
│ │ │ │ ├── OpaqueTypes.ts
│ │ │ │ ├── RescriptMocha.res
│ │ │ │ ├── Yargs.res
│ │ │ │ └── vendored-lodash-fns.js
│ │ │ │ ├── db
│ │ │ │ ├── Db.res
│ │ │ │ ├── DbFunctions.res
│ │ │ │ ├── DbFunctionsEntities.res
│ │ │ │ ├── DbFunctionsImplementation.js
│ │ │ │ ├── Migrations.res
│ │ │ │ └── TablesStatic.res
│ │ │ │ ├── eventFetching
│ │ │ │ ├── ChainFetcher.res
│ │ │ │ ├── ChainManager.res
│ │ │ │ ├── NetworkSources.res
│ │ │ │ ├── hyperfuel
│ │ │ │ │ └── HyperFuelSource.res
│ │ │ │ ├── hypersync
│ │ │ │ │ └── HyperSyncSource.res
│ │ │ │ └── rpc
│ │ │ │ │ └── RpcSource.res
│ │ │ │ ├── globalState
│ │ │ │ ├── GlobalState.res
│ │ │ │ ├── GlobalStateManager.res
│ │ │ │ └── GlobalStateManager.resi
│ │ │ │ └── ink
│ │ │ │ ├── EnvioInkApp.res
│ │ │ │ ├── bindings
│ │ │ │ ├── DateFns.res
│ │ │ │ ├── Ink.res
│ │ │ │ └── Style.res
│ │ │ │ └── components
│ │ │ │ ├── BufferedProgressBar.res
│ │ │ │ ├── ChainData.res
│ │ │ │ ├── CustomHooks.res
│ │ │ │ ├── Messages.res
│ │ │ │ └── SyncETA.res
│ │ │ ├── erc20_template
│ │ │ ├── javascript
│ │ │ │ ├── config.yaml
│ │ │ │ ├── src
│ │ │ │ │ └── EventHandlers.js
│ │ │ │ └── test
│ │ │ │ │ └── test.js
│ │ │ ├── rescript
│ │ │ │ ├── config.yaml
│ │ │ │ ├── rescript.json
│ │ │ │ ├── src
│ │ │ │ │ ├── EventHandlers.bs.js
│ │ │ │ │ └── EventHandlers.res
│ │ │ │ └── test
│ │ │ │ │ └── Test.res
│ │ │ ├── shared
│ │ │ │ ├── .env.example
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ └── schema.graphql
│ │ │ └── typescript
│ │ │ │ ├── build
│ │ │ │ └── src
│ │ │ │ │ └── EventHandlers.js
│ │ │ │ ├── config.yaml
│ │ │ │ ├── src
│ │ │ │ └── EventHandlers.ts
│ │ │ │ ├── test
│ │ │ │ └── test.ts
│ │ │ │ └── tsconfig.json
│ │ │ ├── greeter_template
│ │ │ ├── javascript
│ │ │ │ ├── README.md
│ │ │ │ ├── config.yaml
│ │ │ │ ├── src
│ │ │ │ │ └── EventHandlers.js
│ │ │ │ └── test
│ │ │ │ │ └── test.js
│ │ │ ├── rescript
│ │ │ │ ├── README.md
│ │ │ │ ├── config.yaml
│ │ │ │ ├── rescript.json
│ │ │ │ ├── src
│ │ │ │ │ └── EventHandlers.res
│ │ │ │ └── test
│ │ │ │ │ └── Test.res
│ │ │ ├── shared
│ │ │ │ ├── .env.example
│ │ │ │ ├── .gitignore
│ │ │ │ ├── abis
│ │ │ │ │ └── greeter-abi.json
│ │ │ │ └── schema.graphql
│ │ │ └── typescript
│ │ │ │ ├── README.md
│ │ │ │ ├── config.yaml
│ │ │ │ ├── src
│ │ │ │ └── EventHandlers.ts
│ │ │ │ ├── test
│ │ │ │ └── test.ts
│ │ │ │ └── tsconfig.json
│ │ │ └── greeteronfuel_template
│ │ │ ├── javascript
│ │ │ ├── README.md
│ │ │ ├── config.yaml
│ │ │ ├── src
│ │ │ │ └── EventHandlers.js
│ │ │ └── test
│ │ │ │ └── test.js
│ │ │ ├── rescript
│ │ │ ├── README.md
│ │ │ ├── config.yaml
│ │ │ ├── rescript.json
│ │ │ ├── src
│ │ │ │ └── EventHandlers.res
│ │ │ └── test
│ │ │ │ └── Test.res
│ │ │ ├── shared
│ │ │ ├── .env.example
│ │ │ ├── .gitignore
│ │ │ ├── abis
│ │ │ │ └── greeter-abi.json
│ │ │ └── schema.graphql
│ │ │ └── typescript
│ │ │ ├── README.md
│ │ │ ├── config.yaml
│ │ │ ├── src
│ │ │ └── EventHandlers.ts
│ │ │ ├── test
│ │ │ └── test.ts
│ │ │ └── tsconfig.json
│ └── test
│ │ ├── abis
│ │ ├── Contract1.json
│ │ ├── Contract2.json
│ │ ├── greeter-abi.json
│ │ └── nested-abi.json
│ │ ├── api_response
│ │ └── GetSourceCodeResponse.json
│ │ ├── configs
│ │ ├── config1.yaml
│ │ ├── config2.yaml
│ │ ├── config3.yaml
│ │ ├── config4.yaml
│ │ ├── config5.yaml
│ │ ├── dynamic-address-config.yaml
│ │ ├── factory-contract-config.yaml
│ │ ├── fuel-config.yaml
│ │ ├── graph-manifest.yaml
│ │ ├── gravatar-with-required-entities.yaml
│ │ ├── invalid-multiple-sync-config.yaml
│ │ ├── nested-abi.yaml
│ │ └── schema.graphql
│ │ └── schemas
│ │ ├── gravatar-schema.graphql
│ │ ├── schema-with-directive.graphql
│ │ └── schema.graphql
└── integration_tests
│ ├── Cargo.toml
│ ├── src
│ ├── hypersync_health.rs
│ └── main.rs
│ └── tests
│ ├── DynamicContracts.js
│ ├── EndblockSuccess.js
│ ├── WildcardUniFactory.js
│ ├── databaseTestHelpers.js
│ ├── evm_Erc20.js
│ ├── evm_Greeter.js
│ ├── fuel_Greeter.js
│ ├── graphqlFetchWithTestCallback.js
│ ├── runAll.sh
│ ├── runSingle.sh
│ ├── testIndexerExits.sh
│ └── test_indexers
│ ├── dynamic_contracts
│ ├── .gitignore
│ ├── config-dynamic-contracts.yaml
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── schema.graphql
│ ├── src
│ │ └── DynamicContractHandlers.ts
│ └── tsconfig.json
│ ├── test_exits
│ ├── .gitignore
│ ├── config-broken.yaml
│ ├── config.yaml
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── schema.graphql
│ ├── src
│ │ ├── BrokenHandler.ts
│ │ ├── DynamicContractHandlers.ts
│ │ └── EventHandler.ts
│ └── tsconfig.json
│ └── wildcard-uni-factory
│ ├── .gitignore
│ ├── README.md
│ ├── config.yaml
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── schema.graphql
│ ├── src
│ └── EventHandlers.ts
│ └── tsconfig.json
├── internal_docs
├── EventFetchers.md
├── EventProcessor.md
├── IndexerStructure.md
└── README.md
├── licenses
├── CLA.md
├── EULA.md
├── LICENSE.md
└── README.md
├── scenarios
├── erc20_multichain_factory
│ ├── .gitignore
│ ├── .mocharc.json
│ ├── README.md
│ ├── config.yaml
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── pnpm-workspace.yaml
│ ├── rescript.json
│ ├── schema.graphql
│ ├── src
│ │ └── EventHandlers.res
│ └── test
│ │ ├── ChainDataHelpers.res
│ │ ├── DbHelpers.res
│ │ ├── DynamicContractRecovery_test.res
│ │ ├── Handler_Test.res
│ │ ├── MockChainData.res
│ │ ├── RollbackDynamicContract_test.res
│ │ ├── RollbackMultichain_test.res
│ │ ├── TestDeleteEntity.res
│ │ └── TestWhereQuery.res
├── fuel_test
│ ├── .env.example
│ ├── .gitignore
│ ├── README.md
│ ├── abis
│ │ ├── all-events-abi.json
│ │ └── greeter-abi.json
│ ├── config.yaml
│ ├── contracts
│ │ ├── all-events
│ │ │ ├── .gitignore
│ │ │ ├── Forc.lock
│ │ │ ├── Forc.toml
│ │ │ └── src
│ │ │ │ └── main.sw
│ │ ├── interaction-tools
│ │ │ ├── .env.example
│ │ │ ├── .gitignore
│ │ │ ├── Cargo.lock
│ │ │ ├── Cargo.toml
│ │ │ └── src
│ │ │ │ └── main.rs
│ │ └── ts-interaction-tools
│ │ │ ├── .env.example
│ │ │ ├── .gitignore
│ │ │ ├── README.md
│ │ │ ├── package.json
│ │ │ ├── src
│ │ │ ├── @types
│ │ │ │ └── env.d.ts
│ │ │ └── deploy.ts
│ │ │ └── tsconfig.json
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── rescript.json
│ ├── schema.graphql
│ ├── src
│ │ ├── AllEventsHandlers.ts
│ │ └── GreeterHandlers.ts
│ ├── test
│ │ ├── HyperFuelSource_test.res
│ │ └── test.ts
│ └── tsconfig.json
├── helpers
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── rescript.json
│ └── src
│ │ ├── ChainMocking.res
│ │ └── Indexer.res
└── test_codegen
│ ├── .gitignore
│ ├── .mocharc.json
│ ├── .npmrc
│ ├── README.md
│ ├── abis
│ ├── NftFactory.json
│ ├── SimpleNft.json
│ └── gravatar-abi.json
│ ├── config.yaml
│ ├── contracts
│ ├── .gitignore
│ ├── README.md
│ ├── artifacts
│ │ └── contracts
│ │ │ ├── GravatarRegistry.sol
│ │ │ └── GravatarRegistry.json
│ │ │ ├── NftFactory.sol
│ │ │ └── NftFactory.json
│ │ │ ├── SimpleNft.sol
│ │ │ └── SimpleNft.json
│ │ │ └── TestEvents.sol
│ │ │ └── TestEvents.json
│ ├── contracts
│ │ ├── GravatarRegistry.sol
│ │ ├── NftFactory.sol
│ │ ├── SimpleNft.sol
│ │ └── TestEvents.sol
│ ├── deploy
│ │ └── deploy.js
│ ├── package.json
│ ├── secretsManager.example.ts
│ └── tasks
│ │ ├── index.js
│ │ ├── newGravatarTask.js
│ │ ├── updateGravatarImageTask.js
│ │ └── updateGravatarNameTask.js
│ ├── hardhat.config.ts
│ ├── package.json
│ ├── pnpm-lock.yaml
│ ├── pnpm-workspace.yaml
│ ├── rescript.json
│ ├── schema.graphql
│ ├── src
│ ├── EventHandlers.res
│ └── EventHandlers.ts
│ ├── test
│ ├── ChainFetcher_test.res
│ ├── ChainManager_test.res
│ ├── Config_test.res
│ ├── CustomSelection_test.res
│ ├── CustomSelection_test.ts
│ ├── E2EEthNode_test.res
│ ├── Encoders_schema_test.res
│ ├── EventFilters_test.res
│ ├── EventHandler_test.ts
│ ├── HyperSyncSource_test.res
│ ├── Integration_ts_helpers.gen.ts
│ ├── Integration_ts_helpers.res
│ ├── LoadLayer_test.res
│ ├── LoadLinkedEntities.res
│ ├── Mock_test.res
│ ├── ReorgDetection_test.res
│ ├── RpcSource_test.res
│ ├── SerDe_Test.res
│ ├── Utils_test.res
│ ├── Viem_test.res
│ ├── __mocks__
│ │ ├── DbStub.res
│ │ ├── MockConfig.res
│ │ ├── MockEntities.res
│ │ └── MockEvents.res
│ ├── entity-column-types-test.ts
│ ├── helpers
│ │ ├── DbHelpers.res
│ │ ├── LiveGravatarTask.res
│ │ ├── Mock.res
│ │ ├── SetupRpcNode.res
│ │ ├── contracts
│ │ │ └── GravatarRegistry.sol
│ │ ├── node-and-contracts.ts
│ │ ├── setupNodeAndContracts.js
│ │ ├── taskLiveGravatarTxs.js
│ │ └── utils.ts
│ ├── integration-raw-events-test.ts
│ ├── lib_tests
│ │ ├── EntityHistory_test.res
│ │ ├── EventRouter_test.res
│ │ ├── FetchState_test.res
│ │ ├── Persistence_test.res
│ │ ├── PgStorage_test.res
│ │ ├── Rpc_Test.res
│ │ ├── SingleOrMultiple_test.res
│ │ ├── SourceManager_test.res
│ │ ├── Table_test.res
│ │ └── Throttler_test.res
│ ├── manual
│ │ ├── LogTesting.res
│ │ └── README.md
│ ├── raw-events-table-migration-test.ts
│ ├── rollback
│ │ ├── ChainDataHelpers.res
│ │ ├── MockChainData.res
│ │ ├── MockChainData_test.res
│ │ └── Rollback_test.res
│ ├── schema_types
│ │ ├── BigDecimal_test.res
│ │ ├── BigDecimal_test_typescript.ts
│ │ └── Timestamp_test.res
│ ├── sql-transaction-test.ts
│ └── topic-hashing-test.ts
│ └── tsconfig.json
└── sync.gif
/.cursor/rules/rescript-rule.mdc:
--------------------------------------------------------------------------------
1 | ---
2 | description:
3 | globs: *.res
4 | alwaysApply: false
5 | ---
6 | Always use ReScript 11 documentation.
7 | Never suggest ReasonML syntax.
--------------------------------------------------------------------------------
/.cursor/rules/rescript.mdc:
--------------------------------------------------------------------------------
1 | ---
2 | description: Rules to let Cursor help you write relevant ReScript code.
3 | globs: *.res,*.resi
4 | alwaysApply: false
5 | ---
6 | - Always use ReScript 11 documentation.
7 | - Never suggest ReasonML syntax.
8 | - Never use `[| item |]` to create an array. Use `[ item ]` instead.
9 | - Must always use `=` for setting value to a field. Use `:=` only for ref values created using `ref` function.
10 |
--------------------------------------------------------------------------------
/.github/Dockerfile:
--------------------------------------------------------------------------------
1 |
2 | #rescript base
3 |
4 | FROM --platform=linux/amd64 node:18.16.1-bookworm-slim
5 | # FROM --platform=linux/amd64 node:20.4.0-bookworm-slim # Testing differen versions for
6 | WORKDIR /app/base-template
7 |
8 | RUN apt-get update
9 | RUN apt-get install -y wget
10 | #install the libssl required by the rust package
11 | RUN wget http://nz2.archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2.19_amd64.deb
12 | RUN dpkg -i libssl1.1_1.1.1f-1ubuntu2.19_amd64.deb
13 |
14 | ENV PNPM_HOME /usr/local/binp
15 | RUN npm install --global pnpm
16 |
17 | ARG ENVIO_VERSION
18 | RUN npm install --global envio@${ENVIO_VERSION}
19 |
20 | ARG COMMIT_HASH_ARG
21 | ENV COMMIT_HASH=${COMMIT_HASH_ARG}
22 |
23 | RUN envio init -d . --name erc20indexer -t erc20 -l rescript
24 |
--------------------------------------------------------------------------------
/.github/Dockerfile.typescript:
--------------------------------------------------------------------------------
1 |
2 | #rescript base
3 |
4 | FROM --platform=linux/amd64 node:18.16.1-bookworm-slim
5 | # FROM --platform=linux/amd64 node:20.4.0-bookworm-slim # Testing differen versions for
6 | WORKDIR /app/base-template
7 |
8 | RUN apt-get update
9 | RUN apt-get install -y wget
10 |
11 | RUN wget http://nz2.archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2.19_amd64.deb
12 | RUN dpkg -i libssl1.1_1.1.1f-1ubuntu2.19_amd64.deb
13 |
14 | ENV PNPM_HOME /usr/local/binp
15 | RUN npm install --global pnpm
16 |
17 | ARG ENVIO_VERSION
18 | RUN npm install --global envio@${ENVIO_VERSION}
19 |
20 | ARG COMMIT_HASH_ARG
21 | ENV COMMIT_HASH=${COMMIT_HASH_ARG}
22 |
23 | RUN envio init -d . --name erc20indexer -t erc20 -l typescript
24 |
25 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 |
16 | E.g.
17 | 1. Go to '...'
18 | 2. Click on '....'
19 | 3. Scroll down to '....'
20 | 4. See error
21 |
22 | **Expected behavior**
23 | A clear and concise description of what you expected to happen.
24 |
25 | **Screenshots**
26 | If applicable, add screenshots to help explain your problem.
27 |
28 | **Local (please complete the following information):**
29 | - Envio version
30 | - Node version
31 | - pnpm version
32 | - Docker version (if running locally)
33 |
34 | **Hosted Service (please complete the following information):**
35 | - Envio version
36 | - Link to the deployed indexer
37 |
38 |
39 | **Additional context**
40 | Add any other context about the problem here.
41 |
--------------------------------------------------------------------------------
/.github/changelog.json:
--------------------------------------------------------------------------------
1 | {
2 | "categories": [
3 | {
4 | "title": "## Features",
5 | "labels": ["T-feature"]
6 | },
7 | {
8 | "title": "## Fixes",
9 | "labels": ["T-bug", "T-fix"]
10 | }
11 | ],
12 | "ignore_labels": ["L-ignore"],
13 | "template": "${{CHANGELOG}}\n## Other\n\n${{UNCATEGORIZED}}",
14 | "pr_template": "- ${{TITLE}} (#${{NUMBER}})",
15 | "empty_template": "- No changes"
16 | }
17 |
--------------------------------------------------------------------------------
/.github/workflows/cache-clean-guide.md:
--------------------------------------------------------------------------------
1 | # GitHub Cache Cleanup Guide
2 |
3 | This guide outlines the steps to update and clean the GitHub cache for the `hyperindex` repository. Follow these instructions to authenticate with GitHub, install the GitHub CLI if needed, and clear specific cache entries.
4 |
5 | ### Prerequisites
6 |
7 | - Ensure you have the [GitHub CLI (`gh`)](https://cli.github.com/) installed.
8 |
9 | ## Steps
10 |
11 | ### 1. Authenticate with GitHub
12 |
13 | ```bash
14 | gh auth login
15 | gh --version # sanity check version
16 | ```
17 |
18 | ### 2. List GitHub Action Caches
19 |
20 | To view a list of caches in the `hyperindex` repository:
21 |
22 | ```bash
23 | gh api \
24 | -H "Accept: application/vnd.github+json" \
25 | /repos/enviodev/hyperindex/actions/caches
26 | ```
27 |
28 | ### 3. Delete GitHub Action Caches
29 |
30 | To delete specific caches, first identify the cache IDs from the previous step (manually for now, but if needed a jq script could be made). Then, use the following script to delete caches by ID:
31 |
32 | ```bash
33 | # List of cache IDs you want to delete
34 | cache_ids=(111 222 333 444 555)
35 |
36 | # Loop through the list and delete each cache
37 | for id in "${cache_ids[@]}"
38 | do
39 | gh api \
40 | --method DELETE \
41 | -H "Accept: application/vnd.github+json" \
42 | -H "X-GitHub-Api-Version: 2022-11-28" \
43 | /repos/enviodev/hyperindex/actions/caches/$id
44 | echo "Deleted cache with ID $id"
45 | done
46 | ```
47 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | */target
2 | .DS_Store
3 | # vim files
4 | *~
5 | *.swo
6 | *.swp
7 |
8 | #All generated code for scenarios
9 | scenarios/**/*.bs.js
10 | scenarios/**/*.res.js
11 | scenarios/**/*.gen.ts
12 | scenarios/**/lib/*
13 | scenarios/**/node_modules/*
14 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "rust-analyzer.showUnlinkedFileNotification": false
3 | }
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | codegenerator/cli/README.md
--------------------------------------------------------------------------------
/codegenerator/.gitignore:
--------------------------------------------------------------------------------
1 | */target
2 | */tarpaulin_target
3 | */tarpaulin-report.html
4 | integration_test_output
--------------------------------------------------------------------------------
/codegenerator/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | members = ["cli", "integration_tests"]
3 | resolver = "2"
4 |
--------------------------------------------------------------------------------
/codegenerator/cli/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/codegenerator/cli/.idea/codegenerator.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/codegenerator/cli/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/codegenerator/cli/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/codegenerator/cli/Makefile:
--------------------------------------------------------------------------------
1 | # Target to update schemas
2 | update-schemas:
3 | @echo "Updating schemas json schemas for evm human config..."
4 | cargo run -- script print-config-json-schema evm > ./npm/envio/evm.schema.json
5 | @echo "Updating schemas json schemas for fuel human config..."
6 | cargo run -- script print-config-json-schema fuel > ./npm/envio/fuel.schema.json
7 |
8 | # Target to update help
9 | update-help:
10 | @echo "Updating help doc..."
11 | cargo run -- script print-cli-help-md > ./CommandLineHelp.md
12 |
13 | # Target to help find missing networks
14 | print-missing-networks:
15 | @echo "Printing missing networks..."
16 | cargo run -- script print-missing-networks
17 |
18 | # Target to update generated docs, depends on update-schemas and update-help
19 | update-generated-docs: update-schemas update-help
20 |
21 | # Runs rustfmt with format_strings option.
22 | format:
23 | @echo "Formatting code"
24 | cargo fmt -- --config format_strings=true
25 |
--------------------------------------------------------------------------------
/codegenerator/cli/npm/envio/bin.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | //@ts-check
3 | "use strict";
4 |
5 | const { spawnSync } = require("child_process");
6 |
7 | /**
8 | * Returns the executable path for envio located inside node_modules
9 | * The naming convention is envio-${os}-${arch}
10 | * If the platform is `win32` or `cygwin`, executable will include a `.exe` extension
11 | * @see https://nodejs.org/api/os.html#osarch
12 | * @see https://nodejs.org/api/os.html#osplatform
13 | * @example "x/xx/node_modules/envio-darwin-arm64"
14 | */
15 | function getExePath() {
16 | const arch = process.arch;
17 | /**
18 | * @type string
19 | */
20 | let os = process.platform;
21 | let extension = "";
22 | if (["win32", "cygwin"].includes(process.platform)) {
23 | os = "windows";
24 | extension = ".exe";
25 | }
26 |
27 | try {
28 | // Since the bin will be located inside `node_modules`, we can simply call require.resolve
29 | return require.resolve(`envio-${os}-${arch}/bin/envio${extension}`);
30 | } catch (e) {
31 | throw new Error(
32 | `Couldn't find envio binary inside node_modules for ${os}-${arch}`
33 | );
34 | }
35 | }
36 |
37 | /**
38 | * Runs `envio` with args using nodejs spawn
39 | */
40 | function runEnvio() {
41 | const args = process.argv.slice(2);
42 | const processResult = spawnSync(getExePath(), args, { stdio: "inherit" });
43 | process.exit(processResult.status ?? 0);
44 | }
45 |
46 | runEnvio();
47 |
--------------------------------------------------------------------------------
/codegenerator/cli/npm/envio/index.js:
--------------------------------------------------------------------------------
1 | // This file is needed to have control over TS version exports
2 | // Some parts like Sury reexport are impossible to implement
3 | // on the JS side, so we need to do it here
4 |
5 | const envioGen = require("./src/Envio.bs.js");
6 | Object.assign(exports, envioGen);
7 |
8 | const Sury = require("rescript-schema");
9 | // Important! Should match the index.d.ts file
10 | exports.S = {
11 | string: Sury.string,
12 | jsonString: Sury.jsonString,
13 | boolean: Sury.boolean,
14 | int32: Sury.int32,
15 | number: Sury.number,
16 | bigint: Sury.bigint,
17 | never: Sury.never,
18 | union: Sury.union,
19 | object: Sury.object,
20 | // Might change in a near future
21 | // custom: Sury.custom,
22 | // Don't expose recursive for now, since it's too advanced
23 | // recursive: Sury.recursive,
24 | transform: Sury.transform,
25 | refine: Sury.refine,
26 | schema: Sury.schema,
27 | record: Sury.record,
28 | array: Sury.array,
29 | tuple: Sury.tuple,
30 | merge: Sury.merge,
31 | optional: Sury.optional,
32 | nullable: Sury.nullable,
33 | bigDecimal: require("./src/bindings/BigDecimal.bs.js").schema,
34 | // Nullish type will change in "sury@10"
35 | // nullish: Sury.nullish,
36 | assertOrThrow: Sury.assertOrThrow,
37 | };
38 |
--------------------------------------------------------------------------------
/codegenerator/cli/npm/envio/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "envio",
3 | "version": "0.0.1-dev",
4 | "private": true,
5 | "description": "A latency and sync speed optimized, developer friendly blockchain data indexer.",
6 | "bin": "./local-bin.mjs",
7 | "main": "./index.js",
8 | "types": "./index.d.ts",
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/enviodev/hyperindex.git"
12 | },
13 | "scripts": {
14 | "watch": "rescript -w"
15 | },
16 | "author": "envio contributors ",
17 | "license": "GPL-3.0",
18 | "bugs": {
19 | "url": "https://github.com/enviodev/hyperindex/issues"
20 | },
21 | "homepage": "https://envio.dev",
22 | "dependencies": {
23 | "@envio-dev/hypersync-client": "0.6.5",
24 | "rescript": "11.1.3",
25 | "rescript-schema": "9.3.0",
26 | "viem": "2.21.0",
27 | "bignumber.js": "9.1.2"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/codegenerator/cli/npm/envio/package.json.tmpl:
--------------------------------------------------------------------------------
1 | {
2 | "name": "envio",
3 | "version": "${version}",
4 | "description": "A latency and sync speed optimized, developer friendly blockchain data indexer.",
5 | "bin": "./bin.js",
6 | "main": "./index.js",
7 | "types": "./index.d.ts",
8 | "repository": {
9 | "type": "git",
10 | "url": "git+https://github.com/enviodev/hyperindex.git"
11 | },
12 | "keywords": [
13 | "blockchain",
14 | "indexer",
15 | "ethereum",
16 | "evm",
17 | "fuel",
18 | "data",
19 | "dapp"
20 | ],
21 | "author": "envio contributors ",
22 | "license": "GPL-3.0",
23 | "bugs": {
24 | "url": "https://github.com/enviodev/hyperindex/issues"
25 | },
26 | "homepage": "https://envio.dev",
27 | "optionalDependencies": {
28 | "envio-linux-x64": "${version}",
29 | "envio-linux-arm64": "${version}",
30 | "envio-darwin-x64": "${version}",
31 | "envio-darwin-arm64": "${version}"
32 | },
33 | "dependencies": {
34 | "@envio-dev/hypersync-client": "0.6.5",
35 | "rescript": "11.1.3",
36 | "rescript-schema": "9.3.0",
37 | "viem": "2.21.0",
38 | "bignumber.js": "9.1.2"
39 | },
40 | "files": [
41 | "bin.js",
42 | "evm.schema.json",
43 | "fuel.schema.json",
44 | "rescript.json",
45 | "index.d.ts",
46 | "index.js",
47 | "src",
48 | "!src/**/*.bs.js"
49 | ]
50 | }
51 |
--------------------------------------------------------------------------------
/codegenerator/cli/npm/envio/rescript.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "envio",
3 | "namespace": false,
4 | "sources": [
5 | {
6 | "dir": "src",
7 | "subdirs": true
8 | }
9 | ],
10 | "suffix": ".bs.js",
11 | "package-specs": {
12 | "module": "commonjs",
13 | "in-source": true
14 | },
15 | "gentypeconfig": {
16 | "generatedFileExtension": ".gen.ts"
17 | },
18 | "bs-dependencies": ["rescript-schema"],
19 | "bsc-flags": ["-open RescriptSchema"]
20 | }
21 |
--------------------------------------------------------------------------------
/codegenerator/cli/npm/envio/src/Address.gen.ts:
--------------------------------------------------------------------------------
1 | /* TypeScript file generated from Address.res by genType. */
2 |
3 | /* eslint-disable */
4 | /* tslint:disable */
5 |
6 | import type {Address as $$t} from './Types.ts';
7 |
8 | export type t = $$t;
9 |
--------------------------------------------------------------------------------
/codegenerator/cli/npm/envio/src/Address.res:
--------------------------------------------------------------------------------
1 | @genType.import(("./Types.ts", "Address"))
2 | type t
3 |
4 | let schema = S.string->S.setName("Address")->(Utils.magic: S.t => S.t)
5 |
6 | external toString: t => string = "%identity"
7 |
8 | external unsafeFromString: string => t = "%identity"
9 |
10 | module Evm = {
11 | @module("viem")
12 | external fromStringOrThrow: string => t = "getAddress"
13 | // Reassign since the function might be used in the handler code
14 | // and we don't want to have a "viem" import there. It's needed to keep "viem" a dependency
15 | // of generated code instead of adding it to the indexer project dependencies.
16 | // Also, we want a custom error message, which is searchable in our codebase.
17 | let fromStringOrThrow = string => {
18 | try {
19 | fromStringOrThrow(string)
20 | } catch {
21 | | _ =>
22 | Js.Exn.raiseError(
23 | `Address "${string}" is invalid. Expected a 20-byte hex string starting with 0x.`,
24 | )
25 | }
26 | }
27 |
28 | let fromAddressOrThrow = address => address->toString->fromStringOrThrow
29 | }
30 |
--------------------------------------------------------------------------------
/codegenerator/cli/npm/envio/src/ChainMap.res:
--------------------------------------------------------------------------------
1 | open Belt
2 |
3 | module Chain = {
4 | type t = int
5 |
6 | external toChainId: t => int = "%identity"
7 |
8 | let toString = chainId => chainId->Int.toString
9 |
10 | let makeUnsafe = (~chainId) => chainId
11 | }
12 |
13 | module ChainIdCmp = Belt.Id.MakeComparableU({
14 | type t = Chain.t
15 | let cmp = (a, b) => Pervasives.compare(a->Chain.toChainId, b->Chain.toChainId)
16 | })
17 |
18 | type t<'a> = Belt.Map.t
19 |
20 | let fromArrayUnsafe: array<(Chain.t, 'a)> => t<'a> = arr => {
21 | arr->Map.fromArray(~id=module(ChainIdCmp))
22 | }
23 |
24 | let get: (t<'a>, Chain.t) => 'a = (self, chain) =>
25 | switch Map.get(self, chain) {
26 | | Some(v) => v
27 | | None =>
28 | // Should be unreachable, since we validate on Chain.t creation
29 | // Still throw just in case something went wrong
30 | Js.Exn.raiseError("No chain with id " ++ chain->Chain.toString ++ " found in chain map")
31 | }
32 |
33 | let set: (t<'a>, Chain.t, 'a) => t<'a> = (map, chain, v) => Map.set(map, chain, v)
34 | let values: t<'a> => array<'a> = map => Map.valuesToArray(map)
35 | let keys: t<'a> => array = map => Map.keysToArray(map)
36 | let entries: t<'a> => array<(Chain.t, 'a)> = map => Map.toArray(map)
37 | let has: (t<'a>, Chain.t) => bool = (map, chain) => Map.has(map, chain)
38 | let map: (t<'a>, 'a => 'b) => t<'b> = (map, fn) => Map.map(map, fn)
39 | let mapWithKey: (t<'a>, (Chain.t, 'a) => 'b) => t<'b> = (map, fn) => Map.mapWithKey(map, fn)
40 | let size: t<'a> => int = map => Map.size(map)
41 | let update: (t<'a>, Chain.t, 'a => 'a) => t<'a> = (map, chain, updateFn) =>
42 | Map.update(map, chain, opt => opt->Option.map(updateFn))
43 |
--------------------------------------------------------------------------------
/codegenerator/cli/npm/envio/src/ChainMap.resi:
--------------------------------------------------------------------------------
1 | module Chain: {
2 | type t
3 |
4 | external toChainId: t => int = "%identity"
5 |
6 | let toString: t => string
7 |
8 | let makeUnsafe: (~chainId: int) => t
9 | }
10 |
11 | type t<'a>
12 | let fromArrayUnsafe: array<(Chain.t, 'a)> => t<'a>
13 | let get: (t<'a>, Chain.t) => 'a
14 | let set: (t<'a>, Chain.t, 'a) => t<'a>
15 | let values: t<'a> => array<'a>
16 | let keys: t<'a> => array
17 | let entries: t<'a> => array<(Chain.t, 'a)>
18 | let has: (t<'a>, Chain.t) => bool
19 | let map: (t<'a>, 'a => 'b) => t<'b>
20 | let mapWithKey: (t<'a>, (Chain.t, 'a) => 'b) => t<'b>
21 | let size: t<'a> => int
22 | let update: (t<'a>, Chain.t, 'a => 'a) => t<'a>
23 |
--------------------------------------------------------------------------------
/codegenerator/cli/npm/envio/src/Envio.gen.ts:
--------------------------------------------------------------------------------
1 | /* TypeScript file generated from Envio.res by genType. */
2 |
3 | /* eslint-disable */
4 | /* tslint:disable */
5 |
6 | import type {EffectContext as $$effectContext} from './Types.ts';
7 |
8 | import type {Effect as $$effect} from './Types.ts';
9 |
10 | import type {Logger as $$logger} from './Types.ts';
11 |
12 | import type {S_t as RescriptSchema_S_t} from 'rescript-schema/RescriptSchema.gen';
13 |
14 | export type logger = $$logger;
15 |
16 | export type effect = $$effect;
17 |
18 | export type effectOptions = {
19 | /** The name of the effect. Used for logging and debugging. */
20 | readonly name: string;
21 | /** The input schema of the effect. */
22 | readonly input: RescriptSchema_S_t;
23 | /** The output schema of the effect. */
24 | readonly output: RescriptSchema_S_t