When you set up your Cosmos address in the wallet, you derive a single secp256k1 keypair from your XRPL mnemonic at path m/44'/118'/0'/0/0. That path is the Cosmos community standard (Keplr uses it; Cosmostation uses it; every Hub-compatible wallet uses it).
But you'll see two different addresses in the UI: cosmos1… on the Hub, osmo1… on Osmosis. They share one pubkey. So where does the difference come from?
Bech32 encoding, briefly
Bech32 is the address format the Cosmos ecosystem standardised on (Bitcoin uses it for SegWit too). The format is:
<HRP>1<data><checksum>
- HRP = human-readable prefix.
cosmoson the Hub,osmoon Osmosis,kavaon Kava,junoon Juno, etc. 1= the literal separator character. Always a 1.- data = the 20-byte address (the hash of your pubkey), base32-encoded.
- checksum = 6 characters at the end, calculated from HRP + data. Detects typos.
The 20-byte data portion is the same on every Cosmos chain for a given pubkey. Only the HRP differs. So when the wallet shows you cosmos1abc…xyz and osmo1abc…xyz with the same trailing characters, you're not looking at two different keys — you're looking at the same key rendered two ways.
Why does each chain have its own HRP?
Two reasons:
Brand identity. It's obvious at a glance which chain you're sending on. If a user pastes osmo1… into a Hub send form, the wallet rejects it before broadcasting. We do that check in the cosmos.py route — destination must start with the HRP for the selected network.
Replay protection. If addresses were identical across chains, a tx signed for one chain could be replayed on another. The HRP forces apps to be explicit about which chain they're talking to. Combined with the chain-id field inside every signed tx, this makes cross-chain replays effectively impossible.
What this means for receiving
When someone wants to send you ATOM, give them the cosmos1… form. When they want to send OSMO, give them the osmo1… form. Both are equivalent at the cryptographic layer — both addresses can be unlocked by the same private key. But each chain only recognises its own HRP.
The wallet's receive screen makes this trivial. The Cosmos overview's network tab toggle re-renders the same pubkey with the right HRP. You don't manage two keys; you manage two views of one key.
What about other Cosmos chains?
Every Cosmos chain that uses the standard secp256k1 + bech32 stack works the same way. Iter-G only ships Hub + Osmosis, but the wallet's signer module exposes address_for_network(pubkey, hrp) so attaching Juno or Kava in a future iteration is mostly a config change.
The few chains that diverge:
- Injective, Evmos, Kava EVM use Ethereum's secp256k1 signature scheme (ECDSA with Keccak hashing) instead of Cosmos's standard. They use BIP-44 coin 60 like Ethereum. Those addresses look like inj1… but are derived from an EVM-style key, not a Cosmos-style one. The wallet would handle these in a separate attach.
- Terra Classic uses its own HRP (terra…) and a non-standard derivation in some clients. Not in scope.
The TL;DR
One secp256k1 keypair, derived once from your XRPL mnemonic. Bech32 encoding adds a per-chain HRP that makes the address human-readable and replay-safe. The wallet auto-renders the right HRP for each network and rejects mismatched destinations before broadcast.
Next lesson: how IBC lets you actually move tokens between those two addresses.