- Message → O que o usuário queria fazer (sua proposta assinada)
- Meta → O que realmente aconteceu (o resultado da execução)
<Buffer 00 bf a0 e8...> em vez de endereços e assinaturas legíveis.
Este guia mostra como: Decodificar esses dados binários em formato legível, extrair informações significativas e entender toda a história da transação desde a proposta até a execução.
Uma transmissão ao vivo, sem decodificação
Execute o cliente mínimo abaixo. As flags de filtro descartam votos e transações falhas, e o arrayaccountInclude limita os resultados a atividades que tocam o ID do programa Jupiter.
filters, createdAt mais um branch transaction que oculta duas crianças:
transaction.transaction.transaction→ a mensagem assinadatransaction.transaction.meta→ o meta da execução
Uint8Array permanece opaco por enquanto.
Quando você executa o script com a função de decodificação, verá a estrutura aninhada real com endereços legíveis:
Decodificando os dados binários
Por que decodificar? Dados brutos do Laserstream contêm assinaturas, chaves de conta e hashes como objetos bináriosUint8Array que são ilegíveis. Você precisa convertê-los para strings base58 para entender a transação.
A solução: O Laserstream usa Yellowstone gRPC, que fornece utilitários de decodificação integrados. Em vez de escrever decodificadores separados para cada tipo de campo, usamos uma função recursiva que converte todos os dados binários em formato legível.
Entendendo a estrutura da transação
Agora que podemos ver os dados decodificados, vamos explorar as duas partes principais de cada atualização de transação do Laserstream. Lembre-se do nosso exemplo inicial de que cada transação contém dois objetos chave:- Message (Proposta) →
transaction.transaction.transaction→ a mensagem assinada (proposta do usuário) - Meta (Execução) →
transaction.transaction.meta→ os metadados da execução (resposta do validador)
A proposta: tudo dentro da mensagem
O usuário cria uma mensagem que especifica o que, quem e até quando. Veja como decodificar cada parte:Cabeçalho da Transação
numRequiredSignatures diz ao validador quantas assinaturas verificar, enquanto os dois valores numReadonly* rotulam contas que o runtime pode tratar como somente leitura, permitindo execução paralela.
Dicionário de Chaves de Conta
accountKeys é uma lista simples de chaves públicas que atua como uma tabela de consulta. Cada inteiro posterior na transação - programIdIndex, cada elemento em um array accounts de uma instrução - aponta de volta para esta lista por índice, salvando mais de um quilobyte por mensagem.
Proteção Contra Repetição
recentBlockhash expira uma vez que sai dos últimos 150 hashes de bloco, aproximadamente noventa segundos no mainnet.
Instruções: Os Comandos Reais
- ID do Programa (
programIdIndex): Aponta para um endereço no arrayaccountKeys(por exemplo, índice 10 =ComputeBudget111111111111111111111111111111) - Contas (
accounts): Uma string codificada em base58 representando quais índices de conta essa instrução toca - Dados (
data): Os dados reais da instrução codificados como base58
convertBuffers, contas aparecem como base58, mas na verdade contêm índices de conta (por exemplo, "3vtmrQMafzDoG2CBz1iqgXPTnC" decodifica para índices [21, 19, 12, 17, 2, 6, 1, 22])
Este design significa que em vez de repetir endereços de 32 bytes completos, cada instrução apenas referencia posições na tabela de consulta.
Assinaturas: Prova de Autorização
signatures contém as assinaturas criptográficas provando que as contas necessárias autorizaram esta transação. O número de assinaturas deve coincidir com header.numRequiredSignatures.
Consultas de Tabela de Endereços
versioned é true, addressTableLookups aparece com uma tabela em cadeia e duas listas de índices. Tabelas de consulta elevam a limitação no número de endereços para dezenas, mantendo o pacote abaixo do MTU de 1.232 bytes.
Transação v1: Orçamento de Cálculo no Cabeçalho
A Transação v1 (SIMD-0385, Agave 4.2) adiciona mais um campo à mensagem:transactionConfig.
instructions de uma transação v1 nunca contém uma entrada ComputeBudget111111111111111111111111111111. priorityFee é a taxa total em lamports para toda a transação, não micro-lamports por unidade de cálculo. Um campo null significa que o remetente não o definiu. Mensagens legadas e v0 não possuem transactionConfig, então sua presença identifica uma transação v1.
Duas coisas para verificar em seu decodificador:
- Extração de taxa de prioridade. Leia
transactionConfig.priorityFeequando existir, e recorra à análise das instruções do ComputeBudget apenas para transações legadas e v0. Código que apenas analisa instruções lê cada transação v1 como pagando taxa de prioridade zero. - Versão Proto.
yellowstone-grpc-proto12.6.0 é a primeira versão que contém os campos v1, ehelius-laserstream0.8.4 (JavaScript), 0.6.3 (Rust) e 0.2.0 (Go) são as primeiras versões do SDK construídas sobre ela. Versões mais antigas descartamtransactionConfigsilenciosamente.
Como Tudo se Conecta: O Fluxo
Veja o que acontece a partir dos primeiros princípios:- Construa a tabela de consulta:
accountKeyslista todos os endereços que esta transação tocará - Defina as regras:
headerespecifica quantas assinaturas são necessárias e quais contas são somente leitura - Crie os comandos: Cada
instructionaponta para:- Um programa (via
programIdIndex→accountKeys[index]) - As contas de que precisa (via
accounts→ múltiplas posiçõesaccountKeys[index]) - Os dados da instrução (codificados em
data)
- Um programa (via
- Adicione autorização:
signaturesprova que as contas requeridas aprovaram esta transação - Defina a expiração:
recentBlockhashgarante que esta transação não poderá ser reproduzida posteriormente
A execução: tudo dentro de meta
Enquanto a mensagem mostra o que o usuário queria fazer, o meta mostra o que realmente aconteceu quando os validadores executaram a transação.Informações básicas de execução
Sucesso/Fracassoerr: null= sucessoerr: {...}= falha com detalhes do errofee= lamports cobrados por esta transação
accountKeys por índice:
- Conta 0: Perdeu 15000 lamports (pagamento de taxa)
- Conta 1: Ganhou 1461600 lamports (nova conta criada)
- Conta 3: Ganhou 2001231920 lamports (conta de programa)
Detalhes avançados de execução
Instruções InternasPadrões práticos de decodificação
Aqui estão padrões comuns para extrair informações úteis de transações decodificadas:Exemplo completo: decodificador de troca Jupiter
Aqui está um exemplo completo que decodifica transações de troca Jupiter e extrai informações significativas:Principais pontos
- Estrutura de duas partes: Cada transação tem uma mensagem (o que foi solicitado) e meta (o que realmente aconteceu)
- Decodificação binária: Use
bs58.encode()para converter campos binários em strings base58 legíveis - Consultas de chave de conta: Instruções referenciam contas por índice no array
accountKeys - Acompanhamento de saldos: Compare
preBalancesepostBalancespara ver o que mudou - Transação v1: Leia o orçamento de cálculo e a taxa de prioridade de
transactionConfigquando presente; transações v1 não têm instruções de ComputeBudget