Zum Hauptinhalt springen

Inventar-, Inspect- und Marketplace-Strategie

Diese Seite hält die aktuelle Produkt- und Architekturentscheidung rund um SkinItem, UserInventory, Sticker, inspectLink und spätere Renderbilder fest.

Grundprinzip

  • SkinItem ist die kanonische Marktdefinition eines Skins.
  • UserInventory repräsentiert die konkrete Item-Instanz eines Users oder Bots.
  • Detaillierte CS2-Itemdaten wie float, paint seed, Sticker-Slots, Sticker-Wear, StatTrak-Counter und gerenderte Bilder sind instanzbezogen und gehören deshalb nicht auf SkinItem, sondern an die konkrete Item-Instanz.

Das bedeutet:

  • inspectLink ist instanzbezogen und liegt auf UserInventory, nicht auf SkinItem.
  • Sticker liegen instanzbezogen auf UserInventorySticker, nicht auf SkinItem.
  • SkinItem bleibt trotzdem wichtig als Markt- und Preis-Referenz sowie für kanonische Namen.

Was das öffentliche Steam-Inventar liefert

Der normale Sync über https://steamcommunity.com/inventory/{steamId}/730/2?... liefert aktuell zuverlässig:

  • Basisdaten wie assetId, classId, Name, Waffe, Skin, Zustand, Bild
  • StatTrak-Grundinformationen aus den Beschreibungen
  • Sticker-Namen und Sticker-Icons aus dem sticker_info-HTML-Block

Der öffentliche Feed liefert aktuell nicht verlässlich:

  • einen vollständigen echten inspectLink
  • Sticker-Positionen auf dem Waffenmodell
  • Sticker-Wear / Scrape
  • Sticker-Rotation / Offsets / Scale
  • ein korrektes gerendertes Instanzbild der Waffe

Der Parser für echte Inspect-Links ist implementiert und funktioniert für vollständige Links aus actions oder market_actions.

Der öffentliche Steam-Inventory-Feed liefert in unserem Fall aber häufig nur Platzhalter wie %propid:6% statt eines direkt nutzbaren S...A...D... oder M...A...D...-Links. Dasselbe Verhalten wurde auch an echten Bot-Assets im Steam-Inventar beobachtet.

Das reine Parsen ist also gelöst; die eigentliche Beschaffung eines vollständigen Inspect-Links braucht zusätzlich einen Auflösungsschritt.

Warum Detaildaten nicht am SkinItem liegen

SkinItem beschreibt nur den allgemeinen Marktgegenstand, zum Beispiel:

  • AK-47 | Redline (Field-Tested)
  • Sticker | Crown (Foil)

Zwei konkrete Instanzen desselben SkinItem können sich stark unterscheiden:

  • andere float-Werte
  • anderer paint seed
  • andere Sticker
  • andere Sticker-Wear
  • anderer StatTrak-Zähler
  • anderes gerendertes Bild

Deshalb gilt:

  • Preis-Referenzen für Sticker oder Skins dürfen weiter über SkinItem laufen.
  • Alle echten Instanzdetails müssen an UserInventory beziehungsweise an instanzbezogenen Child-Tabellen hängen.

Redundanz-Entscheidung

Aktueller Zielzustand:

  • SkinItem bleibt die kanonische Quelle für Name, Spiel, Waffe, Skinname und allgemeine Marktreferenz.
  • UserInventory behält vor allem instanzbezogene und operativ nötige Felder.
  • estimatedValue darf vorerst auf UserInventory als Cache bleiben, weil es für Sortierung und schnelle API-Responses nützlich ist.
  • SkinItem soll pro (game, name) eindeutig sein, damit keine Dubletten entstehen.

Pragmatische Regel:

  • Redundanzen für reine Bequemlichkeit sollen mittelfristig reduziert werden.
  • Redundanzen mit klarer Performance- oder API-Caching-Funktion sind akzeptabel.

Public inventory view vs. authoritative marketplace item state

Der Marktplatz braucht deutlich präzisere Daten als die normale Inventaransicht.

Deshalb trennen wir fachlich zwei Stufen:

  • Public inventory view
  • Authoritative marketplace item state

Public inventory view:

  • basiert auf dem öffentlichen Steam-Inventar
  • zeigt Basisdaten, Sticker-Icons, Sticker-Namen und StatTrak-Basiswerte
  • muss nicht für jedes Item perfekte Inspect-Daten haben
  • löst kein Inspect-Enrichment aus
  • startet keine Headless-Chrome- oder Puppeteer-Session

