/** * ROB Domains — OpenAI SDK Integration Example * * Demonstrates using the ROB Domains Agent API with the OpenAI function-calling * (tool_calls) interface. Covers Search, Mint, Set Primary, and Update Profile. * * Requires: npm install openai */ import OpenAI from 'openai'; const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }); const BASE_URL = 'https://robdn.com'; // ─── Tool Definitions ───────────────────────────────────────────────────────── const ROB_DOMAINS_TOOLS: OpenAI.Chat.ChatCompletionTool[] = [ { type: 'function', function: { name: 'search_rob_domain', description: 'Search for a .rob domain name. Returns availability, owner, tokenId, primary owner, and profile summary.', parameters: { type: 'object', properties: { domain: { type: 'string', description: 'Domain label without ".rob" suffix (e.g. "alice")', }, }, required: ['domain'], }, }, }, { type: 'function', function: { name: 'get_rob_profile', description: 'Get the full on-chain profile for a .rob domain.', parameters: { type: 'object', properties: { domain: { type: 'string', description: 'Domain label (e.g. "alice")', }, }, required: ['domain'], }, }, }, { type: 'function', function: { name: 'reverse_resolve_rob', description: 'Reverse-resolve an Ethereum wallet address to its primary .rob domain.', parameters: { type: 'object', properties: { wallet: { type: 'string', description: 'Ethereum wallet address (0x-prefixed)', }, }, required: ['wallet'], }, }, }, { type: 'function', function: { name: 'build_mint_transaction', description: 'Generate an unsigned transaction payload for minting a .rob domain. The user must sign and broadcast it.', parameters: { type: 'object', properties: { domain: { type: 'string', description: 'Domain label to mint (e.g. "alice")', }, }, required: ['domain'], }, }, }, { type: 'function', function: { name: 'build_set_primary_transaction', description: 'Generate an unsigned transaction payload for setting a .rob domain as the primary domain for a wallet.', parameters: { type: 'object', properties: { tokenId: { type: 'string', description: 'On-chain token ID' }, wallet: { type: 'string', description: 'Wallet address that owns the token', }, }, required: ['tokenId', 'wallet'], }, }, }, { type: 'function', function: { name: 'build_update_profile_transaction', description: 'Generate unsigned transaction payload(s) for updating a .rob domain profile.', parameters: { type: 'object', properties: { tokenId: { type: 'string', description: 'Token ID of the domain' }, bio: { type: 'string', description: 'Profile bio (max 500 chars)' }, profilePicture: { type: 'string', description: 'Profile picture URL', }, coverImage: { type: 'string', description: 'Cover image URL' }, background: { type: 'string', description: 'Background CSS class string', }, socialLinks: { type: 'array', items: { type: 'object', properties: { platform: { type: 'string' }, url: { type: 'string' }, }, }, }, }, required: ['tokenId'], }, }, }, { type: 'function', function: { name: 'register_domain_workflow', description: 'Get a complete multi-step execution plan for registering a .rob domain (mint + optional set primary + optional profile).', parameters: { type: 'object', properties: { domain: { type: 'string' }, wallet: { type: 'string' }, setPrimary: { type: 'boolean', default: false }, profile: { type: 'object', properties: { bio: { type: 'string' }, profilePicture: { type: 'string' }, socialLinks: { type: 'array', items: { type: 'object' } }, }, }, }, required: ['domain', 'wallet'], }, }, }, ]; // ─── Tool Execution ─────────────────────────────────────────────────────────── async function executeToolCall( name: string, args: Record ): Promise { const routes: 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 routes[name](); return res.json(); } // ─── Agent Loop ─────────────────────────────────────────────────────────────── async function robDomainsAgent(userMessage: string): Promise { const messages: OpenAI.Chat.ChatCompletionMessageParam[] = [ { role: 'system', content: 'You are a helpful assistant for ROB Domains (.rob), a Web3 domain name system on the Robinhood Chain. Help users search domains, read profiles, and generate transaction payloads for minting, setting a primary domain, and updating profiles. Always remind users that they must sign and broadcast transaction payloads — the API never executes on their behalf.', }, { role: 'user', content: userMessage }, ]; while (true) { const response = await client.chat.completions.create({ model: 'gpt-4o', messages, tools: ROB_DOMAINS_TOOLS, tool_choice: 'auto', }); const choice = response.choices[0]; messages.push(choice.message); if (choice.finish_reason === 'stop') { return choice.message.content ?? ''; } if (choice.finish_reason === 'tool_calls' && choice.message.tool_calls) { for (const toolCall of choice.message.tool_calls) { if (toolCall.type !== 'function') { continue; } const args = JSON.parse(toolCall.function.arguments) as Record< string, unknown >; const result = await executeToolCall(toolCall.function.name, args); messages.push({ role: 'tool', tool_call_id: toolCall.id, content: JSON.stringify(result), }); } } } } // ─── Demo ───────────────────────────────────────────────────────────────────── async function main() { console.log('─── Search ───'); console.log( await robDomainsAgent('Is the domain "alice" available on ROB Domains?') ); console.log('\n─── Mint ───'); console.log( await robDomainsAgent( 'Build me a transaction to mint the domain "alice" on ROB Domains.' ) ); console.log('\n─── Full Registration ───'); console.log( await robDomainsAgent( 'I want to register "alice.rob" for wallet 0xAbCd1234567890AbCd1234567890AbCd12345678, set it as my primary domain, and add a Twitter link to https://twitter.com/alice. Give me the full execution plan.' ) ); } main().catch(console.error);