mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-22 16:38:11 -07:00
global: snapshot
This commit is contained in:
+152
-116
@@ -998,20 +998,14 @@ function dateToIndex(index, d) {
|
||||
* Wrap raw metric data with helper methods.
|
||||
* @template T
|
||||
* @param {MetricData<T>} raw - Raw JSON response
|
||||
* @returns {MetricData<T>}
|
||||
* @returns {DateMetricData<T>}
|
||||
*/
|
||||
function _wrapMetricData(raw) {
|
||||
const { index, start, end, data } = raw;
|
||||
const _dateBased = _DATE_INDEXES.has(index);
|
||||
return /** @type {MetricData<T>} */ ({
|
||||
return /** @type {DateMetricData<T>} */ ({
|
||||
...raw,
|
||||
isDateBased: _dateBased,
|
||||
dates() {
|
||||
/** @type {globalThis.Date[]} */
|
||||
const result = [];
|
||||
for (let i = start; i < end; i++) result.push(indexToDate(index, i));
|
||||
return result;
|
||||
},
|
||||
indexes() {
|
||||
/** @type {number[]} */
|
||||
const result = [];
|
||||
@@ -1019,41 +1013,48 @@ function _wrapMetricData(raw) {
|
||||
return result;
|
||||
},
|
||||
keys() {
|
||||
return _dateBased ? this.dates() : this.indexes();
|
||||
return this.indexes();
|
||||
},
|
||||
entries() {
|
||||
/** @type {Array<[globalThis.Date | number, T]>} */
|
||||
/** @type {Array<[number, T]>} */
|
||||
const result = [];
|
||||
if (_dateBased) {
|
||||
for (let i = 0; i < data.length; i++) result.push([indexToDate(index, start + i), data[i]]);
|
||||
} else {
|
||||
for (let i = 0; i < data.length; i++) result.push([start + i, data[i]]);
|
||||
}
|
||||
for (let i = 0; i < data.length; i++) result.push([start + i, data[i]]);
|
||||
return result;
|
||||
},
|
||||
toMap() {
|
||||
/** @type {Map<globalThis.Date | number, T>} */
|
||||
/** @type {Map<number, T>} */
|
||||
const map = new Map();
|
||||
if (_dateBased) {
|
||||
for (let i = 0; i < data.length; i++) map.set(indexToDate(index, start + i), data[i]);
|
||||
} else {
|
||||
for (let i = 0; i < data.length; i++) map.set(start + i, data[i]);
|
||||
}
|
||||
for (let i = 0; i < data.length; i++) map.set(start + i, data[i]);
|
||||
return map;
|
||||
},
|
||||
*[Symbol.iterator]() {
|
||||
if (_dateBased) {
|
||||
for (let i = 0; i < data.length; i++) yield [indexToDate(index, start + i), data[i]];
|
||||
} else {
|
||||
for (let i = 0; i < data.length; i++) yield [start + i, data[i]];
|
||||
}
|
||||
for (let i = 0; i < data.length; i++) yield /** @type {[number, T]} */ ([start + i, data[i]]);
|
||||
},
|
||||
// DateMetricData methods (only meaningful for date-based indexes)
|
||||
dates() {
|
||||
/** @type {globalThis.Date[]} */
|
||||
const result = [];
|
||||
for (let i = start; i < end; i++) result.push(indexToDate(index, i));
|
||||
return result;
|
||||
},
|
||||
dateEntries() {
|
||||
/** @type {Array<[globalThis.Date, T]>} */
|
||||
const result = [];
|
||||
for (let i = 0; i < data.length; i++) result.push([indexToDate(index, start + i), data[i]]);
|
||||
return result;
|
||||
},
|
||||
toDateMap() {
|
||||
/** @type {Map<globalThis.Date, T>} */
|
||||
const map = new Map();
|
||||
for (let i = 0; i < data.length; i++) map.set(indexToDate(index, start + i), data[i]);
|
||||
return map;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @typedef {Object} MetricData
|
||||
* @typedef {Object} MetricDataBase
|
||||
* @property {number} version - Version of the metric data
|
||||
* @property {Index} index - The index type used for this query
|
||||
* @property {number} total - Total number of data points
|
||||
@@ -1062,26 +1063,33 @@ function _wrapMetricData(raw) {
|
||||
* @property {string} stamp - ISO 8601 timestamp of when the response was generated
|
||||
* @property {T[]} data - The metric data
|
||||
* @property {boolean} isDateBased - Whether this metric uses a date-based index
|
||||
* @property {() => (globalThis.Date[] | number[])} keys - Get keys (dates for date-based, index numbers otherwise)
|
||||
* @property {() => Array<[globalThis.Date | number, T]>} entries - Get [key, value] pairs (dates for date-based, index numbers otherwise)
|
||||
* @property {() => Map<globalThis.Date | number, T>} toMap - Return data as Map (dates for date-based, index numbers otherwise)
|
||||
* @property {() => globalThis.Date[]} dates - Get dates (date-based indexes only, throws otherwise)
|
||||
* @property {() => number[]} indexes - Get index numbers
|
||||
* @property {() => number[]} keys - Get keys as index numbers (alias for indexes)
|
||||
* @property {() => Array<[number, T]>} entries - Get [index, value] pairs
|
||||
* @property {() => Map<number, T>} toMap - Convert to Map<index, value>
|
||||
*/
|
||||
|
||||
/** @template T @typedef {MetricDataBase<T> & Iterable<[number, T]>} MetricData */
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @typedef {Object} DateMetricDataExtras
|
||||
* @property {() => globalThis.Date[]} dates - Get dates for each data point
|
||||
* @property {() => Array<[globalThis.Date, T]>} dateEntries - Get [date, value] pairs
|
||||
* @property {() => Map<globalThis.Date, T>} toDateMap - Convert to Map<date, value>
|
||||
*/
|
||||
|
||||
/** @template T @typedef {MetricData<T> & DateMetricDataExtras<T>} DateMetricData */
|
||||
/** @typedef {MetricData<any>} AnyMetricData */
|
||||
|
||||
/**
|
||||
* Thenable interface for await support.
|
||||
* @template T
|
||||
* @typedef {(onfulfilled?: (value: MetricData<T>) => MetricData<T>, onrejected?: (reason: Error) => never) => Promise<MetricData<T>>} Thenable
|
||||
*/
|
||||
/** @template T @typedef {(onfulfilled?: (value: MetricData<T>) => any, onrejected?: (reason: Error) => never) => Promise<MetricData<T>>} Thenable */
|
||||
/** @template T @typedef {(onfulfilled?: (value: DateMetricData<T>) => any, onrejected?: (reason: Error) => never) => Promise<DateMetricData<T>>} DateThenable */
|
||||
|
||||
/**
|
||||
* Metric endpoint builder. Callable (returns itself) so both .by.day1 and .by.day1() work.
|
||||
* @template T
|
||||
* @typedef {Object} MetricEndpointBuilder
|
||||
* @property {(index: number) => SingleItemBuilder<T>} get - Get single item at index
|
||||
* @property {(start?: number | globalThis.Date, end?: number | globalThis.Date) => RangeBuilder<T>} slice - Slice by index or Date
|
||||
* @property {(start?: number, end?: number) => RangeBuilder<T>} slice - Slice by index
|
||||
* @property {(n: number) => RangeBuilder<T>} first - Get first n items
|
||||
* @property {(n: number) => RangeBuilder<T>} last - Get last n items
|
||||
* @property {(n: number) => SkippedBuilder<T>} skip - Skip first n items, chain with take()
|
||||
@@ -1090,38 +1098,66 @@ function _wrapMetricData(raw) {
|
||||
* @property {Thenable<T>} then - Thenable (await endpoint)
|
||||
* @property {string} path - The endpoint path
|
||||
*/
|
||||
/** @typedef {MetricEndpointBuilder<any>} AnyMetricEndpointBuilder */
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @typedef {Object} SingleItemBuilder
|
||||
* @typedef {Object} DateMetricEndpointBuilder
|
||||
* @property {(index: number | globalThis.Date) => DateSingleItemBuilder<T>} get - Get single item at index or Date
|
||||
* @property {(start?: number | globalThis.Date, end?: number | globalThis.Date) => DateRangeBuilder<T>} slice - Slice by index or Date
|
||||
* @property {(n: number) => DateRangeBuilder<T>} first - Get first n items
|
||||
* @property {(n: number) => DateRangeBuilder<T>} last - Get last n items
|
||||
* @property {(n: number) => DateSkippedBuilder<T>} skip - Skip first n items, chain with take()
|
||||
* @property {(onUpdate?: (value: DateMetricData<T>) => void) => Promise<DateMetricData<T>>} fetch - Fetch all data
|
||||
* @property {() => Promise<string>} fetchCsv - Fetch all data as CSV
|
||||
* @property {DateThenable<T>} then - Thenable (await endpoint)
|
||||
* @property {string} path - The endpoint path
|
||||
*/
|
||||
|
||||
/** @typedef {MetricEndpointBuilder<any>} AnyMetricEndpointBuilder */
|
||||
|
||||
/** @template T @typedef {Object} SingleItemBuilder
|
||||
* @property {(onUpdate?: (value: MetricData<T>) => void) => Promise<MetricData<T>>} fetch - Fetch the item
|
||||
* @property {() => Promise<string>} fetchCsv - Fetch as CSV
|
||||
* @property {Thenable<T>} then - Thenable
|
||||
*/
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @typedef {Object} SkippedBuilder
|
||||
/** @template T @typedef {Object} DateSingleItemBuilder
|
||||
* @property {(onUpdate?: (value: DateMetricData<T>) => void) => Promise<DateMetricData<T>>} fetch - Fetch the item
|
||||
* @property {() => Promise<string>} fetchCsv - Fetch as CSV
|
||||
* @property {DateThenable<T>} then - Thenable
|
||||
*/
|
||||
|
||||
/** @template T @typedef {Object} SkippedBuilder
|
||||
* @property {(n: number) => RangeBuilder<T>} take - Take n items after skipped position
|
||||
* @property {(onUpdate?: (value: MetricData<T>) => void) => Promise<MetricData<T>>} fetch - Fetch from skipped position to end
|
||||
* @property {() => Promise<string>} fetchCsv - Fetch as CSV
|
||||
* @property {Thenable<T>} then - Thenable
|
||||
*/
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @typedef {Object} RangeBuilder
|
||||
/** @template T @typedef {Object} DateSkippedBuilder
|
||||
* @property {(n: number) => DateRangeBuilder<T>} take - Take n items after skipped position
|
||||
* @property {(onUpdate?: (value: DateMetricData<T>) => void) => Promise<DateMetricData<T>>} fetch - Fetch from skipped position to end
|
||||
* @property {() => Promise<string>} fetchCsv - Fetch as CSV
|
||||
* @property {DateThenable<T>} then - Thenable
|
||||
*/
|
||||
|
||||
/** @template T @typedef {Object} RangeBuilder
|
||||
* @property {(onUpdate?: (value: MetricData<T>) => void) => Promise<MetricData<T>>} fetch - Fetch the range
|
||||
* @property {() => Promise<string>} fetchCsv - Fetch as CSV
|
||||
* @property {Thenable<T>} then - Thenable
|
||||
*/
|
||||
|
||||
/** @template T @typedef {Object} DateRangeBuilder
|
||||
* @property {(onUpdate?: (value: DateMetricData<T>) => void) => Promise<DateMetricData<T>>} fetch - Fetch the range
|
||||
* @property {() => Promise<string>} fetchCsv - Fetch as CSV
|
||||
* @property {DateThenable<T>} then - Thenable
|
||||
*/
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @typedef {Object} MetricPattern
|
||||
* @property {string} name - The metric name
|
||||
* @property {Readonly<Partial<Record<Index, MetricEndpointBuilder<T>>>>} by - Index endpoints as lazy getters. Access via .by.day1 or .by['day1']
|
||||
* @property {Readonly<Partial<Record<Index, MetricEndpointBuilder<T>>>>} by - Index endpoints as lazy getters
|
||||
* @property {() => readonly Index[]} indexes - Get the list of available indexes
|
||||
* @property {(index: Index) => MetricEndpointBuilder<T>|undefined} get - Get an endpoint for a specific index
|
||||
*/
|
||||
@@ -1134,7 +1170,7 @@ function _wrapMetricData(raw) {
|
||||
* @param {BrkClientBase} client
|
||||
* @param {string} name - The metric vec name
|
||||
* @param {Index} index - The index name
|
||||
* @returns {MetricEndpointBuilder<T>}
|
||||
* @returns {DateMetricEndpointBuilder<T>}
|
||||
*/
|
||||
function _endpoint(client, name, index) {
|
||||
const p = `/api/metric/${name}/${index}`;
|
||||
@@ -1157,7 +1193,7 @@ function _endpoint(client, name, index) {
|
||||
/**
|
||||
* @param {number} [start]
|
||||
* @param {number} [end]
|
||||
* @returns {RangeBuilder<T>}
|
||||
* @returns {DateRangeBuilder<T>}
|
||||
*/
|
||||
const rangeBuilder = (start, end) => ({
|
||||
fetch(onUpdate) { return client._fetchMetricData(buildPath(start, end), onUpdate); },
|
||||
@@ -1167,7 +1203,7 @@ function _endpoint(client, name, index) {
|
||||
|
||||
/**
|
||||
* @param {number} idx
|
||||
* @returns {SingleItemBuilder<T>}
|
||||
* @returns {DateSingleItemBuilder<T>}
|
||||
*/
|
||||
const singleItemBuilder = (idx) => ({
|
||||
fetch(onUpdate) { return client._fetchMetricData(buildPath(idx, idx + 1), onUpdate); },
|
||||
@@ -1177,7 +1213,7 @@ function _endpoint(client, name, index) {
|
||||
|
||||
/**
|
||||
* @param {number} start
|
||||
* @returns {SkippedBuilder<T>}
|
||||
* @returns {DateSkippedBuilder<T>}
|
||||
*/
|
||||
const skippedBuilder = (start) => ({
|
||||
take(n) { return rangeBuilder(start, start + n); },
|
||||
@@ -1186,9 +1222,9 @@ function _endpoint(client, name, index) {
|
||||
then(resolve, reject) { return this.fetch().then(resolve, reject); },
|
||||
});
|
||||
|
||||
/** @type {MetricEndpointBuilder<T>} */
|
||||
/** @type {DateMetricEndpointBuilder<T>} */
|
||||
const endpoint = {
|
||||
get(idx) { return singleItemBuilder(idx); },
|
||||
get(idx) { if (idx instanceof Date) idx = dateToIndex(index, idx); return singleItemBuilder(idx); },
|
||||
slice(start, end) {
|
||||
if (start instanceof Date) start = dateToIndex(index, start);
|
||||
if (end instanceof Date) end = dateToIndex(index, end);
|
||||
@@ -1215,7 +1251,8 @@ class BrkClientBase {
|
||||
*/
|
||||
constructor(options) {
|
||||
const isString = typeof options === 'string';
|
||||
this.baseUrl = isString ? options : options.baseUrl;
|
||||
const rawUrl = isString ? options : options.baseUrl;
|
||||
this.baseUrl = rawUrl.endsWith('/') ? rawUrl.slice(0, -1) : rawUrl;
|
||||
this.timeout = isString ? 5000 : (options.timeout ?? 5000);
|
||||
/** @type {Promise<Cache | null>} */
|
||||
this._cachePromise = _openCache(isString ? undefined : options.cache);
|
||||
@@ -1229,8 +1266,7 @@ class BrkClientBase {
|
||||
* @returns {Promise<Response>}
|
||||
*/
|
||||
async get(path) {
|
||||
const base = this.baseUrl.endsWith('/') ? this.baseUrl.slice(0, -1) : this.baseUrl;
|
||||
const url = `${base}${path}`;
|
||||
const url = `${this.baseUrl}${path}`;
|
||||
const res = await fetch(url, { signal: AbortSignal.timeout(this.timeout) });
|
||||
if (!res.ok) throw new BrkError(`HTTP ${res.status}: ${url}`, res.status);
|
||||
return res;
|
||||
@@ -1244,8 +1280,7 @@ class BrkClientBase {
|
||||
* @returns {Promise<T>}
|
||||
*/
|
||||
async getJson(path, onUpdate) {
|
||||
const base = this.baseUrl.endsWith('/') ? this.baseUrl.slice(0, -1) : this.baseUrl;
|
||||
const url = `${base}${path}`;
|
||||
const url = `${this.baseUrl}${path}`;
|
||||
const cache = this._cache ?? await this._cachePromise;
|
||||
|
||||
let resolved = false;
|
||||
@@ -1307,8 +1342,8 @@ class BrkClientBase {
|
||||
* Fetch metric data and wrap with helper methods (internal)
|
||||
* @template T
|
||||
* @param {string} path
|
||||
* @param {(value: MetricData<T>) => void} [onUpdate]
|
||||
* @returns {Promise<MetricData<T>>}
|
||||
* @param {(value: DateMetricData<T>) => void} [onUpdate]
|
||||
* @returns {Promise<DateMetricData<T>>}
|
||||
*/
|
||||
async _fetchMetricData(path, onUpdate) {
|
||||
const wrappedOnUpdate = onUpdate ? (/** @type {MetricData<T>} */ raw) => onUpdate(_wrapMetricData(raw)) : undefined;
|
||||
@@ -1382,7 +1417,7 @@ const _i37 = /** @type {const} */ (["emptyaddressindex"]);
|
||||
* @param {readonly Index[]} indexes - The supported indexes
|
||||
*/
|
||||
function _mp(client, name, indexes) {
|
||||
const by = /** @type {any} */ ({});
|
||||
const by = {};
|
||||
for (const idx of indexes) {
|
||||
Object.defineProperty(by, idx, {
|
||||
get() { return _endpoint(client, name, idx); },
|
||||
@@ -1393,123 +1428,124 @@ function _mp(client, name, indexes) {
|
||||
return {
|
||||
name,
|
||||
by,
|
||||
/** @returns {readonly Index[]} */
|
||||
indexes() { return indexes; },
|
||||
/** @param {Index} index */
|
||||
/** @param {Index} index @returns {MetricEndpointBuilder<T>|undefined} */
|
||||
get(index) { return indexes.includes(index) ? _endpoint(client, name, index) : undefined; }
|
||||
};
|
||||
}
|
||||
|
||||
/** @template T @typedef {{ name: string, by: { readonly minute1: MetricEndpointBuilder<T>, readonly minute5: MetricEndpointBuilder<T>, readonly minute10: MetricEndpointBuilder<T>, readonly minute30: MetricEndpointBuilder<T>, readonly hour1: MetricEndpointBuilder<T>, readonly hour4: MetricEndpointBuilder<T>, readonly hour12: MetricEndpointBuilder<T>, readonly day1: MetricEndpointBuilder<T>, readonly day3: MetricEndpointBuilder<T>, readonly week1: MetricEndpointBuilder<T>, readonly month1: MetricEndpointBuilder<T>, readonly month3: MetricEndpointBuilder<T>, readonly month6: MetricEndpointBuilder<T>, readonly year1: MetricEndpointBuilder<T>, readonly year10: MetricEndpointBuilder<T>, readonly halvingepoch: MetricEndpointBuilder<T>, readonly difficultyepoch: MetricEndpointBuilder<T>, readonly height: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern1 */
|
||||
/** @template T @typedef {{ name: string, by: { readonly minute1: DateMetricEndpointBuilder<T>, readonly minute5: DateMetricEndpointBuilder<T>, readonly minute10: DateMetricEndpointBuilder<T>, readonly minute30: DateMetricEndpointBuilder<T>, readonly hour1: DateMetricEndpointBuilder<T>, readonly hour4: DateMetricEndpointBuilder<T>, readonly hour12: DateMetricEndpointBuilder<T>, readonly day1: DateMetricEndpointBuilder<T>, readonly day3: DateMetricEndpointBuilder<T>, readonly week1: DateMetricEndpointBuilder<T>, readonly month1: DateMetricEndpointBuilder<T>, readonly month3: DateMetricEndpointBuilder<T>, readonly month6: DateMetricEndpointBuilder<T>, readonly year1: DateMetricEndpointBuilder<T>, readonly year10: DateMetricEndpointBuilder<T>, readonly halvingepoch: MetricEndpointBuilder<T>, readonly difficultyepoch: MetricEndpointBuilder<T>, readonly height: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern1 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern1<T>} */
|
||||
function createMetricPattern1(client, name) { return _mp(client, name, _i1); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly minute1: MetricEndpointBuilder<T>, readonly minute5: MetricEndpointBuilder<T>, readonly minute10: MetricEndpointBuilder<T>, readonly minute30: MetricEndpointBuilder<T>, readonly hour1: MetricEndpointBuilder<T>, readonly hour4: MetricEndpointBuilder<T>, readonly hour12: MetricEndpointBuilder<T>, readonly day1: MetricEndpointBuilder<T>, readonly day3: MetricEndpointBuilder<T>, readonly week1: MetricEndpointBuilder<T>, readonly month1: MetricEndpointBuilder<T>, readonly month3: MetricEndpointBuilder<T>, readonly month6: MetricEndpointBuilder<T>, readonly year1: MetricEndpointBuilder<T>, readonly year10: MetricEndpointBuilder<T>, readonly halvingepoch: MetricEndpointBuilder<T>, readonly difficultyepoch: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern2 */
|
||||
function createMetricPattern1(client, name) { return /** @type {MetricPattern1<T>} */ (_mp(client, name, _i1)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly minute1: DateMetricEndpointBuilder<T>, readonly minute5: DateMetricEndpointBuilder<T>, readonly minute10: DateMetricEndpointBuilder<T>, readonly minute30: DateMetricEndpointBuilder<T>, readonly hour1: DateMetricEndpointBuilder<T>, readonly hour4: DateMetricEndpointBuilder<T>, readonly hour12: DateMetricEndpointBuilder<T>, readonly day1: DateMetricEndpointBuilder<T>, readonly day3: DateMetricEndpointBuilder<T>, readonly week1: DateMetricEndpointBuilder<T>, readonly month1: DateMetricEndpointBuilder<T>, readonly month3: DateMetricEndpointBuilder<T>, readonly month6: DateMetricEndpointBuilder<T>, readonly year1: DateMetricEndpointBuilder<T>, readonly year10: DateMetricEndpointBuilder<T>, readonly halvingepoch: MetricEndpointBuilder<T>, readonly difficultyepoch: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern2 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern2<T>} */
|
||||
function createMetricPattern2(client, name) { return _mp(client, name, _i2); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly minute1: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern3 */
|
||||
function createMetricPattern2(client, name) { return /** @type {MetricPattern2<T>} */ (_mp(client, name, _i2)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly minute1: DateMetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern3 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern3<T>} */
|
||||
function createMetricPattern3(client, name) { return _mp(client, name, _i3); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly minute5: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern4 */
|
||||
function createMetricPattern3(client, name) { return /** @type {MetricPattern3<T>} */ (_mp(client, name, _i3)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly minute5: DateMetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern4 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern4<T>} */
|
||||
function createMetricPattern4(client, name) { return _mp(client, name, _i4); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly minute10: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern5 */
|
||||
function createMetricPattern4(client, name) { return /** @type {MetricPattern4<T>} */ (_mp(client, name, _i4)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly minute10: DateMetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern5 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern5<T>} */
|
||||
function createMetricPattern5(client, name) { return _mp(client, name, _i5); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly minute30: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern6 */
|
||||
function createMetricPattern5(client, name) { return /** @type {MetricPattern5<T>} */ (_mp(client, name, _i5)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly minute30: DateMetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern6 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern6<T>} */
|
||||
function createMetricPattern6(client, name) { return _mp(client, name, _i6); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly hour1: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern7 */
|
||||
function createMetricPattern6(client, name) { return /** @type {MetricPattern6<T>} */ (_mp(client, name, _i6)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly hour1: DateMetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern7 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern7<T>} */
|
||||
function createMetricPattern7(client, name) { return _mp(client, name, _i7); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly hour4: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern8 */
|
||||
function createMetricPattern7(client, name) { return /** @type {MetricPattern7<T>} */ (_mp(client, name, _i7)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly hour4: DateMetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern8 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern8<T>} */
|
||||
function createMetricPattern8(client, name) { return _mp(client, name, _i8); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly hour12: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern9 */
|
||||
function createMetricPattern8(client, name) { return /** @type {MetricPattern8<T>} */ (_mp(client, name, _i8)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly hour12: DateMetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern9 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern9<T>} */
|
||||
function createMetricPattern9(client, name) { return _mp(client, name, _i9); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly day1: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern10 */
|
||||
function createMetricPattern9(client, name) { return /** @type {MetricPattern9<T>} */ (_mp(client, name, _i9)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly day1: DateMetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern10 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern10<T>} */
|
||||
function createMetricPattern10(client, name) { return _mp(client, name, _i10); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly day3: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern11 */
|
||||
function createMetricPattern10(client, name) { return /** @type {MetricPattern10<T>} */ (_mp(client, name, _i10)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly day3: DateMetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern11 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern11<T>} */
|
||||
function createMetricPattern11(client, name) { return _mp(client, name, _i11); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly week1: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern12 */
|
||||
function createMetricPattern11(client, name) { return /** @type {MetricPattern11<T>} */ (_mp(client, name, _i11)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly week1: DateMetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern12 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern12<T>} */
|
||||
function createMetricPattern12(client, name) { return _mp(client, name, _i12); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly month1: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern13 */
|
||||
function createMetricPattern12(client, name) { return /** @type {MetricPattern12<T>} */ (_mp(client, name, _i12)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly month1: DateMetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern13 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern13<T>} */
|
||||
function createMetricPattern13(client, name) { return _mp(client, name, _i13); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly month3: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern14 */
|
||||
function createMetricPattern13(client, name) { return /** @type {MetricPattern13<T>} */ (_mp(client, name, _i13)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly month3: DateMetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern14 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern14<T>} */
|
||||
function createMetricPattern14(client, name) { return _mp(client, name, _i14); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly month6: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern15 */
|
||||
function createMetricPattern14(client, name) { return /** @type {MetricPattern14<T>} */ (_mp(client, name, _i14)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly month6: DateMetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern15 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern15<T>} */
|
||||
function createMetricPattern15(client, name) { return _mp(client, name, _i15); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly year1: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern16 */
|
||||
function createMetricPattern15(client, name) { return /** @type {MetricPattern15<T>} */ (_mp(client, name, _i15)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly year1: DateMetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern16 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern16<T>} */
|
||||
function createMetricPattern16(client, name) { return _mp(client, name, _i16); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly year10: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern17 */
|
||||
function createMetricPattern16(client, name) { return /** @type {MetricPattern16<T>} */ (_mp(client, name, _i16)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly year10: DateMetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern17 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern17<T>} */
|
||||
function createMetricPattern17(client, name) { return _mp(client, name, _i17); }
|
||||
function createMetricPattern17(client, name) { return /** @type {MetricPattern17<T>} */ (_mp(client, name, _i17)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly halvingepoch: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern18 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern18<T>} */
|
||||
function createMetricPattern18(client, name) { return _mp(client, name, _i18); }
|
||||
function createMetricPattern18(client, name) { return /** @type {MetricPattern18<T>} */ (_mp(client, name, _i18)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly difficultyepoch: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern19 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern19<T>} */
|
||||
function createMetricPattern19(client, name) { return _mp(client, name, _i19); }
|
||||
function createMetricPattern19(client, name) { return /** @type {MetricPattern19<T>} */ (_mp(client, name, _i19)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly height: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern20 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern20<T>} */
|
||||
function createMetricPattern20(client, name) { return _mp(client, name, _i20); }
|
||||
function createMetricPattern20(client, name) { return /** @type {MetricPattern20<T>} */ (_mp(client, name, _i20)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly txindex: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern21 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern21<T>} */
|
||||
function createMetricPattern21(client, name) { return _mp(client, name, _i21); }
|
||||
function createMetricPattern21(client, name) { return /** @type {MetricPattern21<T>} */ (_mp(client, name, _i21)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly txinindex: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern22 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern22<T>} */
|
||||
function createMetricPattern22(client, name) { return _mp(client, name, _i22); }
|
||||
function createMetricPattern22(client, name) { return /** @type {MetricPattern22<T>} */ (_mp(client, name, _i22)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly txoutindex: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern23 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern23<T>} */
|
||||
function createMetricPattern23(client, name) { return _mp(client, name, _i23); }
|
||||
function createMetricPattern23(client, name) { return /** @type {MetricPattern23<T>} */ (_mp(client, name, _i23)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly emptyoutputindex: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern24 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern24<T>} */
|
||||
function createMetricPattern24(client, name) { return _mp(client, name, _i24); }
|
||||
function createMetricPattern24(client, name) { return /** @type {MetricPattern24<T>} */ (_mp(client, name, _i24)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly opreturnindex: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern25 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern25<T>} */
|
||||
function createMetricPattern25(client, name) { return _mp(client, name, _i25); }
|
||||
function createMetricPattern25(client, name) { return /** @type {MetricPattern25<T>} */ (_mp(client, name, _i25)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly p2aaddressindex: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern26 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern26<T>} */
|
||||
function createMetricPattern26(client, name) { return _mp(client, name, _i26); }
|
||||
function createMetricPattern26(client, name) { return /** @type {MetricPattern26<T>} */ (_mp(client, name, _i26)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly p2msoutputindex: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern27 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern27<T>} */
|
||||
function createMetricPattern27(client, name) { return _mp(client, name, _i27); }
|
||||
function createMetricPattern27(client, name) { return /** @type {MetricPattern27<T>} */ (_mp(client, name, _i27)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly p2pk33addressindex: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern28 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern28<T>} */
|
||||
function createMetricPattern28(client, name) { return _mp(client, name, _i28); }
|
||||
function createMetricPattern28(client, name) { return /** @type {MetricPattern28<T>} */ (_mp(client, name, _i28)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly p2pk65addressindex: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern29 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern29<T>} */
|
||||
function createMetricPattern29(client, name) { return _mp(client, name, _i29); }
|
||||
function createMetricPattern29(client, name) { return /** @type {MetricPattern29<T>} */ (_mp(client, name, _i29)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly p2pkhaddressindex: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern30 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern30<T>} */
|
||||
function createMetricPattern30(client, name) { return _mp(client, name, _i30); }
|
||||
function createMetricPattern30(client, name) { return /** @type {MetricPattern30<T>} */ (_mp(client, name, _i30)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly p2shaddressindex: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern31 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern31<T>} */
|
||||
function createMetricPattern31(client, name) { return _mp(client, name, _i31); }
|
||||
function createMetricPattern31(client, name) { return /** @type {MetricPattern31<T>} */ (_mp(client, name, _i31)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly p2traddressindex: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern32 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern32<T>} */
|
||||
function createMetricPattern32(client, name) { return _mp(client, name, _i32); }
|
||||
function createMetricPattern32(client, name) { return /** @type {MetricPattern32<T>} */ (_mp(client, name, _i32)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly p2wpkhaddressindex: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern33 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern33<T>} */
|
||||
function createMetricPattern33(client, name) { return _mp(client, name, _i33); }
|
||||
function createMetricPattern33(client, name) { return /** @type {MetricPattern33<T>} */ (_mp(client, name, _i33)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly p2wshaddressindex: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern34 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern34<T>} */
|
||||
function createMetricPattern34(client, name) { return _mp(client, name, _i34); }
|
||||
function createMetricPattern34(client, name) { return /** @type {MetricPattern34<T>} */ (_mp(client, name, _i34)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly unknownoutputindex: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern35 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern35<T>} */
|
||||
function createMetricPattern35(client, name) { return _mp(client, name, _i35); }
|
||||
function createMetricPattern35(client, name) { return /** @type {MetricPattern35<T>} */ (_mp(client, name, _i35)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly fundedaddressindex: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern36 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern36<T>} */
|
||||
function createMetricPattern36(client, name) { return _mp(client, name, _i36); }
|
||||
function createMetricPattern36(client, name) { return /** @type {MetricPattern36<T>} */ (_mp(client, name, _i36)); }
|
||||
/** @template T @typedef {{ name: string, by: { readonly emptyaddressindex: MetricEndpointBuilder<T> }, indexes: () => readonly Index[], get: (index: Index) => MetricEndpointBuilder<T>|undefined }} MetricPattern37 */
|
||||
/** @template T @param {BrkClientBase} client @param {string} name @returns {MetricPattern37<T>} */
|
||||
function createMetricPattern37(client, name) { return _mp(client, name, _i37); }
|
||||
function createMetricPattern37(client, name) { return /** @type {MetricPattern37<T>} */ (_mp(client, name, _i37)); }
|
||||
|
||||
// Reusable structural pattern factories
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ console.log("\n2. isDateBased:");
|
||||
if (!price.isDateBased) throw new Error("day1 should be date-based");
|
||||
console.log(` day1: ${price.isDateBased}`);
|
||||
|
||||
// Test indexes()
|
||||
// Test indexes() - always returns numbers
|
||||
console.log("\n3. indexes():");
|
||||
const indexes = price.indexes();
|
||||
console.log(` ${JSON.stringify(indexes)}`);
|
||||
@@ -29,7 +29,7 @@ if (indexes.length !== 5) throw new Error("Expected 5 indexes");
|
||||
if (indexes[0] !== price.start)
|
||||
throw new Error("First index should equal start");
|
||||
|
||||
// Test dates()
|
||||
// Test dates() - DateMetricData method
|
||||
console.log("\n4. dates():");
|
||||
const dates = price.dates();
|
||||
console.log(
|
||||
@@ -47,69 +47,85 @@ if (
|
||||
);
|
||||
}
|
||||
|
||||
// Test keys() - date-based returns dates
|
||||
console.log("\n5. keys() (date-based):");
|
||||
// Test keys() - always returns numbers (alias for indexes)
|
||||
console.log("\n5. keys():");
|
||||
const keys = price.keys();
|
||||
console.log(` Length: ${keys.length}, First: ${keys[0].toISOString()}`);
|
||||
if (keys.length !== 5) throw new Error("Expected 5 keys");
|
||||
if (!(keys[0] instanceof Date)) throw new Error("Expected Date keys for day1");
|
||||
if (typeof keys[0] !== "number") throw new Error("Expected number keys");
|
||||
console.log(` Length: ${keys.length}, First: ${keys[0]}`);
|
||||
|
||||
// Test entries()
|
||||
// Test entries() - returns [number, value] pairs
|
||||
console.log("\n6. entries():");
|
||||
const entries = price.entries();
|
||||
console.log(
|
||||
` First: [${entries[0][0].toISOString()}, ${entries[0][1]}]`,
|
||||
);
|
||||
if (typeof entries[0][0] !== "number")
|
||||
throw new Error("Expected number entry key");
|
||||
console.log(` First: [${entries[0][0]}, ${entries[0][1]}]`);
|
||||
if (entries[0][1] !== price.data[0])
|
||||
throw new Error("First entry value mismatch");
|
||||
|
||||
// Test toMap()
|
||||
console.log("\n7. toMap():");
|
||||
// Test dateEntries() - DateMetricData method, returns [Date, value] pairs
|
||||
console.log("\n7. dateEntries():");
|
||||
const dateEntries = price.dateEntries();
|
||||
if (!(dateEntries[0][0] instanceof Date))
|
||||
throw new Error("Expected Date entry key");
|
||||
console.log(` First: [${dateEntries[0][0].toISOString()}, ${dateEntries[0][1]}]`);
|
||||
|
||||
// Test toMap() - returns Map<number, value>
|
||||
console.log("\n8. toMap():");
|
||||
const map = price.toMap();
|
||||
console.log(` Size: ${map.size}`);
|
||||
if (map.size !== 5) throw new Error("Expected map size 5");
|
||||
|
||||
// Test Symbol.iterator (for...of) - date-based should yield [date, value]
|
||||
console.log("\n8. for...of iteration (date-based):");
|
||||
// Test toDateMap() - DateMetricData method
|
||||
console.log("\n9. toDateMap():");
|
||||
const dateMap = price.toDateMap();
|
||||
console.log(` Size: ${dateMap.size}`);
|
||||
if (dateMap.size !== 5) throw new Error("Expected date map size 5");
|
||||
|
||||
// Test Symbol.iterator (for...of) - yields [number, value]
|
||||
console.log("\n10. for...of iteration:");
|
||||
let count = 0;
|
||||
for (const [key, val] of price) {
|
||||
if (count === 0 && !(key instanceof Date))
|
||||
throw new Error("Expected Date keys in iteration for date-based");
|
||||
for (const [key, _val] of price) {
|
||||
if (count === 0 && typeof key !== "number")
|
||||
throw new Error("Expected number keys in iteration");
|
||||
count++;
|
||||
}
|
||||
console.log(` Iterated ${count} items`);
|
||||
if (count !== 5) throw new Error("Expected 5 iterations");
|
||||
|
||||
// Test with non-date-based index (height)
|
||||
console.log("\n9. Testing height-based metric:");
|
||||
console.log("\n11. Testing height-based metric:");
|
||||
const heightMetric = await client.metrics.prices.usd.price.by.height.last(3);
|
||||
console.log(
|
||||
` Total: ${heightMetric.total}, Start: ${heightMetric.start}, End: ${heightMetric.end}`,
|
||||
);
|
||||
if (heightMetric.isDateBased) throw new Error("height should not be date-based");
|
||||
if (heightMetric.isDateBased)
|
||||
throw new Error("height should not be date-based");
|
||||
|
||||
// Test keys() - non-date returns numbers
|
||||
// Test keys() - always numbers
|
||||
const heightKeys = heightMetric.keys();
|
||||
console.log(` keys(): ${JSON.stringify(heightKeys)}`);
|
||||
if (typeof heightKeys[0] !== "number")
|
||||
throw new Error("Expected number keys for height");
|
||||
|
||||
// Test entries() - non-date returns [number, value]
|
||||
// Test entries() - [number, value]
|
||||
const heightEntries = heightMetric.entries();
|
||||
console.log(` entries()[0]: [${heightEntries[0][0]}, ${heightEntries[0][1]}]`);
|
||||
console.log(
|
||||
` entries()[0]: [${heightEntries[0][0]}, ${heightEntries[0][1]}]`,
|
||||
);
|
||||
if (heightEntries[0][0] !== heightMetric.start)
|
||||
throw new Error("First entry index mismatch");
|
||||
|
||||
// Test toMap() - non-date
|
||||
// Test toMap() - Map<number, value>
|
||||
const heightMap = heightMetric.toMap();
|
||||
if (heightMap.size !== 3) throw new Error("Expected map size 3");
|
||||
if (heightMap.get(heightMetric.start) !== heightMetric.data[0])
|
||||
throw new Error("First value mismatch");
|
||||
|
||||
// Test for...of on non-date metric
|
||||
console.log("\n10. for...of iteration (height):");
|
||||
console.log("\n12. for...of iteration (height):");
|
||||
let heightCount = 0;
|
||||
for (const [key, val] of heightMetric) {
|
||||
for (const [key, _val] of heightMetric) {
|
||||
if (heightCount === 0 && typeof key !== "number")
|
||||
throw new Error("Expected number keys for height iteration");
|
||||
heightCount++;
|
||||
@@ -117,7 +133,7 @@ for (const [key, val] of heightMetric) {
|
||||
console.log(` Iterated ${heightCount} items`);
|
||||
|
||||
// Test different date indexes
|
||||
console.log("\n11. Testing month1:");
|
||||
console.log("\n13. Testing month1:");
|
||||
const monthMetric =
|
||||
await client.metrics.prices.usd.split.close.by.month1.first(3);
|
||||
const monthDates = monthMetric.dates();
|
||||
@@ -132,7 +148,7 @@ if (
|
||||
}
|
||||
|
||||
// Test indexToDate directly
|
||||
console.log("\n12. Testing indexToDate():");
|
||||
console.log("\n14. Testing indexToDate():");
|
||||
const genesis = client.indexToDate("day1", 0);
|
||||
if (
|
||||
genesis.getFullYear() !== 2009 ||
|
||||
@@ -199,13 +215,14 @@ console.log(` year10 0: ${d0.toISOString()}`);
|
||||
console.log(` year10 1: ${d1.toISOString()}`);
|
||||
|
||||
// Test dateToIndex
|
||||
console.log("\n13. Testing dateToIndex():");
|
||||
console.log("\n15. Testing dateToIndex():");
|
||||
const idx = client.dateToIndex("day1", new Date(Date.UTC(2009, 0, 9)));
|
||||
if (idx !== 1) throw new Error(`Expected day1 index 1, got ${idx}`);
|
||||
console.log(` day1 2009-01-09: ${idx}`);
|
||||
|
||||
const monthIdx = client.dateToIndex("month1", new Date(Date.UTC(2010, 0, 1)));
|
||||
if (monthIdx !== 12) throw new Error(`Expected month1 index 12, got ${monthIdx}`);
|
||||
if (monthIdx !== 12)
|
||||
throw new Error(`Expected month1 index 12, got ${monthIdx}`);
|
||||
console.log(` month1 2010-01-01: ${monthIdx}`);
|
||||
|
||||
const yearIdx = client.dateToIndex("year1", new Date(Date.UTC(2019, 0, 1)));
|
||||
@@ -215,15 +232,18 @@ console.log(` year1 2019-01-01: ${yearIdx}`);
|
||||
// Test roundtrip: indexToDate -> dateToIndex
|
||||
const testDate = client.indexToDate("day1", 100);
|
||||
const roundtrip = client.dateToIndex("day1", testDate);
|
||||
if (roundtrip !== 100) throw new Error(`Roundtrip failed: expected 100, got ${roundtrip}`);
|
||||
if (roundtrip !== 100)
|
||||
throw new Error(`Roundtrip failed: expected 100, got ${roundtrip}`);
|
||||
console.log(` Roundtrip day1 100: ${testDate.toISOString()} -> ${roundtrip}`);
|
||||
|
||||
// Test slice with Date
|
||||
console.log("\n14. Testing slice with Date:");
|
||||
console.log("\n16. Testing slice with Date:");
|
||||
const dateSlice = await client.metrics.prices.usd.split.close.by.day1
|
||||
.slice(new Date(Date.UTC(2020, 0, 1)), new Date(Date.UTC(2020, 0, 4)))
|
||||
.fetch();
|
||||
console.log(` Slice start: ${dateSlice.start}, end: ${dateSlice.end}, items: ${dateSlice.data.length}`);
|
||||
console.log(
|
||||
` Slice start: ${dateSlice.start}, end: ${dateSlice.end}, items: ${dateSlice.data.length}`,
|
||||
);
|
||||
if (dateSlice.data.length !== dateSlice.end - dateSlice.start)
|
||||
throw new Error("Slice data length mismatch");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user