← Back to list

Running a Hyperbridge Relayer : A Complete Guide

As blockchain ecosystems become increasingly fragmented across different chains, the ability to move assets and messages between them…

Blockops Network in Blockops Network · 2025-09-18 19:36 · 50 claps · 10.0 min read
#hyperbridge #relayer #cross-chain-bridge #interoperability #web3
Open on Medium ↗
Wiki topics: RAG · RAG & Retrieval CRY · Crypto & Web3 🏃 · Running & Endurance

Running Hyperbridge Relayers: A Complete Guide

As blockchain ecosystems become increasingly fragmented across different chains, the ability to move assets and messages between them becomes critical. Traditional bridges have lost over $2.8 billion to hacks because they rely on small groups of validators who can be compromised or collude.

This is where Hyperbridge changes the game. Instead of trusting a committee, Hyperbridge uses cryptographic proofs that can be verified by anyone. But these proofs don’t move themselves — they need relayers to transmit them across chains.

Think of relayers as the postal service of the blockchain world. They pick up messages from one chain and deliver them to another, getting paid for successful deliveries. What makes Hyperbridge special is that anyone can become a relayer — no permission needed, no stake required.

What Makes Hyperbridge Relayers Different?

Traditional cross-chain protocols require relayers to:

  • Lock up significant capital as stake (often $100K+)
  • Get whitelisted by the protocol team
  • Trust other validators in the network

Hyperbridge removes all these barriers:

  • Zero stake required — Start relaying immediately
  • Fully permissionless — No approval process needed
  • Trust-free — Cryptographic proofs ensure security
  • Competitive marketplace — Multiple relayers race to deliver messages

This means you can start earning rewards today with just a server and some gas funds.

Understanding the Two Types of Relayers

Before diving into setup, it’s important to understand that Hyperbridge has two distinct relayer types, each serving a different purpose:

Consensus Relayers

A Consensus Relayer in Hyperbridge is a permissionless node that monitors a source blockchain, generates verifiable proofs of its finalized state, and submits them to Hyperbridge so the network can stay in sync. The first relayer to submit a valid proof is rewarded in $BRIDGE tokens, making it a competitive process where rewards directly depend on how quickly and reliably the relayer updates the system’s consensus state.

What they do: Monitor blockchains and submit consensus proofs to Hyperbridge Compensation: BRIDGE tokens from the protocol Requirements: No upfront funding needed Best for: Consistent, predictable rewards

Messaging Relayers

A Messaging Relayer in Hyperbridge is a permissionless operator that delivers user-initiated messages across chains. Users pay fees upfront (in stablecoins like DAI) to cover delivery and execution, and relayers compete to process these requests profitably. Their earnings depend on how efficiently they can detect, relay, and execute messages, making performance and infrastructure speed critical to success.

What they do: Deliver cross-chain messages between chains Compensation: DAI stablecoins from users & daily incentives capped at 6kb of messages per day Requirements: Gas funds on each supported chain

You can run either type or both, you can use separate docker configuration files or bundle them together in a docker-compose file

Prerequisites and System Requirements

To maximize the performance of your relayers and ensure they relay proofs and messages effectively, it’s critical to optimize your host machine setup. Relaying is highly competitive, and your rewards are directly tied to the volume and efficiency of the activity your node can successfully process.

Before starting, ensure you have:

Hardware Requirements (Minimum)

  • CPU: 4 cores
  • RAM: 4GB
  • Storage: 100GB SSD
  • Network: 100Mb/s connection

Software Requirements

Before proceeding, make sure your server has the required tools installed, run the following commands on your server to setup docker and docker-compose at the minimum:

# install_dependencies.sh

## Install Docker - the container runtime for our relayers
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

## Install Docker Compose - for managing multiple containers
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

## Install jq - for parsing JSON responses
sudo apt-get update && sudo apt-get install -y jq

## Verify everything is installed correctly
docker --version
docker-compose --version
jq --version

You should see version numbers for all three tools:

