repositories
loading repo index
repositories
loading repo index
repository
loading code, commits, and activity
public Clawd ADK gateway launch mirror
stars
latest
clone command
git clone gitlawb://did:key:z6Mkq5mY...iFZ5/my-project-publ...git clone gitlawb://did:key:z6Mkq5mY.../my-project-publ...2fa351d6docs: add automaton and perps launch sources16d ago| #1 | /** |
| #2 | * ERC-8004 On-Chain Agent Registration |
| #3 | * |
| #4 | * Registers the automaton on-chain as a Trustless Agent via ERC-8004. |
| #5 | * Uses the Identity Registry on Base mainnet. |
| #6 | * |
| #7 | * Contract: 0x8004A169FB4a3325136EB29fA0ceB6D2e539a432 (Base) |
| #8 | * Reputation: 0x8004BAa17C55a88189AE136b182e5fdA19dE9b63 (Base) |
| #9 | */ |
| #10 | import { createPublicClient, createWalletClient, http, parseAbi, } from "viem"; |
| #11 | import { base, baseSepolia } from "viem/chains"; |
| #12 | // ─── Contract Addresses ────────────────────────────────────── |
| #13 | const CONTRACTS = { |
| #14 | mainnet: { |
| #15 | identity: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432", |
| #16 | reputation: "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63", |
| #17 | chain: base, |
| #18 | }, |
| #19 | testnet: { |
| #20 | identity: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432", |
| #21 | reputation: "0x8004BAa17C55a88189AE136b182e5fdA19dE9b63", |
| #22 | chain: baseSepolia, |
| #23 | }, |
| #24 | }; |
| #25 | // ─── ABI (minimal subset needed for registration) ──────────── |
| #26 | const IDENTITY_ABI = parseAbi([ |
| #27 | "function register(string agentURI) external returns (uint256 agentId)", |
| #28 | "function updateAgentURI(uint256 agentId, string newAgentURI) external", |
| #29 | "function agentURI(uint256 agentId) external view returns (string)", |
| #30 | "function ownerOf(uint256 tokenId) external view returns (address)", |
| #31 | "function totalSupply() external view returns (uint256)", |
| #32 | "function balanceOf(address owner) external view returns (uint256)", |
| #33 | ]); |
| #34 | const REPUTATION_ABI = parseAbi([ |
| #35 | "function leaveFeedback(uint256 agentId, uint8 score, string comment) external", |
| #36 | "function getFeedback(uint256 agentId) external view returns (tuple(address from, uint8 score, string comment, uint256 timestamp)[])", |
| #37 | ]); |
| #38 | /** |
| #39 | * Register the automaton on-chain with ERC-8004. |
| #40 | * Returns the agent ID (NFT token ID). |
| #41 | */ |
| #42 | export async function registerAgent(account, agentURI, network = "mainnet", db) { |
| #43 | const contracts = CONTRACTS[network]; |
| #44 | const chain = contracts.chain; |
| #45 | const publicClient = createPublicClient({ |
| #46 | chain, |
| #47 | transport: http(), |
| #48 | }); |
| #49 | const walletClient = createWalletClient({ |
| #50 | account, |
| #51 | chain, |
| #52 | transport: http(), |
| #53 | }); |
| #54 | // Call register(agentURI) |
| #55 | const hash = await walletClient.writeContract({ |
| #56 | address: contracts.identity, |
| #57 | abi: IDENTITY_ABI, |
| #58 | functionName: "register", |
| #59 | args: [agentURI], |
| #60 | }); |
| #61 | // Wait for transaction receipt |
| #62 | const receipt = await publicClient.waitForTransactionReceipt({ hash }); |
| #63 | // Extract agentId from Transfer event logs |
| #64 | // The register function mints an ERC-721 token |
| #65 | let agentId = "0"; |
| #66 | for (const log of receipt.logs) { |
| #67 | if (log.topics.length >= 4) { |
| #68 | // Transfer(address from, address to, uint256 tokenId) |
| #69 | agentId = BigInt(log.topics[3]).toString(); |
| #70 | break; |
| #71 | } |
| #72 | } |
| #73 | const entry = { |
| #74 | agentId, |
| #75 | agentURI, |
| #76 | chain: `eip155:${chain.id}`, |
| #77 | contractAddress: contracts.identity, |
| #78 | txHash: hash, |
| #79 | registeredAt: new Date().toISOString(), |
| #80 | }; |
| #81 | db.setRegistryEntry(entry); |
| #82 | return entry; |
| #83 | } |
| #84 | /** |
| #85 | * Update the agent's URI on-chain. |
| #86 | */ |
| #87 | export async function updateAgentURI(account, agentId, newAgentURI, network = "mainnet", db) { |
| #88 | const contracts = CONTRACTS[network]; |
| #89 | const chain = contracts.chain; |
| #90 | const walletClient = createWalletClient({ |
| #91 | account, |
| #92 | chain, |
| #93 | transport: http(), |
| #94 | }); |
| #95 | const hash = await walletClient.writeContract({ |
| #96 | address: contracts.identity, |
| #97 | abi: IDENTITY_ABI, |
| #98 | functionName: "updateAgentURI", |
| #99 | args: [BigInt(agentId), newAgentURI], |
| #100 | }); |
| #101 | // Update in DB |
| #102 | const entry = db.getRegistryEntry(); |
| #103 | if (entry) { |
| #104 | entry.agentURI = newAgentURI; |
| #105 | entry.txHash = hash; |
| #106 | db.setRegistryEntry(entry); |
| #107 | } |
| #108 | return hash; |
| #109 | } |
| #110 | /** |
| #111 | * Leave reputation feedback for another agent. |
| #112 | */ |
| #113 | export async function leaveFeedback(account, agentId, score, comment, network = "mainnet", db) { |
| #114 | const contracts = CONTRACTS[network]; |
| #115 | const chain = contracts.chain; |
| #116 | const walletClient = createWalletClient({ |
| #117 | account, |
| #118 | chain, |
| #119 | transport: http(), |
| #120 | }); |
| #121 | const hash = await walletClient.writeContract({ |
| #122 | address: contracts.reputation, |
| #123 | abi: REPUTATION_ABI, |
| #124 | functionName: "leaveFeedback", |
| #125 | args: [BigInt(agentId), score, comment], |
| #126 | }); |
| #127 | return hash; |
| #128 | } |
| #129 | /** |
| #130 | * Query the registry for an agent by ID. |
| #131 | */ |
| #132 | export async function queryAgent(agentId, network = "mainnet") { |
| #133 | const contracts = CONTRACTS[network]; |
| #134 | const chain = contracts.chain; |
| #135 | const publicClient = createPublicClient({ |
| #136 | chain, |
| #137 | transport: http(), |
| #138 | }); |
| #139 | try { |
| #140 | const [uri, owner] = await Promise.all([ |
| #141 | publicClient.readContract({ |
| #142 | address: contracts.identity, |
| #143 | abi: IDENTITY_ABI, |
| #144 | functionName: "agentURI", |
| #145 | args: [BigInt(agentId)], |
| #146 | }), |
| #147 | publicClient.readContract({ |
| #148 | address: contracts.identity, |
| #149 | abi: IDENTITY_ABI, |
| #150 | functionName: "ownerOf", |
| #151 | args: [BigInt(agentId)], |
| #152 | }), |
| #153 | ]); |
| #154 | return { |
| #155 | agentId, |
| #156 | owner: owner, |
| #157 | agentURI: uri, |
| #158 | }; |
| #159 | } |
| #160 | catch { |
| #161 | return null; |
| #162 | } |
| #163 | } |
| #164 | /** |
| #165 | * Get the total number of registered agents. |
| #166 | */ |
| #167 | export async function getTotalAgents(network = "mainnet") { |
| #168 | const contracts = CONTRACTS[network]; |
| #169 | const chain = contracts.chain; |
| #170 | const publicClient = createPublicClient({ |
| #171 | chain, |
| #172 | transport: http(), |
| #173 | }); |
| #174 | try { |
| #175 | const supply = await publicClient.readContract({ |
| #176 | address: contracts.identity, |
| #177 | abi: IDENTITY_ABI, |
| #178 | functionName: "totalSupply", |
| #179 | }); |
| #180 | return Number(supply); |
| #181 | } |
| #182 | catch { |
| #183 | return 0; |
| #184 | } |
| #185 | } |
| #186 | /** |
| #187 | * Check if an address has a registered agent. |
| #188 | */ |
| #189 | export async function hasRegisteredAgent(address, network = "mainnet") { |
| #190 | const contracts = CONTRACTS[network]; |
| #191 | const chain = contracts.chain; |
| #192 | const publicClient = createPublicClient({ |
| #193 | chain, |
| #194 | transport: http(), |
| #195 | }); |
| #196 | try { |
| #197 | const balance = await publicClient.readContract({ |
| #198 | address: contracts.identity, |
| #199 | abi: IDENTITY_ABI, |
| #200 | functionName: "balanceOf", |
| #201 | args: [address], |
| #202 | }); |
| #203 | return Number(balance) > 0; |
| #204 | } |
| #205 | catch { |
| #206 | return false; |
| #207 | } |
| #208 | } |
| #209 | //# sourceMappingURL=erc8004.js.map |