@exodus/market-history 10.2.3 → 10.2.4

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.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,12 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [10.2.4](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/market-history@10.2.3...@exodus/market-history@10.2.4) (2025-06-17)
7
+
8
+ ### Performance
9
+
10
+ - perf(market-history): Optimize price transformation logic (#12932)
11
+
6
12
  ## [10.2.3](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/market-history@10.2.2...@exodus/market-history@10.2.3) (2025-06-16)
7
13
 
8
14
  ### Performance
package/module/index.js CHANGED
@@ -1,4 +1,3 @@
1
- import { mapValues } from '@exodus/basic-utils'
2
1
  import dayjs from '@exodus/dayjs'
3
2
  import { fetchHistoricalPrices } from '@exodus/price-api'
4
3
  import delay from 'delay'
@@ -12,14 +11,6 @@ const CLEAR_MARKET_HISTORY_CACHE_FROM_REMOTE_CONFIG_KEY =
12
11
  'clear-market-history-cache-from-remote-config'
13
12
  const MARKET_HISTORY_REFRESH_KEY = 'market-history-cache-refresh'
14
13
 
15
- const transformPriceEntries = (entries = []) => {
16
- const closePrices = entries.map((entry) => [entry[0], entry[1].close])
17
- return Object.fromEntries(closePrices)
18
- }
19
-
20
- const transformPricesByAssetName = (pricesByAssetName) =>
21
- mapValues(pricesByAssetName, (entries) => transformPriceEntries(entries))
22
-
23
14
  // when provided cache version from local or remote config is different from stored on device we clear the cache and fetch new prices
24
15
  const _invalidateStorageCache = async ({
25
16
  storage,
@@ -62,6 +53,36 @@ const filterMapAssetDataFromServer = (data) =>
62
53
  .filter((piece) => piece.close !== 0)
63
54
  .map((piece) => [piece.time * 1000, { close: piece.close }])
64
55
 
56
+ const mapPricesForCache = (pricesMap, assetNames, assets) => {
57
+ const result = Object.create(null)
58
+ for (const assetName of assetNames) {
59
+ const assetPricesMap = pricesMap.get(assets[assetName].ticker)
60
+ result[assetName] = assetPricesMap ? [...assetPricesMap] : []
61
+ }
62
+
63
+ return result
64
+ }
65
+
66
+ const transformHistoricalPrices = (pricesMap, assetNames, assets) => {
67
+ const result = Object.create(null)
68
+ for (const assetName of assetNames) {
69
+ const assetPrices = pricesMap.get(assets[assetName].ticker)
70
+ if (assetPrices) {
71
+ const closePrices = Object.create(null)
72
+ // assetPrices is a Map, iterate it directly to avoid creating an intermediate array
73
+ for (const [time, priceData] of assetPrices.entries()) {
74
+ closePrices[time] = priceData.close
75
+ }
76
+
77
+ result[assetName] = closePrices
78
+ } else {
79
+ result[assetName] = Object.create(null)
80
+ }
81
+ }
82
+
83
+ return result
84
+ }
85
+
65
86
  const delayWithJitter = (ms, jitter = 0, signal) =>
66
87
  delay(Math.floor(ms + Math.random() * jitter), { signal })
67
88
 
@@ -229,29 +250,23 @@ class MarketHistoryMonitor {
229
250
  requestLimit: requestLimit || this.#granularityRequestLimits[granularity],
230
251
  })
231
252
 
232
- const mapPrices = (pricesMap) => {
233
- return Object.fromEntries(
234
- assetNames.map((assetName) => {
235
- const assetPricesMap = pricesMap.get(assets[assetName].ticker)
236
- const value = assetPricesMap ? [...assetPricesMap] : []
237
- return [assetName, value]
238
- })
239
- )
240
- }
241
-
242
- const pricesByAssetName = mapPrices(fetchedPricesMap)
243
-
244
- const fullHistoryByAssetName =
245
- fetchedPricesMap.size === historicalPricesMap.size
246
- ? pricesByAssetName
247
- : mapPrices(historicalPricesMap)
248
-
249
253
  if (fetchedPricesMap.size > 0) {
250
- await this.#setCache({ currency, granularity, pricesByAssetName })
254
+ const pricesByAssetNameForCache = mapPricesForCache(fetchedPricesMap, assetNames, assets)
255
+ await this.#setCache({
256
+ currency,
257
+ granularity,
258
+ pricesByAssetName: pricesByAssetNameForCache,
259
+ })
251
260
  }
252
261
 
262
+ const fullHistoryByAssetName = transformHistoricalPrices(
263
+ historicalPricesMap,
264
+ assetNames,
265
+ assets
266
+ )
267
+
253
268
  return {
254
- prices: transformPricesByAssetName(fullHistoryByAssetName),
269
+ prices: fullHistoryByAssetName,
255
270
  hasNewPrices: fetchedPricesMap.size > 0,
256
271
  }
257
272
  }
@@ -631,7 +646,9 @@ class MarketHistoryMonitor {
631
646
  })
632
647
 
633
648
  await this.#marketHistoryAtom.set(async (current) => {
634
- const transformedPrices = transformPriceEntries([...updatedAssetHistoryMap])
649
+ const transformedPrices = Object.fromEntries(
650
+ [...updatedAssetHistoryMap].map(([time, priceData]) => [time, priceData.close])
651
+ )
635
652
  const parsedGranularity = parseGranularity(granularity)
636
653
 
637
654
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/market-history",
3
- "version": "10.2.3",
3
+ "version": "10.2.4",
4
4
  "description": "Fetches historical prices for assets",
5
5
  "author": "Exodus Movement, Inc.",
6
6
  "license": "MIT",
@@ -59,5 +59,5 @@
59
59
  "publishConfig": {
60
60
  "access": "public"
61
61
  },
62
- "gitHead": "a75b31501250fd4a5001ee29eaf929c4dead9c44"
62
+ "gitHead": "724247d832b6972c09ecf018bbeac77d80829457"
63
63
  }