> For the complete documentation index, see [llms.txt](https://docs.t-rex.network/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.t-rex.network/identity-onchainid/wallet-linking-and-the-global-identity-registry.md).

# Wallet linking and the global identity registry

An ONCHAINID holds tokens itself, and its owner can also hold tokens in other addresses: an existing wallet, a second wallet, a wallet on another chain. For the register to treat those addresses as the same holder, each one is linked to the identity. An address that cannot link itself, such as a custody account that cannot sign, is registered for each asset by the Issuer's agent instead. The global identity registry is where those links are kept: one record per wallet, valid for every asset, under the control of the identity's owner.

## From registration per token to one link

In the earlier model, a wallet became usable for a token when an agent of that token's Issuer registered it. The participant was a passive subject: to use a new wallet, it asked an authorized party to register it, for each token, one at a time.

The global identity registry inverts this.

|                          | Registration per token          | Global link                                           |
| ------------------------ | ------------------------------- | ----------------------------------------------------- |
| **Who binds the wallet** | A Registry Agent of each Issuer | The Identity Owner                                    |
| **How often**            | Once per token                  | Once                                                  |
| **Proof**                | The agent's word                | A proof from the wallet and a proof from the identity |
| **Scope**                | One token                       | Every token, on every chain                           |
| **Address format**       | An address on one chain         | An ERC-7930 interoperable address                     |

The registry is implemented by the `IdentityFactory`. The same contract that creates identities keeps the record of which wallets belong to which identity.

## Interoperable addresses

The registry identifies a wallet by its ERC-7930 interoperable address: the type of chain, the chain, and the address in that chain's own format. A Solana account or an XRPL address is represented as naturally as an Ethereum one.

Two consequences:

* **One identity spans every chain.** The identity is the durable thing. Wallets, on whatever chain, are linked facets of it.
* **A wallet is a wallet on a chain.** The same address on two EVM chains is two entries. Each is linked separately, with the proof that fits its chain.

The registry stores the canonical encoding of each address, so one wallet has exactly one entry however its address was supplied.

## Two proofs

A link requires two proofs, from two sides.

* **Control of the wallet.** The wallet itself agrees to be linked to this identity.
* **Ownership of the identity.** The identity itself asks for the link, which takes one of its `MANAGEMENT` keys.

Neither side can create a link alone. How the wallet gives its proof depends on where the wallet lives.

### A wallet on the reference chain

The wallet signs a typed message, and the identity presents it.

```mermaid
sequenceDiagram
    participant W as Wallet
    participant ID as ONCHAINID
    participant F as IdentityFactory

    W-->>ID: signs LinkAccount(account, identity, nonce, expiry)
    Note over ID: a MANAGEMENT key instructs the identity
    ID->>F: linkAccount(account, signature, nonce, expiry)
    F->>F: account is on this chain
    F->>F: signature valid, nonce current, not expired
    F->>F: wallet not bound to another identity, never revoked
    F-->>ID: AccountLinked
```

* The message is ERC-712 typed data, `LinkAccount(bytes account, address identity, uint256 nonce, uint256 expiry)`, so the wallet shows its owner what is being signed.
* The signature is accepted from an externally owned account, from a smart-contract wallet through ERC-1271, and from an ERC-7913 signer such as a passkey. For an ERC-7913 signer, the verifier must be on the factory's list of trusted verifiers.
* The nonce is per wallet and is consumed by the link. The expiry is mandatory: the binding is permanent, so the signature that creates it must be fresh.
* The call comes from the identity, so only a `MANAGEMENT` key of that identity can make it.

### A wallet on another chain

A signature checked on the reference chain proves nothing about an address on another chain. A wallet on a non-EVM chain, or on a different EVM chain, proves control where it lives and sends the proof across.

```mermaid
sequenceDiagram
    participant W as Wallet on another chain
    participant G as ERC-7786 gateway
    participant F as IdentityFactory
    participant ID as ONCHAINID

    W->>G: link proposal: wallet, identity, expiry
    G->>F: deliver, with the sender authenticated
    F->>F: gateway is trusted for that chain
    F->>F: sender is the wallet named in the proposal
    F->>F: stage the proposal as pending
    Note over ID: a MANAGEMENT key instructs the identity
    ID->>F: settlePendingCrossChainLink(account, true)
    F->>F: proposal not expired, wallet not bound elsewhere
    F-->>ID: CrossChainLinkConfirmed
```

* **The wallet originates the message on its own chain.** ERC-7786 authenticates the sender of a cross-chain message. The factory requires that sender to be the wallet named in the proposal. That is the proof of control.
* **The gateway is trusted per origin chain.** The factory accepts a proposal only from a gateway that Network governance has listed for the chain the message comes from.
* **The identity settles the proposal.** Nothing is linked when the message arrives. The proposal waits until the named identity accepts it, which links the wallet, or declines it, which deletes the proposal. An expired proposal can no longer be accepted.
* **A local wallet cannot use this path.** A wallet on the reference chain has to sign.

### The first account

An identity is created with a first linked account: the caller that deployed it, or the account it was deployed for. See [Identity types and factory gating](/identity-onchainid/identity-types-and-factory-gating.md). Every later link goes through one of the two paths above.

## The rules of a binding

| Rule                             | Meaning                                                                                                                                                                                                          |
| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **A binding is sticky.**         | A wallet belongs to one identity. Once linked, it can never be linked to another.                                                                                                                                |
| **A revocation is terminal.**    | The identity revokes a wallet with `revokeAccount`. The record stays on-chain with the status `Revoked`, and the wallet can never be linked again, to this identity or to any other.                             |
| **An identity is not a wallet.** | An ONCHAINID cannot be linked as a wallet of another identity. It already resolves to itself.                                                                                                                    |
| **Links and keys are separate.** | Linking a wallet gives it no key on the identity, and revoking a wallet removes no key. Revoking the last wallet of an identity does not disable the identity. Its keys still work and it can link a new wallet. |
| **Some identities never link.**  | A single-binding identity, such as the identity of a token, keeps the one account set at its creation. It cannot link or revoke.                                                                                 |

A wallet is in one of three states: never seen, `Active` or `Revoked`.

### Why a binding cannot be undone

A link is a statement the register relies on to attribute ownership. Two properties follow from that.

* **A revoked wallet keeps its owner.** A wallet that still holds tokens must stay attributed to the identity that owned them, so that the identity can still move the position, and an agent can recover, burn or transfer it for the right holder. The registry keeps the record for that reason.
* **A wallet cannot change identity.** If a wallet could move from one identity to another, a position could change holder without a transfer, and rules that count holders or cap positions could be evaded.

## When a wallet is compromised

The owner revokes it. From that moment:

* The wallet is no longer verified. It cannot receive the asset. It can still send: revoking a wallet does not stop its own key from transferring its free tokens.
* Its holdings remain attributed to the identity. The identity's position does not change.
* The identity itself is unaffected: its keys, its claims, its other wallets and its eligibility stay as they were.
* The position that sits in the revoked wallet is moved to an address the owner controls, in one of two ways.

|                   | The owner moves it                                        | An agent recovers it                                |
| ----------------- | --------------------------------------------------------- | --------------------------------------------------- |
| **Call**          | `identityTransfer`, ordered by the identity               | `recoveryAddress`, by an agent of each asset        |
| **Needs**         | A key of the identity. The wallet's own key is not used.  | A request to the Issuer, verified under its process |
| **Free tokens**   | Moved                                                     | Moved                                               |
| **Frozen tokens** | Stay in the wallet. A transfer cannot move frozen tokens. | Moved, and frozen again at the new address          |

For free tokens the result is the same. When part of the balance is frozen, only the agent's recovery moves it.

Eligibility is a fact about the identity, not about any one wallet. Revoking a wallet does not revoke the investor.

## Reading the registry

| Function                               | Returns                                                                                                                                                            |
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `getIdentity(account)`                 | The identity an active wallet is linked to, or zero. An ONCHAINID resolves to itself.                                                                              |
| `getIdentityWithType(account)`         | The same, with the identity's type.                                                                                                                                |
| `getIdentityIncludingRevoked(account)` | The identity and the status of a wallet binding, including a revoked one. For an ONCHAINID's own address it returns the identity itself, with the status `Active`. |
| `getAccountStatus(account)`            | The status of a wallet binding. An ONCHAINID's own address is always `Active`: it cannot be revoked.                                                               |
| `getAccounts(identity, start, end)`    | The active wallets of an identity, by pages.                                                                                                                       |
| `getAccountsCount(identity)`           | The number of active wallets.                                                                                                                                      |
| `nonceForAccount(account)`             | The nonce a wallet must sign to be linked.                                                                                                                         |
| `getPendingCrossChainLink(account)`    | The pending proposal for a wallet, if there is one.                                                                                                                |

## How a token uses the registry

A token resolves a holding address to an identity in this order:

1. **A local registration, if the asset has one.** A Registry Agent of the asset can still register an address for that asset with `registerIdentity`. A local registration takes precedence over the global link for that asset, and an event signals when the two differ.
2. **The global link otherwise.** An address with no local registration resolves through the `IdentityFactory`.

For a wallet on a satellite chain, the token reads the global registry directly, by interoperable address. A satellite wallet is eligible for an asset when it is linked to an identity that satisfies the asset's requirements.

The work a participant does once, creating its identity and linking its wallets, carries across every asset it is eligible for. No Issuer has to register anything.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.t-rex.network/identity-onchainid/wallet-linking-and-the-global-identity-registry.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
