diff --git a/apps/liaison-api/handlers/agent-tools.handlers.ts b/apps/liaison-api/handlers/agent-tools.handlers.ts index eb0dde6..31e84d8 100644 --- a/apps/liaison-api/handlers/agent-tools.handlers.ts +++ b/apps/liaison-api/handlers/agent-tools.handlers.ts @@ -26,6 +26,7 @@ export async function makeAgentToolCall(c: Context) { } const privateKey = agentService.seedToPrivateKey(agent.wallet.seed); + const wallet = await Wallet.import(agent.wallet); merge(metadata, { privateKey }); @@ -50,5 +51,5 @@ export async function makeAgentToolCall(c: Context) { // @ts-expect-error - dynamic method call const data = await toolWithMethod[toolCall.function.name](args, metadata); - return data; + return c.json(data); } diff --git a/apps/liaison-api/handlers/agents.handlers.ts b/apps/liaison-api/handlers/agents.handlers.ts index b09983b..4019b02 100644 --- a/apps/liaison-api/handlers/agents.handlers.ts +++ b/apps/liaison-api/handlers/agents.handlers.ts @@ -1,12 +1,10 @@ -import { Wallet } from "@coinbase/coinbase-sdk"; +import type { ContractTool } from "../tools/contract.tool.js"; +import type { IpfsTool } from "../tools/ipfs.tool.js"; +import dedent from "dedent"; import { eq } from "drizzle-orm"; import type { Context } from "hono"; -import { COMMON_TOKEN_ADDRESS } from "../lib/addresses.js"; +import { HTTPException } from "hono/http-exception"; import { find, map, omit } from "lodash-es"; -import { database as db } from "../services/database.service.js"; -import typia from "typia"; -import type { CDPTool } from "../tools/cdp.tool.js"; -import dedent from "dedent"; import type { ChatCompletion, ChatCompletionCreateParams, @@ -14,15 +12,21 @@ import type { ChatCompletionMessageParam, ChatCompletionTool, } from "openai/resources.mjs"; -import { HTTPException } from "hono/http-exception"; -import { sessionService } from "../services/session.service.js"; +import typia from "typia"; +import { agentService } from "../services/agent.service.js"; +import { database as db } from "../services/database.service.js"; import { openai } from "../services/openai.service.js"; +import { sessionService } from "../services/session.service.js"; +import type { CDPTool } from "../tools/cdp.tool.js"; import type { GraphQLTool } from "../tools/graphql.tool.js"; -import { agentService } from "../services/agent.service.js"; import { createLogEntry } from "./logs.handlers.js"; +import { inspect } from "node:util"; // This is the same "app" from typia-based approach -const app = typia.llm.application(); +const app = typia.llm.application< + CDPTool & GraphQLTool & ContractTool & IpfsTool, + "chatgpt" +>(); export async function createAgent(c: Context) { const body = await c.req.json<{ @@ -159,10 +163,12 @@ export async function runAgent(c: Context) { ({ type: "function", function: _, - endpoint: `http://localhost:${process.env.PORT}/v1/agents/tools`, + endpoint: `http://localhost:${process.env.PORT}/v1/agents/${agentId}/tools`, } as unknown as ChatCompletionTool & { endpoint: string }) ); + console.log(inspect(tools, { depth: null })); + let chatGPTResponse: ChatCompletion; let finalAIContent = "(No content)"; let done = false; diff --git a/apps/liaison-api/lib/chains.ts b/apps/liaison-api/lib/chains.ts index 673b18f..8f0fac3 100644 --- a/apps/liaison-api/lib/chains.ts +++ b/apps/liaison-api/lib/chains.ts @@ -48,7 +48,13 @@ const baseSepolia = defineChain({ name: "Base Sepolia", network: "base-sepolia", nativeCurrency: { name: "Base ETH", symbol: "ETH", decimals: 18 }, - rpcUrls: { default: { http: ["https://rpc.ankr.com/base_sepolia"] } }, + rpcUrls: { + default: { + http: [ + "https://base-sepolia.g.alchemy.com/v2/GdfwUj5ztvKOwgSxHHRA7KJXfkN6fBJ7", + ], + }, + }, blockExplorers: { default: { name: "BaseScan", url: "https://sepolia.basescan.org" }, }, diff --git a/apps/liaison-api/services/agent.service.ts b/apps/liaison-api/services/agent.service.ts index 47146f8..4a0cafa 100644 --- a/apps/liaison-api/services/agent.service.ts +++ b/apps/liaison-api/services/agent.service.ts @@ -121,10 +121,10 @@ export class AgentService { await publicClient.waitForTransactionReceipt({ hash: txHash }); } - public async checkCommonsBalance(agentId: string) { + public async checkTokenBalance(agentId: string, contractAddress: string) { const row = await this.getAgent(agentId); const wallet = await Wallet.import(row.wallet); - const balance = await wallet.getBalance(COMMON_TOKEN_ADDRESS); + const balance = await wallet.getBalance(contractAddress); return balance.toNumber(); } } diff --git a/apps/liaison-api/services/solc.service.ts b/apps/liaison-api/services/solc.service.ts index 677ca85..031777d 100644 --- a/apps/liaison-api/services/solc.service.ts +++ b/apps/liaison-api/services/solc.service.ts @@ -1,5 +1,5 @@ // @ts-ignore -import * as solc from "solc"; +import solc from "solc"; import { createWalletClient, http } from "viem"; import { privateKeyToAccount } from "viem/accounts"; import type { Chain } from "viem"; @@ -45,7 +45,9 @@ export class SolcService { constructorArgs: any[] = [] ) { const walletClient = createWalletClient({ - account: privateKeyToAccount(`0x${privateKey}` as `0x${string}`), + account: privateKeyToAccount( + `0x${process.env.WALLET_PRIVATE_KEY}` as `0x${string}` + ), chain: this.chain, transport: http(), }); @@ -56,6 +58,7 @@ export class SolcService { args: constructorArgs, }); // Wait + console.log(`Waiting for transaction receipt: ${hash}`); const receipt = await publicClient.waitForTransactionReceipt({ hash }); return receipt.contractAddress; } diff --git a/apps/liaison-api/src/index.ts b/apps/liaison-api/src/index.ts index b49d5e3..da07e71 100644 --- a/apps/liaison-api/src/index.ts +++ b/apps/liaison-api/src/index.ts @@ -10,7 +10,8 @@ const v1 = new Hono().basePath("/v1"); v1.post("/agents", createAgent); v1.post("/agents/run", runAgent); -v1.post("/agents/tools", makeAgentToolCall); +// v1.post("/agents/tools", makeAgentToolCall); +v1.post("/agents/:agentId/tools", makeAgentToolCall); // Liaison key required v1.post("/liaison/interact", verifyLiaisonKey, runAgent); diff --git a/apps/liaison-api/tools/cdp.tool.ts b/apps/liaison-api/tools/cdp.tool.ts index 93596f1..fd9458e 100644 --- a/apps/liaison-api/tools/cdp.tool.ts +++ b/apps/liaison-api/tools/cdp.tool.ts @@ -22,8 +22,14 @@ type TransformClass = { : T[K]; }; -export interface CDPTool - extends PickDeep, "createTransfer"> {} +// extends PickDeep, "createTransfer"> +export interface CDPTool { + createTransfer(args: { + amount: number; + assetId: string; + destination: string; + }): Promise; +} // Function to apply overrides only for missing methods export function applyDefaults( diff --git a/apps/liaison-api/tools/contract.tool.ts b/apps/liaison-api/tools/contract.tool.ts index fa44917..1fc6cc1 100644 --- a/apps/liaison-api/tools/contract.tool.ts +++ b/apps/liaison-api/tools/contract.tool.ts @@ -4,6 +4,7 @@ import { getChainByName } from "../lib/chains.js"; import { publicClient } from "../services/coinbase.service.js"; import { SolcService } from "../services/solc.service.js"; import { fetchAbiFromExplorer } from "../services/etherscan.service.js"; +import { AgentService } from "../services/agent.service.js"; export interface ContractTool { callContract( @@ -14,8 +15,8 @@ export interface ContractTool { method: string; methodArgs?: any[]; isWrite?: boolean; - }, - _metadata: any + } + // _metadata: any ): Promise<{ status: string; result?: any; txHash?: string }>; compileAndDeploy( @@ -24,8 +25,8 @@ export interface ContractTool { sourceCode: string; contractName?: string; constructorArgs?: any[]; - }, - _metadata: any + } + // _metadata: any ): Promise<{ status: string; contractAddress: string; @@ -36,8 +37,8 @@ export interface ContractTool { args: { sourceCode: string; contractName?: string; - }, - _metadata: any + } + // _metadata: any ): Promise<{ status: string; abi: any; @@ -50,8 +51,8 @@ export interface ContractTool { abi: any; bytecode: string; constructorArgs?: any[]; - }, - _metadata: any + } + // _metadata: any ): Promise<{ status: string; contractAddress: string; @@ -63,14 +64,22 @@ export interface ContractTool { sourceCode?: string; contractName?: string; useExplorer?: boolean; - }, - _metadata: any + } + // _metadata: any ): Promise<{ abi: any }>; + + getBalance( + args: { + agentId: string; + } + //_metadata: any + ): Promise<{ balance: number }>; } export class ContractToolEngine implements ContractTool { constructor(private network: string) {} + // @ts-expect-error public async callContract( args: { privateKey: string; @@ -109,6 +118,7 @@ export class ContractToolEngine implements ContractTool { } } + // @ts-expect-error public async compileAndDeploy( args: { privateKey: string; @@ -137,6 +147,7 @@ export class ContractToolEngine implements ContractTool { return { status: "success", contractAddress: newAddress, abi }; } + // @ts-expect-error public async compileContract( args: { sourceCode: string; @@ -157,6 +168,7 @@ export class ContractToolEngine implements ContractTool { return { status: "success", abi, bytecode }; } + // @ts-expect-error public async deployContract( args: { privateKey: string; @@ -180,6 +192,7 @@ export class ContractToolEngine implements ContractTool { * If `useExplorer = true`, fetch ABI from an Etherscan-like explorer. * Otherwise, if sourceCode is provided, compile locally to get the ABI. */ + // @ts-expect-error public async getAbi( args: { contractAddress?: string; @@ -213,4 +226,17 @@ export class ContractToolEngine implements ContractTool { "Must provide either (contractAddress + useExplorer) or (sourceCode) to get ABI." ); } + + //check balance using checkTokenBalance method from agent service + public async getBalance(args: { + agentId: string; + contractAddress: string; + }): Promise<{ balance: number }> { + const agentService = new AgentService(); + const balance = await agentService.checkTokenBalance( + args.agentId, + "0x09d3e33fBeB985653bFE868eb5a62435fFA04e4F" + ); + return { balance }; + } } diff --git a/apps/liaison-api/tools/ipfs.tool.ts b/apps/liaison-api/tools/ipfs.tool.ts index 1aeaa78..1aa4c80 100644 --- a/apps/liaison-api/tools/ipfs.tool.ts +++ b/apps/liaison-api/tools/ipfs.tool.ts @@ -7,12 +7,13 @@ export interface IpfsTool { fileName: string; mimeType: string; agentId?: string; - }, - _metadata: any + } + // _metadata: any ): Promise<{ ipfsUrl: string }>; } export class IpfsToolEngine implements IpfsTool { + // @ts-expect-error async uploadFileToIPFS( args: { base64String: string; diff --git a/apps/liaison-api/tsconfig.json b/apps/liaison-api/tsconfig.json index 91be83e..da1e41e 100644 --- a/apps/liaison-api/tsconfig.json +++ b/apps/liaison-api/tsconfig.json @@ -11,7 +11,7 @@ "node" ], "paths": { - "#/*": ["./*"] + // "#/*": ["./*"] }, "outDir": "./dist", "jsx": "react-jsx", diff --git a/apps/liaison-app/components/agents/liaison-form.tsx b/apps/liaison-app/components/agents/liaison-form.tsx index 494b633..b4a5667 100644 --- a/apps/liaison-app/components/agents/liaison-form.tsx +++ b/apps/liaison-app/components/agents/liaison-form.tsx @@ -74,7 +74,7 @@ export default function LiaisonForm() { }, servers: [ { - url: `${process.env.NEXT_PUBLIC_NEST_API_BASE_URL}/v1`, + url: `https://arttribute-liaison-agents-api-prod-848878149972.europe-west1.run.app/v1`, }, ], paths: {