|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +XRP Ledger blockchain indexer built in Go. Collects blocks and transactions from XRP and stores them in PostgreSQL. Built on the `verifier-indexer-framework` which provides the indexing loop, database management, and configuration loading — this repo implements the XRP-specific `BlockchainClient` interface. |
| 8 | + |
| 9 | +## Build & Run Commands |
| 10 | + |
| 11 | +```bash |
| 12 | +# Build |
| 13 | +go build ./cmd/indexer |
| 14 | + |
| 15 | +# Run locally (two terminals): |
| 16 | +# Terminal 1: start PostgreSQL |
| 17 | +cd tests/ && docker compose up postgresdb |
| 18 | +# Terminal 2: run the indexer |
| 19 | +go run ./cmd/indexer --config tests/config_test.toml |
| 20 | + |
| 21 | +# Test (requires running xrpld — see below) |
| 22 | +go test ./... |
| 23 | + |
| 24 | +# Run a single test |
| 25 | +go test ./internal/xrp/ -run TestFirstMemoDataHash |
| 26 | +# Run a single subtest |
| 27 | +go test ./internal/xrp/ -run TestXrpTestSuite/TestGetBlockResult |
| 28 | + |
| 29 | +# Lint (uses golangci-lint v2+) |
| 30 | +golangci-lint run --timeout 5m0s |
| 31 | + |
| 32 | +# Format |
| 33 | +go fmt ./... |
| 34 | +``` |
| 35 | + |
| 36 | +## Test Infrastructure |
| 37 | + |
| 38 | +There are two types of tests: |
| 39 | +- **Unit tests** (e.g., `TestFirstMemoDataHash` in `memo_test.go`): Run without external dependencies, use `package xrp` to test unexported functions. |
| 40 | +- **Integration tests** (e.g., `XrpTestSuite`): Require a running xrpld standalone node. The test setup creates wallets, funds accounts, and submits transactions against the local xrpld. |
| 41 | + |
| 42 | +```bash |
| 43 | +# Start xrpld standalone node (from repo root) |
| 44 | +docker compose up -d |
| 45 | +# Tests connect to xrpld RPC at http://localhost:5005 |
| 46 | +# Override with XRP_RPC_URL env var |
| 47 | +``` |
| 48 | + |
| 49 | +Test suites use `testify/suite`. Integration tests are in `xrp_test.go` (package `xrp_test`), unit tests are in `memo_test.go` (package `xrp`). |
| 50 | + |
| 51 | +## Architecture |
| 52 | + |
| 53 | +**Entry point**: `cmd/indexer/main.go` — minimal bootstrap that calls the framework's `Run()` with XRP-specific types. The framework handles config loading, CLI arg parsing (`--config`, default `config.toml`), logger setup, database init, and the indexing loop. |
| 54 | + |
| 55 | +**Core implementation**: `internal/xrp/` (only 3 source files): |
| 56 | +- `xrp.go` — `xrpClient` implementing `indexer.BlockchainClient` interface (GetLatestBlockInfo, GetBlockTimestamp, GetBlockResult, GetServerInfo). Handles JSON-RPC communication with XRP nodes, transaction parsing, and field extraction. |
| 57 | +- `entities.go` — GORM models for `Block` and `Transaction` tables. Implements `database.Deletable` for history cleanup. |
| 58 | + |
| 59 | +**Transaction field extraction** (in `GetBlockResult`): |
| 60 | +- `PaymentReference`: From first memo's MemoData if exactly 64 hex chars (payment transactions only) |
| 61 | +- `FirstMemoDataHash`: Keccak256 hash of hex-decoded first memo MemoData |
| 62 | +- `IsNativePayment`: True if Amount is a digit string (drops) or has `currency: "XRP"` |
| 63 | +- `SourceAddressesRoot`: Merkle root of Keccak256-hashed accounts with decreased balance |
| 64 | +- `SourceAddress`, `Sequence`, `TicketSequence`, `DestinationTag`: Passed through from XRP transaction JSON |
| 65 | + |
| 66 | +**Key domain details**: |
| 67 | +- XRP timestamps use a custom epoch offset: `XRPTimeToUTD = 946684800` (seconds from Unix epoch to 2000-01-01) |
| 68 | +- XRP MemoData is hex-encoded — decode before hashing |
| 69 | +- Only `validated: true` ledgers are processed |
| 70 | +- The XRPL testnet is periodically reset; old blocks become unavailable |
| 71 | + |
| 72 | +## Configuration |
| 73 | + |
| 74 | +TOML-based config (see `config.example.toml`). The framework loads `config.toml` by default, overridable with `--config` flag or `CONFIG_FILE` env var. The `[blockchain].url` field can be overridden with the `XRP_URL` env var. |
| 75 | + |
| 76 | +Key `[indexer]` settings: `start_block_number` and `end_block_number` control the block range. With `history_drop` enabled (seconds), `start_block_number` is ignored and the indexer starts from the history window. |
| 77 | + |
| 78 | +## Local Framework Development |
| 79 | + |
| 80 | +To develop against a local fork of `verifier-indexer-framework`, add a `replace` directive to `go.mod` (outside the `require` block): |
| 81 | + |
| 82 | +``` |
| 83 | +replace github.com/flare-foundation/verifier-indexer-framework => ../verifier-indexer-framework |
| 84 | +``` |
| 85 | + |
| 86 | +Keep the original `require` line with version intact. Remove the `replace` before committing. |
| 87 | + |
| 88 | +## Linting |
| 89 | + |
| 90 | +Strict `golangci-lint` config in `.golangci.yml` with ~28 linters enabled including `exhaustive` (switch completeness), `nolintlint` (requires specific linter in nolint directives), and `bodyclose`. |
0 commit comments