NOUVEAU : Helius acquiert Light Protocol
Atteindre une exécution sans changement de slot avec Sender et LaserStream
Blog/Développement

Atteindre une exécution sans changement de slot avec Sender et LaserStream

Developer Experience Engineer0xIchigo sur X0xIchigo sur LinkedIn0xIchigo sur GitHub
13 min de lecture

Introduction

Tout le monde souhaite que ses transactions soient intégrées aussi vite que possible. Cependant, à mesure que l’infrastructure de trading de Solana se perfectionne et que les marchés on-chain gagnent en maturité, il ne suffit plus d’envoyer une transaction en espérant qu’elle aboutisse : la congestion, la concurrence et les particularités du réseau rendent la « rapidité » désespérément peu fiable.

L’objectif est simple : lorsqu’un signal survient — un prix franchit un certain seuil, un compte est mis à jour ou un programme est invoqué — la transaction qui réagit à ce signal doit être intégrée dans le même slot. 

C’est le principe de l’exécution sans changement de slot : la détection et la soumission s’enchaînent avec une telle fluidité que les opportunités sont saisies avant de disparaître en quelques millisecondes. 

Dans la pratique, cet objectif est de plus en plus difficile à atteindre. Il exige l’ingestion de signaux à latence ultra-faible ainsi qu’une livraison fiable et déterministe.

Helius fournit les deux.

En associant LaserStream, qui détecte les événements à une vitesse fulgurante, à Sender, qui optimise la soumission des transactions, Helius fournit un pipeline de bout en bout spécialement conçu pour l’exécution sans changement de slot.

Aucune infrastructure disparate, aucune approximation, aucun cycle gaspillé : seulement les signaux et les chemins vers les leaders les plus rapides, conçus pour donner un avantage concurrentiel à vos opérations de trading.

Sender surpasse systématiquement les autres services en intégrant mes transactions presque instantanément, la plupart dans un seul slot. Auparavant, des transactions rentables m’échappaient souvent en raison d’une latence plus élevée en nombre de slots. Désormais, leur inclusion est presque garantie et bien plus fiable. Helius a toujours fourni d’excellents services, et Sender se démarque une nouvelle fois en ayant directement amélioré mes résultats.

Alan
Trader

LaserStream et Sender : un workflow unifié

Sender complète LaserStream pour créer un pipeline fluide de bout en bout destiné aux workflows de trading réactifs sur Solana. Dans la pratique :

  1. Utilisez LaserStream pour écouter les signaux : l’ingestion au niveau des shreds et le filtrage avancé transmettent les événements on-chain en temps réel plus rapidement que n’importe quel autre pipeline.
  2. Utilisez Helius Sender pour réagir aux signaux : les transactions sont envoyées simultanément via SWQoS et Jito, avec un routage mondial et une livraison tenant compte des validateurs afin de maximiser l’inclusion et de réduire la latence.
  3. Générez des bénéfices : ensemble, ces services permettent de saisir des opportunités rentables dans la pratique, et pas seulement en théorie.

Avec Helius, les développeurs bénéficient d’une stack verticalement intégrée, spécialement conçue pour la vitesse et la fiabilité :

  • Plus besoin d’assembler des RPC tiers, des relais ou une infrastructure développée en interne.
  • Le routage mondial, les nouvelles tentatives automatiques et la livraison tenant compte des validateurs sont intégrés.
  • Une approche transparente et équitable : nous ne soumettons pas activement les utilisateurs à des attaques sandwich et n’extrayons aucune forme de MEV négative à leurs dépens.

Helius fournit déjà la meilleure détection de signaux avec LaserStream. Pourquoi ne pas l’associer au meilleur service d’envoi de transactions avec Sender ? 

Ensemble, ils forment un pipeline unique et unifié pour les workflows Solana où chaque milliseconde compte. Confiez à Helius la boucle de lecture-écriture afin d’obtenir des résultats déterministes et rentables.

À quoi cela ressemble-t-il dans la pratique ?

Trouver le bon signal

