Merge pull request #1290 from cosmos/test-MsgCreateValidator
Test and fix MsgCreateValidator and MsgEditValidator
This commit is contained in:
commit
bb5ef035a6
@ -14,6 +14,8 @@ and this project adheres to
|
||||
`anyToSinglePubkey`. Export `anyToSinglePubkey`.
|
||||
- @cosmjs/utils: Add `isDefined` which checks for `undefined` in a
|
||||
TypeScript-friendly way.
|
||||
- @cosmjs/stargate: Add missing `{is,}MsgBeginRedelegateEncodeObject`,
|
||||
`{is,MsgCreateValidatorEncodeObject}` and `{is,MsgEditValidatorEncodeObject}`.
|
||||
|
||||
### Fixed
|
||||
|
||||
@ -22,9 +24,14 @@ and this project adheres to
|
||||
`CosmWasmClient.queryContractSmart`, `SigningCosmWasmClient.instantiate`,
|
||||
`SigningCosmWasmClient.migrate`, `SigningCosmWasmClient.execute`). This
|
||||
reverts the type change done in CosmJS 0.23.0. ([#1281], [#1284])
|
||||
- @cosmjs/cosmwasm-stargate: `AminoMsgCreateValidator` and
|
||||
`createStakingAminoConverters` were fixed after testing both
|
||||
`MsgCreateValidator` and `MsgEditValidator` in sign mode direct and Amino JSON
|
||||
([#1290]).
|
||||
|
||||
[#1281]: https://github.com/cosmos/cosmjs/pull/1281
|
||||
[#1284]: https://github.com/cosmos/cosmjs/pull/1284
|
||||
[#1290]: https://github.com/cosmos/cosmjs/pull/1290
|
||||
|
||||
## [0.29.1] - 2022-10-09
|
||||
|
||||
|
||||
@ -61,8 +61,11 @@ export {
|
||||
isAminoMsgVoteWeighted,
|
||||
isAminoMsgWithdrawDelegatorReward,
|
||||
isAminoMsgWithdrawValidatorCommission,
|
||||
isMsgBeginRedelegateEncodeObject,
|
||||
isMsgCreateValidatorEncodeObject,
|
||||
isMsgDelegateEncodeObject,
|
||||
isMsgDepositEncodeObject,
|
||||
isMsgEditValidatorEncodeObject,
|
||||
isMsgSendEncodeObject,
|
||||
isMsgSubmitProposalEncodeObject,
|
||||
isMsgTransferEncodeObject,
|
||||
@ -72,8 +75,11 @@ export {
|
||||
isMsgWithdrawDelegatorRewardEncodeObject,
|
||||
MintExtension,
|
||||
MintParams,
|
||||
MsgBeginRedelegateEncodeObject,
|
||||
MsgCreateValidatorEncodeObject,
|
||||
MsgDelegateEncodeObject,
|
||||
MsgDepositEncodeObject,
|
||||
MsgEditValidatorEncodeObject,
|
||||
MsgSendEncodeObject,
|
||||
MsgSubmitProposalEncodeObject,
|
||||
MsgTransferEncodeObject,
|
||||
|
||||
@ -84,9 +84,15 @@ export {
|
||||
isAminoMsgUndelegate,
|
||||
} from "./staking/aminomessages";
|
||||
export {
|
||||
isMsgBeginRedelegateEncodeObject,
|
||||
isMsgCreateValidatorEncodeObject,
|
||||
isMsgDelegateEncodeObject,
|
||||
isMsgEditValidatorEncodeObject,
|
||||
isMsgUndelegateEncodeObject,
|
||||
MsgBeginRedelegateEncodeObject,
|
||||
MsgCreateValidatorEncodeObject,
|
||||
MsgDelegateEncodeObject,
|
||||
MsgEditValidatorEncodeObject,
|
||||
MsgUndelegateEncodeObject,
|
||||
stakingTypes,
|
||||
} from "./staking/messages";
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import { encodeBech32Pubkey } from "@cosmjs/amino";
|
||||
import { fromBase64 } from "@cosmjs/encoding";
|
||||
import { coin } from "@cosmjs/proto-signing";
|
||||
import { PubKey as CosmosCryptoSecp256k1Pubkey } from "cosmjs-types/cosmos/crypto/secp256k1/keys";
|
||||
import {
|
||||
MsgBeginRedelegate,
|
||||
MsgCreateValidator,
|
||||
@ -56,16 +56,22 @@ describe("AminoTypes", () => {
|
||||
details: "...",
|
||||
},
|
||||
commission: {
|
||||
rate: "0.2",
|
||||
maxRate: "0.3",
|
||||
maxChangeRate: "0.1",
|
||||
rate: "200000000000000000", // 0.2
|
||||
maxRate: "300000000000000000", // 0.3
|
||||
maxChangeRate: "100000000000000000", // 0.1
|
||||
},
|
||||
minSelfDelegation: "123",
|
||||
delegatorAddress: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6",
|
||||
validatorAddress: "cosmos10dyr9899g6t0pelew4nvf4j5c3jcgv0r73qga5",
|
||||
pubkey: {
|
||||
typeUrl: "/cosmos.crypto.secp256k1.PubKey",
|
||||
value: fromBase64("A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ"),
|
||||
value: Uint8Array.from(
|
||||
CosmosCryptoSecp256k1Pubkey.encode(
|
||||
CosmosCryptoSecp256k1Pubkey.fromPartial({
|
||||
key: fromBase64("A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ"),
|
||||
}),
|
||||
).finish(),
|
||||
),
|
||||
},
|
||||
value: coin(1234, "ucosm"),
|
||||
};
|
||||
@ -85,17 +91,17 @@ describe("AminoTypes", () => {
|
||||
details: "...",
|
||||
},
|
||||
commission: {
|
||||
rate: "0.2",
|
||||
max_rate: "0.3",
|
||||
max_change_rate: "0.1",
|
||||
rate: "0.200000000000000000",
|
||||
max_rate: "0.300000000000000000",
|
||||
max_change_rate: "0.100000000000000000",
|
||||
},
|
||||
min_self_delegation: "123",
|
||||
delegator_address: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6",
|
||||
validator_address: "cosmos10dyr9899g6t0pelew4nvf4j5c3jcgv0r73qga5",
|
||||
pubkey: encodeBech32Pubkey(
|
||||
{ type: "tendermint/PubKeySecp256k1", value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ" },
|
||||
"cosmos",
|
||||
),
|
||||
pubkey: {
|
||||
type: "tendermint/PubKeySecp256k1",
|
||||
value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ",
|
||||
},
|
||||
value: coin(1234, "ucosm"),
|
||||
},
|
||||
};
|
||||
@ -133,7 +139,7 @@ describe("AminoTypes", () => {
|
||||
securityContact: "Hamburglar",
|
||||
details: "...",
|
||||
},
|
||||
commissionRate: "0.2",
|
||||
commissionRate: "21000000000000000", // 0.021
|
||||
minSelfDelegation: "123",
|
||||
validatorAddress: "cosmos10dyr9899g6t0pelew4nvf4j5c3jcgv0r73qga5",
|
||||
};
|
||||
@ -152,7 +158,7 @@ describe("AminoTypes", () => {
|
||||
security_contact: "Hamburglar",
|
||||
details: "...",
|
||||
},
|
||||
commission_rate: "0.2",
|
||||
commission_rate: "0.021000000000000000",
|
||||
min_self_delegation: "123",
|
||||
validator_address: "cosmos10dyr9899g6t0pelew4nvf4j5c3jcgv0r73qga5",
|
||||
},
|
||||
@ -219,17 +225,17 @@ describe("AminoTypes", () => {
|
||||
details: "...",
|
||||
},
|
||||
commission: {
|
||||
rate: "0.2",
|
||||
max_rate: "0.3",
|
||||
max_change_rate: "0.1",
|
||||
rate: "0.200000000000000000",
|
||||
max_rate: "0.300000000000000000",
|
||||
max_change_rate: "0.100000000000000000",
|
||||
},
|
||||
min_self_delegation: "123",
|
||||
delegator_address: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6",
|
||||
validator_address: "cosmos10dyr9899g6t0pelew4nvf4j5c3jcgv0r73qga5",
|
||||
pubkey: encodeBech32Pubkey(
|
||||
{ type: "tendermint/PubKeySecp256k1", value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ" },
|
||||
"cosmos",
|
||||
),
|
||||
pubkey: {
|
||||
type: "tendermint/PubKeySecp256k1",
|
||||
value: "A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ",
|
||||
},
|
||||
value: coin(1234, "ucosm"),
|
||||
},
|
||||
};
|
||||
@ -243,16 +249,22 @@ describe("AminoTypes", () => {
|
||||
details: "...",
|
||||
},
|
||||
commission: {
|
||||
rate: "0.2",
|
||||
maxRate: "0.3",
|
||||
maxChangeRate: "0.1",
|
||||
rate: "200000000000000000", // 0.2
|
||||
maxRate: "300000000000000000", // 0.3
|
||||
maxChangeRate: "100000000000000000", // 0.1
|
||||
},
|
||||
minSelfDelegation: "123",
|
||||
delegatorAddress: "cosmos1pkptre7fdkl6gfrzlesjjvhxhlc3r4gmmk8rs6",
|
||||
validatorAddress: "cosmos10dyr9899g6t0pelew4nvf4j5c3jcgv0r73qga5",
|
||||
pubkey: {
|
||||
typeUrl: "/cosmos.crypto.secp256k1.PubKey",
|
||||
value: fromBase64("A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ"),
|
||||
value: Uint8Array.from(
|
||||
CosmosCryptoSecp256k1Pubkey.encode(
|
||||
CosmosCryptoSecp256k1Pubkey.fromPartial({
|
||||
key: fromBase64("A08EGB7ro1ORuFhjOnZcSgwYlpe0DSFjVNUIkNNQxwKQ"),
|
||||
}),
|
||||
).finish(),
|
||||
),
|
||||
},
|
||||
value: coin(1234, "ucosm"),
|
||||
};
|
||||
@ -294,7 +306,7 @@ describe("AminoTypes", () => {
|
||||
security_contact: "Hamburglar",
|
||||
details: "...",
|
||||
},
|
||||
commission_rate: "0.2",
|
||||
commission_rate: "0.050000000000000000", // 0.05
|
||||
min_self_delegation: "123",
|
||||
validator_address: "cosmos10dyr9899g6t0pelew4nvf4j5c3jcgv0r73qga5",
|
||||
},
|
||||
@ -308,7 +320,7 @@ describe("AminoTypes", () => {
|
||||
securityContact: "Hamburglar",
|
||||
details: "...",
|
||||
},
|
||||
commissionRate: "0.2",
|
||||
commissionRate: "50000000000000000", // 0.05
|
||||
minSelfDelegation: "123",
|
||||
validatorAddress: "cosmos10dyr9899g6t0pelew4nvf4j5c3jcgv0r73qga5",
|
||||
};
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import { AminoMsg, Coin, decodeBech32Pubkey, encodeBech32Pubkey } from "@cosmjs/amino";
|
||||
import { fromBase64, toBase64 } from "@cosmjs/encoding";
|
||||
import { AminoMsg, Coin, Pubkey } from "@cosmjs/amino";
|
||||
import { Decimal } from "@cosmjs/math";
|
||||
import { anyToSinglePubkey, encodePubkey } from "@cosmjs/proto-signing";
|
||||
import { assertDefinedAndNotNull } from "@cosmjs/utils";
|
||||
import {
|
||||
MsgBeginRedelegate,
|
||||
@ -28,6 +29,17 @@ interface Description {
|
||||
readonly details: string;
|
||||
}
|
||||
|
||||
function protoDecimalToJson(decimal: string): string {
|
||||
const parsed = Decimal.fromAtomics(decimal, 18);
|
||||
const [whole, fractional] = parsed.toString().split(".");
|
||||
return `${whole}.${fractional.padEnd(18, "0")}`;
|
||||
}
|
||||
|
||||
function jsonDecimalToProto(decimal: string): string {
|
||||
const parsed = Decimal.fromUserInput(decimal, 18);
|
||||
return parsed.atomics;
|
||||
}
|
||||
|
||||
/** Creates a new validator. */
|
||||
export interface AminoMsgCreateValidator extends AminoMsg {
|
||||
readonly type: "cosmos-sdk/MsgCreateValidator";
|
||||
@ -39,8 +51,8 @@ export interface AminoMsgCreateValidator extends AminoMsg {
|
||||
readonly delegator_address: string;
|
||||
/** Bech32 encoded validator address */
|
||||
readonly validator_address: string;
|
||||
/** Bech32 encoded public key */
|
||||
readonly pubkey: string;
|
||||
/** Public key */
|
||||
readonly pubkey: Pubkey;
|
||||
readonly value: Coin;
|
||||
};
|
||||
}
|
||||
@ -120,7 +132,7 @@ export function isAminoMsgUndelegate(msg: AminoMsg): msg is AminoMsgUndelegate {
|
||||
}
|
||||
|
||||
export function createStakingAminoConverters(
|
||||
prefix: string,
|
||||
_prefix: string,
|
||||
): Record<string, AminoConverter | "not_supported_by_chain"> {
|
||||
return {
|
||||
"/cosmos.staking.v1beta1.MsgBeginRedelegate": {
|
||||
@ -175,20 +187,14 @@ export function createStakingAminoConverters(
|
||||
details: description.details,
|
||||
},
|
||||
commission: {
|
||||
rate: commission.rate,
|
||||
max_rate: commission.maxRate,
|
||||
max_change_rate: commission.maxChangeRate,
|
||||
rate: protoDecimalToJson(commission.rate),
|
||||
max_rate: protoDecimalToJson(commission.maxRate),
|
||||
max_change_rate: protoDecimalToJson(commission.maxChangeRate),
|
||||
},
|
||||
min_self_delegation: minSelfDelegation,
|
||||
delegator_address: delegatorAddress,
|
||||
validator_address: validatorAddress,
|
||||
pubkey: encodeBech32Pubkey(
|
||||
{
|
||||
type: "tendermint/PubKeySecp256k1",
|
||||
value: toBase64(pubkey.value),
|
||||
},
|
||||
prefix,
|
||||
),
|
||||
pubkey: anyToSinglePubkey(pubkey),
|
||||
value: value,
|
||||
};
|
||||
},
|
||||
@ -201,10 +207,6 @@ export function createStakingAminoConverters(
|
||||
pubkey,
|
||||
value,
|
||||
}: AminoMsgCreateValidator["value"]): MsgCreateValidator => {
|
||||
const decodedPubkey = decodeBech32Pubkey(pubkey);
|
||||
if (decodedPubkey.type !== "tendermint/PubKeySecp256k1") {
|
||||
throw new Error("Only Secp256k1 public keys are supported");
|
||||
}
|
||||
return {
|
||||
description: {
|
||||
moniker: description.moniker,
|
||||
@ -214,17 +216,14 @@ export function createStakingAminoConverters(
|
||||
details: description.details,
|
||||
},
|
||||
commission: {
|
||||
rate: commission.rate,
|
||||
maxRate: commission.max_rate,
|
||||
maxChangeRate: commission.max_change_rate,
|
||||
rate: jsonDecimalToProto(commission.rate),
|
||||
maxRate: jsonDecimalToProto(commission.max_rate),
|
||||
maxChangeRate: jsonDecimalToProto(commission.max_change_rate),
|
||||
},
|
||||
minSelfDelegation: min_self_delegation,
|
||||
delegatorAddress: delegator_address,
|
||||
validatorAddress: validator_address,
|
||||
pubkey: {
|
||||
typeUrl: "/cosmos.crypto.secp256k1.PubKey",
|
||||
value: fromBase64(decodedPubkey.value),
|
||||
},
|
||||
pubkey: encodePubkey(pubkey),
|
||||
value: value,
|
||||
};
|
||||
},
|
||||
@ -266,7 +265,7 @@ export function createStakingAminoConverters(
|
||||
security_contact: description.securityContact,
|
||||
details: description.details,
|
||||
},
|
||||
commission_rate: commissionRate,
|
||||
commission_rate: protoDecimalToJson(commissionRate),
|
||||
min_self_delegation: minSelfDelegation,
|
||||
validator_address: validatorAddress,
|
||||
};
|
||||
@ -284,7 +283,7 @@ export function createStakingAminoConverters(
|
||||
securityContact: description.security_contact,
|
||||
details: description.details,
|
||||
},
|
||||
commissionRate: commission_rate,
|
||||
commissionRate: jsonDecimalToProto(commission_rate),
|
||||
minSelfDelegation: min_self_delegation,
|
||||
validatorAddress: validator_address,
|
||||
}),
|
||||
|
||||
289
packages/stargate/src/modules/staking/messages.spec.ts
Normal file
289
packages/stargate/src/modules/staking/messages.spec.ts
Normal file
@ -0,0 +1,289 @@
|
||||
import { coin, Secp256k1HdWallet } from "@cosmjs/amino";
|
||||
import { Random } from "@cosmjs/crypto";
|
||||
import { fromBech32, toBase64, toBech32 } from "@cosmjs/encoding";
|
||||
import { DirectSecp256k1HdWallet, encodePubkey } from "@cosmjs/proto-signing";
|
||||
|
||||
import { calculateFee } from "../../fee";
|
||||
import { SigningStargateClient } from "../../signingstargateclient";
|
||||
import { assertIsDeliverTxFailure, assertIsDeliverTxSuccess } from "../../stargateclient";
|
||||
import {
|
||||
defaultGasPrice,
|
||||
defaultSigningClientOptions,
|
||||
faucet,
|
||||
pendingWithoutSimapp,
|
||||
simapp,
|
||||
} from "../../testutils.spec";
|
||||
import { MsgCreateValidatorEncodeObject, MsgEditValidatorEncodeObject } from "./messages";
|
||||
|
||||
function changePrefix(address: string, newPrefix: string): string {
|
||||
return toBech32(newPrefix, fromBech32(address).data);
|
||||
}
|
||||
|
||||
async function sendFeeAndStakingTokens(address: string): Promise<void> {
|
||||
const wallet = await DirectSecp256k1HdWallet.fromMnemonic(faucet.mnemonic);
|
||||
const [firstAccount] = await wallet.getAccounts();
|
||||
const client = await SigningStargateClient.connectWithSigner(
|
||||
simapp.tendermintUrl,
|
||||
wallet,
|
||||
defaultSigningClientOptions,
|
||||
);
|
||||
|
||||
const res = await client.sendTokens(
|
||||
firstAccount.address,
|
||||
address,
|
||||
[coin(11000, simapp.denomFee), coin(28, simapp.denomStaking)],
|
||||
"auto",
|
||||
);
|
||||
assertIsDeliverTxSuccess(res);
|
||||
client.disconnect();
|
||||
}
|
||||
|
||||
describe("staking messages", () => {
|
||||
const createFee = calculateFee(200_000, defaultGasPrice);
|
||||
const editFee = calculateFee(200_000, defaultGasPrice);
|
||||
|
||||
describe("MsgCreateValidator", () => {
|
||||
it("works", async () => {
|
||||
pendingWithoutSimapp();
|
||||
|
||||
const valWallet = await DirectSecp256k1HdWallet.generate();
|
||||
const [valAccount] = await valWallet.getAccounts();
|
||||
|
||||
await sendFeeAndStakingTokens(valAccount.address);
|
||||
|
||||
const client = await SigningStargateClient.connectWithSigner(
|
||||
simapp.tendermintUrl,
|
||||
valWallet,
|
||||
defaultSigningClientOptions,
|
||||
);
|
||||
|
||||
const createMsg: MsgCreateValidatorEncodeObject = {
|
||||
typeUrl: "/cosmos.staking.v1beta1.MsgCreateValidator",
|
||||
value: {
|
||||
description: {
|
||||
moniker: "That's me",
|
||||
identity: "AABB1234",
|
||||
website: "http://example.com/me",
|
||||
details: "What should I write?",
|
||||
securityContact: "DM on Twitter",
|
||||
},
|
||||
commission: {
|
||||
maxChangeRate: "10000000000000000", // 0.01
|
||||
maxRate: "200000000000000000", // 0.2
|
||||
rate: "100000000000000000", // 0.1
|
||||
},
|
||||
minSelfDelegation: "1",
|
||||
// Those two addresses need to be the same with different prefix 🤷♂️
|
||||
delegatorAddress: valAccount.address,
|
||||
validatorAddress: changePrefix(valAccount.address, "cosmosvaloper"),
|
||||
pubkey: encodePubkey({
|
||||
type: "tendermint/PubKeyEd25519",
|
||||
value: toBase64(Random.getBytes(32)),
|
||||
}),
|
||||
value: {
|
||||
amount: "1",
|
||||
denom: simapp.denomStaking,
|
||||
},
|
||||
},
|
||||
};
|
||||
const result = await client.signAndBroadcast(valAccount.address, [createMsg], createFee);
|
||||
|
||||
assertIsDeliverTxSuccess(result);
|
||||
|
||||
client.disconnect();
|
||||
});
|
||||
|
||||
it("works with Amino JSON sign mode", async () => {
|
||||
pendingWithoutSimapp();
|
||||
|
||||
const valWallet = await Secp256k1HdWallet.generate();
|
||||
const [valAccount] = await valWallet.getAccounts();
|
||||
|
||||
await sendFeeAndStakingTokens(valAccount.address);
|
||||
|
||||
const client = await SigningStargateClient.connectWithSigner(
|
||||
simapp.tendermintUrl,
|
||||
valWallet,
|
||||
defaultSigningClientOptions,
|
||||
);
|
||||
|
||||
const createMsg: MsgCreateValidatorEncodeObject = {
|
||||
typeUrl: "/cosmos.staking.v1beta1.MsgCreateValidator",
|
||||
value: {
|
||||
description: {
|
||||
moniker: "That's me",
|
||||
identity: "AABB1234",
|
||||
website: "http://example.com/me",
|
||||
details: "What should I write?",
|
||||
securityContact: "DM on Twitter",
|
||||
},
|
||||
commission: {
|
||||
maxChangeRate: "10000000000000000", // 0.01
|
||||
maxRate: "200000000000000000", // 0.2
|
||||
rate: "100000000000000000", // 0.1
|
||||
},
|
||||
minSelfDelegation: "1",
|
||||
// Those two addresses need to be the same with different prefix 🤷♂️
|
||||
delegatorAddress: valAccount.address,
|
||||
validatorAddress: changePrefix(valAccount.address, "cosmosvaloper"),
|
||||
pubkey: encodePubkey({
|
||||
type: "tendermint/PubKeyEd25519",
|
||||
value: toBase64(Random.getBytes(32)),
|
||||
}),
|
||||
value: {
|
||||
amount: "1",
|
||||
denom: simapp.denomStaking,
|
||||
},
|
||||
},
|
||||
};
|
||||
const result = await client.signAndBroadcast(valAccount.address, [createMsg], createFee);
|
||||
|
||||
assertIsDeliverTxSuccess(result);
|
||||
|
||||
client.disconnect();
|
||||
});
|
||||
});
|
||||
|
||||
describe("MsgEditValidator", () => {
|
||||
it("works", async () => {
|
||||
pendingWithoutSimapp();
|
||||
|
||||
const valWallet = await DirectSecp256k1HdWallet.generate();
|
||||
const [valAccount] = await valWallet.getAccounts();
|
||||
|
||||
await sendFeeAndStakingTokens(valAccount.address);
|
||||
|
||||
const client = await SigningStargateClient.connectWithSigner(
|
||||
simapp.tendermintUrl,
|
||||
valWallet,
|
||||
defaultSigningClientOptions,
|
||||
);
|
||||
|
||||
const createMsg: MsgCreateValidatorEncodeObject = {
|
||||
typeUrl: "/cosmos.staking.v1beta1.MsgCreateValidator",
|
||||
value: {
|
||||
description: {
|
||||
moniker: "That's me",
|
||||
identity: "AABB1234",
|
||||
website: "http://example.com/me",
|
||||
details: "What should I write?",
|
||||
securityContact: "DM on Twitter",
|
||||
},
|
||||
commission: {
|
||||
maxChangeRate: "10000000000000000", // 0.01
|
||||
maxRate: "200000000000000000", // 0.2
|
||||
rate: "100000000000000000", // 0.1
|
||||
},
|
||||
minSelfDelegation: "1",
|
||||
// Those two addresses need to be the same with different prefix 🤷♂️
|
||||
delegatorAddress: valAccount.address,
|
||||
validatorAddress: changePrefix(valAccount.address, "cosmosvaloper"),
|
||||
pubkey: encodePubkey({
|
||||
type: "tendermint/PubKeyEd25519",
|
||||
value: toBase64(Random.getBytes(32)),
|
||||
}),
|
||||
value: {
|
||||
amount: "1",
|
||||
denom: simapp.denomStaking,
|
||||
},
|
||||
},
|
||||
};
|
||||
const result = await client.signAndBroadcast(valAccount.address, [createMsg], createFee);
|
||||
assertIsDeliverTxSuccess(result);
|
||||
|
||||
const editMsg: MsgEditValidatorEncodeObject = {
|
||||
typeUrl: "/cosmos.staking.v1beta1.MsgEditValidator",
|
||||
value: {
|
||||
commissionRate: "100000000000000000", // we cannot change until 24h have passed
|
||||
description: {
|
||||
moniker: "new name",
|
||||
identity: "ZZZZ",
|
||||
website: "http://example.com/new-site",
|
||||
details: "Still no idea",
|
||||
securityContact: "DM on Discord",
|
||||
},
|
||||
minSelfDelegation: "1",
|
||||
validatorAddress: changePrefix(valAccount.address, "cosmosvaloper"), // unchanged
|
||||
},
|
||||
};
|
||||
const editResult = await client.signAndBroadcast(valAccount.address, [editMsg], editFee);
|
||||
|
||||
// Currently we have no way to unset commissionRate, so the DeliverTx is expected to fail
|
||||
// with "commission cannot be changed more than once in 24h" :(
|
||||
assertIsDeliverTxFailure(editResult);
|
||||
|
||||
client.disconnect();
|
||||
});
|
||||
|
||||
it("works with Amino JSON sign mode", async () => {
|
||||
pendingWithoutSimapp();
|
||||
|
||||
const valWallet = await Secp256k1HdWallet.generate();
|
||||
const [valAccount] = await valWallet.getAccounts();
|
||||
|
||||
await sendFeeAndStakingTokens(valAccount.address);
|
||||
|
||||
const client = await SigningStargateClient.connectWithSigner(
|
||||
simapp.tendermintUrl,
|
||||
valWallet,
|
||||
defaultSigningClientOptions,
|
||||
);
|
||||
|
||||
const createMsg: MsgCreateValidatorEncodeObject = {
|
||||
typeUrl: "/cosmos.staking.v1beta1.MsgCreateValidator",
|
||||
value: {
|
||||
description: {
|
||||
moniker: "That's me",
|
||||
identity: "AABB1234",
|
||||
website: "http://example.com/me",
|
||||
details: "What should I write?",
|
||||
securityContact: "DM on Twitter",
|
||||
},
|
||||
commission: {
|
||||
maxChangeRate: "10000000000000000", // 0.01
|
||||
maxRate: "200000000000000000", // 0.2
|
||||
rate: "100000000000000000", // 0.1
|
||||
},
|
||||
minSelfDelegation: "1",
|
||||
// Those two addresses need to be the same with different prefix 🤷♂️
|
||||
delegatorAddress: valAccount.address,
|
||||
validatorAddress: changePrefix(valAccount.address, "cosmosvaloper"),
|
||||
pubkey: encodePubkey({
|
||||
type: "tendermint/PubKeyEd25519",
|
||||
value: toBase64(Random.getBytes(32)),
|
||||
}),
|
||||
value: {
|
||||
amount: "1",
|
||||
denom: simapp.denomStaking,
|
||||
},
|
||||
},
|
||||
};
|
||||
const result = await client.signAndBroadcast(valAccount.address, [createMsg], createFee);
|
||||
assertIsDeliverTxSuccess(result);
|
||||
|
||||
const editMsg: MsgEditValidatorEncodeObject = {
|
||||
typeUrl: "/cosmos.staking.v1beta1.MsgEditValidator",
|
||||
value: {
|
||||
commissionRate: "100000000000000000", // we cannot change until 24h have passed
|
||||
description: {
|
||||
moniker: "new name",
|
||||
identity: "ZZZZ",
|
||||
website: "http://example.com/new-site",
|
||||
details: "Still no idea",
|
||||
securityContact: "DM on Discord",
|
||||
},
|
||||
minSelfDelegation: "1",
|
||||
validatorAddress: changePrefix(valAccount.address, "cosmosvaloper"), // unchanged
|
||||
},
|
||||
};
|
||||
const editResult = await client.signAndBroadcast(valAccount.address, [editMsg], editFee);
|
||||
|
||||
// Currently we have no way to unset commissionRate, so the DeliverTx is expected to fail
|
||||
// with "commission cannot be changed more than once in 24h" :(
|
||||
// assertIsDeliverTxSuccess(editResult);
|
||||
assertIsDeliverTxFailure(editResult);
|
||||
|
||||
client.disconnect();
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -15,6 +15,24 @@ export const stakingTypes: ReadonlyArray<[string, GeneratedType]> = [
|
||||
["/cosmos.staking.v1beta1.MsgUndelegate", MsgUndelegate],
|
||||
];
|
||||
|
||||
export interface MsgBeginRedelegateEncodeObject extends EncodeObject {
|
||||
readonly typeUrl: "/cosmos.staking.v1beta1.MsgBeginRedelegate";
|
||||
readonly value: Partial<MsgBeginRedelegate>;
|
||||
}
|
||||
|
||||
export function isMsgBeginRedelegateEncodeObject(o: EncodeObject): o is MsgBeginRedelegateEncodeObject {
|
||||
return (o as MsgBeginRedelegateEncodeObject).typeUrl === "/cosmos.staking.v1beta1.MsgBeginRedelegate";
|
||||
}
|
||||
|
||||
export interface MsgCreateValidatorEncodeObject extends EncodeObject {
|
||||
readonly typeUrl: "/cosmos.staking.v1beta1.MsgCreateValidator";
|
||||
readonly value: Partial<MsgCreateValidator>;
|
||||
}
|
||||
|
||||
export function isMsgCreateValidatorEncodeObject(o: EncodeObject): o is MsgCreateValidatorEncodeObject {
|
||||
return (o as MsgCreateValidatorEncodeObject).typeUrl === "/cosmos.staking.v1beta1.MsgCreateValidator";
|
||||
}
|
||||
|
||||
export interface MsgDelegateEncodeObject extends EncodeObject {
|
||||
readonly typeUrl: "/cosmos.staking.v1beta1.MsgDelegate";
|
||||
readonly value: Partial<MsgDelegate>;
|
||||
@ -24,6 +42,15 @@ export function isMsgDelegateEncodeObject(object: EncodeObject): object is MsgDe
|
||||
return (object as MsgDelegateEncodeObject).typeUrl === "/cosmos.staking.v1beta1.MsgDelegate";
|
||||
}
|
||||
|
||||
export interface MsgEditValidatorEncodeObject extends EncodeObject {
|
||||
readonly typeUrl: "/cosmos.staking.v1beta1.MsgEditValidator";
|
||||
readonly value: Partial<MsgEditValidator>;
|
||||
}
|
||||
|
||||
export function isMsgEditValidatorEncodeObject(o: EncodeObject): o is MsgEditValidatorEncodeObject {
|
||||
return (o as MsgEditValidatorEncodeObject).typeUrl === "/cosmos.staking.v1beta1.MsgEditValidator";
|
||||
}
|
||||
|
||||
export interface MsgUndelegateEncodeObject extends EncodeObject {
|
||||
readonly typeUrl: "/cosmos.staking.v1beta1.MsgUndelegate";
|
||||
readonly value: Partial<MsgUndelegate>;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user