XChain Platform UTXO Tracker
What is xchain-utxo-tracker
xchain-utxo-tracker is the UTXO indexing service of the XChain Platform. It runs as a long-lived Node.js process that continuously polls a coin node (bitcoind, litecoind, or dogecoind) via JSON-RPC, decodes every block, and maintains a real-time index of all unspent transaction outputs (UTXOs) in a LevelDB database. The encoder queries this service to find spendable inputs when constructing transactions.
The tracker uses a compact binary key schema with 11 prefix types to store block metadata, transaction mappings, outputs, inputs, and reorg-recovery archives. All keys and values are raw binary Buffers (not hex strings), reducing database size by approximately 50% compared to string-based encoding. Transaction IDs are truncated to 8 bytes in index keys, further reducing the storage footprint.
In addition to confirmed block data, the tracker maintains a separate in-memory database for unconfirmed mempool transactions, updated every 60 seconds. This allows the encoder to distinguish between confirmed and pending UTXOs when selecting inputs.
Features
- Full UTXO index — every unspent output indexed by SHA-256 scriptPubKey hash for fast address lookups
- Compact binary encoding — all LevelDB keys and values stored as raw binary Buffers with 11 prefix types, reducing DB size ~50%
- Truncated txid keys — transaction IDs stored as 8-byte truncations in index keys for further space savings
- Active-UTXO-only storage — only unspent outputs kept in the live index; spent outputs archived temporarily for reorg recovery
- Real-time mempool tracking — unconfirmed transactions tracked in a separate in-memory LevelDB, updated every 60 seconds
- BigInt precision — all balance calculations use BigInt arithmetic with
satoshiToDecimalString()conversion, eliminating floating-point errors - Reorg handling — maintains a 10-block undo history (K/M archive records) and rolls back correctly on chain reorganization
- Concurrent block prefetch — pre-fetches up to 10 blocks concurrently via JSON-RPC batch requests with HTTP keep-alive
- Batch writes — LevelDB writes batched in groups of 100 blocks for throughput efficiency with atomic commit
- Two-pass transaction processing — outputs inserted before inputs within each block, correctly handling intra-block spends
- Multi-chain support — Bitcoin, Litecoin, and Dogecoin on mainnet, testnet, and regtest
- AuxPoW block parsing — Dogecoin and Litecoin HogEx block header stripping for correct decoding
- Bootstrap support — compressed tar archive backup and restore for fast initial sync without re-scanning the full chain
- REST + JSON-RPC API — dual interface for UTXO queries, balance lookups, address info, and bootstrap operations
- Rolling ETA — 1000-block rolling window with day/hour/minute display for sync progress estimation
- 618 tests — unit, integration, e2e, smoke, fuzz, chaos, performance, and mutation testing
Documentation
| Document | Description |
|---|---|
| Architecture | Data pipeline position, internal components, LevelDB key schema, block processing loop, reorg handling, mempool tracking |
| Configuration | Environment variables, internal constants, database paths |
| Operations | Running, Docker, REST and JSON-RPC API reference, resilience, troubleshooting |
Installation
Clone the repository and install dependencies from within the xchain-utxo-tracker directory:
git clone https://github.com/XChain-Platform/xchain-utxo-tracker.git
cd xchain-utxo-tracker
npm install
Quick Start
Create a .env file with the required environment variables (see Configuration for full details):
NETWORK=bitcoin-mainnet
NODE_URL=127.0.0.1
NODE_PORT=8332
NODE_USER=rpc
NODE_PASSWORD=rpc
UTXO_TRACKER_API_PORT=3000
Start the tracker:
npm run api
On startup, the tracker:
- Loads environment variables from
.env - Starts the Express REST + JSON-RPC API server
- Opens (or creates) the LevelDB database at
/data/xchain-utxo-tracker - Waits for the coin node to reach 99% sync progress
- Reads the last checkpoint (
LAST_BLOCK_HEIGHT,LAST_BLOCK_HASH) and resumes - Begins the block polling loop with concurrent prefetch
Scripts
| Command | Description |
|---|---|
npm run api |
Start the tracker and API server |
npm test |
Unit tests (~247 tests) |
npm run test:smoke |
Smoke tests (11 tests) |
npm run test:integration |
Integration tests (~131 tests, requires LevelDB) |
npm run test:e2e |
End-to-end tests (33 tests) |
npm run test:fuzz |
Fuzz tests (12 campaigns, 1000 iterations each) |
npm run test:fuzz:quick |
Quick fuzz (100 iterations) |
npm run test:fuzz:deep |
Deep fuzz (10,000 iterations) |
npm run test:perf |
Performance tests (36 tests) |
npm run test:perf:quick |
Quick performance (small scale) |
npm run test:perf:deep |
Deep performance (large scale, 4 GB heap) |
npm run test:chaos |
Chaos engineering tests (41 tests) |
npm run test:all |
All unit + integration + e2e tests |
npm run mutate |
Mutation testing (Stryker Mutator) |
npm run mutate:quick |
Quick mutation testing |
npm run mutate:p1 |
P1 priority mutation testing |
npm run mutate:p2 |
P2 priority mutation testing |
npm run mutate:p3 |
P3 priority mutation testing |
npm run mutate:incremental |
Incremental mutation testing |
npm run mutate:custom |
Custom Buffer/encoding mutations |
Dependencies
Runtime
| Package | Purpose |
|---|---|
levelup |
LevelDB abstraction layer |
leveldown |
LevelDB backend for persistent storage |
memdown |
In-memory LevelDB backend for mempool database |
encoding-down |
Encoding wrapper for LevelDB |
bitcoinjs-lib |
Block and transaction parsing, address-to-scriptPubKey conversion |
tiny-secp256k1 |
Elliptic curve operations |
bip32, bip39, bs58check, ecpair |
Key derivation and address encoding |
axios |
HTTP client for JSON-RPC calls to coin node |
express |
HTTP server for REST and JSON-RPC API |
express-json-rpc-router |
JSON-RPC 2.0 request routing |
helmet |
HTTP security headers |
cors |
Cross-Origin Resource Sharing |
binary-search |
Efficient sorted-list operations for mempool diff |
dotenv |
Environment variable loading from .env files |
Development
| Package | Purpose |
|---|---|
mocha |
Test framework |
chai |
Assertion library |
sinon |
Mocking, stubbing, and spying for tests |
supertest |
HTTP endpoint testing |
fast-check |
Property-based (fuzz) testing |
autocannon |
HTTP load testing |
@stryker-mutator/core |
Mutation testing framework |
@stryker-mutator/mocha-runner |
Mocha integration for Stryker |
Related
- Encoder — the primary consumer of UTXO tracker queries
- Decoder — also polls coin nodes, but extracts XChain ACTION data rather than UTXOs
- Data Pipeline — how the UTXO tracker fits into the full platform flow
Copyright © 2025–2026 Dankest, LLC
Based on XChain Platform by Dankest, LLC – https://dankest.llc
Licensed under the GNU Affero General Public License v3.0 (AGPL-3.0-or-later) with a commercial license available for proprietary use.
You may use, modify, and distribute this material under the terms of the License. See LICENSE and NOTICE for full terms. See the licensing overview.