Skip to content

v0.7.2#20

Merged
nman98 merged 30 commits into
Cogwheel-Validator:mainfrom
nman98:main
Jun 30, 2026
Merged

v0.7.2#20
nman98 merged 30 commits into
Cogwheel-Validator:mainfrom
nman98:main

Conversation

@nman98

@nman98 nman98 commented Jun 30, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features
    • Added CLI/API support for PostgreSQL SSL/TLS (root cert, client cert, key) and improved log-level handling.
    • Added a changelog make target and a new “Quick Start” guide.
  • Bug Fixes
    • Improved hourly volume calculation and average block production time windowing.
    • Hardened TimescaleDB connection-string handling for special characters.
  • Documentation
    • Refreshed setup/install instructions and configuration examples (including command help/output).
  • Tests
    • Expanded schema validation and decoder/conversion coverage (including COPY-row alignment and aggregate/table invariants).

nman98 added 20 commits June 24, 2026 13:58
This function did exist before however there was a possibility to
create a bug if indexer worked for a limited time or there simply isn't
enough data. There was a temporary solution to return a true mean
value. Now the API should be able to return the needed data even
with limited data inserted into the database
This only marks some initial progress to support the send data using SSL
The process now uses typed system so the program doesn't need to work
with map[string]any. It should provide more maintainable code.
@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@nman98, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 56 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f438acc9-fdbb-4635-bca4-490da52e010f

📥 Commits

Reviewing files that changed from the base of the PR and between dae2116 and 04c1680.

📒 Files selected for processing (1)
  • CHANGELOG.md
📝 Walkthrough

Walkthrough

This PR renames sql_data_types to schema, adds generic row insertion and typed message decoding, wires PostgreSQL SSL/TLS through config and startup paths, and updates runtime queries, CLI behavior, docs, config examples, and release metadata.

Changes

Schema, decoder, database, and runtime wiring

Layer / File(s) Summary
Schema package core
pkgs/schema/types.go, pkgs/schema/hypertables.go, pkgs/schema/copyrow.go, pkgs/schema/assertions.go, pkgs/schema/copyrow_test.go
Renames the package to schema, adds Insertable/Message plus AsInsertable and pgArray, implements CopyRow() for persisted row types and message rows, and adds conformance and COPY-alignment tests.
Table and aggregate registries
pkgs/schema/table.go, pkgs/schema/materialize.go, pkgs/schema/tables_validation_test.go, pkgs/schema/aggregates_validation_test.go
Adds Hypertable, RegularTables(), Hypertables(), and AllTables(), derives aggregate names from AllAggregates(), and adds reflection-based validation for table and aggregate tags.
Typed message decoding
indexer/decoder/types.go, indexer/decoder/decoder.go, indexer/decoder/product.go, indexer/decoder/process.go, indexer/decoder/registry.go
Switches decoded messages and fees to typed schema values, replaces map-based message handling with a codec registry over std.Msg, and introduces DbMessages batching with typed conversion helpers.
Codec registry and conversion tests
indexer/decoder/registry_test.go
Adds registry, round-trip decode, conversion fan-out, address resolution, multi-send, session, and unknown-type tests for the typed decoder path.
Generic TimescaleDB insertion and DSN building
pkgs/database/timescaledb/insert.go, pkgs/database/timescaledb/pool.go, pkgs/database/timescaledb/pool_test.go
Replaces table-specific insert methods with InsertRows, adds quoted DSN construction with optional SSL certificate fields, switches custom type registration to schema helpers, and verifies DSN escaping.
Data processor migration to schema rows
indexer/data_processor/types.go, indexer/data_processor/operator.go, indexer/data_processor/event.go, indexer/data_processor/operator_test.go
Collapses the database interface to InsertRows, migrates block/transaction/validator/event flows to schema-backed rows, and updates message batching, address extraction, and mock/test coverage.
SSL/TLS and CLI wiring
indexer/config/types.go, api/config/types.go, api/serve.go, indexer/main_operator/operator.go, indexer/cli/root.go, indexer/cli/func.go, indexer/cli/setup.go, indexer/cmd/indexer.go, indexer/db_init/tables.go
Adds SSL/TLS fields to config, passes them into DB pools, adds --log-level handling on the root command, extends setup commands with SSL flags and schema registries, and changes the user password prompt output.
Runtime query and orchestrator changes
pkgs/database/timescaledb/query_block.go, pkgs/database/timescaledb/query_view.go, indexer/orchestrator/operator.go, indexer/orchestrator/operator_test.go, integration/synthetic/init.go
Splits block-time averaging into windowed and true-mean methods, truncates hourly volume series inputs to the hour, and adds context cancellation handling to historic processing call sites.
Docs, changelog, config, and dependencies
CHANGELOG.md, Makefile, README.md, docs/*, config*.yml, cliff.toml, go.mod, .github/workflows/govulncheck.yml, .gitignore
Adds the 0.7.2 changelog entry and changelog target, expands setup and quick-start docs, adjusts example configs and API docs, updates dependency versions and workflow Go version, and ignores a local Docker Compose file.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Poem

🐇 I hopped through schemas, clean and bright,
Typed msgs now leap in ordered flight.
The DSN sparkles, quoted just so,
And rows hop fast where COPY flows.
With flags and docs and timing tuned,
This rabbit’s burrow feels newly groomed.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 48.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is only a version string and does not describe the change set. Use a concise, descriptive title that summarizes the main change, such as the new release/changelog and TLS/database updates.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
indexer/db_init/tables.go (1)

579-588: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Quote the role name and password before executing CREATE USER. userName and the prompted password are concatenated into SQL as-is, so a crafted value can break the statement or inject extra SQL. Use PostgreSQL-safe quoting/sanitization instead of fmt.Sprintf.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@indexer/db_init/tables.go` around lines 579 - 588, The CREATE USER statement
in tables.go is built by concatenating userName and the prompted password
directly into SQL, so update the user creation flow to use PostgreSQL-safe
quoting or parameterization instead of fmt.Sprintf. Locate the SQL assembly
around the password prompt in the user creation path and ensure both the role
name and password are safely escaped before db.pool.Exec is called.
indexer/data_processor/operator.go (1)

153-167: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Avoid inserting zero-value block rows after per-block failures.

processBlock returns early on decode/parse errors, but ProcessBlocks still inserts every slot in blocksData. Track valid indexes like the transaction/validator paths before calling InsertRows.

Proposed fix
 	blocksData := make([]s.Blocks, blockAmount)
+	valid := make([]bool, blockAmount)
 	wg := sync.WaitGroup{}
 	wg.Add(blockAmount)

 	for idx, block := range blocks {
-		go d.processBlock(idx, block, &wg, blocksData)
+		go d.processBlock(idx, block, &wg, &valid[idx], blocksData)
 	}

 	wg.Wait()
+
+	result := make([]s.Blocks, 0, blockAmount)
+	for idx, ok := range valid {
+		if ok {
+			result = append(result, blocksData[idx])
+		}
+	}

 	// add multiplier for the timeout depending on the block amount
-	timeout := 10*time.Second + (time.Duration(blockAmount) * time.Second / 5)
+	timeout := 10*time.Second + (time.Duration(len(result)) * time.Second / 5)
 	ctx, cancel := context.WithTimeout(context.Background(), timeout)
 	defer cancel()
-	err := d.dbPool.InsertRows(ctx, s.AsInsertable(blocksData))
+	err := d.dbPool.InsertRows(ctx, s.AsInsertable(result))
 func (d *DataProcessor) processBlock(
 	idx int,
 	block *rpcClient.BlockResponse,
 	wg *sync.WaitGroup,
+	valid *bool,
 	blocksData []s.Blocks,
 ) {
@@
 	blocksData[idx] = s.Blocks{
 		Hash:      hash,
 		Height:    height,
 		Timestamp: block.Result.Block.Header.Time,
 		ChainID:   block.Result.Block.Header.ChainID,
 		ChainName: d.chainName,
 	}
+	*valid = true
 }

Also applies to: 187-210

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@indexer/data_processor/operator.go` around lines 153 - 167, ProcessBlocks is
inserting every entry from blocksData even when processBlock exits early on
decode/parse errors, leaving zero-value rows behind. Update ProcessBlocks to
track only successfully processed block indexes, similar to the
transaction/validator paths, and build the insert payload from that valid set
before calling dbPool.InsertRows. Make the change in the code path that fills
blocksData and the corresponding insertion logic so failed blocks are skipped
entirely.
🧹 Nitpick comments (6)
indexer/orchestrator/operator.go (1)

270-270: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Typo in doc comment: "smae" → "same".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@indexer/orchestrator/operator.go` at line 270, Fix the typo in the doc
comment for collectTransactionsFromBlocks by changing “smae” to “same”; update
the comment text only and leave the function logic unchanged.
README.md (1)

63-63: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Update to modern Docker Compose command.

docker-compose (hyphen) is the deprecated v1 command. Modern Docker uses docker compose (plugin). Update to prevent setup failures for new users.

- docker-compose up -d timescaledb
+ docker compose up -d timescaledb
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` at line 63, The README setup command still uses the deprecated
docker-compose v1 syntax. Update the documented command to the modern docker
compose form so new users can start the timescaledb service without setup
issues. Refer to the README setup step containing docker-compose up -d
timescaledb and replace it with the current Docker Compose plugin command.
cliff.toml (1)

19-19: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Trailing \n likely produces an extra blank line in the regenerated header.

In a triple-quoted TOML string this line already ends with a real newline; the appended \n adds a second one, so the full-file (-o) header gains a blank line after the Semantic Versioning sentence before the closing of the block. Drop it unless the extra spacing is intended.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cliff.toml` at line 19, The generated header text in cliff.toml includes an
unnecessary literal newline escape after the Semantic Versioning sentence, which
can introduce an extra blank line in the output. Update the header string so the
Semantic Versioning line in the TOML block ends naturally without the appended
newline escape, keeping the template aligned with the surrounding header text.
docs/requirements.md (1)

64-64: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Go version drift between docs and CI.

Docs state go 1.26.1 (matching go.mod), but .github/workflows/govulncheck.yml pins 1.26.4. Not a defect since the doc reflects the module floor, but consider aligning the stated version with the toolchain you actually validate against to avoid confusion.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/requirements.md` at line 64, The Go version noted in the docs is out of
sync with the toolchain version used in CI, which can confuse readers about what
is actually validated. Update the version referenced in the requirements
documentation to match the pinned Go version used by the govulncheck workflow,
and keep the `go.mod`-based minimum separate if needed. Use the existing Go
version reference in `requirements.md` and the CI workflow’s version pin as the
source of truth when aligning the wording.
indexer/decoder/registry.go (1)

162-164: 🗄️ Data Integrity & Integration | 🔵 Trivial | 💤 Low value

strings.Join(m.Args, ",") loses argument boundaries when an arg itself contains a comma.

Joining args with a bare , makes the stored value ambiguous (e.g. ["a,b","c"] is indistinguishable from ["a","b","c"]). If exact reconstruction of call args matters downstream, consider a non-ambiguous encoding (JSON array, or a separator that's escaped). If this matches the prior column semantics, it can be left as-is.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@indexer/decoder/registry.go` around lines 162 - 164, The
`strings.Join(m.Args, ",")` assignment in `registry.go` makes `Args` ambiguous
when individual arguments can contain commas. Update the `Args` serialization in
the registry path that builds the record from `m.PkgPath`, `m.Func`, and
`m.Args` to use an unambiguous encoding such as a JSON array, or otherwise
escape separators so the original arguments can be reconstructed exactly. If the
downstream column is intentionally a legacy comma-separated field, keep it
unchanged only if that semantics is required.
indexer/cli/setup.go (1)

241-245: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the repeated aggregate interval.

SonarCloud is failing on the duplicated "1 month" literal; a local constant keeps this list aligned.

+	const aggregateChunkInterval = "1 month"
 	views := []struct {
 		agg           dbinit.ContinuousAggregateDefinition
 		segmentByCols []string
 		chunkInterval string
 	}{
-		{s.TxCounter{}, []string{"chain_name"}, "1 month"},
+		{s.TxCounter{}, []string{"chain_name"}, aggregateChunkInterval},

Apply the same constant to the remaining entries.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@indexer/cli/setup.go` around lines 241 - 245, The repeated "1 month"
aggregate interval in the setup list should be extracted into a local constant
to keep the entries aligned and satisfy SonarCloud. Update the slice in setup.go
where the metric definitions are assembled in the setup logic to use a shared
constant instead of repeating the literal, and apply that constant consistently
to all remaining aggregate entries in the same list.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CHANGELOG.md`:
- Line 37: The changelog entry in CHANGELOG.md has a spelling error in the
commit description. Update the text in that entry to change “privilages” to
“privileges” while keeping the rest of the commit message and link intact.
- Line 30: Update the changelog entry text in CHANGELOG.md to fix the spelling
error in the commit description by changing “grammer” to “grammar”; adjust the
specific changelog item that mentions the quick start section so the user-facing
release note is spelled correctly.
- Line 24: Fix the spelling mistake in the changelog entry from “reflaction” to
“reflection” in the affected commit description. Update the user-facing text in
CHANGELOG.md so the summary line reads correctly and remains consistent with the
existing entry format.

In `@docs/requirements.md`:
- Around line 25-30: Fix the small wording typos in the storage requirements
paragraph by editing the prose in the relevant documentation section: change
“you might needs SSD” to “you might need an SSD,” and correct “arround” to
“around.” Keep the rest of the paragraph intact and make the wording read
naturally in the surrounding requirements text.

In `@docs/setup.md`:
- Around line 76-80: The privilege description in the setup docs is incomplete
and the `keymgr` role is introduced without explanation. Update the prose near
the privilege list to complete the writer privileges description in the setup
documentation, and add a short sentence explaining what `keymgr` grants and when
it should be used. Refer to the existing privilege wording around the
reader/writer/keymgr section so the documentation stays consistent.
- Line 24: Remove the duplicated word in the documentation sentence so the
phrase reads naturally; update the text in the setup guide where it mentions the
GitHub project packages, and ensure the wording around the linked packages URL
is corrected without changing the meaning.

In `@indexer/cli/setup.go`:
- Around line 83-85: The help text for the database creation command is using a
raw string literal with escaped newline text, so Cobra will display the
characters literally instead of a line break. Update the help text in the setup
command definition to use an actual newline inside the backtick string for the
Long description, keeping the command metadata in the same place so the help
output renders correctly.
- Line 70: The create-user command still exposes a stale --user flag even though
user_name is now passed as a positional argument, so remove the unused flag from
the setup in createUserCmd to keep the help text and behavior aligned. Update
the command wiring in setup so only the positional user_name path is supported,
and verify any related parsing or validation around createUserCmd no longer
references the old flag.

In `@indexer/data_processor/operator.go`:
- Around line 443-448: Message conversion failures are currently being dropped
because nil entries from ConvertToDbMessages are skipped when building
aggregatedDbMessages, allowing ProcessMessages to succeed with missing rows.
Update the message conversion flow in ProcessMessages and the affected batch
handling around msgResults so ConvertToDbMessages errors are collected in a
separate error channel/slice and returned immediately instead of continuing to
Phase 2. Make sure the aggregation step that calls aggregatedDbMessages.Merge
only runs when all conversions succeeded, and abort before any insert if any
conversion error was encountered.

In `@indexer/main_operator/operator.go`:
- Around line 107-108: `HistoricProcess` is not observing the shutdown context
even though `signalHandler.RegisterOperation()` is used before it starts. Update
`orch.HistoricProcess` (and any chunk-processing path it calls) to accept
`signalHandler.Context()` and check `ctx.Done()` inside the historic chunk loop
so a SIGTERM can stop processing early. Use the existing
`signalHandler.Context()` and `HistoricProcess` symbols to wire the context
through the historic range processing flow.

In `@pkgs/database/timescaledb/insert.go`:
- Around line 43-47: InsertRows should validate that every element in the rows
batch targets the same table and column layout before building the COPY call.
Add a homogeneity check in InsertRows around the first-row metadata usage so
rows[0].TableName() and rows[0].TableColumns() are only used after confirming
all Insertable items match; otherwise reject the batch early with a clear error.
Keep the fix localized to InsertRows and the CopyFromSlice/CopyFrom path so
mixed batches cannot be copied with the wrong table metadata.

In `@pkgs/database/timescaledb/pool.go`:
- Around line 72-91: The buildDSN logic in pool.go is concatenating libpq
keyword/value pairs directly, so fields like password, SslRootCert, SslCert, and
SslKey can break parsing when they contain spaces, quotes, or backslashes.
Update buildDSN to either construct a URL-style DSN or quote/escape each value
before appending it to the string, keeping the existing config fields and
pgxpool.ParseConfig flow intact.

In `@pkgs/database/timescaledb/query_block.go`:
- Around line 313-318: The error handling in the block-time query is too broad:
the row.Scan path in the query block collapses every database failure into the
same “not enough block data” message. Update the logic around row.Scan so only
pgx.ErrNoRows maps to the friendly missing-data error, and any other scan/query
error is wrapped and returned with its original details. Keep the heightDiff ==
0 check as the data-shortage case, and ensure the query block uses errors and
github.com/jackc/pgx/v5 to distinguish these paths cleanly.

---

Outside diff comments:
In `@indexer/data_processor/operator.go`:
- Around line 153-167: ProcessBlocks is inserting every entry from blocksData
even when processBlock exits early on decode/parse errors, leaving zero-value
rows behind. Update ProcessBlocks to track only successfully processed block
indexes, similar to the transaction/validator paths, and build the insert
payload from that valid set before calling dbPool.InsertRows. Make the change in
the code path that fills blocksData and the corresponding insertion logic so
failed blocks are skipped entirely.

In `@indexer/db_init/tables.go`:
- Around line 579-588: The CREATE USER statement in tables.go is built by
concatenating userName and the prompted password directly into SQL, so update
the user creation flow to use PostgreSQL-safe quoting or parameterization
instead of fmt.Sprintf. Locate the SQL assembly around the password prompt in
the user creation path and ensure both the role name and password are safely
escaped before db.pool.Exec is called.

---

Nitpick comments:
In `@cliff.toml`:
- Line 19: The generated header text in cliff.toml includes an unnecessary
literal newline escape after the Semantic Versioning sentence, which can
introduce an extra blank line in the output. Update the header string so the
Semantic Versioning line in the TOML block ends naturally without the appended
newline escape, keeping the template aligned with the surrounding header text.

In `@docs/requirements.md`:
- Line 64: The Go version noted in the docs is out of sync with the toolchain
version used in CI, which can confuse readers about what is actually validated.
Update the version referenced in the requirements documentation to match the
pinned Go version used by the govulncheck workflow, and keep the `go.mod`-based
minimum separate if needed. Use the existing Go version reference in
`requirements.md` and the CI workflow’s version pin as the source of truth when
aligning the wording.

In `@indexer/cli/setup.go`:
- Around line 241-245: The repeated "1 month" aggregate interval in the setup
list should be extracted into a local constant to keep the entries aligned and
satisfy SonarCloud. Update the slice in setup.go where the metric definitions
are assembled in the setup logic to use a shared constant instead of repeating
the literal, and apply that constant consistently to all remaining aggregate
entries in the same list.

In `@indexer/decoder/registry.go`:
- Around line 162-164: The `strings.Join(m.Args, ",")` assignment in
`registry.go` makes `Args` ambiguous when individual arguments can contain
commas. Update the `Args` serialization in the registry path that builds the
record from `m.PkgPath`, `m.Func`, and `m.Args` to use an unambiguous encoding
such as a JSON array, or otherwise escape separators so the original arguments
can be reconstructed exactly. If the downstream column is intentionally a legacy
comma-separated field, keep it unchanged only if that semantics is required.

In `@indexer/orchestrator/operator.go`:
- Line 270: Fix the typo in the doc comment for collectTransactionsFromBlocks by
changing “smae” to “same”; update the comment text only and leave the function
logic unchanged.

In `@README.md`:
- Line 63: The README setup command still uses the deprecated docker-compose v1
syntax. Update the documented command to the modern docker compose form so new
users can start the timescaledb service without setup issues. Refer to the
README setup step containing docker-compose up -d timescaledb and replace it
with the current Docker Compose plugin command.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c8208ce1-0fad-49f5-8198-dcaec371a4f0

📥 Commits

Reviewing files that changed from the base of the PR and between 212d856 and 4a944db.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (45)
  • .github/workflows/govulncheck.yml
  • CHANGELOG.md
  • Makefile
  • README.md
  • api/config/types.go
  • api/serve.go
  • cliff.toml
  • config-api-example.yml
  • config.yml.example
  • docs/README.md
  • docs/requirements.md
  • docs/setup.md
  • go.mod
  • indexer/cli/func.go
  • indexer/cli/root.go
  • indexer/cli/setup.go
  • indexer/cmd/indexer.go
  • indexer/config/types.go
  • indexer/data_processor/event.go
  • indexer/data_processor/operator.go
  • indexer/data_processor/operator_test.go
  • indexer/data_processor/types.go
  • indexer/db_init/tables.go
  • indexer/decoder/convert.go
  • indexer/decoder/decoder.go
  • indexer/decoder/process.go
  • indexer/decoder/product.go
  • indexer/decoder/registry.go
  • indexer/decoder/registry_test.go
  • indexer/decoder/types.go
  • indexer/main_operator/operator.go
  • indexer/orchestrator/operator.go
  • pkgs/database/timescaledb/insert.go
  • pkgs/database/timescaledb/pool.go
  • pkgs/database/timescaledb/query_block.go
  • pkgs/database/timescaledb/query_view.go
  • pkgs/schema/aggregates_validation_test.go
  • pkgs/schema/assertions.go
  • pkgs/schema/copyrow.go
  • pkgs/schema/copyrow_test.go
  • pkgs/schema/hypertables.go
  • pkgs/schema/materialize.go
  • pkgs/schema/table.go
  • pkgs/schema/tables_validation_test.go
  • pkgs/schema/types.go
💤 Files with no reviewable changes (3)
  • docs/README.md
  • indexer/decoder/process.go
  • indexer/decoder/convert.go

Comment thread CHANGELOG.md
- Refac(indexer/schema):adjust aggregate tables similarly to db tables [5c48476](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/5c484764f2138c4c125fb4e3c823f84dcb12c7eb)
- Chore(data_processor): remove dead code [f55e7ce](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/f55e7ce535e2dbb54e4f76291f883cb85d20926f)
- Refac(schema&cli): move setup logic closer to schema [35324dd](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/35324dddf59968cc0e766b35ee0cc6997fce37a9)
- Refac(pkgs/schema): add data type assertion and reflaction testing [21b01eb](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/21b01eb9a72756721fd010cc464ed79c37f90f42)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix typo: "reflaction" → "reflection".

User-facing changelog contains a spelling error in the commit description.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CHANGELOG.md` at line 24, Fix the spelling mistake in the changelog entry
from “reflaction” to “reflection” in the affected commit description. Update the
user-facing text in CHANGELOG.md so the summary line reads correctly and remains
consistent with the existing entry format.

Comment thread CHANGELOG.md
- Refac(pkgs/schema): add generics for inserting data [eca95f9](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/eca95f9d419977a79121c35b7523d4b080b9473e)
- Refac(pkgs/schema): move the copy the row logic closer to the schemas [cd43e3b](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/cd43e3bbe2ca566b2a5a40b4116c35758af16918)
- Refac(pkgs): rename sql_data_types to schema [8874feb](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/8874feb9ee8face4188a19deafbf8bada2feef36)
- Docs: update grammer and add quick start section [46f9d0b](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/46f9d0b79b42dd64da847d008e64ce00e9165144)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix typo: "grammer" → "grammar".

User-facing changelog contains a spelling error in the commit description.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CHANGELOG.md` at line 30, Update the changelog entry text in CHANGELOG.md to
fix the spelling error in the commit description by changing “grammer” to
“grammar”; adjust the specific changelog item that mentions the quick start
section so the user-facing release note is spelled correctly.

Comment thread CHANGELOG.md

- Fix(indexer): a bug where the database pool closes before the ingestion [076f3f5](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/076f3f5f2417085cfd5266de54e1da5924f72372)
- Fix(indexer/cli): add missing tables for adding privilages to the user [74be438](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/74be438702ec7197b3d7be7c0dabe6e45ac60b76)
- Fix(ci): revert the go version for govulncheck [13ba5fc](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/commit/13ba5fc2e0403c767c3a41e1eeab864e2d111099)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix typo: "privilages" → "privileges".

User-facing changelog contains a spelling error in the commit description.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CHANGELOG.md` at line 37, The changelog entry in CHANGELOG.md has a spelling
error in the commit description. Update the text in that entry to change
“privilages” to “privileges” while keeping the rest of the commit message and
link intact.

Comment thread docs/requirements.md
Comment on lines +25 to +30
It can work on HDD for development but for any bigger projects where write and read
speeds are important you might needs SSD depending on what you are doing. The SATA SSD is a good choice for the
most part but you can also use the NVMe SSD for better performance.

As for the size it depends on the amount of the data that you are indexing.
For example the integration test did about 400K blocks and 1 million
transactions. So it took around 2.2 GB of disk space. There are a lot of things that can affect the size of the
database but at least use this as some reference point to how much space you might need.
For the storage capacity it depends. Given that the indexer is still in development it may vary and it can't be said for certain. For Gnoland Testnet 13 at arround 500K blocks and 250K transactions it used a
bit over 1.2 GB. This should give you some sort of image of how much space you might need.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix small typos in this paragraph.

you might needs SSDyou might need an SSD, and arroundaround.

✏️ Proposed wording fixes
-speeds are important you might needs SSD depending on what you are doing. The SATA SSD is a good choice for the
+speeds are important you might need an SSD depending on what you are doing. The SATA SSD is a good choice for the
@@
-For the storage capacity it depends. Given that the indexer is still in development it may vary and it can't be said for certain. For Gnoland Testnet 13 at arround 500K blocks and 250K transactions it used a 
+For the storage capacity it depends. Given that the indexer is still in development it may vary and it can't be said for certain. For Gnoland Testnet 13 at around 500K blocks and 250K transactions it used a 
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
It can work on HDD for development but for any bigger projects where write and read
speeds are important you might needs SSD depending on what you are doing. The SATA SSD is a good choice for the
most part but you can also use the NVMe SSD for better performance.
As for the size it depends on the amount of the data that you are indexing.
For example the integration test did about 400K blocks and 1 million
transactions. So it took around 2.2 GB of disk space. There are a lot of things that can affect the size of the
database but at least use this as some reference point to how much space you might need.
For the storage capacity it depends. Given that the indexer is still in development it may vary and it can't be said for certain. For Gnoland Testnet 13 at arround 500K blocks and 250K transactions it used a
bit over 1.2 GB. This should give you some sort of image of how much space you might need.
It can work on HDD for development but for any bigger projects where write and read
speeds are important you might need an SSD depending on what you are doing. The SATA SSD is a good choice for the
most part but you can also use the NVMe SSD for better performance.
For the storage capacity it depends. Given that the indexer is still in development it may vary and it can't be said for certain. For Gnoland Testnet 13 at around 500K blocks and 250K transactions it used a
bit over 1.2 GB. This should give you some sort of image of how much space you might need.
🧰 Tools
🪛 LanguageTool

[grammar] ~29-~29: Ensure spelling is correct
Context: ... for certain. For Gnoland Testnet 13 at arround 500K blocks and 250K transactions it us...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/requirements.md` around lines 25 - 30, Fix the small wording typos in
the storage requirements paragraph by editing the prose in the relevant
documentation section: change “you might needs SSD” to “you might need an SSD,”
and correct “arround” to “around.” Keep the rest of the paragraph intact and
make the wording read naturally in the surrounding requirements text.

Source: Linters/SAST tools

Comment thread docs/setup.md
For now there aren't any prebuilt docker images. You can build your own by using the Dockerfile. It will also assume that you have the docker installed and that user has the docker group.
To build the image you can use the following command:
There are prebuilt docker images. Check the [`docker-compose.yml`](https://github.com/Cogwheel-Validator/spectra-gnoland-indexer/blob/main/docker-compose.yml)
to see how can you use them. All of the images are available at the the Github project [packages](https://github.com/orgs/Cogwheel-Validator/packages?repo_name=spectra-gnoland-indexer).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Duplicated word: "the the Github".

✏️ Fix
-to see how can you use them. All of the images are available at the the Github project [packages](https://github.com/orgs/Cogwheel-Validator/packages?repo_name=spectra-gnoland-indexer).
+to see how you can use them. All the images are available at the Github project [packages](https://github.com/orgs/Cogwheel-Validator/packages?repo_name=spectra-gnoland-indexer).
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
to see how can you use them. All of the images are available at the the Github project [packages](https://github.com/orgs/Cogwheel-Validator/packages?repo_name=spectra-gnoland-indexer).
to see how you can use them. All the images are available at the Github project [packages](https://github.com/orgs/Cogwheel-Validator/packages?repo_name=spectra-gnoland-indexer).
🧰 Tools
🪛 LanguageTool

[style] ~24-~24: Consider removing “of” to be more concise
Context: ...pose.yml) to see how can you use them. All of the images are available at the the Github ...

(ALL_OF_THE)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/setup.md` at line 24, Remove the duplicated word in the documentation
sentence so the phrase reads naturally; update the text in the setup guide where
it mentions the GitHub project packages, and ensure the wording around the
linked packages URL is corrected without changing the meaning.

Source: Linters/SAST tools

Comment thread indexer/data_processor/operator.go
Comment thread indexer/main_operator/operator.go Outdated
Comment on lines +43 to +47
pgxSlice := pgx.CopyFromSlice(len(rows), func(i int) ([]any, error) {
return rows[i].CopyRow(), nil
})

columns := blocks[0].TableColumns()
tableName := blocks[0].TableName()

_, err := t.pool.CopyFrom(ctx, pgx.Identifier{tableName}, columns, pgxSlice)
return err
}

// InsertValidatorBlockSignings inserts a slice of validator block signings using COPY FROM.
func (t *TimescaleDb) InsertValidatorBlockSignings(
ctx context.Context,
validatorBlockSigning []sql_data_types.ValidatorBlockSigning,
) error {
if len(validatorBlockSigning) == 0 {
return nil
}

pgxSlice := pgx.CopyFromSlice(len(validatorBlockSigning), func(i int) ([]any, error) {
return []any{
validatorBlockSigning[i].BlockHeight,
validatorBlockSigning[i].Timestamp,
validatorBlockSigning[i].Proposer,
makePgxArray(validatorBlockSigning[i].SignedVals),
validatorBlockSigning[i].ChainName}, nil
})

columns := validatorBlockSigning[0].TableColumns()
tableName := validatorBlockSigning[0].TableName()

_, err := t.pool.CopyFrom(ctx, pgx.Identifier{tableName}, columns, pgxSlice)
return err
}

// InsertTransactionsGeneral inserts a slice of transaction general data using COPY FROM.
func (t *TimescaleDb) InsertTransactionsGeneral(
ctx context.Context,
transactionsGeneral []sql_data_types.TransactionGeneral,
) error {
if len(transactionsGeneral) == 0 {
return nil
}

pgxSlice := pgx.CopyFromSlice(len(transactionsGeneral), func(i int) ([]any, error) {
return []any{
transactionsGeneral[i].TxId,
transactionsGeneral[i].ChainName,
transactionsGeneral[i].Timestamp,
transactionsGeneral[i].BlockHeight,
makePgxArray(transactionsGeneral[i].MsgTypes),
makePgxArray(transactionsGeneral[i].TxEvents),
transactionsGeneral[i].TxEventsCompressed,
transactionsGeneral[i].CompressionOn,
transactionsGeneral[i].GasUsed,
transactionsGeneral[i].GasWanted,
transactionsGeneral[i].FeeAmount,
transactionsGeneral[i].FeeDenom,
transactionsGeneral[i].Success,
transactionsGeneral[i].ErrorLog,
}, nil
})

columns := transactionsGeneral[0].TableColumns()
tableName := transactionsGeneral[0].TableName()

_, err := t.pool.CopyFrom(ctx, pgx.Identifier{tableName}, columns, pgxSlice)
_, err := t.pool.CopyFrom(ctx, pgx.Identifier{rows[0].TableName()}, rows[0].TableColumns(), pgxSlice)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Validate homogeneous COPY batches before using the first row’s table metadata.

InsertRows accepts any []s.Insertable, but COPY uses only rows[0].TableName() and rows[0].TableColumns(). A mixed batch can fail late or map same-width rows into the wrong columns.

Proposed guard
+	tableName := rows[0].TableName()
+	tableColumns := rows[0].TableColumns()
+	for i := 1; i < len(rows); i++ {
+		if rows[i].TableName() != tableName || !equalStrings(rows[i].TableColumns(), tableColumns) {
+			return fmt.Errorf("mixed InsertRows batch: row %d targets %s", i, rows[i].TableName())
+		}
+	}
+
 	pgxSlice := pgx.CopyFromSlice(len(rows), func(i int) ([]any, error) {
 		return rows[i].CopyRow(), nil
 	})
 
-	_, err := t.pool.CopyFrom(ctx, pgx.Identifier{rows[0].TableName()}, rows[0].TableColumns(), pgxSlice)
+	_, err := t.pool.CopyFrom(ctx, pgx.Identifier{tableName}, tableColumns, pgxSlice)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkgs/database/timescaledb/insert.go` around lines 43 - 47, InsertRows should
validate that every element in the rows batch targets the same table and column
layout before building the COPY call. Add a homogeneity check in InsertRows
around the first-row metadata usage so rows[0].TableName() and
rows[0].TableColumns() are only used after confirming all Insertable items
match; otherwise reject the batch early with a clear error. Keep the fix
localized to InsertRows and the CopyFromSlice/CopyFrom path so mixed batches
cannot be copied with the wrong table metadata.

Comment thread pkgs/database/timescaledb/pool.go
Comment thread pkgs/database/timescaledb/query_block.go
@sonarqubecloud

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
api/handlers/transactions.go (1)

67-77: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Optional: avoid rebuilding the dispatch map per request.

dispatch is reallocated on every GetTransactionMessage call. Since the values are receiver-bound methods, you could build it once per handler (e.g. lazily via sync.Once or in the constructor and store on TransactionsHandler) to avoid the per-request allocation. Low impact given the small map.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api/handlers/transactions.go` around lines 67 - 77, The dispatch map in
GetTransactionMessage is rebuilt on every request, causing avoidable allocation
overhead. Move the map creation out of the hot path by storing it on
TransactionsHandler or initializing it once with sync.Once, and keep the
receiver-bound handlers like getBankSendResponse and getMsgRunResponse wired
through that cached map so the per-request call only performs lookup.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@api/handlers/transactions.go`:
- Around line 67-77: The dispatch map in GetTransactionMessage is rebuilt on
every request, causing avoidable allocation overhead. Move the map creation out
of the hot path by storing it on TransactionsHandler or initializing it once
with sync.Once, and keep the receiver-bound handlers like getBankSendResponse
and getMsgRunResponse wired through that cached map so the per-request call only
performs lookup.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c6fc0388-9064-4c45-9fa7-1bbe776b9013

📥 Commits

Reviewing files that changed from the base of the PR and between 4a944db and dae2116.

📒 Files selected for processing (17)
  • .gitignore
  • README.md
  • api/handlers/address.go
  • api/handlers/transactions.go
  • docs/api.md
  • indexer/cli/setup.go
  • indexer/data_processor/operator.go
  • indexer/main_operator/operator.go
  • indexer/orchestrator/operator.go
  • indexer/orchestrator/operator_test.go
  • integration/synthetic/init.go
  • pkgs/database/timescaledb/pool.go
  • pkgs/database/timescaledb/pool_test.go
  • pkgs/database/timescaledb/query_block.go
  • pkgs/schema/aggregates_validation_test.go
  • pkgs/schema/copyrow_test.go
  • pkgs/schema/table.go
✅ Files skipped from review due to trivial changes (3)
  • docs/api.md
  • .gitignore
  • README.md
🚧 Files skipped from review as they are similar to previous changes (8)
  • indexer/main_operator/operator.go
  • pkgs/schema/aggregates_validation_test.go
  • pkgs/schema/table.go
  • pkgs/schema/copyrow_test.go
  • pkgs/database/timescaledb/pool.go
  • pkgs/database/timescaledb/query_block.go
  • indexer/data_processor/operator.go
  • indexer/cli/setup.go

@nman98 nman98 merged commit 2d4aa0d into Cogwheel-Validator:main Jun 30, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant