mirror of
https://github.com/cosmos/cosmjs.git
synced 2025-03-11 14:09:15 +00:00
Merge pull request #538 from cosmos/reduce-dependency-on-tendermint-version-detection
Reduce dependency on tendermint version detection
This commit is contained in:
commit
030bff75fd
@ -13,6 +13,15 @@
|
||||
- @cosmjs/proto-signing: Add new package for handling transaction signing with
|
||||
protobuf encoding.
|
||||
- @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: Make the constructor of `Client` private. Add
|
||||
`Client.create` for creating a Tendermint client given an RPC client and an
|
||||
optional adaptor.
|
||||
- @cosmjs/tendermint-rpc: Add an optional adaptor argument to `Client.connect`
|
||||
which allows skipping the auto-detection.
|
||||
- @cosmjs/tendermint-rpc: Remove export `v0_33` in favour of `adaptor33` and
|
||||
`adaptor34`. Export the `Adaptor` type.
|
||||
|
||||
## 0.23.1 (2020-10-27)
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import { encodePubkey } from "@cosmjs/proto-signing";
|
||||
import { Client as TendermintClient } from "@cosmjs/tendermint-rpc";
|
||||
import { adaptor34, Client as TendermintClient } from "@cosmjs/tendermint-rpc";
|
||||
import { assert } from "@cosmjs/utils";
|
||||
import Long from "long";
|
||||
|
||||
@ -12,7 +12,7 @@ import { QueryClient } from "./queryclient";
|
||||
const { Any } = google.protobuf;
|
||||
|
||||
async function makeClientWithAuth(rpcUrl: string): Promise<[QueryClient & AuthExtension, TendermintClient]> {
|
||||
const tmClient = await TendermintClient.connect(rpcUrl);
|
||||
const tmClient = await TendermintClient.connect(rpcUrl, adaptor34);
|
||||
return [QueryClient.withExtensions(tmClient, setupAuthExtension), tmClient];
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Client as TendermintClient } from "@cosmjs/tendermint-rpc";
|
||||
import { adaptor34, Client as TendermintClient } from "@cosmjs/tendermint-rpc";
|
||||
|
||||
import {
|
||||
nonExistentAddress,
|
||||
@ -11,7 +11,7 @@ import { BankExtension, setupBankExtension } from "./bank";
|
||||
import { QueryClient } from "./queryclient";
|
||||
|
||||
async function makeClientWithBank(rpcUrl: string): Promise<[QueryClient & BankExtension, TendermintClient]> {
|
||||
const tmClient = await TendermintClient.connect(rpcUrl);
|
||||
const tmClient = await TendermintClient.connect(rpcUrl, adaptor34);
|
||||
return [QueryClient.withExtensions(tmClient, setupBankExtension), tmClient];
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Client as TendermintClient } from "@cosmjs/tendermint-rpc";
|
||||
import { adaptor34, Client as TendermintClient } from "@cosmjs/tendermint-rpc";
|
||||
import Long from "long";
|
||||
|
||||
import { cosmos, ibc } from "../codec";
|
||||
@ -8,7 +8,7 @@ import * as ibcTest from "./ibctestdata.spec";
|
||||
import { QueryClient } from "./queryclient";
|
||||
|
||||
async function makeClientWithIbc(rpcUrl: string): Promise<[QueryClient & IbcExtension, TendermintClient]> {
|
||||
const tmClient = await TendermintClient.connect(rpcUrl);
|
||||
const tmClient = await TendermintClient.connect(rpcUrl, adaptor34);
|
||||
return [QueryClient.withExtensions(tmClient, setupIbcExtension), tmClient];
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import { toAscii } from "@cosmjs/encoding";
|
||||
import { Client as TendermintClient } from "@cosmjs/tendermint-rpc";
|
||||
import { adaptor34, Client as TendermintClient } from "@cosmjs/tendermint-rpc";
|
||||
|
||||
import { cosmos } from "../codec";
|
||||
import { nonNegativeIntegerMatcher, pendingWithoutSimapp, simapp, unused } from "../testutils.spec";
|
||||
@ -11,7 +11,7 @@ const { Coin } = cosmos.base.v1beta1;
|
||||
const { QueryAllBalancesRequest, QueryAllBalancesResponse } = cosmos.bank.v1beta1;
|
||||
|
||||
async function makeClient(rpcUrl: string): Promise<[QueryClient, TendermintClient]> {
|
||||
const tmClient = await TendermintClient.connect(rpcUrl);
|
||||
const tmClient = await TendermintClient.connect(rpcUrl, adaptor34);
|
||||
return [QueryClient.withExtensions(tmClient), tmClient];
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ import {
|
||||
OfflineSigner,
|
||||
Registry,
|
||||
} from "@cosmjs/proto-signing";
|
||||
import { Client as TendermintClient } from "@cosmjs/tendermint-rpc";
|
||||
import { adaptor34, Client as TendermintClient } from "@cosmjs/tendermint-rpc";
|
||||
|
||||
import { cosmos } from "./codec";
|
||||
import { getMsgType } from "./encoding";
|
||||
@ -54,7 +54,7 @@ export class SigningStargateClient extends StargateClient {
|
||||
signer: OfflineSigner,
|
||||
options: SigningStargateClientOptions = {},
|
||||
): Promise<SigningStargateClient> {
|
||||
const tmClient = await TendermintClient.connect(endpoint);
|
||||
const tmClient = await TendermintClient.connect(endpoint, adaptor34);
|
||||
return new SigningStargateClient(tmClient, signer, options);
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,7 @@ describe("StargateClient", () => {
|
||||
pendingWithoutSimapp();
|
||||
const client = await StargateClient.connect(simapp.tendermintUrl);
|
||||
expect(await client.getChainId()).toEqual(simapp.chainId);
|
||||
client.disconnect();
|
||||
});
|
||||
|
||||
it("caches chain ID", async () => {
|
||||
@ -52,6 +53,8 @@ describe("StargateClient", () => {
|
||||
expect(await client.getChainId()).toEqual(simapp.chainId); // from cache
|
||||
|
||||
expect(getCodeSpy).toHaveBeenCalledTimes(1);
|
||||
|
||||
client.disconnect();
|
||||
});
|
||||
});
|
||||
|
||||
@ -66,6 +69,8 @@ describe("StargateClient", () => {
|
||||
const height2 = await client.getHeight();
|
||||
expect(height2).toBeGreaterThanOrEqual(height1 + 1);
|
||||
expect(height2).toBeLessThanOrEqual(height1 + 2);
|
||||
|
||||
client.disconnect();
|
||||
});
|
||||
});
|
||||
|
||||
@ -160,6 +165,8 @@ describe("StargateClient", () => {
|
||||
expect(new ReadonlyDate(response.header.time).getTime()).toBeGreaterThanOrEqual(
|
||||
ReadonlyDate.now() - 5_000,
|
||||
);
|
||||
|
||||
client.disconnect();
|
||||
});
|
||||
|
||||
it("works for block by height", async () => {
|
||||
@ -183,6 +190,8 @@ describe("StargateClient", () => {
|
||||
expect(new ReadonlyDate(response.header.time).getTime()).toBeGreaterThanOrEqual(
|
||||
ReadonlyDate.now() - 5_000,
|
||||
);
|
||||
|
||||
client.disconnect();
|
||||
});
|
||||
});
|
||||
|
||||
@ -242,13 +251,18 @@ describe("StargateClient", () => {
|
||||
denom: simapp.denomStaking,
|
||||
},
|
||||
]);
|
||||
|
||||
client.disconnect();
|
||||
});
|
||||
|
||||
it("returns an empty list for non-existent account", async () => {
|
||||
pendingWithoutSimapp();
|
||||
const client = await StargateClient.connect(simapp.tendermintUrl);
|
||||
|
||||
const balances = await client.getAllBalancesUnverified(nonExistentAddress);
|
||||
expect(balances).toEqual([]);
|
||||
|
||||
client.disconnect();
|
||||
});
|
||||
});
|
||||
|
||||
@ -309,6 +323,8 @@ describe("StargateClient", () => {
|
||||
const { rawLog, transactionHash } = txResult;
|
||||
expect(rawLog).toMatch(/{"key":"amount","value":"1234567ucosm"}/);
|
||||
expect(transactionHash).toMatch(/^[0-9A-F]{64}$/);
|
||||
|
||||
client.disconnect();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -13,7 +13,12 @@ import {
|
||||
} from "@cosmjs/launchpad";
|
||||
import { Uint53, Uint64 } from "@cosmjs/math";
|
||||
import { decodePubkey } from "@cosmjs/proto-signing";
|
||||
import { broadcastTxCommitSuccess, Client as TendermintClient, QueryString } from "@cosmjs/tendermint-rpc";
|
||||
import {
|
||||
adaptor34,
|
||||
broadcastTxCommitSuccess,
|
||||
Client as TendermintClient,
|
||||
QueryString,
|
||||
} from "@cosmjs/tendermint-rpc";
|
||||
import { assert, assertDefined } from "@cosmjs/utils";
|
||||
import Long from "long";
|
||||
|
||||
@ -121,7 +126,7 @@ export class StargateClient {
|
||||
private chainId: string | undefined;
|
||||
|
||||
public static async connect(endpoint: string): Promise<StargateClient> {
|
||||
const tmClient = await TendermintClient.connect(endpoint);
|
||||
const tmClient = await TendermintClient.connect(endpoint, adaptor34);
|
||||
return new StargateClient(tmClient);
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@
|
||||
"test-safari": "yarn pack-web && karma start --single-run --browsers Safari",
|
||||
"test": "yarn build-or-skip && yarn test-node",
|
||||
"coverage": "nyc --reporter=text --reporter=lcov yarn test --quiet",
|
||||
"move-types": "shx rm -rf ./types/* && shx mv build/types/* ./types && rm -rf ./types/testdata && shx rm -f ./types/*.spec.d.ts && shx rm ./types/**/*.spec.d.ts",
|
||||
"move-types": "shx rm -rf ./types/* && shx mv build/types/* ./types && rm -rf ./types/testdata && shx rm -f ./types/*.spec.d.ts ./types/*/*.spec.d.ts ./types/*/*/*.spec.d.ts",
|
||||
"format-types": "prettier --write --loglevel warn \"./types/**/*.d.ts\"",
|
||||
"prebuild": "shx rm -rf ./build",
|
||||
"build": "tsc",
|
||||
|
@ -1,26 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
// This module exposes translators for multiple tendermint versions
|
||||
// Pick a version that matches the server to properly encode the data types
|
||||
import { Adaptor } from "./adaptor";
|
||||
import { v0_33 } from "./v0-33";
|
||||
|
||||
const hashes = {
|
||||
v0_34: [
|
||||
"ca2c9df", // v0.34.0-rc6
|
||||
"", // See https://github.com/cosmos/cosmos-sdk/issues/7963
|
||||
],
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns an Adaptor implementation for a given tendermint version.
|
||||
* Throws when version is not supported.
|
||||
*
|
||||
* @param version full Tendermint version string, e.g. "0.20.1"
|
||||
*/
|
||||
export function adaptorForVersion(version: string): Adaptor {
|
||||
if (version.startsWith("0.33.") || version.startsWith("0.34.") || hashes.v0_34.includes(version)) {
|
||||
return v0_33;
|
||||
} else {
|
||||
throw new Error(`Unsupported tendermint version: ${version}`);
|
||||
}
|
||||
}
|
49
packages/tendermint-rpc/src/adaptors/index.ts
Normal file
49
packages/tendermint-rpc/src/adaptors/index.ts
Normal file
@ -0,0 +1,49 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import { Adaptor } from "../adaptor";
|
||||
import { v0_33 } from "./v0-33";
|
||||
|
||||
/**
|
||||
* Adaptor for Tendermint 0.33.
|
||||
*
|
||||
* Use this to skip auto-detection:
|
||||
*
|
||||
* ```
|
||||
* import { adaptor33, Client as TendermintClient } from "@cosmjs/tendermint-rpc";
|
||||
* // ...
|
||||
* const client = await TendermintClient.connect(url, adaptor33);
|
||||
* ```
|
||||
*/
|
||||
export const adaptor33 = v0_33;
|
||||
|
||||
/**
|
||||
* Adaptor for Tendermint 0.34.
|
||||
*
|
||||
* Use this to skip auto-detection:
|
||||
*
|
||||
* ```
|
||||
* import { adaptor34, Client as TendermintClient } from "@cosmjs/tendermint-rpc";
|
||||
* // ...
|
||||
* const client = await TendermintClient.connect(url, adaptor34);
|
||||
* ```
|
||||
*/
|
||||
export const adaptor34 = v0_33; // With this alias we can swap out the implementation without affecting caller code.
|
||||
|
||||
const hashes = {
|
||||
v0_34: [
|
||||
"ca2c9df", // v0.34.0-rc6
|
||||
],
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns an Adaptor implementation for a given tendermint version.
|
||||
* Throws when version is not supported.
|
||||
*
|
||||
* @param version full Tendermint version string, e.g. "0.20.1"
|
||||
*/
|
||||
export function adaptorForVersion(version: string): Adaptor {
|
||||
if (version.startsWith("0.33.") || version.startsWith("0.34.") || hashes.v0_34.includes(version)) {
|
||||
return v0_33;
|
||||
} else {
|
||||
throw new Error(`Unsupported tendermint version: ${version}`);
|
||||
}
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
import { fromBase64, fromHex } from "@cosmjs/encoding";
|
||||
import { ReadonlyDate } from "readonly-date";
|
||||
|
||||
import { ReadonlyDateWithNanoseconds } from "../responses";
|
||||
import { TxBytes } from "../types";
|
||||
import { ReadonlyDateWithNanoseconds } from "../../responses";
|
||||
import { TxBytes } from "../../types";
|
||||
import { hashBlock, hashTx } from "./hasher";
|
||||
|
||||
describe("Hasher", () => {
|
@ -1,8 +1,15 @@
|
||||
import { Sha256 } from "@cosmjs/crypto";
|
||||
|
||||
import { encodeBlockId, encodeBytes, encodeInt, encodeString, encodeTime, encodeVersion } from "../encodings";
|
||||
import { Header } from "../responses";
|
||||
import { BlockHash, TxBytes, TxHash } from "../types";
|
||||
import {
|
||||
encodeBlockId,
|
||||
encodeBytes,
|
||||
encodeInt,
|
||||
encodeString,
|
||||
encodeTime,
|
||||
encodeVersion,
|
||||
} from "../../encodings";
|
||||
import { Header } from "../../responses";
|
||||
import { BlockHash, TxBytes, TxHash } from "../../types";
|
||||
|
||||
// hash is sha256
|
||||
// https://github.com/tendermint/tendermint/blob/master/UPGRADING.md#v0260
|
@ -1,5 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import { Adaptor } from "../adaptor";
|
||||
import { Adaptor } from "../../adaptor";
|
||||
import { hashBlock, hashTx } from "./hasher";
|
||||
import { Params } from "./requests";
|
||||
import { Responses } from "./responses";
|
@ -2,9 +2,17 @@
|
||||
import { toHex } from "@cosmjs/encoding";
|
||||
import { JsonRpcRequest } from "@cosmjs/json-rpc";
|
||||
|
||||
import { assertNotEmpty, Base64, Base64String, HexString, Integer, IntegerString, may } from "../encodings";
|
||||
import { createJsonRpcRequest } from "../jsonrpc";
|
||||
import * as requests from "../requests";
|
||||
import {
|
||||
assertNotEmpty,
|
||||
Base64,
|
||||
Base64String,
|
||||
HexString,
|
||||
Integer,
|
||||
IntegerString,
|
||||
may,
|
||||
} from "../../encodings";
|
||||
import { createJsonRpcRequest } from "../../jsonrpc";
|
||||
import * as requests from "../../requests";
|
||||
|
||||
interface HeightParam {
|
||||
readonly height?: number;
|
@ -9,6 +9,7 @@ import {
|
||||
assertNumber,
|
||||
assertObject,
|
||||
assertSet,
|
||||
assertString,
|
||||
Base64,
|
||||
Base64String,
|
||||
DateTime,
|
||||
@ -20,10 +21,10 @@ import {
|
||||
IntegerString,
|
||||
may,
|
||||
optional,
|
||||
} from "../encodings";
|
||||
import * as responses from "../responses";
|
||||
import { SubscriptionEvent } from "../rpcclients";
|
||||
import { IpPortString, TxBytes, TxHash, ValidatorPubkey, ValidatorSignature } from "../types";
|
||||
} from "../../encodings";
|
||||
import * as responses from "../../responses";
|
||||
import { SubscriptionEvent } from "../../rpcclients";
|
||||
import { IpPortString, TxBytes, TxHash, ValidatorPubkey, ValidatorSignature } from "../../types";
|
||||
import { hashTx } from "./hasher";
|
||||
|
||||
interface AbciInfoResult {
|
||||
@ -502,9 +503,7 @@ function decodeNodeInfo(data: RpcNodeInfo): responses.NodeInfo {
|
||||
id: fromHex(assertNotEmpty(data.id)),
|
||||
listenAddr: assertNotEmpty(data.listen_addr),
|
||||
network: assertNotEmpty(data.network),
|
||||
// TODO: Reactivate check when https://github.com/cosmos/cosmos-sdk/issues/7963 is resolved
|
||||
// version: assertNotEmpty(data.version),
|
||||
version: data.version,
|
||||
version: assertString(data.version), // Can be empty (https://github.com/cosmos/cosmos-sdk/issues/7963)
|
||||
channels: assertNotEmpty(data.channels),
|
||||
moniker: assertNotEmpty(data.moniker),
|
||||
other: dictionaryToStringMap(data.other),
|
@ -6,7 +6,7 @@ import { ReadonlyDate } from "readonly-date";
|
||||
import { Stream } from "xstream";
|
||||
|
||||
import { Adaptor } from "./adaptor";
|
||||
import { adaptorForVersion } from "./adaptorforversion";
|
||||
import { adaptorForVersion } from "./adaptors";
|
||||
import { Client } from "./client";
|
||||
import { ExpectedValues, tendermintInstances } from "./config.spec";
|
||||
import { buildQuery } from "./requests";
|
||||
@ -42,24 +42,26 @@ function randomString(): string {
|
||||
}
|
||||
|
||||
function defaultTestSuite(rpcFactory: () => RpcClient, adaptor: Adaptor, expected: ExpectedValues): void {
|
||||
it("can connect to tendermint with known version", async () => {
|
||||
pendingWithoutTendermint();
|
||||
const client = new Client(rpcFactory(), adaptor);
|
||||
expect(await client.abciInfo()).toBeTruthy();
|
||||
client.disconnect();
|
||||
});
|
||||
describe("create", () => {
|
||||
it("can auto-discover Tendermint version and communicate", async () => {
|
||||
pendingWithoutTendermint();
|
||||
const client = await Client.create(rpcFactory());
|
||||
const info = await client.abciInfo();
|
||||
expect(info).toBeTruthy();
|
||||
client.disconnect();
|
||||
});
|
||||
|
||||
it("can auto-discover tendermint version and connect", async () => {
|
||||
pendingWithoutTendermint();
|
||||
const client = await Client.detectVersion(rpcFactory());
|
||||
const info = await client.abciInfo();
|
||||
expect(info).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();
|
||||
@ -67,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 });
|
||||
@ -85,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);
|
||||
|
||||
@ -97,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();
|
||||
@ -116,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();
|
||||
@ -130,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();
|
||||
|
||||
@ -159,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);
|
||||
@ -175,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()]);
|
||||
@ -192,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);
|
||||
@ -206,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);
|
||||
@ -220,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);
|
||||
@ -234,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);
|
||||
@ -264,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();
|
||||
@ -321,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<void> {
|
||||
@ -347,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 }] });
|
||||
|
||||
@ -366,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 }] });
|
||||
|
||||
@ -391,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({
|
||||
@ -449,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) => {
|
||||
@ -505,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) => {
|
||||
@ -549,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();
|
||||
@ -587,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);
|
||||
@ -620,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();
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Stream } from "xstream";
|
||||
|
||||
import { Adaptor, Decoder, Encoder, Params, Responses } from "./adaptor";
|
||||
import { adaptorForVersion } from "./adaptorforversion";
|
||||
import { adaptorForVersion } from "./adaptors";
|
||||
import { createJsonRpcRequest } from "./jsonrpc";
|
||||
import * as requests from "./requests";
|
||||
import * as responses from "./responses";
|
||||
@ -14,13 +14,34 @@ import {
|
||||
} from "./rpcclients";
|
||||
|
||||
export class Client {
|
||||
public static async connect(url: string): Promise<Client> {
|
||||
/**
|
||||
* Creates a new Tendermint client for the given endpoint.
|
||||
*
|
||||
* Uses HTTP when the URL schema is http or https. Uses WebSockets otherwise.
|
||||
*
|
||||
* If the adaptor is not set an auto-detection is attempted.
|
||||
*/
|
||||
public static async connect(url: string, adaptor?: Adaptor): Promise<Client> {
|
||||
const useHttp = url.startsWith("http://") || url.startsWith("https://");
|
||||
const client = useHttp ? new HttpClient(url) : new WebsocketClient(url);
|
||||
return this.detectVersion(client);
|
||||
const rpcClient = useHttp ? new HttpClient(url) : new WebsocketClient(url);
|
||||
return Client.create(rpcClient, adaptor);
|
||||
}
|
||||
|
||||
public static async detectVersion(client: RpcClient): Promise<Client> {
|
||||
/**
|
||||
* Creates a new Tendermint client given an RPC client.
|
||||
*
|
||||
* If the adaptor is not set an auto-detection is attempted.
|
||||
*/
|
||||
public static async create(rpcClient: RpcClient, adaptor?: Adaptor): Promise<Client> {
|
||||
// For some very strange reason I don't understand, tests start to fail on some systems
|
||||
// (our CI) when skipping the status call before doing other queries. Sleeping a little
|
||||
// while did not help. Thus we query the version as a way to say "hi" to the backend,
|
||||
// even in cases where we don't use the result.
|
||||
const version = await this.detectVersion(rpcClient);
|
||||
return new Client(rpcClient, adaptor || adaptorForVersion(version));
|
||||
}
|
||||
|
||||
private static async detectVersion(client: RpcClient): Promise<string> {
|
||||
const req = createJsonRpcRequest(requests.Method.Status);
|
||||
const response = await client.execute(req);
|
||||
const result = response.result;
|
||||
@ -33,15 +54,17 @@ export class Client {
|
||||
if (typeof version !== "string") {
|
||||
throw new Error("Unrecognized version format: must be string");
|
||||
}
|
||||
|
||||
return new Client(client, adaptorForVersion(version));
|
||||
return version;
|
||||
}
|
||||
|
||||
private readonly client: RpcClient;
|
||||
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;
|
||||
|
@ -40,6 +40,20 @@ export function assertBoolean(value: boolean): boolean {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* A runtime checker that ensures a given value is a string.
|
||||
*
|
||||
* This is used when you want to verify that data at runtime matches the expected type.
|
||||
* This implies assertSet.
|
||||
*/
|
||||
export function assertString(value: string): string {
|
||||
assertSet(value);
|
||||
if (typeof (value as unknown) !== "string") {
|
||||
throw new Error("Value must be a string");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* A runtime checker that ensures a given value is a number
|
||||
*
|
||||
|
@ -1,7 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
// exported to access version-specific hashing
|
||||
export { v0_33 } from "./v0-33";
|
||||
|
||||
export { Adaptor } from "./adaptor";
|
||||
export { adaptor33, adaptor34 } from "./adaptors";
|
||||
export { Client } from "./client";
|
||||
export {
|
||||
AbciInfoRequest,
|
||||
|
@ -1,8 +0,0 @@
|
||||
import { Adaptor } from "./adaptor";
|
||||
/**
|
||||
* Returns an Adaptor implementation for a given tendermint version.
|
||||
* Throws when version is not supported.
|
||||
*
|
||||
* @param version full Tendermint version string, e.g. "0.20.1"
|
||||
*/
|
||||
export declare function adaptorForVersion(version: string): Adaptor;
|
32
packages/tendermint-rpc/types/adaptors/index.d.ts
vendored
Normal file
32
packages/tendermint-rpc/types/adaptors/index.d.ts
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
import { Adaptor } from "../adaptor";
|
||||
/**
|
||||
* Adaptor for Tendermint 0.33.
|
||||
*
|
||||
* Use this to skip auto-detection:
|
||||
*
|
||||
* ```
|
||||
* import { adaptor33, Client as TendermintClient } from "@cosmjs/tendermint-rpc";
|
||||
* // ...
|
||||
* const client = await TendermintClient.connect(url, adaptor33);
|
||||
* ```
|
||||
*/
|
||||
export declare const adaptor33: Adaptor;
|
||||
/**
|
||||
* Adaptor for Tendermint 0.34.
|
||||
*
|
||||
* Use this to skip auto-detection:
|
||||
*
|
||||
* ```
|
||||
* import { adaptor34, Client as TendermintClient } from "@cosmjs/tendermint-rpc";
|
||||
* // ...
|
||||
* const client = await TendermintClient.connect(url, adaptor34);
|
||||
* ```
|
||||
*/
|
||||
export declare const adaptor34: Adaptor;
|
||||
/**
|
||||
* Returns an Adaptor implementation for a given tendermint version.
|
||||
* Throws when version is not supported.
|
||||
*
|
||||
* @param version full Tendermint version string, e.g. "0.20.1"
|
||||
*/
|
||||
export declare function adaptorForVersion(version: string): Adaptor;
|
@ -1,4 +1,4 @@
|
||||
import { Header } from "../responses";
|
||||
import { BlockHash, TxBytes, TxHash } from "../types";
|
||||
import { Header } from "../../responses";
|
||||
import { BlockHash, TxBytes, TxHash } from "../../types";
|
||||
export declare function hashTx(tx: TxBytes): TxHash;
|
||||
export declare function hashBlock(header: Header): BlockHash;
|
2
packages/tendermint-rpc/types/adaptors/v0-33/index.d.ts
vendored
Normal file
2
packages/tendermint-rpc/types/adaptors/v0-33/index.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
import { Adaptor } from "../../adaptor";
|
||||
export declare const v0_33: Adaptor;
|
@ -1,5 +1,5 @@
|
||||
import { JsonRpcRequest } from "@cosmjs/json-rpc";
|
||||
import * as requests from "../requests";
|
||||
import * as requests from "../../requests";
|
||||
export declare class Params {
|
||||
static encodeAbciInfo(req: requests.AbciInfoRequest): JsonRpcRequest;
|
||||
static encodeAbciQuery(req: requests.AbciQueryRequest): JsonRpcRequest;
|
@ -1,7 +1,7 @@
|
||||
import { JsonRpcSuccessResponse } from "@cosmjs/json-rpc";
|
||||
import { Base64String } from "../encodings";
|
||||
import * as responses from "../responses";
|
||||
import { SubscriptionEvent } from "../rpcclients";
|
||||
import { Base64String } from "../../encodings";
|
||||
import * as responses from "../../responses";
|
||||
import { SubscriptionEvent } from "../../rpcclients";
|
||||
export interface RpcProofOp {
|
||||
readonly type: string;
|
||||
readonly key: Base64String;
|
22
packages/tendermint-rpc/types/client.d.ts
vendored
22
packages/tendermint-rpc/types/client.d.ts
vendored
@ -4,12 +4,28 @@ import * as requests from "./requests";
|
||||
import * as responses from "./responses";
|
||||
import { RpcClient } from "./rpcclients";
|
||||
export declare class Client {
|
||||
static connect(url: string): Promise<Client>;
|
||||
static detectVersion(client: RpcClient): Promise<Client>;
|
||||
/**
|
||||
* Creates a new Tendermint client for the given endpoint.
|
||||
*
|
||||
* Uses HTTP when the URL schema is http or https. Uses WebSockets otherwise.
|
||||
*
|
||||
* If the adaptor is not set an auto-detection is attempted.
|
||||
*/
|
||||
static connect(url: string, adaptor?: Adaptor): Promise<Client>;
|
||||
/**
|
||||
* Creates a new Tendermint client given an RPC client.
|
||||
*
|
||||
* If the adaptor is not set an auto-detection is attempted.
|
||||
*/
|
||||
static create(rpcClient: RpcClient, adaptor?: Adaptor): Promise<Client>;
|
||||
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<responses.AbciInfoResponse>;
|
||||
abciQuery(params: requests.AbciQueryParams): Promise<responses.AbciQueryResponse>;
|
||||
|
7
packages/tendermint-rpc/types/encodings.d.ts
vendored
7
packages/tendermint-rpc/types/encodings.d.ts
vendored
@ -17,6 +17,13 @@ export declare function assertSet<T>(value: T): T;
|
||||
* This implies assertSet.
|
||||
*/
|
||||
export declare function assertBoolean(value: boolean): boolean;
|
||||
/**
|
||||
* A runtime checker that ensures a given value is a string.
|
||||
*
|
||||
* This is used when you want to verify that data at runtime matches the expected type.
|
||||
* This implies assertSet.
|
||||
*/
|
||||
export declare function assertString(value: string): string;
|
||||
/**
|
||||
* A runtime checker that ensures a given value is a number
|
||||
*
|
||||
|
3
packages/tendermint-rpc/types/index.d.ts
vendored
3
packages/tendermint-rpc/types/index.d.ts
vendored
@ -1,4 +1,5 @@
|
||||
export { v0_33 } from "./v0-33";
|
||||
export { Adaptor } from "./adaptor";
|
||||
export { adaptor33, adaptor34 } from "./adaptors";
|
||||
export { Client } from "./client";
|
||||
export {
|
||||
AbciInfoRequest,
|
||||
|
@ -1,2 +0,0 @@
|
||||
import { Adaptor } from "../adaptor";
|
||||
export declare const v0_33: Adaptor;
|
Loading…
x
Reference in New Issue
Block a user