Les opportunités d’arbitrage et de liquidation peuvent disparaître en quelques millisecondes sur Solana. Il est donc primordial de détecter le bon signal on-chain à temps. Ici, un « signal » désigne tout événement en temps réel, comme un transfert de token, la mise à jour d’un compte ou l’invocation d’un programme, qui présente une opportunité de trading. Sans ingestion à latence ultra-faible, les avantages disparaissent avant de pouvoir être exploités. Un streaming de données rapide et fiable est donc indispensable.

LaserStream est le service de streaming de données Solana nouvelle génération de Helius. Il associe la vitesse d’une ingestion au niveau des shreds à la fiabilité et à la portée d’un service distribué mondialement, sans les coûts ni les difficultés opérationnelles liés à l’exploitation de plusieurs nœuds dédiés.

Le filtrage avancé de LaserStream permet aux développeurs de se concentrer sur des signaux précis, comme certains types de transactions ou les mises à jour de comptes, ainsi que sur le streaming général de blocs. Pour obtenir un signal encore plus tôt, Preprocessed Transactions diffuse des transactions signées décodées à partir des shreds jusqu’à 8 ms avant le niveau d’engagement processed et s’associe à Sender exactement de la même manière.

L’intégration est fluide, car le service est conçu pour remplacer directement Yellowstone gRPC et prend en charge plusieurs clients, notamment Rust, Go et TypeScript. 

Toutefois, disposer du meilleur service de streaming de données ne représente que la moitié du travail, car les opportunités révélées par les signaux comportent deux volets :

  • Détection des événements — prendre connaissance des signaux potentiels.
  • Soumission réactive des transactions — créer, soumettre et intégrer des transactions en réponse à un signal potentiel.

LaserStream offre un avantage dans la détection des événements, ce qui permet une soumission réactive des transactions plus efficace. Toutefois, LaserStream n’est pas un service d’envoi de transactions et, malheureusement, intégrer efficacement des transactions sur Solana n’est pas aussi simple que d’effectuer un simple appel RPC sendTransaction.

Optimiser les workflows d’envoi de transactions

L’inclusion des transactions est un problème d’optimisation à plusieurs variables qui nécessite une compréhension approfondie de plusieurs aspects de l’architecture de Solana. Le moment d’arrivée, la réussite de la simulation, les conflits de verrouillage des comptes, les frais associés aux transactions et la priorité interagissent pour déterminer quand une transaction donnée s’exécute on-chain. 

Négliger l’un de ces facteurs dans votre workflow de détection des signaux et de création des transactions peut avoir des effets néfastes et transformer un avantage concurrentiel en occasion manquée. 

Par exemple, même si un trader détecte un signal quelques millisecondes avant ses concurrents, une arrivée tardive ou des frais insuffisants peuvent entraîner l’échec on-chain d’une transaction avec un slot de retard, transformant une opportunité rentable en manque à gagner.

Pour intégrer efficacement les transactions, vous avez besoin d’un workflow global qui maximise la priorité, réduit la latence et anticipe tous les scénarios d’échec potentiels sur l’ensemble de la stack. 

Pour intégrer efficacement une transaction sur Solana aujourd’hui, un développeur doit :

Utiliser des connexions stakées

Les connexions stakées exploitent la qualité de service pondérée par le stake (SWQoS) de Solana. Elles donnent la priorité au trafic des validateurs stakés et des RPC associés afin de mieux atteindre les leaders et d’accélérer la propagation. Les développeurs doivent passer par des connexions stakées pour réduire les échecs de propagation et ainsi améliorer les délais d’arrivée et les taux d’inclusion, sans dépendre uniquement des endpoints publics susceptibles d’être congestionnés.

Ajouter des frais de priorité dynamiques

Les frais de priorité améliorent la position d’une transaction dans le planificateur du leader lors de la Banking Stage, où un prio-graph, c’est-à-dire une file de priorité tenant compte des dépendances, ordonne l’exécution on-chain selon les frais par CU. Les frais de priorité doivent être calculés dynamiquement afin d’éviter les valeurs statiques qui entraîneraient un paiement excessif ou insuffisant et nuiraient à l’inclusion lors de l’accès à un état fortement sollicité.

Optimiser l’utilisation des CU

