Merge pull request #362 from CosmWasm/stargate-height-chainId

Add StargateClient.getChainId and .getHeight
This commit is contained in:
Simon Warta 2020-08-11 11:12:57 +02:00 committed by GitHub
commit a1fa442ee9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 67 additions and 2 deletions

View File

@ -1,6 +1,6 @@
import { assert } from "@cosmjs/utils";
import { assert, sleep } from "@cosmjs/utils";
import { StargateClient } from "./stargateclient";
import { PrivateStargateClient, StargateClient } from "./stargateclient";
import { nonExistentAddress, pendingWithoutSimapp, simapp, unused, validator } from "./testutils.spec";
describe("StargateClient", () => {
@ -13,6 +13,40 @@ describe("StargateClient", () => {
});
});
describe("getChainId", () => {
it("works", async () => {
pendingWithoutSimapp();
const client = await StargateClient.connect(simapp.tendermintUrl);
expect(await client.getChainId()).toEqual(simapp.chainId);
});
it("caches chain ID", async () => {
pendingWithoutSimapp();
const client = await StargateClient.connect(simapp.tendermintUrl);
const openedClient = (client as unknown) as PrivateStargateClient;
const getCodeSpy = spyOn(openedClient.tmClient, "status").and.callThrough();
expect(await client.getChainId()).toEqual(simapp.chainId); // from network
expect(await client.getChainId()).toEqual(simapp.chainId); // from cache
expect(getCodeSpy).toHaveBeenCalledTimes(1);
});
});
describe("getHeight", () => {
it("works", async () => {
pendingWithoutSimapp();
const client = await StargateClient.connect(simapp.tendermintUrl);
const height1 = await client.getHeight();
expect(height1).toBeGreaterThan(0);
await sleep(simapp.blockTime * 1.4); // tolerate chain being 40% slower than expected
const height2 = await client.getHeight();
expect(height2).toBeGreaterThanOrEqual(height1 + 1);
expect(height2).toBeLessThanOrEqual(height1 + 2);
});
});
describe("getAccount", () => {
it("works for unused account", async () => {
pendingWithoutSimapp();

View File

@ -49,8 +49,14 @@ function coinFromProto(input: cosmos.ICoin): Coin {
};
}
/** Use for testing only */
export interface PrivateStargateClient {
readonly tmClient: TendermintClient;
}
export class StargateClient {
private readonly tmClient: TendermintClient;
private chainId: string | undefined;
public static async connect(endpoint: string): Promise<StargateClient> {
const tmClient = await TendermintClient.connect(endpoint);
@ -61,6 +67,22 @@ export class StargateClient {
this.tmClient = tmClient;
}
public async getChainId(): Promise<string> {
if (!this.chainId) {
const response = await this.tmClient.status();
const chainId = response.nodeInfo.network;
if (!chainId) throw new Error("Chain ID must not be empty");
this.chainId = chainId;
}
return this.chainId;
}
public async getHeight(): Promise<number> {
const status = await this.tmClient.status();
return status.syncInfo.latestBlockHeight;
}
public async getAccount(searchAddress: string): Promise<Account | null> {
const { prefix, data: binAddress } = Bech32.decode(searchAddress);
// https://github.com/cosmos/cosmos-sdk/blob/8cab43c8120fec5200c3459cbf4a92017bb6f287/x/auth/types/keys.go#L29-L32

View File

@ -9,6 +9,7 @@ export const simapp = {
chainId: "simd-testing",
denomStaking: "ustake",
denomFee: "ucosm",
blockTime: 1_000, // ms
};
/** Unused account */

View File

@ -1,4 +1,5 @@
import { Coin, PubKey } from "@cosmjs/launchpad";
import { Client as TendermintClient } from "@cosmjs/tendermint-rpc";
export interface Account {
/** Bech32 account address */
readonly address: string;
@ -10,10 +11,17 @@ export interface SequenceResponse {
readonly accountNumber: number;
readonly sequence: number;
}
/** Use for testing only */
export interface PrivateStargateClient {
readonly tmClient: TendermintClient;
}
export declare class StargateClient {
private readonly tmClient;
private chainId;
static connect(endpoint: string): Promise<StargateClient>;
private constructor();
getChainId(): Promise<string>;
getHeight(): Promise<number>;
getAccount(searchAddress: string): Promise<Account | null>;
getSequence(address: string): Promise<SequenceResponse | null>;
getBalance(address: string, searchDenom: string): Promise<Coin | null>;