Paket @solana-commerce/connector menyediakan koneksi wallet headless yang
dibangun di atas
Wallet Standard. Paket ini
mengelola penemuan wallet, status koneksi, manajemen akun, dan koneksi ulang
otomatis. Paket ini dirancang agar agnostik terhadap framework dengan binding
React yang disertakan. Paket ini disesuaikan untuk penggunaan yang mulus dalam
Solana Commerce Kit dan kompatibel dengan
@solana/kit dan
gill.
Koneksi Wallet
Instalasi
pnpm add @solana-commerce/connector
Konfigurasi Provider
ConnectorProvider
Komponen ConnectorProvider membungkus aplikasi Anda dan menyediakan status
koneksi wallet ke semua komponen turunan. Komponen ini mengelola instance
ConnectorClient singleton yang persisten selama siklus mount/unmount komponen.
Props
Semua konfigurasi diberikan melalui prop config:
config(ConnectorConfig, opsional) - Objek konfigurasi untuk konektor. Semua field bersifat opsional.
ConnectorConfig
Objek konfigurasi untuk perilaku koneksi wallet.
Field Opsional
-
autoConnect(boolean) - Ketikatrue, secara otomatis terhubung kembali ke wallet yang terakhir digunakan saat mount. Preferensi wallet disimpan dalam storage yang dikonfigurasi (default kelocalStorage). Default:false. -
debug(boolean) - Mengaktifkan logging konsol verbose untuk debugging alur koneksi, perubahan akun, dan error. Log mencakup prefix seperti[Connector]dan[ConnectorProvider]. Default:false. -
accountPollingIntervalMs(number) - Interval polling dalam milidetik untuk memeriksa perubahan akun ketika wallet tidak mendukung fiturstandard:events. Sebagian besar wallet modern mendukung event, jadi polling adalah fallback. Default:1500(1,5 detik). -
storage(Storage) - Adapter storage kustom untuk menyimpan preferensi wallet. Harus mengimplementasikan:getItem(key: string): string | nullsetItem(key: string, value: string): voidremoveItem(key: string): void
Default:
window.localStorageketika tersedia (browser saja). Gunakan ini untuk React Native (AsyncStorage) atau storage kustom yang aman untuk SSR.
Arsitektur Provider
Provider menggunakan pola singleton dengan penghitungan referensi:
- Beberapa instance
ConnectorProviderberbagiConnectorClientyang sama - Client dibuat saat mount pertama dan bertahan meskipun di-unmount
- Ketika semua provider di-unmount, pembersihan ditunda selama 5 detik untuk menangani remount cepat
- Selama pembersihan, dompet diputuskan dan semua event listener dihapus
Desain ini mencegah pemutusan dompet selama perpindahan rute atau pembaruan komponen.
Hook
useConnector()
Hook utama untuk mengakses status dan aksi koneksi dompet. Harus digunakan di
dalam ConnectorProvider.
Mengembalikan objek ConnectorSnapshot yang berisi:
Properti State
-
wallets(WalletInfo[]) - Array dari semua dompet yang kompatibel dengan Wallet Standard yang ditemukan. Diperbarui secara otomatis ketika dompet dipasang atau dihapus. Setiap dompet menyertakan metadata seperti nama, ikon, dan kapabilitas. Lihat WalletInfo. -
selectedWallet(Wallet | null) - Objek dompet Wallet Standard yang sedang terhubung.nullketika terputus. Ini adalah instance dompet mentah dari API Wallet Standard. -
connected(boolean) - Status koneksi.trueketika dompet terhubung dan akun tersedia. Gunakan ini untuk rendering UI kondisional. -
connecting(boolean) - Status loading selama koneksi dompet.trueantara pemanggilanselect()dan menerima hasil koneksi. Gunakan ini untuk menampilkan indikator loading atau menonaktifkan tombol. -
accounts(AccountInfo[]) - Array akun dari dompet yang terhubung. Kebanyakan dompet menyediakan satu akun, tetapi beberapa mendukung beberapa akun. Diperbarui secara otomatis melalui event dompet atau polling. Lihat AccountInfo. -
selectedAccount(string | null) - Alamat dari akun yang sedang dipilih (kunci publik yang dikodekan base58). Ketika dompet terhubung dengan akun baru, akun tersebut secara otomatis dipilih. Jika tidak, akun yang dipilih sebelumnya akan dipertahankan.
Metode Aksi
-
select((walletName: string) => Promise<void>) - Menghubungkan ke wallet berdasarkan nama (misalnya,"Phantom","Solflare"). Nama wallet harus cocok persis dengan fieldnamedari wallet yang ditemukan.Proses:
- Mengatur
connecting: true - Memanggil fitur
standard:connectdari wallet - Mengambil akun dari wallet
- Berlangganan event wallet (atau memulai polling jika event tidak tersedia)
- Menyimpan preferensi wallet di penyimpanan yang dikonfigurasi
- Memperbarui state dengan akun dan akun yang dipilih
Throws: Error jika wallet tidak ditemukan, wallet tidak mendukung koneksi, atau koneksi ditolak oleh pengguna.
- Mengatur
-
disconnect(() => Promise<void>) - Memutuskan koneksi wallet saat ini dan membersihkan semua state.Proses:
- Berhenti berlangganan dari event wallet
- Menghentikan polling akun
- Memanggil fitur
standard:disconnectdari wallet jika tersedia - Menghapus wallet yang dipilih, akun, dan akun yang dipilih
- Menghapus preferensi wallet dari penyimpanan
Tidak pernah throw error (error dicatat jika debug diaktifkan).
-
selectAccount((address: string) => Promise<void>) - Mengganti akun yang dipilih ke alamat yang berbeda dari wallet yang terhubung. Jika alamat tidak ada di array akun saat ini, memicu koneksi ulang untuk mengambil akun yang diperbarui.Throws: Error jika tidak ada wallet yang terhubung atau akun yang diminta tidak ditemukan setelah koneksi ulang.
useConnectorClient()
Menyediakan akses langsung ke instance ConnectorClient yang mendasarinya untuk
kasus penggunaan tingkat lanjut.
Returns: ConnectorClient | null - Instance client singleton, atau null
ketika digunakan di luar ConnectorProvider.
Kasus penggunaan:
- Akses langsung ke
getConnectorState()untuk pembacaan state secara imperatif - Langganan manual dengan
subscribe(listener)untuk listener state kustom - Memanggil
destroy()untuk pembersihan paksa (tidak disarankan dalam penggunaan normal)
Contoh:
const client = useConnectorClient();// Get current state without triggering re-renderconst state = client?.getConnectorState();// Subscribe to state changes manuallyuseEffect(() => {if (!client) return;const unsubscribe = client.subscribe((state) => {console.log("Wallet state changed:", state);});return unsubscribe;}, [client]);
Definisi Tipe
WalletInfo
Metadata tentang wallet yang ditemukan.
interface WalletInfo {wallet: Wallet; // Raw Wallet Standard wallet objectname: string; // Display name (e.g., "Phantom", "Solflare")icon?: string; // Data URL for wallet icon (base64 encoded)installed: boolean; // Always true (only installed wallets are discovered)connectable?: boolean; // Whether wallet supports required features}
connectable Persyaratan: Sebuah wallet dapat terhubung ketika mendukung:
- Fitur
standard:connect - Fitur
standard:disconnect - Chain Solana (terdeteksi melalui
wallet.chainsyang berisi"solana")
Wallet yang tidak dapat terhubung muncul di array wallets tetapi tidak dapat
dipilih.
AccountInfo
Informasi tentang akun wallet.
interface AccountInfo {address: string; // Base58-encoded public keyicon?: string; // Account-specific icon (data URL)raw: WalletAccount; // Raw WalletAccount object from Wallet Standard}
Field raw menyediakan akses ke properti akun tambahan:
address: string- Public key yang dikodekan Base58publicKey: Uint8Array- Byte public key mentahlabel?: string- Label akun (jika wallet menyediakannya)icon?: string- Ikon khusus akun (URL data)chains: string[]- Chain yang didukung untuk akun inifeatures: string[]- Fitur yang didukung untuk akun ini
ConnectorSnapshot
Tipe kembalian dari useConnector(), menggabungkan state dan action.
type ConnectorSnapshot = ConnectorState & {select: (walletName: string) => Promise<void>;disconnect: () => Promise<void>;selectAccount: (address: string) => Promise<void>;};interface ConnectorState {wallets: WalletInfo[];selectedWallet: Wallet | null;connected: boolean;connecting: boolean;accounts: AccountInfo[];selectedAccount: string | null;}
Deteksi Perubahan Akun
Connector secara otomatis mendeteksi ketika akun wallet berubah (pengguna menambahkan/menghapus akun, beralih akun di wallet). Dua strategi digunakan:
Berbasis Event (Disarankan)
Ketika wallet mendukung standard:events, connector berlangganan event
change:
- Menerima notifikasi real-time ketika akun berubah
- Lebih efisien (tanpa polling)
- Mengagregasi akun dari event dan
wallet.accountsuntuk menangani wallet yang hanya menyertakan akun terpilih dalam event
Fallback Polling
Ketika event tidak didukung, connector melakukan polling wallet.accounts:
- Memeriksa setiap
accountPollingIntervalMs(default: 1500ms) - Membandingkan alamat akun untuk mendeteksi perubahan
- Hanya memicu render ulang ketika akun benar-benar berubah
Logika Pemilihan Akun:
- Ketika akun berubah, pertahankan akun terpilih jika masih ada
- Jika akun terpilih dihapus, pilih akun pertama yang tersedia
- Ketika terhubung dengan akun baru (tidak ada di akun sebelumnya), prioritaskan akun baru
Penyimpanan & Koneksi Otomatis
Persistensi Penyimpanan
Konektor menyimpan satu kunci dalam penyimpanan yang dikonfigurasi:
- Kunci:
arc-connector:lastWallet - Nilai: Nama dompet (misalnya,
"Phantom")
Operasi penyimpanan dibungkus dalam try-catch untuk menangani:
- Iframe sandboxed di mana
localStoragemengeluarkan error - Lingkungan SSR di mana
windowtidak terdefinisi - React Native di mana
localStoragetidak ada
Jika penyimpanan gagal, konektor tetap berjalan tanpa persistensi (tidak ada error yang dilempar).
Perilaku Koneksi Otomatis
Ketika autoConnect: true:
- Saat mount, membaca nama dompet terakhir dari penyimpanan
- Menunggu 100ms (memungkinkan dompet untuk mendaftar)
- Memanggil
select(walletName)jika dompet ditemukan - Jika koneksi otomatis gagal, menghapus preferensi yang tidak valid dari penyimpanan
Catatan Keamanan: Preferensi yang disimpan hanyalah nama dompet (string), bukan data sensitif. Dompet menangani autentikasi/otorisasi melalui UI-nya sendiri.
Contoh Penggunaan
Tombol Dompet Dasar
import { ConnectorProvider, useConnector } from "@solana-commerce/connector";function App() {return (<ConnectorProvider config={{ autoConnect: true }}><WalletButton /></ConnectorProvider>);}function WalletButton() {const { wallets, select, disconnect, connected, accounts, connecting } =useConnector();if (!connected) {return (<div><h3>Connect Wallet</h3>{wallets.map((wallet) => (<buttonkey={wallet.name}onClick={() => select(wallet.name)}disabled={!wallet.connectable || connecting}>{wallet.icon && (<img src={wallet.icon} alt={wallet.name} width={24} />)}{wallet.name}{!wallet.connectable && " (Unsupported)"}</button>))}</div>);}return (<div><p>Connected: {accounts[0]?.address.slice(0, 8)}...</p><button onClick={disconnect}>Disconnect</button></div>);}
Pemilih Multi-Akun
function AccountSelector() {const { accounts, selectedAccount, selectAccount } = useConnector();if (accounts.length <= 1) return null;return (<selectvalue={selectedAccount || ""}onChange={(e) => selectAccount(e.target.value)}>{accounts.map((account) => (<option key={account.address} value={account.address}>{account.raw.label || `${account.address.slice(0, 8)}...`}</option>))}</select>);}
Pemantauan Koneksi
function ConnectionMonitor() {const { connected, selectedWallet, accounts } = useConnector();useEffect(() => {if (connected) {console.log("Wallet connected:", selectedWallet?.name);console.log("Accounts:",accounts.map((a) => a.address));}}, [connected, selectedWallet, accounts]);return null;}
Dompet yang Didukung
Konektor mendukung semua dompet yang mengimplementasikan Wallet Standard, termasuk:
- Phantom
- Solflare
- Backpack
- Glow
- Brave Wallet
- Coinbase Wallet
- Dompet lain yang kompatibel dengan Wallet Standard
Dompet secara otomatis ditemukan ketika mereka mendaftar dengan API Wallet Standard (tidak memerlukan konfigurasi).
Penggunaan Headless (Tanpa React)
Untuk aplikasi non-React atau penggunaan sisi server, gunakan ConnectorClient
secara langsung:
import { ConnectorClient } from "@solana-commerce/connector";const connector = new ConnectorClient({autoConnect: true,debug: true});// Get current stateconst state = connector.getConnectorState();console.log("Available wallets:", state.wallets);// Connect to a walletawait connector.select("Phantom");// Subscribe to state changesconst unsubscribe = connector.subscribe((state) => {console.log("Connected:", state.connected);console.log("Accounts:", state.accounts);});// Switch accountawait connector.selectAccount("account-address-here");// Disconnectawait connector.disconnect();// Cleanup (removes all listeners and timers)connector.destroy();
Catatan: ConnectorClient mengelola state-nya sendiri dan tidak pernah
memicu re-render React. Anda harus berlangganan perubahan state secara manual.
Is this page helpful?