Transacciones

Para interactuar con la red de Solana, debes enviar una transacción. Puedes pensar en una transacción como un sobre que contiene varios formularios. Cada formulario es una instrucción que le dice a la red qué hacer. Enviar la transacción es como enviar el sobre por correo para que los formularios puedan ser procesados.

El ejemplo a continuación muestra una versión simplificada de dos transacciones. Cuando la primera transacción es procesada, ejecutará una sola instrucción. Cuando la segunda transacción es procesada, ejecutará tres instrucciones en orden secuencial: primero la instrucción 1, seguida por la instrucción 2, seguida por la instrucción 3.

Las transacciones son atómicas: si una sola instrucción falla, toda la transacción fallará y no ocurrirá ningún cambio.

Un diagrama simplificado que muestra dos transaccionesUn diagrama simplificado que muestra dos transacciones

Una Transaction consiste en la siguiente información:

  • signatures: Un array de firmas
  • message: Información de la transacción, incluyendo la lista de instrucciones a procesar
Transaction
pub struct Transaction {
#[wasm_bindgen(skip)]
#[serde(with = "short_vec")]
pub signatures: Vec<Signature>,
#[wasm_bindgen(skip)]
pub message: Message,
}

Diagrama que muestra las dos partes de una transacciónDiagrama que muestra las dos partes de una transacción

Las transacciones tienen un límite de tamaño total de 1232 bytes. Este límite incluye tanto el array de signatures como la estructura message.

Este límite proviene del tamaño de la Unidad Máxima de Transmisión (MTU) de IPv6 de 1280 bytes, menos 48 bytes para encabezados de red (40 bytes IPv6 + 8 bytes de encabezado).

Diagrama que muestra el formato de transacción y los límites de tamañoDiagrama que muestra el formato de transacción y los límites de tamaño

Firmas

El array signatures de la transacción contiene estructuras Signature. Cada Signature tiene 64 bytes y se crea firmando el Message de la transacción con la clave privada de la cuenta. Se debe proporcionar una firma para cada cuenta firmante incluida en cualquiera de las instrucciones de la transacción.

La primera firma pertenece a la cuenta que pagará la tarifa base de la transacción y es la firma de la transacción. La firma de la transacción puede utilizarse para buscar los detalles de la transacción en la red.

Mensaje

El message de la transacción es una estructura Message que contiene la siguiente información:

Para ahorrar espacio, la transacción no almacena permisos para cada cuenta individualmente. En su lugar, los permisos de las cuentas se determinan utilizando el header y el account_keys.

Message
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>,
}

Encabezado

El header del mensaje es una estructura MessageHeader. Contiene la siguiente información:

  • num_required_signatures: El número total de firmas requeridas por la transacción
  • num_readonly_signed_accounts: El número total de cuentas de solo lectura que requieren firmas
  • num_readonly_unsigned_accounts: El número total de cuentas de solo lectura que no requieren firmas
MessageHeader
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 que muestra las tres partes del encabezado del mensajeDiagrama que muestra las tres partes del encabezado del mensaje

Direcciones de cuentas

El account_keys del mensaje es un array de direcciones de cuentas, enviado en formato de array compacto. El prefijo del array indica su longitud. Cada elemento en el array es una clave pública, que apunta a una cuenta utilizada por sus instrucciones. El array accounts_keys debe estar completo y estrictamente ordenado de la siguiente manera:

  1. Firmante + Escribible
  2. Firmante + Solo lectura
  3. No firmante + Escribible
  4. No firmante + Solo lectura

El orden estricto permite que el array account_keys se combine con la información en el header del mensaje para determinar los permisos de cada cuenta.

Diagrama que muestra el orden del array de direcciones de cuentasDiagrama que muestra el orden del array de direcciones de cuentas

Blockhash reciente

El recent_blockhash del mensaje es un valor hash que actúa como una marca de tiempo de la transacción y evita transacciones duplicadas. Un blockhash expira después de 150 bloques. (Equivalente a un minuto, asumiendo que cada bloque dura 400ms). Después de que el bloque expira, la transacción caduca y no puede ser procesada.

El método RPC getLatestBlockhash te permite obtener el blockhash actual y la altura del último bloque en el que el blockhash será válido.

Instrucciones

El instructions del mensaje es un array de todas las instrucciones a procesar, enviado en formato de array compacto. El prefijo del array indica su longitud. Cada elemento en el array es una estructura CompiledInstruction e incluye la siguiente información:

  1. program_id_index: Un índice que apunta a una dirección en el array account_keys. Este valor indica la dirección del programa que procesa la instrucción.
  2. accounts: Un array de índices que apuntan a direcciones en el array account_keys. Cada índice apunta a la dirección de una cuenta requerida para esta instrucción.
  3. data: Un array de bytes que especifica qué instrucción invocar en el programa. También incluye cualquier dato adicional requerido por la instrucción. (Por ejemplo, argumentos de función)
CompiledInstruction
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 instruccionesArray compacto de instrucciones

Estructura de transacción de ejemplo

El siguiente ejemplo muestra la estructura de una transacción que contiene una única instrucción de transferencia 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 keypairs
const sender = await generateKeyPairSigner();
const recipient = await generateKeyPairSigner();
// Define the amount to transfer
const 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 recipient
const transferInstruction = getTransferSolInstruction({
source: sender,
destination: recipient.address,
amount: transferAmount
});
// Create transaction message
const transactionMessage = pipe(
createTransactionMessage({ version: 0 }),
(tx) => setTransactionMessageFeePayerSigner(sender, tx),
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
(tx) => appendTransactionMessageInstructions([transferInstruction], tx)
);
const signedTransaction =
await signTransactionMessageWithSigners(transactionMessage);
// Decode the messageBytes
const compiledTransactionMessage =
getCompiledTransactionMessageDecoder().decode(signedTransaction.messageBytes);
console.log(JSON.stringify(compiledTransactionMessage, 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 difiere entre SDKs, pero observa que cada instrucción contiene la misma información requerida.

{
"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
}
}
]
}

Después de enviar una transacción, puedes recuperar sus detalles utilizando la firma de la transacción y el método RPC getTransaction. La respuesta tendrá una estructura similar al siguiente fragmento.

También puedes encontrar la transacción usando el Explorador de Solana.

Transaction Data
{
"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?

Tabla de Contenidos

Editar Página

Gestionado por

© 2025 Fundación Solana.
Todos los derechos reservados.
Conéctate
Transacciones | Solana