Integration Guide
You can integrate Sui Name Service (SuiNS) into your application using offchain or onchain resolution. The following sections list the active SuiNS package and object IDs on Mainnet and Testnet and describe how subnames work.
Sui Name Service (SuiNS) is a decentralized naming service on the Sui blockchain that enables users to replace complex wallet addresses with human-readable names. You can integrate SuiNS into your application using either onchain or offchain resolution.
What are the active SuiNS constants?
The following list shows the current active objects for interacting with SuiNS.
Look here for the latest state, as some active constants might change. These changes come from secondary packages responsible for registering a name, renewing a name, and associated utilities. The core package cannot change, nor can the core SuiNS object.
- Mainnet
- Testnet
SuiNS deploys, authorizes, and maintains the following packages on Mainnet.
- Packages
- Objects
| Kind | Package ID |
|---|---|
| SuiNS Core (latest) | 0x55800f20ca5ac11f2d8ef41e3900e8d4e338efd3cb263b62e73fd8be75be2003 |
| SuiNS Core V1 | 0xd22b24490e0bae52676651b4f56660a5ff8022a2576e0089f79b3c88d44e08f0 |
| Subnames | 0xe177697e191327901637f8d2c5ffbbde8b1aaac27ec1024c4b62d1ebd1cd7430 |
| Subnames Proxy | 0xf335dfbcb2020fc996250c0d6fd4655c5e2036b0606cac7408aa163f51340886 |
| Discounts | 0x03f625d805339b1b0235ba8c503fa6ea62c88c02ddf14cd9d246d9e1febc0c76 |
| Coupons | 0xb162340524e0697461c307b9dc530c17e837b0f2c6d7f787da40d29d29681e5e |
| Payments | 0xdbbf23390d9fb0dc0cf05c701ee61b02ae648268bff8c7ed4fe3e3128ec90b99 |
| Kind | Object ID |
|---|---|
| SuiNS Core Object | 0x6e0ddefc0ad98889c04bab9639e512c21766c5e6366f89e696956d9be6952871 |
| Discount House | 0x4ce82dee11e6f4858509dcdba1a62985f12e5afb054df680a04f16790bfe1d04 |
SuiNS deploys, authorizes, and maintains the following packages on Testnet.
- Packages
- Objects
| Kind | Package ID |
|---|---|
| SuiNS Core (latest) | 0x40eee27b014a872f5c3330dcd5329aa55c7fe0fcc6e70c6498852e2e3727172e |
| SuiNS Core V1 | 0x22fa05f21b1ad71442491220bb9338f7b7095fe35000ef88d5400d28523bdd93 |
| Subnames | 0x3c272bc45f9157b7818ece4f7411bdfa8af46303b071aca4e18c03119c9ff636 |
| Subnames Proxy | 0x295a0749dae0e76126757c305f218f929df0656df66a6361f8b6c6480a943f12 |
| Discounts | 0x7976f9bfe81dcbdbb635efb0ecb02844cd79109d3a698d05c06ca9fd2f97d262 |
| Coupons | 0x63029aae8abbefae4f4ac6c5e3e0021159ea93a94ba648681fd64caf5b40677a |
| Payments | 0x4f33a0e1e30530f2aa500a41b9e3d502f8af3ef2c20bd0a1e42374e329da7cb0 |
| Kind | Object ID |
|---|---|
| SuiNS Core Object | 0x300369e8909b9a6464da265b9a5a9ab6fe2158a040e84e808628cde7a07ee5a3 |
| Discount House | 0x9f1ac0f49ddaec4fd2248ae1cc63ed91946f43a236b333439efb9126f31f8e9b |
Integration
You can integrate SuiNS in multiple ways depending on your use case. For apps, you typically integrate SuiNS through offchain resolution using remote procedural calls (RPCs). The calls enable you to interact with the Sui network or display names instead of addresses. For example, your RPCs might create transactions that send assets to names, or show names instead of addresses on a leaderboard.
Resolution types
SuiNS supports 2 types of resolution:
-
Lookup: A name can point to an address or an object (target address). This allows you to resolve a name like
example.suito its target address. -
Reverse lookup: An address can have a default name. This allows you to find the name associated with a particular address.
Address types
Lookups work with different types of addresses:
-
Target address: The address that a SuiNS name resolves to. For example,
example.suimight point to0x2, making0x2the target address forexample.sui. Lookup resolution retrieves this information. -
Default address: The SuiNS name that the owner of a particular address has selected to represent that address. For example, if you own
0x2you can makeexample.suiits default address. The owner must sign and execute a set default transaction to establish this connection. The default address resets anytime the target address changes. Reverse lookup resolution retrieves this name.
Use the target address when you start from a name and need an address, for example to send assets to a name. Use the default address when you start from an address and want to display a name, for example on a leaderboard.
SuiNS NFT ownership
Do not use ownership of a SuiNS NFT as a resolution method. An NFT acts as the key (capability) to change the target address, but do not use it to identify any name with an address.
With SuiNS NFT ownership, you can set any address as the target address. So, the example.sui address used in the previous section can point to any address, not just 0x2. Consequently, when you want to display default addresses, you should trust the default address over target address because Sui guarantees it onchain.
How do I resolve a name offchain?
For offchain resolution, pass the name to the address GraphQL query. To fetch the full name record instead of just the target address, use the nameRecord query.
The JSON-RPC suix_resolveNameServiceAddress method previously served this lookup. Sui Foundation has disabled JSON-RPC on its Mainnet full nodes, so migrate any code still calling it. See the JSON-RPC Migration Guide.
For reverse lookup, read the defaultNameRecord field on the Address type. It replaced defaultSuinsName.
How do I resolve a name onchain?
Use the SuiNS core package for onchain resolution. Add the following dependency in your Move.toml file depending on which network you are targeting:
- Mainnet
- Testnet
[dependencies]
suins = { git = "https://github.com/mystenlabs/suins-contracts/", subdir = "packages/suins", rev = "releases/mainnet/core/v3" }
[dependencies]
suins = { git = "https://github.com/mystenlabs/suins-contracts/", subdir = "packages/suins", rev = "releases/testnet/core/v2" }
Example: transfer object to SuiNS name
The following demo module demonstrates how to transfer an object of any type to a SuiNS name. This is a basic example of how to interact with SuiNS onchain.
module demo::demo {
use std::string::String;
use sui::clock::Clock;
/// Import the SuiNS dependency.
use suins::{
suins::SuiNS,
registry::Registry,
domain
};
/// Different custom error messages.
const ENameNotFound: u64 = 0;
const ENameNotPointingToAddress: u64 = 1;
const ENameExpired: u64 = 2;
/// A function to transfer an object of any type T to a name (for instance `example.sui`)
public fun send_to_name<T: key + store>(suins: &SuiNS, obj: T, name: String, clock: &Clock) {
// Look up the name on the registry.
let mut optional = suins.registry<Registry>().lookup(domain::new(name));
// Check that the name indeed exists.
assert!(optional.is_some(), ENameNotFound);
let name_record = optional.extract();
// Check that name has not expired.
// This check is optional, but it's recommended you perform the verification.
assert!(!name_record.has_expired(clock), ENameExpired);
// Check that the name has a target address set.
assert!(name_record.target_address().is_some(), ENameNotPointingToAddress);
// Transfer the object to that name.
transfer::public_transfer(obj, name_record.target_address().extract())
}
}
If the name does not exist, has expired, or has no target address set, send_to_name aborts with ENameNotFound, ENameExpired, or ENameNotPointingToAddress, respectively.
You should integrate SuiNS onchain using the core package only. SuiNS is likely to replace the utility packages, rendering your logic non-functional unless you update your code with each change.
Indexing
The indexer enables more expressive queries about the active domain state when onchain resolution is not sufficient to power your interface.
This allows for complex queries such as:
-
Get all the subnames for a given parent: Retrieve every subdomain linked to a parent domain, enhancing the ability to manage and analyze domain structures.
-
Get all names pointing to a specified address: Identify all domain names associated with a specific wallet address to track ownership and usage.
You can find the indexer in the suins-indexer GitHub repository. You can run your own service if you want to index data tailored to your needs.
For a deeper understanding of how the indexer works and how to integrate it into your projects, refer to Sui's custom indexer documentation.
Subnames
Subnames are nested names under a parent name. Unlike regular names, creating subnames has no cost.
The maximum nesting depth is 8 levels. The total depth, including the second-level domain (SLD) and top-level domain (TLD), means the maximum total depth is 10 levels. For example, a.b.c.d.e.f.g.h.example.sui has 8 subname levels under the SLD example and the TLD sui.
Parent rules control whether you can create nested names or not and can also allow a subname to extend the expiration to match the parent's expiration. You can alter the parent rules at any time, but revoking or burning follows the same rules.
What is the difference between node and leaf subnames?
Subnames can be one of 2 types:
-
Node subnames: Similar to regular names, they have an NFT associated with them that gives access to all extra features (personalization, avatars, and so on).
-
Leaf subnames: These subnames exist under a node subname. They do not have an NFT associated with them, so the parent controls their configuration. Consequently, the typical use case for leaf subnames is to use them programmatically.
The following table provides more details on the differences between the types of names:
| Capabilities or category | Node subnames | Leaf subnames |
|---|---|---|
| Has NFT | ✅ Yes,
| ❌ No, parent's NFT acts as the capability |
| Can create children (node or leaf) | ✅ Yes, provided the name is an SLD or the parent allows it | ❌ No |
| Expiration | ✅ Yes, SuiNS determines expiration for SLDs, otherwise the parent determines | ❌ No, the parent's expiration determines the leaf expiration |
| Extend expiration | ✅ Yes, you can extend expiration if parent rules allow it (or you can pay for it for SLD) | ✅ Yes, leaf names have no independent expiration; the parent's expiration determines the leaf expiration |
| Target address | ✅ Yes, NFT holder can update the target address; address can be empty | ✅ Yes, active parent's NFT holder can update the target address; address cannot be empty |
| Reverse registry | ✅ Yes | ✅ Yes |
| Revoke | ❌ No, you cannot remove a node name (except when expired) | ✅ Yes, active parent holder can remove a leaf name |
| Burn | ✅ Yes, post-expiration only | ✅ Yes, burn and revoking is the same for leaf names |
| Transfer ownership | ✅ Yes, the NFT determines node name ownership | ❌ No, SuiNS preserves ownership for the active parent name holder |
SLD: Second-level domain (for example, example in example.sui)