Identity: an Inbox, not a wallet address¶
Using a wallet address directly as the messenger ID makes three things impossible.
- Merging one person's several wallets into a single inbox
- Letting a phone and a laptop hold different keys (you cannot copy an address's private key onto every device)
- Cutting off only the one device that leaked
XMTP v3 solves this with a three-layer identity model (XIP-46).
flowchart TB
inbox["Inbox ID<br/>stable identifier, the message destination"]
w1["Wallet 1 (EOA)"]
w2["Wallet 2 (smart contract wallet)"]
i1["installation: phone"]
i2["installation: laptop"]
i3["installation: tablet"]
inbox --> w1
inbox --> w2
w1 --> i1
w1 --> i2
w2 --> i3
| Layer | What it is | Count |
|---|---|---|
| Inbox ID | The user's stable identifier. SHA256 of the first wallet address concatenated with a nonce. Messages are addressed to this value, not to an address | One per person |
| identity | A wallet linked to the Inbox. Both EOAs (EIP-191 signatures) and smart contract wallets (ERC-1271 signatures) are supported | Several per Inbox |
| installation | An Ed25519 key pair created per device (strictly, per client) that installs the app. The actual agent of encryption and decryption | 10 active per Inbox |
If you lose a device¶
The Inbox's first identity becomes the recovery address, and only the recovery address can revoke a wallet or a device. That makes it possible to cut off just the lost phone's installation while keeping the identity.
Identity changes come in four operations: CreateInbox, Add, Revoke, and
ChangeRecoveryAddress.
Where the 10-installation limit actually bites¶
An Inbox allows up to 10 active installations. Every sign-in from empty browser storage registers a new installation. So all of the following burn a slot.
- Signing in from a new browser or an incognito window
- Signing in again after
Clear site data - Running E2E tests repeatedly with a fresh profile
Once the limit is reached, Client.create hangs without responding. The
symptom is "pressing sign in never advances to the inbox."
On top of that, because MLS keys differ per installation, a new installation cannot decrypt messages sent before it joined the conversation. The ciphertext is still on the network, but there is no key to open it. That is what the "my conversation disappeared" symptom really is in Umul; the details and Umul's response are in Message History.
Identity changes are recorded on chain¶
Identity changes — adding a wallet, adding a device, revoking — are recorded as
blockchain transactions rather than as ordinary messages stored on nodes.
The decentralized node implementation (xmtpd) outright rejects an Identity
Update arriving on the message path and accepts it only through a call to the
IdentityUpdateBroadcaster contract.
An indexer reads those events back to build an "address → Inbox ID" mapping, and the "look up the peer" step just before starting a conversation reads that mapping in reverse.
What stays on chain and what stays on nodes is tabulated in Encryption and Delivery.