Локальна розробка та тестування на devnet — чудові способи почати роботу з платежами Solana. Однак, коли ви готові до розгортання на Mainnet, потрібно врахувати нюанси mainnet. Devnet прощає помилки. Mainnet — ні. Цей посібник охоплює відмінності, які мають значення для забезпечення безперебійного досвіду ваших користувачів.
| Devnet | Mainnet |
|---|---|
| Безкоштовний SOL з кранів | Придбайте справжній SOL для комісій |
| Низька конкуренція за місце у блоці | Пріоритетні комісії мають значення |
| Транзакції проходять легко | Конфігурація транзакцій критична |
| Публічний RPC підходить | Потрібен продакшн RPC |
| Ключі та токени devnet | Інші ключі та токени — оновіть конфігурацію |
RPC-інфраструктура
Публічні ендпоінти
(api.mainnet-beta.solana.com) мають обмеження швидкості без SLA. Вони
підходять для розробки, але не витримають продакшн платіжних потоків — це як
намагатися запустити платіжний процесор через спільний API без гарантій
безвідмовності.
Ніколи не використовуйте публічний RPC для продакшену
Використовуйте приватного RPC-провайдера для надійного доступу з низькою затримкою.
При виборі RPC-провайдера зверніть увагу на:
- Надійність: SLA з гарантіями безвідмовності (99,9%+)
- Затримка: географічна близькість до ваших користувачів
- Функції: функції доставки транзакцій, індексація, API пріоритетних комісій
Повний список RPC-провайдерів дивіться у посібнику Провайдери RPC-інфраструктури.
Резервна конфігурація RPC
Як і будь-який постачальник мережевих послуг, RPC-провайдери можуть зазнавати простоїв або періодів погіршення продуктивності. Щоб забезпечити стійкість вашого застосунку, слід налаштувати його на використання кількох RPC-провайдерів.
Solana Kit надає бібліотеку для налаштування RPC-транспортів, що дозволяє створювати власний резервний RPC-клієнт. Ось приклад того, як ви можете використати його для створення резервного RPC-клієнта:
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);}
Якщо ви не хочете створювати власні інструменти маршрутизації, ви можете скористатися стороннім сервісом, таким як Iron Forge, щоб він обробляв маршрутизацію за вас.
Підтвердження транзакції
У Devnet транзакції підтверджуються досить легко. У Mainnet ви конкуруєте за місце в блоці. Щоб збільшити шанси включення вашої транзакції в блок, ви повинні переконатися, що правильно зібрали транзакцію. Це означає:
- включення свіжого blockhash перед відправкою транзакції
- включення інструкції пріоритетної комісії в транзакцію з конкурентною пріоритетною комісією
- включення інструкції ліміту обчислювальних одиниць у транзакцію з лімітом обчислювальних одиниць на основі оцінки необхідних обчислювальних одиниць для транзакції
Крім того, ви повинні розглянути інші інструменти, такі як Jito Bundles, щоб збільшити шанси включення вашої транзакції в блок. Давайте детальніше розглянемо ці інструменти.
Конфігурація відправки транзакції
Під час відправки транзакцій у Mainnet налаштуйте ці параметри для оптимальних показників підтвердження:
Управління blockhash:
- Отримуйте з
confirmedcommitment - Зберігайте
lastValidBlockHeight, повернутийgetLatestBlockhash— це вказує, коли закінчується термін дії вашої транзакції - Термін дії blockhash закінчується через ~150 блоків (~60-90 секунд)
Параметри відправки:
maxRetries: 0— Вимкнути автоматичні повторні спроби RPC. Обробляйте повторні спроби самостійно, щоб ви могли оновити blockhash за потреби.skipPreflight: true— Пропустити симуляцію перед відправкою. Використовуйте це, коли ви вже перевірили транзакцію і хочете найменшу затримку. Залишайтеfalseпід час розробки, щоб виявляти помилки на ранніх етапах.
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
Використовуйте пріоритетні комісії
Кожна транзакція Solana вимагає комісії за транзакцію, яка сплачується в SOL. Комісії за транзакції поділяються на дві частини: базову комісію та пріоритетну комісію. Базова комісія компенсує валідаторам обробку транзакції. Пріоритетна комісія — це додаткова комісія, яка збільшує ймовірність того, що поточний лідер обробить вашу транзакцію. Уявіть це як експрес-доставку: ви платите більше за швидшу та надійнішу доставку.
Як працюють комісії:
Total fee = Base fee (5,000 lamports per signature) + Priority feePriority fee = Compute units x Price per unit (micro-lamports per compute unit)
Реальні витрати:
- Простий переказ USDC: ~$0.001-0.005 за звичайних умов
- Під час перевантаження: ~$0.01-0.05
- Пікове перевантаження: може зростати вище
Приклад реалізації:
Пакет
@solana-program/compute-budget
надає допоміжну функцію для легкого оновлення або додавання інструкції ціни
обчислювальної одиниці (у мікролампортах) до транзакції.
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));
Отримання оцінок комісій: більшість RPC-провайдерів пропонують API пріоритетних комісій:
Для повної механіки комісій дивіться Комісії за транзакції та наш посібник: Як додати пріоритетні комісії до транзакції.
Оптимізуйте обчислювальні одиниці
Обчислення в Solana — це фактично міра обсягу роботи, яку виконує програма. Існує ліміт на кількість обчислень, які можна використати в транзакції (наразі 1,4 мільйона обчислювальних одиниць), та ліміт на кількість обчислень, які можна використати на акаунт за блок (наразі 100 мільйонів обчислювальних одиниць).
Коли ви надсилаєте транзакцію, вам потрібно оцінити кількість обчислень, які будуть використані, та відповідно встановити ліміт обчислювальних одиниць — це фактично запит на те, яка частина загальної потужності має бути зарезервована для вашої транзакції. На практиці це означає, що правильна оцінка обчислювальних одиниць, необхідних для вашої транзакції, є критично важливою для включення вашої транзакції в блок (і важливою для управління вашими пріоритетними комісіями).
Solana JSON RPC API має метод
simulatetransaction, який можна
використовувати для оцінки обчислювальних одиниць, необхідних для транзакції, що
включає оцінку обчислювальних одиниць, які будуть використані. Пакет
@solana-program/compute-budget
надає допоміжну функцію для легкої оцінки обчислювальних одиниць, необхідних для
транзакції (яка використовує метод simulatetransaction під капотом).
import {estimateComputeUnitLimitFactory,updateOrAppendSetComputeUnitLimitInstruction} from "@solana-program/compute-budget";const estimateComputeUnitLimit = estimateComputeUnitLimitFactory({ rpc });const computeUnitLimit = await estimateComputeUnitLimit(tx);const txWithComputeUnitLimit = updateOrAppendSetComputeUnitLimitInstruction(computeUnitLimit,tx);
У продакшені, якщо ви повторюєте один і той самий тип транзакції кілька разів, варто розглянути кешування оцінки обчислень для типу транзакції, щоб уникнути накладних витрат на оцінку обчислювальних одиниць щоразу.
Jito Bundles
Jito bundles — це інструмент для керування атомарним виконанням кількох транзакцій. Це досягається шляхом надсилання кількох транзакцій до мережі Jito з чайовими. Чайові можна використовувати для стимулювання мережі Jito включити ваші транзакції в блок.
Ресурси:
Стратегії повторних спроб
Транзакції можуть не виконатися з багатьох причин. На відміну від традиційних платіжних API, які повертають успіх/невдачу негайно, блокчейн-транзакції вимагають відстеження підтвердження.
Ключові концепції:
- Закінчення терміну дії blockhash: транзакції дійсні протягом ~150 блоків (~60-90 секунд)
- Ідемпотентність: одна й та сама підписана транзакція завжди створює той самий підпис — повторне надсилання безпечне
- Експоненційна затримка: уникайте перевантаження мережі швидкими повторними спробами
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;}
sendAndConfirmTransactionFactory з @solana/kit автоматично обробляє
опитування підтвердження та відстеження висоти блоку. Він викидає
SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED, коли закінчується термін дії blockhash
транзакції, сигналізуючи, що потрібно перебудувати транзакцію зі свіжим
blockhash.
Додаткові ресурси
- Посібник: Підтвердження та закінчення терміну дії транзакцій
- Helius: Як успішно виконувати транзакції в Solana
- QuickNode: Стратегії оптимізації транзакцій Solana
Розуміння рівнів підтвердження
Solana пропонує три рівні підтвердження. У термінах традиційних фінансів:
| Рівень | Визначення в Solana | Традиційний еквівалент | Випадок використання |
|---|---|---|---|
processed | У блоці, ще не проголосовано | Очікує авторизації | Оновлення UI в реальному часі |
confirmed | Проголосовано суперменшістю | Підтверджені кошти | Більшість платежів |
finalized | Закріплено, незворотно | Остаточно зараховані кошти | Великі суми, комплаєнс |
Коли використовувати кожен:
- Оновлення UI: Показуйте
processedдля миттєвого зворотного зв'язку ("Платіж надіслано") - Зарахування на рахунок користувача: Очікуйте
confirmed(безпечно для більшості транзакцій) - Відправлення фізичних товарів: Очікуйте
finalized - Великі виведення коштів: Очікуйте
finalized - Комплаєнс/аудит: Завжди записуйте статус
finalized
Докладніше про перевірку статусу транзакцій див. Взаємодія з Solana.
Обробка помилок
Solana Kit надає типізовані помилки через isSolanaError(). Використовуйте
конкретні коди помилок замість порівняння рядків:
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 };}
Поширені коди помилок:
| Код помилки | Причина | Відновлення |
|---|---|---|
BLOCK_HEIGHT_EXCEEDED | Blockhash застарів | Перебудуйте зі свіжим blockhash |
BLOCKHASH_NOT_FOUND | Blockhash не знайдено | Перебудуйте зі свіжим blockhash |
INSUFFICIENT_FUNDS_FOR_FEE | Недостатньо SOL | Поповніть рахунок платника комісії або використайте абстракцію комісій |
INSUFFICIENT_FUNDS | Недостатньо токенів | Користувачу потрібен більший баланс |
ACCOUNT_NOT_FOUND | Відсутній token account | Створіть ATA в транзакції |
Транзакції без комісій
Користувачі очікують платити стейблкоїнами, а не купувати SOL для мережевих комісій. Транзакції без комісій вирішують це — подібно до того, як користувачі Venmo не думають про комісії ACH. Див. Абстракція комісій для повної реалізації.
Безпека
Управління ключами
- Ніколи не розкривайте приватні ключі у фронтенд-коді. Використовуйте підписання на бекенді, апаратні гаманці, мультипідписні гаманці або сервіси управління ключами.
- Розділяйте гарячі та холодні гаманці. Гарячий гаманець для операцій, холодний для казначейства.
- Створюйте резервні копії всіх продакшн-ключів. Зберігайте зашифровані резервні копії в кількох безпечних місцях. Втрата ключа означає безповоротну втрату доступу.
- Використовуйте різні ключі для devnet і mainnet. Ваші ключі devnet не повинні бути ключами mainnet. Використовуйте конфігурацію на основі середовища, щоб забезпечити завантаження правильних ключів для кожної мережі.
Безпека RPC
Ставтеся до RPC-ендпоінтів як до API-ключів — не розкривайте їх у фронтенд-коді, звідки їх можна витягти та зловжити. Використовуйте бекенд-проксі або змінні середовища, які не включаються в клієнтський код.
- QuickNode: найкращі практики безпеки ендпоінтів
- Helius: захистіть свої API-ключі Solana: найкращі практики безпеки
Моніторинг
Відстежуйте ці метрики в продакшні:
| Метрика | Навіщо |
|---|---|
| Рівень успішності транзакцій | Раннє виявлення проблем |
| Затримка підтвердження | Моніторинг здоров'я мережі |
| Витрати на пріоритетну комісію | Управління витратами |
| Рівень помилок RPC | Здоров'я провайдера |
Налаштуйте сповіщення для:
- Переказів вище порогу з казначейства
- Сплесків рівня невдалих транзакцій
- Незвичних патернів одержувачів
- Зростання рівня помилок RPC
Для моніторингу транзакцій у реальному часі в масштабі див. наш посібник з індексації.
Перевірка адрес
Кожен токен і програма мають рівно одну правильну адресу в мейннеті. Підроблені токени, що імітують USDC або інші стейблкоїни, є поширеним явищем — вони матимуть ту саму назву та символ, але іншу адресу mint. Ваш застосунок повинен жорстко кодувати або додавати до білого списку адреси mint (залежно від ваших вимог), ніколи не приймати їх динамічно з ненадійних джерел.
Конфігурація на основі середовища: Devnet і Mainnet часто використовують абсолютно різні mint токенів. Налаштуйте конфігурацію вашого застосунку для завантаження правильних адрес для кожного середовища — не жорстко кодуйте адреси мейннету і не забувайте їх змінювати під час тестування, або, що ще гірше, не відправляйте адреси devnet у продакшн.
Деякі поширені mint стейблкоїнів:
| Токен | Емітент | Адреса mint |
|---|---|---|
| USDC | Circle | EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v |
| USDT | Tether | Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB |
| PYUSD | PayPal | 2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo |
| USDG | Paxos | 2u1tszSeqZ3qBWF3uNGPFc8TzMk2tdiwknnRMWGWjGWH |
Адреси програм також мають значення. Надсилання інструкцій до неправильної програми призведе до помилки — або, що ще гірше, до безповоротної втрати коштів. Адреси Token Program:
| Програма | Адреса |
|---|---|
| Token Program | TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA |
| Token-2022 Program | TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb |
Чек-лист перед запуском
- Придбано SOL у мейннеті для комісій та rent
- Налаштовано продакшн RPC (не публічна кінцева точка)
- Налаштовано резервну кінцеву точку RPC
- Реалізовано пріоритетні комісії з динамічним ціноутворенням
- Логіка повторних спроб обробляє закінчення терміну дії blockhash
- Рівень підтвердження відповідає випадку використання
- Усі поширені помилки обробляються коректно
- Налаштовано gasless (якщо застосовно)
- Перевірено адреси токенів мейннету (не mint devnet)
- Усі ключі надійно збережено
- Переглянуто управління ключами (немає ключів у фронтенді)
- Активний моніторинг транзакцій та сповіщення
- Проведено навантажувальне тестування на очікуваному обсязі
Розгортання програм
Якщо ви розгортаєте власну програму Solana як частину вашої платіжної інфраструктури, є додаткові міркування.
Перед розгортанням
- Версія Solana CLI: Переконайтеся, що ви використовуєте останню версію Solana CLI.
- Keypair програми: Ваша програма матиме іншу адресу в mainnet, ніж у devnet
(якщо ви не використовуєте той самий keypair повторно). Оновіть усі посилання
в конфігурації вашого застосунку. Зберігайте keypair вашої програми в
безпечному місці (зауважте, що виконання
cargo cleanймовірно видалить keypair вашої програми). - Ініціалізація акаунтів: Якщо ваша програма потребує адміністративних акаунтів, PDA або інших акаунтів стану, переконайтеся, що вони створені в mainnet до того, як користувачі взаємодіятимуть з вашим застосунком. Те саме стосується будь-яких Associated Token Accounts (ATA), які потрібні вашій програмі.
Процес розгортання
- Буферні акаунти: Великі програми розгортаються через буферні акаунти.
Команда
solana program deployобробляє це автоматично, але майте на увазі, що розгортання не є атомарним — якщо його перервано, вам може знадобитися відновити або закрити буферні акаунти. Див. Deploying Programs. - Права на оновлення: Вирішіть, чи має ваша програма бути оновлюваною після запуску. Для незмінності відкличте права на оновлення після розгортання. Для гнучкості належним чином захистіть ключ прав на оновлення.
- Rent: Переконайтеся, що ваш гаманець для розгортання має достатньо SOL для покриття мінімумів, звільнених від rent, для всіх акаунтів програми.
- Верифікація: Верифікуйте вашу програму, щоб переконатися, що виконувана програма, яку ви розгортаєте в мережі Solana, відповідає вихідному коду у вашому репозиторії
Для повного керівництва з розгортання програм див. Deploying Programs.
Is this page helpful?