Developing and Testing Multichain Applications with Starship: Best Practices and Code Examples
Starship provides a Kubernetes-native testing framework that lets you define entire multichain environments in a single YAML file, spin them up locally with one command, and run deterministic Go or JavaScript tests against real IBC-connected chains.
Developing and testing multichain applications with Starship requires treating your infrastructure as code. The hyperweb-io/starship repository delivers a declarative devnet environment where every chain, validator, relayer, and auxiliary service is version-controlled in a config.yaml file. This approach eliminates "works on my machine" inconsistencies and enables reproducible CI/CD pipelines for complex Cosmos SDK applications.
Declarative Configuration for Multichain Environments
Starship orchestrates multichain devnets through a single YAML manifest. According to the docs/config/chains.mdx documentation, you define each blockchain in the chains array, specify IBC connectivity in the relayers block, and enable auxiliary services like explorers or faucets.
Defining Chains and Validators
Each chain entry requires a unique id, a name (referencing built-in defaults), and numValidators to specify consensus participation. For standard chains like Osmosis or Cosmos Hub, use canonical names to inherit pre-filled defaults for Docker images, binaries, and HD paths from the internal chart values.
chains:
- id: osmosis-1
name: osmosis
numValidators: 2
ports:
rest: 1313
rpc: 26653
faucet: 8003
- id: cosmoshub-4
name: cosmoshub
numValidators: 2
ports:
rest: 1317
rpc: 26657
faucet: 8007
For chains not in the built-in registry, set name: custom and provide full specifications including image, binary, and repo locations as documented in docs/config/chains.mdx.
Configuring Relayers and IBC Connectivity
The relayers array defines Inter-Blockchain Communication (IBC) links between your defined chains. Specify the relayer implementation (e.g., hermes), replica count, and participating chain IDs to establish packet relay paths.
relayers:
- name: osmos-cosmos
type: hermes
replicas: 1
chains:
- osmosis-1
- cosmoshub-4
This configuration creates the infrastructure necessary for testing token transfers, cross-chain queries, and channel handshake protocols in examples/multi-chain/config.yaml.
Resource Tuning and Port Management
Per-validator resources blocks allow CPU and memory allocation adjustments to keep devnets lightweight for local development or scaled for stress testing. Explicitly map ports for rest, rpc, grpc, and faucet services to avoid collisions when running multiple chains on localhost. The docs/config/chains.mdx file details valid port ranges and resource constraints.
Local Development Workflow
Starship provides a CLI tool (@starship-ci/cli) that abstracts Kubernetes orchestration into familiar npm commands. The workflow follows four distinct phases:
-
Install dependencies – Run
npm install -g @starship-ci/clifollowed bystarship installto bootstrap Docker, Helm, and kubectl. -
Spin up the devnet – Execute
yarn starship start --config config.yamlto deploy all chain pods, relayers, and services. -
Iterate – Modify
config.yamlas needed, then runyarn starship restartor a full stop/start cycle. Hot-reloading is not supported; full restarts ensure clean genesis states. -
Teardown – Run
yarn starship stop --config config.yamlto free cluster resources and eliminate stale pods.
This cycle is documented in README.md and ensures that every code change is tested against a fresh, deterministic blockchain state.
End-to-End Testing Strategies
Starship supports polyglot testing through native Go clients and JavaScript CosmJS integrations, both executing against the live RPC and gRPC endpoints exposed by your local devnet.
Go-Based Chain Upgrade Testing
The examples/upgrade-test/upgrade_test.go file demonstrates a complete software upgrade flow. The test suite follows a deterministic pattern:
- Create a random wallet using
chain.CreateRandWallet - Execute pre-upgrade token transfers via
s.TransferTokens - Submit a
SoftwareUpgradeProposalwith a targetupgradeHeight - Vote on the proposal using validator keys
- Wait for the upgrade height with
s.WaitForHeight - Validate post-upgrade state through balance checks
plan := upgradetypes.Plan{
Name: version,
Height: upgradeHeight,
}
content := upgradetypes.NewSoftwareUpgradeProposal(
"Software upgrade",
"software upgrade",
plan,
)
msg := &gov.MsgSubmitProposal{
InitialDeposit: sdk.NewCoins(sdk.NewCoin("uxprt", sdk.NewInt(10000000))),
Proposer: chain.Address,
}
s.Require().NoError(msg.SetContent(content))
res, err := chain.SendMsg(context.Background(), msg, "Software upgrade proposal")
s.Require().NoError(err)
s.WaitForTx(chain, res.TxHash)
Best practice dictates calculating upgradeHeight relative to the current block height to accommodate varying chain speeds across CI runners.
JavaScript and CosmJS Integration
For frontend or contract-focused testing, use the Starship CLI's starship test command to execute JavaScript test suites against localhost ports. The examples/osmojs directory contains reference implementations using CosmJS to query balances, submit governance proposals, and test staking flows.
import { StargateClient } from "@cosmjs/stargate"
const rpc = "http://localhost:26657"
const client = await StargateClient.connect(rpc)
const balance = await client.getAllBalances("<address>")
console.assert(balance[0].denom === "uosmo")
CI/CD Pipeline Integration
The .github/workflows/run-client-tests.yml workflow demonstrates production-ready CI configuration. The pipeline executes yarn starship start, runs both Go and JavaScript test suites against the devnet, and performs guaranteed teardown. This pattern ensures that every pull request is validated against a full multichain topology with live IBC channels.
Advanced Features for Robust Multichain Testing
Starship exposes several advanced capabilities through the config.yaml schema to simulate edge cases and optimize resource usage.
CometMock – Replace the standard CometBFT binary with an in-process mock consensus engine by adding cometmock: { enabled: true } under a chain definition. This accelerates validator startup times when testing with many validators on limited hardware, as documented in docs/config/chains.mdx.
Interchain Security (ICS) – Test hub-consumer security models by enabling ics: { enabled: true, provider: <provider-chain-id> }. This configuration allows consumer chains to trust the validator set of a provider chain without running separate consensus.
Custom Scripts and Environment Variables – Override default genesis configurations or inject debug flags using the scripts and env arrays within chain definitions. This capability supports testing non-standard genesis states or feature toggles without rebuilding Docker images.
Debugging and Troubleshooting
When chains fail to reach ready state, inspect pod logs directly via kubectl logs -l app=<chain-id>-validator. If your binary requires extended initialization, customize the readinessProbe parameters in the chain configuration block.
For faucet-related issues, verify that faucet.enabled matches your intended implementation type (cosmjs versus starship), referencing the faucet microservice source in starship/faucet/main.go.
Summary
- Use a single
config.yamlas the source of truth for all chains, relayers, and services to ensure reproducible environments. - Version-lock Docker images and binary references in your configuration to prevent CI drift.
- Allocate minimal viable resources per validator to keep local development lightweight while allowing CI scaling.
- Implement both Go and JavaScript test suites to cover chain upgrades, IBC flows, and client-library integrations.
- Leverage CometMock and ICS features to test complex topologies without provisioning excessive hardware.
Frequently Asked Questions
How do I configure a custom chain not in Starship's default list?
Set name: custom in your chain definition and provide explicit values for image, binary, repo, and other genesis parameters. The docs/config/chains.mdx file specifies the required fields for custom chain integration, allowing you to test private or pre-release chain binaries.
What is the difference between using CometMock and standard CometBFT in Starship?
CometMock runs consensus in-process without the full CometBFT networking stack, significantly reducing startup time and resource consumption when testing with multiple validators. Standard CometBFT provides production-grade consensus behavior but requires more CPU and memory. Use CometMock for rapid iteration and standard CometBFT for final consensus validation.
How can I run both Go and JavaScript tests in the same CI pipeline?
Configure your GitHub Actions workflow to execute yarn starship start, then run your Go test suite using the native Go client against the exposed ports, followed by starship test for JavaScript suites. Reference the .github/workflows/run-client-tests.yml for the exact job sequencing and teardown procedures.
How do I troubleshoot a chain that fails to reach ready state?
Check validator logs using kubectl logs, verify that your configured ports do not conflict with host system services, and adjust the readinessProbe thresholds if your chain binary has a slow initialization sequence. Ensure your resources allocation meets the chain's minimum memory requirements.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →