Docs

Introduction

What is Rob Domains and how does it work?

Rob Domains is a decentralized name system built on Robinhood Chain. Every .rob domain is an ERC-721 NFT minted directly to your wallet. No central authority can revoke, reassign, or expire it.

True Ownership

ERC-721 NFT on Robinhood Chain. Yours forever.

On-Chain Profiles

Bio, links, and images stored permanently on-chain.

Resolver Layer

Forward and reverse resolution for wallets and dApps.

Marketplace

Non-custodial peer-to-peer domain trading.

Architecture

How the system components fit together

DomainMarketplace.solDeployed

Marketplace Contract

Non-custodial offer/accept marketplace. Holds ETH escrow in-contract. No custody by Rob Domains team.

DomainNFT.solDeployed

Core NFT Contract

ERC-721 contract that owns all domain data — name, profile, social links, custom links. Deployed and immutable.

DomainChat.solDeployed

Chat Contract

Decentralized messaging protocol for domain owners.

RobResolver.solDeployed

Resolver Contract

Independent resolver for forward/reverse resolution and primary domain registration. Reads DomainNFT via interface.

Design principle: The Resolver is completely independent from the DomainNFT. It interacts through the IDomainNFT interface and never modifies NFT storage. Future upgrades to resolution logic can be deployed as new Resolver contracts without touching the NFT contract.

Smart Contracts

Contract addresses and key interfaces

Robinhood Chain

Chain ID4663
RPC URLhttps://rpc.mainnet.chain.robinhood.com
Explorerhttps://robinhoodchain.blockscout.com
Native TokenETH

Contract Addresses

DomainNFT0x37F7ba486afE8Be3C3C70A4FC3eCacC6DD51c6C8Live
DomainMarketplace0xAefec6e65ADE8D95c0Cf69D20e9254556f6cC637Live
DomainChat0xB96eCa3BE710aFC822e2342D0bCae7103371dE81Live
RobResolver0xeDe40500f6047F2Ef8d8F5dec12F096969A1bF47Live

Key DomainNFT Functions

solidity
// Minting
function isAvailable(string memory domainName) view returns (bool)
function mintDomain(string memory domainName) payable returns (uint256)
function mintFee() view returns (uint256)

// Resolution
function getTokenIdByName(string memory domainName) view returns (uint256)
function getNameByTokenId(uint256 tokenId) view returns (string)
function getFullDomainName(uint256 tokenId) view returns (string)
function getDomainsOfOwner(address owner) view returns (uint256[])

// Profile
function getProfile(uint256 tokenId) view returns (
  string domainName, address owner,
  string profilePicture, string coverImage,
  string bio, string background,
  SocialLink[] socialLinks, CustomLink[] customLinks
)
function updateProfile(uint256 tokenId, string profilePicture,
  string coverImage, string bio, string background)

Key RobResolver Functions

solidity
// Primary domain — write (requires ownership)
function setPrimaryDomain(uint256 tokenId) external
function clearPrimaryDomain() external

// Primary domain — read
function getPrimaryToken(address wallet) view returns (uint256)
function getPrimaryDomain(address wallet) view returns (string)
function hasPrimaryDomain(address wallet) view returns (bool)
function isPrimaryOwner(address wallet, uint256 tokenId) view returns (bool)

// Resolution
function reverseResolve(address wallet) view returns (
  uint256 tokenId, string domainName, string fullDomain
)
function resolve(string domain) view returns (
  address owner, uint256 tokenId, string fullDomain
)

// Future records (reserved — returns safe defaults now)
function getTextRecord(uint256 tokenId, string key) view returns (string)
function getAddressRecord(uint256 tokenId, uint256 coinType) view returns (address)
function getContentHash(uint256 tokenId) view returns (bytes)

Resolver Standard

How resolution works in the .rob name system

Forward Resolution

Maps a human-readable .rob domain to its owner address and token ID. Delegates directly to the DomainNFT contract — always reflects current on-chain state.

text
alice.rob  ──resolve()──►  { owner: "0xAlice...", tokenId: 42, fullDomain: "alice.rob" }

Reverse Resolution

Maps a wallet address to its self-designated primary .rob domain. Ownership is re-verified on every call — stale data is never returned.

text
0xAlice...  ──reverseResolve()──►  { tokenId: 42, domainName: "alice", fullDomain: "alice.rob" }

