RIF Name Service (RNS) Javascript SDK
The @rsksmart/rns-sdk package helps you interact with the Rootstock Name Service (RNS). It lets you:
- Register .rsk domains
- Check domain and subdomain availability
- Query and set domain ownership
- Resolve domains to addresses
- Manage subdomains
- Work with partner registrars
Installation​
Install the package using npm:
npm install @rsksmart/rns-sdk ethers
Contract Addresses​
You will need these addresses to initialize the SDK:
| Contract | Mainnet | Rootstock Testnet |
|---|---|---|
| RNS Registry | 0xcb868aeabd31e2b66f74e9a55cf064abb31a4ad5 | 0x7d284aaac6e925aad802a53c0c69efe3764597b8 |
| RIF Token | 0x2acc95758f8b5f583470ba265eb685a8f45fc9d5 | 0x19f64674d8a5b4e652319f5e239efd3bc969a1fe |
| RSK Owner | 0x45d3e4fb311982a06ba52359d44cb4f5980e0ef1 | 0xca0a477e19bac7e0e172ccfd2e3c28a7200bdb71 |
| FIFS Addr Registrar | 0xd9c79ced86ecf49f5e4a973594634c83197c35ab | 0x90734bd6bf96250a7b262e2bc34284b0d47c1e8d |
| Partner Registrar | - | 0x8104d97f6d82a7d3afbf45f72118fad51f190c42 |
Initialization​
After obtaining the contract addresses from the table above, initialize the SDK by creating instances of the desired classes, passing the relevant addresses as constructor parameters. You'll also need a signer (e.g., from ethers.js) connected to the Rootstock network.
For example, to initialize the RNS class for mainnet:
import { ethers } from 'ethers';
import { RNS } from '@rsksmart/rns-sdk';
const provider = new ethers.providers.JsonRpcProvider('https://public-node.rsk.co');
const signer = new ethers.Wallet('your-private-key', provider);
const registryAddress = '0xcb868aeabd31e2b66f74e9a55cf064abb31a4ad5' // RNS Registry Mainnet address
const rns = new RNS(registryAddress, signer);
See the individual class sections below for more details on constructors and required addresses.
SDK Classes​
The SDK provides five main classes:
| Class | Purpose |
|---|---|
RNS | Domain management (owner, resolver, subdomains) |
AddrResolver | Address resolution |
RSKRegistrar | Standard .rsk domain registration |
PartnerRegistrar | Partner-based domain registration |
PartnerConfiguration | Partner contract configuration |
1. RNS Class​
The RNS class handles domain management operations.
Constructor​
import { Signer } from 'ethers'
import { RNS } from '@rsksmart/rns-sdk'
let signer: Signer
const rns = new RNS(registryAddress, signer)
Methods​
1. getOwner(domain)​
Gets the controller/owner of a domain.
const owner = await rns.getOwner('mydomain.rsk')
console.log('Owner:', owner)
2. setOwner(domain, newController)​
Transfers domain ownership to a new controller.
const domain = 'mydomain.rsk'
const newController = '0xb774...d771'
const tx = await rns.setOwner(domain, newController)
await tx.wait()
console.log('Ownership transferred!')
3. resolver(domain)​
Gets the resolver contract address for a domain.
const resolverAddress = await rns.resolver('mydomain.rsk')
console.log('Resolver:', resolverAddress)
4. setResolver(domain, resolverAddress)​
Sets a new resolver contract for the domain.
const domain = 'mydomain.rsk'
const resolverAddr = '0xb774...d771'
const tx = await rns.setResolver(domain, resolverAddr)
await tx.wait()
console.log('Resolver updated!')
5. getSubdomainAvailability(domain, label)​
Checks if a subdomain is available under a parent domain.
const isAvailable = await rns.getSubdomainAvailability('mydomain.rsk', 'blog')
console.log(isAvailable ? 'Subdomain available!' : 'Subdomain taken')
6. setSubdomainOwner(domain, label, ownerAddress)​
Creates a subdomain and assigns ownership.
const domain = 'mydomain.rsk'
const subdomainLabel = 'blog'
const ownerAddress = '0x8c0f...1264'
const tx = await rns.setSubdomainOwner(domain, subdomainLabel, ownerAddress)
await tx.wait()
console.log('Subdomain created: blog.mydomain.rsk')
You must own the parent domain to create subdomains.
2. AddrResolver Class​
The AddrResolver class handles address resolution for domains.
Constructor​
import { Signer } from 'ethers'
import { AddrResolver } from '@rsksmart/rns-sdk'
let signer: Signer
const addrResolver = new AddrResolver(registryAddress, signer)
Methods​
1. addr(domain)​
Resolves a domain to its linked address.
const address = await addrResolver.addr('mydomain.rsk')
console.log('Address:', address)
2. setAddr(domain, address)​
Sets or updates the address a domain points to.
const domain = 'mydomain.rsk'
const newAddress = '0xABCD...7890'
const tx = await addrResolver.setAddr(domain, newAddress)
await tx.wait()
console.log('Address updated!')
You must own the domain to set its address.
3. RSKRegistrar Class​
The RSKRegistrar class handles standard .rsk domain registration using RIF tokens.
Constructor​
import { Signer } from 'ethers'
import { RSKRegistrar } from '@rsksmart/rns-sdk'
let signer: Signer
const rskRegistrar = new RSKRegistrar(
rskOwnerAddress,
fifsAddrRegistrarAddress,
rifTokenAddress,
signer
)
Methods​
1. available(label)​
Checks if a domain label is available for registration.
const label = 'mynewdomain'
const isAvailable = await rskRegistrar.available(label)
console.log(isAvailable ? 'Available!' : 'Already registered')
Pass only the label without .rsk suffix.
2. price(label, duration)​
Gets the registration price in RIF tokens.
import { BigNumber } from 'ethers'
const label = 'mynewdomain'
const duration = BigNumber.from('1') // 1 year
const price = await rskRegistrar.price(label, duration)
console.log('Price:', ethers.utils.formatEther(price), 'RIF')
3. commitToRegister(label, ownerAddress)​
Step 1 of registration: Makes a commitment to register a domain.
const label = 'mynewdomain'
const ownerAddress = '0x1234...5678'
const { makeCommitmentTransaction, secret, canReveal } =
await rskRegistrar.commitToRegister(label, ownerAddress)
await makeCommitmentTransaction.wait()
console.log('Commitment made! Wait ~1 minute before registering.')
// Save the secret - you'll need it for step 2
Returns:
| Property | Description |
|---|---|
makeCommitmentTransaction | The commitment transaction object |
secret | Secret needed for registration (save this!) |
canReveal() | Function to check if ready to register |
4. register(label, owner, secret, duration, price)​
Step 2 of registration: Completes the domain registration.
// Wait for commitment to be ready (at least 1 minute)
const isReady = await canReveal()
if (!isReady) {
console.log('Please wait, commitment not ready yet')
return
}
const registerTx = await rskRegistrar.register(
label,
ownerAddress,
secret, // from commitToRegister()
duration,
price
)
await registerTx.wait()
console.log('Domain registered successfully!')
Complete Registration Example​
import { BigNumber, ethers } from 'ethers'
import { RSKRegistrar } from '@rsksmart/rns-sdk'
async function registerDomain(label, ownerAddress, signer) {
const rskRegistrar = new RSKRegistrar(
rskOwnerAddress,
fifsAddrRegistrarAddress,
rifTokenAddress,
signer
)
// Check availability
const available = await rskRegistrar.available(label)
if (!available) {
throw new Error('Domain not available')
}
// Get price
const duration = BigNumber.from('1')
const price = await rskRegistrar.price(label, duration)
console.log('Price:', ethers.utils.formatEther(price), 'RIF')
// Step 1: Commit
const { makeCommitmentTransaction, secret, canReveal } =
await rskRegistrar.commitToRegister(label, ownerAddress)
await makeCommitmentTransaction.wait()
console.log('Commitment made!')
// Wait for commitment to mature (poll canReveal)
while (!(await canReveal())) {
console.log('Waiting for commitment...')
await new Promise(r => setTimeout(r, 10000)) // Wait 10 seconds
}
// Step 2: Register
const registerTx = await rskRegistrar.register(
label,
ownerAddress,
secret,
duration,
price
)
await registerTx.wait()
console.log(`Successfully registered ${label}.rsk!`)
}
4. PartnerRegistrar Class​
The PartnerRegistrar class provides partner-based registration with one-click registration support.
Constructor​
import { Signer } from 'ethers'
import { PartnerRegistrar } from '@rsksmart/rns-sdk'
let signer: Signer
// Option 1: Use network presets (recommended)
const partnerRegistrar = new PartnerRegistrar(signer, 'testnet')
// Option 2: Custom addresses (for localhost or custom setup)
const partnerRegistrar = new PartnerRegistrar(signer, 'localhost', {
rskOwnerAddress: '0x...',
rifTokenAddress: '0x...',
partnerRegistrarAddress: '0x...',
partnerRenewerAddress: '0x...',
partnerAddress: '0x...'
})
Network Options:
| Value | Description |
|---|---|
'mainnet' | RSK Mainnet (uses default addresses) |
'testnet' | RSK Testnet (uses default addresses) |
'localhost' | Local network (requires custom addresses) |
Methods​
1. available(label)​
Checks if a domain is available.
const available = await partnerRegistrar.available('mynewdomain')
console.log(available ? 'Available!' : 'Taken')
2. price(label, duration)​
Gets the price with partner pricing applied.
import { BigNumber } from 'ethers'
const duration = BigNumber.from('1')
const price = await partnerRegistrar.price('mynewdomain', duration)
console.log('Partner price:', ethers.utils.formatEther(price), 'RIF')
3. commitAndRegister(label, owner, duration, price)​
One-click registration - handles both commit and register in one call.
import { BigNumber } from 'ethers'
const label = 'mynewdomain'
const ownerAddress = '0x1234...5678'
const duration = BigNumber.from('1')
const price = await partnerRegistrar.price(label, duration)
const { commitHash, commitSecret, registerTxHash } =
await partnerRegistrar.commitAndRegister(label, ownerAddress, duration, price)
console.log('Domain registered!')
console.log('Commit hash:', commitHash)
console.log('Register TX:', registerTxHash)
4. transfer(label, toAddress)​
Transfers domain ownership to another address.
const label = 'mydomain'
const toAddress = '0xABCD...7890'
const txHash = await partnerRegistrar.transfer(label, toAddress)
console.log('Domain transferred! TX:', txHash)
5. renew(label, duration, price)​
Renews a domain registration.
import { BigNumber } from 'ethers'
const label = 'mydomain'
const duration = BigNumber.from('1')
const price = await partnerRegistrar.price(label, duration)
const txHash = await partnerRegistrar.renew(label, duration, price)
console.log('Domain renewed! TX:', txHash)
5. PartnerConfiguration Class​
The PartnerConfiguration class queries partner contract settings.
Constructor​
import { Signer } from 'ethers'
import { PartnerConfiguration } from '@rsksmart/rns-sdk'
let signer: Signer
const partnerConfig = new PartnerConfiguration(partnerConfigurationAddress, signer)
Methods​
1. getMinLength()​
Gets the minimum allowed domain label length.
const minLength = await partnerConfig.getMinLength()
console.log('Min length:', minLength.toString())
2. getMaxLength()​
Gets the maximum allowed domain label length.
const maxLength = await partnerConfig.getMaxLength()
console.log('Max length:', maxLength.toString())
3. getMinDuration()​
Gets the minimum registration duration (in years).
const minDuration = await partnerConfig.getMinDuration()
console.log('Min duration:', minDuration.toString(), 'years')
getMaxDuration()​
Gets the maximum registration duration (in years).
const maxDuration = await partnerConfig.getMaxDuration()
console.log('Max duration:', maxDuration.toString(), 'years')
4. getMinCommitmentAge()​
Gets the minimum time (in seconds) before a commitment can be revealed.
const minAge = await partnerConfig.getMinCommitmentAge()
console.log('Min commitment age:', minAge.toString(), 'seconds')
5. getFeePercentage()​
Gets the partner fee percentage.
const fee = await partnerConfig.getFeePercentage()
console.log('Fee percentage:', fee.toString(), '%')
6. getDiscount()​
Gets the partner discount percentage.
const discount = await partnerConfig.getDiscount()
console.log('Discount:', discount.toString(), '%')
7. getPrice(label, duration)​
Gets the price for a domain with partner pricing.
import { BigNumber } from 'ethers'
const price = await partnerConfig.getPrice('mydomain', BigNumber.from('1'))
console.log('Price:', ethers.utils.formatEther(price), 'RIF')
8. validateName(label, duration)​
Validates if a name meets partner requirements. Throws an error if invalid.
import { BigNumber } from 'ethers'
try {
await partnerConfig.validateName('mydomain', BigNumber.from('1'))
console.log('Name is valid!')
} catch (error) {
console.log('Invalid name:', error.message)
}
Name Validation​
The SDK automatically validates and normalizes domain names:
Validation Rules:
- Names can only contain letters (a-z), digits (0-9), and hyphens (-)
- Names must start and end with a letter or digit
Normalization:
- All letters are converted to lowercase
- Punycode-encoded internationalized domain names (IDNs) are expanded to Unicode
Troubleshooting​
Browser Environment​
The SDK requires Buffer to be globally available. Add this to your webpack config:
const webpack = require('webpack')
module.exports = {
resolve: {
fallback: {
buffer: require.resolve('buffer/'),
},
},
plugins: [
new webpack.ProvidePlugin({
Buffer: ['buffer', 'Buffer'],
}),
],
}
Or add this to your app's entry point:
window.Buffer = window.Buffer || require('buffer/').Buffer
React Native​
Use the rn-nodeify package:
rn-nodeify --install buffer --hack --yarn && patch-package
Additional Resources​
- RNS Resolver Library: For advanced resolution features (reverse lookup, multi-chain), see
@rsksmart/rns-resolver.js - GitHub Repository: rsksmart/rns-sdk
- RNS Registry Testnet: Explorer
- RNS Registry Mainnet: Explorer