-
Notifications
You must be signed in to change notification settings - Fork 484
Description
my env is correct and has the compiler options set...however I am still getting errors on the @CreateAction and arguments..
here is my current MyActionProvider.ts...still working through schema and actions but wanted to resolve my errors in the @CreateAction first ..
ty ;)
.......................
// =============================================================================
// MyActionProvider.ts
// =============================================================================
//
// Developer Notes:
// ----------------
// This file defines your custom ActionProvider, integrating multiple actions
// (fetching market data, executing trades, signing messages, and running bot
// logic). It leverages Coinbase AgentKit under the hood and MUST be used in a
// server-side context only.
//
// =============================================================================
import "reflect-metadata";
import {
ActionProvider,
WalletProvider,
Network,
AgentKit,
walletActionProvider,
CreateAction,
} from "@coinbase/agentkit";
import { z } from "zod";
import { initWalletSingleton } from "./walletProvider";
// Import AI trading logic
import { runAiDecisionFlowForCandidate } from "../features/trading/aiAgent";
// -----------------------------------------------------------------------------
// SCHEMAS FOR ACTIONS
// -----------------------------------------------------------------------------
const MarketDataSchema = z.object({
symbol: z.string().describe("Symbol of the asset to fetch market data for"),
});
const TradeActionSchema = z.object({
asset: z.string().describe("Asset symbol (e.g. ETH)"),
amount: z.number().describe("Amount of the asset to buy or sell"),
side: z.enum(["buy", "sell"]).describe("Side of the trade"),
});
const SignMessageSchema = z.object({
message: z.string().describe("Message to be signed with EIP-191"),
});
const RunBotLogicSchema = z.object({
symbol: z.string().optional(),
tags: z.string().optional(),
});
// New action schema
const MyNewActionSchema = z.object({
param1: z.string().describe("Parameter 1 description"),
param2: z.number().describe("Parameter 2 description"),
});
// Define CreateActionParams if it doesn't exist
type CreateActionParams
= {
name: string;
schema: any; // Replace 'any' with the appropriate type
handler: (provider: P, args: any) => Promise; // Adjust types as needed
description?: string;
};
// -----------------------------------------------------------------------------
// MyActionProvider Class (Fixed)
// -----------------------------------------------------------------------------
class MyActionProvider extends ActionProvider {
declare provider: WalletProvider;
private actions: CreateActionParams[] = [];
constructor() {
// ✅ Register actions before calling super
super("my-action-provider", []);
if (typeof window !== "undefined") {
throw new Error("MyActionProvider is intended for server-side use only.");
}
void this.initializeProvider();
// ✅ Register actions before calling `super()`
this.registerActions();
this.setActions(this.actions); // ✅ Properly set actions inside AgentKit
}
// Initializes the wallet provider
private async initializeProvider() {
this.provider = (await initWalletSingleton()) as unknown as WalletProvider;
}
// 🔥 Register actions manually
private registerActions() {
this.addAction({
name: "fetch_market_data",
description:
"Fetch current or recent historical market data for a token symbol from CoinGecko",
schema: MarketDataSchema,
handler: this.fetchMarketData.bind(this),
});
this.addAction({
name: "trade",
description: "Execute a trade using the Coinbase wallet",
schema: TradeActionSchema,
handler: this.trade.bind(this),
});
this.addAction({
name: "sign_message",
description: "Sign a message using the Coinbase CDP wallet",
schema: SignMessageSchema,
handler: this.signMessage.bind(this),
});
this.addAction({
name: "run_bot_logic",
description:
"Run advanced AI logic to analyze market data and execute trades for the specified token",
schema: RunBotLogicSchema,
handler: this.runBotLogic.bind(this),
});
this.addAction({
name: "my_new_action",
description:
"A custom action that takes param1 (string) and param2 (number) and returns a message.",
schema: MyNewActionSchema,
handler: this.myNewAction.bind(this),
});
}
// ✅ Properly registers actions in AgentKit
private addAction(action: CreateActionParams) {
this.actions.push(action);
}
// -----------------------------------------------------------------------------
// ACTION HANDLERS
// -----------------------------------------------------------------------------
@CreateAction({
name: "fetch_market_data",
description: "Fetch current or recent historical market data for a token symbol from CoinGecko",
schema: MarketDataSchema,
})
async fetchMarketData(
_walletProvider: WalletProvider,
args: z.infer = { symbol: '' }
): Promise {
if (!args || !args.symbol) {
console.error("fetchMarketData called without valid arguments");
return "Error: No valid arguments provided";
}
const { symbol } = args;
const coinMapping: Record<string, string> = {
eth: "ethereum",
btc: "bitcoin",
};
const coinId = coinMapping[symbol.toLowerCase()] || symbol.toLowerCase();
console.log("[fetchMarketData] Fetching market data for:", coinId);
const response = await fetch(
`https://api.coingecko.com/api/v3/coins/${coinId}/market_chart?vs_currency=usd&days=1`
);
if (!response.ok) {
throw new Error(`Failed to fetch market data for ${coinId}`);
}
const data = await response.json();
return JSON.stringify(data.prices.map((p: [number, number]) => ({
symbol,
timestamp: p[0],
price: p[1],
})));
}
@CreateAction({
name: "trade",
description: "Execute a trade using the Coinbase wallet",
schema: TradeActionSchema,
})
async trade(
_walletProvider: WalletProvider,
args: z.infer = { asset: '', amount: 0, side: 'buy' }
): Promise {
if (!args) {
console.error("Trade action called without arguments");
return "Error: No arguments provided";
}
const { asset, amount, side } = args;
console.log(`[trade] Request => asset: ${asset}, amount: ${amount}, side: ${side}`);
// Implement the trade logic here
// Return a mock result for demonstration
return `Trade executed: side=${side}, asset=${asset}, amount=${amount}`;
}
@CreateAction({
name: "sign_message",
description: "Sign a message using the Coinbase CDP wallet",
schema: SignMessageSchema,
})
async signMessage(
_walletProvider: WalletProvider,
args: z.infer
): Promise {
const { message } = args;
console.log("[sign_message] Signing message =>", message);
const signature = await this.provider.signMessage(message);
return Signed message: ${signature}
;
}
@CreateAction({
name: "run_bot_logic",
description: "Run advanced AI logic to analyze market data and execute trades for the specified token",
schema: RunBotLogicSchema,
})
async runBotLogic(
_walletProvider: WalletProvider,
args: z.infer
): Promise {
console.log("[run_bot_logic] Invoked with =>", args);
const symbol = args.symbol || "eth";
const tags = args.tags || "momentum";
console.log("[run_bot_logic] Creating candidate =>", { symbol, tags });
const candidate = { symbol, tags };
const result = await runAiDecisionFlowForCandidate(candidate);
return JSON.stringify(result);
}
@CreateAction({
name: "my_new_action",
description: "A custom action that takes param1 (string) and param2 (number) and returns a message.",
schema: MyNewActionSchema,
})
async myNewAction(
_walletProvider: WalletProvider,
args: z.infer
): Promise {
console.log("[my_new_action] Invoked with =>", args);
return Received param1=${args.param1} and param2=${args.param2}
;
}
// Required by Coinbase AgentKit to indicate supported networks.
supportsNetwork = (_network: Network) => true;
private setActions(actions: CreateActionParams[]): void {
this.actions = actions;
}
}
// Factory function to retrieve an instance of MyActionProvider.
export function myActionProvider() {
return new MyActionProvider();
}
// =============================================================================
// END OF FILE
// =============================================================================