Concepts
This page explains the standards behind interoperable addresses and how the package implements them.
The problem
An Ethereum address like 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 doesn't say which chain the account is on. In a multichain world, this ambiguity leads to lost funds, broken UIs, and manual chain selection.
Interoperable addresses solve this by encoding the chain alongside the address in a single, standardized format — in two complementary ways.
Human-readable: ERC-7828
ERC-7828 defines a readable name format designed for end-users, wallets, and UIs:
vitalik.eth@ethereum
0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045@eip155:10#1A2B3C4D
The format is: {address}@{chain}#{checksum}
What makes it user-friendly:
- ENS names work directly —
vitalik.ethinstead of a raw hex address - Chain shortnames like
ethereum,base, oroptimismresolve automatically via an onchain registry - Checksums (4 bytes, calculated from the binary form) catch typos and detect tampering
- Fully-qualified CAIP-2 identifiers (
eip155:1) also work when precision matters
This is what users see and what apps display.
Onchain-optimized: EIP-7930
EIP-7930 defines a compact binary format optimized for smart contracts, where minimal byte size directly reduces gas costs:
0x00010000010114d8da6bf26964af9d7eed9e03e53415d37aa96045
The binary encodes a version byte, chain type, chain reference, and the address into a single byte sequence — no ambiguity, no resolution needed. This is the format smart contracts pass around and store onchain.
How they relate
Both formats carry the same information. A human-readable ERC-7828 name resolves to the same structured address that EIP-7930 serializes into bytes:
vitalik.eth@eip155:1 ←→ { chainType: "eip155", chainReference: "1", address: "0xd8dA..." } ←→ 0x0001...
(name) (structured address) (binary)
A third standard, CAIP-350, defines chain-type-specific rules for representing binary fields as text:
- eip155: Chain references as decimal strings, addresses as hex with EIP-55 checksumming
- bip122: Chain references as 32-char lowercase hex (genesis hash prefix), addresses as base58check or bech32/bech32m
- solana: Base58 encoding for both chain references and addresses
Package API design
The package API reflects the two formats:
- Functions that work with names (
parseName,nameToBinary,getAddress,getChainId) are async — they may need to resolve ENS names or chain shortnames over the network. - Functions that work with binary/structured addresses (
encodeAddress,decodeAddress,formatName,binaryToName) are sync — everything is already resolved.
The structured InteroperableAddress in the middle is a discriminated union — it can hold either text strings or raw bytes:
// Text variant — human-friendly strings
{ version: 1, chainType: "eip155", chainReference: "1", address: "0xd8dA..." }
// Binary variant — raw bytes
{ version: 1, chainType: Uint8Array, chainReference: Uint8Array, address: Uint8Array }
Use isTextAddress() or isBinaryAddress() type guards to narrow the union.
Chain resolution
When a name uses a chain shortname (e.g., @ethereum instead of @eip155:1), the SDK resolves it using a two-tier strategy:
- Onchain: Queries the
on.ethENS registry on Ethereum mainnet. The registry maps labels likeethereumto their ERC-7930 binary representation. - Offchain fallback: Uses the chainid.network registry to map shortnames to chain IDs.
Both are enabled by default. Fully-qualified CAIP-2 identifiers (e.g., eip155:10) skip resolution entirely.
You can customize resolution behavior per call:
// Disable onchain, use offchain only (chainid.network uses "eth" shortname)
await parseName("0x...@eth", { onchainRegistry: false });
// Custom registry domain
await parseName("0x...@ethereum", { onchainRegistry: "custom.eth" });
// Custom RPC URL for onchain resolution
await parseName("0x...@ethereum", { rpcUrl: "https://my-rpc.example.com" });
Checksums
Checksums protect against typos and address tampering. The checksum is computed from the binary serialization of the address and appended to the name after a #:
vitalik.eth@eip155:1#4CA88C9C
^^^^^^^^ checksum
The SDK always calculates the checksum when parsing. If the input includes a checksum, the SDK compares it against the calculated value and reports any mismatch via result.meta.checksumMismatch.