Docker version 24.0.7, build afdd53b
docker-compose version 1.29.2
Jq-1.6

Setting Up Your Environment

Now that you have the prerequisites installed, let’s create a proper directory structure for your relayer.

Creating Your Workspace

## Create and navigate to your relayer directory
mkdir -p ~/hyperbridge-relayer
cd ~/hyperbridge-relayer

## Create subdirectories for different components
mkdir -p config data logs keys

## Secure the keys directory
chmod 700 keys

## Verify the structure was created
tree -L 1

You should see:

├── config
├── data
├── keys
└── logs

Getting the Official Docker Images

Hyperbridge provides pre-built Docker images, so you don’t need to compile anything:

## Pull the messaging relayer (Tesseract)
docker pull polytopelabs/tesseract:latest

## Pull the consensus relayer
docker pull polytopelabs/tesseract-consensus:latest

## Verify the images were downloaded
docker images | grep polytope

You should see both images listed:


polytopelabs/tesseract-consensus            latest    4583b2c96f3f   2 days ago    184MB
polytopelabs/tesseract                      latest    785c94acf9a2   2 days ago    155MB

Finding and Configuring RPC Endpoints

Your relayer needs to communicate with the blockchains it’s supporting. This requires RPC endpoints — think of them as the phone numbers your relayer uses to call each blockchain.

Understanding RPC Requirements

Different chains have different requirements:

For EVM chains (Ethereum, Arbitrum, Optimism, etc.)

  • HTTP/HTTPS RPC endpoint for transactions
  • Debug namespace enabled for transaction tracing
  • Etherscan API key for gas price data

For Substrate chains (Polkadot, Kusama parachains)

  • WebSocket RPC endpoint
  • Unsafe RPC methods enabled

For Consensus relaying (additional requirements)

  • Beacon chain endpoints for Ethereum
  • Specific L2 contract addresses

Finding and Configuring RPC Endpoints

Your relayer needs reliable RPC endpoints to communicate with other blockchains. For best performance, we recommend using our RPC which provides both execution and beacon chain endpoints that are fully optimized for relayer operations.

We currently provide endpoints for Polkadot/Kusama, Ethereum, Polygon, BNB Chain, Arbitrum, Optimism, Avalanche, Solana, Starknet, Sui, Aptos, Base with support extending to 50+ protocols.

To get started, create your account if you haven’t already: How to Create an Account

Then get your API endpoints from our API Service: API Service Documentation

Make sure to grab WebSocket endpoints if you’re running a consensus relayer — you’ll need real-time updates for consensus proofs.

You’ll also need Etherscan API keys for gas prices, You can obtain the required etherscan API key by following this guide for the appropriate network. Do note that since Ethereum and its L2s all use Ether as the gas token. They can all share the same etherscan API key.

Deploying Your First Messaging Relayer

Let’s start with a messaging relayer, which is simpler to set up and can start earning DAI rewards immediately.

Creating Your Configuration

First, let’s create a configuration file that tells your relayer which chains to support and how to connect to them.

Create config/messaging-config.toml:

[hyperbridge]
state_machine = "POLKADOT-3367"  # Hyperbridge on Polkadot mainnet
hashing = "Keccak"
signer = "" // add your hyperbridge signer key here
consensus_state_id = "DOT0"
rpc_ws = "wss://nexus-rpc.hyperbridge.blockops.network:443"

## Ethereum Mainnet
[ethereum]
type = "ethereum"
poll_interval = 15
state_machine = "EVM-1"
rpc_urls = [
    "https://ethereum-mainnet.blockops.network/YOUR_API_KEY"  # Replace YOUR_API_KEY
]
consensus_state_id = "ETH0"
etherscan_api_key = "YOUR_ETHERSCAN_KEY"
ismp_host = "0x792A6236AF69787C40cF76b69B4c8c7B28c4cA20"
signer = "YOUR_PRIVATE_KEY"  # Your wallet private key (without 0x prefix)
tracing_batch_size = 5
query_batch_size = 10000
gas_price_buffer = 1

