unitysdk.mp4
Unity SDK for Solana Mobile Wallet Adapter (MWA) 2.0, providing full API parity with the React Native MWA SDK. Build Android games and apps that connect to Solana wallets like Phantom and Solflare.
Mobile Wallet Adapter (MWA) is a protocol by Solana Mobile that enables Android dApps to communicate with wallet apps installed on the same device. Instead of bundling wallet functionality into your app, MWA leverages the user's existing wallet for transaction signing and authorization.
This SDK wraps the official mobile-wallet-adapter-clientlib-ktx Android library and exposes it to Unity C# through a JNI bridge, following the same architecture as the Godot MWA SDK.
- Full MWA 2.0 API parity with the React Native SDK
- All wallet methods: Authorize, Reauthorize, Deauthorize, Sign Transactions, Sign & Send Transactions, Sign Messages, Get Capabilities
- Sign In With Solana (SIWS) support via
SignInPayload - Extensible authorization cache — built-in
FileMWACache+ customIMWACacheinterface - Disconnect & Reconnect — easily manage wallet sessions with cache persistence
- Event-driven API — C# events for all async operations
- Cluster selection — Devnet, Mainnet, Testnet
- Singleton pattern —
MobileWalletAdapter.Instancefor easy global access - Zero external Unity dependencies — works with any Unity 2021.3+ project
Add via Unity Package Manager using the git URL:
Window > Package Manager > + > Add package from git URL:
https://github.com/nicoeseworthy/Unity-MWA-SDK.git
- File > Build Profiles > Select Android > Switch Platform
- Player Settings > Other Settings:
- Minimum API Level: Android 7.0 (API 24)
- Target API Level: Automatic (highest installed)
- Player Settings > Publishing Settings:
- Enable Custom Main Gradle Template
- Enable Custom Gradle Properties Template
- Enable Custom Gradle Settings Template
- Add MWA dependencies to
Assets/Plugins/Android/mainTemplate.gradle:dependencies { implementation 'com.solanamobile:mobile-wallet-adapter-clientlib-ktx:2.0.3' implementation 'com.solanamobile:rpc-core:0.2.8' implementation 'androidx.activity:activity-compose:1.8.2' implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.7.0' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3' implementation 'androidx.compose.ui:ui:1.5.4' implementation 'androidx.compose.material:material:1.5.4' } - Add to
Assets/Plugins/Android/gradleTemplate.properties:android.useAndroidX=true android.enableJetifier=true
using Solana.MWA;
using UnityEngine;
public class WalletManager : MonoBehaviour
{
private MobileWalletAdapter mwa;
void Start()
{
mwa = MobileWalletAdapter.Instance;
// Configure your dApp identity (shown to user in wallet)
mwa.Identity = new DappIdentity(
"My Game",
"https://mygame.com",
"favicon.ico"
);
mwa.ActiveCluster = Cluster.Devnet;
// Listen for events
mwa.OnAuthorized += OnWalletConnected;
mwa.OnAuthorizationFailed += OnWalletFailed;
mwa.OnDeauthorized += () => Debug.Log("Disconnected");
}
public void ConnectWallet()
{
mwa.Authorize();
}
void OnWalletConnected(AuthorizationResult result)
{
Debug.Log($"Connected! Account: {result.Accounts[0].Address}");
Debug.Log($"Auth token: {result.AuthToken}");
}
void OnWalletFailed(MWAErrorCode code, string message)
{
Debug.LogError($"Failed ({code}): {message}");
}
}Build to an Android device with a MWA-compatible wallet installed (Phantom, Solflare).
The main entry point. Access via MobileWalletAdapter.Instance (singleton) or attach to a GameObject.
| Property | Type | Description |
|---|---|---|
Identity |
DappIdentity |
dApp identity shown to user in wallet prompt |
ActiveCluster |
Cluster |
Blockchain cluster (Devnet, Mainnet, Testnet) |
AuthCache |
IMWACache |
Authorization cache (default: FileMWACache) |
State |
ConnectionState |
Current state (Disconnected, Connecting, Connected, Signing, Deauthorizing) |
CurrentAuth |
AuthorizationResult |
Current authorization (accounts, auth token) |
Capabilities |
WalletCapabilities |
Last queried wallet capabilities |
IsAuthorized |
bool |
Has valid authorization |
IsConnected |
bool |
Connected with active session |
| Method | React Native Equivalent | Description |
|---|---|---|
Authorize(signInPayload?) |
wallet.authorize() |
Connect to wallet, optionally with SIWS |
Reconnect() |
wallet.reauthorize() |
Restore session from cached auth token |
Deauthorize() |
wallet.deauthorize() |
Revoke authorization, clear cache |
Disconnect() |
— | Alias for Deauthorize() |
| Method | React Native Equivalent | Description |
|---|---|---|
SignTransactions(byte[][] payloads) |
wallet.signTransactions() |
Sign without broadcasting |
SignAndSendTransactions(byte[][] payloads, SendOptions options?) |
wallet.signAndSendTransactions() |
Sign and broadcast to network |
SignMessages(byte[][] messages, byte[][] addresses?) |
wallet.signMessages() |
Sign arbitrary off-chain messages |
| Method | React Native Equivalent | Description |
|---|---|---|
GetCapabilities() |
wallet.getCapabilities() |
Query wallet features and limits |
GetAccount() |
— | Get primary authorized account |
GetAccounts() |
— | Get all authorized accounts |
GetPublicKey() |
— | Get primary account public key |
SetCache(IMWACache) |
— | Replace cache at runtime |
| Event | Signature | Description |
|---|---|---|
OnAuthorized |
Action<AuthorizationResult> |
Wallet authorized successfully |
OnAuthorizationFailed |
Action<MWAErrorCode, string> |
Authorization rejected or failed |
OnDeauthorized |
Action |
Session ended |
OnDeauthorizationFailed |
Action<string> |
Deauthorization failed |
OnCapabilitiesReceived |
Action<WalletCapabilities> |
Capabilities query completed |
OnTransactionsSigned |
Action<byte[][]> |
Transactions signed |
OnTransactionsSignFailed |
Action<MWAErrorCode, string> |
Signing failed |
OnTransactionsSent |
Action<string[]> |
Transactions sent (signatures) |
OnTransactionsSendFailed |
Action<MWAErrorCode, string> |
Send failed |
OnMessagesSigned |
Action<byte[][]> |
Messages signed |
OnMessagesSignFailed |
Action<MWAErrorCode, string> |
Message signing failed |
OnAuthorizationCloned |
Action<string> |
Auth cloned (new token) |
OnCloneFailed |
Action<string> |
Clone failed |
OnStateChanged |
Action<ConnectionState> |
Connection state changed |
new DappIdentity(
name: "My App", // Display name in wallet
uri: "https://app.com", // Your dApp URI
icon: "favicon.ico" // Icon URI
)new SendOptions {
Commitment =