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.
| Devnet | Mainnet |
|---|---|
| SOL gratuit via les faucets | Acquérir du vrai SOL pour les frais |
| Faible concurrence pour l'espace de bloc | Les frais de priorité comptent |
| Les transactions passent facilement | La configuration des transactions est critique |
| Le RPC public convient | RPC de production requis |
| Keypairs et mints devnet | Clé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 serverconst 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 themlet 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
confirmedcommitment - Stockez le
lastValidBlockHeightrenvoyé pargetLatestBlockhash— 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 àfalsependant 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 commitmentconst { value: latestBlockhash } = await rpc.getLatestBlockhash({ commitment: "confirmed" }).send();// 2. Build and sign your transaction with the blockhash// ... (transaction building code)// 3. Send with production settingsconst signature = await rpc.sendTransaction(encodedTransaction, {encoding: "base64",maxRetries: 0n, // Handle retries yourselfskipPreflight: true, // Skip simulation for speed (use false during dev)preflightCommitment: "confirmed"}).send();// 4. Track expiration using lastValidBlockHeightconst { 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 feePriority 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é :
- API de frais de priorité Helius
- Module complémentaire de frais de priorité QuickNode
- API de frais de priorité Triton
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 monitoringtry {await sendAndConfirmTransaction(signedTransaction, {commitment: "confirmed",// Optional: abort after 75 secondsabortSignal: AbortSignal.timeout(75_000)});} catch (e) {if (isSolanaError(e, SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED)) {// Blockhash expired—rebuild transaction with fresh blockhash and retryrebuildAndRetryTransaction(); // 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
- Guide : Confirmation et expiration des transactions
- Helius : Comment faire passer des transactions sur Solana
- QuickNode : Stratégies pour optimiser les transactions Solana
Comprendre les niveaux de confirmation
Solana propose trois niveaux de confirmation. En termes de finance traditionnelle :
| Niveau | Définition Solana | Équivalent traditionnel | Cas d'usage |
|---|---|---|---|
processed | Dans un bloc, pas encore voté | Autorisation en attente | Mises à jour UI en temps réel |
confirmed | Supermajorité votée | Fonds compensés | La plupart des paiements |
finalized | Ancré, irréversible | Fonds réglés | Haute valeur, conformité |
Quand utiliser chaque niveau :
- Mises à jour UI : Afficher
processedpour 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 retryif (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 feesif (isSolanaError(error,SOLANA_ERROR__TRANSACTION_ERROR__INSUFFICIENT_FUNDS_FOR_FEE)) {return { message: "Not enough SOL for fees", retryable: false };}// Insufficient token balanceif (isSolanaError(error, SOLANA_ERROR__INSTRUCTION_ERROR__INSUFFICIENT_FUNDS)) {return { message: "Insufficient balance", retryable: false };}// Unknown errorconsole.error("Payment error:", error);return { message: "Payment failed—please retry", retryable: true };}
Codes d'erreur courants :
| Code d'erreur | Cause | Résolution |
|---|---|---|
BLOCK_HEIGHT_EXCEEDED | Blockhash expiré | Reconstruire avec un nouveau blockhash |
BLOCKHASH_NOT_FOUND | Blockhash introuvable | Reconstruire avec un nouveau blockhash |
INSUFFICIENT_FUNDS_FOR_FEE | SOL insuffisant | Alimenter le payeur de frais ou utiliser l'abstraction de frais |
INSUFFICIENT_FUNDS | Tokens insuffisants | L'utilisateur doit avoir un solde plus élevé |
ACCOUNT_NOT_FOUND | token account manquant | Cré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.
- QuickNode : Bonnes pratiques de sécurité des endpoints
- Helius : Protégez vos clés API Solana : Bonnes pratiques de sécurité
Surveillance
Suivez ces métriques en production :
| Métrique | Pourquoi |
|---|---|
| Taux de réussite des transactions | Détecter les problèmes tôt |
| Latence de confirmation | Surveiller la santé du réseau |
| Dépense de frais prioritaires | Gestion des coûts |
| Taux d'erreur RPC | Santé 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 | Émetteur | Adresse du Mint |
|---|---|---|
| USDC | Circle | EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v |
| USDT | Tether | Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB |
| PYUSD | PayPal | 2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo |
| USDG | Paxos | 2u1tszSeqZ3qBWF3uNGPFc8TzMk2tdiwknnRMWGWjGWH |
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 :
| Programme | Adresse |
|---|---|
| Token Program | TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA |
| Token-2022 Program | TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb |
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 cleanrisque 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 deploygè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?