/wasi-sol

💳 A Solana Wallet adapter for WASM frameworks (WIP).

Primary LanguageRustMIT LicenseMIT

🦀 Wasi Sol

made-with-rust Netlify Status Rust Maintenance Crates.io Crates.io Downloads docs License

WASI SOL Demo

A Solana Wallet adapter for WASM frameworks.

🔒 Wallets Support

Note

By default, this crate triggers all EIP-1193 compatible wallets, but you can only connect and perform all actions listed below if it is Phantom wallet.

Wallet Supported Features
Phantom All
Metamask Wallet Connect Only
Solflare

🌐 Wasm Frameworks Support

Framework Supported
Yew
Dioxus
Leptos

⚙️ Features

Method Supported Tested
connect
disconnect
send_transaction
sign_message
sign_transaction
sign_all_transactions
sign_in

❌: TODO

🚀 Examples

In addition to the examples directory, you can use the following snippet of code to add wasi-sol wallet adapter using its built-in providers and hooks:

use yew::prelude::*;

use wasi_sol::{
    core::traits::WalletAdapter,
    core::wallet::BaseWalletAdapter,
    provider::{
        connection::{use_connection, ConnectionProvider},
        wallet::{use_wallet, WalletProvider},
    },
    spawn_local
};

#[function_component]
pub fn App() -> Html {
    let endpoint = "https://api.mainnet-beta.solana.com";
    let wallets = vec![BaseWalletAdapter::new(
        "Phantom",
        "https://phantom.app",
        "phantom_icon_url",
    )];

    html! {
        <ConnectionProvider {endpoint}>
            <WalletProvider {endpoint} {wallets}>
                <LoginPage />
            </WalletProvider>
        </ConnectionProvider>
    }
}

#[function_component]
pub fn LoginPage() -> Html {
    let _connection_context = use_connection();
    let wallet_context = use_wallet();
    let connected = use_state(|| false);
    let wallet_adapter = use_state(|| wallet_context);

    let wallet_info = (*wallet_adapter).clone();

    let connect_wallet = {
        let connected = connected.clone();
        let wallet_adapter = wallet_adapter.clone();

        Callback::from(move |_| {
            let connected = connected.clone();
            let wallet_adapter = wallet_adapter.clone();

            spawn_local(async move {
                let mut wallet_info = (*wallet_adapter).clone();

                match wallet_info.connect().await {
                    Ok(_) => {
                        wallet_adapter.set(wallet_info);
                        connected.set(true);
                    }
                    Err(err) => {
                        log::error!("Failed to connect wallet: {}", err);
                    }
                }
            });
        })
    };

    let disconnect_wallet = {
        let connected = connected.clone();
        let wallet_adapter = wallet_adapter.clone();

        Callback::from(move |_| {
            let connected = connected.clone();
            let wallet_adapter = wallet_adapter.clone();

            spawn_local(async move {
                let mut wallet_info = (*wallet_adapter).clone();

                match wallet_info.disconnect().await {
                    Ok(_) => {
                        wallet_adapter.set(wallet_info);
                        connected.set(false);
                    }
                    Err(err) => {
                        log::error!("Failed to disconnect wallet: {}", err);
                    }
                }
            });
        })
    };

    html! {
        <div class="content">
            <div class="wallet-info">
                if *connected {
                    if let Some(ref key) = wallet_info.public_key() {
                        <p>{ format!("Connected Wallet: {}", wallet_info.name()) }</p>
                        <p>{ format!("Connected Public Key: {}", key) }</p>
                    } else {
                        <p>{ "Connected but no wallet info available" }</p>
                    }
                }
            </div>
            <div class="buttons">
                if !*connected {
                    <button class="connect-button" onclick={connect_wallet}>
                        <img src="images/phantom_logo.png" alt="Phantom Wallet" class="button-icon" />
                        { "Connect Wallet" }
                    </button>
                } else {
                    <button class="disconnect-button" onclick={disconnect_wallet}>
                        <img src="images/phantom_logo.png" alt="Disconnect Wallet" class="button-icon" />
                        { "Disconnect Wallet" }
                    </button>
                }
            </div>
        </div>
    }
}

fn main() {
    console_error_panic_hook::set_once();
    wasm_logger::init(wasm_logger::Config::default());
    yew::Renderer::<App>::new().render();
}

👥 Contributing

Contributions and feedback are welcome! If you'd like to contribute, report an issue, or suggest an enhancement, please engage with the project on GitHub. Your contributions help improve this library for the community.

📝 License

This project is licensed under the MIT License.