/* eslint-disable valtio/state-snapshot-rule */ import { ConnectionsController, CoreHelperUtil, LogController } from '@reown/appkit-core-react-native'; import { useMemo } from 'react'; import { useSnapshot } from 'valtio'; import type { AccountType, AppKitNetwork } from '@reown/appkit-common-react-native'; import { useAppKitContext } from './useAppKitContext'; /** * Represents a blockchain account with its associated metadata */ export interface Account { /** The blockchain address of the account */ address: string; /** The blockchain namespace (e.g., 'eip155' for Ethereum, 'solana' for Solana) */ namespace: string; /** The chain ID where this account is active */ chainId: string; /** Optional account type (e.g. 'eoa' or 'smartAccount') */ type?: AccountType; } /** * Hook to access the current account state and connection information * * @remarks * This hook provides access to all connected accounts, the currently active account, * connection status, and active chain information. It automatically subscribes to * connection state changes via valtio. * * The hook parses account data from CAIP-10 format (namespace:chainId:address) * and provides a normalized structure. * * @returns An object containing: * - `allAccounts` - Array of all connected accounts across all connections * - `address` - The plain address of the currently active account (without namespace or chain prefix) * - `isConnected` - Boolean indicating if a wallet is currently connected * - `chainId` - The ID of the currently active chain * - `chain` - The full chain/network object of the currently active chain * - `namespace` - The namespace of the currently active account (e.g. 'eip155', 'solana' or 'bip122') * * @example * ```tsx * function MyComponent() { * const { address, isConnected, chainId, allAccounts } = useAccount(); * * if (!isConnected) { * return Not connected; * } * * return ( * * Connected: {address} * Chain: {chainId} * Total accounts: {allAccounts.length} * * ); * } * ``` * * @throws Will log errors via LogController if account parsing fails */ export function useAccount() { useAppKitContext(); const { activeAddress: address, activeNamespace, connection, connections, networks } = useSnapshot(ConnectionsController.state); const allAccounts: Account[] = useMemo(() => { if (!address) return []; return Array.from(connections.values()).flatMap( _connection => _connection.accounts .map(account => { const [namespace, chainId, plainAddress] = account.split(':'); if (!plainAddress || !namespace || !chainId) { LogController.sendError('Invalid account', 'useAccount.ts', 'useAccount', { account }); return undefined; } return { address: plainAddress, namespace, chainId, type: _connection.type }; }) .filter(account => account !== undefined) as Account[] ); }, [connections, address]); const activeChain = useMemo( () => connection?.caipNetwork ? networks.find(network => network.caipNetworkId === connection?.caipNetwork) : undefined, [connection?.caipNetwork, networks] ); return { allAccounts, address: CoreHelperUtil.getPlainAddress(address), isConnected: !!address, chainId: activeChain?.id !== undefined ? String(activeChain.id) : undefined, chain: activeChain as AppKitNetwork | undefined, namespace: activeNamespace }; }