wallet_standard_browser
The WebAssembly/browser compatible Rust implementation of the Wallet Standard.

Overview
The wallet_standard_browser crate provides a WebAssembly-compatible implementation of the Wallet Standard for Solana. It enables Rust-based wallets to be used in browser environments and allows dApps to interact with these wallets through a consistent interface.
Installation
To install you can use the following command:
cargo add wallet_standard_browser
Or directly add the following to your Cargo.toml:
[dependencies]
wallet_standard_browser = "0.5.0"
Features
| Feature |
Description |
solana |
Enables Solana-specific functionality |
Core Components
This crate provides several key components:
BrowserWallet: A wrapper around JavaScript wallet implementations that conforms to the Wallet Standard
BrowserWalletInfo: Represents wallet metadata for browser-based wallets
BrowserWalletAccountInfo: Represents account information for browser-based wallets
- Feature wrappers: JavaScript bindings for wallet features like connect, disconnect, sign message, etc.
Usage for dApp Developers
Detecting and Connecting to Wallets
use wallet_standard_browser::prelude::*;
use wasm_bindgen_futures::spawn_local;
use web_sys::console;
async fn connect_to_wallet() -> WalletResult<()> {
let wallets = get_wallets().await?;
console::log_1(&format!("Found {} wallets", wallets.get().len()).into());
if let Some(wallet) = wallets.get().iter().find(|w| w.name() == "Phantom") {
console::log_1(&format!("Found Phantom wallet").into());
let mut wallet_instance = BrowserWallet::from(wallet.clone());
let accounts = wallet_instance.connect().await?;
console::log_1(&format!("Connected to {} accounts", accounts.len()).into());
if wallet_instance.connected() {
let message = b"Hello, Solana!";
let signature = wallet_instance.sign_message_async(message).await?;
console::log_1(&format!("Message signed successfully").into());
}
} else {
console::log_1(&"Phantom wallet not found".into());
}
Ok(())
}
fn initialize() {
spawn_local(async {
if let Err(err) = connect_to_wallet().await {
console::error_1(&format!("Error: {:?}", err).into());
}
});
}
Listening for Wallet Events
use wallet_standard_browser::prelude::*;
use wasm_bindgen::JsCast;
use wasm_bindgen::prelude::*;
use wasm_bindgen_futures::spawn_local;
fn listen_for_wallets() -> WalletResult<()> {
let wallets_callback = Closure::wrap(Box::new(move |wallet: BrowserWalletInfo| {
let wallet_name = wallet.name();
web_sys::console::log_1(&format!("New wallet registered: {}", wallet_name).into());
let wallet_instance = BrowserWallet::from(wallet);
}) as Box<dyn FnMut(BrowserWalletInfo)>);
spawn_local(async move {
match get_wallets().await {
Ok(wallets) => {
let _dispose = wallets.on_register(&wallets_callback);
wallets_callback.forget();
}
Err(err) => {
web_sys::console::error_1(&format!("Error getting wallets: {:?}", err).into());
}
}
});
Ok(())
}
Signing and Sending Transactions (Solana)
use solana_message::Message;
use solana_pubkey::Pubkey;
use solana_transaction::Transaction;
use solana_transaction::VersionedTransaction;
use wallet_standard_browser::prelude::*;
use wasm_bindgen_futures::spawn_local;
async fn send_transaction(wallet: &mut BrowserWallet) -> WalletResult<()> {
if !wallet.connected() {
wallet.connect().await?;
}
let pubkey = wallet.try_solana_pubkey()?;
let instructions = vec![solana_system_interface::instructions::transfer(
&pubkey, &pubkey, 1_000_000, )];
let message = Message::new(&instructions, Some(&pubkey));
let transaction = Transaction::new_unsigned(message);
let versioned_transaction = VersionedTransaction::from(transaction);
let props = SolanaSignAndSendTransactionProps::builder()
.transaction(versioned_transaction)
.build();
let result = wallet.sign_and_send_transaction(props).await?;
let signature = result.signature();
web_sys::console::log_1(&format!("Transaction sent with signature: {}", signature).into());
Ok(())
}
Usage for Wallet Developers
Implementing a Browser Wallet
If you're developing a wallet that needs to be compatible with the Wallet Standard in a browser environment, you'll need to:
- Create a JavaScript wallet implementation that conforms to the Wallet Standard
- Register your wallet with the Wallet Standard
Here's a simplified example of how to register your wallet:
use wallet_standard_browser::constants::*;
use wasm_bindgen::prelude::*;
use web_sys::CustomEvent;
use web_sys::CustomEventInit;
use web_sys::window;
#[wasm_bindgen]
pub fn register_wallet() {
let wallet_info = create_wallet_info();
let window = window().expect("no global window exists");
let event_init = CustomEventInit::new();
event_init.detail(&JsValue::from_serde(&wallet_info).unwrap());
let event = CustomEvent::new_with_event_init_dict(REGISTER_WALLET_EVENT, &event_init)
.expect("failed to create custom event");
window
.dispatch_event(&event)
.expect("failed to dispatch event");
}
fn create_wallet_info() -> serde_json::Value {
serde_json::json!({
"name": "My Wallet",
"icon": "data:image/svg+xml;base64,...", "version": "1.0.0",
"chains": ["solana:mainnet"],
"features": [
"standard:connect",
"standard:disconnect",
"solana:signMessage",
"solana:signTransaction",
"solana:signAndSendTransaction"
],
"accounts": []
})
}
Implementing Wallet Features
For each feature your wallet supports, you'll need to implement the corresponding JavaScript functions. Here's an example for the solana:signMessage feature:
window.myWallet = {
features: {
"solana:signMessage": {
version: "1.0.0",
signMessage: async function(accounts, messages) {
return messages.map(message => ({
signature: new Uint8Array(...), signedMessage: message, signatureType: "ed25519" }));
}
}
}
};
Then in your Rust code, you can use the wallet_standard_browser crate to interact with this JavaScript implementation:
use wallet_standard_browser::prelude::*;
use wasm_bindgen_futures::spawn_local;
fn use_wallet() {
spawn_local(async {
let wallets = get_wallets().await.unwrap();
if let Some(wallet) = wallets.get().iter().find(|w| w.name() == "My Wallet") {
let mut wallet_instance = BrowserWallet::from(wallet.clone());
wallet_instance.connect().await.unwrap();
let message = b"Hello, Solana!";
let signature = wallet_instance.sign_message_async(message).await.unwrap();
web_sys::console::log_1(&format!("Signature: {:?}", signature.signature()).into());
}
});
}
Examples
For complete examples of how to use this crate, check out the examples directory in the repository.
API Reference
For detailed API documentation, please refer to the API documentation.