The [`@rsksmart/rns-sdk`](https://github.com/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: ```bash 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: ```js 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 ```js let signer: Signer const rns = new RNS(registryAddress, signer) ``` ### Methods #### 1. [`getOwner(domain)`](https://github.com/rsksmart/rns-sdk?tab=readme-ov-file#owner) Gets the controller/owner of a domain. ```js const owner = await rns.getOwner('mydomain.rsk') console.log('Owner:', owner) ``` #### 2. [`setOwner(domain, newController)`](https://github.com/rsksmart/rns-sdk?tab=readme-ov-file#owner) Transfers domain ownership to a new controller. ```js 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)`](https://github.com/rsksmart/rns-sdk?tab=readme-ov-file#resolver) Gets the resolver contract address for a domain. ```js const resolverAddress = await rns.resolver('mydomain.rsk') console.log('Resolver:', resolverAddress) ``` #### 4. [`setResolver(domain, resolverAddress)`](https://github.com/rsksmart/rns-sdk?tab=readme-ov-file#resolver) Sets a new resolver contract for the domain. ```js 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)`](https://github.com/rsksmart/rns-sdk?tab=readme-ov-file#subdomains) Checks if a subdomain is available under a parent domain. ```js const isAvailable = await rns.getSubdomainAvailability('mydomain.rsk', 'blog') console.log(isAvailable ? 'Subdomain available!' : 'Subdomain taken') ``` #### 6. [`setSubdomainOwner(domain, label, ownerAddress)`](https://github.com/rsksmart/rns-sdk?tab=readme-ov-file#subdomains) Creates a subdomain and assigns ownership. ```js 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') ``` :::note You must own the parent domain to create subdomains. ::: --- ## 2. AddrResolver Class The [`AddrResolver`](https://github.com/rsksmart/rns-sdk?tab=readme-ov-file#address-resolution) class handles address resolution for domains. ### Constructor ```js let signer: Signer const addrResolver = new AddrResolver(registryAddress, signer) ``` ### Methods #### 1. [`addr(domain)`](https://github.com/rsksmart/rns-sdk?tab=readme-ov-file#address-resolution) Resolves a domain to its linked address. ```js const address = await addrResolver.addr('mydomain.rsk') console.log('Address:', address) ``` #### 2. [`setAddr(domain, address)`](https://github.com/rsksmart/rns-sdk?tab=readme-ov-file#address-resolution) Sets or updates the address a domain points to. ```js const domain = 'mydomain.rsk' const newAddress = '0xABCD...7890' const tx = await addrResolver.setAddr(domain, newAddress) await tx.wait() console.log('Address updated!') ``` :::note You must own the domain to set its address. ::: --- ## 3. RSKRegistrar Class The [`RSKRegistrar`](https://github.com/rsksmart/rns-sdk?tab=readme-ov-file#1-using-the-rskregistrar) class handles standard `.rsk` domain registration using RIF tokens. ### Constructor ```js let signer: Signer const rskRegistrar = new RSKRegistrar( rskOwnerAddress, fifsAddrRegistrarAddress, rifTokenAddress, signer ) ``` ### Methods #### 1. `available(label)` Checks if a domain label is available for registration. ```js const label = 'mynewdomain' const isAvailable = await rskRegistrar.available(label) console.log(isAvailable ? 'Available!' : 'Already registered') ``` :::note Pass only the label without `.rsk` suffix. ::: #### 2. `price(label, duration)` Gets the registration price in RIF tokens. ```js 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. ```js 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. ```js // 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 ```js 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 ```js 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. ```js const available = await partnerRegistrar.available('mynewdomain') console.log(available ? 'Available!' : 'Taken') ``` #### 2. `price(label, duration)` Gets the price with partner pricing applied. ```js 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. ```js 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. ```js 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. ```js 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 ```js let signer: Signer const partnerConfig = new PartnerConfiguration(partnerConfigurationAddress, signer) ``` ### Methods #### 1. `getMinLength()` Gets the minimum allowed domain label length. ```js const minLength = await partnerConfig.getMinLength() console.log('Min length:', minLength.toString()) ``` #### 2. `getMaxLength()` Gets the maximum allowed domain label length. ```js const maxLength = await partnerConfig.getMaxLength() console.log('Max length:', maxLength.toString()) ``` #### 3. `getMinDuration()` Gets the minimum registration duration (in years). ```js const minDuration = await partnerConfig.getMinDuration() console.log('Min duration:', minDuration.toString(), 'years') ``` #### `getMaxDuration()` Gets the maximum registration duration (in years). ```js 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. ```js const minAge = await partnerConfig.getMinCommitmentAge() console.log('Min commitment age:', minAge.toString(), 'seconds') ``` #### 5. `getFeePercentage()` Gets the partner fee percentage. ```js const fee = await partnerConfig.getFeePercentage() console.log('Fee percentage:', fee.toString(), '%') ``` #### 6. `getDiscount()` Gets the partner discount percentage. ```js const discount = await partnerConfig.getDiscount() console.log('Discount:', discount.toString(), '%') ``` #### 7. `getPrice(label, duration)` Gets the price for a domain with partner pricing. ```js 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. ```js 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: ```js 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: ```js window.Buffer = window.Buffer || require('buffer/').Buffer ``` ### React Native Use the `rn-nodeify` package: ```bash 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`](https://github.com/rsksmart/rns-resolver.js) - **GitHub Repository**: [rsksmart/rns-sdk](https://github.com/rsksmart/rns-sdk) - **RNS Registry Testnet**: [Explorer](https://explorer.testnet.rootstock.io/address/0x7d284aaac6e925aad802a53c0c69efe3764597b8) - **RNS Registry Mainnet**: [Explorer](https://explorer.rootstock.io/address/0xcb868aeabd31e2b66f74e9a55cf064abb31a4ad5)