ChainLaunch

Pro Feature

Testnet Provisioning

One-shot testnet provisioning requires ChainLaunch Pro. Learn more about Pro features.

ChainLaunch Pro Feature

One-shot testnet provisioning requires ChainLaunch Pro. Learn more about Pro features.

The testnet API spins up a fully-functional Hyperledger Fabric or Hyperledger Besu network in a single API call — keys, organizations, peers/orderers/validators, channels, and genesis block all generated and started for you. Use it for local development, demos, integration tests, and CI fixtures. It's not for production.

For production-grade networks, use the network builder UI or Network Templates — those give you control over crypto material, MSP definitions, channel policies, and node configuration. The testnet API trades that control for one-command convenience.

What you get

Platform Topology
Besu N validator nodes (≥ 4) with QBFT consensus, shared genesis with optional initial balances, Docker or systemd mode
Fabric Configurable peer orgs and orderer orgs, configurable peer/orderer counts per org, configurable channels, etcdraft or SmartBFT consensus

Each testnet creates:

  • One key per node, generated in parallel under the configured key provider.
  • One Organization per peer org and orderer org (Fabric).
  • One Network row + genesis block.
  • N Node rows, started immediately.
  • Channels (Fabric only) joined by every peer.

You get back the network ID and the node IDs. The whole thing typically takes 30–90 seconds for a 4-node Besu network or a 2-org Fabric network.

Permissions

Testnet endpoints require network:create + node:create (granted to ADMIN and OPERATOR by default). See RBAC.

Quickstart — Besu

chainlaunch testnet besu \
  --name besu-dev \
  --nodes 4 \
  --prefix validator \
  --mode docker \
  --version 25.5.0 \
  --provider-id 1 \
  --initial-balance "0x627306090abaB3A6e1400e9345bC60c78a8BEf57=0x3635c9adc5dea00000" \
  --initial-balance "0xf17f52151EbEF6C7334FAD080c5704D77216b732=0x3635c9adc5dea00000"

CLI output (plain text — the CLI streams progress and prints the network ID):

Creating 4 validator keys...
  Creating key for node validator-besu-dev-1...
    Key created: ID 101
  ...
  Besu network created: ID 12
Creating 4 Besu nodes...
  Creating Besu node validator-besu-dev-1 with key ID 101...
    Node created ID: 201
  ...
Besu testnet created successfully! Network ID: 12

Equivalent REST API response (POST /testnets/besu), useful for automation:

{
  "network_id": 12,
  "node_ids": [101, 102, 103, 104],
  "message": "Besu testnet 'besu-dev' created with 4 validators"
}

The four validators come up running QBFT, the genesis block prefunds the addresses you listed, and you can immediately point web3.js / ethers / hardhat at the JSON-RPC endpoint of any node.

Fields

Field Required Default Notes
name yes Used as the network name and the key/node prefix
nodes yes Minimum 4 for QBFT (3f+1, f=1)
prefix no besu Prefix applied to validator node names
mode yes docker or service (systemd)
version no 25.5.0 Besu version
provider_id no 1 Key provider — see Key Management
initial_balances no empty Map of address → wei for genesis prefunding

Quickstart — Fabric

chainlaunch testnet fabric \
  --name fabric-dev \
  --mode docker \
  --org Org1 \
  --peerOrgs Org1,Org2 \
  --ordererOrgs OrdererOrg \
  --peerCounts Org1=2,Org2=2 \
  --ordererCounts OrdererOrg=3

CLI output (plain text):

Fabric testnet created successfully! Network ID: 13
Peer joined network 13 successfully. Network ID: 201, Status: joined
Peer joined network 13 successfully. Network ID: 202, Status: joined
...
Orderer joined network 13 successfully. Network ID: 205, Status: joined
...

Equivalent REST API response (POST /testnets/fabric), useful for automation:

{
  "network_id": 13,
  "node_ids": [201, 202, 203, 204, 205, 206, 207],
  "message": "Fabric testnet 'fabric-dev' created with 2 peer orgs, 1 orderer org, 1 channel"
}

You get four peers (two per org) and three orderers in the orderer org, all joined to a brand-new network with its own genesis block. Channels and chaincode are created in follow-up steps -- see Chaincode CI/CD with the CLI.

`--channels` is currently unused by the CLI

The --channels flag is accepted by chainlaunch testnet fabric but the runner does not wire it through to network creation today. Use POST /testnets/fabric with a channels field in the JSON body if you need channels provisioned at testnet creation time, or create channels separately via the network builder after provisioning.

Fields

Field Required Default Notes
name yes Network name
mode yes docker or service
peer_orgs yes List of peer org names; one Organization is created per entry
orderer_orgs yes List of orderer org names
peer_counts yes Map of orgName → count. Each peer org needs an entry.
orderer_counts yes Map of orgName → count. Each orderer org needs an entry. Total must be ≥ 3 orderers for consenters.
channels no ["mychannel"] if omitted Channels to create. All peers join all channels. REST-only: not wired through --channels on the CLI today.
consensus_type no etcdraft etcdraft or smartbft. REST-only: the CLI does not expose this.

