Configuration
Overview
Most configuration files should live under ./config
, including the signer configurations, under ./config/keys
.
Please ensure appropriate access permissions on all configuration files (for ./config/keys/*
, we recommend 0500
.
The configuration system consists of two main components:
Both files must be properly configured before starting the application. Changes to either file require restarting the container to take effect. For quick setup examples with pre-configured files, see the examples directory in our GitHub repository. |
Environment configuration (.env)
This defines some base configurations for the Relayer application:
Copy the example environment file and update values according to your needs
cp .env.example .env
This table lists the environment variables and their default values.
Environment Variable | Default Value | Accepted Values | Description |
---|---|---|---|
|
|
|
Log level. |
|
|
|
Relative path of directory where config files reside |
|
|
|
File Name of the configuration file. |
|
|
|
Rate limit for the API in requests per second. |
|
|
|
Rate limit burst size. |
|
`` |
|
API key to use for authentication to the relayer server. Minimum length 32 characters. |
|
`` |
|
Signing key to use for webhook notifications. Minimum length 32 characters. |
|
|
|
Write logs either to console or to file. |
|
|
|
Directory to persist log files on host. |
|
|
|
Size after which logs needs to be rolled. |
|
|
|
Enable metrics server for external tools to scrape metrics. |
|
|
|
Port to use for metrics server. |
|
|
|
Redis connection URL for the relayer. |
|
|
|
Connection timeout for Redis in milliseconds. |
|
|
|
Sets the maximum time to wait for RPC connections before timing out. |
|
|
|
Maximum number of retry attempts for provider operations. |
|
|
|
Base delay between retry attempts in milliseconds. |
|
|
|
Maximum delay between retry attempts in milliseconds. |
|
|
|
Maximum number of failovers (switching to different providers). |
|
|
|
Enable or disable Swagger UI for API documentation. |
|
`` |
|
Passphrase for the keystore file used for signing transactions. |
Environment configuration example
.env
file config example:
RUST_LOG=DEBUG
CONFIG_DIR=./config
CONFIG_FILE_NAME=config.json
WEBHOOK_SIGNING_KEY=e1d42480-6f74-4d0b-85f4-b7f0bb690fae
API_KEY=5eefd216-0e44-4ca7-b421-2925f90d30d5
RATE_LIMIT_RPS=100
RATE_LIMIT_BURST_SIZE=300
METRICS_ENABLED=true
METRICS_PORT=8081
REDIS_URL=redis://localhost:6379
REDIS_CONNECTION_TIMEOUT_MS=10000
RPC_TIMEOUT_MS=10000
PROVIDER_MAX_RETRIES=3
PROVIDER_RETRY_BASE_DELAY_MS=100
PROVIDER_RETRY_MAX_DELAY_MS=2000
PROVIDER_MAX_FAILOVERS=3
ENABLE_SWAGGER=false
KEYSTORE_PASSPHRASE=your_keystore_passphrase
Main configuration file (config.json)
This file can exist in any directory, but the default location is ./config/config.json
.
Copy the example config file and update values according to your needs
cp config/config.example.json config/config.json
Key sections in this file include:
-
Signers: Defines transaction signing methods.
-
Notifications: Sets up status alerts
-
Relayers: Configures networks, notifications channels, policies & singers.
-
Networks: Defines blockchain network configurations.
-
Plugins: Configures plugins.
1. Signers
Transaction signers are responsible for cryptographically signing transactions before they are submitted to blockchain networks. The signers
array must contain at least one valid signer configuration.
For comprehensive details on configuring all supported signer types including:
-
Local keystore file signers
-
HashiCorp Vault (secret, cloud, and transit)
-
Cloud KMS providers (Google Cloud, AWS)
-
Turnkey signers
-
Security best practices and troubleshooting
See the dedicated Signers Configuration guide.
2. Notifications
-
notifications
array, which should contain, at least, one valid configuration:
"notifications": [
{
"id": "notification-test",
"type": "webhook",
"url": "https://webhook.site/f95cf78d-742d-4b21-88b7-d683e6fd147b",
"signing_key": {
"type": "env",
"value": "WEBHOOK_SIGNING_KEY"
}
}
]
Available configuration fields
Field | Type | Description |
---|---|---|
id |
String |
Unique id for the notification |
type |
String |
Type of notification (only |
url |
String |
Notification URL |
signing_key.type |
String |
Type of key used in signing the notification ( |
signing_key.value |
String |
Signing key value, env variable name, … |
3. Relayers
-
relayers
array, containing at least one valid relayer configuration:
"relayers": [
{
"id": "solana-testnet",
"name": "Solana Testnet",
"paused": false,
"notification_id": "notification-test",
"signer_id": "local-signer",
"network_type": "solana",
"network": "testnet",
"custom_rpc_urls": [
{
"url": "https://primary-rpc.example.com",
"weight": 2 // Higher weight routes more requests to this endpoint. The value must be an integer between 0 and 100 (inclusive).
},
{
"url": "https://backup-rpc.example.com",
"weight": 1
}
],
"policies": {
"allowed_programs": [
"11111111111111111111111111111111",
"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
"BPFLoaderUpgradeab1e11111111111111111111111"
]
}
}
]
Available configuration fields
Field | Type | Description |
---|---|---|
id |
String |
Unique id for the relayer |
name |
String |
Human readable name for the relayer |
paused |
Boolean |
Whether or not the relayer is paused ( |
notification_id |
String |
ID of a configured notification object |
signer_id |
String |
ID of a configured signer |
network_type |
String |
Type of network the relayer will connect to ( |
network |
String |
Network the relayer will connect to. Must match a network identifier defined in your network configuration files. See Network Configuration for details on defining networks. |
custom_rpc_urls |
list |
Optional custom RPC URLs for the network. If provided, this will be used instead of the public RPC URLs. This is useful for using your own RPC node or a paid service provider. The first url of the list is going to be used as the default |
policies |
list |
Overrides default policies. Please refer to the |
Policies
Network type | Policy | Type | Description |
---|---|---|---|
solana, evm |
min_balance |
unsigned 128 |
Minimum balance (in lamports or wei) required for the relayer to operate. Optional. |
solana |
fee_payment_strategy |
enum(user,relayer) |
Specifies who pays the fee. "user" (default) means the sender pays; "relayer" means the relayer pays. For "user", RPC methods add an instruction to transfer SPL tokens (calculated from the current SOL price plus a configurable margin) from the user to the relayer, ensuring fees are sustainably covered in tokens rather than SOL. |
solana |
swap_config |
SwapConfig |
Optional object configuring automated token‐swaps on Solana. |
solana |
fee_margin_percentage |
f32 |
Additional margin percentage added to estimated transaction fees to account for price fluctuations. For example, a value of 10 will add 10% to estimated fees. Optional. |
solana |
max_allowed_fee_lamports |
unsigned 64 |
Maximum allowed fee (in lamports) for a transaction. Optional. |
solana |
allowed_tokens |
Vector<AllowedToken> |
List of allowed tokens. Only these tokens are supported if provided. Optional. |
solana |
allowed_programs |
Vector<String> |
List of allowed programs by their identifiers. Only these programs are supported if provided. |
solana |
allowed_accounts |
Vector<String> |
List of allowed accounts by their public keys. The relayer will only operate with these accounts if provided. |
solana |
disallowed_accounts |
Vector<String> |
List of disallowed accounts by their public keys. These accounts will be explicitly blocked. |
solana |
max_tx_data_size |
unsigned 16 |
Maximum transaction size. Optional. |
solana |
max_signatures |
unsigned 8 |
Maximum supported signatures. Optional. |
evm |
gas_price_cap |
unsigned 128 |
Specify a maximum gas price for every transaction sent with the Relayer. When enabled, any transaction exceeding the cap will have its gasPrice or maxFeePerGas overwritten. (Optional) |
evm |
whitelist_receivers |
Vector<String> |
A list of authorized contracts for each transaction sent using the Relayer. Transactions will be rejected if the destination address is not on the list. (Optional) |
RPC URL Configuration
The relayer supports two ways to configure RPC URLs:
-
Public RPC URLs: These are the default RPC endpoints provided by the network. They are automatically selected based on the network configuration.
-
Custom RPC URLs: You can specify custom RPC URLs using the
custom_rpc_urls
field in the relayer configuration. Each URL can be configured with an optional weight for high availability:
"custom_rpc_urls": [
{
"url": "https://primary-rpc.example.com",
"weight": 2 // Higher weight routes more requests to this endpoint. The value must be an integer between 0 and 100 (inclusive).
},
{
"url": "https://secondary-rpc.example.com",
"weight": 100, // Max allowed weight
},
{
"url": "https://backup-rpc.example.com" // No weight specified, defaults to 100
},
{
"url": "https://backup2-rpc.example.com",
"weight": 0, // A value of 0 disables the endpoint.
}
]
This is useful when you want to: * Use your own RPC nodes with load balancing * Use a paid service provider for better reliability and performance * Override the default public RPC URLs * Access custom network endpoints * Configure primary and backup endpoints with different weights
When both are available, the relayer will:
1. First attempt to use the custom_rpc_urls
if configured.
2. Fall back to the public RPC URLs if no custom URL is configured.
For backward compatibility, string arrays are still supported:
"custom_rpc_urls": ["https://your-rpc.example.com"]
When using custom RPC URLs:
|
4. Plugins
For more information on how to write a plugin, please refer to the Plugins page.
-
plugins
array, containing plugin configurations:
"plugins": [
{
"id": "my-plugin",
"path": "my-plugin.ts"
}
]
Available configuration fields
Field | Type | Description |
---|---|---|
id |
String |
Unique id for the plugin |
path |
String |
Path to the plugin file |
5. Networks
You can configure networks either:
-
In separate JSON files (recommended for better organization)
-
Directly in your main
config.json
For comprehensive network configuration details, including:
-
Network field reference
-
Configuration examples for all network types
-
Network inheritance
-
Special tags and their behavior
-
Best practices and troubleshooting
See the dedicated Network Configuration guide.
Configuration File Example
Full config/config.json
example with evm and solana relayers definitions using keystore signer:
{
"relayers": [
{
"id": "sepolia-example",
"name": "Sepolia Example",
"network": "sepolia",
"paused": false,
"notification_id": "notification-example",
"signer_id": "local-signer",
"network_type": "evm",
"custom_rpc_urls": [
{
"url": "https://primary-rpc.example.com",
"weight": 2
},
{
"url": "https://backup-rpc.example.com",
"weight": 1
}
],
"policies": {
"gas_price_cap": 30000000000000,
"eip1559_pricing": true
}
},
{
"id": "solana-example",
"name": "Solana Example",
"network": "devnet",
"paused": false,
"notification_id": "notification-example",
"signer_id": "local-signer",
"network_type": "solana",
"custom_rpc_urls": [
{
"url": "https://primary-solana-rpc.example.com",
"weight": 2
},
{
"url": "https://backup-solana-rpc.example.com",
"weight": 1
}
],
"policies": {
"fee_payment_strategy": "user",
"min_balance": 0,
"allowed_tokens": [
{
"mint": "Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr",
"max_allowed_fee": 100000000
},
{
"mint": "So11111111111111111111111111111111111111112"
}
]
}
},
{
"id": "solana-mainnet-example",
"name": "Solana Mainnet Example",
"network": "mainnet-beta",
"paused": false,
"notification_id": "notification-example",
"signer_id": "local-signer",
"network_type": "solana",
"custom_rpc_urls": ["https://your-private-solana-rpc.example.com"],
"policies": {
"fee_payment_strategy": "user",
"min_balance": 0,
"swap_config": {
"cron_schedule": "0 0 * * * *",
"min_balance_threshold": 0,
"strategy": "jupiter-ultra"
},
"allowed_tokens": [
{
"mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"max_allowed_fee": 100000000,
"swap_config": {
"min_amount": 0,
"max_amount": 0,
"retain_min_amount": 0
}
},
{
"mint": "So11111111111111111111111111111111111111112"
}
]
}
}
],
"notifications": [
{
"id": "notification-example",
"type": "webhook",
"url": "https://webhook.site/1384d4d9-21b1-40a0-bcd1-d3f3b66be955",
"signing_key": {
"type": "env",
"value": "WEBHOOK_SIGNING_KEY"
}
}
],
"signers": [
{
"id": "local-signer",
"type": "local",
"config": {
"path": "config/keys/local-signer.json",
"passphrase": {
"type": "env",
"value": "KEYSTORE_PASSPHRASE"
}
}
}
],
"networks": [
{
"average_blocktime_ms": 12000,
"chain_id": 11155111,
"explorer_urls": [
"https://api-sepolia.etherscan.io/api",
"https://sepolia.etherscan.io"
],
"features": [
"eip1559"
],
"is_testnet": true,
"network": "sepolia",
"required_confirmations": 6,
"rpc_urls": [
"https://sepolia.drpc.org",
"https://1rpc.io/sepolia",
"https://ethereum-sepolia-rpc.publicnode.com",
"https://ethereum-sepolia-public.nodies.app"
],
"symbol": "ETH",
"tags": [
"deprecated"
],
"type": "evm"
},
{
"type": "solana",
"network": "devnet",
"rpc_urls": ["https://api.devnet.solana.com"],
"explorer_urls": ["https://explorer.solana.com?cluster=devnet"],
"average_blocktime_ms": 400,
"is_testnet": true
},
{
"type": "solana",
"network": "mainnet-beta",
"rpc_urls": ["https://api.mainnet-beta.solana.com"],
"explorer_urls": ["https://explorer.solana.com"],
"average_blocktime_ms": 400,
"is_testnet": false
}
]
}