Préparation à la production

Construire localement et tester sur devnet sont d'excellents moyens de débuter avec les paiements Solana. Cependant, lorsque vous êtes prêt à déployer sur Mainnet, vous devez être conscient des nuances du mainnet. Devnet pardonne les erreurs. Mainnet ne pardonne pas. Ce guide couvre les différences importantes pour garantir à vos utilisateurs une expérience fluide.

DevnetMainnet
SOL gratuit via les faucetsAcquérir du vrai SOL pour les frais
Faible concurrence pour l'espace de blocLes frais de priorité comptent
Les transactions passent facilementLa configuration des transactions est critique
Le RPC public convientRPC de production requis
Keypairs et mints devnetClés et mints de tokens différents—mettez à jour votre configuration

Infrastructure RPC

Les endpoints publics (api.mainnet-beta.solana.com) sont limités en débit sans SLA. Ils conviennent pour le développement mais échoueront dans les flux de paiement en production—comme essayer de faire fonctionner un processeur de paiement via une API partagée sans garantie de disponibilité.

N'utilisez jamais le RPC public pour la production

Utilisez un fournisseur RPC privé pour un accès fiable et à faible latence.

Lors du choix d'un fournisseur RPC, recherchez :

  • Fiabilité : SLA avec garanties de disponibilité (99,9 %+)
  • Latence : proximité géographique avec vos utilisateurs
  • Fonctionnalités : fonctionnalités d'atterrissage de transactions, indexation, API de frais de priorité

Pour une liste complète des fournisseurs RPC, consultez le guide Fournisseurs d'infrastructure RPC.

Configuration RPC redondante

Comme tout fournisseur de services réseau, les fournisseurs RPC peuvent connaître des temps d'arrêt ou des périodes de performances dégradées. Pour garantir la résilience de votre application, vous devez configurer votre application pour utiliser plusieurs fournisseurs RPC.

Solana Kit fournit une bibliothèque pour personnaliser les transports RPC qui vous permet de construire votre propre client RPC redondant. Voici un exemple de la façon dont vous pourriez l'utiliser pour construire un client RPC redondant :

import { RpcTransport } from "@solana/rpc-spec";
import { RpcResponse } from "@solana/rpc-spec-types";
import { createHttpTransport } from "@solana/rpc-transport-http";
// Create a transport for each RPC server
const transports = [
createHttpTransport({ url: "https://mainnet-beta.my-server-1.com" }),
createHttpTransport({ url: "https://mainnet-beta.my-server-2.com" }),
createHttpTransport({ url: "https://mainnet-beta.my-server-3.com" })
];
// Create a wrapper transport that distributes requests to them
let nextTransport = 0;
async function roundRobinTransport<TResponse>(
...args: Parameters<RpcTransport>
): Promise<RpcResponse<TResponse>> {
const transport = transports[nextTransport];
nextTransport = (nextTransport + 1) % transports.length;
return await transport(...args);
}

Si vous préférez ne pas construire vos propres outils de routage, vous pouvez utiliser un service tierce partie comme Iron Forge pour gérer le routage à votre place.

Atterrissage des transactions

Sur Devnet, les transactions atterrissent assez facilement. Sur Mainnet, vous êtes en concurrence pour l'espace de bloc. Pour augmenter les chances que votre transaction soit incluse dans un bloc, vous devez vous assurer d'avoir correctement assemblé votre transaction. Cela signifie :

  • inclure un blockhash récent avant d'envoyer la transaction
  • inclure une instruction de frais de priorité dans la transaction avec des frais de priorité compétitifs
  • inclure une instruction de limite d'unités de calcul dans la transaction avec une limite d'unités de calcul basée sur les unités de calcul estimées requises pour la transaction

De plus, vous devriez envisager d'autres outils comme Jito Bundles pour augmenter les chances que votre transaction soit incluse dans un bloc. Explorons ces outils plus en détail.

Configuration d'envoi de transaction

Lors de l'envoi de transactions sur Mainnet, configurez ces paramètres pour des taux d'atterrissage optimaux :

Gestion du blockhash :

  • Récupérez avec confirmed commitment
  • Stockez le lastValidBlockHeight renvoyé par getLatestBlockhash — cela vous indique quand votre transaction expire
  • Les blockhashes expirent après ~150 blocs (~60-90 secondes)

