react-native-solana-mobile-wallet-adapter
v0.1.0
Published
React Native Solana Mobile Wallet Adapter for iOS and Android
Readme
react-native-solana-mobile-wallet-adapter
Unified cross-platform Solana wallet adapter for React Native and Expo.
- Android: Mobile Wallet Adapter (MWA) 2.0 protocol
- iOS: Phantom/Solflare deeplinks with encrypted sessions
Features
- ✅ Unified API for both iOS and Android
- ✅ Session persistence across app restarts
- ✅ Multiple wallet support (Phantom, Solflare, Backpack)
- ✅ Sign transactions, messages, and more
- ✅ Works with Expo Router
- ✅ TypeScript support
Installation
# Install the package
npm install react-native-solana-mobile-wallet-adapter
# Install required peer dependencies
npm install expo-linking expo-secure-store @solana/web3.js
# Android only - install MWA protocol (optional if iOS-only)
npm install @solana-mobile/mobile-wallet-adapter-protocol-web3jsQuick Start
import { transact, isConnected, getConnectedAddress } from 'react-native-solana-mobile-wallet-adapter';
// Connect to wallet
const result = await transact(async (wallet) => {
const auth = await wallet.authorize({
cluster: 'mainnet-beta',
identity: {
name: 'My App',
uri: 'https://myapp.com',
icon: 'favicon.ico',
},
});
return auth.accounts[0].address;
});
// Check connection status
if (isConnected()) {
console.log('Connected to:', getConnectedAddress());
}App Configuration
Expo (app.json / app.config.ts)
{
"expo": {
"scheme": "myapp",
"ios": {
"infoPlist": {
"LSApplicationQueriesSchemes": ["phantom", "solflare", "backpack"]
}
}
}
}Important: The scheme is required for iOS deeplink callbacks.
React Native CLI (Info.plist)
<!-- Allow querying wallet apps -->
<key>LSApplicationQueriesSchemes</key>
<array>
<string>phantom</string>
<string>solflare</string>
<string>backpack</string>
</array>
<!-- Register your app's URL scheme -->
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
</dict>
</array>Import Options
Option 1: Auto-detect platform (recommended)
import { transact } from 'react-native-solana-mobile-wallet-adapter';
// Automatically uses iOS or Android implementation
await transact(async (wallet) => { /* ... */ });Option 2: Platform-specific imports
// iOS
import { transact } from 'react-native-solana-mobile-wallet-adapter/ios';
// Android
import { transact } from 'react-native-solana-mobile-wallet-adapter/android';Option 3: Explicit platform config
import { transact } from 'react-native-solana-mobile-wallet-adapter';
import { Platform } from 'react-native';
await transact(callback, { platform: Platform.OS as 'ios' | 'android' });API Reference
transact<T>(callback, config?): Promise<T>
Opens a wallet session and executes the callback.
interface TransactConfig {
platform?: 'ios' | 'android'; // Explicit platform
wallet?: 'phantom' | 'solflare'; // iOS: wallet to use
redirectScheme?: string; // iOS: custom URL scheme
walletUriBase?: string; // Android: wallet URI base
}MobileWallet Methods
authorize(params): Promise<AuthorizationResult>
const auth = await wallet.authorize({
cluster: 'mainnet-beta', // 'mainnet-beta' | 'devnet' | 'testnet'
identity: {
name: 'My App',
uri: 'https://myapp.com',
icon: 'favicon.ico',
},
authToken: previousToken, // Optional: for re-authorization
});
// Returns:
// auth.accounts[0].address - wallet address (string)
// auth.accounts[0].publicKey - wallet public key (Uint8Array)
// auth.authToken - session tokendeauthorize(params): Promise<void>
await wallet.deauthorize({ authToken: auth.authToken });signTransactions(params): Promise<Transaction[]>
const [signedTx] = await wallet.signTransactions({
transactions: [transaction],
});signMessages(params): Promise<Uint8Array[]>
const [signature] = await wallet.signMessages({
addresses: [auth.accounts[0].address],
payloads: [new TextEncoder().encode('Hello!')],
});signAndSendTransactions(params): Promise<string[]> (Android only)
const signatures = await wallet.signAndSendTransactions({
transactions: [tx],
minContextSlot: slot,
});Helper Functions
| Function | Description |
|----------|-------------|
| isConnected() | Returns true if there's an active session |
| getConnectedAddress() | Returns the connected wallet address or null |
| getConnectedWalletType() | Returns 'phantom' | 'solflare' | null (iOS only) |
| disconnect() | Clears the session without calling the wallet |
| getInstalledWallets() | Returns list of installed wallet apps (iOS) |
| getSelectedWallet() | Returns the user's selected wallet (iOS) |
| setSelectedWallet(wallet) | Sets the preferred wallet (iOS) |
| handleRedirectUrl(url) | Handle deeplink callback (for Expo Router) |
Platform Differences
| Feature | Android (MWA) | iOS (Deeplinks) |
|---------|---------------|-----------------|
| signAndSendTransactions | ✅ | ❌ Deprecated |
| Multiple wallet picker | ✅ System UI | Manual selection |
| Background signing | ✅ | ❌ |
| Session encryption | MWA protocol | X25519 |
Troubleshooting
"Could not detect platform" error
For local/linked packages, either:
- Use platform-specific imports
- Pass
{ platform: Platform.OS }in config - Configure Metro (see USAGE.md)
iOS wallet doesn't return to app
Ensure your scheme is configured in app.json and matches your deeplink setup.
Android wallet picker doesn't appear
Make sure @solana-mobile/mobile-wallet-adapter-protocol-web3js is installed.
Documentation
- 📖 USAGE.md - Complete integration guide with Expo Router
- 🔗 Solana Mobile Docs
- 👻 Phantom Deeplinks
License
MIT
