@exodus/market-history 10.7.0 → 10.7.1

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,10 @@
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.7.1](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/market-history@10.7.0...@exodus/market-history@10.7.1) (2026-05-04)
7
+
8
+ **Note:** Version bump only for package @exodus/market-history
9
+
6
10
  ## [10.7.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/market-history@10.6.3...@exodus/market-history@10.7.0) (2026-05-01)
7
11
 
8
12
  ### Features
@@ -3,7 +3,7 @@ import type { MarketHistoryState } from '../types.js';
3
3
  export declare const marketHistoryAtomDefinition: {
4
4
  readonly id: "marketHistoryAtom";
5
5
  readonly type: "atom";
6
- readonly factory: () => import("@exodus/atoms").Atom<MarketHistoryState>;
6
+ readonly factory: () => import("@exodus/atoms").Atom<MarketHistoryState | undefined>;
7
7
  readonly dependencies: readonly [];
8
8
  readonly public: true;
9
9
  };
@@ -0,0 +1,3 @@
1
+ export declare const DEFAULT_DAILY_REQUEST_LIMIT = 366;
2
+ export declare const DEFAULT_HOURLY_REQUEST_LIMIT: number;
3
+ export declare const DEFAULT_MINUTELY_REQUEST_LIMIT: number;
@@ -0,0 +1,3 @@
1
+ export const DEFAULT_DAILY_REQUEST_LIMIT = 366;
2
+ export const DEFAULT_HOURLY_REQUEST_LIMIT = 7 * 24;
3
+ export const DEFAULT_MINUTELY_REQUEST_LIMIT = 2 * 60;
package/lib/index.d.ts CHANGED
@@ -105,7 +105,7 @@ declare const marketHistory: ({ clearHistoryCacheDefaultValue, remoteConfigClear
105
105
  stop: () => void;
106
106
  hydrate: () => Promise<void>;
107
107
  };
108
- marketHistoryAtom: import("@exodus/atoms").Atom<import("./types.js").MarketHistoryState>;
108
+ marketHistoryAtom: import("@exodus/atoms").Atom<import("./types.js").MarketHistoryState | undefined>;
109
109
  appProcessAtom?: import("@exodus/atoms").ReadonlyAtom<{
110
110
  mode: string;
111
111
  }>;
@@ -126,7 +126,7 @@ declare const marketHistory: ({ clearHistoryCacheDefaultValue, remoteConfigClear
126
126
  definition: {
127
127
  readonly id: "marketHistoryAtom";
128
128
  readonly type: "atom";
129
- readonly factory: () => import("@exodus/atoms").Atom<import("./types.js").MarketHistoryState>;
129
+ readonly factory: () => import("@exodus/atoms").Atom<import("./types.js").MarketHistoryState | undefined>;
130
130
  readonly dependencies: readonly [];
131
131
  readonly public: true;
132
132
  };
package/lib/index.js CHANGED
@@ -3,11 +3,9 @@ import { marketHistoryAtomDefinition, marketHistoryClearCacheAtomDefinition, mar
3
3
  import marketHistoryMonitorDefinition from './module/index.js';
4
4
  import marketHistoryPluginDefinition from './plugin/index.js';
5
5
  import marketHistoryApiDefinition from './api/index.js';
6
+ import { DEFAULT_DAILY_REQUEST_LIMIT, DEFAULT_HOURLY_REQUEST_LIMIT, DEFAULT_MINUTELY_REQUEST_LIMIT, } from './constants.js';
6
7
  const CLEAR_MARKET_HISTORY_VERSION = 'infrastructure.marketHistory.clearVersion';
7
8
  const REFRESH_INTERVAL_ATOM_PATH = 'infrastructure.marketHistory.refreshInterval';
8
- const DEFAULT_DAILY_REQUEST_LIMIT = 366;
9
- const DEFAULT_HOURLY_REQUEST_LIMIT = 7 * 24;
10
- const DEFAULT_MINUTELY_REQUEST_LIMIT = 2 * 60;
11
9
  const marketHistory = ({ clearHistoryCacheDefaultValue = null, remoteConfigClearHistoryCachePath = CLEAR_MARKET_HISTORY_VERSION, remoteConfigClearHistoryCacheDefaultValue = null, marketHistoryRefreshIntervalPath = REFRESH_INTERVAL_ATOM_PATH, marketHistoryRefreshIntervalDefaultValue = null, dailyRequestLimit = DEFAULT_DAILY_REQUEST_LIMIT, hourlyRequestLimit = DEFAULT_HOURLY_REQUEST_LIMIT, minutelyRequestLimit = DEFAULT_MINUTELY_REQUEST_LIMIT, } = Object.create(null)) => {
12
10
  return {
13
11
  id: safeString `marketHistory`,
@@ -14,6 +14,6 @@ export default function fetchAndProcessTickers({ assetTickersToFetch, api, fiatT
14
14
  historicalPricesMap: Map<string, Map<number, PriceData>>;
15
15
  fetchedPricesMap: Map<string, Map<number, PriceData>>;
16
16
  specificTimestamp?: number | null;
17
- requestLimit?: number;
17
+ requestLimit: number;
18
18
  }): Promise<void>;
19
19
  export {};
@@ -5,7 +5,7 @@ export default function fetchHistoricalPrices({ api, assetTickers, fiatTicker, g
5
5
  fiatTicker: string;
6
6
  granularity?: Granularity;
7
7
  getCacheFromStorage: (ticker: string) => Promise<CacheEntry[] | string | undefined>;
8
- requestLimit?: number;
8
+ requestLimit: number;
9
9
  timestamp?: number;
10
10
  getCurrentTime?: () => number;
11
11
  ignoreInvalidSymbols?: boolean;
@@ -3,7 +3,7 @@ declare const getLimit: ({ granularity, history, requestLimit, requestTimestamp,
3
3
  granularity: Granularity;
4
4
  history: Map<number, PriceData>;
5
5
  requestTimestamp: number;
6
- requestLimit?: number;
6
+ requestLimit: number;
7
7
  specificTimestamp?: number | null;
8
8
  }) => number;
9
9
  export default getLimit;
@@ -1,21 +1,20 @@
1
- import { LIMIT, START_TIME } from './constants.js';
2
1
  import lastTimestampFromPricesMap from './last-timestamp-from-prices-map.js';
3
2
  import { timeToDays, timeToHours, timeToMinutes } from './utils.js';
3
+ const START_TIME = new Date('2015-12-09').getTime();
4
4
  const getLimit = ({ granularity, history, requestLimit, requestTimestamp, specificTimestamp, }) => {
5
5
  if (specificTimestamp)
6
6
  return 1;
7
7
  const lastCachedTime = lastTimestampFromPricesMap(history);
8
- const limitFromOptions = requestLimit || LIMIT[granularity];
9
8
  if (granularity === 'minute') {
10
9
  if (!lastCachedTime)
11
- return limitFromOptions;
12
- return Math.ceil(Math.min(limitFromOptions, timeToMinutes(requestTimestamp - lastCachedTime)));
10
+ return requestLimit;
11
+ return Math.ceil(Math.min(requestLimit, timeToMinutes(requestTimestamp - lastCachedTime)));
13
12
  }
14
13
  if (granularity === 'hour') {
15
14
  if (!lastCachedTime)
16
- return limitFromOptions;
17
- return Math.min(limitFromOptions, timeToHours(requestTimestamp - lastCachedTime));
15
+ return requestLimit;
16
+ return Math.min(requestLimit, timeToHours(requestTimestamp - lastCachedTime));
18
17
  }
19
- return Math.min(limitFromOptions, timeToDays(requestTimestamp - (lastCachedTime || START_TIME)));
18
+ return Math.min(requestLimit, timeToDays(requestTimestamp - (lastCachedTime || START_TIME)));
20
19
  };
21
20
  export default getLimit;
@@ -109,7 +109,7 @@ class MarketHistoryMonitorImpl {
109
109
  #runtimeCache = new Map();
110
110
  #marketHistoryAtom;
111
111
  #enabledAssetsAtom;
112
- #granularityRequestLimits = null;
112
+ #granularityRequestLimits;
113
113
  #logger;
114
114
  #abortController = new AbortController();
115
115
  #synchronizedTime;
@@ -138,6 +138,9 @@ class MarketHistoryMonitorImpl {
138
138
  this.#synchronizedTime = synchronizedTime;
139
139
  }
140
140
  #isActive = false;
141
+ #stillActive() {
142
+ return this.#isActive;
143
+ }
141
144
  #setCache = async ({ currency, granularity, pricesByAssetName, }) => {
142
145
  const assetNamesWithChanges = [];
143
146
  const changes = Object.create(null);
@@ -186,7 +189,7 @@ class MarketHistoryMonitorImpl {
186
189
  granularity,
187
190
  assetName: getAssetFromTicker(this.assetsModule.getAssets(), assetTicker).name,
188
191
  });
189
- #fetch = async ({ currency, granularity, assetNames, requestLimit, }) => {
192
+ #fetch = async ({ currency, granularity, assetNames, }) => {
190
193
  const assets = this.assetsModule.getAssets();
191
194
  const assetTickers = assetNames
192
195
  .filter((assetName) => !assets[assetName].isCombined)
@@ -219,7 +222,7 @@ class MarketHistoryMonitorImpl {
219
222
  ignoreCache,
220
223
  runtimeCache: this.#runtimeCache,
221
224
  getRuntimeCacheKey: ({ fiatTicker, granularity, assetTicker, }) => this.#getRuntimeCacheKey({ fiatTicker, granularity, assetTicker }),
222
- requestLimit: requestLimit || this.#granularityRequestLimits[granularity],
225
+ requestLimit: this.#granularityRequestLimits[granularity],
223
226
  });
224
227
  if (fetchedPricesMap.size > 0) {
225
228
  const pricesByAssetNameForCache = mapPricesForCache(fetchedPricesMap, assetNames, assets);
@@ -307,7 +310,7 @@ class MarketHistoryMonitorImpl {
307
310
  const currency = this.#currency;
308
311
  const promises = granularities.map((granularity) => this.#fetchPricesByGranularity({ granularity, assetNames, currency }));
309
312
  const results = await Promise.all(promises);
310
- if (!this.#isActive) {
313
+ if (!this.#stillActive()) {
311
314
  return;
312
315
  }
313
316
  await this.#marketHistoryAtom.set((current) => {
@@ -330,7 +333,7 @@ class MarketHistoryMonitorImpl {
330
333
  daily: Object.create(null),
331
334
  hourly: Object.create(null),
332
335
  minutely: Object.create(null),
333
- ...current?.data?.[currency],
336
+ ...current?.data[currency],
334
337
  },
335
338
  };
336
339
  granularities.forEach((granularity, index) => {
@@ -502,7 +505,7 @@ class MarketHistoryMonitorImpl {
502
505
  if (hydratedCount === 0)
503
506
  return;
504
507
  await this.#marketHistoryAtom.set((current) => {
505
- if (current?.data?.[currency])
508
+ if (current?.data[currency])
506
509
  return current;
507
510
  return {
508
511
  data: {
@@ -522,28 +525,28 @@ class MarketHistoryMonitorImpl {
522
525
  await this.hydrate().catch((error) => {
523
526
  this.#logger.error('market history hydrate failed', error);
524
527
  });
525
- if (!this.#isActive) {
528
+ if (!this.#stillActive()) {
526
529
  return;
527
530
  }
528
531
  const remoteConfigClearCacheVersion = await this.#remoteConfigClearCacheAtom.get();
529
532
  await this.#invalidateStorage({ remoteConfigClearCacheVersion });
530
- if (!this.#isActive) {
533
+ if (!this.#stillActive()) {
531
534
  return;
532
535
  }
533
536
  this.#currency = await this.#currencyAtom.get();
534
537
  this.#previouslyEnabledAssets = await this.#enabledAssetsAtom.get();
535
- if (!this.#isActive) {
538
+ if (!this.#stillActive()) {
536
539
  return;
537
540
  }
538
541
  await this.#initMarketHistoryAtom();
539
- if (!this.#isActive) {
542
+ if (!this.#stillActive()) {
540
543
  return;
541
544
  }
542
545
  this.#setupTimers();
543
546
  this.#listenRemoteConfigClearCacheVersionChanges();
544
547
  this.#listenCurrencyChanges();
545
548
  this.#listenEnabledAssetsChanges();
546
- if (!this.#isActive) {
549
+ if (!this.#stillActive()) {
547
550
  return;
548
551
  }
549
552
  await this.updateAll();
@@ -616,9 +619,9 @@ class MarketHistoryMonitorImpl {
616
619
  return {
617
620
  data: {
618
621
  [currency]: {
619
- ...current?.data?.[currency],
622
+ ...current?.data[currency],
620
623
  [parsedGranularity]: {
621
- ...current?.data?.[currency]?.[parsedGranularity],
624
+ ...current?.data[currency]?.[parsedGranularity],
622
625
  [assetName]: transformedPrices,
623
626
  },
624
627
  },
@@ -4,7 +4,7 @@ export default function prepareFetchInstructions({ tickerSymbol, fiatTicker, gra
4
4
  fiatTicker: string;
5
5
  granularity: Granularity;
6
6
  getCacheFromStorage: (ticker: string) => Promise<CacheEntry[] | string | undefined>;
7
- requestLimit?: number;
7
+ requestLimit: number;
8
8
  specificTimestamp?: number | null;
9
9
  ignoreCache: boolean;
10
10
  runtimeCache: Map<string, CacheEntry[]>;
@@ -8,5 +8,5 @@ export default function processApiResponse({ assetTicker, fiatTicker, fetchedPri
8
8
  historicalPricesMap: Map<string, Map<number, PriceData>>;
9
9
  granularity: Granularity;
10
10
  specificTimestamp?: number | null;
11
- requestLimit?: number;
11
+ requestLimit: number;
12
12
  }): Map<number, PriceData> | null;
@@ -7,7 +7,7 @@ type MarketHistoryMonitor = {
7
7
  };
8
8
  type Dependencies = {
9
9
  marketHistoryMonitor: MarketHistoryMonitor;
10
- marketHistoryAtom: Atom<MarketHistoryState>;
10
+ marketHistoryAtom: Atom<MarketHistoryState | undefined>;
11
11
  appProcessAtom?: ReadonlyAtom<{
12
12
  mode: string;
13
13
  }>;
package/lib/types.d.ts CHANGED
@@ -77,7 +77,7 @@ export type MarketHistoryMonitorDependencies = {
77
77
  clearCacheAtom?: Atom<string | null>;
78
78
  remoteConfigClearCacheAtom?: Atom<string | null>;
79
79
  enabledAssetsAtom: ReadonlyAtom<Record<string, Asset>>;
80
- marketHistoryAtom: Atom<MarketHistoryState>;
80
+ marketHistoryAtom: Atom<MarketHistoryState | undefined>;
81
81
  logger: Logger;
82
82
  config?: {
83
83
  granularityRequestLimits?: Record<Granularity, number>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/market-history",
3
- "version": "10.7.0",
3
+ "version": "10.7.1",
4
4
  "description": "Fetches historical prices for assets",
5
5
  "author": "Exodus Movement, Inc.",
6
6
  "license": "MIT",
@@ -17,8 +17,13 @@
17
17
  "main": "lib/index.js",
18
18
  "types": "lib/index.d.ts",
19
19
  "typings": "lib/index.d.ts",
20
+ "exports": {
21
+ ".": "./lib/index.js",
22
+ "./redux": "./lib/redux/index.js"
23
+ },
20
24
  "files": [
21
25
  "lib",
26
+ "redux.js",
22
27
  "CHANGELOG.md",
23
28
  "README.md"
24
29
  ],
@@ -44,7 +49,7 @@
44
49
  "@exodus/locale": "^2.7.0",
45
50
  "@exodus/logger": "^1.2.3",
46
51
  "@exodus/rates-monitor": "^4.14.8",
47
- "@exodus/redux-dependency-injection": "^4.4.0",
52
+ "@exodus/redux-dependency-injection": "^4.5.0",
48
53
  "@exodus/storage-memory": "^2.4.0",
49
54
  "events": "^3.3.0",
50
55
  "redux": "^4.0.0"
@@ -61,5 +66,5 @@
61
66
  "access": "public",
62
67
  "provenance": false
63
68
  },
64
- "gitHead": "15750a8f551c1d4d869c6a133f1c5199c6dcfa93"
69
+ "gitHead": "ef035f3c387767ab37076ad2d2dfb8be62f19ea6"
65
70
  }
package/redux.js ADDED
@@ -0,0 +1,2 @@
1
+ // eslint-disable-next-line import/no-unresolved -- shim re-exports built artifact
2
+ export { default } from './lib/redux/index.js'
@@ -1,2 +0,0 @@
1
- export declare const LIMIT: Record<string, number>;
2
- export declare const START_TIME: number;
@@ -1,9 +0,0 @@
1
- const HOURLY_LIMIT = 24 * 7;
2
- const DAILY_LIMIT = 3000;
3
- const MINUTE_LIMIT = 60 * 2;
4
- export const LIMIT = {
5
- minute: MINUTE_LIMIT,
6
- hour: HOURLY_LIMIT,
7
- day: DAILY_LIMIT,
8
- };
9
- export const START_TIME = new Date('2015-12-09').getTime();