Options d'envoi :

  • maxRetries: 0 — Désactive les nouvelles tentatives RPC automatiques. Gérez les nouvelles tentatives vous-même afin de pouvoir actualiser le blockhash si nécessaire.
  • skipPreflight: true — Contourne la simulation avant l'envoi. Utilisez ceci lorsque vous avez déjà validé la transaction et souhaitez la latence la plus faible. Gardez-le à false pendant le développement pour détecter les erreurs tôt.
import { createSolanaRpc } from "@solana/kit";
const rpc = createSolanaRpc(process.env.RPC_URL!);
// 1. Get blockhash with confirmed commitment
const { value: latestBlockhash } = await rpc
.getLatestBlockhash({ commitment: "confirmed" })
.send();
// 2. Build and sign your transaction with the blockhash
// ... (transaction building code)
// 3. Send with production settings
const signature = await rpc
.sendTransaction(encodedTransaction, {
encoding: "base64",
maxRetries: 0n, // Handle retries yourself
skipPreflight: true, // Skip simulation for speed (use false during dev)
preflightCommitment: "confirmed"
})
.send();
// 4. Track expiration using lastValidBlockHeight
const { lastValidBlockHeight } = latestBlockhash;
// Stop retrying when current block height exceeds lastValidBlockHeight

Utiliser les frais de priorité

Chaque transaction Solana nécessite des frais de transaction, payés en SOL. Les frais de transaction sont divisés en deux parties : les frais de base et les frais de priorité. Les frais de base rémunèrent les validateurs pour le traitement de la transaction. Les frais de priorité sont des frais optionnels, pour augmenter les chances que le leader actuel traite votre transaction. Considérez cela comme une livraison express : vous payez plus pour une livraison plus rapide et plus fiable.

Fonctionnement des frais :

Total fee = Base fee (5,000 lamports per signature) + Priority fee
Priority fee = Compute units x Price per unit (micro-lamports per compute unit)

Coûts réels :

  • Transfert USDC simple : ~0,001-0,005 $ dans des conditions normales
  • En cas de congestion : ~0,01-0,05 $
  • Congestion maximale : peut augmenter davantage

Exemple d'implémentation :

Le package @solana-program/compute-budget fournit une fonction d'aide pour mettre à jour ou ajouter facilement l'instruction de prix d'unité de calcul (en micro-lamports) à une transaction.

import { updateOrAppendSetComputeUnitPriceInstruction } from "@solana-program/compute-budget";
const tx = pipe(
createTransactionMessage({ version: 0 }),
(m) => setTransactionMessageFeePayerSigner(payer, m),
(m) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m),
(m) => appendTransactionMessageInstructions([myInstructions], m),
(m) => updateOrAppendSetComputeUnitPriceInstruction(1000n as MicroLamports, m)
);

Obtenir des estimations de frais : la plupart des fournisseurs RPC proposent des API de frais de priorité :

Pour la mécanique complète des frais, consultez Frais de transaction et notre guide : Comment ajouter des frais de priorité à une transaction.

Optimiser les unités de calcul

Le calcul sur Solana est effectivement une mesure de la quantité de travail effectuée par le programme. Il existe une limite sur la quantité de calcul pouvant être utilisée dans une transaction (actuellement 1,4 million d'unités de calcul), et une limite sur la quantité de calcul pouvant être utilisée par compte par bloc (actuellement 100 millions d'unités de calcul).

Lorsque vous soumettez une transaction, vous devez estimer la quantité de calcul qui sera utilisée et définir la limite d'unités de calcul en conséquence - il s'agit effectivement d'une demande de la part de la capacité totale qui doit être réservée pour votre transaction. En pratique, cela signifie qu'estimer correctement les unités de calcul requises pour votre transaction est essentiel pour que votre transaction soit incluse dans un bloc (et important pour gérer vos frais de priorité).

L'API JSON RPC de Solana dispose d'une méthode simulatetransaction qui peut être utilisée pour estimer les unités de calcul requises pour une transaction, ce qui inclut une estimation des unités de calcul qui seront utilisées. @solana/kit fournit des fonctions utilitaires qui estiment les limites de ressources d'une transaction et les définissent sur le message en une seule étape (en utilisant la méthode simulatetransaction en arrière-plan). Pour les transactions de version 1, ces utilitaires estiment également la limite de taille des données des comptes chargés.

import {
estimateResourceLimitsFactory,
estimateAndSetResourceLimitsFactory
} from "@solana/kit";
const estimateResourceLimits = estimateResourceLimitsFactory({ rpc });
const estimateAndSetResourceLimits = estimateAndSetResourceLimitsFactory(
estimateResourceLimits
);
const txWithResourceLimits = await estimateAndSetResourceLimits(tx);

