Пакет @solana-commerce/sdk надає React hooks для створення власних платіжних
рішень на Solana. Ці hooks забезпечують повний контроль над SOL та SPL
токен-переказами з вбудованим управлінням станом, автоматичною логікою повторних
спроб, обробкою помилок та UI-помічниками.
Під капотом SDK використовує TanStack Query для
кешування та управління станом, @solana/kit
для примітивів Solana та безперешкодно інтегрується з
@solana-commerce/connector для підключення гаманця.
Встановлення
pnpm add @solana-commerce/sdk
Налаштування провайдера
ArcProvider
ArcProvider — це кореневий провайдер, який ініціалізує RPC-клієнт Solana,
керує конфігурацією мережі та забезпечує підключення до блокчейну для всіх
hooks. Він повинен обгортати будь-які компоненти, що використовують hooks SDK.
Властивості
config(ArcWebClientConfig) - Об'єкт конфігурації для клієнта Arcchildren(ReactNode) - Дочірні компоненти, які матимуть доступ до hooksqueryClient(QueryClient, необов'язково) - Власний клієнт TanStack Query. Якщо не вказано, автоматично створюється екземпляр за замовчуванням.
ArcWebClientConfig
Конфігурація для клієнта Arc, яка керує RPC-підключенням та рівнями підтвердження.
Обов'язкові поля
Провайдер автоматично інтегрується з @solana-commerce/connector через hook
useConnectorClient, тому явна конфігурація коннектора не потрібна при
використанні всередині ConnectorProvider.
Необов'язкові поля
-
network('mainnet' | 'devnet' | 'testnet') - Мережа Solana для підключення. За замовчуванням:'mainnet'. -
rpcUrl(string) - URL власної RPC-точки доступу. Якщо не вказано, використовуються публічні точки доступу для обраної мережі. -
commitment('processed' | 'confirmed' | 'finalized') - Рівень підтвердження транзакції. За замовчуванням:'confirmed'. -
debug(boolean) - Увімкнення детального логування в консолі для налагодження. За замовчуванням:false. -
autoConnect(boolean) - Автоматично підключається до гаманця при монтуванні компонента. За замовчуванням:true. -
storage(Storage) - Користувацький адаптер сховища для збереження налаштувань гаманця. Повинен реалізовувати:getItem(key: string): string | nullsetItem(key: string, value: string): voidremoveItem(key: string): void
За замовчуванням:
window.localStorage, коли доступний (тільки браузер). Використовуйте для React Native (AsyncStorage) або користувацького SSR-безпечного сховища.
Інтеграція з ConnectorProvider
Провайдер інтегрується з ConnectorProvider з @solana-commerce/connector.
Завжди обгортайте ваш додаток за допомогою ConnectorProvider перед
ArcProvider:
import { ConnectorProvider } from "@solana-commerce/connector";import { ArcProvider } from "@solana-commerce/sdk";function App() {return (<ConnectorProvider config={{ autoConnect: true }}><ArcProvider config={{ network: "mainnet", commitment: "confirmed" }}><YourApp /></ArcProvider></ConnectorProvider>);}
Основні хуки
useTransferSOL
Хук для переказу SOL з автоматичною логікою повторних спроб, керуванням станом та допоміжними функціями UI. Побудований на TanStack Query для кешування та дедуплікації запитів.
Сигнатура
function useTransferSOL(initialToInput?: string,initialAmountInput?: string): UseTransferSOLReturn;
Параметри
initialToInput(string, необов'язковий) - Початкове значення для поля введення адреси одержувача. Корисно для попереднього заповнення форм.initialAmountInput(string, необов'язковий) - Початкове значення для поля суми в SOL. Корисно для попереднього заповнення форм.
Значення, що повертається
interface UseTransferSOLReturn {// Core transfer functiontransferSOL: (options: TransferSOLOptions) => Promise<TransferSOLResult>;// StateisLoading: boolean;error: Error | null;data: TransferSOLResult | null;reset: () => void;// UI HelperstoInput: string;amountInput: string;setToInput: (value: string) => void;setAmountInput: (value: string) => void;handleToInputChange: (event: React.ChangeEvent<HTMLInputElement>) => void;handleAmountInputChange: (event: React.ChangeEvent<HTMLInputElement>) => void;handleSubmit: (event?: {preventDefault?: () => void;}) => Promise<TransferSOLResult | undefined>;transferFromInputs: () => Promise<TransferSOLResult | undefined>;}
Основна функція
transferSOL- Ініціює переказ SOL. Повертає проміс, який виконується, коли транзакція підтверджена в блокчейні.
Властивості стану
-
isLoading(boolean) -trueпід час обробки транзакції (підписання, надсилання, підтвердження). Використовуйте для індикаторів завантаження та станів кнопок. -
error(Error | null) - Об'єкт помилки, якщо транзакція не вдалася на будь-якому етапі.null, коли помилок немає. Помилки включають відхилення гаманця, недостатній баланс, мережеві збої тощо. -
data(TransferSOLResult | null) - Об'єкт результату, коли транзакція успішна. Містить підпис, адреси, суми та метадані блокчейну.nullдо першого успішного переказу. -
reset(() => void) - Скидає стан мутації, очищуючиerrorтаdata. Корисно для потоків повторних спроб або скидання форм після завершення.
Допоміжні властивості та методи UI
Хук надає вбудоване керування станом для полів форми:
-
toInput/setToInput- Керований стан для поля введення адреси отримувача -
amountInput/setAmountInput- Керований стан для поля введення суми (в SOL, а не lamport) -
handleToInputChange- Попередньо прив'язаний обробник onChange для введення отримувача:<input onChange={handleToInputChange} /> -
handleAmountInputChange- Попередньо прив'язаний обробник onChange для введення суми:<input onChange={handleAmountInputChange} /> -
transferFromInputs- Зручний метод для переказу SOL з використанням поточних значеньtoInputтаamountInput. Автоматично конвертує суму з SOL у lamport. -
handleSubmit- Обробник відправки форми, який викликаєtransferFromInputs()і запобігає стандартній поведінці форми. Використовуйте з<form onSubmit={handleSubmit}>.
Параметри
interface TransferSOLOptions {to: string | Address; // Recipient wallet addressamount: bigint; // Amount in lamports (1 SOL = 1,000,000,000 lamports)from?: string | Address; // Optional sender address (defaults to connected wallet)}
-
to(обов'язково) - Solana-адреса отримувача. Може бути рядком або типомAddressз@solana/kit. -
amount(обов'язково) - Сума переказу в lamport (не SOL). Має бути типомbigint. ВикористовуйтеBigInt()або літеральну нотацію:1_000_000_000n= 1 SOL. -
from(необов'язково) - Адреса відправника. Якщо не вказано, використовується адреса з підключеного гаманця. Потрібна лише для складних випадків використання (наприклад, підписання від імені іншого облікового запису).
Результат
Результат включає метадані транзакції, зокрема деталі переказу та підпис транзакції:
interface TransferSOLResult {signature: string; // Transaction signature (base58)amount: bigint; // Amount transferred in lamportsfrom: Address; // Sender addressto: Address; // Recipient addressblockTime?: number; // Unix timestamp when transaction was processedslot?: number; // Slot number where transaction was confirmed}
Внутрішня архітектура
Конструктор транзакцій: Хук використовує спільний конструктор транзакцій, який:
- Отримує свіжі блокхеші для кожної транзакції
- Будує оптимізовані повідомлення транзакцій з мінімальними комісіями
- Підписує транзакції за допомогою підключеного гаманця
- Відправляє та підтверджує транзакції в єдиному потоці
Інвалідація кешу: При успішному переказі хук автоматично інвалідує кеші TanStack Query для:
- Балансу відправника (адреса
from) - Балансу отримувача (адреса
to)
Це гарантує, що будь-які компоненти, які відображають баланси (наприклад, через
useArcClient), автоматично повторно отримують і оновлюють дані без ручного
втручання.
Точне перетворення суми: При використанні transferFromInputs() сума
перетворюється з SOL на лампорти за допомогою рядкової арифметики, щоб уникнути
помилок точності чисел з рухомою комою. Перетворення:
- Перевіряє формат введення (відхиляє від'ємні та недійсні числа)
- Обробляє до 9 знаків після коми (1 лампорт = 0.000000001 SOL)
- Обрізає або доповнює дробові значення за потреби
- Видає описові помилки для недійсних даних
useTransferToken
Як і useTransferSOL, цей хук використовується для переказу SPL токенів. Окрім
обробки переказів, хук також забезпечує автоматичне створення Associated Token
Account (ATA) за потреби.
Сигнатура
function useTransferToken(initialMintInput?: string,initialToInput?: string,initialAmountInput?: string): UseTransferTokenReturn;
Параметри
initialMintInput(string, необов'язково) - Початкова адреса mint токена. Корисно для переказів фіксованого токена.initialToInput(string, необов'язково) - Початкова адреса одержувача.initialAmountInput(string, необов'язково) - Початкова сума в базових одиницях токена (з урахуванням десяткових знаків).
Повертає
interface UseTransferTokenReturn {// Core transfer functiontransferToken: (options: TransferTokenOptions) => Promise<TransferTokenResult>;// StateisLoading: boolean;error: Error | null;data: TransferTokenResult | null;reset: () => void;// UI HelpersmintInput: string;toInput: string;amountInput: string;setMintInput: (value: string) => void;setToInput: (value: string) => void;setAmountInput: (value: string) => void;handleMintInputChange: (event: React.ChangeEvent<HTMLInputElement>) => void;handleToInputChange: (event: React.ChangeEvent<HTMLInputElement>) => void;handleAmountInputChange: (event: React.ChangeEvent<HTMLInputElement>) => void;handleSubmit: (event?: {preventDefault?: () => void;}) => Promise<TransferTokenResult | undefined>;transferFromInputs: () => Promise<TransferTokenResult | undefined>;}
Повертає значення, аналогічне useTransferSOL, але з додатковим станом
mintInput для вибору токена.
Опції
interface TransferTokenOptions {mint: string | Address; // Token mint addressto: string | Address; // Recipient wallet addressamount: bigint; // Amount in token's smallest unitfrom?: string | Address; // Optional sender (defaults to connected wallet)createAccountIfNeeded?: boolean; // Auto-create recipient's ATA (default: true)retryConfig?: TransferRetryConfig; // Optional retry configuration}
Обов'язкові поля
-
mint- Адреса mint SPL токена. Наприклад:- USDC:
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' - USDT:
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'
- USDC:
-
to- Адреса гаманця одержувача (а не його токен-акаунта). Хук автоматично визначає правильний Associated Token Account. -
amount- Сума переказу в найменшій одиниці токена. Має враховувати десяткові знаки токена:- USDC (6 десяткових знаків):
1_000_000n= 1 USDC - Токени з обгорткою SOL (9 десяткових знаків):
1_000_000_000n= 1 токен
- USDC (6 десяткових знаків):
Необов'язкові поля
-
from- Адреса гаманця відправника. За замовчуванням використовується підключений гаманець. -
createAccountIfNeeded(за замовчуванням:true) - Якщо одержувач не має токен-акаунта для цього mint, автоматично створити його як частину транзакції. Коли встановленоfalse, переказ не вдасться, якщо акаунт одержувача не існує.Примітка: Створення токен-акаунта коштує ~0.00203 SOL. Це сплачує відправник.
-
retryConfig- Налаштування автоматичного повтору при закінченні терміну дії блокхешу. Див. Налаштування повторів.
Результат
Результат включає метадані транзакції, зокрема деталі переказу та підпис транзакції:
interface TransferTokenResult {signature: string; // Transaction signaturemint: Address; // Token mint addressamount: bigint; // Amount transferredfrom: Address; // Sender wallet addressto: Address; // Recipient wallet addressfromTokenAccount: Address; // Sender's token accounttoTokenAccount: Address; // Recipient's token accountcreatedAccount?: boolean; // Whether recipient's ATA was createdblockTime?: number; // Transaction timestampslot?: number; // Block slot number}
Налаштування повторів
Хук включає досконалу логіку повторів для обробки закінчення терміну дії блокхешу, що часто трапляється під час перевантаження мережі.
interface TransferRetryConfig {maxAttempts?: number; // Max retry attempts (default: 3)baseDelay?: number; // Base delay in ms (default: 1000)backoffMultiplier?: number; // Backoff multiplier (default: 1)}
-
maxAttempts- Максимальна кількість спроб виконання транзакції. Кожна спроба отримує свіжий блокхеш. За замовчуванням:3. -
baseDelay- Затримка в мілісекундах перед першим повтором. За замовчуванням:1000(1 секунда). -
backoffMultiplier- Множник експоненційної затримки. Кожен повтор очікуєbaseDelay * (backoffMultiplier ^ attemptNumber)мілісекунд.1= лінійна затримка (1с, 1с, 1с)1.5= експоненційна затримка (1с, 1,5с, 2,25с)2= агресивна експоненційна (1с, 2с, 4с)
Як працюють повтори:
- Перша спроба: Транзакція будується з поточним блокхешем і надсилається
- Блокхеш закінчується: Якщо блокхеш застаріває до підтвердження, Solana відхиляє транзакцію
- Автоматичний повтор: Хук виявляє закінчення терміну, отримує свіжий блокхеш, перебудовує транзакцію та повторно надсилає
- Експоненційна затримка: Кожен повтор очікує довше, щоб уникнути перевантаження мережі
- Остаточна невдача: Після
maxAttemptsвикидаєBlockhashExpirationErrorз контекстом
Коли повтори не спрацьовують:
- Помилки, не пов'язані з блокхешем (недостатньо коштів, недійсні акаунти тощо), викидаються негайно без повторів
- Лише помилки закінчення терміну дії блокхешу запускають механізм повторів
Внутрішня архітектура
Управління ATA:
- Детерміновано виводить associated token account за допомогою
findAssociatedTokenPda(Примітка: наразі підтримується лише Token Program) - Перевіряє, чи відправник має токен-акаунт (швидко завершується невдачею, якщо відправник не володіє токеном)
- Перевіряє, чи одержувач має токен-акаунт (створює за потреби та
createAccountIfNeeded: true) - Перевірки акаунтів виконуються лише при першій спробі, щоб уникнути зайвих RPC-викликів під час повторів
Інвалідація кешу: У разі успіху інвалідує кеші TanStack Query для:
- Баланс токенів відправника для цього mint
- Баланс токенів одержувача для цього mint
- Пов'язані дані облікового запису
Це автоматично підтримує синхронізацію всіх компонентів UI, що відображають баланси.
useArcClient
Хук для доступу до базового RPC-клієнта Solana, стану гаманця та конфігурації мережі. Це хук нижчого рівня для просунутих сценаріїв використання, які потребують прямого доступу до RPC.
Сигнатура
function useArcClient(): ArcClientSnapshot;
Значення, що повертається
interface ArcClientSnapshot {// Wallet Statewallet: {address: Address | null;signer: TransactionSigner | null;};// Network Configurationnetwork: {cluster: "mainnet" | "devnet" | "testnet";rpcUrl: string;};// Client Configurationconfig: ArcWebClientConfig;// Actionsselect: (walletName: string) => Promise<void>;disconnect: () => Promise<void>;selectAccount: (accountAddress: Address) => Promise<void>;}
Стан
ArcClientSnapshot розширює ArcWebClient, який надає доступ до:
- стан гаманця (адреса, підписувач, доступні гаманці, функції та статус гаманця)
- конфігурація мережі (RPC-ендпоінт, кластер Solana)
Сценарії використання
Прямі RPC-запити:
import { useArcClient } from "@solana-commerce/sdk";import { getSharedRpc } from "@solana-commerce/sdk/core/rpc-manager";import { address } from "@solana/kit";function AccountBalance() {const { network, wallet } = useArcClient();const [balance, setBalance] = useState<bigint | null>(null);useEffect(() => {if (!wallet.address) return;const rpc = getSharedRpc(network.rpcUrl);async function fetchBalance() {const result = await rpc.getBalance(wallet.address).send();setBalance(result);}fetchBalance();}, [wallet.address, network.rpcUrl]);if (!wallet.address) return <div>Connect wallet to see balance</div>;return <div>Balance: {(Number(balance) / 1e9).toFixed(4)} SOL</div>;}
Компоненти з урахуванням мережі:
function NetworkIndicator() {const { network } = useArcClient();return (<div><span>Network: {network.cluster}</span>{network.canAirdrop && <button onClick={handleAirdrop}>Airdrop</button>}</div>);}
Умовний рендеринг на основі гаманця:
function SendButton() {const { wallet } = useArcClient();const { transferSOL, isLoading } = useTransferSOL();if (!wallet.address) {return <div>Connect wallet to send SOL</div>;}return (<buttononClick={() =>transferSOL({to: "recipient-address",amount: BigInt(1_000_000_000)})}disabled={isLoading}>{isLoading ? "Sending..." : "Send 1 SOL"}</button>);}
Is this page helpful?