@@ -8,12 +8,13 @@ use alloy_consensus::{SignableTransaction, TxEip1559, TxEnvelope};
8
8
use alloy_primitives:: { hex, Signature , TxKind , U256 } ;
9
9
use candid:: { CandidType , Deserialize , Nat , Principal } ;
10
10
use evm_rpc_canister_types:: {
11
- BlockTag , EvmRpcCanister , GetTransactionCountArgs , GetTransactionCountResult ,
12
- MultiGetTransactionCountResult ,
11
+ BlockTag , EthMainnetService , EthSepoliaService , EvmRpcCanister , GetTransactionCountArgs ,
12
+ GetTransactionCountResult , MultiGetTransactionCountResult , RequestResult , RpcService ,
13
13
} ;
14
14
use ic_cdk:: api:: management_canister:: ecdsa:: { EcdsaCurve , EcdsaKeyId } ;
15
15
use ic_cdk:: { init, update} ;
16
16
use ic_ethereum_types:: Address ;
17
+ use num:: { BigUint , Num } ;
17
18
use std:: str:: FromStr ;
18
19
19
20
pub const EVM_RPC_CANISTER_ID : Principal =
@@ -35,6 +36,47 @@ pub async fn ethereum_address(owner: Option<Principal>) -> String {
35
36
wallet. ethereum_address ( ) . to_string ( )
36
37
}
37
38
39
+ #[ update]
40
+ pub async fn get_balance ( address : String ) -> Nat {
41
+ let _caller = validate_caller_not_anonymous ( ) ;
42
+ let json = format ! (
43
+ r#"{{ "jsonrpc": "2.0", "method": "eth_getBalance", "params": ["{}", "latest"], "id": 1 }}"# ,
44
+ address
45
+ ) ;
46
+
47
+ let max_response_size_bytes = 500_u64 ;
48
+ let num_cycles = 1_000_000_000u128 ;
49
+
50
+ let ethereum_network = read_state ( |s| s. ethereum_network ( ) ) ;
51
+
52
+ let rpc_service = match ethereum_network {
53
+ EthereumNetwork :: Mainnet => RpcService :: EthMainnet ( EthMainnetService :: PublicNode ) ,
54
+ EthereumNetwork :: Sepolia => RpcService :: EthSepolia ( EthSepoliaService :: PublicNode ) ,
55
+ } ;
56
+
57
+ let ( response, ) = EVM_RPC
58
+ . request ( rpc_service, json, max_response_size_bytes, num_cycles)
59
+ . await
60
+ . expect ( "RPC call failed" ) ;
61
+
62
+ let hex_balance = match response {
63
+ RequestResult :: Ok ( balance_result) => {
64
+ // The response to a successful `eth_getBalance` call has the following format:
65
+ // { "id": "[ID]", "jsonrpc": "2.0", "result": "[BALANCE IN HEX]" }
66
+ let response: serde_json:: Value = serde_json:: from_str ( & balance_result) . unwrap ( ) ;
67
+ response
68
+ . get ( "result" )
69
+ . and_then ( |v| v. as_str ( ) )
70
+ . unwrap ( )
71
+ . to_string ( )
72
+ }
73
+ RequestResult :: Err ( e) => panic ! ( "Received an error response: {:?}" , e) ,
74
+ } ;
75
+
76
+ // Remove the "0x" prefix before converting to a decimal number.
77
+ Nat ( BigUint :: from_str_radix ( & hex_balance[ 2 ..] , 16 ) . unwrap ( ) )
78
+ }
79
+
38
80
#[ update]
39
81
pub async fn transaction_count ( owner : Option < Principal > , block : Option < BlockTag > ) -> Nat {
40
82
let caller = validate_caller_not_anonymous ( ) ;
0 commit comments