# Hyperliquid copy-research watchlist/report v1.1 pattern

Use when extending the read-only Hyperliquid copy-research collector beyond concept/v1 into configurable watchlists, degradation-aware collector results, and richer daily reports.

## Core stance

- Keep the copy-research track strictly read-only: no live copy, no orders, no vault deposits, no wallet/API-wallet execution, no signing, and no cron/systemd autostart without explicit approval.
- Runtime config and snapshots live outside the repo, for example `/home/agent/.local/state/CryptoTradingBot/copy_research/`.
- Commit only code/tests/docs/fixtures. Never commit runtime watchlists, reports, JSONL snapshots, or real leader/wallet addresses.

## Runtime watchlist

Create a runtime-only watchlist:

```text
copy_research/state/watchlist.json
```

Schema:

```json
{
  "version": 1,
  "wallets": [
    {"address": "0x...", "label": "optional_name", "source": "manual", "enabled": true, "notes": ""}
  ],
  "vaults": [
    {"vault_address": "0x...", "label": "optional_name", "source": "manual", "enabled": true, "notes": ""}
  ]
}
```

Implementation pattern:

- Provide `load_watchlist()`, `save_watchlist()`, `validate_watchlist()`, `enabled_wallets()`, and `enabled_vaults()`.
- Missing watchlist should default to an empty valid watchlist and should not crash collection/reporting.
- `--init` should create the empty runtime file; `--show` should display summary/payload without secrets.
- Validate EVM-style addresses structurally; tests must use dummy fixture addresses only.
- Ignore `enabled=false` entries.
- Wallets/vaults may come only from runtime config or explicit CLI args; do not hardcode real addresses in code/tests.

## Read-only guard

Add a central guard module and have both collector result and report surface it:

```text
read_only = true
live_orders = false
vault_deposits = false
wallet_execution = false
signing_enabled = false
```

Add a safety test over productive `src/ctb_copy` code that blocks order/signing/exchange terms such as `create_order`, `market_open`, `set_leverage`, `vaultDeposit`, `exchange.order`, `Account.from_key`, `HL_AGENT_PRIVATE_KEY`, and `HL_API_PRIVATE_KEY`. If the test itself needs to mention the strings, build them dynamically or scan only productive code so the test does not fail on its own fixture text.

## Collector v1.1 behavior

Collector result should include:

```text
status: ok | degraded
vault_summaries_count
vault_watchlist_count
vault_snapshot_count
vault_collection_status
api_response_shape_known
wallet_watchlist_count
wallet_snapshots
market_context_snapshots
new_leaders
disappeared_leaders
data_quality
partial_errors
snapshot_paths
guard
watchlist summary
```

Rules:

- Partial wallet/vault/API errors mark the run `degraded`, not full failed.
- Do not crash the whole run when one configured wallet/vault fails.
- If `vaultSummaries` returns zero, record zero and the response-shape status; do not infer missing vault data.
- For configured vaults, use read-only `vaultDetails` if supported by the official Info API; never deposit or sign.
- Write collector results under `reports/collector_results/YYYY-MM-DD.json` so reports can render the last run without rereading raw exchange data.

## Market Context v1.1

Store a compact summary alongside raw read-only payloads:

```text
timestamp
universe_count
perp_dex_count
core_symbols_available: BTC, ETH, SOL, LINK
research_alt_available: WLD, SUI, ENA, BCH
all_mids_count
meta_count
api_status
api_errors
optional mids: btc_mid, eth_mid, sol_mid, hype_mid
```

Use one bounded collection pass (`meta`, `perpDexs`, `allMids`) and avoid REST spam.

## Daily Report v1.1

Include:

- watchlist exists yes/no;
- enabled wallet/vault counts;
- explicit note when no wallets are enabled: `Keine Wallets in watchlist.json aktiviert. Wallet-Snapshots deshalb 0.`;
- vault summary/watchlist/snapshot counts and `api_response_shape_known`;
- market-context summary;
- new and disappeared leaders;
- discovery registry summary;
- snapshot paths;
- data quality / partial errors;
- read-only guard values and a clear no-live/no-deposit/no-signing statement.

## Verification checklist

Before commit/push:

```bash
PYTHONPATH=. pytest -q
PYTHONPATH=. python3 -m compileall -q src tests
git diff --check
git status --short
grep -RInE "private_key|secret|api_key|agent_wallet|master_key|CTB_.*SECRET|HYPERLIQUID.*KEY" src/ctb_copy tests/test_ctb_copy_* || true
```

Run a real one-shot smoke, still with no autostart:

```bash
PYTHONPATH=. python3 -m src.ctb_copy.watchlist --init
PYTHONPATH=. python3 -m src.ctb_copy.watchlist --show
PYTHONPATH=. python3 -m src.ctb_copy.run_collector_once
PYTHONPATH=. python3 -m src.ctb_copy.reports.daily_copy_report
find /home/agent/.local/state/CryptoTradingBot/copy_research -maxdepth 5 -type f | sort | tail -30
```

Verify the remote feature branch by checking `git ls-remote origin refs/heads/<branch>` against `git rev-parse HEAD`; do not use remote `HEAD` as branch proof.
