Instruções
Instruções são o bloco fundamental para interagir com a blockchain Solana. Uma instrução é essencialmente uma função pública que qualquer pessoa usando a rede Solana pode chamar. Cada instrução é usada para realizar uma ação específica. A lógica de execução para instruções é armazenada em programas, onde cada programa define seu próprio conjunto de instruções. Para interagir com a rede Solana, uma ou mais instruções são adicionadas a uma transação e enviadas para a rede para serem processadas.
Exemplo de transferência de SOL
O diagrama abaixo mostra como transações e instruções trabalham juntas para permitir que os usuários interajam com a rede. Neste exemplo, SOL é transferido de uma conta para outra.
Os metadados da conta do remetente indicam que ela deve assinar a transação. (Isso permite que o System Program deduza lamports.) Tanto a conta do remetente quanto a do destinatário devem ser graváveis, para que seu saldo de lamport possa mudar. Para executar esta instrução, a carteira do remetente envia a transação contendo sua assinatura e a mensagem contendo a instrução de transferência de SOL.
Diagrama de transferência de SOL
Depois que a transação é enviada, o System Program processa a instrução de transferência e atualiza o saldo de lamport de ambas as contas.
Diagrama do processo de transferência de SOL
O exemplo abaixo mostra o código relevante para os diagramas acima. (Veja a instrução de transferência do System Program.)
import {airdropFactory,appendTransactionMessageInstructions,createSolanaRpc,createSolanaRpcSubscriptions,createTransactionMessage,generateKeyPairSigner,getSignatureFromTransaction,lamports,pipe,sendAndConfirmTransactionFactory,setTransactionMessageFeePayerSigner,setTransactionMessageLifetimeUsingBlockhash,signTransactionMessageWithSigners} from "@solana/kit";import { getTransferSolInstruction } from "@solana-program/system";// Create a connection to clusterconst rpc = createSolanaRpc("http://localhost:8899");const rpcSubscriptions = createSolanaRpcSubscriptions("ws://localhost:8900");// Generate sender and recipient keypairsconst sender = await generateKeyPairSigner();const recipient = await generateKeyPairSigner();const LAMPORTS_PER_SOL = 1_000_000_000n;const transferAmount = lamports(LAMPORTS_PER_SOL / 100n); // 0.01 SOL// Fund sender with airdropawait airdropFactory({ rpc, rpcSubscriptions })({recipientAddress: sender.address,lamports: lamports(LAMPORTS_PER_SOL), // 1 SOLcommitment: "confirmed"});// Check balance before transferconst { value: preBalance1 } = await rpc.getBalance(sender.address).send();const { value: preBalance2 } = await rpc.getBalance(recipient.address).send();// Create a transfer instruction for transferring SOL from sender to recipientconst transferInstruction = getTransferSolInstruction({source: sender,destination: recipient.address,amount: transferAmount // 0.01 SOL in lamports});// Add the transfer instruction to a new transactionconst { value: latestBlockhash } = await rpc.getLatestBlockhash().send();const transactionMessage = pipe(createTransactionMessage({ version: 0 }),(tx) => setTransactionMessageFeePayerSigner(sender, tx),(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),(tx) => appendTransactionMessageInstructions([transferInstruction], tx));// Send the transaction to the networkconst signedTransaction =await signTransactionMessageWithSigners(transactionMessage);await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(signedTransaction,{ commitment: "confirmed" });const transactionSignature = getSignatureFromTransaction(signedTransaction);// Check balance after transferconst { value: postBalance1 } = await rpc.getBalance(sender.address).send();const { value: postBalance2 } = await rpc.getBalance(recipient.address).send();console.log("Sender prebalance:",Number(preBalance1) / Number(LAMPORTS_PER_SOL));console.log("Recipient prebalance:",Number(preBalance2) / Number(LAMPORTS_PER_SOL));console.log("Sender postbalance:",Number(postBalance1) / Number(LAMPORTS_PER_SOL));console.log("Recipient postbalance:",Number(postBalance2) / Number(LAMPORTS_PER_SOL));console.log("Transaction Signature:", transactionSignature);
Console
Click to execute the code.
Instruções
Diagrama mostrando uma transação com uma instrução, dividida em seus 3 componentes
Uma
Instruction
consiste nas seguintes informações:
program_id
: O ID do programa sendo invocado.accounts
: Um array de metadados de contadata
: Um array de bytes com [dados] adicionais a serem utilizados pela instrução.
Instruction struct
pub struct Instruction {/// Pubkey of the program that executes this instruction.pub program_id: Pubkey,/// Metadata describing accounts that should be passed to the program.pub accounts: Vec<AccountMeta>,/// Opaque data passed to the program for its own interpretation.pub data: Vec<u8>,}
ID do programa
O program_id
da instrução é o
endereço de chave pública do programa que contém a lógica de negócio da
instrução.
Metadados da conta
O array accounts
da instrução é um array de estrutura
AccountMeta
.
Os metadados devem ser fornecidos para cada conta com a qual a instrução
interage (Isso permite que a transação execute instruções em paralelo, desde que
não modifiquem a mesma conta.)
O diagrama abaixo representa uma transação que contém uma única instrução. O
array accounts
da instrução contém metadados para duas contas.
Uma transação com uma instrução. A instrução contém duas estruturas AccountMeta em seu array accounts.
Os metadados da conta incluem as seguintes informações:
- pubkey: O endereço de chave pública da conta
- is_signer: Definido como
true
se a conta deve assinar a transação - is_writable: Definido como
true
se a instrução modifica os dados da conta
Para saber quais contas uma instrução requer, incluindo quais devem ser graváveis, somente leitura ou assinar a transação, você deve consultar a implementação da instrução, conforme definido pelo programa.
AccountMeta
pub struct AccountMeta {/// An account's public key.pub pubkey: Pubkey,/// True if an `Instruction` requires a `Transaction` signature matching `pubkey`.pub is_signer: bool,/// True if the account data or metadata may be mutated during program execution.pub is_writable: bool,}
Dados
O data
da instrução é um array de bytes que especifica qual das instruções do
programa invocar. Também inclui quaisquer argumentos necessários para a
instrução.
Exemplo de criação de instrução
O exemplo abaixo mostra a estrutura de uma instrução de transferência de SOL.
import { generateKeyPairSigner, lamports } from "@solana/kit";import { getTransferSolInstruction } from "@solana-program/system";// 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});console.log(JSON.stringify(transferInstruction, null, 2));
Console
Click to execute the code.
O código abaixo mostra a saída dos trechos de código anteriores. O formato será
diferente entre os SDKs, mas observe que cada instrução contém as mesmas três
peças de informação necessárias: program_id
,
accounts
, data
.
{"accounts": [{"address": "Hu28vRMGWpQXN56eaE7jRiDDRRz3vCXEs7EKHRfL6bC","role": 3,"signer": {"address": "Hu28vRMGWpQXN56eaE7jRiDDRRz3vCXEs7EKHRfL6bC","keyPair": {"privateKey": {},"publicKey": {}}}},{"address": "2mBY6CTgeyJNJDzo6d2Umipw2aGUquUA7hLdFttNEj7p","role": 1}],"programAddress": "11111111111111111111111111111111","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}}
Os exemplos abaixo mostram como construir manualmente a instrução de
transferência. (A aba Expanded Instruction
é funcionalmente equivalente à aba
Instruction
.)
Na prática, geralmente você não precisa construir uma Instruction
manualmente. A maioria dos programas fornece bibliotecas de cliente com
funções auxiliares que criam as instruções para você. Se uma biblioteca não
estiver disponível, você pode construir a instrução manualmente.
const transferAmount = 0.01; // 0.01 SOLconst transferInstruction = getTransferSolInstruction({source: sender,destination: recipient.address,amount: transferAmount * LAMPORTS_PER_SOL});
Is this page helpful?