Pull out pubkey functionality into @cosmjs/amino
This commit is contained in:
parent
9a87826142
commit
f8cf23766c
@ -22,6 +22,8 @@ and this project adheres to
|
||||
connection tx, as well as Tendermint.
|
||||
- @cosmjs/stargate: Add support for IBC message types in
|
||||
`SigningStargateClient`.
|
||||
- @cosmjs/amino: New package created that contains the shared amino signing
|
||||
functionality for @cosmjs/launchpad and @cosmjs/stargate.
|
||||
|
||||
### Changed
|
||||
|
||||
|
||||
8
packages/amino/.eslintignore
Normal file
8
packages/amino/.eslintignore
Normal file
@ -0,0 +1,8 @@
|
||||
node_modules/
|
||||
|
||||
build/
|
||||
custom_types/
|
||||
dist/
|
||||
docs/
|
||||
generated/
|
||||
types/
|
||||
3
packages/amino/.gitignore
vendored
Normal file
3
packages/amino/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
build/
|
||||
dist/
|
||||
docs/
|
||||
1
packages/amino/.nycrc.yml
Symbolic link
1
packages/amino/.nycrc.yml
Symbolic link
@ -0,0 +1 @@
|
||||
../../.nycrc.yml
|
||||
12
packages/amino/README.md
Normal file
12
packages/amino/README.md
Normal file
@ -0,0 +1,12 @@
|
||||
# @cosmjs/amino
|
||||
|
||||
[](https://www.npmjs.com/package/@cosmjs/amino)
|
||||
|
||||
Helpers for Amino based signing which are shared between @cosmjs/launchpad and
|
||||
@cosmjs/stargate.
|
||||
|
||||
## License
|
||||
|
||||
This package is part of the cosmjs repository, licensed under the Apache License
|
||||
2.0 (see [NOTICE](https://github.com/cosmos/cosmjs/blob/main/NOTICE) and
|
||||
[LICENSE](https://github.com/cosmos/cosmjs/blob/main/LICENSE)).
|
||||
39
packages/amino/jasmine-testrunner.js
Executable file
39
packages/amino/jasmine-testrunner.js
Executable file
@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env node
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
|
||||
if (process.env.SES_ENABLED) {
|
||||
require("ses/lockdown");
|
||||
// eslint-disable-next-line no-undef
|
||||
lockdown();
|
||||
}
|
||||
|
||||
require("source-map-support").install();
|
||||
const defaultSpecReporterConfig = require("../../jasmine-spec-reporter.config.json");
|
||||
|
||||
// setup Jasmine
|
||||
const Jasmine = require("jasmine");
|
||||
const jasmine = new Jasmine();
|
||||
jasmine.loadConfig({
|
||||
spec_dir: "build",
|
||||
spec_files: ["**/*.spec.js"],
|
||||
helpers: [],
|
||||
random: false,
|
||||
seed: null,
|
||||
stopSpecOnExpectationFailure: false,
|
||||
});
|
||||
jasmine.jasmine.DEFAULT_TIMEOUT_INTERVAL = 15 * 1000;
|
||||
|
||||
// setup reporter
|
||||
const { SpecReporter } = require("jasmine-spec-reporter");
|
||||
const reporter = new SpecReporter({
|
||||
...defaultSpecReporterConfig,
|
||||
spec: {
|
||||
...defaultSpecReporterConfig.spec,
|
||||
displaySuccessful: !process.argv.includes("--quiet"),
|
||||
},
|
||||
});
|
||||
|
||||
// initialize and execute
|
||||
jasmine.env.clearReporters();
|
||||
jasmine.addReporter(reporter);
|
||||
jasmine.execute();
|
||||
47
packages/amino/karma.conf.js
Normal file
47
packages/amino/karma.conf.js
Normal file
@ -0,0 +1,47 @@
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
// base path that will be used to resolve all patterns (eg. files, exclude)
|
||||
basePath: ".",
|
||||
|
||||
// frameworks to use
|
||||
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
|
||||
frameworks: ["jasmine"],
|
||||
|
||||
// list of files / patterns to load in the browser
|
||||
files: ["dist/web/tests.js"],
|
||||
|
||||
client: {
|
||||
jasmine: {
|
||||
random: false,
|
||||
timeoutInterval: 15000,
|
||||
},
|
||||
},
|
||||
|
||||
// test results reporter to use
|
||||
// possible values: 'dots', 'progress'
|
||||
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
|
||||
reporters: ["progress", "kjhtml"],
|
||||
|
||||
// web server port
|
||||
port: 9876,
|
||||
|
||||
// enable / disable colors in the output (reporters and logs)
|
||||
colors: true,
|
||||
|
||||
// level of logging
|
||||
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
||||
logLevel: config.LOG_INFO,
|
||||
|
||||
// enable / disable watching file and executing tests whenever any file changes
|
||||
autoWatch: false,
|
||||
|
||||
// start these browsers
|
||||
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
|
||||
browsers: ["Firefox"],
|
||||
|
||||
browserNoActivityTimeout: 90000,
|
||||
|
||||
// Keep brower open for debugging. This is overridden by yarn scripts
|
||||
singleRun: false,
|
||||
});
|
||||
};
|
||||
1
packages/amino/nonces/README.txt
Normal file
1
packages/amino/nonces/README.txt
Normal file
@ -0,0 +1 @@
|
||||
Directory used to trigger lerna package updates for all packages
|
||||
48
packages/amino/package.json
Normal file
48
packages/amino/package.json
Normal file
@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "@cosmjs/amino",
|
||||
"version": "0.25.0-alpha.0",
|
||||
"description": "Helpers for Amino based signing which are shared between @cosmjs/launchpad and @cosmjs/stargate.",
|
||||
"contributors": [
|
||||
"Simon Warta <webmaster128@users.noreply.github.com>"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"main": "build/index.js",
|
||||
"types": "build/index.d.ts",
|
||||
"files": [
|
||||
"build/",
|
||||
"*.md",
|
||||
"!*.spec.*",
|
||||
"!**/testdata/"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/cosmos/cosmjs/tree/main/packages/amino"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"scripts": {
|
||||
"docs": "typedoc --options typedoc.js",
|
||||
"lint": "eslint --max-warnings 0 \"**/*.{js,ts}\"",
|
||||
"lint-fix": "eslint --max-warnings 0 \"**/*.{js,ts}\" --fix",
|
||||
"format": "prettier --write --loglevel warn \"./src/**/*.ts\"",
|
||||
"format-text": "prettier --write --prose-wrap always --print-width 80 \"./*.md\"",
|
||||
"test-node": "node jasmine-testrunner.js",
|
||||
"test-edge": "yarn pack-web && karma start --single-run --browsers Edge",
|
||||
"test-firefox": "yarn pack-web && karma start --single-run --browsers Firefox",
|
||||
"test-chrome": "yarn pack-web && karma start --single-run --browsers ChromeHeadless",
|
||||
"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",
|
||||
"prebuild": "shx rm -rf ./build",
|
||||
"build": "tsc",
|
||||
"build-or-skip": "[ -n \"$SKIP_BUILD\" ] || yarn build",
|
||||
"pack-web": "yarn build-or-skip && webpack --mode development --config webpack.web.config.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cosmjs/encoding": "^0.25.0-alpha.0",
|
||||
"@cosmjs/utils": "^0.25.0-alpha.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
}
|
||||
}
|
||||
135
packages/amino/src/encoding.spec.ts
Normal file
135
packages/amino/src/encoding.spec.ts
Normal file
@ -0,0 +1,135 @@
|
||||
import { Bech32, fromBase64 } from "@cosmjs/encoding";
|
||||
|
||||
import {
|
||||
decodeAminoPubkey,
|
||||
decodeBech32Pubkey,
|
||||
encodeAminoPubkey,
|
||||
encodeBech32Pubkey,
|
||||
encodeSecp256k1Pubkey,
|
||||
} from "./encoding";
|
||||
import { PubKey } from "./pubkeys";
|
||||
|
||||
describe("pubkey", () => {
|
||||
describe("encodeSecp256k1Pubkey", () => {
|
||||
it("encodes a compresed pubkey", () => {
|
||||
const pubkey = fromBase64("AtQaCqFnshaZQp6rIkvAPyzThvCvXSDO+9AzbxVErqJP");
|
||||
expect(encodeSecp256k1Pubkey(pubkey)).toEqual({
|
||||
type: "tendermint/PubKeySecp256k1",
|
||||
value: "AtQaCqFnshaZQp6rIkvAPyzThvCvXSDO+9AzbxVErqJP",
|
||||
});
|
||||
});
|
||||
|
||||
it("throws for uncompressed public keys", () => {
|
||||
const pubkey = fromBase64(
|
||||
"BE8EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQE7WHpoHoNswYeoFkuYpYSKK4mzFzMV/dB0DVAy4lnNU=",
|
||||
);
|
||||
expect(() => encodeSecp256k1Pubkey(pubkey)).toThrowError(/public key must be compressed secp256k1/i);
|
||||
});
|
||||
});
|
||||
|
||||
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(
|
||||
decodeBech32Pubkey("cosmospub1addwnpepqd8sgxq7aw348ydctp3n5ajufgxp395hksxjzc6565yfp56scupfqhlgyg5"),
|
||||
).toEqual({
|
||||
type: "tendermint/PubKeySecp256k1",
|
||||
value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ",
|
||||
});
|
||||
});
|
||||
|
||||
it("works for enigma pubkey", () => {
|
||||
expect(
|
||||
decodeBech32Pubkey("enigmapub1addwnpepqw5k9p439nw0zpg2aundx4umwx4nw233z5prpjqjv5anl5grmnchzp2xwvv"),
|
||||
).toEqual({
|
||||
type: "tendermint/PubKeySecp256k1",
|
||||
value: "A6lihrEs3PEFCu8m01ebcas3KjEVAjDIEmU7P9ED3PFx",
|
||||
});
|
||||
});
|
||||
|
||||
it("works for ed25519", () => {
|
||||
// Encoded from `corald tendermint show-validator`
|
||||
// Decoded from http://localhost:26657/validators
|
||||
const decoded = decodeBech32Pubkey(
|
||||
"coralvalconspub1zcjduepqvxg72ccnl9r65fv0wn3amlk4sfzqfe2k36l073kjx2qyaf6sk23qw7j8wq",
|
||||
);
|
||||
expect(decoded).toEqual({
|
||||
type: "tendermint/PubKeyEd25519",
|
||||
value: "YZHlYxP5R6olj3Tj3f7VgkQE5VaOvv9G0jKATqdQsqI=",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
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 = {
|
||||
type: "tendermint/PubKeySecp256k1",
|
||||
value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ",
|
||||
};
|
||||
expect(encodeBech32Pubkey(pubkey, "cosmospub")).toEqual(
|
||||
"cosmospub1addwnpepqd8sgxq7aw348ydctp3n5ajufgxp395hksxjzc6565yfp56scupfqhlgyg5",
|
||||
);
|
||||
});
|
||||
|
||||
it("works for ed25519", () => {
|
||||
// Decoded from http://localhost:26657/validators
|
||||
// Encoded from `corald tendermint show-validator`
|
||||
const pubkey: PubKey = {
|
||||
type: "tendermint/PubKeyEd25519",
|
||||
value: "YZHlYxP5R6olj3Tj3f7VgkQE5VaOvv9G0jKATqdQsqI=",
|
||||
};
|
||||
expect(encodeBech32Pubkey(pubkey, "coralvalconspub")).toEqual(
|
||||
"coralvalconspub1zcjduepqvxg72ccnl9r65fv0wn3amlk4sfzqfe2k36l073kjx2qyaf6sk23qw7j8wq",
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
97
packages/amino/src/encoding.ts
Normal file
97
packages/amino/src/encoding.ts
Normal file
@ -0,0 +1,97 @@
|
||||
import { Bech32, fromBase64, fromHex, toBase64, toHex } from "@cosmjs/encoding";
|
||||
import { arrayContentEquals } from "@cosmjs/utils";
|
||||
|
||||
import { PubKey, pubkeyType } from "./pubkeys";
|
||||
|
||||
export function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey {
|
||||
if (pubkey.length !== 33 || (pubkey[0] !== 0x02 && pubkey[0] !== 0x03)) {
|
||||
throw new Error("Public key must be compressed secp256k1, i.e. 33 bytes starting with 0x02 or 0x03");
|
||||
}
|
||||
return {
|
||||
type: pubkeyType.secp256k1,
|
||||
value: toBase64(pubkey),
|
||||
};
|
||||
}
|
||||
|
||||
// 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 = fromHex("eb5ae98721");
|
||||
const pubkeyAminoPrefixEd25519 = fromHex("1624de6420");
|
||||
const pubkeyAminoPrefixSr25519 = fromHex("0dfb1005");
|
||||
const pubkeyAminoPrefixLength = pubkeyAminoPrefixSecp256k1.length;
|
||||
|
||||
/**
|
||||
* Decodes a pubkey in the Amino binary format to a type/value object.
|
||||
*/
|
||||
export function decodeAminoPubkey(data: Uint8Array): PubKey {
|
||||
const aminoPrefix = data.slice(0, pubkeyAminoPrefixLength);
|
||||
const rest = data.slice(pubkeyAminoPrefixLength);
|
||||
if (arrayContentEquals(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 (arrayContentEquals(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 (arrayContentEquals(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: " + toHex(aminoPrefix));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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
|
||||
case pubkeyType.secp256k1:
|
||||
aminoPrefix = pubkeyAminoPrefixSecp256k1;
|
||||
break;
|
||||
case pubkeyType.ed25519:
|
||||
aminoPrefix = pubkeyAminoPrefixEd25519;
|
||||
break;
|
||||
default:
|
||||
throw new Error("Unsupported pubkey type");
|
||||
}
|
||||
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));
|
||||
}
|
||||
8
packages/amino/src/index.ts
Normal file
8
packages/amino/src/index.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export {
|
||||
decodeAminoPubkey,
|
||||
decodeBech32Pubkey,
|
||||
encodeAminoPubkey,
|
||||
encodeBech32Pubkey,
|
||||
encodeSecp256k1Pubkey,
|
||||
} from "./encoding";
|
||||
export { PubKey, pubkeyType } from "./pubkeys";
|
||||
18
packages/amino/src/pubkeys.ts
Normal file
18
packages/amino/src/pubkeys.ts
Normal file
@ -0,0 +1,18 @@
|
||||
export interface PubKey {
|
||||
// type is one of the strings defined in pubkeyType
|
||||
// I don't use a string literal union here as that makes trouble with json test data:
|
||||
// https://github.com/cosmos/cosmjs/pull/44#pullrequestreview-353280504
|
||||
readonly type: string;
|
||||
// Value field is base64-encoded in all cases
|
||||
// Note: if type is Secp256k1, this must contain a COMPRESSED pubkey - to encode from bcp/keycontrol land, you must compress it first
|
||||
readonly value: string;
|
||||
}
|
||||
|
||||
export const pubkeyType = {
|
||||
/** @see https://github.com/tendermint/tendermint/blob/v0.33.0/crypto/ed25519/ed25519.go#L22 */
|
||||
secp256k1: "tendermint/PubKeySecp256k1" as const,
|
||||
/** @see https://github.com/tendermint/tendermint/blob/v0.33.0/crypto/secp256k1/secp256k1.go#L23 */
|
||||
ed25519: "tendermint/PubKeyEd25519" as const,
|
||||
/** @see https://github.com/tendermint/tendermint/blob/v0.33.0/crypto/sr25519/codec.go#L12 */
|
||||
sr25519: "tendermint/PubKeySr25519" as const,
|
||||
};
|
||||
11
packages/amino/tsconfig.json
Normal file
11
packages/amino/tsconfig.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"outDir": "build",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
]
|
||||
}
|
||||
11
packages/amino/typedoc.js
Normal file
11
packages/amino/typedoc.js
Normal file
@ -0,0 +1,11 @@
|
||||
const packageJson = require("./package.json");
|
||||
|
||||
module.exports = {
|
||||
entryPoints: ["./src"],
|
||||
out: "docs",
|
||||
exclude: "**/*.spec.ts",
|
||||
name: `${packageJson.name} Documentation`,
|
||||
readme: "README.md",
|
||||
excludeExternals: true,
|
||||
excludePrivate: true,
|
||||
};
|
||||
17
packages/amino/webpack.web.config.js
Normal file
17
packages/amino/webpack.web.config.js
Normal file
@ -0,0 +1,17 @@
|
||||
const glob = require("glob");
|
||||
const path = require("path");
|
||||
|
||||
const target = "web";
|
||||
const distdir = path.join(__dirname, "dist", "web");
|
||||
|
||||
module.exports = [
|
||||
{
|
||||
// bundle used for Karma tests
|
||||
target: target,
|
||||
entry: glob.sync("./build/**/*.spec.js"),
|
||||
output: {
|
||||
path: distdir,
|
||||
filename: "tests.js",
|
||||
},
|
||||
},
|
||||
];
|
||||
@ -42,6 +42,7 @@
|
||||
"postdefine-proto": "prettier --write \"src/codec/**/*.ts\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@cosmjs/amino": "^0.25.0-alpha.0",
|
||||
"@cosmjs/cosmwasm-launchpad": "^0.25.0-alpha.0",
|
||||
"@cosmjs/crypto": "^0.25.0-alpha.0",
|
||||
"@cosmjs/encoding": "^0.25.0-alpha.0",
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import { encodeSecp256k1Pubkey } from "@cosmjs/amino";
|
||||
import {
|
||||
ChangeAdminResult,
|
||||
CosmWasmFeeTable,
|
||||
@ -16,7 +17,6 @@ import {
|
||||
buildFeeTable,
|
||||
Coin,
|
||||
CosmosFeeTable,
|
||||
encodeSecp256k1Pubkey,
|
||||
GasLimits,
|
||||
GasPrice,
|
||||
logs,
|
||||
|
||||
@ -39,6 +39,7 @@
|
||||
"pack-web": "yarn build-or-skip && webpack --mode development --config webpack.web.config.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cosmjs/amino": "^0.25.0-alpha.0",
|
||||
"@cosmjs/crypto": "^0.25.0-alpha.0",
|
||||
"@cosmjs/encoding": "^0.25.0-alpha.0",
|
||||
"@cosmjs/math": "^0.25.0-alpha.0",
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import { PubKey, pubkeyType } from "@cosmjs/amino";
|
||||
import { ripemd160, sha256 } from "@cosmjs/crypto";
|
||||
import { Bech32, fromBase64 } from "@cosmjs/encoding";
|
||||
|
||||
import { PubKey, pubkeyType } from "./types";
|
||||
|
||||
export function rawSecp256k1PubkeyToAddress(pubkeyRaw: Uint8Array, prefix: string): string {
|
||||
if (pubkeyRaw.length !== 33) {
|
||||
throw new Error(`Invalid Secp256k1 pubkey length (compressed): ${pubkeyRaw.length}`);
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { PubKey } from "@cosmjs/amino";
|
||||
import { sha256 } from "@cosmjs/crypto";
|
||||
import { fromBase64, fromHex, toHex } from "@cosmjs/encoding";
|
||||
import { Uint53 } from "@cosmjs/math";
|
||||
@ -13,7 +14,6 @@ import {
|
||||
} from "./lcdapi";
|
||||
import { Log, parseLogs } from "./logs";
|
||||
import { StdTx, WrappedStdTx } from "./tx";
|
||||
import { PubKey } from "./types";
|
||||
|
||||
export interface GetSequenceResult {
|
||||
readonly accountNumber: number;
|
||||
|
||||
@ -1,3 +1,14 @@
|
||||
// Re-exports for backwards compatibility
|
||||
export {
|
||||
decodeAminoPubkey,
|
||||
decodeBech32Pubkey,
|
||||
encodeAminoPubkey,
|
||||
encodeBech32Pubkey,
|
||||
encodeSecp256k1Pubkey,
|
||||
pubkeyType,
|
||||
PubKey,
|
||||
} from "@cosmjs/amino";
|
||||
|
||||
import * as logs from "./logs";
|
||||
export { logs };
|
||||
|
||||
@ -125,19 +136,12 @@ export {
|
||||
MsgWithdrawValidatorCommission,
|
||||
} from "./msgs";
|
||||
export { makeCosmoshubPath } from "./paths";
|
||||
export {
|
||||
decodeAminoPubkey,
|
||||
decodeBech32Pubkey,
|
||||
encodeAminoPubkey,
|
||||
encodeBech32Pubkey,
|
||||
encodeSecp256k1Pubkey,
|
||||
} from "./pubkey";
|
||||
export { findSequenceForSignedTx } from "./sequence";
|
||||
export { encodeSecp256k1Signature, decodeSignature } from "./signature";
|
||||
export { AccountData, Algo, AminoSignResponse, OfflineSigner } from "./signer";
|
||||
export { CosmosFeeTable, SigningCosmosClient } from "./signingcosmosclient";
|
||||
export { isStdTx, isWrappedStdTx, makeStdTx, CosmosSdkTx, StdTx, WrappedStdTx, WrappedTx } from "./tx";
|
||||
export { pubkeyType, PubKey, StdFee, StdSignature } from "./types";
|
||||
export { StdFee, StdSignature } from "./types";
|
||||
export { executeKdf, KdfConfiguration } from "./wallet";
|
||||
export { extractKdfConfiguration, Secp256k1HdWallet } from "./secp256k1hdwallet";
|
||||
export { Secp256k1Wallet } from "./secp256k1wallet";
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import { PubKey } from "@cosmjs/amino";
|
||||
|
||||
import { Coin } from "../coins";
|
||||
import { PubKey } from "../types";
|
||||
import { LcdClient } from "./lcdclient";
|
||||
|
||||
/**
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { PubKey } from "../types";
|
||||
import { PubKey } from "@cosmjs/amino";
|
||||
|
||||
import { normalizePubkey, uint64ToNumber, uint64ToString } from "./utils";
|
||||
|
||||
describe("utils", () => {
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import { decodeBech32Pubkey, PubKey } from "@cosmjs/amino";
|
||||
import { Uint64 } from "@cosmjs/math";
|
||||
|
||||
import { decodeBech32Pubkey } from "../pubkey";
|
||||
import { PubKey } from "../types";
|
||||
|
||||
/**
|
||||
* Converts an integer expressed as number or string to a number.
|
||||
* Throws if input is not a valid uint64 or if the value exceeds MAX_SAFE_INTEGER.
|
||||
|
||||
@ -1,135 +0,0 @@
|
||||
import { Bech32, fromBase64 } from "@cosmjs/encoding";
|
||||
|
||||
import {
|
||||
decodeAminoPubkey,
|
||||
decodeBech32Pubkey,
|
||||
encodeAminoPubkey,
|
||||
encodeBech32Pubkey,
|
||||
encodeSecp256k1Pubkey,
|
||||
} from "./pubkey";
|
||||
import { PubKey } from "./types";
|
||||
|
||||
describe("pubkey", () => {
|
||||
describe("encodeSecp256k1Pubkey", () => {
|
||||
it("encodes a compresed pubkey", () => {
|
||||
const pubkey = fromBase64("AtQaCqFnshaZQp6rIkvAPyzThvCvXSDO+9AzbxVErqJP");
|
||||
expect(encodeSecp256k1Pubkey(pubkey)).toEqual({
|
||||
type: "tendermint/PubKeySecp256k1",
|
||||
value: "AtQaCqFnshaZQp6rIkvAPyzThvCvXSDO+9AzbxVErqJP",
|
||||
});
|
||||
});
|
||||
|
||||
it("throws for uncompressed public keys", () => {
|
||||
const pubkey = fromBase64(
|
||||
"BE8EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQE7WHpoHoNswYeoFkuYpYSKK4mzFzMV/dB0DVAy4lnNU=",
|
||||
);
|
||||
expect(() => encodeSecp256k1Pubkey(pubkey)).toThrowError(/public key must be compressed secp256k1/i);
|
||||
});
|
||||
});
|
||||
|
||||
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(
|
||||
decodeBech32Pubkey("cosmospub1addwnpepqd8sgxq7aw348ydctp3n5ajufgxp395hksxjzc6565yfp56scupfqhlgyg5"),
|
||||
).toEqual({
|
||||
type: "tendermint/PubKeySecp256k1",
|
||||
value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ",
|
||||
});
|
||||
});
|
||||
|
||||
it("works for enigma pubkey", () => {
|
||||
expect(
|
||||
decodeBech32Pubkey("enigmapub1addwnpepqw5k9p439nw0zpg2aundx4umwx4nw233z5prpjqjv5anl5grmnchzp2xwvv"),
|
||||
).toEqual({
|
||||
type: "tendermint/PubKeySecp256k1",
|
||||
value: "A6lihrEs3PEFCu8m01ebcas3KjEVAjDIEmU7P9ED3PFx",
|
||||
});
|
||||
});
|
||||
|
||||
it("works for ed25519", () => {
|
||||
// Encoded from `corald tendermint show-validator`
|
||||
// Decoded from http://localhost:26657/validators
|
||||
const decoded = decodeBech32Pubkey(
|
||||
"coralvalconspub1zcjduepqvxg72ccnl9r65fv0wn3amlk4sfzqfe2k36l073kjx2qyaf6sk23qw7j8wq",
|
||||
);
|
||||
expect(decoded).toEqual({
|
||||
type: "tendermint/PubKeyEd25519",
|
||||
value: "YZHlYxP5R6olj3Tj3f7VgkQE5VaOvv9G0jKATqdQsqI=",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
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 = {
|
||||
type: "tendermint/PubKeySecp256k1",
|
||||
value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ",
|
||||
};
|
||||
expect(encodeBech32Pubkey(pubkey, "cosmospub")).toEqual(
|
||||
"cosmospub1addwnpepqd8sgxq7aw348ydctp3n5ajufgxp395hksxjzc6565yfp56scupfqhlgyg5",
|
||||
);
|
||||
});
|
||||
|
||||
it("works for ed25519", () => {
|
||||
// Decoded from http://localhost:26657/validators
|
||||
// Encoded from `corald tendermint show-validator`
|
||||
const pubkey: PubKey = {
|
||||
type: "tendermint/PubKeyEd25519",
|
||||
value: "YZHlYxP5R6olj3Tj3f7VgkQE5VaOvv9G0jKATqdQsqI=",
|
||||
};
|
||||
expect(encodeBech32Pubkey(pubkey, "coralvalconspub")).toEqual(
|
||||
"coralvalconspub1zcjduepqvxg72ccnl9r65fv0wn3amlk4sfzqfe2k36l073kjx2qyaf6sk23qw7j8wq",
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1,97 +0,0 @@
|
||||
import { Bech32, fromBase64, fromHex, toBase64, toHex } from "@cosmjs/encoding";
|
||||
import { arrayContentEquals } from "@cosmjs/utils";
|
||||
|
||||
import { PubKey, pubkeyType } from "./types";
|
||||
|
||||
export function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey {
|
||||
if (pubkey.length !== 33 || (pubkey[0] !== 0x02 && pubkey[0] !== 0x03)) {
|
||||
throw new Error("Public key must be compressed secp256k1, i.e. 33 bytes starting with 0x02 or 0x03");
|
||||
}
|
||||
return {
|
||||
type: pubkeyType.secp256k1,
|
||||
value: toBase64(pubkey),
|
||||
};
|
||||
}
|
||||
|
||||
// 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 = fromHex("eb5ae98721");
|
||||
const pubkeyAminoPrefixEd25519 = fromHex("1624de6420");
|
||||
const pubkeyAminoPrefixSr25519 = fromHex("0dfb1005");
|
||||
const pubkeyAminoPrefixLength = pubkeyAminoPrefixSecp256k1.length;
|
||||
|
||||
/**
|
||||
* Decodes a pubkey in the Amino binary format to a type/value object.
|
||||
*/
|
||||
export function decodeAminoPubkey(data: Uint8Array): PubKey {
|
||||
const aminoPrefix = data.slice(0, pubkeyAminoPrefixLength);
|
||||
const rest = data.slice(pubkeyAminoPrefixLength);
|
||||
if (arrayContentEquals(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 (arrayContentEquals(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 (arrayContentEquals(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: " + toHex(aminoPrefix));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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
|
||||
case pubkeyType.secp256k1:
|
||||
aminoPrefix = pubkeyAminoPrefixSecp256k1;
|
||||
break;
|
||||
case pubkeyType.ed25519:
|
||||
aminoPrefix = pubkeyAminoPrefixEd25519;
|
||||
break;
|
||||
default:
|
||||
throw new Error("Unsupported pubkey type");
|
||||
}
|
||||
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));
|
||||
}
|
||||
@ -1,8 +1,8 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import { encodeSecp256k1Pubkey, pubkeyType } from "@cosmjs/amino";
|
||||
import { fromBase64, toBase64 } from "@cosmjs/encoding";
|
||||
|
||||
import { encodeSecp256k1Pubkey } from "./pubkey";
|
||||
import { pubkeyType, StdSignature } from "./types";
|
||||
import { StdSignature } from "./types";
|
||||
|
||||
/**
|
||||
* Takes a binary pubkey and signature to create a signature object
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import { PubKey } from "@cosmjs/amino";
|
||||
|
||||
import { Coin } from "./coins";
|
||||
|
||||
export interface StdFee {
|
||||
@ -10,22 +12,3 @@ export interface StdSignature {
|
||||
readonly pub_key: PubKey;
|
||||
readonly signature: string;
|
||||
}
|
||||
|
||||
export interface PubKey {
|
||||
// type is one of the strings defined in pubkeyType
|
||||
// I don't use a string literal union here as that makes trouble with json test data:
|
||||
// https://github.com/cosmos/cosmjs/pull/44#pullrequestreview-353280504
|
||||
readonly type: string;
|
||||
// Value field is base64-encoded in all cases
|
||||
// Note: if type is Secp256k1, this must contain a COMPRESSED pubkey - to encode from bcp/keycontrol land, you must compress it first
|
||||
readonly value: string;
|
||||
}
|
||||
|
||||
export const pubkeyType = {
|
||||
/** @see https://github.com/tendermint/tendermint/blob/v0.33.0/crypto/ed25519/ed25519.go#L22 */
|
||||
secp256k1: "tendermint/PubKeySecp256k1" as const,
|
||||
/** @see https://github.com/tendermint/tendermint/blob/v0.33.0/crypto/secp256k1/secp256k1.go#L23 */
|
||||
ed25519: "tendermint/PubKeyEd25519" as const,
|
||||
/** @see https://github.com/tendermint/tendermint/blob/v0.33.0/crypto/sr25519/codec.go#L12 */
|
||||
sr25519: "tendermint/PubKeySr25519" as const,
|
||||
};
|
||||
|
||||
@ -43,6 +43,7 @@
|
||||
"postdefine-proto": "prettier --write \"src/codec/**/*.ts\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@cosmjs/amino": "^0.25.0-alpha.0",
|
||||
"@cosmjs/launchpad": "^0.25.0-alpha.0",
|
||||
"long": "^4.0.0",
|
||||
"protobufjs": "~6.10.2"
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import { encodeSecp256k1Pubkey, PubKey as AminoPubKey } from "@cosmjs/amino";
|
||||
import { fromBase64 } from "@cosmjs/encoding";
|
||||
import { encodeSecp256k1Pubkey, PubKey as LaunchpadPubKey } from "@cosmjs/launchpad";
|
||||
|
||||
import { PubKey } from "./codec/cosmos/crypto/secp256k1/keys";
|
||||
import { Any } from "./codec/google/protobuf/any";
|
||||
|
||||
export function encodePubkey(pubkey: LaunchpadPubKey): Any {
|
||||
export function encodePubkey(pubkey: AminoPubKey): Any {
|
||||
switch (pubkey.type) {
|
||||
case "tendermint/PubKeySecp256k1": {
|
||||
const pubkeyProto = PubKey.fromPartial({
|
||||
@ -21,7 +21,7 @@ export function encodePubkey(pubkey: LaunchpadPubKey): Any {
|
||||
}
|
||||
}
|
||||
|
||||
export function decodePubkey(pubkey?: Any | null): LaunchpadPubKey | null {
|
||||
export function decodePubkey(pubkey?: Any | null): AminoPubKey | null {
|
||||
if (!pubkey || !pubkey.value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -43,6 +43,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@confio/ics23": "^0.6.3",
|
||||
"@cosmjs/amino": "^0.25.0-alpha.0",
|
||||
"@cosmjs/encoding": "^0.25.0-alpha.0",
|
||||
"@cosmjs/launchpad": "^0.25.0-alpha.0",
|
||||
"@cosmjs/math": "^0.25.0-alpha.0",
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { PubKey } from "@cosmjs/launchpad";
|
||||
import { PubKey } from "@cosmjs/amino";
|
||||
import { Uint64 } from "@cosmjs/math";
|
||||
import { decodePubkey } from "@cosmjs/proto-signing";
|
||||
import { assert } from "@cosmjs/utils";
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import { encodeBech32Pubkey } from "@cosmjs/amino";
|
||||
import { fromBase64 } from "@cosmjs/encoding";
|
||||
import {
|
||||
coin,
|
||||
coins,
|
||||
encodeBech32Pubkey,
|
||||
MsgBeginRedelegate as LaunchpadMsgBeginRedelegate,
|
||||
MsgCreateValidator as LaunchpadMsgCreateValidator,
|
||||
MsgDelegate as LaunchpadMsgDelegate,
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import { decodeBech32Pubkey, encodeBech32Pubkey } from "@cosmjs/amino";
|
||||
import { fromBase64, toBase64 } from "@cosmjs/encoding";
|
||||
import {
|
||||
decodeBech32Pubkey,
|
||||
encodeBech32Pubkey,
|
||||
Msg,
|
||||
MsgBeginRedelegate as LaunchpadMsgBeginRedelegate,
|
||||
MsgCreateValidator as LaunchpadMsgCreateValidator,
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { encodeSecp256k1Pubkey } from "@cosmjs/amino";
|
||||
import { fromBase64 } from "@cosmjs/encoding";
|
||||
import {
|
||||
buildFeeTable,
|
||||
Coin,
|
||||
CosmosFeeTable,
|
||||
encodeSecp256k1Pubkey,
|
||||
GasLimits,
|
||||
GasPrice,
|
||||
makeSignDoc as makeSignDocAmino,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user