@@ -20,10 +20,13 @@ use log::{error, info};
2020
2121use aligned_sdk:: sdk:: { get_verification_key_commitment, submit_multiple, verify_proof_onchain} ;
2222
23+ use ethers:: utils:: format_ether;
2324use ethers:: utils:: hex;
2425use ethers:: utils:: parse_ether;
26+ use transaction:: eip2718:: TypedTransaction ;
2527
2628use crate :: AlignedCommands :: DepositToBatcher ;
29+ use crate :: AlignedCommands :: GetUserBalance ;
2730use crate :: AlignedCommands :: GetVerificationKeyCommitment ;
2831use crate :: AlignedCommands :: Submit ;
2932use crate :: AlignedCommands :: VerifyProofOnchain ;
@@ -54,6 +57,8 @@ pub enum AlignedCommands {
5457 name = "deposit-to-batcher"
5558 ) ]
5659 DepositToBatcher ( DepositToBatcherArgs ) ,
60+ #[ clap( about = "Get user balance from the batcher" , name = "get-user-balance" ) ]
61+ GetUserBalance ( GetUserBalanceArgs ) ,
5762}
5863
5964#[ derive( Parser , Debug ) ]
@@ -158,6 +163,29 @@ pub struct GetVerificationKeyCommitmentArgs {
158163 output_file : Option < PathBuf > ,
159164}
160165
166+ #[ derive( Parser , Debug ) ]
167+ #[ command( version, about, long_about = None ) ]
168+ pub struct GetUserBalanceArgs {
169+ #[ arg(
170+ name = "Batcher Eth Address" ,
171+ long = "batcher_addr" ,
172+ default_value = "0x7969c5eD335650692Bc04293B07F5BF2e7A673C0"
173+ ) ]
174+ batcher_eth_address : String ,
175+ #[ arg(
176+ name = "Ethereum RPC provider address" ,
177+ long = "rpc" ,
178+ default_value = "http://localhost:8545"
179+ ) ]
180+ eth_rpc_url : String ,
181+ #[ arg(
182+ name = "The user's Ethereum address" ,
183+ long = "user_addr" ,
184+ required = true
185+ ) ]
186+ user_address : String ,
187+ }
188+
161189#[ derive( Debug , Clone , ValueEnum ) ]
162190enum ChainArg {
163191 Devnet ,
@@ -410,6 +438,35 @@ async fn main() -> Result<(), AlignedError> {
410438 error ! ( "Transaction failed" ) ;
411439 }
412440 }
441+ GetUserBalance ( get_user_balance_args) => {
442+ let eth_rpc_url = get_user_balance_args. eth_rpc_url ;
443+
444+ let eth_rpc_provider = Provider :: < Http > :: try_from ( eth_rpc_url) . map_err ( |e| {
445+ SubmitError :: EthError ( format ! ( "Error while connecting to Ethereum: {}" , e) )
446+ } ) ?;
447+
448+ let user_address =
449+ Address :: from_str ( & get_user_balance_args. user_address ) . map_err ( |e| {
450+ SubmitError :: EthError ( format ! ( "Error while parsing user address: {}" , e) )
451+ } ) ?;
452+
453+ let batcher_addr = Address :: from_str ( & get_user_balance_args. batcher_eth_address )
454+ . map_err ( |e| {
455+ SubmitError :: EthError ( format ! ( "Error while parsing batcher address: {}" , e) )
456+ } ) ?;
457+
458+ let balance = get_user_balance ( eth_rpc_provider, batcher_addr, user_address)
459+ . await
460+ . map_err ( |e| {
461+ SubmitError :: EthError ( format ! ( "Error while getting user balance: {}" , e) )
462+ } ) ?;
463+
464+ info ! (
465+ "User {} has {} ether in the batcher" ,
466+ user_address,
467+ format_ether( balance)
468+ ) ;
469+ }
413470 }
414471
415472 Ok ( ( ) )
@@ -494,3 +551,33 @@ fn save_response(
494551
495552 Ok ( ( ) )
496553}
554+
555+ pub async fn get_user_balance (
556+ provider : Provider < Http > ,
557+ contract_address : Address ,
558+ user_address : Address ,
559+ ) -> Result < U256 , ProviderError > {
560+ let selector = & ethers:: utils:: keccak256 ( "UserBalances(address)" . as_bytes ( ) ) [ ..4 ] ;
561+
562+ let encoded_params = ethers:: abi:: encode ( & [ ethers:: abi:: Token :: Address ( user_address) ] ) ;
563+
564+ let mut call_data = selector. to_vec ( ) ;
565+ call_data. extend_from_slice ( & encoded_params) ;
566+
567+ let tx = TypedTransaction :: Legacy ( TransactionRequest {
568+ to : Some ( NameOrAddress :: Address ( contract_address) ) ,
569+ data : Some ( Bytes ( call_data. into ( ) ) ) ,
570+ ..Default :: default ( )
571+ } ) ;
572+
573+ let result = provider. call_raw ( & tx) . await ?;
574+
575+ if result. len ( ) == 32 {
576+ let balance = U256 :: from_big_endian ( & result) ;
577+ Ok ( balance)
578+ } else {
579+ Err ( ProviderError :: CustomError (
580+ "Invalid response from contract" . to_string ( ) ,
581+ ) )
582+ }
583+ }
0 commit comments