When using the web_sys library with Rust to interact with Web APIs, accessing window.ethereum requires utilizing the Window object provided by web_sys and methods for handling JavaScript objects. window.ethereum is provided by Ethereum browser extensions such as MetaMask, enabling web applications to request user Ethereum account access and send transactions.
Steps 1: Add Dependencies
First, ensure that the web-sys dependency is included in your Cargo.toml and the relevant features are enabled:
toml[dependencies] web-sys = { version = "0.3", features = ["Window", "console"] }
Steps 2: Access the Window Object with Web-sys
In Rust code, you first need to obtain the current window object:
rustuse web_sys::window; fn main() { let window = window().expect("should have a Window"); // The following steps will continue here }
Steps 3: Access window.ethereum
Since the window.ethereum object is a global JavaScript object, it may not exist (e.g., if the user has not installed MetaMask). Rust and WebAssembly do not natively support dynamic properties like this, so we need to use JsValue and Reflect:
rustuse wasm_bindgen::JsCast; use wasm_bindgen::JsValue; use web_sys::{Reflect, Window}; fn get_ethereum(window: &Window) -> Option<JsValue> { if let Ok(ethereum) = Reflect::get(&JsValue::from(window), &JsValue::from_str("ethereum")) { if ethereum.is_undefined() { None } else { Some(ethereum) } } else { None } } fn main() { let window = window().expect("should have a Window"); if let Some(ethereum) = get_ethereum(&window) { // Now you can use this ethereum object console::log_1(&"Ethereum object found!".into()); } else { console::log_1(&"Ethereum object not found.".into()); } }
Example
For example, if you want to check whether the user has installed MetaMask and connected it to your web application, you can call its API methods after obtaining the ethereum object. For instance, requesting account access:
rustuse wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; #[wasm_bindgen] extern "C" { #[wasm_bindgen(js_namespace = console)] fn log(s: &str); #[wasm_bindgen(method, js_name = requestAccounts)] pub async fn request_accounts(this: &JsValue) -> Result<JsValue, JsValue>; } async fn request_user_accounts(ethereum: JsValue) -> Result<JsValue, JsValue> { ethereum.unchecked_into::<JsValue>().request_accounts().await } #[wasm_bindgen(start)] pub async fn run() -> Result<(), JsValue> { let window = web_sys::window().expect("should have a window"); let ethereum = get_ethereum(&window).expect("Ethereum object should be available"); match request_user_accounts(ethereum).await { Ok(accounts) => log(&format!("Accounts: {:?}", accounts)), Err(_) => log("Failed to get accounts."), } Ok(()) }