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
2026-01-19 12:07:14 +08:00
2025-12-28 23:29:59 +08:00
2026-01-19 12:07:14 +08:00
2025-12-21 01:36:16 +08:00
2025-12-21 01:36:16 +08:00
2025-11-25 20:32:01 +08:00
2025-12-21 01:36:16 +08:00
2025-11-25 20:18:29 +08:00
2025-12-21 01:36:16 +08:00

NOFX — Open Source AI Trading OS

The infrastructure layer for AI-powered financial trading.

Stars Release License Telegram

Go React TypeScript

CONTRIBUTOR AIRDROP PROGRAM
Code · Bug Fixes · Issues → Airdrop
Learn More

Languages: English | 中文 | 日本語 | 한국어 | Русский | Українська | Tiếng Việt


Supported Markets

Market Trading Status
🪙 Crypto BTC, ETH, Altcoins Supported
📈 US Stocks AAPL, TSLA, NVDA, etc. Supported
💱 Forex EUR/USD, GBP/USD, etc. Supported
🥇 Metals Gold, Silver Supported

Core Features

  • Multi-AI Support: Run DeepSeek, Qwen, GPT, Claude, Gemini, Grok, Kimi - switch models anytime
  • Multi-Exchange: Trade on Binance, Bybit, OKX, Bitget, KuCoin, Gate, Hyperliquid, Aster DEX, Lighter from one platform
  • Strategy Studio: Visual strategy builder with coin sources, indicators, and risk controls
  • AI Debate Arena: Multiple AI models debate trading decisions with different roles (Bull, Bear, Analyst)
  • AI Competition Mode: Multiple AI traders compete in real-time, track performance side by side
  • Web-Based Config: No JSON editing - configure everything through the web interface
  • Real-Time Dashboard: Live positions, P/L tracking, AI decision logs with Chain of Thought

Core Team

Risk Warning: This system is experimental. AI auto-trading carries significant risks. Strongly recommended for learning/research purposes or testing with small amounts only!

Developer Community

Join our Telegram developer community: NOFX Developer Community


Before You Begin

To use NOFX, you'll need:

  1. Exchange Account - Register on any supported exchange and create API credentials with trading permissions
  2. AI Model API Key - Get from any supported provider (DeepSeek recommended for cost-effectiveness)

Supported Exchanges

CEX (Centralized Exchanges)

Exchange Status Register (Fee Discount)
Binance Register
Bybit Register
OKX Register
Bitget Register
KuCoin Register
Gate Register

Perp-DEX (Decentralized Perpetual Exchanges)

Exchange Status Register (Fee Discount)
Hyperliquid Register
Aster DEX Register
Lighter Register

Supported AI Models

AI Model Status Get API Key
DeepSeek Get API Key
Qwen Get API Key
OpenAI (GPT) Get API Key
Claude Get API Key
Gemini Get API Key
Grok Get API Key
Kimi Get API Key

Screenshots

Config Page

AI Models & Exchanges Traders List
Config - AI Models & Exchanges Config - Traders List

Competition & Backtest

Competition Mode Backtest Lab
Competition Page Backtest Lab

Dashboard

Overview Market Chart
Dashboard Overview Dashboard Market Chart
Trading Stats Position History
Trading Stats Position History
Positions Trader Details
Dashboard Positions Trader Details

Strategy Studio

Strategy Editor Indicators Config
Strategy Studio Strategy Indicators

Debate Arena

AI Debate Session Create Debate
Debate Arena Create Debate

Quick Start

One-Click Install (Local/Server)

Linux / macOS:

curl -fsSL https://raw.githubusercontent.com/NoFxAiOS/nofx/main/install.sh | bash

That's it! Open http://127.0.0.1:3000 in your browser.

One-Click Cloud Deploy (Railway)

Deploy to Railway with one click - no server setup required:

Deploy on Railway

After deployment, Railway will provide a public URL to access your NOFX instance.

Docker Compose (Manual)

