From 432920203bddf29dbb593c64767ca1fdf5fd0a71 Mon Sep 17 00:00:00 2001 From: Surinder Singh Matoo Date: Sat, 16 Mar 2024 00:03:15 +0530 Subject: [PATCH] WIP: chrome extension message api --- core/src/adaptor.rs | 36 +------ core/src/app.rs | 24 ++--- core/src/core.rs | 2 +- core/src/modules/account_manager/mod.rs | 3 +- core/src/runtime/mod.rs | 15 +++ extensions/chrome/src/lib.rs | 27 +++++- extensions/chrome/src/server.rs | 124 +++++++++++------------- 7 files changed, 119 insertions(+), 112 deletions(-) diff --git a/core/src/adaptor.rs b/core/src/adaptor.rs index 9ca6952..779b29e 100644 --- a/core/src/adaptor.rs +++ b/core/src/adaptor.rs @@ -1,39 +1,11 @@ // Chrome Extension Wallet Adaptor use crate::imports::*; -use wasm_bindgen::prelude::*; -struct Inner { - #[allow(dead_code)] - runtime: Runtime, +pub enum WebEvent { + AccountSelection(AccountId), } -impl Inner { - pub fn new(runtime: Runtime) -> Self { - Self { runtime } - } +pub trait AdaptorApi: Sync + Send { + fn post_to_server(&self, event: WebEvent); } - -#[wasm_bindgen] -pub struct Adaptor { - #[allow(dead_code)] - inner: Arc, -} - -impl Adaptor { - pub fn new(runtime: Runtime) -> Self { - Self { - inner: Arc::new(Inner::new(runtime.clone())), - } - } -} - -#[wasm_bindgen] -impl Adaptor { - #[wasm_bindgen(js_name = "sendTransaction")] - pub fn send_transaction(&self) -> Result<()> { - Ok(()) - } -} - -// static mut ADAPTOR : Option = None; diff --git a/core/src/app.rs b/core/src/app.rs index e1ba7f3..c3f7f88 100644 --- a/core/src/app.rs +++ b/core/src/app.rs @@ -259,7 +259,7 @@ cfg_if! { "Kaspa NG", native_options, Box::new(move |cc| { - let runtime = runtime::Runtime::new(&cc.egui_ctx, &settings, wallet_api, application_events); + let runtime = runtime::Runtime::new(&cc.egui_ctx, &settings, wallet_api, application_events, None); delegate.lock().unwrap().replace(runtime.clone()); runtime::signals::Signals::bind(&runtime); runtime.start(); @@ -279,9 +279,9 @@ cfg_if! { } else { // use crate::result::Result; + use crate::adaptor::AdaptorApi; - pub async fn kaspa_ng_main(wallet_api : Option>, application_events : Option) -> Result<()> { - use wasm_bindgen::prelude::*; + pub async fn kaspa_ng_main(wallet_api : Option>, application_events : Option, adaptor: Option>) -> Result<()> { use workflow_dom::utils::document; // ------------------------------------------------------------ @@ -330,16 +330,18 @@ cfg_if! { // wallet_api.ping() - let runtime = runtime::Runtime::new(&cc.egui_ctx, &settings, wallet_api, application_events); + // let adaptor = kaspa_ng_core::adaptor::Adaptor::new(runtime.clone()); + // let window = web_sys::window().expect("no global `window` exists"); + // js_sys::Reflect::set( + // &window, + // &JsValue::from_str("adaptor"), + // &JsValue::from(adaptor), + // ).expect("failed to set adaptor"); + + let runtime = runtime::Runtime::new(&cc.egui_ctx, &settings, wallet_api, application_events, adaptor); runtime.start(); - let adaptor = kaspa_ng_core::adaptor::Adaptor::new(runtime.clone()); - let window = web_sys::window().expect("no global `window` exists"); - js_sys::Reflect::set( - &window, - &JsValue::from_str("adaptor"), - &JsValue::from(adaptor), - ).expect("failed to set adaptor"); + Box::new(kaspa_ng_core::Core::new(cc, runtime, settings, false)) }), diff --git a/core/src/core.rs b/core/src/core.rs index 129537a..2289e6e 100644 --- a/core/src/core.rs +++ b/core/src/core.rs @@ -913,7 +913,7 @@ impl Core { self.purge_secure_stack(); } - CoreWallet::AccountSelection { id: _ } => { } + CoreWallet::AccountSelection { id: _ } => {} CoreWallet::DaaScoreChange { current_daa_score } => { self.state.current_daa_score.replace(current_daa_score); } diff --git a/core/src/modules/account_manager/mod.rs b/core/src/modules/account_manager/mod.rs index b6297ca..dc42a17 100644 --- a/core/src/modules/account_manager/mod.rs +++ b/core/src/modules/account_manager/mod.rs @@ -363,8 +363,9 @@ impl AccountManager { account_collection.iter().for_each(|account_select| { if ui.account_selector_button(account_select, &network_type, false, core.balance_padding()).clicked() { this.select(Some(account_select.clone()), core.device().clone()); - // let id = account_select.id(); + let id = account_select.id(); // let _ = core.sender().try_send(Events::Wallet { event: Box::new(kaspa_wallet_core::events::Events::AccountSelection{id: Some(id)}) }); + runtime().post_to_server(crate::adaptor::WebEvent::AccountSelection(id)); if core.device().single_pane() { this.section = AccountManagerSection::Overview; } else { diff --git a/core/src/runtime/mod.rs b/core/src/runtime/mod.rs index ed187bf..b859255 100644 --- a/core/src/runtime/mod.rs +++ b/core/src/runtime/mod.rs @@ -13,6 +13,7 @@ pub mod channel; pub mod payload; pub mod services; pub mod system; +use crate::adaptor::{AdaptorApi, WebEvent}; pub use payload::Payload; pub use services::Service; use services::*; @@ -27,6 +28,8 @@ pub struct Inner { start_time: Instant, system: Option, + adaptor: Option>, + kaspa: Arc, peer_monitor_service: Arc, update_monitor_service: Arc, @@ -52,6 +55,7 @@ impl Runtime { settings: &Settings, wallet_api: Option>, application_events: Option, + adaptor: Option>, ) -> Self { let system = System::new(); @@ -113,6 +117,7 @@ impl Runtime { is_running: Arc::new(AtomicBool::new(false)), start_time: Instant::now(), system: Some(system), + adaptor, // #[cfg(not(feature = "lean"))] metrics_service, #[cfg(not(feature = "lean"))] @@ -125,6 +130,16 @@ impl Runtime { runtime } + // pub fn set_adaptor(&self, adapter:Adaptor){ + // self.inner.adaptor.lock().unwrap().adaptor = Some(adapter); + // } + + pub fn post_to_server(&self, event: WebEvent) { + if let Some(adaptor) = self.inner.adaptor.as_ref() { + adaptor.post_to_server(event); + } + } + pub fn uptime(&self) -> Duration { self.inner.start_time.elapsed() } diff --git a/extensions/chrome/src/lib.rs b/extensions/chrome/src/lib.rs index a0cc760..94e4a32 100644 --- a/extensions/chrome/src/lib.rs +++ b/extensions/chrome/src/lib.rs @@ -3,6 +3,9 @@ pub mod imports; pub mod ipc; pub mod server; +use kaspa_ng_core::adaptor::AdaptorApi; +use workflow_wasm::extensions::ObjectExtension; + use crate::imports::*; static mut SERVER: Option> = None; @@ -33,7 +36,25 @@ pub async fn kaspa_ng_background() { server.start().await; } +struct Adaptor {} + +impl Adaptor { + pub fn new() -> Self { + Self {} + } +} + +impl AdaptorApi for Adaptor { + fn post_to_server(&self, _event: kaspa_ng_core::adaptor::WebEvent) { + let obj = js_sys::Object::new(); + let _ = obj.set("type", &"WebApi".into()); + let _ = obj.set("data", &"Web".into()); + // chrome_sys::bindings::send_message(); + } +} + // extension popup +#[cfg(target_arch = "wasm32")] #[wasm_bindgen] pub async fn kaspa_ng_main() { log_info!("kaspa_ng_main called successfully in the popup!"); @@ -54,8 +75,10 @@ pub async fn kaspa_ng_main() { .await .expect("ping failed"); log_info!("Client received response: {response:?}"); - - if let Err(err) = app::kaspa_ng_main(Some(wallet_client), Some(application_events)).await { + let adaptor = Arc::new(Adaptor::new()); + if let Err(err) = + app::kaspa_ng_main(Some(wallet_client), Some(application_events), Some(adaptor)).await + { log_error!("Error: {err}"); } } diff --git a/extensions/chrome/src/server.rs b/extensions/chrome/src/server.rs index db79f10..ee8b260 100644 --- a/extensions/chrome/src/server.rs +++ b/extensions/chrome/src/server.rs @@ -1,23 +1,26 @@ use kaspa_ng_core::imports::KaspaRpcClient; use kaspa_wallet_core::rpc::{ // ConnectOptions, ConnectStrategy, RpcCtl, - DynRpcApi, NotificationMode, Rpc, WrpcEncoding, + DynRpcApi, + NotificationMode, + Rpc, + WrpcEncoding, }; use crate::imports::*; pub type PortListenerClosure = Closure JsValue>; pub type PortEventClosure = Closure JsValue>; +use rand::Rng; use std::collections::HashMap; -use workflow_wasm::extensions::ObjectExtension; use workflow_core::enums::Describe; -use rand::Rng; +use workflow_wasm::extensions::ObjectExtension; #[wasm_bindgen] extern "C" { - #[wasm_bindgen(js_name="initPageScript")] - fn init_page_script(tab_id: u32, args:JsValue); + #[wasm_bindgen(js_name = "initPageScript")] + fn init_page_script(tab_id: u32, args: JsValue); - #[wasm_bindgen(js_name="openPopup")] + #[wasm_bindgen(js_name = "openPopup")] fn open_popup_window(); } @@ -35,71 +38,62 @@ unsafe impl Send for Server {} unsafe impl Sync for Server {} #[derive(Debug, Describe)] -enum WebActions{ +enum WebActions { InjectPageScript, Connect, } - #[derive(Debug)] -struct WebMessage{ +struct WebMessage { action: WebActions, rid: Option, - data: JsValue + data: JsValue, } #[derive(Debug)] -struct InternalMessage{ +struct InternalMessage { target: Target, op: u64, - data: Vec + data: Vec, } #[derive(Debug)] -enum Message{ +enum Message { Web(WebMessage), - Internal(InternalMessage) + Internal(InternalMessage), } -impl From for Message{ +impl From for Message { fn from(value: WebMessage) -> Self { Self::Web(value) } } -impl From for Message{ +impl From for Message { fn from(value: InternalMessage) -> Self { Self::Internal(value) } } -fn msg_to_req(msg: js_sys::Object)->Result { +fn msg_to_req(msg: js_sys::Object) -> Result { let msg_type = msg.get_string("type")?; if msg_type == "WebAPI" { let info = msg.get_object("data")?; - let action = WebActions::from_str(&info.get_string("action")?).expect("`action` is required for WEBAPI message."); + let action = WebActions::from_str(&info.get_string("action")?) + .expect("`action` is required for WEBAPI message."); let data = info.get_value("data")?; let rid = info.try_get_string("rid")?; - return Ok(WebMessage{ - action, - data, - rid - }.into()); + return Ok(WebMessage { action, data, rid }.into()); } - if msg_type == "Internal"{ + if msg_type == "Internal" { let info = msg.get_value("data")?; let (target, op, data) = jsv_to_req(info)?; - return Ok(InternalMessage{ - target, - op, - data - }.into()); + return Ok(InternalMessage { target, op, data }.into()); } Err("Invalid msg: {msg_type}".to_string().into()) - // let src = Vec::::from_hex( // src.as_string() @@ -206,7 +200,9 @@ impl Server { let this_clone = this_clone.clone(); let port_clone = port_clone.clone(); spawn_local(async move { - let result = this_clone.handle_port_event(js_sys::Object::from(msg), port_clone.clone()).await; + let result = this_clone + .handle_port_event(js_sys::Object::from(msg), port_clone.clone()) + .await; port_clone.post_message(result); }); @@ -217,7 +213,11 @@ impl Server { let this_clone = this.clone(); let disconnect_closure = Rc::new(Closure::new(move |_| -> JsValue { workflow_log::log_info!("port disconnect: {index}"); - this_clone.port_events_closures.lock().unwrap().remove(&index); + this_clone + .port_events_closures + .lock() + .unwrap() + .remove(&index); JsValue::from(true) })); port.on_disconnect().add_listener(&disconnect_closure); @@ -235,27 +235,25 @@ impl Server { *self.port_closure.lock().unwrap() = Some(closure); } - async fn handle_port_event(self: &Arc, msg_jsv: js_sys::Object, port:Rc)->JsValue{ - + async fn handle_port_event( + self: &Arc, + msg_jsv: js_sys::Object, + port: Rc, + ) -> JsValue { let msg = msg_to_req(msg_jsv.clone()).unwrap(); workflow_log::log_info!("handle_port_event: msg {:?}", msg); match msg { - Message::Web(msg)=>{ - match msg.action{ - WebActions::InjectPageScript => { - let tab_id = port.sender().tab().id(); - init_page_script(tab_id, msg.data); - }, - WebActions::Connect => { - open_popup_window() - } + Message::Web(msg) => match msg.action { + WebActions::InjectPageScript => { + let tab_id = port.sender().tab().id(); + init_page_script(tab_id, msg.data); } + WebActions::Connect => open_popup_window(), }, - Message::Internal(_)=>{ + Message::Internal(_) => { // } } - format!("handle_port_event: got msg: {msg_jsv:?}").into() } @@ -310,28 +308,24 @@ impl Server { ); let msg = msg_to_req(js_sys::Object::from(msg_jsv)).unwrap(); - match msg{ - Message::Internal(msg)=>{ - match msg.target { - Target::Wallet => { - spawn_local(async move { - let resp = resp_to_jsv( - Target::Wallet, - self.wallet_server.call_with_borsh(msg.op, &msg.data).await, - ); - if let Err(err) = callback.call1(&JsValue::UNDEFINED, &resp) { - log_error!("onMessage callback error: {:?}", err); - } - }); - } - Target::Runtime => { - todo!() - } + match msg { + Message::Internal(msg) => match msg.target { + Target::Wallet => { + spawn_local(async move { + let resp = resp_to_jsv( + Target::Wallet, + self.wallet_server.call_with_borsh(msg.op, &msg.data).await, + ); + if let Err(err) = callback.call1(&JsValue::UNDEFINED, &resp) { + log_error!("onMessage callback error: {:?}", err); + } + }); + } + Target::Runtime => { + todo!() } }, - Message::Web(_msg)=>{ - - } + Message::Web(_msg) => {} } Ok(())