* feat: implement exchange account state management and UI updates
- Added functionality to invalidate exchange account state cache on exchange config updates, creation, and deletion.
- Introduced new API endpoint to fetch exchange account states.
- Updated frontend components to display exchange account states, including status and balance information.
- Enhanced user experience by refreshing exchange account states after relevant actions.
* feat: enhance trader creation readiness in AITradersPage and BeginnerGuideCards
---------
Co-authored-by: Dean <afei.wuhao@gmail.com>
- invalidateSystemConfig() now dispatches a custom event
- useSystemConfig() listens for the event and re-fetches automatically
- Fixes stale initialized=false after register/logout causing
incorrect redirect to SetupPage
- LoginPage/SetupPage: clear localStorage auth tokens on mount
- AuthContext: clear onboarding state on register, invalidate config on logout
- Extract shared LanguageSwitcher component for consistent UI
- Merge duplicate config import in AuthContext
- auto_trader_risk: skip drawdown check when entryPrice <= 0
- AuthContext: redirect to / on logout
- App.tsx: simplify data page navigation
- BeginnerOnboardingPage: add close button to overlay
- Lower MaxCandidateCoins from 50 to 10 (backend)
- Update CoinSourceEditor: options 1-10, default 3, max static coins 10
- Fix NofxSelect dropdown closing on internal scroll
- Fix NofxSelect position flash on open (useLayoutEffect)
- Pass `lang` from register request body to createDefaultStrategies
- Support zh/en/id locales for strategy names and descriptions
- Wrap strategy creation in a transaction to prevent partial writes
- Frontend sends current UI language in register request body
- Strategy list UI: 2-line clamp, unselected border, larger spacing, smaller font for non-zh
CoinAnk recently stopped providing free kline data for OKX/Bitget/Gate
exchanges (returns success but empty array). This caused '3-minute
k-line data is empty' errors for all users on those exchanges.
Fix: detect empty kline response and automatically fallback to Binance
kline data, which is always available.
* feat: enforce strategy limits to prevent token overflow
* fix: tune token limits after real-world testing
- Relax kline max 20→30, timeframes 3→4 (tested ~41K tokens, safe under 131K)
- Restore ranking limits to original [5,10,15,20] options (only ~1.5K token impact)
- Add static coins limit (max 3) with toast notification
- Add timeframe limit toast when exceeding 4
- Log SSE token usage (prompt/completion/total) from API response
- Fix nil logger crash in claw402 data client (engine.go)
* feat: add token estimation functionality for strategy configurations
* feat: add discard changes button in Strategy Studio for unsaved modifications
* feat: retain selected strategy after saving in Strategy Studio
* feat: enhance strategy display in Strategy Studio with improved layout and sorting of token limits
* refactor: improve layout and styling of stats display in CompetitionPage
* refactor: replace select elements with NofxSelect component for improved consistency in strategy configuration forms
* style: update NofxSelect component to use smaller text size for improved readability
* feat: implement token overflow handling in strategy updates and UI
---------
Co-authored-by: Dean <afei.wuhao@gmail.com>
When a trader uses claw402 as AI provider, the same wallet private key
is now automatically used to route nofxos data API calls (AI500, OI,
NetFlow, etc.) through claw402 payment as well.
Users don't need to configure anything extra — if they already set up
claw402 for AI, data APIs automatically go through claw402 too.
When CLAW402_WALLET_KEY env var is set, all nofxos.ai data API calls
(AI500, OI rankings, NetFlow, price rankings) are automatically routed
through claw402.ai with x402 USDC micropayment.
- provider/nofxos/claw402.go: x402 GET request client for data APIs
- provider/nofxos/client.go: claw402 mode support in doRequest()
- kernel/engine.go: auto-detect CLAW402_WALLET_KEY and enable routing
- mcp/payment/x402.go: MakeClaw402SignFunc helper
Without CLAW402_WALLET_KEY, falls back to direct nofxos.ai (backward compat).
- Track consecutive AI failures
- After 3 failures: activate safe mode (no new positions, close/hold only)
- Auto-deactivate when AI recovers
- Keep loop running in safe mode (retry each cycle)
- Log clearly: 🛡️ SAFE MODE ACTIVATED/DEACTIVATED
sonner's toast.promise() returns a toast ID (not a Promise), so
await resolves immediately and subsequent data refresh fetches stale
data. Users had to manually reload to see changes.
Fixed across AITradersPage, SettingsPage, and TraderConfigModal.
* feat: add X-Client-ID header for claw402 monitoring
* feat(mcp): add context length guard to prevent oversized requests
- Add MaxContext field to Config (default 0 = no limit)
- Add WithMaxContext() option for setting model context limits
- Add context_guard.go: token estimation + message truncation
- Integrate guard into both BuildMCPRequestBody and BuildRequestBodyFromRequest
- Support both map[string]string and map[string]any message formats
- Truncates oldest non-system messages when estimated tokens exceed limit
- Always preserves system messages and keeps at least 1 non-system message
- Logs warning when truncation occurs for debugging
Usage: mcp.NewDeepSeekClient(mcp.WithMaxContext(131072))
- Extract ParseSSEStream as shared function from CallWithRequestStream
- Add DoX402RequestStream and X402CallStream for streaming x402 payments
- Switch Claw402Client.Call to use streaming (X402CallStream)
- TeeReader fallback: SSE parsing with JSON fallback for non-SSE responses
- Idle timeout watchdog (90s) protects against stalled streams
CoinSourceEditor constructs keys as `${value}Desc` where value='oi_top',
expecting 'oi_topDesc' but the translation key was 'oiTopDesc' (camelCase).
This caused ts(undefined, lang) → "Cannot read properties of undefined".
- Add missing configResponse.ok check in handleCreateStrategy to prevent
rendering with invalid config data when API fails
- Remove deleted benefit3 translation key reference from LoginRequiredOverlay
The outer retry loop in client.go re-initiates the entire x402 payment
flow on each attempt, causing duplicate USDC charges. The inner x402
retry loop (5 attempts with re-signing) already handles all retryable
scenarios. Set MaxRetries=1 for Claw402, BlockRunBase, and BlockRunSol
to ensure only one payment per AI decision.
AI inference (especially DeepSeek) often exceeds the default 120s HTTP
timeout, causing the client to disconnect while the server completes
successfully — resulting in repeated payments on each retry.
Changes:
- Set X402Timeout = 5min for all x402 providers (Claw402, BlockRunBase, BlockRunSol)
- Handle 402 during payment retry by re-extracting Payment-Required
header and re-signing instead of failing immediately
- Increase payment retry attempts from 3 to 5 for unstable gateways
The .gitignore had a Python-inherited `lib/` rule that blocked the
entire web/src/lib/api/ directory from being tracked. The original
api.ts was a file (not matched), but the split created a directory
inside lib/ which was ignored. Remove the `lib/` gitignore rule and
add the api module split files that were missing from the previous commit.