From 1a1cbeb401eca8da0a3adc84f2c55183b265ae7a Mon Sep 17 00:00:00 2001 From: Thomas Locher Date: Wed, 4 Sep 2024 19:16:21 +0200 Subject: [PATCH 01/12] Added json_serde. --- rust/basic_ethereum/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/rust/basic_ethereum/Cargo.toml b/rust/basic_ethereum/Cargo.toml index f9c3b3d97..6f4fb1432 100644 --- a/rust/basic_ethereum/Cargo.toml +++ b/rust/basic_ethereum/Cargo.toml @@ -21,5 +21,6 @@ ic-crypto-extended-bip32 = { git = "https://github.com/dfinity/ic", tag = "relea ic-crypto-sha3 = { git = "https://github.com/dfinity/ic", tag = "release-2024-06-26_23-01-base", package = "ic-crypto-sha3" } ic-ethereum-types = { git = "https://github.com/dfinity/ic", tag = "release-2024-06-26_23-01-base", package = "ic-ethereum-types" } serde = "1.0" +serde_json = "1.0" serde_bytes = "0.11.15" num-traits = "0.2.19" \ No newline at end of file From 7e124288e38a86fba970db8289dac17e4bd5e912 Mon Sep 17 00:00:00 2001 From: Thomas Locher Date: Wed, 4 Sep 2024 19:16:38 +0200 Subject: [PATCH 02/12] Added a `get_balance` endpoint. --- rust/basic_ethereum/basic_ethereum.did | 3 ++ rust/basic_ethereum/src/lib.rs | 42 +++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/rust/basic_ethereum/basic_ethereum.did b/rust/basic_ethereum/basic_ethereum.did index 723e6d14f..c704e4174 100644 --- a/rust/basic_ethereum/basic_ethereum.did +++ b/rust/basic_ethereum/basic_ethereum.did @@ -42,6 +42,9 @@ service : (opt InitArg) -> { // If the owner is not set, it defaults to the caller's principal. ethereum_address : (owner: opt principal) -> (text); + // Returns the balance of the given Ethereum address. + get_balance : (address: text) -> (Wei); + // Returns the transaction count for the Ethereum address derived for the given principal. // // If the owner is not set, it defaults to the caller's principal. diff --git a/rust/basic_ethereum/src/lib.rs b/rust/basic_ethereum/src/lib.rs index 49695fa57..66202e6c7 100644 --- a/rust/basic_ethereum/src/lib.rs +++ b/rust/basic_ethereum/src/lib.rs @@ -9,12 +9,13 @@ use alloy_primitives::{hex, Signature, TxKind, U256}; use candid::{CandidType, Deserialize, Nat, Principal}; use evm_rpc_canister_types::{ BlockTag, EvmRpcCanister, GetTransactionCountArgs, GetTransactionCountResult, - MultiGetTransactionCountResult, + MultiGetTransactionCountResult, EthSepoliaService, RpcService, RequestResult }; use ic_cdk::api::management_canister::ecdsa::{EcdsaCurve, EcdsaKeyId}; use ic_cdk::{init, update}; use ic_ethereum_types::Address; use std::str::FromStr; +use std::u64; pub const EVM_RPC_CANISTER_ID: Principal = Principal::from_slice(b"\x00\x00\x00\x00\x02\x30\x00\xCC\x01\x01"); // 7hfb6-caaaa-aaaar-qadga-cai @@ -35,6 +36,45 @@ pub async fn ethereum_address(owner: Option) -> String { wallet.ethereum_address().to_string() } +#[derive(Debug, Deserialize)] +struct Balance { + result: String, +} + +#[update] +pub async fn get_balance(address: String) -> Nat { + let _caller = validate_caller_not_anonymous(); + let chain_id = read_state(|s| s.ethereum_network().chain_id()); + let json = format!(r#"{{ "jsonrpc": "2.0", "method": "eth_getBalance", "params": ["{}", "latest"], "id": {} }}"#, address, chain_id); + let (response,) = EVM_RPC.request(RpcService::EthSepolia(EthSepoliaService::PublicNode), json, 500u64, 1_000_000_000u128) + .await + .unwrap_or_else(|e| { + panic!( + "failed to get the balance of address {:?}, error: {:?}", + address, e + ) + }); + match response { + RequestResult::Ok(balance_result) => { + let balance_result : Result = serde_json::from_str(&balance_result); + let balance_string = balance_result + .unwrap_or_else(|e| { + panic!( + "failed to get parse get_balance, error: {:?}", + e + ) + }); + if balance_string.result.len() % 2 == 0 { + u64::from_str_radix(&balance_string.result[2..], 16).unwrap().into() + } else { + u64::from_str_radix(&format!("0{}", &balance_string.result[2..]), 16).unwrap().into() + } + }, + RequestResult::Err(_) => panic!("Say something here.") + } + +} + #[update] pub async fn transaction_count(owner: Option, block: Option) -> Nat { let caller = validate_caller_not_anonymous(); From f677c40fca458a110fc96fd2ee27520c695f0be4 Mon Sep 17 00:00:00 2001 From: Thomas Locher Date: Thu, 5 Sep 2024 10:40:02 +0200 Subject: [PATCH 03/12] CChanges to make clippy happy. --- rust/basic_ethereum/Cargo.lock | 1 + rust/basic_ethereum/src/lib.rs | 39 ++++++++++++++++++++-------------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/rust/basic_ethereum/Cargo.lock b/rust/basic_ethereum/Cargo.lock index 7cc70636f..bcbdd30d8 100644 --- a/rust/basic_ethereum/Cargo.lock +++ b/rust/basic_ethereum/Cargo.lock @@ -348,6 +348,7 @@ dependencies = [ "num-traits", "serde", "serde_bytes", + "serde_json", ] [[package]] diff --git a/rust/basic_ethereum/src/lib.rs b/rust/basic_ethereum/src/lib.rs index 66202e6c7..106bf3ef4 100644 --- a/rust/basic_ethereum/src/lib.rs +++ b/rust/basic_ethereum/src/lib.rs @@ -8,8 +8,8 @@ use alloy_consensus::{SignableTransaction, TxEip1559, TxEnvelope}; use alloy_primitives::{hex, Signature, TxKind, U256}; use candid::{CandidType, Deserialize, Nat, Principal}; use evm_rpc_canister_types::{ - BlockTag, EvmRpcCanister, GetTransactionCountArgs, GetTransactionCountResult, - MultiGetTransactionCountResult, EthSepoliaService, RpcService, RequestResult + BlockTag, EthSepoliaService, EvmRpcCanister, GetTransactionCountArgs, + GetTransactionCountResult, MultiGetTransactionCountResult, RequestResult, RpcService, }; use ic_cdk::api::management_canister::ecdsa::{EcdsaCurve, EcdsaKeyId}; use ic_cdk::{init, update}; @@ -45,8 +45,17 @@ struct Balance { pub async fn get_balance(address: String) -> Nat { let _caller = validate_caller_not_anonymous(); let chain_id = read_state(|s| s.ethereum_network().chain_id()); - let json = format!(r#"{{ "jsonrpc": "2.0", "method": "eth_getBalance", "params": ["{}", "latest"], "id": {} }}"#, address, chain_id); - let (response,) = EVM_RPC.request(RpcService::EthSepolia(EthSepoliaService::PublicNode), json, 500u64, 1_000_000_000u128) + let json = format!( + r#"{{ "jsonrpc": "2.0", "method": "eth_getBalance", "params": ["{}", "latest"], "id": {} }}"#, + address, chain_id + ); + let (response,) = EVM_RPC + .request( + RpcService::EthSepolia(EthSepoliaService::PublicNode), + json, + 500u64, + 1_000_000_000u128, + ) .await .unwrap_or_else(|e| { panic!( @@ -56,23 +65,21 @@ pub async fn get_balance(address: String) -> Nat { }); match response { RequestResult::Ok(balance_result) => { - let balance_result : Result = serde_json::from_str(&balance_result); + let balance_result: Result = serde_json::from_str(&balance_result); let balance_string = balance_result - .unwrap_or_else(|e| { - panic!( - "failed to get parse get_balance, error: {:?}", - e - ) - }); + .unwrap_or_else(|e| panic!("failed to get parse get_balance, error: {:?}", e)); if balance_string.result.len() % 2 == 0 { - u64::from_str_radix(&balance_string.result[2..], 16).unwrap().into() + u64::from_str_radix(&balance_string.result[2..], 16) + .unwrap() + .into() } else { - u64::from_str_radix(&format!("0{}", &balance_string.result[2..]), 16).unwrap().into() + u64::from_str_radix(&format!("0{}", &balance_string.result[2..]), 16) + .unwrap() + .into() } - }, - RequestResult::Err(_) => panic!("Say something here.") + } + RequestResult::Err(_) => panic!("Say something here."), } - } #[update] From 12d0cecb9fc42db9748e9dab600c18bfa65447bf Mon Sep 17 00:00:00 2001 From: Thomas Locher Date: Thu, 5 Sep 2024 10:45:07 +0200 Subject: [PATCH 04/12] AAdded an error message. --- rust/basic_ethereum/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/basic_ethereum/src/lib.rs b/rust/basic_ethereum/src/lib.rs index 106bf3ef4..47600f901 100644 --- a/rust/basic_ethereum/src/lib.rs +++ b/rust/basic_ethereum/src/lib.rs @@ -59,7 +59,7 @@ pub async fn get_balance(address: String) -> Nat { .await .unwrap_or_else(|e| { panic!( - "failed to get the balance of address {:?}, error: {:?}", + "Failed to get the balance of address {:?}, error: {:?}", address, e ) }); @@ -67,7 +67,7 @@ pub async fn get_balance(address: String) -> Nat { RequestResult::Ok(balance_result) => { let balance_result: Result = serde_json::from_str(&balance_result); let balance_string = balance_result - .unwrap_or_else(|e| panic!("failed to get parse get_balance, error: {:?}", e)); + .unwrap_or_else(|e| panic!("Failed to get parse get_balance, error: {:?}", e)); if balance_string.result.len() % 2 == 0 { u64::from_str_radix(&balance_string.result[2..], 16) .unwrap() @@ -78,7 +78,7 @@ pub async fn get_balance(address: String) -> Nat { .into() } } - RequestResult::Err(_) => panic!("Say something here."), + RequestResult::Err(e) => panic!("Received an error response: {:?}", e), } } From 5ab30ca3c06e37674d04c95e3a64a9677558105b Mon Sep 17 00:00:00 2001 From: Thomas Locher Date: Thu, 5 Sep 2024 10:48:05 +0200 Subject: [PATCH 05/12] FFixed another error message. --- rust/basic_ethereum/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rust/basic_ethereum/src/lib.rs b/rust/basic_ethereum/src/lib.rs index 47600f901..e02d90cdc 100644 --- a/rust/basic_ethereum/src/lib.rs +++ b/rust/basic_ethereum/src/lib.rs @@ -66,8 +66,9 @@ pub async fn get_balance(address: String) -> Nat { match response { RequestResult::Ok(balance_result) => { let balance_result: Result = serde_json::from_str(&balance_result); - let balance_string = balance_result - .unwrap_or_else(|e| panic!("Failed to get parse get_balance, error: {:?}", e)); + let balance_string = balance_result.unwrap_or_else(|e| { + panic!("Failed to decode the eth_getBalance response: {:?}", e) + }); if balance_string.result.len() % 2 == 0 { u64::from_str_radix(&balance_string.result[2..], 16) .unwrap() From a0fbe753b5b6047f5c65f71210620fb5717ed26e Mon Sep 17 00:00:00 2001 From: Thomas Locher Date: Thu, 5 Sep 2024 13:51:15 +0200 Subject: [PATCH 06/12] Improved the get_balance implementation. --- rust/basic_ethereum/src/lib.rs | 45 ++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/rust/basic_ethereum/src/lib.rs b/rust/basic_ethereum/src/lib.rs index e02d90cdc..6299f7af4 100644 --- a/rust/basic_ethereum/src/lib.rs +++ b/rust/basic_ethereum/src/lib.rs @@ -15,7 +15,6 @@ use ic_cdk::api::management_canister::ecdsa::{EcdsaCurve, EcdsaKeyId}; use ic_cdk::{init, update}; use ic_ethereum_types::Address; use std::str::FromStr; -use std::u64; pub const EVM_RPC_CANISTER_ID: Principal = Principal::from_slice(b"\x00\x00\x00\x00\x02\x30\x00\xCC\x01\x01"); // 7hfb6-caaaa-aaaar-qadga-cai @@ -37,8 +36,17 @@ pub async fn ethereum_address(owner: Option) -> String { } #[derive(Debug, Deserialize)] -struct Balance { - result: String, +#[allow(dead_code)] +struct JsonRpcResult { + result: Option, + error: Option, +} + +#[derive(Debug, Deserialize)] +#[allow(dead_code)] +struct JsonRpcError { + code: isize, + message: String, } #[update] @@ -57,27 +65,22 @@ pub async fn get_balance(address: String) -> Nat { 1_000_000_000u128, ) .await - .unwrap_or_else(|e| { - panic!( - "Failed to get the balance of address {:?}, error: {:?}", - address, e - ) - }); + .expect("RPC call failed"); + match response { RequestResult::Ok(balance_result) => { - let balance_result: Result = serde_json::from_str(&balance_result); - let balance_string = balance_result.unwrap_or_else(|e| { - panic!("Failed to decode the eth_getBalance response: {:?}", e) - }); - if balance_string.result.len() % 2 == 0 { - u64::from_str_radix(&balance_string.result[2..], 16) - .unwrap() - .into() + let json_rpc_result: JsonRpcResult = + serde_json::from_str(&balance_result).expect("JSON is not well-formatted"); + // The response to a successful `eth_getBalance` call has the format + // { "id": "[CHAIN ID]", "jsonrpc": "2.0", "result": "[BALANCE IN HEX]" } + let hex_balance = json_rpc_result.result.expect("No balance received"); + + let hex_balance = if hex_balance.len() % 2 != 0 { + format!("0{}", &hex_balance[2..]) } else { - u64::from_str_radix(&format!("0{}", &balance_string.result[2..]), 16) - .unwrap() - .into() - } + hex_balance[2..].to_string() + }; + Nat::from_str(&U256::from_str_radix(&hex_balance, 16).unwrap().to_string()).unwrap() } RequestResult::Err(e) => panic!("Received an error response: {:?}", e), } From 35f4e12a6057d6806d7edf5b71a99fec312b9856 Mon Sep 17 00:00:00 2001 From: Thomas Locher Date: Mon, 9 Sep 2024 14:13:48 +0200 Subject: [PATCH 07/12] Improvements to the get_balance endpoint. --- rust/basic_ethereum/Cargo.lock | 35 ++++++++++++++++++++++++++++++++++ rust/basic_ethereum/Cargo.toml | 3 ++- rust/basic_ethereum/src/lib.rs | 33 +++++++++++++++++++++----------- 3 files changed, 59 insertions(+), 12 deletions(-) diff --git a/rust/basic_ethereum/Cargo.lock b/rust/basic_ethereum/Cargo.lock index bcbdd30d8..568c2be1a 100644 --- a/rust/basic_ethereum/Cargo.lock +++ b/rust/basic_ethereum/Cargo.lock @@ -345,6 +345,7 @@ dependencies = [ "ic-crypto-extended-bip32", "ic-crypto-sha3", "ic-ethereum-types", + "num", "num-traits", "serde", "serde_bytes", @@ -2079,6 +2080,20 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + [[package]] name = "num-bigint" version = "0.4.6" @@ -2107,6 +2122,15 @@ dependencies = [ "smallvec", ] +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + [[package]] name = "num-conv" version = "0.1.0" @@ -2133,6 +2157,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" diff --git a/rust/basic_ethereum/Cargo.toml b/rust/basic_ethereum/Cargo.toml index 6f4fb1432..86db41dbc 100644 --- a/rust/basic_ethereum/Cargo.toml +++ b/rust/basic_ethereum/Cargo.toml @@ -23,4 +23,5 @@ ic-ethereum-types = { git = "https://github.com/dfinity/ic", tag = "release-2024 serde = "1.0" serde_json = "1.0" serde_bytes = "0.11.15" -num-traits = "0.2.19" \ No newline at end of file +num-traits = "0.2.19" +num = "0.4.3" \ No newline at end of file diff --git a/rust/basic_ethereum/src/lib.rs b/rust/basic_ethereum/src/lib.rs index 6299f7af4..20a9a10c8 100644 --- a/rust/basic_ethereum/src/lib.rs +++ b/rust/basic_ethereum/src/lib.rs @@ -8,14 +8,18 @@ use alloy_consensus::{SignableTransaction, TxEip1559, TxEnvelope}; use alloy_primitives::{hex, Signature, TxKind, U256}; use candid::{CandidType, Deserialize, Nat, Principal}; use evm_rpc_canister_types::{ - BlockTag, EthSepoliaService, EvmRpcCanister, GetTransactionCountArgs, + BlockTag, EthMainnetService, EthSepoliaService, EvmRpcCanister, GetTransactionCountArgs, GetTransactionCountResult, MultiGetTransactionCountResult, RequestResult, RpcService, }; use ic_cdk::api::management_canister::ecdsa::{EcdsaCurve, EcdsaKeyId}; use ic_cdk::{init, update}; use ic_ethereum_types::Address; +use num::{BigUint, Num}; use std::str::FromStr; +pub const ETH_MAINNET_CHAIN_ID: u64 = 1; +pub const ETH_SEPOLIA_CHAIN_ID: u64 = 11155111; + pub const EVM_RPC_CANISTER_ID: Principal = Principal::from_slice(b"\x00\x00\x00\x00\x02\x30\x00\xCC\x01\x01"); // 7hfb6-caaaa-aaaar-qadga-cai pub const EVM_RPC: EvmRpcCanister = EvmRpcCanister(EVM_RPC_CANISTER_ID); @@ -52,18 +56,24 @@ struct JsonRpcError { #[update] pub async fn get_balance(address: String) -> Nat { let _caller = validate_caller_not_anonymous(); - let chain_id = read_state(|s| s.ethereum_network().chain_id()); let json = format!( - r#"{{ "jsonrpc": "2.0", "method": "eth_getBalance", "params": ["{}", "latest"], "id": {} }}"#, - address, chain_id + r#"{{ "jsonrpc": "2.0", "method": "eth_getBalance", "params": ["{}", "latest"], "id": 1 }}"#, + address ); + + let max_response_size_bytes = 500_u64; + let num_cycles = 1_000_000_000u128; + + let chain_id = read_state(|s| s.ethereum_network().chain_id()); + + let rpc_service = match chain_id { + ETH_MAINNET_CHAIN_ID => RpcService::EthMainnet(EthMainnetService::PublicNode), + ETH_SEPOLIA_CHAIN_ID => RpcService::EthSepolia(EthSepoliaService::PublicNode), + _ => panic!("Unsupported chain ID in get_balance call."), + }; + let (response,) = EVM_RPC - .request( - RpcService::EthSepolia(EthSepoliaService::PublicNode), - json, - 500u64, - 1_000_000_000u128, - ) + .request(rpc_service, json, max_response_size_bytes, num_cycles) .await .expect("RPC call failed"); @@ -75,12 +85,13 @@ pub async fn get_balance(address: String) -> Nat { // { "id": "[CHAIN ID]", "jsonrpc": "2.0", "result": "[BALANCE IN HEX]" } let hex_balance = json_rpc_result.result.expect("No balance received"); + // Make sure that the number of digits is even and remove the "0x" prefix. let hex_balance = if hex_balance.len() % 2 != 0 { format!("0{}", &hex_balance[2..]) } else { hex_balance[2..].to_string() }; - Nat::from_str(&U256::from_str_radix(&hex_balance, 16).unwrap().to_string()).unwrap() + Nat(BigUint::from_str_radix(&hex_balance, 16).unwrap()) } RequestResult::Err(e) => panic!("Received an error response: {:?}", e), } From d4909140ab3e1e6cf6636a49e216f868a317f708 Mon Sep 17 00:00:00 2001 From: Thomas Locher Date: Mon, 9 Sep 2024 14:19:32 +0200 Subject: [PATCH 08/12] Added a new line to the Cargo.toml file. --- rust/basic_ethereum/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/basic_ethereum/Cargo.toml b/rust/basic_ethereum/Cargo.toml index 86db41dbc..b4b2591a4 100644 --- a/rust/basic_ethereum/Cargo.toml +++ b/rust/basic_ethereum/Cargo.toml @@ -24,4 +24,4 @@ serde = "1.0" serde_json = "1.0" serde_bytes = "0.11.15" num-traits = "0.2.19" -num = "0.4.3" \ No newline at end of file +num = "0.4.3" From 142b2330f09c6583823296415369cf728ee48a2f Mon Sep 17 00:00:00 2001 From: Thomas Locher Date: Mon, 9 Sep 2024 14:35:38 +0200 Subject: [PATCH 09/12] Update rust/basic_ethereum/src/lib.rs Co-authored-by: gregorydemay <112856886+gregorydemay@users.noreply.github.com> --- rust/basic_ethereum/src/lib.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/rust/basic_ethereum/src/lib.rs b/rust/basic_ethereum/src/lib.rs index 20a9a10c8..40c565ef4 100644 --- a/rust/basic_ethereum/src/lib.rs +++ b/rust/basic_ethereum/src/lib.rs @@ -64,12 +64,11 @@ pub async fn get_balance(address: String) -> Nat { let max_response_size_bytes = 500_u64; let num_cycles = 1_000_000_000u128; - let chain_id = read_state(|s| s.ethereum_network().chain_id()); + let ethereum_network = read_state(|s| s.ethereum_network()); - let rpc_service = match chain_id { - ETH_MAINNET_CHAIN_ID => RpcService::EthMainnet(EthMainnetService::PublicNode), - ETH_SEPOLIA_CHAIN_ID => RpcService::EthSepolia(EthSepoliaService::PublicNode), - _ => panic!("Unsupported chain ID in get_balance call."), + let rpc_service = match ethereum_network { + EthereumNetwork::Mainnet => RpcService::EthMainnet(EthMainnetService::PublicNode), + EthereumNetwork::Sepolia => RpcService::EthSepolia(EthSepoliaService::PublicNode), }; let (response,) = EVM_RPC From 338c2d19670a413aae4d63a457c14122fe68074d Mon Sep 17 00:00:00 2001 From: Thomas Locher Date: Mon, 9 Sep 2024 14:35:46 +0200 Subject: [PATCH 10/12] Update rust/basic_ethereum/src/lib.rs Co-authored-by: gregorydemay <112856886+gregorydemay@users.noreply.github.com> --- rust/basic_ethereum/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/rust/basic_ethereum/src/lib.rs b/rust/basic_ethereum/src/lib.rs index 40c565ef4..12812fa9b 100644 --- a/rust/basic_ethereum/src/lib.rs +++ b/rust/basic_ethereum/src/lib.rs @@ -17,8 +17,6 @@ use ic_ethereum_types::Address; use num::{BigUint, Num}; use std::str::FromStr; -pub const ETH_MAINNET_CHAIN_ID: u64 = 1; -pub const ETH_SEPOLIA_CHAIN_ID: u64 = 11155111; pub const EVM_RPC_CANISTER_ID: Principal = Principal::from_slice(b"\x00\x00\x00\x00\x02\x30\x00\xCC\x01\x01"); // 7hfb6-caaaa-aaaar-qadga-cai From e2382e7ce0bba7bf2014cc8ccd202df8c0b2158a Mon Sep 17 00:00:00 2001 From: Thomas Locher Date: Mon, 9 Sep 2024 16:36:56 +0200 Subject: [PATCH 11/12] Cleaned up the get_balance endpoint. --- rust/basic_ethereum/src/lib.rs | 47 +++++++++++++--------------------- 1 file changed, 18 insertions(+), 29 deletions(-) diff --git a/rust/basic_ethereum/src/lib.rs b/rust/basic_ethereum/src/lib.rs index 12812fa9b..b7280caf3 100644 --- a/rust/basic_ethereum/src/lib.rs +++ b/rust/basic_ethereum/src/lib.rs @@ -17,7 +17,6 @@ use ic_ethereum_types::Address; use num::{BigUint, Num}; use std::str::FromStr; - pub const EVM_RPC_CANISTER_ID: Principal = Principal::from_slice(b"\x00\x00\x00\x00\x02\x30\x00\xCC\x01\x01"); // 7hfb6-caaaa-aaaar-qadga-cai pub const EVM_RPC: EvmRpcCanister = EvmRpcCanister(EVM_RPC_CANISTER_ID); @@ -37,20 +36,6 @@ pub async fn ethereum_address(owner: Option) -> String { wallet.ethereum_address().to_string() } -#[derive(Debug, Deserialize)] -#[allow(dead_code)] -struct JsonRpcResult { - result: Option, - error: Option, -} - -#[derive(Debug, Deserialize)] -#[allow(dead_code)] -struct JsonRpcError { - code: isize, - message: String, -} - #[update] pub async fn get_balance(address: String) -> Nat { let _caller = validate_caller_not_anonymous(); @@ -74,24 +59,28 @@ pub async fn get_balance(address: String) -> Nat { .await .expect("RPC call failed"); - match response { + let hex_balance = match response { RequestResult::Ok(balance_result) => { - let json_rpc_result: JsonRpcResult = - serde_json::from_str(&balance_result).expect("JSON is not well-formatted"); // The response to a successful `eth_getBalance` call has the format - // { "id": "[CHAIN ID]", "jsonrpc": "2.0", "result": "[BALANCE IN HEX]" } - let hex_balance = json_rpc_result.result.expect("No balance received"); - - // Make sure that the number of digits is even and remove the "0x" prefix. - let hex_balance = if hex_balance.len() % 2 != 0 { - format!("0{}", &hex_balance[2..]) - } else { - hex_balance[2..].to_string() - }; - Nat(BigUint::from_str_radix(&hex_balance, 16).unwrap()) + // { "id": "[ID]", "jsonrpc": "2.0", "result": "[BALANCE IN HEX]" } + let response: serde_json::Value = serde_json::from_str(&balance_result).unwrap(); + response + .get("result") + .and_then(|v| v.as_str()) + .unwrap() + .to_string() } RequestResult::Err(e) => panic!("Received an error response: {:?}", e), - } + }; + + // Make sure that the number of digits is even and remove the "0x" prefix. + let hex_balance = if hex_balance.len() % 2 != 0 { + format!("0{}", &hex_balance[2..]) + } else { + hex_balance[2..].to_string() + }; + + Nat(BigUint::from_str_radix(&hex_balance, 16).unwrap()) } #[update] From 148ba4e83d9b46b95fe1901716afedc9f355f1c2 Mon Sep 17 00:00:00 2001 From: Thomas Locher Date: Mon, 9 Sep 2024 16:51:43 +0200 Subject: [PATCH 12/12] Removed the unnecessary size check of the hexadecimal balance. --- rust/basic_ethereum/src/lib.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/rust/basic_ethereum/src/lib.rs b/rust/basic_ethereum/src/lib.rs index b7280caf3..34f6484cd 100644 --- a/rust/basic_ethereum/src/lib.rs +++ b/rust/basic_ethereum/src/lib.rs @@ -61,7 +61,7 @@ pub async fn get_balance(address: String) -> Nat { let hex_balance = match response { RequestResult::Ok(balance_result) => { - // The response to a successful `eth_getBalance` call has the format + // The response to a successful `eth_getBalance` call has the following format: // { "id": "[ID]", "jsonrpc": "2.0", "result": "[BALANCE IN HEX]" } let response: serde_json::Value = serde_json::from_str(&balance_result).unwrap(); response @@ -73,14 +73,8 @@ pub async fn get_balance(address: String) -> Nat { RequestResult::Err(e) => panic!("Received an error response: {:?}", e), }; - // Make sure that the number of digits is even and remove the "0x" prefix. - let hex_balance = if hex_balance.len() % 2 != 0 { - format!("0{}", &hex_balance[2..]) - } else { - hex_balance[2..].to_string() - }; - - Nat(BigUint::from_str_radix(&hex_balance, 16).unwrap()) + // Remove the "0x" prefix before converting to a decimal number. + Nat(BigUint::from_str_radix(&hex_balance[2..], 16).unwrap()) } #[update]