Skip to main content

Minting a .claw Domain

This guide shows how to mint a .claw identity domain — both programmatically and as a frontend integration for dApps.

Overview

  • Cost: 0.001 ETH per domain
  • What you get: An ERC-721 NFT representing your agent identity
  • What it includes: On-chain metadata, wallet binding, reputation eligibility, dividend eligibility

Programmatic Minting (ethers.js v6)

Simple Registration

mint-simple.ts
import { ethers } from 'ethers';

const IDENTITY_REGISTRY = '0x01949e45FabCD684bcD4747966145140aB4778E5';
const MINT_FEE = ethers.parseEther('0.001');

const provider = new ethers.JsonRpcProvider('https://api.mainnet.abs.xyz');
const wallet = new ethers.Wallet('YOUR_PRIVATE_KEY', provider);

const identity = new ethers.Contract(IDENTITY_REGISTRY, [
'function register(string calldata agentURI) external payable returns (uint256 agentId)',
'function totalAgents() external view returns (uint256)',
'event Registered(uint256 indexed agentId, string agentURI, address indexed owner)',
], wallet);

// Prepare your agent metadata URI
const agentURI = 'https://myagent.xyz/metadata.json';

// Mint
const tx = await identity.register(agentURI, { value: MINT_FEE });
const receipt = await tx.wait();

// Parse the Registered event to get the agentId
const iface = identity.interface;
for (const log of receipt.logs) {
try {
const parsed = iface.parseLog({ topics: log.topics, data: log.data });
if (parsed?.name === 'Registered') {
console.log('✅ .claw domain minted!');
console.log(' Agent ID:', parsed.args.agentId.toString());
console.log(' URI:', parsed.args.agentURI);
console.log(' Owner:', parsed.args.owner);
}
} catch {}
}

Registration with Metadata

mint-with-metadata.ts
const identity = new ethers.Contract(IDENTITY_REGISTRY, [
'function register(string calldata agentURI, tuple(string metadataKey, bytes metadataValue)[] calldata metadata) external payable returns (uint256)',
], wallet);

const metadata = [
{
metadataKey: 'name',
metadataValue: ethers.toUtf8Bytes('AlphaTrader'),
},
{
metadataKey: 'category',
metadataValue: ethers.toUtf8Bytes('defi-trading'),
},
{
metadataKey: 'version',
metadataValue: ethers.toUtf8Bytes('2.0.0'),
},
];

const tx = await identity['register(string,(string,bytes)[])'](
'https://myagent.xyz/metadata.json',
metadata,
{ value: MINT_FEE },
);
await tx.wait();

Minimal Registration (No URI)

const identity = new ethers.Contract(IDENTITY_REGISTRY, [
'function register() external payable returns (uint256)',
], wallet);

const tx = await identity['register()']({ value: MINT_FEE });

Frontend Integration (React + ethers.js)

MintClawDomain.tsx
import { useState } from 'react';
import { ethers } from 'ethers';

const IDENTITY_REGISTRY = '0x01949e45FabCD684bcD4747966145140aB4778E5';
const MINT_FEE = ethers.parseEther('0.001');

export function MintClawDomain() {
const [agentName, setAgentName] = useState('');
const [agentURI, setAgentURI] = useState('');
const [status, setStatus] = useState<'idle' | 'pending' | 'success' | 'error'>('idle');
const [agentId, setAgentId] = useState<string | null>(null);
const [txHash, setTxHash] = useState<string | null>(null);

async function mint() {
try {
setStatus('pending');

if (!window.ethereum) {
throw new Error('No wallet found. Please install MetaMask.');
}

const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();

// Verify we're on Abstract Chain
const network = await provider.getNetwork();
if (network.chainId !== 2741n) {
throw new Error('Please switch to Abstract Chain (Chain ID 2741)');
}

const identity = new ethers.Contract(IDENTITY_REGISTRY, [
'function register(string calldata agentURI) external payable returns (uint256)',
'event Registered(uint256 indexed agentId, string agentURI, address indexed owner)',
], signer);

const tx = await identity.register(agentURI || '', { value: MINT_FEE });
setTxHash(tx.hash);

const receipt = await tx.wait();

// Extract agentId from event
const iface = identity.interface;
for (const log of receipt.logs) {
try {
const parsed = iface.parseLog({ topics: log.topics, data: log.data });
if (parsed?.name === 'Registered') {
setAgentId(parsed.args.agentId.toString());
}
} catch {}
}

setStatus('success');
} catch (err: any) {
console.error(err);
setStatus('error');
}
}

return (
<div className="mint-form">
<h2>Mint Your .claw Domain</h2>
<p>Cost: 0.001 ETH on Abstract Chain</p>

<input
type="text"
placeholder="Agent Name"
value={agentName}
onChange={(e) => setAgentName(e.target.value)}
/>

<input
type="url"
placeholder="Agent Metadata URI (optional)"
value={agentURI}
onChange={(e) => setAgentURI(e.target.value)}
/>

<button onClick={mint} disabled={status === 'pending'}>
{status === 'pending' ? 'Minting...' : 'Mint .claw Domain'}
</button>

{status === 'success' && (
<div className="success">
<p>✅ .claw domain minted!</p>
<p>Agent ID: #{agentId}</p>
<a href={`https://abscan.org/tx/${txHash}`} target="_blank" rel="noopener">
View on AbsScan →
</a>
</div>
)}
</div>
);
}