Les unités de calcul (CU) quantifient les ressources de calcul requises par une transaction. Dépasser le budget demandé provoque des échecs d’exécution, tandis qu’une demande excessive augmente les coûts de priorité. Sauf indication contraire, une transaction demande 200 000 CU par défaut. Vous pouvez optimiser ses CU en simulant préalablement la transaction pour estimer sa consommation, puis en demandant un montant précis à l’aide de l’instruction SetComputeUnitLimit du Compute Budget Program.

Utiliser le bon niveau d’engagement pour récupérer les données

Les niveaux d’engagement déterminent la profondeur de confirmation des données récupérées, comme les blockhashes, qui doivent être récents pour éviter leur expiration et garantir la validité d’une transaction. Utiliser le niveau confirmed pour les appels getLatestBlockhash est nettement plus rapide qu’utiliser finalized.

Ignorer les vérifications préalables

Les vérifications préalables simulent une transaction sur le nœud RPC avant sa soumission. Elles vérifient les signatures, les instructions et l’exécution afin de détecter rapidement les erreurs. Toutefois, elles peuvent ajouter plus de 100 ms de latence. Pour les workflows sensibles au temps et lorsque les développeurs ont la certitude absolue d’envoyer des transactions correctement formées, ils doivent définir le paramètre skipPreflight de la méthode RPC sendTransaction sur true.

Notez qu’il est vivement recommandé de réaliser le prototypage sans ignorer les vérifications préalables afin de s’assurer que les transactions sont correctement formatées et bien intégrées on-chain. Bien que cela accélère le processus, ignorer ces vérifications revient à avancer à l’aveugle : les transactions peuvent échouer pour diverses raisons et vous ne disposerez d’aucune information expliquant ces échecs.

Définir le paramètre maxRetries sur zéro

Le paramètre maxRetries de la méthode sendTransaction permet au RPC de renvoyer automatiquement une transaction en cas d’échec. Cela peut s’avérer inefficace, par exemple lorsque des transactions en double sont envoyées avec des blockhashes obsolètes. Les développeurs doivent définir maxRetries sur 0 pour reprendre le contrôle et mettre en œuvre leurs propres nouvelles tentatives côté client. Celles-ci doivent utiliser un backoff exponentiel, actualiser les blockhashes et les frais lors d’une rediffusion, et surveiller la hauteur de bloc afin de laisser expirer proprement les tentatives.

Envisager d’utiliser Jito

Les pourboires Jito permettent de créer des bundles off-chain via des enchères MEV, garantissant l’inclusion et l’ordre des transactions dans des blocs partiels. Cette approche convient parfaitement aux traders et aux arbitragistes qui ont besoin d’une exécution en tête de bloc ou de l’atomicité de plusieurs transactions. Elle est extrêmement avantageuse pour les transactions à forte valeur, sensibles au temps ou en concurrence pour accéder à un état fortement sollicité. Toutefois, ces enchères ajoutent un délai susceptible de dégrader les temps d’intégration par rapport à l’envoi d’une transaction bien optimisée via des connexions stakées. Les développeurs doivent combiner ces enchères hors protocole à la fiabilité des connexions stakées afin d’intégrer tout type de transaction aussi vite que possible, à tout moment.

La mise en œuvre de ces bonnes pratiques produit un effet cumulatif qui réduit considérablement les taux d’échec et améliore la fiabilité de l’intégration. Cependant, leur gestion manuelle exige des efforts d’ingénierie considérables. Il faut également suivre les dernières évolutions du protocole et adapter les workflows en conséquence, notamment par des ajustements constants, des modifications de l’infrastructure et la gestion des erreurs. Ces efforts seraient plus utiles ailleurs.

Sender

Sender est le service d’envoi de transactions à latence ultra-faible de Helius. Il exploite SWQoS et les enchères off-chain de Jito afin d’optimiser l’inclusion pour la MEV, tout en utilisant le routage géographique pour réduire les délais de propagation. 

En envoyant simultanément les transactions via des connexions stakées et la plateforme d’enchères de Jito, Sender offre deux chemins d’intégration. Il améliore ainsi la fiabilité et réduit les temps d’exécution sans consommer de crédits supplémentaires.

Sender est disponible avec tous les plans et offre une limite de débit par défaut de 6 TPS, qui peut être augmentée sur demande. Il est conçu pour les traders, les chercheurs de MEV et les applications à haute fréquence qui ont besoin de résultats déterministes. Sender complète LaserStream et permet de créer des workflows réactifs fluides pour une exécution sans changement de slot.

