Commit Graph

80 Commits

Author SHA1 Message Date
tinkle-community
3c061aee94 fix(security): tighten strategy-market iframe permissions
Two issues in the prior commit that the embedded vergex.trade explore
iframe did not actually need:

  1. `allow=clipboard-write` granted the iframe silent write access to
     the user's clipboard via the Clipboard API. A compromised or
     compromised-by-injection vergex page could overwrite copied
     content — classic clipboard-hijack pattern (e.g. swap a copied
     wallet address right before the user pastes it into a send form).
     The explore view does not need this capability; drop it. Matches
     the existing DataPage.tsx iframe pattern.

  2. No `sandbox` attribute, so the iframe ran with full implicit
     permissions: arbitrary scripts, form submission, top-level
     navigation, modals, pointer lock, etc. Add an explicit sandbox
     whitelist that grants only what the explore view actually uses:

       allow-scripts allow-same-origin allow-forms
       allow-popups allow-popups-to-escape-sandbox

     Notably withheld:
       - allow-top-navigation: the iframe cannot redirect the NOFX
         shell to an arbitrary URL.
       - allow-modals / allow-pointer-lock / allow-orientation-lock:
         not used by the explore page.
       - allow-storage-access-by-user-activation: keeps third-party
         storage access prompts off the embedded surface.

Verified: explore page renders identically; no sandbox-related
violations in the console (residual errors are vergex's own internal
CSP rejecting analytics + asset fetches, unrelated to our embedding).
2026-06-02 01:56:32 +08:00
tinkle-community
30c6abca74 feat(web): inline-embed vergex.trade/explore in the strategy market
vergex.trade now lists the NOFX origins in the enforced CSP
`frame-ancestors` directive for the /explore path:

  frame-ancestors 'self' https://nofxos.ai https://www.nofxos.ai
                  http://127.0.0.1:3000 http://localhost:3000

so cross-origin embedding from any NOFX deployment works. The
X-Frame-Options header is still SAMEORIGIN, but modern browsers honor
the CSP `frame-ancestors` directive when both are present (per CSP
Level 2), and the embed verifies cleanly under Chromium.

Replaces the prior fallback "open in new tab" CTA card with the same
iframe pattern DataPage.tsx already uses for vergex.trade/trending —
single iframe filling the AppChrome content area, full-screen and
clipboard permissions enabled, strict-origin referrer.
2026-06-02 01:49:22 +08:00
tinkle-community
e4adafa364 feat(web): quick-trade button actually trades - auto-start + honest status
The lightning button on the symbol panel was the single biggest
"agent does nothing" complaint: it created a trader and a strategy via
direct REST calls, then handed the user a hardcoded reply that read
"我没有自动启动实盘交易。请到 Traders 面板确认风控后手动 Start" —
i.e. the chat bot openly admitted it bypassed the agent and refused to
do the work the user had clearly asked for.

- web/src/lib/hyperliquidQuickTrade.ts: after createStrategy +
  createTrader (or finding an existing trader), call POST
  /api/traders/:id/start immediately. Report `started`, `reusedTrader`,
  and an optional `startError` so the chat reply can be honest about
  what happened — created vs reused, running vs failed, and why.

- web/src/pages/AgentChatPage.tsx: replace the canned "please start
  manually" reply with one that reflects reality. Success path shows
  the symbol, strategy, 5-min scan interval, and how to halt it via
  chat. Failure path surfaces the actual start error and tells the
  user the trader exists but is not running.

- web/src/lib/hyperliquidQuickTrade.ts: per-symbol prompt now routes
  on category. Stocks (category="stock") get a long-only, momentum-
  seeking prompt — break of high, volume spike, support reclaim, sector
  catalyst — because shorting individual US equities through the agent
  is rarely what the user wants. Crypto stays bidirectional but
  disciplined. The trader-level custom_prompt is rewritten in the same
  style and explicitly forbids rotating to other symbols.
2026-05-29 22:13:51 +08:00
tinkle-community
75832f9eb2 feat(web): redesign login page and proxy strategy market to vergex.trade
- LoginPage: two-column desktop layout with brand panel (status pill,
  gradient headline, stats strip) and form panel; single-column mobile
  layout with centered brand mark. Self-contained grid centering so
  layout no longer depends on parent flex behavior. Drop the dead
  OnboardingModeSelector (it belongs to SetupPage, not login) and add
  loader spinner, animated submit arrow, and clearer error banner.
- StrategyMarketPage: replace the 560-line bespoke marketplace with a
  branded handoff to vergex.trade/explore. Direct iframe embedding is
  currently blocked by vergex's X-Frame-Options: SAMEORIGIN and
  frame-ancestors 'self', and there is no way to reliably detect the
  block from JavaScript (load event fires for the browser error page,
  contentWindow.location throws SecurityError in both success and
  failure). The component now renders a centered card with the
  POWERED BY VERGEX.TRADE pill, headline, description, gold CTA, and
  a stats row, with all three supported languages.