Si vous construisez et envoyez des transactions avec un client plugin kit, vous n'avez généralement pas besoin de cette étape — le client ajoute automatiquement les instructions de budget de calcul lors de l'envoi (.sendTransaction()). Le flux manuel ci-dessus est destiné à ceux qui assemblent les transactions directement avec @solana/kit.

En production, si vous répétez le même type de transaction plusieurs fois, vous devriez envisager de mettre en cache l'estimation de calcul pour ce type de transaction afin d'éviter la surcharge liée à l'estimation des unités de calcul à chaque fois.

Bundles Jito

Les bundles Jito sont un outil permettant de gérer l'exécution atomique de plusieurs transactions. Cela s'obtient en envoyant plusieurs transactions au réseau Jito avec un pourboire. Les pourboires peuvent être utilisés pour inciter le réseau Jito à inclure vos transactions dans un bloc.

Ressources :

Stratégies de nouvelle tentative

Les transactions peuvent échouer pour de nombreuses raisons. Contrairement aux API de paiement traditionnelles qui retournent immédiatement un succès ou un échec, les transactions blockchain nécessitent un suivi de confirmation.

Concepts clés :

  • Expiration du blockhash : Les transactions sont valides pendant ~150 blocs (~60-90 secondes)
  • Idempotence : La même transaction signée produit toujours la même signature — la resoumettre est sans danger
  • Backoff exponentiel : Évitez de surcharger le réseau avec des tentatives répétées rapides
import {
createSolanaRpc,
createSolanaRpcSubscriptions,
sendAndConfirmTransactionFactory,
isSolanaError,
SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED
} from "@solana/kit";
const rpc = createSolanaRpc(process.env.RPC_URL!);
const rpcSubscriptions = createSolanaRpcSubscriptions(process.env.RPC_WSS_URL!);
const sendAndConfirmTransaction = sendAndConfirmTransactionFactory({
rpc,
rpcSubscriptions
});
// Send with automatic confirmation tracking and block height monitoring
try {
await sendAndConfirmTransaction(signedTransaction, {
commitment: "confirmed",
// Optional: abort after 75 seconds
abortSignal: AbortSignal.timeout(75_000)
});
} catch (e) {
if (isSolanaError(e, SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED)) {
// Blockhash expired—rebuild transaction with fresh blockhash and retry
rebuildAndRetryTransaction(); // implement your own logic for rebuilding and retrying the transaction
}
throw e;
}

Le sendAndConfirmTransactionFactory de @solana/kit gère automatiquement l'interrogation de confirmation et le suivi de la hauteur de bloc. Il lève une exception SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED lorsque le blockhash de la transaction expire, indiquant que vous devez reconstruire la transaction avec un nouveau blockhash.

Ressources supplémentaires

Comprendre les niveaux de confirmation

Solana propose trois niveaux de confirmation. En termes de finance traditionnelle :

NiveauDéfinition SolanaÉquivalent traditionnelCas d'usage
processedDans un bloc, pas encore votéAutorisation en attenteMises à jour UI en temps réel
confirmedSupermajorité votéeFonds compensésLa plupart des paiements
finalizedAncré, irréversibleFonds réglésHaute valeur, conformité

Quand utiliser chaque niveau :

  • Mises à jour UI : Afficher processed pour un retour immédiat (« Paiement soumis »)
  • Créditer le compte utilisateur : Attendre confirmed (sûr pour la plupart des transactions)
  • Expédier des biens physiques : Attendre finalized
  • Retraits importants : Attendre finalized
  • Conformité/audit : Toujours enregistrer le statut finalized

Pour en savoir plus sur la vérification du statut des transactions, consultez Interagir avec Solana.

Gestion des erreurs

Solana Kit fournit des erreurs typées via isSolanaError(). Utilisez des codes d'erreur spécifiques plutôt que la correspondance par chaîne de caractères :

import {
isSolanaError,
SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED,
SOLANA_ERROR__TRANSACTION_ERROR__INSUFFICIENT_FUNDS_FOR_FEE,
SOLANA_ERROR__TRANSACTION_ERROR__BLOCKHASH_NOT_FOUND,
SOLANA_ERROR__INSTRUCTION_ERROR__INSUFFICIENT_FUNDS
} from "@solana/kit";
function handlePaymentError(error: unknown): {
message: string;
retryable: boolean;
} {
// Blockhash expired—rebuild and retry
if (
isSolanaError(error, SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED) ||
isSolanaError(error, SOLANA_ERROR__TRANSACTION_ERROR__BLOCKHASH_NOT_FOUND)
) {
return { message: "Transaction expired—rebuilding", retryable: true };
}
// Insufficient SOL for fees
if (
isSolanaError(
error,
SOLANA_ERROR__TRANSACTION_ERROR__INSUFFICIENT_FUNDS_FOR_FEE
)
) {
return { message: "Not enough SOL for fees", retryable: false };
}
// Insufficient token balance
if (
isSolanaError(error, SOLANA_ERROR__INSTRUCTION_ERROR__INSUFFICIENT_FUNDS)
) {
return { message: "Insufficient balance", retryable: false };
}
// Unknown error
console.error("Payment error:", error);
return { message: "Payment failed—please retry", retryable: true };
}

