# Welcome !

<figure><img src="/files/2rFyfhSs7QRoib3HZFCM" alt=""><figcaption></figcaption></figure>

Welcome to Nad Name Service docs!

Nad Name Service (NNS) is a web3 name service built on Monad. NNS maps human-readable names like 'salmo.nad' to machine-readable identifiers such as cryptocurrency addresses, metadata, and more.

This comprehensive document provides everything you need to navigate and utilize NNS effectively.

Are you ready? Let's get started, nad!


# Introduction

Provide a brief introduction to the Nad Name Service protocol

As the Monad ecosystem expands, users will need a convenient way to interact with dApps, protocols; and the need for an efficient means to engage with dApps and protocols becomes essential. Using cryptocurrency addresses can be cumbersome and error-prone sometimes.&#x20;

This is where Nad Name Service shines.

### What is Nad Name Service ?

Nad Name Service (NNS) is a distributed, open web3 name service based on the Monad blockchain.

At its core, NNS provides mapping between human-readable names like 'salmo.nad' to machine-readable identifiers such as cryptocurrency addresses, content hashes, metadata, and more.

DApps and protocols integrated with NNS enable users to use  human-readable names instead of cryptocurrency addresses , making interactions as seamless and smooth as possible.

<figure><img src="/files/GTgIAMPss41eJFrBYjfa" alt=""><figcaption><p>Name mapping by NNS</p></figcaption></figure>

### NNS Names

Nad Name Service supports a wide range of character sets and emojis, allowing users to choose any name they want. This enables users to freely express their style through their chosen names.

Examples of valid name:

* salmo.nad
* 🥚keone🥚.nad
* 🐸🤝🐸.nad
* 안녕하세요.nad
* 你好.nad
* ...

Each name will be a NFT so that users can easily trade names on NFT marketplaces.

***

### Profile

Each name comes with a customizable profile. Users can personalize their profile by setting an avatar, adding social links, and configuring text records for their name.


# Roadmap

This page provides you with a specific and transparent overview of the protocol's development roadmap. Note that the roadmap might change in the future to better serve the community.

## Pre-launch

* [x] Develop all the necessary components for the NNS protocol.
  * [x] **Protocol core smart contracts**: the backbone of the protocol.
  * [x] **NNS Name Manager App**: the web application for user to manage NNS names.
  * [x] **NFT metadata service**: provide NFT name's metadata.
  * [x] **Websites**: landing page, documents, ....
  * [x] **NNS SDKs:** for developers to integrate NNS into their existing applications.
* [x] Community
  * [x] **X**&#x20;
  * [x] **Discord server**
* [x] Testnet launch
  * [x] **Monad devnet**
  * [x] **Monad testnet**

## Launch

* [ ] Deploy NNS protocol to Monad mainnet.
* [ ] List NNS name NFT collection on NFT marketplaces.

## Post - launch

* [ ] Collecting community feedback about NNS.
* [ ] Improving the protocol based on community feedback.
* [ ] Incentive program: Reward NNS protocol early adopters.
* [ ] Airdrop

Stay tune for more updates about the protocol roadmap!

If you have any ideas or improvements, feel free to contact us! [Contact](/others/contact)


# Incentives

Nad Name Service (NNS) Incentive Program rewards early adopters with exclusive benefits.

Community is everything 💜

Stay tuned for more updates!


# Terminology

This page contains glossaries used in the NNS documentation.

## Name

An NNS identifier such as 'salmo.nad'.

## Owner

The owner of a name is the owner of the NFT token that represent the name. An owner may transfer ownership, set resolved address, name's attributes, ...

## Primary name

The NNS name that you want a particular wallet account to be associated with. When set, it will be displayed instead of your 0x address on integrating websites/apps.

## Avatar

A picture that is associated with a NNS name.

## Text record

A pair of key - value, use to store informations associated with a NNS name.

## Label

An individual component of a name, such as 'salmo' in name 'salmo.nad'.

## Labelhash

The keccak256 hash of an individual label.

## Namehash

The algorithm used to process a name and return a cryptographic hash uniquely identifying that name. Namehash takes a name as input and produces a *node*.

## Node

A cryptographic hash uniquely identifying a name.


# Introduction

More details coming soon

$NAD is not launched yet, please beware of scams and fake tokens.


# Name Manager App

The NNS Name Manager App is a web based application for managing NNS names. It provides the following features:

