Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/liaison-api/handlers/agent-tools.handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 });

Expand All @@ -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);
}
28 changes: 17 additions & 11 deletions apps/liaison-api/handlers/agents.handlers.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
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,
ChatCompletionCreateParamsNonStreaming,
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<CDPTool & GraphQLTool, "chatgpt">();
const app = typia.llm.application<
CDPTool & GraphQLTool & ContractTool & IpfsTool,
"chatgpt"
>();

export async function createAgent(c: Context) {
const body = await c.req.json<{
Expand Down Expand Up @@ -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;
Expand Down
8 changes: 7 additions & 1 deletion apps/liaison-api/lib/chains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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" },
},
Expand Down
4 changes: 2 additions & 2 deletions apps/liaison-api/services/agent.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
Expand Down
7 changes: 5 additions & 2 deletions apps/liaison-api/services/solc.service.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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(),
});
Expand All @@ -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;
}
Expand Down
3 changes: 2 additions & 1 deletion apps/liaison-api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
10 changes: 8 additions & 2 deletions apps/liaison-api/tools/cdp.tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,14 @@ type TransformClass<T> = {
: T[K];
};

export interface CDPTool
extends PickDeep<TransformClass<Wallet>, "createTransfer"> {}
// extends PickDeep<TransformClass<Wallet>, "createTransfer">
export interface CDPTool {
createTransfer(args: {
amount: number;
assetId: string;
destination: string;
}): Promise<any>;
}

// Function to apply overrides only for missing methods
export function applyDefaults<T extends object>(
Expand Down
46 changes: 36 additions & 10 deletions apps/liaison-api/tools/contract.tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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(
Expand All @@ -24,8 +25,8 @@ export interface ContractTool {
sourceCode: string;
contractName?: string;
constructorArgs?: any[];
},
_metadata: any
}
// _metadata: any
): Promise<{
status: string;
contractAddress: string;
Expand All @@ -36,8 +37,8 @@ export interface ContractTool {
args: {
sourceCode: string;
contractName?: string;
},
_metadata: any
}
// _metadata: any
): Promise<{
status: string;
abi: any;
Expand All @@ -50,8 +51,8 @@ export interface ContractTool {
abi: any;
bytecode: string;
constructorArgs?: any[];
},
_metadata: any
}
// _metadata: any
): Promise<{
status: string;
contractAddress: string;
Expand All @@ -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;
Expand Down Expand Up @@ -109,6 +118,7 @@ export class ContractToolEngine implements ContractTool {
}
}

// @ts-expect-error
public async compileAndDeploy(
args: {
privateKey: string;
Expand Down Expand Up @@ -137,6 +147,7 @@ export class ContractToolEngine implements ContractTool {
return { status: "success", contractAddress: newAddress, abi };
}

// @ts-expect-error
public async compileContract(
args: {
sourceCode: string;
Expand All @@ -157,6 +168,7 @@ export class ContractToolEngine implements ContractTool {
return { status: "success", abi, bytecode };
}

// @ts-expect-error
public async deployContract(
args: {
privateKey: string;
Expand All @@ -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;
Expand Down Expand Up @@ -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 };
}
}
5 changes: 3 additions & 2 deletions apps/liaison-api/tools/ipfs.tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion apps/liaison-api/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"node"
],
"paths": {
"#/*": ["./*"]
// "#/*": ["./*"]
},
"outDir": "./dist",
"jsx": "react-jsx",
Expand Down
6 changes: 4 additions & 2 deletions apps/liaison-app/components/agents/liaison-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ export default function LiaisonForm() {
const { authState } = useAuth();
const { walletAddress } = authState;
const userAddress = walletAddress?.toLowerCase();
console.log("User Address:", userAddress);
// State for the agent form
const [agentData, setAgentData] = useState({
name: "",
owner: userAddress,
owner: walletAddress?.toLowerCase(),
network: "base", // Default network
isLiaison: "true",
});
console.log("Initial Agent Data:", agentData);

interface ResultType {
liaisonKey: string;
Expand Down Expand Up @@ -72,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: {
Expand Down