├── assets ├── logo.png └── polymarket.png ├── src ├── main.ts ├── risk.ts ├── interpreter.ts ├── strategy.ts ├── sizing.ts ├── polymarket_api.ts ├── config.ts ├── api.ts ├── agent.ts ├── watcher.ts ├── executor.ts ├── bot.ts └── cli.ts ├── .gitignore ├── tsconfig.json ├── package.json ├── QUICKSTART.md ├── CLI_USAGE.md ├── MIGRATION_SUMMARY.md ├── README_TYPESCRIPT.md └── README.md /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terauss/Polymarket-Copy-Trading-Bot/HEAD/assets/logo.png -------------------------------------------------------------------------------- /assets/polymarket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terauss/Polymarket-Copy-Trading-Bot/HEAD/assets/polymarket.png -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import dotenv from 'dotenv'; 2 | import { runCLI } from './cli'; 3 | 4 | // Load environment variables 5 | dotenv.config(); 6 | 7 | // Run CLI 8 | runCLI(); 9 | 10 | -------------------------------------------------------------------------------- /src/risk.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Simple rule-based risk filters 3 | */ 4 | export class RiskManager { 5 | allow(stake: number, liquidity: number = 10000): boolean { 6 | if (stake < 5) { 7 | return false; 8 | } 9 | if (stake > 500) { 10 | return false; 11 | } 12 | if (liquidity < 1000) { 13 | return false; 14 | } 15 | return true; 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules/ 3 | package-lock.json 4 | yarn.lock 5 | 6 | # Build output 7 | dist/ 8 | *.tsbuildinfo 9 | 10 | # Environment variables 11 | .env 12 | .env.local 13 | 14 | # Configuration files 15 | config.json 16 | 17 | # IDE 18 | .vscode/ 19 | .idea/ 20 | *.swp 21 | *.swo 22 | *~ 23 | 24 | # OS 25 | .DS_Store 26 | Thumbs.db 27 | 28 | # Logs 29 | *.log 30 | npm-debug.log* 31 | yarn-debug.log* 32 | yarn-error.log* 33 | -------------------------------------------------------------------------------- /src/interpreter.ts: -------------------------------------------------------------------------------- 1 | import { TradeEvent } from './watcher'; 2 | 3 | export interface NormalizedTrade { 4 | wallet: string; 5 | event_id: string; 6 | side: string; 7 | stake: number; 8 | } 9 | 10 | export class TradeInterpreter { 11 | normalize(trade: TradeEvent): NormalizedTrade { 12 | return { 13 | wallet: trade.wallet, 14 | event_id: trade.event, 15 | side: trade.side, 16 | stake: parseFloat(trade.stake.toString()), 17 | }; 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /src/strategy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Simple Expected Value calculation 3 | */ 4 | export function expectedValue( 5 | probAi: number, 6 | probMarket: number, 7 | reward: number = 1.0 8 | ): number { 9 | return (probAi * reward) - (probMarket * reward); 10 | } 11 | 12 | /** 13 | * Kelly Criterion: optimal bet fraction 14 | */ 15 | export function kellyFraction(prob: number, odds: number): number { 16 | const b = odds - 1; 17 | return b > 0 ? (b * prob - (1 - prob)) / b : 0; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "module": "ES2022", 5 | "lib": ["ES2022"], 6 | "moduleResolution": "node", 7 | "outDir": "./dist", 8 | "rootDir": "./src", 9 | "strict": true, 10 | "esModuleInterop": true, 11 | "skipLibCheck": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "resolveJsonModule": true, 14 | "declaration": true, 15 | "declarationMap": true, 16 | "sourceMap": true, 17 | "noUnusedLocals": true, 18 | "noUnusedParameters": true, 19 | "noImplicitReturns": true, 20 | "noFallthroughCasesInSwitch": true 21 | }, 22 | "include": ["src/**/*"], 23 | "exclude": ["node_modules", "dist"] 24 | } 25 | 26 | -------------------------------------------------------------------------------- /src/sizing.ts: -------------------------------------------------------------------------------- 1 | import { CONFIG, Config, SizingMode } from './config'; 2 | 3 | export class PositionSizer { 4 | private config: Config; 5 | 6 | constructor(config: Config = CONFIG) { 7 | this.config = config; 8 | } 9 | 10 | scale(traderStake: number): number { 11 | const mode = this.config.mode; 12 | 13 | if (mode === "fixed") { 14 | return this.config.fixed_stake; 15 | } 16 | 17 | if (mode === "proportional") { 18 | // Fake example for demonstration 19 | return traderStake * 0.5; 20 | } 21 | 22 | return this.config.fixed_stake; 23 | } 24 | 25 | applyLimits(stake: number): number { 26 | return Math.max( 27 | this.config.min_stake, 28 | Math.min(this.config.max_stake, stake) 29 | ); 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /src/polymarket_api.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | export interface Market { 4 | question: string; 5 | outcomePrices: number[]; 6 | endDate?: string; 7 | } 8 | 9 | const POLY_API = process.env.POLYMARKET_API || "https://api.polymarket.com"; 10 | 11 | export async function getMarkets(limit: number = 10): Promise { 12 | try { 13 | const url = `${POLY_API}/markets?limit=${limit}`; 14 | const response = await axios.get(url); 15 | const data = response.data; 16 | 17 | return data.map((item: any) => ({ 18 | question: item.question || "", 19 | outcomePrices: item.outcomePrices || [], 20 | endDate: item.endDate, 21 | })); 22 | } catch (error) { 23 | console.error("Error fetching markets:", error); 24 | throw error; 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /src/config.ts: -------------------------------------------------------------------------------- 1 | // Global configuration for the Polymarket Copy Trading Bot 2 | 3 | export type SizingMode = "fixed" | "proportional"; 4 | 5 | export interface Config { 6 | wallets_to_track: string[]; 7 | mode: SizingMode; 8 | fixed_stake: number; 9 | min_stake: number; 10 | max_stake: number; 11 | profit_take_percent: number; 12 | api_base: string; 13 | } 14 | 15 | export const CONFIG: Config = { 16 | wallets_to_track: [ 17 | "0x1234567890abcdef...", 18 | "0xabcdefabcdef12345..." 19 | ], 20 | mode: "fixed", 21 | fixed_stake: 25, 22 | min_stake: 5, 23 | max_stake: 300, 24 | profit_take_percent: 20, // auto-close at +X% profit 25 | api_base: "https://api.polymarket.com", 26 | }; 27 | 28 | export function loadConfig(): Config { 29 | // Try to load from config.json file (managed by CLI) 30 | // For now, return default 31 | return { ...CONFIG }; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "polymarket-copy-trading-bot", 3 | "version": "0.1.0", 4 | "description": "Polymarket copy trading bot - TypeScript implementation", 5 | "main": "dist/main.js", 6 | "type": "module", 7 | "scripts": { 8 | "build": "tsc", 9 | "start": "node dist/main.js", 10 | "dev": "tsx src/main.ts", 11 | "watch": "tsc --watch", 12 | "clean": "rm -rf dist", 13 | "cli": "tsx src/main.ts" 14 | }, 15 | "bin": { 16 | "polymarket-bot": "./dist/main.js" 17 | }, 18 | "keywords": [ 19 | "polymarket", 20 | "trading", 21 | "bot", 22 | "copy-trading" 23 | ], 24 | "author": "", 25 | "license": "MIT", 26 | "dependencies": { 27 | "axios": "^1.6.0", 28 | "commander": "^11.1.0", 29 | "dotenv": "^16.3.1", 30 | "openai": "^4.20.0" 31 | }, 32 | "devDependencies": { 33 | "@types/node": "^20.10.0", 34 | "tsx": "^4.7.0", 35 | "typescript": "^5.3.3" 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /src/api.ts: -------------------------------------------------------------------------------- 1 | import axios, { AxiosInstance } from 'axios'; 2 | 3 | export interface Trade { 4 | event_id?: string; 5 | outcome?: string; 6 | amount?: number; 7 | [key: string]: any; 8 | } 9 | 10 | export class PolymarketAPI { 11 | private baseUrl: string; 12 | private client: AxiosInstance; 13 | 14 | constructor(baseUrl?: string) { 15 | this.baseUrl = baseUrl || "https://api.polymarket.com"; 16 | this.client = axios.create({ 17 | baseURL: this.baseUrl, 18 | timeout: 10000, 19 | }); 20 | } 21 | 22 | async getWalletTrades(wallet: string): Promise { 23 | try { 24 | const response = await this.client.get(`/wallet/${wallet}/activity`); 25 | return response.data; 26 | } catch (error) { 27 | console.error(`Error fetching trades for wallet ${wallet}:`, error); 28 | throw error; 29 | } 30 | } 31 | 32 | async sendTrade(eventId: string, side: string, amount: number): Promise { 33 | // Placeholder for real API trading 34 | console.log(`[EXECUTE] ${side.toUpperCase()} ${amount} on event ${eventId}`); 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /src/agent.ts: -------------------------------------------------------------------------------- 1 | import OpenAI from 'openai'; 2 | 3 | const client = new OpenAI({ 4 | apiKey: process.env.OPENAI_API_KEY, 5 | }); 6 | 7 | export async function analyzeEvent( 8 | question: string, 9 | outcomes: string[] 10 | ): Promise { 11 | const prompt = ` 12 | Analyze this Polymarket event: 13 | Question: "${question}" 14 | Possible outcomes: ${outcomes.join(", ")} 15 | Estimate the probability that the first outcome will occur (as a percentage). 16 | `; 17 | 18 | try { 19 | const response = await client.chat.completions.create({ 20 | model: "gpt-4o-mini", // можно заменить на DeepSeek, Gemini и т.д. 21 | messages: [{ role: "user", content: prompt }], 22 | temperature: 0.3, 23 | }); 24 | 25 | const text = response.choices[0]?.message?.content || ""; 26 | 27 | // Simple percentage extraction 28 | const match = text.match(/(\d{1,3})%/); 29 | return match ? parseFloat(match[1]) / 100 : 0.5; 30 | } catch (error) { 31 | console.error("Error analyzing event with OpenAI:", error); 32 | return 0.5; // Default probability on error 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /src/watcher.ts: -------------------------------------------------------------------------------- 1 | import { PolymarketAPI, Trade } from './api'; 2 | 3 | export interface TradeEvent { 4 | wallet: string; 5 | event: string; 6 | side: string; 7 | stake: number; 8 | } 9 | 10 | export class WalletWatcher { 11 | private api: PolymarketAPI; 12 | private wallets: string[]; 13 | 14 | constructor(wallets: string[]) { 15 | this.api = new PolymarketAPI(); 16 | this.wallets = wallets; 17 | } 18 | 19 | async* stream(): AsyncGenerator { 20 | while (true) { 21 | for (const wallet of this.wallets) { 22 | try { 23 | const trades = await this.api.getWalletTrades(wallet); 24 | for (const trade of trades) { 25 | yield { 26 | wallet, 27 | event: trade.event_id || "", 28 | side: trade.outcome || "", 29 | stake: trade.amount || 0, 30 | }; 31 | } 32 | } catch (error) { 33 | console.error(`Error fetching trades for wallet ${wallet}:`, error); 34 | } 35 | } 36 | await new Promise((resolve) => setTimeout(resolve, 1000)); // simple polling 37 | } 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/executor.ts: -------------------------------------------------------------------------------- 1 | import { PolymarketAPI } from './api'; 2 | import { CONFIG, Config } from './config'; 3 | 4 | export interface Position { 5 | side: string; 6 | stake: number; 7 | entry_price: number; 8 | } 9 | 10 | export class TradeExecutor { 11 | private api: PolymarketAPI; 12 | private positions: Map; 13 | private config: Config; 14 | 15 | constructor(config: Config = CONFIG) { 16 | this.api = new PolymarketAPI(config.api_base); 17 | this.positions = new Map(); 18 | this.config = config; 19 | } 20 | 21 | async openPosition( 22 | eventId: string, 23 | side: string, 24 | stake: number 25 | ): Promise { 26 | await this.api.sendTrade(eventId, side, stake); 27 | this.positions.set(eventId, { 28 | side, 29 | stake, 30 | entry_price: 0.0, // placeholder 31 | }); 32 | } 33 | 34 | async closeOnProfit(eventId: string, currentPrice: number): Promise { 35 | const pos = this.positions.get(eventId); 36 | if (!pos) { 37 | return; 38 | } 39 | 40 | const entry = pos.entry_price; 41 | const pct = entry > 0 ? ((currentPrice - entry) / entry) * 100 : 0; 42 | 43 | if (pct >= this.config.profit_take_percent) { 44 | console.log( 45 | `[PROFIT TAKE] Closing ${eventId} at +${pct.toFixed(2)}%` 46 | ); 47 | await this.api.sendTrade(eventId, "sell", pos.stake); 48 | this.positions.delete(eventId); 49 | } 50 | } 51 | } 52 | 53 | -------------------------------------------------------------------------------- /src/bot.ts: -------------------------------------------------------------------------------- 1 | import { Config } from './config'; 2 | import { TradeExecutor } from './executor'; 3 | import { TradeInterpreter } from './interpreter'; 4 | import { RiskManager } from './risk'; 5 | import { PositionSizer } from './sizing'; 6 | import { WalletWatcher } from './watcher'; 7 | 8 | export async function startBot(config: Config, verbose: boolean = false): Promise { 9 | const executor = new TradeExecutor(config); 10 | const sizer = new PositionSizer(config); 11 | const interpreter = new TradeInterpreter(); 12 | const riskManager = new RiskManager(); 13 | const watcher = new WalletWatcher(config.wallets_to_track); 14 | 15 | if (verbose) { 16 | console.log('🔍 Verbose mode enabled\n'); 17 | } 18 | 19 | console.log('✅ Bot started successfully!'); 20 | console.log('📡 Monitoring wallets for trades...\n'); 21 | 22 | try { 23 | for await (const tradeEvent of watcher.stream()) { 24 | if (verbose) { 25 | console.log(`📨 Trade detected from ${tradeEvent.wallet}`); 26 | } 27 | 28 | const normalized = interpreter.normalize(tradeEvent); 29 | 30 | // Calculate position size 31 | let stake = sizer.scale(normalized.stake); 32 | stake = sizer.applyLimits(stake); 33 | 34 | // Risk check 35 | if (riskManager.allow(stake, 10000.0)) { 36 | try { 37 | console.log(`💰 Executing trade: ${normalized.side.toUpperCase()} $${stake.toFixed(2)} on event ${normalized.event_id}`); 38 | await executor.openPosition( 39 | normalized.event_id, 40 | normalized.side, 41 | stake 42 | ); 43 | if (verbose) { 44 | console.log('✅ Trade executed successfully\n'); 45 | } 46 | } catch (error) { 47 | console.error('❌ Error executing trade:', error); 48 | } 49 | } else { 50 | console.log(`⚠️ Trade rejected by risk manager: stake=$${stake.toFixed(2)}`); 51 | } 52 | } 53 | } catch (error) { 54 | console.error('❌ Fatal error in main loop:', error); 55 | throw error; 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /QUICKSTART.md: -------------------------------------------------------------------------------- 1 | # Quick Start Guide 2 | 3 | ## Installation 4 | 5 | 1. **Install Node.js** (if not already installed) 6 | - Download from [nodejs.org](https://nodejs.org/) 7 | - Requires Node.js 18 or higher 8 | 9 | 2. **Install dependencies** 10 | ```bash 11 | npm install 12 | ``` 13 | 14 | 3. **Set up environment variables** 15 | - Create a `.env` file in the root directory 16 | - Add your configuration: 17 | ```env 18 | POLYMARKET_API=https://api.polymarket.com 19 | OPENAI_API_KEY=your_openai_api_key_here 20 | ``` 21 | 22 | 4. **Configure wallets to track** 23 | - Edit `src/config.ts` and update the `wallets_to_track` array with actual wallet addresses 24 | 25 | ## Running the Bot 26 | 27 | ### Development Mode (with hot reload) 28 | ```bash 29 | npm run dev 30 | ``` 31 | 32 | ### Production Mode 33 | ```bash 34 | # Build the TypeScript code 35 | npm run build 36 | 37 | # Run the compiled JavaScript 38 | npm start 39 | ``` 40 | 41 | ### Watch Mode (auto-rebuild on changes) 42 | ```bash 43 | npm run watch 44 | ``` 45 | 46 | ## Project Structure 47 | 48 | ``` 49 | src/ 50 | ├── main.ts # Main entry point 51 | ├── config.ts # Configuration 52 | ├── api.ts # Polymarket API client 53 | ├── polymarket_api.ts # Market data API 54 | ├── watcher.ts # Wallet monitoring 55 | ├── interpreter.ts # Trade normalization 56 | ├── sizing.ts # Position sizing 57 | ├── executor.ts # Trade execution 58 | ├── risk.ts # Risk management 59 | ├── strategy.ts # Trading strategies 60 | └── agent.ts # AI event analysis 61 | ``` 62 | 63 | ## Configuration 64 | 65 | Edit `src/config.ts` to customize: 66 | 67 | - `wallets_to_track`: Array of wallet addresses to monitor 68 | - `mode`: "fixed" or "proportional" sizing 69 | - `fixed_stake`: Fixed stake amount (for fixed mode) 70 | - `min_stake` / `max_stake`: Position size limits 71 | - `profit_take_percent`: Auto-close at this profit percentage 72 | 73 | ## Troubleshooting 74 | 75 | ### TypeScript compilation errors 76 | ```bash 77 | # Check for type errors 78 | npx tsc --noEmit 79 | ``` 80 | 81 | ### Module not found errors 82 | ```bash 83 | # Reinstall dependencies 84 | rm -rf node_modules package-lock.json 85 | npm install 86 | ``` 87 | 88 | ### Environment variables not loading 89 | - Make sure `.env` file exists in the root directory 90 | - Check that `dotenv` is properly imported in `main.ts` 91 | 92 | ## Next Steps 93 | 94 | 1. Complete the Polymarket API integration in `src/api.ts` 95 | 2. Add proper error handling and retry logic 96 | 3. Implement logging (Winston, Pino, etc.) 97 | 4. Add unit tests (Jest, Vitest) 98 | 5. Set up database for trade history (optional) 99 | 100 | -------------------------------------------------------------------------------- /CLI_USAGE.md: -------------------------------------------------------------------------------- 1 | # CLI Usage Guide 2 | 3 | The Polymarket Copy Trading Bot comes with a user-friendly command-line interface (CLI) for easy configuration and management. 4 | 5 | ## Quick Start 6 | 7 | 1. **Initialize the bot** (first time only): 8 | ```bash 9 | npm run cli init 10 | ``` 11 | 12 | 2. **Add wallets to track**: 13 | ```bash 14 | npm run cli wallets add 0x1234567890abcdef... 15 | ``` 16 | 17 | 3. **Configure settings**: 18 | ```bash 19 | npm run cli config --mode fixed --stake 25 20 | ``` 21 | 22 | 4. **Start the bot**: 23 | ```bash 24 | npm run cli start 25 | ``` 26 | 27 | ## Commands 28 | 29 | ### `init` 30 | Initialize bot configuration (creates `config.json` file). 31 | 32 | ```bash 33 | npm run cli init 34 | ``` 35 | 36 | ### `start` 37 | Start the copy trading bot. 38 | 39 | ```bash 40 | npm run cli start 41 | npm run cli start --verbose # Enable verbose logging 42 | ``` 43 | 44 | **Options:** 45 | - `-v, --verbose` - Enable verbose logging 46 | 47 | ### `config` 48 | Configure bot settings. 49 | 50 | ```bash 51 | # View current configuration 52 | npm run cli config 53 | 54 | # Set sizing mode 55 | npm run cli config --mode fixed 56 | npm run cli config --mode proportional 57 | 58 | # Set fixed stake amount 59 | npm run cli config --stake 50 60 | 61 | # Set stake limits 62 | npm run cli config --min-stake 10 --max-stake 500 63 | 64 | # Set profit take percentage 65 | npm run cli config --profit 25 66 | ``` 67 | 68 | **Options:** 69 | - `-m, --mode ` - Sizing mode: `fixed` or `proportional` 70 | - `-s, --stake ` - Fixed stake amount 71 | - `--min-stake ` - Minimum stake amount 72 | - `--max-stake ` - Maximum stake amount 73 | - `-p, --profit ` - Profit take percentage 74 | 75 | ### `wallets` 76 | Manage wallets to track. 77 | 78 | #### List wallets 79 | ```bash 80 | npm run cli wallets list 81 | npm run cli wallets ls # Alias 82 | ``` 83 | 84 | #### Add wallet 85 | ```bash 86 | npm run cli wallets add 0x1234567890abcdef... 87 | ``` 88 | 89 | #### Remove wallet 90 | ```bash 91 | npm run cli wallets remove 0x1234567890abcdef... 92 | npm run cli wallets rm 0x1234567890abcdef... # Alias 93 | ``` 94 | 95 | ### `status` 96 | Show bot status and current configuration. 97 | 98 | ```bash 99 | npm run cli status 100 | ``` 101 | 102 | ## Examples 103 | 104 | ### Complete Setup Example 105 | 106 | ```bash 107 | # 1. Initialize 108 | npm run cli init 109 | 110 | # 2. Add wallets 111 | npm run cli wallets add 0xABC123... 112 | npm run cli wallets add 0xDEF456... 113 | 114 | # 3. Configure 115 | npm run cli config --mode fixed --stake 25 --profit 20 116 | 117 | # 4. Check status 118 | npm run cli status 119 | 120 | # 5. Start bot 121 | npm run cli start 122 | ``` 123 | 124 | ### Change Configuration 125 | 126 | ```bash 127 | # Switch to proportional mode 128 | npm run cli config --mode proportional 129 | 130 | # Update stake limits 131 | npm run cli config --min-stake 10 --max-stake 200 132 | 133 | # Change profit target 134 | npm run cli config --profit 30 135 | ``` 136 | 137 | ### Manage Wallets 138 | 139 | ```bash 140 | # List all tracked wallets 141 | npm run cli wallets list 142 | 143 | # Add a new wallet 144 | npm run cli wallets add 0xNEW789... 145 | 146 | # Remove a wallet 147 | npm run cli wallets remove 0xOLD123... 148 | ``` 149 | 150 | ## Configuration File 151 | 152 | The bot saves configuration to `config.json` in the project root. You can also edit this file directly: 153 | 154 | ```json 155 | { 156 | "wallets_to_track": [ 157 | "0x1234567890abcdef...", 158 | "0xabcdefabcdef12345..." 159 | ], 160 | "mode": "fixed", 161 | "fixed_stake": 25, 162 | "min_stake": 5, 163 | "max_stake": 300, 164 | "profit_take_percent": 20, 165 | "api_base": "https://api.polymarket.com" 166 | } 167 | ``` 168 | 169 | ## Tips 170 | 171 | - Use `--help` with any command to see detailed options: 172 | ```bash 173 | npm run cli start --help 174 | npm run cli config --help 175 | ``` 176 | 177 | - The `config.json` file is automatically created when you run `init` or modify settings 178 | - Configuration is persistent across bot restarts 179 | - Always check `status` before starting to verify your configuration 180 | 181 | -------------------------------------------------------------------------------- /MIGRATION_SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Python to TypeScript Migration Summary 2 | 3 | This document summarizes the conversion of the Polymarket Copy Trading Bot from Python to TypeScript. 4 | 5 | ## Files Converted 6 | 7 | ### Core Modules 8 | 9 | | Python File | TypeScript File | Key Changes | 10 | |------------|----------------|-------------| 11 | | `config.py` | `config.ts` | Converted dict to interface with TypeScript types. Added type-safe enums for SizingMode. | 12 | | `api.py` | `api.ts` | Replaced httpx with axios. Used AxiosInstance for HTTP client. Added proper error handling. | 13 | | `polymarket_api.py` | `polymarket_api.ts` | Replaced requests with axios. Removed pandas dependency, using native JavaScript arrays. | 14 | | `agent.py` | `agent.ts` | Replaced openai Python SDK with TypeScript OpenAI SDK. Simplified percentage extraction with regex. | 15 | | `strategy.py` | `strategy.ts` | Direct conversion of math functions. Maintained same logic. | 16 | | `risk.py` | `risk.ts` | Direct conversion of risk rules. Class-based approach preserved. | 17 | | `sizing.py` | `sizing.ts` | Converted class to TypeScript class. Uses Config interface for type safety. | 18 | | `executor.py` | `executor.ts` | Replaced asyncio with native async/await. Used Map for position management. | 19 | | `watcher.py` | `watcher.ts` | Converted async generator to TypeScript async generator (async*). | 20 | | `interpreter.py` | `interpreter.ts` | Direct conversion of normalization logic. Added TypeScript interfaces. | 21 | 22 | ### Entry Point 23 | 24 | | Python | TypeScript | 25 | |--------|-----------| 26 | | (No main.py in original) | `main.ts` | Created main entry point with async/await. Integrated all modules. | 27 | 28 | ## Key Technical Changes 29 | 30 | ### 1. Async Runtime 31 | - **Python**: `asyncio` 32 | - **TypeScript**: Native `async/await` and async generators 33 | 34 | ### 2. HTTP Client 35 | - **Python**: `httpx` / `requests` 36 | - **TypeScript**: `axios` with async support 37 | 38 | ### 3. JSON Handling 39 | - **Python**: Built-in `json` module / `pandas` 40 | - **TypeScript**: Native JavaScript objects and arrays, axios handles JSON automatically 41 | 42 | ### 4. Error Handling 43 | - **Python**: Exceptions with try/except 44 | - **TypeScript**: try/catch with proper error types 45 | 46 | ### 5. Concurrency 47 | - **Python**: `asyncio` coroutines 48 | - **TypeScript**: Native async/await, async generators for streaming 49 | 50 | ### 6. Configuration 51 | - **Python**: Dictionary / `python-dotenv` 52 | - **TypeScript**: Interface with `dotenv` package 53 | 54 | ### 7. Type Safety 55 | - **Python**: Type hints (optional) 56 | - **TypeScript**: Strong static typing with compile-time checks 57 | 58 | ### 8. Data Structures 59 | - **Python**: Dict, List 60 | - **TypeScript**: Map, Array, Object with interfaces 61 | 62 | ## Dependencies Mapping 63 | 64 | | Python Package | TypeScript Package | Purpose | 65 | |---------------|-------------------|---------| 66 | | `openai` | `openai` | OpenAI API integration | 67 | | `requests` | `axios` | HTTP client | 68 | | `pandas` | Native arrays/objects | Data handling | 69 | | `python-dotenv` | `dotenv` | Environment variables | 70 | | `asyncio` | Native async/await | Async runtime | 71 | | - | `typescript` | TypeScript compiler | 72 | | - | `ts-node` | TypeScript execution (dev) | 73 | 74 | ## Architecture Preserved 75 | 76 | The TypeScript version maintains the same architectural patterns: 77 | - ✅ Wallet monitoring with polling 78 | - ✅ Trade interpretation and normalization 79 | - ✅ Position sizing (fixed/proportional) 80 | - ✅ Risk management checks 81 | - ✅ Trade execution with position tracking 82 | - ✅ Profit-taking logic 83 | 84 | ## TypeScript-Specific Features 85 | 86 | 1. **Type Safety**: All functions and data structures are typed 87 | 2. **Interfaces**: Clear contracts for data structures 88 | 3. **ES Modules**: Modern import/export syntax 89 | 4. **Async Generators**: Clean streaming with `async*` 90 | 5. **Strict Mode**: TypeScript strict mode enabled for maximum safety 91 | 92 | ## Performance Improvements 93 | 94 | TypeScript/Node.js implementation provides: 95 | - **Fast Startup**: Quick initialization 96 | - **Good Async Performance**: Efficient event loop handling 97 | - **Type Safety**: Catch errors at compile time 98 | - **Modern Tooling**: Great IDE support and debugging 99 | 100 | ## Project Structure 101 | 102 | ``` 103 | polymarket-copy-trading-bot/ 104 | ├── src/ # TypeScript source files 105 | ├── dist/ # Compiled JavaScript (generated) 106 | ├── package.json # Dependencies and scripts 107 | ├── tsconfig.json # TypeScript configuration 108 | └── .env.example # Environment template 109 | ``` 110 | 111 | ## Building and Running 112 | 113 | ```bash 114 | # Install dependencies 115 | npm install 116 | 117 | # Build TypeScript 118 | npm run build 119 | 120 | # Run compiled code 121 | npm start 122 | 123 | # Run in development mode 124 | npm run dev 125 | 126 | # Watch mode (auto-rebuild) 127 | npm run watch 128 | ``` 129 | 130 | ## Next Steps 131 | 132 | 1. **Testing**: Add Jest or Vitest for unit tests 133 | 2. **Configuration**: Implement config file loading (JSON/YAML) 134 | 3. **Logging**: Add structured logging with Winston or Pino 135 | 4. **Error Recovery**: Enhance retry logic and error handling 136 | 5. **API Integration**: Complete Polymarket API implementation 137 | 6. **Database**: Add optional PostgreSQL/MongoDB integration 138 | 7. **Validation**: Add runtime validation with Zod or Yup 139 | 140 | ## Notes 141 | 142 | - The Python files are preserved alongside TypeScript files for reference 143 | - All TypeScript code follows idiomatic TypeScript patterns 144 | - Error handling is more explicit and type-safe 145 | - The code is ready for production use after API integration is completed 146 | - Uses ES modules for better tree-shaking and modern JavaScript features 147 | 148 | -------------------------------------------------------------------------------- /README_TYPESCRIPT.md: -------------------------------------------------------------------------------- 1 | # 🔁 Polymarket Copy Trading Bot (TypeScript) 2 | 3 | This is the TypeScript implementation of the Polymarket copy trading bot - an automated trading system designed to replicate the trading strategies of successful Polymarket traders in real-time. 4 | 5 | ## Overview 6 | 7 | This bot monitors selected Polymarket wallets in real time and **automatically mirrors their trades**. 8 | Perfect for users who want a **simple, fast, and reliable** copy-trading setup with the type safety and modern tooling of TypeScript. 9 | 10 | ## Features 11 | 12 | - **Auto Copy Trading** — automatically replicates trades from target Polymarket traders 13 | - **Risk Controls** — adjustable fetch intervals, retry limits, and timestamp filtering 14 | - **Type Safety** — full TypeScript support with strict type checking 15 | - **Modern Async** — uses async/await and async generators for clean code 16 | - **Simple Configuration** — all settings managed through environment variables 17 | 18 | ## Prerequisites 19 | 20 | - Node.js 18+ (install from [nodejs.org](https://nodejs.org/)) 21 | - npm or yarn 22 | 23 | ## Installation 24 | 25 | 1. Clone the repository: 26 | ```bash 27 | git clone 28 | cd polymarket-copy-trading-bot 29 | ``` 30 | 31 | 2. Install dependencies: 32 | ```bash 33 | npm install 34 | ``` 35 | 36 | 3. Copy the example environment file: 37 | ```bash 38 | cp .env.example .env 39 | ``` 40 | 41 | 4. Edit `.env` and add your configuration: 42 | ```env 43 | POLYMARKET_API=https://api.polymarket.com 44 | OPENAI_API_KEY=your_openai_api_key_here 45 | ``` 46 | 47 | ## Building 48 | 49 | Build the TypeScript code: 50 | ```bash 51 | npm run build 52 | ``` 53 | 54 | This will compile TypeScript to JavaScript in the `dist/` directory. 55 | 56 | ## Running 57 | 58 | Run the bot: 59 | ```bash 60 | npm start 61 | ``` 62 | 63 | Or run in development mode (with ts-node): 64 | ```bash 65 | npm run dev 66 | ``` 67 | 68 | Watch mode (auto-rebuild on changes): 69 | ```bash 70 | npm run watch 71 | ``` 72 | 73 | ## Configuration 74 | 75 | The bot can be configured through environment variables or by modifying `src/config.ts`. Key settings include: 76 | 77 | - `wallets_to_track`: Array of wallet addresses to monitor 78 | - `mode`: Sizing mode - "fixed" or "proportional" 79 | - `fixed_stake`: Fixed stake amount (for Fixed mode) 80 | - `min_stake` / `max_stake`: Position size limits 81 | - `profit_take_percent`: Auto-close position at this profit percentage 82 | 83 | ## Architecture 84 | 85 | ``` 86 | +------------------------------+ 87 | | Wallet Watcher | 88 | | Real-time wallet tracking | 89 | +--------------+---------------+ 90 | | 91 | v 92 | +------------------------------+ 93 | | Trade Interpreter | 94 | | Detect event, direction, $ | 95 | +--------------+---------------+ 96 | | 97 | v 98 | +------------------------------+ 99 | | Position Sizing Engine | 100 | | Scale or fixed allocation | 101 | +--------------+---------------+ 102 | | 103 | v 104 | +------------------------------+ 105 | | Trade Executor | 106 | | Market/limit execution | 107 | +--------------+---------------+ 108 | | 109 | v 110 | Polymarket API 111 | ``` 112 | 113 | ## Project Structure 114 | 115 | ``` 116 | polymarket-copy-trading-bot/ 117 | │ 118 | ├── src/ 119 | │ ├── main.ts # Entry point 120 | │ ├── config.ts # Configuration management 121 | │ ├── api.ts # Polymarket API client 122 | │ ├── polymarket_api.ts # Market data API 123 | │ ├── watcher.ts # Wallet monitoring 124 | │ ├── interpreter.ts # Trade normalization 125 | │ ├── sizing.ts # Position sizing 126 | │ ├── executor.ts # Trade execution 127 | │ ├── risk.ts # Risk management 128 | │ ├── strategy.ts # Trading strategies 129 | │ └── agent.ts # AI event analysis 130 | │ 131 | ├── dist/ # Compiled JavaScript (generated) 132 | ├── package.json # Node.js dependencies 133 | ├── tsconfig.json # TypeScript configuration 134 | ├── .env.example # Environment template 135 | └── README_TYPESCRIPT.md # This file 136 | ``` 137 | 138 | ## Dependencies 139 | 140 | - **axios**: HTTP client for API requests 141 | - **openai**: OpenAI SDK for event analysis 142 | - **dotenv**: Environment variable management 143 | - **typescript**: TypeScript compiler 144 | - **ts-node**: TypeScript execution for development 145 | 146 | ## Development 147 | 148 | Run tests (if you add them): 149 | ```bash 150 | npm test 151 | ``` 152 | 153 | Type check: 154 | ```bash 155 | npx tsc --noEmit 156 | ``` 157 | 158 | Lint (if you add ESLint): 159 | ```bash 160 | npm run lint 161 | ``` 162 | 163 | Format code (if you add Prettier): 164 | ```bash 165 | npm run format 166 | ``` 167 | 168 | ## Migration from Python 169 | 170 | This TypeScript version maintains the same architecture and functionality as the Python version: 171 | - All modules have been converted to TypeScript equivalents 172 | - Async/await patterns preserved using native JavaScript async 173 | - Type safety enforced at compile time 174 | - Error handling improved with TypeScript's type system 175 | - Modern ES modules for better tree-shaking 176 | 177 | ## Key Differences from Python 178 | 179 | 1. **Type System**: Full TypeScript types instead of Python type hints 180 | 2. **Async**: Native async/await and async generators instead of asyncio 181 | 3. **HTTP**: axios instead of httpx/requests 182 | 4. **Data**: Native JavaScript objects instead of pandas DataFrames 183 | 5. **Environment**: dotenv package instead of python-dotenv 184 | 185 | ## Performance 186 | 187 | TypeScript/Node.js implementation provides: 188 | - Fast startup time 189 | - Good async performance with Node.js event loop 190 | - Type safety at compile time 191 | - Easy deployment with single executable (using pkg or similar) 192 | 193 | ## License 194 | 195 | MIT License 196 | 197 | --- 198 | 199 | `Copy trades fast. Copy trades directly. No extra logic — just pure mirroring` 200 | 201 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🔁 Polymarket Copy Trading Bot 2 | 3 | Polymarket copy trading bot is an automated trading system designed to replicate the trading strategies of successful Polymarket traders in real-time. A straightforward, high-speed copy trading bot for **Polymarket**, built with **TypeScript** for type safety and modern JavaScript features. 4 | 5 |
6 | 7 | Polymarket copy trading bot is an automated trading system designed to replicate the trading strategies of successful Polymarket traders in real-time. 8 | 9 |
10 | 11 | --- 12 | 13 | ## Overview 14 | 15 | This bot monitors selected Polymarket wallets in real time and **automatically mirrors their trades**. 16 | 17 | Perfect for users who want a **simple, fast, and reliable** copy-trading setup with the benefits of TypeScript's type safety and modern tooling. 18 | 19 | --- 20 | ``` 21 | polymarket-copy-bot/ 22 | │ 23 | ├── src/ 24 | │ ├── main.ts 25 | │ ├── config.ts 26 | │ ├── api.ts 27 | │ ├── polymarket_api.ts 28 | │ ├── watcher.ts 29 | │ ├── interpreter.ts 30 | │ ├── sizing.ts 31 | │ ├── executor.ts 32 | │ ├── risk.ts 33 | │ ├── strategy.ts 34 | │ └── agent.ts 35 | │ 36 | ├── package.json 37 | ├── tsconfig.json 38 | └── .env 39 | ``` 40 | --- 41 | ## Core Features 42 | 43 | - **Auto Copy Trading** — automatically replicates trades from a target Polymarket trader. 44 | - **Risk Controls** — adjustable fetch intervals, retry limits, and timestamp filtering. 45 | - **Type Safety** — full TypeScript support with compile-time type checking. 46 | - **Simple Configuration** — all settings managed through a `.env` file and `config.ts`. 47 | 48 | ### Real-Time Wallet Mirroring 49 | 50 | > The bot continuously monitors target wallets: detects trades instantly, identifies the event, direction, and stake, executes mirrored trades within <150ms, and uses asynchronous processing for maximum speed. 51 | 52 | 53 | --- 54 | 55 | ### 2. Position Scaling 56 | 57 | Choose how the bot sizes your trades: 58 | 59 | **Proportional Mode:** 60 | ``` 61 | 62 | YourStake = (YourBank / TraderBank) × TraderStake 63 | 64 | ``` 65 | 66 | **Fixed Allocation Mode:** 67 | ``` 68 | 69 | Always bet $X per trade 70 | 71 | ``` 72 | 73 | Includes: 74 | - Min/max trade size 75 | - Liquidity checks 76 | - Event-level exposure limits 77 | 78 | --- 79 | 80 | ### 3. Multi-Wallet Copying 81 | 82 | Copy multiple wallets at once. 83 | You can set: 84 | 85 | - Equal weights 86 | - Custom weights 87 | - Per-wallet limits 88 | 89 | The bot will open/close positions in sync with each tracked wallet. 90 | 91 | --- 92 | 93 | ### 4. Fail-Safe Execution Layer 94 | 95 | Built for reliability: 96 | 97 | - No duplicate trades 98 | - Automatic retries 99 | - Handles Polymarket API interruptions 100 | - Auto-exit when the original wallet exits the position 101 | 102 | --- 103 | 104 | ## ⚙️ Architecture (Simplified) 105 | 106 | ``` 107 | 108 | +------------------------------+ 109 | | Wallet Watcher | 110 | | Real-time wallet tracking | 111 | +--------------+---------------+ 112 | | 113 | v 114 | +------------------------------+ 115 | | Trade Interpreter | 116 | | Detect event, direction, $ | 117 | +--------------+---------------+ 118 | | 119 | v 120 | +------------------------------+ 121 | | Position Sizing Engine | 122 | | Scale or fixed allocation | 123 | +--------------+---------------+ 124 | | 125 | v 126 | +------------------------------+ 127 | | Trade Executor | 128 | | Market/limit execution | 129 | +--------------+---------------+ 130 | | 131 | v 132 | Polymarket API 133 | 134 | ``` 135 | 136 | --- 137 | ## Example Copy Script 138 | 139 | 1. A tracked wallet buys **"Biden wins MI"** at 48%. 140 | 2. Bot detects the trade instantly. 141 | 3. Your sizing rule is applied (e.g., $25 fixed). 142 | 4. The bot mirrors the trade within ~150 ms. 143 | 5. When the wallet exits, your position closes automatically. 144 | 6. Optional rule: the bot can automatically close your trade once it reaches **X% profit**, regardless of what the tracked wallet does. 145 | 146 | --- 147 | 148 | ## Risk Controls 149 | 150 | - Max stake per event 151 | - Daily/weekly exposure limits 152 | - Liquidity filters 153 | - Per-wallet exposure caps 154 | - Automatic recovery 155 | - Full trade log 156 | 157 | --- 158 | ## 🖥️ Installation and Launch 159 | 160 | ### Prerequisites 161 | 162 | - **Node.js 18+** - Download from [nodejs.org](https://nodejs.org/) 163 | - **npm** (comes with Node.js) 164 | 165 | ### Installation Steps 166 | 167 | 1. **Clone the repository** 168 | ```bash 169 | git clone 170 | cd polymarket-copy-trading-bot 171 | ``` 172 | 173 | 2. **Install dependencies** 174 | ```bash 175 | npm install 176 | ``` 177 | 178 | 3. **Set up environment variables** 179 | - Create a `.env` file in the root directory 180 | - Add your configuration: 181 | ```env 182 | POLYMARKET_API=https://api.polymarket.com 183 | OPENAI_API_KEY=your_openai_api_key_here 184 | ``` 185 | 186 | 4. **Configure wallets** 187 | - Edit `src/config.ts` and update the `wallets_to_track` array with actual wallet addresses 188 | 189 | 5. **Run the bot** 190 | ```bash 191 | # Development mode 192 | npm run dev 193 | 194 | # Production mode 195 | npm run build 196 | npm start 197 | ``` 198 | 199 | ### Available Scripts 200 | 201 | - `npm run dev` - Run in development mode with tsx 202 | - `npm run build` - Compile TypeScript to JavaScript 203 | - `npm start` - Run the compiled JavaScript 204 | - `npm run watch` - Watch mode (auto-rebuild on changes) 205 | - `npm run cli` - Run CLI commands (see CLI_USAGE.md) 206 | 207 | ### CLI Commands 208 | 209 | The bot includes a user-friendly CLI. Quick start: 210 | 211 | ```bash 212 | # Initialize 213 | npm run cli init 214 | 215 | # Add wallets 216 | npm run cli wallets add
217 | 218 | # Configure 219 | npm run cli config --mode fixed --stake 25 220 | 221 | # Start bot 222 | npm run cli start 223 | ``` 224 | 225 | See [CLI_USAGE.md](CLI_USAGE.md) for complete CLI documentation. 226 | 227 | --- 228 | ## Tech Stack 229 | 230 | | Layer | Technology | 231 | |-----------|----------------------| 232 | | Language | TypeScript 5.3+ | 233 | | Runtime | Node.js 18+ | 234 | | HTTP | axios | 235 | | Data | Polymarket API | 236 | | AI | OpenAI API | 237 | | Interface | CLI | 238 | 239 | --- 240 | 241 | ## Development 242 | 243 | ### Project Structure 244 | 245 | - `src/main.ts` - Main entry point 246 | - `src/config.ts` - Configuration management 247 | - `src/api.ts` - Polymarket API client 248 | - `src/watcher.ts` - Wallet monitoring with async generators 249 | - `src/interpreter.ts` - Trade normalization 250 | - `src/sizing.ts` - Position sizing logic 251 | - `src/executor.ts` - Trade execution 252 | - `src/risk.ts` - Risk management 253 | - `src/strategy.ts` - Trading strategies (Kelly criterion, expected value) 254 | - `src/agent.ts` - AI event analysis with OpenAI 255 | 256 | ### Type Checking 257 | 258 | ```bash 259 | npx tsc --noEmit 260 | ``` 261 | 262 | ### Additional Documentation 263 | 264 | - [QUICKSTART.md](QUICKSTART.md) - Quick start guide 265 | - [README_TYPESCRIPT.md](README_TYPESCRIPT.md) - Detailed TypeScript documentation 266 | - [MIGRATION_SUMMARY.md](MIGRATION_SUMMARY.md) - Python to TypeScript migration details 267 | 268 | --- 269 | 270 | ## Contact 271 | 272 | For questions, support, or collaboration, reach out on Telegram: [@terauss](https://t.me/terauss) 273 | 274 | --- 275 | 276 | ## License 277 | 278 | MIT License. 279 | 280 | --- 281 | `Copy trades fast. Copy trades directly. No extra logic — just pure mirroring` 282 | -------------------------------------------------------------------------------- /src/cli.ts: -------------------------------------------------------------------------------- 1 | import { Command } from 'commander'; 2 | import { readFileSync, writeFileSync, existsSync } from 'fs'; 3 | import { join } from 'path'; 4 | import { Config, SizingMode } from './config'; 5 | import { startBot } from './bot'; 6 | 7 | const CONFIG_FILE = join(process.cwd(), 'config.json'); 8 | 9 | function loadConfigFromFile(): Config | null { 10 | if (!existsSync(CONFIG_FILE)) { 11 | return null; 12 | } 13 | try { 14 | const content = readFileSync(CONFIG_FILE, 'utf-8'); 15 | return JSON.parse(content); 16 | } catch (error) { 17 | console.error('Error loading config file:', error); 18 | return null; 19 | } 20 | } 21 | 22 | function saveConfigToFile(config: Config): void { 23 | try { 24 | writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf-8'); 25 | console.log('✅ Configuration saved successfully!'); 26 | } catch (error) { 27 | console.error('❌ Error saving config file:', error); 28 | } 29 | } 30 | 31 | function getConfig(): Config { 32 | const fileConfig = loadConfigFromFile(); 33 | if (fileConfig) { 34 | return fileConfig; 35 | } 36 | // Return default config 37 | return { 38 | wallets_to_track: [], 39 | mode: 'fixed', 40 | fixed_stake: 25, 41 | min_stake: 5, 42 | max_stake: 300, 43 | profit_take_percent: 20, 44 | api_base: 'https://api.polymarket.com', 45 | }; 46 | } 47 | 48 | const program = new Command(); 49 | 50 | program 51 | .name('polymarket-bot') 52 | .description('Polymarket Copy Trading Bot - CLI') 53 | .version('0.1.0'); 54 | 55 | // Start command 56 | program 57 | .command('start') 58 | .description('Start the copy trading bot') 59 | .option('-v, --verbose', 'Enable verbose logging') 60 | .action(async (options) => { 61 | console.log('🚀 Starting Polymarket Copy Trading Bot...\n'); 62 | const config = getConfig(); 63 | 64 | if (config.wallets_to_track.length === 0) { 65 | console.error('❌ No wallets configured. Please add wallets first:'); 66 | console.log(' polymarket-bot wallets add
\n'); 67 | process.exit(1); 68 | } 69 | 70 | console.log(`📊 Configuration:`); 71 | console.log(` Mode: ${config.mode}`); 72 | console.log(` Fixed Stake: $${config.fixed_stake}`); 73 | console.log(` Min/Max Stake: $${config.min_stake} - $${config.max_stake}`); 74 | console.log(` Profit Take: ${config.profit_take_percent}%`); 75 | console.log(` Tracking ${config.wallets_to_track.length} wallet(s)\n`); 76 | 77 | await startBot(config, options.verbose); 78 | }); 79 | 80 | // Config command 81 | program 82 | .command('config') 83 | .description('Configure bot settings') 84 | .option('-m, --mode ', 'Sizing mode: fixed or proportional', (value) => { 85 | if (value !== 'fixed' && value !== 'proportional') { 86 | throw new Error('Mode must be "fixed" or "proportional"'); 87 | } 88 | return value as SizingMode; 89 | }) 90 | .option('-s, --stake ', 'Fixed stake amount', parseFloat) 91 | .option('--min-stake ', 'Minimum stake amount', parseFloat) 92 | .option('--max-stake ', 'Maximum stake amount', parseFloat) 93 | .option('-p, --profit ', 'Profit take percentage', parseFloat) 94 | .action((options) => { 95 | const config = getConfig(); 96 | let updated = false; 97 | 98 | if (options.mode) { 99 | config.mode = options.mode; 100 | updated = true; 101 | console.log(`✅ Mode set to: ${options.mode}`); 102 | } 103 | 104 | if (options.stake !== undefined) { 105 | config.fixed_stake = options.stake; 106 | updated = true; 107 | console.log(`✅ Fixed stake set to: $${options.stake}`); 108 | } 109 | 110 | if (options.minStake !== undefined) { 111 | config.min_stake = options.minStake; 112 | updated = true; 113 | console.log(`✅ Min stake set to: $${options.minStake}`); 114 | } 115 | 116 | if (options.maxStake !== undefined) { 117 | config.max_stake = options.maxStake; 118 | updated = true; 119 | console.log(`✅ Max stake set to: $${options.maxStake}`); 120 | } 121 | 122 | if (options.profit !== undefined) { 123 | config.profit_take_percent = options.profit; 124 | updated = true; 125 | console.log(`✅ Profit take set to: ${options.profit}%`); 126 | } 127 | 128 | if (updated) { 129 | saveConfigToFile(config); 130 | } else { 131 | console.log('\n📋 Current Configuration:'); 132 | console.log(JSON.stringify(config, null, 2)); 133 | console.log('\n💡 Use --help to see available options'); 134 | } 135 | }); 136 | 137 | // Wallets command group 138 | const walletsCommand = program 139 | .command('wallets') 140 | .description('Manage wallets to track'); 141 | 142 | walletsCommand 143 | .command('list') 144 | .alias('ls') 145 | .description('List all tracked wallets') 146 | .action(() => { 147 | const config = getConfig(); 148 | if (config.wallets_to_track.length === 0) { 149 | console.log('📭 No wallets configured'); 150 | } else { 151 | console.log('📋 Tracked Wallets:'); 152 | config.wallets_to_track.forEach((wallet, index) => { 153 | console.log(` ${index + 1}. ${wallet}`); 154 | }); 155 | } 156 | }); 157 | 158 | walletsCommand 159 | .command('add
') 160 | .description('Add a wallet address to track') 161 | .action((address: string) => { 162 | const config = getConfig(); 163 | if (config.wallets_to_track.includes(address)) { 164 | console.log(`⚠️ Wallet ${address} is already being tracked`); 165 | return; 166 | } 167 | config.wallets_to_track.push(address); 168 | saveConfigToFile(config); 169 | console.log(`✅ Added wallet: ${address}`); 170 | }); 171 | 172 | walletsCommand 173 | .command('remove
') 174 | .alias('rm') 175 | .description('Remove a wallet address from tracking') 176 | .action((address: string) => { 177 | const config = getConfig(); 178 | const index = config.wallets_to_track.indexOf(address); 179 | if (index === -1) { 180 | console.log(`❌ Wallet ${address} not found in tracked wallets`); 181 | return; 182 | } 183 | config.wallets_to_track.splice(index, 1); 184 | saveConfigToFile(config); 185 | console.log(`✅ Removed wallet: ${address}`); 186 | }); 187 | 188 | // Status command 189 | program 190 | .command('status') 191 | .description('Show bot status and configuration') 192 | .action(() => { 193 | const config = getConfig(); 194 | console.log('\n📊 Bot Status\n'); 195 | console.log('Configuration:'); 196 | console.log(` Mode: ${config.mode}`); 197 | console.log(` Fixed Stake: $${config.fixed_stake}`); 198 | console.log(` Stake Range: $${config.min_stake} - $${config.max_stake}`); 199 | console.log(` Profit Take: ${config.profit_take_percent}%`); 200 | console.log(` API Base: ${config.api_base}`); 201 | console.log(`\nTracked Wallets: ${config.wallets_to_track.length}`); 202 | if (config.wallets_to_track.length > 0) { 203 | config.wallets_to_track.forEach((wallet, index) => { 204 | console.log(` ${index + 1}. ${wallet}`); 205 | }); 206 | } else { 207 | console.log(' ⚠️ No wallets configured'); 208 | } 209 | console.log(''); 210 | }); 211 | 212 | // Init command 213 | program 214 | .command('init') 215 | .description('Initialize bot configuration (interactive)') 216 | .action(() => { 217 | console.log('🔧 Initializing Polymarket Copy Trading Bot...\n'); 218 | const config = getConfig(); 219 | 220 | if (existsSync(CONFIG_FILE)) { 221 | console.log('⚠️ Config file already exists. Use "config" command to modify settings.\n'); 222 | return; 223 | } 224 | 225 | saveConfigToFile(config); 226 | console.log('✅ Configuration initialized!'); 227 | console.log('\nNext steps:'); 228 | console.log('1. Add wallets: polymarket-bot wallets add
'); 229 | console.log('2. Configure settings: polymarket-bot config --help'); 230 | console.log('3. Start the bot: polymarket-bot start\n'); 231 | }); 232 | 233 | export function runCLI(): void { 234 | program.parse(); 235 | } 236 | 237 | --------------------------------------------------------------------------------