added steambot, trades and trasctions.
This commit is contained in:
445
TRADE_WORKFLOW.md
Normal file
445
TRADE_WORKFLOW.md
Normal file
@@ -0,0 +1,445 @@
|
||||
# TurboTrades - Steam Trade Workflow Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
This document explains the complete workflow for selling items through Steam trade offers with real-time WebSocket updates and verification codes.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
User (Frontend) <--WebSocket--> Backend <--> Steam Bot Manager <--> Steam API
|
||||
|
|
||||
v
|
||||
Database
|
||||
(Trades, Users, Transactions)
|
||||
```
|
||||
|
||||
## Complete Trade Flow
|
||||
|
||||
### 1. User Initiates Sale (Frontend)
|
||||
|
||||
**File**: `frontend/src/views/SellPage.vue`
|
||||
|
||||
1. User logs in and navigates to `/sell`
|
||||
2. Frontend fetches user's Steam inventory via `/api/inventory/steam`
|
||||
3. Items are displayed with market prices (pre-fetched from database)
|
||||
4. User selects items to sell
|
||||
5. User clicks "Sell Selected Items"
|
||||
6. Frontend makes POST request to `/api/inventory/sell` with:
|
||||
```json
|
||||
{
|
||||
"tradeUrl": "user's Steam trade URL",
|
||||
"items": [
|
||||
{
|
||||
"assetid": "123456789",
|
||||
"appid": 730,
|
||||
"contextid": "2",
|
||||
"name": "AK-47 | Redline (Field-Tested)",
|
||||
"price": 25.50,
|
||||
"image": "url",
|
||||
"wear": "ft",
|
||||
"rarity": "classified"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Backend Creates Trade Offer
|
||||
|
||||
**File**: `routes/inventory.js` - POST `/api/inventory/sell`
|
||||
|
||||
1. Validates user authentication and trade URL
|
||||
2. Calculates total value of items
|
||||
3. Calls `botManager.createTradeOffer()` with:
|
||||
- User's trade URL
|
||||
- Items to receive (assetid, appid, contextid)
|
||||
- User ID (for WebSocket notifications)
|
||||
4. Bot manager selects best available bot (least busy)
|
||||
5. Bot manager generates 6-character verification code
|
||||
6. Bot creates Steam trade offer with verification code in message
|
||||
|
||||
### 3. Trade Offer Created
|
||||
|
||||
**File**: `services/steamBot.js` - `SteamBotInstance.createTradeOffer()`
|
||||
|
||||
1. Bot sends trade offer to Steam
|
||||
2. Bot confirms trade offer with 2FA (identity_secret)
|
||||
3. Trade record saved to database with status: `pending`
|
||||
4. WebSocket notifications sent to user:
|
||||
|
||||
**WebSocket Events Sent**:
|
||||
- `trade_creating` - Trade is being created
|
||||
- `trade_sent` - Trade offer sent to Steam
|
||||
- `trade_confirmed` - Trade confirmed with 2FA
|
||||
- `trade_created` - Complete trade details
|
||||
|
||||
5. Response sent to frontend with:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"trade": {
|
||||
"tradeId": "db_record_id",
|
||||
"offerId": "steam_offer_id",
|
||||
"verificationCode": "A3X9K2",
|
||||
"itemCount": 3,
|
||||
"totalValue": 75.50,
|
||||
"status": "pending",
|
||||
"botId": "bot1"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. User Views Verification Code
|
||||
|
||||
**File**: `frontend/src/views/SellPage.vue`
|
||||
|
||||
1. Toast notification shows verification code (doesn't auto-dismiss)
|
||||
2. User receives WebSocket message with trade details
|
||||
3. User opens Steam client/mobile app
|
||||
4. User sees trade offer from TurboTrades bot
|
||||
|
||||
### 5. User Verifies and Accepts Trade
|
||||
|
||||
**Steam Side**:
|
||||
1. User checks trade offer message for verification code
|
||||
2. User compares code in Steam with code shown on website
|
||||
3. If codes match, user accepts trade
|
||||
4. If codes don't match, user declines (security protection)
|
||||
|
||||
### 6. Bot Detects Trade Acceptance
|
||||
|
||||
**File**: `services/steamBot.js` - `_handleOfferStateChange()`
|
||||
|
||||
When Steam trade state changes to `Accepted` (state 3):
|
||||
|
||||
1. Bot emits `tradeAccepted` event
|
||||
2. Event includes offer details and trade data
|
||||
|
||||
### 7. Backend Processes Completed Trade
|
||||
|
||||
**File**: `index.js` - Trade event listener
|
||||
|
||||
```javascript
|
||||
botManager.on('tradeAccepted', async (offer, tradeData) => {
|
||||
// 1. Find trade record in database
|
||||
// 2. Find user record
|
||||
// 3. Credit user balance with trade value
|
||||
// 4. Update trade status to 'completed'
|
||||
// 5. Create transaction record (type: 'sale')
|
||||
// 6. Send WebSocket notifications
|
||||
});
|
||||
```
|
||||
|
||||
**WebSocket Events Sent**:
|
||||
- `trade_accepted` - Trade was accepted on Steam
|
||||
- `trade_completed` - Balance credited successfully
|
||||
- `balance_update` - User's new balance
|
||||
|
||||
### 8. User Receives Funds
|
||||
|
||||
1. User balance updated in database
|
||||
2. Transaction record created for audit trail
|
||||
3. WebSocket notifications update frontend in real-time
|
||||
4. Toast notification shows credited amount
|
||||
5. User can spend balance on marketplace
|
||||
|
||||
## WebSocket Events Reference
|
||||
|
||||
### Events Sent to User During Trade
|
||||
|
||||
| Event | Trigger | Data |
|
||||
|-------|---------|------|
|
||||
| `trade_creating` | Bot starting to create offer | verificationCode, itemCount, botId |
|
||||
| `trade_sent` | Offer sent to Steam | offerId, verificationCode, status |
|
||||
| `trade_confirmed` | Offer confirmed with 2FA | offerId, verificationCode |
|
||||
| `trade_created` | Complete - offer ready | tradeId, offerId, verificationCode, totalValue |
|
||||
| `trade_accepted` | User accepted on Steam | offerId, verificationCode, itemCount |
|
||||
| `trade_completed` | Balance credited | tradeId, amount, newBalance |
|
||||
| `balance_update` | Balance changed | balance, change, reason |
|
||||
| `trade_declined` | User declined on Steam | offerId, tradeId |
|
||||
| `trade_expired` | Offer expired (15 days) | offerId, tradeId |
|
||||
| `trade_canceled` | User/bot canceled | offerId, tradeId |
|
||||
| `trade_error` | Error occurred | error, verificationCode |
|
||||
|
||||
### WebSocket Message Format
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "trade_completed",
|
||||
"data": {
|
||||
"tradeId": "507f1f77bcf86cd799439011",
|
||||
"offerId": "5847362918",
|
||||
"amount": 75.50,
|
||||
"newBalance": 125.75,
|
||||
"itemCount": 3,
|
||||
"timestamp": 1704067200000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Database Models
|
||||
|
||||
### Trade Model
|
||||
|
||||
**File**: `models/Trade.js`
|
||||
|
||||
```javascript
|
||||
{
|
||||
offerId: String, // Steam trade offer ID
|
||||
botId: String, // Bot that created the offer
|
||||
user: ObjectId, // User reference
|
||||
items: [{ // Items in trade
|
||||
assetid: String,
|
||||
name: String,
|
||||
price: Number,
|
||||
image: String
|
||||
}],
|
||||
totalValue: Number, // Total value of items
|
||||
verificationCode: String, // 6-char code
|
||||
status: String, // pending, completed, declined, expired, cancelled
|
||||
type: String, // sell, buy
|
||||
createdAt: Date,
|
||||
completedAt: Date
|
||||
}
|
||||
```
|
||||
|
||||
### Transaction Model
|
||||
|
||||
**File**: `models/Transaction.js`
|
||||
|
||||
```javascript
|
||||
{
|
||||
user: ObjectId,
|
||||
type: String, // sale, deposit, withdrawal, purchase
|
||||
amount: Number,
|
||||
description: String,
|
||||
status: String, // completed, pending, failed
|
||||
metadata: {
|
||||
tradeId: ObjectId,
|
||||
offerId: String,
|
||||
botId: String,
|
||||
verificationCode: String
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Security Features
|
||||
|
||||
### Verification Codes
|
||||
|
||||
- **Purpose**: Prevent phishing and fake trade offers
|
||||
- **Format**: 6 alphanumeric characters (no ambiguous chars: O, 0, I, l, 1)
|
||||
- **Display**: Shown on website and in Steam trade message
|
||||
- **Validation**: User must verify codes match before accepting
|
||||
|
||||
### Trade URL Privacy
|
||||
|
||||
- Trade URLs stored encrypted in database
|
||||
- Only sent to bot manager, never exposed to frontend
|
||||
- Required for creating trade offers
|
||||
|
||||
### Bot Security
|
||||
|
||||
- Each bot uses separate Steam account
|
||||
- Proxies supported for IP distribution
|
||||
- 2FA required (shared_secret, identity_secret)
|
||||
- Rate limiting on trade creation
|
||||
- Health monitoring and auto-failover
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### POST /api/inventory/sell
|
||||
|
||||
Create a new trade offer to sell items.
|
||||
|
||||
**Request**:
|
||||
```json
|
||||
{
|
||||
"tradeUrl": "https://steamcommunity.com/tradeoffer/new/?partner=XXX&token=YYY",
|
||||
"items": [
|
||||
{
|
||||
"assetid": "123456789",
|
||||
"appid": 730,
|
||||
"contextid": "2",
|
||||
"name": "Item Name",
|
||||
"price": 10.50
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"trade": {
|
||||
"tradeId": "db_id",
|
||||
"offerId": "steam_id",
|
||||
"verificationCode": "A3X9K2",
|
||||
"itemCount": 1,
|
||||
"totalValue": 10.50,
|
||||
"status": "pending"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### GET /api/inventory/trades
|
||||
|
||||
Get user's trade history.
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"trades": [
|
||||
{
|
||||
"_id": "507f1f77bcf86cd799439011",
|
||||
"offerId": "5847362918",
|
||||
"status": "completed",
|
||||
"totalValue": 75.50,
|
||||
"createdAt": "2024-01-01T00:00:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### GET /api/inventory/trade/:tradeId
|
||||
|
||||
Get specific trade details.
|
||||
|
||||
### POST /api/inventory/trade/:tradeId/cancel
|
||||
|
||||
Cancel a pending trade offer.
|
||||
|
||||
## Bot Configuration
|
||||
|
||||
### Config File Format
|
||||
|
||||
**File**: `config/steam-bots.json`
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"username": "turbotrades_bot1",
|
||||
"password": "your_password",
|
||||
"sharedSecret": "your_shared_secret",
|
||||
"identitySecret": "your_identity_secret",
|
||||
"steamApiKey": "your_steam_api_key",
|
||||
"proxy": {
|
||||
"type": "socks5",
|
||||
"host": "proxy.example.com",
|
||||
"port": 1080,
|
||||
"username": "proxy_user",
|
||||
"password": "proxy_pass"
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
|
||||
```bash
|
||||
# Auto-start bots on server startup
|
||||
STEAM_BOT_AUTO_START=true
|
||||
|
||||
# Steam API key for inventory fetching
|
||||
STEAM_APIS_KEY=your_api_key
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Trade Creation Errors
|
||||
|
||||
| Error | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| `No bots available` | All bots offline/busy | Wait or add more bots |
|
||||
| `Trade URL is required` | User hasn't set trade URL | Redirect to profile settings |
|
||||
| `Bot not ready` | Bot not logged in | Check bot status, restart if needed |
|
||||
| `Invalid trade URL` | Malformed URL | User must update trade URL |
|
||||
|
||||
### Trade State Errors
|
||||
|
||||
- **Declined**: User declined offer - notify user, can retry
|
||||
- **Expired**: 15 days passed - notify user, items returned to user
|
||||
- **Canceled**: Bot/user canceled - update status, no funds credited
|
||||
- **Invalid**: Steam error - log error, notify admin
|
||||
|
||||
## Monitoring & Logging
|
||||
|
||||
### Bot Health Checks
|
||||
|
||||
```javascript
|
||||
botManager.getAllBotsHealth();
|
||||
// Returns health status for all bots
|
||||
```
|
||||
|
||||
### Trade Statistics
|
||||
|
||||
```javascript
|
||||
botManager.getStats();
|
||||
// Returns total trades, active trades, errors, etc.
|
||||
```
|
||||
|
||||
### Database Indexes
|
||||
|
||||
- `Trade.offerId` - Fast lookup by Steam offer ID
|
||||
- `Trade.user` + `Trade.status` - User's pending trades
|
||||
- `Transaction.user` + `Transaction.createdAt` - Transaction history
|
||||
|
||||
## Testing
|
||||
|
||||
### Test Sell Flow
|
||||
|
||||
1. Set up test bot with Steam account
|
||||
2. Configure bot credentials in `config/steam-bots.json`
|
||||
3. Start backend with `STEAM_BOT_AUTO_START=true`
|
||||
4. Set trade URL in profile
|
||||
5. Navigate to `/sell` page
|
||||
6. Select items and click sell
|
||||
7. Check verification code matches
|
||||
8. Accept trade in Steam
|
||||
9. Verify balance credited
|
||||
|
||||
### Mock Testing (No Real Trades)
|
||||
|
||||
For development without real Steam bots:
|
||||
- Comment out bot initialization
|
||||
- Create mock trade records directly
|
||||
- Test WebSocket notifications
|
||||
- Test UI with fake verification codes
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Trade Not Creating
|
||||
|
||||
1. Check bot status: `GET /api/admin/bots/health`
|
||||
2. Verify Steam API key is valid
|
||||
3. Check bot login credentials
|
||||
4. Review bot error logs
|
||||
5. Ensure identity_secret is correct
|
||||
|
||||
### Trade Created But Not Accepted
|
||||
|
||||
1. Verify user has mobile authenticator
|
||||
2. Check if items are still tradable
|
||||
3. Verify verification codes match
|
||||
4. Check Steam trade restrictions (7-day holds)
|
||||
|
||||
### Balance Not Credited
|
||||
|
||||
1. Check trade status in database
|
||||
2. Review server logs for `tradeAccepted` event
|
||||
3. Verify transaction was created
|
||||
4. Check for any database errors
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
- [ ] Queue system (Bull/Redis) for high-volume trades
|
||||
- [ ] Trade status page with live updates
|
||||
- [ ] Mobile notifications when trade is ready
|
||||
- [ ] Automatic retry on trade failure
|
||||
- [ ] Multi-region bot distribution
|
||||
- [ ] Trade escrow handling for new devices
|
||||
- [ ] Price history tracking per trade
|
||||
- [ ] CSV export of trade history
|
||||
- [ ] Admin dashboard for trade monitoring
|
||||
Reference in New Issue
Block a user