# Solana Mobile

> Solana Mobile development with Mobile Wallet Adapter (MWA), Seeker device integration, SeedVault secure storage, and React Native dApp patterns for building mobile-first Solana applications.

- **Type:** Skill
- **Install:** `agentstack add skill-agentic-reserve-agent-skill-solana-mobile`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [agentic-reserve](https://agentstack.voostack.com/s/agentic-reserve)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** Apache-2.0
- **Upstream author:** [agentic-reserve](https://github.com/agentic-reserve)
- **Source:** https://github.com/agentic-reserve/AGENT_SKILL/tree/main/solana-mobile

## Install

```sh
agentstack add skill-agentic-reserve-agent-skill-solana-mobile
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Solana Mobile Development Skill

Expert knowledge for building mobile dApps on Solana with Mobile Wallet Adapter, Seeker device integration, and SeedVault support.

---

## Overview

This skill provides comprehensive guidance for developing mobile applications on the Solana blockchain, with focus on:

- **Mobile Wallet Adapter (MWA)** - Protocol for connecting mobile dApps to wallets
- **Solana Mobile Seeker** - Detecting and optimizing for Seeker devices
- **SeedVault** - Secure key storage on Solana Mobile devices
- **React Native Integration** - Building cross-platform mobile dApps
- **dApp Store Publishing** - Submitting apps to Solana dApp Store

---

## When to Use This Skill

Activate this skill when:
- Building React Native dApps for Solana
- Implementing Mobile Wallet Adapter
- Detecting Solana Mobile Seeker users
- Integrating with SeedVault for secure key storage
- Publishing to Solana dApp Store
- Optimizing mobile user experience
- Implementing Sign-In With Solana (SIWS)

---

## Core Concepts

### Mobile Wallet Adapter (MWA)

MWA is a protocol that enables secure communication between mobile dApps and wallet apps.

**Key Features:**
- Secure WebSocket-based communication
- Session-based authorization
- Transaction signing
- Message signing
- Multi-wallet support

**Protocol Flow:**
1. **Association** - Establish connection via URI scheme
2. **Session Establishment** - ECDH key exchange
3. **Authorization** - Request wallet access
4. **Privileged Methods** - Sign transactions/messages

### Solana Mobile Seeker

Seeker is Solana's flagship mobile device with built-in crypto features.

**Detection Methods:**
1. **Platform Constants** (Client-side, spoofable)
2. **Genesis Token Verification** (On-chain, guaranteed)

**Seeker Features:**
- SeedVault secure storage
- Optimized Solana performance
- Seeker Genesis Token (SGT)
- Native dApp Store integration

### SeedVault

Secure enclave for storing private keys on Solana Mobile devices.

**Benefits:**
- Hardware-backed security
- Biometric authentication
- Secure key derivation
- Isolated from app memory

---

## Implementation Patterns

### 1. Mobile Wallet Adapter Setup

#### Install Dependencies

```bash
npm install @solana-mobile/mobile-wallet-adapter-protocol \
  @solana-mobile/mobile-wallet-adapter-protocol-web3js \
  @solana/web3.js \
  react-native-quick-crypto
```

#### Configure Polyfills

Create `polyfill.js`:

```javascript
import { install } from 'react-native-quick-crypto';
install();
```

Create `index.js`:

```javascript
import './polyfill';
import 'expo-router/entry';
```

Update `package.json`:

```json
{
  "main": "./index.js"
}
```

#### MWA Provider Setup

```typescript
import {
  ConnectionProvider,
  RPC_ENDPOINT,
} from '@solana/web3.js';
import {
  SolanaMobileWalletAdapter,
} from '@solana-mobile/mobile-wallet-adapter-protocol-web3js';

export function MobileWalletProvider({ children }) {
  return (
    
      
        {children}
      
    
  );
}
```

### 2. Authorization Flow

```typescript
import { transact } from '@solana-mobile/mobile-wallet-adapter-protocol-web3js';

async function authorizeWallet() {
  const result = await transact(async (wallet) => {
    const authResult = await wallet.authorize({
      cluster: 'solana:mainnet',
      identity: {
        name: 'Obscura DEX',
        uri: 'https://obscura.finance',
        icon: 'icon.png',
      },
      features: [
        'solana:signMessages',
        'solana:signAndSendTransaction',
      ],
    });

    return {
      accounts: authResult.accounts,
      authToken: authResult.auth_token,
      walletUriBase: authResult.wallet_uri_base,
    };
  });

  return result;
}
```

### 3. Sign and Send Transaction

```typescript
import { Transaction } from '@solana/web3.js';
import { transact } from '@solana-mobile/mobile-wallet-adapter-protocol-web3js';

async function signAndSendTransaction(transaction: Transaction) {
  const result = await transact(async (wallet) => {
    // Authorize if needed
    const authResult = await wallet.authorize({
      cluster: 'solana:mainnet',
      identity: APP_IDENTITY,
    });

    // Get latest blockhash
    const { blockhash } = await connection.getLatestBlockhash();
    transaction.recentBlockhash = blockhash;
    transaction.feePayer = authResult.accounts[0].publicKey;

    // Sign and send
    const signedTxs = await wallet.signAndSendTransactions({
      transactions: [transaction],
    });

    return signedTxs[0];
  });

  return result;
}
```

### 4. Sign Message

```typescript
async function signMessage(message: string) {
  const result = await transact(async (wallet) => {
    const authResult = await wallet.authorize({
      cluster: 'solana:mainnet',
      identity: APP_IDENTITY,
    });

    const encodedMessage = new TextEncoder().encode(message);
    
    const signedMessages = await wallet.signMessages({
      addresses: [authResult.accounts[0].address],
      payloads: [encodedMessage],
    });

    return {
      signature: signedMessages.signed_payloads[0],
      address: authResult.accounts[0].address,
    };
  });

  return result;
}
```

### 5. Seeker Detection (Platform Constants)

```typescript
import { Platform } from 'react-native';

function isSeekerDevice(): boolean {
  return Platform.constants?.Model === 'Seeker';
}

function getSeekerInfo() {
  if (!isSeekerDevice()) {
    return null;
  }

  return {
    model: Platform.constants.Model,
    brand: Platform.constants.Brand,
    manufacturer: Platform.constants.Manufacturer,
    fingerprint: Platform.constants.Fingerprint,
  };
}

// Usage
if (isSeekerDevice()) {
  console.log('Running on Seeker device!');
  // Show Seeker-specific UI
}
```

### 6. Seeker Genesis Token Verification

#### Client-Side: Sign-In With Solana (SIWS)

```typescript
async function signInWithSolana() {
  const result = await transact(async (wallet) => {
    const authResult = await wallet.authorize({
      cluster: 'solana:mainnet',
      identity: APP_IDENTITY,
      sign_in_payload: {
        domain: 'obscura.finance',
        statement: 'Sign in to verify Seeker ownership',
        uri: 'https://obscura.finance',
        version: '1',
        chainId: 'solana:mainnet',
        nonce: generateNonce(),
        issuedAt: new Date().toISOString(),
      },
    });

    return {
      walletAddress: authResult.accounts[0].address,
      signInResult: authResult.sign_in_result,
    };
  });

  // Send to backend for verification
  const isVerified = await verifyOnBackend(result);
  return isVerified;
}
```

#### Server-Side: Verify SIWS + Check SGT

```typescript
import { verifySignIn } from '@solana/wallet-standard-util';
import { Connection, PublicKey } from '@solana/web3.js';

// Step 1: Verify SIWS signature
async function verifySIWS(signInPayload, signInResult): Promise {
  const serializedOutput = {
    account: {
      publicKey: new Uint8Array(signInResult.account.publicKey),
      ...signInResult.account,
    },
    signature: new Uint8Array(signInResult.signature),
    signedMessage: new Uint8Array(signInResult.signedMessage),
  };
  
  return verifySignIn(signInPayload, serializedOutput);
}

// Step 2: Check for Seeker Genesis Token
async function checkSeekerGenesisToken(
  walletAddress: string,
  heliusApiKey: string
): Promise {
  const response = await fetch(
    `https://api.helius.xyz/v0/addresses/${walletAddress}/balances?api-key=${heliusApiKey}`
  );
  
  const data = await response.json();
  
  // Check for Seeker Genesis Token
  // SGT Collection: https://solscan.io/collection/...
  const hasSGT = data.tokens?.some(
    (token) => token.mint === 'SEEKER_GENESIS_TOKEN_MINT'
  );
  
  return hasSGT;
}

// Step 3: Combined verification
async function verifySeekerUser(signInResult, heliusApiKey): Promise {
  // Verify SIWS signature
  const siwsVerified = await verifySIWS(
    signInResult.payload,
    signInResult.result
  );
  
  if (!siwsVerified) {
    return false;
  }
  
  // Check SGT ownership
  const hasSGT = await checkSeekerGenesisToken(
    signInResult.walletAddress,
    heliusApiKey
  );
  
  return hasSGT;
}
```

### 7. SeedVault Integration

```typescript
// SeedVault is automatically used by MWA-compatible wallets
// No additional code needed - keys are stored securely

// To leverage SeedVault features:
async function requestBiometricAuth() {
  // Wallet apps handle biometric auth automatically
  // when accessing SeedVault keys
  
  const result = await transact(async (wallet) => {
    // This will trigger biometric prompt if enabled
    const authResult = await wallet.authorize({
      cluster: 'solana:mainnet',
      identity: APP_IDENTITY,
    });
    
    return authResult;
  });
  
  return result;
}
```

### 8. Reauthorization (Persistent Sessions)

```typescript
// Store auth token securely
import AsyncStorage from '@react-native-async-storage/async-storage';

async function saveAuthToken(authToken: string) {
  await AsyncStorage.setItem('mwa_auth_token', authToken);
}

async function getAuthToken(): Promise {
  return await AsyncStorage.getItem('mwa_auth_token');
}

// Reauthorize with stored token
async function reauthorize() {
  const authToken = await getAuthToken();
  
  if (!authToken) {
    return authorizeWallet(); // First time auth
  }
  
  try {
    const result = await transact(async (wallet) => {
      const authResult = await wallet.authorize({
        cluster: 'solana:mainnet',
        identity: APP_IDENTITY,
        auth_token: authToken, // Reuse token
      });
      
      // Save new token if updated
      await saveAuthToken(authResult.auth_token);
      
      return authResult;
    });
    
    return result;
  } catch (error) {
    // Token expired, request new auth
    await AsyncStorage.removeItem('mwa_auth_token');
    return authorizeWallet();
  }
}
```

---

## Best Practices

### Security

1. **Never Request Private Keys**
   - Always use MWA signing methods
   - Never ask users for seed phrases
   - Trust wallet apps for key management

2. **Verify Signatures**
   - Always verify SIWS signatures on backend
   - Use on-chain verification for critical features
   - Don't trust client-side checks alone

3. **Secure Token Storage**
   - Use AsyncStorage for auth tokens
   - Encrypt sensitive data
   - Clear tokens on logout

### User Experience

1. **Handle Wallet Not Installed**
   ```typescript
   try {
     await transact(async (wallet) => {
       // ... wallet operations
     });
   } catch (error) {
     if (error.message.includes('No wallet found')) {
       // Show wallet installation prompt
       showInstallWalletDialog();
     }
   }
   ```

2. **Loading States**
   ```typescript
   const [isConnecting, setIsConnecting] = useState(false);
   
   async function connect() {
     setIsConnecting(true);
     try {
       await authorizeWallet();
     } finally {
       setIsConnecting(false);
     }
   }
   ```

3. **Error Handling**
   ```typescript
   try {
     await signAndSendTransaction(tx);
   } catch (error) {
     if (error.message.includes('User rejected')) {
       showToast('Transaction cancelled');
     } else if (error.message.includes('Insufficient funds')) {
       showToast('Insufficient SOL balance');
     } else {
       showToast('Transaction failed');
     }
   }
   ```

### Performance

1. **Reuse Connections**
   - Store auth tokens
   - Reauthorize instead of fresh auth
   - Use wallet_uri_base for faster connections

2. **Batch Transactions**
   ```typescript
   await wallet.signAndSendTransactions({
     transactions: [tx1, tx2, tx3], // Batch multiple
   });
   ```

3. **Optimize for Seeker**
   ```typescript
   if (isSeekerDevice()) {
     // Use optimized settings for Seeker
     connection.commitment = 'confirmed'; // Faster
   }
   ```

---

## Common Patterns

### Pattern 1: Connect Button

```typescript
function ConnectWalletButton() {
  const [wallet, setWallet] = useState(null);
  const [loading, setLoading] = useState(false);
  
  async function handleConnect() {
    setLoading(true);
    try {
      const result = await reauthorize();
      setWallet(result.accounts[0]);
    } catch (error) {
      console.error('Connection failed:', error);
    } finally {
      setLoading(false);
    }
  }
  
  if (wallet) {
    return (
      
        Connected: {wallet.address.slice(0, 8)}...
      
    );
  }
  
  return (
    
  );
}
```

### Pattern 2: Seeker-Specific UI

```typescript
function SeekerBanner() {
  const isSeeker = isSeekerDevice();
  const [hasGenesisToken, setHasGenesisToken] = useState(false);
  
  useEffect(() => {
    if (isSeeker) {
      verifyGenesisToken().then(setHasGenesisToken);
    }
  }, [isSeeker]);
  
  if (!isSeeker) return null;
  
  return (
    
      🎉 Seeker Device Detected!
      {hasGenesisToken && (
        ✅ Genesis Token Verified
      )}
    
  );
}
```

### Pattern 3: Transaction with Confirmation

```typescript
async function sendTransactionWithConfirmation(transaction: Transaction) {
  // Sign and send
  const signature = await signAndSendTransaction(transaction);
  
  // Wait for confirmation
  const confirmation = await connection.confirmTransaction(
    signature,
    'confirmed'
  );
  
  if (confirmation.value.err) {
    throw new Error('Transaction failed');
  }
  
  return signature;
}
```

---

## Publishing to dApp Store

### 1. Build APK

```bash
# For Expo
eas build --platform android --profile production

# For React Native
cd android
./gradlew assembleRelease
```

### 2. Sign APK

```bash
# Generate keystore
keytool -genkey -v -keystore my-release-key.keystore \
  -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000

# Sign APK
jarsigner -verbose -sigalg SHA256withRSA -digestalg SHA-256 \
  -keystore my-release-key.keystore \
  app-release-unsigned.apk my-key-alias
```

### 3. Submit to dApp Store

```bash
# Install publishing CLI
npm install -g @solana-mobile/dapp-store-cli

# Login
dapp-store login

# Create app NFT (first time only)
dapp-store create

# Submit release
dapp-store publish \
  --apk ./app-release.apk \
  --requestor-is-authorized \
  --complies-with-solana-dapp-store-policies
```

---

## Troubleshooting

### Issue: Wallet Not Connecting

**Solutions:**
1. Check if wallet app is installed
2. Verify network (devnet/mainnet)
3. Clear app cache
4. Reinstall wallet app

### Issue: Transaction Fails

**Solutions:**
1. Check SOL balance for fees
2. Verify recent blockhash
3. Check transaction size
4. Ensure correct cluster

### Issue: Seeker Not Detected

**Solutions:**
1. Verify Platform.constants.Model
2. Check device fingerprint
3. Use Genesis Token verification
4. Test on actual Seeker device

### Issue: Auth Token Expired

**Solutions:**
1. Clear stored token
2. Request fresh authorization
3. Implement token refresh logic
4. Handle ERROR_AUTHORIZATION_FAILED

---

## Resources

### Documentation
- [Solana Mobile Docs](https://docs.solanamobile.com)
- [MWA Specification](https://solana-mobile.github.io/mobile-wallet-adapter/spec/spec.html)
- [React Native Guide](https://docs.solanamobile.com/get-started/react-native/quickstart)
- [dApp Store Guide](https://docs.solanamobile.com/dapp-store/intro)

### Tools
- [MWA Protocol](https://github.com/solana-mobile/mobile-wallet-adapter)
- [Solana Mobile SDK](https://github.com/solana-mobile/solana-mobile-stack-sdk)
- [dApp Store CLI](https://www.npmjs.com/package/@solana-mobile/dapp-store-cli)

### Example Apps
- [Solana Mobile Sample Apps](https://github.com/solana-mobile/solana-mobile-stack-sdk/tree/main/samples)
- [Anchor Counter dApp](https://github.com/solana-mobile/tutorial-apps/tree/main/AnchorCounterDapp)

---

## Integration with Obscura DEX

### Mobile-Specific Features

1. **Seeker Rewards**
   - Detect Seeker users
   - Offer reduced trading fees
   - Exclusive features for SGT holders

2. **Mobile-Optimized UI**
   - Touch-friendly controls
   - Simplified trading interface
   - Biometric authentication

3. **Push Notificati

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [agentic-reserve](https://github.com/agentic-reserve)
- **Source:** [agentic-reserve/AGENT_SKILL](https://github.com/agentic-reserve/AGENT_SKILL)
- **License:** Apache-2.0

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-agentic-reserve-agent-skill-solana-mobile
- Seller: https://agentstack.voostack.com/s/agentic-reserve
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
