Skip to main content

steam_user/types/
trade.rs

1//! Trade-related types.
2
3use serde::{Deserialize, Serialize};
4use steamid::SteamID;
5
6/// A Steam trade offer.
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct TradeOffer {
9    /// Unique identifier for the trade offer.
10    pub tradeofferid: u64,
11    /// Trading partner information.
12    pub partner: TradeOfferPartner,
13    /// Whether the trade offer is currently active.
14    pub active: bool,
15    /// Items from the primary perspective (usually the current user).
16    pub primary: TradeOfferItems,
17    /// Items from the secondary perspective (the partner).
18    pub secondary: TradeOfferItems,
19    /// Status banner text (e.g., "Items Now Unavailable For Trade", "Trade
20    /// Accepted 8 Mar, 2026 @ 3:46am").
21    #[serde(default)]
22    pub banner_text: String,
23    /// Unix timestamp parsed from banner_text (if it contains a date), in UTC
24    /// seconds.
25    #[serde(default)]
26    pub banner_timestamp: Option<i64>,
27    /// Status derived from banner (e.g., "accepted", "unavailable", "active").
28    #[serde(default)]
29    pub status: TradeOfferStatus,
30}
31
32/// Status of a trade offer, derived from the HTML banner class and text.
33#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
34#[non_exhaustive]
35pub enum TradeOfferStatus {
36    /// Trade is active and can be accepted/declined.
37    #[default]
38    Active,
39    /// Trade was accepted.
40    Accepted,
41    /// Trade expired or items are no longer available.
42    Unavailable,
43    /// Trade was countered.
44    Countered,
45    /// Other/unknown inactive state.
46    Inactive,
47}
48
49/// Trading partner details in a trade offer.
50#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct TradeOfferPartner {
52    /// Partner's SteamID. `None` if the offer HTML did not expose a parseable
53    /// SteamID (rare — Steam embeds it in `ReportTradeScam(steamid, ...)`).
54    #[serde(default)]
55    pub steamid: Option<SteamID>,
56    /// Display name.
57    pub name: String,
58    /// Avatar hash.
59    pub avatar_hash: String,
60    /// Profile link.
61    pub link: String,
62    /// Header text (e.g., "You have a trade offer from...").
63    pub header: String,
64}
65
66/// Container for assets belonging to one side of a trade.
67#[derive(Debug, Clone, Serialize, Deserialize)]
68pub struct TradeOfferItems {
69    /// SteamID of the owner of these items. `None` if the `data-miniprofile`
70    /// attribute was missing or unparseable.
71    #[serde(default)]
72    pub steamid: Option<SteamID>,
73    /// List of items in this side of the trade.
74    pub items: Vec<TradeOfferItem>,
75}
76
77/// A single item within a trade offer summary.
78#[derive(Debug, Clone, Serialize, Deserialize)]
79pub struct TradeOfferItem {
80    /// Economy item string (e.g., "classinfo/730/310777338/302028390").
81    pub economy_item: String,
82    /// Image URL (standard resolution).
83    pub img: String,
84    /// High-resolution image URL (2x), if available from srcset.
85    #[serde(default)]
86    pub img_hi: String,
87    /// Whether this item is marked as missing/unavailable in the trade.
88    #[serde(default)]
89    pub missing: bool,
90}
91
92/// Response containing trade offers summary and active offers.
93#[derive(Debug, Clone, Serialize, Deserialize)]
94pub struct TradeOffersResponse {
95    /// Summary of incoming offers.
96    pub incoming_offers: TradeOfferSummary,
97    /// Summary of sent offers.
98    pub sent_offers: TradeOfferSummary,
99    /// Number of trades on hold.
100    pub trade_hold_count: u32,
101    /// List of parsed trade offer details.
102    pub trade_offers: Vec<TradeOffer>,
103}
104
105/// Summary information for a category of trade offers.
106#[derive(Debug, Clone, Serialize, Deserialize)]
107pub struct TradeOfferSummary {
108    /// URL to view these offers.
109    pub link: String,
110    /// Count of offers in this category.
111    pub count: u32,
112}
113
114/// An asset being offered or requested in a new trade offer.
115#[derive(Debug, Clone, Serialize, Deserialize)]
116pub struct TradeOfferAsset {
117    /// App ID of the item.
118    pub appid: u32,
119    /// Context ID of the item.
120    pub contextid: String,
121    /// Amount (usually 1).
122    pub amount: u32,
123    /// Asset ID.
124    pub assetid: String,
125}
126
127/// Result of sending a trade offer.
128#[derive(Debug, Clone, Serialize, Deserialize)]
129pub struct TradeOfferResult {
130    /// The ID of the created trade offer.
131    pub tradeofferid: String,
132    /// Whether mobile confirmation is required.
133    pub needs_mobile_confirmation: bool,
134    /// Whether email confirmation is required.
135    pub needs_email_confirmation: bool,
136    /// Domain of the confirmation email, if applicable.
137    pub email_domain: Option<String>,
138}
139
140/// Information extracted from a trade offer URL.
141#[derive(Debug, Clone, Serialize, Deserialize)]
142pub struct ParsedTradeURL {
143    /// Account ID (32-bit).
144    pub account_id: String,
145    /// SteamID (64-bit).
146    pub steam_id: SteamID,
147    /// Trade access token.
148    pub token: Option<String>,
149}
150
151/// Cursor for paginating inventory history.
152#[derive(Debug, Clone, Serialize, Deserialize)]
153pub struct InventoryCursor {
154    pub time: u64,
155    pub time_frac: u32,
156    pub s: u32,
157}
158
159impl Default for InventoryCursor {
160    fn default() -> Self {
161        use std::time::{SystemTime, UNIX_EPOCH};
162        let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or_default().as_secs();
163
164        Self { time: now, time_frac: 0, s: 0 }
165    }
166}
167
168/// A row in the inventory history.
169#[derive(Debug, Clone, Serialize, Deserialize)]
170pub struct InventoryHistoryItem {
171    pub id: String,
172    pub timestamp: u64,
173    pub timestamp_str: String,
174    pub description: String,
175    pub plusminus: String,
176    pub trade_history_items: Vec<serde_json::Value>,
177    /// SteamID of the account whose history this row belongs to (i.e. the
178    /// logged-in user). `None` only if there is no active session.
179    #[serde(default)]
180    pub steamid: Option<SteamID>,
181    pub trade_people: Option<TradePeople>,
182}
183
184/// Trading partner in inventory history.
185#[derive(Debug, Clone, Serialize, Deserialize)]
186pub struct TradePeople {
187    pub name: String,
188    pub url: String,
189}
190
191/// Result of fetching inventory history.
192#[derive(Debug, Clone, Serialize, Deserialize)]
193pub struct InventoryHistoryResult {
194    pub cursor: Option<InventoryCursor>,
195    pub trade_history: Vec<InventoryHistoryItem>,
196}