feat: server-side launch preflight with structured checks and runtime AI wallet health

- POST /api/launch/preflight and GET /api/traders/:id/preflight run every
  launch prerequisite (AI model credential, claw402 wallet key + Base USDC
  balance, strategy, exchange config, live account state, funding minimums)
  and return a structured checklist with stable codes; minimums (1 USDC AI
  fee / 12 USDC trading) now live server-side and are exposed in the response.
- POST /traders/:id/start enforces the preflight (400 with error_key
  trader.start.preflight_failed + full checklist; ?force=true to override).
  Funding gates use max(available, equity) so restarting a bot with deployed
  margin is not blocked; indeterminate probes (RPC outage) degrade to
  warnings instead of blocking.
- Run loop now surfaces runtime health via GetStatus: safe_mode(+reason) and
  ai_wallet_status/balance (ok|low|empty|unknown), including typed detection
  of claw402 ErrInsufficientFunds instead of burying it in logs; safe-mode
  state is mutex-guarded for API readers.
- Onboarding wallet endpoints switch to the cached, error-aware balance query
  and report balance_status so the UI can tell an RPC outage from an empty
  wallet.
This commit is contained in:
tinkle-community
2026-07-05 20:38:38 +09:00
parent e61f12d307
commit b17d97effc
10 changed files with 843 additions and 14 deletions

View File

@@ -91,6 +91,19 @@ func (at *AutoTrader) GetStatus() map[string]interface{} {
}
}
// Runtime health: safe mode + AI fee wallet, so the dashboard can show a
// persistent banner instead of the user digging through logs.
safeMode, safeModeReason := at.safeModeState()
result["safe_mode"] = safeMode
if safeModeReason != "" {
result["safe_mode_reason"] = safeModeReason
}
if status, balance, checkedAt := at.aiWalletHealth(); status != "" {
result["ai_wallet_status"] = status
result["ai_wallet_balance_usdc"] = balance
result["ai_wallet_checked_at"] = checkedAt.Format(time.RFC3339)
}
return result
}