Skip to content

chainbound/vixy

Repository files navigation

Vixy

A high-performance Ethereum node proxy built in Rust that monitors node health and automatically routes traffic to healthy endpoints.

License: MIT Rust


Overview

Vixy is a transparent proxy that sits between your application and Ethereum nodes (both Execution Layer and Consensus Layer). It continuously monitors node health, tracks synchronization status, and intelligently routes requests to healthy nodes with automatic failover.

Key Capabilities:

  • Health Monitoring: Continuous health checks for EL and CL nodes
  • Automatic Failover: Seamless routing to backup nodes when primary nodes fail
  • WebSocket Support: Proxies WebSocket connections with subscription replay on reconnection
  • Metrics & Observability: Comprehensive Prometheus metrics and Grafana dashboards
  • HTTP & WebSocket Proxying: Support for both REST APIs and WebSocket subscriptions

Quick Start

Using Docker

# Pull the latest image
docker pull ghcr.io/chainbound/vixy:latest

# Create a configuration file
cp config.example.toml config.toml
# Edit config.toml with your node URLs

# Run Vixy
docker run -v $(pwd)/config.toml:/app/config.toml \
  -p 8080:8080 -p 9090:9090 \
  ghcr.io/chainbound/vixy:latest

Building from Source

# Clone the repository
git clone https://github.com/chainbound/vixy.git
cd vixy

# Build and run
cargo run --release -- --config config.toml

Configuration

Create a config.toml file based on config.example.toml:

[server]
listen = "127.0.0.1:8080"

[metrics]
enabled = true
listen = "127.0.0.1:9090"

[[el_nodes]]
name = "geth-primary"
url = "http://geth-1:8545"
ws_url = "ws://geth-1:8546"
tier = "primary"

[[cl_nodes]]
name = "lighthouse-1"
url = "http://lighthouse-1:5052"

See config.example.toml for all available options.

API Endpoints

Vixy exposes the following HTTP endpoints:

Proxy Endpoints

Execution Layer (EL)

POST /el

  • Proxies JSON-RPC requests to healthy EL nodes (uses JSON-RPC protocol, not REST)
  • Selects first healthy primary node
  • Falls back to first healthy backup node if all primary nodes are unhealthy
  • Automatic failover: primary → backup tier when no primary nodes available
  • Supports batch requests
  • Content-Type: application/json

Example:

curl -X POST http://localhost:8080/el \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "eth_blockNumber",
    "params": [],
    "id": 1
  }'

GET /el/ws

  • Transparent WebSocket proxy supporting all JSON-RPC methods over WebSocket
  • Connects to first healthy primary node, falls back to first healthy backup
  • Special handling for eth_subscribe and eth_unsubscribe:
    • Tracks active subscriptions
    • Automatic subscription replay on reconnection
  • Health-aware upstream switching (primary → backup tier when needed)
  • Supports both text and binary WebSocket frames

Example:

const ws = new WebSocket('ws://localhost:8080/el/ws');

// Subscribe to new blocks
ws.send(JSON.stringify({
  jsonrpc: '2.0',
  method: 'eth_subscribe',
  params: ['newHeads'],
  id: 1
}));

// Can also send regular JSON-RPC calls over WebSocket
ws.send(JSON.stringify({
  jsonrpc: '2.0',
  method: 'eth_blockNumber',
  params: [],
  id: 2
}));

Consensus Layer (CL)

ANY /cl/{path}

  • Proxies all HTTP methods (GET, POST, etc.) to healthy CL nodes (uses REST API)
  • Selects first healthy CL node from configured nodes
  • Forwards all paths under /cl/ to beacon node API endpoints
  • Automatic failover to next healthy node if current node becomes unhealthy

Example:

# Get beacon chain head
curl http://localhost:8080/cl/eth/v1/beacon/headers/head

# Check node health
curl http://localhost:8080/cl/eth/v1/node/health

# Get node syncing status
curl http://localhost:8080/cl/eth/v1/node/syncing

Monitoring Endpoints

GET /health

  • Simple health check for the proxy itself
  • Returns: OK (200 status)
  • Useful for load balancer health checks

Example:

curl http://localhost:8080/health

GET /status

  • Detailed JSON status of all monitored nodes
  • Shows health state, block/slot numbers, and lag
  • Content-Type: application/json

Example:

curl http://localhost:8080/status | jq .

Response format:

{
  "el_chain_head": 12345678,
  "cl_chain_head": 9876543,
  "el_failover_active": false,
  "el_nodes": [
    {
      "name": "geth-primary",
      "http_url": "http://geth-1:8545",
      "is_primary": true,
      "block_number": 12345678,
      "lag": 0,
      "check_ok": true,
      "is_healthy": true
    }
  ],
  "cl_nodes": [
    {
      "name": "lighthouse-1",
      "url": "http://lighthouse-1:5052",
      "slot": 9876543,
      "lag": 1,
      "health_ok": true,
      "is_healthy": true
    }
  ]
}