Fonctionnement de Sender

Sender traite les transactions de la même manière que le traitement standard : via une simple requête POST JSON-RPC, dans laquelle la transaction est sérialisée en base64 et soumise à l’un de ses endpoints. 

Sender dispose d’un endpoint HTTPS mondial qui assure automatiquement le routage vers la région géographique la plus proche. Il est donc recommandé pour les applications frontend afin d’éviter les problèmes liés à CORS. 

Sender propose également plusieurs endpoints HTTP régionaux pour une latence serveur à serveur optimale, notamment à Salt Lake City, Tokyo et Francfort.

Point important : aucune authentification par clé API n’est requise. Le service est minimaliste et aucun service intermédiaire ne sépare la réception de la transaction de sa soumission, ce qui le rend idéal pour les cas d’utilisation à latence ultra-faible. 

Pour utiliser Sender efficacement, une transaction doit être préparée comme suit :

  • Un pourboire minimal de 0,0002 SOL pour Jito ou de 0,000005 SOL (5 000 lamports) pour les soumissions via SWQoS uniquement, ce qui peut être spécifié en ajoutant ?swqos_only=true à l’endpoint
  • Le paramètre skipPreflight doit être défini sur true : Sender est optimisé pour privilégier la vitesse plutôt que la validation des transactions
  • Le paramètre maxRetries doit être défini sur 0 : les nouvelles tentatives ajoutent de la latence
  • Des frais de priorité doivent être ajoutés afin d’améliorer la priorité de la transaction lors de la Banking Stage du leader

Toutes les transactions envoyées via Sender doivent inclure un pourboire et des frais de priorité. 

Un pourboire est nécessaire pour accéder à l’infrastructure de Jito et à l’inclusion des transactions fondée sur des enchères. Les frais de priorité indiquent au leader, c’est-à-dire au validateur chargé de traiter la transaction, que vous acceptez de payer pour un traitement prioritaire. Ce mécanisme offre un double avantage : les pourboires donnent accès à l’infrastructure d’enchères de Jito, tandis que les frais de priorité augmentent la priorité d’une transaction. Les deux contribuent à maximiser son inclusion.

Nous recommandons de récupérer dynamiquement les pourboires à l’aide de l’API de seuil des pourboires de Jito, par exemple en prenant le 75e percentile et en ajoutant une petite marge, ainsi que les frais de priorité à l’aide de l’API Priority Fee de Helius. 

Une fois les transactions soumises, Sender les envoie en parallèle via SWQoS et Jito afin d’en maximiser l’inclusion sans frais supplémentaires. 

Nous recommandons également de maintenir les connexions actives pendant les périodes d’inactivité, c’est-à-dire après plus d’une minute, en envoyant un ping à /ping, c’est-à-dire https://sender.helius-rpc.com/ping, afin d’éviter les démarrages à froid. Nous recommandons aussi de suivre les bonnes pratiques de soumission des transactions pour garantir davantage une inclusion optimale. 

Bien démarrer

Voici comment commencer à trader avec LaserStream et Sender :

Utiliser LaserStream

LaserStream offre la même expérience de développement que gRPC. Il vous suffit de modifier l’endpoint et la clé API pour les faire pointer vers LaserStream. Vous profitez alors immédiatement de tous ses avantages.

Pour du code existant, la migration est aussi simple que ceci :

Migrating from Yellowstone to LaserStream
// Before: Using standard Yellowstone gRPC
const connection = new GeyserConnection(
  "your-current-endpoint.com",
  { token: "your-current-token" }
);

// After: Using LaserStream (just change the endpoint and token)
const connection = new GeyserConnection(
  "https://laserstream-mainnet-ewr.helius-rpc.com", // Choose the closest region to you
  { token: "your-helius-api-key" }
);

Nous recommandons d’utiliser l’un des clients de LaserStream pour simplifier le processus de développement.

Par exemple, ouvrir un abonnement est aussi simple que ceci :

A Simple Subscription
// Using the dedicated LaserStream SDK
import { subscribe, CommitmentLevel, LaserstreamConfig } from 'helius-laserstream';

