Mobile
Desenvolvimento Mobile Solana: Tutorial React Native e MWA

Desenvolvimento Mobile Solana: Tutorial React Native e MWA

Mobile Wallet Adapter

Mobile Wallet Adapter

Se você já construiu dApps Solana com wallet-adapter, conhece o procedimento: o usuário clica em Conectar, a extensão do navegador aparece, o usuário aprova. Simples. Mas tente isso em um celular e você descobrirá que tudo o que você sabe sobre conexões de carteira está errado.

Não existem extensões de navegador no mobile. Usuários não navegam dentro de navegadores dApp das carteiras. O modelo familiar de popup não se traduz para apps nativos. O Mobile Wallet Adapter existe porque o modelo web fundamentalmente não funciona em celulares.

O MWA não é uma versão mobile do wallet-adapter. É uma arquitetura inteiramente diferente onde seu app se comunica diretamente com apps de carteira através de sessões seguras e efêmeras.

Por que o Mobile é Diferente

Na web, extensões de carteira se injetam no contexto JavaScript do navegador. Seu dApp as descobre, solicita uma conexão, e a extensão cuida da assinatura. A carteira vive dentro do mesmo processo do navegador que seu dApp.

Sistemas operacionais mobile não funcionam assim. iOS e Android isolam apps uns dos outros por segurança. Seu dApp não pode acessar a memória de outro app, chamar suas funções ou compartilhar um contexto JavaScript. Cada app é uma fortaleza.

Esse isolamento cria um problema fundamental: como seu dApp pede a um app de carteira para assinar algo quando eles não podem se comunicar diretamente?

A resposta é o Mobile Wallet Adapter, um protocolo que estabelece canais de comunicação criptografados entre apps usando o sistema de mensagens inter-app do sistema operacional, combinado com conexões WebSocket locais.

Vantagens principais

  • UX Nativa: Usuários permanecem em seus apps de carteira familiares em vez de experiências de navegador embarcadas

  • Segurança Aprimorada: Chaves privadas nunca saem do app da carteira, nem temporariamente

  • Compatibilidade Universal: Uma implementação funciona com qualquer carteira compatível com MWA (Phantom, Solflare, e outras)

O Modelo de Sessão

O wallet-adapter web mantém uma conexão persistente. Você conecta uma vez, depois assina transações quando necessário durante a sessão. A carteira lembra que você está conectado.

O MWA funciona de forma diferente. Cada interação é uma sessão atômica que abre, realiza operações e fecha. Pense nisso como fazer uma ligação telefônica versus ter uma conexão de chat sempre ativa.

Fluxo do wallet-adapter web:

text
Connect → [persistent connection] → Sign → Sign → Sign → Disconnect

Fluxo do Mobile Wallet Adapter:

text
Open Session → Authorize → Sign (uma ou mais) → Close Session
Open Session → Authorize → Sign (uma ou mais) → Close Session
...repetir para cada interação

Toda vez que seu app precisa da carteira, ele abre uma nova sessão. Dentro dessa sessão, você pode autorizar (ou re-autorizar com um token em cache) e solicitar múltiplas assinaturas. Quando a sessão fecha, a carteira pode retornar ao segundo plano.

Isso pode parecer ineficiente, mas na verdade é elegante:

  1. Sem conexões obsoletas: Você nunca precisa lidar com "carteira desconectou inesperadamente"

  2. Intenção clara do usuário: Cada sessão é uma ação explícita do usuário

  3. Eficiente em bateria: Sem WebSocket persistente consumindo energia

A Função transact

Todo o SDK do MWA gira em torno de uma função: transact(). Tudo acontece dentro de seu callback.

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

await transact(async (wallet: Web3MobileWallet) => {
  // Sessão agora está ABERTA
  // App da carteira está em primeiro plano
  // Usuário pode ver as solicitações do seu dApp
  
  const { accounts } = await wallet.authorize({
    identity: APP_IDENTITY,
    chain: 'solana:devnet',
  });
  
  // Você agora tem a chave pública do usuário
  // Solicitar assinaturas, enviar transações, etc.
  
}); // Sessão FECHA quando o callback completa

Quando você chama transact():

  1. Seu app gera um keypair efêmero e cria uma URI de associação

  2. O SO inicia o app da carteira via essa URI

  3. A carteira inicia um servidor WebSocket local

  4. Seu app conecta e realiza um handshake criptografado

  5. Seu callback executa com acesso total à carteira

  6. Quando seu callback retorna (ou lança erro), a sessão termina

O app da carteira vem para o primeiro plano durante este processo. O usuário vê a identidade do seu app e pode aprovar ou rejeitar solicitações. Quando termina, retornam ao seu app.

Autorização vs Conexão

