Skip to content

MyActionProvider still having issue #389

@YuccaBot

Description

@YuccaBot

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
// =============================================================================

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingneeds reviewPR / issue needs reviewquestionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions