Das @solana-commerce/sdk-Paket stellt React Hooks zum Erstellen
benutzerdefinierter Solana-Zahlungserlebnisse bereit. Diese Hooks bieten volle
Kontrolle über SOL- und SPL- Token-Überweisungen mit integriertem
Zustandsmanagement, automatischer Wiederholungslogik, Fehler- behandlung und
UI-Hilfsfunktionen.
Unter der Haube verwendet das SDK TanStack Query
für Caching und Zustandsmanagement,
@solana/kit für Solana-Primitive und
integriert sich nahtlos mit @solana-commerce/connector für die
Wallet-Verbindung.
Installation
pnpm add @solana-commerce/sdk
Provider-Einrichtung
ArcProvider
Der ArcProvider ist der Root-Provider, der den Solana-RPC-Client
initialisiert, die Netzwerkkonfiguration verwaltet und allen Hooks die
Blockchain-Konnektivität bereitstellt. Er muss alle Komponenten umschließen, die
SDK-Hooks verwenden.
Props
config(ArcWebClientConfig) - Konfigurationsobjekt für den Arc-Clientchildren(ReactNode) - Untergeordnete Komponenten, die Zugriff auf die Hooks erhaltenqueryClient(QueryClient, optional) - Benutzerdefinierter TanStack Query-Client. Falls nicht angegeben, wird intern eine Standardinstanz erstellt.
ArcWebClientConfig
Konfiguration für den Arc-Client, der RPC-Konnektivität und Commitment- Level steuert.
Erforderliche Felder
Der Provider integriert sich automatisch über den useConnectorClient-Hook mit
@solana-commerce/connector, sodass keine explizite Connector-Konfiguration
erforderlich ist, wenn er innerhalb eines ConnectorProvider verwendet wird.
Optionale Felder
-
network('mainnet' | 'devnet' | 'testnet') - Solana-Netzwerk, zu dem eine Verbindung hergestellt werden soll. Standard:'mainnet'. -
rpcUrl(string) - Benutzerdefinierte RPC-Endpunkt-URL. Falls nicht angegeben, werden öffentliche Endpunkte für das ausgewählte Netzwerk verwendet. -
commitment('processed' | 'confirmed' | 'finalized') - Transaktions- bestätigungslevel. Standard:'confirmed'. -
debug(boolean) - Aktiviert ausführliches Konsolen-Logging für Debugging-Zwecke. Standard:false. -
autoConnect(boolean) - Stellt automatisch eine Verbindung zur Wallet her, wenn die Komponente gemountet wird. Standard:true. -
storage(Storage) - Benutzerdefinierter Speicheradapter für das Persistieren von Wallet-Einstellungen. Muss implementieren:getItem(key: string): string | nullsetItem(key: string, value: string): voidremoveItem(key: string): void
Standard:
window.localStoragewenn verfügbar (nur Browser). Verwenden Sie dies für React Native (AsyncStorage) oder benutzerdefinierten SSR-sicheren Speicher.
Integration mit ConnectorProvider
Der Provider integriert sich mit ConnectorProvider von
@solana-commerce/connector. Umschließen Sie Ihre App immer mit
ConnectorProvider vor 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>);}
Zentrale Hooks
useTransferSOL
Hook für die Übertragung von SOL mit automatischer Wiederholungslogik, Zustandsverwaltung und UI-Hilfsfunktionen. Basiert auf TanStack Query für Caching und Request-Deduplizierung.
Signatur
function useTransferSOL(initialToInput?: string,initialAmountInput?: string): UseTransferSOLReturn;
Parameter
initialToInput(string, optional) - Anfangswert für die Eingabe der Empfängeradresse. Nützlich zum Vorausfüllen von Formularen.initialAmountInput(string, optional) - Anfangswert für die Betragseingabe in SOL. Nützlich zum Vorausfüllen von Formularen.
Rückgabewert
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>;}
Kernfunktion
transferSOL- Initiiert eine SOL-Übertragung. Gibt ein Promise zurück, das aufgelöst wird, sobald die Transaktion on-chain bestätigt wurde.
Zustandseigenschaften
-
isLoading(boolean) -truewährend die Transaktion verarbeitet wird (Signieren, Übermitteln, Bestätigen). Verwenden Sie dies für Ladeanzeigen und Button-Zustände. -
error(Error | null) - Fehlerobjekt, wenn die Transaktion in irgendeiner Phase fehlgeschlagen ist.nullwenn kein Fehler vorliegt. Fehler umfassen Wallet-Ablehnungen, unzureichendes Guthaben, Netzwerkausfälle usw. -
data(TransferSOLResult | null) - Ergebnisobjekt bei erfolgreicher Transaktion. Enthält Signatur, Adressen, Beträge und Blockchain-Metadaten.nullvor der ersten erfolgreichen Übertragung. -
reset(() => void) - Setzt den Mutations-Zustand zurück und löschterrorunddata. Nützlich für Wiederholungs-Abläufe oder zum Zurücksetzen von Formularen nach Abschluss.
UI-Hilfseigenschaften & -Methoden
Der Hook bietet integrierte Zustandsverwaltung für Formulareingaben:
-
toInput/setToInput- Kontrollierter State für das Eingabefeld der Empfängeradresse -
amountInput/setAmountInput- Kontrollierter State für das Betragseingabefeld (in SOL, nicht in lamport) -
handleToInputChange- Vordefinierter onChange-Handler für die Empfängereingabe:<input onChange={handleToInputChange} /> -
handleAmountInputChange- Vordefinierter onChange-Handler für die Betragseingabe:<input onChange={handleAmountInputChange} /> -
transferFromInputs- Komfortmethode, die SOL unter Verwendung der aktuellentoInput- undamountInput-Werte überweist. Konvertiert den Betrag automatisch von SOL in lamport. -
handleSubmit- Formular-Submit-Handler, dertransferFromInputs()aufruft und das standardmäßige Formularverhalten verhindert. Wird mit<form onSubmit={handleSubmit}>verwendet.
Optionen
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(erforderlich) - Solana-Adresse des Empfängers. Kann ein String oder der TypAddressaus@solana/kitsein. -
amount(erforderlich) - Überweisungsbetrag in lamport (nicht SOL). Muss einbigintsein. Verwenden SieBigInt()oder Literal-Notation:1_000_000_000n= 1 SOL. -
from(optional) - Senderadresse. Falls nicht angegeben, wird die Adresse des verbundenen Wallets verwendet. Nur für erweiterte Anwendungsfälle erforderlich (z. B. Signieren für ein anderes Konten).
Ergebnis
Das Ergebnis enthält Transaktionsmetadaten einschließlich Überweisungsdetails und der Transaktionssignatur:
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}
Interne Architektur
Transaction Builder: Der Hook verwendet einen gemeinsamen Transaction Builder, der:
- Aktuelle Blockhashes für jede Transaktion abruft
- Optimierte Transaktionsnachrichten mit minimalen Fee erstellt
- Transaktionen mit dem verbundenen Wallet signiert
- Transaktionen in einem einzigen Ablauf übermittelt und bestätigt
Cache-Invalidierung: Bei erfolgreicher Überweisung invalidiert der Hook automatisch die TanStack-Query-Caches für:
- Saldo des Senders (
from-Adresse) - Saldo des Empfängers (
to-Adresse)
Dies stellt sicher, dass alle Komponenten, die Kontostände anzeigen (z. B. über
useArcClient), automatisch aktualisiert werden, ohne dass ein manueller
Eingriff erforderlich ist.
Präzise Betragsumrechnung: Bei Verwendung von transferFromInputs() wird
der Betrag von SOL in lamports unter Verwendung stringbasierter Arithmetik
umgerechnet, um Gleitkomma-Präzisionsfehler zu vermeiden. Die Umrechnung:
- Validiert das Eingabeformat (lehnt negative, ungültige Zahlen ab)
- Verarbeitet bis zu 9 Dezimalstellen (1 lamport = 0,000000001 SOL)
- Kürzt oder füllt Bruchwerte nach Bedarf auf
- Wirft beschreibende Fehler bei ungültigen Eingaben
useTransferToken
Wie useTransferSOL wird dieser Hook für die Übertragung von SPL-Tokens
verwendet. Zusätzlich zur Abwicklung von Übertragungen behandelt der Hook auch
die automatische Erstellung von Associated Token Accounts (ATA), wenn
erforderlich.
Signatur
function useTransferToken(initialMintInput?: string,initialToInput?: string,initialAmountInput?: string): UseTransferTokenReturn;
Parameter
initialMintInput(string, optional) - Anfängliche Token-Mint-Adresse. Nützlich für Überweisungen mit festem Token.initialToInput(string, optional) - Anfängliche Empfängeradresse.initialAmountInput(string, optional) - Anfänglicher Betrag in den Basiseinheiten des Tokens (unter Berücksichtigung der Dezimalstellen).
Rückgabewert
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>;}
Der Rückgabewert ähnelt useTransferSOL, enthält jedoch zusätzlich einen
mintInput-Status für die Token-Auswahl.
Optionen
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}
Erforderliche Felder
-
mint- SPL-Token-Mint-Adresse. Zum Beispiel:- USDC:
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' - USDT:
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'
- USDC:
-
to- Wallet-Adresse des Empfängers (nicht dessen token account). Der Hook leitet automatisch das korrekte Associated Token Account ab. -
amount- Überweisungsbetrag in der kleinsten Einheit des Tokens. Muss die Token-Dezimalstellen berücksichtigen:- USDC (6 Dezimalstellen):
1_000_000n= 1 USDC - SOL-wrapped-Tokens (9 Dezimalstellen):
1_000_000_000n= 1 Token
- USDC (6 Dezimalstellen):
Optionale Felder
-
from- Wallet-Adresse des Absenders. Standardmäßig verbundenes Wallet. -
createAccountIfNeeded(Standard:true) - Wenn der Empfänger kein token account für dieses Mint besitzt, wird es automatisch als Teil der Transaktion erstellt. Wennfalse, schlägt die Überweisung fehl, falls das Empfänger-Konto nicht existiert.Hinweis: Das Erstellen eines Token-Kontos kostet ~0,00203 SOL. Dies wird vom Absender bezahlt.
-
retryConfig- Konfiguration für automatische Wiederholungsversuche bei Ablauf des Blockhash. Siehe Wiederholungskonfiguration.
Ergebnis
Das Ergebnis enthält Transaktionsmetadaten einschließlich Überweisungsdetails und der Transaktionssignatur:
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}
Wiederholungskonfiguration
Der Hook enthält eine ausgefeilte Wiederholungslogik für den Umgang mit Blockhash-Ablauf, der häufig bei Netzwerküberlastung auftritt.
interface TransferRetryConfig {maxAttempts?: number; // Max retry attempts (default: 3)baseDelay?: number; // Base delay in ms (default: 1000)backoffMultiplier?: number; // Backoff multiplier (default: 1)}
-
maxAttempts- Maximale Anzahl von Transaktionsversuchen. Bei jedem Versuch wird ein neuer Blockhash abgerufen. Standard:3. -
baseDelay- Verzögerung in Millisekunden vor dem ersten Wiederholungsversuch. Standard:1000(1 Sekunde). -
backoffMultiplier- Exponentieller Backoff-Multiplikator. Jeder Wiederholungsversuch wartetbaseDelay * (backoffMultiplier ^ attemptNumber)Millisekunden.1= linearer Backoff (1s, 1s, 1s)1.5= exponentieller Backoff (1s, 1,5s, 2,25s)2= aggressiver exponentieller Backoff (1s, 2s, 4s)
Funktionsweise der Wiederholungsversuche:
- Erster Versuch: Transaktion wird mit aktuellem Blockhash erstellt und übermittelt
- Blockhash läuft ab: Wenn der Blockhash vor der Bestätigung veraltet, lehnt Solana die Transaktion ab
- Automatischer Wiederholungsversuch: Hook erkennt den Ablauf, ruft einen neuen Blockhash ab, erstellt die Transaktion neu und übermittelt sie erneut
- Exponentieller Backoff: Jeder Wiederholungsversuch wartet länger, um Netzwerküberlastung zu vermeiden
- Endgültiges Fehlschlagen: Nach
maxAttemptswirdBlockhashExpirationErrormit Kontext ausgelöst
Wann Wiederholungsversuche nicht ausgelöst werden:
- Nicht-Blockhash-Fehler (unzureichende Mittel, ungültige Konten usw.) werden sofort ohne Wiederholungsversuch ausgelöst
- Nur Blockhash-Ablauffehler lösen den Wiederholungsmechanismus aus
Interne Architektur
ATA-Verwaltung:
- Leitet Associated Token Accounts deterministisch mit
findAssociatedTokenPdaab (Hinweis: derzeit wird nur das Token Program unterstützt) - Prüft, ob der Absender ein Token-Konto hat (schlägt sofort fehl, wenn der Absender den Token nicht hält)
- Prüft, ob der Empfänger ein Token-Konto hat (erstellt es bei Bedarf und
createAccountIfNeeded: true) - Kontoprüfungen werden nur beim ersten Versuch durchgeführt, um redundante RPC-Aufrufe während Wiederholungsversuchen zu vermeiden
Cache-Invalidierung: Bei Erfolg werden TanStack-Query-Caches invalidiert für:
- Token-Guthaben des Absenders für diesen Mint
- Token-Guthaben des Empfängers für diesen Mint
- Zugehörige Kontendaten
Dies hält alle UI-Komponenten, die Guthaben anzeigen, automatisch synchron.
useArcClient
Hook für den Zugriff auf den zugrundeliegenden Solana-RPC-Client, den Wallet-Status und die Netzwerkkonfiguration. Dies ist ein Hook auf niedrigerer Ebene für fortgeschrittene Anwendungsfälle, die direkten RPC-Zugriff benötigen.
Signatur
function useArcClient(): ArcClientSnapshot;
Rückgabewert
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>;}
Status
Der ArcClientSnapshot erweitert den ArcWebClient, der Zugriff bietet auf:
- Wallet-Status (Adresse, Signer, verfügbare Wallets, Funktionen und Wallet-Status)
- Netzwerkkonfiguration (RPC-Endpunkt, Solana-Cluster)
Anwendungsfälle
Direkte RPC-Abfragen:
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>;}
Netzwerkabhängige Komponenten:
function NetworkIndicator() {const { network } = useArcClient();return (<div><span>Network: {network.cluster}</span>{network.canAirdrop && <button onClick={handleAirdrop}>Airdrop</button>}</div>);}
Bedingte Darstellung basierend auf Wallet:
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?