# hood-names — .hood names on Robinhood Chain > Permanent, fully on-chain names. `robin.hood` resolves to a wallet address. Every name is an ERC-721 token whose > metadata and card image are drawn by the contract itself. Reads are free and need no API key, indexer or signup. ## Networks and contracts | Network | Chain id | RPC | HoodNames (registry) | HoodMarket | |---|---|---|---|---| | Robinhood Chain | 4663 | https://rpc.mainnet.chain.robinhood.com | `0xF2F2aae8f045EE2806099C322Ca715F65E2409d5` | `0x4c2615c36328a1bF9F74b7e13C8fA0EE53F9210d` | | Robinhood Chain Testnet | 46630 | https://rpc.testnet.chain.robinhood.com | `0x7d99E42EBF68de1Bf54eC76e2AF85D6eEE1a3bAd` | `0xA70B48cc4a33E07e1cdc2934e27E1c931F42848a` | Both are verified on Sourcify (exact match). Explorers: https://robinhoodchain.blockscout.com and https://explorer.testnet.chain.robinhood.com. ## The two calls that matter ```solidity function resolve(string label) view returns (address) // name -> address, 0x0 when unregistered function primaryName(address account) view returns (string) // address -> label, "" when none is set ``` `label` is the part before `.hood`, lowercase. Pass `"robin"`, not `"robin.hood"`, when calling the contract directly; the SDK and the HTTP API accept either form. Everything else is optional: `available(label)`, `priceFor(label)`, `isValidLabel(label)`, `tokenIdOf(label)`, `labelOf(tokenId)`, `fullName(tokenId)`, `registeredAt(tokenId)`, `tokenURI(tokenId)`, plus the ERC-721 surface (`ownerOf`, `balanceOf`, `transferFrom`, …). ## Quick start ### SDK (TypeScript, viem) ```bash npm install hoodnames viem ``` ```ts import { createPublicClient, http } from "viem"; import { createHood, robinhoodMainnet } from "hoodnames"; const client = createPublicClient({ chain: robinhoodMainnet, transport: http() }); const hood = createHood(client); await hood.resolve("robin"); // "0x…" or null (accepts "robin" or "robin.hood") await hood.primaryName("0xAbC…"); // "robin.hood" or null await hood.lookup("robin"); // { label, name, owner, tokenId, registeredAt } or null await hood.available("robin"); // true / false await hood.priceFor("robin"); // 1000000000000000n (wei, one-time) await hood.listing("robin"); // { seller, price } or null ``` Every helper also exists standalone with the client as the first argument (`resolve(client, "robin")`), so bundlers can tree-shake. `decodeTokenURI(uri)` unpacks the on-chain metadata and SVG card. Pure helpers, no network: `normalize`, `validate`, `isValidLabel`, `tokenIdOf`, `fullName`, `tierOf`. The package also exports `robinhoodMainnet`, `robinhoodTestnet`, `deployments`, `hoodNamesAbi` and `hoodMarketAbi` for writes. ### Plain viem, no SDK ```ts import { createPublicClient, http, parseAbi } from "viem"; const NAMES = "0xF2F2aae8f045EE2806099C322Ca715F65E2409d5"; const abi = parseAbi([ "function resolve(string label) view returns (address)", "function primaryName(address account) view returns (string)", ]); const client = createPublicClient({ chain: { id: 4663, name: "Robinhood Chain", nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 }, rpcUrls: { default: { http: ["https://rpc.mainnet.chain.robinhood.com"] } } }, transport: http(), }); // name -> address const owner = await client.readContract({ address: NAMES, abi, functionName: "resolve", args: ["robin"] }); // address -> name (empty string means the address has no primary name) const label = await client.readContract({ address: NAMES, abi, functionName: "primaryName", args: [owner] }); ``` ### ethers ```ts import { Contract, JsonRpcProvider } from "ethers"; const provider = new JsonRpcProvider("https://rpc.mainnet.chain.robinhood.com", 4663); const names = new Contract("0xF2F2aae8f045EE2806099C322Ca715F65E2409d5", [ "function resolve(string) view returns (address)", "function primaryName(address) view returns (string)", ], provider); const owner = await names.resolve("robin"); const label = await names.primaryName(owner); ``` ### HTTP, no web3 library ``` GET https://www.hoodnames.lol/api/resolve/robin { "name": "robin.hood", "label": "robin", "network": "mainnet", "registered": true, "owner": "0x…", "tokenId": "0x…", "registeredAt": "2026-09-06T12:00:00.000Z" } GET https://www.hoodnames.lol/api/primary/0xAbC… { "address": "0xAbC…", "network": "mainnet", "name": "robin.hood", "label": "robin" } # add ?network=testnet for the testnet deployment ``` CORS is open, responses are cached for 30 seconds. The endpoints are a convenience layer over the same contract; for production resolution prefer reading the chain directly so you do not depend on this host. OpenAPI spec: https://www.hoodnames.lol/openapi.json ## Integration recipes ### Wallets ```js // A wallet's "send to" field: accept a .hood name wherever it accepts an address. async function resolveRecipient(input) { if (isAddress(input)) return input; if (!/\.hood$/i.test(input)) return null; const owner = await hood.resolve(input); // null when the name is unregistered return owner; } // Show the name instead of the hex, when the holder opted in: const display = (await hood.primaryName(account)) ?? shortAddress(account); ``` Two rules that keep users safe: resolve at send time rather than caching, and show the resolved address next to the name before the user confirms. A primary name is opt-in and revalidated on read, so a name that changed hands never displays for its former owner. ### Explorers and indexers ```js // Names are ERC-721 tokens; index them with the standard Transfer event plus one custom event. // HoodNames: // event NameRegistered(uint256 indexed tokenId, string label, address indexed owner, uint256 paid) // event PrimaryNameSet(address indexed account, uint256 indexed tokenId, string label) // event Transfer(address indexed from, address indexed to, uint256 indexed tokenId) // ERC-721 // HoodMarket: // event Listed(uint256 indexed tokenId, string label, address indexed seller, uint256 price) // event Unlisted(uint256 indexed tokenId, address indexed seller) // event Sold(uint256 indexed tokenId, string label, address indexed seller, address buyer, uint256 price, uint256 fee) // labelOf(tokenId) returns the label for any token, so an index can be rebuilt from Transfer alone. ``` An explorer typically needs address → name for account pages and name → address for search. Both are single view calls; no subgraph is required, though the events above make a full index cheap. ### Apps and bots Accept a name anywhere you accept an address, and display `primaryName` where you show a truncated hex. Registration and transfers are ordinary ERC-721 operations, so existing NFT tooling works unchanged. ## Name rules - 3 to 32 characters, `a-z`, `0-9` and hyphens; no leading or trailing hyphen. - Lowercase ASCII only. The contract rejects everything else, so there are no unicode look-alike names and normalization is a simple `toLowerCase()` plus stripping one trailing `.hood`. - Token id is `uint256(keccak256(bytes(label)))`. It is a hash of the label alone, not an ENS-style namehash. - Names are permanent: one payment, no expiry, no renewal, no grace period and no admin reclaim. Ownership only changes when the holder transfers or sells the token. - Fees at registration by length: 0.01 ETH for 3 characters, 0.005 ETH for 4, 0.001 ETH for 5 or more. - The marketplace is fixed-price. The seller keeps custody until the sale and pays a 2.5% fee. ## Fees and the token Registration fees (0.01 / 0.005 / 0.001 ETH by length) accrue in the HoodNames contract. Marketplace fees (2.5% of each sale, paid by the seller, capped at 10% in code) accrue in the HoodMarket contract. The stated plan is that marketplace fees buy HOOD on the open market and burn it, so each sale removes supply; registration fees are not part of that. As of today the HOOD token has not launched and the deployed contracts contain no burn logic, so fees simply accumulate and only the owner can withdraw them. Live totals: https://www.hoodnames.lol/token ## Cards `tokenURI(tokenId)` returns `data:application/json;base64,…` with an SVG image embedded as a data URI. Nothing is hosted off-chain, so the card renders from the chain alone. `decodeTokenURI` in the SDK returns `{ metadata, svg }`. ## Test vectors - HoodNames on mainnet: `0xF2F2aae8f045EE2806099C322Ca715F65E2409d5` - HoodMarket on mainnet: `0x4c2615c36328a1bF9F74b7e13C8fA0EE53F9210d` - HoodNames on testnet: `0x7d99E42EBF68de1Bf54eC76e2AF85D6eEE1a3bAd` - HoodMarket on testnet: `0xA70B48cc4a33E07e1cdc2934e27E1c931F42848a` - `tokenIdOf("alice")` = `0x9c0257114eb9399a2985f8e75dad7600c5d89fe3824ffa99ec1c3eb8bf3b0501` - Registered on testnet: `vault.hood` and `zorti.hood` both resolve to `0x16A1f74C233772dA1b4F528559f5AeD4c797Db53` - Live check: https://www.hoodnames.lol/api/resolve/vault?network=testnet ## Links - Site: https://www.hoodnames.lol - Integration page: https://www.hoodnames.lol/sdk - Package: `hoodnames` on npm - JSON API: https://www.hoodnames.lol/api/resolve/{name} and https://www.hoodnames.lol/api/primary/{address} - This document: https://www.hoodnames.lol/llms-full.txt