cosmjs
cosmjs copied to clipboard
Q: How to convert proposerAddress back to bech32
I am trying to convert the proposerAddress
back to bech32 format, but when I do so it doesn't match the validator address showing up on mintscan.
const tendermintClient = await StargateClient.connect('https://osmosis-1.technofractal.com/');
const res = await tendermintClient.tmClient.block(2956000);
const string = Bech32.encode("osmo", res.block.header.proposerAddress);
console.log(string);
This outputs: osmo1arm6ztth2njxndd2cwpg6gt6q79wdfyf26rnjx
, while on mintscan it shows the proposer as Nascent which has address osmo1gxlsy3jmt5aevkmlfh7rnnxrtqzqe4a6wmtafa
. The address I encoded has no tokens either, so I must be doing something wrong.
The proposer address you get from the Tendermint client is derived from an ed25519 Tendermint consensus keypair. Those are the addresses that have "cons" in their bech32 prefix.
You cannot interact with this address on the application level directly. This is why fancy browsers map it to the Cosmos SDK app level addresses for the users because they know both addresses of a validator.
I think you can do the mapping through the /staking/validators list (e.g. https://lcd-osmosis.blockapsis.com/staking/validators) by deriving the Tendermint address from consensus_pubkey
using pubkeyToAddress
from @cosmjs/tendermint-rpc
. You might find a better query API for doing the mapping in packages/stargate/src/queries/staking.ts.
this also worked Since cosmosvaloper address has a consensus pubkey, the consensus address could be gotten from the consensus pubkey this way
import { sha256 } from "@cosmjs/crypto";
import { Bech32, fromBase64 } from "@cosmjs/encoding";
import { encodeBech32Pubkey } from "@cosmjs/launchpad";
const pubkey = {
type: "tendermint/PubKeyEd25519",
value: "w3rKE+tQoLK8G+XPmjn+NszCk07iQ0sWaBbN5hQZcBY=",
};
const ed25519PubkeyRaw = fromBase64(pubkey.value);
const addressData = sha256(ed25519PubkeyRaw).slice(0, 20);
const bech32Address = Bech32.encode(“cosmosvalcons", addressData);
console.log(bech32Address);
The address matches with the proposer hex address when encoded to bech32
Another solution
import { fromBase64, toHex } from "@cosmjs/encoding";
import { decodeBech32Pubkey } from "@cosmjs/launchpad"
Convert the consensus pubkey to valconspub like this
const bech32Pubkey = encodeBech32Pubkey(pubkey, “cosmosvalconspub");
console.log(bech32Pubkey)
Then decode like this
const pubkey = decodeBech32Pubkey(
"cosmosvalconspub1zcjduepqcdav5ylt2zst90qmuh8e5w07xmxv9y6wufp5k9ngzmx7v9qewqtqkcq4z8",
);
const addressData = sha256(fromBase64(pubkey.value)).slice(0, 20);
const address = toHex(addressData).toUpperCase();
console.log(address)
This address here matches the hex proposer address
Here is a full example how to do the mapping via the staking.validators query: https://github.com/noislabs/proposers/blob/f552cf24724f8ab719168a149c7e3109b7606d37/index.ts. The core to produce the mapping from proposer address to operator are those lines: https://github.com/noislabs/proposers/blob/f552cf24724f8ab719168a149c7e3109b7606d37/index.ts#L34-L48