Integration docs
Show .ely names instead of 0x addresses in your feeds, holder lists and profiles. One batched REST call, or read it on-chain with viem.
A primary name is set by the wallet owner and verified both ways on-chain, so it is safe to display as an address's identity.
01 · Fastest path
Base URL https://api.claimely.xyz. No API key needed. JSON responses with Access-Control-Allow-Origin: *, so you can call it from the browser or a server. Addresses are accepted in any case; responses use checksummed addresses. Names are lowercase label.ely.
This is the call to use for feeds and holder lists. Collect the addresses on screen, de-duplicate them, and resolve them in one request (one on-chain multicall behind the scenes). Response keys are exactly the strings you sent, so names[yourAddress] always works. null means the address has no primary name.
curl -X POST https://api.claimely.xyz/v1/reverse \
-H 'content-type: application/json' \
-d '{"addresses":["0xFCbed3fB642e12901664745E20fF04F35A4369F1","0x0000000000000000000000000000000000000001"]}'
{
"names": {
"0xFCbed3fB642e12901664745E20fF04F35A4369F1": "claimely.ely",
"0x0000000000000000000000000000000000000001": null
}
}
const res = await fetch("https://api.claimely.xyz/v1/reverse", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ addresses: [...new Set(traders)] }), // ≤ 200
});
const { names } = await res.json(); // { [address]: string | null }
const label = (a) => names[a] ?? `${a.slice(0, 6)}…${a.slice(-4)}`;
curl https://api.claimely.xyz/v1/reverse/0xFCbed3fB642e12901664745E20fF04F35A4369F1
{ "address": "0xFCbed3fB642e12901664745E20fF04F35A4369F1", "name": "claimely.ely" }
curl https://api.claimely.xyz/v1/resolve/claimely.ely
{ "name": "claimely.ely", "address": "0xFCbed3fB642e12901664745E20fF04F35A4369F1" }
curl https://api.claimely.xyz/v1/name/claimely.ely
{
"name": "claimely.ely",
"label": "claimely",
"labelhash": "0xd04dc94e087eea0ac06d8de4b70facf59febd45c6d79431b6704202896d538ad",
"tokenId": "94218509084093597133996286554616863271930817717212298156845629241608059041965",
"node": "0xe0e8723de22d472a184ee6c9e32eefeb13f8174424c504bf205b27eecff42fe7",
"owner": "0xFCbed3fB642e12901664745E20fF04F35A4369F1",
"expires": 1825855742,
"registeredAt": 1794319742,
"status": "active",
"resolver": "0xD7711E83C51a129133F3744ed2653643d3e62d3D",
"address": "0xFCbed3fB642e12901664745E20fF04F35A4369F1",
"primaryOf": [],
"records": { "url": "https://claimely.xyz" }
}
Text record keys: avatar, description, url, com.twitter, com.github, org.telegram, com.discord, email. Only records that are set are returned. Timestamps are Unix seconds. status is active, grace (expired, renewable by the owner for 90 days) or expired. primaryOf lists the addresses whose primary name is this name (empty here: this owner's primary name is claimely.ely). Unregistered names return 404.
Cache-Control: public, max-age=60). A newly set primary name can take up to a minute to appear.POST /v1/reverse) and cache results on your side for about 60 s. For heavy or latency-critical use, read on-chain with your own RPC (below).{"error": "…"} with 400 (bad input: invalid address or name, more than 200 addresses), 404, 405 (wrong method), 413 (body over 32 KB), 429 or 5xx. Treat any error as "no name" and show the short address.Limits are per client IP, per minute:
| Requests | Public | Partner key |
|---|---|---|
POST /v1/reverse (up to 200 addresses each) | 30 / min | 300 / min |
Other GET /v1/* | 120 / min | 1,200 / min |
/metadata/*, /og/*, docs | 1,200 / min | 1,200 / min |
/health | unlimited | unlimited |
Over the limit you get 429 with a Retry-After header (seconds) and {"error":"rate limited","retryAfter":60,…}. Back off and show short addresses in the meantime. API responses carry X-RateLimit-Tier: public | partner. Under heavy load, live lookups may briefly return 503 with Retry-After: 1.
IPv6 clients are limited per /64 network. Calling from Cloudflare Workers? Workers share one public bucket, so use a partner key.
x-api-key header for 10× limits, from your backend so it stays private.
curl -X POST https://api.claimely.xyz/v1/reverse -H 'x-api-key: <your key>' -H 'content-type: application/json' -d '{"addresses":["0xFCbed3fB642e12901664745E20fF04F35A4369F1"]}'02 · No API dependency
.ely runs on the ENS v1 contract architecture, so viem's built-in ENS actions work unchanged. Add the Elysium chain with the .ely UniversalResolver. With batch: { multicall: true }, concurrent lookups are aggregated into a single eth_call. Use a recent viem 2.x (we test with 2.57).
import { createPublicClient, defineChain, http } from "viem";
export const elysium = defineChain({
id: 99901,
name: "Elysium",
nativeCurrency: { name: "HYPE", symbol: "HYPE", decimals: 18 },
rpcUrls: { default: { http: ["https://rpc.elysium.kinetiq.xyz"] } },
blockExplorers: { default: { name: "Elysium Explorer", url: "https://elysium.kinetiq.xyz/explorer" } },
contracts: {
multicall3: { address: "0xcA11bde05977b3631167028862bE2a173976CA11" },
ensUniversalResolver: { address: "0x5e17414A975008EC85A93f33143Fba8d6B807FDC" },
},
});
export const client = createPublicClient({
chain: elysium,
transport: http(), // use your own RPC URL in production
batch: { multicall: true }, // many lookups → one eth_call
});
// address → primary name (forward-verified by the UniversalResolver)
const name = await client.getEnsName({ address: "0xFCbed3fB642e12901664745E20fF04F35A4369F1" });
// "claimely.ely" | null
// many addresses at once: still one eth_call thanks to multicall batching
const names = await Promise.all(addresses.map((address) => client.getEnsName({ address })));
// name → address
const address = await client.getEnsAddress({ name: "claimely.ely" });
// text records / avatar
const url = await client.getEnsText({ name: "claimely.ely", key: "url" }); // "https://claimely.xyz"
const avatar = await client.getEnsAvatar({ name: "claimely.ely" }); // null if no avatar record
import { createConfig, http, useEnsName } from "wagmi";
import { elysium } from "./elysium"; // the defineChain above
export const config = createConfig({
chains: [elysium],
transports: { [elysium.id]: http() },
batch: { multicall: true },
});
function Trader({ address }: { address: `0x${string}` }) {
const { data: name } = useEnsName({ address, chainId: elysium.id });
return <span>{name ?? `${address.slice(0, 6)}…${address.slice(-4)}`}</span>;
}
normalize() on user input before resolving. It rejects labels with "--" in positions 3–4; treat those as unresolvable.Pass chainId: elysium.id (wagmi) or use an Elysium client (viem). Without it, lookups go to Ethereum mainnet ENS. The public RPC is rate-limited per IP. Use your own endpoint for backends.
03 · Elysium, chain id 99901
All contracts are verified on the Elysium explorer. Deployed at block 4056527.
| Contract | Address | Purpose |
|---|---|---|
| UniversalResolver | 0x5e17414A975008EC85A93f33143Fba8d6B807FDC | Forward + reverse resolution entry point (viem/wagmi ENS actions) |
| ENSRegistry | 0xe30464cE2b52fac438F2053F58Ea2A6042542382 | Registry (ENS v1 compatible) |
| BaseRegistrar | 0xfdCb4D3c419F9cDE42C89848Df965404f3d6fc97 | ERC-721 for .ely names (tokenId = uint256(labelhash)) |
| PublicResolver | 0xD7711E83C51a129133F3744ed2653643d3e62d3D | Default resolver: addr, text, name records |
| ReverseRegistrar | 0xEc8431357449570a57E0e996DF0004Bb8C9ABc12 | Primary names (addr.reverse) |
| NameWrapper | 0x07f5dc00D33Ef154Db161826152152E7aDc2C0FB | ERC-1155 wrapper (tokenId = uint256(namehash)) |
| ElyRegistrarController | 0x25E6eF0f63f2441F749E28F966a7cbB75A514318 | Registration / renewal |
| ElyPriceOracle | 0x5CcdF19Bc72f72d0eE7fE9d42450C0791A2e4525 | Pricing |
| HypeUsdFeed | 0x9d80121C9acad7c155B236fe7253D697Cc9C8A8b | HYPE/USD price feed |
| FeeRouter | 0x6e0c909746ADd5DF18332aB99d64109381DD8970 | Registration fees: half buys and burns KNTQ, half is held for $ELY's buyback |
| StaticMetadataService | 0x77e0cC5Ba84107eB60C6cFBa549c3a0682ae0B7b | NameWrapper metadata URI |
| GatewayProvider | 0xB74B11C1C9FD310A92CB8A7B9961aFF38c7BcCF0 | Batch gateway config (for UniversalResolver) |
| Multicall3 | 0xcA11bde05977b3631167028862bE2a173976CA11 | Canonical Multicall3 (batching) |
Key hashes: namehash("ely") = 0x3be82acffc98307c4d985a244620d3bb2ae087e06446863fd2c64d5925b06d55, reverse names live under addr.reverse (coin type 60, the EVM address).
04 · Showing names
POST /v1/reverse, /v1/reverse/:address, or getEnsName) to label an address. It returns a name only if that name's address record points back to the same address (forward-verified), so it can't be spoofed by someone pointing their reverse record at a name they don't control.0xFCbe…69F1 when the result is null or on any error. Never block rendering on the lookup..ely. If space is tight, truncate the middle of the label (verylongna…me.ely), not the suffix.https://elysium.kinetiq.xyz/explorer/address/<address>).Reference
| Endpoint | Returns |
|---|---|
GET /v1/names?owner=0x… | Names owned by an address (active + grace period) |
GET /v1/recent?limit=20 | Latest registrations (&kind=all includes renewals) |
GET /v1/burns?limit= | Buy-and-burn history (FeeRouter Burned events), newest first; limit 1–500, default 100 |
GET /v1/stats | Registrations, owners, revenue and burn totals (wei strings) |
GET /v1/airdrop | Airdrop standing: totals |
GET /v1/airdrop/:address | Airdrop standing for one wallet |
GET /metadata/:tokenId | ERC-721 metadata for a name NFT (/image for the SVG) |
GET /og/:name.png | 1200×630 share card (PNG) for a registered name, e.g. /og/claimely.png; others redirect to the generic card |
GET /health | Indexer status |