Zum Hauptinhalt springen

Trades

Trading-Modell

Aktueller Flow:

  • Seller listet ein Item.
  • Seller überträgt das Item zunächst an den Bot.
  • Erst wenn das Item beim Bot liegt, wird das Listing öffentlich sichtbar.
  • Wenn auf dem Bot noch eine Steam-Handelssperre aktiv ist, bleibt das Listing sichtbar und zeigt die verbleibende Verfügbarkeit an.
  • Offer- und Counteroffer-Logik laufen weiter über den Chat.
  • Nach Deal-Akzept sendet der Bot das Item an den Buyer, sobald Steam es erlaubt.

Wichtige Regeln

  • Das Seiteninventar bleibt bis zur echten Übergabe an den Buyer beim Seller sichtbar.
  • Der Steam-Trade-Monitor überwacht Offer-Status, Sperrfristen und weitere Trade-Fortschritte automatisch im Backend-Prozess.
  • Listings und Trades speichern den zugewiesenen botId dauerhaft.
  • Ein bereits laufendes Listing oder ein laufender Trade bleibt an seinem Bot hängen, auch wenn STEAM_DEFAULT_BOT_ID später geändert wird.
  • Ein Listing kann mehrere Trade-Versuche über die Zeit haben.
  • Fehlgeschlagene, rückabgewickelte oder abgebrochene Trades bleiben als Historie erhalten, blockieren aber keinen neuen Kaufversuch auf demselben Listing.
  • Parallelität wird über den Listing-Status und nicht-terminale Trades verhindert.

Bestehende Listings und Trades

Wenn von einem älteren Stand auf Multi-Bot umgestellt wird, sollten bestehende Datensätze botId einmalig nachgepflegt werden.

Beispiel für einen vorhandenen Bot florian_bot:

UPDATE "UserListing"
SET "botId" = 'florian_bot'
WHERE "botId" IS NULL;

UPDATE "Trade" t
SET "botId" = l."botId"
FROM "UserListing" l
WHERE t."listingId" = l."id"
AND t."botId" IS NULL
AND l."botId" IS NOT NULL;

UPDATE "Trade"
SET "botId" = 'florian_bot'
WHERE "botId" IS NULL;

Steam-Trade-Monitor

Der Trade-Monitor startet automatisch zusammen mit dem Backend.

Zusätzlich stößt die Trades-Ansicht (/dashboard/trades) einen gedrosselten Background-Sync für die offenen Steam-Trades des eingeloggten Users an. Solange Käufer oder Verkäufer diese Seite geöffnet haben, werden seller_offer_sent und buyer_offer_sent dadurch deutlich schneller gegen Steam geprüft als nur über den globalen Monitor.

Fehler- und Backoff-Zeiten werden respektiert, damit Steam nicht unnötig belastet wird.

Die Steam-Trade-Verarbeitung ist pro Trade-ID serialisiert. Initialer Dispatch, Monitorlauf und viewer-getriggerter Sync dürfen denselben Trade dadurch nicht parallel an Steam senden.

Listing-Lifecycle-Fehler aus dem Monitor werden nicht nur geloggt, sondern wieder auf dem Listing persistiert. Dabei werden retryCount, lastSteamError, lastCheckedAt und nextCheckAt aktualisiert. So läuft ein fehlerhaftes pending_intake-Listing nicht dauerhaft ohne Backoff in denselben Steam-Fehler.

Bot-Inventar-Abfragen werden pro Bot, App, Context und tradableOnly dedupliziert. Wenn Steam trotzdem eine Duplicate-Antwort bei der Inventarprüfung liefert, wird der Trade nur kurz für eine erneute Inventarprüfung geparkt und nicht fälschlich als Buyer-Offer-Duplicate behandelt.

Beim finalen bot -> buyer-Offer darf das Backend nach einer Duplicate-Antwort der Inventarprüfung mit dem bekannten Bot-Asset fortfahren, wenn botAssetId bereits persistiert ist und keine bekannte Trade-Sperre mehr aktiv ist. Falls das Asset wider Erwarten doch nicht sendbar ist, kommt der Fehler dann aus dem echten Send-Schritt und wird dort normal behandelt.

Duplicate-Recovery beim Buyer-Offer

Beim bot -> buyer-Schritt ist Steam-Duplicate-Recovery eingebaut:

  • Wenn Steam beim Senden meldet, dass dieselbe Aktion bereits in der Vergangenheit passiert ist, sucht das Backend zuerst in der gesendeten Bot-Offer-Historie nach einem passenden Offer.
  • Ein Offer gilt als passend, wenn Partner, Bot-Asset oder Trade-ID zur erwarteten Auszahlung passen und der Offer in einem recoverbaren Status ist: active, accepted, needs_confirmation oder in_escrow.
  • Wird ein passender Offer gefunden, wird die fehlende steamOfferId nachgetragen und der Trade wieder als buyer_offer_sent überwacht.
  • Bevor ein neuer Buyer-Offer gesendet wird, prüft das Backend ebenfalls zuerst die gesendete Bot-Offer-Historie.
  • Jeder neue Buyer-Offer bekommt eine eindeutige Message mit Attempt und Nonce, damit Steam nicht erneut denselben Payload dedupliziert.
  • Wird bei einem Duplicate kein passender Offer gefunden, bleibt der Trade kurz im Retry-Pfad und versucht es danach wieder mit einer neuen eindeutigen Message.

Diese Recovery ist für Fälle gedacht, in denen Steam einen Send-Versuch als Duplicate behandelt, obwohl in der Datenbank noch keine steamOfferId persistiert wurde.