@exodus/market-history 10.6.3 → 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 +10 -0
- package/lib/atoms/index.d.ts +1 -1
- package/lib/constants.d.ts +3 -0
- package/lib/constants.js +3 -0
- package/lib/index.d.ts +6 -5
- package/lib/index.js +1 -3
- package/lib/module/fetch-and-process-tickers.d.ts +1 -1
- package/lib/module/fetch-historical-prices.d.ts +1 -1
- package/lib/module/get-limit-to-fetch.d.ts +1 -1
- package/lib/module/get-limit-to-fetch.js +6 -7
- package/lib/module/index.js +100 -20
- package/lib/module/prepare-fetch-instructions.d.ts +1 -1
- package/lib/module/process-api-response.d.ts +1 -1
- package/lib/plugin/index.d.ts +3 -2
- package/lib/plugin/index.js +5 -2
- package/lib/types.d.ts +3 -1
- package/package.json +13 -8
- package/redux.js +2 -0
- package/lib/module/constants.d.ts +0 -2
- package/lib/module/constants.js +0 -9
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,16 @@
|
|
|
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
|
+
|
|
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)
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
- feat(market-history): hydrate prices from cache on start (#16273)
|
|
15
|
+
|
|
6
16
|
## [10.6.3](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/market-history@10.6.2...@exodus/market-history@10.6.3) (2026-04-08)
|
|
7
17
|
|
|
8
18
|
### Bug Fixes
|
package/lib/atoms/index.d.ts
CHANGED
|
@@ -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
|
};
|
package/lib/constants.js
ADDED
package/lib/index.d.ts
CHANGED
|
@@ -62,7 +62,7 @@ declare const marketHistory: ({ clearHistoryCacheDefaultValue, remoteConfigClear
|
|
|
62
62
|
path: string;
|
|
63
63
|
defaultValue: string | null;
|
|
64
64
|
};
|
|
65
|
-
remoteConfig: import("
|
|
65
|
+
remoteConfig: import("@exodus/remote-config").RemoteConfigType;
|
|
66
66
|
}) => import("@exodus/atoms").ReadonlyAtom<string | null>;
|
|
67
67
|
readonly dependencies: readonly ["config", "remoteConfig"];
|
|
68
68
|
readonly public: true;
|
|
@@ -83,7 +83,7 @@ declare const marketHistory: ({ clearHistoryCacheDefaultValue, remoteConfigClear
|
|
|
83
83
|
path: string;
|
|
84
84
|
defaultValue: number | null;
|
|
85
85
|
};
|
|
86
|
-
remoteConfig: import("
|
|
86
|
+
remoteConfig: import("@exodus/remote-config").RemoteConfigType;
|
|
87
87
|
}) => import("@exodus/atoms").ReadonlyAtom<number | null>;
|
|
88
88
|
readonly dependencies: readonly ["config", "remoteConfig"];
|
|
89
89
|
readonly public: true;
|
|
@@ -103,16 +103,17 @@ declare const marketHistory: ({ clearHistoryCacheDefaultValue, remoteConfigClear
|
|
|
103
103
|
marketHistoryMonitor: {
|
|
104
104
|
start: () => Promise<void>;
|
|
105
105
|
stop: () => void;
|
|
106
|
+
hydrate: () => Promise<void>;
|
|
106
107
|
};
|
|
107
|
-
marketHistoryAtom: import("@exodus/atoms").Atom<import("./types.js").MarketHistoryState>;
|
|
108
|
+
marketHistoryAtom: import("@exodus/atoms").Atom<import("./types.js").MarketHistoryState | undefined>;
|
|
108
109
|
appProcessAtom?: import("@exodus/atoms").ReadonlyAtom<{
|
|
109
110
|
mode: string;
|
|
110
111
|
}>;
|
|
111
112
|
port: import("./types.js").MarketHistoryPort;
|
|
112
113
|
errorTracking: import("./types.js").ErrorTracking;
|
|
113
114
|
}) => {
|
|
115
|
+
onStart: () => void;
|
|
114
116
|
onUnlock: () => void;
|
|
115
|
-
onLoad: () => void;
|
|
116
117
|
onStop: () => void;
|
|
117
118
|
};
|
|
118
119
|
readonly dependencies: readonly ["marketHistoryMonitor", "marketHistoryAtom", "appProcessAtom?", "port", "errorTracking"];
|
|
@@ -125,7 +126,7 @@ declare const marketHistory: ({ clearHistoryCacheDefaultValue, remoteConfigClear
|
|
|
125
126
|
definition: {
|
|
126
127
|
readonly id: "marketHistoryAtom";
|
|
127
128
|
readonly type: "atom";
|
|
128
|
-
readonly factory: () => import("@exodus/atoms").Atom<import("./types.js").MarketHistoryState>;
|
|
129
|
+
readonly factory: () => import("@exodus/atoms").Atom<import("./types.js").MarketHistoryState | undefined>;
|
|
129
130
|
readonly dependencies: readonly [];
|
|
130
131
|
readonly public: true;
|
|
131
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
|
|
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
|
|
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
|
|
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
|
|
12
|
-
return Math.ceil(Math.min(
|
|
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
|
|
17
|
-
return Math.min(
|
|
15
|
+
return requestLimit;
|
|
16
|
+
return Math.min(requestLimit, timeToHours(requestTimestamp - lastCachedTime));
|
|
18
17
|
}
|
|
19
|
-
return Math.min(
|
|
18
|
+
return Math.min(requestLimit, timeToDays(requestTimestamp - (lastCachedTime || START_TIME)));
|
|
20
19
|
};
|
|
21
20
|
export default getLimit;
|
package/lib/module/index.js
CHANGED
|
@@ -109,7 +109,7 @@ class MarketHistoryMonitorImpl {
|
|
|
109
109
|
#runtimeCache = new Map();
|
|
110
110
|
#marketHistoryAtom;
|
|
111
111
|
#enabledAssetsAtom;
|
|
112
|
-
#granularityRequestLimits
|
|
112
|
+
#granularityRequestLimits;
|
|
113
113
|
#logger;
|
|
114
114
|
#abortController = new AbortController();
|
|
115
115
|
#synchronizedTime;
|
|
@@ -138,22 +138,42 @@ 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
|
-
|
|
143
|
-
const changes = Object.
|
|
144
|
-
|
|
145
|
+
const assetNamesWithChanges = [];
|
|
146
|
+
const changes = Object.create(null);
|
|
147
|
+
for (const assetName of Object.keys(pricesByAssetName)) {
|
|
145
148
|
const values = pricesByAssetName[assetName];
|
|
146
149
|
if (values.length > 0) {
|
|
147
|
-
|
|
148
|
-
|
|
150
|
+
const key = this.#getCacheKey({ currency, assetName, granularity });
|
|
151
|
+
assetNamesWithChanges.push(assetName);
|
|
152
|
+
changes[key] = values;
|
|
149
153
|
this.#runtimeCache.set(key, values);
|
|
150
154
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
if (!hasChanges)
|
|
155
|
+
}
|
|
156
|
+
if (assetNamesWithChanges.length === 0)
|
|
154
157
|
return;
|
|
155
158
|
await this.storage.batchSet(changes);
|
|
159
|
+
await this.#extendCacheIndex(currency, assetNamesWithChanges);
|
|
156
160
|
};
|
|
161
|
+
#cacheIndexKey = (currency) => `cached-assets-${currency}`;
|
|
162
|
+
#extendCacheIndex = makeConcurrent(async (currency, addedAssetNames) => {
|
|
163
|
+
const indexKey = this.#cacheIndexKey(currency);
|
|
164
|
+
const existing = ((await this.storage.get(indexKey)) || []);
|
|
165
|
+
const existingSet = new Set(existing);
|
|
166
|
+
let added = 0;
|
|
167
|
+
for (const name of addedAssetNames) {
|
|
168
|
+
if (!existingSet.has(name)) {
|
|
169
|
+
existingSet.add(name);
|
|
170
|
+
added += 1;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (added === 0)
|
|
174
|
+
return;
|
|
175
|
+
await this.storage.set(indexKey, [...existingSet]);
|
|
176
|
+
}, { concurrency: 1 });
|
|
157
177
|
#getCache = async ({ currency, granularity, assetName, }) => {
|
|
158
178
|
const key = this.#getCacheKey({ currency, assetName, granularity });
|
|
159
179
|
const cachedValue = this.#runtimeCache.get(key);
|
|
@@ -169,7 +189,7 @@ class MarketHistoryMonitorImpl {
|
|
|
169
189
|
granularity,
|
|
170
190
|
assetName: getAssetFromTicker(this.assetsModule.getAssets(), assetTicker).name,
|
|
171
191
|
});
|
|
172
|
-
#fetch = async ({ currency, granularity, assetNames,
|
|
192
|
+
#fetch = async ({ currency, granularity, assetNames, }) => {
|
|
173
193
|
const assets = this.assetsModule.getAssets();
|
|
174
194
|
const assetTickers = assetNames
|
|
175
195
|
.filter((assetName) => !assets[assetName].isCombined)
|
|
@@ -202,7 +222,7 @@ class MarketHistoryMonitorImpl {
|
|
|
202
222
|
ignoreCache,
|
|
203
223
|
runtimeCache: this.#runtimeCache,
|
|
204
224
|
getRuntimeCacheKey: ({ fiatTicker, granularity, assetTicker, }) => this.#getRuntimeCacheKey({ fiatTicker, granularity, assetTicker }),
|
|
205
|
-
requestLimit:
|
|
225
|
+
requestLimit: this.#granularityRequestLimits[granularity],
|
|
206
226
|
});
|
|
207
227
|
if (fetchedPricesMap.size > 0) {
|
|
208
228
|
const pricesByAssetNameForCache = mapPricesForCache(fetchedPricesMap, assetNames, assets);
|
|
@@ -290,7 +310,7 @@ class MarketHistoryMonitorImpl {
|
|
|
290
310
|
const currency = this.#currency;
|
|
291
311
|
const promises = granularities.map((granularity) => this.#fetchPricesByGranularity({ granularity, assetNames, currency }));
|
|
292
312
|
const results = await Promise.all(promises);
|
|
293
|
-
if (!this.#
|
|
313
|
+
if (!this.#stillActive()) {
|
|
294
314
|
return;
|
|
295
315
|
}
|
|
296
316
|
await this.#marketHistoryAtom.set((current) => {
|
|
@@ -313,7 +333,7 @@ class MarketHistoryMonitorImpl {
|
|
|
313
333
|
daily: Object.create(null),
|
|
314
334
|
hourly: Object.create(null),
|
|
315
335
|
minutely: Object.create(null),
|
|
316
|
-
...current?.data
|
|
336
|
+
...current?.data[currency],
|
|
317
337
|
},
|
|
318
338
|
};
|
|
319
339
|
granularities.forEach((granularity, index) => {
|
|
@@ -396,7 +416,7 @@ class MarketHistoryMonitorImpl {
|
|
|
396
416
|
this.#logger.info('market history update because currency changes', currency);
|
|
397
417
|
this.#currency = currency;
|
|
398
418
|
void this.#marketHistoryAtom.set((current) => {
|
|
399
|
-
const data = current?.data ||
|
|
419
|
+
const data = current?.data || Object.create(null);
|
|
400
420
|
return {
|
|
401
421
|
data: {
|
|
402
422
|
...data,
|
|
@@ -442,31 +462,91 @@ class MarketHistoryMonitorImpl {
|
|
|
442
462
|
};
|
|
443
463
|
});
|
|
444
464
|
};
|
|
465
|
+
#hydratePromise = null;
|
|
466
|
+
hydrate = () => {
|
|
467
|
+
this.#hydratePromise ??= this.#performHydrate();
|
|
468
|
+
return this.#hydratePromise;
|
|
469
|
+
};
|
|
470
|
+
#performHydrate = async () => {
|
|
471
|
+
const currency = await this.#currencyAtom.get();
|
|
472
|
+
const indexed = ((await this.storage.get(this.#cacheIndexKey(currency))) || []);
|
|
473
|
+
if (indexed.length === 0)
|
|
474
|
+
return;
|
|
475
|
+
const granularities = ['day', 'hour', 'minute'];
|
|
476
|
+
const keys = [];
|
|
477
|
+
const meta = [];
|
|
478
|
+
for (const assetName of indexed) {
|
|
479
|
+
for (const granularity of granularities) {
|
|
480
|
+
keys.push(this.#getCacheKey({ currency, assetName, granularity }));
|
|
481
|
+
meta.push({ assetName, granularity });
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
const results = (await this.storage.batchGet(keys));
|
|
485
|
+
const granularityPrices = {
|
|
486
|
+
daily: Object.create(null),
|
|
487
|
+
hourly: Object.create(null),
|
|
488
|
+
minutely: Object.create(null),
|
|
489
|
+
};
|
|
490
|
+
let hydratedCount = 0;
|
|
491
|
+
results.forEach((cacheEntries, index) => {
|
|
492
|
+
if (!cacheEntries || cacheEntries.length === 0)
|
|
493
|
+
return;
|
|
494
|
+
const { assetName, granularity } = meta[index];
|
|
495
|
+
const key = keys[index];
|
|
496
|
+
this.#runtimeCache.set(key, cacheEntries);
|
|
497
|
+
const priceRecord = new Map();
|
|
498
|
+
for (const [time, { close }] of cacheEntries) {
|
|
499
|
+
priceRecord.set(time, close);
|
|
500
|
+
}
|
|
501
|
+
const parsedGranularity = parseGranularity(granularity);
|
|
502
|
+
granularityPrices[parsedGranularity][assetName] = priceRecord;
|
|
503
|
+
hydratedCount += 1;
|
|
504
|
+
});
|
|
505
|
+
if (hydratedCount === 0)
|
|
506
|
+
return;
|
|
507
|
+
await this.#marketHistoryAtom.set((current) => {
|
|
508
|
+
if (current?.data[currency])
|
|
509
|
+
return current;
|
|
510
|
+
return {
|
|
511
|
+
data: {
|
|
512
|
+
...current?.data,
|
|
513
|
+
[currency]: granularityPrices,
|
|
514
|
+
},
|
|
515
|
+
};
|
|
516
|
+
});
|
|
517
|
+
this.#logger.info(`market history hydrated from cache (currency=${currency})`);
|
|
518
|
+
};
|
|
445
519
|
start = makeConcurrent(async () => {
|
|
446
520
|
if (this.#isActive)
|
|
447
521
|
return;
|
|
448
522
|
this.#logger.info('market history start');
|
|
449
523
|
this.#isActive = true;
|
|
450
524
|
this.#abortController = new AbortController();
|
|
525
|
+
await this.hydrate().catch((error) => {
|
|
526
|
+
this.#logger.error('market history hydrate failed', error);
|
|
527
|
+
});
|
|
528
|
+
if (!this.#stillActive()) {
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
451
531
|
const remoteConfigClearCacheVersion = await this.#remoteConfigClearCacheAtom.get();
|
|
452
532
|
await this.#invalidateStorage({ remoteConfigClearCacheVersion });
|
|
453
|
-
if (!this.#
|
|
533
|
+
if (!this.#stillActive()) {
|
|
454
534
|
return;
|
|
455
535
|
}
|
|
456
536
|
this.#currency = await this.#currencyAtom.get();
|
|
457
537
|
this.#previouslyEnabledAssets = await this.#enabledAssetsAtom.get();
|
|
458
|
-
if (!this.#
|
|
538
|
+
if (!this.#stillActive()) {
|
|
459
539
|
return;
|
|
460
540
|
}
|
|
461
541
|
await this.#initMarketHistoryAtom();
|
|
462
|
-
if (!this.#
|
|
542
|
+
if (!this.#stillActive()) {
|
|
463
543
|
return;
|
|
464
544
|
}
|
|
465
545
|
this.#setupTimers();
|
|
466
546
|
this.#listenRemoteConfigClearCacheVersionChanges();
|
|
467
547
|
this.#listenCurrencyChanges();
|
|
468
548
|
this.#listenEnabledAssetsChanges();
|
|
469
|
-
if (!this.#
|
|
549
|
+
if (!this.#stillActive()) {
|
|
470
550
|
return;
|
|
471
551
|
}
|
|
472
552
|
await this.updateAll();
|
|
@@ -539,9 +619,9 @@ class MarketHistoryMonitorImpl {
|
|
|
539
619
|
return {
|
|
540
620
|
data: {
|
|
541
621
|
[currency]: {
|
|
542
|
-
...current?.data
|
|
622
|
+
...current?.data[currency],
|
|
543
623
|
[parsedGranularity]: {
|
|
544
|
-
...current?.data
|
|
624
|
+
...current?.data[currency]?.[parsedGranularity],
|
|
545
625
|
[assetName]: transformedPrices,
|
|
546
626
|
},
|
|
547
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
|
|
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
|
|
11
|
+
requestLimit: number;
|
|
12
12
|
}): Map<number, PriceData> | null;
|
package/lib/plugin/index.d.ts
CHANGED
|
@@ -3,10 +3,11 @@ import type { ErrorTracking, MarketHistoryPort, MarketHistoryState } from '../ty
|
|
|
3
3
|
type MarketHistoryMonitor = {
|
|
4
4
|
start: () => Promise<void>;
|
|
5
5
|
stop: () => void;
|
|
6
|
+
hydrate: () => Promise<void>;
|
|
6
7
|
};
|
|
7
8
|
type Dependencies = {
|
|
8
9
|
marketHistoryMonitor: MarketHistoryMonitor;
|
|
9
|
-
marketHistoryAtom: Atom<MarketHistoryState>;
|
|
10
|
+
marketHistoryAtom: Atom<MarketHistoryState | undefined>;
|
|
10
11
|
appProcessAtom?: ReadonlyAtom<{
|
|
11
12
|
mode: string;
|
|
12
13
|
}>;
|
|
@@ -17,8 +18,8 @@ declare const marketHistoryLifecyclePluginDefinition: {
|
|
|
17
18
|
readonly id: "marketHistoryLifecyclePlugin";
|
|
18
19
|
readonly type: "plugin";
|
|
19
20
|
readonly factory: ({ marketHistoryMonitor, marketHistoryAtom, appProcessAtom, port, errorTracking, }: Dependencies) => {
|
|
21
|
+
onStart: () => void;
|
|
20
22
|
onUnlock: () => void;
|
|
21
|
-
onLoad: () => void;
|
|
22
23
|
onStop: () => void;
|
|
23
24
|
};
|
|
24
25
|
readonly dependencies: readonly ["marketHistoryMonitor", "marketHistoryAtom", "appProcessAtom?", "port", "errorTracking"];
|
package/lib/plugin/index.js
CHANGED
|
@@ -19,8 +19,11 @@ const createMarketHistoryLifecyclePlugin = ({ marketHistoryMonitor, marketHistor
|
|
|
19
19
|
previousMode = mode;
|
|
20
20
|
});
|
|
21
21
|
};
|
|
22
|
-
const
|
|
22
|
+
const onStart = () => {
|
|
23
23
|
void observer.start();
|
|
24
|
+
marketHistoryMonitor.hydrate().catch((e) => {
|
|
25
|
+
errorTracking.track({ error: e, context: 'start' });
|
|
26
|
+
});
|
|
24
27
|
};
|
|
25
28
|
const onUnlock = () => {
|
|
26
29
|
const nonBlockingStart = async () => {
|
|
@@ -40,7 +43,7 @@ const createMarketHistoryLifecyclePlugin = ({ marketHistoryMonitor, marketHistor
|
|
|
40
43
|
unobserve?.();
|
|
41
44
|
marketHistoryMonitor.stop();
|
|
42
45
|
};
|
|
43
|
-
return {
|
|
46
|
+
return { onStart, onUnlock, onStop };
|
|
44
47
|
};
|
|
45
48
|
const marketHistoryLifecyclePluginDefinition = {
|
|
46
49
|
id: 'marketHistoryLifecyclePlugin',
|
package/lib/types.d.ts
CHANGED
|
@@ -56,6 +56,7 @@ export type MarketHistoryStorage = {
|
|
|
56
56
|
get: (key: string) => Promise<unknown>;
|
|
57
57
|
set: (key: string, value: unknown) => Promise<void>;
|
|
58
58
|
clear: () => Promise<void>;
|
|
59
|
+
batchGet: (keys: string[]) => Promise<unknown[]>;
|
|
59
60
|
batchSet: (changes: Record<string, CacheEntry[]>) => Promise<void>;
|
|
60
61
|
};
|
|
61
62
|
export type AssetsModule = {
|
|
@@ -76,7 +77,7 @@ export type MarketHistoryMonitorDependencies = {
|
|
|
76
77
|
clearCacheAtom?: Atom<string | null>;
|
|
77
78
|
remoteConfigClearCacheAtom?: Atom<string | null>;
|
|
78
79
|
enabledAssetsAtom: ReadonlyAtom<Record<string, Asset>>;
|
|
79
|
-
marketHistoryAtom: Atom<MarketHistoryState>;
|
|
80
|
+
marketHistoryAtom: Atom<MarketHistoryState | undefined>;
|
|
80
81
|
logger: Logger;
|
|
81
82
|
config?: {
|
|
82
83
|
granularityRequestLimits?: Record<Granularity, number>;
|
|
@@ -89,6 +90,7 @@ export type MarketHistoryMonitorDependencies = {
|
|
|
89
90
|
export type MarketHistoryMonitor = {
|
|
90
91
|
start: () => Promise<void>;
|
|
91
92
|
stop: () => void;
|
|
93
|
+
hydrate: () => Promise<void>;
|
|
92
94
|
update: (granularity: Granularity) => Promise<void>;
|
|
93
95
|
updateAll: () => Promise<void>;
|
|
94
96
|
fetchAssetPricesFromDate: (params: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/market-history",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.7.1",
|
|
4
4
|
"description": "Fetches historical prices for assets",
|
|
5
5
|
"author": "Exodus Movement, Inc.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -17,14 +17,19 @@
|
|
|
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
|
],
|
|
25
30
|
"dependencies": {
|
|
26
|
-
"@exodus/atoms": "^
|
|
27
|
-
"@exodus/basic-utils": "^
|
|
31
|
+
"@exodus/atoms": "^10.3.3",
|
|
32
|
+
"@exodus/basic-utils": "^5.0.0",
|
|
28
33
|
"@exodus/dayjs": "^1.0.2",
|
|
29
34
|
"@exodus/remote-config": "^3.5.1",
|
|
30
35
|
"@exodus/remote-config-atoms": "^1.1.0",
|
|
@@ -36,15 +41,15 @@
|
|
|
36
41
|
},
|
|
37
42
|
"devDependencies": {
|
|
38
43
|
"@exodus/assets": "^11.0.0",
|
|
39
|
-
"@exodus/assets-base": "^
|
|
40
|
-
"@exodus/assets-feature": "^9.
|
|
44
|
+
"@exodus/assets-base": "^12.0.0",
|
|
45
|
+
"@exodus/assets-feature": "^9.2.2",
|
|
41
46
|
"@exodus/bitcoin-meta": "^2.0.0",
|
|
42
47
|
"@exodus/dependency-types": "^2.1.1",
|
|
43
48
|
"@exodus/ethereum-meta": "^2.4.1",
|
|
44
|
-
"@exodus/locale": "^2.
|
|
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.
|
|
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": "
|
|
69
|
+
"gitHead": "ef035f3c387767ab37076ad2d2dfb8be62f19ea6"
|
|
65
70
|
}
|
package/redux.js
ADDED
package/lib/module/constants.js
DELETED