Merge pull request #587 from cosmos/rm-tagged-string-types

Remove tagged string types
This commit is contained in:
Simon Warta 2020-12-22 11:09:51 +01:00 committed by GitHub
commit 90934dd3f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 221 additions and 293 deletions

View File

@ -11,6 +11,8 @@
- @cosmjs/cosmwasm: Add `CosmWasmClient.getTx` method for searching by ID and
remove such functionality from `CosmWasmClient.searchTx`.
- @cosmjs/cosmwasm-stargate: Add new package for CosmWasm Stargate support.
- @cosmjs/crypto: Change `Secp256k1Keypair` from tagged type to simple
interface.
- @cosmjs/launchpad: Add `Secp256k1Wallet` to manage a single raw secp256k1
keypair.
- @cosmjs/launchpad: `OfflineSigner` types `sign` method renamed `signAmino`
@ -33,6 +35,10 @@
- @cosmjs/tendermint-rpc: Remove export `v0_33` in favour of `adaptor33` and
`adaptor34`. Export the `Adaptor` type.
- @cosmjs/tendermint-rpc: Export `DateTime` class.
- @cosmjs/tendermint-rpc: Remove types `QueryString`, `Base64String`,
`HexString`, `IntegerString` and `IpPortString`. Use `string` instead.
- @cosmjs/tendermint-rpc: Remove types `BlockHash`, `TxBytes` and `TxHash`. Use
`Uint8Array` instead.
## 0.23.1 (2020-10-27)

View File