* Registering new names
* Set resolved address for name
* Set avatar for name
* Set primary name for an address
* Get, set text records for a name
* ...


# Registering new name

This document will take you through the registration process

## Registering new names

In order to register a new NNS name using the Name Manager App, you need to complete these following steps :

* Pick a name and check if it's available.
* Confirming registration infos.
* Sending transaction using crypto wallet to register.

<figure><img src="/files/SbjeG5WQSgvNVvzlZSew" alt=""><figcaption><p>Pick a name and check if it's available.</p></figcaption></figure>

<figure><img src="/files/zVTvSqUlTnNPWze0Sxvv" alt=""><figcaption><p>Confirming registration infos.</p></figcaption></figure>

<figure><img src="/files/MJZjrVLUF7wLYI3MNga1" alt="" width="359"><figcaption><p>Sending transaction using crypto wallet to register</p></figcaption></figure>


# Manage names

After registering, users can manage NNS names in the Name Manager App.

The Name Manager App provide the following feature:&#x20;

* Registering new names
* Set resolved address for name
* Set avatar for name
* Set primary name for an address
* Get, set text records for a name
* ...


# Primary name

Wallet addresses are not always easy to remember and make sense of. Because of that, NNS provide a way for users to set primary name for their wallet address. Using primary name, dapps can display user's preferred NNS name instead of long, boring wallet addresses.

How to set a name as primary name:

Go to the name manager page by clicking "My Names" "

<figure><img src="/files/jUVU9XogvV3YRS8H8ypL" alt=""><figcaption></figcaption></figure>

Select the name you want to set as primary, then click "Set as primary name":

<figure><img src="/files/8StwKKqgDoAs4kxijCCd" alt=""><figcaption></figcaption></figure>

Confirm the transaction, wait for it to success:

<figure><img src="/files/UGE2BQ1oZ3Yp6hjxKn8p" alt="" width="375"><figcaption></figcaption></figure>


# Avatar

Personalization is great, especially for users that want to express their unique style in the web3 spaces.

NNS support setting the avatar associated with a name through a special record: **avatar**

How to set avatar for a .nad name:

Prepare the url to the image (example below):

<https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUjp-gA3So3QrwGJmT5ETg9X7r3TAB_LvncA&s>

Go to the Records tab of the name you want to set avatar, fill in the url and click save:

<figure><img src="/files/8NIkSzXVjteEMGqmJXbD" alt=""><figcaption></figcaption></figure>

Confirm the transaction:

<figure><img src="/files/sgyrGKIEGNjOzB37Uhr2" alt="" width="375"><figcaption></figcaption></figure>

Done!

<figure><img src="/files/lm4zxuHUkESy5eWtXDmV" alt=""><figcaption></figcaption></figure>


# Text records

With every registered NNS name comes with an set of records. These are a set of key - values pair used to store informations about user profile. DApps and protocol can used these records to store or retrieve informations associated with a name.

How to set text records for a name:

Go to the Records tab of the name you want to set text records, fill in the record value and click save:

<figure><img src="/files/j54bWb4krm19Pjwam269" alt=""><figcaption></figcaption></figure>

Confirm the transaction:

<figure><img src="/files/8MfH26uGcuSdjYvZU7R7" alt="" width="375"><figcaption></figcaption></figure>

Done!

<figure><img src="/files/kqpoiSLwQrzfO4WdiAPt" alt="" width="375"><figcaption></figcaption></figure>


# NadCard

Each .nad name come with a NardCard you can share to socials!

Set the avatar and com.x record to have your avatar and X username on the card.

<figure><img src="/files/ziAM6jLZ27ajQn18BSP1" alt=""><figcaption></figcaption></figure>

To share your NadCard on social, click the "Copy NardCard URL" then paste the link to any web like X, Telegram, Discord,... to have the card display:

<figure><img src="/files/hidd7gmIdPnt6Tg0J3ay" alt="" width="375"><figcaption></figcaption></figure>

<figure><img src="/files/FWor6SfYpn0dbhgi1pF3" alt="" width="375"><figcaption></figcaption></figure>


# Discord profile sync

You can sync your Discord profile with .nad name profile

Info that can be sync:

* Discord username
* Discord avatar
* Connected social accounts like X, Github, reddit, ...

<div data-full-width="false"><figure><img src="/files/CTd5jYI9OlcpTtYPOMNQ" alt=""><figcaption></figcaption></figure></div>


# Integrating into your dapps

