diff --git a/CHANGELOG.md b/CHANGELOG.md index ff76430efd..f35deb4eab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - @cosmjs/cli: Import `encodeBech32Pubkey` and `decodeBech32Pubkey` by default. - @cosmjs/launchpad: Add ed25519 support to `encodeBech32Pubkey`. +- @cosmjs/launchpad: Add `encodeAminoPubkey` and `decodeAminoPubkey`. ## 0.22.0 (2020-08-03) diff --git a/packages/launchpad/src/index.ts b/packages/launchpad/src/index.ts index 0149c07fd4..6d6e238886 100644 --- a/packages/launchpad/src/index.ts +++ b/packages/launchpad/src/index.ts @@ -84,7 +84,13 @@ export { uint64ToString, } from "./lcdapi"; export { isMsgDelegate, isMsgSend, Msg, MsgDelegate, MsgSend } from "./msgs"; -export { decodeBech32Pubkey, encodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey"; +export { + decodeAminoPubkey, + decodeBech32Pubkey, + encodeAminoPubkey, + encodeBech32Pubkey, + encodeSecp256k1Pubkey, +} from "./pubkey"; export { findSequenceForSignedTx } from "./sequence"; export { encodeSecp256k1Signature, decodeSignature } from "./signature"; export { FeeTable, SigningCosmosClient } from "./signingcosmosclient"; diff --git a/packages/launchpad/src/pubkey.spec.ts b/packages/launchpad/src/pubkey.spec.ts index f76cbe0f8e..9576239b88 100644 --- a/packages/launchpad/src/pubkey.spec.ts +++ b/packages/launchpad/src/pubkey.spec.ts @@ -1,6 +1,12 @@ -import { fromBase64 } from "@cosmjs/encoding"; +import { Bech32, fromBase64 } from "@cosmjs/encoding"; -import { decodeBech32Pubkey, encodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey"; +import { + decodeAminoPubkey, + decodeBech32Pubkey, + encodeAminoPubkey, + encodeBech32Pubkey, + encodeSecp256k1Pubkey, +} from "./pubkey"; import { PubKey } from "./types"; describe("pubkey", () => { @@ -21,6 +27,30 @@ describe("pubkey", () => { }); }); + describe("decodeAminoPubkey", () => { + it("works for secp256k1", () => { + const amino = Bech32.decode( + "cosmospub1addwnpepqd8sgxq7aw348ydctp3n5ajufgxp395hksxjzc6565yfp56scupfqhlgyg5", + ).data; + expect(decodeAminoPubkey(amino)).toEqual({ + type: "tendermint/PubKeySecp256k1", + value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ", + }); + }); + + it("works for ed25519", () => { + // Encoded from `corald tendermint show-validator` + // Decoded from http://localhost:26657/validators + const amino = Bech32.decode( + "coralvalconspub1zcjduepqvxg72ccnl9r65fv0wn3amlk4sfzqfe2k36l073kjx2qyaf6sk23qw7j8wq", + ).data; + expect(decodeAminoPubkey(amino)).toEqual({ + type: "tendermint/PubKeyEd25519", + value: "YZHlYxP5R6olj3Tj3f7VgkQE5VaOvv9G0jKATqdQsqI=", + }); + }); + }); + describe("decodeBech32Pubkey", () => { it("works", () => { expect( @@ -53,6 +83,32 @@ describe("pubkey", () => { }); }); + describe("encodeAminoPubkey", () => { + it("works for secp256k1", () => { + const pubkey: PubKey = { + type: "tendermint/PubKeySecp256k1", + value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ", + }; + const expected = Bech32.decode( + "cosmospub1addwnpepqd8sgxq7aw348ydctp3n5ajufgxp395hksxjzc6565yfp56scupfqhlgyg5", + ).data; + expect(encodeAminoPubkey(pubkey)).toEqual(expected); + }); + + it("works for ed25519", () => { + // Decoded from http://localhost:26657/validators + // Encoded from `corald tendermint show-validator` + const pubkey: PubKey = { + type: "tendermint/PubKeyEd25519", + value: "YZHlYxP5R6olj3Tj3f7VgkQE5VaOvv9G0jKATqdQsqI=", + }; + const expected = Bech32.decode( + "coralvalconspub1zcjduepqvxg72ccnl9r65fv0wn3amlk4sfzqfe2k36l073kjx2qyaf6sk23qw7j8wq", + ).data; + expect(encodeAminoPubkey(pubkey)).toEqual(expected); + }); + }); + describe("encodeBech32Pubkey", () => { it("works for secp256k1", () => { const pubkey: PubKey = { diff --git a/packages/launchpad/src/pubkey.ts b/packages/launchpad/src/pubkey.ts index abadc6377c..e68cf3f818 100644 --- a/packages/launchpad/src/pubkey.ts +++ b/packages/launchpad/src/pubkey.ts @@ -22,14 +22,9 @@ const pubkeyAminoPrefixSr25519 = fromHex("0dfb1005"); const pubkeyAminoPrefixLength = pubkeyAminoPrefixSecp256k1.length; /** - * Decodes a bech32 pubkey to Amino binary, which is then decoded to a type/value object. - * The bech32 prefix is ignored and discareded. - * - * @param bechEncoded the bech32 encoded pubkey + * Decodes a pubkey in the Amino binary format to a type/value object. */ -export function decodeBech32Pubkey(bechEncoded: string): PubKey { - const { data } = Bech32.decode(bechEncoded); - +export function decodeAminoPubkey(data: Uint8Array): PubKey { const aminoPrefix = data.slice(0, pubkeyAminoPrefixLength); const rest = data.slice(pubkeyAminoPrefixLength); if (equal(aminoPrefix, pubkeyAminoPrefixSecp256k1)) { @@ -62,12 +57,20 @@ export function decodeBech32Pubkey(bechEncoded: string): PubKey { } /** - * Encodes a public key to binary Amino and then to bech32. + * Decodes a bech32 pubkey to Amino binary, which is then decoded to a type/value object. + * The bech32 prefix is ignored and discareded. * - * @param pubkey the public key to encode - * @param prefix the bech32 prefix (human readable part) + * @param bechEncoded the bech32 encoded pubkey */ -export function encodeBech32Pubkey(pubkey: PubKey, prefix: string): string { +export function decodeBech32Pubkey(bechEncoded: string): PubKey { + const { data } = Bech32.decode(bechEncoded); + return decodeAminoPubkey(data); +} + +/** + * Encodes a public key to binary Amino. + */ +export function encodeAminoPubkey(pubkey: PubKey): Uint8Array { let aminoPrefix: Uint8Array; switch (pubkey.type) { // Note: please don't add cases here without writing additional unit tests @@ -80,7 +83,15 @@ export function encodeBech32Pubkey(pubkey: PubKey, prefix: string): string { default: throw new Error("Unsupported pubkey type"); } - - const data = new Uint8Array([...aminoPrefix, ...fromBase64(pubkey.value)]); - return Bech32.encode(prefix, data); + return new Uint8Array([...aminoPrefix, ...fromBase64(pubkey.value)]); +} + +/** + * Encodes a public key to binary Amino and then to bech32. + * + * @param pubkey the public key to encode + * @param prefix the bech32 prefix (human readable part) + */ +export function encodeBech32Pubkey(pubkey: PubKey, prefix: string): string { + return Bech32.encode(prefix, encodeAminoPubkey(pubkey)); } diff --git a/packages/launchpad/types/index.d.ts b/packages/launchpad/types/index.d.ts index d8dfe32e4a..03c9a87d44 100644 --- a/packages/launchpad/types/index.d.ts +++ b/packages/launchpad/types/index.d.ts @@ -82,7 +82,13 @@ export { uint64ToString, } from "./lcdapi"; export { isMsgDelegate, isMsgSend, Msg, MsgDelegate, MsgSend } from "./msgs"; -export { decodeBech32Pubkey, encodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey"; +export { + decodeAminoPubkey, + decodeBech32Pubkey, + encodeAminoPubkey, + encodeBech32Pubkey, + encodeSecp256k1Pubkey, +} from "./pubkey"; export { findSequenceForSignedTx } from "./sequence"; export { encodeSecp256k1Signature, decodeSignature } from "./signature"; export { FeeTable, SigningCosmosClient } from "./signingcosmosclient"; diff --git a/packages/launchpad/types/pubkey.d.ts b/packages/launchpad/types/pubkey.d.ts index 04ae9ebf8a..e39865126b 100644 --- a/packages/launchpad/types/pubkey.d.ts +++ b/packages/launchpad/types/pubkey.d.ts @@ -1,5 +1,9 @@ import { PubKey } from "./types"; export declare function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey; +/** + * Decodes a pubkey in the Amino binary format to a type/value object. + */ +export declare function decodeAminoPubkey(data: Uint8Array): PubKey; /** * Decodes a bech32 pubkey to Amino binary, which is then decoded to a type/value object. * The bech32 prefix is ignored and discareded. @@ -7,6 +11,10 @@ export declare function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey; * @param bechEncoded the bech32 encoded pubkey */ export declare function decodeBech32Pubkey(bechEncoded: string): PubKey; +/** + * Encodes a public key to binary Amino. + */ +export declare function encodeAminoPubkey(pubkey: PubKey): Uint8Array; /** * Encodes a public key to binary Amino and then to bech32. *