Zerochord
Concepts

Networks and configuration

Why a network is always explicit, how a configuration file is validated, and what a null value means.

A network is one configuration file. Everything network specific lives in it: every address, script hash, policy id, endpoint, reference UTxO and protocol parameter.

Nothing in the codebase branches on the network name to decide behaviour. Moving to a new network is a new configuration file plus a deployment, never a code change.

There is no default network

NETWORKS is ["mainnet", "preprod", "preview"] and parseNetwork throws with the accepted set when given anything else.

Every entry point demands the network explicitly:

  • Every cardano-swap command requires --network, or CARDANO_SWAP_NETWORK in the environment.
  • The web build reads VITE_CARDANO_SWAP_NETWORK and throws a named error when it is unset: "There is no default network."

Preprod and mainnet policy ids, script hashes and addresses differ completely. A silent default would mix them.

Where the configuration is found

resolveConfigDir looks in this order:

  1. The configDir argument, when a caller passes one.
  2. The CARDANO_SWAP_CONFIG_DIR environment variable.
  3. A config directory found by walking up from the module, containing preprod.json or mainnet.json.

If none resolves, it throws and names the environment variable to set.

The browser build passes a virtual directory holding the bundled configuration files, so the same loader runs in the browser and on the command line, and the two agree on the asset set by construction.

config/ ships mainnet.json and preprod.json.

What loading validates

loadNetworkConfig(network) does four things, and any one of them failing throws rather than producing a partly trusted configuration.

Parses the file

A file that is not valid JSON throws naming the path.

Validates against the schema

The whole file is checked against a Zod schema. Hex fields must be lower case hex of the right length, out refs must be txHash#index, addresses must be bech32 with the right prefix. Failures print every issue.

Confirms the file is for the network it was loaded as

config/preprod.json declaring "network": "mainnet" throws.

Recomputes every asset fingerprint

For each asset, the CIP-14 fingerprint is recomputed from the policy id and the asset name and compared with the recorded value. A single altered character in a policy id throws at load rather than producing a wrong quote later.

Duplicate asset keys and duplicate symbols also throw.

The result is cached per directory and network.

Null means "not deployed here"

A value that can only be known after a deployment on a given network is present in the schema and set to null.

Reading one goes through requireDeployed, which throws a message naming the key and the network:

settlement.address is not set for mainnet. It is filled by the deployment on that network; there is no fallback to another network's value.

That is the point. Borrowing another network's value silently would submit a transaction against the wrong script.

The same applies to venues. A venue whose poolScriptHash is null on a network is skipped during router construction with the reason not deployed on <network>, and the skip is reported rather than swallowed.

Secrets are named, never inlined

The configuration holds the name of the environment variable that carries a credential, never the credential.

"koios": {
  "baseUrl": "https://preprod.koios.rest/api/v1",
  "bearerTokenEnv": "KOIOS_BEARER_TOKEN"
}

requireEnv(varName) reads it and throws naming the variable when it is unset. It never returns an empty string.

Adding a network

Write config/<network>.json

Copy the shape of an existing file. Fill in the assets with correct fingerprints, the venues that are deployed there, and the provider endpoints. Set every value that needs a deployment to null.

Deploy what needs deploying

cardano-swap deploy settlement --network <network> --submit publishes the settlement validator and prints the script hash, script address and reference UTxO.

Fill the nulls

Write the printed values into settlement.validatorHash, settlement.address, settlement.referenceScript and settlement.deploymentTx.

Verify

cardano-swap config show --network <network> prints the resolved configuration. cardano-swap footprint check --network <network> resolves every declared identifier on chain.

On this page