## Binance Smart Chain
[bsc]
type = "evm"
poll_interval = 15
state_machine = "EVM-56"
rpc_urls = [
    "https://bsc-mainnet.blockops.network/YOUR_API_KEY"
consensus_state_id = "BSC0"
etherscan_api_key = "YOUR_ETHERSCAN_KEY"
ismp_host = "0x24B5d421Ec373FcA57325dd2F0C074009Af021F7"
signer = "YOUR_PRIVATE_KEY"  # Same key works for all chains
tracing_batch_size = 5
query_batch_size = 10000

## Gnosis Chain
[gnosis]
type = "evm"
poll_interval = 15
state_machine = "EVM-100"
rpc_urls = [
    "https://gnosis-mainnet.blockops.network/YOUR_API_KEY"  # Replace YOUR_API_KEY
]
consensus_state_id = "GNO0"
etherscan_api_key = "YOUR_ETHERSCAN_KEY"
ismp_host = "0x50c236247447B9d4Ee0561054ee596fbDa7791b1"
signer = "YOUR_PRIVATE_KEY"  # Same key works for all chains
tracing_batch_size = 5
query_batch_size = 10000

## Relayer Business Logic
[relayer]
minimum_profit_percentage = 1  # Require 1% profit minimum
unprofitable_retry_frequency = 120  # Retry every 2 minutes

# the delivery endpoint should have all the evm chain configured above
delivery_endpoints = [
    "EVM-1",    # Ethereum
    "EVM-100",  # Gnosis
    "EVM-56"    # BSC
]

Remember to replace:

  • YOUR_API_KEY — Get this from your Blockops account
  • YOUR_ETHERSCAN_KEY — From etherscan.io (works for Ethereum and L2s)
  • YOUR_PRIVATE_KEY — Your relayer wallet private key (keep this secure!)

Now the next step is to run the messaging relayers. Now let’s run your relayer:

docker run -d \
  --name=tesseract \
  --network=host \
  --restart=always \
  --volume=$(pwd)/config:/home/root:ro \
  --volume=$(pwd)/data:/data \
  --volume=$(pwd)/logs:/logs \
  polytopelabs/tesseract:latest \
  --config=/home/root/messaging-config.toml \
  --db=/data/tesseract.db

## Check if it started successfully
docker ps | grep tesseract

You should see your container running:

 tech-blog docker ps | grep tesseract
3d583ba280cf   polytopelabs/tesseract:latest   "./tesseract --confi..."   4 minutes ago   Up 4 minutes             tesseract
➜  tech-blog 

Verifying Your Relayer is Working

Let’s check the logs to ensure everything is running correctly:

tech-blog docker logs -f tesseract
2025-09-16T19:10:10.621154Z  INFO tesseract::cli: 🧊 Initializing tesseract    
2025-09-16T19:10:10.666453Z  INFO quaint::pooled: Starting a sqlite pool with 25 connections.
2025-09-16T19:10:10.738819Z  INFO migration_core::commands::apply_migrations: Analysis run in 27ms analysis_duration_ms=27
2025-09-16T19:10:10.739218Z  INFO Applying migration{migration_name="20240227154307_"}: migration_core::commands::apply_migrations: Applying `20240227154307_` script="-- CreateTable\nCREATE TABLE \"Deliveries\" (\n    \"id\" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,\n    \"hash\" TEXT NOT NULL,\n    \"source_chain\" TEXT NOT NULL,\n    \"dest_chain\" TEXT NOT NULL,\n    \"delivery_type\" INTEGER NOT NULL,\n    \"created_at\" INTEGER NOT NULL,\n    \"height\" INTEGER NOT NULL\n);\n"
2025-09-16T19:10:10.749442Z  INFO Applying migration{migration_name="20240315095442_pending_withdrawals"}: migration_core::commands::apply_migrations: Applying `20240315095442_pending_withdrawals` script="-- CreateTable\nCREATE TABLE \"PendingWithdrawal\" (\n    \"id\" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,\n    \"dest\" TEXT NOT NULL,\n    \"encoded\" BLOB NOT NULL\n);\n"
2025-09-16T19:10:10.751924Z  INFO Applying migration{migration_name="20240327084356_unproitable_retries"}: migration_core::commands::apply_migrations: Applying `20240327084356_unproitable_retries` script="-- CreateTable\nCREATE TABLE \"UnprofitableMessages\" (\n    \"id\" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,\n    \"dest\" TEXT NOT NULL,\n    \"encoded\" BLOB NOT NULL\n);\n"
2025-09-16T19:10:13.821654Z  INFO tesseract_evm: Initialized height for Evm(100) at 42155907    
2025-09-16T19:10:15.173344Z  INFO tesseract_evm: Initialized height for Evm(1) at 23377529    
2025-09-16T19:10:16.419903Z  INFO tesseract_evm: Initialized height for Evm(56) at 61401324    
2025-09-16T19:10:18.102534Z  INFO tesseract_substrate: Initialized height for Polkadot(3367)->Evm(100) at 6996392    
2025-09-16T19:10:19.517199Z  INFO tesseract_substrate: Initialized height for Polkadot(3367)->Evm(1) at 6996392    
2025-09-16T19:10:20.999692Z  INFO tesseract_substrate: Initialized height for Polkadot(3367)->Evm(56) at 6996392    
2025-09-16T19:10:21.011825Z  INFO tesseract::cli: 💬 Initialized messaging tasks    
2025-09-16T19:10:21.011907Z  INFO tesseract::fees: Auto-withdraw frequency set to 86400s
2025-09-16T19:10:21.014645Z  INFO tesseract::fees: Minimum auto-withdrawal amount set to $100.000000000000000000
2025-09-16T19:10:52.940253Z  INFO tesseract_messaging: Skipping latest finalized height 61401324 on Polkadot(3367), no new messages from EVM-56 in range 61401324..=61401324
2025-09-16T19:11:21.084436Z  INFO tesseract_primitives: Waiting for challenge period 90s for EVM-100 on Polkadot(3367)    
2025-09-16T19:11:45.509441Z  INFO tesseract_messaging: Skipping latest finalized height 61401387 on Polkadot(3367), no new messages from EVM-56 in range 61401324..=61401387
2025-09-16T19:12:03.742736Z  INFO tesseract_primitives: Waiting for challenge period 90s for EVM-1 on Polkadot(3367) 

Congratulations! Your messaging relayer is now running on mainnet.

Running a Consensus Relayer

Consensus relayers submit blockchain state proofs to Hyperbridge and earn BRIDGE tokens. They require more complex configuration but provide steady rewards.

Creating Your Consensus Configuration

Create config/consensus-config.toml:

```toml

[hyperbridge]
type = "grandpa"
rpc_ws = 

[hyperbridge.substrate]
state_machine = "POLKADOT-3367"
hashing = "Keccak"
rpc_ws = "wss://nexus-rpc.hyperbridge.blockops.network:443"

[hyperbridge.grandpa]
rpc = "wss://nexus-rpc.hyperbridge.blockops.network"
slot_duration = 12000
para_ids = [3367]

[ethereum]
type = "ethereum"
state_machine = "EVM-1"
# This should be execution layer rpc
rpc_urls = [
    "https://eth.rpc.blockops.network?api_key=<api_key>"
]
consensus_state_id = "ETH0"
etherscan_api_key = "YOUR_ETHERSCAN_KEY"
ismp_host = "0x792A6236AF69787C40cF76b69B4c8c7B28c4cA20"
signer = "0xYOUR_PRIVATE_KEY"

[ethereum.host]
beacon_http_urls = [
    "Your_beacon_node_url"
]
consensus_update_frequency = 60

[gnosis]
type = "gnosis"
state_machine = "EVM-100"
rpc_urls = [
    "https://gnosis.rpc.blockops.network?<api_key>"
]
consensus_state_id = "GNO0"
etherscan_api_key = "YOUR_ETHERSCAN_KEY"
ismp_host = "0x50c236247447B9d4Ee0561054ee596fbDa7791b1"
signer = "0xYOUR_PRIVATE_KEY"

[gnosis.host]
beacon_http_urls = [
    "You_beano_url"
]
consensus_update_frequency = 60

[arbitrum]
type = "arbitrum_orbit"
state_machine = "EVM-42161"
rpc_urls = [
    "https://arbitrum.rpc.blockops.network?api_key="
]
consensus_state_id = "ARB0"
etherscan_api_key = "YOUR_ETHERSCAN_KEY"
ismp_host = "0xE05AFD4Eb2ce6d65c40e1048381BD0Ef8b4B299e"
signer = "0xYOUR_PRIVATE_KEY"
gas_price_buffer = 8

[arbitrum.host]
# this shold be L1 execution rpc
beacon_rpc_url = [
    "https://arbitrum.rpc.blockops.network?api_key="
]
rollup_core = "0x4DCeB440657f21083db8aDd07665f8ddBe1DCfc0"
l1_state_machine = "EVM-1"
l1_consensus_state_id = "ETH0"
consensus_update_frequency = 60

[bsc]
type = "bsc"
state_machine = "EVM-56"
rpc_urls = [
    "https://bsc.rpc.blockops.network?api_key="
]
consensus_state_id = "BSC0"
etherscan_api_key = "${ETHERSCAN_KEY}"
ismp_host = "0x24B5d421Ec373FcA57325dd2F0C074009Af021F7"
signer = "0xYOUR_PRIVATE_KEY"

[bsc.host]
consensus_update_frequency = 60
epoch_length = 1000

[relayer]
challenge_period = 0
enable_hyperbridge_consensus = false
maximum_update_intervals = [
    [{state_id = "EVM-1", consensus_state_id = "ETH0"}, 900],
    [{state_id = "EVM-100", consensus_state_id = "GNO0"}, 420],
    [{state_id = "EVM-56", consensus_state_id = "BSC0"}, 300]
]

You should see:

➜  tech-blog docker ps                            
CONTAINER ID   IMAGE                                     COMMAND                  CREATED          STATUS          PORTS                                         NAMES
19f4cacb7bb0   polytopelabs/tesseract-consensus:latest   "./tesseract-consens..."   20 seconds ago   Up 20 seconds                                                 tesseract-consensus
3d583ba280cf   polytopelabs/tesseract:latest             "./tesseract --confi..."   4 hours ago      Up 4 hours                                                    tesseract

➜ tech-blog

➜ tech-blog docker logs tesseract-consensus      
2025-09-16T22:47:23.270109Z  INFO tesseract_consensus::cli: 🧊 Initializing tesseract consensus    
2025-09-16T22:47:26.860297Z  INFO redis_async::reconnect: Attempting to reconnect, current state: ReconnectState::NotConnected    
2025-09-16T22:47:26.874052Z  INFO redis_async::reconnect: Connection established    
2025-09-16T22:47:37.103871Z  INFO redis_async::reconnect: Attempting to reconnect, current state: ReconnectState::NotConnected    
2025-09-16T22:47:37.107573Z  INFO redis_async::reconnect: Connection established    
2025-09-16T22:47:40.848310Z  INFO redis_async::reconnect: Attempting to reconnect, current state: ReconnectState::NotConnected    
2025-09-16T22:47:40.856722Z  INFO redis_async::reconnect: Connection established    
2025-09-16T22:47:44.192576Z  INFO redis_async::reconnect: Attempting to reconnect, current state: ReconnectState::NotConnected    
2025-09-16T22:47:44.195459Z  INFO redis_async::reconnect: Connection established    
2025-09-16T22:47:48.033398Z  INFO redis_async::reconnect: Attempting to reconnect, current state: ReconnectState::NotConnected    
2025-09-16T22:47:48.039538Z  INFO redis_async::reconnect: Connection established    
2025-09-16T22:47:51.424825Z  INFO redis_async::reconnect: Attempting to reconnect, current state: ReconnectState::NotConnected    
2025-09-16T22:47:51.428228Z  INFO redis_async::reconnect: Connection established    
2025-09-16T22:47:55.363087Z  INFO redis_async::reconnect: Attempting to reconnect, current state: ReconnectState::NotConnected    
2025-09-16T22:47:55.371333Z  INFO redis_async::reconnect: Connection established    
2025-09-16T22:47:58.963930Z  INFO tesseract: 🛰️ Transmitting consensus message from Evm(56) to Polkadot(3367)    
2025-09-16T22:47:59.128059Z  INFO redis_async::reconnect: Attempting to reconnect, current state: ReconnectState::NotConnected    
2025-09-16T22:47:59.130885Z  INFO redis_async::reconnect: Connection established    
2025-09-16T22:47:59.184667Z  INFO tesseract_substrate::extrinsic: Unsigned extrinsic successfully inserted into pool with hash: 0xbd250f2d1240a7c6fe0e788b3a4eff278bdcb995da490ed01b3c8d3b7c9f3c19    
2025-09-16T22:48:02.508161Z  INFO redis_async::reconnect: Attempting to reconnect, current state: ReconnectState::NotConnected    
2025-09-16T22:48:02.513582Z  INFO redis_async::reconnect: Connection established    
2025-09-16T22:48:02.516039Z  INFO tesseract_consensus::cli: Initializing consensus update monitoring task    
2025-09-16T22:48:02.517214Z  INFO tesseract_consensus::cli: Initialized consensus tasks    
2025-09-16T22:48:06.544686Z  INFO redis_async::reconnect: Attempting to reconnect, current state: ReconnectState::NotConnected    
2025-09-16T22:48:06.550496Z  INFO redis_async::reconnect: Connection established    
2025-09-16T22:48:57.918883Z  INFO tesseract: 🛰️ Transmitting consensus message from Evm(56) to Polkadot(3367)    
2025-09-16T22:48:58.142934Z  INFO tesseract_substrate::extrinsic: Unsigned extrinsic successfully inserted into pool with hash: 0x44342916ea7528030c12384515eb65671d58edda19baee562bc60ba88a5e317f    
2025-09-16T22:49:57.362904Z  INFO tesseract: 🛰️ Transmitting consensus message from Evm(56) to Polkadot(3367)    
2025-09-16T22:49:57.586720Z  INFO tesseract_substrate::extrinsic: Unsigned extrinsic successfully inserted into pool with hash: 0x493cc9b2476520b3f12c00e351018499596ad91105636c062f99ca037f5cb85a    
➜  tech-blog

Congratulations! Your consensus relayer is now running on mainnet.

Conclusion

You now have both relayers running successfully — your messaging relayer facilitating cross-chain communication and your consensus relayer submitting blockchain state proofs to Hyperbridge. Your relayers are now part of Hyperbridge’s decentralized infrastructure, helping secure cross-chain communication 24/7.

For further technical documentation:

Messaging Relayer Guide: https://docs.hyperbridge.network/developers/network/relayer/messaging/relayer

Consensus Relayer Guide: https://docs.hyperbridge.network/developers/network/relayer/consensus/relayer

Welcome to the Hyperbridge relayer network!


메타데이터
post_id
c42e255dcc92
slug
running-a-hyperbridge-relayer-a-complete-guide-c42e255dcc92
url
https://blog.blockops.network/running-a-hyperbridge-relayer-a-complete-guide-c42e255dcc92
canonical_url
https://blog.blockops.network/running-a-hyperbridge-relayer-a-complete-guide-c42e255dcc92
author_url
https://medium.com/@blockopsnetwork
status
ok
fetched_at
2026-07-13 06:23:13