The Active Connection
The ActiveConnection is used to store the ConnectionInfo. Since the ConnectionInfo is wrapped in an Arc<async_lock::RwLock<T>>
, storing the connection info inside its own type can help in cases where you don't want to perform an async call inside a component by use of a hook or effect.
Type definition
{{#tabs }} {{#tab name="Dioxus" }}
#![allow(unused)] fn main() { use dioxus::prelude::*; use wallet_adapter::ConnectionInfo; // defined as a global variable pub(crate) static ACTIVE_CONNECTION: GlobalSignal<ConnectionInfo> = Signal::global(|| ConnectionInfo::default()); #[component] pub(crate) fn App() -> Element { let wallet_event_listener = WALLET_ADAPTER.read().events().clone(); // Whenever a `WalletEvent` occurs, the `ACTIVE_CONNECTION` is modified spawn(async move { while let Ok(wallet_event) = wallet_event_listener.recv().await { *ACCOUNT_STATE.write() = AccountState::default(); // The connection information is extracted here within an async scope let connection_info = (*WALLET_ADAPTER.read().connection_info().await).clone(); // the connection_info is set *ACTIVE_CONNECTION.write() = connection_info; } }); mod another_scope { use dioxus::prelude::*; use crate::ACTIVE_CONNECTION; #[component] pub fn MyComponent() -> Element { // Now `ConnectionInfo` is `reactive` and can be accessed // without the need for an async scope if let Ok(wallet_account) = ACTIVE_CONNECTION.read().connected_account() { address = wallet_account.address().to_string(); shortened_address = wallet_account .shorten_address() .unwrap_or_default() .to_string(); public_key_bytes = wallet_account.public_key(); } } } }
{{#endtab }}
{{#tab name="Sycamore" }}
#![allow(unused)] fn main() { use sycamore::prelude::*; #[component] fn App() -> View { // ConnectionInfo is wrapped in a `provide_context` to expose it to the global scope provide_context(create_signal(ConnectionInfo::default())); let adapter = use_context::<Signal<WalletAdapter>>(); // use the active connection here in order to listen for events let active_connection = use_context::<Signal<ConnectionInfo>>(); spawn_local(async move { while let Ok(wallet_event) = adapter.get_clone().events().recv().await { account_state.set(AccountState::default()); // Access the `ConnectionInfo` within a async scope let connection_info = (adapter.get_clone().connection_info().await).clone(); // Set the `connection_info` to the `active_connection` active_connection.set(connection_info); } }); } mod another_scope { use sycamore::prelude::*; use wallet_adapter::ConnectionInfo; #[component] pub fn Accounts() -> View { let active_connection = use_context::<Signal<ConnectionInfo>>(); if let Ok(wallet_account) = active_connection.get_clone().connected_account() { }else { } } } }
{{#endtab }}
{{#tab name="Yew" }}
#![allow(unused)] fn main() { use yew::prelude::*; #[function_component(App)] pub fn app() -> Html { let adapter = WalletAdapter::init().unwrap(); let events = adapter.events().clone(); // The active connection is part of the `GlobalAppInfo` type let init_state = GlobalAppInfo::new(adapter); // Use a reducer to make the state global let global_state = use_reducer(|| init_state); html! { <ContextProvider<GlobalAppState> context={global_state.clone()}> <ContextProvider<ClusterStoreState> context={cluster_store_state.clone()}> // All child components of this element have access to the `GlobalAppInfo` <MyComponent/> </ContextProvider<GlobalAppState>> } } mod another_scope { use yew::prelude::*; use crate::GlobalAppState; #[function_component] pub fn MyComponent() -> Html { // Accessible from global scope let global_state = use_context::<GlobalAppState>().expect("no global ctx `GlobalAppState` found"); // Access the active connection // an get the `connected_account` for this example if let Ok(connected_account) = global_state.active_connection.borrow().connected_account(){} } } }
{{#endtab }} {{#endtabs }}