> ## Documentation Index
> Fetch the complete documentation index at: https://www.helius.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Guía de optimización de transacciones de Solana

> Optimiza las transacciones de Solana para minimizar la latencia de confirmación y maximizar las tasas de entrega. Aprende sobre las comisiones de prioridad, las unidades de cómputo y las prácticas recomendadas.

Existen dos métodos principales para enviar transacciones en Solana:

1. Usar [conexiones con stake](https://www.helius.dev/staked-connections) (opción predeterminada)
2. Usar servicios especializados de inclusión como [Sender](https://www.helius.dev/sender) (recomendado)

Este artículo abarca las prácticas recomendadas para optimizar transacciones mediante conexiones con stake, que son el método predeterminado para todos los planes de pago de Helius.

Las conexiones con stake son más adecuadas para casos de uso en los que la latencia no es crítica para tu negocio (por ejemplo, pagos, billeteras, aplicaciones sociales, etc.).

Si eres un trader avanzado (por ejemplo, propAMM, sniper, copy trader, bot de liquidación o arbitraje) y buscas un servicio especializado de inclusión de transacciones con latencia ultrabaja, consulta nuestro [tutorial de Sender](/docs/es/sending-transactions/sender).

## Resumen

Las conexiones con stake de Helius garantizan una entrega de transacciones del 100 % con tiempos de confirmación mínimos. Para optimizar las tasas de inclusión de tus transacciones con conexiones con stake, recomendamos las siguientes prácticas:

* Usa el commitment "confirmed" para obtener el [blockhash más reciente](/docs/es/rpc/guides/getlatestblockhash)
* Agrega [comisiones de prioridad](/docs/es/sending-transactions/optimizing-transactions#establecer-la-comisión-de-prioridad-correcta) y calcúlalas dinámicamente
* Optimiza el uso de unidades de cómputo (CU)
* Establece `maxRetries` en 0 e implementa una lógica sólida de reintentos
* Envía con `skipPreflight` establecido en `true` (opcional)

<Tip>
  ¿Quieres profundizar? Cubrimos todos los fundamentos en esta [publicación del blog](https://www.helius.dev/blog/how-to-land-transactions-on-solana).
</Tip>

## Optimizaciones recomendadas para traders

Para casos de uso de trading sensibles a la latencia, recomendamos [usar Sender](/docs/es/sending-transactions/sender).

Sin embargo, si usas conexiones con stake y quieres optimizar tu configuración para obtener las latencias más bajas posibles, recomendamos las siguientes optimizaciones, además de aplicar las prácticas mencionadas anteriormente:

* Tu servidor cliente (la máquina desde la que envías las transacciones) debe estar ubicado en el este de EE. UU. o en Europa occidental.
* Elige FRA o PIT si quieres ubicarte junto a los servidores de envío de transacciones de Helius.
* Evita realizar envíos desde regiones alejadas de la red de validadores (por ejemplo, Latinoamérica o Sudáfrica).
* Precalienta las cachés regionales de Helius para minimizar la latencia de cola.
* Solo se requiere un hilo de precalentamiento por región; agregar más no aportará ningún beneficio.
* Envía una llamada RPC [`getHealth`](/docs/es/rpc/guides/gethealth) cada segundo con el mismo endpoint y la misma clave de API que usas para enviar transacciones.

Estos beneficios solo serán perceptibles para traders experimentados. Para desarrolladores de aplicaciones en general, recomendamos seguir las pautas de la sección Envío de transacciones inteligentes que aparece a continuación.

<Tip>
  Obtén datos de transacciones on-chain lo más rápido posible con [Raw Shreds (UDP)](/docs/es/shred-delivery/raw-shreds). [Suscríbete desde tu panel de Helius](https://dashboard.helius.dev/shred-delivery-seats).
</Tip>

## Envío de transacciones inteligentes

Los SDK de Helius para [TypeScript](/docs/es/sending-transactions/optimizing-transactions#sdk-de-typescript) y [Rust](/docs/es/sending-transactions/optimizing-transactions#sdk-de-rust) pueden enviar transacciones inteligentes. Este nuevo método crea y envía una transacción optimizada mientras gestiona su estado de confirmación.

Los usuarios pueden configurar las opciones de envío de la transacción, como omitir o no las verificaciones previas.

En el nivel más básico, los usuarios deben proporcionar su par de claves y las instrucciones que quieren ejecutar; nosotros nos encargamos del resto.

Nosotros:

* Obtenemos el blockhash más reciente
* Creamos la transacción inicial
* Simulamos la transacción inicial para obtener las unidades de cómputo (CU) consumidas
* Establecemos el límite de CU en las CU consumidas en el paso anterior, con cierto margen
* Obtenemos la comisión de prioridad recomendada por Helius mediante nuestra [API de comisiones de prioridad](/docs/es/priority-fee-api)
* Establecemos la comisión de prioridad (microlamports por CU) en el valor recomendado por Helius
* Agregamos una pequeña comisión de reserva por si la comisión recomendada cambia durante los próximos segundos
* Creamos y enviamos la transacción optimizada
* Devolvemos la firma de la transacción si se completa correctamente

<Note>
  Exigir el valor recomendado (o uno superior) para nuestras conexiones con stake garantiza que Helius envíe transacciones de alta calidad y que los validadores no nos apliquen límites de frecuencia.
</Note>

Este método es la forma más sencilla de crear, enviar e incluir una transacción en Solana.

Al usar la comisión recomendada por Helius, las transacciones que envíen los usuarios de Helius con uno de nuestros [planes de pago estándar](/docs/es/billing/plans) se enrutarán a través de nuestras conexiones con stake, lo que garantiza una entrega de transacciones cercana al 100 % y una latencia mínima.

### SDK de TypeScript

El método `sendSmartTransaction` está disponible en nuestro [SDK de Helius para TypeScript](/docs/es/sdks/typescript) en las [versiones >= 1.3.2](https://www.npmjs.com/package/helius-sdk). Para actualizar a una versión más reciente del SDK, ejecuta `npm update helius-sdk`.

Este ejemplo transfiere SOL a una cuenta de tu elección. Usa `sendSmartTransaction` para enviar una transacción optimizada que no omite las verificaciones previas:

```typescript theme={"system"}
import { Helius } from "helius-sdk";
import {
  Keypair,
  SystemProgram,
  LAMPORTS_PER_SOL,
  TransactionInstruction,
} from "@solana/web3.js";

const helius = new Helius("YOUR_API_KEY");
const fromKeypair = /* Your keypair goes here */;
const fromPubkey = fromKeypair.publicKey;
const toPubkey = /* The person we're sending 0.5 SOL to */;

const instructions: TransactionInstruction[] = [
  SystemProgram.transfer({
    fromPubkey: fromPubkey,
    toPubkey: toPubkey,
    lamports: 0.5 * LAMPORTS_PER_SOL, 
  }),
];

const transactionSignature = await helius.rpc.sendSmartTransaction(instructions, [fromKeypair]);
console.log(`Successful transfer: ${transactionSignature}`);
```

### SDK de Rust

El método `send_smart_transaction` está disponible en nuestro [SDK de Rust](/docs/es/sdks/rust) en las [versiones >= 0.1.5](https://docs.rs/helius/latest/helius/). Para actualizar a una versión más reciente del SDK, ejecuta `cargo update helius`.

El siguiente ejemplo transfiere 0.01 SOL a una cuenta de tu elección.

Utiliza `send_smart_transaction` para enviar una transacción optimizada que omite las verificaciones previas y realiza hasta dos reintentos si es necesario:

```rust theme={"system"}
use helius::types::*;
use helius::Helius;
use solana_sdk::{
    pubkey::Pubkey,
    signature::Keypair,
    system_instruction
};

#[tokio::main]
async fn main() {
    let api_key: &str = "YOUR_API_KEY";
    let cluster: Cluster = Cluster::MainnetBeta;
    let helius: Helius = Helius::new(api_key, cluster).unwrap();
    
    let from_keypair: Keypair = /* Your keypair goes here */;
    let from_pubkey: Pubkey = from_keypair.pubkey();
    let to_pubkey: Pubkey = /* The person we're sending 0.01 SOL to */;

    // Create a simple instruction (transfer 0.01 SOL from from_pubkey to to_pubkey)
    let transfer_amount = 100_000; // 0.01 SOL in lamports
    let instruction = system_instruction::transfer(&from_pubkey, &to_pubkey, transfer_amount);

    // Create the SmartTransactionConfig
    let config = SmartTransactionConfig {
        instructions,
        signers: vec![&from_keypair],
        send_options: RpcSendTransactionConfig {
            skip_preflight: true,
            preflight_commitment: None,
            encoding: None,
            max_retries: Some(2),
            min_context_slot: None,
        },
        lookup_tables: None,
    };

    // Send the optimized transaction
    match helius.send_smart_transaction(config).await {
        Ok(signature) => {
            println!("Transaction sent successfully: {}", signature);
        }
        Err(e) => {
            eprintln!("Failed to send transaction: {:?}", e);
        }
    }
}
```

## Envío de transacciones sin el SDK

Recomendamos enviar transacciones inteligentes con uno de nuestros SDK, pero puedes obtener la misma funcionalidad sin usar uno.

Tanto el SDK de TypeScript como el SDK de Rust son de código abierto, por lo que puedes consultar en cualquier momento el código subyacente de la funcionalidad de envío de transacciones inteligentes.

### Preparar y crear la transacción inicial

Primero, prepara y crea la transacción inicial. Esto incluye crear una nueva transacción con un conjunto de instrucciones, agregar el blockhash reciente y asignar un pagador de comisiones.

Para las transacciones con versión, crea un `TransactionMessage` y compílalo con tablas de consulta si existe alguna.

Luego, crea una nueva transacción con versión y fírmala. Esto es necesario para el siguiente paso, en el que simularemos la transacción, ya que debe estar firmada.

Por ejemplo, si quisiéramos preparar una transacción con versión:

```typescript theme={"system"}
// Prepare your instructions and set them to an instructions variable
// The payerKey is the public key that will be paying for this transaction
// Prepare your lookup tables and set them to a lookupTables variable
let recentBlockhash = (await this.connection.getLatestBlockhash()).blockhash;
const v0Message = new TransactionMessage({
    instructions: instructions,
    payerKey: pubKey,
    recentBlockhash: recentBlockhash,
}).compileToV0Message(lookupTables);
versionedTransaction = new VersionedTransaction(v0Message);
versionedTransaction.sign([fromKeypair]);
```

### Optimizar el uso de unidades de cómputo (CU) de la transacción

Para [optimizar el uso de unidades de cómputo (CU) de la transacción](https://www.helius.dev/blog/optimizing-solana-programs), podemos usar el método RPC `simulateTransaction` para simularla.

La [simulación de la transacción](/docs/es/api-reference/rpc/http/simulatetransaction) devolverá la cantidad de CU utilizadas, por lo que podemos usar este valor para establecer el límite de cómputo correspondiente.

Se recomienda usar primero una transacción de prueba con las instrucciones deseadas, además de una instrucción que establezca el límite de cómputo en 1.4 millones de CU.

Esto permite garantizar que la simulación de la transacción se complete correctamente.

Por ejemplo:

```typescript theme={"system"}
const testInstructions = [
    ComputeBudgetProgram.setComputeUnitLimit({ units: 1_400_000 }),
    ...instructions,
];

const testTransaction = new VersionedTransaction(
    new TransactionMessage({
        instructions: testInstructions,
        payerKey: payer,
        recentBlockhash: (await this.connection.getLatestBlockhash()).blockhash,
    }).compileToV0Message(lookupTables)
);

const rpcResponse = await this.connection.simulateTransaction(testTransaction, {
    replaceRecentBlockhash: true,
    sigVerify: false,
});

const unitsConsumed = rpcResponse.value.unitsConsumed;
```

También se recomienda agregar un pequeño margen para garantizar que la transacción se ejecute sin problemas. Podemos hacerlo con la siguiente configuración:

```typescript theme={"system"}
let customersCU = Math.ceil(unitsConsumed * 1.1);
```

Luego, crea una instrucción que establezca el límite de unidades de cómputo en este valor y agrégala a tu arreglo de instrucciones:

```typescript theme={"system"}
const computeUnitIx = ComputeBudgetProgram.setComputeUnitLimit({
    units: customersCU
});
instructions.push(computeUnitIx);
```

### Serializar y codificar la transacción

Esto es relativamente sencillo.

Primero, para serializar la transacción, tanto el tipo Transaction como VersionedTransaction tienen un método `.serialize()`. Luego, usa el [paquete bs58](https://www.npmjs.com/package/bs58) para codificar la transacción.

Tu código debería verse como `bs58.encode(txt.serialize());`

### Establecer la comisión de prioridad correcta

Primero, usa la [API de comisiones de prioridad](/docs/es/priority-fee-api) para obtener la estimación de la comisión de prioridad. Queremos proporcionar nuestra transacción y obtener la comisión recomendada por Helius mediante el parámetro recommended:

```typescript theme={"system"}
const response = await fetch(HeliusURL, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
        jsonrpc: "2.0",
        id: "1",
        method: "getPriorityFeeEstimate",
        params: [
            {
                transaction: bs58.encode(versionedTransaction), // Pass the serialized transaction in
                options: { recommended: true },
            },
        ],   
    }),
});

const data = await response.json();
const priorityFeeRecommendation = data.result.priorityFeeEstimate;
```

Luego, crea una instrucción que establezca el precio de las unidades de cómputo en este valor y agrégala a las instrucciones anteriores:

```typescript theme={"system"}
const computeBudgetIx = ComputeBudgetProgram.setComputeUnitPrice({
    microLamports: priorityFeeRecommendation,
});

instructions.push(computeBudgetIx);
```

### Crear y enviar la transacción optimizada

Este paso es casi una repetición del primero. Sin embargo, el arreglo de instrucciones iniciales se modificó para agregar dos instrucciones que establecen de forma óptima el límite y el precio de las unidades de cómputo.

Ahora, envía la transacción.

No importa si la envías con o sin verificaciones previas, ni si cambias otras opciones de envío: en todos los planes de pago, la transacción se enrutará a través de nuestras conexiones con stake.

### Consultar el estado de la transacción y retransmitirla

<Warning>
  Aunque las conexiones con stake reenvían una transacción directamente al líder, aún es posible que se descarte durante la [etapa bancaria](https://www.helius.dev/blog/solana-virtual-machine#the-banking-stage). Se recomienda implementar tu propia lógica de retransmisión en lugar de depender del RPC para que reintente la transacción.
</Warning>

El [método RPC `sendTransaction`](/docs/es/api-reference/rpc/http/sendtransaction) tiene un parámetro `maxRetries` que puedes establecer para reemplazar la lógica de reintentos predeterminada del RPC, lo que da a los desarrolladores más control sobre el proceso de reintento.

Un patrón común consiste en obtener el blockhash actual mediante [`getLatestBlockhash`](/docs/es/rpc/guides/getlatestblockhash), almacenar `lastValidBlockHeight` y reintentar la transacción hasta que venza el blockhash.

Es fundamental volver a firmar una transacción solo cuando el blockhash ya no sea válido. De lo contrario, la red podría aceptar ambas transacciones.

Después de enviar una transacción, es importante consultar su estado de confirmación para comprobar si la red la procesó y confirmó antes de reintentarla. Usa el [método RPC `getSignatureStatuses`](/docs/es/rpc/guides/getsignaturestatuses) para consultar el estado de confirmación de una lista de transacciones.

El SDK @solana/web3.js también tiene un método `getSignatureStatuses` en su clase `Connection` para obtener el estado actual de varias firmas.

### Cómo gestiona sendSmartTransaction las consultas y retransmisiones

El método `sendSmartTransaction` tiene un tiempo de espera de 60 segundos. Como un blockhash es válido durante 150 slots y suponiendo slots perfectos de 400 ms, podemos asumir razonablemente que el blockhash de una transacción dejará de ser válido después de un minuto.

El método envía la transacción y consulta su firma durante este periodo de espera:

```typescript theme={"system"}
try {
   // Create a smart transaction
   const transaction = await this.createSmartTransaction(instructions, signers, lookupTables, sendOptions);
  
   const timeout = 60000;
   const startTime = Date.now();
   let txtSig;
  
   while (Date.now() - startTime < timeout) {
     try {
       txtSig = await this.connection.sendRawTransaction(transaction.serialize(), {
         skipPreflight: sendOptions.skipPreflight,
         ...sendOptions,
       });
  
       return await this.pollTransactionConfirmation(txtSig);
     } catch (error) {
       continue;
     }
   }
} catch (error) {
   throw new Error(`Error sending smart transaction: ${error}`);
}
```

`txtSig` se establece en la firma de la transacción que se acaba de enviar.

Luego, el método usa `pollTransactionConfirmation()` para consultar el estado de confirmación de la transacción. Este método comprueba el estado de una transacción cada cinco segundos, hasta un máximo de tres veces.

Si la transacción no se confirma durante este periodo, se devuelve un error:

```typescript theme={"system"}
async pollTransactionConfirmation(txtSig: TransactionSignature): Promise<TransactionSignature> {
    // 15 second timeout
    const timeout = 15000;
    // 5 second retry interval
    const interval = 5000;
    let elapsed = 0;

    return new Promise<TransactionSignature>((resolve, reject) => {
      const intervalId = setInterval(async () => {
        elapsed += interval;

        if (elapsed >= timeout) {
          clearInterval(intervalId);
          reject(new Error(`Transaction ${txtSig}'s confirmation timed out`));
        }

        const status = await this.connection.getSignatureStatuses([txtSig]);

        if (status?.value[0]?.confirmationStatus === "confirmed") {
          clearInterval(intervalId);
          resolve(txtSig);
        }
      }, interval);
   });
}
```