Currently, we offer four ways for integrating Nad Name Service into your dapps:

* Query contract directly
* Using SDKs
* Using REST APIs
* NNS Adapters

## Which integration method is best for you&#x20;

### 🔍 Comparative summary

<table data-full-width="false"><thead><tr><th width="173.07421875">Integration Method</th><th width="164.390625">Control Level</th><th>Developer Effort</th><th>Speed &#x26; Latency</th><th>Flexibility</th><th>Ecosystem Fit</th></tr></thead><tbody><tr><td>Query Contract Directly</td><td>High</td><td>High</td><td>Very fast (RPC)</td><td>Fully flexible</td><td>Neutral (raw)</td></tr><tr><td>NNS Adapters</td><td>Moderate</td><td>Very low</td><td>Fast</td><td>Moderate (ENS‑aligned)</td><td>Best for ENS-based tools</td></tr><tr><td>NNS SDKs</td><td>Moderate-high</td><td>Low-moderate</td><td>Fast</td><td>High</td><td>JavaScript-heavy dApps</td></tr><tr><td>REST APIs</td><td>Medium</td><td>Low</td><td>Moderate</td><td>Moderate</td><td>Backend / external service</td></tr></tbody></table>

### 🤔 Decision Matrix

Higher score = Better

<table><thead><tr><th width="146.49609375">Factor</th><th width="161.16015625" data-type="rating" data-max="5">Query Contract</th><th data-type="rating" data-max="5">NNS Adapters</th><th data-type="rating" data-max="5">SDKs</th><th data-type="rating" data-max="5">REST APIs</th></tr></thead><tbody><tr><td>Implementation Speed</td><td>2</td><td>5</td><td>3</td><td>5</td></tr><tr><td>Customization</td><td>5</td><td>3</td><td>2</td><td>2</td></tr><tr><td>Performance</td><td>5</td><td>4</td><td>4</td><td>3</td></tr><tr><td>Decentralization</td><td>5</td><td>5</td><td>5</td><td>2</td></tr><tr><td>Maintenance Effort</td><td>2</td><td>5</td><td>3</td><td>5</td></tr><tr><td>Learning Curve</td><td>2</td><td>5</td><td>3</td><td>4</td></tr></tbody></table>

### 🧠 Best choice based on your needs

* **You want maximum control with no dependencies? Or you are developing smart contracts** → Use **Direct Contract Queries**
* **Already using ENS tooling and library and want quick adapter support?** → **NNS Adapters** will let you reuse existing code with minimal changes
* **You're building a high‑performance frontend dApp with JS frameworks?** → **NNS SDKs** strike a solid balance between control, speed, and ease-of-use.
* **Working server-side or need simple HTTP integration? Or you just simply want to display .nad names** → **REST APIs** offer minimal setup and broad compatibility.


# Name processing

When interacting with Nad Name Service smart-contracts directly, note that names are not stored in their human readable format. We must process the name before it can be used by a smart-contract by execute below steps **in order**:

* Name normalization
* Name hash

### Name normalization

Normalization is the process of standardizing a name before passing it through the Namehash algorithm. It's crucial to normalize all input consistently, as even a small variation, such as a difference between uppercase and lowercase letters, can result in a completely different namehash.

For example,  `Salmo.Nad` normalizes to `salmo.nad`. This ensures that no matter how the user types in the name, the correct node is used.

Using `viem:`

{% code lineNumbers="true" %}

```typescript
import { normalize } from 'viem/ens'

const normalizedName = normalize('Salmo.Nad') 
// => salmo.nad
```

{% endcode %}

Using `ethersjs(v6):`

<pre class="language-typescript" data-line-numbers><code class="lang-typescript">import { ensNormalize, namehash } from "ethers/hash";

<strong>const normalizedName = ensNormalize('Salmo.Nad')
</strong><strong>// => salmo.nad
</strong></code></pre>

### Namehash

{% hint style="info" %}
You must normalize names before creating a namehash.
{% endhint %}