GET /metrics

  • Prometheus metrics endpoint
  • Only available if metrics.enabled = true in config
  • Can be on main port or separate port (see metrics.port)

Example:

curl http://localhost:9090/metrics

See grafana/README.md for full metrics documentation.

Documentation

User Guide

Architecture

API Documentation

Development

Prerequisites

  • Rust 1.86 or later (for let_chains support)
  • Docker (for integration tests)
  • Kurtosis (for testnet setup)
  • just (optional, for task automation)

Development Workflow

# Format code
cargo fmt

# Run lints
cargo clippy -- -D warnings

# Run unit tests
cargo test

# Run BDD tests
cargo test --test cucumber

# Full CI check
just ci

Integration Testing

Vixy includes comprehensive integration tests:

# Run full integration test suite (Kurtosis + WSS tests)
just integration-test

# Or step-by-step for Kurtosis tests
just kurtosis-up      # Start testnet
just kurtosis-vixy    # Run Vixy
just kurtosis-test    # Run tests
just kurtosis-down    # Cleanup

# Or run WSS tests separately
just test-wss

The integration-test command runs:

  1. Kurtosis Tests: Against a local Ethereum testnet
  2. WSS Tests: Against public Hoodi endpoints (non-critical, may fail)

Note: WSS tests use public Hoodi endpoints (publicnode.com, no API key required) and failures are non-critical. They verify TLS/WSS support but may fail due to network issues, rate limiting, or endpoint unavailability.

See INTEGRATION_TESTS.md for detailed testing documentation.

Monitoring

Vixy exposes Prometheus metrics on /metrics (default port 9090). A pre-configured Grafana dashboard is available in the grafana/ directory.

Dashboard Features:

  • EL/CL node health and lag monitoring
  • Request rates and latency (P50/P95/P99)
  • WebSocket connection tracking
  • Failover events and status

See grafana/README.md for setup instructions.

Contributing

We welcome contributions! Here's how to get started:

Reporting Issues

  • Bug Reports: Use the issue tracker with a clear description and reproduction steps
  • Feature Requests: Open an issue describing the use case and proposed solution
  • Security Issues: Please report security vulnerabilities privately to [email protected]

Development Process

  1. Fork the repository and create a feature branch

    git checkout -b feat/your-feature-name
  2. Make your changes following our coding standards:

    • Run cargo fmt before committing
    • Ensure cargo clippy -- -D warnings passes
    • Add tests for new functionality
    • Update documentation as needed
  3. Test thoroughly:

    # Run full test suite
    just ci
    
    # Run integration tests
    just integration-test
  4. Commit with clear messages:

    git commit -m "feat: add support for node prioritization"

    Follow Conventional Commits format:

    • feat: - New features
    • fix: - Bug fixes
    • docs: - Documentation changes
    • refactor: - Code refactoring
    • test: - Test additions/changes
    • chore: - Maintenance tasks
  5. Submit a Pull Request:

    • Provide a clear description of the changes
    • Reference any related issues
    • Ensure CI passes

Code Review Process

  • All submissions require review before merging
  • Maintainers will provide feedback within a few days
  • Address review comments and update your PR
  • Once approved, a maintainer will merge your PR

Development Tools

We use these tools to maintain code quality:

  • rustfmt: Code formatting (cargo fmt)
  • clippy: Linting (cargo clippy)
  • cucumber: BDD testing (cargo test --test cucumber)
  • just: Task automation (just --list)

Run the full CI suite locally before submitting:

just ci

Getting Help

  • Discord: Join our community (coming soon)
  • Discussions: Use GitHub Discussions
  • Documentation: Check AGENT.md for architecture details

Roadmap

Future enhancements we're considering:

  • Dynamic node discovery and registration
  • Advanced load balancing strategies
  • Rate limiting per application/API key
  • gRPC support for CL nodes
  • WebAssembly plugin system
  • Multi-region node distribution

Have ideas? Open an issue or discussion!

License

This project is licensed under the MIT License - see the LICENSE file for details.

Third-Party Licenses

Vixy depends on various open-source libraries. Their licenses can be found in their respective repositories:

Acknowledgments

Built with ❤️ by Chainbound

Special thanks to:

  • The Ethereum community for the robust infrastructure
  • All contributors who have helped improve Vixy
  • The Rust community for excellent tooling and libraries

Need Help? Check our documentation or open an issue.

About

Vibing the Ethereum EL and CL Proxy

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors 3

  •  
  •  
  •