From 91f99ff725e7a2433c60e41c68ce19bf05179a20 Mon Sep 17 00:00:00 2001 From: ai16z-demirizx Date: Tue, 4 Feb 2025 22:54:17 +0100 Subject: [PATCH 1/5] plugin-cronos: vitest config --- packages/plugin-cronos/vitest.config.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 packages/plugin-cronos/vitest.config.ts diff --git a/packages/plugin-cronos/vitest.config.ts b/packages/plugin-cronos/vitest.config.ts new file mode 100644 index 00000000000..419efc958f9 --- /dev/null +++ b/packages/plugin-cronos/vitest.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + setupFiles: ['./__tests__/setup.ts'], + include: ['**/__tests__/**/*.test.ts'], + } +}); From 18136554b466ad7af73d1f78d59a4a6cd98bbef8 Mon Sep 17 00:00:00 2001 From: ai16z-demirizx Date: Tue, 4 Feb 2025 22:54:32 +0100 Subject: [PATCH 2/5] plugin-cronos: package json --- packages/plugin-cronos/package.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/plugin-cronos/package.json b/packages/plugin-cronos/package.json index 34f50cfc680..ed528261ec2 100644 --- a/packages/plugin-cronos/package.json +++ b/packages/plugin-cronos/package.json @@ -23,7 +23,8 @@ }, "devDependencies": { "@biomejs/biome": "1.9.4", - "tsup": "8.3.5" + "tsup": "8.3.5", + "vitest": "3.0.5" }, "scripts": { "build": "tsup --format esm --no-dts", @@ -32,7 +33,8 @@ "lint": "biome lint .", "lint:fix": "biome check --apply .", "format": "biome format .", - "format:fix": "biome format --write ." + "format:fix": "biome format --write .", + "test": "vitest run" }, "peerDependencies": { "whatwg-url": "7.1.0" From 3066afe59a3799e3f00e12b210804b8e57a09deb Mon Sep 17 00:00:00 2001 From: ai16z-demirizx Date: Tue, 4 Feb 2025 22:54:44 +0100 Subject: [PATCH 3/5] plugin-cronos: setup --- packages/plugin-cronos/__tests__/setup.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 packages/plugin-cronos/__tests__/setup.ts diff --git a/packages/plugin-cronos/__tests__/setup.ts b/packages/plugin-cronos/__tests__/setup.ts new file mode 100644 index 00000000000..cea985b0bf4 --- /dev/null +++ b/packages/plugin-cronos/__tests__/setup.ts @@ -0,0 +1,22 @@ +import { vi } from 'vitest'; + +// Mock viem functions +vi.mock('viem', () => ({ + isAddress: vi.fn().mockReturnValue(true), + formatEther: vi.fn().mockReturnValue('1.0'), + parseEther: vi.fn().mockReturnValue(BigInt(1000000000000000000)), // 1 ETH +})); + +// Mock wallet provider +vi.mock('../../src/providers/wallet', () => ({ + initCronosWalletProvider: vi.fn().mockReturnValue({ + switchChain: vi.fn(), + getWalletClient: vi.fn().mockReturnValue({ + account: { + address: '0x1234567890123456789012345678901234567890', + }, + sendTransaction: vi.fn().mockResolvedValue('0x123'), + }), + getAddressBalance: vi.fn().mockResolvedValue('1.0'), + }), +})); From 10fd79a95f88d79b2ac6eb2495f2f85dab2bb35f Mon Sep 17 00:00:00 2001 From: ai16z-demirizx Date: Tue, 4 Feb 2025 22:54:56 +0100 Subject: [PATCH 4/5] plugin-cronos: balance tests --- .../__tests__/actions/balance.test.ts | 152 ++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 packages/plugin-cronos/__tests__/actions/balance.test.ts diff --git a/packages/plugin-cronos/__tests__/actions/balance.test.ts b/packages/plugin-cronos/__tests__/actions/balance.test.ts new file mode 100644 index 00000000000..71e0534afd8 --- /dev/null +++ b/packages/plugin-cronos/__tests__/actions/balance.test.ts @@ -0,0 +1,152 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { balanceAction } from '../../src/actions/balance'; +import { + type IAgentRuntime, + type Memory, + ModelClass, + ModelProviderName, + type State, + type HandlerCallback, +} from '@elizaos/core'; +import * as core from '@elizaos/core'; + +// Mock generateObject +vi.mock('@elizaos/core', async () => { + const actual = await vi.importActual('@elizaos/core'); + return { + ...actual, + generateObject: vi.fn().mockResolvedValue({ + object: { + chain: 'cronos', + address: '0x1234567890123456789012345678901234567890' + } + }), + }; +}); + +// Mock wallet provider +vi.mock('../../src/providers/wallet', () => ({ + initCronosWalletProvider: vi.fn().mockReturnValue({ + switchChain: vi.fn(), + getWalletClient: vi.fn(), + getAddressBalance: vi.fn().mockResolvedValue('1.0'), + }), +})); + +describe('balance action', () => { + const mockRuntime: IAgentRuntime = { + getSetting: vi.fn().mockReturnValue('0x1234567890123456789012345678901234567890123456789012345678901234'), + composeState: vi.fn().mockResolvedValue({}), + updateRecentMessageState: vi.fn().mockResolvedValue({}), + generateText: vi.fn(), + model: { + [ModelClass.SMALL]: { + name: 'gpt-4', + maxInputTokens: 128000, + maxOutputTokens: 8192, + frequency_penalty: 0.0, + presence_penalty: 0.0, + temperature: 0.6, + stop: [], + }, + [ModelClass.MEDIUM]: { + name: 'gpt-4', + maxInputTokens: 128000, + maxOutputTokens: 8192, + frequency_penalty: 0.0, + presence_penalty: 0.0, + temperature: 0.6, + stop: [], + }, + [ModelClass.LARGE]: { + name: 'gpt-4', + maxInputTokens: 128000, + maxOutputTokens: 8192, + frequency_penalty: 0.0, + presence_penalty: 0.0, + temperature: 0.6, + stop: [], + } + }, + modelProvider: ModelProviderName.OPENAI, + }; + + const mockMessage: Memory = { + content: { + text: 'Check balance for 0x1234567890123456789012345678901234567890 on Cronos', + }, + }; + + const mockCallback: HandlerCallback = vi.fn(); + + beforeEach(() => { + vi.clearAllMocks(); + }); + + it('should validate successfully', async () => { + const result = await balanceAction.validate(mockRuntime); + expect(result).toBe(true); + }); + + it('should handle successful balance check', async () => { + const result = await balanceAction.handler( + mockRuntime, + mockMessage, + undefined, + undefined, + mockCallback + ); + + expect(result).toBe(true); + expect(mockCallback).toHaveBeenCalledWith({ + text: 'Balance for 0x1234567890123456789012345678901234567890 on cronos is 1.0 CRO', + content: { + success: true, + balance: '1.0', + chain: 'cronos', + address: '0x1234567890123456789012345678901234567890' + } + }); + }); + + it('should handle balance check with existing state', async () => { + const mockState = {}; + const result = await balanceAction.handler( + mockRuntime, + mockMessage, + mockState, + undefined, + mockCallback + ); + + expect(result).toBe(true); + expect(mockRuntime.updateRecentMessageState).toHaveBeenCalledWith(mockState); + }); + + it('should handle balance check failure', async () => { + const mockError = new Error('Failed to fetch balance'); + const mockProvider = { + switchChain: vi.fn(), + getWalletClient: vi.fn(), + getAddressBalance: vi.fn().mockRejectedValue(mockError), + }; + + // Reset the mock first + const walletModule = await import('../../src/providers/wallet'); + vi.mocked(walletModule.initCronosWalletProvider).mockResolvedValueOnce(mockProvider); + + const result = await balanceAction.handler( + mockRuntime, + mockMessage, + undefined, + undefined, + mockCallback + ); + + expect(result).toBe(false); + expect(mockCallback).toHaveBeenCalledWith({ + text: 'Error checking balance: Failed to fetch balance', + content: { error: 'Failed to fetch balance' } + }); + }); +}); From 7d8ebe5aeee6600a1f878f78920934f5be70bd1a Mon Sep 17 00:00:00 2001 From: ai16z-demirizx Date: Tue, 4 Feb 2025 22:55:11 +0100 Subject: [PATCH 5/5] plugin-cronos: transfer tests --- .../__tests__/actions/transfer.test.ts | 164 ++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 packages/plugin-cronos/__tests__/actions/transfer.test.ts diff --git a/packages/plugin-cronos/__tests__/actions/transfer.test.ts b/packages/plugin-cronos/__tests__/actions/transfer.test.ts new file mode 100644 index 00000000000..19165442840 --- /dev/null +++ b/packages/plugin-cronos/__tests__/actions/transfer.test.ts @@ -0,0 +1,164 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { transferAction } from '../../src/actions/transfer'; +import { + type IAgentRuntime, + type Memory, + ModelClass, + ModelProviderName, + type State, + type HandlerCallback, +} from '@elizaos/core'; +import * as core from '@elizaos/core'; +import { parseEther } from 'viem'; + +// Mock generateObject +vi.mock('@elizaos/core', async () => { + const actual = await vi.importActual('@elizaos/core'); + return { + ...actual, + generateObject: vi.fn().mockResolvedValue({ + object: { + chain: 'cronos', + toAddress: '0x1234567890123456789012345678901234567890', + amount: '1.0' + } + }), + }; +}); + +// Mock wallet provider +vi.mock('../../src/providers/wallet', () => ({ + initCronosWalletProvider: vi.fn().mockReturnValue({ + switchChain: vi.fn(), + getWalletClient: vi.fn().mockReturnValue({ + account: { + address: '0x1234567890123456789012345678901234567890', + }, + sendTransaction: vi.fn().mockResolvedValue('0x123'), + }), + }), +})); + +describe('transfer action', () => { + const mockRuntime: IAgentRuntime = { + getSetting: vi.fn().mockReturnValue('0x1234567890123456789012345678901234567890123456789012345678901234'), + composeState: vi.fn().mockResolvedValue({}), + updateRecentMessageState: vi.fn().mockResolvedValue({}), + generateText: vi.fn(), + model: { + [ModelClass.SMALL]: { + name: 'gpt-4', + maxInputTokens: 128000, + maxOutputTokens: 8192, + frequency_penalty: 0.0, + presence_penalty: 0.0, + temperature: 0.6, + stop: [], + }, + [ModelClass.MEDIUM]: { + name: 'gpt-4', + maxInputTokens: 128000, + maxOutputTokens: 8192, + frequency_penalty: 0.0, + presence_penalty: 0.0, + temperature: 0.6, + stop: [], + }, + [ModelClass.LARGE]: { + name: 'gpt-4', + maxInputTokens: 128000, + maxOutputTokens: 8192, + frequency_penalty: 0.0, + presence_penalty: 0.0, + temperature: 0.6, + stop: [], + } + }, + modelProvider: ModelProviderName.OPENAI, + }; + + const mockMessage: Memory = { + content: { + text: 'Send 1.0 CRO to 0x1234567890123456789012345678901234567890 on Cronos', + }, + }; + + const mockCallback: HandlerCallback = vi.fn(); + + beforeEach(() => { + vi.clearAllMocks(); + }); + + it('should validate successfully', async () => { + const result = await transferAction.validate(mockRuntime); + expect(result).toBe(true); + }); + + it('should handle successful transfer', async () => { + const result = await transferAction.handler( + mockRuntime, + mockMessage, + undefined, + undefined, + mockCallback + ); + + expect(result).toBe(true); + expect(mockCallback).toHaveBeenCalledWith({ + text: 'Successfully transferred 1.0 CRO to 0x1234567890123456789012345678901234567890\nTransaction Hash: 0x123', + content: { + success: true, + hash: '0x123', + amount: '1', + recipient: '0x1234567890123456789012345678901234567890', + chain: undefined + } + }); + }); + + it('should handle transfer with existing state', async () => { + const mockState = {}; + const result = await transferAction.handler( + mockRuntime, + mockMessage, + mockState, + undefined, + mockCallback + ); + + expect(result).toBe(true); + expect(mockRuntime.updateRecentMessageState).toHaveBeenCalledWith(mockState); + }); + + + it('should handle transfer failure', async () => { + const mockError = new Error('Transfer failed'); + const mockProvider = { + switchChain: vi.fn(), + getWalletClient: vi.fn().mockReturnValue({ + account: { + address: '0x1234567890123456789012345678901234567890', + }, + sendTransaction: vi.fn().mockRejectedValue(mockError), + }), + }; + + // Reset the mock first + const walletModule = await import('../../src/providers/wallet'); + vi.mocked(walletModule.initCronosWalletProvider).mockResolvedValueOnce(mockProvider); + + const result = await transferAction.handler( + mockRuntime, + mockMessage, + undefined, + undefined, + mockCallback + ); + + expect(result).toBe(false); + expect(mockCallback).toHaveBeenCalledWith({ + text: 'Error transferring tokens: Transfer failed: Transfer failed', + content: { error: 'Transfer failed: Transfer failed' } + }); + }); +});