Authoritative marketplace item state:

  • entsteht erst dann, wenn das Item im bot-kontrollierten Flow angekommen ist
  • ist die Grundlage für Marketplace-Detailansicht, korrekte Sticker-Metadaten und korrekte Renderbilder

Der aktuelle Zielpfad:

  • Für die normale Inventaransicht reichen öffentliche Basisdaten.
  • Sobald ein Item für den Marktplatz relevant wird und beim Bot liegt, wird ein autoritatives Inspect-Enrichment angestoßen.
  • Ab dann werden die detaillierten Daten persistiert und für Marketplace, Chat und spätere Auslieferung wiederverwendet.

Das autoritative Inspect-Enrichment gehört zum bot-kontrollierten Marktplatzpfad, nicht zum normalen User-Inventar-Sync. Der Headless-Fallback zur Inspect-Link-Auflösung darf nur im Bot-/Marketplace-Kontext laufen, in dem ein konkretes Bot-Asset geprüft wird.

Persistenz

Auch wenn die Daten an der konkreten Item-Instanz hängen, sollten sie gespeichert werden, sobald sie einmal verifiziert vorliegen.

Gründe:

  • weniger Abhängigkeit von Steam- oder GC-Calls
  • schnellere Seiten- und API-Antworten
  • stabile Marketplace-Darstellung
  • konsistente Detaildaten für Listing, Trade und Historie
  • kein wiederholtes Erraten derselben Instanzdaten

Persistenz bedeutet hier nicht, die Daten auf SkinItem zu verschieben. Persistenz bedeutet, die Daten an der konkreten Instanz oder an einem instanzbezogenen Snapshot zu speichern.

Autoritative Daten nach Bot-Eingang

Sobald ein Item beim Bot angekommen ist, soll der Enrichment-Pfad nach Möglichkeit mindestens diese Daten materialisieren:

  • vollständiger inspectLink
  • floatValue
  • paintSeed
  • paintIndex
  • minFloatValue
  • maxFloatValue
  • Sticker-Slots inklusive Name, Position und Wear
  • StatTrak-Zähler, sofern vorhanden
  • inspectImageUrl und später ein finales gerendertes Marktplatzbild

Diese Daten werden anschließend für die Marktplatzdarstellung bevorzugt verwendet.

Aktueller Implementierungsstand

  • Ein Listing wird nach einem akzeptierten seller -> bot-Offer erst dann auf active gesetzt, wenn der eingeloggte Bot das konkrete Asset in seinem eigenen Inventar sieht.
  • Bot-Inventar sichtbar bedeutet nicht öffentlich über das Steam-Profil sichtbar, sondern sichtbar für die authentifizierte Bot-Session via eigenem Steam-Inventarzugriff.
  • Steam-Exchange-Details aus dem angenommenen Offer werden nur als Hinweis verwendet.
  • Exchange-Details dürfen nicht als autoritative Quelle für finale botAssetId, botContextId, assetId, steamClassId, steamInstanceId oder steamContextId persistiert werden.
  • Wenn die Bot-Inventarkopie noch nicht sichtbar ist, bleibt das Listing im Retry-Pfad und wird nicht mit Exchange-Details als aktives Marketplace-Listing materialisiert.
  • Erst nach erfolgreichem Bot-Inventar-Match werden botAssetId und botContextId auf dem Listing gespeichert; danach darf der autoritative Inspect-Capture starten.
  • Wenn ein Listing nach erfolgreichem seller -> bot-Transfer auf active gesetzt wird, versucht das Backend zuerst direkt am konkreten Bot-Asset den echten Inspect-Link aus actions oder market_actions zu lesen.
  • Falls dort weiterhin nur %propid:6% vorliegt, nutzt das Backend einen Headless-Browser-Fallback mit der vorhandenen Bot-Websession, um den Link im echten Steam-Seitenkontext aufzulösen.
  • Ein erfolgreich aufgelöster Link wird getrennt als authoritativeInspectLink auf UserInventory gespeichert.
  • Das Inspect-Enrichment bevorzugt authoritativeInspectLink gegenüber dem normalen inspectLink.
  • Der Marketplace verwendet in der Kartenübersicht weiterhin bewusst nur das normale Basisbild (imageUrl) des Items, auch wenn das Item bereits autoritativ angereichert wurde.
  • Sobald ein inspectLink vorhanden ist, erscheint im Marketplace ein Lupen-Button Im Spiel untersuchen. Dieser öffnet direkt den steam://-Inspect-Link in CS2 und ist bewusst früher sichtbar als spätere Renderbilder.
  • Echte Detailrender für Vorder- und Rückseite sind getrennt modelliert. Sie werden auf UserInventory separat als Front-/Back-Assets persistiert und nicht mit dem normalen Kartenbild vermischt.
  • Persistierte Renderbilder werden lokal unter ./storage/inspect-renders gespeichert, über Docker als Volume an das Backend gemountet und unter /api/media/... ausgeliefert.
  • Der Kamera-Button im Marketplace erscheint erst dann, wenn mindestens ein persistiertes Detailrenderbild vorliegt.
  • Beim späteren Transfer zum Buyer wird der autoritative Link mit auf die übergehende Instanz übernommen.
  • Solange noch kein autoritativer Link vorliegt, fällt die Darstellung weiterhin auf die öffentlichen Basisdaten zurück.
  • Der Lupen-Button ist bereits ein vollwertiger Produktpfad und nicht von einem späteren Render-Provider abhängig.

