{"id":39103470,"url":"https://github.com/eigerco/axelar-relayer-core","last_synced_at":"2026-01-17T19:17:51.478Z","repository":{"id":267953639,"uuid":"881532307","full_name":"eigerco/axelar-relayer-core","owner":"eigerco","description":null,"archived":false,"fork":false,"pushed_at":"2025-10-08T10:29:18.000Z","size":637,"stargazers_count":4,"open_issues_count":5,"forks_count":2,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-10-08T11:29:15.813Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eigerco.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-10-31T19:02:34.000Z","updated_at":"2025-09-23T13:38:18.000Z","dependencies_parsed_at":null,"dependency_job_id":"b0c603d9-4dd2-4326-a841-d4ebe9058235","html_url":"https://github.com/eigerco/axelar-relayer-core","commit_stats":null,"previous_names":["eigerco/axelar-relayer-core"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/eigerco/axelar-relayer-core","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eigerco%2Faxelar-relayer-core","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eigerco%2Faxelar-relayer-core/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eigerco%2Faxelar-relayer-core/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eigerco%2Faxelar-relayer-core/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eigerco","download_url":"https://codeload.github.com/eigerco/axelar-relayer-core/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eigerco%2Faxelar-relayer-core/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28516698,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T18:55:29.170Z","status":"ssl_error","status_checked_at":"2026-01-17T18:55:03.375Z","response_time":85,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-17T19:17:50.755Z","updated_at":"2026-01-17T19:17:51.471Z","avatar_url":"https://github.com/eigerco.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Axelar Relayer core libraries\n\nThis repo provides building blocks for Axelar\u003c\u003eBlockchain Relayer\n\n## Relayer Architecture Overview\n\n```mermaid\ngraph TD\n    subgraph \"Relayer System\"\n        subgraph \"Amplifier to Blockchain Flow\"\n            amp_sub[Amplifier Subscriber]\n            tasks_queue[Amplifier Tasks Queue]\n            bcx_ing[Blockchain Ingester]\n        end\n\n        subgraph \"Blockchain to Amplifier Flow\"\n            bcx_sub[Blockchain Subscriber]\n            events_queue[Amplifier Events Queue]\n            amp_ing[Amplifier Ingester]\n        end\n    end\n\n    %% External systems\n    amp_api[/\"Amplifier REST API\"\\]\n    bcx[\"Blockchain\"]\n\n    %% Amplifier to Blockchain flow\n    amp_api --\u003e|amplifier tasks| amp_sub\n    amp_sub --\u003e|pushes amplifier tasks| tasks_queue\n    tasks_queue --\u003e|consumes amplifier tasks| bcx_ing\n    bcx_ing --\u003e|transforms \u0026 includes amplifier tasks| bcx\n\n    %% Blockchain to Amplifier flow\n    bcx --\u003e|blockchain events| bcx_sub\n    bcx_sub --\u003e|transforms to amplifier events| events_queue\n    events_queue --\u003e|consumes amplifier events| amp_ing\n    amp_ing --\u003e|sends amplifier events| amp_api\n\n    %% Styling\n    classDef component fill:#d9d2e9,stroke:#674ea7,stroke-width:2px;\n    classDef queue fill:#ffe6cc,stroke:#d79b00,stroke-width:2px;\n    classDef api fill:#d5e8d4,stroke:#82b366,stroke-width:3px,color:#000,font-weight:bold,font-size:18px;\n    classDef blockchain fill:#dae8fc,stroke:#6c8ebf,stroke-width:3px,color:#000,font-weight:bold,font-size:18px;\n\n    class amp_sub,bcx_ing,bcx_sub,amp_ing component;\n    class tasks_queue,events_queue queue;\n    class amp_api api;\n    class bcx blockchain;\n\n    %% Styling\n    classDef component stroke:#333,stroke-width:2px;\n    classDef queue fill:#ff9,stroke:#333,stroke-width:2px;\n    classDef external fill:#bbf,stroke:#333,stroke-width:1px;\n\n    class amp_sub,bcx_ing,bcx_sub,amp_ing component;\n    class tasks_queue,events_queue queue;\n    class amp_api,bcx external;\n```\n\n## Bidirectional Flow Architecture\n\nThe relayer establishes bidirectional communication between an Amplifier API and a blockchain. It consists of these main flows:\n\n### Amplifier to Blockchain Flow\n\n- **Amplifier Subscriber**: Subscribes to the Amplifier REST API and receives amplifier tasks then sends them to queue\n- **Amplifier Tasks Queue**: Stores amplifier tasks\n- **Blockchain Ingester**: Consumes tasks from the queue, transforms them to a compatible format, and includes them in the blockchain\n\n### Blockchain to Amplifier Flow\n\n- **Blockchain Subscriber**: Subscribes to blockchain events, transforms them into amplifier events and sends to queue\n- **Amplifier Events Queue**: Stores amplifier events\n- **Amplifier Ingester**: Consumes events from the queue and sends them to the Amplifier API\n\n## Internal Relayer Architecture\n\nThe relayer is designed as 4 components: 2 ingesters \u0026 2 subscribers - 1 for each chain (Axelar/amplifier API and the connecting chain)\n\n**Important for Blockchain Integration**: The [amplifier-ingester](./crates/amplifier-ingester/README.md) and [amplifier-subscriber](./crates/amplifier-subscriber/README.md) components are generic and don't need modification. To integrate a new blockchain, implement only the blockchain-specific ingester and subscriber that interact with your blockchain and the message queues.\n\n**Implementation Reference**: When implementing blockchain-specific ingester and subscriber components, refer to the [amplifier-ingester](./crates/amplifier-ingester/) and [amplifier-subscriber](./crates/amplifier-subscriber/) implementations as examples of how to structure your components, handle message queues, implement health checks, and integrate with the infrastructure layer.\n\n\n**Supervisor**: There's a [supervisor](./crates/supervisor) crate allowing start of all relayer components that implement `Worker` trait inside single binary\n\n```rust\npub trait Worker: Send {\n    /// do work\n    fn do_work\u003c's\u003e(\u0026's mut self) -\u003e Pin\u003cBox\u003cdyn Future\u003cOutput = eyre::Result\u003c()\u003e\u003e + 's\u003e\u003e;\n}\n\nSupervisor **SHOULD BE USED ONLY** in development env as it simplifies start of all relayer components.\n```\n\n### Blockchain-Specific Configuration\n\n#### BigInt Precision for Token Amounts\n\nThe `amplifier-api` crate provides compile-time configuration to optimize numeric precision for your specific blockchain. See the [amplifier-api README](./crates/amplifier-api/README.md#bigint-type-configuration) for details.\n\n#### TLS Certificate Configuration\n\nThe relayer requires TLS certificates to authenticate with the Amplifier API. You have two options:\n\n##### Option 1: Direct Certificate (Development/Testing)\n\nStore the certificate and private key directly in the configuration:\n\n```toml\n[amplifier]\n# Certificate + private key in PEM format\nidentity = '''\n-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n'''\n```\n\n**⚠️ Warning**: This method stores the private key in plaintext and should only be used for development.\n\n##### Option 2: Google Cloud KMS (Production)\n\nFor production deployments, use Google Cloud KMS to secure your private keys:\n\n```toml\n[amplifier]\n# Only the public certificate is stored locally\ntls_public_certificate = '''\n-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n'''\n\n[gcp.kms]\nproject_id = \"your-gcp-project\"\nlocation = \"global\"\nkeyring = \"amplifier_api_keyring\"\ncryptokey = \"amplifier_api_signing_key\"\n```\n\nWith KMS:\n- Private keys never leave Google Cloud\n- All signing operations happen within KMS\n- Keys can be rotated without changing the relayer configuration\n- Access is controlled through GCP IAM\n\n##### Environment Variables\n\nTLS configuration can also be provided via environment variables:\n\n```bash\n# For direct certificate (base64 encoded)\nexport RELAYER_AMPLIFIER_IDENTITY=\"\u003cbase64-encoded-pem\u003e\"\n\n# For KMS with public certificate\nexport RELAYER_AMPLIFIER_TLS_PUBLIC_CERTIFICATE=\"\u003cbase64-encoded-cert\u003e\"\nexport RELAYER_GCP_KMS_PROJECT_ID=\"your-project\"\nexport RELAYER_GCP_KMS_LOCATION=\"global\"\nexport RELAYER_GCP_KMS_KEYRING=\"amplifier_api_keyring\"\nexport RELAYER_GCP_KMS_CRYPTOKEY=\"amplifier_api_signing_key\"\n```\n\n### Core Libraries\n\n- **[amplifier-api](./crates/amplifier-api/README.md)**: Rust client for the Axelar Amplifier API with configurable BigInt precision for different blockchains\n- **[bin-util](./crates/bin-util/README.md)**: Common binary utilities for all relayer components including configuration management, health checks, telemetry, logging, and metrics\n- **[infrastructure](./crates/infrastructure/README.md)**: Storage bus implementations providing abstraction for message queuing (GCP Pub/Sub, NATS) and key-value storage\n- **[terraform](./terraform/README.md)**: Infrastructure as Code for provisioning GCP resources (Pub/Sub, KMS, Memorystore, IAM, K8s)\n\n#### Components\n\n1. **Supervisor**(optional development optimized setup):\n\n   - Runs on its own dedicated thread with a Tokio runtime\n   - Spawns and monitors worker threads only for the components selected via CLI\n   - Detects crashes and automatically restarts failed components\n   - Provides a graceful shutdown period when termination is requested\n   - Is fully optional\n\n2. **Termination Handling**:\n\n   - A dedicated thread listens for Ctrl+C signals\n   - Uses an CancellationToken as a shared termination flag\n   - When Ctrl+C is received, the CancellationToken is set to true\n   - All components, including optional supervisor, watch this CancellationToken\n   - Upon termination, components have graceful period to finish current work\n\n3. **Worker Components**:\n\n   - Each component (Amplifier Subscriber, Blockchain Ingester, Blockchain Subscriber, Amplifier Ingester) runs isolated\n   - Components check the termination flag regularly and shut down when needed\n   - Isolation ensures a failure in one component doesn't affect others\n   - It's up to the implementation to run all components at once (and isolate via supervisor) or as separate binaries\n\n4. **Queue Abstraction**:\n   - Queue is push based\n   - Currently implemented using [NATS](https://nats.io/) and [GCP](https://cloud.google.com/pubsub?hl=en)\n   - Abstraction allows for easy replacement with different queue technologies\n   - Components interact with queues only through trait interfaces, maintaining loose coupling\n   - Supports horizontal scaling by allowing multiple instances to consume from the same queue\n\nThe supervisor is optional, and each component can be started as a separate binary.\n\n## Development Environment\n\n### Using Nix\n\nThis project includes a Nix flake that provides a development shell with all necessary tooling. This ensures consistent development environments across different machines.\n\nTo use the Nix development environment:\n\n1. **Install Nix** (if not already installed):\n   ```bash\n   # On macOS or Linux\n   curl -L https://nixos.org/nix/install | sh\n   ```\n\n2. **Enable flakes** (if not already enabled):\n   ```bash\n   echo \"experimental-features = nix-command flakes\" \u003e\u003e ~/.config/nix/nix.conf\n   ```\n\n3. **Enter the development shell**:\n   ```bash\n   nix develop\n   ```\n\nThe development shell includes:\n- **Rust toolchain**: stable Rust with cargo, clippy, rustfmt, and rust-analyzer\n- **NATS tools**: natscli and nats-server for local testing\n- **Google Cloud SDK**: for working with GCP services\n- **OpenTofu**: for managing Terraform infrastructure\n- **cargo-make**: for task automation\n- **Development tools**: nixd, pkg-config, vscode-lldb\n\nAll tools are automatically available in your PATH when you enter the Nix shell.\n\n## Running the Components\n\n### Configuration\n\nBefore running the components, you need to create a configuration file. An example configuration file is provided in `config-example.toml`. You can copy this file and modify it according to your needs:\n\n```bash\ncp config-example.toml relayer-config.toml\n```\n\nEdit the `relayer-config.toml` file to configure:\n\n- Amplifier API configuration (chain name, URL, TLS certificates)\n- Backend configuration (NATS or GCP Pub/Sub)\n- TLS authentication (direct certificate or GCP KMS)\n- Tickrate for processing events\n- Health check endpoints\n\nConfig file is fully optional and app could be configured via env vars with prefix `RELAYER_`\n\n\n### Running Amplifier Ingester\n\n```bash\n# Build the ingester\ncargo build --bin amplifier-ingester\n\n# Run with default config path (looks for relayer-config.toml in current directory)\n./target/debug/amplifier-ingester\n\n# Or specify a custom config path\n./target/debug/amplifier-ingester --config /path/to/your/config.toml\n```\n\n### Running Amplifier Subscriber\n\n```bash\n# Build the subscriber\ncargo build --bin amplifier-subscriber\n\n# Option 1: Run with environment variables only (no config file needed)\nexport RELAYER_HEALTH_CHECK_PORT=8080\nexport RELAYER_CHAIN=\"ethereum\"\nexport RELAYER_TICKRATE=\"5s\"\n# ... set other required variables\n./target/debug/amplifier-subscriber\n\n# Option 2: Run with default config path (looks for relayer-config.toml in current directory)\n./target/debug/amplifier-subscriber\n\n# Option 3: Specify a custom config path\n./target/debug/amplifier-subscriber --config /path/to/your/config.toml\n```\n\n### Running with Specific Backend\n\nBy default, both components are built with GCP support as the message queue backend. To use NATS instead, compile with the `nats` feature:\n\n```bash\n# Build with NATS backend support (requires disabling default GCP features)\ncargo build --bin amplifier-ingester --no-default-features --features nats\ncargo build --bin amplifier-subscriber --no-default-features --features nats\n```\n\n### Health Checks\n\nOnce running, you can check the health of the components by sending an HTTP request to the configured health check endpoints:\n\n```bash\n# Check health of a component (assuming default port 8080)\ncurl http://localhost:8080/healthz\n\n# Check readiness of a component\ncurl http://localhost:8080/readyz\n```\n\n## Docker Deployment\n\nThe Axelar Relayer Core components can be containerized using Docker. Dockerfiles are provided for both the amplifier-ingester and amplifier-subscriber components.\n\n### Building Docker Images\n\nTo build the Docker images:\n\n```bash\n# For the ingester with default backend (GCP)\ndocker build -t axelar-amplifier-ingester -f crates/amplifier-ingester/Dockerfile .\n\n# For the subscriber with default backend (GCP)\ndocker build -t axelar-amplifier-subscriber -f crates/amplifier-subscriber/Dockerfile .\n```\n\n### Using NATS Instead of GCP\n\nGCP is default backend as it is fully implemented and **SHOULD BE** in production. Nats is used as simplified way to support easy development.\n\nYou can build with NATS support by using build arguments:\n\n```bash\n# Build with NATS backend\ndocker build -t axelar-amplifier-ingester-nats \\\n  --build-arg FEATURES=nats \\\n  -f crates/amplifier-ingester/Dockerfile .\n\ndocker build -t axelar-amplifier-subscriber-nats \\\n  --build-arg FEATURES=nats \\\n  -f crates/amplifier-subscriber/Dockerfile .\n```\n\n### Running Docker Containers\n\n**Option 1: Using environment variables only (recommended for containers)**\n\n```bash\n# Run the ingester with environment variables only\ndocker run -p 8080:8080 \\\n  -e RELAYER_HEALTH_CHECK_PORT=8080 \\\n  -e RELAYER_TICKRATE=\"5s\" \\\n  -e RELAYER_CHAIN=\"ethereum\" \\\n  -e RELAYER_AMPLIFIER_URL=\"https://api.amplifier.axelar.network\" \\\n  axelar-amplifier-ingester\n\n# Run the subscriber with environment variables only\ndocker run -p 8081:8080 \\\n  -e RELAYER_HEALTH_CHECK_PORT=8080 \\\n  -e RELAYER_CHAIN=\"ethereum\" \\\n  -e RELAYER_TICKRATE=\"5s\" \\\n  axelar-amplifier-subscriber\n```\n\n**Option 2: Using a configuration file**\n\n```bash\n# Run the ingester\ndocker run -p 8080:8080 -v /path/to/your/relayer-config.toml:/app/relayer-config.toml axelar-amplifier-ingester\n\n# Run the subscriber\ndocker run -p 8081:8080 -v /path/to/your/relayer-config.toml:/app/relayer-config.toml axelar-amplifier-subscriber\n```\n\nBy default, the health check endpoints will be available at:\n\n- http://localhost:8080/healthz and http://localhost:8080/readyz for the ingester\n- http://localhost:8081/healthz and http://localhost:8081/readyz for the subscriber (mapped to a different host port to avoid conflicts)\n\n### Environment Variables Override\n\nWhen using a config file, you can still override specific configuration options using environment variables:\n\n```bash\ndocker run -p 8080:8080 \\\n  -v /path/to/your/relayer-config.toml:/app/relayer-config.toml \\\n  -e \"RELAYER_TICKRATE=10s\" \\\n  -e \"RELAYER_NATS_CONNECTION_URL=nats://nats-server:4222\" \\\n  axelar-amplifier-ingester\n```\n\n### Docker Compose\n\nThe project includes dedicated Docker Compose files for both GCP and NATS backends:\n\n- `docker-compose.gcp.yaml` - For running with GCP (default) backend\n- `docker-compose.nats.yaml` - For running with NATS backend\n\n#### Using the GCP Backend\n\nTo run the components with GCP as the backend:\n\n```bash\n# First ensure you have a configuration file\ncp relayer-config-example.toml relayer-config.toml\n\n# Edit the relayer-config.toml to configure your GCP settings\n# Make sure your GCP configuration is properly set in the [gcp] section\n\n# Start all services using the GCP compose file\ndocker compose -f docker-compose.gcp.yaml up -d\n\n# Check the status of the services\ndocker compose -f docker-compose.gcp.yaml ps\n\n# View the logs\ndocker compose -f docker-compose.gcp.yaml logs -f\n```\n\nFor GCP, you may need to provide authentication credentials by uncommenting the relevant volume mounts and environment variables in the Docker Compose file.\n\n#### Using the NATS Backend\n\n**IMPORTANT**: Nats is used only for development and **SHOULD NOT** be used in production as the implementation is not robust enough and wasn't finished fully\n\nTo run the components with NATS as the backend:\n\n```bash\n# First ensure you have a configuration file\ncp relayer-config-example.toml relayer-config.toml\n\n# Edit the relayer-config.toml to configure your NATS settings\n# Make sure your NATS configuration is properly set in the [nats] section\n\n# Start all services using the NATS compose file\ndocker compose -f docker-compose.nats.yaml up -d\n\n# Check the status of the services\ndocker compose -f docker-compose.nats.yaml ps\n\n# View the logs\ndocker compose -f docker-compose.nats.yaml logs -f\n```\n\nThe NATS server exposes:\n\n- Port 4222 for client connections\n- Port 8222 for HTTP monitoring\n\nThe ingester and subscriber configuration automatically connects to the NATS server using the internal Docker network.\n\n#### Stopping Services\n\nTo stop the services:\n\n```bash\ndocker compose -f docker-compose.\u003cbackend\u003e.yaml down\n```\n\nWhere `\u003cbackend\u003e` is either `gcp` or `nats`.\n\n\n#### Telemetry\n\nOpentelemetry is added to all components and could be tested via prometheus/grafana bundled in docker-compose files in this repo\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feigerco%2Faxelar-relayer-core","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feigerco%2Faxelar-relayer-core","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feigerco%2Faxelar-relayer-core/lists"}