diff --git a/packages/jellyfish-api-core/__tests__/category/blockchain.test.ts b/packages/jellyfish-api-core/__tests__/category/blockchain.test.ts index 12ef84dc46..669945a2b6 100644 --- a/packages/jellyfish-api-core/__tests__/category/blockchain.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/blockchain.test.ts @@ -314,4 +314,67 @@ describe('masternode', () => { }) }) }) + + describe('getBlockStats', () => { + it('should get blockchain stats and return all values', async () => { + const blockHash = await waitForBlockHash(1) + const stats = await client.blockchain.getBlockStats(blockHash) + + expect(stats.height).toStrictEqual(1) + expect(stats.minfee).toBeLessThanOrEqual(stats.medianfee) + expect(stats.medianfee).toBeLessThanOrEqual(stats.maxfee) + expect(stats.mediantxsize).toBeLessThanOrEqual(stats.maxtxsize) + expect(stats.avgfeerate).toBeLessThanOrEqual(stats.maxfeerate) + expect(stats.minfeerate).toBeLessThanOrEqual(stats.maxfeerate) + expect(stats.mintxsize).toBeLessThanOrEqual(stats.mediantxsize) + expect(stats.utxo_increase).toStrictEqual(stats.outs - stats.ins) + + expect(typeof stats.utxo_size_inc).toStrictEqual('number') + expect(typeof stats.avgfee).toStrictEqual('number') + expect(typeof stats.avgtxsize).toStrictEqual('number') + expect(typeof stats.blockhash).toStrictEqual('string') + expect(typeof stats.outs).toStrictEqual('number') + expect(typeof stats.totalfee).toStrictEqual('number') + expect(typeof stats.total_out).toStrictEqual('number') + expect(typeof stats.total_size).toStrictEqual('number') + expect(typeof stats.total_weight).toStrictEqual('number') + expect(typeof stats.time).toStrictEqual('number') + expect(typeof stats.swtotal_size).toStrictEqual('number') + expect(typeof stats.swtxs).toStrictEqual('number') + expect(typeof stats.swtxs).toStrictEqual('number') + expect(typeof stats.swtotal_weight).toStrictEqual('number') + expect(typeof stats.subsidy).toStrictEqual('number') + expect(typeof stats.txs).toStrictEqual('number') + expect(typeof stats.minfeerate).toStrictEqual('number') + + expect(stats.feerate_percentiles.length).toStrictEqual(5) + expect(stats.feerate_percentiles[0]).toBeLessThanOrEqual(stats.feerate_percentiles[1]) + expect(stats.feerate_percentiles[1]).toBeLessThanOrEqual(stats.feerate_percentiles[2]) + expect(stats.feerate_percentiles[2]).toBeLessThanOrEqual(stats.feerate_percentiles[3]) + expect(stats.feerate_percentiles[3]).toBeLessThanOrEqual(stats.feerate_percentiles[4]) + }) + + it('should get blockchain stats with specific values', async () => { + const blockHash = await waitForBlockHash(1) + const stats = await client.blockchain.getBlockStats(blockHash, ['avgfee', 'height']) + + expect('height' in stats).toStrictEqual(true) + expect('avgfee' in stats).toStrictEqual(true) + expect(stats.height).toStrictEqual(1) + expect(Object.keys(stats).length).toStrictEqual(2) + }) + + it('should fail when a negative height is provided', async () => { + const promise = client.blockchain.getBlockStats(-1, ['avgfee', 'height']) + await expect(promise).rejects.toThrow('Target block height -1 is negative') + }) + }) + + describe('getBestBlockHash', () => { + it('should get hash of best block and return a string', async () => { + const bestBlockHash = await client.blockchain.getBestBlockHash() + + expect(typeof bestBlockHash).toStrictEqual('string') + }) + }) }) diff --git a/packages/jellyfish-api-core/src/category/blockchain.ts b/packages/jellyfish-api-core/src/category/blockchain.ts index 18fc2df497..c1d61a3689 100644 --- a/packages/jellyfish-api-core/src/category/blockchain.ts +++ b/packages/jellyfish-api-core/src/category/blockchain.ts @@ -152,6 +152,26 @@ export class Blockchain { async getRawMempool (verbose: boolean): Promise { return await this.client.call('getrawmempool', [verbose], 'bignumber') } + + /** + * Get block statistics for a given window. + * + * @param {number} hashOrHeight The block hash or height of the target block. + * @param {Array} stats Default = all values. See BlockStats Interface. + * @return {Promise} + */ + async getBlockStats (hashOrHeight: number | string, stats?: Array): Promise { + return await this.client.call('getblockstats', [hashOrHeight, stats], 'number') + } + + /** + * Get the hash of the best (tip) block in the most-work fully-validated chain. + * + * @returns {Promise} + */ + async getBestBlockHash (): Promise { + return await this.client.call('getbestblockhash', [], 'number') + } } /** @@ -306,3 +326,35 @@ export interface MempoolTx { 'bip125-replaceable': boolean } } + +export interface BlockStats { + avgfee: number + avgfeerate: number + avgtxsize: number + blockhash: string + height: number + ins: number + maxfee: number + maxfeerate: number + maxtxsize: number + medianfee: number + mediantime: number + mediantxsize: number + minfee: number + minfeerate: number + mintxsize: number + outs: number + subsidy: number + swtxs: number + time: number + totalfee: number + txs: number + swtotal_size: number + swtotal_weight: number + total_out: number + total_size: number + total_weight: number + utxo_increase: number + utxo_size_inc: number + feerate_percentiles: [number, number, number, number, number] +} diff --git a/website/docs/jellyfish/api/blockchain.md b/website/docs/jellyfish/api/blockchain.md index 833a23f936..46572c5209 100644 --- a/website/docs/jellyfish/api/blockchain.md +++ b/website/docs/jellyfish/api/blockchain.md @@ -257,3 +257,56 @@ interface MempoolTx { } } ``` + +## getBlockStats + +Get block statistics for a given window. Returns all stats values if nothing is passed in the second param. + +```ts title="client.blockchain.getBlockStats()" +interface blockchain { + getBlockStats(hashOrHeight: number | string): Promise + getBlockStats(hashOrHeight: number | string, stats: Array): Promise +} + +interface BlockStats { + avgfee: number + avgfeerate: number + avgtxsize: number + blockhash: string + height: number + ins: number + maxfee: number + maxfeerate: number + maxtxsize: number + medianfee: number + mediantime: number + mediantxsize: number + minfee: number + minfeerate: number + mintxsize: number + outs: number + subsidy: number + swtxs: number + time: number + totalfee: number + txs: number + swtotal_size: number + swtotal_weight: number + total_out: number + total_size: number + total_weight: number + utxo_increase: number + utxo_size_inc: number + feerate_percentiles: [number, number, number, number, number] +} +``` + +## getBestBlockHash + +Get the hash of the best (tip) block in the most-work fully-validated chain. + +```ts title="client.blockchain.getBestBlockHash()" +interface blockchain { + getBestBlockHash (): Promise +} +```