Costruire localmente e testare su devnet sono ottimi modi per iniziare con i pagamenti Solana. Tuttavia, quando sei pronto per il deployment su mainnet, devi essere consapevole delle sfumature della mainnet. La devnet perdona gli errori. La mainnet no. Questa guida copre le differenze che contano per garantire ai tuoi utenti un'esperienza fluida.
| Devnet | Mainnet |
|---|---|
| SOL gratuiti dai faucet | Acquista SOL reali per le commissioni |
| Bassa competizione per lo spazio nei blocchi | Le commissioni di priorità contano |
| Le transazioni vengono confermate facilmente | La configurazione delle transazioni è critica |
| L'RPC pubblico va bene | È richiesto un RPC di produzione |
| Keypair e mint di devnet | Chiavi e token mint diversi—aggiorna la tua configurazione |
Infrastruttura RPC
Gli
endpoint pubblici
(api.mainnet-beta.solana.com) hanno limiti di velocità senza SLA. Vanno bene
per lo sviluppo ma falliranno nei flussi di pagamento in produzione—come cercare
di gestire un processore di pagamenti attraverso un'API condivisa senza garanzia
di uptime.
Non usare mai RPC pubblici per la produzione
Usa un provider RPC privato per un accesso affidabile e a bassa latenza.
Quando scegli un provider RPC, cerca:
- Affidabilità: SLA con garanzie di uptime (99,9%+)
- Latenza: prossimità geografica ai tuoi utenti
- Funzionalità: funzionalità di conferma delle transazioni, indicizzazione, API per le commissioni di priorità
Per un elenco completo dei provider RPC, consulta la guida Provider di infrastruttura RPC.
Configurazione RPC ridondante
Come qualsiasi fornitore di servizi di rete, i provider RPC possono subire downtime o periodi di prestazioni degradate. Per garantire che la tua applicazione sia resiliente, dovresti configurare la tua applicazione per utilizzare più provider RPC.
Solana Kit fornisce una libreria per personalizzare i trasporti RPC che ti consente di costruire il tuo client RPC ridondante. Ecco un esempio di come potresti utilizzarlo per costruire un client RPC ridondante:
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);}
Se preferisci non costruire i tuoi strumenti di routing, puoi sfruttare un servizio di terze parti come Iron Forge per gestire il routing al posto tuo.
Atterraggio delle transazioni
Su Devnet, le transazioni atterrano abbastanza facilmente. Su Mainnet, stai competendo per lo spazio nei blocchi. Per aumentare le probabilità che la tua transazione venga inclusa in un blocco, dovresti assicurarti di aver assemblato correttamente la tua transazione. Questo significa:
- includere un blockhash recente prima di inviare la transazione
- includere un'istruzione di commissione prioritaria nella transazione con una commissione prioritaria competitiva
- includere un'istruzione di limite delle unità di calcolo nella transazione con un limite di unità di calcolo basato sulle unità di calcolo stimate richieste per la transazione
Inoltre, dovresti considerare altri strumenti come Jito Bundles per aumentare le probabilità che la tua transazione venga inclusa in un blocco. Esploriamo questi strumenti in maggior dettaglio.
Configurazione dell'invio delle transazioni
Quando invii transazioni su Mainnet, configura questi parametri per tassi di atterraggio ottimali:
Gestione del blockhash:
- Recupera con commitment
confirmed - Memorizza il
lastValidBlockHeightrestituito dagetLatestBlockhash—questo ti dice quando la tua transazione scade - I blockhash scadono dopo ~150 blocchi (~60-90 secondi)
Opzioni di invio:
maxRetries: 0— Disabilita i tentativi automatici RPC. Gestisci i tentativi tu stesso in modo da poter aggiornare il blockhash quando necessario.skipPreflight: true— Ignora la simulazione prima dell'invio. Usa questa opzione quando hai già validato la transazione e vuoi la latenza più bassa. Mantienilafalsedurante lo sviluppo per individuare gli errori in anticipo.
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
Usa le commissioni prioritarie
Ogni transazione Solana richiede una commissione di transazione, pagata in SOL. Le commissioni di transazione sono suddivise in due parti: la commissione base e la commissione prioritaria. La commissione base compensa i validatori per l'elaborazione della transazione. La commissione prioritaria è una commissione opzionale, per aumentare la probabilità che il leader corrente elabori la tua transazione. Pensala come una spedizione espressa: paghi di più per una consegna più veloce e affidabile.
Come funzionano le commissioni:
Total fee = Base fee (5,000 lamports per signature) + Priority feePriority fee = Compute units x Price per unit (micro-lamports per compute unit)
Costi reali:
- Trasferimento USDC semplice: ~$0.001-0.005 in condizioni normali
- Durante la congestione: ~$0.01-0.05
- Congestione di picco: può aumentare ulteriormente
Esempio di implementazione:
Il pacchetto
@solana-program/compute-budget
fornisce una funzione helper per aggiornare o aggiungere facilmente l'istruzione
del prezzo dell'unità di calcolo (in micro-lamport) a una transazione.
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));
Ottenere stime delle commissioni: la maggior parte dei provider RPC offre API per le commissioni prioritarie:
Per i meccanismi completi delle commissioni, consulta Commissioni di transazione e la nostra guida: Come aggiungere commissioni prioritarie a una transazione.
Ottimizza le unità di calcolo
Il calcolo su Solana è effettivamente una misura della quantità di lavoro che il programma sta svolgendo. C'è un limite alla quantità di calcolo che può essere utilizzata in una transazione (attualmente 1,4 milioni di unità di calcolo) e un limite alla quantità di calcolo che può essere utilizzata per account per blocco (attualmente 100 milioni di unità di calcolo).
Quando invii una transazione, devi stimare la quantità di calcolo che verrà utilizzata e impostare di conseguenza il limite di unità di calcolo - questo è effettivamente una richiesta di quanta capacità totale dovrebbe essere riservata per la tua transazione. In pratica, ciò significa che stimare correttamente le unità di calcolo richieste per la tua transazione è fondamentale per far includere la tua transazione in un blocco (ed è importante per gestire le tue commissioni prioritarie).
L'API JSON RPC di Solana dispone di un metodo
simulatetransaction che può essere
utilizzato per stimare le unità di calcolo necessarie per una transazione,
inclusa una stima delle unità di calcolo che verranno utilizzate.
@solana/kit fornisce funzioni helper che
stimano i limiti delle risorse di una transazione e li impostano sul messaggio
in un unico passaggio (utilizzando internamente il metodo
simulatetransaction). Per le transazioni di versione 1 questi helper stimano
anche il limite della dimensione dei dati degli account caricati.
import {estimateResourceLimitsFactory,estimateAndSetResourceLimitsFactory} from "@solana/kit";const estimateResourceLimits = estimateResourceLimitsFactory({ rpc });const estimateAndSetResourceLimits = estimateAndSetResourceLimitsFactory(estimateResourceLimits);const txWithResourceLimits = await estimateAndSetResourceLimits(tx);
Se costruisci e invii transazioni con un client plugin kit, in genere non hai
bisogno di questo passaggio — il client aggiunge automaticamente le istruzioni
del budget di calcolo durante l'invio (.sendTransaction()). Il flusso
manuale sopra descritto è per quando assembli le transazioni direttamente con
@solana/kit.
In produzione, se si ripete lo stesso tipo di transazione più volte, è consigliabile memorizzare nella cache la stima del calcolo per quel tipo di transazione per evitare il sovraccarico derivante dalla stima delle unità di calcolo ogni volta.
Bundle Jito
I bundle Jito sono uno strumento per gestire l'esecuzione atomica di più transazioni. Ciò viene ottenuto inviando più transazioni alla rete Jito con una mancia. Le mance possono essere utilizzate per incentivare la rete Jito a includere le transazioni in un blocco.
Risorse:
Strategie di Ritentativo
Le transazioni possono fallire per molte ragioni. A differenza delle tradizionali API di pagamento che restituiscono immediatamente esito positivo o negativo, le transazioni blockchain richiedono il monitoraggio della conferma.
Concetti chiave:
- Scadenza del blockhash: Le transazioni sono valide per ~150 blocchi (~60-90 secondi)
- Idempotenza: La stessa transazione firmata produce sempre la stessa firma — il reinvio è sicuro
- Backoff esponenziale: Evita di sovraccaricare la rete con tentativi rapidi
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;}
Il sendAndConfirmTransactionFactory di @solana/kit gestisce automaticamente
il polling delle conferme e il tracciamento dell'altezza del blocco. Genera
SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED quando il blockhash della transazione
scade, segnalando che è necessario ricostruire la transazione con un blockhash
aggiornato.
Risorse aggiuntive
- Guida: Conferma ed Espirazione delle Transazioni
- Helius: Come finalizzare le transazioni su Solana
- QuickNode: Strategie per ottimizzare le transazioni su Solana
Comprendere i livelli di conferma
Solana offre tre livelli di conferma. In termini di finanza tradizionale:
| Livello | Definizione Solana | Equivalente tradizionale | Caso d'uso |
|---|---|---|---|
processed | In un blocco, non ancora votato | Autorizzazione in sospeso | Aggiornamenti UI in tempo reale |
confirmed | Supermajority votata | Fondi liquidati | Pagamenti comuni |
finalized | Radicato, irreversibile | Fondi regolati | Alto valore, conformità |
Quando usare ciascun livello:
- Aggiornamenti UI: Mostra
processedper un feedback immediato ("Pagamento inviato") - Accredito sull'account utente: Attendi
confirmed(sicuro per la maggior parte delle transazioni) - Spedizione di beni fisici: Attendi
finalized - Prelievi ingenti: Attendi
finalized - Conformità/audit: Registra sempre lo stato
finalized
Per ulteriori informazioni sulla verifica dello stato delle transazioni, consulta Interagire con Solana.
Gestione degli errori
Solana Kit fornisce errori tipizzati tramite isSolanaError(). Utilizza codici
di errore specifici anziché il confronto tra stringhe:
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 };}
Codici di errore comuni:
| Codice di errore | Causa | Soluzione |
|---|---|---|
BLOCK_HEIGHT_EXCEEDED | Blockhash scaduto | Ricostruire con un blockhash aggiornato |
BLOCKHASH_NOT_FOUND | Blockhash non trovato | Ricostruire con un blockhash aggiornato |
INSUFFICIENT_FUNDS_FOR_FEE | SOL insufficiente | Finanziare il pagatore delle commissioni o usare l'astrazione delle commissioni |
INSUFFICIENT_FUNDS | Token insufficienti | L'utente deve disporre di un saldo maggiore |
ACCOUNT_NOT_FOUND | token account mancante | Creare l'ATA nella transazione |
Transazioni Senza Gas
Gli utenti si aspettano di pagare in stablecoin, senza dover acquisire SOL per le commissioni di rete. Le transazioni senza gas risolvono questo problema—in modo simile a come gli utenti di Venmo non pensano alle commissioni ACH. Consulta Astrazione delle Commissioni per un'implementazione completa.
Sicurezza
Gestione delle Chiavi
- Non esporre mai le chiavi private nel codice frontend. Utilizza la firma backend, hardware wallet, wallet multifirma o servizi di gestione delle chiavi.
- Separa i wallet hot e cold. Il wallet hot per le operazioni, il cold per la tesoreria.
- Esegui il backup di tutte le chiavi di produzione. Archivia backup cifrati in più luoghi sicuri. Perdere una chiave significa perdere l'accesso in modo permanente.
- Usa chiavi diverse per devnet e mainnet. Le tue chiavi devnet non dovrebbero essere le tue chiavi mainnet. Utilizza una configurazione basata sull'ambiente per garantire che le chiavi corrette vengano caricate per ciascuna rete.
Infrastruttura di Firma
Per la firma backend in produzione, utilizza Keychain—una libreria di firma unificata che astrae più backend di gestione delle chiavi tramite un'unica interfaccia: Memory, Vault, Privy, Turnkey, AWS KMS, Fireblocks, GCP KMS, CDP, Para, Dfns, Crossmint, Openfort e Utila. Questo ti consente di sviluppare localmente con chiavi in memoria, per poi passare a backend di livello produzione senza modificare il codice dell'applicazione.
Non sai quale backend fa al caso tuo? Consulta Scegliere un backend. Keychain è disponibile sia per Rust che per TypeScript.
Sicurezza RPC
Tratta gli endpoint RPC come chiavi API—non esporli nel codice frontend dove possono essere estratti e abusati. Utilizza un proxy backend o variabili d'ambiente che non vengono incluse nel codice client.
- QuickNode: Best Practice per la Sicurezza degli Endpoint
- Helius: Proteggi le Tue Chiavi API Solana: Best Practice di Sicurezza
Monitoraggio
Traccia queste metriche in produzione:
| Metrica | Perché |
|---|---|
| Tasso di successo transazioni | Rilevare problemi tempestivamente |
| Latenza di conferma | Monitorare la salute della rete |
| Spesa commissioni prioritarie | Gestione dei costi |
| Tasso di errore RPC | Salute del provider |
Configura avvisi per:
- Trasferimenti superiori alla soglia dal treasury
- Picchi nel tasso di transazioni fallite
- Pattern di destinatari insoliti
- Aumenti nel tasso di errore RPC
Per il monitoraggio delle transazioni in tempo reale su larga scala, consulta la nostra Guida all'Indicizzazione.
Verifica degli Indirizzi
Ogni token e programma ha esattamente un indirizzo corretto sulla mainnet. I token contraffatti che imitano USDC o altre stablecoin sono comuni—avranno lo stesso nome e simbolo ma un mint diverso. La tua applicazione dovrebbe codificare direttamente o inserire in allowlist gli indirizzi mint (in base ai tuoi requisiti), senza mai accettarli dinamicamente da fonti non attendibili.
Configurazione basata sull'ambiente: Devnet e Mainnet utilizzano spesso mint di token completamente diversi. Configura la tua applicazione per caricare gli indirizzi corretti per ciascun ambiente—non inserire indirizzi mainnet in modo statico per poi dimenticarti di cambiarli durante i test, o peggio ancora, rilasciare in produzione indirizzi devnet.
Alcuni mint comuni di stablecoin sono:
| Token | Emittente | Indirizzo Mint |
|---|---|---|
| USDC | Circle | EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v |
| USDT | Tether | Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB |
| PYUSD | PayPal | 2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo |
| USDG | Paxos | 2u1tszSeqZ3qBWF3uNGPFc8TzMk2tdiwknnRMWGWjGWH |
Anche gli indirizzi dei programmi sono importanti. Inviare istruzioni al programma sbagliato provocherà un errore—o peggio, la perdita irreversibile di fondi. Gli indirizzi del Token Program sono:
| Programma | Indirizzo |
|---|---|
| Token Program | TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA |
| Token-2022 Program | TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb |
L'inserimento nella lista degli indirizzi consentiti protegge dai token contraffatti, ma non protegge dall'invio al tipo sbagliato di account. Un indirizzo destinatario può essere un wallet, un token account, un mint o un programma, e ognuno richiede una gestione diversa. SOL nativo inviato a qualsiasi cosa che non sia un wallet sfugge al controllo del mittente — perso definitivamente nel caso di un mint o di un programma, recuperabile solo dal proprietario dell'account nel caso di un token account — senza alcuna transazione fallita che avvisi l'utente.
Valida i destinatari prima di inviare
Classifica ogni indirizzo destinatario prima di firmare un trasferimento. Consulta Verifica Indirizzo per l'albero decisionale completo e il codice di riferimento che distingue wallet, token account, mint e programmi.
Checklist Pre-Lancio
- SOL mainnet acquisito per commissioni e rent
- RPC di produzione configurato (non endpoint pubblico)
- Endpoint RPC di fallback configurato
- Commissioni prioritarie implementate con prezzi dinamici
- La logica di retry gestisce la scadenza del blockhash
- Livello di conferma appropriato per il caso d'uso
- Tutti gli errori comuni gestiti correttamente
- Gasless configurato (se applicabile)
- Indirizzi token mainnet verificati (non mint devnet)
- Validazione dell'indirizzo destinatario prima dell'invio (wallet vs token account vs mint vs programma)
- Tutte le chiavi salvate in modo sicuro
- Gestione delle chiavi verificata (nessuna chiave nel frontend)
- Monitoraggio e alerting delle transazioni attivi
- Test di carico al volume previsto
Distribuzione dei Programmi
Se stai distribuendo un programma Solana personalizzato come parte della tua infrastruttura di pagamento, ci sono considerazioni aggiuntive.
Pre-distribuzione
- Versione della Solana CLI: Assicurati di utilizzare la versione più recente della Solana CLI.
- keypair del programma: Il tuo programma avrà un indirizzo diverso sulla
mainnet rispetto alla devnet (a meno che tu non stia riutilizzando lo stesso
keypair). Aggiorna tutti i riferimenti nella configurazione della tua
applicazione. Conserva il keypair del tuo programma in un luogo sicuro (nota
che l'esecuzione di
cargo cleanpotrebbe eliminare il keypair del tuo programma). - Inizializzazione degli account: Se il tuo programma richiede account amministratore, PDA o altri account di stato, assicurati che questi vengano creati sulla mainnet prima che gli utenti interagiscano con la tua applicazione. Lo stesso vale per qualsiasi associated token account (ATA) richiesto dal tuo programma.
Processo di distribuzione
- Account buffer: I programmi di grandi dimensioni vengono distribuiti
tramite account buffer. Il comando
solana program deploygestisce questo automaticamente, ma tieni presente che la distribuzione non è atomica—se viene interrotta, potrebbe essere necessario recuperare o chiudere gli account buffer. Consulta Distribuzione dei programmi. - Autorità di aggiornamento: Decidi se il tuo programma deve essere aggiornabile dopo il lancio. Per garantire l'immutabilità, revoca l'autorità di aggiornamento dopo la distribuzione. Per maggiore flessibilità, proteggi adeguatamente la chiave dell'autorità di aggiornamento.
- Rent: Assicurati che il tuo wallet di distribuzione disponga di SOL sufficiente a coprire i minimi di esenzione dal rent per tutti i program account.
- Verifica: Verifica il tuo programma per assicurarti che il programma eseguibile che distribuisci sulla rete di Solana corrisponda al codice sorgente nel tuo repository
Per una guida completa alla distribuzione dei programmi, consulta Distribuzione dei programmi.
Is this page helpful?