const config = {
  apiKey: "your-helius-api-key",
  endpoint: "https://laserstream-mainnet-ewr.helius-rpc.com" // Choose the closest region to you
};

// The SDK automatically handles:
// - Connection management
// - Reconnection with backoff
// - Historical replay after disconnects
// - Subscription management
await subscribe(config, subscriptionRequest, handleData, handleError);

Essayez LaserStream gratuitement

Vous souhaitez tester LaserStream avant de migrer ? Obtenez un essai gratuit pour mesurer la latence de LaserStream, la comparer à celle d’autres solutions de streaming et évaluer le service pour votre cas d’utilisation spécifique.

Utiliser Sender

Helius Sender est disponible pour tous les utilisateurs et ne consomme aucun crédit supplémentaire. Aucun plan payant ni accès spécial n’est requis.

Pour commencer, créez un compte sur le tableau de bord Helius. Accédez ensuite à la section Clés API et copiez la clé fournie. Elle est nécessaire pour récupérer les blockhashes et confirmer la transaction, car Sender gère uniquement la soumission des transactions.

Vous trouverez ci-dessous un transfert simple de SOL avec Sender. Cet exemple inclut tous les composants requis : le pourboire, les frais de priorité et l’omission des vérifications préalables.

A Simple SOL Transfer Using Sender
import { pipe } from "@solana/kit";
import {
  createSolanaRpc,
  createTransactionMessage,
  setTransactionMessageFeePayerSigner,
  setTransactionMessageLifetimeUsingBlockhash,
  appendTransactionMessageInstruction,
  signTransactionMessageWithSigners,
  lamports,
  getBase64EncodedWireTransaction,
} from "@solana/kit";
import { getTransferSolInstruction } from "@solana-program/system";
import {
  getSetComputeUnitLimitInstruction,
  getSetComputeUnitPriceInstruction,
} from "@solana-program/compute-budget";

(async () => {
  const HELIUS_API_KEY = "your_api_key";
  const PRIV_KEY_B58 = "your_private_key";
  const RECIPIENT = "recipient_address";
  const TIP_ACCOUNTS = [
    "4ACfpUFoaSD9bfPdeu6DBt89gB6ENTeHBXCAi87NhDEE",
    "D2L6yPZ2FmmmTKPgzaMKdhu6EWZcTpLy1Vhx8uvZe7NZ",
    "9bnz4RShgq1hAnLnZbP8kbgBg1kEmcJBYQq3gQbmnSta",
    "5VY91ws6B2hMmBFRsXkoAAdsPHBJwRfBht4DXox3xkwn",
    "2nyhqdwKcJZR2vcqCyrYsaPVdAnFoJjiksCXJ7hfEYgD",
    "2q5pghRs6arqVjRvT5gfgWfWcHWmw1ZuCzphgd5KfWGJ",
    "wyvPkWjVZz1M8fHQnMMCDTQDbkManefNNhweYk5WkcF",
    "3KCKozbAaF75qEU33jtzozcJ29yJuaLJTy2jFdzUY8bT",
    "4vieeGHPYPG2MmyPRcYjdiDmmhN3ww7hsFNap8pVN3Ey",
    "4TQLFNWK8AovT1gFvda5jfw2oJeRMKEmw7aH6MGBJ3or"
  ];

  // Load signer from base58 private key
  const ownerSigner = await createKeyPairSignerFromBytes(bs58.decode(PRIV_KEY_B58));

  // Init RPC and fetch blockhash
  const rpc = createSolanaRpc(`https://mainnet.helius-rpc.com/?api-key=${HELIUS_API_KEY}`);
  const { value: blockhash } = await rpc.getLatestBlockhash().send();

  // Build and sign transaction
  const tx = pipe(
    createTransactionMessage({ version: 0 }),
    (m) => setTransactionMessageFeePayerSigner(ownerSigner, m),
    (m) => setTransactionMessageLifetimeUsingBlockhash(blockhash, m),
    (m) => appendTransactionMessageInstruction(getSetComputeUnitLimitInstruction({ units: 1000 }), m),
    (m) => appendTransactionMessageInstruction(getSetComputeUnitPriceInstruction({ microLamports: 200_000 }), m),
    (m) =>
      appendTransactionMessageInstruction(
        getTransferSolInstruction({
          source: ownerSigner,
          destination: RECIPIENT,
          amount: lamports(1_000_000n), // 0.001 SOL
        }),
        m
      ),
    (m) =>
      appendTransactionMessageInstruction(
        getTransferSolInstruction({
          source: ownerSigner,
          destination: TIP_ACCOUNTS[Math.floor(Math.random() * TIP_ACCOUNTS.length)],
          amount: lamports(200_000n), // 0.0002 SOL
        }),
        m
      )
  );

  const signedTx = await signTransactionMessageWithSigners(tx);
  const base64Tx = getBase64EncodedWireTransaction(signedTx);

  // Send via Sender
  const res = await fetch("https://sender.helius-rpc.com/fast", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      jsonrpc: "2.0",
      id: Date.now().toString(),
      method: "sendTransaction",
      params: [
        base64Tx,
        { encoding: "base64", skipPreflight: true, maxRetries: 0 },
      ],
    }),
  });

  const { result: sig, error } = await res.json();
  if (error) throw new Error(error.message);

  console.log("Transaction sent: ", sig);
  console.log(`Explorer: https://orb.helius.dev/tx/${sig}?cluster=mainnet`);
})();

