---
title: "Fan-out de Durable Nonce para SWQoS"
description: "Configuración de una cuenta de Durable Nonce y envío en fan-out por SWQoS con web3.js"
canonical: "https://erpc.global/es/doc/rpc/durable-nonce-send-transaction/"
locale: "es"
---

# Fan-out de Durable Nonce para SWQoS

## Contexto y escenario de uso

En el envío de transacciones en Solana, el avance de los slots, la asignación de los líderes y la congestión de las rutas de red cambian constantemente qué ruta llega antes al líder. Esto no es propio de ningún proveedor de RPC ni de ningún servicio de envío; es una característica estructural del modelo de ejecución de Solana.

El endpoint SWQoS de ERPC ofrece una ruta de envío que inyecta las transacciones en el carril prioritario que los líderes asignan según Stake-weighted Quality of Service (SWQoS). Este ancho de banda prioritario es aproximadamente 5× el del carril no prioritario y se aplica antes de evaluar las comisiones de prioridad.

Por eso, el endpoint SWQoS es una opción importante para enviar transacciones, pero en producción un único endpoint no siempre es el más rápido. Incluso dentro del mismo slot, diferencias transitorias entre rutas o desequilibrios de carga pueden hacer que otro endpoint rápido llegue primero.

Dadas estas características, en lugar de depender de una sola ruta, puede ser eficaz un patrón operativo que envíe la misma transacción por varias rutas rápidas en paralelo y acepte la primera que se procese.

Sin embargo, cuando se envía la misma transacción a varios endpoints, no se puede garantizar que se ejecute una sola vez sin un control adicional. Un fan-out sin ese control puede provocar una doble ejecución no deseada o romper el control de reintentos.

Solana ofrece Durable Nonce como mecanismo para ello. Con Durable Nonce puedes enviar la misma transacción firmada por varias rutas y, al mismo tiempo, limitar su ejecución on-chain a una sola vez.

Esta página explica cómo implementar operaciones de fan-out que combinan el endpoint SWQoS de ERPC con otros endpoints RPC rápidos, partiendo de que las transacciones se envían con Durable Nonce.

---

## Alcance y requisitos previos

Esta guía explica cómo crear una cuenta de Durable Nonce con web3.js y cómo usarla para enviar transacciones y en operaciones de fan-out.

Requisitos previos que conviene entender:

- En las transacciones con Durable Nonce, usa el valor del nonce como `recentBlockhash` y coloca `nonceAdvance` como primera instrucción
- Una vez que se ejecuta `nonceAdvance`, el nonce puede consumirse aunque fallen las instrucciones posteriores. No puedes reenviar el mismo rawTx tal cual.
- La cuenta de nonce se crea una sola vez y normalmente se reutiliza

---

## Paso 1: Preparar la autoridad del nonce y la conexión

La autoridad del nonce es un Keypair que puede avanzar el nonce.

```ts
import {
  Connection,
  Keypair,
  SystemProgram,
  NONCE_ACCOUNT_LENGTH,
} from '@solana/web3.js'

const connection = new Connection('https://<primary-rpc-endpoint>', 'confirmed')

const nonceAuthority = Keypair.fromSecretKey(/* secret key */)
```

- La autoridad del nonce puede ejecutar `nonceAdvance`
- Puede ser el fee payer o un keypair distinto

---

## Paso 2: Generar el Keypair de la cuenta de nonce

Una cuenta de nonce es una **cuenta del sistema** (System Account).

```ts
const nonceAccount = Keypair.generate()
```

Este Keypair se usa para:

- Guardar el valor del nonce (sustituye a `recentBlockhash`)
- Firmar solo en el momento de la creación
- Después, guardarlo de forma segura; no se necesita para los envíos diarios

---

## Paso 3: Calcular el mínimo para la exención de renta

Las cuentas de nonce deben estar exentas de renta. No escribas los valores a mano en el código; obtenlos del RPC.

```ts
const lamports =
  await connection.getMinimumBalanceForRentExemption(NONCE_ACCOUNT_LENGTH)
```

---

## Paso 4: Crear e inicializar la cuenta de nonce

Crea la cuenta de nonce con **createAccount + nonceInitialize** en una sola transacción.

