Skip to content

A pure Rust implementation of the Solana Wallet Standard for WebAssembly applications. Provides a type-safe, async-first API for connecting to browser wallet extensions (Phantom, Solflare, etc.) and interacting with the Solana blockchain. Designed for Rust frontend frameworks like Dioxus, Yew, and Sycamore, with zero unsafe code and comprehensive

License

Notifications You must be signed in to change notification settings

mooncitydev/solana-wallet-adapter-rust

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Solana Wallet Adapter for Rust

Rust WebAssembly Solana

crates.io Docs License Rust

A lightweight, type-safe Solana wallet adapter for Rust-based frontends and WebAssembly applications

Documentation β€’ Features β€’ Quick Start β€’ Examples β€’ Contributing


πŸ“– Overview

wallet-adapter is a pure Rust implementation of the Solana Wallet Standard, designed for building WebAssembly-based dApps with frameworks like Dioxus, Yew, and Sycamore. It provides a type-safe, async-first API for connecting to browser wallet extensions and interacting with the Solana blockchain.

Key Features

  • βœ… Full Wallet Standard Compliance - Implements all standard wallet features
  • βœ… Type-Safe API - Leverages Rust's type system for compile-time safety
  • βœ… Async/Await Support - Built on async primitives for modern Rust applications
  • βœ… Zero Unsafe Code - #![forbid(unsafe_code)] enforced throughout
  • βœ… Framework Templates - Ready-to-use templates for Dioxus, Yew, and Sycamore
  • βœ… Comprehensive Error Handling - Detailed error types for all failure modes
  • βœ… Event-Driven Architecture - Reactive wallet state management

πŸš€ Quick Start

Installation

Add wallet-adapter to your Cargo.toml:

[dependencies]
wallet-adapter = "1.1.2"
web-sys = { version = "0.3", features = [
    "Window",
    "Document",
    "Event",
    "EventTarget",
    "CustomEvent",
] }
wasm-bindgen-futures = "0.4"

Basic Usage

use wallet_adapter::{WalletAdapter, WalletResult};

async fn connect_wallet() -> WalletResult<()> {
    // Initialize the wallet adapter
    let mut adapter = WalletAdapter::init()?;
    
    // Connect to a wallet by name
    adapter.connect_by_name("Phantom").await?;
    
    // Get connection info
    let connection = adapter.connection_info().await;
    let account = connection.connected_account()?;
    
    println!("Connected to: {}", account.address());
    
    Ok(())
}

πŸ“š Documentation

Comprehensive Guides

Core Concepts

Initialization

The adapter can be initialized in several ways:

// Default initialization (channel capacity: 5)
let adapter = WalletAdapter::init()?;

// Custom channel capacity
let adapter = WalletAdapter::init_with_channel_capacity(10)?;

// With custom Window and Document
let window = web_sys::window().unwrap();
let document = window.document().unwrap();
let adapter = WalletAdapter::init_custom(window, document)?;

Wallet Events

Listen for wallet events asynchronously:

let adapter = WalletAdapter::init()?;
let event_receiver = adapter.events();

while let Ok(event) = event_receiver.recv().await {
    match event {
        WalletEvent::Registered(wallet) => {
            println!("Wallet registered: {}", wallet.name());
        }
        WalletEvent::Connected(account) => {
            println!("Connected: {}", account.address());
        }
        WalletEvent::Disconnected => {
            println!("Wallet disconnected");
        }
        _ => {}
    }
}

Connecting to Wallets

// Connect by wallet name
adapter.connect_by_name("Phantom").await?;

// Or iterate through available wallets
for wallet in adapter.wallets() {
    if wallet.name() == "Phantom" {
        adapter.connect(wallet).await?;
        break;
    }
}

Checking Wallet Features

// Check cluster support
let supports_mainnet = adapter.mainnet().await?;
let supports_devnet = adapter.devnet().await?;

// Check feature support
let supports_sign_message = adapter.solana_sign_message().await?;
let supports_sign_transaction = adapter.solana_sign_transaction().await?;
let supports_sign_and_send = adapter.solana_sign_and_send_transaction().await?;

πŸ’‘ Examples

Sign In With Solana (SIWS)

use wallet_adapter::{WalletAdapter, SigninInput, Cluster};

async fn sign_in() -> WalletResult<()> {
    let mut adapter = WalletAdapter::init()?;
    adapter.connect_by_name("Phantom").await?;
    
    let public_key = adapter.connection_info().await
        .connected_account()?.public_key();
    let address = adapter.connection_info().await
        .connected_account()?.address().to_string();
    
    let mut signin_input = SigninInput::new();
    signin_input
        .set_domain(&adapter.window())?
        .set_statement("Login to My DApp")
        .set_chain_id(Cluster::DevNet)
        .set_address(&address)?;
    
    let signin_output = adapter.sign_in(&signin_input, public_key).await?;
    
    Ok(())
}

Sign Message

async fn sign_message() -> WalletResult<()> {
    let mut adapter = WalletAdapter::init()?;
    adapter.connect_by_name("Phantom").await?;
    
    if adapter.solana_sign_message().await? {
        let output = adapter.sign_message(b"Hello, Solana!").await?;
        println!("Signature: {}", output.signature);
    }
    
    Ok(())
}

Sign Transaction

use solana_sdk::{
    native_token::LAMPORTS_PER_SOL,
    pubkey::Pubkey,
    system_instruction,
    transaction::Transaction,
};
use wallet_adapter::{WalletAdapter, Cluster};