L’envoi d’une transaction via Sender est simple avec notre SDK Node.js. La méthode `sendTransactionWithSender` gère dynamiquement tous les calculs d’unités de calcul et de frais, y compris les pourboires Jito : 

A Streamlined Sender Example Using the Node.js SDK
import { createHelius } from "helius-sdk";
import { address, createKeyPairSignerFromBytes, lamports } from "@solana/kit";
import { getTransferSolInstruction } from "@solana-program/system";
import bs58 from "bs58";

(async () => {
  const apiKey = ""; // From Helius dashboard
  const helius = createHelius({ apiKey });

  try {
    const feePayerSigner = await createKeyPairSignerFromBytes(
      bs58.decode(process.env.FEEPAYER_SECRET ?? "")
    );

    const toPubkey = address("your_to_address");

    const transferIx = getTransferSolInstruction({
      amount: lamports(1_000_000n), // 0.001 SOL
      destination: toPubkey,
      source: feePayerSigner,
    });

    const sig = await helius.tx.sendTransactionWithSender({
      signers: [feePayerSigner],
      instructions: [transferIx],
      version: 0,
      commitment: "confirmed",
      minUnits: 1_000,
      bufferPct: 0.1,
      region: "US_EAST",
      swqosOnly: true,
      pollTimeoutMs: 60_000,
      pollIntervalMs: 2_000,
    });

    console.log("Confirmed signature:", sig);
    console.log(
      `Explorer link: https://orb.helius.dev/tx/${sig}?cluster=mainnet`
    );
  } catch (error) {
    console.error("Error:", error);
  }
})();

Ce processus peut également être simplifié avec notre SDK Rust via la méthode send_smart_transaction_with_sender().

Utiliser LaserStream et Sender

La véritable puissance de Helius réside dans l’association de LaserStream et de Sender au sein d’un même workflow. LaserStream révèle les signaux exploitables dès qu’ils surviennent, tandis que Sender garantit que les transactions qui y réagissent sont intégrées aussi vite que possible.

Le modèle est simple :

  • Abonnez-vous avec LaserStream pour écouter les modifications de comptes, les invocations de programmes ou les transferts.
  • Créez une transaction en réponse à un signal donné.
  • Envoyez la transaction via Sender afin de garantir le chemin d’inclusion le plus rapide et le plus fiable.

Voici un exemple minimal illustrant ce workflow complet dans la pratique : 

A unified LaserStream and Sender Workflow
import bs58 from "bs58";
import { subscribe, CommitmentLevel } from "helius-laserstream";
import {
  pipe,
  createSolanaRpc,
  createTransactionMessage,
  setTransactionMessageFeePayerSigner,
  setTransactionMessageLifetimeUsingBlockhash,
  appendTransactionMessageInstruction,
  signTransactionMessageWithSigners,
  getBase64EncodedWireTransaction,
  createKeyPairSignerFromBytes,
  lamports,
  address,
} from "@solana/kit";
import { getTransferSolInstruction } from "@solana-program/system";
import {
  getSetComputeUnitLimitInstruction,
  getSetComputeUnitPriceInstruction,
} from "@solana-program/compute-budget";

