11import { TradeOfferState } from '../types/steam_constants' ;
2- import { Trade } from '../types/float_market' ;
2+ import { Trade , TradeState } from '../types/float_market' ;
33import { TradeOfferStatus , TradeOffersType } from '../bridge/handlers/trade_offer_status' ;
44import { clearAccessTokenFromStorage , getAccessToken } from './access_token' ;
55import { AnnotateOffer } from '../bridge/handlers/annotate_offer' ;
6+ import { PingCancelTrade } from '../bridge/handlers/ping_cancel_trade' ;
67
78interface OfferStatus {
89 offer_id : string ;
@@ -64,6 +65,44 @@ export async function pingSentTradeOffers(pendingTrades: Trade[]) {
6465 }
6566}
6667
68+ export async function pingCancelTrades ( pendingTrades : Trade [ ] ) {
69+ const hasWaitForCancelPing = pendingTrades . find ( ( e ) => e . state === TradeState . PENDING && e . wait_for_cancel_ping ) ;
70+ if ( ! hasWaitForCancelPing ) {
71+ // Nothing to process/ping, exit
72+ return ;
73+ }
74+
75+ const tradeOffers = await getSentAndReceivedTradeOffersFromAPI ( ) ;
76+
77+ const allTradeOffers = [ ...( tradeOffers . sent || [ ] ) , ...( tradeOffers . received || [ ] ) ] ;
78+
79+ for ( const trade of pendingTrades ) {
80+ if ( trade . state !== TradeState . PENDING ) {
81+ continue ;
82+ }
83+
84+ if ( ! trade . wait_for_cancel_ping ) {
85+ continue ;
86+ }
87+
88+ const tradeOffer = allTradeOffers . find ( ( e ) => e . offer_id === trade . steam_offer . id ) ;
89+ if (
90+ tradeOffer &&
91+ ( tradeOffer . state === TradeOfferState . Active ||
92+ tradeOffer . state === TradeOfferState . Accepted ||
93+ tradeOffer . state === TradeOfferState . CreatedNeedsConfirmation )
94+ ) {
95+ // We don't want to send a cancel ping if the offer is active or valid
96+ continue ;
97+ }
98+
99+ try {
100+ await PingCancelTrade . handleRequest ( { trade_id : trade . id } , { } ) ;
101+ } catch ( e ) {
102+ console . error ( `failed to send cancel ping for trade ${ trade . id } ` , e ) ;
103+ }
104+ }
105+ }
67106async function getEnglishSentTradeOffersHTML ( ) : Promise < string > {
68107 const resp = await fetch ( `https://steamcommunity.com/id/me/tradeoffers/sent` , {
69108 credentials : 'include' ,
@@ -90,7 +129,7 @@ async function getEnglishSentTradeOffersHTML(): Promise<string> {
90129
91130async function getSentTradeOffers ( ) : Promise < { offers : OfferStatus [ ] ; type : TradeOffersType } > {
92131 try {
93- const offers = await getTradeOffersFromAPI ( ) ;
132+ const offers = await getSentTradeOffersFromAPI ( ) ;
94133 if ( offers . length > 0 ) {
95134 // Hedge in case this endpoint gets killed, only return if there are results, fallback to HTML parser
96135 return { offers, type : TradeOffersType . API } ;
@@ -109,19 +148,31 @@ interface TradeOfferItem {
109148 assetid : string ;
110149}
111150
151+ interface TradeOffersAPIOffer {
152+ tradeofferid : string ;
153+ accountid_other : string ;
154+ trade_offer_state : TradeOfferState ;
155+ items_to_give ?: TradeOfferItem [ ] ;
156+ items_to_receive ?: TradeOfferItem [ ] ;
157+ }
158+
112159interface TradeOffersAPIResponse {
113160 response : {
114- trade_offers_sent : {
115- tradeofferid : string ;
116- accountid_other : string ;
117- trade_offer_state : TradeOfferState ;
118- items_to_give ?: TradeOfferItem [ ] ;
119- items_to_receive ?: TradeOfferItem [ ] ;
120- } [ ] ;
161+ trade_offers_sent : TradeOffersAPIOffer [ ] ;
162+ trade_offers_received : TradeOffersAPIOffer [ ] ;
121163 } ;
122164}
123165
124- async function getTradeOffersFromAPI ( ) : Promise < OfferStatus [ ] > {
166+ function offerStateMapper ( e : TradeOffersAPIOffer ) : OfferStatus {
167+ return {
168+ offer_id : e . tradeofferid ,
169+ state : e . trade_offer_state ,
170+ given_asset_ids : ( e . items_to_give || [ ] ) . map ( ( e ) => e . assetid ) ,
171+ received_asset_ids : ( e . items_to_receive || [ ] ) . map ( ( e ) => e . assetid ) ,
172+ } as OfferStatus ;
173+ }
174+
175+ async function getSentTradeOffersFromAPI ( ) : Promise < OfferStatus [ ] > {
125176 const accessToken = await getAccessToken ( ) ;
126177
127178 const resp = await fetch (
@@ -136,14 +187,28 @@ async function getTradeOffersFromAPI(): Promise<OfferStatus[]> {
136187 }
137188
138189 const data = ( await resp . json ( ) ) as TradeOffersAPIResponse ;
139- return data . response . trade_offers_sent . map ( ( e ) => {
140- return {
141- offer_id : e . tradeofferid ,
142- state : e . trade_offer_state ,
143- given_asset_ids : ( e . items_to_give || [ ] ) . map ( ( e ) => e . assetid ) ,
144- received_asset_ids : ( e . items_to_receive || [ ] ) . map ( ( e ) => e . assetid ) ,
145- } as OfferStatus ;
146- } ) ;
190+ return data . response . trade_offers_sent . map ( offerStateMapper ) ;
191+ }
192+
193+ async function getSentAndReceivedTradeOffersFromAPI ( ) : Promise < { received : OfferStatus [ ] ; sent : OfferStatus [ ] } > {
194+ const accessToken = await getAccessToken ( ) ;
195+
196+ const resp = await fetch (
197+ `https://api.steampowered.com/IEconService/GetTradeOffers/v1/?access_token=${ accessToken } &get_received_offers=true&get_sent_offers=true` ,
198+ {
199+ credentials : 'include' ,
200+ }
201+ ) ;
202+
203+ if ( resp . status !== 200 ) {
204+ throw new Error ( 'invalid status' ) ;
205+ }
206+
207+ const data = ( await resp . json ( ) ) as TradeOffersAPIResponse ;
208+ return {
209+ received : data . response . trade_offers_received . map ( offerStateMapper ) ,
210+ sent : data . response . trade_offers_sent . map ( offerStateMapper ) ,
211+ } ;
147212}
148213
149214const BANNER_TO_STATE : { [ banner : string ] : TradeOfferState } = {
0 commit comments