diff --git a/src/lib/bridge/handlers/fetch_steam_inventory.ts b/src/lib/bridge/handlers/fetch_steam_inventory.ts new file mode 100644 index 00000000..f5356e22 --- /dev/null +++ b/src/lib/bridge/handlers/fetch_steam_inventory.ts @@ -0,0 +1,127 @@ +import {SimpleHandler} from './main'; +import {RequestType} from './types'; +import {getAccessToken} from '../../alarms/access_token'; + +export interface FetchSteamPoweredInventoryRequest { + // steam_id needs to correspond to the logged in user + steam_id: string; + app_id: number; + context_id: number; + start_assetid?: string; + count?: number; + get_descriptions?: boolean; + for_trade_offer_verification?: boolean; + language?: string; + get_asset_properties?: boolean; +} + +export interface InventoryAsset { + assetid: string; + classid: string; + instanceid: string; +} + +export interface InventoryDescriptionItem { + value: string; + name: string; +} + +export interface InventoryTag { + category: string; + internal_name: string; + localized_category_name: string; + localized_tag_name: string; +} + +export interface AssetProperty { + propertyid: number; + int_value?: string; + float_value?: string; + string_value?: string; +} + +export interface AssetPropertyWrapper { + appid: number; + asset_properties: AssetProperty[]; + assetid: string; + contextid: string; +} + +export interface InventoryDescription { + name: string; + market_hash_name: string; + icon_url: string; + icon_url_large: string; + tradable: boolean; + type: string; + name_color: string; + commodity: boolean; + inspect_link?: string; + classid: string; + instanceid: string; + marketable: boolean; + descriptions: InventoryDescriptionItem[]; + tags: InventoryTag[]; +} + +export interface FetchSteamPoweredInventoryResponse { + assets: InventoryAsset[]; + descriptions: InventoryDescription[]; + asset_properties?: AssetPropertyWrapper[]; + last_assetid?: string; + total_inventory_count: number; +} + +export const FetchSteamPoweredInventory = new SimpleHandler< + FetchSteamPoweredInventoryRequest, + FetchSteamPoweredInventoryResponse +>(RequestType.FETCH_STEAM_POWERED_INVENTORY, async (req) => { + const accessToken = await getAccessToken(req.steam_id); + + const params = new URLSearchParams({ + access_token: accessToken.token, + steamid: req.steam_id, + appid: req.app_id.toString(), + contextid: req.context_id.toString(), + }); + + if (req.start_assetid) { + params.set('start_assetid', req.start_assetid); + } + + if (req.count) { + params.set('count', req.count.toString()); + } + + if (req.get_descriptions !== undefined) { + params.set('get_descriptions', req.get_descriptions.toString()); + } + + if (req.for_trade_offer_verification !== undefined) { + params.set('for_trade_offer_verification', req.for_trade_offer_verification.toString()); + } + + if (req.language) { + params.set('language', req.language); + } + + if (req.get_asset_properties !== undefined) { + params.set('get_asset_properties', req.get_asset_properties.toString()); + } + + const resp = await fetch( + `https://api.steampowered.com/IEconService/GetInventoryItemsWithDescriptions/v1/?${params.toString()}` + ); + + if (!resp.ok) { + throw new Error(`Invalid response code: ${resp.status}`); + } + + const data = await resp.json(); + + if (!data.response) { + throw new Error('Invalid response from Steam API'); + } + + return data.response as FetchSteamPoweredInventoryResponse; +}); diff --git a/src/lib/bridge/handlers/handlers.ts b/src/lib/bridge/handlers/handlers.ts index ac1b2f00..cd6181bd 100644 --- a/src/lib/bridge/handlers/handlers.ts +++ b/src/lib/bridge/handlers/handlers.ts @@ -36,6 +36,7 @@ import {FetchSlimTrades} from './fetch_slim_trades'; import {NotaryProve} from './notary_prove'; import {FetchNotaryMeta} from './fetch_notary_meta'; import {FetchNotaryToken} from './fetch_notary_token'; +import {FetchSteamPoweredInventory} from './fetch_steam_inventory'; export const HANDLERS_MAP: {[key in RequestType]: RequestHandler} = { [RequestType.EXECUTE_SCRIPT_ON_PAGE]: ExecuteScriptOnPage, @@ -74,4 +75,5 @@ export const HANDLERS_MAP: {[key in RequestType]: RequestHandler} = { [RequestType.NOTARY_PROVE]: NotaryProve, [RequestType.FETCH_NOTARY_META]: FetchNotaryMeta, [RequestType.FETCH_NOTARY_TOKEN]: FetchNotaryToken, + [RequestType.FETCH_STEAM_POWERED_INVENTORY]: FetchSteamPoweredInventory, }; diff --git a/src/lib/bridge/handlers/types.ts b/src/lib/bridge/handlers/types.ts index 033fc919..70d0a2d5 100644 --- a/src/lib/bridge/handlers/types.ts +++ b/src/lib/bridge/handlers/types.ts @@ -35,4 +35,5 @@ export enum RequestType { NOTARY_PROVE = 33, FETCH_NOTARY_META = 34, FETCH_NOTARY_TOKEN = 35, + FETCH_STEAM_POWERED_INVENTORY = 36, } diff --git a/src/lib/notary/types.ts b/src/lib/notary/types.ts index cb6cd782..40c85ea8 100644 --- a/src/lib/notary/types.ts +++ b/src/lib/notary/types.ts @@ -3,6 +3,7 @@ export enum ProofType { TRADE_OFFER = 'trade_offer', TRADE_HISTORY = 'trade_history', TRADE_STATUS = 'trade_status', + INVENTORY = 'inventory', } interface ProveRequestPayloads { @@ -38,6 +39,18 @@ interface ProveRequestPayloads { get_descriptions?: boolean; language?: string; }; + // IEconService/GetInventoryItemsWithDescriptions/v1/ + [ProofType.INVENTORY]: { + steamid: string; + appid: number; + contextid: number; + get_descriptions?: boolean; + for_trade_offer_verification?: boolean; + language?: string; + start_assetid?: string; + count?: number; + get_asset_properties?: boolean; + }; } export type NotaryProveRequest = { diff --git a/src/lib/notary/utils.ts b/src/lib/notary/utils.ts index 4c0aa09d..2c29314b 100644 --- a/src/lib/notary/utils.ts +++ b/src/lib/notary/utils.ts @@ -6,6 +6,7 @@ const PROOF_BASE_URLS: Record = { [ProofType.TRADE_OFFER]: 'https://api.steampowered.com/IEconService/GetTradeOffer/v1/', [ProofType.TRADE_HISTORY]: 'https://api.steampowered.com/IEconService/GetTradeHistory/v1/', [ProofType.TRADE_STATUS]: 'https://api.steampowered.com/IEconService/GetTradeStatus/v1/', + [ProofType.INVENTORY]: 'https://api.steampowered.com/IEconService/GetInventoryItemsWithDescriptions/v1/', }; function buildQueryString(params: Record): string {