@bsv/wallet-toolbox
Version:
BRC100 conforming wallet, wallet storage and wallet signer components
137 lines • 5.87 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.WhatsOnChainServices = void 0;
exports.wocGetHeadersHeaderToBlockHeader = wocGetHeadersHeaderToBlockHeader;
const WhatsOnChain_1 = require("../../../providers/WhatsOnChain");
const ChaintracksFetch_1 = require("../util/ChaintracksFetch");
const HeightRange_1 = require("../util/HeightRange");
class WhatsOnChainServices {
static createWhatsOnChainServicesOptions(chain) {
const options = {
chain,
apiKey: '',
timeout: 30000,
userAgent: 'BabbageWhatsOnChainServices',
enableCache: true,
chainInfoMsecs: 5000
};
return options;
}
constructor(options) {
this.options = options;
const config = {
apiKey: this.options.apiKey,
timeout: this.options.timeout,
userAgent: this.options.userAgent,
enableCache: this.options.enableCache
};
this.chain = options.chain;
WhatsOnChainServices.chainInfoMsecs[this.chain] = options.chainInfoMsecs;
this.woc = new WhatsOnChain_1.WhatsOnChain(this.chain, config);
}
async getHeaderByHash(hash) {
const header = await this.woc.getBlockHeaderByHash(hash);
return header;
}
async getChainInfo() {
const now = new Date();
let update = WhatsOnChainServices.chainInfo[this.chain] === undefined;
if (!update && WhatsOnChainServices.chainInfoTime[this.chain] !== undefined) {
const elapsed = now.getTime() - WhatsOnChainServices.chainInfoTime[this.chain].getTime();
update = elapsed > WhatsOnChainServices.chainInfoMsecs[this.chain];
}
if (update) {
WhatsOnChainServices.chainInfo[this.chain] = await this.woc.getChainInfo();
WhatsOnChainServices.chainInfoTime[this.chain] = now;
}
if (!WhatsOnChainServices.chainInfo[this.chain])
throw new Error('Unexpected failure to update chainInfo.');
return WhatsOnChainServices.chainInfo[this.chain];
}
async getChainTipHeight() {
return (await this.getChainInfo()).blocks;
}
async getChainTipHash() {
return (await this.getChainInfo()).bestblockhash;
}
/**
* @param fetch
* @returns returns the last 10 block headers including height, size, chainwork...
*/
async getHeaders(fetch) {
fetch || (fetch = new ChaintracksFetch_1.ChaintracksFetch());
const headers = await fetch.fetchJson(`https://api.whatsonchain.com/v1/bsv/${this.chain}/block/headers`);
return headers;
}
async getHeaderByteFileLinks(neededRange, fetch) {
fetch || (fetch = new ChaintracksFetch_1.ChaintracksFetch());
const files = await fetch.fetchJson(`https://api.whatsonchain.com/v1/bsv/${this.chain}/block/headers/resources`);
const r = [];
let range = undefined;
for (const link of files.files) {
const parsed = parseFileLink(link);
if (parsed === undefined)
continue; // parse error, return empty result
if (parsed.range === 'latest') {
if (range === undefined)
continue; // should not happen on valid input
const fromHeight = range.maxHeight + 1;
if (neededRange.maxHeight >= fromHeight) {
// We need this range but don't know maxHeight
const data = await fetch.download(link);
range = new HeightRange_1.HeightRange(fromHeight, fromHeight + data.length / 80 - 1);
if (!neededRange.intersect(range).isEmpty)
r.push({ sourceUrl: parsed.sourceUrl, fileName: parsed.fileName, range, data });
}
}
else {
range = new HeightRange_1.HeightRange(parsed.range.fromHeight, parsed.range.toHeight);
if (!neededRange.intersect(range).isEmpty)
r.push({ sourceUrl: parsed.sourceUrl, fileName: parsed.fileName, range, data: undefined });
}
}
return r;
function parseFileLink(file) {
const url = new URL(file);
const parts = url.pathname.split('/');
const fileName = parts.pop();
if (!fileName)
return undefined; // no file name, invalid link
const sourceUrl = `${url.protocol}//${url.hostname}${parts.join('/')}`;
const bits = fileName.split('_');
if (bits.length === 1 && bits[0] === 'latest') {
return { range: 'latest', sourceUrl, fileName };
}
if (bits.length === 3) {
const fromHeight = parseInt(bits[0], 10);
const toHeight = parseInt(bits[1], 10);
if (Number.isInteger(fromHeight) && Number.isInteger(toHeight)) {
return { range: { fromHeight, toHeight }, sourceUrl, fileName };
}
}
return undefined;
}
}
}
exports.WhatsOnChainServices = WhatsOnChainServices;
WhatsOnChainServices.chainInfo = [];
WhatsOnChainServices.chainInfoTime = [];
WhatsOnChainServices.chainInfoMsecs = [];
function wocGetHeadersHeaderToBlockHeader(h) {
const bits = typeof h.bits === 'string' ? parseInt(h.bits, 16) : h.bits;
if (!h.previousblockhash) {
h.previousblockhash = '0000000000000000000000000000000000000000000000000000000000000000'; // genesis
}
const bh = {
height: h.height,
hash: h.hash,
version: h.version,
previousHash: h.previousblockhash,
merkleRoot: h.merkleroot,
time: h.time,
bits,
nonce: h.nonce
};
return bh;
}
//# sourceMappingURL=WhatsOnChainServices.js.map