```ts
import { Transaction } from '@solana/web3.js'

const tx = new Transaction()

tx.add(
  SystemProgram.createAccount({
    fromPubkey: nonceAuthority.publicKey,
    newAccountPubkey: nonceAccount.publicKey,
    lamports,
    space: NONCE_ACCOUNT_LENGTH,
    programId: SystemProgram.programId,
  }),
  SystemProgram.nonceInitialize({
    noncePubkey: nonceAccount.publicKey,
    authorizedPubkey: nonceAuthority.publicKey,
  }),
)

// fee payer is the nonce authority
tx.feePayer = nonceAuthority.publicKey

// use a normal blockhash for initialization
const { blockhash, lastValidBlockHeight } =
  await connection.getLatestBlockhash('confirmed')

tx.recentBlockhash = blockhash

// sign with both the new account and the authority
tx.sign(nonceAccount, nonceAuthority)

const signature = await connection.sendRawTransaction(tx.serialize())
await connection.confirmTransaction(
  { signature, blockhash, lastValidBlockHeight },
  'confirmed',
)
```

Usa esta `nonceAccount.publicKey` en los envíos posteriores.

---

## Paso 5: Obtener el nonce antes de cada envío

En cada transacción, obtén el valor actual del nonce.

```ts
import { NonceAccount } from '@solana/web3.js'

const { value, context } = await connection.getAccountInfoAndContext(
  nonceAccount.publicKey,
  'confirmed',
)

if (!value) {
  throw new Error('Nonce account not found')
}

const nonce = NonceAccount.fromAccountData(value.data).nonce
const minContextSlot = context.slot
```

- Usa `nonce` como `recentBlockhash`
- `context.slot` se usa en la confirmación

---

## Paso 6: Construir la transacción con Durable Nonce

Las transacciones con Durable Nonce deben cumplir estas condiciones:

- `recentBlockhash = nonce`
- La primera instrucción es `nonceAdvance`

```ts
import { TransactionMessage, VersionedTransaction } from '@solana/web3.js'

const instructions = [
  SystemProgram.nonceAdvance({
    noncePubkey: nonceAccount.publicKey,
    authorizedPubkey: nonceAuthority.publicKey,
  }),
  // add your real instructions after this
]

const message = new TransactionMessage({
  payerKey: nonceAuthority.publicKey,
  recentBlockhash: nonce,
  instructions,
}).compileToV0Message()

const tx = new VersionedTransaction(message)
tx.sign([nonceAuthority /* + other signers */])

const rawTx = tx.serialize()
```

Notas:

- Si usas instrucciones de ComputeBudget, deben ir **después** de `nonceAdvance`
- Si `nonceAdvance` no es la primera instrucción, la transacción será rechazada

---

## Paso 7: Hacer fan-out a varios RPC

Envía el mismo rawTx de forma concurrente.

```ts
const endpoints = [
  'https://swqos-fra2.erpc.global?api-key=YOUR_API_KEY',
  'https://swqos-ams1.erpc.global?api-key=YOUR_API_KEY',
  'https://<backup-rpc-1>',
]

const results = await Promise.allSettled(
  endpoints.map((url) =>
    new Connection(url, 'confirmed').sendRawTransaction(rawTx, {
      skipPreflight: true,
      minContextSlot,
    }),
  ),
)

const success = results.find(
  (r): r is PromiseFulfilledResult<string> => r.status === 'fulfilled',
)

if (!success) {
  throw new Error('All sends failed')
}

const signature = success.value
```

- La firma es idéntica en todos los endpoints
- Un envío correcto **no** es una confirmación

---

## Paso 8: Confirmar con Durable Nonce

Con Durable Nonce, incluye la información del nonce en la confirmación.

```ts
await connection.confirmTransaction(
  {
    signature,
    nonceAccountPubkey: nonceAccount.publicKey,
    nonceValue: nonce,
    minContextSlot,
  },
  'confirmed',
)
```

Si la confirmación se completa:

- El nonce avanza
- Las copias enviadas a otros RPC devuelven `InvalidNonce`

---

## Envíos siguientes

- Después de la confirmación, obtén un nonce nuevo
- No reutilices el mismo rawTx ni el mismo valor de nonce
- Para flujos de trabajo en paralelo, usa cuentas de nonce distintas

Para la siguiente transacción, obtén el nonce actualizado y construye la transacción con los mismos pasos.