- .gitignore: exclude .gstack/ (local security audit reports).
2026-05-29 16:14:46 +08:00
tinklefund
3b2e7027db feat(web): refresh Hyperliquid-focused product UI
- Update landing, chart, settings, and data page copy for stock trading

- Adjust branding and translations around Hyperliquid positioning

- Extend frontend config types for the updated exchange settings
2026-05-25 01:25:23 +08:00
tinklefund
f4ee723aa2 feat(agent): surface Hyperliquid stock trading context
- Add stock symbol panel and agent chat page wiring

- Update onboarding and tool visibility for focused trader flows

- Tighten related tests around configuration and trader scope
2026-05-25 01:25:10 +08:00
tinklefund
5bdffee3b0 feat(strategy): support Hyperliquid stock strategy editing
- Extend strategy storage and engine analysis for Hyperliquid defaults

- Rework coin source and indicator editors for the stock strategy flow

- Update Strategy Studio translations and page wiring
2026-05-25 01:25:05 +08:00
shinchan-zhai
d80bb31c0a fix(web): fix UI bugs and unify design tokens
- Add missing .nofx-glass CSS class (used in 20+ places but undefined)
- Fix Input component referencing undefined --brand-black/--brand-light-gray
- Unify background colors to #0B0E11 (was 3 different near-blacks)
- Switch body font from IBM Plex Mono to Inter for readability
- Improve chat bubble contrast (bg 0.03→0.05, border 0.05→0.08)
- Brighten timestamp (#2c2c42→#5a5a72) and disclaimer (#1e1e32→#4a4a62)
- Unify ::selection color to gold (was orange)
- Remove global button:hover translateY that conflicted with active:scale

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-11 23:51:27 +08:00
lky-spec
159f27dfdd Improve NOFXi agent product handling 2026-05-02 22:55:10 +08:00
lky-spec
25d0b30ea9 Split strategy config by strategy type 2026-04-28 20:19:24 +08:00
lky-spec
9ee931ee30 v2 2026-04-25 20:24:46 +08:00
lky-spec
c244e4cdf1 change v1 2026-04-25 16:18:45 +08:00
lky-spec
737f9bca95 Enhance NOFXi agent workflow and diagnostics 2026-04-19 16:06:28 +08:00
lky-spec
5c4e7502d7 feat: integrate NOFXi agent into dev 2026-04-18 16:06:42 +08:00
deanokk
e1b5a5d833 refactor: replace window.location with useNavigate for routing in auth components (#1470)
Co-authored-by: Dean <afei.wuhao@gmail.com>
2026-04-13 23:44:14 +08:00
deanokk
a1af4fec58 feat(store): prevent deletion of active strategies and update translations (#1461)
Co-authored-by: Dean <afei.wuhao@gmail.com>
2026-04-11 01:09:13 +08:00
deanokk
1d6e99c74a feat(beginner): protect default AI model and prevent repeated onboarding (#1444)
Co-authored-by: Dean <afei.wuhao@gmail.com>
2026-03-30 21:04:43 +08:00
shinchan-zhai
fb0bd13f51 fix: division by zero guard, logout redirect, onboarding close button
- 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
2026-03-30 14:02:50 +08:00
Zavier
55db747318 feat: refine beginner wallet onboarding modal (#1438)
Co-authored-by: Codex <codex@openai.com>
2026-03-28 16:09:04 +08:00
shinchan-zhai
cab58afe6d fix: guard short trader ID, i18n setup page, simplify onboarding UX
- main.go: prevent panic when trader ID < 8 chars
- SetupPage: add zh/en i18n labels
- BeginnerOnboardingPage: show private key by default, simplify code
2026-03-28 14:14:20 +08:00
Dean
2e2598e4e0 fix: update token limits and error handling in Trader Dashboard 2026-03-28 00:23:11 +08:00
Dean
c6adc34247 fix: update error handling for account data fetch on Trader Dashboard 2026-03-28 00:23:11 +08:00
Dean
1d897f635e feat: localize default strategy names by UI language at registration
- 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
2026-03-28 00:23:11 +08:00
Dean
1c378007ee fix: show -- instead of 0 when account data fetch fails on dashboard
Replace zero-value fallback with undefined, pass accountFailed prop to
distinguish load failure from initial loading skeleton.
2026-03-28 00:22:49 +08:00
Dean
95e76f6a56 feat: enhance token estimation and context limit handling in strategy configurations 2026-03-28 00:22:49 +08:00
Dean
6cb6c31b34 feat: enhance strategy deletion process with user feedback and validation checks 2026-03-28 00:21:37 +08:00
Zavier
b331733e23 feat: improve user onboarding and setup UX (#1436)
* feat: add beginner onboarding and mode switching flow

* chore: ignore local gh auth config

* fix: restore kline fallback and align onboarding language

---------

Co-authored-by: zavier-bin <zhaobbbhhh@gmail.com>
2026-03-28 00:17:37 +08:00
deanokk
f0d3352971 fix: prevent DeepSeek token overflow with product-level limits (#1431)
* 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>
2026-03-27 00:26:40 +08:00
shinchan-zhai
53ac52562f fix: replace toast.promise with await to ensure state refresh after API calls
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.
2026-03-21 00:54:36 +08:00
tinkle-community
7203655ae7 fix: strategy studio black screen on create and remove stale benefit3 ref
- 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
2026-03-16 07:55:47 +08:00
tinkle-community
21a15f98eb refactor: remove all backtest module code and references
Delete backtest/ engine (19 files), api/backtest.go, store/backtest.go,
web backtest components (7 files), API client, types, docs, screenshot.
Clean all backtest references from main.go, api/server.go, store/store.go,
App.tsx, HeaderBar.tsx, LandingPage.tsx, translations, README and docs.
2026-03-16 07:38:01 +08:00
tinkle-community
736d2d385d refactor: optimize codebase encoding 2026-03-12 16:14:56 +08:00
tinkle-community
cb31782be4 refactor: split large files and clean up project structure
- Rename experience/ to telemetry/ for clarity
- Split 15+ large Go files (800-2200 lines) into focused modules:
  kernel/engine.go, backtest/runner.go, market/data.go, store/position.go,
  api/handler_trader.go, trader/auto_trader_grid.go, and 9 exchange traders
- Split frontend monoliths: types.ts, api.ts, AITradersPage.tsx, BacktestPage.tsx
  into domain-specific modules with barrel re-exports
- Remove stale files: screenshots, .yml.old, pyproject.toml
- Remove unused scripts/ and cmd/ directories
- Remove broken/outdated test files (network-dependent, stale expectations)
2026-03-12 12:53:57 +08:00
tinkle-community
8e294a5eed refactor: restructure project directories for better modularity
- Delete llm/ dead code (3 files, zero references)
- Split mcp/ into sub-packages: mcp/provider/ (8 providers) and
  mcp/payment/ (4 payment clients) with registry pattern
- Export Client internal fields and ClientHooks interface for
  sub-package access
- Split api/server.go (3892 lines) into 8 domain-specific handler files
- Split trader/auto_trader.go (2296 lines) into 5 focused files
- Reorganize web/src/components/ flat files into auth/, charts/,
  trader/, common/, modals/, backtest/ subdirectories
- Update all consumer imports to use registry-based provider creation
2026-03-11 23:58:13 +08:00
tinkle-community
94ef009bb5 refactor: remove all Debate Arena feature code
Remove the entire AI Debate Arena module (~5,300 lines) to simplify
the codebase. This removes the multi-AI debate trading decision system
including backend engine, API handlers, database store, frontend page,
navigation, translations, and documentation references.
2026-03-11 17:32:41 +08:00
tinkle-community
9c5c976d9a feat: Claw402 x402 payment provider + Telegram agent + x402 refactoring (#1409)
* feat(telegram): add AI agent bot with streaming and account context

- Add Telegram bot with long-polling and AI agent loop (api_call tool)
- SSE streaming with real-time message editing and  placeholder
- Account state injection at conversation start (models, exchanges,
  strategies, traders, per-trader PnL and statistics)
- Lane semaphore per chat serializes concurrent messages (60s timeout)
- Idle timeout watchdog (60s) prevents hung streaming connections
- Look-ahead buffer prevents partial <api_call> tag leaking to user
- Fix PUT /strategies/:id to merge config (read-then-merge pattern)
- Add route registry with full API schema for LLM documentation
- Add TelegramConfig store and Web UI config modal
- Add GetAnyEnabled to AIModel store for bot LLM client selection

* fix(telegram): eliminate narration, add full-setup workflow and tests

- Rewrite NO NARRATION rule: response is EITHER api_call tag alone OR
  final text reply — no text before api_call under any circumstances
- Ban all narration patterns: 现在我将/好的/正在/I will/Let me etc.
- Add 'create strategy + create trader + start' full setup workflow
- Add 12 automated tests covering:
  - No narration leaking to user (5 narration variants tested)
  - api_call tag never leaks to user
  - Full setup workflow: POST strategy → verify → POST trader → start
  - Start existing trader workflow
  - Max iterations safety, tag stripping, parser edge cases

* refactor(agent): replace XML api_call with native function calling

Migrate the Telegram bot agent from an XML tag hack (<api_call>) to
OpenAI-native function calling via CallWithRequestFull.

Key changes:
- mcp/interface.go: add parseMCPResponseFull to clientHooks interface
- mcp/client.go: route callWithRequestFull through hooks for overridability
- mcp/claude_client.go: override parseMCPResponseFull for Claude response
  format (tool_use blocks instead of choices[].message.tool_calls)
- telegram/agent/agent.go: rewrite Run() to use CallWithRequestFull;
  define api_request tool with JSON Schema; implement tool-call loop
  with role="tool" result messages; remove XML parsing entirely
- telegram/agent/apicall.go: remove parseAPICall (dead code)
- telegram/agent/prompt.go: simplify — remove XML format instructions,
  replace with concise api_request tool usage instructions
- telegram/agent/agent_test.go: rebuild all tests using LLMResponse
  objects; add TestNarrationStructurallyImpossible, TestOnChunkCalledWithFinalReply,
  TestToolCallIDPropagated; remove XML-specific tests

Architecture advantage: with native function calling, the LLM returns
EITHER ToolCalls OR Content — never both. Narration is now structurally
impossible at the protocol level, not just enforced by prompt rules.

All 11 agent tests pass. mcp package tests pass.

* refactor(mcp): route buildRequestBodyFromRequest through hooks + full Anthropic format

Problem: callWithRequest/Full/Stream all called client.buildRequestBodyFromRequest
directly (not via hooks), so ClaudeClient could never override it. This meant
tool calling sent OpenAI format to Anthropic (wrong field names, wrong roles).

Changes:

mcp/interface.go
- Add buildRequestBodyFromRequest(*Request) map[string]any to clientHooks
- Improve comments: document what each hook group does and why

mcp/client.go
- All three paths (callWithRequest, callWithRequestFull, CallWithRequestStream)
  now call client.hooks.buildRequestBodyFromRequest — ClaudeClient picks up

mcp/claude_client.go
- Full rewrite with format comparison table in package doc
- buildRequestBodyFromRequest: produces correct Anthropic wire format
    * system prompt → top-level "system" field
    * tools: parameters → input_schema, no "type:function" wrapper
    * tool_choice "auto" → {"type":"auto"} object
    * assistant tool calls → content[{type:tool_use, id, name, input}]
    * role=tool results → role=user content[{type:tool_result,...}]
    * consecutive tool results merged into single user turn
- convertMessagesToAnthropic: handles all three message types
- parseMCPResponseFull: extracts text + tool_use blocks
- parseMCPResponse: delegates to parseMCPResponseFull

All mcp and agent tests pass.

* fix(telegram): fix claude client dispatch + strategy creation workflow

- telegram/bot.go: clientForProvider now returns NewClaudeClient() for
  'claude' provider (was incorrectly falling back to DeepSeekClient which
  uses OpenAI wire format, breaking Anthropic API calls)

- api/server.go: fix scan_interval_minutes schema default (3, not 60);
  POST /api/strategies now clearly states config is OPTIONAL with complete
  working defaults; POST /api/traders removes redundant GET workflow note

- telegram/agent/prompt.go: simplify strategy creation — just POST {name}
  without config (backend applies full working defaults automatically);
  only include config when user requests custom settings

* test(mcp): add ClaudeClient wire format tests

Tests cover all Anthropic-specific format conversions:
- system prompt lifted to top-level field
- tools use input_schema (not parameters)
- tool_choice is object {type:auto} not string
- assistant tool calls → content[{type:tool_use}]
- consecutive tool results merged into single user turn
- parseMCPResponseFull: text, tool_use, and error cases
- x-api-key header (not Authorization: Bearer)
- /messages endpoint URL

* fix(telegram): clientForProvider returns correct client for all 7 providers

Previously qwen/kimi/grok/gemini all fell back to DeepSeekClient.
Each provider now gets its own dedicated client with correct default
base URL and model. All 7 providers now fully supported:
openai, deepseek, claude, qwen, kimi, grok, gemini

* fix(telegram): newLLMClient uses bound user's model, not any user's model

GetAnyEnabled() searched across all users in DB — if user B has an
enabled model, bot could use their API key while acting as user A.

Now uses GetDefault(botUserID) which only looks up the bound user's
enabled model, matching the same user scope as all API calls.

* fix(auth): single-user deployment by default, no open registration

Registration logic redesigned:
- Empty DB (first-time setup): registration always open, no config needed
- After first user exists: registration closed by default
- Multi-user opt-in: set REGISTRATION_ENABLED=true + MAX_USERS=N in .env

Config defaults changed:
- RegistrationEnabled: true → false (closed after first user)
- MaxUsers: 10 → 1 (single-user deployment default)

This eliminates the confusion of multiple users appearing in a personal
deployment where Telegram is bound to a single admin account.

* feat(solo): beginner-friendly onboarding — smart setup guide + direct config commands

start.sh:
- Interactive Telegram Bot Token prompt on first run
- Token format validation (must match 12345:ABC... pattern)
- Friendly step-by-step startup instructions after launch

telegram/bot.go:
- /start now shows context-aware setup guide based on actual config state:
  - No AI model → explains how to configure, lists all providers
  - AI model OK but no exchange → guides to configure exchange via chat
  - All configured → full capabilities welcome message
- New: direct setup commands ('配置 deepseek sk-xxx') bypass LLM entirely
  so AI model can be configured even before any model exists (bootstrap fix)
- All messages now in Chinese (匹配用户语言)

telegram/agent/prompt.go:
- Added first-time setup detection section
- Agent told to never ask user to visit web UI — everything via chat

* feat(i18n): bilingual EN/ZH setup guide with language selection

store/telegram_config.go:
- Add Language field to TelegramConfig (persisted in DB)
- Add SetLanguage(lang) and GetLanguage() methods
- Default language: English (en)

telegram/bot.go:
- First /start triggers language selection (1=English, 2=中文)
- /lang command to change language at any time
- awaitingLang state machine handles language choice before any other input
- buildSetupGuide() now fully bilingual (EN/ZH), context-aware:
  Step 1: configure AI model (no model yet)
  Step 2: configure exchange (model OK, no exchange)
  Ready: show full capabilities
- tryHandleSetupCommand() bilingual: 'configure/配置 <provider> <key>'
- helpMessage(lang) fully bilingual
- All error/status messages bilingual

Default: English. isLangDefault() detects whether user has explicitly
chosen a language vs falling back to the 'en' default.

* fix(telegram): use Markdown rendering + simplify language selection condition

- sendMarkdownMsg() helper: sends with ParseMode=Markdown, falls back to plain text
- All formatted messages (langSelectionMsg, buildSetupGuide, helpMessage) now render
  bold text and code blocks correctly in Telegram
- Simplify /start language check: isLangDefault(st) alone is sufficient
  (lang == 'en' && isLangDefault was redundant — GetLanguage returns 'en' when empty)

* fix(start.sh): translate all user-facing text to English

Entire script was in Chinese. Now English-first throughout:
- startup banner, prompts, success/error messages
- setup_telegram(): English instructions and validation messages
- start(): English next-steps after launch
- stop/restart/clean/update/regenerate-keys/show_help: all English

* fix(telegram): remove 'default' user fallback — resolve user dynamically

- botUserID no longer captured once at startup (was 'default' if no user yet)
- resolveBotUser() reads first registered user from DB on demand:
  * called on every /start (handles: registered after bot launch)
  * called before every AI message (handles mid-session registration)
- If no user registered: clear English error 'No account found. Please register on the web UI first'
- start.sh: fix set_env_var appending without newline (token was concatenated to prev line)

* refactor(telegram): clean onboarding — web UI for setup, Telegram for operations

- /start shows clean status: 'setup required → open web UI' or 'ready → examples'
- Removed tryHandleSetupCommand (no more CLI-style 'configure deepseek sk-xxx')
- Removed automatic language selection on /start (use /lang anytime instead)
- newLLMClient returns nil when no model → clear guard, not fallback
- statusMsg() replaces buildSetupGuide(): two states only (missing config / ready)
- Bot is now purely an operations interface; config lives in the web UI

* refactor: single-user web-based setup — replace env config with Settings UI

Move from multi-user env-var config to single-user web-first architecture:
- Add SetupPage for first-time initialization (replaces /register)
- Add SettingsPage for AI models, exchanges, Telegram, and password management
- Enrich all API route schemas with exact ID usage documentation
- Add PUT /user/password endpoint for in-app password changes
- Remove REGISTRATION_ENABLED, MAX_USERS, TELEGRAM_BOT_TOKEN from env config
- Simplify LoginPage design, remove admin mode and registration links
- Telegram bot now resolves user email for identity display
- start.sh no longer runs interactive Telegram setup

* feat: add blockRun (x402 USDC) support to all AI model consumers

- telegram/bot.go: add blockrun-base, blockrun-sol, minimax to
  clientForProvider; fix newLLMClient to prefer TelegramConfig.ModelID
  over GetDefault; log USDC payment provider usage
- debate/engine.go: add blockrun-base, blockrun-sol to InitializeClients
- api/strategy.go: add blockrun-base, blockrun-sol to runRealAITest
- backtest/ai_client.go: add blockrun-base, blockrun-sol to configureMCPClient

* feat: add Claw402 (claw402.ai) x402 USDC payment provider

Add Claw402Client for claw402.ai's x402 micropayment gateway (Base USDC).
Supports 15+ AI models (GPT-5.4, Claude Opus, DeepSeek, Qwen, Grok, etc.)
with per-model endpoint routing.

- mcp/claw402.go: new client with model→endpoint mapping, x402 v2 payment flow
- mcp/blockrun_base.go: extract shared signX402Payment() for reuse
- Register "claw402" provider in all 6 consumer switch statements:
  api/server.go, api/strategy.go, trader/auto_trader.go,
  telegram/bot.go, debate/engine.go, backtest/ai_client.go

* feat: redesign Claw402 model config UI — friendly wallet setup, USDC guide, official logo, nginx no-cache for index.html

* refactor: centralize x402 payment flow into shared mcp/x402.go

Extract duplicated doRequestWithPayment/call/CallWithRequestFull/buildRequest/
setAuthHeader (~165 lines x3) into shared helpers in mcp/x402.go. Consolidate
shared types (x402v2PaymentRequired, x402AcceptOption, x402Resource) and remove
duplicate Solana types. Fix validAfter to 0 (official SDK standard), drain 402
body before retry, log Payment-Response tx hash, check Payment-Required before
X-Payment-Required.

* fix: stop PR template bot from overwriting user-written descriptions

The pr-template-suggester workflow was triggered on opened/edited/synchronize
events and forcefully replaced the PR body with a template when body < 100 chars.
This caused user-written descriptions to be overwritten.

Replace with a lightweight labeler (OpenClaw-style) that:
- Only adds labels (backend/frontend/docs, size: XS/S/M/L/XL)
- Never modifies the PR body
- Simplified unified PR template at .github/pull_request_template.md

* chore: simplify PR template (OpenClaw-style)
2026-03-11 16:01:42 +08:00
ximi
8406f2f998 feat: add MiniMax provider support (#1406)
Add MiniMax as a new AI model provider with OpenAI-compatible API.

Supported models:
- MiniMax-M2.5 (default) - Peak Performance, Ultimate Value
- MiniMax-M2.5-highspeed - Same performance, faster and more agile

Changes:
- Add MiniMax client (mcp/minimax_client.go) with OpenAI-compatible API
- Add comprehensive unit tests (mcp/minimax_client_test.go)
- Add WithMiniMaxConfig option (mcp/options.go)
- Register MiniMax provider in trader, debate engine, backtest, and API
- Add MiniMax to frontend provider config and model icons
- Add MiniMax SVG icon

API Base URL: https://api.minimax.io/v1
2026-03-09 23:18:51 +08:00
Muhammad Syaiful Anwar
3358c5a53e feat(i18n): add Indonesian (Bahasa Indonesia) language support (#1399)
- Add 'id' to Language type in translations.ts
- Add ~1000 Indonesian translation keys covering all UI sections
- Update LanguageContext to persist 'id' in localStorage
- Add ID button to Header.tsx language toggle
- Add �� option to HeaderBar.tsx desktop dropdown and mobile toggle
- Add Indonesian translations to inline text objects in
  LoginRequiredOverlay, StrategyMarketPage, PositionHistory

Closes #XX
2026-03-03 18:39:09 +08:00
tinkle-community
0b4f43d72b fix: adaptive price precision for meme coins
- Add adaptivePriceRound() in store/position.go for database storage
- Update position_builder.go to use adaptive precision for entry/exit prices
- Add Gate to OrderSync skip list in auto_trader.go
- Add debug logging in gate/order_sync.go for price parsing issues
- Create web/src/utils/format.ts with formatPrice() for frontend display
- Update TraderDashboardPage.tsx and PositionHistory.tsx to use adaptive formatting

Fixes issue where meme coin prices (e.g. 0.000000166) displayed as 0.0000
2026-02-06 00:46:48 +08:00
tinkle-community
7e96c5d0f2 Ai grid (#1344)
* feat: add AI grid trading and market regime classification

- Add GridTrader interface with PlaceLimitOrder, CancelOrder, GetOrderBook
- Implement GridTrader for all exchanges (Binance, Bybit, OKX, Bitget, Hyperliquid, Aster, Lighter)
- Add grid engine with ATR-based boundary calculation and fund distribution
- Add market regime classification documents (Chinese/English)
- Add GridConfigEditor component for frontend configuration

* fix: implement GetOpenOrders for Lighter exchange

* debug: add logging for Lighter GetActiveOrders API call

* fix: correct Lighter API response parsing for GetOpenOrders

- Changed response field from 'data' to 'orders' to match Lighter API
- Updated OrderResponse struct to match Lighter's actual field names
- Fixed field types: price/quantity as strings, is_ask for side

* feat: implement GetOpenOrders for Aster, OKX, Bitget exchanges

- Aster: uses /fapi/v3/openOrders endpoint
- OKX: uses /api/v5/trade/orders-pending and orders-algo-pending
- Bitget: uses /api/v2/mix/order/orders-pending and orders-plan-pending

* fix: address code review issues for GetOpenOrders

- Add error logging for OKX/Bitget API failures (was silently swallowed)
- Fix Lighter position side logic to handle reduce-only orders
- Change verbose debug logs from Infof to Debugf level

* fix: provide FromAccountIndex and ApiKeyIndex for Lighter nonce auto-fetch

Root cause: SDK requires these fields to fetch nonce from API, otherwise nonce gets cached/stuck

* fix: use auth query parameter instead of Authorization header for Lighter API

* test: add Lighter API authentication tests and diagnostic tools

* fix(grid): add leverage setting before order placement

CRITICAL BUG FIX:
- Call SetLeverage() in GridTraderAdapter.PlaceLimitOrder()
- Set leverage during grid initialization
- Log leverage setting results

* fix(grid): prevent CancelOrder from canceling all orders

CRITICAL BUG FIX:
- CancelOrder no longer calls CancelAllOrders
- Try exchange-specific CancelOrder if available
- Return error if individual cancellation not supported

* fix(grid): add total position value limit check

CRITICAL: Prevent excessive position accumulation
- New checkTotalPositionLimit() function
- Checks current + pending + new order value
- Rejects orders that would exceed TotalInvestment x Leverage
- Logs clear error messages when limit exceeded

* feat(grid): implement stop loss execution

CRITICAL: Add code-level stop loss protection
- New checkAndExecuteStopLoss() function
- Checks each filled level against StopLossPct
- Automatically closes positions exceeding stop loss
- Called during every grid state sync

* feat(grid): add breakout detection and auto-pause

CRITICAL: Detect price breakout from grid range
- New checkBreakout() function to detect upper/lower breakouts
- Auto-pause grid on significant breakout (>2%)
- Cancel all orders when breakout detected
- Prevent continued losses in trending market
- Minor breakouts (1-2%) logged for AI consideration

* feat(grid): enforce max drawdown limit with emergency exit

CRITICAL: Add drawdown protection
- New checkMaxDrawdown() function tracks peak equity
- emergencyExit() closes all positions and cancels orders
- Auto-pause grid when MaxDrawdownPct exceeded
- Protect capital from excessive losses

* feat(grid): enforce daily loss limit

- Add checkDailyLossLimit() function to check if daily loss exceeds limit
- Track daily PnL with auto-reset at midnight
- Pause grid when DailyLossLimitPct exceeded
- Add updateDailyPnL() helper for realized PnL tracking
- Prevent excessive single-day losses

* fix(grid): update daily PnL when stop loss is executed

The updateDailyPnL() function was added but never called, leaving
DailyPnL always at 0 and preventing daily loss limit checks from
triggering.

This fix updates DailyPnL and TotalProfit directly in checkAndExecuteStopLoss()
when a stop loss is executed. We update directly rather than calling
updateDailyPnL() because the mutex is already held in that function.

* feat(grid): add automatic grid adjustment

- New checkGridSkew() detects imbalanced grid
- autoAdjustGrid() reinitializes around current price
- Prevents grid from becoming ineffective after drift
- Triggers when one side is 3x more filled than other

* fix(grid): recalculate bounds in autoAdjustGrid before reinitializing levels

Critical fix for grid auto-adjustment:
- Recalculate grid bounds (UpperPrice, LowerPrice, GridSpacing) centered
  on current price before reinitializing grid levels
- Preserve filled positions during adjustment by saving and restoring
  them to the closest new level after reinitialization
- Hold mutex lock for the entire adjustment operation to ensure atomicity
- Add locked variants of calculateDefaultBounds, calculateATRBounds, and
  initializeGridLevels to use during adjustment

Without this fix, autoAdjustGrid was using old boundaries when creating
new grid levels, defeating the purpose of auto-adjustment when price
moved significantly.

* fix(grid): improve order state sync logic

- Don't assume missing orders are filled
- Compare position size to determine fill vs cancel
- Properly reset cancelled orders to empty state
- More accurate grid state tracking

* fix(grid): use actual PositionSize sum instead of count in syncGridState heuristic

The position-based heuristic was using `float64(previousFilledCount) * level.OrderQuantity`
which incorrectly assumed uniform order quantities. Since the grid uses weighted distribution
(gaussian, pyramid, uniform) where orders have different quantities, this could lead to
incorrect fill detection.

Now sums the actual PositionSize from filled levels for accurate comparison.
Also adds warning log when GetPositions() fails.

* docs: add grid market regime detection design

Design for enhanced market state recognition with:
- Multi-dimensional indicators (ATR, Bollinger, EMA, MACD, RSI)
- Multi-period box indicators (72/240/500 1h candles)
- 4-level ranging classification
- Breakout detection and handling
- Frontend risk control panel

* docs: add grid market regime implementation plan

20 tasks covering:
- Donchian channel calculation
- Box data types and API
- Regime classification (4 levels)
- Breakout detection and handling
- False breakout recovery
- Frontend risk panel
- AI prompt updates

* feat(market): add Donchian channel calculation

Add calculateDonchian function to compute highest high and lowest low
over a specified period. This is the foundation for box (range) detection
in the multi-period box indicator system for grid trading.

* fix(market): handle invalid period in calculateDonchian

* feat(market): add BoxData and RegimeLevel types

* feat(market): add GetBoxData for multi-period box calculation

Adds calculateBoxData internal function and GetBoxData public API that
fetches 1h klines and computes three Donchian box levels (short/mid/long).
This will be used by the grid trading system to detect market regime.

* feat(store): add box and regime fields to grid models

* feat(trader): add regime classification and breakout detection

Implements Tasks 6-9 for grid market regime awareness:
- Task 6: classifyRegimeLevel with Bollinger/ATR thresholds
- Task 7: detectBoxBreakout for multi-period box breakouts
- Task 8: confirmBreakout with 3-candle confirmation logic
- Task 9: getBreakoutAction mapping breakout levels to actions

* feat(trader): integrate box breakout detection into grid cycle

- Task 10: Add checkBoxBreakout with 3-candle confirmation
- Task 11: Add checkFalseBreakoutRecovery for 50% position recovery
- Task 12: Add box/breakout/regime fields to GridState

* feat: add grid risk panel with API endpoint

- Task 13: Add GridRiskInfo type to frontend
- Task 14: Add /traders/:id/grid-risk API endpoint
- Task 15: Add GetGridRiskInfo method to AutoTrader
- Task 16: Create GridRiskPanel component with i18n

* feat(kernel): add box indicators to AI prompt

- Add BoxData field to GridContext
- Add box indicator table to both zh/en prompts
- Show breakout/warning alerts based on price position

* feat(web): integrate GridRiskPanel into TraderDashboardPage

* feat(lighter): improve API key validation and market caching

- Add API key validation status tracking
- Add market list caching to reduce API calls
- Improve logging (debug vs info levels)
- Add comprehensive integration tests
- Update trader manager and store for lighter support

* fix: remove hardcoded test wallet address

* fix(grid): improve GridRiskPanel layout and fix liquidation data

- Make panel collapsible with summary badges when collapsed
- Use compact 2-column grid layout for detailed info
- Fix auth token key (token -> auth_token)
- Only calculate liquidation distance when position exists

* fix(grid): add isRunning checks to prevent trades after Stop() is called
2026-01-19 12:07:14 +08:00
tinkle-community
7db84d57d3 fix(web): add data route to LandingPage navigation 2026-01-17 23:42:44 +08:00
tinkle-community
95486173f7 feat(web): add Data page with embedded nofxos.ai dashboard
- Add Data navigation item before Market in header
- Create DataPage component with iframe embedding
- Publicly accessible without login required
2026-01-17 23:37:12 +08:00
tinkle-community
e92222950a fix: use completeRegistration for incomplete OTP setup in login flow
- LoginPage: call completeRegistration instead of verifyOTP when qrCodeURL exists
- This ensures otp_verified is set to true for users completing OTP setup
- Backend: reorder maxUsers check to allow existing incomplete users to continue
- Backend: return OTP info when login with incomplete OTP setup
2026-01-07 20:15:27 +08:00
tinkle-community
799d8b9c2e feat: migrate timestamps to int64 and security improvements
- Convert all time.Time fields to int64 Unix milliseconds (UTC)
- Add PostgreSQL migration to convert timestamp columns to bigint
- Reduce Binance sync window from 7 days to 24 hours
- Fix dashboard trader name visibility (add nofx-text-main color)
- Add position value column to history table
- Remove hardcoded API keys from test files
2026-01-06 15:56:07 +08:00
tinkle-community
962df5c3ed feat: add strategy description input field 2026-01-05 00:08:51 +08:00
tinkle-community
5c9e134e99 fix: ensure all timestamps use UTC timezone
- Add NowFunc to GORM config for UTC auto-generated timestamps
- Add .UTC() to all time.UnixMilli() calls in trader files
- Add .UTC() to all time.Now() calls in store and api files
- Fix TypeScript unused imports in frontend
2026-01-04 20:03:56 +08:00
tinkle-community
50923f6a2e feat: add DeepVoidBackground and update UI theme across pages
- Add DeepVoidBackground component with animated gradient effects
- Apply nofx theme classes to StrategyStudioPage, AITradersPage, etc.
- Update styling for consistent dark theme with gold accents
- Add PageNotFound and TraderDashboardPage components
2026-01-04 17:49:59 +08:00
tinkle-community
0275e23b7e feat: unify NofxOS data provider and fix language consistency
- Add unified NofxOS API key configuration in IndicatorEditor
- Add language field to StrategyConfig for consistent prompt generation
- Auto-update prompt sections when interface language changes
- Remove scattered URL inputs from CoinSourceEditor and IndicatorEditor
- Create nofxos provider package with formatted data output
- Update kernel engine to use config-based language setting
2026-01-04 00:59:07 +08:00
tinkle-community
cc726adb57 feat: add strategy publish settings and reorder navigation
- Add is_public and config_visible fields to Strategy type
- Add PublishSettingsEditor component for strategy studio
- Enable GORM AutoMigrate to add new columns
- Reorder nav: Market → Config → Dashboard → Strategy → Leaderboard → Arena → Backtest → FAQ
- Rename Live to Leaderboard, Debate Arena to Arena
2026-01-03 00:52:11 +08:00
tinkle-community
09117bb404 feat: add strategy market, login overlay, and registration limit page
- Add public strategy market API endpoint (/api/strategies/public)
- Add is_public and config_visible fields to Strategy model
- Add LoginRequiredOverlay component for unified auth prompts
- Add WhitelistFullPage for registration capacity limit
- Add StrategyMarketPage for browsing public strategies
- Unify navigation logic across HeaderBar, LandingPage, App
- Reduce klines API calls (fetch once on mount)
- Fix various page transition issues
2026-01-01 23:05:58 +08:00