Aktueller Teststand

  • Das rohe Bot-Inventar liefert derzeit weiterhin nur %propid:6%.
  • Der Headless-Pfad kann die Steam-Inventarseite mit echter Bot-Websession laden und das aktive Inventar im Seitenkontext erreichen.
  • Der finale Inspect-Link wird im bot-authentifizierten DOM als self-encoded steam://...csgo_econ_action_preview D...-Link gerendert und kann dort zuverlässig extrahiert werden.
  • Für CS2 ist wichtig: Der normale Bot-Inventarlookup kann weiterhin auf contextId = 2 laufen, während die funktionierende private Steam-Inventarseite für den DOM-Link im Browserkontext häufig über #730_16_<assetId> aufgelöst werden muss.
  • Der Browser-Extractor versucht deshalb autoritativ beide Kontexte: 2 und 16.
  • Der normale autoritative Capture-Flow für aktive Bot-Listings ist verifiziert: authoritativeInspectLink, floatValue, paintIndex, paintSeed und inspectEnrichmentStatus = fresh werden automatisch auf UserInventory persistiert.
  • Der Render-Persistenzpfad steht ebenfalls.
  • Wenn ein Inspect-/Render-Provider Bild-URLs liefert, werden Front-/Back-Bilder lokal gespeichert und als getrennte Render-Assets auf UserInventory materialisiert.
  • Ohne konfigurierten Render-Producer gibt es derzeit noch keine echten Front-/Back-Bilder. In diesem Zustand ist bereits die Lupe verfügbar, aber noch kein Kamera-Button.
  • Die Auswahl eines externen Render-Providers ist bewusst vertagt.
  • Der bestehende Codepfad bleibt darauf vorbereitet, aber die aktuelle Produktentscheidung lautet: erst den verifizierten Inspect-Link und die In-Game-Lupe nutzen, spätere Detailrender erst mit einem sauber evaluierten Producer anbinden.

Konsequenz für weitere Umsetzung

Die nächsten Implementierungsschritte sollen sich nicht darauf fokussieren, für jedes beliebige öffentliche User-Inventar perfekte Inspect-Daten zu erzwingen.

Stattdessen gilt:

  • Das öffentliche Inventar bleibt die Quelle für die allgemeine Inventaransicht.
  • Der bot-kontrollierte Pfad wird zur autoritativen Quelle für Marketplace-Details.
  • Der Fokus liegt auf sauberem Enrichment nach Bot-Eingang.
  • Browser-Automation ist inzwischen ein bewusst eingebauter Fallback im bot-kontrollierten Pfad.

Konkrete Teststrategie

Um den Flow verlässlich zu prüfen, ist ein echter End-to-End-Fall mit einem Bot-gehaltenen Item entscheidend.

Sinnvolle Reihenfolge:

  • Listing erstellen und seller -> bot erfolgreich abschließen
  • prüfen, ob das Bot-Asset im Inventar des zugewiesenen Bots sichtbar ist
  • am konkreten Bot-Asset zuerst den rohen Inventar-Link prüfen
  • falls dort nur %propid:6% vorliegt, den Headless-Auflösungspfad mit derselben Bot-Websession verwenden
  • bei Erfolg: authoritativeInspectLink speichern und Enrichment auf derselben Item-Instanz forcieren
  • danach prüfen, ob float, paint seed, Sticker-Wear/Positionen und bevorzugte Bilder im Marketplace erscheinen

Wichtige Interpretation:

  • Wenn das rohe Bot-Asset keinen echten Inspect-Link liefert, ist das aktuell der erwartete Steam-Zustand.
  • Wenn der Browser-Fallback den Link erfolgreich auflöst, ist das der gewünschte Pfad für autoritative Marketplace-Daten.
  • Wenn auch der Browser-Fallback keinen echten Link liefert, bleibt die Datenquelle der Engpass und der Marktplatz fällt weiter auf Basisdaten zurück.