# Register a Master Address

## Overview

Registering a master is a one-time onchain step that binds a `masterId` to your wallet. The
`masterId` is derived from your address plus a salt that must satisfy a small proof-of-work, so you
mine a valid salt offchain first, then submit the registration. Registrations are immutable, so
register the address (or proxy) you intend to keep.

[See the Virtual Addresses specification](https://docs.tempo.xyz/protocol/tip20/virtual-addresses)

## Recipes

These recipes assume you have [set up a Tempo client](/tempo).

### Mine a Salt and Register

Mine a proof-of-work salt for your master address with `VirtualMaster.mineSaltAsync`, then register
it with [`virtualAddress.registerMasterSync`](/tempo/actions/virtualAddress.registerMaster). The
result includes the `masterId` you use to derive deposit addresses.

:::code-group
```ts twoslash [example.ts]
import { VirtualMaster } from 'viem/tempo'
import { client } from './viem.config'

const mined = await VirtualMaster.mineSaltAsync({
  address: client.account.address,
})

const { masterId, masterAddress } = await client.virtualAddress.registerMasterSync({
  salt: mined!.salt,
})
```

```ts twoslash [viem.config.ts] filename="viem.config.ts"
// [!include ~/snippets/tempo/viem.config.ts:setup]
```
:::

### Look Up a Registered Master

Resolve the wallet behind a `masterId` with
[`virtualAddress.getMasterAddress`](/tempo/actions/virtualAddress.getMasterAddress).

:::code-group
```ts twoslash [example.ts]
import { client } from './viem.config'

const address = await client.virtualAddress.getMasterAddress({
  masterId: '0x58e21090',
})
```

```ts twoslash [viem.config.ts] filename="viem.config.ts"
// [!include ~/snippets/tempo/viem.config.ts:setup]
```
:::

## Best Practices

### Register an Address You Can Keep

A `masterId` registration cannot be rotated or reassigned. If you may need to change the controlling
keys later, register a multisig or upgradeable proxy as the master so you can rotate keys at the
contract layer without re-registering.

### Mine Salts Off the Hot Path

`mineSaltAsync` runs a proof-of-work search and uses parallel workers when available. Run it ahead of
time (or in a background job) rather than in a latency-sensitive request, and persist the resulting
`salt` and `masterId`.

### Persist the Master ID

You need the `masterId` to derive deposit addresses. Store it after registration so you don't have to
re-derive it, and so the rest of your system can mint deposit addresses consistently.

## See More

<Cards>
  <Card icon="lucide:search" title="Resolve & Accept Payments" description="Derive deposit addresses from your master and resolve them." to="/tempo/guides/virtual-addresses/resolve" />

  <Card icon="lucide:square-function" title="virtualAddress.getMasterAddress" description="Look up the wallet registered for a master id." to="/tempo/actions/virtualAddress.getMasterAddress" />

  <Card icon="lucide:book-open" title="Tempo Docs: Virtual Addresses" description="Master registration and proof-of-work salt derivation." to="https://docs.tempo.xyz/protocol/tip20/virtual-addresses" />
</Cards>
