diff --git a/packages/stargate/src/stargateclient.spec.ts b/packages/stargate/src/stargateclient.spec.ts index b6e8996d..5befdfe8 100644 --- a/packages/stargate/src/stargateclient.spec.ts +++ b/packages/stargate/src/stargateclient.spec.ts @@ -1,6 +1,6 @@ import { assert } 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,26 @@ 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("getAccount", () => { it("works for unused account", async () => { pendingWithoutSimapp(); diff --git a/packages/stargate/src/stargateclient.ts b/packages/stargate/src/stargateclient.ts index 7ee31b9f..faae603f 100644 --- a/packages/stargate/src/stargateclient.ts +++ b/packages/stargate/src/stargateclient.ts @@ -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 { const tmClient = await TendermintClient.connect(endpoint); @@ -61,6 +67,17 @@ export class StargateClient { this.tmClient = tmClient; } + public async getChainId(): Promise { + 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 getAccount(searchAddress: string): Promise { const { prefix, data: binAddress } = Bech32.decode(searchAddress); // https://github.com/cosmos/cosmos-sdk/blob/8cab43c8120fec5200c3459cbf4a92017bb6f287/x/auth/types/keys.go#L29-L32 diff --git a/packages/stargate/types/stargateclient.d.ts b/packages/stargate/types/stargateclient.d.ts index d0ea02ca..3f745705 100644 --- a/packages/stargate/types/stargateclient.d.ts +++ b/packages/stargate/types/stargateclient.d.ts @@ -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,16 @@ 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; private constructor(); + getChainId(): Promise; getAccount(searchAddress: string): Promise; getSequence(address: string): Promise; getBalance(address: string, searchDenom: string): Promise;