Expand description
§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_browserOr 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 StandardBrowserWalletInfo: Represents wallet metadata for browser-based walletsBrowserWalletAccountInfo: 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;
// 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());
}
});
}§Listening for Wallet Events
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(())
}§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<()> {
// 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(())
}§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() {
// 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": []
})
}§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:
// 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());
}
});
}§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.
Modules§
Structs§
- Browser
Experimental Decrypt Output - Browser
Experimental Encrypt Output - Browser
Standard Connect Output - Browser
Standard Events Properties - Browser
Wallet - Browser
Wallet Account Info - Interface of a
WalletAccount, also referred to as an Account. - Browser
Wallet Account Info Props - Browser
Wallet Info - Browser
Wallet Info Features - Browser
Wallet Info Props - Experimental
Decrypt Feature - Experimental
Decrypt Input - Experimental
Decrypt Props - Experimental
Encrypt Feature - Experimental
Encrypt Input - Experimental
Encrypt Props - Standard
Connect Feature - Standard
Connect Input - Input options for connecting to a wallet.
- Standard
Disconnect Feature - Standard
Events Feature - Wallets
Enums§
Constants§
- APP_
READY_ EVENT - Event that will be dispatched by the app on the
windowwhen the app is ready to register {@link Wallet | Wallets}. - CIPHER_
X25519_ XSALS A20_ POLY1305 - Default encryption algorithm in
NaCl. Curve25519 scalar multiplication, Salsa20 secret-key encryption, and Poly1305 one-time authentication. - EXPERIMENTAL_
DECRYPT - EXPERIMENTAL_
ENCRYPT - REGISTER_
WALLET_ EVENT - Event that will be dispatched on the
windowby each {@link Wallet | Wallet} when the Wallet is ready to be registered by the app. - STANDARD_
CONNECT - Feature identifier for the standard connect feature.
- STANDARD_
DISCONNECT - Feature identifier for the standard disconnect feature.
- STANDARD_
EVENTS
Traits§
- Connected
Wallet Standard Events - Experimental
Decrypt Output - Experimental
Encrypt Output - Feature
From Js - Into
Wallet Error - Standard
Connect Output - Output of a successful wallet connection.
- Standard
Event Properties - Wallet
- The core trait for wallet implementations.
- Wallet
Account Info - Interface of a
WalletAccount, also referred to as an Account. - Wallet
Experimental Decrypt - Wallet
Experimental Encrypt - Wallet
Info - Provides information about a wallet implementation.
- Wallet
Standard - A trait that combines the core wallet functionality with standard connect and disconnect features.
- Wallet
Standard Connect - Trait for wallets that support connecting to authorize accounts.
- Wallet
Standard Disconnect - Trait for wallets that support disconnecting.
Functions§
- get_
wallets - register_
wallet - Register a {@link “@wallet-standard/base”.Wallet} as a Standard Wallet with the app.