Skip to content

Commit 3769eca

Browse files
authored
Fix engine, module, storage and scaffolder defects found in the code review (#31)
* Fix engine, module, storage and scaffolder defects found in the code review Engine (@eclesia/indexer-engine) - Match CometBFT 0.38 finalize_block events on mode=BeginBlock/EndBlock so begin_block and end_block handlers receive events on SDK 0.50+ chains. - Fill gaps between announced heights in WebSocket mode; live blocks flow through the catch-up fetcher, which applies backpressure via the circular buffer instead of restarting. - Run event handlers sequentially in registration order; drop the uuid acknowledgement protocol; expose EclesiaEmitter.handlersFor(). - Recover when the block subscription errors or closes; enforce the configured chainId; honour ABCI response codes; paginate validator-set fetches; bound every RPC call with a shared withTimeout helper. - Treat an idle chain as WAITING instead of a failure; unlimited capped exponential backoff (5 s to 5 min, or maxRetries); a block that fails maxFailuresPerBlock times emits fatal-error with the height. - Add stale-run guards, exact endHeight, whenStopped(), and an async stop() that tears down timers, subscriptions, clients and HTTP servers. - Fix a leak in the wait for block data: racing against a never-settling recovery promise retained every delivered block (about 10 KB per block). - Genesis import on stream-json 3 / stream-chain 4 with error listeners on the stream chains and onGenesisStart / onGenesisComplete hooks. - Structured stdout-only logging with error formatting and URL redaction, logFormat json|text, and level-guarded per-message log calls. - Configurable bind hosts for the health and metrics servers; a gauge that reports when the indexer is waiting for blocks. - CircularBuffer refuses to overwrite when full and throws on an empty dequeue; PromiseQueue is deprecated. - Export EclesiaIndexer and EclesiaIndexerConfig, keeping the misspelt names as deprecated aliases; ship the global EventMap declaration. - Mock RPC client: CometBFT 0.37 and 0.38 shapes, paginated validators, module accounts, balances, deterministic block hashes, transfer events. - Remove dayjs, uuid and unused type packages; make @cosmjs/encoding a runtime dependency; publish dist/ only. Core modules (@eclesia/core-modules-pg) - Staking: record undelegations and cancelled unbondings, handle MsgUpdateParams, read the latest validator rows (ORDER BY height DESC NULLS LAST), scale LegacyDec values, derive consensus addresses for ed25519 and secp256k1 keys, keep unchanged fields on validator edits, store a NULL avatar_url, paginate delegator delegations, fall back to chain params, and require the blocks-full module. - Bank: import genesis balances for accounts holding several denoms, apply negative deltas correctly, and fix the COIN literal (no leading space). - Auth: import module accounts from the chain with a well-known fallback and snapshot balances at height 1. - Blocks: TIMESTAMPTZ timestamps, bigint-safe JSON serialisation, corrected prepared-statement names. - Versioned SQL migrations per module (schema_migrations), NUMERIC amounts, removal of redundant height indexes. PostgreSQL indexer (@eclesia/basic-pg-indexer) - Reconnect after the connection drops instead of crashing; stop() and run() resolve only once the indexer has stopped; exit on fatal-error unless exitOnFatal is false. - Apply versioned migrations with a baseline for pre-existing schemas; track genesis imports and refuse to resume a partial one. - SET synchronous_commit once per connection (configurable); the silly-mode client is a Proxy; recycling no longer masks errors; addModules rejects duplicates and late additions. - Declare @eclesia/indexer-engine as a runtime dependency and drop unused dependencies. Scaffolder (create-eclesia-indexer) - Fix the published bin, which could not start. - Multi-stage Node 22 Dockerfiles for pnpm, npm and yarn; .dockerignore, gitignore and license in the template; compose stack with generated Postgres and Hasura secrets in .env, depends_on, and Hasura dev mode off. - Validate project input, escape template substitution, allow the bank module without a genesis file, conditional genesisPath, dotenv loading. - Remove the stray package-lock.json. Repository - Changesets release workflow with npm trusted publishing; the four packages form a lockstep fixed group; packageManager pinned. - CI on Node 22 with a Postgres service, unit, build and end-to-end steps, and a production audit that fails on high advisories. - Type-check test files with the sources; new unit tests for the engine lifecycle, mock client, timeouts, storage and modules (184 in total). - End-to-end suite running PgIndexer with the core modules against PostgreSQL for both CometBFT shapes. - Benchmarks updated for the async lifecycle plus a genesis-import benchmark; README, PERFORMANCE, TROUBLESHOOTING, tutorials, Grafana docs and dashboard, and generated API docs refreshed. - Husky runs lint-staged per package; test scripts run vitest once. - Remove the tracked profiler output and the old e2e placeholder. * ci: build the workspace before running unit tests The PostgreSQL indexer and core module tests import @eclesia/indexer-engine through its package entry points, which resolve to dist/. The test job ran pnpm test before pnpm build, so on a clean runner every suite in basic-indexer-pg failed to resolve the engine. Build first, then run the unit and end-to-end suites.
1 parent ccdc870 commit 3769eca

206 files changed

Lines changed: 14361 additions & 4167 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.changeset/cli-cleanups.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"create-eclesia-indexer": patch
3+
---
4+
5+
A failed build in the scaffolded project is reported as a build failure rather than an installation failure; dead code removed.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"create-eclesia-indexer": minor
3+
---
4+
5+
- Generated Dockerfiles are proper multi-stage builds on Node 22: dependencies are installed and compiled in a build stage, only `dist` and production dependencies reach the runtime image, the container runs as the unprivileged `node` user, and pnpm is pinned. A `.dockerignore` keeps `node_modules`, `.env` and the genesis file out of the image.
6+
- Generated projects declare `engines.node >= 22`, pin tsdown 0.16 with `fixedExtension: false` so the output stays `dist/index.js`, depend on the 2.16 line of the eclesia packages, and ship the project license as `LICENSE.md`.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"create-eclesia-indexer": minor
3+
---
4+
5+
- Generated projects get a random Postgres password and Hasura admin secret written to `.env`; `docker-compose.yml` reads them from there, Hasura waits for Postgres and runs with dev mode off. The connection string in `src/index.ts` no longer carries a password.
6+
- The project name, chain name, chain prefix and description are validated at the prompt (and the project name on the command line), and template substitution escapes values for JSON and ignores `$`-patterns in user input.
7+
- The Bank module can be selected without genesis processing; balances are then tracked as changes from the start height, and the scaffolder says so.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"create-eclesia-indexer": patch
3+
---
4+
5+
- The CLI starts again: the bin shim imported `dist/index.js`, but tsdown 0.16 emits `dist/index.mjs`, so `npx create-eclesia-indexer` failed with `ERR_MODULE_NOT_FOUND`. The `exports`, `module` and `types` fields point at the emitted files as well.
6+
- The generated `docker-compose.yml` no longer binds host port 8888 twice; Hasura is mapped to 8080, the port it listens on.

‎.changeset/config.json‎

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
11
{
22
"$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json",
3-
"changelog": "@changesets/cli/changelog",
3+
"changelog": [
4+
"@changesets/changelog-github",
5+
{
6+
"repo": "allinbits/eclesia-indexer-core"
7+
}
8+
],
49
"commit": false,
5-
"fixed": [["*"]],
10+
"fixed": [
11+
[
12+
"@eclesia/indexer-engine",
13+
"@eclesia/basic-pg-indexer",
14+
"@eclesia/core-modules-pg",
15+
"create-eclesia-indexer"
16+
]
17+
],
618
"linked": [],
7-
"access": "restricted",
19+
"access": "public",
820
"baseBranch": "main",
921
"updateInternalDependencies": "patch",
1022
"ignore": []
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"@eclesia/core-modules-pg": patch
3+
---
4+
5+
- Bank: a spend on a denom the account has never been seen holding is recorded as a negative delta instead of a positive balance.
6+
- Auth: module account balances are snapshotted as of the end of block 1 once block 2 starts, so block 1's own flows are no longer counted twice, and the accounts are discovered through the `ModuleAccounts` query with the well-known names as a fallback for older chains.
7+
- Staking: `checkAndSaveValidators` skips only validators without a consensus address yet; database errors now fail the block instead of being swallowed into an aborted transaction that committed as empty.
8+
- Staking: `updateDelegatorDelegations` follows pagination, so delegators with more than 100 delegations are refreshed completely after a slash.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"@eclesia/core-modules-pg": patch
3+
---
4+
5+
- Consensus addresses for secp256k1 validator keys are derived as CometBFT does (ripemd160 of sha256); ed25519 keys are unchanged.
6+
- `MsgEditValidator` follows the SDK: only the `[do-not-modify]` sentinel keeps a description field, an empty string clears it. `avatar_url` is no longer filled with the identity string.
7+
- Event attributes that arrive as raw bytes (CometBFT 0.34) are stored as base64 in `transactions.logs` instead of one key per byte.
8+
- `getValidatorDescription` is the correctly spelt lookup; the old name remains as an alias. Prepared statement names are unique across modules. Two redundant indexes are dropped by migrations.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"@eclesia/core-modules-pg": minor
3+
---
4+
5+
- Every module's schema is now a set of numbered migrations applied through `PgIndexer.applyMigrations`. The previous `module.sql` files became migration 001; existing databases are baselined automatically.
6+
- Migration 002 (blocks): block timestamps are stored as `TIMESTAMPTZ`, so values no longer depend on the indexer host's time zone. Existing rows are reinterpreted in the database session's time zone.
7+
- Migration 002 (staking): `voting_power` and `min_self_delegation` become `NUMERIC` (18-decimal chains overflowed `BIGINT`), `staking_pool` is unique per height instead of per token pair, lookup indexes are added for the latest-row queries on descriptions, commissions and voting powers, and a duplicate index is dropped.
8+
- The `EventMap` augmentation for module events is emitted into the published types.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@eclesia/core-modules-pg": patch
3+
---
4+
5+
- `StakingModule` declares its dependency on `Blocks.FullBlocksModule` and refuses to set up without it, with an explanation, instead of failing on the first block insert.
6+
- The module-account fallback for chains without the `ModuleAccounts` query tolerates names the chain does not know.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@eclesia/basic-pg-indexer": patch
3+
---
4+
5+
Declare `@eclesia/indexer-engine` as a runtime dependency (it was a devDependency, so consumers had to install it themselves) and drop nine dependencies this package never imports.

0 commit comments

Comments
 (0)