# Nado — operations: account, testnet, going live, runbook

How to bring a trading process live on Nado and operate it: configuration and preflight, account and linked-signer setup, testnet and faucet, rollout order, health checks, failure diagnosis, and key rotation.

## TL;DR

1. **Network configuration is fail closed:** the network value (mainnet/testnet) selects the gateway and chain id; a typo aborts startup instead of silently selecting a default network. At startup, compare chain id with the `contracts` query; mismatch aborts startup. Sub-account name is an explicit parameter (1–12 ASCII characters) and is logged with its bytes32. → §1
2. **Geo-block:** Russia is fully blocked; the United States and Canada are view-only. Check the server jurisdiction before the first request. → §2
3. **Testnet is Ink Sepolia** (chain id 763373, `gateway.test.nado.xyz`), with the `testnet.nado.xyz/portfolio/faucet` faucet plus gas ETH from Ink faucets. Run the order smoke test there first, or use micro-orders on mainnet. → §3
4. **Keys:** keep the master wallet only in the browser (popup for `LinkSigner`); the server holds the linked-signer key and master address. Revoke = link the zero address; limit 50 operations per 7 days. → §4, §8
5. **Manual orders are forbidden on the bot’s sub-account:** an order without the nonce tag becomes unmanaged and prevents the conclusion that the account is empty until it is canceled manually. → §7
6. **Go live in stages:** first complete the testnet checklist with live orders, then move to mainnet with a small deposit. → §5
7. **If orders for an asset are not being placed:** grep the journal for `2117` / `2069`, inspect `trading_status` in `symbols`, check symbols-cache freshness (a rename can freeze it—restart), and inspect `ordersComplete` in the snapshot. → §6

---

## 1. Configuration and preflight

| Parameter | Value | Fail closed |
|---|---|---|
| network | `mainnet` / `testnet` | anything else → abort startup |
| gateway | derived from network (`gateway.prod.nado.xyz/v1` / `gateway.test.nado.xyz/v1`), overridable | http/https only |
| chain id | derived from network (57073 / 763373), overridable | non-integer → abort startup; mismatch with `contracts` → abort startup |
| sub-account name | `default` by default | 1–12 printable ASCII characters, otherwise abort startup |
| resting minimum | $100 | do not set manually without measurement |
| IOC minimum | = resting minimum by default | lower only after measuring the floor (`orders.md` §5) |

Startup preflight:
1. `contracts` → chain id matches and `endpoint_addr` is recorded. Otherwise **throw** (every signature would target the wrong network).
2. If the account address is already known: query `subaccount_info` with bytes32 (address + name). `exists:false` or value 0 → a **loud** warning (log + operator alert): “sub-account is empty or does not exist; if a deposit exists, the configured sub-account name is wrong—check the UI.” This is not fatal: starting before a deposit is legitimate.
3. Key-binding check: address derived from the key equals the sub-account’s `linked_signer` or the master address (`account-and-fees.md` §7).
4. A preflight read failure (network) is a warning and startup continues: the main loop handles degraded reads.

---

## 2. Geo-block and jurisdiction

IP block: Russia is fully blocked; the United States and Canada are view-only (according to Nado documentation and observation). Before starting, ensure that the server’s egress address is in an allowed jurisdiction. Access to the web UI and compliance with the ToS are the operator’s responsibility, not the code’s.

---

## 3. Testnet

- Ink Sepolia, chain id **763373**, gateway `https://gateway.test.nado.xyz/v1` (chain id confirmed by `contracts`).
- USDT0 faucet: `testnet.nado.xyz/portfolio/faucet`; gas ETH: Ink faucets (`docs.inkonchain.com/tools/faucets`).
- Testnet checklist (`orders.md` §12): oversized RO IOC, IOC floor, GTC cycle, IOC fill by delta, complete small-size cycle (entry → partial reduction → close to zero).
- Minimum and fill checks can also use **micro-orders** on mainnet (tens of dollars): the fee is cents, and the response comes from mainnet matching, which matters more than the testnet book.

---

## 4. Account setup

1. Use a separate EVM wallet (master) for the bot. Put USDT0 on Ink and deposit it into Nado; the deposit creates the `default` sub-account. One process—one sub-account.
2. Bot key: generate a second key pair (`generatePrivateKey` from `viem`), pass the **address** to the link operation and the **private key** to the process (through secure input or an environment variable without a trailing newline).
3. Link from a browser page: `nonces` → `tx_nonce`, `contracts` → `endpoint_addr`; MetaMask signs the `LinkSigner` typed data (add/switch to Ink with `wallet_addEthereumChain`); send the signed `link_signer` execute to the gateway (in the verified design, through a local proxy rather than directly from the page; weight 30). Then `linked_signer` must show the bot-key address. Documented requirement: the sub-account already holds ≥ 5 USDT0.
4. A less secure alternative is to give the process the master key itself (self-signing); the binding check permits this. Not recommended: a linked signer can withdraw only to the master, while the master can withdraw elsewhere.
5. Verify in the UI that funds are on the sub-account with the **same name** as the configuration.

---

## 5. Rollout order

1. Network `testnet` + the §3 checklist with **live** orders.
2. Mainnet with a small deposit; increase it only after resolving the open checklist items (oversized RO IOC, IOC floor, §11).