const HELIUS_API_KEY = "your_api_key";
const LASERSTREAM_ENDPOINT = "https://laserstream-mainnet-ewr.helius-rpc.com"; // Pick the nearest region
const PRIV_KEY_B58 = "your_private_key";
const RECIPIENT = "recipient_address";
const TIP_ACCOUNTS = [
    "4ACfpUFoaSD9bfPdeu6DBt89gB6ENTeHBXCAi87NhDEE",
    "D2L6yPZ2FmmmTKPgzaMKdhu6EWZcTpLy1Vhx8uvZe7NZ",
    "9bnz4RShgq1hAnLnZbP8kbgBg1kEmcJBYQq3gQbmnSta",
    "5VY91ws6B2hMmBFRsXkoAAdsPHBJwRfBht4DXox3xkwn",
    "2nyhqdwKcJZR2vcqCyrYsaPVdAnFoJjiksCXJ7hfEYgD",
    "2q5pghRs6arqVjRvT5gfgWfWcHWmw1ZuCzphgd5KfWGJ",
    "wyvPkWjVZz1M8fHQnMMCDTQDbkManefNNhweYk5WkcF",
    "3KCKozbAaF75qEU33jtzozcJ29yJuaLJTy2jFdzUY8bT",
    "4vieeGHPYPG2MmyPRcYjdiDmmhN3ww7hsFNap8pVN3Ey",
    "4TQLFNWK8AovT1gFvda5jfw2oJeRMKEmw7aH6MGBJ3or"
  ];

// Example: scope the stream to a program you care about
const PROGRAM_OWNER_TO_WATCH = "11111111111111111111111111111111";

(async () => {
  // Setup signer and fetch blockhash
  const ownerSigner = await createKeyPairSignerFromBytes(bs58.decode(PRIV_KEY_B58));
  const rpc = createSolanaRpc(`https://mainnet.helius-rpc.com/?api-key=${HELIUS_API_KEY}`);

  // Setup LaserStream config and request
  const config = {
    apiKey: HELIUS_API_KEY,
    endpoint: LASERSTREAM_ENDPOINT,
  };

  // We keep it scoped to a given program for less noise
  const request = {
    accounts: {
      watch: {
        account: [],
        owner: [PROGRAM_OWNER_TO_WATCH],
        filters: [],
      },
    },
    commitment: CommitmentLevel.PROCESSED, // Can also change to CONFIRMED for more reliability
    slots: {},
    transactions: {},
    transactionsStatus: {},
    blocks: {},
    blocksMeta: {},
    entry: {},
    accountsDataSlice: [],
  };

  // On signal, build and send a reactive transaction via Sender
  const handleData = async () => {
    // Fresh blockhash for lifetime
    const { value: blockhash } = await rpc.getLatestBlockhash().send();

    // Build the transaction with compute-budget ixs first, then user ixs
    const tx = pipe(
      createTransactionMessage({ version: 0 }),
      (m) => setTransactionMessageFeePayerSigner(ownerSigner, m),
      (m) => setTransactionMessageLifetimeUsingBlockhash(blockhash, m),
      (m) => appendTransactionMessageInstruction(getSetComputeUnitLimitInstruction({ units: 100_000 }), m),
      (m) => appendTransactionMessageInstruction(getSetComputeUnitPriceInstruction({ microLamports: 200_000 }), m),
      (m) =>
        // In prod, this could be a buy / sell instruction
        appendTransactionMessageInstruction(
          getTransferSolInstruction({
            source: ownerSigner,
            destination: address(RECIPIENT),
            amount: lamports(1_000_000n), // 0.001 SOL
          }),
          m
        ),
      (m) =>
        appendTransactionMessageInstruction(
          getTransferSolInstruction({
            source: ownerSigner,
            destination: address(TIP_ACCOUNTS[Math.floor(Math.random() * TIP_ACCOUNTS.length)]),
            amount: lamports(200_000n), // 0.0002 SOL tip
          }),
          m
        )
    );

    const signedTx = await signTransactionMessageWithSigners(tx);
    const base64Tx = getBase64EncodedWireTransaction(signedTx);

    // Send via Sender (i.e., skip preflight and no RPC-side retries)
    const res = await fetch("https://sender.helius-rpc.com/fast", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        jsonrpc: "2.0",
        id: Date.now().toString(),
        method: "sendTransaction",
        params: [base64Tx, { encoding: "base64", skipPreflight: true, maxRetries: 0 }],
      }),
    });

    const { result: sig, error } = await res.json();
    if (error) throw new Error(error.message);

    console.log("Reactive transaction sent: ", sig);
    console.log(`Explorer:  https://orb.helius.dev/tx/${sig}?cluster=mainnet`);
  };

  const handleError = console.error;

  // Start the stream (signals → reactive sends)
  const stream = await subscribe(config, request, handleData, handleError);
  console.log(`LaserStream subscription started (id: ${stream.id})`);
})();

