Create higher level types Block, BlockHeader

This commit is contained in:
Simon Warta 2020-03-02 14:07:37 +01:00
parent 5bf3a191b3
commit 911c9f0649
6 changed files with 79 additions and 32 deletions

View File

@ -138,8 +138,8 @@ export class CosmWasmConnection implements BlockchainConnection {
}
public async height(): Promise<number> {
const { block } = await this.cosmWasmClient.getBlock();
return parseInt(block.header.height, 10);
const { header } = await this.cosmWasmClient.getBlock();
return header.height;
}
public async getToken(searchTicker: TokenTicker): Promise<Token | undefined> {
@ -247,13 +247,12 @@ export class CosmWasmConnection implements BlockchainConnection {
}
public async getBlockHeader(height: number): Promise<BlockHeader> {
// eslint-disable-next-line @typescript-eslint/camelcase
const { block_id: blockId, block } = await this.cosmWasmClient.getBlock(height);
const { id, header, txs } = await this.cosmWasmClient.getBlock(height);
return {
id: blockId.hash as BlockId,
height: parseInt(block.header.height, 10),
time: new ReadonlyDate(block.header.time),
transactionCount: block.data.txs?.length || 0,
id: id as BlockId,
height: header.height,
time: new ReadonlyDate(header.time),
transactionCount: txs.length,
};
}

View File

@ -108,39 +108,39 @@ describe("CosmWasmClient", () => {
const response = await client.getBlock();
// id
expect(response.block_id.hash).toMatch(tendermintIdMatcher);
expect(response.id).toMatch(tendermintIdMatcher);
// header
expect(parseInt(response.block.header.height, 10)).toBeGreaterThanOrEqual(1);
expect(response.block.header.chain_id).toEqual(await client.chainId());
expect(new ReadonlyDate(response.block.header.time).getTime()).toBeLessThan(ReadonlyDate.now());
expect(new ReadonlyDate(response.block.header.time).getTime()).toBeGreaterThanOrEqual(
expect(response.header.height).toBeGreaterThanOrEqual(1);
expect(response.header.chainId).toEqual(await client.chainId());
expect(new ReadonlyDate(response.header.time).getTime()).toBeLessThan(ReadonlyDate.now());
expect(new ReadonlyDate(response.header.time).getTime()).toBeGreaterThanOrEqual(
ReadonlyDate.now() - 5_000,
);
// data
expect(response.block.data.txs === null || Array.isArray(response.block.data.txs)).toEqual(true);
// txs
expect(Array.isArray(response.txs)).toEqual(true);
});
it("works for block by height", async () => {
pendingWithoutWasmd();
const client = new CosmWasmClient(wasmdEndpoint);
const height = parseInt((await client.getBlock()).block.header.height, 10);
const height = (await client.getBlock()).header.height;
const response = await client.getBlock(height - 1);
// id
expect(response.block_id.hash).toMatch(tendermintIdMatcher);
expect(response.id).toMatch(tendermintIdMatcher);
// header
expect(response.block.header.height).toEqual(`${height - 1}`);
expect(response.block.header.chain_id).toEqual(await client.chainId());
expect(new ReadonlyDate(response.block.header.time).getTime()).toBeLessThan(ReadonlyDate.now());
expect(new ReadonlyDate(response.block.header.time).getTime()).toBeGreaterThanOrEqual(
expect(response.header.height).toEqual(height - 1);
expect(response.header.chainId).toEqual(await client.chainId());
expect(new ReadonlyDate(response.header.time).getTime()).toBeLessThan(ReadonlyDate.now());
expect(new ReadonlyDate(response.header.time).getTime()).toBeGreaterThanOrEqual(
ReadonlyDate.now() - 5_000,
);
// data
expect(response.block.data.txs === null || Array.isArray(response.block.data.txs)).toEqual(true);
// txs
expect(Array.isArray(response.txs)).toEqual(true);
});
});

View File

@ -2,7 +2,7 @@ import { Sha256 } from "@iov/crypto";
import { Encoding } from "@iov/encoding";
import { Log, parseLogs } from "./logs";
import { BlockResponse, BroadcastMode, RestClient } from "./restclient";
import { BroadcastMode, RestClient } from "./restclient";
import { CosmosSdkAccount, CosmosSdkTx, StdTx } from "./types";
export interface GetNonceResult {
@ -106,6 +106,25 @@ export interface IndexedTx {
readonly timestamp: string;
}
export interface BlockHeader {
readonly version: {
readonly block: string;
readonly app: string;
};
readonly height: number;
readonly chainId: string;
/** An RFC 3339 time string like e.g. '2020-02-15T10:39:10.4696305Z' */
readonly time: string;
}
export interface Block {
/** The ID is a hash of the block header (uppercase hex) */
readonly id: string;
readonly header: BlockHeader;
/** Array of raw transactions */
readonly txs: ReadonlyArray<Uint8Array>;
}
export class CosmWasmClient {
protected readonly restClient: RestClient;
@ -159,12 +178,20 @@ export class CosmWasmClient {
*
* @param height The height of the block. If undefined, the latest height is used.
*/
public async getBlock(height?: number): Promise<BlockResponse> {
if (height !== undefined) {
return this.restClient.blocks(height);
} else {
return this.restClient.blocksLatest();
}
public async getBlock(height?: number): Promise<Block> {
const response =
height !== undefined ? await this.restClient.blocks(height) : await this.restClient.blocksLatest();
return {
id: response.block_id.hash,
header: {
version: response.block.header.version,
time: response.block.header.time,
height: parseInt(response.block.header.height, 10),
chainId: response.block.header.chain_id,
},
txs: (response.block.data.txs || []).map(encoded => Encoding.fromBase64(encoded)),
};
}
public async searchTx(query: SearchTxQuery, filter: SearchTxFilter = {}): Promise<readonly IndexedTx[]> {

View File

@ -7,6 +7,8 @@ export { unmarshalTx } from "./decoding";
export { makeSignBytes, marshalTx } from "./encoding";
export { BroadcastMode, RestClient, TxsResponse } from "./restclient";
export {
Block,
BlockHeader,
Code,
CodeDetails,
Contract,

View File

@ -1,5 +1,5 @@
import { Log } from "./logs";
import { BlockResponse, BroadcastMode, RestClient } from "./restclient";
import { BroadcastMode, RestClient } from "./restclient";
import { CosmosSdkAccount, CosmosSdkTx, StdTx } from "./types";
export interface GetNonceResult {
readonly accountNumber: number;
@ -76,6 +76,23 @@ export interface IndexedTx {
readonly gasUsed?: number;
readonly timestamp: string;
}
export interface BlockHeader {
readonly version: {
readonly block: string;
readonly app: string;
};
readonly height: number;
readonly chainId: string;
/** An RFC 3339 time string like e.g. '2020-02-15T10:39:10.4696305Z' */
readonly time: string;
}
export interface Block {
/** The ID is a hash of the block header (uppercase hex) */
readonly id: string;
readonly header: BlockHeader;
/** Array of raw transactions */
readonly txs: ReadonlyArray<Uint8Array>;
}
export declare class CosmWasmClient {
protected readonly restClient: RestClient;
constructor(url: string, broadcastMode?: BroadcastMode);
@ -98,7 +115,7 @@ export declare class CosmWasmClient {
*
* @param height The height of the block. If undefined, the latest height is used.
*/
getBlock(height?: number): Promise<BlockResponse>;
getBlock(height?: number): Promise<Block>;
searchTx(query: SearchTxQuery, filter?: SearchTxFilter): Promise<readonly IndexedTx[]>;
postTx(tx: StdTx): Promise<PostTxResult>;
getCodes(): Promise<readonly Code[]>;

View File

@ -6,6 +6,8 @@ export { unmarshalTx } from "./decoding";
export { makeSignBytes, marshalTx } from "./encoding";
export { BroadcastMode, RestClient, TxsResponse } from "./restclient";
export {
Block,
BlockHeader,
Code,
CodeDetails,
Contract,