@ -36,7 +36,6 @@ import {
broadcastTxCommitSuccess,
Client as TendermintClient,
DateTime,
QueryString,
} from "@cosmjs/tendermint-rpc";
import { assert } from "@cosmjs/utils";
@ -343,10 +342,7 @@ export class CosmWasmClient {
}
private async txsQuery(query: string): Promise<readonly IndexedTx[]> {
const params = {
query: query as QueryString,
};
const results = await this.tmClient.txSearchAll(params);
const results = await this.tmClient.txSearchAll({ query: query });
return results.txs.map((tx) => {
return {
height: tx.height,

View File

@ -56,7 +56,6 @@
"pbkdf2": "^3.1.1",
"ripemd160": "^2.0.2",
"sha.js": "^2.4.11",
"type-tagger": "^1.0.0",
"unorm": "^1.5.0"
},
"devDependencies": {

View File

@ -1,20 +1,17 @@
import { fromHex, toHex } from "@cosmjs/encoding";
import BN from "bn.js";
import elliptic from "elliptic";
import { As } from "type-tagger";
import { ExtendedSecp256k1Signature, Secp256k1Signature } from "./secp256k1signature";
const secp256k1 = new elliptic.ec("secp256k1");
const secp256k1N = new BN("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", "hex");
interface Keypair {
export interface Secp256k1Keypair {
readonly pubkey: Uint8Array;
readonly privkey: Uint8Array;
}
export type Secp256k1Keypair = Keypair & As<"secp256k1-keypair">;
export class Secp256k1 {
public static async makeKeypair(privkey: Uint8Array): Promise<Secp256k1Keypair> {
if (privkey.length !== 32) {
@ -35,7 +32,7 @@ export class Secp256k1 {
throw new Error("input data is not a valid secp256k1 private key");
}
const out: Keypair = {
const out: Secp256k1Keypair = {
privkey: fromHex(keypair.getPrivate("hex")),
// encodes uncompressed as
// - 1-byte prefix "04"
@ -43,7 +40,7 @@ export class Secp256k1 {
// - 32-byte y coordinate
pubkey: Uint8Array.from(keypair.getPublic("array")),
};
return out as Secp256k1Keypair;
return out;
}
// Creates a signature that is

View File

@ -1,10 +1,8 @@
import { As } from "type-tagger";
import { ExtendedSecp256k1Signature, Secp256k1Signature } from "./secp256k1signature";
interface Keypair {
export interface Secp256k1Keypair {
readonly pubkey: Uint8Array;
readonly privkey: Uint8Array;
}
export declare type Secp256k1Keypair = Keypair & As<"secp256k1-keypair">;
export declare class Secp256k1 {
static makeKeypair(privkey: Uint8Array): Promise<Secp256k1Keypair>;
static createSignature(messageHash: Uint8Array, privkey: Uint8Array): Promise<ExtendedSecp256k1Signature>;
@ -17,4 +15,3 @@ export declare class Secp256k1 {
static compressPubkey(pubkey: Uint8Array): Uint8Array;
static trimRecoveryByte(signature: Uint8Array): Uint8Array;
}
export {};

View File

@ -12,12 +12,7 @@ import {
} from "@cosmjs/launchpad";
import { Uint53, Uint64 } from "@cosmjs/math";
import { decodePubkey } from "@cosmjs/proto-signing";
import {
adaptor34,
broadcastTxCommitSuccess,
Client as TendermintClient,
QueryString,
} from "@cosmjs/tendermint-rpc";
import { adaptor34, broadcastTxCommitSuccess, Client as TendermintClient } from "@cosmjs/tendermint-rpc";
import { assert, assertDefined } from "@cosmjs/utils";
import Long from "long";
@ -281,10 +276,7 @@ export class StargateClient {
}
private async txsQuery(query: string): Promise<readonly IndexedTx[]> {
const params = {
query: query as QueryString,
};
const results = await this.tmClient.txSearchAll(params);
const results = await this.tmClient.txSearchAll({ query: query });
return results.txs.map((tx) => {
return {
height: tx.height,

View File

@ -54,7 +54,6 @@
"@cosmjs/stream": "^0.24.0-alpha.11",
"axios": "^0.19.0",
"readonly-date": "^1.0.0",
"type-tagger": "^1.0.0",
"xstream": "^11.14.0"
},
"devDependencies": {

View File

@ -3,13 +3,12 @@ import { JsonRpcRequest, JsonRpcSuccessResponse } from "@cosmjs/json-rpc";
import * as requests from "./requests";
import * as responses from "./responses";
import { SubscriptionEvent } from "./rpcclients";
import { BlockHash, TxBytes, TxHash } from "./types";
export interface Adaptor {
readonly params: Params;
readonly responses: Responses;
readonly hashTx: (tx: TxBytes) => TxHash;
readonly hashBlock: (header: responses.Header) => BlockHash;
readonly hashTx: (tx: Uint8Array) => Uint8Array;
readonly hashBlock: (header: responses.Header) => Uint8Array;
}
// Encoder is a generic that matches all methods of Params

View File

@ -2,7 +2,6 @@ import { fromBase64, fromHex } from "@cosmjs/encoding";
import { ReadonlyDate } from "readonly-date";
import { ReadonlyDateWithNanoseconds } from "../../responses";
import { TxBytes } from "../../types";
import { hashBlock, hashTx } from "./hasher";
describe("Hasher", () => {
@ -10,7 +9,7 @@ describe("Hasher", () => {
// This was taken from a result from /tx_search of some random test transaction
// curl "http://localhost:11127/tx_search?query=\"tx.hash='5CB2CF94A1097A4BC19258BC2353C3E76102B6D528458BE45C855DC5563C1DB2'\""
const txId = fromHex("5CB2CF94A1097A4BC19258BC2353C3E76102B6D528458BE45C855DC5563C1DB2");
const txData = fromBase64("YUpxZDY2NURaUDMxPWd2TzBPdnNrVWFWYg==") as TxBytes;
const txData = fromBase64("YUpxZDY2NURaUDMxPWd2TzBPdnNrVWFWYg==");
expect(hashTx(txData)).toEqual(txId);
});

View File

@ -1,4 +1,4 @@
import { Sha256 } from "@cosmjs/crypto";
import { Sha256, sha256 } from "@cosmjs/crypto";
import {
encodeBlockId,
@ -9,13 +9,11 @@ import {
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
export function hashTx(tx: TxBytes): TxHash {
const hash = new Sha256(tx).digest();
return hash as TxHash;
export function hashTx(tx: Uint8Array): Uint8Array {
return sha256(tx);
}
function getSplitPoint(n: number): number {
@ -54,7 +52,7 @@ function hashTree(hashes: readonly Uint8Array[]): Uint8Array {
}
}
export function hashBlock(header: Header): BlockHash {
export function hashBlock(header: Header): Uint8Array {
const encodedFields: readonly Uint8Array[] = [
encodeVersion(header.version),
encodeString(header.chainId),
@ -72,5 +70,5 @@ export function hashBlock(header: Header): BlockHash {
encodeBytes(header.evidenceHash),
encodeBytes(header.proposerAddress),
];
return hashTree(encodedFields) as BlockHash;
return hashTree(encodedFields);
}

View File

@ -1,16 +1,8 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { toHex } from "@cosmjs/encoding";
import { toBase64, toHex } from "@cosmjs/encoding";
import { JsonRpcRequest } from "@cosmjs/json-rpc";
import {
assertNotEmpty,
Base64,
Base64String,
HexString,
Integer,
IntegerString,
may,
} from "../../encodings";
import { assertNotEmpty, Integer, may } from "../../encodings";
import { createJsonRpcRequest } from "../../jsonrpc";
import * as requests from "../../requests";
@ -18,7 +10,7 @@ interface HeightParam {
readonly height?: number;
}
interface RpcHeightParam {
readonly height?: IntegerString;
readonly height?: string;
}
function encodeHeightParam(param: HeightParam): RpcHeightParam {
return {
@ -27,8 +19,8 @@ function encodeHeightParam(param: HeightParam): RpcHeightParam {
}
interface RpcBlockchainRequestParams {
readonly minHeight?: IntegerString;
readonly maxHeight?: IntegerString;
readonly minHeight?: string;
readonly maxHeight?: string;
}
function encodeBlockchainRequestParams(param: requests.BlockchainRequestParams): RpcBlockchainRequestParams {
@ -40,7 +32,8 @@ function encodeBlockchainRequestParams(param: requests.BlockchainRequestParams):
interface RpcAbciQueryParams {
readonly path: string;
readonly data: HexString;
/** hex encoded */
readonly data: string;
readonly height?: string;
readonly prove?: boolean;
}
@ -48,37 +41,39 @@ interface RpcAbciQueryParams {
function encodeAbciQueryParams(params: requests.AbciQueryParams): RpcAbciQueryParams {
return {
path: assertNotEmpty(params.path),
data: toHex(params.data) as HexString,
data: toHex(params.data),
height: may(Integer.encode, params.height),
prove: params.prove,
};
}
interface RpcBroadcastTxParams {
readonly tx: Base64String;
/** base64 encoded */
readonly tx: string;
}
function encodeBroadcastTxParams(params: requests.BroadcastTxParams): RpcBroadcastTxParams {
return {
tx: Base64.encode(assertNotEmpty(params.tx)),
tx: toBase64(assertNotEmpty(params.tx)),
};
}
interface RpcTxParams {
readonly hash: Base64String;
/** base64 encoded */
readonly hash: string;
readonly prove?: boolean;
}
function encodeTxParams(params: requests.TxParams): RpcTxParams {
return {
hash: Base64.encode(assertNotEmpty(params.hash)),
hash: toBase64(assertNotEmpty(params.hash)),
prove: params.prove,
};
}
interface RpcTxSearchParams {
readonly query: requests.QueryString;
readonly query: string;
readonly prove?: boolean;
readonly page?: IntegerString;
readonly per_page?: IntegerString;
readonly page?: string;
readonly per_page?: string;
}
function encodeTxSearchParams(params: requests.TxSearchParams): RpcTxSearchParams {
return {

View File

@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { fromHex } from "@cosmjs/encoding";
import { fromBase64, fromHex } from "@cosmjs/encoding";
import { JsonRpcSuccessResponse } from "@cosmjs/json-rpc";
import {
@ -10,20 +10,15 @@ import {
assertObject,
assertSet,
assertString,
Base64,
Base64String,
DateTime,
dictionaryToStringMap,
Hex,
HexString,
Integer,
IntegerString,
may,
optional,
} from "../../encodings";
import * as responses from "../../responses";
import { SubscriptionEvent } from "../../rpcclients";
import { IpPortString, TxBytes, TxHash, ValidatorPubkey, ValidatorSignature } from "../../types";
import { ValidatorPubkey, ValidatorSignature } from "../../types";
import { hashTx } from "./hasher";
interface AbciInfoResult {
@ -32,15 +27,16 @@ interface AbciInfoResult {
interface RpcAbciInfoResponse {
readonly data?: string;
readonly last_block_height?: IntegerString;
readonly last_block_app_hash?: Base64String;
readonly last_block_height?: string;
/** base64 encoded */
readonly last_block_app_hash?: string;
}
function decodeAbciInfo(data: RpcAbciInfoResponse): responses.AbciInfoResponse {
return {
data: data.data,
lastBlockHeight: may(Integer.parse, data.last_block_height),
lastBlockAppHash: may(Base64.decode, data.last_block_app_hash),
lastBlockAppHash: may(fromBase64, data.last_block_app_hash),
};
}
@ -50,8 +46,10 @@ interface AbciQueryResult {
export interface RpcProofOp {
readonly type: string;
readonly key: Base64String;
readonly data: Base64String;
/** base64 encoded */
readonly key: string;
/** base64 encoded */
readonly data: string;
}
export interface RpcQueryProof {
@ -62,26 +60,28 @@ function decodeQueryProof(data: RpcQueryProof): responses.QueryProof {
return {
ops: data.ops.map((op) => ({
type: op.type,
key: Base64.decode(op.key),
data: Base64.decode(op.data),
key: fromBase64(op.key),
data: fromBase64(op.data),
})),
};
}
interface RpcAbciQueryResponse {
readonly key: Base64String;
readonly value?: Base64String;
/** base64 encoded */
readonly key: string;
/** base64 encoded */
readonly value?: string;
readonly proof?: RpcQueryProof;
readonly height?: IntegerString;
readonly index?: IntegerString;
readonly code?: IntegerString; // only for errors
readonly height?: string;
readonly index?: string;
readonly code?: string; // only for errors
readonly log?: string;
}
function decodeAbciQuery(data: RpcAbciQueryResponse): responses.AbciQueryResponse {
return {
key: Base64.decode(optional(data.key, "" as Base64String)),
value: Base64.decode(optional(data.value, "" as Base64String)),
key: fromBase64(optional(data.key, "")),
value: fromBase64(optional(data.value, "")),
proof: may(decodeQueryProof, data.proof),
height: may(Integer.parse, data.height),
code: may(Integer.parse, data.code),
@ -91,14 +91,16 @@ function decodeAbciQuery(data: RpcAbciQueryResponse): responses.AbciQueryRespons
}
interface RpcAttribute {
readonly key: Base64String;
readonly value: Base64String;
/** base64 encoded */
readonly key: string;
/** base64 encoded */
readonly value: string;
}
function decodeAttribute(attribute: RpcAttribute): responses.Attribute {
return {
key: Base64.decode(assertNotEmpty(attribute.key)),
value: Base64.decode(assertNotEmpty(attribute.value)),
key: fromBase64(assertNotEmpty(attribute.key)),
value: fromBase64(assertNotEmpty(attribute.value)),
};
}
@ -125,13 +127,14 @@ function decodeEvents(events: readonly RpcEvent[]): readonly responses.Event[] {
interface RpcTxData {
readonly code?: number;
readonly log?: string;
readonly data?: Base64String;
/** base64 encoded */
readonly data?: string;
readonly events: readonly RpcEvent[];
}
function decodeTxData(data: RpcTxData): responses.TxData {
return {
data: may(Base64.decode, data.data),
data: may(fromBase64, data.data),
log: data.log,
code: Integer.parse(assertNumber(optional<number>(data.code, 0))),
events: decodeEvents(data.events),
@ -141,7 +144,8 @@ function decodeTxData(data: RpcTxData): responses.TxData {
// yes, a different format for status and dump consensus state
interface RpcPubkey {
readonly type: string;
readonly value: Base64String;
/** base64 encoded */
readonly value: string;
}
function decodePubkey(data: RpcPubkey): ValidatorPubkey {
@ -149,7 +153,7 @@ function decodePubkey(data: RpcPubkey): ValidatorPubkey {
// go-amino special code
return {
algorithm: "ed25519",
data: Base64.decode(assertNotEmpty(data.value)),
data: fromBase64(assertNotEmpty(data.value)),
};
}
throw new Error(`unknown pubkey type: ${data.type}`);
@ -157,22 +161,23 @@ function decodePubkey(data: RpcPubkey): ValidatorPubkey {
// for evidence, block results, etc.
interface RpcValidatorUpdate {
readonly address: HexString;
/** hex encoded */
readonly address: string;
readonly pub_key: RpcPubkey;
readonly voting_power: IntegerString;
readonly voting_power: string;
}
function decodeValidatorUpdate(data: RpcValidatorUpdate): responses.Validator {
return {
pubkey: decodePubkey(assertObject(data.pub_key)),
votingPower: Integer.parse(assertNotEmpty(data.voting_power)),
address: Hex.decode(assertNotEmpty(data.address)),
address: fromHex(assertNotEmpty(data.address)),
};
}
interface RpcBlockParams {
readonly max_bytes: IntegerString;
readonly max_gas: IntegerString;
readonly max_bytes: string;
readonly max_gas: string;
}
/**
@ -189,8 +194,8 @@ function decodeBlockParams(data: RpcBlockParams): responses.BlockParams {
}
interface RpcEvidenceParams {
readonly max_age_num_blocks: IntegerString;
readonly max_age_duration: IntegerString;
readonly max_age_num_blocks: string;
readonly max_age_duration: string;
}
function decodeEvidenceParams(data: RpcEvidenceParams): responses.EvidenceParams {
@ -232,7 +237,7 @@ function decodeConsensusParams(data: RpcConsensusParams): responses.ConsensusPar
}
interface RpcBlockResultsResponse {
readonly height: IntegerString;
readonly height: string;
readonly txs_results: readonly RpcTxData[] | null;
readonly begin_block_events: readonly RpcEvent[] | null;
readonly end_block_events: readonly RpcEvent[] | null;
@ -252,10 +257,12 @@ function decodeBlockResults(data: RpcBlockResultsResponse): responses.BlockResul
}
interface RpcBlockId {
readonly hash: HexString;
/** hex encoded */
readonly hash: string;
readonly parts: {
readonly total: IntegerString;
readonly hash: HexString;
readonly total: string;
/** hex encoded */
readonly hash: string;
};
}
@ -270,8 +277,8 @@ function decodeBlockId(data: RpcBlockId): responses.BlockId {
}
interface RpcBlockVersion {
readonly block: IntegerString;
readonly app?: IntegerString;
readonly block: string;
readonly app?: string;
}
function decodeBlockVersion(data: RpcBlockVersion): responses.Version {
@ -284,24 +291,33 @@ function decodeBlockVersion(data: RpcBlockVersion): responses.Version {
interface RpcHeader {
readonly version: RpcBlockVersion;
readonly chain_id: string;
readonly height: IntegerString;
readonly height: string;
readonly time: string;
readonly num_txs: IntegerString;
readonly total_txs: IntegerString;
readonly num_txs: string;
readonly total_txs: string;
readonly last_block_id: RpcBlockId;
readonly last_commit_hash: HexString;
readonly data_hash: HexString;
/** hex encoded */
readonly last_commit_hash: string;
/** hex encoded */
readonly data_hash: string;
readonly validators_hash: HexString;
readonly next_validators_hash: HexString;
readonly consensus_hash: HexString;
readonly app_hash: HexString;
readonly last_results_hash: HexString;
/** hex encoded */
readonly validators_hash: string;
/** hex encoded */
readonly next_validators_hash: string;
/** hex encoded */
readonly consensus_hash: string;
/** hex encoded */
readonly app_hash: string;
/** hex encoded */
readonly last_results_hash: string;
readonly evidence_hash: HexString;
readonly proposer_address: HexString;
/** hex encoded */
readonly evidence_hash: string;
/** hex encoded */
readonly proposer_address: string;
}
function decodeHeader(data: RpcHeader): responses.Header {
@ -340,7 +356,7 @@ function decodeBlockMeta(data: RpcBlockMeta): responses.BlockMeta {
}
interface RpcBlockchainResponse {
readonly last_height: IntegerString;
readonly last_height: string;
readonly block_metas: readonly RpcBlockMeta[];
}
@ -352,19 +368,21 @@ function decodeBlockchain(data: RpcBlockchainResponse): responses.BlockchainResp
}
interface RpcBroadcastTxSyncResponse extends RpcTxData {
readonly hash: HexString;
/** hex encoded */
readonly hash: string;
}
function decodeBroadcastTxSync(data: RpcBroadcastTxSyncResponse): responses.BroadcastTxSyncResponse {
return {
...decodeTxData(data),
hash: fromHex(assertNotEmpty(data.hash)) as TxHash,
hash: fromHex(assertNotEmpty(data.hash)),
};
}
interface RpcBroadcastTxCommitResponse {
readonly height: IntegerString;
readonly hash: HexString;
readonly height: string;
/** hex encoded */
readonly hash: string;
readonly check_tx: RpcTxData;
readonly deliver_tx?: RpcTxData;
}
@ -372,7 +390,7 @@ interface RpcBroadcastTxCommitResponse {
function decodeBroadcastTxCommit(data: RpcBroadcastTxCommitResponse): responses.BroadcastTxCommitResponse {
return {
height: Integer.parse(data.height),
hash: fromHex(assertNotEmpty(data.hash)) as TxHash,
hash: fromHex(assertNotEmpty(data.hash)),
checkTx: decodeTxData(assertObject(data.check_tx)),
deliverTx: may(decodeTxData, data.deliver_tx),
};
@ -380,15 +398,17 @@ function decodeBroadcastTxCommit(data: RpcBroadcastTxCommitResponse): responses.
type RpcSignature = {
readonly block_id_flag: number;
readonly validator_address: HexString;
/** hex encoded */
readonly validator_address: string;
readonly timestamp: string;
readonly signature: Base64String;
/** bae64 encoded */
readonly signature: string;
};
function decodeSignature(data: RpcSignature): ValidatorSignature {
return {
algorithm: "ed25519",
data: Base64.decode(assertNotEmpty(data.signature)),
data: fromBase64(assertNotEmpty(data.signature)),
};
}
@ -422,7 +442,7 @@ function decodeCommitResponse(data: RpcCommitResponse): responses.CommitResponse
interface RpcValidatorGenesis {
readonly pub_key: RpcPubkey;
readonly power: IntegerString;
readonly power: string;
readonly name?: string;
}
@ -441,7 +461,8 @@ interface RpcGenesisResponse {
// The validators key is used to specify a set of validators for testnets or PoA blockchains.
// PoS blockchains use the app_state.genutil.gentxs field to stake and bond a number of validators in the first block.
readonly validators?: readonly RpcValidatorGenesis[];
readonly app_hash: HexString;
/** hex encoded */
readonly app_hash: string;
readonly app_state: Record<string, unknown> | undefined;
}
@ -462,9 +483,10 @@ function decodeGenesis(data: RpcGenesisResponse): responses.GenesisResponse {
// this is in status
interface RpcValidatorInfo {
readonly address: HexString;
/** hex encoded */
readonly address: string;
readonly pub_key: RpcPubkey;
readonly voting_power: IntegerString;
readonly voting_power: string;
}
function decodeValidatorInfo(data: RpcValidatorInfo): responses.Validator {
@ -476,16 +498,18 @@ function decodeValidatorInfo(data: RpcValidatorInfo): responses.Validator {
}
interface RpcNodeInfo {
readonly id: HexString;
readonly listen_addr: IpPortString;
/** hex encoded */
readonly id: string;
/** IP and port */
readonly listen_addr: string;
readonly network: string;
readonly version: string;
readonly channels: string; // ???
readonly moniker: string;
readonly protocol_version: {
readonly p2p: IntegerString;
readonly block: IntegerString;
readonly app: IntegerString;
readonly p2p: string;
readonly block: string;
readonly app: string;
};
/**
* Additional information. E.g.
@ -515,9 +539,11 @@ function decodeNodeInfo(data: RpcNodeInfo): responses.NodeInfo {
}
interface RpcSyncInfo {
readonly latest_block_hash: HexString;
readonly latest_app_hash: HexString;
readonly latest_block_height: IntegerString;
/** hex encoded */
readonly latest_block_hash: string;
/** hex encoded */
readonly latest_app_hash: string;
readonly latest_block_height: string;
readonly latest_block_time: string;
readonly catching_up: boolean;
}
@ -560,52 +586,58 @@ function decodeStatus(data: RpcStatusResponse): responses.StatusResponse {
* }
*/
interface RpcTxProof {
readonly data: Base64String;
readonly root_hash: HexString;
/** base64 encoded */
readonly data: string;
/** hex encoded */
readonly root_hash: string;
readonly proof: {
readonly total: IntegerString;
readonly index: IntegerString;
readonly leaf_hash: Base64String;
readonly aunts: readonly Base64String[];
readonly total: string;
readonly index: string;
/** base64 encoded */
readonly leaf_hash: string;
/** base64 encoded */
readonly aunts: readonly string[];
};
}
function decodeTxProof(data: RpcTxProof): responses.TxProof {
return {
data: Base64.decode(assertNotEmpty(data.data)),
data: fromBase64(assertNotEmpty(data.data)),
rootHash: fromHex(assertNotEmpty(data.root_hash)),
proof: {
total: Integer.parse(assertNotEmpty(data.proof.total)),
index: Integer.parse(assertNotEmpty(data.proof.index)),
leafHash: Base64.decode(assertNotEmpty(data.proof.leaf_hash)),
aunts: assertArray(data.proof.aunts).map(Base64.decode),
leafHash: fromBase64(assertNotEmpty(data.proof.leaf_hash)),
aunts: assertArray(data.proof.aunts).map(fromBase64),
},
};
}
interface RpcTxResponse {
readonly tx: Base64String;
/** Raw tx bytes, base64 encoded */
readonly tx: string;
readonly tx_result: RpcTxData;
readonly height: IntegerString;
readonly height: string;
readonly index: number;
readonly hash: HexString;
/** hex encoded */
readonly hash: string;
readonly proof?: RpcTxProof;
}
function decodeTxResponse(data: RpcTxResponse): responses.TxResponse {
return {
tx: Base64.decode(assertNotEmpty(data.tx)) as TxBytes,
tx: fromBase64(assertNotEmpty(data.tx)),
result: decodeTxData(assertObject(data.tx_result)),
height: Integer.parse(assertNotEmpty(data.height)),
index: Integer.parse(assertNumber(data.index)),
hash: fromHex(assertNotEmpty(data.hash)) as TxHash,
hash: fromHex(assertNotEmpty(data.hash)),
proof: may(decodeTxProof, data.proof),
};
}
interface RpcTxSearchResponse {
readonly txs: readonly RpcTxResponse[];
readonly total_count: IntegerString;
readonly total_count: string;
}
function decodeTxSearch(data: RpcTxSearchResponse): responses.TxSearchResponse {
@ -616,15 +648,16 @@ function decodeTxSearch(data: RpcTxSearchResponse): responses.TxSearchResponse {
}
interface RpcTxEvent {
readonly tx: Base64String;
/** Raw tx bytes, base64 encoded */
readonly tx: string;
readonly result: RpcTxData;
readonly height: IntegerString;
readonly height: string;
/** Not set since Tendermint 0.34 */
readonly index?: number;
}
function decodeTxEvent(data: RpcTxEvent): responses.TxEvent {
const tx = Base64.decode(assertNotEmpty(data.tx)) as TxBytes;
const tx = fromBase64(assertNotEmpty(data.tx));
return {
tx: tx,
hash: hashTx(tx),
@ -636,7 +669,7 @@ function decodeTxEvent(data: RpcTxEvent): responses.TxEvent {
// for validators
interface RpcValidatorData extends RpcValidatorUpdate {
readonly accum?: IntegerString;
readonly accum?: string;
}
function decodeValidatorData(data: RpcValidatorData): responses.Validator {
@ -647,7 +680,7 @@ function decodeValidatorData(data: RpcValidatorData): responses.Validator {
}
interface RpcValidatorsResponse {
readonly block_height: IntegerString;
readonly block_height: string;
readonly validators: readonly RpcValidatorData[];
}
@ -661,9 +694,9 @@ function decodeValidators(data: RpcValidatorsResponse): responses.ValidatorsResp
interface RpcEvidence {
readonly type: string;
readonly validator: RpcValidatorUpdate;
readonly height: IntegerString;
readonly time: IntegerString;
readonly totalVotingPower: IntegerString;
readonly height: string;
readonly time: string;
readonly totalVotingPower: string;
}
function decodeEvidence(data: RpcEvidence): responses.Evidence {
@ -684,7 +717,8 @@ interface RpcBlock {
readonly header: RpcHeader;
readonly last_commit: RpcCommit;
readonly data: {
readonly txs?: readonly Base64String[];
/** Raw tx bytes, base64 encoded */
readonly txs?: readonly string[];
};
readonly evidence?: {
readonly evidence?: readonly RpcEvidence[];
@ -695,7 +729,7 @@ function decodeBlock(data: RpcBlock): responses.Block {
return {
header: decodeHeader(assertObject(data.header)),
lastCommit: decodeCommit(assertObject(data.last_commit)),
txs: data.data.txs ? assertArray(data.data.txs).map(Base64.decode) : [],
txs: data.data.txs ? assertArray(data.data.txs).map(fromBase64) : [],
evidence: data.evidence && may(decodeEvidences, data.evidence.evidence),
};
}

View File

@ -13,7 +13,6 @@ import { buildQuery } from "./requests";
import * as responses from "./responses";
import { HttpClient, RpcClient, WebsocketClient } from "./rpcclients";
import { chainIdMatcher } from "./testutil.spec";
import { TxBytes } from "./types";
function tendermintEnabled(): boolean {
return !!process.env.TENDERMINT_ENABLED;
@ -30,8 +29,8 @@ async function tendermintSearchIndexUpdated(): Promise<void> {
return sleep(75);
}
function buildKvTx(k: string, v: string): TxBytes {
return toAscii(`${k}=${v}`) as TxBytes;
function buildKvTx(k: string, v: string): Uint8Array {
return toAscii(`${k}=${v}`);
}
function randomString(): string {

View File

@ -186,7 +186,7 @@ export class Client {
return this.subscribe(request, this.r.decodeNewBlockHeaderEvent);
}
public subscribeTx(query?: requests.QueryString): Stream<responses.TxEvent> {
public subscribeTx(query?: string): Stream<responses.TxEvent> {
const request: requests.SubscribeRequest = {
method: requests.Method.Subscribe,
query: {

View File

@ -1,13 +1,8 @@
import { fromBase64, fromHex, fromRfc3339, toBase64, toHex, toUtf8 } from "@cosmjs/encoding";
import { fromRfc3339, toUtf8 } from "@cosmjs/encoding";
import { Int53 } from "@cosmjs/math";
import { As } from "type-tagger";
import { BlockId, ReadonlyDateWithNanoseconds, Version } from "./responses";
export type Base64String = string & As<"base64">;
export type HexString = string & As<"hex">;
export type IntegerString = string & As<"integer">;
/**
* A runtime checker that ensures a given value is set (i.e. not undefined or null)
*
@ -150,23 +145,13 @@ export function dictionaryToStringMap(obj: Record<string, unknown>): Map<string,
}
export class Integer {
public static parse(input: IntegerString | number): number {
public static parse(input: string | number): number {
const asInt = typeof input === "number" ? new Int53(input) : Int53.fromString(input);
return asInt.toNumber();
}
public static encode(num: number): IntegerString {
return new Int53(num).toString() as IntegerString;
}
}
export class Base64 {
public static encode(data: Uint8Array): Base64String {
return toBase64(data) as Base64String;
}
public static decode(base64String: Base64String): Uint8Array {
return fromBase64(base64String);
public static encode(num: number): string {
return new Int53(num).toString();
}
}
@ -186,16 +171,6 @@ export class DateTime {
}
}
export class Hex {
public static encode(data: Uint8Array): HexString {
return toHex(data) as HexString;
}
public static decode(hexString: HexString): Uint8Array {
return fromHex(hexString);
}
}
// Encodings needed for hashing block headers
// Several of these functions are inspired by https://github.com/nomic-io/js-tendermint/blob/tendermint-0.30/src/

View File

@ -16,7 +16,6 @@ export {
HealthRequest,
Method,
Request,
QueryString,
QueryTag,
StatusRequest,
SubscriptionEventType,
@ -75,9 +74,6 @@ export {
} from "./responses";
export { HttpClient, WebsocketClient } from "./rpcclients"; // TODO: Why do we export those outside of this package?
export {
IpPortString,
TxBytes,
TxHash,
ValidatorEd25519Pubkey,
ValidatorEd25519Signature,
ValidatorPubkey,

View File

@ -1,4 +1,4 @@
import { buildQuery, QueryString } from "./requests";
import { buildQuery } from "./requests";
describe("Requests", () => {
describe("buildQuery", () => {
@ -23,7 +23,7 @@ describe("Requests", () => {
});
it("works for raw input", () => {
const query = buildQuery({ raw: "aabbCCDD" as QueryString });
const query = buildQuery({ raw: "aabbCCDD" });
expect(query).toEqual("aabbCCDD");
});
@ -33,7 +33,7 @@ describe("Requests", () => {
{ key: "k", value: "9" },
{ key: "L", value: "7" },
],
raw: "aabbCCDD" as QueryString,
raw: "aabbCCDD",
});
expect(query).toEqual("k='9' AND L='7' AND aabbCCDD");
});

View File

@ -1,5 +1,4 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { As } from "type-tagger";
/**
* RPC methods as documented in https://docs.tendermint.com/master/rpc/
@ -129,12 +128,10 @@ export interface SubscribeRequest {
readonly method: Method.Subscribe;
readonly query: {
readonly type: SubscriptionEventType;
readonly raw?: QueryString;
readonly raw?: string;
};
}
export type QueryString = string & As<"query">;
export interface QueryTag {
readonly key: string;
readonly value: string;
@ -154,8 +151,9 @@ export interface TxSearchRequest {
readonly method: Method.TxSearch;
readonly params: TxSearchParams;
}
export interface TxSearchParams {
readonly query: QueryString;
readonly query: string;
readonly prove?: boolean;
readonly page?: number;
readonly per_page?: number;
@ -170,13 +168,13 @@ export interface ValidatorsRequest {
export interface BuildQueryComponents {
readonly tags?: readonly QueryTag[];
readonly raw?: QueryString;
readonly raw?: string;
}
export function buildQuery(components: BuildQueryComponents): QueryString {
export function buildQuery(components: BuildQueryComponents): string {
const tags = components.tags ? components.tags : [];
const tagComponents = tags.map((tag) => `${tag.key}='${tag.value}'`);
const rawComponents = components.raw ? [components.raw] : [];
return [...tagComponents, ...rawComponents].join(" AND ") as QueryString;
return [...tagComponents, ...rawComponents].join(" AND ");
}

View File

@ -1,6 +1,6 @@
import { ReadonlyDate } from "readonly-date";
import { IpPortString, TxBytes, TxHash, ValidatorPubkey, ValidatorSignature } from "./types";
import { ValidatorPubkey, ValidatorSignature } from "./types";
export type Response =
| AbciInfoResponse
@ -68,7 +68,7 @@ export interface BlockchainResponse {
export interface BroadcastTxAsyncResponse {}
export interface BroadcastTxSyncResponse extends TxData {
readonly hash: TxHash;
readonly hash: Uint8Array;
}
/**
@ -81,7 +81,7 @@ export function broadcastTxSyncSuccess(res: BroadcastTxSyncResponse): boolean {
export interface BroadcastTxCommitResponse {
readonly height: number;
readonly hash: TxHash;
readonly hash: Uint8Array;
readonly checkTx: TxData;
readonly deliverTx?: TxData;
}
@ -125,8 +125,8 @@ export interface StatusResponse {
* Try to keep this compatible to TxEvent
*/
export interface TxResponse {
readonly tx: TxBytes;
readonly hash: TxHash;
readonly tx: Uint8Array;
readonly hash: Uint8Array;
readonly height: number;
readonly index: number;
readonly result: TxData;
@ -150,8 +150,8 @@ export interface NewBlockEvent extends Block {}
export interface NewBlockHeaderEvent extends Header {}
export interface TxEvent {
readonly tx: TxBytes;
readonly hash: TxHash;
readonly tx: Uint8Array;
readonly hash: Uint8Array;
readonly height: number;
/** @deprecated this value is not set in Tendermint 0.34+ */
readonly index?: number;
@ -283,7 +283,8 @@ export interface Header {
export interface NodeInfo {
readonly id: Uint8Array;
readonly listenAddr: IpPortString;
/** IP and port */
readonly listenAddr: string;
readonly network: string;
readonly version: string;
readonly channels: string; // ???

View File

@ -1,23 +1,6 @@
// Types in this file are exported outside of the @cosmjs/tendermint-rpc package,
// e.g. as part of a request or response
import { As } from "type-tagger";
/**
* Merkle root
*/
export type BlockHash = Uint8Array & As<"block-hash">;
/** Raw transaction bytes */
export type TxBytes = Uint8Array & As<"tx-bytes">;
/**
* A raw tendermint transaction hash, currently 20 bytes
*/
export type TxHash = Uint8Array & As<"tx-hash">;
export type IpPortString = string & As<"ipport">;
export interface ValidatorEd25519Pubkey {
readonly algorithm: "ed25519";
readonly data: Uint8Array;

View File

@ -2,12 +2,11 @@ import { JsonRpcRequest, JsonRpcSuccessResponse } from "@cosmjs/json-rpc";
import * as requests from "./requests";
import * as responses from "./responses";
import { SubscriptionEvent } from "./rpcclients";
import { BlockHash, TxBytes, TxHash } from "./types";
export interface Adaptor {
readonly params: Params;
readonly responses: Responses;
readonly hashTx: (tx: TxBytes) => TxHash;
readonly hashBlock: (header: responses.Header) => BlockHash;
readonly hashTx: (tx: Uint8Array) => Uint8Array;
readonly hashBlock: (header: responses.Header) => Uint8Array;
}
export declare type Encoder<T extends requests.Request> = (req: T) => JsonRpcRequest;
export declare type Decoder<T extends responses.Response> = (res: JsonRpcSuccessResponse) => T;

View File

@ -1,4 +1,3 @@
import { Header } from "../../responses";
import { BlockHash, TxBytes, TxHash } from "../../types";
export declare function hashTx(tx: TxBytes): TxHash;
export declare function hashBlock(header: Header): BlockHash;
export declare function hashTx(tx: Uint8Array): Uint8Array;
export declare function hashBlock(header: Header): Uint8Array;

View File

@ -1,11 +1,12 @@
import { JsonRpcSuccessResponse } from "@cosmjs/json-rpc";
import { Base64String } from "../../encodings";
import * as responses from "../../responses";
import { SubscriptionEvent } from "../../rpcclients";
export interface RpcProofOp {
readonly type: string;
readonly key: Base64String;
readonly data: Base64String;
/** base64 encoded */
readonly key: string;
/** base64 encoded */
readonly data: string;
}
export interface RpcQueryProof {
readonly ops: readonly RpcProofOp[];

View File

@ -62,7 +62,7 @@ export declare class Client {
status(): Promise<responses.StatusResponse>;
subscribeNewBlock(): Stream<responses.NewBlockEvent>;
subscribeNewBlockHeader(): Stream<responses.NewBlockHeaderEvent>;
subscribeTx(query?: requests.QueryString): Stream<responses.TxEvent>;
subscribeTx(query?: string): Stream<responses.TxEvent>;
/**
* Get a single transaction by hash
*

View File

@ -1,8 +1,4 @@
import { As } from "type-tagger";
import { BlockId, ReadonlyDateWithNanoseconds, Version } from "./responses";
export declare type Base64String = string & As<"base64">;
export declare type HexString = string & As<"hex">;
export declare type IntegerString = string & As<"integer">;
/**
* A runtime checker that ensures a given value is set (i.e. not undefined or null)
*
@ -58,21 +54,13 @@ export declare function optional<T>(value: T | null | undefined, fallback: T): T
export declare function may<T, U>(transform: (val: T) => U, value: T | null | undefined): U | undefined;
export declare function dictionaryToStringMap(obj: Record<string, unknown>): Map<string, string>;
export declare class Integer {
static parse(input: IntegerString | number): number;
static encode(num: number): IntegerString;
}
export declare class Base64 {
static encode(data: Uint8Array): Base64String;
static decode(base64String: Base64String): Uint8Array;
static parse(input: string | number): number;
static encode(num: number): string;
}
export declare class DateTime {
static decode(dateTimeString: string): ReadonlyDateWithNanoseconds;
static encode(dateTime: ReadonlyDateWithNanoseconds): string;
}
export declare class Hex {
static encode(data: Uint8Array): HexString;
static decode(hexString: HexString): Uint8Array;
}
export declare function encodeString(s: string): Uint8Array;
export declare function encodeInt(n: number): Uint8Array;
export declare function encodeTime(time: ReadonlyDateWithNanoseconds): Uint8Array;

View File

@ -16,7 +16,6 @@ export {
HealthRequest,
Method,
Request,
QueryString,
QueryTag,
StatusRequest,
SubscriptionEventType,
@ -75,9 +74,6 @@ export {
} from "./responses";
export { HttpClient, WebsocketClient } from "./rpcclients";
export {
IpPortString,
TxBytes,
TxHash,
ValidatorEd25519Pubkey,
ValidatorEd25519Signature,
ValidatorPubkey,

View File

@ -1,4 +1,3 @@
import { As } from "type-tagger";
/**
* RPC methods as documented in https://docs.tendermint.com/master/rpc/
*
@ -113,10 +112,9 @@ export interface SubscribeRequest {
readonly method: Method.Subscribe;
readonly query: {
readonly type: SubscriptionEventType;
readonly raw?: QueryString;
readonly raw?: string;
};
}
export declare type QueryString = string & As<"query">;
export interface QueryTag {
readonly key: string;
readonly value: string;
@ -134,7 +132,7 @@ export interface TxSearchRequest {
readonly params: TxSearchParams;
}
export interface TxSearchParams {
readonly query: QueryString;
readonly query: string;
readonly prove?: boolean;
readonly page?: number;
readonly per_page?: number;
@ -147,6 +145,6 @@ export interface ValidatorsRequest {
}
export interface BuildQueryComponents {
readonly tags?: readonly QueryTag[];
readonly raw?: QueryString;
readonly raw?: string;
}
export declare function buildQuery(components: BuildQueryComponents): QueryString;
export declare function buildQuery(components: BuildQueryComponents): string;

View File

@ -1,5 +1,5 @@
import { ReadonlyDate } from "readonly-date";
import { IpPortString, TxBytes, TxHash, ValidatorPubkey, ValidatorSignature } from "./types";
import { ValidatorPubkey, ValidatorSignature } from "./types";
export declare type Response =
| AbciInfoResponse
| AbciQueryResponse
@ -57,7 +57,7 @@ export interface BlockchainResponse {
/** No data in here because RPC method BroadcastTxAsync "returns right away, with no response" */
export interface BroadcastTxAsyncResponse {}
export interface BroadcastTxSyncResponse extends TxData {
readonly hash: TxHash;
readonly hash: Uint8Array;
}
/**
* Returns true iff transaction made it sucessfully into the transaction pool
@ -65,7 +65,7 @@ export interface BroadcastTxSyncResponse extends TxData {
export declare function broadcastTxSyncSuccess(res: BroadcastTxSyncResponse): boolean;
export interface BroadcastTxCommitResponse {
readonly height: number;
readonly hash: TxHash;
readonly hash: Uint8Array;
readonly checkTx: TxData;
readonly deliverTx?: TxData;
}
@ -99,8 +99,8 @@ export interface StatusResponse {
* Try to keep this compatible to TxEvent
*/
export interface TxResponse {
readonly tx: TxBytes;
readonly hash: TxHash;
readonly tx: Uint8Array;
readonly hash: Uint8Array;
readonly height: number;
readonly index: number;
readonly result: TxData;
@ -117,8 +117,8 @@ export interface ValidatorsResponse {
export interface NewBlockEvent extends Block {}
export interface NewBlockHeaderEvent extends Header {}
export interface TxEvent {
readonly tx: TxBytes;
readonly hash: TxHash;
readonly tx: Uint8Array;
readonly hash: Uint8Array;
readonly height: number;
/** @deprecated this value is not set in Tendermint 0.34+ */
readonly index?: number;
@ -219,7 +219,8 @@ export interface Header {
}
export interface NodeInfo {
readonly id: Uint8Array;
readonly listenAddr: IpPortString;
/** IP and port */
readonly listenAddr: string;
readonly network: string;
readonly version: string;
readonly channels: string;

View File

@ -1,15 +1,3 @@
import { As } from "type-tagger";
/**
* Merkle root
*/
export declare type BlockHash = Uint8Array & As<"block-hash">;
/** Raw transaction bytes */
export declare type TxBytes = Uint8Array & As<"tx-bytes">;
/**
* A raw tendermint transaction hash, currently 20 bytes
*/
export declare type TxHash = Uint8Array & As<"tx-hash">;
export declare type IpPortString = string & As<"ipport">;
export interface ValidatorEd25519Pubkey {
readonly algorithm: "ed25519";
readonly data: Uint8Array;

View File

@ -8767,11 +8767,6 @@ type-is@^1.6.16, type-is@~1.6.17:
media-typer "0.3.0"
mime-types "~2.1.24"
type-tagger@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/type-tagger/-/type-tagger-1.0.0.tgz#dc6297e52e17097c1b92b42c16816a18f631e7f4"
integrity sha512-FIPqqpmDgdaulCnRoKv1/d3U4xVBUrYn42QXWNP3XYmgfPUDuBUsgFOb9ntT0aIe0UsUP+lknpQ5d9Kn36RssA==
typedarray-to-buffer@^3.1.5:
version "3.1.5"
resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"