If ownership transferred since setPrimaryDomain() was called:
0xAlice...  ──reverseResolve()──►  { tokenId: 0, domainName: "", fullDomain: "" }

Primary Domains

When a wallet owns multiple .rob domains it can designate one as its Primary Domain. This is the domain shown in wallets and block explorers via reverse resolution.

solidity
// Set primary — caller must own tokenId
resolver.setPrimaryDomain(42);

// Clear primary
resolver.clearPrimaryDomain();

// Check primary
resolver.hasPrimaryDomain(wallet);          // → true/false
resolver.getPrimaryDomain(wallet);          // → "alice"
resolver.getPrimaryToken(wallet);           // → 42
resolver.isPrimaryOwner(wallet, 42);        // → true

Future Record Types

The RobResolver storage layout reserves space for ENS-compatible record types. These are read-only stubs today — they return safe defaults without reverting.

Record TypeKey / Coin TypeExampleStatus
Text recordavataripfs://Qm...Reserved
Text recorddescriptionOn-chain identityReserved
Text recordcom.twitter@aliceReserved
Text recordcom.githubaliceReserved
Address recordSLIP-44: 60 (ETH)0xAlice...Reserved
Address recordSLIP-44: 0 (BTC)bc1q...Reserved
Address recordSLIP-44: 501 (SOL)Gh7k...Reserved
Content hashIPFS CID / ENS encodingipfs://Qm...Reserved
Avatar hashavatarHashQm...Reserved

Resolution APIs

HTTP endpoints for resolution, profiles, and ownership

All endpoints are served from the Rob Domains Next.js application. Responses follow the standard envelope:

json
{
  "ok": true,
  "data": { ... },
  "meta": { "chain": "Robinhood", "chainId": 4663, "timestamp": "2024-01-01T00:00:00Z" }
}

// Errors:
{ "ok": false, "error": "Domain not found or not yet minted", "code": 404 }
GET
/api/resolve/:domain

Forward resolution — maps a .rob domain name to its owner and token ID.

Live
GET
/api/reverse/:wallet

Reverse resolution — maps a wallet address to its primary .rob domain (requires RobResolver).

Live
GET
/api/profile/:domain

Returns the full on-chain profile: bio, social links, custom links, images.

Live
GET
/api/token/:tokenId

Returns profile data by ERC-721 token ID.

Live
GET
/api/owner/:wallet

Returns all .rob domains owned by a wallet.

Live
GET
/api/primary/:wallet

Returns the primary .rob domain for a wallet (requires RobResolver).

Live
GET
/api/records/:domain

Returns all records for a domain: profile fields, social links, text records.

Live

Example Responses

json
// GET /api/resolve/alice
{
  "ok": true,
  "data": {
    "domain": "alice",
    "owner": "0xAbCd...1234",
    "tokenId": "42",
    "fullDomain": "alice.rob"
  },
  "meta": { "chain": "Robinhood", "chainId": 4663, "timestamp": "..." }
}

// GET /api/profile/alice
{
  "ok": true,
  "data": {
    "domain": "alice",
    "owner": "0xAbCd...1234",
    "tokenId": "42",
    "fullDomain": "alice.rob",
    "profile": {
      "bio": "Building on Robinhood Chain",
      "profilePicture": "https://...",
      "socialLinks": [{ "platform": "twitter", "url": "https://twitter.com/alice", "icon": "twitter" }],
      "customLinks": [{ "title": "My Website", "url": "https://alice.xyz" }]
    }
  }
}

// GET /api/owner/0xAbCd...1234
{
  "ok": true,
  "data": {
    "wallet": "0xAbCd...1234",
    "count": 3,
    "domains": [
      { "tokenId": "42", "domain": "alice", "fullDomain": "alice.rob" },
      { "tokenId": "57", "domain": "alicedev", "fullDomain": "alicedev.rob" }
    ]
  }
}

Agent APIs

AI agent endpoints — status, OpenAPI spec, and unsigned transaction generation

The Agent API provides AI-agent-friendly endpoints for health checks, machine-readable spec discovery, and unsigned transaction payload generation. No authentication is required. Transaction endpoints return payloads only — the user's wallet must sign and broadcast independently.

AI plugin manifest: /.well-known/ai-plugin.json  ·  OpenAPI spec: /agent/docs/openapi.yaml  ·  MCP manifest: /mcp/robdomains-mcp.json

GET
/agent/status

Health check — returns API status, chain connectivity, and live contract addresses.

Live
GET
/agent/docs/openapi.yaml

