@ledgerhq/live-countervalues 0.1.0

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.
Files changed (99) hide show
  1. package/.eslintrc.js +33 -0
  2. package/.turbo/turbo-build.log +4 -0
  3. package/.unimportedrc.json +4 -0
  4. package/CHANGELOG.md +1 -0
  5. package/LICENSE.txt +21 -0
  6. package/jest-global-setup.js +9 -0
  7. package/jest.config.js +14 -0
  8. package/lib/api/api.d.ts +4 -0
  9. package/lib/api/api.d.ts.map +1 -0
  10. package/lib/api/api.js +82 -0
  11. package/lib/api/api.js.map +1 -0
  12. package/lib/api/api.mock.d.ts +4 -0
  13. package/lib/api/api.mock.d.ts.map +1 -0
  14. package/lib/api/api.mock.js +103 -0
  15. package/lib/api/api.mock.js.map +1 -0
  16. package/lib/api/index.d.ts +4 -0
  17. package/lib/api/index.d.ts.map +1 -0
  18. package/lib/api/index.js +19 -0
  19. package/lib/api/index.js.map +1 -0
  20. package/lib/helpers.d.ts +31 -0
  21. package/lib/helpers.d.ts.map +1 -0
  22. package/lib/helpers.js +77 -0
  23. package/lib/helpers.js.map +1 -0
  24. package/lib/logic.d.ts +40 -0
  25. package/lib/logic.d.ts.map +1 -0
  26. package/lib/logic.integration.test.d.ts +2 -0
  27. package/lib/logic.integration.test.d.ts.map +1 -0
  28. package/lib/logic.integration.test.js +191 -0
  29. package/lib/logic.integration.test.js.map +1 -0
  30. package/lib/logic.js +422 -0
  31. package/lib/logic.js.map +1 -0
  32. package/lib/logic.test.d.ts +2 -0
  33. package/lib/logic.test.d.ts.map +1 -0
  34. package/lib/logic.test.js +29 -0
  35. package/lib/logic.test.js.map +1 -0
  36. package/lib/mock.d.ts +4 -0
  37. package/lib/mock.d.ts.map +1 -0
  38. package/lib/mock.js +10 -0
  39. package/lib/mock.js.map +1 -0
  40. package/lib/mock.test.d.ts +2 -0
  41. package/lib/mock.test.d.ts.map +1 -0
  42. package/lib/mock.test.js +210 -0
  43. package/lib/mock.test.js.map +1 -0
  44. package/lib/types.d.ts +47 -0
  45. package/lib/types.d.ts.map +1 -0
  46. package/lib/types.js +4 -0
  47. package/lib/types.js.map +1 -0
  48. package/lib-es/api/api.d.ts +4 -0
  49. package/lib-es/api/api.d.ts.map +1 -0
  50. package/lib-es/api/api.js +77 -0
  51. package/lib-es/api/api.js.map +1 -0
  52. package/lib-es/api/api.mock.d.ts +4 -0
  53. package/lib-es/api/api.mock.d.ts.map +1 -0
  54. package/lib-es/api/api.mock.js +98 -0
  55. package/lib-es/api/api.mock.js.map +1 -0
  56. package/lib-es/api/index.d.ts +4 -0
  57. package/lib-es/api/index.d.ts.map +1 -0
  58. package/lib-es/api/index.js +14 -0
  59. package/lib-es/api/index.js.map +1 -0
  60. package/lib-es/helpers.d.ts +31 -0
  61. package/lib-es/helpers.d.ts.map +1 -0
  62. package/lib-es/helpers.js +67 -0
  63. package/lib-es/helpers.js.map +1 -0
  64. package/lib-es/logic.d.ts +40 -0
  65. package/lib-es/logic.d.ts.map +1 -0
  66. package/lib-es/logic.integration.test.d.ts +2 -0
  67. package/lib-es/logic.integration.test.d.ts.map +1 -0
  68. package/lib-es/logic.integration.test.js +186 -0
  69. package/lib-es/logic.integration.test.js.map +1 -0
  70. package/lib-es/logic.js +406 -0
  71. package/lib-es/logic.js.map +1 -0
  72. package/lib-es/logic.test.d.ts +2 -0
  73. package/lib-es/logic.test.d.ts.map +1 -0
  74. package/lib-es/logic.test.js +27 -0
  75. package/lib-es/logic.test.js.map +1 -0
  76. package/lib-es/mock.d.ts +4 -0
  77. package/lib-es/mock.d.ts.map +1 -0
  78. package/lib-es/mock.js +6 -0
  79. package/lib-es/mock.js.map +1 -0
  80. package/lib-es/mock.test.d.ts +2 -0
  81. package/lib-es/mock.test.d.ts.map +1 -0
  82. package/lib-es/mock.test.js +205 -0
  83. package/lib-es/mock.test.js.map +1 -0
  84. package/lib-es/types.d.ts +47 -0
  85. package/lib-es/types.d.ts.map +1 -0
  86. package/lib-es/types.js +3 -0
  87. package/lib-es/types.js.map +1 -0
  88. package/package.json +81 -0
  89. package/src/api/api.mock.ts +117 -0
  90. package/src/api/api.ts +79 -0
  91. package/src/api/index.ts +19 -0
  92. package/src/helpers.ts +82 -0
  93. package/src/logic.integration.test.ts +209 -0
  94. package/src/logic.test.ts +30 -0
  95. package/src/logic.ts +533 -0
  96. package/src/mock.test.ts +231 -0
  97. package/src/mock.ts +8 -0
  98. package/src/types.ts +70 -0
  99. package/tsconfig.json +15 -0
