# Multi-Bot Setup with Proxies & Verification Codes ## šŸŽÆ Overview TurboTrades now supports **multiple Steam bots** with: - āœ… **Load Balancing** - Automatically distributes trades across bots - āœ… **Proxy Support** - Each bot can use different proxy (SOCKS5/HTTP) - āœ… **Verification Codes** - 6-digit codes shown on site and in trade - āœ… **Automatic Failover** - If one bot fails, others take over - āœ… **Health Monitoring** - Track bot status and performance --- ## šŸ” Why Verification Codes? **Security Feature**: Prevents scam bots from impersonating your trade offers. **How it works:** 1. User clicks "Sell Items" on website 2. System generates unique 6-digit code (e.g., `A3K9P2`) 3. Code is shown prominently on website 4. Same code is included in Steam trade offer message 5. User **MUST verify** code matches before accepting **Benefits:** - āœ… User can verify trade is legitimate - āœ… Prevents phishing/fake trade offers - āœ… Adds extra layer of security - āœ… Easy to implement and understand --- ## šŸ“‹ Prerequisites ### For Each Bot Account: 1. **Separate Steam Account** - Not your personal account! - Must have spent $5+ (not limited) - Public inventory - Valid trade URL 2. **Steam Mobile Authenticator** - Enabled on each bot account - Trade cooldown period expired (7 days) 3. **Shared Secret & Identity Secret** - Extract using SDA (Steam Desktop Authenticator) - Or use mobile app extraction tools 4. **Steam API Key** - Get from: https://steamcommunity.com/dev/apikey - Can use same API key for all bots 5. **Proxy (Optional but Recommended)** - SOCKS5 or HTTP/HTTPS proxy - One proxy per bot - Prevents IP rate limiting --- ## šŸ› ļø Bot Configuration ### Configuration File Format Create `config/steam-bots.json`: ```json { "bots": [ { "accountName": "turbobot_01", "password": "secure_password_1", "sharedSecret": "abcdef1234567890", "identitySecret": "xyz9876543210abc", "steamApiKey": "YOUR_STEAM_API_KEY", "proxy": { "type": "socks5", "host": "proxy1.example.com", "port": 1080, "username": "proxy_user", "password": "proxy_pass" }, "maxConcurrentTrades": 10, "pollInterval": 30000, "tradeTimeout": 600000 }, { "accountName": "turbobot_02", "password": "secure_password_2", "sharedSecret": "fedcba0987654321", "identitySecret": "cba0123456789xyz", "steamApiKey": "YOUR_STEAM_API_KEY", "proxy": { "type": "http", "host": "proxy2.example.com", "port": 8080, "username": "proxy_user2", "password": "proxy_pass2" }, "maxConcurrentTrades": 10, "pollInterval": 30000, "tradeTimeout": 600000 }, { "accountName": "turbobot_03", "password": "secure_password_3", "sharedSecret": "1234567890abcdef", "identitySecret": "0987654321zyxwvu", "steamApiKey": "YOUR_STEAM_API_KEY", "proxy": null, "maxConcurrentTrades": 10, "pollInterval": 30000, "tradeTimeout": 600000 } ] } ``` ### Environment Variables (Alternative) Or use environment variables: ```env # Bot 1 STEAM_BOT_1_USERNAME=turbobot_01 STEAM_BOT_1_PASSWORD=secure_password_1 STEAM_BOT_1_SHARED_SECRET=abcdef1234567890 STEAM_BOT_1_IDENTITY_SECRET=xyz9876543210abc STEAM_BOT_1_PROXY=socks5://user:pass@proxy1.example.com:1080 # Bot 2 STEAM_BOT_2_USERNAME=turbobot_02 STEAM_BOT_2_PASSWORD=secure_password_2 STEAM_BOT_2_SHARED_SECRET=fedcba0987654321 STEAM_BOT_2_IDENTITY_SECRET=cba0123456789xyz STEAM_BOT_2_PROXY=http://user2:pass2@proxy2.example.com:8080 # Bot 3 STEAM_BOT_3_USERNAME=turbobot_03 STEAM_BOT_3_PASSWORD=secure_password_3 STEAM_BOT_3_SHARED_SECRET=1234567890abcdef STEAM_BOT_3_IDENTITY_SECRET=0987654321zyxwvu # No proxy for bot 3 # Global Settings STEAM_API_KEY=YOUR_STEAM_API_KEY STEAM_BOT_COUNT=3 ``` --- ## 🌐 Proxy Configuration ### Why Use Proxies? - āœ… **Prevent Rate Limiting** - Each bot has own IP - āœ… **Geographic Distribution** - Bots appear from different locations - āœ… **Avoid Bans** - If one IP gets rate limited, others continue - āœ… **Better Performance** - Distribute load across proxies ### Proxy Types Supported #### 1. SOCKS5 (Recommended) ```json { "type": "socks5", "host": "proxy.example.com", "port": 1080, "username": "user", "password": "pass" } ``` **Best for:** - Steam connections - High performance - Full protocol support #### 2. HTTP/HTTPS ```json { "type": "http", "host": "proxy.example.com", "port": 8080, "username": "user", "password": "pass" } ``` **Best for:** - Web requests - Simple setup - Most proxy providers #### 3. No Proxy ```json { "proxy": null } ``` **Use when:** - Testing locally - VPS with good IP reputation - Low trade volume ### Proxy Providers **Recommended Providers:** - **Bright Data** (formerly Luminati) - Premium, reliable - **Oxylabs** - High quality, expensive - **IPRoyal** - Good balance of price/quality - **Webshare** - Budget friendly - **SmartProxy** - Good for Steam **Requirements:** - Dedicated or semi-dedicated IPs - SOCKS5 support preferred - Good uptime (99%+) - Reasonable speed (<500ms latency) --- ## šŸš€ Starting Multiple Bots ### Method 1: Using Configuration File ```javascript // index.js or startup file import { getSteamBotManager } from './services/steamBot.js'; import botsConfig from './config/steam-bots.json' assert { type: 'json' }; const botManager = getSteamBotManager(); // Initialize all bots await botManager.initialize(botsConfig.bots); console.log('āœ… All bots initialized'); ``` ### Method 2: Using Environment Variables ```javascript import { getSteamBotManager } from './services/steamBot.js'; const botManager = getSteamBotManager(); // Build config from environment const botsConfig = []; const botCount = parseInt(process.env.STEAM_BOT_COUNT || '1'); for (let i = 1; i <= botCount; i++) { const prefix = `STEAM_BOT_${i}_`; if (!process.env[prefix + 'USERNAME']) continue; botsConfig.push({ accountName: process.env[prefix + 'USERNAME'], password: process.env[prefix + 'PASSWORD'], sharedSecret: process.env[prefix + 'SHARED_SECRET'], identitySecret: process.env[prefix + 'IDENTITY_SECRET'], steamApiKey: process.env.STEAM_API_KEY, proxy: process.env[prefix + 'PROXY'] ? parseProxyUrl(process.env[prefix + 'PROXY']) : null, }); } await botManager.initialize(botsConfig); ``` ### Method 3: Auto-Start on Backend Launch ```javascript // In your main server file import { getSteamBotManager } from './services/steamBot.js'; // After fastify.listen() if (process.env.STEAM_BOT_AUTO_START === 'true') { console.log('šŸ¤– Auto-starting Steam bots...'); const botManager = getSteamBotManager(); // Load config const botsConfig = loadBotsConfig(); // Your config loading logic await botManager.initialize(botsConfig); console.log('āœ… Steam bots ready'); } ``` --- ## šŸŽ® Creating Trades with Verification Codes ### Backend Example ```javascript import { getSteamBotManager } from '../services/steamBot.js'; import Trade from '../models/Trade.js'; // User sells items fastify.post('/api/trade/create', async (request, reply) => { const { items } = request.body; const userId = request.user._id; const steamId = request.user.steamId; const tradeUrl = request.user.tradeUrl; // Calculate values const totalValue = items.reduce((sum, item) => sum + item.price, 0); const fee = totalValue * 0.05; // 5% fee const userReceives = totalValue - fee; // Create trade offer with automatic bot selection const botManager = getSteamBotManager(); const result = await botManager.createTradeOffer({ tradeUrl: tradeUrl, itemsToReceive: items.map(item => ({ assetid: item.assetId, appid: 730, // CS2 contextid: 2 })), userId: userId, metadata: { itemCount: items.length, totalValue: totalValue } }); // Create trade record in database const trade = await Trade.createTrade({ offerId: result.offerId, userId: userId, steamId: steamId, state: 'pending', items: items, totalValue: totalValue, fee: fee, feePercentage: 5, userReceives: userReceives, tradeUrl: tradeUrl, verificationCode: result.verificationCode, botId: result.botId, expiresAt: new Date(Date.now() + 10 * 60 * 1000), // 10 minutes sessionId: request.session?.id, }); return reply.send({ success: true, trade: { id: trade._id, offerId: trade.offerId, verificationCode: trade.verificationCode, // ⭐ IMPORTANT: Show to user state: 'pending', totalValue: totalValue, userReceives: userReceives, expiresAt: trade.expiresAt, message: 'Trade offer sent! Please check your Steam app.' } }); }); ``` ### What User Sees on Website ``` ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” │ Trade Offer Sent! │ ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤ │ │ │ Verification Code: │ │ ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”“ │ │ ā”ƒ A 3 K 9 P 2 ā”ƒ <- Large, clear │ │ ┗━━━━━━━━━━━━━━━┛ │ │ │ │ āš ļø IMPORTANT: │ │ Check that this code appears in your │ │ Steam trade offer. DO NOT accept trades │ │ without this code! │ │ │ │ Status: Waiting for acceptance... │ │ Expires in: 9:45 │ │ │ │ [View in Steam] [Cancel Trade] │ │ │ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ ``` ### What User Sees in Steam Trade Offer ``` Trade Offer from turbobot_01 TurboTrades Trade Verification Code: A3K9P2 Please verify this code matches the one shown on our website before accepting. Do not accept trades without a valid verification code! You will receive: - Nothing You will give: - AK-47 | Redline (Field-Tested) - AWP | Asiimov (Battle-Scarred) [Accept] [Decline] ``` --- ## šŸ”„ Load Balancing ### How Bot Selection Works 1. **Filter Available Bots** - Must be logged in - Must be healthy (low error count) - Must have capacity (< max concurrent trades) 2. **Sort by Load** - Bots with fewer active trades ranked higher - Distributes load evenly 3. **Select Best Bot** - Returns bot with lowest current load - If all bots busy, throws error ### Example Load Distribution ``` Bot 1: 3 active trades <- Selected (lowest) Bot 2: 5 active trades Bot 3: 7 active trades Next trade goes to Bot 1 After assignment: Bot 1: 4 active trades Bot 2: 5 active trades <- Next trade goes here Bot 3: 7 active trades ``` ### Manual Bot Selection (Advanced) ```javascript // Get specific bot const bot = botManager.getBot('bot_1'); // Create trade with specific bot const result = await bot.createTradeOffer({ tradeUrl: userTradeUrl, itemsToReceive: items, verificationCode: 'MANUAL1', metadata: {} }); ``` --- ## šŸ“Š Monitoring & Health ### Check Bot Health ```javascript const botManager = getSteamBotManager(); // Get all bots health const health = botManager.getAllBotsHealth(); console.log(health); ``` **Output:** ```json [ { "botId": "bot_1", "isReady": true, "isLoggedIn": true, "isHealthy": true, "activeTrades": 3, "tradeCount": 150, "errorCount": 2, "lastTradeTime": "2024-01-10T12:05:00Z", "username": "turbobot_01", "proxy": "socks5://proxy1.example.com:1080" }, { "botId": "bot_2", "isReady": true, "isLoggedIn": true, "isHealthy": true, "activeTrades": 5, "tradeCount": 180, "errorCount": 1, "lastTradeTime": "2024-01-10T12:03:00Z", "username": "turbobot_02", "proxy": "http://proxy2.example.com:8080" } ] ``` ### System-Wide Stats ```javascript const stats = botManager.getStats(); console.log(stats); ``` **Output:** ```json { "totalBots": 3, "readyBots": 3, "healthyBots": 3, "totalTrades": 450, "totalActiveTrades": 12, "totalErrors": 5, "verificationCodesStored": 12 } ``` ### Admin Dashboard Integration Add to admin panel: ```javascript // GET /api/admin/bots/health fastify.get('/admin/bots/health', async (request, reply) => { const botManager = getSteamBotManager(); return reply.send({ success: true, bots: botManager.getAllBotsHealth(), stats: botManager.getStats() }); }); ``` --- ## šŸŽÆ Trade Events ### Listen to Trade Events ```javascript const botManager = getSteamBotManager(); // Trade accepted - Credit user balance! botManager.on('tradeAccepted', async (offer, tradeData, botId) => { console.log(`āœ… Trade ${offer.id} accepted on ${botId}`); const trade = await Trade.getByOfferId(offer.id); const user = await User.findById(trade.userId); // Credit user balance user.balance += trade.userReceives; await user.save(); // Create transaction const transaction = await Transaction.createTransaction({ userId: trade.userId, steamId: trade.steamId, type: 'sale', status: 'completed', amount: trade.userReceives, fee: trade.fee, feePercentage: trade.feePercentage, balanceBefore: user.balance - trade.userReceives, balanceAfter: user.balance, metadata: { tradeId: trade._id, offerId: trade.offerId, itemCount: trade.items.length } }); // Update trade await trade.markAsCompleted(transaction._id); // Notify user via WebSocket websocketManager.sendToUser(trade.steamId, { type: 'trade_accepted', data: { tradeId: trade._id, balance: user.balance, amount: trade.userReceives } }); }); // Trade declined botManager.on('tradeDeclined', async (offer, tradeData, botId) => { console.log(`āŒ Trade ${offer.id} declined on ${botId}`); const trade = await Trade.getByOfferId(offer.id); await trade.markAsDeclined(); // Notify user websocketManager.sendToUser(trade.steamId, { type: 'trade_declined', data: { tradeId: trade._id, message: 'Trade offer was declined' } }); }); // Trade expired botManager.on('tradeExpired', async (offer, tradeData, botId) => { console.log(`ā° Trade ${offer.id} expired on ${botId}`); const trade = await Trade.getByOfferId(offer.id); await trade.markAsExpired(); // Optionally retry if (trade.retryCount < 3) { console.log('šŸ”„ Retrying expired trade...'); // Retry logic here } }); // Bot error botManager.on('botError', (err, botId) => { console.error(`āŒ Bot ${botId} error:`, err.message); // Send alert to admins // Log to monitoring service }); ``` --- ## šŸ”’ Security Best Practices ### 1. Secure Credentials ```env # āœ… Good - Use environment variables STEAM_BOT_1_PASSWORD=secure_password # āŒ Bad - Never hardcode in config files "password": "my_password_123" ``` ### 2. Rotate Proxies - Change proxies monthly - Use different proxy providers - Monitor proxy performance - Replace slow/banned proxies ### 3. Bot Account Security - āœ… Use unique passwords for each bot - āœ… Enable Steam Guard on all bots - āœ… Don't share bot accounts - āœ… Keep secrets in secure vault - āœ… Use 2FA on bot accounts ### 4. Verification Code Validation ```javascript // Always verify code before crediting balance const isValid = botManager.verifyTradeCode(offerId, userEnteredCode); if (!isValid) { throw new Error('Invalid verification code'); } ``` ### 5. Rate Limiting ```javascript // Limit trades per user per hour const userTrades = await Trade.find({ userId: userId, createdAt: { $gte: new Date(Date.now() - 60 * 60 * 1000) } }); if (userTrades.length >= 10) { throw new Error('Trade limit exceeded. Try again later.'); } ``` --- ## šŸ› Troubleshooting ### Bot Won't Login **Symptoms:** - Bot stuck at "Logging in..." - Error: "Invalid credentials" - Error: "SteamGuardMobile needed" **Solutions:** 1. Check credentials are correct 2. Verify shared secret is valid 3. Disable proxy temporarily to test 4. Check Steam is not under maintenance 5. Verify bot account not limited/banned ### Proxy Connection Failed **Symptoms:** - Bot disconnects frequently - Error: "ECONNREFUSED" - Error: "Proxy authentication failed" **Solutions:** 1. Test proxy with curl: ```bash curl -x socks5://user:pass@proxy:1080 https://steamcommunity.com ``` 2. Verify proxy credentials 3. Check proxy IP not banned by Steam 4. Try different proxy 5. Contact proxy provider ### Verification Codes Not Showing **Symptoms:** - Trade offer created but no code - Code is null/undefined **Solutions:** 1. Check `verificationCode` saved in database 2. Verify frontend is receiving code 3. Check trade creation response 4. View logs for code generation ### Trades Not Accepting **Symptoms:** - User accepts trade in Steam - Balance not credited - Trade stuck in pending **Solutions:** 1. Check bot event handlers are working 2. Verify bot polling is active 3. Check trade state in database 4. Manually check trade status in Steam 5. Review bot logs for errors --- ## šŸ“ˆ Performance Optimization ### 1. Optimal Bot Count **Small Sites** (<100 trades/day): - 2-3 bots sufficient - No proxies needed initially **Medium Sites** (100-500 trades/day): - 3-5 bots recommended - 1 proxy per bot **Large Sites** (>500 trades/day): - 5-10 bots - Multiple proxies per region - Redis queue for trade management ### 2. Proxy Pool Management ```javascript // Rotate proxies periodically setInterval(() => { console.log('šŸ”„ Checking proxy health...'); const health = botManager.getAllBotsHealth(); health.forEach(bot => { if (bot.errorCount > 20) { console.warn(`āš ļø ${bot.botId} has high error count, consider rotating proxy`); } }); }, 60 * 60 * 1000); // Check every hour ``` ### 3. Trade Queue System For high volume, implement queue: ```javascript import Bull from 'bull'; const tradeQueue = new Bull('steam-trades', { redis: { host: 'localhost', port: 6379 } }); tradeQueue.process(5, async (job) => { // Process 5 at a time const { userId, items, tradeUrl } = job.data; return await botManager.createTradeOffer({ tradeUrl, itemsToReceive: items, userId }); }); // Add to queue await tradeQueue.add({ userId, items, tradeUrl }, { attempts: 3, backoff: { type: 'exponential', delay: 5000 } }); ``` --- ## āœ… Production Checklist Before going live: - [ ] All bot accounts created and funded - [ ] Steam Mobile Authenticator enabled on all bots - [ ] Shared/identity secrets extracted - [ ] Proxies tested and working - [ ] Configuration file created - [ ] All bots successfully login - [ ] Test trade offer sent and accepted - [ ] Verification codes displayed correctly - [ ] Balance credits after acceptance - [ ] Trade events firing properly - [ ] Error handling tested - [ ] Monitoring dashboard set up - [ ] Rate limiting implemented - [ ] Backup bots configured - [ ] Documentation updated - [ ] Team trained on bot management --- ## šŸŽ“ Example: 3-Bot Setup ### Complete Configuration ```json { "bots": [ { "accountName": "turbotrades_bot1", "password": "StrongPass123!@#", "sharedSecret": "Xj9mK3pL2qN5vB8cD4fG7hJ1kM6nP0rT", "identitySecret": "Aa1Bb2Cc3Dd4Ee5Ff6Gg7Hh8Ii9Jj0Kk", "steamApiKey": "YOUR_STEAM_API_KEY_HERE", "proxy": { "type": "socks5", "host": "us-proxy1.example.com", "port": 1080, "username": "proxyuser1", "password": "ProxyPass123" }, "maxConcurrentTrades": 15, "pollInterval": 25000, "tradeTimeout": 600000 }, { "accountName": "turbotrades_bot2", "password": "AnotherStrong456!@#", "sharedSecret": "Yh8jM2kL4pN7vC9dF3gH6jK0mP5qR1tS", "identitySecret": "Bb2Cc3Dd4Ee5Ff6Gg7Hh8Ii9Jj0Kk1Ll", "steamApiKey": "YOUR_STEAM_API_KEY_HERE", "proxy": { "type": "socks5", "host": "eu-proxy1.example.com", "port": 1080, "username": "proxyuser2", "password": "ProxyPass456" }, "maxConcurrentTrades": 15, "pollInterval": 25000, "tradeTimeout": 600000 }, { "accountName": "turbotrades_bot3", "password": "SecureBot789!@#", "sharedSecret": "Zi7kN1mL3oP6wD8eG2hJ5lM9qT4rU0vX", "identitySecret": "Cc3Dd4Ee5Ff6Gg7Hh8Ii9Jj0Kk1Ll2Mm", "steamApiKey": "YOUR_STEAM_API_KEY_HERE", "proxy": { "type": "http", "host": "asia-proxy1.example.com", "port": 8080, "username": "proxyuser3", "password": "ProxyPass789" }, "maxConcurrentTrades": 15, "pollInterval": 25000, "tradeTimeout": 600000 } ] } ``` ### Startup Script ```javascript import { getSteamBotManager } from './services/steamBot.js'; import fs from 'fs'; async function startBots() { console.log('šŸ¤– Starting TurboTrades Bot System...\n'); // Load configuration const config = JSON.parse( fs.readFileSync('./config/steam-bots.json', 'utf8') ); // Initialize bot manager const botManager = getSteamBotManager(); // Start all bots const results = await botManager.initialize(config.bots); // Show results results.forEach(result => { if (result.success) { console.log(`āœ… ${result.botId} - Ready`); } else { console.log(`āŒ ${result.botId} - Failed: ${result.error}`); } }); console.log('\nšŸ“Š System Status:'); console.log(botManager.getStats()); return botManager; } // Start bots const botManager = await startBots(); // Handle graceful shutdown process.on('SIGINT', () => { console.log('\nšŸ‘‹ Shutting down bots...'); botManager.shutdown(); process.exit(0); }); ``` --- ## šŸ“š Additional Resources - **Steam Web API**: https://developer.valvesoftware.com/wiki/Steam_Web_API - **node-steam-user**: https://github.com/DoctorMcKay/node-steam-user - **steam-tradeoffer-manager**: https://github.com/DoctorMcKay/node-steam-tradeoffer-manager - **SOCKS Proxy Agent**: https://www.npmjs.com/package/socks-proxy-agent --- ## šŸŽ‰ Summary You now have: - āœ… Multiple Steam bots with load balancing - āœ… Proxy support for each bot - āœ… Verification codes for security - āœ… Automatic failover - āœ… Health monitoring - āœ… Event-driven architecture - āœ… Production-ready setup **Next Steps:** 1. Set up bot accounts 2. Configure proxies 3. Create configuration file 4. Test bot login 5. Create test trade with verification code 6. Integrate with sell endpoint 7. Add UI for verification code display 8. Deploy to production **The system will now:** - Accept sell requests from users - Generate unique verification code - Select best available bot - Create trade offer with code in message - Wait for user to accept - Credit balance ONLY after trade accepted - Handle failures gracefully šŸš€ **Your marketplace is now secure and scalable!**