Codes d'erreur courants :

Code d'erreurCauseRésolution
BLOCK_HEIGHT_EXCEEDEDBlockhash expiréReconstruire avec un nouveau blockhash
BLOCKHASH_NOT_FOUNDBlockhash introuvableReconstruire avec un nouveau blockhash
INSUFFICIENT_FUNDS_FOR_FEESOL insuffisantAlimenter le payeur de frais ou utiliser l'abstraction de frais
INSUFFICIENT_FUNDSTokens insuffisantsL'utilisateur doit avoir un solde plus élevé
ACCOUNT_NOT_FOUNDtoken account manquantCréer un ATA dans la transaction

Transactions sans frais de gaz

Les utilisateurs s'attendent à payer en stablecoins, et non à acquérir des SOL pour couvrir les frais réseau. Les transactions sans frais de gaz résolvent ce problème — à l'image des utilisateurs de Venmo qui ne se soucient pas des frais ACH. Consultez l'abstraction des frais pour une implémentation complète.

Sécurité

Gestion des clés

  • Ne jamais exposer les clés privées dans le code frontend. Utilisez la signature côté serveur, des portefeuilles matériels, des portefeuilles multisignatures ou des services de gestion de clés.
  • Séparez les portefeuilles chauds et froids. Le portefeuille chaud pour les opérations courantes, le portefeuille froid pour la trésorerie.
  • Sauvegardez toutes les clés de production. Stockez des sauvegardes chiffrées dans plusieurs emplacements sécurisés. La perte d'une clé entraîne une perte d'accès définitive.
  • Utilisez des clés différentes pour le devnet et le mainnet. Vos clés devnet ne doivent pas être vos clés mainnet. Utilisez une configuration basée sur l'environnement pour garantir le chargement des bonnes clés sur chaque réseau.

Infrastructure de signature

Pour la signature backend en production, utilisez Keychain — une bibliothèque de signature unifiée qui abstrait plusieurs backends de gestion de clés via une interface unique : Memory, Vault, Privy, Turnkey, AWS KMS, Fireblocks, GCP KMS, CDP, Para, Dfns, Crossmint, Openfort et Utila. Cela vous permet de développer localement avec des clés en mémoire, puis de basculer vers des backends de niveau production sans modifier le code de l'application.

Vous ne savez pas quel backend vous convient ? Consultez Choisir un backend. Keychain est disponible pour Rust et TypeScript.

Sécurité RPC

Traitez les endpoints RPC comme des clés API—ne les exposez pas dans le code frontend où ils peuvent être extraits et exploités abusivement. Utilisez un proxy backend ou des variables d'environnement qui ne sont pas intégrées dans le code client.

Surveillance

Suivez ces métriques en production :

MétriquePourquoi
Taux de réussite des transactionsDétecter les problèmes tôt
Latence de confirmationSurveiller la santé du réseau
Dépense de frais prioritairesGestion des coûts
Taux d'erreur RPCSanté du fournisseur

Configurez des alertes pour :

  • Transferts au-dessus du seuil depuis la trésorerie
  • Pics de taux d'échec des transactions
  • Schémas de destinataires inhabituels
  • Augmentation du taux d'erreur RPC

Pour la surveillance des transactions en temps réel à grande échelle, consultez notre guide d'indexation.

Vérifier les adresses

Chaque jeton et programme possède exactement une adresse correcte sur le mainnet. Les jetons usurpés imitant l'USDC ou d'autres stablecoins sont courants—ils auront le même nom et le même symbole mais un mint différent. Votre application doit coder en dur ou mettre en liste blanche les adresses de mint (selon vos exigences), ne jamais les accepter de manière dynamique de sources non fiables.

Configuration basée sur l'environnement : Devnet et Mainnet utilisent souvent des mints de jetons complètement différents. Configurez votre application pour charger les adresses appropriées selon l'environnement — n'encodez pas en dur les adresses mainnet en oubliant de les changer pendant les tests, ou pire, ne déployez pas des adresses devnet en production.

