# Steam Bot Setup Guide ## ๐Ÿค– Overview The Steam bot system handles trade offers for buying items from users. When a user sells items, instead of immediately crediting funds, the system: 1. โœ… Creates a trade offer via Steam bot 2. โณ Tracks trade state (pending, accepted, declined, etc.) 3. ๐Ÿ’ฐ Credits user balance ONLY after trade is accepted 4. ๐Ÿ”„ Handles failures, expirations, and retries --- ## ๐Ÿ“‹ Prerequisites ### 1. Steam Bot Account You need a separate Steam account for the bot: - โœ… Account with Steam Mobile Authenticator enabled - โœ… Public inventory - โœ… Valid trade URL - โœ… API key from https://steamcommunity.com/dev/apikey - โœ… Not limited (must have spent $5+ on Steam) - โœ… Trade cooldown period expired (if newly set up) ### 2. Required Packages Already installed in package.json: ```json { "steam-user": "^5.0.0", "steamcommunity": "^3.47.0", "steam-tradeoffer-manager": "^2.10.6", "steam-totp": "^2.1.1" } ``` Install if needed: ```bash npm install steam-user steamcommunity steam-tradeoffer-manager steam-totp ``` --- ## ๐Ÿ” Getting Steam Bot Credentials ### Step 1: Get Shared Secret & Identity Secret 1. **Enable Steam Mobile Authenticator** on bot account 2. Use one of these tools to extract secrets: - **SDA (Steam Desktop Authenticator)**: https://github.com/Jessecar96/SteamDesktopAuthenticator - **Android**: Use app like "Steam Guard Mobile Authenticator" - **Manual extraction**: Follow guides online 3. You'll need: - `shared_secret` - For generating 2FA codes - `identity_secret` - For confirming trades ### Step 2: Get Steam API Key 1. Go to: https://steamcommunity.com/dev/apikey 2. Register domain: `turbotrades.com` (or your domain) 3. Copy the API key ### Step 3: Get Bot Trade URL 1. Login to bot account 2. Go to: https://steamcommunity.com/id/me/tradeoffers/privacy 3. Copy the trade URL (looks like: `https://steamcommunity.com/tradeoffer/new/?partner=XXXXX&token=XXXXXXXX`) --- ## โš™๏ธ Configuration ### Environment Variables Add to your `.env` file: ```env # Steam Bot Credentials STEAM_BOT_USERNAME=your_bot_username STEAM_BOT_PASSWORD=your_bot_password STEAM_BOT_SHARED_SECRET=your_shared_secret_here STEAM_BOT_IDENTITY_SECRET=your_identity_secret_here # Steam API STEAM_API_KEY=your_steam_api_key # Bot Trade URL STEAM_BOT_TRADE_URL=https://steamcommunity.com/tradeoffer/new/?partner=XXXXX&token=XXXXXXXX # Optional: Bot Settings STEAM_BOT_POLL_INTERVAL=30000 STEAM_BOT_AUTO_START=true ``` ### Security Notes - โš ๏ธ **NEVER commit `.env` to git** - โš ๏ธ Keep secrets secure - โš ๏ธ Use different account from your personal Steam - โš ๏ธ Enable Steam Guard on bot account - โš ๏ธ Use strong password --- ## ๐Ÿš€ Starting the Bot ### Automatic Start (Recommended) Bot starts automatically when backend launches if `STEAM_BOT_AUTO_START=true` ```bash npm run dev ``` You'll see: ``` ๐Ÿ” Logging into Steam... โœ… Steam bot logged in successfully โœ… Steam web session established ๐Ÿค– Steam bot ready for trades ``` ### Manual Start ```javascript import { getSteamBot } from './services/steamBot.js'; const bot = getSteamBot(); await bot.login(); console.log('Bot ready:', bot.isOnline()); ``` --- ## ๐Ÿ”„ How It Works ### User Sells Items Flow ``` 1. User selects items on Sell page 2. User clicks "Sell Selected Items" โ†“ 3. Backend creates Trade record (state: pending) - Does NOT credit balance yet โ†“ 4. Steam bot creates trade offer - Requests items from user - User sees trade offer in Steam โ†“ 5. User accepts trade in Steam app โ†“ 6. Bot receives "trade accepted" event โ†“ 7. Backend: - Updates Trade state to "accepted" - Creates Transaction record - Credits user balance - Updates WebSocket โ†“ 8. User sees balance update in UI ``` ### Trade States | State | Description | User Balance | Can Retry | |-------|-------------|--------------|-----------| | **pending** | Trade offer sent, waiting for user | โŒ Not credited | โœ… Yes | | **accepted** | User accepted, items received | โœ… Credited | โŒ No | | **declined** | User declined the offer | โŒ Not credited | โš ๏ธ Maybe | | **expired** | Trade offer expired (10min timeout) | โŒ Not credited | โœ… Yes | | **canceled** | Trade was canceled | โŒ Not credited | โœ… Yes | | **failed** | Technical error occurred | โŒ Not credited | โœ… Yes | | **escrow** | Trade in Steam escrow | โŒ Not credited | โณ Wait | --- ## ๐Ÿ“Š Database Schema ### Trade Model ```javascript { offerId: String, // Steam trade offer ID userId: ObjectId, // User who's selling steamId: String, // User's Steam ID state: String, // pending, accepted, declined, etc. items: [{ assetId: String, name: String, price: Number, image: String, // ... item details }], totalValue: Number, // Total price of all items fee: Number, // Platform fee (e.g., 5%) feePercentage: Number, // Fee percentage userReceives: Number, // Amount user gets (after fees) tradeUrl: String, // User's trade URL tradeOfferUrl: String, // Link to view offer on Steam sentAt: Date, // When trade was sent acceptedAt: Date, // When user accepted completedAt: Date, // When balance was credited expiresAt: Date, // When trade expires (10min) transactionId: ObjectId, // Transaction created after acceptance sessionId: ObjectId, // User's session errorMessage: String, // If failed retryCount: Number, // How many times retried metadata: Mixed // Additional data } ``` --- ## ๐ŸŽฎ Bot Events The bot emits events you can listen to: ```javascript const bot = getSteamBot(); // Bot is ready bot.on('ready', () => { console.log('Bot is ready!'); }); // Trade accepted bot.on('tradeAccepted', async (offer, tradeData) => { console.log('Trade accepted:', offer.id); // Credit user balance here }); // Trade declined bot.on('tradeDeclined', async (offer, tradeData) => { console.log('Trade declined:', offer.id); // Notify user }); // Trade expired bot.on('tradeExpired', async (offer, tradeData) => { console.log('Trade expired:', offer.id); // Can retry or cancel }); // Bot error bot.on('error', (err) => { console.error('Bot error:', err); }); // Bot disconnected bot.on('disconnected', () => { console.warn('Bot disconnected, will reconnect...'); }); ``` --- ## ๐Ÿ› ๏ธ API Endpoints ### Create Trade Offer ```http POST /api/trade/create Authorization: Bearer { "items": [ { "assetId": "123456789", "name": "AK-47 | Redline (Field-Tested)", "price": 12.50, "image": "https://...", // ... other item data } ] } ``` **Response:** ```json { "success": true, "trade": { "id": "trade_id", "offerId": "steam_offer_id", "state": "pending", "totalValue": 12.50, "userReceives": 11.88, "items": [...], "tradeOfferUrl": "https://steamcommunity.com/tradeoffer/...", "expiresAt": "2024-01-10T12:10:00Z" }, "message": "Trade offer sent! Check your Steam app to accept." } ``` ### Get Trade Status ```http GET /api/trade/:tradeId Authorization: Bearer ``` **Response:** ```json { "success": true, "trade": { "id": "trade_id", "offerId": "steam_offer_id", "state": "accepted", "totalValue": 12.50, "userReceives": 11.88, "acceptedAt": "2024-01-10T12:05:00Z", "timeElapsed": "5m ago" } } ``` ### Cancel Trade ```http POST /api/trade/:tradeId/cancel Authorization: Bearer ``` ### Retry Trade ```http POST /api/trade/:tradeId/retry Authorization: Bearer ``` --- ## ๐Ÿ”ง Bot Management ### Check Bot Status ```javascript const bot = getSteamBot(); const health = bot.getHealth(); console.log(health); // { // isReady: true, // isLoggedIn: true, // activeTradesCount: 5, // username: "bot_username" // } ``` ### Get Active Trades ```javascript const activeTrades = bot.getActiveTrades(); console.log(`${activeTrades.length} trades active`); ``` ### Cancel All Pending Trades ```javascript const pendingTrades = await Trade.getPendingTrades(); for (const trade of pendingTrades) { if (trade.isExpired) { await bot.cancelTradeOffer(trade.offerId); await trade.markAsExpired(); } } ``` --- ## ๐Ÿงช Testing ### Test Bot Login ```bash node -e "import('./services/steamBot.js').then(async m => { const bot = m.getSteamBot(); await bot.login(); console.log('Bot logged in:', bot.isOnline()); bot.logout(); process.exit(0); })" ``` ### Test Trade Creation ```javascript const bot = getSteamBot(); await bot.login(); const result = await bot.createTradeOffer({ tradeUrl: "https://steamcommunity.com/tradeoffer/new/?partner=XXX&token=XXX", itemsToReceive: [ { assetid: "123456789", appid: 730, contextid: 2 } ], message: "Test trade offer" }); console.log('Trade created:', result); ``` --- ## ๐Ÿ“ˆ Monitoring ### Database Queries ```javascript // Get all pending trades const pending = await Trade.find({ state: 'pending' }); // Get expired trades const expired = await Trade.getExpiredTrades(); // Get trade stats const stats = await Trade.getStats(); console.log(` Total trades: ${stats.total} Accepted: ${stats.accepted} Pending: ${stats.pending} Declined: ${stats.declined} `); // Get user's trades const userTrades = await Trade.getUserTrades(userId); ``` ### Admin Panel Integration Add to admin panel: - โœ… View pending trades - โœ… Cancel stale trades - โœ… Retry failed trades - โœ… View trade statistics - โœ… Bot health status --- ## ๐Ÿ› Troubleshooting ### Bot Won't Login **Check:** - โœ… Username and password correct - โœ… Shared secret is valid - โœ… Steam account not limited - โœ… No active VAC ban - โœ… No trade cooldown **Solution:** ```bash # Test credentials node -e "console.log('Username:', process.env.STEAM_BOT_USERNAME)" node -e "console.log('Has password:', !!process.env.STEAM_BOT_PASSWORD)" node -e "console.log('Has shared secret:', !!process.env.STEAM_BOT_SHARED_SECRET)" ``` ### Trades Not Confirming **Check:** - โœ… Identity secret is correct - โœ… Mobile authenticator is active - โœ… Bot has trade URL **Solution:** - Manually confirm in Steam app first time - Check if identity secret is correct - Regenerate secrets if needed ### Trades Stuck in Pending **Reasons:** - User hasn't accepted yet - Trade expired (10 minutes) - Steam API issues - User's inventory is private **Solution:** ```javascript // Cancel expired trades const expired = await Trade.find({ state: 'pending', expiresAt: { $lt: new Date() } }); for (const trade of expired) { await bot.cancelTradeOffer(trade.offerId); await trade.markAsExpired(); } ``` ### Bot Keeps Disconnecting **Check:** - โœ… Network connection stable - โœ… Steam not under maintenance - โœ… No rate limiting **Solution:** - Implement auto-reconnect (already built-in) - Use connection pooling - Monitor logs for error patterns --- ## ๐Ÿ”’ Security Best Practices ### 1. Secure Credentials - โœ… Never hardcode credentials - โœ… Use environment variables - โœ… Keep .env out of git - โœ… Rotate secrets regularly ### 2. Trade Validation - โœ… Verify user owns items before creating trade - โœ… Check item values match database - โœ… Validate trade URLs - โœ… Prevent duplicate trades ### 3. Rate Limiting - โœ… Limit trades per user per hour - โœ… Limit total trades per minute - โœ… Queue trades during high load ### 4. Monitoring - โœ… Log all trade events - โœ… Alert on failed trades - โœ… Track bot uptime - โœ… Monitor Steam API status --- ## ๐Ÿ“Š Performance Optimization ### Trade Queue System For high volume, implement trade queue: ```javascript // Redis-based queue import Bull from 'bull'; const tradeQueue = new Bull('trades', { redis: { host: 'localhost', port: 6379 } }); tradeQueue.process(async (job) => { const { userId, items } = job.data; return await createTradeOffer(userId, items); }); // Add to queue await tradeQueue.add({ userId, items }, { attempts: 3, backoff: { type: 'exponential', delay: 2000 } }); ``` ### Retry Strategy ```javascript async function createTradeWithRetry(data, maxRetries = 3) { let lastError; for (let i = 0; i < maxRetries; i++) { try { return await bot.createTradeOffer(data); } catch (error) { lastError = error; await sleep(Math.pow(2, i) * 1000); // Exponential backoff } } throw lastError; } ``` --- ## ๐ŸŽฏ Next Steps ### Phase 1: Basic Setup (You are here) - [x] Install packages - [x] Create bot service - [x] Create Trade model - [ ] Configure environment variables - [ ] Test bot login ### Phase 2: Integration - [ ] Update sell endpoint to create trades - [ ] Add trade event handlers - [ ] Credit balance on acceptance - [ ] Add trade status polling ### Phase 3: Frontend - [ ] Show trade status in UI - [ ] Add "View Trade" button - [ ] Show pending trades list - [ ] Add trade notifications ### Phase 4: Admin Tools - [ ] Bot health dashboard - [ ] Trade management panel - [ ] Retry/cancel controls - [ ] Statistics and reports ### Phase 5: Advanced - [ ] Trade queue system - [ ] Multiple bot support - [ ] Automatic retries - [ ] Fraud detection --- ## ๐Ÿ“š Additional Resources - **Steam Web API**: https://developer.valvesoftware.com/wiki/Steam_Web_API - **Trade Offer Manager**: https://github.com/DoctorMcKay/node-steam-tradeoffer-manager - **Steam User**: https://github.com/DoctorMcKay/node-steam-user - **Steam TOTP**: https://github.com/DoctorMcKay/node-steam-totp --- ## โœ… Configuration Checklist Before going live: - [ ] Bot account created and funded ($5+ spent) - [ ] Steam Mobile Authenticator enabled - [ ] Shared secret and identity secret extracted - [ ] API key obtained from Steam - [ ] Environment variables configured - [ ] Bot successfully logs in - [ ] Test trade offer sent and accepted - [ ] Trade events properly handled - [ ] Balance credits on acceptance - [ ] Error handling tested - [ ] Monitoring set up - [ ] Backup credentials stored securely --- **Status**: Implementation Ready **Next**: Configure bot credentials and test login **Priority**: High - Required for production sell functionality