Lifecycle

POST /testnets/{platform}
    → ChainLaunch creates keys, orgs, network, nodes
    → Returns 201 with networkId + nodeIds

# Treat the resulting network like any other ChainLaunch network from here:
GET  /networks/{networkId}
GET  /nodes/{nodeId}
POST /networks/{networkId}/chaincodes      (Fabric)
DELETE /networks/{networkId}               (tears down everything)

The testnet API is provisioning-only — it has no special teardown. Delete the network the same way you'd delete any other.

CLI

# Besu
chainlaunch testnet besu \
  --name besu-dev --nodes 4 --mode docker
 
# Fabric (note: CLI uses camelCase flag names — different from the JSON API)
chainlaunch testnet fabric \
  --name fabric-dev --mode docker \
  --org Org1 \
  --peerOrgs Org1,Org2 \
  --ordererOrgs OrdererOrg \
  --peerCounts Org1=2,Org2=2 \
  --ordererCounts OrdererOrg=3
# Channels are not yet wired through the CLI — create them after provisioning
# or call POST /testnets/fabric directly with a `channels` field.

Common patterns

CI fixture

Spin up a fresh network for every test job and tear it down afterwards. ChainLaunch handles the cleanup atomically:

# .github/workflows/integration.yml
- name: Provision testnet
  run: |
    # The CLI prints plain-text status, so call the REST endpoint when you
    # need a parseable response. (At least 3 orderers are required by the
    # CLI runner; the REST endpoint enforces the same consenter floor.)
    RESP=$(curl -fsS -u "$CHAINLAUNCH_USER:$CHAINLAUNCH_PASSWORD" \
      -H 'Content-Type: application/json' \
      -d '{"name":"ci-fabric","mode":"docker","peer_orgs":["Org1","Org2"],"orderer_orgs":["OrdererOrg"],"peer_counts":{"Org1":1,"Org2":1},"orderer_counts":{"OrdererOrg":3},"channels":["mychannel"]}' \
      "$CHAINLAUNCH_API_URL/testnets/fabric")
    NETWORK_ID=$(echo "$RESP" | jq .network_id)
    echo "NETWORK_ID=$NETWORK_ID" >> $GITHUB_ENV
 
- name: Run integration tests
  run: pytest tests/integration
 
- name: Teardown
  if: always()
  run: |
    # Network deletion via the CLI is not yet wrapped — use the API.
    curl -sX DELETE -u "$CHAINLAUNCH_USER:$CHAINLAUNCH_PASSWORD" \
      "$CHAINLAUNCH_API_URL/networks/fabric/$NETWORK_ID"

Demo environment

A lightweight network for sales demos. Default the prefix so all containers are easy to spot in docker ps:

chainlaunch testnet besu --name demo --prefix demo --nodes 4 --mode docker

Development against a stable testnet

For longer-lived shared dev networks, provision once and don't tear down. Treat the testnet output as an ordinary network — every other ChainLaunch feature (backups, monitoring, RBAC, audit) applies.

Limits

  • Besu testnets require ≥ 4 nodes (QBFT 3f+1 with f=1). The API rejects fewer.
  • Fabric peer orgs that aren't listed in peer_counts (or with count 0) cause the request to fail.
  • The same key provider is used for every node. To split keys across providers, build the network the long way via Network Templates.
  • All nodes in one testnet land on the same host (mode=docker runs all containers on the ChainLaunch host; mode=service runs all systemd units on the host). For multi-host testnets, use Pro Sharing to pair multiple ChainLaunch instances and share network metadata.
  • The genesis block is generated once at provisioning. To change parameters later, you have to recreate the network.

Troubleshooting

Symptom Cause Fix
besu testnet requires at least 4 nodes for QBFT consensus nodes < 4 Bump to 4 or more
Some node IDs returned but their containers aren't running Port exhaustion on the host Check docker ps, free up ports, redeploy
peer_counts must include all peer_orgs Mismatch between peer_orgs array and peer_counts map Make sure every org name in peer_orgs is a key in peer_counts
Slow startup (>2min) Image pull on first run Subsequent runs reuse cached images
Channel doesn't appear after provisioning etcdraft hadn't elected a leader yet Wait 10–15 seconds and retry; or check orderer logs
Initial balances missing Address case-sensitive issue Use checksum-cased Ethereum addresses

When NOT to use the testnet API

  • Production networks. Hand-build via the UI or Network Templates so you control crypto material and policies.
  • Multi-host networks. The testnet runs everything on one ChainLaunch host. Pair instances via Pro Sharing for distributed deployments.
  • Custom MSP definitions. The testnet uses ChainLaunch defaults; if you need fine-grained MSP policies, build it manually.
  • Existing-org reuse. The testnet API creates fresh organizations every time. To deploy a new network using existing keys/orgs, use the regular network builder.

Next steps