Files
TurboTrades/MULTI_BOT_SETUP.md
2026-01-10 04:57:43 +00:00

23 KiB

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

  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:

{
  "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:

# 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

{
  "type": "socks5",
  "host": "proxy.example.com",
  "port": 1080,
  "username": "user",
  "password": "pass"
}

Best for:

  • Steam connections
  • High performance
  • Full protocol support

2. HTTP/HTTPS

{
  "type": "http",
  "host": "proxy.example.com",
  "port": 8080,
  "username": "user",
  "password": "pass"
}

Best for:

  • Web requests
  • Simple setup
  • Most proxy providers

3. No Proxy

{
  "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

// 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

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

// 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

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)

// 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

const botManager = getSteamBotManager();

// Get all bots health
const health = botManager.getAllBotsHealth();
console.log(health);

Output:

[
  {
    "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

const stats = botManager.getStats();
console.log(stats);

Output:

{
  "totalBots": 3,
  "readyBots": 3,
  "healthyBots": 3,
  "totalTrades": 450,
  "totalActiveTrades": 12,
  "totalErrors": 5,
  "verificationCodesStored": 12
}

Admin Dashboard Integration

Add to admin panel:

// 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

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

# ✅ 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

// Always verify code before crediting balance
const isValid = botManager.verifyTradeCode(offerId, userEnteredCode);
if (!isValid) {
  throw new Error('Invalid verification code');
}

5. Rate Limiting

// 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:
    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

// 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:

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

{
  "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

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


🎉 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!