Instrucciones
Las instrucciones son el bloque fundamental para interactuar con la blockchain de Solana. Una instrucción es esencialmente una función pública que cualquier usuario de la red Solana puede llamar. Cada instrucción se utiliza para realizar una acción específica. La lógica de ejecución para las instrucciones se almacena en programas, donde cada programa define su propio conjunto de instrucciones. Para interactuar con la red Solana, una o más instrucciones se agregan a una transacción y se envían a la red para ser procesadas.
Ejemplo de transferencia de SOL
El diagrama a continuación muestra cómo las transacciones e instrucciones trabajan juntas para permitir a los usuarios interactuar con la red. En este ejemplo, se transfiere SOL de una cuenta a otra.
Los metadatos de la cuenta del remitente indican que debe firmar la transacción. (Esto permite al System Program deducir lamports.) Tanto la cuenta del remitente como la del destinatario deben ser modificables, para que su saldo de lamports pueda cambiar. Para ejecutar esta instrucción, la billetera del remitente envía la transacción que contiene su firma y el mensaje que contiene la instrucción de transferencia de SOL.
Diagrama de transferencia de SOL
Después de enviar la transacción, el System Program procesa la instrucción de transferencia y actualiza el saldo de lamports de ambas cuentas.
Diagrama del proceso de transferencia de SOL
El ejemplo a continuación muestra el código relevante para los diagramas anteriores. (Ver la instrucción de transferencia del 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.
Instrucciones
Diagrama que muestra una transacción con una instrucción, dividida en sus 3 componentes
Una
Instruction
consiste en la siguiente información:
program_id
: El ID del programa que se está invocando.accounts
: Un array de metadatos de cuentadata
: Un array de bytes con [datos] adicionales para ser utilizados por la instrucción.
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 del programa
El program_id
de la instrucción es
la dirección de clave pública del programa que contiene la lógica de negocio de
la instrucción.
Metadatos de cuenta
El array accounts
de la instrucción es un array de estructuras
AccountMeta
.
Se deben proporcionar metadatos para cada cuenta con la que interactúa la
instrucción. (Esto permite que la transacción ejecute instrucciones en paralelo,
siempre que no modifiquen la misma cuenta.)
El diagrama a continuación muestra una transacción que contiene una sola
instrucción. El array accounts
de la instrucción contiene metadatos para dos
cuentas.
Una transacción con una instrucción. La instrucción contiene dos estructuras AccountMeta en su array accounts.
Los metadatos de la cuenta incluyen la siguiente información:
- pubkey: La dirección de clave pública de la cuenta
- is_signer: Se establece en
true
si la cuenta debe firmar la transacción - is_writable: Se establece en
true
si la instrucción modifica los datos de la cuenta
Para saber qué cuentas requiere una instrucción, incluidas las que deben ser escribibles, de solo lectura o firmar la transacción, debes consultar la implementación de la instrucción, según lo definido por el 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,}
Datos
El data
de la instrucción es un array de bytes que especifica cuál de las
instrucciones del programa invocar. También incluye cualquier argumento
requerido por la instrucción.
Ejemplo de creación de instrucción
El ejemplo a continuación muestra la estructura de una instrucción de transferencia 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.
El código a continuación muestra la salida de los fragmentos de código
anteriores. El formato diferirá entre SDKs, pero observe que cada instrucción
contiene las mismas tres piezas de información requerida:
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}}
Los ejemplos a continuación muestran cómo construir manualmente la instrucción
de transferencia. (La pestaña Expanded Instruction
es funcionalmente
equivalente a la pestaña Instruction
.)
En la práctica, normalmente no tienes que construir una Instruction
manualmente. La mayoría de los programas proporcionan bibliotecas cliente con
funciones auxiliares que crean las instrucciones por ti. Si no hay una
biblioteca disponible, puedes construir la instrucción manualmente.
const transferAmount = 0.01; // 0.01 SOLconst transferInstruction = getTransferSolInstruction({source: sender,destination: recipient.address,amount: transferAmount * LAMPORTS_PER_SOL});
Is this page helpful?