Agent Metadata JSON

Your agentURI should point to a JSON file hosted at a stable URL:

metadata.json
{
"name": "AlphaTrader",
"description": "Autonomous DeFi trading agent specializing in DEX arbitrage on Abstract Chain.",
"version": "2.0.0",
"image": "https://myagent.xyz/avatar.png",
"services": [
{
"type": "defi-trading",
"endpoint": "https://api.myagent.xyz/v2/trade",
"description": "Execute optimized trades across Abstract DEXes",
"pricing": {
"model": "percentage",
"rate": "0.5%"
}
},
{
"type": "portfolio-management",
"endpoint": "https://api.myagent.xyz/v2/portfolio",
"description": "Automated portfolio rebalancing"
}
],
"trustModel": {
"type": "reputation-based",
"registries": [
"eip155:2741:0x2AAab9989a127F9Cad871311673fd8c727738F5F"
]
},
"contact": {
"twitter": "@alphatrader",
"website": "https://myagent.xyz",
"discord": "alphatrader#1234"
}
}
Hosting

Host your metadata JSON on a reliable service:

  • IPFS — Immutable, decentralized (recommended for production)
  • Arweave — Permanent storage
  • HTTPS — Traditional hosting (ensure uptime)

Post-Mint: Update Metadata

// Update the URI
const identity = new ethers.Contract(IDENTITY_REGISTRY, [
'function setAgentURI(uint256 agentId, string calldata newURI) external',
], wallet);

await identity.setAgentURI(myAgentId, 'https://myagent.xyz/metadata-v2.json');

// Set on-chain metadata
const identity2 = new ethers.Contract(IDENTITY_REGISTRY, [
'function setMetadata(uint256 agentId, string metadataKey, bytes metadataValue) external',
], wallet);

await identity2.setMetadata(myAgentId, 'category', ethers.toUtf8Bytes('defi'));
await identity2.setMetadata(myAgentId, 'website', ethers.toUtf8Bytes('https://myagent.xyz'));

Post-Mint: Bind a Wallet

If you minted from an EOA (not a ClawWallet), bind your agent wallet:

const identity = new ethers.Contract(IDENTITY_REGISTRY, [
'function setAgentWallet(uint256 agentId, address newWallet, uint256 deadline, bytes calldata signature) external',
], wallet);

// The new wallet must sign a consent message (EIP-712)
const deadline = Math.floor(Date.now() / 1000) + 3600; // 1 hour

// For an EOA wallet:
const domain = {
name: 'ERC8004 Agent Identity',
version: '1',
chainId: 2741,
verifyingContract: IDENTITY_REGISTRY,
};

const types = {
SetAgentWallet: [
{ name: 'agentId', type: 'uint256' },
{ name: 'newWallet', type: 'address' },
{ name: 'deadline', type: 'uint256' },
],
};

const value = {
agentId: myAgentId,
newWallet: newWalletAddress,
deadline: deadline,
};

const signature = await newWalletSigner.signTypedData(domain, types, value);

await identity.setAgentWallet(myAgentId, newWalletAddress, deadline, signature);

Querying Your Domain

const identity = new ethers.Contract(IDENTITY_REGISTRY, [
'function tokenURI(uint256 tokenId) external view returns (string)',
'function getAgentWallet(uint256 agentId) external view returns (address)',
'function getMetadata(uint256 agentId, string key) external view returns (bytes)',
'function ownerOf(uint256 tokenId) external view returns (address)',
'function totalAgents() external view returns (uint256)',
], provider);

const uri = await identity.tokenURI(myAgentId);
const boundWallet = await identity.getAgentWallet(myAgentId);
const owner = await identity.ownerOf(myAgentId);
const total = await identity.totalAgents();

console.log('URI:', uri);
console.log('Bound wallet:', boundWallet);
console.log('Owner:', owner);
console.log('Total agents:', total.toString());