# Developing and Testing Multichain Applications with Starship: Best Practices and Code Examples

> Learn best practices for developing and testing multichain applications with Starship a Kubernetes-native framework. Define, spin up, and test IBC-connected chains locally with ease.

- Repository: [Hyperweb/starship](https://github.com/hyperweb-io/starship)
- Tags: best-practices
- Published: 2026-03-03

---

**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`](https://github.com/hyperweb-io/starship/blob/main/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.

```yaml
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.

```yaml
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`](https://github.com/hyperweb-io/starship/blob/main/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:

1. **Install dependencies** – Run `npm install -g @starship-ci/cli` followed by `starship install` to bootstrap Docker, Helm, and kubectl.

2. **Spin up the devnet** – Execute `yarn starship start --config config.yaml` to deploy all chain pods, relayers, and services.

3. **Iterate** – Modify [`config.yaml`](https://github.com/hyperweb-io/starship/blob/main/config.yaml) as needed, then run `yarn starship restart` or a full stop/start cycle. Hot-reloading is not supported; full restarts ensure clean genesis states.

4. **Teardown** – Run `yarn starship stop --config config.yaml` to free cluster resources and eliminate stale pods.

This cycle is documented in [`README.md`](https://github.com/hyperweb-io/starship/blob/main/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`](https://github.com/hyperweb-io/starship/blob/main/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 `SoftwareUpgradeProposal` with a target `upgradeHeight`
- Vote on the proposal using validator keys
- Wait for the upgrade height with `s.WaitForHeight`
- Validate post-upgrade state through balance checks

```go
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.

```javascript
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`](https://github.com/hyperweb-io/starship/blob/main/.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`](https://github.com/hyperweb-io/starship/blob/main/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`](https://github.com/hyperweb-io/starship/blob/main/starship/faucet/main.go).

## Summary

- **Use a single [`config.yaml`](https://github.com/hyperweb-io/starship/blob/main/config.yaml)** as 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`](https://github.com/hyperweb-io/starship/blob/main/.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.