-
Notifications
You must be signed in to change notification settings - Fork 18
Contributing
cmd/ # Application entry points (api, indexer, private_api, celestials)
internal/ # Non-exportable packages (storage interfaces, postgres implementations, types)
pkg/ # Importable packages (indexer pipeline, node clients, types)
database/ # SQL scripts, materialized views, PostgreSQL functions
configs/ # YAML configuration with env-var substitution
test/ # Newman API test collection, test fixtures
See Architecture for the full directory breakdown.
-
Fork the repository and create a feature branch:
git checkout -b feature/my-feature # new feature git checkout -b fix/my-bug # bug fix git checkout -b docs/update-readme # documentation
-
Make your changes with tests.
-
Run the full check before committing:
make gc # lint β test β git commitOr run steps individually:
make lint make test -
Submit a pull request with a clear description of what and why.
-
Address review feedback.
We use conventional commits with the following prefixes:
feat: add Hyperlane token indexing
fix: correct block height overflow in ID calculation
docs: update configuration reference
refactor: split storage module into domain files
test: add integration tests for IBC transfers
deps: update celestia-app to v7.0.3
chore: update license headers
- Run
go fmtandgolangci-lintbefore every commit (make lint) - Use
zerologfor logging β neverfmt.Printin production paths - Use
errors.Wrap(err, "context")fromgithub.com/pkg/errors - Use storage interfaces only β never use concrete
postgres.*types outsideinternal/ - Use
github.com/bytedance/sonicfor JSON marshaling (faster thanencoding/json)
Every new Go source file must begin with:
// SPDX-FileCopyrightText: 2025 Bb Strategy Pte. Ltd. <celenium@baking-bad.org>
// SPDX-License-Identifier: MITApply to all files automatically:
make license-headerEnum types in internal/storage/types/ are code-generated. Never edit *_enum.go files manually. After changing an enum definition, run:
make generateAll storage interface mocks are auto-generated into mock/ subdirectories. Add a //go:generate directive to your interface file, then run:
make generateNever edit generated mock files manually.
Every new handler must include Swagger annotations:
// @Summary Get block info
// @Tags block
// @ID get-block
// @Param height path integer true "Block height" minimum(1)
// @Produce json
// @Success 200 {object} responses.Block
// @Failure 400 {object} Error
// @Router /v1/blocks/{height} [get]
func (h *BlockHandler) Get(c echo.Context) error { ... }After adding or changing handlers, regenerate the Swagger docs:
make api-docs
# or together with mocks:
make gaFollow this checklist to add a new indexed entity end-to-end:
-
Storage model β add model struct + filter struct + interface
IFooininternal/storage/ -
Postgres implementation β implement queries in
internal/storage/postgres/foo.gousing the subquery+JOIN pattern -
Register in Storage struct β
internal/storage/postgres/core.go; add hypertable if time-series -
Indexes β add DB indexes in
internal/storage/postgres/index.go -
Transaction save/rollback β add save and rollback methods in
internal/storage/postgres/transaction.go -
Mock β add
//go:generatedirective, runmake generate -
Migration β create a migration file in
internal/storage/postgres/migrations/with bothupanddown -
Parser / DecodeContext β add parsing logic; assign deterministic ID via
idFromHeightAndPosition(height, position); accumulate intodCtxviactx.AddXxx()methods -
Storage module β create
pkg/indexer/storage/foo.gowith asaveFoo(ctx, tx, dCtx.Foos)function; call it fromprocessBlockInTransactioninstorage.go -
Rollback β add rollback logic in
pkg/indexer/rollback/if needed -
API handler β create
cmd/api/handler/foo.gowith Swagger annotations -
Response DTO β add response struct in
cmd/api/handler/responses/ -
Routes β register routes in
cmd/api/init.go -
Regenerate docs β run
make ga
- Migration files live in
internal/storage/postgres/migrations/, namedYYYYMMDDNNNNNN_description.go - Each file registers exactly one migration via
init() -
Both
upanddownare required β never leavedownas a stub or TODO -
downmust fully revert everythingupdoes
- Write unit tests for all new logic
- Write integration tests for new storage queries β these spin up a real TimescaleDB container (Docker required)
- Use
testfixturesfor DB test data (fixtures live intest/) - Mocks are for handler/service tests only β never mock the database in integration tests
- Ensure
make testpasses before submitting a PR
- Validate all external input (user requests, node responses)
- Never commit secrets, tokens, or credentials
- Be aware of OWASP Top 10: SQL injection, XSS, command injection, etc.
-
goseclinter is enabled and must pass
Releases are tagged from master. The Docker images are published automatically on tag push:
| Image | Registry |
|---|---|
ghcr.io/celenium-io/celestia-indexer |
Indexer |
ghcr.io/celenium-io/celestia-indexer-api |
Public API |
ghcr.io/celenium-io/celestia-indexer-private-api |
Private API |