diff --git a/CHANGELOG.md b/CHANGELOG.md index b15d26cb89..768e8da0cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,8 +15,9 @@ - @cosmjs/stargate: Add new package for Cosmos SDK Stargate support. - @cosmjs/tendermint-rpc: Make `Client.detectVersion` private and let it return a version instead of a client. -- @cosmjs/tendermint-rpc: Add `Client.create` for creating a Tendermint client - given an RPC client. +- @cosmjs/tendermint-rpc: Make the constructor of `Client` private. Add + `Client.create` for creating a Tendermint client given an RPC client and an + optional adaptor. ## 0.23.1 (2020-10-27) diff --git a/packages/tendermint-rpc/src/client.spec.ts b/packages/tendermint-rpc/src/client.spec.ts index b8d0235398..95d790a858 100644 --- a/packages/tendermint-rpc/src/client.spec.ts +++ b/packages/tendermint-rpc/src/client.spec.ts @@ -50,18 +50,18 @@ function defaultTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expecte expect(info).toBeTruthy(); client.disconnect(); }); - }); - it("can connect to tendermint with known version", async () => { - pendingWithoutTendermint(); - const client = new Client(rpcFactory(), adaptor); - expect(await client.abciInfo()).toBeTruthy(); - client.disconnect(); + it("can connect to Tendermint with known version", async () => { + pendingWithoutTendermint(); + const client = await Client.create(rpcFactory(), adaptor); + expect(await client.abciInfo()).toBeTruthy(); + client.disconnect(); + }); }); it("can get genesis", async () => { pendingWithoutTendermint(); - const client = new Client(rpcFactory(), adaptor); + const client = await Client.create(rpcFactory(), adaptor); const genesis = await client.genesis(); expect(genesis).toBeTruthy(); client.disconnect(); @@ -69,7 +69,7 @@ function defaultTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expecte it("can broadcast a transaction", async () => { pendingWithoutTendermint(); - const client = new Client(rpcFactory(), adaptor); + const client = await Client.create(rpcFactory(), adaptor); const tx = buildKvTx(randomString(), randomString()); const response = await client.broadcastTxCommit({ tx: tx }); @@ -87,7 +87,7 @@ function defaultTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expecte it("gets the same tx hash from backend as calculated locally", async () => { pendingWithoutTendermint(); - const client = new Client(rpcFactory(), adaptor); + const client = await Client.create(rpcFactory(), adaptor); const tx = buildKvTx(randomString(), randomString()); const calculatedTxHash = adaptor.hashTx(tx); @@ -99,7 +99,7 @@ function defaultTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expecte it("can query the state", async () => { pendingWithoutTendermint(); - const client = new Client(rpcFactory(), adaptor); + const client = await Client.create(rpcFactory(), adaptor); const key = randomString(); const value = randomString(); @@ -118,7 +118,7 @@ function defaultTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expecte it("can call a bunch of methods", async () => { pendingWithoutTendermint(); - const client = new Client(rpcFactory(), adaptor); + const client = await Client.create(rpcFactory(), adaptor); expect(await client.block()).toBeTruthy(); expect(await client.commit(4)).toBeTruthy(); @@ -132,7 +132,7 @@ function defaultTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expecte describe("status", () => { it("works", async () => { pendingWithoutTendermint(); - const client = new Client(rpcFactory(), adaptor); + const client = await Client.create(rpcFactory(), adaptor); const status = await client.status(); @@ -161,7 +161,7 @@ function defaultTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expecte describe("blockResults", () => { it("works", async () => { pendingWithoutTendermint(); - const client = new Client(rpcFactory(), adaptor); + const client = await Client.create(rpcFactory(), adaptor); const height = 3; const results = await client.blockResults(height); @@ -177,7 +177,7 @@ function defaultTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expecte describe("blockchain", () => { it("returns latest in descending order by default", async () => { pendingWithoutTendermint(); - const client = new Client(rpcFactory(), adaptor); + const client = await Client.create(rpcFactory(), adaptor); // Run in parallel to increase chance there is no block between the calls const [status, blockchain] = await Promise.all([client.status(), client.blockchain()]); @@ -194,7 +194,7 @@ function defaultTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expecte it("can limit by maxHeight", async () => { pendingWithoutTendermint(); - const client = new Client(rpcFactory(), adaptor); + const client = await Client.create(rpcFactory(), adaptor); const height = (await client.status()).syncInfo.latestBlockHeight; const blockchain = await client.blockchain(undefined, height - 1); @@ -208,7 +208,7 @@ function defaultTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expecte it("works with maxHeight in the future", async () => { pendingWithoutTendermint(); - const client = new Client(rpcFactory(), adaptor); + const client = await Client.create(rpcFactory(), adaptor); const height = (await client.status()).syncInfo.latestBlockHeight; const blockchain = await client.blockchain(undefined, height + 20); @@ -222,7 +222,7 @@ function defaultTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expecte it("can limit by minHeight and maxHeight", async () => { pendingWithoutTendermint(); - const client = new Client(rpcFactory(), adaptor); + const client = await Client.create(rpcFactory(), adaptor); const height = (await client.status()).syncInfo.latestBlockHeight; const blockchain = await client.blockchain(height - 2, height - 1); @@ -236,7 +236,7 @@ function defaultTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expecte it("contains all the info", async () => { pendingWithoutTendermint(); - const client = new Client(rpcFactory(), adaptor); + const client = await Client.create(rpcFactory(), adaptor); const height = (await client.status()).syncInfo.latestBlockHeight; const blockchain = await client.blockchain(height - 1, height - 1); @@ -266,7 +266,7 @@ function defaultTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expecte describe("tx", () => { it("can query a tx properly", async () => { pendingWithoutTendermint(); - const client = new Client(rpcFactory(), adaptor); + const client = await Client.create(rpcFactory(), adaptor); const find = randomString(); const me = randomString(); @@ -323,7 +323,7 @@ function defaultTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expecte beforeAll(async () => { if (tendermintEnabled()) { - const client = new Client(rpcFactory(), adaptor); + const client = await Client.create(rpcFactory(), adaptor); // eslint-disable-next-line no-inner-declarations async function sendTx(): Promise { @@ -349,7 +349,7 @@ function defaultTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expecte it("can paginate over txSearch results", async () => { pendingWithoutTendermint(); - const client = new Client(rpcFactory(), adaptor); + const client = await Client.create(rpcFactory(), adaptor); const query = buildQuery({ tags: [{ key: "app.key", value: key }] }); @@ -368,7 +368,7 @@ function defaultTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expecte it("can get all search results in one call", async () => { pendingWithoutTendermint(); - const client = new Client(rpcFactory(), adaptor); + const client = await Client.create(rpcFactory(), adaptor); const query = buildQuery({ tags: [{ key: "app.key", value: key }] }); @@ -393,7 +393,7 @@ function websocketTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expec (async () => { const events: responses.NewBlockHeaderEvent[] = []; - const client = new Client(rpcFactory(), adaptor); + const client = await Client.create(rpcFactory(), adaptor); const stream = client.subscribeNewBlockHeader(); expect(stream).toBeTruthy(); const subscription = stream.subscribe({ @@ -451,7 +451,7 @@ function websocketTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expec const transactionData2 = buildKvTx(randomString(), randomString()); const events: responses.NewBlockEvent[] = []; - const client = new Client(rpcFactory(), adaptor); + const client = await Client.create(rpcFactory(), adaptor); const stream = client.subscribeNewBlock(); const subscription = stream.subscribe({ next: (event) => { @@ -507,7 +507,7 @@ function websocketTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expec pendingWithoutTendermint(); const events: responses.TxEvent[] = []; - const client = new Client(rpcFactory(), adaptor); + const client = await Client.create(rpcFactory(), adaptor); const stream = client.subscribeTx(); const subscription = stream.subscribe({ next: (event) => { @@ -551,7 +551,7 @@ function websocketTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expec const transactionData2 = buildKvTx(randomString(), randomString()); const events: responses.TxEvent[] = []; - const client = new Client(rpcFactory(), adaptor); + const client = await Client.create(rpcFactory(), adaptor); const query = buildQuery({ tags: [{ key: "app.creator", value: expected.appCreator }] }); const stream = client.subscribeTx(query); expect(stream).toBeTruthy(); @@ -589,7 +589,7 @@ function websocketTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expec it("can unsubscribe and re-subscribe to the same stream", async () => { pendingWithoutTendermint(); - const client = new Client(rpcFactory(), adaptor); + const client = await Client.create(rpcFactory(), adaptor); const stream = client.subscribeNewBlockHeader(); const event1 = await firstEvent(stream); @@ -622,7 +622,7 @@ function websocketTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expec it("can subscribe twice", async () => { pendingWithoutTendermint(); - const client = new Client(rpcFactory(), adaptor); + const client = await Client.create(rpcFactory(), adaptor); const stream1 = client.subscribeNewBlockHeader(); const stream2 = client.subscribeNewBlockHeader(); diff --git a/packages/tendermint-rpc/src/client.ts b/packages/tendermint-rpc/src/client.ts index 0b158c1e85..76862189d9 100644 --- a/packages/tendermint-rpc/src/client.ts +++ b/packages/tendermint-rpc/src/client.ts @@ -27,10 +27,18 @@ export class Client { /** * Creates a new Tendermint client given an RPC client. + * + * If the adaptor is not set, an auto-detection is performed. */ - public static async create(rpcClient: RpcClient): Promise { - const version = await this.detectVersion(rpcClient); - return new Client(rpcClient, adaptorForVersion(version)); + public static async create(rpcClient: RpcClient, adaptor?: Adaptor): Promise { + let usedAdaptor: Adaptor; + if (adaptor) { + usedAdaptor = adaptor; + } else { + const version = await this.detectVersion(rpcClient); + usedAdaptor = adaptorForVersion(version); + } + return new Client(rpcClient, usedAdaptor); } private static async detectVersion(client: RpcClient): Promise { @@ -53,7 +61,10 @@ export class Client { private readonly p: Params; private readonly r: Responses; - public constructor(client: RpcClient, adaptor: Adaptor) { + /** + * Use `Client.connect` or `Client.create` to create an instance. + */ + private constructor(client: RpcClient, adaptor: Adaptor) { this.client = client; this.p = adaptor.params; this.r = adaptor.responses; diff --git a/packages/tendermint-rpc/types/client.d.ts b/packages/tendermint-rpc/types/client.d.ts index 5612c85392..ab3d3ec834 100644 --- a/packages/tendermint-rpc/types/client.d.ts +++ b/packages/tendermint-rpc/types/client.d.ts @@ -12,13 +12,18 @@ export declare class Client { static connect(url: string): Promise; /** * Creates a new Tendermint client given an RPC client. + * + * If the adaptor is not set, an auto-detection is performed. */ - static create(rpcClient: RpcClient): Promise; + static create(rpcClient: RpcClient, adaptor?: Adaptor): Promise; private static detectVersion; private readonly client; private readonly p; private readonly r; - constructor(client: RpcClient, adaptor: Adaptor); + /** + * Use `Client.connect` or `Client.create` to create an instance. + */ + private constructor(); disconnect(): void; abciInfo(): Promise; abciQuery(params: requests.AbciQueryParams): Promise;