Lokales Entwickeln und Testen im Devnet sind großartige Möglichkeiten, um mit Solana-Zahlungen zu beginnen. Wenn Sie jedoch bereit sind, im Mainnet zu deployen, müssen Sie sich der Besonderheiten des Mainnets bewusst sein. Das Devnet verzeiht Fehler. Das Mainnet nicht. Dieser Leitfaden behandelt die wichtigen Unterschiede, um sicherzustellen, dass Ihre Nutzer eine reibungslose Erfahrung haben.
| Devnet | Mainnet |
|---|---|
| Kostenlose SOL von Faucets | Echte SOL erwerben für Fees |
| Geringe Konkurrenz um Block-Space | Priority Fees sind wichtig |
| Transaktionen landen problemlos | Transaktionskonfiguration ist entscheidend |
| Öffentliche RPC ist ausreichend | Produktions-RPC erforderlich |
| Devnet-Keypairs und Mints | Andere Keys und Token-Mints – aktualisieren Sie Ihre Konfiguration |
RPC-Infrastruktur
Öffentliche Endpoints
(api.mainnet-beta.solana.com) sind ratenlimitiert ohne SLA. Sie sind für die
Entwicklung geeignet, werden aber Produktions-Zahlungsabläufe zum Scheitern
bringen – als würden Sie versuchen, einen Zahlungsabwickler über eine gemeinsam
genutzte API ohne Verfügbarkeitsgarantie zu betreiben.
Verwenden Sie niemals öffentliche RPC für die Produktion
Nutzen Sie einen privaten RPC-Provider für zuverlässigen Zugriff mit niedriger Latenz.
Bei der Auswahl eines RPC-Providers sollten Sie auf Folgendes achten:
- Zuverlässigkeit: SLAs mit Verfügbarkeitsgarantien (99,9 %+)
- Latenz: geografische Nähe zu Ihren Nutzern
- Features: Transaction-Landing-Features, Indexierung, Priority-Fee-APIs
Eine vollständige Liste der RPC-Provider finden Sie im Leitfaden RPC Infrastructure Providers.
Redundante RPC-Konfiguration
Wie jeder Netzwerkdienstanbieter können auch RPC-Provider Ausfallzeiten oder Phasen mit eingeschränkter Leistung erleben. Um sicherzustellen, dass Ihre Anwendung resilient ist, sollten Sie Ihre Anwendung so konfigurieren, dass sie mehrere RPC-Provider verwendet.
Solana Kit bietet eine Bibliothek zur Anpassung von RPC-Transporten, mit der Sie Ihren eigenen redundanten RPC-Client erstellen können. Hier ist ein Beispiel, wie Sie ihn zum Aufbau eines redundanten RPC-Clients verwenden könnten:
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);}
Wenn Sie es vorziehen, keine eigenen Routing-Tools zu erstellen, können Sie einen Drittanbieterdienst wie Iron Forge nutzen, um das Routing für Sie zu übernehmen.
Transaktionslandung
Im Devnet landen Transaktionen relativ einfach. Im Mainnet konkurrieren Sie um Blockspeicherplatz. Um die Chancen zu erhöhen, dass Ihre Transaktion in einen Block aufgenommen wird, sollten Sie sicherstellen, dass Sie Ihre Transaktion korrekt zusammengestellt haben. Das bedeutet:
- Einfügen eines aktuellen Blockhashes vor dem Senden der Transaktion
- Einfügen einer Priority-Fee-Anweisung in die Transaktion mit einer wettbewerbsfähigen Priority Fee
- Einfügen einer Compute-Unit-Limit-Anweisung in die Transaktion mit einem Compute-Unit-Limit basierend auf den geschätzten Compute Units, die für die Transaktion erforderlich sind
Zusätzlich sollten Sie andere Tools wie Jito Bundles in Betracht ziehen, um die Chancen zu erhöhen, dass Ihre Transaktion in einen Block aufgenommen wird. Lassen Sie uns diese Tools genauer betrachten.
Konfiguration des Transaktionsversands
Beim Senden von Transaktionen im Mainnet konfigurieren Sie diese Parameter für optimale Landeraten:
Blockhash-Verwaltung:
- Abrufen mit
confirmed-Commitment - Speichern Sie den
lastValidBlockHeight, der vongetLatestBlockhashzurückgegeben wird – dieser zeigt Ihnen, wann Ihre Transaktion abläuft - Blockhashes laufen nach ~150 Blöcken (~60-90 Sekunden) ab
Sendeoptionen:
maxRetries: 0— Deaktiviert automatische RPC-Wiederholungen. Verwalten Sie Wiederholungen selbst, damit Sie den Blockhash bei Bedarf aktualisieren können.skipPreflight: true— Umgeht die Simulation vor dem Senden. Verwenden Sie dies, wenn Sie die Transaktion bereits validiert haben und die niedrigste Latenz wünschen. Behalten Sie es während der Entwicklung auffalse, um Fehler frühzeitig zu erkennen.
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
Priority fees verwenden
Jede Solana-Transaktion erfordert eine Transaktionsgebühr, die in SOL bezahlt wird. Transaktionsgebühren werden in zwei Teile aufgeteilt: die Basisgebühr und die Priority fee. Die Basisgebühr entschädigt Validatoren für die Verarbeitung der Transaktion. Die Priority fee ist eine optionale Gebühr, um die Chance zu erhöhen, dass der aktuelle Leader Ihre Transaktion verarbeitet. Stellen Sie es sich wie einen Expressversand vor: Sie zahlen mehr für eine schnellere, zuverlässigere Zustellung.
So funktionieren Gebühren:
Total fee = Base fee (5,000 lamports per signature) + Priority feePriority fee = Compute units x Price per unit (micro-lamports per compute unit)
Kosten in der Praxis:
- Einfache USDC-Überweisung: ~0,001–0,005 $ unter normalen Bedingungen
- Bei Überlastung: ~0,01–0,05 $
- Spitzenüberlastung: kann höher steigen
Beispielimplementierung:
Das
@solana-program/compute-budget-Paket
bietet eine Hilfsfunktion, um die Anweisung für den Compute-Unit-Preis (in
Micro-Lamports) einfach zu aktualisieren oder an eine Transaktion anzuhängen.
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));
Gebührenschätzungen erhalten: Die meisten RPC-Anbieter bieten Priority-Fee-APIs an:
Für die vollständige Fee-Mechanik siehe Transaktionsgebühren und unseren Leitfaden: So fügen Sie Priority fees zu einer Transaktion hinzu.
Compute-Units optimieren
Compute auf Solana ist effektiv ein Maß für die Menge an Arbeit, die das Programm leistet. Es gibt eine Begrenzung für die Menge an Compute, die in einer Transaktion verwendet werden kann (derzeit 1,4 Millionen Compute-Units), und eine Begrenzung für die Menge an Compute, die pro Konto pro Block verwendet werden kann (derzeit 100 Millionen Compute-Units).
Wenn Sie eine Transaktion einreichen, müssen Sie die Menge an Compute schätzen, die verwendet wird, und das Compute-Unit-Limit entsprechend festlegen – dies ist effektiv eine Anfrage, wie viel der Gesamtkapazität für Ihre Transaktion reserviert werden soll. In der Praxis bedeutet dies, dass die ordnungsgemäße Schätzung der für Ihre Transaktion erforderlichen Compute-Units entscheidend dafür ist, dass Ihre Transaktion in einen Block aufgenommen wird (und wichtig für die Verwaltung Ihrer Priority fees).
Die Solana JSON RPC API verfügt über eine
simulatetransaction-Methode, die
verwendet werden kann, um die für eine Transaktion erforderlichen
Recheneinheiten zu schätzen, einschließlich einer Schätzung der Recheneinheiten,
die verwendet werden. Das
@solana-program/compute-budget-Paket
bietet eine Hilfsfunktion, um die für eine Transaktion erforderlichen
Recheneinheiten einfach zu schätzen (die unter der Haube die
simulatetransaction-Methode verwendet).
import {estimateComputeUnitLimitFactory,updateOrAppendSetComputeUnitLimitInstruction} from "@solana-program/compute-budget";const estimateComputeUnitLimit = estimateComputeUnitLimitFactory({ rpc });const computeUnitLimit = await estimateComputeUnitLimit(tx);const txWithComputeUnitLimit = updateOrAppendSetComputeUnitLimitInstruction(computeUnitLimit,tx);
In der Produktion sollten Sie, wenn Sie denselben Transaktionstyp mehrmals wiederholen, erwägen, die Rechenschätzung für den Transaktionstyp zu cachen, um den Overhead der Schätzung der Recheneinheiten bei jedem Mal zu vermeiden.
Jito Bundles
Jito Bundles sind ein Tool zur Verwaltung der atomaren Ausführung mehrerer Transaktionen. Dies wird erreicht, indem mehrere Transaktionen mit einem Tip an das Jito-Netzwerk gesendet werden. Tips können verwendet werden, um das Jito-Netzwerk zu incentivieren, Ihre Transaktionen in einen Block aufzunehmen.
Ressourcen:
Retry-Strategien
Transaktionen können aus vielen Gründen fehlschlagen. Im Gegensatz zu traditionellen Payment-APIs, die sofort Erfolg/Fehler zurückgeben, erfordern Blockchain-Transaktionen ein Confirmation-Tracking.
Wichtige Konzepte:
- Blockhash-Ablauf: Transaktionen sind für ~150 Blöcke (~60-90 Sekunden) gültig
- Idempotenz: Dieselbe signierte Transaktion erzeugt immer dieselbe Signatur – erneutes Senden ist sicher
- Exponential Backoff: Vermeiden Sie es, das Netzwerk mit schnellen Wiederholungsversuchen zu überlasten
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;}
Die sendAndConfirmTransactionFactory aus @solana/kit übernimmt das
Confirmation-Polling und Block-Height-Tracking automatisch. Sie wirft
SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED, wenn der Blockhash der Transaktion
abläuft, was signalisiert, dass Sie die Transaktion mit einem frischen Blockhash
neu erstellen müssen.
Zusätzliche Ressourcen
- Leitfaden: Transaktionsbestätigung & Ablauf
- Helius: Wie man Transaktionen auf Solana landet
- QuickNode: Strategien zur Optimierung von Solana-Transaktionen
Bestätigungsstufen verstehen
Solana bietet drei Bestätigungsstufen. In traditionellen Finanzterminologie:
| Stufe | Solana-Definition | Traditionelles Äquivalent | Anwendungsfall |
|---|---|---|---|
processed | In einem Block, noch nicht abgestimmt | Ausstehende Autorisierung | Echtzeit-UI-Aktualisierungen |
confirmed | Supermehrheit hat abgestimmt | Freigegebene Mittel | Die meisten Zahlungen |
finalized | Verwurzelt, unumkehrbar | Abgerechnete Mittel | Hoher Wert, Compliance |
Wann welche Stufe verwenden:
- UI-Aktualisierungen: Zeige
processedfür sofortiges Feedback ("Zahlung übermittelt") - Benutzerkonto gutschreiben: Warte auf
confirmed(sicher für die meisten Transaktionen) - Physische Waren versenden: Warte auf
finalized - Große Abhebungen: Warte auf
finalized - Compliance/Audit: Erfasse immer den
finalized-Status
Weitere Informationen zur Überprüfung des Transaktionsstatus finden Sie unter Interaktion mit Solana.
Fehlerbehandlung
Solana Kit bietet typisierte Fehler über isSolanaError(). Verwenden Sie
spezifische Fehlercodes anstelle von String-Matching:
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 };}
Häufige Fehlercodes:
| Fehlercode | Ursache | Wiederherstellung |
|---|---|---|
BLOCK_HEIGHT_EXCEEDED | Blockhash abgelaufen | Mit frischem Blockhash neu erstellen |
BLOCKHASH_NOT_FOUND | Blockhash nicht gefunden | Mit frischem Blockhash neu erstellen |
INSUFFICIENT_FUNDS_FOR_FEE | Nicht genug SOL | Gebührenzahler finanzieren oder Gebührenabstraktion verwenden |
INSUFFICIENT_FUNDS | Nicht genug Token | Benutzer benötigt mehr Guthaben |
ACCOUNT_NOT_FOUND | Token-Konto fehlt | ATA in Transaktion erstellen |
Gebührenfreie Transaktionen
Nutzer erwarten, in Stablecoins zu zahlen, nicht SOL für Netzwerkgebühren zu erwerben. Gebührenfreie Transaktionen lösen dies – ähnlich wie Venmo-Nutzer nicht über ACH-Gebühren nachdenken. Siehe Fee-Abstraktion für die vollständige Implementierung.
Sicherheit
Schlüsselverwaltung
- Private Schlüssel niemals im Frontend-Code offenlegen. Verwenden Sie Backend-Signierung, Hardware-Wallets, Multisignatur-Wallets oder Schlüsselverwaltungsdienste.
- Hot und Cold Wallets trennen. Hot Wallet für Operationen, Cold für Treasury.
- Alle Produktionsschlüssel sichern. Verschlüsselte Backups an mehreren sicheren Orten speichern. Der Verlust eines Schlüssels bedeutet dauerhaften Zugriffsverlust.
- Unterschiedliche Schlüssel für Devnet und Mainnet verwenden. Ihre Devnet-Schlüssel sollten nicht Ihre Mainnet-Schlüssel sein. Verwenden Sie umgebungsbasierte Konfiguration, um sicherzustellen, dass die richtigen Schlüssel für jedes Netzwerk geladen werden.
RPC-Sicherheit
Behandeln Sie RPC-Endpunkte wie API-Schlüssel – legen Sie sie nicht im Frontend-Code offen, wo sie extrahiert und missbraucht werden können. Verwenden Sie einen Backend-Proxy oder Umgebungsvariablen, die nicht in Client-Code gebündelt werden.
- QuickNode: Best Practices für Endpunktsicherheit
- Helius: Schützen Sie Ihre Solana-API-Schlüssel: Best Practices für Sicherheit
Monitoring
Überwachen Sie diese Metriken in der Produktion:
| Metrik | Warum |
|---|---|
| Transaktionserfolgsrate | Probleme früh erkennen |
| Bestätigungslatenz | Netzwerkgesundheit überwachen |
| Priority-Fee-Ausgaben | Kostenmanagement |
| RPC-Fehlerrate | Provider-Gesundheit |
Richten Sie Benachrichtigungen ein für:
- Überweisungen über Schwellenwert aus Treasury
- Spitzen bei fehlgeschlagenen Transaktionen
- Ungewöhnliche Empfängermuster
- Erhöhungen der RPC-Fehlerrate
Für Echtzeit-Transaktionsüberwachung im großen Maßstab siehe unseren Indexing-Leitfaden.
Adressen verifizieren
Jeder Token und jedes Programm hat genau eine korrekte Adresse im Mainnet. Gefälschte Tokens, die USDC oder andere Stablecoins imitieren, sind weit verbreitet – sie haben denselben Namen und dasselbe Symbol, aber eine andere Mint-Adresse. Ihre Anwendung sollte die Mint-Adressen fest codieren oder auf eine Allowlist setzen (basierend auf Ihren Anforderungen) und sie niemals dynamisch aus nicht vertrauenswürdigen Quellen akzeptieren.
Umgebungsbasierte Konfiguration: Devnet und Mainnet verwenden oft völlig unterschiedliche Token-Mints. Richten Sie Ihre Anwendungskonfiguration so ein, dass sie die korrekten Adressen pro Umgebung lädt – codieren Sie nicht Mainnet-Adressen fest und vergessen Sie, diese während des Testens auszutauschen, oder noch schlimmer, liefern Sie Devnet-Adressen in die Produktion aus.
Einige gängige Stablecoin-Mints sind:
| Token | Herausgeber | Mint-Adresse |
|---|---|---|
| USDC | Circle | EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v |
| USDT | Tether | Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB |
| PYUSD | PayPal | 2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo |
| USDG | Paxos | 2u1tszSeqZ3qBWF3uNGPFc8TzMk2tdiwknnRMWGWjGWH |
Programmadressen sind ebenfalls wichtig. Das Senden von Anweisungen an das falsche Programm wird fehlschlagen – oder schlimmer noch, zu einem irreversiblen Verlust von Geldern führen. Die Token Program-Adressen sind:
| Programm | Adresse |
|---|---|
| Token Program | TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA |
| Token-2022 Program | TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb |
Checkliste vor dem Launch
- Mainnet-SOL für Fees und Rent erworben
- Produktions-RPC konfiguriert (kein öffentlicher Endpunkt)
- Fallback-RPC-Endpunkt konfiguriert
- Priority Fees mit dynamischer Preisgestaltung implementiert
- Retry-Logik behandelt Blockhash-Ablauf
- Bestätigungslevel dem Anwendungsfall angemessen
- Alle gängigen Fehler werden elegant behandelt
- Gasless konfiguriert (falls zutreffend)
- Mainnet-Token-Adressen verifiziert (keine Devnet-Mints)
- Alle Schlüssel sicher gesichert
- Schlüsselverwaltung überprüft (keine Schlüssel im Frontend)
- Transaktionsüberwachung und Alarmierung aktiv
- Lasttests mit erwartetem Volumen durchgeführt
Deployment von Programmen
Wenn Sie ein benutzerdefiniertes Solana-Programm als Teil Ihrer Zahlungsinfrastruktur deployen, gibt es zusätzliche Überlegungen.
Vor dem Deployment
- Solana CLI-Version: Stellen Sie sicher, dass Sie die neueste Version der Solana CLI verwenden.
- Programm-Keypair: Ihr Programm wird eine andere Adresse im Mainnet haben
als im Devnet (es sei denn, Sie verwenden dasselbe Keypair wieder).
Aktualisieren Sie alle Referenzen in Ihrer Anwendungskonfiguration. Bewahren
Sie Ihr Programm-Keypair an einem sicheren Ort auf (beachten Sie, dass die
Ausführung von
cargo cleanwahrscheinlich Ihr Programm-Keypair löschen wird). - Accounts initialisieren: Wenn Ihr Programm Admin-Accounts, PDAs oder andere State-Accounts benötigt, stellen Sie sicher, dass diese im Mainnet erstellt werden, bevor Benutzer mit Ihrer Anwendung interagieren. Dasselbe gilt für alle Associated Token Accounts (ATAs), die Ihr Programm benötigt.
Deployment-Prozess
- Buffer-Accounts: Große Programme werden über Buffer-Accounts deployed. Der
Befehl
solana program deployübernimmt dies automatisch, aber beachten Sie, dass das Deployment nicht atomar ist – bei Unterbrechung müssen Sie möglicherweise Buffer-Accounts wiederherstellen oder schließen. Siehe Deploying Programs. - Upgrade-Authority: Entscheiden Sie, ob Ihr Programm nach dem Launch aktualisierbar sein soll. Für Unveränderlichkeit widerrufen Sie die Upgrade-Authority nach dem Deployment. Für Flexibilität sichern Sie den Upgrade-Authority-Schlüssel entsprechend ab.
- Rent: Stellen Sie sicher, dass Ihr Deployment-Wallet genug SOL hat, um die Rent-Exempt-Minima für alle Programm-Accounts zu decken.
- Verifizierung: Verifizieren Sie Ihr Programm, um sicherzustellen, dass das ausführbare Programm, das Sie im Solana-Netzwerk deployen, mit dem Quellcode in Ihrem Repository übereinstimmt
Für eine vollständige Anleitung zum Programm-Deployment siehe Deploying Programs.
Is this page helpful?