# How Starship Enables Faucet Support for Test Tokens in Multichain Deployments

> Starship enables faucet support for test tokens in multichain deployments by treating faucets as first-class declarative features. Learn how Starship automates token distribution and provides local access.

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

---

**Starship facilitates faucet support for test tokens in multichain deployments by treating faucets as first-class declarative features that run as isolated Go services with automated token distribution pools and built-in port forwarding for local access.**

Starship, developed by `hyperweb-io/starship`, is a comprehensive multichain testing framework designed for Cosmos-based local testnets. Its architecture delivers seamless **faucet support for test tokens in multichain deployments** through a declarative YAML configuration system, allowing each chain to independently specify faucet capabilities, resource constraints, and API exposure ports.

## Declarative Configuration for Faucet Features

Starship separates faucet configuration into **per-chain definitions** and **global service settings**, enabling precise control over token distribution across complex multichain topologies.

### Per-Chain Faucet Definition

The E2E test configuration in [`starship/tests/e2e/config.go`](https://github.com/hyperweb-io/starship/blob/main/starship/tests/e2e/config.go) defines a `Faucet` field on each `Chain` struct, allowing individual chains to declare their own faucet instances:

```go
type Chain struct {
    …
    Faucet *Feature `name:"faucet" json:"faucet" yaml:"faucet"`   // per-chain faucet
    …
}

```

A concrete deployment manifest (e.g., [`starship/tests/e2e/configs/multi-validator-starship-faucet.yaml`](https://github.com/hyperweb-io/starship/blob/main/starship/tests/e2e/configs/multi-validator-starship-faucet.yaml)) wires the feature with specific resource limits and concurrency settings:

```yaml
chains:
  - id: osmosis-1
    …
    faucet:
      type: starship          # selects the built-in faucet binary

      concurrency: 2          # number of distributor accounts

      resources:
        cpu: "0.1"
        memory: "200M"
    ports:
      faucet: 8000            # exposed port for the faucet API

```

The `ports.faucet` entry is consumed by the port-forward script to map the pod’s internal faucet port to a local development address.

### Global Faucet Services

The top-level `Config` struct also supports a global `Faucet` field for deployment-wide faucet services:

```go
type Config struct {
    …
    Faucet *Feature `name:"faucet" json:"faucet" yaml:"faucet"`   // global faucet service
}

```

This dual-layer configuration enables scenarios where individual chains maintain dedicated faucets while a global service manages cross-chain token distribution.

## Faucet Service Architecture

The faucet runs as an independent Go binary ([`starship/faucet/main.go`](https://github.com/hyperweb-io/starship/blob/main/starship/faucet/main.go)) with a gRPC/HTTP interface, isolated from chain nodes to ensure reliable token distribution under load.

### Entry Point and Server Bootstrapping

The CLI entry point initializes the server configuration and starts the `AppServer`:

```go
func NewApp() *cli.App {
    conf := NewDefaultConfig()
    …
    server, err := NewAppServer(conf)
    …
    server.Run()
}

```

This separation ensures the faucet service can be deployed, scaled, and restarted independently of the chain nodes it serves.

### Request Handling via Status and Credit RPCs

The [`starship/faucet/handler.go`](https://github.com/hyperweb-io/starship/blob/main/starship/faucet/handler.go) file implements two primary RPC methods:

- **Status**: Returns the faucet’s health, RPC endpoint, chain ID, supported tokens, the **holder** account, and the list of **distributor** accounts.
- **Credit**: Executes a token transfer to a user-provided address, then polls the balance until confirming the expected increase or reaching a timeout.

The `Credit` handler implements a robust verification pattern:

```go
func (a *AppServer) Credit(ctx context.Context, req *pb.RequestCredit) (*pb.ResponseCredit, error) {
    // snapshot balance, send tokens, confirm increase
}

```

This confirmation loop ensures test suites receive definitive feedback when tokens are actually spendable, not merely broadcast.

### Token Pool Management with Distributor Accounts

The [`starship/faucet/distributor.go`](https://github.com/hyperweb-io/starship/blob/main/starship/faucet/distributor.go) file manages the **holder** (genesis-funded) account and a configurable pool of **distributor** accounts to prevent nonce collisions and handle concurrent requests.

Key responsibilities include:

- **Credit Coin Parsing**: Converts `config.CreditCoins` into the distributor’s `CreditCoins` list.
- **Automatic Refilling**: Monitors distributor balances against `RefillThreshold`; triggers `Distributor.Refill` when accounts require topping up from the holder account.
- **Randomized Selection**: Chooses a random distributor for each request to distribute load:

```go
func (d *Distributor) SendTokens(address, denom string) error {
    if d.Addrs == nil {
        return d.Holder.SendTokens(address, denom, amount)
    }
    randIndex := rand.Intn(len(d.Addrs))
    return d.Addrs[randIndex].SendTokens(address, denom, amount)
}

```

The concurrency setting in the YAML configuration directly controls the size of the distributor pool, allowing developers to optimize for high-throughput testing scenarios.

## Network Exposure and Client Access

Starship automates network connectivity between local development environments and cluster-internal faucet pods.

### Automated Port Forwarding

The [`starship/scripts/port-forward.sh`](https://github.com/hyperweb-io/starship/blob/main/starship/scripts/port-forward.sh) script reads the `chains[i].ports.faucet` values from the deployment configuration and creates `kubectl port-forward` tunnels:

```bash
localfaucet=$(yq -r ".chains[$i].ports.faucet" ${CONFIGFILE})
kubectl port-forward pods/$chain-genesis-0 $localfaucet:$CHAIN_FAUCET_PORT &

```

This makes the faucet API reachable at `http://localhost:<port>` without manual Kubernetes networking configuration.

### SDK Integration

Client libraries interact with the exposed endpoint using standard HTTP/gRPC. The test suite in [`starship/tests/e2e/faucet_test.go`](https://github.com/hyperweb-io/starship/blob/main/starship/tests/e2e/faucet_test.go) demonstrates the request flow, where applications can request specific denominations to be credited to test addresses.

## End-to-End Usage Example

Deploy a multichain environment with faucet support using the following workflow:

```bash

# 1. Start Starship with a faucet-enabled configuration

starship up -f ./starship/tests/e2e/configs/multi-validator-starship-faucet.yaml

# 2. Forward faucet ports to localhost

./starship/scripts/port-forward.sh ./starship/tests/e2e/configs/multi-validator-starship-faucet.yaml

```

Then request tokens programmatically:

```javascript
import { FaucetClient } from '@hyperweb/starshipjs'

const client = new FaucetClient('http://localhost:8000')
await client.credit({ address: 'cosmos1xyz...', denom: 'uatom' })

```

The client communicates with the `Credit` RPC, which triggers the distributor to send the configured amount and waits for balance confirmation before returning success.

## Summary

- **Declarative Configuration**: Each chain independently declares faucet features with resource limits and exposure ports via [`starship/tests/e2e/config.go`](https://github.com/hyperweb-io/starship/blob/main/starship/tests/e2e/config.go) structures.
- **Isolated Service Architecture**: The faucet runs as a dedicated Go binary ([`starship/faucet/main.go`](https://github.com/hyperweb-io/starship/blob/main/starship/faucet/main.go)) with `Status` and `Credit` RPC handlers separate from chain nodes.
- **Robust Token Pool**: The `Distributor` in [`starship/faucet/distributor.go`](https://github.com/hyperweb-io/starship/blob/main/starship/faucet/distributor.go) maintains holder and refillable distributor accounts, automatically topping up balances when thresholds are reached.
- **Automated Network Exposure**: The [`port-forward.sh`](https://github.com/hyperweb-io/starship/blob/main/port-forward.sh) script maps internal Kubernetes ports to local addresses using the `ports.faucet` configuration.
- **Multichain Native**: Because configuration lives per-chain in the YAML manifest, a single Starship deployment supports independent faucets for any number of test chains simultaneously.

## Frequently Asked Questions

### How do I enable faucet support for a specific chain in Starship?

Add a `faucet` field to the chain definition in your YAML configuration file, specifying the `type` (typically `starship`), `concurrency` (number of distributor accounts), and `resources`. Expose the service by defining `ports.faucet` with a port number, which the port-forward script will use to create a local tunnel.

### What is the difference between holder and distributor accounts in Starship's faucet?

The **holder** account is the primary genesis-funded wallet that holds the initial token supply. **Distributor** accounts are secondary wallets spawned according to the `concurrency` setting; they receive periodic refills from the holder and handle actual token distribution requests. This separation prevents nonce conflicts during concurrent credit requests and enables horizontal scaling.

### How does Starship automate token refills for faucets?

The `Distributor` implementation in [`starship/faucet/distributor.go`](https://github.com/hyperweb-io/starship/blob/main/starship/faucet/distributor.go) monitors each distributor account's balance against a `RefillThreshold`. When an account's balance drops below this threshold, the `requireRefill` logic triggers the `Refill` method, which transfers tokens from the holder account to the depleted distributor, ensuring continuous availability for test token requests.

### Can multiple chain faucets run simultaneously in one deployment?

Yes. Because the `Chain` struct in [`starship/tests/e2e/config.go`](https://github.com/hyperweb-io/starship/blob/main/starship/tests/e2e/config.go) includes a per-chain `Faucet` field, each chain in a multichain deployment can define its own independent faucet configuration with unique ports. The port-forward script iterates through all chains, creating separate tunnels for each faucet endpoint, enabling isolated token distribution for every chain in the test topology.