@@ -14,12 +14,12 @@ import {
14
14
AccountInfo ,
15
15
ContractInteractionResult
16
16
} from '../types/mcpTools' ;
17
- import { bytesToHex } from '@ethereumjs/util'
18
17
import { Plugin } from '@remixproject/engine' ;
19
18
import { getContractData } from '@remix-project/core-plugin'
20
19
import type { TxResult } from '@remix-project/remix-lib' ;
21
20
import type { TransactionReceipt } from 'web3'
22
- import web3 from 'web3'
21
+ import { BrowserProvider } from "ethers"
22
+ import web3 , { Web3 } from 'web3'
23
23
24
24
/**
25
25
* Deploy Contract Tool Handler
@@ -65,7 +65,7 @@ export class DeployContractHandler extends BaseToolHandler {
65
65
description : 'The file containing the contract to deploy'
66
66
}
67
67
} ,
68
- required : [ 'contractName' ]
68
+ required : [ 'contractName' , 'file' ]
69
69
} ;
70
70
71
71
getPermissions ( ) : string [ ] {
@@ -116,7 +116,7 @@ export class DeployContractHandler extends BaseToolHandler {
116
116
const compilerContracts = await plugin . call ( 'compilerArtefacts' , 'getLastCompilationResult' )
117
117
plugin . call ( 'blockchain' , 'deployContractAndLibraries' ,
118
118
data ,
119
- args . constructorArgs ? args : [ ] ,
119
+ args . constructorArgs ? args . constructorArgs : [ ] ,
120
120
null ,
121
121
compilerContracts . getData ( ) . contracts ,
122
122
callbacks ,
@@ -128,7 +128,6 @@ export class DeployContractHandler extends BaseToolHandler {
128
128
}
129
129
130
130
131
- console . log ( 'txReturn' , txReturn )
132
131
const receipt = ( txReturn . txResult . receipt as TransactionReceipt )
133
132
const result : DeploymentResult = {
134
133
transactionHash : web3 . utils . bytesToHex ( receipt . transactionHash ) ,
@@ -216,15 +215,15 @@ export class CallContractHandler extends BaseToolHandler {
216
215
description : 'Account to call from'
217
216
}
218
217
} ,
219
- required : [ 'address' , 'abi' , 'methodName' ]
218
+ required : [ 'address' , 'abi' , 'methodName' , 'contractName' ]
220
219
} ;
221
220
222
221
getPermissions ( ) : string [ ] {
223
222
return [ 'contract:interact' ] ;
224
223
}
225
224
226
225
validate ( args : CallContractArgs ) : boolean | string {
227
- const required = this . validateRequired ( args , [ 'address' , 'abi' , 'methodName' ] ) ;
226
+ const required = this . validateRequired ( args , [ 'address' , 'abi' , 'methodName' , 'contractName' ] ) ;
228
227
if ( required !== true ) return required ;
229
228
230
229
const types = this . validateTypes ( args , {
@@ -261,7 +260,7 @@ export class CallContractHandler extends BaseToolHandler {
261
260
args . abi ,
262
261
funcABI ,
263
262
undefined ,
264
- args . args ? args : [ ] ,
263
+ args . args ? args . args : [ ] ,
265
264
args . address ,
266
265
params ,
267
266
isView ,
@@ -314,15 +313,6 @@ export class CallContractHandler extends BaseToolHandler {
314
313
return this . createErrorResult ( `Contract call failed: ${ error . message } ` ) ;
315
314
}
316
315
}
317
-
318
- private async getAccounts ( plugin : Plugin ) : Promise < string [ ] > {
319
- try {
320
- // TODO: Get accounts from Remix API
321
- return [ '0x' + Math . random ( ) . toString ( 16 ) . substr ( 2 , 40 ) ] ; // Mock account
322
- } catch ( error ) {
323
- return [ ] ;
324
- }
325
- }
326
316
}
327
317
328
318
/**
@@ -397,40 +387,44 @@ export class SendTransactionHandler extends BaseToolHandler {
397
387
398
388
async execute ( args : SendTransactionArgs , plugin : Plugin ) : Promise < IMCPToolResult > {
399
389
try {
400
- // Get accounts
401
- const accounts = await this . getAccounts ( plugin ) ;
402
- const sendAccount = args . account || accounts [ 0 ] ;
390
+ // Get accounts
391
+ const sendAccount = args . account
403
392
404
393
if ( ! sendAccount ) {
405
394
return this . createErrorResult ( 'No account available for sending transaction' ) ;
406
395
}
396
+ const web3 : Web3 = await plugin . call ( 'blockchain' , 'web3' )
397
+ const ethersProvider = new BrowserProvider ( web3 . currentProvider )
398
+ const signer = await ethersProvider . getSigner ( ) ;
399
+ const tx = await signer . sendTransaction ( {
400
+ from : args . account ,
401
+ to : args . to ,
402
+ value : args . value || '0' ,
403
+ data : args . data ,
404
+ gasLimit : args . gasLimit ,
405
+ gasPrice : args . gasPrice
406
+ } ) ;
407
407
408
+ // Wait for the transaction to be mined
409
+ const receipt = await tx . wait ( )
408
410
// TODO: Send a real transaction via Remix Run Tab API
409
411
const mockResult = {
410
412
success : true ,
411
- transactionHash : '0x' + Math . random ( ) . toString ( 16 ) . substr ( 2 , 64 ) ,
412
- from : sendAccount ,
413
+ transactionHash : receipt . hash ,
414
+ from : args . account ,
413
415
to : args . to ,
414
416
value : args . value || '0' ,
415
- gasUsed : args . gasLimit || 21000 ,
416
- blockNumber : Math . floor ( Math . random ( ) * 1000000 )
417
+ gasUsed : web3 . utils . toNumber ( receipt . gasUsed ) ,
418
+ blockNumber : receipt . blockNumber
417
419
} ;
418
420
419
421
return this . createSuccessResult ( mockResult ) ;
420
422
421
423
} catch ( error ) {
424
+ console . log ( error )
422
425
return this . createErrorResult ( `Transaction failed: ${ error . message } ` ) ;
423
426
}
424
427
}
425
-
426
- private async getAccounts ( plugin : Plugin ) : Promise < string [ ] > {
427
- try {
428
- // TODO: Get accounts from Remix API
429
- return [ '0x' + Math . random ( ) . toString ( 16 ) . substr ( 2 , 40 ) ] ; // Mock account
430
- } catch ( error ) {
431
- return [ ] ;
432
- }
433
- }
434
428
}
435
429
436
430
/**
@@ -455,21 +449,11 @@ export class GetDeployedContractsHandler extends BaseToolHandler {
455
449
456
450
async execute ( args : { network ?: string } , plugin : Plugin ) : Promise < IMCPToolResult > {
457
451
try {
458
- // TODO: Get deployed contracts from Remix storage/state
459
- const mockDeployedContracts = [
460
- {
461
- name : 'MyToken' ,
462
- address : '0x' + Math . random ( ) . toString ( 16 ) . substr ( 2 , 40 ) ,
463
- network : args . network || 'local' ,
464
- deployedAt : new Date ( ) . toISOString ( ) ,
465
- transactionHash : '0x' + Math . random ( ) . toString ( 16 ) . substr ( 2 , 64 )
466
- }
467
- ] ;
468
-
452
+ const deployedContracts = await plugin . call ( 'udapp' , 'getAllDeployedInstances' )
469
453
return this . createSuccessResult ( {
470
454
success : true ,
471
- contracts : mockDeployedContracts ,
472
- count : mockDeployedContracts . length
455
+ contracts : deployedContracts ,
456
+ count : deployedContracts . length
473
457
} ) ;
474
458
475
459
} catch ( error ) {
@@ -489,7 +473,7 @@ export class SetExecutionEnvironmentHandler extends BaseToolHandler {
489
473
properties : {
490
474
environment : {
491
475
type : 'string' ,
492
- enum : [ 'vm-london' , 'vm-berlin' , 'injected' , 'web3 ' ] ,
476
+ enum : [ 'vm-prague' , 'vm-cancun' , 'vm-shanghai' , 'vm-paris' , 'vm- london', 'vm-berlin' , 'vm-mainnet-fork' , 'vm-sepolia-fork' , 'vm-custom-fork' , 'walletconnect' , 'basic-http-provider' , 'hardhat-provider' , 'ganache-provider' , 'foundry-provider' , ' injected-Rabby Wallet ', 'injected-MetaMask' , 'injected-metamask-optimism' , 'injected-metamask-arbitrum' , 'injected-metamask-sepolia' , 'injected-metamask-ephemery' , 'injected-metamask-gnosis' , 'injected-metamask-chiado' , 'injected-metamask-linea '] ,
493
477
description : 'Execution environment'
494
478
} ,
495
479
networkUrl : {
@@ -505,26 +489,23 @@ export class SetExecutionEnvironmentHandler extends BaseToolHandler {
505
489
}
506
490
507
491
validate ( args : { environment : string ; networkUrl ?: string } ) : boolean | string {
508
- const required = this . validateRequired ( args , [ 'environment' ] ) ;
509
- if ( required !== true ) return required ;
510
-
511
- const validEnvironments = [ 'vm-london' , 'vm-berlin' , 'injected' , 'web3' ] ;
512
- if ( ! validEnvironments . includes ( args . environment ) ) {
513
- return `Invalid environment. Must be one of: ${ validEnvironments . join ( ', ' ) } ` ;
514
- }
515
-
492
+ // we validate in the execute method to have access to the list of available providers.
516
493
return true ;
517
494
}
518
495
519
- async execute ( args : { environment : string ; networkUrl ?: string } , plugin : Plugin ) : Promise < IMCPToolResult > {
496
+ async execute ( args : { environment : string } , plugin : Plugin ) : Promise < IMCPToolResult > {
520
497
try {
521
- // TODO: Set execution environment via Remix Run Tab API
522
-
498
+ const providers = await plugin . call ( 'blockchain' , 'getAllProviders' )
499
+ console . log ( 'available providers' , Object . keys ( providers ) )
500
+ const provider = Object . keys ( providers ) . find ( ( p ) => p === args . environment )
501
+ if ( ! provider ) {
502
+ return this . createErrorResult ( `Could not find provider for environment '${ args . environment } '` ) ;
503
+ }
504
+ await plugin . call ( 'blockchain' , 'changeExecutionContext' , { context : args . environment } )
523
505
return this . createSuccessResult ( {
524
506
success : true ,
525
507
message : `Execution environment set to: ${ args . environment } ` ,
526
508
environment : args . environment ,
527
- networkUrl : args . networkUrl
528
509
} ) ;
529
510
530
511
} catch ( error ) {
@@ -568,16 +549,14 @@ export class GetAccountBalanceHandler extends BaseToolHandler {
568
549
569
550
async execute ( args : { account : string } , plugin : Plugin ) : Promise < IMCPToolResult > {
570
551
try {
571
- // TODO: Get account balance from current provider
572
- const mockBalance = ( Math . random ( ) * 10 ) . toFixed ( 4 ) ;
573
-
552
+ const web3 = await plugin . call ( 'blockchain' , 'web3' )
553
+ const balance = await web3 . eth . getBalance ( args . account )
574
554
return this . createSuccessResult ( {
575
555
success : true ,
576
556
account : args . account ,
577
- balance : mockBalance ,
557
+ balance : web3 . utils . fromWei ( balance , 'ether' ) ,
578
558
unit : 'ETH'
579
- } ) ;
580
-
559
+ } )
581
560
} catch ( error ) {
582
561
return this . createErrorResult ( `Failed to get account balance: ${ error . message } ` ) ;
583
562
}
@@ -712,9 +691,10 @@ export class SetSelectedAccountHandler extends BaseToolHandler {
712
691
try {
713
692
// Set the selected account through the udapp plugin
714
693
await plugin . call ( 'udapp' as any , 'setAccount' , args . address ) ;
694
+ await new Promise ( ( resolve ) => setTimeout ( resolve , 1000 ) ) ; // Wait a moment for the change to propagate
715
695
716
696
// Verify the account was set
717
- const runTabApi = await plugin . call ( 'udapp' as any , 'getAccounts ' ) ;
697
+ const runTabApi = await plugin . call ( 'udapp' as any , 'getRunTabAPI ' ) ;
718
698
const currentSelected = runTabApi ?. accounts ?. selectedAccount ;
719
699
720
700
if ( currentSelected !== args . address ) {
@@ -750,37 +730,25 @@ export class GetCurrentEnvironmentHandler extends BaseToolHandler {
750
730
async execute ( _args : any , plugin : Plugin ) : Promise < IMCPToolResult > {
751
731
try {
752
732
// Get environment information
753
- const provider = await plugin . call ( 'blockchain' as any , 'getCurrentProvider' ) ;
754
- const networkName = await plugin . call ( 'blockchain' as any , 'getNetworkName' ) . catch ( ( ) => 'unknown' ) ;
755
- const chainId = await plugin . call ( 'blockchain' as any , 'getChainId' ) . catch ( ( ) => 'unknown' ) ;
733
+ const provider = await plugin . call ( 'blockchain' as any , 'getProvider' ) ;
734
+ const network = await plugin . call ( 'network' , 'detectNetwork' )
756
735
757
- // Get accounts info
758
- const runTabApi = await plugin . call ( 'udapp' as any , 'getAccounts' ) ;
759
- const accountsCount = runTabApi ?. accounts ?. loadedAccounts
760
- ? Object . keys ( runTabApi . accounts . loadedAccounts ) . length
761
- : 0 ;
736
+ // Verify the account was set
737
+ const runTabApi = await plugin . call ( 'udapp' as any , 'getRunTabAPI' ) ;
738
+ const accounts = runTabApi ?. accounts ;
762
739
763
740
const result = {
764
741
success : true ,
765
742
environment : {
766
- provider : {
767
- name : provider ?. name || 'unknown' ,
768
- displayName : provider ?. displayName || provider ?. name || 'unknown' ,
769
- kind : provider ?. kind || 'unknown'
770
- } ,
771
- network : {
772
- name : networkName ,
773
- chainId : chainId
774
- } ,
775
- accounts : {
776
- total : accountsCount ,
777
- selected : runTabApi ?. accounts ?. selectedAccount || null
778
- }
743
+ provider,
744
+ network,
745
+ accounts
779
746
}
780
747
} ;
781
748
782
749
return this . createSuccessResult ( result ) ;
783
750
} catch ( error ) {
751
+ console . error ( error )
784
752
return this . createErrorResult ( `Failed to get environment information: ${ error . message } ` ) ;
785
753
}
786
754
}
0 commit comments