OpenAPI 3.1 specification (YAML). Import into ChatGPT, Cursor, or any OpenAPI-compatible tool.

Live
POST
/agent/tx/mint

Generate an unsigned mint transaction payload. Body: { domain: string }.

Live
POST
/agent/tx/set-primary

Generate an unsigned set-primary-domain transaction. Body: { tokenId: number, wallet: string }.

Live
POST
/agent/tx/update-profile

Generate an unsigned update-profile transaction. Body: { tokenId, bio, profilePicture, coverImage, background }.

Live
POST
/agent/tx/transfer

Generate an unsigned ERC-721 transfer transaction. Body: { tokenId: number, from: string, to: string }.

Live

Example: Status Response

json
// GET /agent/status
{
  "ok": true,
  "status": "operational",
  "chain": "Robinhood",
  "chainId": 4663,
  "contracts": {
    "domainNFT": "0x37F7ba486afE8Be3C3C70A4FC3eCacC6DD51c6C8",
    "marketplace": "0xAefec6e65ADE8D95c0Cf69D20e9254556f6cC637"
  },
  "timestamp": "2026-07-21T00:00:00Z"
}

Example: Mint Transaction Payload

json
// POST /agent/tx/mint  { "domain": "alice" }
{
  "ok": true,
  "transaction": {
    "to": "0x37F7ba486afE8Be3C3C70A4FC3eCacC6DD51c6C8",
    "data": "0x...",
    "value": "500000000000000",
    "chainId": 4663
  },
  "domain": "alice",
  "fullDomain": "alice.rob",
  "mintFee": "0.0005 ETH"
}

Future APIs

Planned endpoints — documented now, arriving in upcoming releases

These endpoints are planned and documented here for integrators to prepare against. They will return 501 Not Implemented until the underlying contract or indexer infrastructure is ready.

GET
/api/text/:domain/:key

Returns a text record by key (avatar, email, twitter…)

Coming Soon
GET
/api/address/:domain/:coin

Returns the address record for a coin type (ETH, BTC, SOL)

Coming Soon
GET
/api/avatar/:domain

Returns the resolved avatar URL for a domain

Coming Soon
GET
/api/contenthash/:domain

Returns the IPFS / content hash for a domain

Coming Soon
GET
/api/multicall

Batch multiple resolution calls in a single HTTP request

Coming Soon
GET
/api/batch-resolve

Resolve multiple domain names in one request

Coming Soon
GET
/api/search

Full-text search across registered domains

Coming Soon
GET
/api/metadata/:tokenId

ERC-721 metadata JSON for OpenSea / wallets

Coming Soon
GET
/api/verify/:domain/:wallet

Verify that a wallet currently owns a domain

Coming Soon
GET
/api/stats

Protocol statistics: total domains, daily mints, floor price

Coming Soon
GET
/api/market/history/:domain

Historical marketplace sales for a domain

Coming Soon
GET
/api/market/sales

Global sales feed ordered by recency

Coming Soon
GET
/api/activity/:domain

Full on-chain activity log for a domain

Coming Soon
GET
/api/qr/:domain

Returns a QR code image for a profile URL

Coming Soon
GET
/api/og/:domain

OpenGraph card image for social sharing

Coming Soon

SDK & Examples

Code samples in JavaScript, TypeScript, ethers v6, and viem

Installation

bash
npm install ethers viem @rainbow-me/rainbowkit wagmi

Forward Resolution — ethers v6

typescript
import { ethers } from "ethers";

const DOMAIN_NFT = "0x37F7ba486afE8Be3C3C70A4FC3eCacC6DD51c6C8";
const RPC        = "https://rpc.mainnet.chain.robinhood.com";

const DOMAIN_NFT_ABI = [
  "function getTokenIdByName(string) view returns (uint256)",
  "function ownerOf(uint256) view returns (address)",
  "function getFullDomainName(uint256) view returns (string)",
];

async function resolve(domain: string) {
  const provider = new ethers.JsonRpcProvider(RPC);
  const nft = new ethers.Contract(DOMAIN_NFT, DOMAIN_NFT_ABI, provider);

  const tokenId = await nft.getTokenIdByName(domain.replace(/\.rob$/, ""));
  if (tokenId === 0n) return null;

  const owner      = await nft.ownerOf(tokenId);
  const fullDomain = await nft.getFullDomainName(tokenId);
  return { owner, tokenId: tokenId.toString(), fullDomain };
}

