wallet_adapter/wallet_ser_der/standard_features/
events.rs

1use std::{future::Future, pin::Pin};
2
3use async_channel::Receiver;
4use web_sys::wasm_bindgen::{prelude::Closure, JsValue};
5
6use crate::{
7    ConnectionInfoInner, Reflection, SemverVersion, StandardFunction, WalletAccount, WalletError,
8    WalletEvent, WalletEventSender, WalletResult,
9};
10
11/// `standard:events` struct containing the `version` and `callback`
12/// within the [StandardFunction] field
13#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
14pub struct StandardEvents(StandardFunction);
15
16impl StandardEvents {
17    /// parse the callback for `standard:events` from the [JsValue]
18    pub(crate) fn new(reflection: &Reflection, version: SemverVersion) -> WalletResult<Self> {
19        let get_standard_event_fn = reflection.get_function("on")?;
20
21        Ok(Self(StandardFunction {
22            version,
23            callback: get_standard_event_fn,
24        }))
25    }
26
27    pub(crate) async fn call_on_event(
28        &self,
29        connection_info: ConnectionInfoInner,
30        wallet_name: String,
31        sender: WalletEventSender,
32        stop_signal: Receiver<()>,
33    ) -> WalletResult<()> {
34        let sender2 = sender.clone();
35
36        let on_account_change = Closure::wrap(Box::new(move |value: JsValue| {
37            let wallet_name = wallet_name.clone();
38            web_sys::console::log_3(
39                &"CALLED ON EV for ".into(),
40                &wallet_name.clone().into(),
41                &value,
42            );
43
44            let connection_info_inner = connection_info.clone();
45            let sender_inner = sender2.clone();
46
47            wasm_bindgen_futures::spawn_local(async move {
48                let reflect_accounts =
49                    send_wallet_event_error()(Reflection::new(value), sender_inner.clone())
50                        .await
51                        .unwrap(); // Never fails
52                let mut get_accounts = send_wallet_event_error()(
53                    reflect_accounts.reflect_js_array("accounts"),
54                    sender_inner.clone(),
55                )
56                .await
57                .unwrap()
58                .to_vec(); // Never fails
59
60                let processed_wallet_account = if !get_accounts.is_empty() {
61                    let first_account = send_wallet_event_error()(
62                        Reflection::new(get_accounts.remove(0)),
63                        sender_inner.clone(),
64                    )
65                    .await
66                    .unwrap(); // Never fails
67
68                    let account_processing = send_wallet_event_error()(
69                        WalletAccount::parse(first_account),
70                        sender_inner.clone(),
71                    )
72                    .await
73                    .unwrap(); //Never fails
74                    web_sys::console::error_2(
75                        &"PRE ACCOUNT PROCESSING".into(),
76                        &format!("{account_processing:?}").into(),
77                    );
78
79                    Some(account_processing)
80                } else {
81                    Option::None
82                };
83
84                connection_info_inner
85                    .write()
86                    .await
87                    .emit_wallet_event(&wallet_name, processed_wallet_account, sender_inner.clone())
88                    .await
89            });
90        }) as Box<dyn Fn(_)>);
91
92        let on_account_change_fn =
93            Reflection::new(on_account_change.into_js_value())?.into_function()?;
94
95        let on_event_fn = self.0.callback.clone();
96
97        wasm_bindgen_futures::spawn_local(async move {
98            while (stop_signal.recv().await).is_ok() {
99                let invoke_outcome = on_event_fn
100                    .call2(
101                        &JsValue::null(),
102                        &"change".into(),
103                        &on_account_change_fn.clone().into(),
104                    )
105                    .map_err(|error| {
106                        let into_error: WalletError = error.into();
107
108                        into_error
109                    });
110
111                send_wallet_event_error()(invoke_outcome, sender.clone())
112                    .await
113                    .unwrap();
114            }
115        });
116
117        Ok(())
118    }
119}
120
121pub(crate) async fn send_wallet_event(wallet_event: WalletEvent, sender: WalletEventSender) {
122    if let Err(error) = sender.clone().send(wallet_event).await {
123        web_sys::console::log_2(
124            &"BACKGROUND TASK ERROR: [standard:events]on() > ".into(),
125            &format!("{error:?}").into(),
126        );
127    }
128}
129
130type SendWalletEventErrorOutput<T> = Pin<Box<dyn Future<Output = Result<T, ()>>>>;
131
132pub(crate) fn send_wallet_event_error<T>(
133) -> impl Fn(WalletResult<T>, WalletEventSender) -> SendWalletEventErrorOutput<T> + 'static
134where
135    T: core::fmt::Debug + 'static,
136{
137    move |outcome: WalletResult<T>, sender: WalletEventSender| {
138        Box::pin(async move {
139            match outcome {
140                Ok(value) => Ok(value),
141                Err(error) => {
142                    web_sys::console::log_2(
143                        &"BACKGROUND TASK ERROR: [standard:events]on() > ".into(),
144                        &format!("{error:?}").into(),
145                    );
146
147                    if let Err(channel_error) = sender
148                        .send(WalletEvent::BackgroundTaskError(error.clone()))
149                        .await
150                    {
151                        web_sys::console::log_2(
152                            &"Encountered error while sending a wallet event: ".into(),
153                            &format!("{channel_error:?}").into(),
154                        );
155                    }
156
157                    Err(())
158                }
159            }
160        })
161    }
162}