From 9b5f4af4129354238624f0c62850abcf318a1e12 Mon Sep 17 00:00:00 2001 From: Step7750 Date: Tue, 9 Sep 2025 15:57:40 -0600 Subject: [PATCH 1/3] Prevents Sending Redundant Trade Pings as Seller Re-affirming the state of a trade offer or trade history as a seller doesn't provide value server-side. Will extend to buyers as well in the future, but it requires a couple server-side changes in the works. --- src/lib/alarms/csfloat_trade_pings.ts | 8 ++++---- src/lib/alarms/trade_history.ts | 25 ++++++++++++++++++------- src/lib/alarms/trade_offer.ts | 21 +++++++++++++++++---- 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/lib/alarms/csfloat_trade_pings.ts b/src/lib/alarms/csfloat_trade_pings.ts index 0abae72..84855d7 100644 --- a/src/lib/alarms/csfloat_trade_pings.ts +++ b/src/lib/alarms/csfloat_trade_pings.ts @@ -49,7 +49,7 @@ export async function pingTradeStatus(expectedSteamID?: string) { let errors; if (pendingTrades.length > 0) { - errors = await pingUpdates(pendingTrades); + errors = await pingUpdates(pendingTrades, access?.steam_id); } // Ping status of ext + permissions @@ -75,7 +75,7 @@ interface UpdateErrors { rollback_trades_error?: string; } -async function pingUpdates(pendingTrades: SlimTrade[]): Promise { +async function pingUpdates(pendingTrades: SlimTrade[], steamID?: string|null): Promise { const errors: UpdateErrors = {}; try { @@ -93,14 +93,14 @@ async function pingUpdates(pendingTrades: SlimTrade[]): Promise { let tradeHistory: TradeHistoryStatus[] = []; try { - tradeHistory = await pingTradeHistory(pendingTrades); + tradeHistory = await pingTradeHistory(pendingTrades, steamID); } catch (e) { console.error('failed to ping trade history', e); errors.history_error = (e as any).toString(); } try { - await pingSentTradeOffers(pendingTrades); + await pingSentTradeOffers(pendingTrades, steamID); } catch (e) { console.error('failed to ping sent trade offer state', e); errors.trade_offer_error = (e as any).toString(); diff --git a/src/lib/alarms/trade_history.ts b/src/lib/alarms/trade_history.ts index c4fde65..2cb0b72 100644 --- a/src/lib/alarms/trade_history.ts +++ b/src/lib/alarms/trade_history.ts @@ -1,27 +1,38 @@ -import {SlimTrade, Trade} from '../types/float_market'; +import {SlimTrade} from '../types/float_market'; import {TradeHistoryStatus, TradeHistoryType} from '../bridge/handlers/trade_history_status'; -import {AppId, TradeStatus} from '../types/steam_constants'; +import {AppId, TradeOfferState, TradeStatus} from '../types/steam_constants'; import {clearAccessTokenFromStorage, getAccessToken} from './access_token'; -export async function pingTradeHistory(pendingTrades: SlimTrade[]): Promise { +export async function pingTradeHistory(pendingTrades: SlimTrade[], steamID?: string|null): Promise { const {history, type} = await getTradeHistory(); // premature optimization in case it's 100 trades const assetsToFind = pendingTrades.reduce( (acc, e) => { - acc[e.contract.item.asset_id] = true; + acc[e.contract.item.asset_id] = e; return acc; }, - {} as {[key: string]: boolean} + {} as {[key: string]: SlimTrade} ); // We only want to send history that is relevant to verifying trades on CSFloat const historyForCSFloat = history.filter((e) => { const received_ids = e.received_assets.map((e) => e.asset_id); const given_ids = e.given_assets.map((e) => e.asset_id); - return !![...received_ids, ...given_ids].find((e) => { + + const foundSlimTrades = [...received_ids, ...given_ids].map((e) => { return assetsToFind[e]; - }); + }).filter(e => !!e); + if (!foundSlimTrades || foundSlimTrades.length === 0) { + return false; + } + + // Have we already reported this status as a seller? If so, we can skip doing it again + if (foundSlimTrades.every((t) => t.steam_offer?.state === TradeOfferState.Accepted && t.seller_id === steamID)) { + return false; + } + + return true; }); if (historyForCSFloat.length === 0) { diff --git a/src/lib/alarms/trade_offer.ts b/src/lib/alarms/trade_offer.ts index 07655a9..05b74f0 100644 --- a/src/lib/alarms/trade_offer.ts +++ b/src/lib/alarms/trade_offer.ts @@ -11,20 +11,33 @@ import {HasPermissions} from '../bridge/handlers/has_permissions'; import {convertSteamID32To64} from '../utils/userinfo'; import {TradeHistoryStatus} from '../bridge/handlers/trade_history_status'; -export async function pingSentTradeOffers(pendingTrades: SlimTrade[]) { +export async function pingSentTradeOffers(pendingTrades: SlimTrade[], steamID?: string|null) { const {offers, type} = await getSentTradeOffers(); const offersToFind = pendingTrades.reduce( (acc, e) => { - acc[e.steam_offer.id] = true; + if (!acc[e.steam_offer.id]) { + acc[e.steam_offer.id] = []; + } + acc[e.steam_offer.id].push(e); return acc; }, - {} as {[key: string]: boolean} + {} as {[key: string]: SlimTrade[]} ); // We only want to send offers that are relevant to verifying trades on CSFloat const offersForCSFloat = offers.filter((e) => { - return !!offersToFind[e.offer_id]; + const slimTrades = offersToFind[e.offer_id]; + if (!slimTrades || slimTrades.length === 0) { + return false; + } + + if (slimTrades.every(t => t.steam_offer?.state === e.state && t.seller_id === steamID)) { + // We're pushing the same trade offer state update as a seller, this has no effect server-side, skip + return false; + } + + return true; }); if (offersForCSFloat.length > 0) { From 89a6a1050a57df924a60d1422faf86356f844f4f Mon Sep 17 00:00:00 2001 From: Step7750 Date: Tue, 9 Sep 2025 16:13:37 -0600 Subject: [PATCH 2/3] prettier --- src/lib/alarms/csfloat_trade_pings.ts | 2 +- src/lib/alarms/trade_history.ts | 17 ++++++++++++----- src/lib/alarms/trade_offer.ts | 4 ++-- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/lib/alarms/csfloat_trade_pings.ts b/src/lib/alarms/csfloat_trade_pings.ts index 84855d7..dce2597 100644 --- a/src/lib/alarms/csfloat_trade_pings.ts +++ b/src/lib/alarms/csfloat_trade_pings.ts @@ -75,7 +75,7 @@ interface UpdateErrors { rollback_trades_error?: string; } -async function pingUpdates(pendingTrades: SlimTrade[], steamID?: string|null): Promise { +async function pingUpdates(pendingTrades: SlimTrade[], steamID?: string | null): Promise { const errors: UpdateErrors = {}; try { diff --git a/src/lib/alarms/trade_history.ts b/src/lib/alarms/trade_history.ts index 2cb0b72..5dcfade 100644 --- a/src/lib/alarms/trade_history.ts +++ b/src/lib/alarms/trade_history.ts @@ -3,7 +3,10 @@ import {TradeHistoryStatus, TradeHistoryType} from '../bridge/handlers/trade_his import {AppId, TradeOfferState, TradeStatus} from '../types/steam_constants'; import {clearAccessTokenFromStorage, getAccessToken} from './access_token'; -export async function pingTradeHistory(pendingTrades: SlimTrade[], steamID?: string|null): Promise { +export async function pingTradeHistory( + pendingTrades: SlimTrade[], + steamID?: string | null +): Promise { const {history, type} = await getTradeHistory(); // premature optimization in case it's 100 trades @@ -20,15 +23,19 @@ export async function pingTradeHistory(pendingTrades: SlimTrade[], steamID?: str const received_ids = e.received_assets.map((e) => e.asset_id); const given_ids = e.given_assets.map((e) => e.asset_id); - const foundSlimTrades = [...received_ids, ...given_ids].map((e) => { - return assetsToFind[e]; - }).filter(e => !!e); + const foundSlimTrades = [...received_ids, ...given_ids] + .map((e) => { + return assetsToFind[e]; + }) + .filter((e) => !!e); if (!foundSlimTrades || foundSlimTrades.length === 0) { return false; } // Have we already reported this status as a seller? If so, we can skip doing it again - if (foundSlimTrades.every((t) => t.steam_offer?.state === TradeOfferState.Accepted && t.seller_id === steamID)) { + if ( + foundSlimTrades.every((t) => t.steam_offer?.state === TradeOfferState.Accepted && t.seller_id === steamID) + ) { return false; } diff --git a/src/lib/alarms/trade_offer.ts b/src/lib/alarms/trade_offer.ts index 05b74f0..b51b10d 100644 --- a/src/lib/alarms/trade_offer.ts +++ b/src/lib/alarms/trade_offer.ts @@ -11,7 +11,7 @@ import {HasPermissions} from '../bridge/handlers/has_permissions'; import {convertSteamID32To64} from '../utils/userinfo'; import {TradeHistoryStatus} from '../bridge/handlers/trade_history_status'; -export async function pingSentTradeOffers(pendingTrades: SlimTrade[], steamID?: string|null) { +export async function pingSentTradeOffers(pendingTrades: SlimTrade[], steamID?: string | null) { const {offers, type} = await getSentTradeOffers(); const offersToFind = pendingTrades.reduce( @@ -32,7 +32,7 @@ export async function pingSentTradeOffers(pendingTrades: SlimTrade[], steamID?: return false; } - if (slimTrades.every(t => t.steam_offer?.state === e.state && t.seller_id === steamID)) { + if (slimTrades.every((t) => t.steam_offer?.state === e.state && t.seller_id === steamID)) { // We're pushing the same trade offer state update as a seller, this has no effect server-side, skip return false; } From b844681835e2be0e3f31c7b5f1658ed174f28b78 Mon Sep 17 00:00:00 2001 From: Step7750 Date: Tue, 9 Sep 2025 17:27:24 -0600 Subject: [PATCH 3/3] address comment --- src/lib/alarms/trade_history.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/lib/alarms/trade_history.ts b/src/lib/alarms/trade_history.ts index 5dcfade..40613df 100644 --- a/src/lib/alarms/trade_history.ts +++ b/src/lib/alarms/trade_history.ts @@ -23,11 +23,7 @@ export async function pingTradeHistory( const received_ids = e.received_assets.map((e) => e.asset_id); const given_ids = e.given_assets.map((e) => e.asset_id); - const foundSlimTrades = [...received_ids, ...given_ids] - .map((e) => { - return assetsToFind[e]; - }) - .filter((e) => !!e); + const foundSlimTrades = [...received_ids, ...given_ids].map((e) => assetsToFind[e]).filter((e) => !!e); if (!foundSlimTrades || foundSlimTrades.length === 0) { return false; }