const result = await resolve("alice");
console.log(result);
// → { owner: "0xAbCd…", tokenId: "42", fullDomain: "alice.rob" }

Reverse Resolution — ethers v6

typescript
const RESOLVER_ABI = [
  "function reverseResolve(address) view returns (uint256, string, string)",
  "function hasPrimaryDomain(address) view returns (bool)",
];

async function reverseResolve(wallet: string) {
  const provider = new ethers.JsonRpcProvider(RPC);
  const resolver = new ethers.Contract(RESOLVER_ADDRESS, RESOLVER_ABI, provider);

  const has = await resolver.hasPrimaryDomain(wallet);
  if (!has) return null;

  const [tokenId, domainName, fullDomain] = await resolver.reverseResolve(wallet);
  return { tokenId: tokenId.toString(), domainName, fullDomain };
}

Forward Resolution — viem

typescript
import { createPublicClient, http, defineChain } from "viem";

const robinhoodChain = defineChain({
  id: 4663,
  name: "Robinhood",
  nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
  rpcUrls: { default: { http: ["https://rpc.mainnet.chain.robinhood.com"] } },
  blockExplorers: { default: { name: "Blockscout", url: "https://robinhoodchain.blockscout.com" } },
});

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

const tokenId = await client.readContract({
  address: "0x37F7ba486afE8Be3C3C70A4FC3eCacC6DD51c6C8",
  abi: [{ name: "getTokenIdByName", type: "function",
    inputs: [{ name: "domainName", type: "string" }],
    outputs: [{ name: "", type: "uint256" }], stateMutability: "view" }],
  functionName: "getTokenIdByName",
  args: ["alice"],
});

HTTP API — JavaScript fetch

javascript
// Forward resolve
const res = await fetch("/api/resolve/alice");
const { data } = await res.json();
console.log(data.owner, data.tokenId);

// Reverse resolve
const r2 = await fetch("/api/reverse/0xAbCd...1234");
const { data: d2 } = await r2.json();
console.log(d2.fullDomain); // "alice.rob"

// Full profile
const r3 = await fetch("/api/profile/alice");
const { data: d3 } = await r3.json();
console.log(d3.profile.bio, d3.profile.socialLinks);

// All domains for a wallet
const r4 = await fetch("/api/owner/0xAbCd...1234");
const { data: d4 } = await r4.json();
console.log(d4.count, d4.domains);

Set Primary Domain — ethers v6

typescript
const RESOLVER_ABI = [
  "function setPrimaryDomain(uint256 tokenId) external",
  "function clearPrimaryDomain() external",
];

// Connect a signer (user wallet)
const provider = new ethers.BrowserProvider(window.ethereum);
const signer   = await provider.getSigner();
const resolver = new ethers.Contract(RESOLVER_ADDRESS, RESOLVER_ABI, signer);

// Set token #42 as primary
const tx = await resolver.setPrimaryDomain(42);
await tx.wait();
console.log("Primary domain set on-chain");

// Clear primary domain
const tx2 = await resolver.clearPrimaryDomain();
await tx2.wait();

Integration Guides

How to integrate Rob Domains into wallets, explorers, and dApps

Wallet Integration

Display a human-readable .rob name in place of raw wallet addresses using reverse resolution.

  1. 1.Call GET /api/reverse/{wallet} or reverseResolve() on the RobResolver contract
  2. 2.If the wallet has a primary domain, display it as "alice.rob" in place of "0xAbCd…"
  3. 3.Fall back to the shortened address when no primary domain is set
  4. 4.Cache results for 30–60 seconds; re-fetch on block confirmations

Block Explorer Integration

Show human-readable .rob names on address pages and transaction lists.

  1. 1.For each address, call GET /api/reverse/{address} to check for a primary domain
  2. 2.Display "alice.rob" as the label alongside the address
  3. 3.Link the name to the Rob Domains profile: robdn.com/alice
  4. 4.For domain pages, call GET /api/profile/{domain} to show profile details

dApp Integration

Resolve .rob names entered by users as recipients or identifiers.

  1. 1.When a user types a .rob name, call GET /api/resolve/{domain}
  2. 2.Use the returned owner address for the on-chain transaction
  3. 3.Display "alice.rob → 0xAbCd…" for transparency before signing
  4. 4.Always re-verify ownership immediately before sending funds

Profile Lookup