# Download and start
curl -O https://raw.githubusercontent.com/NoFxAiOS/nofx/main/docker-compose.prod.yml
docker compose -f docker-compose.prod.yml up -d

Access Web Interface: http://127.0.0.1:3000

# Management commands
docker compose -f docker-compose.prod.yml logs -f    # View logs
docker compose -f docker-compose.prod.yml restart    # Restart
docker compose -f docker-compose.prod.yml down       # Stop
docker compose -f docker-compose.prod.yml pull && docker compose -f docker-compose.prod.yml up -d  # Update

Keeping Updated

💡 Updates are frequent. Run this command daily to stay current with the latest features and fixes:

curl -fsSL https://raw.githubusercontent.com/NoFxAiOS/nofx/main/install.sh | bash

This one-liner pulls the latest official images and restarts services automatically.

Manual Installation (For Developers)

Prerequisites

  • Go 1.21+
  • Node.js 18+
  • TA-Lib (technical indicator library)
# Install TA-Lib
# macOS
brew install ta-lib

# Ubuntu/Debian
sudo apt-get install libta-lib0-dev

Installation Steps

# 1. Clone the repository
git clone https://github.com/NoFxAiOS/nofx.git
cd nofx

# 2. Install backend dependencies
go mod download

# 3. Install frontend dependencies
cd web
npm install
cd ..

# 4. Build and start backend
go build -o nofx
./nofx

# 5. Start frontend (new terminal)
cd web
npm run dev

Access Web Interface: http://127.0.0.1:3000


Windows Installation

  1. Install Docker Desktop

  2. Run NOFX

    # Open PowerShell and run:
    curl -o docker-compose.prod.yml https://raw.githubusercontent.com/NoFxAiOS/nofx/main/docker-compose.prod.yml
    docker compose -f docker-compose.prod.yml up -d
    
  3. Access: Open http://127.0.0.1:3000 in your browser

Method 2: WSL2 (For Development)

  1. Install WSL2

    # Open PowerShell as Administrator
    wsl --install
    

    Restart your computer after installation.

  2. Install Ubuntu from Microsoft Store

    • Open Microsoft Store
    • Search "Ubuntu 22.04" and install
    • Launch Ubuntu and set up username/password
  3. Install Dependencies in WSL2

    # Update system
    sudo apt update && sudo apt upgrade -y
    
    # Install Go
    wget https://go.dev/dl/go1.21.5.linux-amd64.tar.gz
    sudo tar -C /usr/local -xzf go1.21.5.linux-amd64.tar.gz
    echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
    source ~/.bashrc
    
    # Install Node.js
    curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
    sudo apt-get install -y nodejs
    
    # Install TA-Lib
    sudo apt-get install -y libta-lib0-dev
    
    # Install Git
    sudo apt-get install -y git
    
  4. Clone and Run NOFX

    git clone https://github.com/NoFxAiOS/nofx.git
    cd nofx
    
    # Build and run backend
    go build -o nofx && ./nofx
    
    # In another terminal, run frontend
    cd web && npm install && npm run dev
    
  5. Access: Open http://127.0.0.1:3000 in Windows browser

Method 3: Docker in WSL2 (Best of Both Worlds)

  1. Install Docker Desktop with WSL2 backend

    • During Docker Desktop installation, enable "Use WSL 2 based engine"
    • In Docker Desktop Settings → Resources → WSL Integration, enable your Linux distro
  2. Run from WSL2 terminal

    curl -fsSL https://raw.githubusercontent.com/NoFxAiOS/nofx/main/install.sh | bash
    

Server Deployment

Quick Deploy (HTTP via IP)

By default, transport encryption is disabled, allowing you to access NOFX via IP address without HTTPS:

# Deploy to your server
curl -fsSL https://raw.githubusercontent.com/NoFxAiOS/nofx/main/install.sh | bash

Access via http://YOUR_SERVER_IP:3000 - works immediately.

Enhanced Security (HTTPS)

For enhanced security, enable transport encryption in .env:

TRANSPORT_ENCRYPTION=true

