# Register a Master Address

## Overview

A TIP-1022 master registration binds a 4-byte master ID to an address. Before submitting that
registration, find a salt whose registration hash satisfies the protocol's proof-of-work rule.
[`VirtualMaster.mineSaltAsync`](/tempo/reference/VirtualMaster/mineSaltAsync) performs this search
with parallel workers when the environment supports them.

Ox returns the salt, master ID, and registration hash. The registration itself is an onchain state
change, so submitting it and confirming the resulting record require a Tempo client or direct
contract call.

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

## Recipes

### Mine a Registration Salt

Pass the master address to `mineSaltAsync`. The default search covers the bounded 32-bit search
space and returns `undefined` if no matching salt is found.

```ts twoslash
import { VirtualMaster } from 'ox/tempo'

const masterAddress = '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'

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

if (!mined) throw new Error('No registration salt found')

const { masterId, registrationHash, salt } = mined
```

Submit `salt` for `masterAddress` through the protocol's master-registration call. Ox deliberately
does not submit this transaction. For an end-to-end client flow, see Viem's
[Register a Master Address](https://viem.sh/tempo/guides/virtual-addresses/register) guide.

### Verify Stored Registration Data

Use [`VirtualMaster.validateSalt`](/tempo/reference/VirtualMaster/validateSalt) before reusing a
persisted salt. You can independently recompute the master ID with
[`VirtualMaster.getMasterId`](/tempo/reference/VirtualMaster/getMasterId) and the registration hash
with [`VirtualMaster.getRegistrationHash`](/tempo/reference/VirtualMaster/getRegistrationHash).

```ts twoslash
import { VirtualMaster } from 'ox/tempo'

const registration = {
  address: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
  salt: '0x00000000000000000000000000000000000000000000000000000000abf52baf',
} as const

if (!VirtualMaster.validateSalt(registration))
  throw new Error('Invalid registration salt')

const masterId = VirtualMaster.getMasterId(registration)
const registrationHash = VirtualMaster.getRegistrationHash(registration)
```

These checks only validate the local derivation. Query the Tempo registry to confirm that the
master ID is registered to the expected address.

## Best Practices

### Mine Outside Request Paths

Salt mining can take time. Run it in a background task, use the `onProgress` callback for
observability, and pass an `AbortSignal` when the operation must be cancellable.

### Persist the Exact Inputs

Store the master address, salt, master ID, and confirmed transaction reference together. Recomputing
from those inputs makes it easier to detect mismatched or corrupted records.

### Confirm Onchain State

`validateSalt` proves that a salt satisfies the local derivation rules. It does not prove that the
master has been registered or that a zone, token, or application accepts it.

## See More

<Cards>
  <Card icon="lucide:scan-search" title="Create and Parse Addresses" description="Use the registered master ID to derive tagged addresses." to="/tempo/guides/virtual-addresses/create-and-parse-addresses" />

  <Card icon="lucide:square-function" title="VirtualMaster.mineSaltAsync" description="Review mining options, progress reporting, and cancellation." to="/tempo/reference/VirtualMaster/mineSaltAsync" />

  <Card icon="lucide:book-open" title="Tempo Docs: Virtual Addresses" description="Read the onchain registration requirements." to="https://docs.tempo.xyz/protocol/tip20/virtual-addresses" />
</Cards>
