UNPKG

@bsv/wallet-toolbox-client

Version:
140 lines 5.31 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.HeightRange = void 0; /** * Represents a range of block heights. * * Operations support integrating contiguous batches of headers, */ class HeightRange { constructor(minHeight, maxHeight) { this.minHeight = minHeight; this.maxHeight = maxHeight; } /** * @returns true iff minHeight is greater than maxHeight. */ get isEmpty() { return this.minHeight > this.maxHeight; } /** * @param headers an array of objects with a non-negative integer `height` property. * @returns range of height values from the given headers, or the empty range if there are no headers. */ static from(headers) { if (headers.length === 0) return HeightRange.empty; const minHeight = headers.reduce((min, h) => Math.min(min, h.height), headers[0].height); const maxHeight = headers.reduce((max, h) => Math.max(max, h.height), headers[0].height); return new HeightRange(minHeight, maxHeight); } /** * @returns the number of heights in the range, or 0 if the range is empty. */ get length() { return Math.max(0, this.maxHeight - this.minHeight + 1); } /** * @returns an easy to read string representation of the height range. */ toString() { return this.isEmpty ? '<empty>' : `${this.minHeight}-${this.maxHeight}`; } /** * @param range HeightRange or single height value. * @returns true if `range` is entirely within this range. */ contains(range) { if (typeof range === 'number') { return this.minHeight <= range && this.maxHeight >= range; } return this.minHeight <= range.minHeight && this.maxHeight >= range.maxHeight; } /** * Return the intersection with another height range. * * Intersection with an empty range is always empty. * * The result is always a single, possibly empty, range. * @param range * @returns */ intersect(range) { //if (this.isEmpty || range.isEmpty) return HeightRange.empty //if (this.maxHeight < range.minHeight || this.minHeight > range.maxHeight) return HeightRange.empty const r = new HeightRange(Math.max(this.minHeight, range.minHeight), Math.min(this.maxHeight, range.maxHeight)); return r; } /** * Return the union with another height range. * * Only valid if the two ranges overlap or touch, or one is empty. * * Throws an error if the union would create two disjoint ranges. * * @param range * @returns */ union(range) { if (this.isEmpty) return range.copy(); if (range.isEmpty) return this.copy(); if (this.maxHeight + 1 < range.minHeight || range.maxHeight + 1 < this.minHeight) throw new Error('Union of ranges with a gap between them is not supported.'); return new HeightRange(Math.min(this.minHeight, range.minHeight), Math.max(this.maxHeight, range.maxHeight)); } /** * Returns `range` subtracted from this range. * * Throws an error if the subtraction would create two disjoint ranges. * * @param range * @returns */ subtract(range) { if (this.isEmpty || range.isEmpty) return this.copy(); if (this.minHeight < range.minHeight && this.maxHeight > range.maxHeight) throw new Error('Subtraction of range that creates two disjoint ranges is not supported.'); if (range.maxHeight < this.minHeight || range.minHeight > this.maxHeight) // Leave untouched. Subtracted is either all lower or all higher. return this.copy(); if (range.minHeight <= this.minHeight && range.maxHeight < this.maxHeight) // Remove a chunk on the low side. return new HeightRange(range.maxHeight + 1, this.maxHeight); if (range.minHeight <= this.minHeight && range.maxHeight >= this.maxHeight) // Remove the whole thing return new HeightRange(this.minHeight, this.minHeight - 1); // empty if (range.minHeight <= this.maxHeight && range.maxHeight >= this.maxHeight) // Remove a chunk on the high side. return new HeightRange(this.minHeight, range.minHeight - 1); throw new Error('All cases should have been handled :-) .'); } /** * If `range` is not empty and this is not empty, returns a new range minHeight * replaced by to range.maxHeight + 1. * * Otherwise returns a copy of this range. * * This returns the portion of this range that is strictly above `range`. */ above(range) { if (range.isEmpty || this.isEmpty) return this.copy(); return new HeightRange(range.maxHeight + 1, this.maxHeight); } /** * Return a copy of this range. */ copy() { return new HeightRange(this.minHeight, this.maxHeight); } } exports.HeightRange = HeightRange; /** * All ranges where maxHeight is less than minHeight are considered empty. * The canonical empty range is (0, -1). */ HeightRange.empty = new HeightRange(0, -1); //# sourceMappingURL=HeightRange.js.map