@@ -844,6 +844,7 @@ describe('EVM Tools', () => {
844844 // Verify contract interaction tools
845845 expect ( registeredTools . has ( 'read_contract' ) ) . toBe ( true ) ;
846846 expect ( registeredTools . has ( 'write_contract' ) ) . toBe ( true ) ;
847+ expect ( registeredTools . has ( 'deploy_contract' ) ) . toBe ( true ) ;
847848 } ) ;
848849
849850 // Group 4: Transaction Tools
@@ -2501,4 +2502,211 @@ describe('EVM Tools', () => {
25012502 verifyErrorResponse ( response , 'Error checking if address is a contract: Test error' ) ;
25022503 } ) ;
25032504 } ) ;
2505+
2506+ test ( 'write_contract - error with non-Error object' , async ( ) => {
2507+ const tool = checkToolExists ( 'write_contract' ) ;
2508+ if ( ! tool ) return ;
2509+
2510+ const params = {
2511+ contractAddress : '0x1234567890123456789012345678901234567890' ,
2512+ abi : [
2513+ {
2514+ inputs : [ { name : 'to' , type : 'address' } , { name : 'value' , type : 'uint256' } ] ,
2515+ name : 'transfer' ,
2516+ outputs : [ { name : '' , type : 'bool' } ] ,
2517+ stateMutability : 'nonpayable' ,
2518+ type : 'function'
2519+ }
2520+ ] ,
2521+ functionName : 'transfer' ,
2522+ args : [ '0x0987654321098765432109876543210987654321' , '1000000000000000000' ] ,
2523+ network : mockNetwork
2524+ } ;
2525+
2526+ const nonErrorObject = "This is a string error" ;
2527+
2528+ ( services . writeContract as jest . Mock ) . mockImplementationOnce ( ( ) => {
2529+ throw nonErrorObject ;
2530+ } ) ;
2531+
2532+ const response = await tool . handler ( params ) ;
2533+
2534+ expect ( response ) . toHaveProperty ( 'isError' , true ) ;
2535+ expect ( response . content [ 0 ] . text ) . toContain ( 'Error writing to contract: This is a string error' ) ;
2536+ } ) ;
2537+
2538+ test ( 'deploy_contract - success path' , async ( ) => {
2539+ const tool = checkToolExists ( 'deploy_contract' ) ;
2540+ if ( ! tool ) return ;
2541+
2542+ const mockDeployResult = {
2543+ address : '0x1234567890123456789012345678901234567890' as `0x${string } `,
2544+ transactionHash : '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890' as `0x${string } `
2545+ } ;
2546+
2547+ // Mock the deployContract function before calling testToolSuccess
2548+ ( services . deployContract as jest . Mock ) . mockImplementationOnce ( ( ) => {
2549+ return Promise . resolve ( mockDeployResult ) ;
2550+ } ) ;
2551+
2552+ const params = {
2553+ bytecode : '0x608060405234801561001057600080fd5b50' ,
2554+ abi : [
2555+ {
2556+ inputs : [ { name : 'initialValue' , type : 'uint256' } ] ,
2557+ stateMutability : 'nonpayable' ,
2558+ type : 'constructor'
2559+ }
2560+ ] ,
2561+ args : [ '1000' ] ,
2562+ network : mockNetwork
2563+ } ;
2564+
2565+ const response = await testToolSuccess ( tool , params ) ;
2566+
2567+ expect ( services . deployContract ) . toHaveBeenCalledWith (
2568+ '0x608060405234801561001057600080fd5b50' ,
2569+ params . abi ,
2570+ params . args ,
2571+ mockNetwork
2572+ ) ;
2573+
2574+ expect ( response ) . toHaveProperty ( 'content' ) ;
2575+ expect ( response . content [ 0 ] ) . toHaveProperty ( 'type' , 'text' ) ;
2576+
2577+ const responseData = JSON . parse ( response . content [ 0 ] . text ) ;
2578+ expect ( responseData ) . toMatchObject ( {
2579+ success : true ,
2580+ network : mockNetwork ,
2581+ contractAddress : mockDeployResult . address ,
2582+ transactionHash : mockDeployResult . transactionHash ,
2583+ message : 'Contract deployed successfully'
2584+ } ) ;
2585+ } ) ;
2586+
2587+ test ( 'deploy_contract - success path without 0x prefix in bytecode' , async ( ) => {
2588+ const tool = checkToolExists ( 'deploy_contract' ) ;
2589+ if ( ! tool ) return ;
2590+
2591+ const mockDeployResult = {
2592+ address : '0x1234567890123456789012345678901234567890' as `0x${string } `,
2593+ transactionHash : '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890' as `0x${string } `
2594+ } ;
2595+
2596+ // Mock the deployContract function before calling testToolSuccess
2597+ ( services . deployContract as jest . Mock ) . mockImplementationOnce ( ( ) => {
2598+ return Promise . resolve ( mockDeployResult ) ;
2599+ } ) ;
2600+
2601+ const params = {
2602+ bytecode : '608060405234801561001057600080fd5b50' , // Without 0x prefix
2603+ abi : [
2604+ {
2605+ inputs : [ ] ,
2606+ stateMutability : 'nonpayable' ,
2607+ type : 'constructor'
2608+ }
2609+ ] ,
2610+ network : mockNetwork
2611+ } ;
2612+
2613+ const response = await testToolSuccess ( tool , params ) ;
2614+
2615+ expect ( services . deployContract ) . toHaveBeenCalledWith (
2616+ '0x608060405234801561001057600080fd5b50' , // Should be formatted with 0x
2617+ params . abi ,
2618+ [ ] ,
2619+ mockNetwork
2620+ ) ;
2621+
2622+ expect ( response ) . toHaveProperty ( 'content' ) ;
2623+ expect ( response . content [ 0 ] ) . toHaveProperty ( 'type' , 'text' ) ;
2624+ } ) ;
2625+
2626+ test ( 'deploy_contract - success path with default network and no args' , async ( ) => {
2627+ const tool = checkToolExists ( 'deploy_contract' ) ;
2628+ if ( ! tool ) return ;
2629+
2630+ const mockDeployResult = {
2631+ address : '0x1234567890123456789012345678901234567890' as `0x${string } `,
2632+ transactionHash : '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890' as `0x${string } `
2633+ } ;
2634+
2635+ // Mock the deployContract function before calling testToolSuccess
2636+ ( services . deployContract as jest . Mock ) . mockImplementationOnce ( ( ) => {
2637+ return Promise . resolve ( mockDeployResult ) ;
2638+ } ) ;
2639+
2640+ const params = {
2641+ bytecode : '0x608060405234801561001057600080fd5b50' ,
2642+ abi : [
2643+ {
2644+ inputs : [ ] ,
2645+ stateMutability : 'nonpayable' ,
2646+ type : 'constructor'
2647+ }
2648+ ]
2649+ } ;
2650+
2651+ const response = await testToolSuccess ( tool , params ) ;
2652+
2653+ expect ( services . deployContract ) . toHaveBeenCalledWith (
2654+ params . bytecode ,
2655+ params . abi ,
2656+ [ ] ,
2657+ 'sei' // DEFAULT_NETWORK
2658+ ) ;
2659+
2660+ expect ( response ) . toHaveProperty ( 'content' ) ;
2661+ expect ( response . content [ 0 ] ) . toHaveProperty ( 'type' , 'text' ) ;
2662+ } ) ;
2663+
2664+ test ( 'deploy_contract - error path' , async ( ) => {
2665+ const tool = checkToolExists ( 'deploy_contract' ) ;
2666+ if ( ! tool ) return ;
2667+
2668+ const params = {
2669+ bytecode : '0x608060405234801561001057600080fd5b50' ,
2670+ abi : [
2671+ {
2672+ inputs : [ ] ,
2673+ stateMutability : 'nonpayable' ,
2674+ type : 'constructor'
2675+ }
2676+ ] ,
2677+ network : mockNetwork
2678+ } ;
2679+
2680+ const response = await testToolError ( tool , params , services . deployContract as jest . Mock , mockError ) ;
2681+
2682+ verifyErrorResponse ( response , 'Error deploying contract: Test error' ) ;
2683+ } ) ;
2684+
2685+ test ( 'deploy_contract - error with non-Error object' , async ( ) => {
2686+ const tool = checkToolExists ( 'deploy_contract' ) ;
2687+ if ( ! tool ) return ;
2688+
2689+ const params = {
2690+ bytecode : '0x608060405234801561001057600080fd5b50' ,
2691+ abi : [
2692+ {
2693+ inputs : [ ] ,
2694+ stateMutability : 'nonpayable' ,
2695+ type : 'constructor'
2696+ }
2697+ ] ,
2698+ network : mockNetwork
2699+ } ;
2700+
2701+ const nonErrorObject = "This is a string error" ;
2702+
2703+ ( services . deployContract as jest . Mock ) . mockImplementationOnce ( ( ) => {
2704+ throw nonErrorObject ;
2705+ } ) ;
2706+
2707+ const response = await tool . handler ( params ) ;
2708+
2709+ expect ( response ) . toHaveProperty ( 'isError' , true ) ;
2710+ expect ( response . content [ 0 ] . text ) . toContain ( 'Error deploying contract: This is a string error' ) ;
2711+ } ) ;
25042712} ) ;
0 commit comments