Skip to content
Merged
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
5 changes: 5 additions & 0 deletions typescript/.changeset/bitter-pugs-flow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@coinbase/agentkit": patch
---

Converted all dynamic to static imports
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { acrossActionProvider } from "./acrossActionProvider";
import { EvmWalletProvider } from "../../wallet-providers";
import { Network } from "../../network";
import { createPublicClient, PublicClient } from "viem";
import { createAcrossClient as mockCreateAcrossClient } from "@across-protocol/app-sdk";

// Mock the necessary imports and modules
jest.mock("viem", () => {
Expand Down Expand Up @@ -67,11 +68,15 @@ jest.mock("../../network", () => {
});

// Mock the Across SDK
const mockCreateAcrossClient = jest.fn();
jest.mock("@across-protocol/app-sdk", () => ({
createAcrossClient: mockCreateAcrossClient,
createAcrossClient: jest.fn(),
}));

// Cast the imported mock to a Jest mock function
const mockedCreateAcrossClient = mockCreateAcrossClient as jest.MockedFunction<
typeof mockCreateAcrossClient
>;

// Default implementation for the createAcrossClient mock
const defaultClientImplementation = () => ({
getSupportedChains: jest.fn().mockResolvedValue([
Expand Down Expand Up @@ -140,7 +145,7 @@ const defaultClientImplementation = () => ({
});

// Set the default implementation
mockCreateAcrossClient.mockImplementation(() => {
mockedCreateAcrossClient.mockImplementation(() => {
const client = defaultClientImplementation();
// Add the chains property to match what the code expects
return {
Expand All @@ -157,7 +162,8 @@ mockCreateAcrossClient.mockImplementation(() => {
network: "optimism",
},
],
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any;
});

// Mock the isTestnet function
Expand All @@ -180,7 +186,7 @@ describe("Across Action Provider", () => {
beforeEach(() => {
jest.clearAllMocks();
// Reset to default implementation
mockCreateAcrossClient.mockImplementation(() => {
mockedCreateAcrossClient.mockImplementation(() => {
const client = defaultClientImplementation();
// Add the chains property to match what the code expects
return {
Expand All @@ -197,7 +203,8 @@ describe("Across Action Provider", () => {
network: "optimism",
},
],
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any;
});

mockPublicClient = {
Expand Down Expand Up @@ -269,48 +276,52 @@ describe("Across Action Provider", () => {

it("should fail when slippage is too high", async () => {
// Override the default mock with high slippage for this test only
mockCreateAcrossClient.mockImplementationOnce(() => ({
getSupportedChains: jest.fn().mockResolvedValue([
{
chainId: 1,
inputTokens: [
mockedCreateAcrossClient.mockImplementationOnce(
() =>
({
getSupportedChains: jest.fn().mockResolvedValue([
{
symbol: "ETH",
address: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
decimals: 18,
chainId: 1,
inputTokens: [
{
symbol: "ETH",
address: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
decimals: 18,
},
],
},
],
},
]),
getAvailableRoutes: jest.fn().mockResolvedValue([
{
isNative: true,
originToken: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
},
]),
getQuote: jest.fn().mockResolvedValue({
deposit: {
inputAmount: BigInt("1000000000000000000"), // 1 ETH
outputAmount: BigInt("800000000000000000"), // 0.8 ETH (20% difference)
spokePoolAddress: "0x1234567890123456789012345678901234567890",
},
limits: {
minDeposit: BigInt("100000000000000000"),
maxDeposit: BigInt("10000000000000000000"),
},
}),
simulateDepositTx: jest.fn().mockResolvedValue({
request: {
address: "0x1234567890123456789012345678901234567890",
abi: [],
functionName: "deposit",
args: [],
},
}),
waitForDepositTx: jest.fn().mockResolvedValue({
depositId: "123456",
}),
}));
]),
getAvailableRoutes: jest.fn().mockResolvedValue([
{
isNative: true,
originToken: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
},
]),
getQuote: jest.fn().mockResolvedValue({
deposit: {
inputAmount: BigInt("1000000000000000000"), // 1 ETH
outputAmount: BigInt("800000000000000000"), // 0.8 ETH (20% difference)
spokePoolAddress: "0x1234567890123456789012345678901234567890",
},
limits: {
minDeposit: BigInt("100000000000000000"),
maxDeposit: BigInt("10000000000000000000"),
},
}),
simulateDepositTx: jest.fn().mockResolvedValue({
request: {
address: "0x1234567890123456789012345678901234567890",
abi: [],
functionName: "deposit",
args: [],
},
}),
waitForDepositTx: jest.fn().mockResolvedValue({
depositId: "123456",
}),
// eslint-disable-next-line @typescript-eslint/no-explicit-any
}) as any,
);

// Set a low max slippage
const args = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { EvmWalletProvider } from "../../wallet-providers";
import { isAcrossSupportedTestnet } from "./utils";
import { privateKeyToAccount } from "viem/accounts";
import { erc20Abi as ERC20_ABI } from "viem";
import { createAcrossClient } from "@across-protocol/app-sdk";
/**
* Configuration options for the SafeWalletProvider.
*/
Expand Down Expand Up @@ -68,10 +69,6 @@ export class AcrossActionProvider extends ActionProvider<EvmWalletProvider> {
args: z.infer<typeof BridgeTokenSchema>,
): Promise<string> {
try {
// Use dynamic import to get the Across SDK
const acrossModule = await import("@across-protocol/app-sdk");
const createAcrossClient = acrossModule.createAcrossClient;

// Get recipient address if provided, otherwise use sender
const address = walletProvider.getAddress() as Hex;
const recipient = (args.recipient || address) as Hex;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ import {
import { formatTimestamp, formatPeriod } from "./utils";
import { FetchedPermission } from "./types";
import { retryWithExponentialBackoff } from "../../utils";
import {
fetchPermissions,
getPermissionStatus,
prepareSpendCallData,
prepareRevokeCallData,
} from "@base-org/account/spend-permission";

/**
* Fetch spend permissions for a user account from a spender address
Expand All @@ -28,7 +34,6 @@ async function fetchUserSpendPermissions(
tokenAddress?: Address,
): Promise<FetchedPermission[]> {
try {
const { fetchPermissions } = await import("@base-org/account/spend-permission");
const permissions = await fetchPermissions({
account: userAccount,
chainId: 8453,
Expand Down Expand Up @@ -257,9 +262,6 @@ Important notes:
}

// Check permission status and prepare spend call data
const { getPermissionStatus, prepareSpendCallData } = await import(
"@base-org/account/spend-permission"
);
const status = await retryWithExponentialBackoff(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
() => getPermissionStatus(_permission as any),
Expand Down Expand Up @@ -405,7 +407,6 @@ Important notes:
const _permission = permissions[permissionIndex - 1];

// Prepare the revoke transaction
const { prepareRevokeCallData } = await import("@base-org/account/spend-permission");
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const revokeCall = await prepareRevokeCallData(_permission as any);

Expand Down
3 changes: 1 addition & 2 deletions typescript/agentkit/src/action-providers/clanker/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { createWalletClient, http } from "viem";
import { EvmWalletProvider } from "../../wallet-providers";
import { NETWORK_ID_TO_VIEM_CHAIN } from "../../network";
import { Clanker } from "clanker-sdk/v4";

/**
* Creates the client Clanker expects from the EvmWalletProvider
Expand All @@ -10,8 +11,6 @@ import { NETWORK_ID_TO_VIEM_CHAIN } from "../../network";
* @returns The Clanker implementation
*/
export async function createClankerClient(walletProvider: EvmWalletProvider, networkId: string) {
const { Clanker } = await import("clanker-sdk/v4");

const account = walletProvider.toSigner();

const publicClient = walletProvider.getPublicClient();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { CreateAction } from "../actionDecorator";
import { SwapTokenSchema } from "./schemas";
import { PublicKey, VersionedTransaction } from "@solana/web3.js";
import { createJupiterApiClient, SwapRequest } from "@jup-ag/api";
import { getMint } from "@solana/spl-token";

/**
* JupiterActionProvider handles token swaps using Jupiter's API.
Expand Down Expand Up @@ -46,8 +47,6 @@ export class JupiterActionProvider extends ActionProvider<SvmWalletProvider> {
const inputMint = new PublicKey(args.inputMint);
const outputMint = new PublicKey(args.outputMint);

const { getMint } = await import("@solana/spl-token");

let mintInfo: Awaited<ReturnType<typeof getMint>>;
try {
mintInfo = await getMint(walletProvider.getConnection(), inputMint);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ import {
MessageV0,
TransactionInstruction,
} from "@solana/web3.js";
import {
getMint,
getAssociatedTokenAddress,
getAccount,
TokenAccountNotFoundError,
createAssociatedTokenAccountInstruction,
createTransferCheckedInstruction,
} from "@solana/spl-token";

/**
* SplActionProvider serves as a provider for SPL token actions.
Expand Down Expand Up @@ -53,9 +61,6 @@ export class SplActionProvider extends ActionProvider<SvmWalletProvider> {
const mintPubkey = new PublicKey(args.mintAddress);
const ownerPubkey = new PublicKey(args.address);

const { getMint, getAssociatedTokenAddress, getAccount, TokenAccountNotFoundError } =
await import("@solana/spl-token");

let mintInfo: Awaited<ReturnType<typeof getMint>>;
try {
mintInfo = await getMint(connection, mintPubkey);
Expand Down Expand Up @@ -109,14 +114,6 @@ export class SplActionProvider extends ActionProvider<SvmWalletProvider> {
const toPubkey = new PublicKey(args.recipient);
const mintPubkey = new PublicKey(args.mintAddress);

const {
getMint,
getAssociatedTokenAddress,
getAccount,
createAssociatedTokenAccountInstruction,
createTransferCheckedInstruction,
} = await import("@solana/spl-token");

let mintInfo: Awaited<ReturnType<typeof getMint>>;
try {
mintInfo = await getMint(connection, mintPubkey);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { getAccountOutflowQuery } from "./queries";
import { BASE_GRAPH_ENDPOINT } from "./endpoints";
import { SuperfluidAccountResponse } from "./types";
import { GraphQLClient } from "graphql-request";

/**
* Gets the current account outflows for the user
Expand All @@ -12,7 +13,6 @@ export async function getAccountOutflow(
userId: string,
): Promise<SuperfluidAccountResponse | undefined> {
try {
const { GraphQLClient } = await import("graphql-request");
const client = new GraphQLClient(BASE_GRAPH_ENDPOINT);

const variables = { id: userId.toLowerCase() };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { CreateAction } from "../actionDecorator";
import { Hex, encodeFunctionData } from "viem";
import { Network } from "../../network";
import { generateZoraTokenUri } from "./utils";
import { createCoinCall, DeployCurrency, getCoinCreateFromLogs } from "@zoralabs/coins-sdk";

const SUPPORTED_NETWORKS = ["base-mainnet", "base-sepolia"];

Expand Down Expand Up @@ -68,11 +69,6 @@ The action will return the transaction hash, coin address, and deployment detail
pinataConfig: { jwt: this.#pinataJwt },
});

// Dynamically import Zora SDK
const { createCoinCall, DeployCurrency, getCoinCreateFromLogs } = await import(
"@zoralabs/coins-sdk"
);

// Create coin call
const call = {
name: args.name,
Expand Down
3 changes: 2 additions & 1 deletion typescript/agentkit/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src",
"module": "Node16"
"module": "nodenext",
"isolatedModules": true
},
"include": ["src/**/*.ts"],
"exclude": ["src/tests"]
Expand Down
31 changes: 15 additions & 16 deletions typescript/framework-extensions/langchain/src/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
import { z } from "zod";
import { getLangChainTools } from "./index";
import { AgentKit, Action } from "@coinbase/agentkit";
import { AgentKit } from "@coinbase/agentkit";

// Mocking the Action class
const mockAction: Action = {
// Mock AgentKit before importing - this prevents loading ES-only dependencies
jest.mock("@coinbase/agentkit", () => ({
AgentKit: {
from: jest.fn(),
},
}));

// Define mock action after imports
const mockAction = {
name: "testAction",
description: "A test action",
schema: z.object({ test: z.string() }),
invoke: jest.fn(async arg => `Invoked with ${arg.test}`),
invoke: jest.fn(async (arg: { test: string }) => `Invoked with ${arg.test}`),
};

// Creating a mock for AgentKit
jest.mock("@coinbase/agentkit", () => {
const originalModule = jest.requireActual("@coinbase/agentkit");
return {
...originalModule,
AgentKit: {
from: jest.fn().mockImplementation(() => ({
getActions: jest.fn(() => [mockAction]),
})),
},
};
});
// Configure the mock
(AgentKit.from as jest.Mock).mockImplementation(() => ({
getActions: jest.fn(() => [mockAction]),
}));

describe("getLangChainTools", () => {
it("should return an array of tools with correct properties", async () => {
Expand Down
3 changes: 2 additions & 1 deletion typescript/framework-extensions/langchain/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src",
"module": "Node16"
"module": "nodenext",
"isolatedModules": true
},
"include": ["src/**/*.ts"],
"exclude": ["src/**/*.test.ts"]
Expand Down
Loading
Loading