Transações
Para interagir com a rede Solana, você deve enviar uma transação. Você pode pensar em uma transação como um envelope que contém vários formulários. Cada formulário é uma instrução que diz à rede o que fazer. Enviar a transação é como enviar o envelope pelo correio para que os formulários possam ser processados.
O exemplo abaixo mostra uma versão simplificada de duas transações. Quando a primeira transação é processada, ela executará uma única instrução. Quando a segunda transação é processada, ela executará três instruções em ordem sequencial: primeiro a instrução 1, seguida pela instrução 2, seguida pela instrução 3.
As transações são atômicas: Se uma única instrução falhar, toda a transação falhará e nenhuma alteração ocorrerá.
Um diagrama simplificado mostrando duas transações
Uma
Transaction
consiste nas seguintes informações:
signatures: Um array de assinaturasmessage: Informações da transação, incluindo a lista de instruções a serem processadas
pub struct Transaction {#[wasm_bindgen(skip)]#[serde(with = "short_vec")]pub signatures: Vec<Signature>,#[wasm_bindgen(skip)]pub message: Message,}
Diagrama mostrando as duas partes de uma transação
As transações têm um limite total de tamanho de
1232
bytes. Este limite inclui tanto o array signatures quanto a
estrutura message.
Este limite vem do tamanho da Unidade Máxima de Transmissão (MTU) do IPv6 de 1280 bytes, menos 48 bytes para cabeçalhos de rede (40 bytes IPv6 + 8 bytes de cabeçalho).
Diagrama mostrando o formato da transação e limites de tamanho
Assinaturas
O array signatures da transação contém estruturas Signature. Cada
Signature
tem 64 bytes e é criada assinando o Message da transação com a chave privada
da conta. Uma assinatura deve ser fornecida para cada
conta signatária incluída em qualquer uma das instruções
da transação.
A primeira assinatura pertence à conta que pagará a taxa base da transação e é a assinatura da transação. A assinatura da transação pode ser usada para consultar os detalhes da transação na rede.
Mensagem
A message da transação é uma estrutura
Message
que contém as seguintes informações:
header: O cabeçalho da mensagemaccount_keys: Um array de endereços de contas exigidos pelas instruções da transaçãorecent_blockhash: Um blockhash que atua como um timestamp para a transaçãoinstructions: Um array de instruções
Para economizar espaço, a transação não armazena permissões para cada conta
individualmente. Em vez disso, as permissões das contas são determinadas
usando o header e o account_keys.
pub struct Message {/// The message header, identifying signed and read-only `account_keys`.pub header: MessageHeader,/// All the account keys used by this transaction.#[serde(with = "short_vec")]pub account_keys: Vec<Pubkey>,/// The id of a recent ledger entry.pub recent_blockhash: Hash,/// Programs that will be executed in sequence and committed in/// one atomic transaction if all succeed.#[serde(with = "short_vec")]pub instructions: Vec<CompiledInstruction>,}
Cabeçalho
O header da mensagem é uma estrutura
MessageHeader.
Ele contém as seguintes informações:
num_required_signatures: O número total de assinaturas exigidas pela transaçãonum_readonly_signed_accounts: O número total de contas somente leitura que exigem assinaturasnum_readonly_unsigned_accounts: O número total de contas somente leitura que não exigem assinaturas
pub struct MessageHeader {/// The number of signatures required for this message to be considered/// valid. The signers of those signatures must match the first/// `num_required_signatures` of [`Message::account_keys`].pub num_required_signatures: u8,/// The last `num_readonly_signed_accounts` of the signed keys are read-only/// accounts.pub num_readonly_signed_accounts: u8,/// The last `num_readonly_unsigned_accounts` of the unsigned keys are/// read-only accounts.pub num_readonly_unsigned_accounts: u8,}
Diagrama mostrando as três partes do cabeçalho da mensagem
Endereços de contas
O
account_keys
da mensagem é um array de endereços de contas, enviado no
formato de array compacto.
O prefixo do array indica seu comprimento. Cada item no array é uma chave
pública, apontando para uma conta usada por suas instruções. O array
accounts_keys deve ser completo e estritamente ordenado da seguinte forma:
- Assinante + Gravável
- Assinante + Somente leitura
- Não assinante + Gravável
- Não assinante + Somente leitura
A ordenação estrita permite que o array account_keys seja combinado com as
informações no header da mensagem para determinar as permissões
para cada conta.
Diagrama mostrando a ordem do array de endereços de contas
Blockhash recente
O recent_blockhash da mensagem é um valor hash que atua como um timestamp da
transação e impede transações duplicadas. Um blockhash expira após
150 blocos.
(Equivalente a um minuto—assumindo que cada bloco leva 400ms.) Após a expiração
do bloco, a transação expira e não pode ser processada.
O método RPC getLatestBlockhash permite
obter o blockhash atual e a altura do último bloco no qual o blockhash será
válido.
Instruções
O
instructions
da mensagem é um array de todas as instruções a serem processadas, enviadas no
formato de array compacto.
O prefixo do array indica seu comprimento. Cada item no array é uma estrutura
CompiledInstruction
e inclui as seguintes informações:
program_id_index: Um índice que aponta para um endereço no arrayaccount_keys. Este valor indica o endereço do programa que processa a instrução.accounts: Um array de índices que apontam para endereços no arrayaccount_keys. Cada índice aponta para o endereço de uma conta necessária para esta instrução.data: Um array de bytes especificando qual instrução invocar no programa. Também inclui quaisquer dados adicionais exigidos pela instrução. (Por exemplo, argumentos de função)
pub struct CompiledInstruction {/// Index into the transaction keys array indicating the program account that executes this instruction.pub program_id_index: u8,/// Ordered indices into the transaction keys array indicating which accounts to pass to the program.#[serde(with = "short_vec")]pub accounts: Vec<u8>,/// The program input data.#[serde(with = "short_vec")]pub data: Vec<u8>,}
Array compacto de Instruções
Exemplo de estrutura de transação
O exemplo a seguir mostra a estrutura de uma transação que contém uma única instrução de transferência de SOL.
import {createSolanaRpc,generateKeyPairSigner,lamports,createTransactionMessage,setTransactionMessageFeePayerSigner,setTransactionMessageLifetimeUsingBlockhash,appendTransactionMessageInstructions,pipe,signTransactionMessageWithSigners,getCompiledTransactionMessageDecoder} from "@solana/kit";import { getTransferSolInstruction } from "@solana-program/system";const rpc = createSolanaRpc("http://localhost:8899");const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();// Generate sender and recipient keypairsconst sender = await generateKeyPairSigner();const recipient = await generateKeyPairSigner();// Define the amount to transferconst LAMPORTS_PER_SOL = 1_000_000_000n;const transferAmount = lamports(LAMPORTS_PER_SOL / 100n); // 0.01 SOL// Create a transfer instruction for transferring SOL from sender to recipientconst transferInstruction = getTransferSolInstruction({source: sender,destination: recipient.address,amount: transferAmount});// Create transaction messageconst transactionMessage = pipe(createTransactionMessage({ version: 0 }),(tx) => setTransactionMessageFeePayerSigner(sender, tx),(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),(tx) => appendTransactionMessageInstructions([transferInstruction], tx));const signedTransaction =await signTransactionMessageWithSigners(transactionMessage);// Decode the messageBytesconst compiledTransactionMessage =getCompiledTransactionMessageDecoder().decode(signedTransaction.messageBytes);console.log(JSON.stringify(compiledTransactionMessage, null, 2));
O código abaixo mostra a saída dos snippets de código anteriores. O formato difere entre SDKs, mas observe que cada instrução contém as mesmas informações necessárias.
{"version": 0,"header": {"numSignerAccounts": 1,"numReadonlySignerAccounts": 0,"numReadonlyNonSignerAccounts": 1},"staticAccounts": ["HoCy8p5xxDDYTYWEbQZasEjVNM5rxvidx8AfyqA4ywBa","5T388jBjovy7d8mQ3emHxMDTbUF8b7nWvAnSiP3EAdFL","11111111111111111111111111111111"],"lifetimeToken": "EGCWPUEXhqHJWYBfDirq3mHZb4qDpATmYqBZMBy9TBC1","instructions": [{"programAddressIndex": 2,"accountIndices": [0, 1],"data": {"0": 2,"1": 0,"2": 0,"3": 0,"4": 128,"5": 150,"6": 152,"7": 0,"8": 0,"9": 0,"10": 0,"11": 0}}]}
Depois que uma transação é enviada, você pode recuperar seus detalhes usando a assinatura da transação e o método RPC getTransaction. A resposta terá uma estrutura semelhante ao trecho a seguir.
Você também pode encontrar a transação usando o Solana Explorer.
{"blockTime": 1745196488,"meta": {"computeUnitsConsumed": 150,"err": null,"fee": 5000,"innerInstructions": [],"loadedAddresses": {"readonly": [],"writable": []},"logMessages": ["Program 11111111111111111111111111111111 invoke [1]","Program 11111111111111111111111111111111 success"],"postBalances": [989995000, 10000000, 1],"postTokenBalances": [],"preBalances": [1000000000, 0, 1],"preTokenBalances": [],"rewards": [],"status": {"Ok": null}},"slot": 13049,"transaction": {"message": {"header": {"numReadonlySignedAccounts": 0,"numReadonlyUnsignedAccounts": 1,"numRequiredSignatures": 1},"accountKeys": ["8PLdpLxkuv9Nt8w3XcGXvNa663LXDjSrSNon4EK7QSjQ","7GLg7bqgLBv1HVWXKgWAm6YoPf1LoWnyWGABbgk487Ma","11111111111111111111111111111111"],"recentBlockhash": "7ZCxc2SDhzV2bYgEQqdxTpweYJkpwshVSDtXuY7uPtjf","instructions": [{"accounts": [0, 1],"data": "3Bxs4NN8M2Yn4TLb","programIdIndex": 2,"stackHeight": null}],"indexToProgramIds": {}},"signatures": ["3jUKrQp1UGq5ih6FTDUUt2kkqUfoG2o4kY5T1DoVHK2tXXDLdxJSXzuJGY4JPoRivgbi45U2bc7LZfMa6C4R3szX"]},"version": "legacy"}
Is this page helpful?