In NNS core smart-contracts, names are stored as a hash instead of the raw string for optimization purpose. The hashed value is called a `node` , which is a hex-encoded 32-byte value that is derived from the name using the `namehash` algorithm from ENS [ENSIP-1](https://docs.ens.domains/ensip/1).

Using `viem:`

```typescript
import { namehash, normalize } from "viem/ens";

const normalizedName = normalize('salmo.nad');
const node = namehash(normalizedName);
```

Using `ethersjs(v6):`

```typescript
import { ensNormalize, namehash } from "ethers/hash";

const normalizedName = ensNormalize('salmo.nad')
const node = namehash(normalizedName)
```


# Query contract directly

You can query contract directly for resolved address, primary name, attributes,...

<table><thead><tr><th width="260.8515625">Method</th><th>Return</th></tr></thead><tbody><tr><td>getResolvedAddress</td><td>Resolved address for a name</td></tr><tr><td>getResolvedAddresses</td><td>Resolved addresses for a list of name</td></tr><tr><td>getPrimaryNameForAddress</td><td>Primary name for an address (Without TLD <code>.nad</code>)</td></tr><tr><td>getPrimaryNameForAddresses</td><td>Primary names for a list of address (Without TLD <code>.nad</code>)</td></tr><tr><td>getNameAttribute</td><td>An attribute associated with a name</td></tr><tr><td>getNameAttributes</td><td>Attributes associated with a name</td></tr><tr><td>getProfileForAddress</td><td>Return a profile for a wallet address, including primary name, avatar, ...</td></tr><tr><td>getProfilesForAddresses</td><td>Return profiles for a list of wallet address, including primary name, avatar, ...</td></tr><tr><td></td><td></td></tr></tbody></table>

For more information about contract address and ABI, checkout [Contracts](/developers/contracts)

Example:

`Viem:`

```typescript
// Replace with your contract address
  const nnsContractAddress = '0x...'

  // Create contract instance
  const contract = getContract({
    address: nnsContractAddress,
    abi: contractAbi,
    publicClient,
    walletClient
  })

  try {
    // Example domain
    const normalizedName = normalize('salmo.nad');
    const node = namehash(normalizedName);

    // 1. Get resolved address for a name
    const resolvedAddress = await contract.read.getResolvedAddress([node])
    console.log(`Resolved address for ${domain}:`, resolvedAddress)

    // 2. Get primary name for an address
    const address = '0x1234567890123456789012345678901234567890'
    const primaryName = await contract.read.getPrimaryNameForAddress([address])
    console.log('Primary name for address:', primaryName)

    // 3. Get single name attribute
    const attributeKey = 'avatar'
    const attributeValue = await contract.read.getNameAttribute([node, attributeKey])
    console.log(`Attribute ${attributeKey}:`, attributeValue)

    // 4. Get multiple name attributes
    const attributeKeys = ['avatar', 'email', 'url']
    const attributes = await contract.read.getNameAttributes([node, attributeKeys])
    console.log('Multiple attributes:', attributes)

  } catch (error) {
    console.error('Error:', error)
  }
```

Ethersjs:

```typescript
// Setup provider and signer
  const provider = new ethers.providers.JsonRpcProvider('YOUR_RPC_URL');
  const signer = new ethers.Wallet('YOUR_PRIVATE_KEY', provider);
  
  const abi = [...]
  
  // Contract setup
  const nnsContractAddress = 'YOUR_CONTRACT_ADDRESS';
  const contract = new ethers.Contract(nnsContractAddress, abi, provider);
  const contractWithSigner = contract.connect(signer);

  try {
    // Example values
    const domain = 'example.nad';
    const node = namehash(domain);
    const address = '0x1234567890123456789012345678901234567890';

    // Read queries
    // 1. Get resolved address
    const resolvedAddress = await contract.getResolvedAddress(node);
    console.log(`Resolved address for ${domain}:`, resolvedAddress);

    // 2. Get primary name for address
    const primaryName = await contract.getPrimaryNameForAddress(address);
    console.log('Primary name for address:', primaryName);

    // 3. Get single attribute
    const avatarValue = await contract.getNameAttribute(node, 'avatar');
    console.log('Avatar value:', avatarValue);

    // 4. Get multiple attributes
    const attributeKeys = ['avatar', 'email', 'url'];
    const attributes = await contract.getNameAttributes(node, attributeKeys);
    console.log('Multiple attributes:', attributes);
  

  } catch (error) {
    console.error('Error:', error);
  }
```

## Pros & Cons

### ✅ Pro

* **You are in full control**
* **Minimal dependencies**: only requires blockchain client, ABI, and custom name processing.
* **Immediate access** to all on-chain data if you manage smart-contract permissions and upgrades.
* **Decentralized**: No reliance on external APIs or services

### ⚠️ Cons

* **Manual name processing**: you must normalize and compute namehash yourself for each query.
* **Boilerplate code**: constructing contract instances and handling RPC logic manually.
* **Verbosity & error-prone**: more setup work, especially for batch queries.
* **Maintenance Burden**: Need to track contract updates and ABI changes


# Using NNS SDKs

{% hint style="info" %}
For Monad mainnet, please use SDKs with version 2.0.0+
{% endhint %}

We provide SDKs for interacting with Nad Name Service with many different option: using `Wagmi`, `Etherjs` and `Viem`

### [@nadnameservice/nns-wagmi-hooks](https://www.npmjs.com/package/@nadnameservice/nns-wagmi-hooks)

### [@nadnameservice/nns-viem-sdk](https://www.npmjs.com/package/@nadnameservice/nns-viem-sdk)

### [@nadnameservice/nns-ethers-sdk](https://www.npmjs.com/package/@nadnameservice/nns-ethers-sdk)

\
For detail on how to integrating these SDK into your projects, please check the above links.

## Pros & Cons

### ✅ Pro

* **Simplified Integration**: high-level APIs abstract away name normalization, hashing, and contract calls.
* **Supports popular frameworks**: integrates seamlessly with Wagmi, Ethers.js, Viem.
* **Faster development**: less boilerplate, more focus on business logic.
* **Type Safety**: Likely includes TypeScript definitions

### ⚠️ Cons

* **Dependency overhead**: adds libraries and bundles.
* **Black‑box abstraction**: less control over low‑level contract data/query parameters.
* **Customization limitations**: SDK may lack edge-case support or new contract methods until updated.


# Using REST APIs

You can use REST APIs to integrate with NNS protocol

Checkout REST APIs document at:

{% embed url="<https://api.nad.domains/api-docs>" %}

## Pros & Cons

### ✅ Pro

* **No blockchain tooling needed**: just HTTP requests.
* **Easy integration**: ideal for backends, service scripts, or environments where SDKs or RPC clients aren’t ideal.
* **Rapid prototyping**: fetch name resolution, profiles, etc., via simple endpoints.
* **Language Agnostic**: Works with any tech stack.

### ⚠️ Cons

* **Network latency**: HTTP is slower compared to direct RPC.
* **API stability / rate limiting**: subject to API versioning and limits.
* **Potential Latency**: May not reflect the very latest on-chain state.

**Best for:** Traditional web applications, mobile apps, or scenarios where blockchain interaction complexity isn't warranted.


# Using NNS Adapter

You can use our NNS Adapters to use existing api from viem or wagmi or any ENS compatible without writing new code. Just change `ensRegistry`  and `ensUniversalResolver`  in your library config and you're ready to go

For adapters smart contract addresses, please check this page:

{% content-ref url="/pages/yAPeSk4KLzkdVBvsINkp" %}
[Contract addresses](/developers/contracts/contract-addresses)
{% endcontent-ref %}

Example:&#x20;

```typescript
export const monadDevnet = defineChain({
   id: 41454,
  name: 'Monad Devnet',
  nativeCurrency: {
    decimals: 18,
    name: 'Monad',
    symbol: 'MON',
  },

  rpcUrls: {
    default: {
      http: [...],
    },
  },

  contracts: {
    ensRegistry: {
      // NNS Adapter
      address: '0x...',
    },
    ensUniversalResolver: {
      // NNS Universal Resolver Adapter
      address: '0x...',
    },
  },
})

const client = createPublicClient({
  chain: monadDevnet,
  transport: http(),
})

async function main() {
  const ensAddress = await client.getEnsAddress({
    name: normalize('test.nad'),
  })

  const avatar = await client.getEnsAvatar({
    name: normalize('test.nad'),
  })

  const ensName = await client.getEnsName({
    address: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
  })

  const resolver = await client.getEnsResolver({
    name: normalize('test.nad'),
  })
  const avatarStr = await client.getEnsText({
    name: normalize('test.nad'),
    key: 'avatar',
  })

  console.log(ensAddress)
  console.log(avatar)
  console.log(ensName)
  console.log(avatarStr)
  console.log(resolver)
}
```

## Pros & Cons

### ✅ Pro

* **Zero Code Changes**: Simply swap contract addresses in existing ENS integrations
* **Seamless ENS compatibility**: minimal code changes if you already use ENS clients library like Ethers or Viem.
* **Low integration friction**: no new SDKs or coding required, just adapter config.
* **Broad tooling support**: works with any ENS-aware tooling and ecosystem.

### ⚠️ Cons

* **ENS Limitations**: Constrained by ENS API design choices


# Contracts

NNS smart contracts form the backbone of Nad Name Service, powering its functionality on the Monad blockchain. These contracts manage the registration, administration, and transfer of human-readable names, ensuring security and transparency without relying on centralized authorities.

{% content-ref url="/pages/yAPeSk4KLzkdVBvsINkp" %}
[Contract addresses](/developers/contracts/contract-addresses)
{% endcontent-ref %}

{% content-ref url="/pages/4btUny8wqZz2lgpQbzwC" %}
[Contract ABI](/developers/contracts/contract-abi)
{% endcontent-ref %}

### NadNameService.sol

This is the core contract of Nad Name Service. It provides a standardized way to interact with the protocol, allowing developers to:

* Resolve names to address
* Obtain the primary name for an address
* Manage and retrieve attributes associated with names

```solidity
interface INadNameService {
    struct Attribute {
        string key;
        string value;
    }
    
    struct ResolvedAddressItem {
        bytes32 node;
        address addr;
    }
    
    struct PrimaryNameItem {
        address addr;
        string primaryName;
    }
    
    struct Profile {
        address addr;
        string primaryName;
        string avatar;
    }

    /**
     * @notice Emitted when a name's attribute is set.
     * @param node the hash of the name that attribute was set for
     * @param key the key of the attribute that was set
     * @param value the value of the attribute that was set
     */
    event AttributeSet(bytes32 indexed node, string key, string value);

    /**
     * @notice Emitted when multiple attributes for a name are set.
     * @param node the hash of the name that attributes were set for
     * @param attributes an array of attributes with the keys and values
     */
    event AttributesSet(bytes32 indexed node, Attribute[] attributes);
    
    /**
     * @notice Get the resolved address for a name.
     * @param node the hash of the name to get the resolved address for
     * @return the resolved address
     */
    function getResolvedAddress(
       bytes32 node
    ) external view returns (address);
    
    /**
     * @notice Get the resolved addresses for a list of names.
     * @param nodes the hashes of the names to get the resolved addresses for
     * @return an array of ResolvedAddressItem structs containing the node and address
     */
    function getResolvedAddresses(
        bytes32[] calldata nodes
    ) external view returns (ResolvedAddressItem[] memory);
    
     /**
     * @notice Get the primary name for a node.
     * @param node The node address to get the primary name for
     * @return The primary name for the address
     */
    function getPrimaryNameForNode(
        bytes32 node
    ) external view returns (string memory);

    /**
     * @notice Get the primary name for an address.
     * @param addr The address to get the primary name for
     * @return The primary name for the address
     */
    function getPrimaryNameForAddress(
        address addr
    ) external view returns (string memory);
    
    /**
     * @notice Get the primary names for a list of addresses.
     * @param addr The addresses to get the primary names for
     * @return An array of PrimaryNameItem structs containing the address and primary name
     */
    function getPrimaryNameForAddresses(
        address[] calldata addr
    ) external view returns (PrimaryNameItem[] memory);
    
    /**
     * @notice Set an attribute for a name.
     * @param node the hash of the name to set the attribute for
     * @param key the key of the attribute to set
     * @param value the value of the attribute to set
     */
    function setNameAttribute(
        bytes32 node,
        string calldata key,
        string calldata value
    ) external;

    /**
     * @notice Set multiple attributes for a name.
     * @param node the hash of the name to set the attributes for
     * @param attributes an array of attributes with the keys and values
     */
    function setNameAttributes(
        bytes32 node,
        Attribute[] calldata attributes
    ) external;

    /**
     * @notice Get an attribute for a name.
     * @param node the hash of the name to get the attribute for
     * @param key the key of the attribute to get
     * @return result value of the attribute
     */
    function getNameAttribute(
        bytes32 node,
        string calldata key
    ) external view returns (string memory);

    /**
     * @notice Get multiple attributes for a name
     * @param node the hash of the name to get the attributes for
     * @param keys the keys of the attributes to get
     * @return result an array of attributes with the keys and values
     */
    function getNameAttributes(
        bytes32 node,
        string[] calldata keys
    ) external view returns (Attribute[] memory);
    
    /**
     * @notice Get a profile for an address, containing primary name and avatar
     * @param addr the address to get the profile
     * @return profile the profile of the address, including primary name and avatar
     */
    function getProfileForAddress(
        address addr
    ) external view returns (Profile memory);

    /**
     * @notice Get a list of profiles for a list of addresses
     * @param addrs the addresses to get the profiles for
     * @return profiles the profiles of the addresses, including primary name and avatar
     */
    function getProfilesForAddresses(
        address[] calldata addrs
    ) external view returns (Profile[] memory);
}
```


# Contract addresses

#### Monad mainnet

<table><thead><tr><th width="257.15625">Contract</th><th>Address</th></tr></thead><tbody><tr><td>NadNameService</td><td>0xCc7a1bfF8845573dbF0B3b96e25B9b549d4a2eC7</td></tr><tr><td>NNSRegistryAdapter</td><td>0x67785260512139Ee22C7fBbd62b5706c16AA4050</td></tr><tr><td>NNSUniversalResolverAdapter</td><td>0x6ED8Ca3E2fEF58A82fc69B4037062445a3a32DfC</td></tr></tbody></table>

#### Monad testnet

<table><thead><tr><th width="252.49609375">Contract</th><th>Address</th></tr></thead><tbody><tr><td>NadNameService</td><td>0x3019BF1dfB84E5b46Ca9D0eEC37dE08a59A41308</td></tr><tr><td>NNSRegistryAdapter</td><td>0x6A1c3156F66a276f39751cAd4146ea4Ca463EcC7</td></tr><tr><td>NNSUniversalResolverAdapter</td><td>0xE451F2AB9E5d009b7384cD3B8d0B90c71CD4d0F7</td></tr></tbody></table>


# Contract ABI

**NadNameService.sol**

```json
[
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "bytes32",
        "name": "node",
        "type": "bytes32"
      },
      {
        "indexed": false,
        "internalType": "string",
        "name": "key",
        "type": "string"
      },
      {
        "indexed": false,
        "internalType": "string",
        "name": "value",
        "type": "string"
      }
    ],
    "name": "AttributeSet",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "bytes32",
        "name": "node",
        "type": "bytes32"
      },
      {
        "components": [
          {
            "internalType": "string",
            "name": "key",
            "type": "string"
          },
          {
            "internalType": "string",
            "name": "value",
            "type": "string"
          }
        ],
        "indexed": false,
        "internalType": "struct IAttributeStorage.Attribute[]",
        "name": "attributes",
        "type": "tuple[]"
      }
    ],
    "name": "AttributesSet",
    "type": "event"
  },
  {
    "inputs": [
      {
        "internalType": "bytes32",
        "name": "node",
        "type": "bytes32"
      }
    ],
    "name": "getResolvedAddress",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "bytes32[]",
        "name": "nodes",
        "type": "bytes32[]"
      }
    ],
    "name": "getResolvedAddresses",
    "outputs": [
      {
        "components": [
          {
            "internalType": "bytes32",
            "name": "node",
            "type": "bytes32"
          },
          {
            "internalType": "address",
            "name": "addr",
            "type": "address"
          }
        ],
        "internalType": "struct IResolvedAddressStorage.ResolvedAddressItem[]",
        "name": "",
        "type": "tuple[]"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "addr",
        "type": "address"
      }
    ],
    "name": "getPrimaryNameForAddress",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address[]",
        "name": "addr",
        "type": "address[]"
      }
    ],
    "name": "getPrimaryNameForAddresses",
    "outputs": [
      {
        "components": [
          {
            "internalType": "address",
            "name": "addr",
            "type": "address"
          },
          {
            "internalType": "string",
            "name": "primaryName",
            "type": "string"
          }
        ],
        "internalType": "struct IPrimaryNameStorage.PrimaryNameItem[]",
        "name": "",
        "type": "tuple[]"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "bytes32",
        "name": "node",
        "type": "bytes32"
      },
      {
        "internalType": "string",
        "name": "key",
        "type": "string"
      }
    ],
    "name": "getNameAttribute",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "bytes32",
        "name": "node",
        "type": "bytes32"
      },
      {
        "internalType": "string[]",
        "name": "keys",
        "type": "string[]"
      }
    ],
    "name": "getNameAttributes",
    "outputs": [
      {
        "components": [
          {
            "internalType": "string",
            "name": "key",
            "type": "string"
          },
          {
            "internalType": "string",
            "name": "value",
            "type": "string"
          }
        ],
        "internalType": "struct IAttributeStorage.Attribute[]",
        "name": "",
        "type": "tuple[]"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "addr",
        "type": "address"
      }
    ],
    "name": "getNamesOfAddress",
    "outputs": [
      {
        "internalType": "string[]",
        "name": "",
        "type": "string[]"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "bytes32",
        "name": "node",
        "type": "bytes32"
      },
      {
        "internalType": "string",
        "name": "key",
        "type": "string"
      },
      {
        "internalType": "string",
        "name": "value",
        "type": "string"
      }
    ],
    "name": "setNameAttribute",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "bytes32",
        "name": "node",
        "type": "bytes32"
      },
      {
        "components": [
          {
            "internalType": "string",
            "name": "key",
            "type": "string"
          },
          {
            "internalType": "string",
            "name": "value",
            "type": "string"
          }
        ],
        "internalType": "struct IAttributeStorage.Attribute[]",
        "name": "attributes",
        "type": "tuple[]"
      }
    ],
    "name": "setNameAttributes",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "addr",
        "type": "address"
      }
    ],
    "name": "getProfileForAddress",
    "outputs": [
      {
        "components": [
          {
            "internalType": "address",
            "name": "addr",
            "type": "address"
          },
          {
            "internalType": "string",
            "name": "primaryName",
            "type": "string"
          },
          {
            "internalType": "string",
            "name": "avatar",
            "type": "string"
          }
        ],
        "internalType": "struct INadNameService.Profile",
        "name": "",
        "type": "tuple"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address[]",
        "name": "addrs",
        "type": "address[]"
      }
    ],
    "name": "getProfilesForAddresses",
    "outputs": [
      {
        "components": [
          {
            "internalType": "address",
            "name": "addr",
            "type": "address"
          },
          {
            "internalType": "string",
            "name": "primaryName",
            "type": "string"
          },
          {
            "internalType": "string",
            "name": "avatar",
            "type": "string"
          }
        ],
        "internalType": "struct INadNameService.Profile[]",
        "name": "",
        "type": "tuple[]"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  }
]

```


# Contact

email: **<contact@nad.domains>**

X: <https://twitter.com/NadDomains>


# FAQs

## What is a Nad Name Service (NNS)?

Nad Name Service(NNS) is a decentralized application that allows users to register and manage human-readable domain names on the Monad blockchain, simplifying the use of complex wallet addresses, smart contracts, and other blockchain identifiers.

## How does a Nad Name Service work?

NNS uses smart contracts on the Monad blockchain to map human-readable names to machine-readable identifiers, such as cryptocurrency wallet addresses, content hashes, or metadata. This mapping is maintained onchain, ensuring security, decentralization, and immutability.

## What are the benefits of using a Web3 Name Service?

Benefits include simplified transactions by using easy-to-remember names instead of long cryptographic addresses, reduced risk of errors in sending and receiving assets, and the ability to create a unified digital identity.

## How secure is Nad Name Service?

NNS leverages blockchain technology, specifically the Monad blockchain, which ensures a high level of security and decentralization, boasting a lightning speed of 10,000 TPS. Each name registered on NNS is tied to a blockchain address, enhancing security and ownership transparency.

***

## What characters are supported?

NNS names are generally encoded using UTS-46. This means there is partial support for Unicode characters, including emojis.

## Are there any restrictions on the length of names I can register on NNS?

NNS imposes limits on the minimum and maximum length of names that can be registered. These limits are designed to ensure compatibility with the naming system and prevent abuse. Currently, the minimum length allowed is 2 characters, and there is no limit on the maximum length.

## Is my name registration permanent?

Yes, it is. You only need to pay a one-time registration fee. After that, the NNS name you’ve registered will belong to you forever, with no additional fees needed.

## How much will I have to pay for my NNS name?

Detail about registration fee will be available soon.

***

## What can I do with a newly NNS name?

You can set it resolved address, this is the address the name will point to. You can set the name as primary name, in case you have many name pointing to an wallet address. You can also change avatar, view or edit other attributes associated with the name.

## How can I acquire registered NNS names?

You can buy registered NNS names on NFT marketplaces. Detail available soon.

## How can I verify ownership of an NNS name I want to acquire?

You can verify ownership through blockchain transactions and the NNS Name Manager App. This process ensures transparency and confirms that one has legitimate ownership rights to the NNS name.

## Does NNS names save resolved wallet address when I bought them?

If you make a new registration, your resolve address is automatically saved as the registering wallet. If you purchased a domain name from the secondary market, make sure to change the resolved address to any wallet address owned by you.


