Install
openclaw skills install ens-skillResolve ENS names (.eth) to Ethereum addresses and vice versa. Use when a user provides an .eth name (e.g. "send to vitalik.eth"), when displaying addresses (show ENS names), looking up ENS profiles, or helping users register, renew, or manage .eth names.
openclaw skills install ens-skillEnables Gundwane to:
.eth name: "send to vitalik.eth", "look up nick.eth", "who is luc.eth".eth addressAny token matching *.eth in user input is likely an ENS name. Examples:
vitalik.ethnick.ethmynameAlways resolve before using. Never pass a .eth name directly to LI.FI or transaction tools — resolve to a 0x address first.
Use curl to resolve an ENS name to its Ethereum address. Try in priority order.
Best for detailed data (expiry, registrant, resolver). Requires GRAPH_API_KEY env var.
curl -s -X POST \
--url "https://gateway.thegraph.com/api/$GRAPH_API_KEY/subgraphs/id/5XqPmWe6gjyrJtFn9cLy237i4cWw2j9HcUJEXsP5qGtH" \
--header 'Content-Type: application/json' \
--data '{"query":"{ domains(where: { name: \"vitalik.eth\" }) { name resolvedAddress { id } expiryDate registration { registrant { id } expiryDate } } }"}'
Response: data.domains[0].resolvedAddress.id = the 0x address.
Good for quick resolution + profile data in one call.
curl -s "https://api.web3.bio/profile/vitalik.eth"
Returns JSON with address, identity, displayName, avatar, description, and linked social profiles. Use the address field for the resolved 0x address.
If APIs are down and node is available (viem is in the project deps):
node --input-type=module -e "
import { createPublicClient, http } from 'viem';
import { mainnet } from 'viem/chains';
import { normalize } from 'viem/ens';
const c = createPublicClient({ chain: mainnet, transport: http('https://eth.llamarpc.com') });
const addr = await c.getEnsAddress({ name: normalize('REPLACE_NAME') });
console.log(JSON.stringify({ address: addr }));
"
Replace REPLACE_NAME with the actual ENS name.
Priority: Approach 1 → 2 → 3. Use whichever is available and fastest.
Given a 0x address, find the primary ENS name.
curl -s -X POST \
--url "https://gateway.thegraph.com/api/$GRAPH_API_KEY/subgraphs/id/5XqPmWe6gjyrJtFn9cLy237i4cWw2j9HcUJEXsP5qGtH" \
--header 'Content-Type: application/json' \
--data '{"query":"{ domains(where: { resolvedAddress: \"0xd8da6bf26964af9d7eed9e03e53415d37aa96045\" }) { name } }"}'
Note: address must be lowercase in the query.
curl -s "https://api.web3.bio/profile/0xd8da6bf26964af9d7eed9e03e53415d37aa96045"
Returns ENS name and profile if a primary name is set.
node --input-type=module -e "
import { createPublicClient, http } from 'viem';
import { mainnet } from 'viem/chains';
const c = createPublicClient({ chain: mainnet, transport: http('https://eth.llamarpc.com') });
const name = await c.getEnsName({ address: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045' });
console.log(JSON.stringify({ name }));
"
Get ENS profile details: avatar, description, social links, text records.
curl -s "https://api.web3.bio/profile/nick.eth"
Common text record keys (for reference):
com.twitter — Twitter/X handlecom.github — GitHub usernameurl — Websiteemail — Email addressavatar — Avatar URL or NFT referencedescription — Bio/descriptioncom.discord — Discord handleDirect avatar image:
https://metadata.ens.domains/mainnet/avatar/{name}
Example: https://metadata.ens.domains/mainnet/avatar/nick.eth
Use this URL when displaying a user's ENS avatar in messages.
defi_get_wallet, optionally check for a reverse ENS name.fabri.eth (0xabc...def)vitalik.eth → 0xd8dA...6045
Send 0.1 ETH to this address?
0x address.0.1 ETH → vitalik.eth (0xd8d...6045) on BaseRegistration happens on Ethereum mainnet only. Requires ETH for the name price + gas. If the user's ETH is on L2, flag that they need to bridge first.
Pricing:
Contracts (Mainnet):
| Contract | Address |
|---|---|
| ENS Registry | 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e |
| ETH Registrar Controller | 0x253553366Da8546fC250F225fe3d25d0C782303b |
| Public Resolver | 0x231b0Ee14048e9dCcD1d247744d114a4EB5E8E63 |
| Reverse Registrar | 0xa58E81fe9b61B5c3fE2AFD33CF304c454AbFc7Cb |
| Name Wrapper | 0xD4416b13d2b3a9aBae7AcD5D6C2BbDBE25686401 |
| Universal Resolver | 0xce01f8eee7E479C928F8919abD53E553a36CeF67 |
Via the ENS subgraph:
curl -s -X POST \
--url "https://gateway.thegraph.com/api/$GRAPH_API_KEY/subgraphs/id/5XqPmWe6gjyrJtFn9cLy237i4cWw2j9HcUJEXsP5qGtH" \
--header 'Content-Type: application/json' \
--data '{"query":"{ registrations(where: { labelName: \"myname\" }) { labelName expiryDate } }"}'
If no result or expiryDate is in the past (+ 90 day grace period), the name is available.
Or link the user to check directly: https://ens.app/myname.eth
Registration uses a 2-step commit/reveal process (prevents front-running):
Register myname.eth:
• Cost: ~0.002 ETH ($5) for 1 year
• Chain: Ethereum mainnet
• 2-step process (~2 min total)
Register?
commit(bytes32) on the ETH Registrar Controller via defi_send_transaction (chainId: 1). The commitment hash must be computed from the name, owner address, duration, and a random secret.register(name, owner, duration, secret, resolver, data, reverseRecord, fuses) with the name price as value.myname.eth registered! Yours for 1 year (expires Feb 2027). [View tx](...)Simpler alternative: Direct the user to the ENS Manager App for registration: https://ens.app/myname.eth — this handles the full flow with a nice UI. Recommend this for first-time registrations.
Simpler than registration — single transaction, no commit step.
When user says "renew myname.eth":
Renew myname.eth:
• Current expiry: Feb 8, 2027
• Cost: ~0.002 ETH ($5) for 1 year
• New expiry: Feb 8, 2028
renew(string name, uint256 duration) on the ETH Registrar Controller via defi_send_transaction (chainId: 1) with the renewal price as value. Duration in seconds (1 year = 31536000).Grace period: Names have a 90-day grace period after expiry. Only the original owner can renew during this window. After grace period, name goes to public auction with a temporary premium that decreases over 21 days.
When user says "set my ENS primary name" or "make myname.eth my primary":
setName(string name) on the Reverse Registrar (0xa58E81fe9b61B5c3fE2AFD33CF304c454AbFc7Cb) via defi_send_transaction on mainnet (chainId: 1).myname.eth in reverse lookups.Update social/text records via the Public Resolver (0x231b0Ee14048e9dCcD1d247744d114a4EB5E8E63):
setText(bytes32 node, string key, string value)node is the namehash of the full name.com.twitter, com.github, url, email, avatar, descriptionFor complex record updates, recommend the ENS Manager App: https://ens.app/myname.eth
Store registered ENS names in the user's strategy for heartbeat monitoring:
{
"ensNames": [
{
"name": "fabri.eth",
"expiry": "2027-02-08T00:00:00Z",
"isPrimary": true
}
]
}
During heartbeats, check ensNames from each user's strategy:
ENS data is stored per-user in strategy JSON (via defi_set_strategy):
{
"ensNames": [
{
"name": "fabri.eth",
"expiry": "2027-02-08T00:00:00Z",
"isPrimary": true
}
],
"ensPreferences": {
"showEnsInPortfolio": true,
"expiryAlertDays": 30
}
}
Read via defi_get_strategy, write via defi_set_strategy. Automatically per-user.
Narrative data (e.g., "resolved vitalik.eth for a 0.1 ETH transfer") goes to per-user daily memory.
.eth names to LI.FI or transaction tools. Resolve to a 0x address first.0x address before sending funds. ENS records can change.ensNames in user strategies. Alert before names expire.