| Crates.io | wallet_standard_browser |
| lib.rs | wallet_standard_browser |
| version | 0.5.0 |
| created_at | 2024-09-13 11:45:13.428365+00 |
| updated_at | 2025-11-07 10:00:45.186628+00 |
| description | The wasm / browser compatible rust based implementation of the wallet standard. |
| homepage | https://github.com/ifiokjr/wallet_standard |
| repository | https://github.com/ifiokjr/wallet_standard |
| max_upload_size | |
| id | 1373584 |
| size | 117,210 |
wallet_standard_browserThe WebAssembly/browser compatible Rust implementation of the Wallet Standard.
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.
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"
| Feature | Description |
|---|---|
solana |
Enables Solana-specific functionality |
This crate provides several key components:
BrowserWallet: A wrapper around JavaScript wallet implementations that conforms to the Wallet StandardBrowserWalletInfo: Represents wallet metadata for browser-based walletsBrowserWalletAccountInfo: Represents account information for browser-based walletsuse wallet_standard_browser::prelude::*;
use wasm_bindgen_futures::spawn_local;
use web_sys::console;
// Function to detect and connect to available wallets
async fn connect_to_wallet() -> WalletResult<()> {
// Get available wallets
let wallets = get_wallets().await?;
// Log the number of available wallets
console::log_1(&format!("Found {} wallets", wallets.get().len()).into());
// Find a specific wallet by name
if let Some(wallet) = wallets.get().iter().find(|w| w.name() == "Phantom") {
console::log_1(&format!("Found Phantom wallet").into());
// Create a wallet instance
let mut wallet_instance = BrowserWallet::from(wallet.clone());
// Connect to the wallet
let accounts = wallet_instance.connect().await?;
console::log_1(&format!("Connected to {} accounts", accounts.len()).into());
// Now you can use the wallet for operations
if wallet_instance.connected() {
// Example: Sign a message
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(())
}
// Call this function from your application
fn initialize() {
spawn_local(async {
if let Err(err) = connect_to_wallet().await {
console::error_1(&format!("Error: {:?}", err).into());
}
});
}
use wallet_standard_browser::prelude::*;
use wasm_bindgen::JsCast;
use wasm_bindgen::prelude::*;
use wasm_bindgen_futures::spawn_local;
// Create a closure to handle wallet registration events
fn listen_for_wallets() -> WalletResult<()> {
let wallets_callback = Closure::wrap(Box::new(move |wallet: BrowserWalletInfo| {
// A new wallet has been registered
let wallet_name = wallet.name();
web_sys::console::log_1(&format!("New wallet registered: {}", wallet_name).into());
// You can now use this wallet
let wallet_instance = BrowserWallet::from(wallet);
// Store the wallet instance for later use
}) as Box<dyn FnMut(BrowserWalletInfo)>);
// Get the wallets registry
spawn_local(async move {
match get_wallets().await {
Ok(wallets) => {
// Register the callback for new wallet registrations
let _dispose = wallets.on_register(&wallets_callback);
// Keep the callback alive
wallets_callback.forget();
}
Err(err) => {
web_sys::console::error_1(&format!("Error getting wallets: {:?}", err).into());
}
}
});
Ok(())
}
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<()> {
// Ensure the wallet is connected
if !wallet.connected() {
wallet.connect().await?;
}
// Get the wallet's public key
let pubkey = wallet.try_solana_pubkey()?;
// Create a simple transaction (transfer 0.001 SOL to self)
let instructions = vec![solana_system_interface::instructions::transfer(
&pubkey, &pubkey, 1_000_000, // lamports (0.001 SOL)
)];
// Create a message
let message = Message::new(&instructions, Some(&pubkey));
// Create a transaction
let transaction = Transaction::new_unsigned(message);
// Convert to versioned transaction
let versioned_transaction = VersionedTransaction::from(transaction);
// Create transaction props
let props = SolanaSignAndSendTransactionProps::builder()
.transaction(versioned_transaction)
.build();
// Sign and send the transaction
let result = wallet.sign_and_send_transaction(props).await?;
// Get the signature
let signature = result.signature();
web_sys::console::log_1(&format!("Transaction sent with signature: {}", signature).into());
Ok(())
}
If you're developing a wallet that needs to be compatible with the Wallet Standard in a browser environment, you'll need to:
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() {
// Create your wallet implementation
let wallet_info = create_wallet_info();
// Register the wallet with the Wallet Standard
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 {
// Create a wallet info object that conforms to the Wallet Standard
serde_json::json!({
"name": "My Wallet",
"icon": "data:image/svg+xml;base64,...", // Base64 encoded SVG
"version": "1.0.0",
"chains": ["solana:mainnet"],
"features": [
"standard:connect",
"standard:disconnect",
"solana:signMessage",
"solana:signTransaction",
"solana:signAndSendTransaction"
],
"accounts": []
})
}
For each feature your wallet supports, you'll need to implement the corresponding JavaScript functions. Here's an example for the solana:signMessage feature:
// In your wallet's JavaScript code
window.myWallet = {
// ... other wallet properties
features: {
// ... other features
"solana:signMessage": {
version: "1.0.0",
signMessage: async function(accounts, messages) {
// Implement message signing
return messages.map(message => ({
signature: new Uint8Array(...), // The signature bytes
signedMessage: message, // The message that was signed
signatureType: "ed25519" // Optional signature type
}));
}
}
}
};
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 {
// Get available wallets
let wallets = get_wallets().await.unwrap();
// Find your wallet
if let Some(wallet) = wallets.get().iter().find(|w| w.name() == "My Wallet") {
// Create a wallet instance
let mut wallet_instance = BrowserWallet::from(wallet.clone());
// Connect to the wallet
wallet_instance.connect().await.unwrap();
// Sign a message
let message = b"Hello, Solana!";
let signature = wallet_instance.sign_message_async(message).await.unwrap();
// Use the signature
web_sys::console::log_1(&format!("Signature: {:?}", signature.signature()).into());
}
});
}
For complete examples of how to use this crate, check out the examples directory in the repository.
For detailed API documentation, please refer to the API documentation.