Pourquoi choisir Helius

Helius se distingue comme le meilleur choix pour optimiser les workflows de transactions sur Solana, grâce à notre position de plus grand validateur du réseau en termes de stake. La bande passante stakée ne constitue donc pas un problème pour nous. Nous éliminons ainsi efficacement les goulots d’étranglement et les échecs liés à la perte de priorité des transactions ou à l’abandon de paquets en période de congestion. Vos transactions disposent d’un chemin direct et hautement prioritaire vers les leaders, sans aucune restriction. 

En intégrant étroitement diverses optimisations matérielles et logicielles à notre bande passante stakée, Helius continue de dominer le marché en tant que meilleur fournisseur, avec la plus faible latence moyenne en nombre de slots. Cela témoigne de notre expertise verticale sur Solana. 

Notre engagement envers Solana nous place à l’avant-garde des dernières recherches et contributions. Par exemple, les conclusions de Chorus One sur la latence des transactions montrent que SWQoS peut souvent surpasser Jito pour réduire le délai d’inclusion, en particulier pour les utilisateurs dont la latence p95 dépasse 40 secondes. Sender assure intelligemment et simultanément le routage via SWQoS et Jito afin de garantir une fiabilité maximale pour tous les types de transactions. 

En définitive, disposer d’un stake important et acheminer les transactions via des connexions stakées constitue le facteur le plus important pour réduire le délai d’inclusion.

Plus rapide

LaserStream réduit la latence et l’incertitude. Plus un signal arrive tôt, plus les résultats deviennent prévisibles. Associé à Sender, il permet aux transactions envoyées en réaction à un signal d’améliorer la confiance opérationnelle, la prise de décision et la fiabilité. Ce pipeline unifié n’optimise pas seulement la vitesse de façon isolée : il optimise aussi la confiance.

Avec LaserStream, les développeurs savent qu’ils utilisent le meilleur service de streaming de données du marché. Avec Sender, ils ont la certitude que leurs transactions empruntent les chemins les plus rapides et les plus fiables vers les leaders de blocs. 

Ensemble, ces services produisent un effet cumulatif :

  • Latence E2E réduite : de la détection d’un événement à l’inclusion de la transaction, chaque étape ne prend que quelques millisecondes
  • Taux de réussite supérieurs : les transactions sont intégrées où et quand elles doivent l’être, ce qui permet de saisir les opportunités au lieu de les manquer
  • Charge d’ingénierie réduite : vous pouvez vous concentrer davantage sur le produit, la stratégie et l’ajustement précis des algorithmes de trading plutôt que sur la gestion et la configuration de nœuds dédiés pour optimiser l’envoi des transactions
  • Exécution sans changement de slot : LaserStream transmet les notifications pendant l’exécution des transactions d’un slot donné, et non une fois le slot terminé. Une transaction envoyée en réaction à une notification peut donc être intégrée au même slot 

Dans la pratique, cela signifie que les traders saisissent davantage d’opportunités d’arbitrage, que les liquidateurs remportent davantage d’enchères et que les applications à haute fréquence offrent une expérience utilisateur plus fluide. L’exécution sans changement de slot n’est pas un idéal théorique inaccessible, mais un workflow reproductible que seul Helius permet de mettre en œuvre.

Accédez au tableau de bord Helius et lancez-vous dès aujourd’hui.

Abonnez-vous à Helius

Suivez les dernières actualités du développement sur Solana et recevez une notification à chaque publication

Image agrandie