1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
use js_sys::Function;
use wasm_bindgen::JsValue;
use serde::{Deserialize, Serialize};
use js_sys::Promise;
use std::vec::Vec;
use web_sys::Event;
use web_sys::EventTarget;
use wasm_bindgen::closure::Closure;
use wasm_bindgen::JsCast;

pub type Callback = Box<dyn Fn(Result<JsValue, JsValue>) -> ()>;


#[derive(Debug, Clone)]
pub struct Provider {
    pub this: JsValue,
    pub request: Function
}

#[derive(Serialize, Deserialize)]
pub struct RequestMethod {
    method: String
}


impl Provider {

    pub fn new() -> Self {
        let provider = web_sys::window().unwrap().get("ethereum").unwrap();
        let request = js_sys::Reflect::get(
            &provider,
            &JsValue::from("request")
        ).unwrap();
        return Provider {this: JsValue::from(provider), request: Function::from(request)};
    }

    pub fn on(self, event: String, callback: Box<dyn FnMut(Event)>) -> Result<(), JsValue>{
        // doc: https://rustwasm.github.io/wasm-bindgen/examples/paint.html
        let closure = Closure::wrap(callback);
        return EventTarget::from(
            self.this
        ).add_event_listener_with_callback(&event, closure.as_ref().unchecked_ref())
    }

    pub async fn request(self, method: String, params: Option<Vec<String>> ) -> Result<JsValue, JsValue> {
        let ret = self.request.call2(
            &self.this,
            &JsValue::from_serde(&RequestMethod{method: method}).unwrap(),
            &JsValue::from_serde(&params).unwrap()
        );
        match ret {
            Ok(s)=> {
                let promise = Promise::resolve(&s.into());
                Ok(wasm_bindgen_futures::JsFuture::from(promise).await?)
            },
           Err(e) => Err(e)
        }
    }
}