/** * ROB Domains — Google Gemini SDK Integration Example * * Demonstrates using the ROB Domains Agent API with the Google Generative AI * SDK function-calling feature. Covers Search, Mint, Set Primary, and Update Profile. * * Requires: npm install @google/generative-ai */ import { GoogleGenerativeAI, FunctionDeclaration, SchemaType, Part } from '@google/generative-ai'; const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY!); const BASE_URL = 'https://robdn.com'; // ─── Function Declarations ──────────────────────────────────────────────────── const functionDeclarations: FunctionDeclaration[] = [ { name: 'search_rob_domain', description: 'Search for a .rob domain. Returns availability, owner, tokenId, primary owner, and profile summary.', parameters: { type: SchemaType.OBJECT, properties: { domain: { type: SchemaType.STRING, description: 'Domain label without ".rob" suffix' }, }, required: ['domain'], }, }, { name: 'get_rob_profile', description: 'Get the full on-chain profile for a .rob domain.', parameters: { type: SchemaType.OBJECT, properties: { domain: { type: SchemaType.STRING }, }, required: ['domain'], }, }, { name: 'reverse_resolve_rob', description: 'Reverse-resolve an Ethereum wallet to its primary .rob domain.', parameters: { type: SchemaType.OBJECT, properties: { wallet: { type: SchemaType.STRING, description: '0x-prefixed Ethereum wallet address' }, }, required: ['wallet'], }, }, { name: 'build_mint_transaction', description: 'Generate an unsigned transaction payload for minting a .rob domain. User must sign and broadcast.', parameters: { type: SchemaType.OBJECT, properties: { domain: { type: SchemaType.STRING, description: 'Domain label to mint' }, }, required: ['domain'], }, }, { name: 'build_set_primary_transaction', description: 'Generate an unsigned set-primary transaction payload for a .rob domain.', parameters: { type: SchemaType.OBJECT, properties: { tokenId: { type: SchemaType.STRING }, wallet: { type: SchemaType.STRING }, }, required: ['tokenId', 'wallet'], }, }, { name: 'build_update_profile_transaction', description: 'Generate unsigned update-profile transaction payload(s) for a .rob domain.', parameters: { type: SchemaType.OBJECT, properties: { tokenId: { type: SchemaType.STRING }, bio: { type: SchemaType.STRING }, profilePicture: { type: SchemaType.STRING }, coverImage: { type: SchemaType.STRING }, background: { type: SchemaType.STRING }, }, required: ['tokenId'], }, }, { name: 'register_domain_workflow', description: 'Get a complete multi-step execution plan for registering a .rob domain.', parameters: { type: SchemaType.OBJECT, properties: { domain: { type: SchemaType.STRING }, wallet: { type: SchemaType.STRING }, setPrimary: { type: SchemaType.BOOLEAN }, }, required: ['domain', 'wallet'], }, }, ]; // ─── Function Execution ─────────────────────────────────────────────────────── async function executeFunction(name: string, args: Record): Promise { const handlers: Record Promise> = { search_rob_domain: () => fetch(`${BASE_URL}/agent/search/${args.domain}`), get_rob_profile: () => fetch(`${BASE_URL}/agent/profile/${args.domain}`), reverse_resolve_rob: () => fetch(`${BASE_URL}/agent/reverse/${args.wallet}`), build_mint_transaction: () => fetch(`${BASE_URL}/agent/tx/mint`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ domain: args.domain }), }), build_set_primary_transaction: () => fetch(`${BASE_URL}/agent/tx/set-primary`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ tokenId: args.tokenId, wallet: args.wallet }), }), build_update_profile_transaction: () => fetch(`${BASE_URL}/agent/tx/update-profile`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(args), }), register_domain_workflow: () => fetch(`${BASE_URL}/agent/workflow/register-domain`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(args), }), }; const res = await handlers[name](); return res.json(); } // ─── Agent ──────────────────────────────────────────────────────────────────── async function robDomainsAgent(userMessage: string): Promise { const model = genAI.getGenerativeModel({ model: 'gemini-1.5-pro', tools: [{ functionDeclarations }], systemInstruction: 'You are a helpful assistant for ROB Domains (.rob), a Web3 domain name system on Robinhood Chain. Help users search domains, read profiles, and generate unsigned transaction payloads. Remind users they must sign and broadcast transactions — the API never executes on their behalf.', }); const chat = model.startChat(); let response = await chat.sendMessage(userMessage); while (true) { const calls = response.response.functionCalls(); if (!calls || calls.length === 0) { return response.response.text(); } const functionResponses: Part[] = []; for (const call of calls) { const result = await executeFunction(call.name, call.args as Record); functionResponses.push({ functionResponse: { name: call.name, response: { result }, }, }); } response = await chat.sendMessage(functionResponses); } } // ─── Demo ───────────────────────────────────────────────────────────────────── async function main() { console.log('─── Search ───'); console.log(await robDomainsAgent('Is "alice.rob" available?')); console.log('\n─── Mint ───'); console.log(await robDomainsAgent('Build a mint transaction for "alice.rob".')); console.log('\n─── Full Registration ───'); console.log( await robDomainsAgent( 'Register "alice.rob" for wallet 0xAbCd1234567890AbCd1234567890AbCd12345678, set it as primary.' ) ); } main().catch(console.error);