Quelques mints de stablecoins courants sont :

JetonÉmetteurAdresse du Mint
USDCCircleEPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
USDTTetherEs9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB
PYUSDPayPal2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo
USDGPaxos2u1tszSeqZ3qBWF3uNGPFc8TzMk2tdiwknnRMWGWjGWH

Les adresses des programmes sont également importantes. Envoyer des instructions au mauvais programme échouera — ou pire, entraînera une perte irréversible de fonds. Les adresses du Token Program sont :

ProgrammeAdresse
Token ProgramTokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
Token-2022 ProgramTokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb

Autoriser uniquement les bonnes adresses protège contre les tokens falsifiés, mais cela ne protège pas contre l'envoi vers un mauvais type de compte. L'adresse d'un destinataire peut correspondre à un portefeuille, un token account, un mint ou un programme, et chacun nécessite un traitement différent. Les SOL natifs envoyés à autre chose qu'un portefeuille échappent au contrôle de l'expéditeur — définitivement perdus s'il s'agit d'un mint ou d'un programme, récupérables uniquement par le propriétaire du compte s'il s'agit d'un token account — sans qu'aucune transaction échouée n'avertisse l'utilisateur.

Validez les destinataires avant d'envoyer

Classifiez chaque adresse destinataire avant de signer un transfert. Consultez Vérifier une adresse pour l'arbre de décision complet et le code de référence permettant de distinguer les portefeuilles, les token accounts, les mints et les programmes.

Liste de vérification avant lancement

  • SOL Mainnet acquis pour les frais et le rent
  • RPC de production configuré (pas un point de terminaison public)
  • Point de terminaison RPC de secours configuré
  • Frais prioritaires mis en place avec tarification dynamique
  • La logique de réessai gère l'expiration du blockhash
  • Niveau de confirmation adapté au cas d'utilisation
  • Toutes les erreurs courantes gérées correctement
  • Gasless configuré (le cas échéant)
  • Adresses des tokens Mainnet vérifiées (pas des mints devnet)
  • Validation de l'adresse du destinataire avant l'envoi (portefeuille vs token account vs mint vs programme)
  • Toutes les clés sauvegardées de manière sécurisée
  • Gestion des clés vérifiée (pas de clés dans le frontend)
  • Surveillance des transactions et alertes actives
  • Testé en charge au volume attendu

Déploiement de programmes

Si vous déployez un programme Solana personnalisé dans le cadre de votre infrastructure de paiement, des considérations supplémentaires s'appliquent.

Pré-déploiement

  • Version de la CLI Solana : Assurez-vous d'utiliser la dernière version de la CLI Solana.
  • keypair du programme : Votre programme aura une adresse différente sur le mainnet par rapport au devnet (sauf si vous réutilisez le même keypair). Mettez à jour toutes les références dans la configuration de votre application. Conservez le keypair de votre programme dans un endroit sécurisé (notez que l'exécution de cargo clean risque de supprimer votre keypair de programme).
  • Initialiser les comptes : Si votre programme nécessite des comptes administrateurs, des PDAs ou d'autres comptes d'état, assurez-vous qu'ils sont créés sur le mainnet avant que les utilisateurs n'interagissent avec votre application. Il en va de même pour tous les Associated Token Accounts (ATAs) dont votre programme a besoin.

Processus de déploiement

  • Comptes tampon : Les programmes volumineux se déploient via des comptes tampon. La commande solana program deploy gère cela automatiquement, mais sachez que le déploiement n'est pas atomique — en cas d'interruption, vous devrez peut-être récupérer ou fermer des comptes tampon. Consultez Déploiement de programmes.
  • Autorité de mise à niveau : Décidez si votre programme doit être modifiable après le lancement. Pour l'immuabilité, révoquez l'autorité de mise à niveau après le déploiement. Pour plus de flexibilité, sécurisez la clé d'autorité de mise à niveau de manière appropriée.
  • Rent : Assurez-vous que votre portefeuille de déploiement dispose de suffisamment de SOL pour couvrir les minimums d'exemption de rent pour tous les program accounts.
  • Vérification : Vérifiez votre programme pour vous assurer que le programme exécutable que vous déployez sur le réseau de Solana correspond au code source dans votre dépôt

Pour des conseils complets sur le déploiement de programmes, consultez Déploiement de programmes.

Is this page helpful?

© 2026 Fondation Solana. Tous droits réservés.