Understanding Maroo Address Formats
Maroo accounts have two equivalent string representations — EVM hex (0x…) and Bech32 (maroo1…). When each one matters, and how to convert between them in JS/TS.
Prerequisites
- Basic understanding of EVM hex addresses (e.g., from Ethereum).
EVM hex (the default surface)
The standard 42-character
Example:
0x… address. This is what MetaMask shows, what Solidity uses, what JSON-RPC returns, what the Maroo block explorer displays, and what every viem / ethers / Hardhat / Foundry tool expects.Example:
0x71C7656EC7ab88b098defB751B7401B5f6d8976FBech32
Same 20-byte account ID, encoded with a network-identifying HRP (
Example:
It's the same key material — just a different string representation.
maroo for Maroo) and a checksum. You'll see this when:- querying validator / staking / governance modules (they take Bech32),
- inspecting non-EVM query results,
- interfacing with IBC (counterparty addresses).
Example:
maroo1g9aher02v4dmf49m26de25d2n0a2th8g3z4x9aIt's the same key material — just a different string representation.
Converting between them in JS/TS
Both directions are O(1) — there's no network call. Use
@cosmjs/encoding for Bech32 (it's lightweight and ships in many wallet stacks already), and ethers/viem hex helpers for 0x form.import { fromBech32, toBech32 } from "@cosmjs/encoding";
import { getAddress, hexToBytes, bytesToHex } from "viem"; // or ethers equivalents
const HRP = "maroo";
// hex -> bech32
export function hexToBech32(hex: `0x${string}`): string {
const bytes = hexToBytes(hex);
return toBech32(HRP, bytes);
}
// bech32 -> hex (checksummed)
export function bech32ToHex(addr: string): `0x${string}` {
const { data } = fromBech32(addr);
return getAddress(`0x${bytesToHex(data).slice(2)}`);
}
// example round-trip
const hex = "0x71C7656EC7ab88b098defB751B7401B5f6d8976F";
const bech32 = hexToBech32(hex);
// 'maroo1g9aher02v4dmf49m26de25d2n0a2th8g3z4x9a'
const andBack = bech32ToHex(bech32);
// '0x71C7656EC7ab88b098defB751B7401B5f6d8976F' Note: Bech32 has a built-in checksum, so `fromBech32` throws on typos. The `0x` form has no checksum on its own — use viem's `getAddress` (or ethers' `getAddress`) to apply EIP-55 mixed-case checksumming.
Specialized prefixes
Bech32 has prefix variants for non-account roles. You'll only meet them when interfacing with validator / governance modules:
Account-level dApp work essentially never needs these.
maroovaloper1…— validator operators (staking module messages).maroovalcons1…— validator consensus addresses.maroopub1…/maroovaloperpub1…— public-key encoded forms (rare in app code).
Account-level dApp work essentially never needs these.