A real-time Solana blockchain data indexer that streams transactions and account changes using Yellowstone gRPC Geyser plugin, processes them through Kafka, and stores structured data in ClickHouse for analytics and querying.
- Real-time Streaming: Consumes Solana blockchain data from Kafka topics
- Protobuf Decoding: Decodes Yellowstone gRPC protobuf messages (ConfirmedBlock, ConfirmedTransaction, Transaction)
- Table Storage: Stores all data in ClickHouse
- RESTful API: Provides endpoints for querying and managing data
- TypeScript: Fully typed codebase for better development experience
- Graceful Shutdown: Proper cleanup of Kafka and ClickHouse connections
- Backend: Node.js + Express + TypeScript
- Message Queue: Apache Kafka
- Database: ClickHouse
- Protobuf: protobufjs for message decoding
- Blockchain: Solana (via Yellowstone gRPC Geyser plugin)
- Node.js 18+ and npm
- Apache Kafka running on
localhost:9092 - ClickHouse running on
localhost:8123 - Solana node with Yellowstone gRPC Geyser plugin streaming to Kafka topic
grpc1
- Clone and setup the project:
git clone <repository-url>
cd project/indexer/backend
npm install- Build TypeScript:
npm run build- Start the server:
# Development mode with auto-reload
npm run dev
# Production mode
npm startThe server will start on http://localhost:3000
backend/
βββ src/
β βββ database/
β β βββ clickhouse.ts # ClickHouse client and table management
β βββ kafka/
β β βββ consumer.ts # Kafka consumer setup
β βββ protobuf/
β β βββ decoder.ts # Protobuf message decoding
β βββ routes/
β β βββ index.ts # API routes
β βββ services/
β β βββ message-processor.ts # Core message processing logic
β βββ types/
β β βββ index.ts # TypeScript interfaces
β βββ utils/
β β βββ timestamp.ts # Timestamp formatting utilities
β βββ server.ts # Main server entry point
βββ message.proto # Solana protobuf schema
βββ package.json
βββ tsconfig.json
βββ README.md
GET /- Server status and configuration
GET /stats- Database statistics (total blocks, protobuf decoded, decode success)GET /blocks?limit=10- Get recent blocks from ClickHouseDELETE /blocks- Clear all blocks from database
Stores all processed Kafka messages with decoded data:
CREATE TABLE blocks (
timestamp DateTime64(3),
topic String,
partition UInt32,
offset String,
message_type String,
decoded_data String,
is_protobuf Bool,
decode_success Bool
) ENGINE = MergeTree()
ORDER BY (timestamp, topic, partition, offset)Fields:
timestamp- When the message was processedtopic- Kafka topic name (grpc1)partition- Kafka partition numberoffset- Kafka message offsetmessage_type- Type of decoded message (ConfirmedBlock, JSON, Raw, etc.)decoded_data- JSON string of the decoded message contentis_protobuf- Whether message was successfully decoded as protobufdecode_success- Whether any decoding was successful
curl http://localhost:3000/statsResponse:
{
"stats": {
"total_blocks": 1250,
"protobuf_decoded": 1200,
"decode_success": 1240
}
}curl http://localhost:3000/blocks?limit=5curl -X DELETE http://localhost:3000/blocks-- Get message type distribution
SELECT
message_type,
COUNT(*) as count
FROM blocks
GROUP BY message_type
ORDER BY count DESC;
-- Get recent protobuf messages
SELECT
timestamp,
message_type,
is_protobuf,
decode_success
FROM blocks
WHERE is_protobuf = true
ORDER BY timestamp DESC
LIMIT 10;
-- Get processing success rate
SELECT
toDate(timestamp) as date,
COUNT(*) as total_messages,
SUM(decode_success) as successful_decodes,
(SUM(decode_success) * 100.0 / COUNT(*)) as success_rate
FROM blocks
GROUP BY toDate(timestamp)
ORDER BY date DESC;npm run build- Compile TypeScript to JavaScriptnpm run dev- Start development server with auto-reloadnpm run dev:watch- Start with file watchingnpm start- Start production server
PORT- Server port (default: 3000)
The application provides comprehensive logging:
- Raw message hex bytes for protobuf debugging
- Message type identification
- Decode success/failure status
- ClickHouse operation status
All data is stored in ClickHouse for analysis and debugging.
- Kafka Consumer receives messages from
grpc1topic - Message Processor attempts to decode messages in this order:
- Protobuf (ConfirmedBlock β ConfirmedTransaction β Transaction)
- JSON parsing
- Raw data storage
- ClickHouse Writer stores all messages with metadata in
blockstable - API Endpoints provide access to stored data and statistics
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
