Merge pull request #64 from confio/unused-account
Add unused account for more explicit testing of authAccounts
This commit is contained in:
commit
4cd2aff735
@ -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";
|
||||
|
||||
@ -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 = {
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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(addressPrefix: CosmosAddressBech32Prefix, tokens: TokenInfos) {
|
||||
this.addressPrefix = addressPrefix;
|
||||
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 = [
|
||||
{
|
||||
|
||||
@ -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 = [
|
||||
|
||||
@ -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<CosmWasmConnection> {
|
||||
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<ChainData> {
|
||||
@ -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<Account | undefined> {
|
||||
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<Nonce> {
|
||||
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);
|
||||
|
||||
@ -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<CosmWasmConnection> {
|
||||
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,
|
||||
};
|
||||
|
||||
5
packages/bcp/types/address.d.ts
vendored
5
packages/bcp/types/address.d.ts
vendored
@ -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;
|
||||
|
||||
6
packages/bcp/types/cosmwasmcodec.d.ts
vendored
6
packages/bcp/types/cosmwasmcodec.d.ts
vendored
@ -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(addressPrefix: CosmosAddressBech32Prefix, tokens: TokenInfos);
|
||||
bytesToSign(unsigned: UnsignedTransaction, nonce: Nonce): SigningJob;
|
||||
bytesToPost(signed: SignedTransaction): PostableBytes;
|
||||
identifier(_signed: SignedTransaction): TransactionId;
|
||||
|
||||
7
packages/bcp/types/cosmwasmconnection.d.ts
vendored
7
packages/bcp/types/cosmwasmconnection.d.ts
vendored
@ -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<CosmWasmConnection>;
|
||||
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;
|
||||
|
||||
4
packages/bcp/types/cosmwasmconnector.d.ts
vendored
4
packages/bcp/types/cosmwasmconnector.d.ts
vendored
@ -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<CosmWasmConnection>;
|
||||
|
||||
@ -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,69 +1,17 @@
|
||||
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";
|
||||
export type CosmosPubkeyBech32Prefix = "cosmospub" | "cosmosvalconspub" | "cosmosvaloperpub";
|
||||
export type CosmosBech32Prefix = CosmosAddressBech32Prefix | CosmosPubkeyBech32Prefix;
|
||||
|
||||
function isCosmosAddressBech32Prefix(prefix: string): prefix is CosmosAddressBech32Prefix {
|
||||
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,14 @@ import * as logs from "./logs";
|
||||
import * as types from "./types";
|
||||
export { logs, types };
|
||||
|
||||
export { CosmosBech32Prefix, decodeBech32Pubkey, 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";
|
||||
export { makeCosmoshubPath, Pen, PrehashType, Secp256k1Pen } from "./pen";
|
||||
export { encodeSecp256k1Pubkey } from "./pubkey";
|
||||
export {
|
||||
CosmosPubkeyBech32Prefix,
|
||||
decodeBech32Pubkey,
|
||||
encodeBech32Pubkey,
|
||||
encodeSecp256k1Pubkey,
|
||||
} from "./pubkey";
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { Encoding } from "@iov/encoding";
|
||||
|
||||
import { encodeSecp256k1Pubkey } from "./pubkey";
|
||||
import { decodeBech32Pubkey, encodeBech32Pubkey, encodeSecp256k1Pubkey } from "./pubkey";
|
||||
import { PubKey } from "./types";
|
||||
|
||||
const { fromBase64 } = Encoding;
|
||||
|
||||
@ -24,4 +25,27 @@ describe("pubkey", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("decodeBech32Pubkey", () => {
|
||||
it("works", () => {
|
||||
expect(
|
||||
decodeBech32Pubkey("cosmospub1addwnpepqd8sgxq7aw348ydctp3n5ajufgxp395hksxjzc6565yfp56scupfqhlgyg5"),
|
||||
).toEqual({
|
||||
type: "tendermint/PubKeySecp256k1",
|
||||
value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("encodeBech32Pubkey", () => {
|
||||
it("works for secp256k1", () => {
|
||||
const pubkey: PubKey = {
|
||||
type: "tendermint/PubKeySecp256k1",
|
||||
value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ",
|
||||
};
|
||||
expect(encodeBech32Pubkey(pubkey, "cosmospub")).toEqual(
|
||||
"cosmospub1addwnpepqd8sgxq7aw348ydctp3n5ajufgxp395hksxjzc6565yfp56scupfqhlgyg5",
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
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 { Bech32PubKey, PubKey, pubkeyType } from "./types";
|
||||
|
||||
export function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey {
|
||||
return {
|
||||
@ -9,3 +10,70 @@ export function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey {
|
||||
value: Encoding.toBase64(Secp256k1.compressPubkey(pubkey)),
|
||||
};
|
||||
}
|
||||
|
||||
export type CosmosPubkeyBech32Prefix = "cosmospub" | "cosmosvalconspub" | "cosmosvaloperpub";
|
||||
const validPubkeyPrefixes = ["cosmospub", "cosmosvalconspub", "cosmosvaloperpub"];
|
||||
|
||||
function isCosmosPubkeyBech32Prefix(prefix: string): prefix is CosmosPubkeyBech32Prefix {
|
||||
return validPubkeyPrefixes.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 ${validPubkeyPrefixes.join(", ")}.`);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
export function encodeBech32Pubkey(pubkey: PubKey, prefix: CosmosPubkeyBech32Prefix): Bech32PubKey {
|
||||
let aminoPrefix: Uint8Array;
|
||||
switch (pubkey.type) {
|
||||
// Note: please don't add cases here without writing additional unit tests
|
||||
case pubkeyType.secp256k1:
|
||||
aminoPrefix = pubkeyAminoPrefixSecp256k1;
|
||||
break;
|
||||
default:
|
||||
throw new Error("Unsupported pubkey type");
|
||||
}
|
||||
|
||||
const data = new Uint8Array([...aminoPrefix, ...Encoding.fromBase64(pubkey.value)]);
|
||||
return Bech32.encode(prefix, data);
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import { encodeSecp256k1Signature, makeSignBytes, marshalTx } from "./encoding";
|
||||
import { leb128Encode } from "./leb128.spec";
|
||||
import { findAttribute, parseLogs } from "./logs";
|
||||
import { Pen, Secp256k1Pen } from "./pen";
|
||||
import { encodeBech32Pubkey } from "./pubkey";
|
||||
import { PostTxsResponse, RestClient } from "./restclient";
|
||||
import contract from "./testdata/contract.json";
|
||||
import cosmoshub from "./testdata/cosmoshub.json";
|
||||
@ -25,10 +26,19 @@ const { fromBase64, fromHex, toAscii, toBase64, toHex } = Encoding;
|
||||
|
||||
const httpUrl = "http://localhost:1317";
|
||||
const defaultNetworkId = "testing";
|
||||
const faucetMnemonic =
|
||||
"economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone";
|
||||
const faucetAddress = "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6";
|
||||
const faucet = {
|
||||
mnemonic:
|
||||
"economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone",
|
||||
pubkey: {
|
||||
type: "tendermint/PubKeySecp256k1",
|
||||
value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ",
|
||||
},
|
||||
address: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6",
|
||||
};
|
||||
const emptyAddress = "cosmos1ltkhnmdcqemmd2tkhnx7qx66tq7e0wykw2j85k";
|
||||
const unusedAccount = {
|
||||
address: "cosmos1cjsxept9rkggzxztslae9ndgpdyt2408lk850u",
|
||||
};
|
||||
|
||||
function pendingWithoutCosmos(): void {
|
||||
if (!process.env.COSMOS_ENABLED) {
|
||||
@ -80,7 +90,7 @@ async function uploadContract(client: RestClient, pen: Pen): Promise<PostTxsResp
|
||||
const theMsg: MsgStoreCode = {
|
||||
type: "wasm/store-code",
|
||||
value: {
|
||||
sender: faucetAddress,
|
||||
sender: faucet.address,
|
||||
wasm_byte_code: toBase64(getRandomizedContract()),
|
||||
source: "https://github.com/confio/cosmwasm/raw/0.7/lib/vm/testdata/contract_0.6.wasm",
|
||||
builder: "cosmwasm-opt:0.6.2",
|
||||
@ -96,7 +106,7 @@ async function uploadContract(client: RestClient, pen: Pen): Promise<PostTxsResp
|
||||
gas: "89000000",
|
||||
};
|
||||
|
||||
const account = (await client.authAccounts(faucetAddress)).result.value;
|
||||
const account = (await client.authAccounts(faucet.address)).result.value;
|
||||
const signBytes = makeSignBytes([theMsg], fee, defaultNetworkId, memo, account);
|
||||
const signature = encodeSecp256k1Signature(pen.pubkey, await pen.createSignature(signBytes));
|
||||
const signedTx = makeSignedTx(theMsg, fee, memo, signature);
|
||||
@ -114,10 +124,10 @@ async function instantiateContract(
|
||||
const theMsg: MsgInstantiateContract = {
|
||||
type: "wasm/instantiate",
|
||||
value: {
|
||||
sender: faucetAddress,
|
||||
sender: faucet.address,
|
||||
code_id: codeId.toString(),
|
||||
init_msg: {
|
||||
verifier: faucetAddress,
|
||||
verifier: faucet.address,
|
||||
beneficiary: beneficiaryAddress,
|
||||
},
|
||||
init_funds: transferAmount || [],
|
||||
@ -133,7 +143,7 @@ async function instantiateContract(
|
||||
gas: "89000000",
|
||||
};
|
||||
|
||||
const account = (await client.authAccounts(faucetAddress)).result.value;
|
||||
const account = (await client.authAccounts(faucet.address)).result.value;
|
||||
const signBytes = makeSignBytes([theMsg], fee, defaultNetworkId, memo, account);
|
||||
const signature = encodeSecp256k1Signature(pen.pubkey, await pen.createSignature(signBytes));
|
||||
const signedTx = makeSignedTx(theMsg, fee, memo, signature);
|
||||
@ -149,7 +159,7 @@ async function executeContract(
|
||||
const theMsg: MsgExecuteContract = {
|
||||
type: "wasm/execute",
|
||||
value: {
|
||||
sender: faucetAddress,
|
||||
sender: faucet.address,
|
||||
contract: contractAddress,
|
||||
msg: {},
|
||||
sent_funds: [],
|
||||
@ -165,7 +175,7 @@ async function executeContract(
|
||||
gas: "89000000",
|
||||
};
|
||||
|
||||
const account = (await client.authAccounts(faucetAddress)).result.value;
|
||||
const account = (await client.authAccounts(faucet.address)).result.value;
|
||||
const signBytes = makeSignBytes([theMsg], fee, defaultNetworkId, memo, account);
|
||||
const signature = encodeSecp256k1Signature(pen.pubkey, await pen.createSignature(signBytes));
|
||||
const signedTx = makeSignedTx(theMsg, fee, memo, signature);
|
||||
@ -188,13 +198,40 @@ describe("RestClient", () => {
|
||||
});
|
||||
|
||||
describe("authAccounts", () => {
|
||||
it("works", async () => {
|
||||
it("works for unused account without pubkey", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const client = new RestClient(httpUrl);
|
||||
const { result } = await client.authAccounts(faucetAddress);
|
||||
const account = result.value;
|
||||
expect(account.account_number).toEqual(4);
|
||||
expect(account.sequence).toBeGreaterThanOrEqual(0);
|
||||
const { result } = await client.authAccounts(unusedAccount.address);
|
||||
expect(result).toEqual({
|
||||
type: "cosmos-sdk/Account",
|
||||
value: {
|
||||
address: unusedAccount.address,
|
||||
public_key: "", // not known to the chain
|
||||
coins: [
|
||||
{
|
||||
amount: "1000000000",
|
||||
denom: "ucosm",
|
||||
},
|
||||
{
|
||||
amount: "1000000000",
|
||||
denom: "ustake",
|
||||
},
|
||||
],
|
||||
account_number: 5,
|
||||
sequence: 0,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("has correct pubkey for faucet", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const client = new RestClient(httpUrl);
|
||||
const { result } = await client.authAccounts(faucet.address);
|
||||
expect(result.value).toEqual(
|
||||
jasmine.objectContaining({
|
||||
public_key: encodeBech32Pubkey(faucet.pubkey, "cosmospub"),
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -210,13 +247,13 @@ describe("RestClient", () => {
|
||||
describe("post", () => {
|
||||
it("can send tokens", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const pen = await Secp256k1Pen.fromMnemonic(faucetMnemonic);
|
||||
const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
|
||||
|
||||
const memo = "My first contract on chain";
|
||||
const theMsg: MsgSend = {
|
||||
type: "cosmos-sdk/MsgSend",
|
||||
value: {
|
||||
from_address: faucetAddress,
|
||||
from_address: faucet.address,
|
||||
to_address: emptyAddress,
|
||||
amount: [
|
||||
{
|
||||
@ -238,7 +275,7 @@ describe("RestClient", () => {
|
||||
};
|
||||
|
||||
const client = new RestClient(httpUrl);
|
||||
const account = (await client.authAccounts(faucetAddress)).result.value;
|
||||
const account = (await client.authAccounts(faucet.address)).result.value;
|
||||
|
||||
const signBytes = makeSignBytes([theMsg], fee, defaultNetworkId, memo, account);
|
||||
const signature = encodeSecp256k1Signature(pen.pubkey, await pen.createSignature(signBytes));
|
||||
@ -250,7 +287,7 @@ describe("RestClient", () => {
|
||||
|
||||
it("can upload, instantiate and execute wasm", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const pen = await Secp256k1Pen.fromMnemonic(faucetMnemonic);
|
||||
const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
|
||||
const client = new RestClient(httpUrl);
|
||||
|
||||
const transferAmount: readonly Coin[] = [
|
||||
@ -316,7 +353,7 @@ describe("RestClient", () => {
|
||||
describe("query", () => {
|
||||
it("can list upload code", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const pen = await Secp256k1Pen.fromMnemonic(faucetMnemonic);
|
||||
const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
|
||||
const client = new RestClient(httpUrl);
|
||||
|
||||
// check with contracts were here first to compare
|
||||
@ -336,17 +373,17 @@ describe("RestClient", () => {
|
||||
expect(newInfos.length).toEqual(numExisting + 1);
|
||||
const lastInfo = newInfos[newInfos.length - 1];
|
||||
expect(lastInfo.id).toEqual(codeId);
|
||||
expect(lastInfo.creator).toEqual(faucetAddress);
|
||||
expect(lastInfo.creator).toEqual(faucet.address);
|
||||
|
||||
// TODO: check code hash matches expectation
|
||||
// expect(lastInfo.code_hash).toEqual(faucetAddress);
|
||||
// expect(lastInfo.code_hash).toEqual(faucet.address);
|
||||
|
||||
// TODO: download code and check against auto-gen
|
||||
});
|
||||
|
||||
it("can list contracts and get info", async () => {
|
||||
pendingWithoutCosmos();
|
||||
const pen = await Secp256k1Pen.fromMnemonic(faucetMnemonic);
|
||||
const pen = await Secp256k1Pen.fromMnemonic(faucet.mnemonic);
|
||||
const client = new RestClient(httpUrl);
|
||||
const beneficiaryAddress = makeRandomAddress();
|
||||
const transferAmount: readonly Coin[] = [
|
||||
@ -390,7 +427,7 @@ describe("RestClient", () => {
|
||||
// check out info
|
||||
const myInfo = await client.getContractInfo(myAddress);
|
||||
expect(myInfo.code_id).toEqual(codeId);
|
||||
expect(myInfo.creator).toEqual(faucetAddress);
|
||||
expect(myInfo.creator).toEqual(faucet.address);
|
||||
expect((myInfo.init_msg as any).beneficiary).toEqual(beneficiaryAddress);
|
||||
|
||||
// make sure random addresses don't give useful info
|
||||
@ -459,7 +496,7 @@ describe("RestClient", () => {
|
||||
|
||||
// we can query the verifier properly
|
||||
const verifier = await client.queryContractSmart(contractAddress, { verifier: {} });
|
||||
expect(verifier).toEqual(faucetAddress);
|
||||
expect(verifier).toEqual(faucet.address);
|
||||
|
||||
// invalid query syntax throws an error
|
||||
await client.queryContractSmart(contractAddress, { nosuchkey: {} }).then(
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Encoding } from "@iov/encoding";
|
||||
import axios, { AxiosInstance } from "axios";
|
||||
|
||||
import { AminoTx, BaseAccount, CodeInfo, ContractInfo, isAminoStdTx, StdTx, WasmData } from "./types";
|
||||
import { AminoTx, CodeInfo, ContractInfo, CosmosSdkAccount, isAminoStdTx, StdTx, WasmData } from "./types";
|
||||
|
||||
const { fromBase64, fromUtf8, toHex, toUtf8 } = Encoding;
|
||||
|
||||
@ -37,7 +37,8 @@ interface BlocksResponse {
|
||||
|
||||
interface AuthAccountsResponse {
|
||||
readonly result: {
|
||||
readonly value: BaseAccount;
|
||||
readonly type: "cosmos-sdk/Account";
|
||||
readonly value: CosmosSdkAccount;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -151,7 +151,7 @@ export const pubkeyTypes: readonly string[] = [pubkeyType.secp256k1, pubkeyType.
|
||||
// bech32-encoded amino-binary encoded PubKey interface. oof.
|
||||
export type Bech32PubKey = string;
|
||||
|
||||
export interface BaseAccount {
|
||||
export interface CosmosSdkAccount {
|
||||
/** Bech32 account address */
|
||||
readonly address: string;
|
||||
readonly coins: ReadonlyArray<Coin>;
|
||||
@ -160,8 +160,8 @@ export interface BaseAccount {
|
||||
readonly sequence: number;
|
||||
}
|
||||
|
||||
/** The data we need from BaseAccount to create a nonce */
|
||||
export type NonceInfo = Pick<BaseAccount, "account_number" | "sequence">;
|
||||
/** The data we need from CosmosSdkAccount to create a nonce */
|
||||
export type NonceInfo = Pick<CosmosSdkAccount, "account_number" | "sequence">;
|
||||
|
||||
export interface CodeInfo {
|
||||
readonly id: number;
|
||||
|
||||
5
packages/sdk/types/address.d.ts
vendored
5
packages/sdk/types/address.d.ts
vendored
@ -1,7 +1,4 @@
|
||||
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;
|
||||
|
||||
9
packages/sdk/types/index.d.ts
vendored
9
packages/sdk/types/index.d.ts
vendored
@ -1,9 +1,14 @@
|
||||
import * as logs from "./logs";
|
||||
import * as types from "./types";
|
||||
export { logs, types };
|
||||
export { CosmosBech32Prefix, decodeBech32Pubkey, 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";
|
||||
export { makeCosmoshubPath, Pen, PrehashType, Secp256k1Pen } from "./pen";
|
||||
export { encodeSecp256k1Pubkey } from "./pubkey";
|
||||
export {
|
||||
CosmosPubkeyBech32Prefix,
|
||||
decodeBech32Pubkey,
|
||||
encodeBech32Pubkey,
|
||||
encodeSecp256k1Pubkey,
|
||||
} from "./pubkey";
|
||||
|
||||
5
packages/sdk/types/pubkey.d.ts
vendored
5
packages/sdk/types/pubkey.d.ts
vendored
@ -1,2 +1,5 @@
|
||||
import { PubKey } from "./types";
|
||||
import { Bech32PubKey, PubKey } from "./types";
|
||||
export declare function encodeSecp256k1Pubkey(pubkey: Uint8Array): PubKey;
|
||||
export declare type CosmosPubkeyBech32Prefix = "cosmospub" | "cosmosvalconspub" | "cosmosvaloperpub";
|
||||
export declare function decodeBech32Pubkey(bech: Bech32PubKey): PubKey;
|
||||
export declare function encodeBech32Pubkey(pubkey: PubKey, prefix: CosmosPubkeyBech32Prefix): Bech32PubKey;
|
||||
|
||||
5
packages/sdk/types/restclient.d.ts
vendored
5
packages/sdk/types/restclient.d.ts
vendored
@ -1,4 +1,4 @@
|
||||
import { AminoTx, BaseAccount, CodeInfo, ContractInfo, StdTx, WasmData } from "./types";
|
||||
import { AminoTx, CodeInfo, ContractInfo, CosmosSdkAccount, StdTx, WasmData } from "./types";
|
||||
interface NodeInfo {
|
||||
readonly network: string;
|
||||
}
|
||||
@ -26,7 +26,8 @@ interface BlocksResponse {
|
||||
}
|
||||
interface AuthAccountsResponse {
|
||||
readonly result: {
|
||||
readonly value: BaseAccount;
|
||||
readonly type: "cosmos-sdk/Account";
|
||||
readonly value: CosmosSdkAccount;
|
||||
};
|
||||
}
|
||||
declare type WasmResponse = WasmSuccess | WasmError;
|
||||
|
||||
6
packages/sdk/types/types.d.ts
vendored
6
packages/sdk/types/types.d.ts
vendored
@ -110,7 +110,7 @@ export declare const pubkeyType: {
|
||||
};
|
||||
export declare const pubkeyTypes: readonly string[];
|
||||
export declare type Bech32PubKey = string;
|
||||
export interface BaseAccount {
|
||||
export interface CosmosSdkAccount {
|
||||
/** Bech32 account address */
|
||||
readonly address: string;
|
||||
readonly coins: ReadonlyArray<Coin>;
|
||||
@ -118,8 +118,8 @@ export interface BaseAccount {
|
||||
readonly account_number: number;
|
||||
readonly sequence: number;
|
||||
}
|
||||
/** The data we need from BaseAccount to create a nonce */
|
||||
export declare type NonceInfo = Pick<BaseAccount, "account_number" | "sequence">;
|
||||
/** The data we need from CosmosSdkAccount to create a nonce */
|
||||
export declare type NonceInfo = Pick<CosmosSdkAccount, "account_number" | "sequence">;
|
||||
export interface CodeInfo {
|
||||
readonly id: number;
|
||||
/** Bech32 account address */
|
||||
|
||||
@ -78,3 +78,12 @@ You should get output matching the following:
|
||||
threshold: 0
|
||||
pubkeys: []
|
||||
```
|
||||
|
||||
## Preset accounts
|
||||
|
||||
1. Faucet<br>
|
||||
economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone<br>
|
||||
cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6
|
||||
2. Unused: for testing account state; this account never changes balances or nonces<br>
|
||||
oyster design unusual machine spread century engine gravity focus cave carry slot<br>
|
||||
cosmos1cjsxept9rkggzxztslae9ndgpdyt2408lk850u
|
||||
|
||||
@ -26,6 +26,7 @@ const defaultFee = {
|
||||
const faucetMnemonic =
|
||||
"economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone";
|
||||
const faucetAddress = "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6";
|
||||
const unusedAccount = "cosmos1cjsxept9rkggzxztslae9ndgpdyt2408lk850u";
|
||||
|
||||
async function uploadContract(client, pen, wasm) {
|
||||
const memo = "Upload ERC20 contract";
|
||||
@ -96,6 +97,10 @@ async function main() {
|
||||
address: faucetAddress,
|
||||
amount: "11",
|
||||
},
|
||||
{
|
||||
address: unusedAccount,
|
||||
amount: "12812345",
|
||||
},
|
||||
],
|
||||
};
|
||||
const instantiationResult = await instantiateContract(client, pen, codeId, initMsg);
|
||||
|
||||
@ -2,22 +2,24 @@
|
||||
set -o errexit -o nounset -o pipefail
|
||||
command -v shellcheck > /dev/null && shellcheck "$0"
|
||||
|
||||
# Choose from https://hub.docker.com/r/cosmwasm/wasmd/tags
|
||||
REPOSITORY="cosmwasm/wasmd"
|
||||
VERSION="manual"
|
||||
|
||||
SCRIPT_DIR="$(realpath "$(dirname "$0")")"
|
||||
# shellcheck source=./env
|
||||
# shellcheck disable=SC1091
|
||||
source "$SCRIPT_DIR"/env
|
||||
|
||||
rm -rf "$SCRIPT_DIR/template"
|
||||
mkdir "$SCRIPT_DIR/template"
|
||||
|
||||
# any any more addresses you want to fund in genesis below
|
||||
# The usage of the accounts below is documented in README.md of this directory
|
||||
docker run --rm \
|
||||
-e PASSWORD=my-secret-password \
|
||||
--mount type=bind,source="$SCRIPT_DIR/template",target=/root \
|
||||
"$REPOSITORY:$VERSION" \
|
||||
./setup.sh \
|
||||
cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6
|
||||
cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6 cosmos1cjsxept9rkggzxztslae9ndgpdyt2408lk850u
|
||||
|
||||
# this is created as root, let's make it ours
|
||||
sudo chown -R "$(id -u):$(id -g)" "$SCRIPT_DIR/template"
|
||||
# The ./template folder is created by the docker daemon's user (root on Linux, current user
|
||||
# when using Docker Desktop on macOS), let's make it ours if needed
|
||||
if [ ! -x "$SCRIPT_DIR/template/.wasmd/config/gentx" ]; then
|
||||
sudo chown -R "$(id -u):$(id -g)" "$SCRIPT_DIR/template"
|
||||
fi
|
||||
|
||||
@ -1 +0,0 @@
|
||||
eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjcmVhdGVkIjoiMjAyMC0wMS0zMCAyMDo1ODoxOC4wNzA4NjQ4OSArMDAwMCBVVEMgbT0rMC4yMjM1NjMwMDAiLCJlbmMiOiJBMjU2R0NNIiwicDJjIjo4MTkyLCJwMnMiOiJmU2Q5OUVVUldWQW9EY0Z5In0.KuQ7PWpuxAAjkdWw6e9IUPi_o3Ud-L_MhTNQ5NNwI1MFxvc0Jg__Bg.y7kp74vcKuEgrxUa.pLhY4Qup_jmjSpWjJN0NSJ84IMdhpyOT-IOFfdjNvvihg3ohZWFROrLP1LzZ9FINwbnFMqrmIxgxbrNMOH45U1OahlaswRUP8eVcbF4E4ZF-ZfpYEpCClNG41T-cBV2SzMySkdYAv_u-FJ4_b66nfJ7wYkfOJrff5e8g-FDlIe90PBrGR6c6YLr0XOH6X9uZVF3mWFfYc_jxKT_uoJMcbkefOEPr0W3mVFc-RAvaQ54Az6n_o1tOC6iQBoZ2PHc.I5HjgFmEZwtYqYQfM7VnHg
|
||||
@ -0,0 +1 @@
|
||||
eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjcmVhdGVkIjoiMjAyMC0wMi0wOSAxMTowNTozMi4wNjg2NzQ1ICswMDAwIFVUQyBtPSswLjIyNTA4MDAwMSIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjgxOTIsInAycyI6ImR3S2hTZDJfT1c4UDkyY00ifQ._x85VK6XkQ6XVU4zoSEEjAtMO7qCoSGWiVIo0OJtbksUCWsYhbRPTg.09Qg67smHfoMlScZ.YDYvL193V0G2u9fuJYF-1CSykfctJv8VFpQR3eYroPT233CQI9uXb2KUAK0lP_4AIrDREvkVv1CWQ3Wa0WTGSrOFepIB2X3AFGAf2gw8OsZybdsRiN2Y__7Ljmo7rNjMur9L53fiY7Y4eN83oP9034FovfByDeAL85Lwc0r1Jbf9u4wEB4QudtlFGjfbgfUw4MBDImpmI1dPfnw_1izqWgvlbDlpAzQUALo90gCHtwuCOsVgpCNeFOci5eV60LA.kNLZneL-i5Dzi8Xhi8bU_w
|
||||
@ -1 +1 @@
|
||||
$2a$10$vAg6eRcBB2poo3HKW0wpreHFth9sb9oYoFskLYc9H39ApJiPsGriG
|
||||
$2a$10$wE2S5ENI/eoNUjFTtNCisOmJWW0h0yIVHBr1CjlrDzcCDBRozAZqO
|
||||
@ -1 +1 @@
|
||||
eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjcmVhdGVkIjoiMjAyMC0wMS0zMCAyMDo1ODoxOC4wNjI2NzMwNDUgKzAwMDAgVVRDIG09KzAuMjE1MzcxMTY3IiwiZW5jIjoiQTI1NkdDTSIsInAyYyI6ODE5MiwicDJzIjoiLUNHTldlMFg4bjEwZDl1VyJ9.Cxq-oR7LM1CmAaNO6O0nihb4f-4FFY6qnW-XGO3Trbq9694n4LFBlw.da-kCbllD1_XoMHF.oiuts-8U9mWmJs9xOnWC0NJabUM4FRgSnHKgBce3XzhdSnrhODbbaKkR9EhZFHNWw_h1o27ZxeEtHmPyqv-A5lz4zwwbapi1g7qcZhQW_dI0_4yJ16U5AMdvo7PH5lWXK9z6H0ReG8CIW5aw_CrQBd4egjyGMxQVAABOFAhQ747KGGu76L5vIpfi2b7wJx_z7gS1x6PNSHHR7KOvgQ9hqG6B5VkjPo85JdyRRz00jJec88JXutvdKVbpvVldB8BGsURHFVyYvR3Nj0a7daSroxxkk63T1pZTLIPncYn-XFruKTJE3xmzAu-ojjB1VevGp0dQ8drWcNE_D2nphXP3PLdd-zhfpNkIWfSB8Kh1geeK9xFi.XXG7ekj8VeF6RZaLbTsH0w
|
||||
eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjcmVhdGVkIjoiMjAyMC0wMi0wOSAxMTowNTozMi4wNDgzNjkzICswMDAwIFVUQyBtPSswLjIwNDc3NjcwMSIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjgxOTIsInAycyI6IkRfU1A3Ni1zU3lCRkY0cUQifQ.CPLPgBUrK53I4uLXRR7ba78yQlfio1QI6xedzWjCnTlKEUIdso1c7g.SvJq7pwz3Z86LrNU.03eoFsTiIAfHa2XH14Rgh7bvUnzkH_q4ljLyweN93GVIQIgWjqhRXzaf3ZdZ34i5H0TIs9xr7LcvbttvsUpetw1GjujFboY6hDWhMD0hOE67NysQPIYIsIbC76y5O5_Q6HVZ14vxuEbxgF8qJjGUnpAwqoNwUDBQr8Nju8ZpcAt9Y9VGDw-wiYS3TuYLEED84XQuUwWAIbQNbqvRaY6ZuVtL30-j1cVpy6AyuHmKlFS5L7ddB64eQfni9LErc2VqTnBZypuuaJ1CuGwL1gM0cQrtpRXM-rmSFvu0nXciDqJ2bIUa3qBwULtnBaVqSSAkrj-DgTbHPWhX7RyJoVObEqtQ_XRrB252aKj5HudlYjUThE3O.JWWfqTMVbUQpqUTfepEixA
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"genesis_time": "2020-01-30T20:58:17.838935022Z",
|
||||
"genesis_time": "2020-02-09T11:05:31.7520515Z",
|
||||
"chain_id": "testing",
|
||||
"consensus_params": {
|
||||
"block": {
|
||||
@ -19,18 +19,25 @@
|
||||
},
|
||||
"app_hash": "",
|
||||
"app_state": {
|
||||
"slashing": {
|
||||
"distribution": {
|
||||
"params": {
|
||||
"signed_blocks_window": "100",
|
||||
"min_signed_per_window": "0.500000000000000000",
|
||||
"downtime_jail_duration": "600000000000",
|
||||
"slash_fraction_double_sign": "0.050000000000000000",
|
||||
"slash_fraction_downtime": "0.010000000000000000"
|
||||
"community_tax": "0.020000000000000000",
|
||||
"base_proposer_reward": "0.010000000000000000",
|
||||
"bonus_proposer_reward": "0.040000000000000000",
|
||||
"withdraw_addr_enabled": true
|
||||
},
|
||||
"signing_infos": {},
|
||||
"missed_blocks": {}
|
||||
"fee_pool": {
|
||||
"community_pool": []
|
||||
},
|
||||
"delegator_withdraw_infos": [],
|
||||
"previous_proposer": "",
|
||||
"outstanding_rewards": [],
|
||||
"validator_accumulated_commissions": [],
|
||||
"validator_historical_rewards": [],
|
||||
"validator_current_rewards": [],
|
||||
"delegator_starting_infos": [],
|
||||
"validator_slash_events": []
|
||||
},
|
||||
"params": null,
|
||||
"gov": {
|
||||
"starting_proposal_id": "1",
|
||||
"deposits": null,
|
||||
@ -54,12 +61,96 @@
|
||||
"veto": "0.334000000000000000"
|
||||
}
|
||||
},
|
||||
"slashing": {
|
||||
"params": {
|
||||
"signed_blocks_window": "100",
|
||||
"min_signed_per_window": "0.500000000000000000",
|
||||
"downtime_jail_duration": "600000000000",
|
||||
"slash_fraction_double_sign": "0.050000000000000000",
|
||||
"slash_fraction_downtime": "0.010000000000000000"
|
||||
},
|
||||
"signing_infos": {},
|
||||
"missed_blocks": {}
|
||||
},
|
||||
"supply": {
|
||||
"supply": []
|
||||
},
|
||||
"wasm": {
|
||||
"codes": null,
|
||||
"contracts": null
|
||||
},
|
||||
"mint": {
|
||||
"minter": {
|
||||
"inflation": "0.130000000000000000",
|
||||
"annual_provisions": "0.000000000000000000"
|
||||
},
|
||||
"params": {
|
||||
"mint_denom": "ustake",
|
||||
"inflation_rate_change": "0.130000000000000000",
|
||||
"inflation_max": "0.200000000000000000",
|
||||
"inflation_min": "0.070000000000000000",
|
||||
"goal_bonded": "0.670000000000000000",
|
||||
"blocks_per_year": "6311520"
|
||||
}
|
||||
},
|
||||
"genutil": {
|
||||
"gentxs": [
|
||||
{
|
||||
"type": "cosmos-sdk/StdTx",
|
||||
"value": {
|
||||
"msg": [
|
||||
{
|
||||
"type": "cosmos-sdk/MsgCreateValidator",
|
||||
"value": {
|
||||
"description": {
|
||||
"moniker": "testing",
|
||||
"identity": "",
|
||||
"website": "",
|
||||
"security_contact": "",
|
||||
"details": ""
|
||||
},
|
||||
"commission": {
|
||||
"rate": "0.100000000000000000",
|
||||
"max_rate": "0.200000000000000000",
|
||||
"max_change_rate": "0.010000000000000000"
|
||||
},
|
||||
"min_self_delegation": "1",
|
||||
"delegator_address": "cosmos1wreev8h6a75z9zdde7cmxv4fdz75appy7h5wvg",
|
||||
"validator_address": "cosmosvaloper1wreev8h6a75z9zdde7cmxv4fdz75appymrqmqm",
|
||||
"pubkey": "cosmosvalconspub1zcjduepq0hlq4z5lt56ly07u79w3v3m9g59ms0kk7lykn5qvn48267s899hsdtxe88",
|
||||
"value": {
|
||||
"denom": "ustake",
|
||||
"amount": "250000000"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"fee": {
|
||||
"amount": [],
|
||||
"gas": "200000"
|
||||
},
|
||||
"signatures": [
|
||||
{
|
||||
"pub_key": {
|
||||
"type": "tendermint/PubKeySecp256k1",
|
||||
"value": "AjiLD/neb68jAuQI6XAeGfHf9xWz0k05QxVCJtHh2JCQ"
|
||||
},
|
||||
"signature": "+jsUfDU6Ji7li432ryDyVA3GBh82FQN8ufGuX9As+PptSmY8twa2sRD683dglBdq7DBSfxYQ4wSHU7zdzWmp6A=="
|
||||
}
|
||||
],
|
||||
"memo": "67289558533ad6df13f96bfb7c8ae44b457a919a@172.17.0.3:26656"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"evidence": {
|
||||
"params": {
|
||||
"max_evidence_age": "120000000000"
|
||||
},
|
||||
"evidence": []
|
||||
},
|
||||
"params": null,
|
||||
"upgrade": {},
|
||||
"staking": {
|
||||
"params": {
|
||||
"unbonding_time": "1814400000000000",
|
||||
@ -76,35 +167,6 @@
|
||||
"redelegations": null,
|
||||
"exported": false
|
||||
},
|
||||
"distribution": {
|
||||
"params": {
|
||||
"community_tax": "0.020000000000000000",
|
||||
"base_proposer_reward": "0.010000000000000000",
|
||||
"bonus_proposer_reward": "0.040000000000000000",
|
||||
"withdraw_addr_enabled": true
|
||||
},
|
||||
"fee_pool": {
|
||||
"community_pool": []
|
||||
},
|
||||
"delegator_withdraw_infos": [],
|
||||
"previous_proposer": "",
|
||||
"outstanding_rewards": [],
|
||||
"validator_accumulated_commissions": [],
|
||||
"validator_historical_rewards": [],
|
||||
"validator_current_rewards": [],
|
||||
"delegator_starting_infos": [],
|
||||
"validator_slash_events": []
|
||||
},
|
||||
"bank": {
|
||||
"send_enabled": true
|
||||
},
|
||||
"crisis": {
|
||||
"constant_fee": {
|
||||
"denom": "ustake",
|
||||
"amount": "1000"
|
||||
}
|
||||
},
|
||||
"upgrade": {},
|
||||
"auth": {
|
||||
"params": {
|
||||
"max_memo_characters": "256",
|
||||
@ -117,7 +179,7 @@
|
||||
{
|
||||
"type": "cosmos-sdk/Account",
|
||||
"value": {
|
||||
"address": "cosmos1q7glt5peka2zgd8ucnfsxeqkwkffhccwx4ch6w",
|
||||
"address": "cosmos1wreev8h6a75z9zdde7cmxv4fdz75appy7h5wvg",
|
||||
"coins": [
|
||||
{
|
||||
"denom": "ucosm",
|
||||
@ -151,79 +213,36 @@
|
||||
"account_number": 0,
|
||||
"sequence": 0
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"mint": {
|
||||
"minter": {
|
||||
"inflation": "0.130000000000000000",
|
||||
"annual_provisions": "0.000000000000000000"
|
||||
},
|
||||
"params": {
|
||||
"mint_denom": "ustake",
|
||||
"inflation_rate_change": "0.130000000000000000",
|
||||
"inflation_max": "0.200000000000000000",
|
||||
"inflation_min": "0.070000000000000000",
|
||||
"goal_bonded": "0.670000000000000000",
|
||||
"blocks_per_year": "6311520"
|
||||
}
|
||||
},
|
||||
"wasm": {
|
||||
"codes": null,
|
||||
"contracts": null
|
||||
},
|
||||
"supply": {
|
||||
"supply": []
|
||||
},
|
||||
"genutil": {
|
||||
"gentxs": [
|
||||
},
|
||||
{
|
||||
"type": "cosmos-sdk/StdTx",
|
||||
"type": "cosmos-sdk/Account",
|
||||
"value": {
|
||||
"msg": [
|
||||
"address": "cosmos1cjsxept9rkggzxztslae9ndgpdyt2408lk850u",
|
||||
"coins": [
|
||||
{
|
||||
"type": "cosmos-sdk/MsgCreateValidator",
|
||||
"value": {
|
||||
"description": {
|
||||
"moniker": "testing",
|
||||
"identity": "",
|
||||
"website": "",
|
||||
"security_contact": "",
|
||||
"details": ""
|
||||
},
|
||||
"commission": {
|
||||
"rate": "0.100000000000000000",
|
||||
"max_rate": "0.200000000000000000",
|
||||
"max_change_rate": "0.010000000000000000"
|
||||
},
|
||||
"min_self_delegation": "1",
|
||||
"delegator_address": "cosmos1q7glt5peka2zgd8ucnfsxeqkwkffhccwx4ch6w",
|
||||
"validator_address": "cosmosvaloper1q7glt5peka2zgd8ucnfsxeqkwkffhccwrpvzka",
|
||||
"pubkey": "cosmosvalconspub1zcjduepqkhus4g994x0fwrgxrrq963xqughksvk0s3wwjm5whze07cnnm0dqlqy6p9",
|
||||
"value": {
|
||||
"denom": "ustake",
|
||||
"amount": "250000000"
|
||||
}
|
||||
}
|
||||
"denom": "ucosm",
|
||||
"amount": "1000000000"
|
||||
},
|
||||
{
|
||||
"denom": "ustake",
|
||||
"amount": "1000000000"
|
||||
}
|
||||
],
|
||||
"fee": {
|
||||
"amount": [],
|
||||
"gas": "200000"
|
||||
},
|
||||
"signatures": [
|
||||
{
|
||||
"pub_key": {
|
||||
"type": "tendermint/PubKeySecp256k1",
|
||||
"value": "AjOaR16Vw2ojZoNgD+D2/vteeFigwiWY0SgXeQVaPpKH"
|
||||
},
|
||||
"signature": "zUsE2Gx9zO8SmeUg2zTgPJMzqd7ie3DyR3MmOFJh3RtHEWfKPBG4ZNRUtcDPkD+2aAX/UDVYnzZv+J1z9FBUKA=="
|
||||
}
|
||||
],
|
||||
"memo": "c40ec95e305b18861b32f69c11e2d0236d01c9e8@172.17.0.3:26656"
|
||||
"public_key": "",
|
||||
"account_number": 0,
|
||||
"sequence": 0
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"crisis": {
|
||||
"constant_fee": {
|
||||
"denom": "ustake",
|
||||
"amount": "1000"
|
||||
}
|
||||
},
|
||||
"bank": {
|
||||
"send_enabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
{"type":"cosmos-sdk/StdTx","value":{"msg":[{"type":"cosmos-sdk/MsgCreateValidator","value":{"description":{"moniker":"testing","identity":"","website":"","security_contact":"","details":""},"commission":{"rate":"0.100000000000000000","max_rate":"0.200000000000000000","max_change_rate":"0.010000000000000000"},"min_self_delegation":"1","delegator_address":"cosmos1wreev8h6a75z9zdde7cmxv4fdz75appy7h5wvg","validator_address":"cosmosvaloper1wreev8h6a75z9zdde7cmxv4fdz75appymrqmqm","pubkey":"cosmosvalconspub1zcjduepq0hlq4z5lt56ly07u79w3v3m9g59ms0kk7lykn5qvn48267s899hsdtxe88","value":{"denom":"ustake","amount":"250000000"}}}],"fee":{"amount":[],"gas":"200000"},"signatures":[{"pub_key":{"type":"tendermint/PubKeySecp256k1","value":"AjiLD/neb68jAuQI6XAeGfHf9xWz0k05QxVCJtHh2JCQ"},"signature":"+jsUfDU6Ji7li432ryDyVA3GBh82FQN8ufGuX9As+PptSmY8twa2sRD683dglBdq7DBSfxYQ4wSHU7zdzWmp6A=="}],"memo":"67289558533ad6df13f96bfb7c8ae44b457a919a@172.17.0.3:26656"}}
|
||||
@ -1 +0,0 @@
|
||||
{"type":"cosmos-sdk/StdTx","value":{"msg":[{"type":"cosmos-sdk/MsgCreateValidator","value":{"description":{"moniker":"testing","identity":"","website":"","security_contact":"","details":""},"commission":{"rate":"0.100000000000000000","max_rate":"0.200000000000000000","max_change_rate":"0.010000000000000000"},"min_self_delegation":"1","delegator_address":"cosmos1q7glt5peka2zgd8ucnfsxeqkwkffhccwx4ch6w","validator_address":"cosmosvaloper1q7glt5peka2zgd8ucnfsxeqkwkffhccwrpvzka","pubkey":"cosmosvalconspub1zcjduepqkhus4g994x0fwrgxrrq963xqughksvk0s3wwjm5whze07cnnm0dqlqy6p9","value":{"denom":"ustake","amount":"250000000"}}}],"fee":{"amount":[],"gas":"200000"},"signatures":[{"pub_key":{"type":"tendermint/PubKeySecp256k1","value":"AjOaR16Vw2ojZoNgD+D2/vteeFigwiWY0SgXeQVaPpKH"},"signature":"zUsE2Gx9zO8SmeUg2zTgPJMzqd7ie3DyR3MmOFJh3RtHEWfKPBG4ZNRUtcDPkD+2aAX/UDVYnzZv+J1z9FBUKA=="}],"memo":"c40ec95e305b18861b32f69c11e2d0236d01c9e8@172.17.0.3:26656"}}
|
||||
@ -1 +1 @@
|
||||
{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"G0VvywcXFSI5HASlbKRK/vAI2NNolDw1P/2fgWtfva/P8L9yiw2luZfu6cKbijEg/op2lOqV3CbfMo+B1P6G3w=="}}
|
||||
{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"i42pVrwetpGZFC78UUNhL6Bk41/N3sKDW9XKNz+IOm/JX5aN10vUrpA52DXOQNug55lTvTyuPR8izLSBcovIrg=="}}
|
||||
@ -1,11 +1,11 @@
|
||||
{
|
||||
"address": "9CBD80593D47022DFE9A0356F350A4D233E92AEB",
|
||||
"address": "3FBF50B72FE062495F150AEB78D1981E7DAEBE60",
|
||||
"pub_key": {
|
||||
"type": "tendermint/PubKeyEd25519",
|
||||
"value": "tfkKoKWpnpcNBhjAXUTA4i9oMs+EXOlujriy/2Jz29o="
|
||||
"value": "ff4Kip9dNfI/3PFdFkdlRQu4Ptb3yWnQDJ1OrXoHKW8="
|
||||
},
|
||||
"priv_key": {
|
||||
"type": "tendermint/PrivKeyEd25519",
|
||||
"value": "NkIf2Dije6K8xOqZ7ni+f3+TDjuOrV5Q68g0coD8j6O1+Qqgpamelw0GGMBdRMDiL2gyz4Rc6W6OuLL/YnPb2g=="
|
||||
"value": "yMKZJArmVw5zXDTHbYR0sNRqugzW3HNbO6yK5bOHYBp9/gqKn1018j/c8V0WR2VFC7g+1vfJadAMnU6tegcpbw=="
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user