Skip to content

Commit

Permalink
Add blockchain.getBlockStats, blockchain.getBestBlockHash RPC (#256)
Browse files Browse the repository at this point in the history
* getBlockStats, getBestBlockHash  RCP implementation

* Fixed and implemented requested changes.

* Fixed requested changes

* Minor fixes

* Changed assertion to toStricEquals, additional test for getblockstats

* Update packages/jellyfish-api-core/src/category/blockchain.ts

Co-authored-by: Fuxing Loh <[email protected]>

* Update packages/jellyfish-api-core/__tests__/category/blockchain.test.ts

Co-authored-by: Fuxing Loh <[email protected]>

* Update packages/jellyfish-api-core/src/category/blockchain.ts

Co-authored-by: Fuxing Loh <[email protected]>

* Additional test cases for getBlockStats

* Minor fixes

* Update blockchain.md

* Minor fixes

* Update blockchain.md

Co-authored-by: Fuxing Loh <[email protected]>
  • Loading branch information
siradji and fuxingloh authored May 27, 2021
1 parent 9dfd345 commit efc0b68
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 0 deletions.
63 changes: 63 additions & 0 deletions packages/jellyfish-api-core/__tests__/category/blockchain.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -321,4 +321,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')
})
})
})
52 changes: 52 additions & 0 deletions packages/jellyfish-api-core/src/category/blockchain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,26 @@ export class Blockchain {
async getRawMempool (verbose: boolean): Promise<string[] | MempoolTx> {
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<keyof BlockStats>} stats Default = all values. See BlockStats Interface.
* @return {Promise<BlockStats>}
*/
async getBlockStats (hashOrHeight: number | string, stats?: Array<keyof BlockStats>): Promise<BlockStats> {
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<string>}
*/
async getBestBlockHash (): Promise<string> {
return await this.client.call('getbestblockhash', [], 'number')
}
}

/**
Expand Down Expand Up @@ -315,3 +335,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]
}
53 changes: 53 additions & 0 deletions website/docs/jellyfish/api/blockchain.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,3 +267,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<BlockStats>
getBlockStats(hashOrHeight: number | string, stats: Array<keyof BlockStats>): Promise<BlockStats>
}

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<string>
}
```

0 comments on commit efc0b68

Please sign in to comment.