Fetch rich profile data (bio, avatar, social links) for any .rob domain.

  1. 1.Call GET /api/profile/{domain} to get the full profile
  2. 2.Render profilePicture as the avatar
  3. 3.Link socialLinks to their respective platforms
  4. 4.Use customLinks to build a link-in-bio style display

Payment Systems

Accept .rob domain names as payment destinations.

  1. 1.Allow users to enter a .rob name in the "Send to" field
  2. 2.Resolve the name to an address via GET /api/resolve/{domain}
  3. 3.Confirm the resolved address with the user before submitting
  4. 4.Re-verify ownership at transaction time to guard against transfers

OpenAPI

Machine-readable API specification

The full OpenAPI 3.1 specification is live and served at /agent/docs/openapi.yaml with Content-Type: application/yaml. Import it into ChatGPT, Cursor, Swagger UI, or any OpenAPI-compatible tool. Below is an abridged view of the Resolution API paths.

yaml
openapi: "3.1.0"
info:
  title: Rob Domains Resolution API
  version: "1.0.0"
  description: HTTP API for resolving .rob domain names on Robinhood Chain

servers:
  - url: https://robdn.com
    description: Production

paths:
  /api/resolve/{domain}:
    get:
      summary: Forward resolution
      parameters:
        - name: domain
          in: path
          required: true
          schema: { type: string, example: "alice" }
      responses:
        "200":
          description: Resolved domain
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ResolveResponse"
        "404":
          description: Domain not found

  /api/reverse/{wallet}:
    get:
      summary: Reverse resolution
      parameters:
        - name: wallet
          in: path
          required: true
          schema: { type: string, example: "0xAbCd...1234" }
      responses:
        "200":
          description: Primary domain for wallet

components:
  schemas:
    ResolveResponse:
      type: object
      properties:
        ok: { type: boolean }
        data:
          type: object
          properties:
            domain: { type: string }
            owner:  { type: string }
            tokenId: { type: string }
            fullDomain: { type: string }
        meta:
          type: object
          properties:
            chain:    { type: string }
            chainId:  { type: integer }
            timestamp: { type: string, format: date-time }

Security

How Rob Domains protects user assets

Non-Custodial

Domain NFTs are held in user wallets. Rob Domains never has custody of your tokens or funds.

Ownership Verified On Every Call

The Resolver re-verifies token ownership on every read — stale reverse-resolve data is never returned.

Independent Resolver

The RobResolver is deployed separately and cannot modify any DomainNFT state.

Marketplace Escrow On-Chain

Offer amounts are held in the DomainMarketplace contract itself, not by any third party.

Reentrancy Protection

The Marketplace uses a reentrancy guard pattern. Profile-only functions in DomainNFT carry no ETH risk.

No Upgrade Proxy

Contracts are deployed without proxy patterns. Code is immutable once deployed — no admin backdoor.

Roadmap

What's live today and what's coming next

Phase 1 — Core

Completed
  • ERC-721 domain NFT contract
  • On-chain profile storage
  • Domain minting at 0.0005 ETH
  • Social & custom links
  • Primary domain (localStorage)
  • Animated profile backgrounds

Phase 2 — Marketplace

Completed
  • Non-custodial marketplace
  • Peer-to-peer offers system
  • Direct domain transfers
  • IPFS metadata via Pinata
  • NFT visibility on OpenSea
  • QR code profile sharing
  • Farcaster mini-app integration

Phase 3 — Resolver & Agent APIs

Completed
  • RobResolver smart contract
  • On-chain primary domain registration
  • Forward & reverse resolution
  • Resolution HTTP API (/api/resolve, /api/reverse…)
  • Developer documentation (this page)
  • SDK examples (TypeScript, JavaScript, Python)
  • Agent APIs with transaction generation
  • OpenAPI 3.1 specification (live)
  • AI plugin manifest (/.well-known/ai-plugin.json)
  • MCP manifest (/mcp/robdomains-mcp.json)

Phase 4 — Records & Integrations

Planned
  • Text records (avatar, email, social handles)
  • Multi-coin address records (ETH, BTC, SOL)
  • Content hash / IPFS records
  • ENS compatibility layer
  • CCIP-Read support
  • Wallet & explorer integrations
  • Full OpenAPI spec

Phase 5 — Scale

Planned
  • Subdomain support
  • Batch minting & batch resolution
  • Cross-chain bridge support
  • Domain portfolio analytics
  • Mobile app
  • On-chain verification badges