Το πακέτο @solana-commerce/sdk παρέχει React hooks για τη δημιουργία
προσαρμοσμένων εμπειριών πληρωμών Solana. Αυτά τα hooks προσφέρουν πλήρη έλεγχο
των μεταφορών SOL και SPL token με ενσωματωμένη διαχείριση κατάστασης, αυτόματη
λογική επανάληψης, διαχείριση σφαλμάτων και βοηθητικά εργαλεία UI.
Εσωτερικά, το SDK χρησιμοποιεί το TanStack Query
για caching και διαχείριση κατάστασης, το
@solana/kit για πρωτογενή στοιχεία Solana,
και ενσωματώνεται απρόσκοπτα με το @solana-commerce/connector για σύνδεση
πορτοφολιού.
Εγκατάσταση
pnpm add @solana-commerce/sdk
Ρύθμιση Provider
ArcProvider
Το ArcProvider είναι ο ριζικός provider που αρχικοποιεί το Solana RPC client,
διαχειρίζεται τη διαμόρφωση δικτύου και παρέχει συνδεσιμότητα blockchain σε όλα
τα hooks. Πρέπει να περιβάλλει οποιαδήποτε components που χρησιμοποιούν hooks
του SDK.
Props
config(ArcWebClientConfig) - Αντικείμενο διαμόρφωσης για το Arc clientchildren(ReactNode) - Θυγατρικά components που θα έχουν πρόσβαση στα hooksqueryClient(QueryClient, προαιρετικό) - Προσαρμοσμένο TanStack Query client. Εάν δεν παρέχεται, δημιουργείται αυτόματα μια προεπιλεγμένη παρουσία εσωτερικά.
ArcWebClientConfig
Διαμόρφωση για το Arc client που ελέγχει τη συνδεσιμότητα RPC και τα επίπεδα δέσμευσης.
Υποχρεωτικά Πεδία
Ο provider ενσωματώνεται αυτόματα με το @solana-commerce/connector μέσω του
useConnectorClient hook, επομένως δεν απαιτείται ρητή διαμόρφωση connector
όταν χρησιμοποιείται εντός ενός ConnectorProvider.
Προαιρετικά Πεδία
-
network('mainnet' | 'devnet' | 'testnet') - Δίκτυο Solana για σύνδεση. Προεπιλογή:'mainnet'. -
rpcUrl(string) - Προσαρμοσμένη διεύθυνση URL τελικού σημείου RPC. Εάν δεν παρέχεται, χρησιμοποιεί δημόσια τελικά σημεία για το επιλεγμένο δίκτυο. -
commitment('processed' | 'confirmed' | 'finalized') - Επίπεδο επιβεβαίωσης συναλλαγής. Προεπιλογή:'confirmed'. -
debug(boolean) - Ενεργοποιεί λεπτομερή καταγραφή κονσόλας για debugging. Προεπιλογή:false. -
autoConnect(boolean) - Συνδέεται αυτόματα στο πορτοφόλι όταν το component φορτώνεται. Προεπιλογή: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>);}
Βασικά Hooks
useTransferSOL
Hook για τη μεταφορά SOL με αυτόματη λογική επανάληψης, διαχείριση κατάστασης και βοηθητικές συναρτήσεις UI. Βασισμένο στο TanStack Query για caching και αποδιπλοποίηση αιτημάτων.
Υπογραφή
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. Επιστρέφει ένα promise που επιλύεται όταν η συναλλαγή επιβεβαιωθεί on-chain.
Ιδιότητες Κατάστασης
-
isLoading(boolean) -trueενώ η συναλλαγή επεξεργάζεται (υπογραφή, υποβολή, επιβεβαίωση). Χρησιμοποιήστε το για δείκτες φόρτωσης και καταστάσεις κουμπιών. -
error(Error | null) - Αντικείμενο σφάλματος εάν η συναλλαγή απέτυχε σε οποιοδήποτε στάδιο.nullόταν δεν υπάρχει σφάλμα. Τα σφάλματα περιλαμβάνουν απορρίψεις πορτοφολιού, ανεπαρκές υπόλοιπο, αποτυχίες δικτύου κ.λπ. -
data(TransferSOLResult | null) - Αντικείμενο αποτελέσματος όταν η συναλλαγή επιτύχει. Περιέχει υπογραφή, διευθύνσεις, ποσά και μεταδεδομένα blockchain.nullπριν από την πρώτη επιτυχημένη μεταφορά. -
reset(() => void) - Επαναφέρει την κατάσταση mutation, καθαρίζοντας ταerrorκαιdata. Χρήσιμο για ροές επανάληψης ή επαναφορά φορμών μετά την ολοκλήρωση.
Βοηθητικές Ιδιότητες & Μέθοδοι UI
Το hook παρέχει ενσωματωμένη διαχείριση κατάστασης για πεδία εισαγωγής φορμών:
-
toInput/setToInput- Ελεγχόμενη κατάσταση για το πεδίο εισαγωγής διεύθυνσης παραλήπτη -
amountInput/setAmountInput- Ελεγχόμενη κατάσταση για το πεδίο εισαγωγής ποσού (σε SOL, όχι σε lamport) -
handleToInputChange- Προσυνδεδεμένος χειριστής onChange για την εισαγωγή παραλήπτη:<input onChange={handleToInputChange} /> -
handleAmountInputChange- Προσυνδεδεμένος χειριστής onChange για την εισαγωγή ποσού:<input onChange={handleAmountInputChange} /> -
transferFromInputs- Βοηθητική μέθοδος που μεταφέρει SOL χρησιμοποιώντας τις τρέχουσες τιμέςtoInputκαιamountInput. Μετατρέπει αυτόματα το ποσό από SOL σε lamports. -
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 παραλήπτη. Μπορεί να είναι string ή τύποςAddressαπό το@solana/kit. -
amount(απαιτείται) - Ποσό μεταφοράς σε lamports (όχι SOL). Πρέπει να είναιbigint. ΧρησιμοποιήστεBigInt()ή literal σημειογραφία: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}
Εσωτερική Αρχιτεκτονική
Transaction Builder: Το hook χρησιμοποιεί έναν κοινόχρηστο δημιουργό συναλλαγών που:
- Ανακτά ανανεωμένα blockhashes για κάθε συναλλαγή
- Δημιουργεί βελτιστοποιημένα μηνύματα συναλλαγών με ελάχιστες χρεώσεις
- Υπογράφει συναλλαγές χρησιμοποιώντας το συνδεδεμένο πορτοφόλι
- Υποβάλλει και επιβεβαιώνει συναλλαγές σε μία ενιαία ροή
Ακύρωση Cache: Σε επιτυχημένη μεταφορά, το hook ακυρώνει αυτόματα τις TanStack Query caches για:
- Υπόλοιπο αποστολέα (διεύθυνση
from) - Υπόλοιπο παραλήπτη (διεύθυνση
to)
Αυτό διασφαλίζει ότι οποιαδήποτε στοιχεία εμφανίζουν υπόλοιπα (π.χ., μέσω
useArcClient) ανακτούν και ενημερώνουν αυτόματα χωρίς χειροκίνητη παρέμβαση.
Ακριβής Μετατροπή Ποσού: Όταν χρησιμοποιείτε το transferFromInputs(), το
ποσό μετατρέπεται από SOL σε lamports χρησιμοποιώντας αριθμητική με βάση
συμβολοσειρές για την αποφυγή σφαλμάτων ακρίβειας κινητής υποδιαστολής. Η
μετατροπή:
- Επικυρώνει τη μορφή εισόδου (απορρίπτει αρνητικούς, μη έγκυρους αριθμούς)
- Χειρίζεται έως και 9 δεκαδικά ψηφία (1 lamport = 0.000000001 SOL)
- Περικόπτει ή συμπληρώνει κλασματικές τιμές όπως απαιτείται
- Εμφανίζει περιγραφικά σφάλματα για μη έγκυρες εισόδους
useTransferToken
Όπως το useTransferSOL, αυτό το hook χρησιμοποιείται για τη μεταφορά SPL
tokens. Εκτός από τη διαχείριση μεταφορών, το hook χειρίζεται επίσης την
αυτόματη δημιουργία Associated Token Account (ATA) όταν χρειάζεται.
Υπογραφή
function useTransferToken(initialMintInput?: string,initialToInput?: string,initialAmountInput?: string): UseTransferTokenReturn;
Παράμετροι
initialMintInput(string, προαιρετικό) - Αρχική διεύθυνση mint του token. Χρήσιμο για μεταφορές σταθερού token.
Τιμή Επιστροφής
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 για την επιλογή token.
Επιλογές
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 token. Για παράδειγμα:- USDC:
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' - USDT:
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'
- USDC:
-
to- Διεύθυνση πορτοφολιού του παραλήπτη (όχι του token account του). Το hook παράγει αυτόματα το σωστό Associated Token Account. -
amount- Ποσό μεταφοράς στη μικρότερη μονάδα του token. Πρέπει να λαμβάνει υπόψη τα δεκαδικά ψηφία του token:- USDC (6 δεκαδικά):
1_000_000n= 1 USDC - Tokens με περιτύλιγμα SOL (9 δεκαδικά):
1_000_000_000n= 1 token
- USDC (6 δεκαδικά):
Προαιρετικά Πεδία
-
from- Διεύθυνση πορτοφολιού του αποστολέα. Προεπιλογή στο συνδεδεμένο πορτοφόλι. -
createAccountIfNeeded(προεπιλογή:true) - Εάν ο παραλήπτης δεν έχει token account για αυτό το mint, δημιουργείται αυτόματα ως μέρος της συναλλαγής. Όταν είναιfalse, η μεταφορά θα αποτύχει εάν το account του παραλήπτη δεν υπάρχει.Σημείωση: Η δημιουργία ενός token account κοστίζει ~0.00203 SOL. Αυτό καταβάλλεται από τον αποστολέα.
-
retryConfig- Διαμόρφωση για αυτόματη επανάληψη σε περίπτωση λήξης blockhash. Δείτε Διαμόρφωση Επανάληψης.
Αποτέλεσμα
Το αποτέλεσμα περιλαμβάνει μεταδεδομένα συναλλαγής συμπεριλαμβανομένων λεπτομερειών μεταφοράς και της υπογραφής συναλλαγής:
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}
Διαμόρφωση Επανάληψης
Το hook περιλαμβάνει εξελιγμένη λογική επανάληψης για τη διαχείριση λήξης blockhash, που συμβαίνει συχνά κατά τη διάρκεια συμφόρησης δικτύου.
interface TransferRetryConfig {maxAttempts?: number; // Max retry attempts (default: 3)baseDelay?: number; // Base delay in ms (default: 1000)backoffMultiplier?: number; // Backoff multiplier (default: 1)}
-
maxAttempts- Μέγιστος αριθμός προσπαθειών συναλλαγής. Κάθε προσπάθεια ανακτά ένα νέο blockhash. Προεπιλογή:3. -
baseDelay- Καθυστέρηση σε milliseconds πριν από την πρώτη επανάληψη. Προεπιλογή:1000(1 δευτερόλεπτο). -
backoffMultiplier- Πολλαπλασιαστής εκθετικής υποχώρησης. Κάθε επανάληψη περιμένειbaseDelay * (backoffMultiplier ^ attemptNumber)milliseconds.1= γραμμική υποχώρηση (1s, 1s, 1s)1.5= εκθετική υποχώρηση (1s, 1.5s, 2.25s)2= επιθετική εκθετική (1s, 2s, 4s)
Πώς Λειτουργεί η Επανάληψη:
- Πρώτη Προσπάθεια: Η συναλλαγή κατασκευάζεται με το τρέχον blockhash και υποβάλλεται
- Λήξη Blockhash: Εάν το blockhash γίνει παρωχημένο πριν από την επιβεβαίωση, το Solana απορρίπτει τη συναλλαγή
- Αυτόματη Επανάληψη: Το hook εντοπίζει τη λήξη, ανακτά ένα νέο blockhash, ξαναχτίζει τη συναλλαγή και την υποβάλλει ξανά
- Εκθετική Υποχώρηση: Κάθε επανάληψη περιμένει περισσότερο για να αποφευχθεί η συμφόρηση δικτύου
- Τελική Αποτυχία: Μετά από
maxAttempts, εμφανίζειBlockhashExpirationErrorμε πλαίσιο
Πότε δεν Ενεργοποιούνται οι Επαναλήψεις:
- Σφάλματα μη σχετικά με blockhash (ανεπαρκή κεφάλαια, μη έγκυροι λογαριασμοί κ.λπ.) εμφανίζονται άμεσα χωρίς επανάληψη
- Μόνο σφάλματα λήξης blockhash ενεργοποιούν τον μηχανισμό επανάληψης
Εσωτερική Αρχιτεκτονική
Διαχείριση ATA:
- Παράγει Associated Token Accounts με ντετερμινιστικό τρόπο χρησιμοποιώντας
findAssociatedTokenPda(Σημείωση: μόνο το Token Program υποστηρίζεται αυτήν τη στιγμή) - Ελέγχει αν ο αποστολέας έχει token account (αποτυγχάνει άμεσα αν ο αποστολέας δεν κατέχει το token)
- Ελέγχει αν ο παραλήπτης έχει token account (δημιουργεί αν χρειάζεται και
createAccountIfNeeded: true) - Οι έλεγχοι λογαριασμών εκτελούνται μόνο στην πρώτη προσπάθεια για να αποφευχθούν πλεονάζουσες κλήσεις RPC κατά τις επαναλήψεις
Ακύρωση Cache: Σε περίπτωση επιτυχίας, ακυρώνει τις προσωρινές μνήμες του TanStack Query για:
- Υπόλοιπο token του αποστολέα για αυτό το mint
- Υπόλοιπο token του παραλήπτη για αυτό το mint
- Σχετικά δεδομένα λογαριασμού
Αυτό διατηρεί όλα τα στοιχεία της διεπαφής χρήστη που εμφανίζουν υπόλοιπα αυτόματα συγχρονισμένα.
useArcClient
Hook για πρόσβαση στον υποκείμενο RPC client του Solana, την κατάσταση του πορτοφολιού και τη διαμόρφωση δικτύου. Πρόκειται για ένα hook χαμηλότερου επιπέδου για προηγμένες περιπτώσεις χρήσης που απαιτούν άμεση πρόσβαση 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, cluster 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?