Relayer Setup Guide
How to run your own ZKMix relayer
Relayer Setup Guide
This guide walks through the process of setting up and running your own ZKMix relayer. By operating a relayer, you provide an essential service to the ZKMix ecosystem -- enabling users to withdraw funds to fresh addresses without creating on-chain links -- and earn fees for each withdrawal you process.
Requirements
Hardware
| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 2 cores | 4+ cores |
| RAM | 2 GB | 4 GB |
| Storage | 10 GB SSD | 20 GB SSD |
| Network | 100 Mbps | 1 Gbps |
The relayer is not computationally intensive. It does not generate proofs -- it only validates and submits transactions. The primary resource requirements are network bandwidth and reliable uptime.
Software
- Node.js v18.0 or later (LTS recommended)
- npm v9.0 or later (included with Node.js)
- Solana CLI v1.17 or later (for key management)
SOL Balance
The relayer needs SOL to pay transaction fees on behalf of users. Each withdrawal transaction costs approximately 0.000005 SOL in base fees plus priority fees.
| Scenario | Recommended Balance |
|---|---|
| Low volume (< 100/day) | 0.5 SOL |
| Medium volume | 2 SOL |
| High volume (1000+/day) | 10+ SOL |
The relayer earns back more than this amount through fees, but it needs an initial float to cover gas costs before fee revenue accumulates.
Installation
Step 1: Install Node.js
If Node.js is not already installed, download it from nodejs.org or use a version manager:
# Using nvm (Linux/macOS)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
nvm install 18
nvm use 18
# Verify installation
node --version # Should output v18.x.x or later
npm --version # Should output v9.x.x or laterStep 2: Install the ZKMix Relayer
# Install globally
npm install -g @zkmix/relayer
# Verify installation
zkmix-relayer --versionAlternatively, clone the repository and build from source:
git clone https://github.com/zkmix/zkmix-relayer.git
cd zkmix-relayer
npm install
npm run buildStep 3: Generate a Relayer Keypair
The relayer needs a Solana keypair for signing transactions and receiving fees. You can generate a new keypair or use an existing one.
# Generate a new keypair
solana-keygen new --outfile ~/.config/zkmix/relayer-keypair.json
# Or if you have an existing keypair, note its path
# The relayer will use this keypair to:
# 1. Pay transaction fees (gas)
# 2. Receive relayer fees from withdrawalsFund the relayer address with SOL:
# Get the relayer's public key
solana-keygen pubkey ~/.config/zkmix/relayer-keypair.json
# Fund it (devnet)
solana airdrop 2 <RELAYER_ADDRESS> --url devnet
# Fund it (mainnet) - transfer from your wallet
solana transfer <RELAYER_ADDRESS> 2 --url mainnet-betaConfiguration
Create a configuration file at ~/.config/zkmix/relayer-config.json:
{
"network": {
"cluster": "mainnet-beta",
"rpcUrl": "https://api.mainnet-beta.solana.com",
"wsUrl": "wss://api.mainnet-beta.solana.com",
"commitment": "confirmed"
},
"relayer": {
"keypairPath": "~/.config/zkmix/relayer-keypair.json",
"port": 8080,
"host": "0.0.0.0",
"feePercentage": 0.3,
"minFee": 10000,
"maxPendingTransactions": 50,
"transactionTimeout": 60000
},
"pools": {
"supportAll": true,
"whitelist": []
},
"rateLimit": {
"maxRequestsPerMinute": 60,
"maxRequestsPerIp": 10
},
"logging": {
"level": "info",
"file": "~/.config/zkmix/relayer.log",
"maxFileSize": "50m",
"maxFiles": 5
},
"monitoring": {
"healthCheckInterval": 30000,
"balanceAlertThreshold": 100000000,
"metricsEnabled": true,
"metricsPort": 9090
}
}Configuration Options Explained
Network settings:
| Field | Description | Default |
|---|---|---|
cluster | Solana cluster to connect to | "mainnet-beta" |
rpcUrl | HTTP RPC endpoint URL | Public endpoint |
wsUrl | WebSocket endpoint for subscription | Public endpoint |
commitment | Transaction confirmation level | "confirmed" |
Using a dedicated RPC provider is strongly recommended for mainnet relayer operation. Public endpoints have rate limits that can cause failed transactions during high volume.
Relayer settings:
| Field | Description | Default |
|---|---|---|
keypairPath | Path to the relayer's Solana keypair file | Required |
port | HTTP server port | 8080 |
host | HTTP server bind address | 0.0.0.0 |
feePercentage | Fee as a percentage of the denomination | 0.3 |
minFee | Minimum fee in lamports regardless of percentage | 10000 |
maxPendingTransactions | Maximum concurrent in-flight transactions | 50 |
transactionTimeout | Timeout for transaction confirmation in ms | 60000 |
Pool settings:
| Field | Description |
|---|---|
supportAll | If true, relay withdrawals for all active pools |
whitelist | If supportAll is false, list of pool addresses to serve |
Rate limiting:
| Field | Description |
|---|---|
maxRequestsPerMinute | Global rate limit across all clients |
maxRequestsPerIp | Per-IP rate limit to prevent abuse |
Running the Relayer
Start the Relayer
# Using the globally installed package
zkmix-relayer start --config ~/.config/zkmix/relayer-config.json
# Or from the cloned repository
npm start -- --config ~/.config/zkmix/relayer-config.jsonExpected output on successful startup:
[INFO] ZKMix Relayer v1.2.0
[INFO] Loading keypair from ~/.config/zkmix/relayer-keypair.json
[INFO] Relayer address: 7xKp...3nQm
[INFO] SOL balance: 2.45 SOL
[INFO] Connecting to mainnet-beta at https://api.mainnet-beta.solana.com
[INFO] Loaded 7 active pools
[INFO] Fee: 0.3% (min 10,000 lamports)
[INFO] HTTP server listening on 0.0.0.0:8080
[INFO] Health check: OK
[INFO] Relayer is ready to accept requestsRunning as a System Service
For production deployment, run the relayer as a systemd service (Linux) to ensure automatic restarts and boot persistence:
# /etc/systemd/system/zkmix-relayer.service
[Unit]
Description=ZKMix Relayer
After=network.target
[Service]
Type=simple
User=zkmix
ExecStart=/usr/bin/node /opt/zkmix-relayer/dist/index.js --config /etc/zkmix/relayer-config.json
Restart=always
RestartSec=10
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.targetsudo systemctl enable zkmix-relayer
sudo systemctl start zkmix-relayer
sudo systemctl status zkmix-relayerRunning with Docker
A Docker image is also available:
docker run -d \
--name zkmix-relayer \
-p 8080:8080 \
-p 9090:9090 \
-v ~/.config/zkmix:/config \
zkmix/relayer:latest \
--config /config/relayer-config.jsonMonitoring
Health Check Endpoint
The relayer exposes a health check endpoint at GET /health:
curl http://localhost:8080/health{
"status": "healthy",
"uptime": 86400,
"version": "1.2.0",
"solBalance": 2450000000,
"pendingTransactions": 3,
"totalRelayed": 1247,
"totalFeesEarned": 3741000000
}Prometheus Metrics
When metrics are enabled, the relayer exposes a Prometheus-compatible metrics endpoint at the configured metricsPort:
curl http://localhost:9090/metricsAvailable metrics include:
| Metric | Type | Description |
|---|---|---|
zkmix_relayer_requests_total | Counter | Total relay requests received |
zkmix_relayer_success_total | Counter | Successfully relayed transactions |
zkmix_relayer_errors_total | Counter | Failed relay attempts |
zkmix_relayer_fees_earned_total | Counter | Total fees earned in lamports |
zkmix_relayer_sol_balance | Gauge | Current SOL balance |
zkmix_relayer_pending_transactions | Gauge | Currently in-flight transactions |
zkmix_relayer_request_duration_seconds | Histogram | Request processing time |
Balance Alerts
The relayer monitors its SOL balance and logs a warning when it drops below the configured balanceAlertThreshold. You can integrate this with external alerting systems by monitoring the log file or the Prometheus metrics.
Logs
The relayer outputs structured JSON logs that can be consumed by log aggregation tools like ELK, Loki, or Datadog.
Log Levels
| Level | Description |
|---|---|
error | Failed transactions, RPC errors, out-of-balance conditions |
warn | Low balance warnings, rate limit hits, retried transactions |
info | Successful relays, startup/shutdown events, balance reports |
debug | Detailed request/response data, transaction construction |
Log Format
{
"timestamp": "2025-03-15T14:30:22.451Z",
"level": "info",
"message": "Withdrawal relayed successfully",
"txSignature": "5K7p...2xNm",
"pool": "SOL-1",
"recipient": "8xQm...4vRk",
"fee": 3000000,
"processingTime": 2340
}Log Rotation
When using the file logger, logs are automatically rotated based on the maxFileSize and maxFiles configuration. Old log files are compressed and eventually deleted when the maximum number of retained files is reached.
Registering Your Relayer
After your relayer is running and publicly accessible, register it in the on-chain relayer registry so that SDK users can discover it automatically:
zkmix-relayer register \
--config ~/.config/zkmix/relayer-config.json \
--url "https://your-relayer-domain.com"This submits a transaction to the relayer registry program, making your relayer discoverable by the ZKMix SDK. The registration includes your fee percentage, supported pools, and endpoint URL.
Updating Registration
If you change your fee or endpoint URL, update your registration:
zkmix-relayer update-registration \
--config ~/.config/zkmix/relayer-config.json \
--url "https://new-domain.com" \
--fee 0.25Deregistering
To remove your relayer from the registry:
zkmix-relayer deregister --config ~/.config/zkmix/relayer-config.json