Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

blockchain.getBlock, getBlockHeight, getBlockHash #91

Merged
merged 8 commits into from
Apr 6, 2021
133 changes: 118 additions & 15 deletions packages/jellyfish-api-core/__tests__/category/blockchain.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { RegTestContainer, MasterNodeRegTestContainer } from '@defichain/testcontainers'
import { ContainerAdapterClient } from '../container_adapter_client'
import waitForExpect from 'wait-for-expect'
import { Block, Transaction } from '../../src'

describe('non masternode', () => {
const container = new RegTestContainer()
Expand Down Expand Up @@ -55,26 +56,128 @@ describe('masternode', () => {
await container.stop()
})

it('should getBlockchainInfo', async () => {
await waitForExpect(async () => {
describe('getBlockchainInfo', () => {
it('should getBlockchainInfo', async () => {
await waitForExpect(async () => {
const info = await client.blockchain.getBlockchainInfo()
await expect(info.blocks).toBeGreaterThan(1)
})

const info = await client.blockchain.getBlockchainInfo()
await expect(info.blocks).toBeGreaterThan(1)

expect(info.chain).toBe('regtest')
expect(info.blocks).toBeGreaterThan(0)
expect(info.headers).toBeGreaterThan(0)

expect(info.bestblockhash.length).toBe(64)
expect(info.difficulty).toBeGreaterThan(0)
expect(info.mediantime).toBeGreaterThan(1550000000)

expect(info.verificationprogress).toBe(1)
expect(info.initialblockdownload).toBe(false)
expect(info.chainwork.length).toBe(64)
expect(info.size_on_disk).toBeGreaterThan(0)
expect(info.pruned).toBe(false)
})
})

const info = await client.blockchain.getBlockchainInfo()
describe('getBlock', () => {
/**
* Wait for block hash to reach a certain height
*/
async function waitForBlockHash (height: number): Promise<string> {
await waitForExpect(async () => {
const info = await client.blockchain.getBlockchainInfo()
await expect(info.blocks).toBeGreaterThan(height)
})

expect(info.chain).toBe('regtest')
expect(info.blocks).toBeGreaterThan(0)
expect(info.headers).toBeGreaterThan(0)
return await client.blockchain.getBlockHash(height)
}

expect(info.bestblockhash.length).toBe(64)
expect(info.difficulty).toBeGreaterThan(0)
expect(info.mediantime).toBeGreaterThan(1550000000)
it('should getBlock with verbosity 0 and return just a string that is serialized, hex-encoded data for block', async () => {
const blockHash = await waitForBlockHash(1)
const hash: string = await client.blockchain.getBlock(blockHash, 0)

expect(info.verificationprogress).toBe(1)
expect(info.initialblockdownload).toBe(false)
expect(info.chainwork.length).toBe(64)
expect(info.size_on_disk).toBeGreaterThan(0)
expect(info.pruned).toBe(false)
expect(hash).not.toBeNull()
})

it('should getBlock with verbosity 1 and return block with tx as hex', async () => {
const blockHash = await waitForBlockHash(1)
const block: Block<string> = await client.blockchain.getBlock(blockHash, 1)

expect(block.hash.length).toBe(64)

expect(block.confirmations).toBeGreaterThanOrEqual(2)
expect(block.strippedsize).toBeGreaterThanOrEqual(360)

expect(block.size).toBeGreaterThanOrEqual(396)
expect(block.weight).toBeGreaterThanOrEqual(1476)
expect(block.height).toBeGreaterThanOrEqual(1)

expect(block.masternode.length).toBe(64)
expect(block.minter.length).toBe(34) // legacy address length

expect(block.mintedBlocks).toBeGreaterThanOrEqual(1)
expect(block.stakeModifier.length).toBe(64)
expect(block.version).toBeGreaterThanOrEqual(536870912)
expect(block.versionHex).toStrictEqual('20000000')
expect(block.merkleroot.length).toBe(64)

expect(block.tx.length).toBeGreaterThanOrEqual(1)
expect(block.tx[0].length).toBe(64)

expect(block.time).toBeGreaterThan(1)
expect(block.mediantime).toBeGreaterThan(1)

expect(block.bits).toStrictEqual('207fffff')
expect(block.difficulty).toBeGreaterThan(0)

expect(block.chainwork.length).toBe(64)
expect(block.nTx).toBeGreaterThanOrEqual(1)
expect(block.previousblockhash.length).toBe(64)
})

it('should getBlock with verbosity 2 and return block with tx as RawText', async () => {
const blockHash = await waitForBlockHash(1)
const block: Block<Transaction> = await client.blockchain.getBlock(blockHash, 2)

expect(block.tx.length).toBeGreaterThanOrEqual(1)
expect(block.tx[0].vin[0].coinbase).toStrictEqual('5100')
expect(block.tx[0].vin[0].sequence).toBeGreaterThanOrEqual(4294967295)

expect(block.tx[0].vout[0].value).toBeGreaterThanOrEqual(38)
expect(block.tx[0].vout[0].n).toBeGreaterThanOrEqual(0)

expect(block.tx[0].vout[0].scriptPubKey.asm).toStrictEqual('OP_DUP OP_HASH160 b36814fd26190b321aa985809293a41273cfe15e OP_EQUALVERIFY OP_CHECKSIG')
expect(block.tx[0].vout[0].scriptPubKey).toHaveProperty('hex')
expect(block.tx[0].vout[0].scriptPubKey.reqSigs).toBeGreaterThanOrEqual(1)
expect(block.tx[0].vout[0].scriptPubKey.type).toStrictEqual('pubkeyhash')
expect(block.tx[0].vout[0].scriptPubKey.addresses[0].length).toBe(34)
})
})

describe('getBlockHash', () => {
it('should getBlockHash', async () => {
await waitForExpect(async () => {
const info = await client.blockchain.getBlockchainInfo()
await expect(info.blocks).toBeGreaterThan(1)
})

const blockHash: string = await client.blockchain.getBlockHash(1)
expect(blockHash).not.toBeNull()
expect(blockHash.length).toBe(64)
})
})

describe('getBlockCount', () => {
it('should getBlockCount', async () => {
await waitForExpect(async () => {
const info = await client.blockchain.getBlockchainInfo()
await expect(info.blocks).toBeGreaterThan(1)
})

const blockCount: number = await client.blockchain.getBlockCount()
expect(blockCount).toBeGreaterThanOrEqual(2)
})
})
})
114 changes: 114 additions & 0 deletions packages/jellyfish-api-core/src/category/blockchain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,57 @@ export class Blockchain {
async getBlockchainInfo (): Promise<BlockchainInfo> {
return await this.client.call('getblockchaininfo', [], 'number')
}

/**
* Get a hash of block in best-block-chain at height provided.
* @param height
* @return Promise<string>
*/
async getBlockHash (height: number): Promise<string> {
return await this.client.call('getblockhash', [height], 'number')
}

/**
* Get the height of the most-work fully-validated chain.
* @return Promise<number>
*/
async getBlockCount (): Promise<number> {
return await this.client.call('getblockcount', [], 'number')
}
canonbrother marked this conversation as resolved.
Show resolved Hide resolved

/**
* Get block data with particular header hash.
* Returns a string that is serialized, hex-encoded data for block 'hash'
*
* @param hash of the block
* @param verbosity 0
* @return Promise<string>
*/
getBlock (hash: string, verbosity: 0): Promise<string>

/**
* Get block data with particular header hash.
* Returns an Object with information about the block 'hash'.
*
* @param hash of the block
* @param verbosity 1
* @return Promise<Block<string>>
*/
getBlock (hash: string, verbosity: 1): Promise<Block<string>>

/**
* Get block data with particular header hash.
* Returns an Object with information about block 'hash' and information about each transaction.
*
* @param hash of the block
* @param verbosity 2
* @return Promise<Block<Transaction>>
*/
getBlock (hash: string, verbosity: 2): Promise<Block<Transaction>>

async getBlock<T> (hash: string, verbosity: 0 | 1 | 2): Promise<string | Block<T>> {
return await this.client.call('getblock', [hash, verbosity], 'number')
}
}

/**
Expand All @@ -43,3 +94,66 @@ export interface BlockchainInfo {
}
warnings: string
}

export interface Block<T> {
hash: string
confirmations: number
strippedsize: number
size: number
weight: number
height: number
masternode: string
minter: string
mintedBlocks: number
stakeModifier: string
version: number
versionHex: string
merkleroot: string
time: number
mediantime: number
bits: string
difficulty: number
chainwork: string
tx: T[]
nTx: number
previousblockhash: string
nextblockhash: string
}

export interface Transaction {
txid: string
hash: string
version: number
size: number
vsize: number
weight: number
locktime: number
vin: Vin[]
vout: Vout[]
hex: string
}

export interface Vin {
coinbase: string
txid: string
vout: number
scriptSig: {
asm: string
hex: string
}
txinwitness: string[]
sequence: string
}

export interface Vout {
value: number
n: number
scriptPubKey: {
asm: string
hex: string
type: string
reqSigs: number
addresses: string[]
tokenId: string
}
}
97 changes: 97 additions & 0 deletions website/docs/jellyfish/api/blockchain.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,100 @@ interface BlockchainInfo {
warnings: string
}
```

## getBlock

Get block data with particular header hash.

```ts title="client.blockchain.getBlock()"
interface blockchain {
getBlock (hash: string, verbosity: 0): Promise<string>
getBlock (hash: string, verbosity: 1): Promise<Block<string>>
getBlock (hash: string, verbosity: 2): Promise<Block<Transaction>>
getBlock<T> (hash: string, verbosity: 0 | 1 | 2): Promise<string | Block<T>>
}

export interface Block<T> {
hash: string
confirmations: number
strippedsize: number
size: number
weight: number
height: number
masternode: string
minter: string
mintedBlocks: number
stakeModifier: string
version: number
versionHex: string
merkleroot: string
time: number
mediantime: number
bits: string
difficulty: number
chainwork: string
tx: T[]
nTx: number
previousblockhash: string
nextblockhash: string
}

export interface Transaction {
txid: string
hash: string
version: number
size: number
vsize: number
weight: number
locktime: number
vin: Vin[]
vout: Vout[]
hex: string
}

export interface Vin {
coinbase: string
txid: string
vout: number
scriptSig: {
asm: string
hex: string
}
txinwitness: string[]
sequence: string
}

export interface Vout {
value: number
n: number
scriptPubKey: {
asm: string
hex: string
type: string
reqSigs: number
addresses: string[]
tokenId: string
}
}
```

## getBlockHash

Get a hash of block in best-block-chain at height provided.

```ts title="client.blockchain.getBlockHash()"
interface blockchain {
getBlockHash(height: number): Promise<string>
}
```

## getBlockCount

Get the height of the most-work fully-validated chain.

```ts title="client.blockchain.getBlockCount()"
interface blockchain {
getBlockCount (): Promise<number>
}
```