Skip to content

Commit

Permalink
feat: testing (#5)
Browse files Browse the repository at this point in the history
* experimental: implementing testing

* removing unused code

* adding todo for test utils mock

* cleanup

* first pass implementing mint nft test

* cleanup

* warning fix

* wip: register basename test

* wip: request faucet funds test

* adjusting error case messaging

* wip: trade test

* wip: transfer test

* wip: faucet transaction test

* formatting

* second pass implementing request faucet funds test

* refining request faucet funds test

* first pass implementing trade test

* first pass implementing transfer test

* removing dead code from contract invocation mock

* refinements

* reverting package.json

* re-including jest in package.json

* redirecting local action imports

* reverting register basename action to master

* exporting register basename

* package lock

* reverting package-lock

* updates to package-lock

* rebased to master

* first pass implementing register basename test

* init langchain test suite

* langchain basic testing

* implementing John's feedback for deploy_nft_test

* adjusting deploy nft test error message

* second pass implementing deploy token test

* fixes for deploy nft test

* second pass implementing get balance test

* second pass implementing get wallet details test

* wrapping get wallet details in try catch

* second pass implementing mint nft test

* second pass implementing request faucet funds test

* second pass implementing trade test

* second pass implementing transfer test

* second pass implementing register basename test

* removing unused code

* refinements

* moving tests to root test dir

* refinements for cdp-langchain tests

* cleanup

* refinments

* expanding upon cdp-langchain tests

* first pass implementing defi wow action input tests

* defi wow sell token tests

* refinements to defi wow sell token tests

* reverting register basename input schema

* implementing feedback

* refinments for wow sell token test

* first pass implementing wow create token test

* first pass implementing wow buy token test

* Update cdp-agentkit-core/src/tests/deploy_nft_test.ts

Co-authored-by: John Peterson <[email protected]>

* adding types for jest mocked vars

* implementing feedback

* ensuring tests include calledWith(...)

* fixing cdp-langchain tests

* fix jest configs + linters

* remove unused Amount import

* fix lint

---------

Co-authored-by: Christopher Gerber <[email protected]>
Co-authored-by: John Peterson <[email protected]>
Co-authored-by: John Peterson <[email protected]>
  • Loading branch information
4 people authored Dec 3, 2024
1 parent ac5988c commit 8410bcc
Show file tree
Hide file tree
Showing 34 changed files with 1,575 additions and 221 deletions.
3 changes: 1 addition & 2 deletions .eslintrc.base.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,5 @@
"jsdoc/require-returns-description": "error",
"jsdoc/require-returns-type": "off",
"jsdoc/require-hyphen-before-param-description": ["error", "always"]
},
"ignorePatterns": ["src/**/tests/**", "src/**/*.test.ts"]
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import baseConfig from "../jest.config.base.js";
const baseConfig = require("../jest.config.base.cjs");