---

## 6. Health and diagnostics

### 6.1. What to inspect

- Placement journal: asset, side, size and price, type (IOC/GTC, RO), and outcome—filled, in the book, or rejected with `error_code`; code-bearing rejections are the first thing to grep.
- Your orders in the book grouped by asset, with the order-read completeness flag beside them: when `ordersComplete=false`, “empty” proves nothing.
- Labeled throttle counters (`rate-limits.md` §3).

### 6.2. Symptom → cause → action

| Symptom | Check | Action |
|---|---|---|
| Orders for an asset are not being placed | grep `2117` → market is `post_only`; grep `2069` → `not_tradable` | If 2117 repeats for DEFAULT, the symbols cache is stale/frozen → restart (§6.3). If `not_tradable`, wait for listing and do not enable the market for trading |
| `2117` rejections on IOC with an open position | stock perpetual on a weekend / pre-listing | Expected: IOC does not pass on a `post_only` market, so close is rejected. Do not restart. Check execute budget (`rate-limits.md` §5) |
| “New asset is not listed,” but it appears in the UI | symbols cache froze after a rename | §6.3 |
| Equity is `UNKNOWN`, no errors | `subaccount_info.exists`, sub-account name | Compare the name with the UI |
| “Empty account,” but the UI shows orders | order read is partial (`ordersComplete=false`) or orders have no tag (manual) | Wait for a complete survey; cancel manual orders manually |
| Every market action is `REJECTED` without a code | IOC minimum below its floor? price/size quantizes to 0? | Measure the floor; log quantization |
| Every execute is rejected after deployment | chain id / gateway | preflight §1 |
| Every request returns 403 | manually set `Accept-Encoding` header | remove it (`api-and-signing.md` §2) |

### 6.3. Frozen symbols cache

Symptom: a symbols cache with a stability check (“reject refresh if a previously verified asset disappeared”) rejects every refresh and serves the stale cache. Cause: a market rename or removal (for example, CIRCLE → CRCL on 2026-08-10). Trading does not crash, but new listings remain invisible until restart. Remedy: restart the process. **Before restarting**, request `{type:'symbols', product_type:'perp'}` three times in a row and compare the size and presence of your assets: the stability check protects against truncated responses, and restarting on a truncated response would make it the new baseline.

---

## 7. Manual orders are forbidden

Do not trade manually on a sub-account managed by the process. An order without the nonce tag is “foreign”: the process neither cancels nor matches it, but it counts as exposure and blocks conclusions such as “the account is empty” until it is canceled manually. If the operator must act manually, first stop the process, then clear the book, then act.

One process—one sub-account. Two processes on one sub-account will cancel one another’s book.

---

## 8. Key rotation

- A new linked signer **replaces** the old one with a single link operation (including 1-Click Trading from the UI). Limit: 50 link/revoke operations per sub-account per rolling 7 days.
- Sequence: stop the process gracefully and wait for the tick to finish → link the new address in the browser → verify `linked_signer` → put the new key into the process → start → preflight confirms the binding.
- Revoke = link the zero address. Revoke does **not close** positions or cancel orders.
- The master key never enters the server.

---

## 9. Shutdown and restart

- Graceful shutdown waits for the current cycle to finish, or the process may stop between canceling its orders and sending IOC.
- After restart, stored digests of your orders are gone; the first `orders` read restores them. Until an order survey is complete, “empty” has not been proven.

---

## 10. Pitfalls

| What breaks | Why | Correct approach |
|---|---|---|
| Testnet orders went to mainnet | gateway for one network, chain id for another in configuration | preflight with `contracts`; abort startup |
| Process is silent and equity is unknown | sub-account name differs from the UI | explicit parameter, print bytes32, loud alert on `exists:false` |
| “Not listed,” but the market exists | frozen symbols cache | 3 requests → restart |
| Master key is in server environment | linking used a CLI script on the server | browser popup; only the signer is on the server |
| Operator order remains “foreign” | manual trading on the bot’s sub-account | stop → clear → act |
| Restart between order cancellation and IOC | shutdown did not wait for the cycle | wait for the current cycle to finish |
| Duplicate process on one sub-account | a second instance started with the same key | one process—one sub-account; compare addresses, not keys |
| Panic restarts on weekends | 2117 rejections because stock perpetuals are `post_only` | this is not a failure; read the rejection code |

---

## 11. Open questions / not verified

- **Geo-block:** exact behavior (response code) for a request from a blocked jurisdiction was not captured.
- **API withdrawals**, including the signer restriction “only to master,” were not performed.
- **Multiple sub-accounts under one master** across multiple processes are possible by design but were not verified.
- **Exchange behavior when a signer expires or is rotated while orders are open** was not verified (orders presumably remain).
- **Oversized RO IOC and exact IOC floor** (testnet checklist items): responses were not captured; verify on testnet or with micro-orders on mainnet (`orders.md` §12).

---

Facts verified through 2026-09-16. Nado changes: verify the gateway, modes, and linked-signer rules against documentation and live requests.

---

<!-- license-footer -->
_© markpaper authors. Licensed under [CC BY 4.0](LICENSE.md): when publishing or adapting this material, credit “markpaper — Nado knowledge base” and link to the original and the license._
