Referência de Métodos JSON-RPC
Uma vez estabelecida uma sessão segura, o dApp se comunica com a carteira usando JSON-RPC 2.0 sobre o canal criptografado. Esta lição documenta cada método, seus parâmetros e formatos de resposta.
Categorias de Métodos
O MWA define duas categorias de métodos:
Métodos Não Privilegiados: Podem ser chamados a qualquer momento após o estabelecimento de sessão.
authorizedeauthorizeget_capabilities
Métodos Privilegiados: Requerem chamada authorize prévia com sucesso.
sign_and_send_transactionssign_messagesclone_authorization
authorize
Solicita autorização do usuário para o dApp.
Solicitação
{
"jsonrpc": "2.0",
"id": "1",
"method": "authorize",
"params": {
"identity": {
"uri": "https://myapp.com",
"icon": "favicon.ico",
"name": "Meu dApp"
},
"cluster": "mainnet-beta",
"auth_token": "previo...cao",
"features": ["sign_and_send_transactions:2", "sign_messages"],
"addresses": ["base64_encoded_addresses"]
}
}Parâmetros
Resposta (Sucesso)
{
"jsonrpc": "2.0",
"id": "1",
"result": {
"accounts": [
{
"address": "base64_encoded_pubkey",
"display_address": "7xKXt...",
"display_address_format": "base58",
"label": "Carteira Principal",
"icon": "data:image/png;base64,...",
"chains": ["solana:mainnet"],
"features": ["solana:signAndSendTransaction"]
}
],
"auth_token": "novo_ou...token",
"wallet_uri_base": "https://phantom.app/ul/v1/",
"sign_in_result": { /* se sign-in foi solicitado */ }
}
}Campos da Resposta
Fluxo de Reautorização
Se auth_token for fornecido e ainda válido, a carteira pode pular interação do usuário:
dApp Carteira
│ │
│ authorize(auth_token="abc123") │
│──────────────────────────────────────►│
│ │ Token válido?
│ │ Sim → sucesso silencioso
│◄──────────────────────────────────────│
│ result: { accounts, auth_token } │Se o token for inválido ou expirado:
│ authorize(auth_token="expirado") │
│──────────────────────────────────────►│
│ │ Token inválido
│ │ Mostrar UI de autorização
│ │ Usuário aprova
│◄──────────────────────────────────────│
│ result: { accounts, new_auth_token } │deauthorize
Invalida uma autorização prévia.
Solicitação
{
"jsonrpc": "2.0",
"id": "2",
"method": "deauthorize",
"params": {
"auth_token": "token_...data"
}
}Parâmetros
Resposta (Sucesso)
{
"jsonrpc": "2.0",
"id": "2",
"result": {}
}Casos de Uso
Logout do usuário: Quando o usuário explicitamente desconecta sua carteira
Segurança: Após detectar atividade suspeita
Rotação de token: Antes de solicitar autorização fresca
get_capabilities
Consulta as features suportadas pela carteira.
Solicitação
{
"jsonrpc": "2.0",
"id": "3",
"method": "get_capabilities"
}Sem parâmetros necessários.
Resposta
{
"jsonrpc": "2.0",
"id": "3",
"result": {
"supports_clone_authorization": true,
"supports_sign_and_send_transactions": true,
"max_transactions_per_request": 10,
"max_messages_per_request": 10,
"supported_transaction_versions": ["legacy", 0]
}
}Campos da Resposta
Por Que Verificar Capacidades?
Carteiras diferentes têm limites e features diferentes. Verifique capacidades antes de:
Enviar lotes grandes de transações
Usar transações versionadas
Assumir suporte a
clone_authorization
sign_and_send_transactions
Assina transações e as transmite para a rede.
Solicitação
{
"jsonrpc": "2.0",
"id": "4",
"method": "sign_and_send_transactions",
"params": {
"payloads": [
"base64_encoded_transaction_1",
"base64_encoded_transaction_2"
],
"options": {
"min_context_slot": 150000000,
"commitment": "confirmed",
"skip_preflight": false,
"max_retries": 3
}
}
}Parâmetros
Formato do Payload de Transação
Cada payload é uma transação Solana, serializada de acordo com sua versão:
Transações legacy: Serialização padrão
Transações versionadas (v0): Incluem prefixo de versão e tabelas de lookup de endereço
A transação deve:
Ter
recentBlockhashdefinido (ounullpara a carteira preencher)Deixar a assinatura do fee payer vazia (a carteira preenche)
Incluir todas as outras assinaturas necessárias
Resposta (Sucesso)
{
"jsonrpc": "2.0",
"id": "4",
"result": {
"signatures": [
"base64_encoded_signature_1",
"base64_encoded_signature_2"
]
}
}Resposta (Falha Parcial)
{
"jsonrpc": "2.0",
"id": "4",
"error": {
"code": -3,
"message": "Algumas transações não foram assinadas",
"data": {
"valid": [0],
"invalid": [1]
}
}
}Códigos de erro para este método:
-1: Autorização falhou-2: Payloads inválidos (transações malformadas)-3: Nem todas transações assinadas (usuário recusou algumas)-4: Não enviado (transmissão falhou)-6: Payloads demais (excedemax_transactions_per_request)
sign_messages
Assina mensagens arbitrárias (não transações).
Solicitação
{
"jsonrpc": "2.0",
"id": "5",
"method": "sign_messages",
"params": {
"payloads": [
"base64_encoded_message"
],
"addresses": [
"base64_encoded_pubkey"
]
}
}Parâmetros
Resposta (Sucesso)
{
"jsonrpc": "2.0",
"id": "5",
"result": {
"signed_payloads": [
"base64_encoded_signed_message"
]
}
}Formato de Assinatura de Mensagem
Mensagens são assinadas como estão (bytes brutos). Para mensagens legíveis, codifique como UTF-8 primeiro.
Padrões comuns:
Autenticação: Assinar um nonce para provar propriedade da carteira
Dados off-chain: Assinar dados estruturados para protocolos como Sign-In With Solana
clone_authorization
Cria uma nova autorização a partir de uma existente.
Solicitação
{
"jsonrpc": "2.0",
"id": "6",
"method": "clone_authorization",
"params": {}
}Sem parâmetros (usa a autorização da sessão atual).
Resposta (Sucesso)
{
"jsonrpc": "2.0",
"id": "6",
"result": {
"auth_token": "***"
}
}Casos de Uso
Apps multi-sessão: Clonar autorização para usar em serviços em segundo plano
Refresh de token: Obter um novo token enquanto a sessão atual ainda é válida
Este método pode não ser suportado por todas as carteiras (verifique get_capabilities).
Formato de Resposta de Erro
Todos os métodos retornam erros no formato JSON-RPC:
{
"jsonrpc": "2.0",
"id": "1",
"error": {
"code": -1,
"message": "Mensagem de erro legível",
"data": { /* dados adicionais opcionais */ }
}
}Códigos de Erro Padrão
Códigos de Erro Específicos do MWA
Strings de Feature
Strings de feature usam um formato namespacificado para identificar capacidades e versões:
Ao chamar authorize, especifique as features necessárias:
{
"method": "authorize",
"params": {
"features": ["solana:signAndSendTransaction:2", "solana:signMessages"]
}
}A carteira retornará erro se não puder suportar as features solicitadas.
Identificadores de Chain
Respostas de contas incluem identificadores de chain no formato CAIP-2:
Fluxo de Solicitação/Resposta
Uma sessão completa com múltiplas operações:
dApp Carteira
│ │
│ ──── HELLO_REQ ─────────────────────────► │
│ ◄─── HELLO_RSP ───────────────────────── │
│ │
│ ──── authorize ──────────────────────────► │
│ │ [Usuário aprova]
│ ◄─── result: accounts, auth_token ─────── │
│ │
│ ──── sign_and_send_transactions ─────────► │
│ │ [Usuário revisa]
│ ◄─── result: signatures ───────────────── │
│ │
│ ──── deauthorize ────────────────────────► │
│ ◄─── result: {} ──────────────────────── │
│ │
│ ──── [WebSocket close] ──────────────────► │Melhores Práticas
1. Sempre Verifique Autorização
Antes de métodos privilegiados:
if (!authToken) {
const authResult = await wallet.authorize(identity);
authToken = authResult.auth_token;
}2. Lidar com Assinatura Parcial
Verifique o código de erro -3 que indica assinatura parcial:
try {
const result = await wallet.signAndSendTransactions(payloads);
} catch (error) {
if (error.code === -3 && error.data) {
console.log('Assinadas:', error.data.valid);
console.log('Recusadas:', error.data.invalid);
}
}3. Respeitar Limites da Carteira
Consulte capacidades e agrupe adequadamente:
const caps = await wallet.getCapabilities();
const batchSize = caps.max_transactions_per_request || 1;
for (let i = 0; i < transactions.length; i += batchSize) {
const batch = transactions.slice(i, i + batchSize);
await wallet.signAndSendTransactions(batch);
}4. Usar Reautorização
Armazene e reutilize auth_token:
// Ao iniciar o app
const savedToken = await AsyncStorage.getItem('auth_token');
// Em transact()
const result = await wallet.authorize({
identity,
auth_token: savedToken
});
// Salvar para próxima vez
await AsyncStorage.setItem('auth_token', result.auth_token);5. Validar Respostas
Verifique a estrutura da resposta antes de acessar campos:
if (result.accounts && result.accounts.length > 0) {
const address = result.accounts[0].address;
// Usar address...
}Na próxima lição, examinamos verificação de identidade: como carteiras confirmam que o dApp é quem diz ser.