Trading System
Titan implements secure peer-to-peer trading with real-time updates and atomic item swaps.
Trade Flow
Trade States
TradeSession Structure
interface TradeSession {
tradeId: string;
status: TradeStatus; // Pending, Completed, Cancelled, Expired
initiatorCharacterId: string;
targetCharacterId: string;
seasonId: string;
initiatorItems: string[]; // Item IDs offered by initiator
targetItems: string[]; // Item IDs offered by target
initiatorAccepted: boolean;
targetAccepted: boolean;
createdAt: string;
expiresAt: string;
}
Trade Rules
Trades are validated against a rule engine before execution:
| Rule | Description | Error |
|---|---|---|
SameSeasonRule | Characters must be in the same season | "Cannot trade across seasons" |
SoloSelfFoundRule | SSF characters cannot trade | "SSF characters cannot trade" |
Starting a Trade
// Player 1 initiates trade with Player 2
const session = await connection.invoke(
"StartTrade",
myCharacterId,
targetCharacterId,
"season-1"
);
// Join the trade group for updates
await connection.invoke("JoinTradeSession", session.tradeId);
Adding/Removing Items
// Add item to your offer
await connection.invoke("AddItem", tradeId, itemId);
// Remove item from your offer
await connection.invoke("RemoveItem", tradeId, itemId);
Items are validated:
- Must belong to your character's inventory
- Cannot be equipped (must be in bag)
- Cannot already be in another active trade
Accepting the Trade
// Accept current offer
const result = await connection.invoke("AcceptTrade", tradeId);
if (result.completed) {
console.log("Trade completed! Items swapped.");
} else {
console.log("Waiting for other party to accept...");
}
Acceptance is reset when items change - both parties must re-accept.
Cancelling
await connection.invoke("CancelTrade", tradeId);
// Both parties receive TradeCancelled event
Real-Time Events
Subscribe to trade updates:
connection.on("TradeUpdate", (update) => {
switch (update.eventType) {
case "TradeStarted":
showTradeWindow(update.data);
break;
case "ItemAdded":
addItemToDisplay(update.data.characterId, update.data.itemId);
break;
case "ItemRemoved":
removeItemFromDisplay(update.data.characterId, update.data.itemId);
break;
case "TradeAccepted":
markPartyAccepted(update.data.characterId);
break;
case "TradeCompleted":
refreshInventory();
closeTradeWindow();
break;
case "TradeCancelled":
showMessage("Trade cancelled");
closeTradeWindow();
break;
}
});
Atomic Execution
When both parties accept, items are swapped atomically:
- Remove items from initiator's inventory
- Remove items from target's inventory
- Add target's items to initiator's inventory
- Add initiator's items to target's inventory
- Record trade history for all items
If any step fails, the entire transaction rolls back.
Security
- Ownership verification: Can only trade items you own
- Character verification: Can only act as characters you own
- Expiration: Trades timeout after 5 minutes
- Single trade: Items can only be in one active trade