A Kurtosis package for deploying private THORChain testnets with automated genesis generation, network launching, and auxiliary services.
This package automates the deployment of complete THORChain networks through a coordinated orchestration pipeline:
- Configuration parsing - Validates and applies defaults to user configuration
- Genesis file generation - Creates blockchain initial state with validator keys and prefunded accounts
- Network deployment - Launches THORChain nodes with proper seed node topology
- Service deployment - Waits for first block production, then deploys auxiliary services
- Automated genesis creation with validator cryptographic material and account funding
- Proper P2P topology with first node as seed for network formation
- Auxiliary services including token faucets, blockchain indexers, and trading interfaces
- State forking support for testing against mainnet data
- Flexible configuration with comprehensive defaults and customization options
- CosmWasm contract deployment with mimir-based permission control
- Kurtosis installed and running
- Basic understanding of THORChain and Cosmos SDK blockchain architecture
- Docker for running containerized services
Deploy a default THORChain network:
kurtosis run --enclave thorchain-testnet github.com/0xBloctopus/thorchain-packageCreate a configuration file and deploy:
kurtosis run --enclave thor-fork . --args-file examples/forking-genesis.yamlExample minimal configuration:
chains:
- name: "my-thorchain"
type: "thorchain"
chain_id: "thorchain-testnet"The package uses a comprehensive configuration system with defaults from thorchain_defaults.json. All parameters are optional and will fall back to sensible defaults.
| Parameter | Description | Default |
|---|---|---|
name |
Chain identifier for services | "thorchain" |
type |
Must be "thorchain" |
"thorchain" |
chain_id |
Blockchain network ID | "thorchain" |
app_version |
THORChain application version | "3.7.0" |
participants |
Validator node configuration | 1 validator |
additional_services |
Services to deploy | ["faucet", "bdjuno"] |
prefunded_accounts |
Genesis account funding | {} |
forking |
State forking configuration | Disabled |
The package supports extensive Cosmos SDK module configuration including:
- Consensus parameters - Block size, gas limits, evidence parameters
- Auth module - Transaction limits, signature verification costs
- Staking module - Validator limits, minimum self-delegation
- Mint module - Inflation parameters, annual provisions
- Bank module - Token denomination and metadata
participants:
- image: "registry.gitlab.com/thorchain/thornode:mainnet"
account_balance: 1000000000000000
bond_amount: "300000000000000"
count: 1
min_cpu: 500
min_memory: 1024
gomemlimit: 6GiBThe package can optionally deploy a CLI toolchain container alongside the network for local development workflows.
| Parameter | Type | Default | Description |
|---|---|---|---|
deploy_cli |
boolean | false |
Deploy CLI toolchain container with Rust 1.77, wasm-tools, CosmWasm build support |
Note: Package defaults to false for cloud efficiency. MCP tooling overrides to true for developer convenience.
Enable CLI container for local development:
chains:
- name: thorchain
deploy_cli: true # Rust toolchain, pre-configured faucet key, contract build toolsCloud deployment (minimal resources):
chains:
- name: thorchain
# deploy_cli: false (default) - saves ~250MB RAM, 250m CPU, 2GB diskCLI container features:
- Rust 1.77.1 toolchain for CosmWasm contract compilation
- wasm-tools and wasm-opt for WASM optimization
- Pre-configured keyring with imported faucet account
- Direct network access to thornode RPC and API
- Persistent storage for build artifacts
Deploy a lightweight CLI container to interact with remote THORChain networks (mainnet, testnet, or custom endpoints) without running a full node.
| Parameter | Type | Description |
|---|---|---|
config_type |
string | Set to "cli_only" to deploy CLI-only container |
profile |
string | Use predefined profile ("mainnet", "octhornet") or custom name |
rpc_url |
string | Custom RPC endpoint (overrides profile) |
api_url |
string | Custom API endpoint (overrides profile) |
faucet_url |
string | Custom faucet endpoint (optional) |
Built-in profiles (defined in thorchain_defaults.json):
mainnet: thorchain-1, thornode.ninerealms.comocthornet: thorchain testnet, bloctopus.io endpoints
Connect to mainnet:
chains:
- name: mainnet
config_type: cli_only
profile: mainnetConnect to custom remote network:
chains:
- name: my-remote
config_type: cli_only
chain_id: thorchain-testnet-v1
rpc_url: https://rpc.example.com:443
api_url: https://api.example.com
faucet_url: https://faucet.example.com # optionalEnvironment variables set in container:
THORCHAIN_CHAIN_ID: Chain identifierTHORCHAIN_REMOTE_RPC: RPC endpoint URLTHORCHAIN_REMOTE_API: REST API endpoint URLTHORCHAIN_REMOTE_FAUCET: Faucet endpoint URL (if configured)THORCHAIN_PROFILE: Profile/network name
The package supports three auxiliary services that are deployed after the network produces its first block:
faucet- HTTP API for token distribution using the last generated validator mnemonicbdjuno- Complete blockchain indexing stack with PostgreSQL database, Hasura GraphQL API, Big Dipper web explorer, and Nginx reverse proxyswap-ui- Web interface for token swapping with support for prefunded account integration
After deployment, services are accessible at:
- RPC:
http://<node-ip>:26657- Tendermint RPC - API:
http://<node-ip>:1317- Cosmos REST API - gRPC:
<node-ip>:9090- Cosmos gRPC (local) - For mainnet forking, use gRPC endpoint
grpc.thor.pfc.zone:443(TLS) - P2P:
<node-ip>:26656- Peer-to-peer networking - Metrics:
http://<node-ip>:26660- Prometheus metrics
- API:
http://<faucet-ip>:8090- Token distribution endpoint (POST /fund) - Usage:
curl -s -X POST -H "Content-Type: application/json" \-d '{"address":"<thor1...>","amount":"1000000","denom":"rune"}' \http://<faucet-ip>:8090/fund
- Explorer:
http://<explorer-ip>:80- Web interface - GraphQL:
http://<hasura-ip>:8080- Hasura GraphQL API - Database:
<postgres-ip>:5432- PostgreSQL database
- Interface:
http://<swap-ui-ip>:80- Web trading interface
The package can optionally deploy Bifrost (THORChain's cross-chain bridge signer) along with external chain nodes for real cross-chain swap testing.
Set bifrost_enabled: true in your chain configuration:
chains:
- name: thorchain
type: thorchain
bifrost_enabled: true # Launch Bifrost + external chains
bitcoin_enabled: true # Bitcoin regtest (default: true when bifrost enabled)
ethereum_enabled: true # Ethereum via Anvil (default: true when bifrost enabled)When Bifrost is enabled, the package launches (in order):
- Bitcoin regtest (
lncm/bitcoind:v26.0) — RPC on port 18443, with a wallet and 101 pre-mined blocks - Ethereum Anvil (
ghcr.io/foundry-rs/foundry) — RPC on port 8545, 10 prefunded accounts with 1000 ETH each - Bifrost (
registry.gitlab.com/thorchain/thornode:mocknet) — connected to THORNode + both chain nodes
The launcher waits for Bifrost to register its chains with THORNode (visible at /thorchain/inbound_addresses).
You can disable specific chains while keeping Bifrost:
chains:
- name: thorchain
bifrost_enabled: true
bitcoin_enabled: true
ethereum_enabled: false # Skip EthereumFor tests that only need THORChain's quote endpoints (no actual swaps), keep bifrost_enabled: false (the default). This skips all external chain nodes and Bifrost, giving you a much faster startup:
chains:
- name: thorchain
type: thorchain
# bifrost_enabled: false # default — no Bifrost, no external chains| Service | Port | Description |
|---|---|---|
| Bitcoin RPC | 18443 | bitcoin-cli -regtest -rpcuser=thorchain -rpcpassword=thorchain |
| Bitcoin P2P | 18444 | Peer-to-peer (regtest) |
| Ethereum RPC | 8545 | Standard JSON-RPC (Anvil) |
| Bifrost P2P | 5040 | Bifrost peer-to-peer |
| Bifrost RPC | 6040 | Bifrost RPC |
| Chain | Image | Status |
|---|---|---|
| Bitcoin | lncm/bitcoind:v26.0 |
✅ Regtest with wallet + pre-mined blocks |
| Ethereum | ghcr.io/foundry-rs/foundry:latest |
✅ Anvil with prefunded accounts |
- Bifrost env var names and startup scripts are based on the THORChain localnet convention and may need adjustment for different THORNode image versions. Check the
TODOcomments insrc/bifrost/bifrost_launcher.star. - The Bifrost image uses
registry.gitlab.com/thorchain/thornode:mocknet— ensure this tag exists or update to match your THORNode version. - Cross-chain swap end-to-end tests require additional setup (vault funding, chain client configuration) beyond what this launcher provides out of the box.
Fund accounts at genesis time by listing THORChain addresses under prefunded_accounts. No private keys are required or stored; addresses simply appear in genesis with the requested balance for every denom. If you also deploy CLI containers, you can optionally preload mnemonics via cli_service.preload_keys so the CLI keyring has convenient access to those funded accounts while keeping prefunding and key management decoupled. See README_PREFUNDED_ACCOUNTS.md for a deeper dive.
Fork from mainnet state for realistic testing. Requires a forking-enabled THORNode image that can fetch state from the specified RPC endpoint. The package supports caching and configurable gas costs for state fetching operations.
Use default configuration with a single validator:
kurtosis run --enclave thorchain-testnet github.com/0xBloctopus/thorchain-packageFund specific accounts at genesis time (examples/prefunded-accounts.yaml):
chains:
- name: thorchain
type: thorchain
prefunded_accounts:
# Each account receives ALL ~500 mainnet denoms at the specified amount
thor1qpwyke4xyxjaa4rv6r46fflzs2w0vey0yf3kzs: 1000000000000000 # 1M RUNE + all denoms
thor1e0lmk5juawc46jwjwd0xfz587njej7ay5fh6cd: 500000000000000 # 500K RUNE + all denoms
deploy_cli: true
cli_service:
preload_keys:
- name: alice
mnemonic: "<24-word mnemonic for thor1qpwyke4xyxjaa4rv6r46fflzs2w0vey0yf3kzs>"Supply mnemonics exclusively to the CLI toolchain so they are ready for transactions without exposing keys to the network launcher:
chains:
- config_type: cli_only
name: thorchain-cli
rpc_url: "https://thornode.ninerealms.com:443"
preload_keys:
- name: integration-bot
mnemonic: "<24-word mnemonic>"The CLI launcher imports each mnemonic, warns if the derived address is not listed under prefunded_accounts, and automatically uses the first imported key as the CLI default.
Fork from mainnet state with a minimal config (examples/forking-genesis.yaml):
chains:
- name: thorchain
type: thorchain
chain_id: "thorchain-1"
app_version: "3.11.0"
forking:
enabled: true
image: "tiljordan/thornode-forking:1.0.25-23761879"
height: 23015000
participants:
- image: "tiljordan/thornode-forking:1.0.25-23761879"
count: 1
account_balance: 1000000000000
bond_amount: 500000000000
faucet:
faucet_amount: 1000000000000000
transfer_amount: 10000000000000
additional_services:
- faucetNote: the launcher now reads initial_height directly from the generated genesis.json, so no manual override is necessary.
Deploy specific auxiliary services:
chains:
- name: "thorchain-custom"
type: "thorchain"
additional_services: ["faucet", "bdjuno", "swap-ui"]
faucet:
transfer_amount: 50000000000000 # Custom faucet amount (500k RUNE)Enable CLI toolchain for CosmWasm development (examples/cli-with-network.yaml):
chains:
- name: thorchain-dev
deploy_cli: true # Rust toolchain, faucet key, contract build tools
additional_services:
- faucetConnect to remote networks without running a full node (examples/cli-only-custom.yaml):
chains:
# Built-in profile (mainnet or octhornet)
- name: mainnet
config_type: cli_only
profile: mainnet
# OR custom remote network
- name: my-testnet
config_type: cli_only
chain_id: thorchain-testnet-v1
rpc_url: https://rpc.example.com:443
api_url: https://api.example.comDeploy with Bifrost + Bitcoin + Ethereum for real cross-chain swap testing:
chains:
- name: thorchain
type: thorchain
bifrost_enabled: true
additional_services:
- faucet- Network Deployment: Deploy both local (clean state) and forked (mainnet state) networks
- Mimir Configuration: Make sure to have set
WASMPERMISSIONLESS=1to enable permissionless deployment - Contract Upload: Use
thornode tx wasm storeto upload contract bytecode - Contract Instantiation: Use
thornode tx wasm instantiateto create contract instances
THORChain uses a dual permission system:
- Genesis Permissions: Set to "Everybody" in genesis configuration
- Runtime Permissions: Controlled by
WASMPERMISSIONLESSmimir value
Forked networks inherit mainnet mimir values where WASMPERMISSIONLESS=0, requiring manual configuration.
- By default, this package sets
mimir.values.WASMPERMISSIONLESS: 1insrc/package_io/thorchain_defaults.json. - You can override in your args YAML:
chains:
- name: thorchain
type: thorchain
mimir:
enabled: true
values:
WASMPERMISSIONLESS: 0 # override default 1In forking-enabled runs, the configurator first funds the validator via the faucet, then submits the Mimir vote (sync) to avoid insufficient-funds errors.
Current Limitation: THORChain's WASM runtime doesn't support bulk memory operations.
- Contracts compile successfully but fail WASM validation during deployment
- Error: "bulk memory support is not enabled"
- This is a known limitation, not a deployment failure
- Use local networks for rapid iteration and permission testing
- Use forked networks for realistic state testing
- Focus on deployment process validation rather than contract execution
- Monitor THORChain updates for bulk memory support
The package implements proper seed node topology:
- First node starts without seeds (becomes the seed node)
- Subsequent nodes connect to the first node via
--p2p.seeds - Ensures reliable network formation and connectivity
Remove the deployment:
kurtosis enclave rm thorchain-testnetFor detailed configuration options and troubleshooting:
- Service configuration templates in
src/directory - Prefunded accounts documentation
- Kurtosis package configuration - Contains comprehensive package description, prerequisites, and seed node topology details
- Individual service launcher implementations for advanced customization