steamutils 1.5.43 → 1.5.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,6 @@
1
1
  import path from "path";
2
2
  import { fileURLToPath } from "url";
3
3
  import Protobuf from "protobufjs";
4
- import gpf from "google-proto-files";
5
4
 
6
5
  const __filename = fileURLToPath(import.meta.url);
7
6
  const __dirname = path.dirname(__filename);
@@ -12,14 +11,10 @@ export class SteamProto {
12
11
  }
13
12
 
14
13
  toProto() {
15
- const localProto = path.join(`${__dirname}/protos/`, this._proto.filename);
16
-
17
- const descriptorPath = gpf.getProtoPath("protobuf/descriptor.proto");
18
-
19
- const root = new Protobuf.Root().loadSync([descriptorPath, localProto], {
14
+ const root = new Protobuf.Root().loadSync(path.join(`${__dirname}/protos/`, this._proto.filename), {
20
15
  keepCase: true,
21
16
  });
22
- return root.lookupType(this._proto.name);
17
+ return root[this._proto.name];
23
18
  }
24
19
 
25
20
  protoEncode(obj) {
package/index.js CHANGED
@@ -17,10 +17,11 @@ import { StringUtils } from "alpha-common-utils/index.js";
17
17
  import * as https from "https";
18
18
  import path from "path";
19
19
  import CookieManager from "./CookieManager.js";
20
- import { AppID_CSGO, E1GameBanOnRecord, E1VACBanOnRecord, EActivityType, ECommentPrivacyState, ECurrentlyTradeBanned, EdaySinceLastBanRegExp, EFriendRelationship, ELanguage, EmptyProfileSummary, EMultipleGameBansOnRecord, EMultipleVACBansOnRecord, EPrivacyState, ErrorProcessingRequest, FRIEND_CODE_REPLACEMENTS, NotYetSetupProfileTextList, PrivacySettings, PrivateProfileTextList, SteamcommunityURL, SteamErrorTitle, SteamImageCDN } from "./const.js";
20
+ import { AppID_CSGO, E1GameBanOnRecord, E1VACBanOnRecord, EActivityType, ECommentPrivacyState, ECurrentlyTradeBanned, EdaySinceLastBanRegExp, EFriendRelationship, ELanguage, EmptyProfileSummary, EMultipleGameBansOnRecord, EMultipleVACBansOnRecord, EPrivacyState, ErrorProcessingRequest, FRIEND_CODE_REPLACEMENTS, MarketRestrictionReasonText, NotYetSetupProfileTextList, PrivacySettings, PrivateProfileTextList, SteamcommunityURL, SteamErrorTitle, SteamImageCDN } from "./const.js";
21
21
  import SteamTotp from "steam-totp";
22
22
  import { SteamProto, SteamProtoType } from "./steamproto.js";
23
23
  import EventEmitter from "node:events";
24
+ import { extractAssetItemsFromHovers, parseMarketHistoryListings, parseMarketListings } from "./parse_html.js";
24
25
 
25
26
  const eventEmitter = (globalThis.steamUserEventEmitter = new EventEmitter());
26
27
 
@@ -6181,37 +6182,58 @@ export default class SteamUser {
6181
6182
  return response;
6182
6183
  }
6183
6184
 
6184
- async getMarketUnavailable() {
6185
+ /**
6186
+ * Fetches and parses Steam Market unavailability info.
6187
+ *
6188
+ * @returns {Promise<{
6189
+ * marketWarning?: string,
6190
+ * marketRestrictions?: string[],
6191
+ * marketRestrictionExpire?: string,
6192
+ * marketTimeCanUse?: number | null
6193
+ * } | null>} Parsed unavailability data, empty object, or null on error.
6194
+ */
6195
+ async getMarketRestrictions() {
6185
6196
  const result = await this._httpRequest(`market`);
6186
6197
  if (result instanceof ResponseError) {
6187
- return result;
6188
- }
6189
- const data = result?.data;
6190
- if (!data) {
6191
6198
  return null;
6192
6199
  }
6200
+ const data = result?.data;
6201
+ if (!data) return null;
6202
+
6193
6203
  const $ = cheerio.load(data);
6194
- const market_headertip_container_warning_el = $(".market_headertip_container_warning");
6195
- const market_warning_header_el = market_headertip_container_warning_el.find("#market_warning_header");
6196
- if (market_headertip_container_warning_el.length && market_warning_header_el.length) {
6197
- const market_warning_header = StringUtils.cleanSpace(market_warning_header_el.text());
6198
- const market_restrictions = [];
6199
- market_headertip_container_warning_el.find("ul.market_restrictions > li").each(function () {
6200
- const el = $(this);
6201
- el.find("a").remove();
6202
- market_restrictions.push(StringUtils.cleanSpace(el.text()));
6203
- });
6204
- const market_restriction_expire = StringUtils.cleanSpace(market_headertip_container_warning_el.find("#market_restriction_expire").text());
6205
- const market_timecanuse_header = StringUtils.cleanSpace(market_headertip_container_warning_el.find("#market_timecanuse_header").text());
6206
- return {
6207
- market_warning_header,
6208
- market_restrictions,
6209
- market_restriction_expire,
6210
- market_timecanuse_header,
6211
- };
6212
- } else {
6213
- return {};
6204
+
6205
+ const loginMsg1 = $("body").find(':contains("You need to sign in or create an account to do that.")').length;
6206
+ const loginMsg2 = $("body").find(':contains("Login to see, edit, or remove your Community Market listings")').length;
6207
+ const loginMsg3 = $("body").find(':contains("Login to view your Community Market history")').length;
6208
+ const loginLinkBlock = $(".market_login_link_ctn").length;
6209
+ if (loginMsg1 || loginMsg2 || loginMsg3 || loginLinkBlock) return null;
6210
+
6211
+ const warningContainer = $(".market_headertip_container_warning");
6212
+ const warningHeaderElement = warningContainer.find("#market_warning_header");
6213
+ if (!warningContainer.length || !warningHeaderElement.length) {
6214
+ return null;
6214
6215
  }
6216
+
6217
+ const marketWarning = StringUtils.cleanSpace(warningHeaderElement.text());
6218
+
6219
+ const restrictionMessages = [];
6220
+ warningContainer.find("ul.market_restrictions > li").each(function () {
6221
+ const el = $(this);
6222
+ el.find("a").remove();
6223
+ restrictionMessages.push(StringUtils.cleanSpace(el.text()));
6224
+ });
6225
+
6226
+ const marketRestrictions = restrictionMessages.map((message) => Object.entries(MarketRestrictionReasonText).find(([, text]) => text === message)?.[0] || message).filter(Boolean);
6227
+ const marketRestrictionExpire = StringUtils.cleanSpace(warningContainer.find("#market_restriction_expire").text());
6228
+ const marketTimeCanUse = StringUtils.cleanSpace(warningContainer.find("#market_timecanuse_header").text());
6229
+ const marketTimeCanUseMoment = moment(marketTimeCanUse, "ddd, DD MMM YYYY HH:mm:ss Z", true);
6230
+
6231
+ return {
6232
+ marketWarning,
6233
+ marketRestrictions,
6234
+ marketRestrictionExpire,
6235
+ marketTimeCanUse: marketTimeCanUseMoment.isValid() ? marketTimeCanUseMoment.valueOf() : null,
6236
+ };
6215
6237
  }
6216
6238
 
6217
6239
  async getAmountSpentOnSteam() {
@@ -6299,43 +6321,77 @@ export default class SteamUser {
6299
6321
  return null;
6300
6322
  }
6301
6323
 
6302
- const $ = cheerio.load(data.results_html);
6303
- const list = [];
6304
- $(".market_listing_row").each(function () {
6305
- try {
6306
- const $row = $(this);
6307
- const [sElementPrefix, listingid, appid, contextid, itemid] = $row
6308
- .find(".market_listing_cancel_button > a")
6309
- .attr("href")
6310
- .split("(")[1]
6311
- .split(")")[0]
6312
- .split(",")
6313
- .map((r) => r.trim().replaceAll(`'`, "").replaceAll(`"`, ""));
6314
- const image = $row.find(`#mylisting_${listingid}_image`).attr("src");
6315
- const buyer_pays_price = StringUtils.cleanSpace($row.find(`.market_listing_price span[title="This is the price the buyer pays."]`).text().replaceAll(`(`, "").replaceAll(`)`, ""));
6316
- const receive_price = StringUtils.cleanSpace($row.find(`.market_listing_price span[title="This is how much you will receive."]`).text().replaceAll(`(`, "").replaceAll(`)`, ""));
6317
- const item_name = $row.find(".market_listing_item_name_link").text() || $row.find(".market_listing_item_name").text();
6318
- const game_name = $row.find(".market_listing_game_name").text();
6319
- const date_combined = formatMarketHistoryDate(StringUtils.cleanSpace($row.find(".market_listing_game_name + .market_listing_listed_date_combined").text()));
6320
- list.push({
6321
- listingid,
6322
- appid,
6323
- contextid,
6324
- itemid,
6325
- buyer_pays_price,
6326
- receive_price,
6327
- item_name,
6328
- game_name,
6329
- date_combined,
6330
- image,
6331
- });
6332
- } catch (e) {}
6333
- });
6324
+ const list = parseMarketListings(data.results_html);
6334
6325
  const assets = Object.values(data.assets["730"]?.["2"] || {});
6335
6326
  return { list, assets, success: true };
6336
6327
  }
6337
6328
 
6338
- async getMyMarketHistory({ start = 0, count = 100 } = {}) {
6329
+ /**
6330
+ * @typedef {Object} MarketHistoryResponse
6331
+ * @property {boolean} success Whether the request was successful.
6332
+ * @property {number} pagesize Number of items per page.
6333
+ * @property {number} total_count Total count of market entries available.
6334
+ * @property {number} start Starting index of the results.
6335
+ * @property {Array<Asset>} assets Related inventory assets for the transactions.
6336
+ * @property {string} hovers Raw JavaScript code for web asset hovers.
6337
+ * @property {string} results_html Raw HTML snippet of market history.
6338
+ * @property {Array<MarketHistoryListing>} list Simplified, parsed list of market actions (buys/sells).
6339
+ * // Optionally, you may add below for pre-parsed hover info
6340
+ * // @property {Array<HoverItem>} [hoverItems] Parsed item hover info (if extracted from hovers).
6341
+ */
6342
+
6343
+ /**
6344
+ * @typedef {Object} Asset
6345
+ * @property {number} currency
6346
+ * @property {number} appid
6347
+ * @property {string} contextid
6348
+ * @property {string} id
6349
+ * @property {string} classid
6350
+ * @property {string} instanceid
6351
+ * @property {string} amount
6352
+ * @property {number} status
6353
+ * @property {string} original_amount
6354
+ * @property {string} unowned_id
6355
+ * @property {string} unowned_contextid
6356
+ * @property {string} background_color
6357
+ * @property {string} icon_url
6358
+ * @property {Array<AssetDescription>} descriptions
6359
+ * @property {number} tradable
6360
+ * @property {Array<AssetAction>} [actions]
6361
+ * @property {string} name
6362
+ * @property {string} name_color
6363
+ * @property {string} type
6364
+ * @property {string} market_name
6365
+ * @property {string} market_hash_name
6366
+ * @property {Array<AssetAction>} [market_actions]
6367
+ * @property {number} commodity
6368
+ * @property {number} market_tradable_restriction
6369
+ * @property {number} market_marketable_restriction
6370
+ * @property {number} marketable
6371
+ * @property {string} app_icon
6372
+ * @property {number} owner
6373
+ */
6374
+
6375
+ /**
6376
+ * @typedef {Object} AssetDescription
6377
+ * @property {string} type Description style or block type (e.g. "html").
6378
+ * @property {string} value The description's content.
6379
+ * @property {string} name Field/tag name.
6380
+ * @property {string} [color] (Optional) Hex color string for this description entry.
6381
+ */
6382
+
6383
+ /**
6384
+ * @typedef {Object} AssetAction
6385
+ * @property {string} link URL or steam protocol link.
6386
+ * @property {string} name Action button text/description.
6387
+ */
6388
+
6389
+ /**
6390
+ * Retrieves the user's Steam Market transaction history, including assets, listing info, and hover selectors.
6391
+ *
6392
+ * @returns {MarketHistoryResponse} The market history data structure.
6393
+ */
6394
+ async getMarketHistory({ start = 0, count = 100 } = {}) {
6339
6395
  const result = await this._httpRequestAjax({
6340
6396
  url: `market/myhistory/render/?query=&start=${start}&count=${count}`,
6341
6397
  });
@@ -6349,56 +6405,10 @@ export default class SteamUser {
6349
6405
  return null;
6350
6406
  }
6351
6407
 
6352
- const hovers = StringUtils.cleanSpace(data.hovers);
6408
+ const hovers = extractAssetItemsFromHovers(data.hovers);
6353
6409
  const assetById = data.assets?.[730]?.[2] || {};
6354
- const assestByListingId = {};
6355
- hovers.split("CreateItemHoverFromContainer").forEach(function (text) {
6356
- text = text.trim();
6357
- if (!text.startsWith("(")) {
6358
- return;
6359
- }
6360
- const texts = text.split(",");
6361
- const listingId = texts[1]?.substringBetweenOrNull("history_row_", "_");
6362
- const assestId = texts[4]?.trim()?.removeSurrounding("'");
6363
- if (!listingId || !assestId || !assetById[assestId]) {
6364
- return;
6365
- }
6366
- assestByListingId[listingId] = assestId;
6367
- });
6368
-
6369
- const $ = cheerio.load(data.results_html);
6370
- const list = [...$(".market_listing_row")]
6371
- .map(function (el) {
6372
- el = $(el);
6373
- const id = el.attr("id");
6374
- const listingid = id.substringBetweenOrNull("history_row_", "_");
6375
- if (!listingid) {
6376
- return;
6377
- }
6378
- const gainOrLoss = StringUtils.cleanSpace(el.find(".market_listing_gainorloss").text());
6379
- const image = el.find(`.market_listing_item_img`).attr("src");
6380
- const price = parseInt(el.find(`.market_table_value .market_listing_price`).text().replaceAll(`(`, "").replaceAll(`)`, "").replaceAll(`₫`, "").replaceAll(`.`, "").replaceAll(`,`, "").trim()) || "";
6381
- const item_name = el.find(".market_listing_item_name").text();
6382
- const game_name = el.find(".market_listing_game_name").text();
6383
- const listedOn = formatMarketHistoryDate(StringUtils.cleanSpace(el.find(".market_listing_listed_date + .market_listing_listed_date").text().replaceAll(`Listed:`, "")));
6384
- const actedOn = formatMarketHistoryDate(StringUtils.cleanSpace(el.find(".market_listing_whoactedwith + .market_listing_listed_date").text().replaceAll(`Listed:`, "")));
6385
- const status = StringUtils.cleanSpace(el.find(".market_listing_whoactedwith").text());
6386
-
6387
- return {
6388
- id,
6389
- listingid,
6390
- price,
6391
- item_name,
6392
- game_name,
6393
- listedOn,
6394
- actedOn,
6395
- image,
6396
- gainOrLoss,
6397
- status,
6398
- ...(!!assestByListingId[listingid] && { assetId: assestByListingId[listingid] }),
6399
- };
6400
- })
6401
- .filter(Boolean);
6410
+ const assestByListingId = hovers.reduce((map, item) => (item.listingId && item.assetid && (map[item.listingId] = item.assetid), map), {});
6411
+ const list = parseMarketHistoryListings(data.results_html, assestByListingId);
6402
6412
  const assets = Object.values(assetById);
6403
6413
  return { ...data, list, assets, success: true };
6404
6414
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "steamutils",
3
- "version": "1.5.43",
3
+ "version": "1.5.45",
4
4
  "main": "index.js",
5
5
  "dependencies": {
6
6
  "alpha-common-utils": "^1.0.6",
package/parse_html.js ADDED
@@ -0,0 +1,189 @@
1
+ import { StringUtils } from "alpha-common-utils/index.js";
2
+ import { formatMarketHistoryDate } from "./utils.js";
3
+ import * as cheerio from "cheerio";
4
+
5
+ /**
6
+ * @typedef {Object} HoverItem
7
+ * @property {string|null} listingId The listing ID extracted from the selector, if available (as string).
8
+ * @property {number} appid The app (game) ID for this item.
9
+ * @property {number} contextid The context ID for this item.
10
+ * @property {number} assetid The unique asset ID.
11
+ * @property {string} unknown A string field captured from the arguments (usually "0").
12
+ * @property {string} [name_selector] The HTML selector for the item's name, if present.
13
+ * @property {string} [image_selector] The HTML selector for the item's image, if present.
14
+ * @property {string} [other_selector] The selector string if it does not match name/image pattern.
15
+ */
16
+
17
+ /**
18
+ * Extracts item information from Steam inventory trade history or similar HTML fragments.
19
+ * Scans the given HTML string for calls to `CreateItemHoverFromContainer` and extracts
20
+ * key data for each referenced item. Returns each item's info in a structured array.
21
+ *
22
+ * @param {string} html - The HTML string to parse.
23
+ * @returns {HoverItem[]} Array of hover item objects.
24
+ */
25
+ export function extractAssetItemsFromHovers(html) {
26
+ // Use your preferred HTML/space scrubber.
27
+ html = StringUtils.cleanSpace(html);
28
+
29
+ // RegExp for CreateItemHoverFromContainer arguments
30
+ const re = /CreateItemHoverFromContainer\s*\(\s*g_rgAssets\s*,\s*'([^']+)'\s*,\s*(\d+)\s*,\s*'(\d+)'\s*,\s*'(\d+)'\s*,\s*(\d+)\s*\)/g;
31
+
32
+ /** @type {Record<number, HoverItem>} */
33
+ const itemsMap = {};
34
+ let match;
35
+
36
+ while ((match = re.exec(html)) !== null) {
37
+ const [_, selector, appid, contextid, assetid, unknown] = match;
38
+
39
+ // Extract listingId as a string if present: "history_row_<listingId>_"
40
+ let listingId = null;
41
+ const lidMatch = selector.match(/history_row_(\d+)_/);
42
+ if (lidMatch) listingId = lidMatch[1]; // assign as string
43
+
44
+ const appidNum = Number(appid);
45
+ const contextidNum = Number(contextid);
46
+ const assetidNum = Number(assetid);
47
+
48
+ if (!itemsMap[assetidNum]) {
49
+ itemsMap[assetidNum] = {
50
+ listingId,
51
+ appid: appidNum,
52
+ contextid: contextidNum,
53
+ assetid: assetidNum,
54
+ unknown,
55
+ };
56
+ }
57
+
58
+ if (selector.endsWith("_name")) {
59
+ itemsMap[assetidNum].name_selector = selector;
60
+ } else if (selector.endsWith("_image")) {
61
+ itemsMap[assetidNum].image_selector = selector;
62
+ } else {
63
+ itemsMap[assetidNum].other_selector = selector;
64
+ }
65
+ }
66
+ return Object.values(itemsMap);
67
+ }
68
+
69
+ /**
70
+ * @typedef {Object} MarketHistoryListing
71
+ * @property {string} id - HTML row id attribute (e.g. "history_row_4316182845737233773_4316182845737233774").
72
+ * @property {string} listingId - Listing id (e.g. "4316182845737233773").
73
+ * @property {number} price - Price in integer form (e.g. 80270).
74
+ * @property {string} itemName - The market item's name (e.g. "UMP-45 | Mudder").
75
+ * @property {string} gameName - The game's name (e.g. "Counter-Strike 2").
76
+ * @property {string} listedOn - Listing date as string (e.g. "27 May 2024").
77
+ * @property {string} actedOn - Acted on date or empty string.
78
+ * @property {string} image - Full image URL for the item.
79
+ * @property {string} gainOrLoss - "+" for buys, "-" for sells.
80
+ * @property {string} status - Status text, usually empty string.
81
+ * @property {string} [assetId] - (optional) Associated asset id, if available.
82
+ */
83
+
84
+ /**
85
+ * Parses Steam market history listing rows into structured data objects.
86
+ *
87
+ * @param {string} html - The raw HTML string to parse.
88
+ * @param {Object} [assetByListingId={}] - Optional mapping of listingId to assetId.
89
+ * @returns {MarketHistoryListing[]} Array of market listing objects.
90
+ */
91
+ export function parseMarketHistoryListings(html, assetByListingId = {}) {
92
+ const $ = cheerio.load(html);
93
+ return $(".market_listing_row")
94
+ .toArray()
95
+ .map((el) => {
96
+ const $el = $(el);
97
+ const id = $el.attr("id");
98
+ const listingId = id?.match(/history_row_(.*?)_/)?.[1];
99
+ if (!listingId) return null;
100
+ const [gainOrLoss, image, priceText, itemName, gameName, listedOnText, actedOnText, status] = [$el.find(".market_listing_gainorloss").text().trim(), $el.find(".market_listing_item_img").attr("src"), $el.find(".market_table_value .market_listing_price").text(), $el.find(".market_listing_item_name").text().trim(), $el.find(".market_listing_game_name").text().trim(), $el.find(".market_listing_listed_date + .market_listing_listed_date").text(), $el.find(".market_listing_whoactedwith + .market_listing_listed_date").text(), $el.find(".market_listing_whoactedwith").text().trim()];
101
+ const price = parseInt(priceText.replace(/[₫().,]/g, "").trim(), 10) || "";
102
+ const listedOn = typeof formatMarketHistoryDate === "function" ? formatMarketHistoryDate(listedOnText.replace(/Listed:/, "").trim()) : listedOnText.replace(/Listed:/, "").trim();
103
+ const actedOn = typeof formatMarketHistoryDate === "function" ? formatMarketHistoryDate(actedOnText.replace(/Listed:/, "").trim()) : actedOnText.replace(/Listed:/, "").trim();
104
+
105
+ const result = {
106
+ id,
107
+ listingId,
108
+ price,
109
+ itemName,
110
+ gameName,
111
+ listedOn,
112
+ actedOn,
113
+ image,
114
+ gainOrLoss,
115
+ status,
116
+ };
117
+ if (assetByListingId?.[listingId]) result.assetId = assetByListingId[listingId];
118
+ return result;
119
+ })
120
+ .filter(Boolean);
121
+ }
122
+
123
+ /**
124
+ * Parses Steam Market HTML listings to an array of items.
125
+ *
126
+ * @param {string} html - HTML string containing listing rows.
127
+ * @returns {Array<{
128
+ * listingId: string,
129
+ * appId: number,
130
+ * contextId: number,
131
+ * itemId: number,
132
+ * imageUrl: string|null,
133
+ * buyerPaysPrice: string,
134
+ * receivePrice: string,
135
+ * itemName: string,
136
+ * gameName: string,
137
+ * listedDate: string
138
+ * }>}
139
+ */
140
+ export function parseMarketListings(html) {
141
+ const $ = cheerio.load(html);
142
+ const results = [];
143
+
144
+ $(".market_listing_row").each((index, element) => {
145
+ const $row = $(element);
146
+
147
+ const cancelLink = $row.find(".market_listing_cancel_button > a").attr("href");
148
+ if (!cancelLink) return;
149
+
150
+ const paramsMatch = cancelLink.match(/\(([^)]*)\)/);
151
+ if (!paramsMatch) return;
152
+
153
+ let [listingId, appId, contextId, itemId] = paramsMatch[1].split(",").map((param) => param.trim().replace(/^['"]|['"]$/g, ""));
154
+
155
+ appId = Number(appId);
156
+ contextId = Number(contextId);
157
+ itemId = Number(itemId);
158
+
159
+ const imageUrl = $row.find(`#mylisting_${listingId}_image`).attr("src") || null;
160
+
161
+ const buyerPaysElem = $row.find('.market_listing_price span[title="This is the price the buyer pays."]');
162
+ const buyerPaysPrice = StringUtils.cleanSpace(buyerPaysElem.text().replace(/[()]/g, ""));
163
+
164
+ const receiveElem = $row.find('.market_listing_price span[title="This is how much you will receive."]');
165
+ const receivePrice = StringUtils.cleanSpace(receiveElem.text().replace(/[()]/g, ""));
166
+
167
+ const itemName = $row.find(".market_listing_item_name_link").text() || $row.find(".market_listing_item_name").text();
168
+
169
+ const gameName = $row.find(".market_listing_game_name").text();
170
+
171
+ const listedDateElem = $row.find(".market_listing_game_name + .market_listing_listed_date_combined");
172
+ const listedDate = formatMarketHistoryDate(StringUtils.cleanSpace(listedDateElem.text()));
173
+
174
+ results.push({
175
+ listingId,
176
+ appId,
177
+ contextId,
178
+ itemId,
179
+ imageUrl,
180
+ buyerPaysPrice,
181
+ receivePrice,
182
+ itemName,
183
+ gameName,
184
+ listedDate,
185
+ });
186
+ });
187
+
188
+ return results;
189
+ }