diff --git a/packages/bcp/src/address.spec.ts b/packages/bcp/src/address.spec.ts index cdfd3e31..0b52e387 100644 --- a/packages/bcp/src/address.spec.ts +++ b/packages/bcp/src/address.spec.ts @@ -1,7 +1,7 @@ import { Algorithm, PubkeyBytes } from "@iov/bcp"; import { Encoding } from "@iov/encoding"; -import { decodeCosmosPubkey, isValidAddress, pubkeyToAddress } from "./address"; +import { decodeCosmosPubkey, pubkeyToAddress } from "./address"; const { fromBase64, fromHex } = Encoding; @@ -17,23 +17,6 @@ describe("address", () => { }); }); - describe("isValidAddress", () => { - it("accepts valid addresses", () => { - expect(isValidAddress("cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6")).toEqual(true); - expect(isValidAddress("cosmosvalcons10q82zkzzmaku5lazhsvxv7hsg4ntpuhdwadmss")).toEqual(true); - expect(isValidAddress("cosmosvaloper17mggn4znyeyg25wd7498qxl7r2jhgue8u4qjcq")).toEqual(true); - }); - - it("rejects invalid addresses", () => { - // Bad size - expect(isValidAddress("cosmos10q82zkzzmaku5lazhsvxv7hsg4ntpuhh8289f")).toEqual(false); - // Bad checksum - expect(isValidAddress("cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs7")).toEqual(false); - // Bad prefix - expect(isValidAddress("cosmot10q82zkzzmaku5lazhsvxv7hsg4ntpuhd8j5266")).toEqual(false); - }); - }); - describe("pubkeyToAddress", () => { it("works for Secp256k1 compressed", () => { const prefix = "cosmos"; diff --git a/packages/bcp/src/address.ts b/packages/bcp/src/address.ts index ce6aa25b..c702edea 100644 --- a/packages/bcp/src/address.ts +++ b/packages/bcp/src/address.ts @@ -1,10 +1,8 @@ -import { CosmosBech32Prefix, decodeBech32Pubkey, encodeAddress, isValidAddress, types } from "@cosmwasm/sdk"; +import { CosmosAddressBech32Prefix, decodeBech32Pubkey, encodeAddress, types } from "@cosmwasm/sdk"; import { Address, Algorithm, PubkeyBundle, PubkeyBytes } from "@iov/bcp"; import { Secp256k1 } from "@iov/crypto"; import { Encoding } from "@iov/encoding"; -export { CosmosBech32Prefix, isValidAddress }; - const { fromBase64, toBase64 } = Encoding; export function decodeCosmosPubkey( @@ -22,7 +20,7 @@ export function decodeCosmosPubkey( } // See https://github.com/tendermint/tendermint/blob/f2ada0a604b4c0763bda2f64fac53d506d3beca7/docs/spec/blockchain/encoding.md#public-key-cryptography -export function pubkeyToAddress(pubkey: PubkeyBundle, prefix: CosmosBech32Prefix): Address { +export function pubkeyToAddress(pubkey: PubkeyBundle, prefix: CosmosAddressBech32Prefix): Address { let sdkKey: types.PubKey; if (pubkey.algo === Algorithm.Secp256k1) { sdkKey = { diff --git a/packages/bcp/src/cosmwasmcodec.spec.ts b/packages/bcp/src/cosmwasmcodec.spec.ts index 8f5604be..e82d3870 100644 --- a/packages/bcp/src/cosmwasmcodec.spec.ts +++ b/packages/bcp/src/cosmwasmcodec.spec.ts @@ -7,6 +7,27 @@ import { chainId, nonce, sendTxJson, signedTxBin, signedTxEncodedJson, signedTxJ const { toUtf8 } = Encoding; describe("cosmWasmCodec", () => { + describe("isValidAddress", () => { + it("accepts valid addresses", () => { + expect(cosmWasmCodec.isValidAddress("cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6")).toEqual(true); + expect(cosmWasmCodec.isValidAddress("cosmosvalcons10q82zkzzmaku5lazhsvxv7hsg4ntpuhdwadmss")).toEqual( + true, + ); + expect(cosmWasmCodec.isValidAddress("cosmosvaloper17mggn4znyeyg25wd7498qxl7r2jhgue8u4qjcq")).toEqual( + true, + ); + }); + + it("rejects invalid addresses", () => { + // Bad size + expect(cosmWasmCodec.isValidAddress("cosmos10q82zkzzmaku5lazhsvxv7hsg4ntpuhh8289f")).toEqual(false); + // Bad checksum + expect(cosmWasmCodec.isValidAddress("cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs7")).toEqual(false); + // Bad prefix + expect(cosmWasmCodec.isValidAddress("cosmot10q82zkzzmaku5lazhsvxv7hsg4ntpuhd8j5266")).toEqual(false); + }); + }); + it("properly generates bytes to sign", () => { const expected = { bytes: toUtf8( diff --git a/packages/bcp/src/cosmwasmcodec.ts b/packages/bcp/src/cosmwasmcodec.ts index 58644f2b..ff3a9879 100644 --- a/packages/bcp/src/cosmwasmcodec.ts +++ b/packages/bcp/src/cosmwasmcodec.ts @@ -1,5 +1,12 @@ /* eslint-disable @typescript-eslint/camelcase */ -import { makeSignBytes, marshalTx, types, unmarshalTx } from "@cosmwasm/sdk"; +import { + CosmosAddressBech32Prefix, + isValidAddress, + makeSignBytes, + marshalTx, + types, + unmarshalTx, +} from "@cosmwasm/sdk"; import { Address, ChainId, @@ -15,18 +22,18 @@ import { UnsignedTransaction, } from "@iov/bcp"; -import { CosmosBech32Prefix, isValidAddress, pubkeyToAddress } from "./address"; +import { pubkeyToAddress } from "./address"; import { Caip5 } from "./caip5"; import { parseTx } from "./decode"; import { buildSignedTx, buildUnsignedTx } from "./encode"; import { nonceToAccountNumber, nonceToSequence, TokenInfos } from "./types"; export class CosmWasmCodec implements TxCodec { - private readonly prefix: CosmosBech32Prefix; + private readonly addressPrefix: CosmosAddressBech32Prefix; private readonly tokens: TokenInfos; - public constructor(prefix: CosmosBech32Prefix, tokens: TokenInfos) { - this.prefix = prefix; + public constructor(prefix: CosmosAddressBech32Prefix, tokens: TokenInfos) { + this.addressPrefix = prefix; this.tokens = tokens; } @@ -76,7 +83,7 @@ export class CosmWasmCodec implements TxCodec { } public identityToAddress(identity: Identity): Address { - return pubkeyToAddress(identity.pubkey, this.prefix); + return pubkeyToAddress(identity.pubkey, this.addressPrefix); } public isValidAddress(address: string): boolean { @@ -84,7 +91,7 @@ export class CosmWasmCodec implements TxCodec { } } -const defaultPrefix = "cosmos" as CosmosBech32Prefix; +const defaultPrefix = "cosmos" as CosmosAddressBech32Prefix; const defaultTokens: TokenInfos = [ { diff --git a/packages/bcp/src/cosmwasmconnection.spec.ts b/packages/bcp/src/cosmwasmconnection.spec.ts index c59759a7..36e29773 100644 --- a/packages/bcp/src/cosmwasmconnection.spec.ts +++ b/packages/bcp/src/cosmwasmconnection.spec.ts @@ -1,3 +1,4 @@ +import { CosmosAddressBech32Prefix } from "@cosmwasm/sdk"; import { Address, Algorithm, @@ -14,7 +15,6 @@ import { Secp256k1 } from "@iov/crypto"; import { Encoding } from "@iov/encoding"; import { HdPaths, Secp256k1HdWallet, UserProfile } from "@iov/keycontrol"; -import { CosmosBech32Prefix } from "./address"; import { CosmWasmCodec, cosmWasmCodec } from "./cosmwasmcodec"; import { CosmWasmConnection, TokenConfiguration } from "./cosmwasmconnection"; import { signedTxJson, txId } from "./testdata.spec"; @@ -43,7 +43,7 @@ describe("CosmWasmConnection", () => { const faucetPath = HdPaths.cosmos(0); const defaultRecipient = "cosmos1t70qnpr0az8tf7py83m4ue5y89w58lkjmx0yq2" as Address; - const defaultPrefix = "cosmos" as CosmosBech32Prefix; + const defaultPrefix = "cosmos" as CosmosAddressBech32Prefix; // this is for wasmd blockchain const defaultTokens: TokenConfiguration = [ diff --git a/packages/bcp/src/cosmwasmconnection.ts b/packages/bcp/src/cosmwasmconnection.ts index fe4c9f2d..25790a6a 100644 --- a/packages/bcp/src/cosmwasmconnection.ts +++ b/packages/bcp/src/cosmwasmconnection.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/camelcase */ -import { RestClient, TxsResponse, types, unmarshalTx } from "@cosmwasm/sdk"; +import { CosmosAddressBech32Prefix, RestClient, TxsResponse, types, unmarshalTx } from "@cosmwasm/sdk"; import { Account, AccountQuery, @@ -34,7 +34,7 @@ import equal from "fast-deep-equal"; import { ReadonlyDate } from "readonly-date"; import { Stream } from "xstream"; -import { CosmosBech32Prefix, decodeCosmosPubkey, pubkeyToAddress } from "./address"; +import { decodeCosmosPubkey, pubkeyToAddress } from "./address"; import { Caip5 } from "./caip5"; import { decodeAmount, parseTxsResponse } from "./decode"; import { accountToNonce, TokenInfo } from "./types"; @@ -75,12 +75,12 @@ export class CosmWasmConnection implements BlockchainConnection { // we must know prefix and tokens a priori to understand the chain public static async establish( url: string, - prefix: CosmosBech32Prefix, + addressPrefix: CosmosAddressBech32Prefix, tokens: TokenConfiguration, ): Promise { const restClient = new RestClient(url); const chainData = await this.initialize(restClient); - return new CosmWasmConnection(restClient, chainData, prefix, tokens); + return new CosmWasmConnection(restClient, chainData, addressPrefix, tokens); } private static async initialize(restClient: RestClient): Promise { @@ -90,26 +90,22 @@ export class CosmWasmConnection implements BlockchainConnection { private readonly restClient: RestClient; private readonly chainData: ChainData; - private readonly _prefix: CosmosBech32Prefix; + private readonly addressPrefix: CosmosAddressBech32Prefix; private readonly tokenInfo: readonly TokenInfo[]; // these are derived from arguments (cached for use in multiple functions) private readonly primaryToken: Token; private readonly supportedTokens: readonly Token[]; - private get prefix(): CosmosBech32Prefix { - return this._prefix; - } - private constructor( restClient: RestClient, chainData: ChainData, - prefix: CosmosBech32Prefix, + addressPrefix: CosmosAddressBech32Prefix, tokens: TokenConfiguration, ) { this.restClient = restClient; this.chainData = chainData; - this._prefix = prefix; + this.addressPrefix = addressPrefix; this.tokenInfo = tokens; this.supportedTokens = tokens.map(info => ({ @@ -149,7 +145,7 @@ export class CosmWasmConnection implements BlockchainConnection { } public async getAccount(query: AccountQuery): Promise { - const address = isPubkeyQuery(query) ? pubkeyToAddress(query.pubkey, this.prefix) : query.address; + const address = isPubkeyQuery(query) ? pubkeyToAddress(query.pubkey, this.addressPrefix) : query.address; const { result } = await this.restClient.authAccounts(address); const account = result.value; if (!account.address) { @@ -172,7 +168,7 @@ export class CosmWasmConnection implements BlockchainConnection { } public async getNonce(query: AddressQuery | PubkeyQuery): Promise { - const address = isPubkeyQuery(query) ? pubkeyToAddress(query.pubkey, this.prefix) : query.address; + const address = isPubkeyQuery(query) ? pubkeyToAddress(query.pubkey, this.addressPrefix) : query.address; const { result } = await this.restClient.authAccounts(address); const account = result.value; return accountToNonce(account); diff --git a/packages/bcp/src/cosmwasmconnector.ts b/packages/bcp/src/cosmwasmconnector.ts index af0673a3..61aaf006 100644 --- a/packages/bcp/src/cosmwasmconnector.ts +++ b/packages/bcp/src/cosmwasmconnector.ts @@ -1,6 +1,6 @@ +import { CosmosAddressBech32Prefix } from "@cosmwasm/sdk"; import { ChainConnector, ChainId } from "@iov/bcp"; -import { CosmosBech32Prefix } from "./address"; import { CosmWasmCodec } from "./cosmwasmcodec"; import { CosmWasmConnection, TokenConfiguration } from "./cosmwasmconnection"; @@ -9,13 +9,13 @@ import { CosmWasmConnection, TokenConfiguration } from "./cosmwasmconnection"; */ export function createCosmWasmConnector( url: string, - prefix: CosmosBech32Prefix, + addressPrefix: CosmosAddressBech32Prefix, tokens: TokenConfiguration, expectedChainId?: ChainId, ): ChainConnector { - const codec = new CosmWasmCodec(prefix, tokens); + const codec = new CosmWasmCodec(addressPrefix, tokens); return { - establishConnection: async () => CosmWasmConnection.establish(url, prefix, tokens), + establishConnection: async () => CosmWasmConnection.establish(url, addressPrefix, tokens), codec: codec, expectedChainId: expectedChainId, }; diff --git a/packages/bcp/types/address.d.ts b/packages/bcp/types/address.d.ts index 158addbc..7a2c395c 100644 --- a/packages/bcp/types/address.d.ts +++ b/packages/bcp/types/address.d.ts @@ -1,10 +1,9 @@ -import { CosmosBech32Prefix, isValidAddress } from "@cosmwasm/sdk"; +import { CosmosAddressBech32Prefix } from "@cosmwasm/sdk"; import { Address, Algorithm, PubkeyBundle, PubkeyBytes } from "@iov/bcp"; -export { CosmosBech32Prefix, isValidAddress }; export declare function decodeCosmosPubkey( encodedPubkey: string, ): { readonly algo: Algorithm; readonly data: PubkeyBytes; }; -export declare function pubkeyToAddress(pubkey: PubkeyBundle, prefix: CosmosBech32Prefix): Address; +export declare function pubkeyToAddress(pubkey: PubkeyBundle, prefix: CosmosAddressBech32Prefix): Address; diff --git a/packages/bcp/types/cosmwasmcodec.d.ts b/packages/bcp/types/cosmwasmcodec.d.ts index 9ce8a6f0..76121658 100644 --- a/packages/bcp/types/cosmwasmcodec.d.ts +++ b/packages/bcp/types/cosmwasmcodec.d.ts @@ -1,3 +1,4 @@ +import { CosmosAddressBech32Prefix } from "@cosmwasm/sdk"; import { Address, ChainId, @@ -10,12 +11,11 @@ import { TxCodec, UnsignedTransaction, } from "@iov/bcp"; -import { CosmosBech32Prefix } from "./address"; import { TokenInfos } from "./types"; export declare class CosmWasmCodec implements TxCodec { - private readonly prefix; + private readonly addressPrefix; private readonly tokens; - constructor(prefix: CosmosBech32Prefix, tokens: TokenInfos); + constructor(prefix: CosmosAddressBech32Prefix, tokens: TokenInfos); bytesToSign(unsigned: UnsignedTransaction, nonce: Nonce): SigningJob; bytesToPost(signed: SignedTransaction): PostableBytes; identifier(_signed: SignedTransaction): TransactionId; diff --git a/packages/bcp/types/cosmwasmconnection.d.ts b/packages/bcp/types/cosmwasmconnection.d.ts index e5d1a7c6..413795dc 100644 --- a/packages/bcp/types/cosmwasmconnection.d.ts +++ b/packages/bcp/types/cosmwasmconnection.d.ts @@ -1,3 +1,4 @@ +import { CosmosAddressBech32Prefix } from "@cosmwasm/sdk"; import { Account, AccountQuery, @@ -20,7 +21,6 @@ import { UnsignedTransaction, } from "@iov/bcp"; import { Stream } from "xstream"; -import { CosmosBech32Prefix } from "./address"; import { TokenInfo } from "./types"; export declare type TokenConfiguration = ReadonlyArray< TokenInfo & { @@ -30,17 +30,16 @@ export declare type TokenConfiguration = ReadonlyArray< export declare class CosmWasmConnection implements BlockchainConnection { static establish( url: string, - prefix: CosmosBech32Prefix, + addressPrefix: CosmosAddressBech32Prefix, tokens: TokenConfiguration, ): Promise; private static initialize; private readonly restClient; private readonly chainData; - private readonly _prefix; + private readonly addressPrefix; private readonly tokenInfo; private readonly primaryToken; private readonly supportedTokens; - private get prefix(); private constructor(); disconnect(): void; chainId(): ChainId; diff --git a/packages/bcp/types/cosmwasmconnector.d.ts b/packages/bcp/types/cosmwasmconnector.d.ts index d9ed98cd..fbebceea 100644 --- a/packages/bcp/types/cosmwasmconnector.d.ts +++ b/packages/bcp/types/cosmwasmconnector.d.ts @@ -1,12 +1,12 @@ +import { CosmosAddressBech32Prefix } from "@cosmwasm/sdk"; import { ChainConnector, ChainId } from "@iov/bcp"; -import { CosmosBech32Prefix } from "./address"; import { CosmWasmConnection, TokenConfiguration } from "./cosmwasmconnection"; /** * A helper to connect to a cosmos-based chain at a given url */ export declare function createCosmWasmConnector( url: string, - prefix: CosmosBech32Prefix, + addressPrefix: CosmosAddressBech32Prefix, tokens: TokenConfiguration, expectedChainId?: ChainId, ): ChainConnector; diff --git a/packages/sdk/src/address.ts b/packages/sdk/src/address.ts index 85df61c5..cb6b5eb7 100644 --- a/packages/sdk/src/address.ts +++ b/packages/sdk/src/address.ts @@ -8,7 +8,6 @@ const { fromBase64 } = Encoding; // TODO: make this much more configurable export type CosmosAddressBech32Prefix = "cosmos" | "cosmosvalcons" | "cosmosvaloper"; export type CosmosPubkeyBech32Prefix = "cosmospub" | "cosmosvalconspub" | "cosmosvaloperpub"; -export type CosmosBech32Prefix = CosmosAddressBech32Prefix | CosmosPubkeyBech32Prefix; function isCosmosAddressBech32Prefix(prefix: string): prefix is CosmosAddressBech32Prefix { return ["cosmos", "cosmosvalcons", "cosmosvaloper"].includes(prefix); diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index 36d24cbf..b678ce20 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -2,7 +2,7 @@ import * as logs from "./logs"; import * as types from "./types"; export { logs, types }; -export { CosmosBech32Prefix, encodeAddress, isValidAddress } from "./address"; +export { CosmosAddressBech32Prefix, encodeAddress, isValidAddress } from "./address"; export { unmarshalTx } from "./decoding"; export { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding"; export { RestClient, TxsResponse } from "./restclient"; diff --git a/packages/sdk/types/address.d.ts b/packages/sdk/types/address.d.ts index 3390fc29..2d282875 100644 --- a/packages/sdk/types/address.d.ts +++ b/packages/sdk/types/address.d.ts @@ -1,6 +1,5 @@ import { PubKey } from "./types"; export declare type CosmosAddressBech32Prefix = "cosmos" | "cosmosvalcons" | "cosmosvaloper"; export declare type CosmosPubkeyBech32Prefix = "cosmospub" | "cosmosvalconspub" | "cosmosvaloperpub"; -export declare type CosmosBech32Prefix = CosmosAddressBech32Prefix | CosmosPubkeyBech32Prefix; export declare function isValidAddress(address: string): boolean; export declare function encodeAddress(pubkey: PubKey, prefix: string): string; diff --git a/packages/sdk/types/index.d.ts b/packages/sdk/types/index.d.ts index 3c8bdaab..e2733189 100644 --- a/packages/sdk/types/index.d.ts +++ b/packages/sdk/types/index.d.ts @@ -1,7 +1,7 @@ import * as logs from "./logs"; import * as types from "./types"; export { logs, types }; -export { CosmosBech32Prefix, encodeAddress, isValidAddress } from "./address"; +export { CosmosAddressBech32Prefix, encodeAddress, isValidAddress } from "./address"; export { unmarshalTx } from "./decoding"; export { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding"; export { RestClient, TxsResponse } from "./restclient";