Move decodeBech32Pubkey to pubkey.ts
This commit is contained in:
parent
ff78c296d4
commit
b2fcb0b105
@ -1,21 +1,10 @@
|
||||
import { Encoding } from "@iov/encoding";
|
||||
|
||||
import { decodeBech32Pubkey, encodeAddress, isValidAddress } from "./address";
|
||||
import { encodeAddress, isValidAddress } from "./address";
|
||||
|
||||
const { toBase64, fromHex } = Encoding;
|
||||
|
||||
describe("address", () => {
|
||||
describe("decodeBech32Pubkey", () => {
|
||||
it("works", () => {
|
||||
expect(
|
||||
decodeBech32Pubkey("cosmospub1addwnpepqd8sgxq7aw348ydctp3n5ajufgxp395hksxjzc6565yfp56scupfqhlgyg5"),
|
||||
).toEqual({
|
||||
type: "tendermint/PubKeySecp256k1",
|
||||
value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("isValidAddress", () => {
|
||||
it("accepts valid addresses", () => {
|
||||
expect(isValidAddress("cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6")).toEqual(true);
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import { Ripemd160, Sha256 } from "@iov/crypto";
|
||||
import { Bech32, Encoding } from "@iov/encoding";
|
||||
import equal from "fast-deep-equal";
|
||||
|
||||
import { Bech32PubKey, PubKey, pubkeyType } from "./types";
|
||||
import { PubKey, pubkeyType } from "./types";
|
||||
|
||||
const { fromBase64, toBase64 } = Encoding;
|
||||
const { fromBase64 } = Encoding;
|
||||
|
||||
// TODO: make this much more configurable
|
||||
export type CosmosAddressBech32Prefix = "cosmos" | "cosmosvalcons" | "cosmosvaloper";
|
||||
@ -15,55 +14,6 @@ function isCosmosAddressBech32Prefix(prefix: string): prefix is CosmosAddressBec
|
||||
return ["cosmos", "cosmosvalcons", "cosmosvaloper"].includes(prefix);
|
||||
}
|
||||
|
||||
function isCosmosPubkeyBech32Prefix(prefix: string): prefix is CosmosPubkeyBech32Prefix {
|
||||
return ["cosmospub", "cosmosvalconspub", "cosmosvaloperpub"].includes(prefix);
|
||||
}
|
||||
|
||||
// As discussed in https://github.com/binance-chain/javascript-sdk/issues/163
|
||||
// Prefixes listed here: https://github.com/tendermint/tendermint/blob/d419fffe18531317c28c29a292ad7d253f6cafdf/docs/spec/blockchain/encoding.md#public-key-cryptography
|
||||
// Last bytes is varint-encoded length prefix
|
||||
const pubkeyAminoPrefixSecp256k1 = Encoding.fromHex("eb5ae98721");
|
||||
const pubkeyAminoPrefixEd25519 = Encoding.fromHex("1624de6420");
|
||||
const pubkeyAminoPrefixSr25519 = Encoding.fromHex("0dfb1005");
|
||||
const pubkeyAminoPrefixLength = pubkeyAminoPrefixSecp256k1.length;
|
||||
|
||||
export function decodeBech32Pubkey(bech: Bech32PubKey): PubKey {
|
||||
const { prefix, data } = Bech32.decode(bech);
|
||||
if (!isCosmosPubkeyBech32Prefix(prefix)) {
|
||||
throw new Error(`Invalid bech32 prefix. Must be one of cosmos, cosmosvalcons, or cosmosvaloper.`);
|
||||
}
|
||||
|
||||
const aminoPrefix = data.slice(0, pubkeyAminoPrefixLength);
|
||||
const rest = data.slice(pubkeyAminoPrefixLength);
|
||||
if (equal(aminoPrefix, pubkeyAminoPrefixSecp256k1)) {
|
||||
if (rest.length !== 33) {
|
||||
throw new Error("Invalid rest data length. Expected 33 bytes (compressed secp256k1 pubkey).");
|
||||
}
|
||||
return {
|
||||
type: pubkeyType.secp256k1,
|
||||
value: toBase64(rest),
|
||||
};
|
||||
} else if (equal(aminoPrefix, pubkeyAminoPrefixEd25519)) {
|
||||
if (rest.length !== 32) {
|
||||
throw new Error("Invalid rest data length. Expected 32 bytes (Ed25519 pubkey).");
|
||||
}
|
||||
return {
|
||||
type: pubkeyType.ed25519,
|
||||
value: toBase64(rest),
|
||||
};
|
||||
} else if (equal(aminoPrefix, pubkeyAminoPrefixSr25519)) {
|
||||
if (rest.length !== 32) {
|
||||
throw new Error("Invalid rest data length. Expected 32 bytes (Sr25519 pubkey).");
|
||||
}
|
||||
return {
|
||||
type: pubkeyType.sr25519,
|
||||
value: toBase64(rest),
|
||||
};
|
||||
} else {
|
||||
throw new Error("Unsupported Pubkey type. Amino prefix: " + Encoding.toHex(aminoPrefix));
|
||||
}
|
||||
}
|
||||
|
||||
export function isValidAddress(address: string): boolean {
|
||||
try {
|
||||
const { prefix, data } = Bech32.decode(address);
|
||||
|
||||
@ -2,9 +2,9 @@ import * as logs from "./logs";
|
||||
import * as types from "./types";
|
||||
export { logs, types };
|
||||
|
||||
export { CosmosBech32Prefix, decodeBech32Pubkey, encodeAddress, isValidAddress } from "./address";
|
||||
export { CosmosBech32Prefix, encodeAddress, isValidAddress } from "./address";
|
||||
export { unmarshalTx } from "./decoding";
|
||||
export { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding";
|
||||
export { RestClient, TxsResponse } from "./restclient";
|
||||
export { makeCosmoshubPath, Pen, PrehashType, Secp256k1Pen } from "./pen";
|
||||
export { encodeSecp256k1Pubkey } from "./pubkey";
|
||||
export { decodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey";
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Encoding } from "@iov/encoding";
|
||||
|
||||
import { encodeSecp256k1Pubkey } from "./pubkey";
|
||||
import { decodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey";
|
||||
|
||||
const { fromBase64 } = Encoding;
|
||||
|
||||
@ -24,4 +24,15 @@ describe("pubkey", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("decodeBech32Pubkey", () => {
|
||||
it("works", () => {
|
||||
expect(
|
||||
decodeBech32Pubkey("cosmospub1addwnpepqd8sgxq7aw348ydctp3n5ajufgxp395hksxjzc6565yfp56scupfqhlgyg5"),
|
||||
).toEqual({
|
||||
type: "tendermint/PubKeySecp256k1",
|
||||
value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ",
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import { Secp256k1 } from "@iov/crypto";
|
||||
import { Encoding } from "@iov/encoding";
|
||||
import { Bech32, Encoding } from "@iov/encoding";
|
||||
import equal from "fast-deep-equal";
|
||||
|
||||
import { PubKey, pubkeyType } from "./types";
|
||||
import { CosmosPubkeyBech32Prefix } from "./address";
|
||||
import { Bech32PubKey, PubKey, pubkeyType } from "./types";
|
||||
|
||||
export function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey {
|
||||
return {
|
||||
@ -9,3 +11,52 @@ export function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey {
|
||||
value: Encoding.toBase64(Secp256k1.compressPubkey(pubkey)),
|
||||
};
|
||||
}
|
||||
|
||||
function isCosmosPubkeyBech32Prefix(prefix: string): prefix is CosmosPubkeyBech32Prefix {
|
||||
return ["cosmospub", "cosmosvalconspub", "cosmosvaloperpub"].includes(prefix);
|
||||
}
|
||||
|
||||
// As discussed in https://github.com/binance-chain/javascript-sdk/issues/163
|
||||
// Prefixes listed here: https://github.com/tendermint/tendermint/blob/d419fffe18531317c28c29a292ad7d253f6cafdf/docs/spec/blockchain/encoding.md#public-key-cryptography
|
||||
// Last bytes is varint-encoded length prefix
|
||||
const pubkeyAminoPrefixSecp256k1 = Encoding.fromHex("eb5ae98721");
|
||||
const pubkeyAminoPrefixEd25519 = Encoding.fromHex("1624de6420");
|
||||
const pubkeyAminoPrefixSr25519 = Encoding.fromHex("0dfb1005");
|
||||
const pubkeyAminoPrefixLength = pubkeyAminoPrefixSecp256k1.length;
|
||||
|
||||
export function decodeBech32Pubkey(bech: Bech32PubKey): PubKey {
|
||||
const { prefix, data } = Bech32.decode(bech);
|
||||
if (!isCosmosPubkeyBech32Prefix(prefix)) {
|
||||
throw new Error(`Invalid bech32 prefix. Must be one of cosmos, cosmosvalcons, or cosmosvaloper.`);
|
||||
}
|
||||
|
||||
const aminoPrefix = data.slice(0, pubkeyAminoPrefixLength);
|
||||
const rest = data.slice(pubkeyAminoPrefixLength);
|
||||
if (equal(aminoPrefix, pubkeyAminoPrefixSecp256k1)) {
|
||||
if (rest.length !== 33) {
|
||||
throw new Error("Invalid rest data length. Expected 33 bytes (compressed secp256k1 pubkey).");
|
||||
}
|
||||
return {
|
||||
type: pubkeyType.secp256k1,
|
||||
value: Encoding.toBase64(rest),
|
||||
};
|
||||
} else if (equal(aminoPrefix, pubkeyAminoPrefixEd25519)) {
|
||||
if (rest.length !== 32) {
|
||||
throw new Error("Invalid rest data length. Expected 32 bytes (Ed25519 pubkey).");
|
||||
}
|
||||
return {
|
||||
type: pubkeyType.ed25519,
|
||||
value: Encoding.toBase64(rest),
|
||||
};
|
||||
} else if (equal(aminoPrefix, pubkeyAminoPrefixSr25519)) {
|
||||
if (rest.length !== 32) {
|
||||
throw new Error("Invalid rest data length. Expected 32 bytes (Sr25519 pubkey).");
|
||||
}
|
||||
return {
|
||||
type: pubkeyType.sr25519,
|
||||
value: Encoding.toBase64(rest),
|
||||
};
|
||||
} else {
|
||||
throw new Error("Unsupported Pubkey type. Amino prefix: " + Encoding.toHex(aminoPrefix));
|
||||
}
|
||||
}
|
||||
|
||||
3
packages/sdk/types/address.d.ts
vendored
3
packages/sdk/types/address.d.ts
vendored
@ -1,7 +1,6 @@
|
||||
import { Bech32PubKey, PubKey } from "./types";
|
||||
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 decodeBech32Pubkey(bech: Bech32PubKey): PubKey;
|
||||
export declare function isValidAddress(address: string): boolean;
|
||||
export declare function encodeAddress(pubkey: PubKey, prefix: string): string;
|
||||
|
||||
4
packages/sdk/types/index.d.ts
vendored
4
packages/sdk/types/index.d.ts
vendored
@ -1,9 +1,9 @@
|
||||
import * as logs from "./logs";
|
||||
import * as types from "./types";
|
||||
export { logs, types };
|
||||
export { CosmosBech32Prefix, decodeBech32Pubkey, encodeAddress, isValidAddress } from "./address";
|
||||
export { CosmosBech32Prefix, encodeAddress, isValidAddress } from "./address";
|
||||
export { unmarshalTx } from "./decoding";
|
||||
export { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding";
|
||||
export { RestClient, TxsResponse } from "./restclient";
|
||||
export { makeCosmoshubPath, Pen, PrehashType, Secp256k1Pen } from "./pen";
|
||||
export { encodeSecp256k1Pubkey } from "./pubkey";
|
||||
export { decodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey";
|
||||
|
||||
3
packages/sdk/types/pubkey.d.ts
vendored
3
packages/sdk/types/pubkey.d.ts
vendored
@ -1,2 +1,3 @@
|
||||
import { PubKey } from "./types";
|
||||
import { Bech32PubKey, PubKey } from "./types";
|
||||
export declare function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey;
|
||||
export declare function decodeBech32Pubkey(bech: Bech32PubKey): PubKey;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user