export default {
module.exports = {
...baseConfig,
coveragePathIgnorePatterns: ["node_modules", "dist", "docs", "index.ts"],
coverageThreshold: {
Expand Down
8 changes: 6 additions & 2 deletions cdp-agentkit-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"format": "npx --yes prettier -c .prettierrc --write \"**/*.{ts,js,cjs,json,md}\"",
"format-check": "npx --yes prettier -c .prettierrc --check \"**/*.{ts,js,cjs,json,md}\"",
"check": "tsc --noEmit",
"test": "npx --yes jest --no-cache --testMatch=**/*_test.ts",
"test": "npx jest --no-cache --testMatch='**/*_test.ts'",
"test:dry-run": "npm install && npm ci && npm publish --dry-run",
"test:e2e": "npx jest --no-cache --testMatch=**/e2e.ts --coverageThreshold '{}'",
"test:types": "tsd --files src/tests/types.test-d.ts",
Expand All @@ -41,10 +41,14 @@
"zod": "^3.23.8"
},
"devDependencies": {
"@types/jest": "^29.5.14",
"@types/secp256k1": "^4.0.6",
"http-server": "^14.1.1",
"jest": "^29.7.0",
"mock-fs": "^5.2.0",
"tsd": "^0.31.2"
"ts-jest": "^29.2.5",
"tsd": "^0.31.2",
"typescript": "^5.7.2"
},
"exports": {
".": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ This tool will buy a Zora Wow ERC20 memecoin with ETH. This tool takes the WOW t
/**
* Input schema for buy token action.
*/
const WowBuyTokenInput = z
export const WowBuyTokenInput = z
.object({
contractAddress: z.string().describe("The WOW token contract address"),
amountEthInWei: z.string().describe("Amount of ETH to spend (in wei)"),
Expand All @@ -27,7 +27,7 @@ const WowBuyTokenInput = z
* @param args - The input arguments for the action.
* @returns A message containing the token purchase details.
*/
async function wowBuyToken(
export async function wowBuyToken(
wallet: Wallet,
args: z.infer<typeof WowBuyTokenInput>,
): Promise<string> {
Expand Down Expand Up @@ -63,7 +63,7 @@ async function wowBuyToken(
const result = await invocation.wait();
return `Purchased WoW ERC20 memecoin with transaction hash: ${result.getTransaction().getTransactionHash()}`;
} catch (error) {
return `Error buying Zora Wow ERC20 memecoin ${error}`;
return `Error buying Zora Wow ERC20 memecoin: ${error}`;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ This tool will create a Zora Wow ERC20 memecoin using the WoW factory. This tool
/**
* Input schema for create token action.
*/
const WowCreateTokenInput = z
export const WowCreateTokenInput = z
.object({
name: z.string().describe("The name of the token to create, e.g. WowCoin"),
symbol: z.string().describe("The symbol of the token to create, e.g. WOW"),
Expand All @@ -31,7 +31,7 @@ const WowCreateTokenInput = z
* @param args - The input arguments for the action.
* @returns A message containing the token creation details.
*/
async function wowCreateToken(
export async function wowCreateToken(
wallet: Wallet,
args: z.infer<typeof WowCreateTokenInput>,
): Promise<string> {
Expand All @@ -54,7 +54,7 @@ async function wowCreateToken(
const result = await invocation.wait();
return `Created WoW ERC20 memecoin ${args.name} with symbol ${args.symbol} on network ${wallet.getNetworkId()}.\nTransaction hash for the token creation: ${result.getTransaction().getTransactionHash()}`;
} catch (error) {
return `Error creating Zora Wow ERC20 memecoin ${error}`;
return `Error creating Zora Wow ERC20 memecoin: ${error}`;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ This tool will sell a Zora Wow ERC20 memecoin for ETH. This tool takes the WOW t
/**
* Input schema for sell token action.
*/
const WowSellTokenInput = z
export const WowSellTokenInput = z
.object({
contractAddress: z
.string()
Expand All @@ -35,7 +35,7 @@ const WowSellTokenInput = z
* @param args - The input arguments for the action.
* @returns A message confirming the sale with the transaction hash.
*/
async function wowSellToken(
export async function wowSellToken(
wallet: Wallet,
args: z.infer<typeof WowSellTokenInput>,
): Promise<string> {
Expand Down Expand Up @@ -68,7 +68,7 @@ async function wowSellToken(
const result = await invocation.wait();
return `Sold WoW ERC20 memecoin with transaction hash: ${result.getTransaction().getTransactionHash()}`;
} catch (error) {
return `Error selling Zora Wow ERC20 memecoin ${error}`;
return `Error selling Zora Wow ERC20 memecoin: ${error}`;
}
}

Expand Down
11 changes: 7 additions & 4 deletions cdp-agentkit-core/src/actions/cdp/deploy_nft.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ This tool will deploy an NFT (ERC-721) contract onchain from the wallet. It take
/**
* Input schema for deploy NFT action.
*/
const DeployNftInput = z
export const DeployNftInput = z
.object({
name: z.string().describe("The name of the NFT collection"),
symbol: z.string().describe("The symbol of the NFT collection"),
baseUri: z.string().describe("The base URI for the token metadata"),
baseURI: z.string().describe("The base URI for the token metadata"),
})
.strip()
.describe("Instructions for deploying an NFT collection");
Expand All @@ -24,12 +24,15 @@ const DeployNftInput = z
* @param args - The input arguments for the action.
* @returns A message containing the NFT token deployment details.
*/
async function deployNft(wallet: Wallet, args: z.infer<typeof DeployNftInput>): Promise<string> {
export async function deployNft(
wallet: Wallet,
args: z.infer<typeof DeployNftInput>,
): Promise<string> {
try {
const nftContract = await wallet.deployNFT({
name: args.name,
symbol: args.symbol,
baseURI: args.baseUri,
baseURI: args.baseURI,
});

const result = await nftContract.wait();
Expand Down
4 changes: 2 additions & 2 deletions cdp-agentkit-core/src/actions/cdp/deploy_token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This tool will deploy an ERC20 token smart contract. It takes the token name, sy
/**
* Input schema for deploy token action.
*/
const DeployTokenInput = z
export const DeployTokenInput = z
.object({
name: z.string().describe("The name of the token"),
symbol: z.string().describe("The token symbol"),
Expand All @@ -24,7 +24,7 @@ const DeployTokenInput = z
* @param args - The input arguments for the action.
* @returns A message containing the deployed token contract address and details.
*/
async function deployToken(
export async function deployToken(
wallet: Wallet,
args: z.infer<typeof DeployTokenInput>,
): Promise<string> {
Expand Down
7 changes: 5 additions & 2 deletions cdp-agentkit-core/src/actions/cdp/get_balance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ This tool will get the balance of all the addresses in the wallet for a given as
/**
* Input schema for get balance action.
*/
const GetBalanceInput = z
export const GetBalanceInput = z
.object({
assetId: z.string().describe("The asset ID to get the balance for"),
})
Expand All @@ -23,7 +23,10 @@ const GetBalanceInput = z
* @param args - The input arguments for the action.
* @returns A message containing the balance information.
*/
async function getBalance(wallet: Wallet, args: z.infer<typeof GetBalanceInput>): Promise<string> {
export async function getBalance(
wallet: Wallet,
args: z.infer<typeof GetBalanceInput>,
): Promise<string> {
const balances: Record<string, Decimal> = {};

try {
Expand Down
12 changes: 8 additions & 4 deletions cdp-agentkit-core/src/actions/cdp/get_wallet_details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Wallet } from "@coinbase/coinbase-sdk";
* Input schema for get wallet details action.
* This schema intentionally accepts no parameters as the wallet is injected separately.
*/
const GetWalletDetailsInput = z.object({});
export const GetWalletDetailsInput = z.object({});

/**
* Gets a wallet's details.
Expand All @@ -15,13 +15,17 @@ const GetWalletDetailsInput = z.object({});
* @param _ - The input arguments for the action.
* @returns A message containing the wallet details.
*/
async function getWalletDetails(
export async function getWalletDetails(
wallet: Wallet,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_: z.infer<typeof GetWalletDetailsInput>,
): Promise<string> {
const defaultAddress = await wallet.getDefaultAddress();
return `Wallet: ${wallet.getId()} on network: ${wallet.getNetworkId()} with default address: ${defaultAddress.getId()}`;
try {
const defaultAddress = await wallet.getDefaultAddress();
return `Wallet: ${wallet.getId()} on network: ${wallet.getNetworkId()} with default address: ${defaultAddress.getId()}`;
} catch (error) {
return `Error getting wallet details: ${error}`;
}
}

/**
Expand Down
4 changes: 2 additions & 2 deletions cdp-agentkit-core/src/actions/cdp/mint_nft.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This tool will mint an NFT (ERC-721) to a specified destination address onchain
/**
* Input schema for mint NFT action.
*/
const MintNftInput = z
export const MintNftInput = z
.object({
contractAddress: z.string().describe("The contract address of the NFT to mint"),
destination: z.string().describe("The destination address that will receive the NFT"),
Expand All @@ -23,7 +23,7 @@ const MintNftInput = z
* @param args - The input arguments for the action.
* @returns A message containing the NFT mint details.
*/
async function mintNft(wallet: Wallet, args: z.infer<typeof MintNftInput>): Promise<string> {
export async function mintNft(wallet: Wallet, args: z.infer<typeof MintNftInput>): Promise<string> {
const mintArgs = {
to: args.destination,
quantity: "1",
Expand Down
23 changes: 13 additions & 10 deletions cdp-agentkit-core/src/actions/cdp/register_basename.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,19 @@ Do not suggest any alternatives and never try to register a Basename with anothe
Basename fails, you should prompt to try again with a more unique name.`;

// Contract addresses
const BASENAMES_REGISTRAR_CONTROLLER_ADDRESS_MAINNET = "0x4cCb0BB02FCABA27e82a56646E81d8c5bC4119a5";
const BASENAMES_REGISTRAR_CONTROLLER_ADDRESS_TESTNET = "0x49aE3cC2e3AA768B1e5654f5D3C6002144A59581";
const L2_RESOLVER_ADDRESS_MAINNET = "0xC6d566A56A1aFf6508b41f6c90ff131615583BCD";
const L2_RESOLVER_ADDRESS_TESTNET = "0x6533C94869D28fAA8dF77cc63f9e2b2D6Cf77eBA";
export const BASENAMES_REGISTRAR_CONTROLLER_ADDRESS_MAINNET =
"0x4cCb0BB02FCABA27e82a56646E81d8c5bC4119a5";
export const BASENAMES_REGISTRAR_CONTROLLER_ADDRESS_TESTNET =
"0x49aE3cC2e3AA768B1e5654f5D3C6002144A59581";

export const L2_RESOLVER_ADDRESS_MAINNET = "0xC6d566A56A1aFf6508b41f6c90ff131615583BCD";
export const L2_RESOLVER_ADDRESS_TESTNET = "0x6533C94869D28fAA8dF77cc63f9e2b2D6Cf77eBA";

// Default registration duration (1 year in seconds)
const REGISTRATION_DURATION = "31557600";
export const REGISTRATION_DURATION = "31557600";

// Relevant ABI for L2 Resolver Contract.
const L2_RESOLVER_ABI = [
export const L2_RESOLVER_ABI = [
{
inputs: [
{ internalType: "bytes32", name: "node", type: "bytes32" },
Expand All @@ -44,7 +47,7 @@ const L2_RESOLVER_ABI = [
];

// Relevant ABI for Basenames Registrar Controller Contract.
const REGISTRAR_ABI = [
export const REGISTRAR_ABI = [
{
inputs: [
{
Expand Down Expand Up @@ -95,7 +98,7 @@ const REGISTRAR_ABI = [
/**
* Input schema for registering a Basename.
*/
const RegisterBasenameInput = z
export const RegisterBasenameInput = z
.object({
basename: z.string().describe("The Basename to assign to the agent"),
amount: z.string().default("0.002").describe("The amount of ETH to pay for registration"),
Expand Down Expand Up @@ -151,7 +154,7 @@ function createRegisterContractMethodArgs(
* @param args - The input arguments for the action.
* @returns Confirmation message with the basename.
*/
async function registerBasename(
export async function registerBasename(
wallet: Wallet,
args: z.infer<typeof RegisterBasenameInput>,
): Promise<string> {
Expand Down Expand Up @@ -183,7 +186,7 @@ async function registerBasename(
return `Successfully registered basename ${args.basename} for address ${addressId}`;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error) {
return `Error registering basename: ${error}`;
return `Error registering basename: Error: ${error}`;
}
}

Expand Down
8 changes: 4 additions & 4 deletions cdp-agentkit-core/src/actions/cdp/request_faucet_funds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ from another wallet and provide the user with your wallet details.`;
/**
* Input schema for request faucet funds action.
*/
const RequestFaucetFundsInput = z
export const RequestFaucetFundsInput = z
.object({
assetId: z.string().optional().describe("The optional asset ID to request from faucet"),
})
Expand All @@ -25,7 +25,7 @@ const RequestFaucetFundsInput = z
* @param args - The input arguments for the action.
* @returns A confirmation message with transaction details.
*/
async function requestFaucetFunds(
export async function requestFaucetFunds(
wallet: Wallet,
args: z.infer<typeof RequestFaucetFundsInput>,
): Promise<string> {
Expand All @@ -34,9 +34,9 @@ async function requestFaucetFunds(
const faucetTx = await wallet.faucet(args.assetId || undefined);

// Wait for the faucet transaction to be confirmed
await faucetTx.wait();
const result = await faucetTx.wait();

return `Received ${args.assetId || "ETH"} from the faucet. Transaction: ${faucetTx.getTransactionLink()}`;
return `Received ${args.assetId || "ETH"} from the faucet. Transaction: ${result.getTransactionLink()}`;
} catch (error) {
return `Error requesting faucet funds: ${error}`;
}
Expand Down
4 changes: 2 additions & 2 deletions cdp-agentkit-core/src/actions/cdp/trade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This tool will trade a specified amount of a from asset to a to asset for the wa
/**
* Input schema for trade action.
*/
const TradeInput = z
export const TradeInput = z
.object({
amount: z.custom<Amount>().describe("The amount of the from asset to trade"),
fromAssetId: z.string().describe("The from asset ID to trade"),
Expand All @@ -24,7 +24,7 @@ const TradeInput = z
* @param args - The input arguments for the action.
* @returns A message containing the trade details.
*/
async function trade(wallet: Wallet, args: z.infer<typeof TradeInput>): Promise<string> {
export async function trade(wallet: Wallet, args: z.infer<typeof TradeInput>): Promise<string> {
try {
const tradeResult = await wallet.createTrade({
amount: args.amount,
Expand Down
7 changes: 5 additions & 2 deletions cdp-agentkit-core/src/actions/cdp/transfer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This tool will transfer an asset from the wallet to another onchain address. It
/**
* Input schema for transfer action.
*/
const TransferInput = z
export const TransferInput = z
.object({
amount: z.custom<Amount>().describe("The amount of the asset to transfer"),
assetId: z.string().describe("The asset ID to transfer"),
Expand All @@ -25,7 +25,10 @@ const TransferInput = z
* @param args - The input arguments for the action.
* @returns A message containing the transfer details.
*/
async function transfer(wallet: Wallet, args: z.infer<typeof TransferInput>): Promise<string> {
export async function transfer(
wallet: Wallet,
args: z.infer<typeof TransferInput>,
): Promise<string> {
try {
const transferResult = await wallet.createTransfer({
amount: args.amount,
Expand Down
Loading

0 comments on commit 8410bcc

Please sign in to comment.