Готовність до продакшену

Локальна розробка та тестування на devnet — чудові способи почати роботу з платежами Solana. Однак, коли ви готові до розгортання на Mainnet, потрібно врахувати нюанси mainnet. Devnet прощає помилки. Mainnet — ні. Цей посібник охоплює відмінності, які мають значення для забезпечення безперебійного досвіду ваших користувачів.

DevnetMainnet
Безкоштовний 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 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);
}

Якщо ви не хочете створювати власні інструменти маршрутизації, ви можете скористатися стороннім сервісом, таким як Iron Forge, щоб він обробляв маршрутизацію за вас.

Підтвердження транзакції

У Devnet транзакції підтверджуються досить легко. У Mainnet ви конкуруєте за місце в блоці. Щоб збільшити шанси включення вашої транзакції в блок, ви повинні переконатися, що правильно зібрали транзакцію. Це означає:

  • включення свіжого blockhash перед відправкою транзакції
  • включення інструкції пріоритетної комісії в транзакцію з конкурентною пріоритетною комісією
  • включення інструкції ліміту обчислювальних одиниць у транзакцію з лімітом обчислювальних одиниць на основі оцінки необхідних обчислювальних одиниць для транзакції

Крім того, ви повинні розглянути інші інструменти, такі як Jito Bundles, щоб збільшити шанси включення вашої транзакції в блок. Давайте детальніше розглянемо ці інструменти.

Конфігурація відправки транзакції

Під час відправки транзакцій у Mainnet налаштуйте ці параметри для оптимальних показників підтвердження:

Управління blockhash:

  • Отримуйте з confirmed commitment
  • Зберігайте 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 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

Використовуйте пріоритетні комісії

Кожна транзакція Solana вимагає комісії за транзакцію, яка сплачується в SOL. Комісії за транзакції поділяються на дві частини: базову комісію та пріоритетну комісію. Базова комісія компенсує валідаторам обробку транзакції. Пріоритетна комісія — це додаткова комісія, яка збільшує ймовірність того, що поточний лідер обробить вашу транзакцію. Уявіть це як експрес-доставку: ви платите більше за швидшу та надійнішу доставку.

Як працюють комісії:

Total fee = Base fee (5,000 lamports per signature) + Priority fee
Priority 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 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;
}

sendAndConfirmTransactionFactory з @solana/kit автоматично обробляє опитування підтвердження та відстеження висоти блоку. Він викидає SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED, коли закінчується термін дії blockhash транзакції, сигналізуючи, що потрібно перебудувати транзакцію зі свіжим blockhash.

Додаткові ресурси

Розуміння рівнів підтвердження

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 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 };
}

Поширені коди помилок:

Код помилкиПричинаВідновлення
BLOCK_HEIGHT_EXCEEDEDBlockhash застарівПеребудуйте зі свіжим blockhash
BLOCKHASH_NOT_FOUNDBlockhash не знайденоПеребудуйте зі свіжим blockhash
INSUFFICIENT_FUNDS_FOR_FEEНедостатньо SOLПоповніть рахунок платника комісії або використайте абстракцію комісій
INSUFFICIENT_FUNDSНедостатньо токенівКористувачу потрібен більший баланс
ACCOUNT_NOT_FOUNDВідсутній token accountСтворіть ATA в транзакції

Транзакції без комісій

Користувачі очікують платити стейблкоїнами, а не купувати SOL для мережевих комісій. Транзакції без комісій вирішують це — подібно до того, як користувачі Venmo не думають про комісії ACH. Див. Абстракція комісій для повної реалізації.

Безпека

Управління ключами

  • Ніколи не розкривайте приватні ключі у фронтенд-коді. Використовуйте підписання на бекенді, апаратні гаманці, мультипідписні гаманці або сервіси управління ключами.
  • Розділяйте гарячі та холодні гаманці. Гарячий гаманець для операцій, холодний для казначейства.
  • Створюйте резервні копії всіх продакшн-ключів. Зберігайте зашифровані резервні копії в кількох безпечних місцях. Втрата ключа означає безповоротну втрату доступу.
  • Використовуйте різні ключі для devnet і mainnet. Ваші ключі devnet не повинні бути ключами mainnet. Використовуйте конфігурацію на основі середовища, щоб забезпечити завантаження правильних ключів для кожної мережі.

Безпека RPC

Ставтеся до RPC-ендпоінтів як до API-ключів — не розкривайте їх у фронтенд-коді, звідки їх можна витягти та зловжити. Використовуйте бекенд-проксі або змінні середовища, які не включаються в клієнтський код.

Моніторинг

Відстежуйте ці метрики в продакшні:

МетрикаНавіщо
Рівень успішності транзакційРаннє виявлення проблем
Затримка підтвердженняМоніторинг здоров'я мережі
Витрати на пріоритетну комісіюУправління витратами
Рівень помилок RPCЗдоров'я провайдера

Налаштуйте сповіщення для:

  • Переказів вище порогу з казначейства
  • Сплесків рівня невдалих транзакцій
  • Незвичних патернів одержувачів
  • Зростання рівня помилок RPC

Для моніторингу транзакцій у реальному часі в масштабі див. наш посібник з індексації.

Перевірка адрес

Кожен токен і програма мають рівно одну правильну адресу в мейннеті. Підроблені токени, що імітують USDC або інші стейблкоїни, є поширеним явищем — вони матимуть ту саму назву та символ, але іншу адресу mint. Ваш застосунок повинен жорстко кодувати або додавати до білого списку адреси mint (залежно від ваших вимог), ніколи не приймати їх динамічно з ненадійних джерел.

Конфігурація на основі середовища: Devnet і Mainnet часто використовують абсолютно різні mint токенів. Налаштуйте конфігурацію вашого застосунку для завантаження правильних адрес для кожного середовища — не жорстко кодуйте адреси мейннету і не забувайте їх змінювати під час тестування, або, що ще гірше, не відправляйте адреси devnet у продакшн.

Деякі поширені mint стейблкоїнів:

ТокенЕмітентАдреса mint
USDCCircleEPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
USDTTetherEs9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB
PYUSDPayPal2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo
USDGPaxos2u1tszSeqZ3qBWF3uNGPFc8TzMk2tdiwknnRMWGWjGWH

Адреси програм також мають значення. Надсилання інструкцій до неправильної програми призведе до помилки — або, що ще гірше, до безповоротної втрати коштів. Адреси Token Program:

ПрограмаАдреса
Token ProgramTokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
Token-2022 ProgramTokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb

Чек-лист перед запуском

  • Придбано 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?

Керується

© 2026 Фонд Solana.
Всі права захищені.
Залишайтеся на зв'язку