Gói @solana-commerce/connector cung cấp kết nối ví không giao diện được xây
dựng trên Wallet Standard.
Nó quản lý việc phát hiện ví, trạng thái kết nối, quản lý tài khoản và tự động
kết nối lại. Gói này được thiết kế để độc lập với framework và bao gồm các
binding cho React. Nó được tùy chỉnh để sử dụng mượt mà trong Solana Commerce
Kit và tương thích với @solana/kit và
gill.
Kết nối Ví
Cài đặt
pnpm add @solana-commerce/connector
Cấu hình Provider
ConnectorProvider
Component ConnectorProvider bao bọc ứng dụng của bạn và cung cấp trạng thái
kết nối ví cho tất cả các component con. Nó quản lý một instance
ConnectorClient singleton tồn tại xuyên suốt các chu kỳ mount/unmount của
component.
Props
Tất cả cấu hình được truyền qua prop config:
config(ConnectorConfig, tùy chọn) - Đối tượng cấu hình cho connector. Tất cả các trường đều là tùy chọn.
ConnectorConfig
Đối tượng cấu hình cho hành vi kết nối ví.
Các trường tùy chọn
-
autoConnect(boolean) - Khi làtrue, tự động kết nối lại với ví được sử dụng gần nhất khi mount. Tùy chọn ví được lưu trữ trong bộ nhớ đã cấu hình (mặc định làlocalStorage). Mặc định:false. -
debug(boolean) - Bật ghi log chi tiết trên console để debug luồng kết nối, thay đổi tài khoản và lỗi. Logs bao gồm tiền tố như[Connector]và[ConnectorProvider]. Mặc định:false. -
accountPollingIntervalMs(number) - Khoảng thời gian polling tính bằng mili giây để kiểm tra thay đổi tài khoản khi ví không hỗ trợ tính năngstandard:events. Hầu hết các ví hiện đại đều hỗ trợ events, nên polling là phương án dự phòng. Mặc định:1500(1,5 giây). -
storage(Storage) - Adapter lưu trữ tùy chỉnh để duy trì tùy chọn ví. Phải implement:getItem(key: string): string | nullsetItem(key: string, value: string): voidremoveItem(key: string): void
Mặc định:
window.localStoragekhi có sẵn (chỉ trình duyệt). Sử dụng cho React Native (AsyncStorage) hoặc lưu trữ tùy chỉnh tương thích SSR.
Kiến trúc Provider
Provider sử dụng mẫu singleton với cơ chế đếm tham chiếu:
- Nhiều instance
ConnectorProviderdùng chung cùng mộtConnectorClient - Client được tạo khi mount lần đầu và tồn tại qua các lần unmount
- Khi tất cả các provider unmount, việc dọn dẹp bị trễ 5 giây để xử lý các lần remount nhanh
- Trong quá trình dọn dẹp, ví sẽ ngắt kết nối và tất cả event listener được xóa bỏ
Thiết kế này ngăn ngừa việc ngắt kết nối ví trong quá trình thay đổi route hoặc cập nhật component.
Hooks
useConnector()
Hook chính để truy cập trạng thái và hành động kết nối ví. Phải được sử dụng
trong một ConnectorProvider.
Trả về một đối tượng ConnectorSnapshot chứa:
Các Thuộc tính Trạng thái
-
wallets(WalletInfo[]) - Mảng tất cả các ví tương thích Wallet Standard được phát hiện. Tự động cập nhật khi ví được cài đặt hoặc gỡ cài đặt. Mỗi ví bao gồm metadata như tên, biểu tượng và khả năng. Xem WalletInfo. -
selectedWallet(Wallet | null) - Đối tượng ví Wallet Standard hiện đang được kết nối.nullkhi ngắt kết nối. Đây là instance ví thô từ Wallet Standard API. -
connected(boolean) - Trạng thái kết nối.truekhi một ví được kết nối và các tài khoản khả dụng. Sử dụng thuộc tính này để render UI có điều kiện. -
connecting(boolean) - Trạng thái đang tải trong quá trình kết nối ví.truegiữa lúc gọiselect()và nhận kết quả kết nối. Sử dụng thuộc tính này để hiển thị chỉ báo đang tải hoặc vô hiệu hóa các nút. -
accounts(AccountInfo[]) - Mảng các tài khoản từ ví đã kết nối. Hầu hết các ví cung cấp một tài khoản, nhưng một số hỗ trợ nhiều tài khoản. Tự động cập nhật thông qua sự kiện ví hoặc cơ chế polling. Xem AccountInfo. -
selectedAccount(string | null) - Địa chỉ của tài khoản hiện đang được chọn (khóa công khai được mã hóa base58). Khi một ví kết nối với một tài khoản mới, tài khoản đó sẽ tự động được chọn. Nếu không, tài khoản đã chọn trước đó sẽ được giữ nguyên.
Phương Thức Hành Động
-
select((walletName: string) => Promise<void>) - Kết nối với ví theo tên (ví dụ:"Phantom","Solflare"). Tên ví phải khớp chính xác với trườngnamecủa ví đã được phát hiện.Quy trình:
- Thiết lập
connecting: true - Gọi tính năng
standard:connectcủa ví - Lấy các tài khoản từ ví
- Đăng ký nhận sự kiện từ ví (hoặc bắt đầu polling nếu không có sự kiện)
- Lưu trữ tùy chọn ví trong bộ nhớ đã cấu hình
- Cập nhật trạng thái với các tài khoản và tài khoản đã chọn
Throws: Lỗi nếu không tìm thấy ví, ví không hỗ trợ kết nối, hoặc kết nối bị người dùng từ chối.
- Thiết lập
-
disconnect(() => Promise<void>) - Ngắt kết nối ví hiện tại và dọn dẹp toàn bộ trạng thái.Quy trình:
- Hủy đăng ký sự kiện từ ví
- Dừng polling tài khoản
- Gọi tính năng
standard:disconnectcủa ví nếu có - Xóa ví đã chọn, các tài khoản và tài khoản đã chọn
- Xóa tùy chọn ví khỏi bộ nhớ
Không bao giờ throw lỗi (lỗi được ghi log nếu bật chế độ debug).
-
selectAccount((address: string) => Promise<void>) - Chuyển đổi tài khoản đã chọn sang địa chỉ khác từ ví đã kết nối. Nếu địa chỉ không có trong mảng tài khoản hiện tại, sẽ kích hoạt kết nối lại để lấy các tài khoản đã cập nhật.Throws: Lỗi nếu không có ví kết nối hoặc không tìm thấy tài khoản được yêu cầu sau khi kết nối lại.
useConnectorClient()
Cung cấp quyền truy cập trực tiếp vào instance ConnectorClient bên dưới cho
các trường hợp sử dụng nâng cao.
Trả về: ConnectorClient | null - Instance client singleton, hoặc null
khi sử dụng bên ngoài ConnectorProvider.
Các trường hợp sử dụng:
- Truy cập trực tiếp vào
getConnectorState()để đọc trạng thái theo lệnh - Đăng ký thủ công với
subscribe(listener)cho các listener trạng thái tùy chỉnh - Gọi
destroy()để dọn dẹp bắt buộc (không khuyến nghị trong sử dụng thông thường)
Ví dụ:
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]);
Định Nghĩa Kiểu Dữ Liệu
WalletInfo
Metadata về một ví đã được phát hiện.
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 Yêu cầu: Một ví có thể kết nối khi nó hỗ trợ:
- Tính năng
standard:connect - Tính năng
standard:disconnect - Chuỗi Solana (được phát hiện thông qua
wallet.chainschứa"solana")
Các ví không thể kết nối xuất hiện trong mảng wallets nhưng không thể được
chọn.
AccountInfo
Thông tin về một tài khoản ví.
interface AccountInfo {address: string; // Base58-encoded public keyicon?: string; // Account-specific icon (data URL)raw: WalletAccount; // Raw WalletAccount object from Wallet Standard}
Trường raw cung cấp quyền truy cập vào các thuộc tính bổ sung của tài khoản:
address: string- Khóa công khai được mã hóa Base58publicKey: Uint8Array- Byte khóa công khai thôlabel?: string- Nhãn tài khoản (nếu ví cung cấp)icon?: string- Biểu tượng riêng của tài khoản (data URL)chains: string[]- Các chuỗi được hỗ trợ cho tài khoản nàyfeatures: string[]- Các tính năng được hỗ trợ cho tài khoản này
ConnectorSnapshot
Kiểu trả về của useConnector(), kết hợp trạng thái và hành động.
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;}
Phát Hiện Thay Đổi Tài Khoản
Connector tự động phát hiện khi tài khoản ví thay đổi (người dùng thêm/xóa tài khoản, chuyển đổi tài khoản trong ví). Hai chiến lược được sử dụng:
Dựa Trên Sự Kiện (Ưu Tiên)
Khi ví hỗ trợ standard:events, connector đăng ký các sự kiện change:
- Nhận thông báo thời gian thực khi tài khoản thay đổi
- Hiệu quả hơn (không cần polling)
- Tổng hợp tài khoản từ cả sự kiện và
wallet.accountsđể xử lý các ví chỉ bao gồm tài khoản đã chọn trong sự kiện
Dự Phòng Polling
Khi sự kiện không được hỗ trợ, connector sẽ polling wallet.accounts:
- Kiểm tra mỗi
accountPollingIntervalMs(mặc định: 1500ms) - So sánh địa chỉ tài khoản để phát hiện thay đổi
- Chỉ kích hoạt render lại khi tài khoản thực sự thay đổi
Logic Chọn Tài Khoản:
- Khi tài khoản thay đổi, giữ nguyên tài khoản đã chọn nếu nó vẫn tồn tại
- Nếu tài khoản đã chọn bị xóa, chọn tài khoản khả dụng đầu tiên
- Khi kết nối với tài khoản mới (không có trong các tài khoản trước đó), ưu tiên tài khoản mới
Lưu trữ & Tự động Kết nối
Lưu trữ Dữ liệu
Connector lưu trữ một khóa trong bộ nhớ đã cấu hình:
- Khóa:
arc-connector:lastWallet - Giá trị: Tên ví (ví dụ:
"Phantom")
Các thao tác lưu trữ được bao bọc trong try-catch để xử lý:
- Các iframe sandbox nơi
localStorageném lỗi - Môi trường SSR nơi
windowkhông được định nghĩa - React Native nơi
localStoragekhông tồn tại
Nếu lưu trữ thất bại, connector vẫn tiếp tục hoạt động mà không có tính năng lưu trữ (không ném lỗi).
Hành vi Tự động Kết nối
Khi autoConnect: true:
- Khi mount, đọc tên ví cuối cùng từ bộ nhớ
- Chờ 100ms (cho phép các ví đăng ký)
- Gọi
select(walletName)nếu phát hiện ví - Nếu tự động kết nối thất bại, xóa tùy chọn không hợp lệ khỏi bộ nhớ
Lưu ý Bảo mật: Tùy chọn được lưu trữ chỉ là tên ví (chuỗi), không phải dữ liệu nhạy cảm. Ví xử lý xác thực/ủy quyền thông qua giao diện người dùng riêng của nó.
Ví dụ Sử dụng
Nút Ví Cơ bản
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>);}
Bộ chọn Đa Tài khoản
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>);}
Giám sát Kết nối
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;}
Các Ví Được Hỗ trợ
Connector hỗ trợ tất cả các ví triển khai Wallet Standard, bao gồm:
- Phantom
- Solflare
- Backpack
- Glow
- Brave Wallet
- Coinbase Wallet
- Bất kỳ ví tương thích Wallet Standard nào khác
Các ví được tự động phát hiện khi chúng đăng ký với API Wallet Standard (không cần cấu hình).
Sử dụng Headless (Không dùng React)
Đối với các ứng dụng không dùng React hoặc sử dụng phía máy chủ, hãy dùng
ConnectorClient trực tiếp:
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();
Lưu ý: ConnectorClient quản lý trạng thái riêng của nó và không bao giờ
kích hoạt việc render lại trong React. Bạn phải tự theo dõi các thay đổi trạng
thái thủ công.
Is this page helpful?