@@ -0,0 +1,406 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ var __rest = (this && this.__rest) || function (s, e) {
11
+ var t = {};
12
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
13
+ t[p] = s[p];
14
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
15
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
16
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
17
+ t[p[i]] = s[p[i]];
18
+ }
19
+ return t;
20
+ };
21
+ import { log } from "@ledgerhq/logs";
22
+ import { flattenAccounts, getAccountCurrency, isAccountEmpty, } from "@ledgerhq/coin-framework/account/helpers";
23
+ import { promiseAllBatched } from "@ledgerhq/live-promise";
24
+ import { pairId, magFromTo, formatPerGranularity, formatCounterValueDay, formatCounterValueHashes, parseFormattedDate, incrementPerGranularity, datapointLimits, } from "./helpers";
25
+ import api from "./api";
26
+ // yield raw version of the countervalues state to be saved in a db
27
+ export function exportCountervalues({ data, status }) {
28
+ const out = { status };
29
+ for (const path in data) {
30
+ const obj = {};
31
+ for (const [k, v] of data[path]) {
32
+ obj[k] = v;
33
+ }
34
+ out[path] = obj;
35
+ }
36
+ return out;
37
+ }
38
+ // restore a countervalues state from the raw version
39
+ export function importCountervalues(_a, settings) {
40
+ var { status } = _a, rest = __rest(_a, ["status"]);
41
+ const data = {};
42
+ for (const path in rest) {
43
+ const obj = rest[path];
44
+ const map = new Map();
45
+ for (const k in obj) {
46
+ map.set(k, obj[k]);
47
+ }
48
+ data[path] = map;
49
+ }
50
+ return {
51
+ data,
52
+ status,
53
+ cache: Object.entries(data).reduce((prev, [key, val]) => (Object.assign(Object.assign({}, prev), {
54
+ // $FlowFixMe
55
+ [key]: generateCache(key, val, settings) })), {}),
56
+ };
57
+ }
58
+ // infer the tracking pair from user accounts to know which pairs are concerned
59
+ export function inferTrackingPairForAccounts(accounts, countervalue) {
60
+ const yearAgo = new Date();
61
+ yearAgo.setFullYear(yearAgo.getFullYear() - 1);
62
+ yearAgo.setHours(0, 0, 0, 0);
63
+ return resolveTrackingPairs(flattenAccounts(accounts)
64
+ .filter(a => !isAccountEmpty(a))
65
+ .map(account => {
66
+ const currency = getAccountCurrency(account);
67
+ return {
68
+ from: currency,
69
+ to: countervalue,
70
+ startDate: account.creationDate < yearAgo ? account.creationDate : yearAgo,
71
+ };
72
+ }));
73
+ }
74
+ /**
75
+ * yield the ids of the tracking pairs as stored in the database
76
+ */
77
+ export function trackingPairIds(trackingPairs) {
78
+ return trackingPairs.map(pairId);
79
+ }
80
+ export const initialState = {
81
+ data: {},
82
+ status: {},
83
+ cache: {},
84
+ };
85
+ const MAX_RETRY_DELAY = 7 * incrementPerGranularity.daily;
86
+ // synchronize all countervalues incrementally (async update of the countervalues state)
87
+ export function loadCountervalues(state, settings) {
88
+ return __awaiter(this, void 0, void 0, function* () {
89
+ const data = Object.assign({}, state.data);
90
+ const cache = Object.assign({}, state.cache);
91
+ const status = Object.assign({}, state.status);
92
+ const nowDate = new Date();
93
+ const latestToFetch = settings.trackingPairs;
94
+ // determines what historical data need to be fetched
95
+ const histoToFetch = [];
96
+ const rateGranularities = ["daily", "hourly"];
97
+ rateGranularities.forEach((granularity) => {
98
+ const format = formatPerGranularity[granularity];
99
+ const earliestHisto = format(nowDate);
100
+ log("countervalues", "earliestHisto=" + earliestHisto);
101
+ const limit = datapointLimits[granularity];
102
+ settings.trackingPairs.forEach(({ from, to, startDate }) => {
103
+ const key = pairId({
104
+ from,
105
+ to,
106
+ });
107
+ const c = cache[key];
108
+ const stats = c === null || c === void 0 ? void 0 : c.stats;
109
+ const s = status[key];
110
+ // when there are too much http failures, slow down the rate to be actually re-fetched
111
+ if ((s === null || s === void 0 ? void 0 : s.failures) && s.timestamp) {
112
+ const { failures, timestamp } = s;
113
+ const secondsBetweenRetries = Math.min(Math.exp(failures * 0.5), MAX_RETRY_DELAY);
114
+ const nextTarget = timestamp + 1000 * secondsBetweenRetries;
115
+ if (nowDate.valueOf() < nextTarget) {
116
+ log("countervalues", `${key}@${granularity} discarded: too much HTTP failures (${failures}) retry in ~${Math.round((nextTarget - nowDate.valueOf()) / 1000)}s`);
117
+ return;
118
+ }
119
+ }
120
+ let start = startDate;
121
+ const limitDate = Date.now() - limit;
122
+ if (limitDate && start.valueOf() < limitDate) {
123
+ start = new Date(limitDate);
124
+ }
125
+ const needOlderReload = s && s.oldestDateRequested && start < new Date(s.oldestDateRequested);
126
+ if (needOlderReload) {
127
+ log("countervalues", `${key}@${granularity} need older reload (${start.toISOString()} < ${String(s && s.oldestDateRequested)})`);
128
+ }
129
+ if (!needOlderReload) {
130
+ // we do not miss datapoints in the past so we can ask the only remaining part
131
+ if (stats && stats.earliestStableDate && stats.earliestStableDate > start) {
132
+ start = stats.earliestStableDate;
133
+ }
134
+ }
135
+ // nothing to fetch for historical
136
+ if (format(start) === earliestHisto)
137
+ return;
138
+ histoToFetch.push([
139
+ granularity,
140
+ {
141
+ from,
142
+ to,
143
+ startDate: start,
144
+ },
145
+ key,
146
+ ]);
147
+ });
148
+ });
149
+ log("countervalues", `${histoToFetch.length} historical value to fetch (${settings.trackingPairs.length} pairs)`);
150
+ // Fetch it all
151
+ const [histo, latest] = yield Promise.all([
152
+ promiseAllBatched(10, histoToFetch, ([granularity, pair, key]) => api
153
+ .fetchHistorical(granularity, pair)
154
+ .then(rates => {
155
+ var _a;
156
+ // Update status infos
157
+ const id = pairId(pair);
158
+ let oldestDateRequested = (_a = status[id]) === null || _a === void 0 ? void 0 : _a.oldestDateRequested;
159
+ if (!oldestDateRequested || pair.startDate < new Date(oldestDateRequested)) {
160
+ oldestDateRequested = pair.startDate.toISOString();
161
+ }
162
+ status[id] = {
163
+ timestamp: Date.now(),
164
+ oldestDateRequested,
165
+ };
166
+ return {
167
+ [key]: rates,
168
+ };
169
+ })
170
+ .catch(e => {
171
+ if (settings.disableAutoRecoverErrors)
172
+ throw e;
173
+ // TODO work on the semantic of failure.
174
+ // do we want to opt-in for the 404 cases and make other fails it all?
175
+ // do we want to be resilient on individual pulling / keep error somewhere?
176
+ const id = pairId(pair);
177
+ // only on HTTP error, we count the failures (not network down case)
178
+ if (e && typeof e.status === "number" && e.status) {
179
+ const s = status[id];
180
+ status[id] = {
181
+ timestamp: Date.now(),
182
+ failures: ((s === null || s === void 0 ? void 0 : s.failures) || 0) + 1,
183
+ oldestDateRequested: s === null || s === void 0 ? void 0 : s.oldestDateRequested,
184
+ };
185
+ }
186
+ log("countervalues-error", `Failed to fetch ${granularity} history for ${pair.from.ticker}-${pair.to.ticker} ${String(e)}`);
187
+ return null;
188
+ })),
189
+ api
190
+ .fetchLatest(latestToFetch)
191
+ .then(rates => {
192
+ const out = {};
193
+ let hasData = false;
194
+ latestToFetch.forEach((pair, i) => {
195
+ var _a;
196
+ const key = pairId(pair);
197
+ const latest = rates[i];
198
+ if (((_a = data[key]) === null || _a === void 0 ? void 0 : _a.get("latest")) === latest)
199
+ return;
200
+ out[key] = {
201
+ latest: rates[i],
202
+ };
203
+ hasData = true;
204
+ });
205
+ if (!hasData)
206
+ return null;
207
+ return out;
208
+ })
209
+ .catch(e => {
210
+ if (settings.disableAutoRecoverErrors)
211
+ throw e;
212
+ log("countervalues-error", "Failed to fetch latest for " +
213
+ latestToFetch.map(p => `${p.from.ticker}-${p.to.ticker}`).join(",") +
214
+ " " +
215
+ String(e));
216
+ return null;
217
+ }),
218
+ ]);
219
+ const updates = [];
220
+ for (const patch of histo) {
221
+ if (patch) {
222
+ updates.push(patch);
223
+ }
224
+ }
225
+ if (latest) {
226
+ updates.push(latest);
227
+ }
228
+ log("countervalues", updates.length + " updates to apply");
229
+ const changesKeys = {};
230
+ updates.forEach(patch => {
231
+ Object.keys(patch).forEach(key => {
232
+ changesKeys[key] = 1;
233
+ if (!data[key]) {
234
+ data[key] = new Map();
235
+ }
236
+ Object.entries(patch[key]).forEach(([k, v]) => {
237
+ if (typeof v === "number")
238
+ data[key].set(k, v);
239
+ });
240
+ });
241
+ });
242
+ // synchronize the cache
243
+ Object.keys(changesKeys).forEach(pair => {
244
+ cache[pair] = generateCache(pair, data[pair], settings);
245
+ });
246
+ return {
247
+ data,
248
+ cache,
249
+ status,
250
+ };
251
+ });
252
+ }
253
+ export function lenseRateMap(state, pair) {
254
+ const rateId = pairId(pair);
255
+ return state.cache[rateId];
256
+ }
257
+ export function lenseRate({ stats, fallback, map }, query) {
258
+ const { date } = query;
259
+ if (!date)
260
+ return map.get("latest");
261
+ const { iso, hour, day } = formatCounterValueHashes(date);
262
+ if (stats.earliest && iso > stats.earliest)
263
+ return map.get("latest");
264
+ return map.get(hour) || map.get(day) || fallback;
265
+ }
266
+ export function calculate(state, initialQuery) {
267
+ const { from, to } = initialQuery;
268
+ if (from === to)
269
+ return initialQuery.value;
270
+ const { date, value, disableRounding, reverse } = initialQuery;
271
+ const query = {
272
+ date,
273
+ from,
274
+ to,
275
+ };
276
+ const map = lenseRateMap(state, query);
277
+ if (!map)
278
+ return;
279
+ let rate = lenseRate(map, query);
280
+ if (!rate)
281
+ return;
282
+ const mult = reverse
283
+ ? magFromTo(initialQuery.to, initialQuery.from)
284
+ : magFromTo(initialQuery.from, initialQuery.to);
285
+ if (reverse && rate) {
286
+ rate = 1 / rate;
287
+ }
288
+ const val = rate ? value * rate * mult : 0;
289
+ return disableRounding ? val : Math.round(val);
290
+ }
291
+ export function calculateMany(state, dataPoints, initialQuery) {
292
+ const { reverse, disableRounding } = initialQuery;
293
+ const { from, to } = initialQuery;
294
+ if (from === to)
295
+ return dataPoints.map(d => d.value);
296
+ const map = lenseRateMap(state, initialQuery);
297
+ if (!map)
298
+ return Array(dataPoints.length).fill(undefined); // undefined array
299
+ const mult = reverse
300
+ ? magFromTo(initialQuery.to, initialQuery.from)
301
+ : magFromTo(initialQuery.from, initialQuery.to);
302
+ return dataPoints.map(({ value, date }) => {
303
+ if (from === to)
304
+ return value;
305
+ let rate = lenseRate(map, {
306
+ from,
307
+ to,
308
+ date,
309
+ });
310
+ if (!rate)
311
+ return;
312
+ if (reverse && rate) {
313
+ rate = 1 / rate;
314
+ }
315
+ const val = rate ? value * rate * mult : 0;
316
+ return disableRounding ? val : Math.round(val);
317
+ });
318
+ }
319
+ function generateCache(pair, rateMap, settings) {
320
+ const map = new Map(rateMap);
321
+ const sorted = Array.from(map.keys())
322
+ .sort()
323
+ .filter(k => k !== "latest");
324
+ const oldest = sorted[0];
325
+ const earliest = sorted[sorted.length - 1];
326
+ const oldestDate = oldest ? parseFormattedDate(oldest) : null;
327
+ const earliestDate = earliest ? parseFormattedDate(earliest) : null;
328
+ let earliestStableDate = earliestDate;
329
+ let fallback = 0;
330
+ let hasHole = false;
331
+ if (oldestDate && oldest) {
332
+ // we find the most recent stable day and we set it in earliestStableDate
333
+ // if autofillGaps is on, shifting daily gaps (hourly don't need to be shifted as it automatically fallback on a day rate)
334
+ const now = Date.now();
335
+ const oldestTime = oldestDate.getTime();
336
+ let shiftingValue = map.get(oldest) || 0;
337
+ if (settings.autofillGaps) {
338
+ fallback = shiftingValue;
339
+ }
340
+ for (let t = oldestTime; t < now; t += incrementPerGranularity.daily) {
341
+ const d = new Date(t);
342
+ const k = formatCounterValueDay(d);
343
+ if (!map.has(k)) {
344
+ if (!hasHole) {
345
+ hasHole = true;
346
+ earliestStableDate = d;
347
+ }
348
+ if (settings.autofillGaps) {
349
+ map.set(k, shiftingValue);
350
+ }
351
+ }
352
+ else {
353
+ if (settings.autofillGaps) {
354
+ shiftingValue = map.get(k) || 0;
355
+ }
356
+ }
357
+ }
358
+ if (!map.get("latest") && settings.autofillGaps) {
359
+ map.set("latest", shiftingValue);
360
+ }
361
+ }
362
+ else {
363
+ if (settings.autofillGaps) {
364
+ fallback = map.get("latest") || 0;
365
+ }
366
+ }
367
+ const stats = {
368
+ oldest,
369
+ earliest,
370
+ oldestDate,
371
+ earliestDate,
372
+ earliestStableDate,
373
+ };
374
+ return {
375
+ map,
376
+ stats,
377
+ fallback,
378
+ };
379
+ }
380
+ export function resolveTrackingPairs(pairs) {
381
+ const trackingPairs = {};
382
+ for (const pair of pairs) {
383
+ const { from, to } = pair;
384
+ if (from === to)
385
+ continue;
386
+ // dedup and keep oldest date
387
+ let date = pair.startDate;
388
+ const id = pairId(pair);
389
+ if (trackingPairs[id]) {
390
+ const { startDate } = trackingPairs[id];
391
+ if (date) {
392
+ date = date < startDate ? date : startDate;
393
+ }
394
+ }
395
+ trackingPairs[id] = {
396
+ from,
397
+ to,
398
+ startDate: date,
399
+ };
400
+ }
401
+ // to reach more deterministic order, notably in API calls, we sort by from/to
402
+ return Object.keys(trackingPairs)
403
+ .sort()
404
+ .map(id => trackingPairs[id]);
405
+ }
406
+ //# sourceMappingURL=logic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logic.js","sourceRoot":"","sources":["../src/logic.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=logic.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logic.test.d.ts","sourceRoot":"","sources":["../src/logic.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,27 @@
1
+ import { genAccount } from "@ledgerhq/coin-framework/mocks/account";
2
+ import { getCryptoCurrencyById, getFiatCurrencyByTicker } from "@ledgerhq/cryptoassets";
3
+ import { inferTrackingPairForAccounts } from "./logic";
4
+ describe("inferTrackingPairForAccounts", () => {
5
+ const accounts = Array(20)
6
+ .fill(null)
7
+ .map((_, i) => genAccount("test" + i));
8
+ const usd = getFiatCurrencyByTicker("USD");
9
+ test("trackingPairs have a deterministic order regardless of accounts order", () => {
10
+ const trackingPairs = inferTrackingPairForAccounts(accounts, usd);
11
+ const accounts2 = accounts.slice(10).concat(accounts.slice(0, 10));
12
+ const trackingPairs2 = inferTrackingPairForAccounts(accounts2, usd);
13
+ expect(trackingPairs).toEqual(trackingPairs2);
14
+ });
15
+ test("trackingPairs with same from and to are filtered out", () => {
16
+ const first = genAccount("test1", { currency: getCryptoCurrencyById("bitcoin") });
17
+ const trackingPairs = inferTrackingPairForAccounts([first], first.currency);
18
+ expect(trackingPairs).toEqual([]);
19
+ });
20
+ test("trackingPairs with 2 accounts of same coin yield one tracking pair", () => {
21
+ const first = genAccount("test1", { currency: getCryptoCurrencyById("bitcoin") });
22
+ const second = genAccount("test2", { currency: getCryptoCurrencyById("bitcoin") });
23
+ const trackingPairs = inferTrackingPairForAccounts([first, second], usd);
24
+ expect(trackingPairs.length).toBe(1);
25
+ });
26
+ });
27
+ //# sourceMappingURL=logic.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logic.test.js","sourceRoot":"","sources":["../src/logic.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACxF,OAAO,EAAE,4BAA4B,EAAE,MAAM,SAAS,CAAC;AAEvD,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;IAC5C,MAAM,QAAQ,GAAG,KAAK,CAAC,EAAE,CAAC;SACvB,IAAI,CAAC,IAAI,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IACzC,MAAM,GAAG,GAAG,uBAAuB,CAAC,KAAK,CAAC,CAAC;IAE3C,IAAI,CAAC,uEAAuE,EAAE,GAAG,EAAE;QACjF,MAAM,aAAa,GAAG,4BAA4B,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QAClE,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QACnE,MAAM,cAAc,GAAG,4BAA4B,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QACpE,MAAM,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAChE,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,qBAAqB,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAClF,MAAM,aAAa,GAAG,4BAA4B,CAAC,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC5E,MAAM,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC9E,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,qBAAqB,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAClF,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,qBAAqB,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACnF,MAAM,aAAa,GAAG,4BAA4B,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;QACzE,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare const referenceSnapshotDate: Date;
2
+ export declare const BTCtoUSD = 9000;
3
+ export declare const getBTCValues: () => any;
4
+ //# sourceMappingURL=mock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../src/mock.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,qBAAqB,MAA0B,CAAC;AAC7D,eAAO,MAAM,QAAQ,OAAO,CAAC;AAE7B,eAAO,MAAM,YAAY,WAIrB,CAAC"}