---
title: "Fan-out Durable Nonce pour SWQoS"
description: "Configuration d'un compte Durable Nonce et envoi en fan-out via SWQoS avec web3.js"
canonical: "https://erpc.global/fr/doc/rpc/durable-nonce-send-transaction/"
locale: "fr"
---

# Fan-out Durable Nonce pour SWQoS

## Contexte et cas d'usage

Lors de l'envoi de transactions sur Solana, la progression des slots, le placement des leaders et la congestion des chemins réseau modifient sans cesse la route qui atteint le leader le plus rapidement. Ce phénomène n'est propre à aucun fournisseur RPC ni à aucun service d'envoi : c'est une caractéristique structurelle du modèle d'exécution de Solana.

L'endpoint SWQoS d'ERPC fournit un chemin d'envoi qui injecte les transactions dans la voie prioritaire que les leaders allouent selon le Stake-weighted Quality of Service (SWQoS). Cette bande passante prioritaire représente environ 5× celle de la voie non prioritaire et s'applique avant l'évaluation des frais de priorité.

C'est pourquoi l'endpoint SWQoS est une option importante pour l'envoi de transactions ; en production, toutefois, un endpoint unique n'est pas toujours le plus rapide. Même au sein d'un même slot, des écarts de chemin passagers ou un déséquilibre de charge peuvent permettre à un autre endpoint rapide de passer devant.

Compte tenu de ces caractéristiques, plutôt que de dépendre d'une route unique, il peut être efficace d'envoyer la même transaction en parallèle sur plusieurs chemins rapides et de retenir la première qui est traitée.

Cependant, lorsque la même transaction est envoyée à plusieurs endpoints, rien ne garantit, sans contrôle supplémentaire, qu'elle ne sera exécutée qu'une seule fois. Un fan-out sans ce contrôle peut entraîner une double exécution involontaire ou casser le contrôle des nouvelles tentatives.

Solana fournit pour cela le mécanisme Durable Nonce. Avec Durable Nonce, vous pouvez envoyer la même transaction signée par plusieurs routes tout en limitant son exécution on-chain à une seule fois.

Cette page explique comment mettre en œuvre des opérations de fan-out qui combinent l'endpoint SWQoS d'ERPC avec d'autres endpoints RPC rapides, pour un envoi de transactions avec Durable Nonce.

---

## Portée et prérequis

Ce guide couvre la création d'un compte Durable Nonce avec web3.js et son utilisation pour l'envoi de transactions et les opérations de fan-out.

Prérequis à connaître :

- Pour les transactions Durable Nonce, utilisez la valeur du nonce comme `recentBlockhash` et placez `nonceAdvance` en première instruction
- Une fois `nonceAdvance` exécutée, le nonce peut être consommé même si les instructions suivantes échouent. Vous ne pouvez pas renvoyer le même rawTx tel quel.
- La création du compte nonce est une configuration ponctuelle, et le compte est généralement réutilisé

---

## Étape 1 : Préparer l'autorité du nonce et la connexion

L'autorité du nonce est un Keypair qui peut faire avancer le 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 */)
```

- L'autorité du nonce peut exécuter `nonceAdvance`
- Elle peut être le payeur des frais ou un keypair distinct

---

## Étape 2 : Générer le Keypair du compte nonce

Un compte nonce est un **compte système**.

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

Ce Keypair sert à :

- Conserver la valeur du nonce (qui remplace `recentBlockhash`)
- Signer uniquement lors de la création
- Être stocké en lieu sûr ensuite ; il n'est pas nécessaire pour les envois courants

---

## Étape 3 : Calculer le minimum pour l'exonération de loyer

Les comptes nonce doivent être exonérés de loyer. Ne codez pas les valeurs en dur : récupérez-les depuis le RPC.

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

---

## Étape 4 : Créer et initialiser le compte nonce

Créez le compte nonce avec **createAccount + nonceInitialize** dans une seule transaction.

```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',
)
```

Utilisez ce `nonceAccount.publicKey` pour les envois suivants.

---

## Étape 5 : Récupérer le nonce avant chaque envoi

Pour chaque transaction, récupérez la valeur actuelle du 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
```

- Utilisez `nonce` comme `recentBlockhash`
- `context.slot` sert à la confirmation

---

## Étape 6 : Construire la transaction Durable Nonce

Les transactions Durable Nonce doivent remplir les conditions suivantes :

- `recentBlockhash = nonce`
- La première instruction est `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()
```

Remarques :

- Si vous utilisez des instructions ComputeBudget, elles doivent venir **après** `nonceAdvance`
- Si `nonceAdvance` n'est pas en première position, la transaction sera rejetée

---

## Étape 7 : Fan-out vers plusieurs RPC

Envoyez le même rawTx simultanément.

```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 signature est identique d'un endpoint à l'autre
- Un envoi réussi n'est **pas** une confirmation

---

## Étape 8 : Confirmer avec Durable Nonce

Avec Durable Nonce, incluez les informations du nonce dans la confirmation.

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

Si la confirmation réussit :

- Le nonce avance
- Les copies envoyées aux autres RPC renvoient `InvalidNonce`

---

## Envois suivants

- Après la confirmation, récupérez un nouveau nonce
- Ne réutilisez ni le même rawTx ni la même valeur de nonce
- Pour les workflows parallèles, utilisez des comptes nonce distincts

Pour la transaction suivante, récupérez le nonce mis à jour et construisez la transaction en suivant les mêmes étapes.