Na web, "conectar" uma carteira significa que a carteira concorda em compartilhar sua chave pública com seu dApp. Assinar é uma operação separada.

O MWA combina esses conceitos de forma diferente. O método authorize tanto estabelece confiança QUANTO recupera contas:

typescript
const authResult = await wallet.authorize({
  identity: {
    name: 'Meu dApp Solana',
    uri: 'https://mydapp.com',
    icon: 'favicon.ico',
  },
  chain: 'solana:devnet',
});

// authResult contém:
// - accounts: endereços da carteira do usuário
// - auth_token: salve isso para re-autorização silenciosa
// - wallet_uri_base: para conexões diretas futuras

O objeto identity é crucial. Carteiras exibem esta informação aos usuários para que saibam qual app está solicitando acesso. No Android, carteiras podem verificar criptograficamente que a solicitação veio realmente do app que reivindica essa identidade, não de um impostor malicioso.

Re-autorização silenciosa

Ninguém quer aprovar conexões de carteira repetidamente. O MWA resolve isso com auth tokens:

typescript
// Primeira vez: usuário vê diálogo de aprovação
const result = await wallet.authorize({
  identity: APP_IDENTITY,
  chain: 'solana:devnet',
});

// Salvar o token
await AsyncStorage.setItem('auth_token', result.auth_token);

// Sessões posteriores: incluir o token
const cachedToken = await AsyncStorage.getItem('auth_token');

await transact(async (wallet) => {
  const result = await wallet.authorize({
    identity: APP_IDENTITY,
    chain: 'solana:devnet',
    auth_token: cachedToken, // Pular aprovação se válido
  });
  // Se o token for válido, nenhum prompt do usuário é necessário
});

Auth tokens são strings opacas; seu formato é específico da carteira. Seu app apenas armazena e os passa. Se um token expirar ou se tornar inválido, a carteira solicitará uma nova autorização.

Assinando Transações

Uma vez autorizado dentro de uma sessão, você pode solicitar assinaturas. O MWA fornece duas abordagens:

signAndSendTransactions (Recomendado)

A carteira assina E transmite a transação. Este é o método preferido porque:

  • A carteira cuida da seleção do endpoint RPC

  • Melhor lógica de retry

  • Menos round-trips de rede do seu app

typescript
await transact(async (wallet) => {
  const { accounts } = await wallet.authorize({
    identity: APP_IDENTITY,
    chain: 'solana:devnet',
  });
  
  const fromPubkey = new PublicKey(toByteArray(accounts[0].address));
  
  // Construir sua transação
  const tx = new VersionedTransaction(/* ... */);
  
  // Carteira assina e envia para a rede
  const signatures = await wallet.signAndSendTransactions({
    transactions: [tx],
  });
  
  console.log('Assinatura da transação:', signatures[0]);
});

signTransactions

Se você precisa da transação assinada de volta (para simulação, envio personalizado ou assinatura multi-parte), use este método:

typescript
const signedTxs = await wallet.signTransactions({
  transactions: [tx1, tx2],
});

// signedTxs estão assinadas mas NÃO enviadas
// Seu app deve enviá-las para a rede
await connection.sendTransaction(signedTxs[0]);

O que Esperar

Este curso ensina você a construir dApps React Native prontos para produção com Mobile Wallet Adapter. Ao final, você terá:

  1. Um entendimento completo do protocolo MWA e ciclo de vida de sessão

  2. Um projeto React Native funcionando com polyfills e dependências adequadas

  3. Um AuthorizationProvider para gerenciar estado da carteira em todo seu app

  4. Padrões de tratamento de erros para cada modo de falha

  5. Um app capstone que envia tokens entre carteiras

Pré-requisitos

  • Conhecimento básico de React e TypeScript

  • Familiaridade com conceitos Solana (transações, contas, chaves públicas)

  • Experiência com @solana/web3.js é útil mas não obrigatória

  • Um dispositivo Android com uma carteira Solana instalada (Phantom ou Solflare recomendados)

Nota: Embora emuladores funcionem para desenvolvimento básico de UI, testar MWA requer um dispositivo real com um app de carteira instalado.

Estrutura do Curso

LiçãoTópico
1Introdução (você está aqui)
2Aprofundamento no Protocolo: Como o MWA realmente funciona
3Configuração de Ambiente: React Native com Solana
4Conectando a Carteiras: O padrão transact
5Assinando Transações: Construindo e enviando
6Assinando Mensagens: SIWS e provas off-chain
7AuthorizationProvider: Gerenciamento de estado
8Tratamento de Erros: Construindo dApps resilientes
9Teste em Dispositivo Real: Workflow de debug
10Capstone: App de envio de tokens

Vamos começar entendendo exatamente o que acontece quando seu app abre aquela conexão de carteira.

Blueshift © 2026Commit: 1b88646