Skip to content
Join the waitlistWaitlist

Paper, testnet and mainnet

The three modes Guard runs in, what each one sends where, and why mainnet needs you to type it.

Every strategy and every Guard goes through the same three steps, in order. Zunder holds itself to this: backtest, paper, testnet, live.

PaperTestnetMainnet
PricesHyperliquid mainnet, realHyperliquid testnetHyperliquid mainnet
Orders sentnoneto api.hyperliquid-testnet.xyzto api.hyperliquid.xyz
Moneynonetest USDC, no valuereal
Stops rest on the venueno (simulated)yesyes
How you get therethe default--network testnettype the network, confirm the account

Paper mode reads real prices and judges every order exactly as it would on mainnet, then records the decision instead of sending it.

Example. Your bot buys ETH. Guard answers “resized to 0.41 ETH, rule: max loss at the stop”, writes it to the journal and the event log, and sends nothing.

Testnet is a separate Hyperliquid network with test money. Orders are real orders there: stops rest on the venue and fire.

This is where Zunder runs today. Its runner (zunder-runner testnet) trades one book on a testnet account, with the risk engine, the journal, stops on the venue and the kill switch (docs/testnet.md).

Things that differ from mainnet (docs/testnet.md, “What differs between the networks”):

  • Signatures. Orders are signed for one network. A testnet signature is rejected on mainnet and the reverse: the “phantom agent” carries source "b" on testnet and "a" on mainnet.
  • API wallets, asset ids and nonces are per network. An API wallet approved on testnet does not exist on mainnet.
  • Prices on testnet are not mainnet’s.

Mainnet trades real money. Guard never gets there by itself.

Zunder’s own code has a mainnet path, built and reviewed, never run, and switched off. It refuses to start unless every one of these holds at once (docs/testnet.md, “The guards, all at once”):

  • the command names mainnet, and the config says network = "mainnet" (there is no default network);
  • allow_mainnet = true, an equity cap, the account and the API wallet in the config;
  • a confirmation that names the traded account, read at every start, before the key is read;
  • the key arrives on standard input only, and its address must be the configured API wallet;
  • the risk journal was started for mainnet and this account.

Each mode has its own journal. Moving from testnet to mainnet starts a new journal with a new peak. Your limits carry over in the config; the risk state does not.

This page as plain Markdown, for people and LLMs: /docs/concepts/networks.md