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
97 changes: 82 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 { BlockVerbo } from '../../src/category/blockchain'

describe('non masternode', () => {
const container = new RegTestContainer()
Expand Down Expand Up @@ -55,26 +56,92 @@ 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', () => {
const height: number = 1
let blockHash: string = ''
let verbosity: number = 0
canonbrother marked this conversation as resolved.
Show resolved Hide resolved

expect(info.chain).toBe('regtest')
expect(info.blocks).toBeGreaterThan(0)
expect(info.headers).toBeGreaterThan(0)
beforeAll(async () => {
canonbrother marked this conversation as resolved.
Show resolved Hide resolved
blockHash = await client.blockchain.getBlockHash(height)
})

expect(info.bestblockhash.length).toBe(64)
expect(info.difficulty).toBeGreaterThan(0)
expect(info.mediantime).toBeGreaterThan(1550000000)
it('test getblock with verbo 0, should return hash', async () => {
verbosity = 0
const data: BlockVerbo = await client.blockchain.getBlock(blockHash, verbosity)
expect(data).not.toBeNull()
})

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)
it('test getblock with verbo 1', async () => {
verbosity = 1
const data: BlockVerbo = await client.blockchain.getBlock(blockHash, verbosity)
expect(data).toHaveProperty('hash')
expect(data.confirmations).toStrictEqual(1)
expect(data.strippedsize).toStrictEqual(360)
expect(data.size).toStrictEqual(396)
expect(data.weight).toStrictEqual(1476)
expect(data.height).toStrictEqual(1)
expect(data.masternode).toStrictEqual('e86c027861cc0af423313f4152a44a83296a388eb51bf1a6dde9bd75bed55fb4')
expect(data.minter).toStrictEqual('mswsMVsyGMj1FzDMbbxw2QW3KvQAv2FKiy')
expect(data.mintedBlocks).toStrictEqual(1)
expect(data.stakeModifier).toStrictEqual('fdd82eafa32300653d3b2d9b98a6650b4b15fe2eb32cdd847d3bf2272514cfbf')
expect(data.version).toStrictEqual(536870912)
expect(data.versionHex).toStrictEqual('20000000')
expect(data.merkleroot).toStrictEqual('00eed320c213f506038fa29f77d4d2535232fa97b7789ff6fb516c63201c5e44')
expect(data.tx.length).toStrictEqual(1)
expect(data.tx[0]).toStrictEqual('00eed320c213f506038fa29f77d4d2535232fa97b7789ff6fb516c63201c5e44')
expect(data).toHaveProperty('time')
expect(data).toHaveProperty('mediantime')
expect(data.bits).toStrictEqual('207fffff')
expect(data.difficulty).toStrictEqual(4.656542373906925e-10)
expect(data.chainwork).toStrictEqual('0000000000000000000000000000000000000000000000000000000000000004')
expect(data.nTx).toStrictEqual(1)
expect(data.previousblockhash).toStrictEqual('0091f00915b263d08eba2091ba70ba40cea75242b3f51ea29f4a1b8d7814cd01')

// NOTE(canonbrother): Get block without verbo, the verbo default should be 1
const dataTestWithoutVerbo: BlockVerbo = await client.blockchain.getBlock(blockHash)
expect(data).toStrictEqual(dataTestWithoutVerbo)
})

it('test getblock with verbo2', async () => {
verbosity = 2
const data: BlockVerbo = await client.blockchain.getBlock(blockHash, verbosity)
console.log('data: ', data)
// NOTE(canonbrother): The only diff between verbo1 and verbo2 is "tx" format
expect(data.tx.length).toStrictEqual(1)
expect(data.tx[0].vin[0].coinbase).toStrictEqual('5100')
expect(data.tx[0].vin[0].sequence).toStrictEqual(4294967295)
expect(data.tx[0].vout[0].value).toStrictEqual(38)
expect(data.tx[0].vout[0].n).toStrictEqual(0)
expect(data.tx[0].vout[0].scriptPubKey.asm).toStrictEqual('OP_DUP OP_HASH160 b36814fd26190b321aa985809293a41273cfe15e OP_EQUALVERIFY OP_CHECKSIG')
expect(data.tx[0].vout[0].scriptPubKey).toHaveProperty('hex')
expect(data.tx[0].vout[0].scriptPubKey.reqSigs).toStrictEqual(1)
expect(data.tx[0].vout[0].scriptPubKey.type).toStrictEqual('pubkeyhash')
expect(data.tx[0].vout[0].scriptPubKey.addresses[0]).toStrictEqual('mwsZw8nF7pKxWH8eoKL9tPxTpaFkz7QeLU')
})
})
})
103 changes: 103 additions & 0 deletions packages/jellyfish-api-core/src/category/blockchain.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { ApiClient } from '../.'

type BlockVerbo0 = 'string'
export type BlockVerbo = BlockVerbo2 | BlockVerbo1 | BlockVerbo0

/**
* Blockchain related RPC calls for DeFiChain
*/
Expand All @@ -17,6 +20,36 @@ 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.
* @param blockHash
* @param verbosity optional, default is 1, 0 for hex encoded
* @return Promise<BlockVerbo>
*/
async getBlock (blockHash: string, verbosity?: number): Promise<BlockVerbo2>
async getBlock (blockHash: string, verbosity?: number): Promise<BlockVerbo1>
async getBlock (blockHash: string, verbosity?: number): Promise<BlockVerbo0>
async getBlock (blockHash: string, verbosity?: number): Promise<BlockVerbo> {
return await this.client.call('getblock', [blockHash, verbosity], 'number')
}
}

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

export interface BlockBase {
hash: string
confirmations: number
strippedsize: number
size: number
weight: number
height: number
masternode: string
minter: string
mintedBlocks: any
stakeModifier: any
canonbrother marked this conversation as resolved.
Show resolved Hide resolved
version: number
versionHex: string
merkleroot: string
time: number
mediantime: number
bits: string
difficulty: number
chainwork: string
nTx: number
previousblockhash: string
nextblockhash: string
}

export interface BlockVerbo1 extends BlockBase {
tx: string[]
}

export interface BlockVerbo2 extends BlockBase {
tx: RawTx[]
}
canonbrother marked this conversation as resolved.
Show resolved Hide resolved

export interface RawTx {
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
}
}
101 changes: 101 additions & 0 deletions website/docs/jellyfish/api/blockchain.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,104 @@ interface BlockchainInfo {
warnings: string
}
```

## getBlock

Get block data with particular header hash.

```ts title="client.blockchain.getBlock()"
interface blockchain {
getBlock(): Promise<BlockVerbo>;
}

interface BlockBase {
hash: string
confirmations: number
strippedsize: number
size: number
weight: number
height: number
masternode: string
minter: string
mintedBlocks: any
stakeModifier: any
version: number
versionHex: string
merkleroot: string
time: number
mediantime: number
bits: string
difficulty: number
chainwork: string
nTx: number
previousblockhash: string
nextblockhash: string
}

interface BlockVerbo1 extends BlockBase {
tx: string[]
}

interface BlockVerbo2 extends BlockBase {
tx: RawTx[]
}

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

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

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