When enabled, browser uses Web Crypto API to encrypt API keys before transmission. This requires:

  • https:// - Any domain with SSL
  • http://localhost - Local development

Quick HTTPS Setup with Cloudflare

  1. Add your domain to Cloudflare (free plan works)

  2. Create DNS record

    • Type: A
    • Name: nofx (or your subdomain)
    • Content: Your server IP
    • Proxy status: Proxied (orange cloud)
  3. Configure SSL/TLS

    • Go to SSL/TLS settings
    • Set encryption mode to Flexible
    User ──[HTTPS]──→ Cloudflare ──[HTTP]──→ Your Server:3000
    
  4. Enable transport encryption

    # Edit .env and set
    TRANSPORT_ENCRYPTION=true
    
  5. Done! Access via https://nofx.yourdomain.com


Initial Setup (Web Interface)

After starting the system, configure through the web interface:

  1. Configure AI Models - Add your AI API keys (DeepSeek, OpenAI, etc.)
  2. Configure Exchanges - Set up exchange API credentials
  3. Create Strategy - Configure trading strategy in Strategy Studio
  4. Create Trader - Combine AI model + Exchange + Strategy
  5. Start Trading - Launch your configured traders

All configuration is done through the web interface - no JSON file editing required.


Web Interface Features

Competition Page

  • Real-time ROI leaderboard
  • Multi-AI performance comparison charts
  • Live P/L tracking and rankings

Dashboard

  • TradingView-style candlestick charts
  • Real-time position management
  • AI decision logs with Chain of Thought reasoning
  • Equity curve tracking

Strategy Studio

  • Coin source configuration (Static list, AI500 pool, OI Top)
  • Technical indicators (EMA, MACD, RSI, ATR, Volume, OI, Funding Rate)
  • Risk control settings (leverage, position limits, margin usage)
  • AI test with real-time prompt preview

Debate Arena

  • Multi-AI debate sessions for trading decisions
  • Configurable AI roles (Bull, Bear, Analyst, Contrarian, Risk Manager)
  • Multiple rounds of debate with consensus voting
  • Auto-execute consensus trades

Backtest Lab

  • 3-step wizard configuration (Model → Parameters → Confirm)
  • Real-time progress visualization with animated ring
  • Equity curve chart with trade markers
  • Trade timeline with card-style display
  • Performance metrics (Return, Max DD, Sharpe, Win Rate)
  • AI decision trail with Chain of Thought

Common Issues

TA-Lib not found

# macOS
brew install ta-lib

# Ubuntu
sudo apt-get install libta-lib0-dev

AI API timeout

  • Check if API key is correct
  • Check network connection
  • System timeout is 120 seconds

Frontend can't connect to backend


Documentation

Document Description
Architecture Overview System design and module index
Strategy Module Coin selection, data assembly, AI prompts, execution
Backtest Module Historical simulation, metrics, checkpoint/resume
Debate Module Multi-AI debate, voting consensus, auto-execution
FAQ Frequently asked questions
Getting Started Deployment guide

License

This project is licensed under GNU Affero General Public License v3.0 (AGPL-3.0) - See LICENSE file.


Contributing

We welcome contributions! See:


Contributor Airdrop Program

All contributions are tracked on GitHub. When NOFX generates revenue, contributors will receive airdrops based on their contributions.

PRs that resolve Pinned Issues receive the HIGHEST rewards!

Contribution Type Weight
Pinned Issue PRs
Code Commits (Merged PRs)
Bug Fixes
Feature Suggestions
Bug Reports
Documentation

Contact


Sponsors

Thanks to all our sponsors!

pjl914335852-ux cat9999aaa 1733055465 kolal2020 CyberFFarm vip3001003 mrtluh cpcp1117-source match-007 leiwuhen1715 SHAOXIA1991

Become a sponsor


Star History

Star History Chart

S
Description
No description provided
Readme AGPL-3.0 69 MiB
Languages
Go 62.3%
TypeScript 36%
Shell 0.7%
CSS 0.5%
Python 0.3%
Other 0.1%