From 1b61cdb7029438c55abb221cfa47fd8932978cd0 Mon Sep 17 00:00:00 2001 From: Step7750 Date: Sat, 7 Mar 2026 19:17:36 -0700 Subject: [PATCH 1/3] Disables Fetching Floats for "Bugged" Market Listings --- src/lib/components/market/item_row_wrapper.ts | 30 +++++++++++++++++++ src/lib/types/steam.d.ts | 20 +++++++++++++ 2 files changed, 50 insertions(+) diff --git a/src/lib/components/market/item_row_wrapper.ts b/src/lib/components/market/item_row_wrapper.ts index c2f9ec6a..639c8973 100644 --- a/src/lib/components/market/item_row_wrapper.ts +++ b/src/lib/components/market/item_row_wrapper.ts @@ -118,6 +118,28 @@ export class ItemRowWrapper extends FloatElement { } } + /** + * As part of the March 2/2026 update, skins listed on SCM get moved into the trade protected inventory context + * so the user can still use them in-game while listed. However, Valve introduced a bug where these skins + * can't be inspected in game. + * + * Detect and skip these skins to prevent overloaded errors to the user and browser request throttling. + */ + get isBuggedSkin(): boolean { + if (!this.asset || !isSkin(this.asset)) { + return false; + } + + if (this.asset.unowned_contextid !== "16") { + // Only applies for trade protected inventory context + return false; + } + + const fv = (this.asset.asset_properties || []).find((prop) => prop.propertyid === 2); + // Has no FV + return !fv; + } + @state() private itemInfo: ItemInfo | undefined; @state() @@ -143,6 +165,10 @@ export class ItemRowWrapper extends FloatElement { return; } + if (this.isBuggedSkin) { + return; + } + try { this.itemInfo = await this.fetchFloat(); } catch (e: any) { @@ -236,6 +262,10 @@ export class ItemRowWrapper extends FloatElement { return nothing; } + if (this.isBuggedSkin) { + return nothing; + } + if (this.itemInfo && isSkin(this.asset)) { const fadePercentage = this.asset && getFadePercentage(this.asset, this.itemInfo)?.percentage; diff --git a/src/lib/types/steam.d.ts b/src/lib/types/steam.d.ts index 91144ad3..e6638555 100644 --- a/src/lib/types/steam.d.ts +++ b/src/lib/types/steam.d.ts @@ -71,6 +71,25 @@ export interface rgDescription { }[]; } +type RequireOnlyOne = + Pick> + & { + [K in Keys]-?: Required> & Partial, never>> +}[Keys]; + +interface rgAssetPropertyBase { + propertyid: number; + int_value?: string; + float_value?: string; + string_value?: string; +} + +// Only one of int_value, float_value, or string_value can be present +type rgAssetProperty = RequireOnlyOne< + rgAssetPropertyBase, + 'int_value' | 'float_value' | 'string_value' +>; + // g_rgAssets export interface rgAsset extends rgDescription { amount: number; @@ -86,6 +105,7 @@ export interface rgAsset extends rgDescription { unowned_contextid: string; unowned_id: string; element?: HTMLElement; + asset_properties?: rgAssetProperty[]; } export interface rgInventoryAsset { From 7e8ab464191304538ac2747fb88ea4ffb7348279 Mon Sep 17 00:00:00 2001 From: Step7750 Date: Sat, 7 Mar 2026 19:39:36 -0700 Subject: [PATCH 2/3] Adds Bugged Skin Count to Utility Belt --- src/lib/components/market/item_row_wrapper.ts | 27 +-------- src/lib/components/market/utility_belt.ts | 60 ++++++++++++++++++- src/lib/utils/skin.ts | 20 +++++++ 3 files changed, 82 insertions(+), 25 deletions(-) diff --git a/src/lib/components/market/item_row_wrapper.ts b/src/lib/components/market/item_row_wrapper.ts index 639c8973..bc94cb19 100644 --- a/src/lib/components/market/item_row_wrapper.ts +++ b/src/lib/components/market/item_row_wrapper.ts @@ -17,6 +17,7 @@ import { isCharm, isBlueSkin, isHighlightCharm, + isBuggedSkin, } from '../../utils/skin'; import {gFilterService} from '../../services/filter'; import {AppId, ContextId, Currency} from '../../types/steam_constants'; @@ -118,28 +119,6 @@ export class ItemRowWrapper extends FloatElement { } } - /** - * As part of the March 2/2026 update, skins listed on SCM get moved into the trade protected inventory context - * so the user can still use them in-game while listed. However, Valve introduced a bug where these skins - * can't be inspected in game. - * - * Detect and skip these skins to prevent overloaded errors to the user and browser request throttling. - */ - get isBuggedSkin(): boolean { - if (!this.asset || !isSkin(this.asset)) { - return false; - } - - if (this.asset.unowned_contextid !== "16") { - // Only applies for trade protected inventory context - return false; - } - - const fv = (this.asset.asset_properties || []).find((prop) => prop.propertyid === 2); - // Has no FV - return !fv; - } - @state() private itemInfo: ItemInfo | undefined; @state() @@ -165,7 +144,7 @@ export class ItemRowWrapper extends FloatElement { return; } - if (this.isBuggedSkin) { + if (isBuggedSkin(this.asset)) { return; } @@ -262,7 +241,7 @@ export class ItemRowWrapper extends FloatElement { return nothing; } - if (this.isBuggedSkin) { + if (isBuggedSkin(this.asset)) { return nothing; } diff --git a/src/lib/components/market/utility_belt.ts b/src/lib/components/market/utility_belt.ts index 1dbea531..c4554036 100644 --- a/src/lib/components/market/utility_belt.ts +++ b/src/lib/components/market/utility_belt.ts @@ -1,14 +1,21 @@ import {FloatElement} from '../custom'; import {CustomElement, InjectBefore, InjectionMode} from '../injectors'; -import {css, html, HTMLTemplateResult} from 'lit'; +import {css, html, HTMLTemplateResult, nothing} from 'lit'; +import {state} from 'lit/decorators.js'; import '../common/ui/steam-button'; import './page_size'; import './sort_listings'; import '../filter/filter_container'; +import {Observe} from '../../utils/observers'; +import {isBuggedSkin} from '../../utils/skin'; +import {AppId, ContextId} from '../../types/steam_constants'; @CustomElement() @InjectBefore('#searchResultsRows', InjectionMode.ONCE) export class UtilityBelt extends FloatElement { + @state() + private buggedSkinCount = 0; + get marketHashName(): string { return (document.querySelector('.market_listing_nav a:nth-child(2)') as HTMLElement).innerText; } @@ -31,6 +38,16 @@ export class UtilityBelt extends FloatElement { text-decoration: underline; font-family: 'Motiva Sans', sans-serif; } + + .bugged-skin-warning { + padding: 8px 12px; + margin-top: 10px; + background-color: rgba(255, 152, 0, 0.15); + border: 1px solid rgba(255, 152, 0, 0.4); + border-radius: 4px; + color: #ffb74d; + font-size: 13px; + } `, ]; @@ -45,12 +62,53 @@ export class UtilityBelt extends FloatElement { ?hidden="${!this.marketHashName}" .key="${this.marketHashName}" > + ${this.renderBuggedSkinWarning()} `; } + private countBuggedSkins(): number { + try { + const assets = g_rgAssets?.[AppId.CSGO]?.[ContextId.PRIMARY]; + if (!assets) return 0; + + return Object.values(assets).filter((asset) => isBuggedSkin(asset)).length; + } catch { + return 0; + } + } + + private renderBuggedSkinWarning(): HTMLTemplateResult | typeof nothing { + if (this.buggedSkinCount === 0) { + return nothing; + } + + return html` +
+ ${this.buggedSkinCount} skin${this.buggedSkinCount > 1 ? 's' : ''} on this page + cannot display float data since they're not inspectable in-game (March 4, 2026 update). Valve pls fix. +
+ `; + } + async connectedCallback() { super.connectedCallback(); + + this.buggedSkinCount = this.countBuggedSkins(); + + Observe( + () => { + try { + return Object.keys(g_rgAssets?.[AppId.CSGO]?.[ContextId.PRIMARY] || {}).join(','); + } catch { + return ''; + } + }, + () => { + this.buggedSkinCount = this.countBuggedSkins(); + }, + 100 + ); } } diff --git a/src/lib/utils/skin.ts b/src/lib/utils/skin.ts index 8110660d..c6408969 100644 --- a/src/lib/utils/skin.ts +++ b/src/lib/utils/skin.ts @@ -230,3 +230,23 @@ export function floor(n: number, precision?: number) { return Math.floor(n * p) / p; } + +/** + * As part of the March 4/2026 update, skins listed on SCM get moved into the trade protected inventory context + * so the user can still use them in-game while listed. However, Valve introduced a bug where these skins + * can't be inspected in game. + * + * Detect and skip these skins to prevent overloaded errors to the user and browser request throttling. + */ +export function isBuggedSkin(asset: rgAsset | undefined): boolean { + if (!asset || !isSkin(asset)) { + return false; + } + + if (asset.unowned_contextid !== '16') { + return false; + } + + const fv = (asset.asset_properties || []).find((prop) => prop.propertyid === 2); + return !fv; +} From 6b9499f4f8fc520a1d472ee9f7c29fa0bf80987c Mon Sep 17 00:00:00 2001 From: Step7750 Date: Sat, 7 Mar 2026 19:46:56 -0700 Subject: [PATCH 3/3] prettier --- src/lib/components/market/utility_belt.ts | 4 ++-- src/lib/types/steam.d.ts | 14 +++++--------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/lib/components/market/utility_belt.ts b/src/lib/components/market/utility_belt.ts index c4554036..4fe38b83 100644 --- a/src/lib/components/market/utility_belt.ts +++ b/src/lib/components/market/utility_belt.ts @@ -86,8 +86,8 @@ export class UtilityBelt extends FloatElement { return html`
- ${this.buggedSkinCount} skin${this.buggedSkinCount > 1 ? 's' : ''} on this page - cannot display float data since they're not inspectable in-game (March 4, 2026 update). Valve pls fix. + ${this.buggedSkinCount} skin${this.buggedSkinCount > 1 ? 's' : ''} on this page cannot display + float data since they're not inspectable in-game (March 4, 2026 update). Valve pls fix.
`; } diff --git a/src/lib/types/steam.d.ts b/src/lib/types/steam.d.ts index e6638555..1b7d751d 100644 --- a/src/lib/types/steam.d.ts +++ b/src/lib/types/steam.d.ts @@ -71,11 +71,10 @@ export interface rgDescription { }[]; } -type RequireOnlyOne = - Pick> - & { - [K in Keys]-?: Required> & Partial, never>> -}[Keys]; +type RequireOnlyOne = Pick> & + { + [K in Keys]-?: Required> & Partial, never>>; + }[Keys]; interface rgAssetPropertyBase { propertyid: number; @@ -85,10 +84,7 @@ interface rgAssetPropertyBase { } // Only one of int_value, float_value, or string_value can be present -type rgAssetProperty = RequireOnlyOne< - rgAssetPropertyBase, - 'int_value' | 'float_value' | 'string_value' ->; +type rgAssetProperty = RequireOnlyOne; // g_rgAssets export interface rgAsset extends rgDescription {