async fn sign_transaction() -> WalletResult<()> {
    let mut adapter = WalletAdapter::init()?;
    adapter.connect_by_name("Phantom").await?;
    
    let public_key = adapter.connection_info().await
        .connected_account()?.public_key();
    let pubkey = Pubkey::new_from_array(public_key);
    
    let recipient = Pubkey::new_unique();
    let instruction = system_instruction::transfer(&pubkey, &recipient, LAMPORTS_PER_SOL);
    let tx = Transaction::new_with_payer(&[instruction], Some(&pubkey));
    let tx_bytes = bincode::serialize(&tx)?;
    
    let signed_tx = adapter.sign_transaction(&tx_bytes, Some(Cluster::DevNet)).await?;
    
    Ok(())
}

Sign and Send Transaction

use wallet_adapter::{WalletAdapter, Cluster, SendOptions};

async fn sign_and_send() -> WalletResult<()> {
    let mut adapter = WalletAdapter::init()?;
    adapter.connect_by_name("Phantom").await?;
    
    // ... build transaction ...
    
    let send_options = SendOptions::default();
    let signature = adapter.sign_and_send_transaction(
        &tx_bytes,
        Cluster::DevNet,
        send_options
    ).await?;
    
    println!("Transaction signature: {}", signature);
    
    Ok(())
}

🎨 Framework Templates

Ready-to-use templates for popular Rust frontend frameworks:

Each template includes:

  • Complete wallet connection UI
  • Transaction signing flows
  • Account management
  • Network switching
  • Error handling
  • Modern, responsive design

πŸ”§ Features

Wallet Standard Features

  • βœ… wallet-standard:register-wallet - Wallet registration
  • βœ… wallet-standard:app-ready - App readiness notification
  • βœ… standard:connect - Connect to wallet
  • βœ… standard:disconnect - Disconnect from wallet
  • βœ… standard:events - Wallet event subscription

Solana-Specific Features

  • βœ… solana:signIn - Sign In With Solana (SIWS)
  • βœ… solana:signMessage - Message signing
  • βœ… solana:signTransaction - Transaction signing
  • βœ… solana:signAndSendTransaction - Sign and send transactions

Additional Features

  • βœ… Multi-cluster support (Mainnet, Devnet, Testnet, Localnet)
  • βœ… Commitment level configuration
  • βœ… Wallet account parsing and validation
  • βœ… Ed25519 signature verification
  • βœ… In-memory wallet storage
  • βœ… Comprehensive error types

πŸ—οΈ Architecture

Storage

Wallets are stored in-memory using a HashMap keyed by wallet name hash:

use wallet_adapter::WalletStorage;

let storage = WalletStorage::default();
let wallets = storage.get_wallets();
let phantom = storage.get_wallet("Phantom");

Connection Info

Connection state is managed through ConnectionInfo:

let connection = adapter.connection_info().await;
let wallet = connection.connected_wallet()?;
let account = connection.connected_account()?;

Error Handling

All operations return WalletResult<T>, which is Result<T, WalletError>. The error type provides detailed information about failures:

match adapter.connect_by_name("Phantom").await {
    Ok(_) => println!("Connected!"),
    Err(WalletError::WalletNotFound) => println!("Wallet not installed"),
    Err(WalletError::WalletConnectError(msg)) => println!("Connection failed: {}", msg),
    Err(e) => println!("Error: {}", e),
}

πŸ“¦ Project Structure

.
β”œβ”€β”€ crate/                    # Main library crate
β”‚   └── src/
β”‚       β”œβ”€β”€ adapter.rs       # WalletAdapter implementation
β”‚       β”œβ”€β”€ errors.rs        # Error types
β”‚       β”œβ”€β”€ events.rs        # Event handling
β”‚       β”œβ”€β”€ storage.rs       # Wallet storage
β”‚       β”œβ”€β”€ utils.rs         # Utility functions
β”‚       └── wallet_ser_der/  # Wallet serialization/deserialization
β”œβ”€β”€ templates/               # Framework templates
β”‚   β”œβ”€β”€ dioxus-adapter/
β”‚   β”œβ”€β”€ yew-adapter/
β”‚   └── sycamore-adapter/
β”œβ”€β”€ wallet-adapter-book/     # Documentation book
└── partial-idl-parser/      # IDL parser utility

🀝 Contributing

Contributions are welcome! Please read our contributing guidelines and code of conduct.

Development Setup

# Clone the repository
git clone https://github.com/yourusername/solana-wallet-adapter-rust.git
cd solana-wallet-adapter-rust

# Build the project
cargo build

# Run tests
cargo test

# Check code quality
cargo clippy
cargo fmt

Code of Conduct

All contributors must agree to the Rust Code of Conduct.

πŸ“„ License

Licensed under either of:

at your option.

πŸ™ Acknowledgments

  • Built for the Solana ecosystem
  • Implements the Wallet Standard
  • Inspired by the JavaScript wallet adapter ecosystem

πŸ“ž Contact & Support


Built with ❀️ for the Rust and Solana communities

⭐ Star us on GitHub β€’ πŸ“– Read the Docs β€’ πŸ’¬ Get Support

About

A pure Rust implementation of the Solana Wallet Standard for WebAssembly applications. Provides a type-safe, async-first API for connecting to browser wallet extensions (Phantom, Solflare, etc.) and interacting with the Solana blockchain. Designed for Rust frontend frameworks like Dioxus, Yew, and Sycamore, with zero unsafe code and comprehensive

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •