Skip to main content

Handle Accounts

A user can authorize multiple accounts when connecting their KEA Wallet. After the initial connection, your app receives an array of accounts and a default selected account. This guide covers how to access account data, switch the active account, and react to account changes — in both React and vanilla JavaScript.

Prerequisites

The WalletAccount Object

Every account returned by the SDK is a WalletAccount with three fields:

interface WalletAccount {
address: string; // Thru-format wallet address
label: string; // User-friendly account name
accountType: AddressType; // Address type — currently always "thru"
}
FieldTypeDescription
addressstringThe account's on-chain address in Thru format
labelstringA human-readable name the user assigned in KEA Wallet
accountTypeAddressTypeThe address type — currently only "thru" is supported

Accessing Accounts

After connecting, accounts are available immediately. The SDK provides both the full list and the currently selected (active) account:

import { useWallet } from '@kea-wallet/react-sdk';

function MyComponent() {
const { accounts, selectedAccount } = useWallet();

// accounts: WalletAccount[] — all authorized accounts
// selectedAccount: WalletAccount | null — the currently active account
}

React Integration

For React apps, KEA Wallet provides a pre-built component and two hooks. Choose the approach that matches your UI requirements.

Option A: Pre-built Account Switcher

The fastest path — a single component that handles account listing, switching, and disconnecting:

import { KeaAccountSwitcher } from '@kea-wallet/react-ui';

function Toolbar() {
return <KeaAccountSwitcher />;
}

The component handles two states:

StateRendersBehavior
Disconnected"Connect Wallet" buttonClick opens the wallet modal
ConnectedSelected address with dropdownLists all accounts + disconnect action

Selecting a different account in the dropdown calls selectAccount() internally and updates the UI.

warning

<KeaAccountSwitcher /> uses dark-themed inline styles that are not customizable via CSS and currently lacks ARIA attributes. For branded, styled, or accessible account selectors, use Option B below.

See KeaAccountSwitcher API reference.

Option B: Custom UI with useWallet()

For full control over styling and behavior, use the useWallet() hook:

import { useWallet } from '@kea-wallet/react-sdk';

function AccountList() {
const { accounts, selectedAccount, selectAccount } = useWallet();

return (
<ul>
{accounts.map((acc) => (
<li
key={acc.address}
onClick={() => selectAccount(acc)}
style={{ fontWeight: selectedAccount?.address === acc.address ? 'bold' : 'normal' }}
>
{acc.label}{acc.address}
{selectedAccount?.address === acc.address && ' (active)'}
</li>
))}
</ul>
);
}

Key points:

  • selectAccount() takes a WalletAccount object — pass the account from the accounts array directly.
  • Clicking the already-selected account is a no-op — no event fires, no state changes.
  • accounts does not change when switching — only selectedAccount updates.

See UseWalletReturn for all available properties.

Read-Only Hook: useAccounts()

Use useAccounts() in components that display account information but don't need to connect, disconnect, or switch accounts:

import { useAccounts } from '@kea-wallet/react-sdk';

function AccountStatus() {
const { accounts, selectedAccount, isConnected } = useAccounts({
onAccountSelect: (account) => {
console.log('Account switched to:', account.address);
},
});

if (!isConnected) return <p>Not connected</p>;

return (
<div>
<p>Active: {selectedAccount?.address}</p>
<p>Total accounts: {accounts.length}</p>
</div>
);
}

The onAccountSelect callback fires whenever the selected account changes — whether from this component or any other part of your app.

useWallet vs useAccounts:

CapabilityuseWallet()useAccounts()
accountsYesYes
selectedAccountYesYes
isConnected / isConnectingYesYes
selectAccount()Yes
connect() / disconnect()Yes
onAccountSelect callbackYes
wallet (chain adapter)Yes

Use useAccounts() for display-only components (dashboards, headers) and useWallet() when you need to trigger actions.

See UseAccountsOptions and UseAccountsReturn for the full API.

Vanilla JavaScript

For non-React apps, use BrowserSDK directly:

import { BrowserSDK } from '@kea-wallet/browser-sdk';

const sdk = new BrowserSDK({
rpcUrl: 'https://grpc-web.alphanet.thruput.org',
autoConnect: true,
});

await sdk.initialize();
await sdk.connect({ metadata: { appName: 'My App' } });

// Get all authorized accounts
const accounts = sdk.getAccounts();
const selected = sdk.getSelectedAccount();
console.log('Active account:', selected?.address);

// Switch to a different account
if (accounts.length > 1) {
const newSelected = await sdk.selectAccount(accounts[1].address);
console.log('Switched to:', newSelected.address);
}
API difference

In React, selectAccount() takes a WalletAccount object. In vanilla JS, selectAccount() takes a publicKey string and returns Promise<WalletAccount>.

If you pass an invalid address, selectAccount() throws an ACCOUNT_NOT_FOUND error. See the Error Handling guide.

Account persistence

The selected account does not persist across page reloads — it resets to accounts[0] when the session is restored via autoConnect. If your app needs persistence, store the selected address in localStorage and call selectAccount() after reconnection.

Listening for Account Changes

The accountChanged event fires whenever the active account is switched via selectAccount(). The payload is the new WalletAccount.

The simplest way in React — use the onAccountSelect callback:

const { accounts, selectedAccount } = useAccounts({
onAccountSelect: (account) => {
console.log('Switched to:', account.address);
},
});

Account-related events:

EventPayloadWhen it fires
accountChangedWalletAccountselectAccount() completes successfully
connectConnectResultInitial connection (includes the accounts array)
reconnecting{ isReconnecting: boolean }Auto-reconnect starts or ends

For the full event reference, see the SDK Events guide.

UX Best Practices

  • Show the account label alongside the addresslabel gives users a recognizable name instead of a raw address string.
  • Truncate addresses in the UI — display address.slice(0, 6)...address.slice(-4) for readability.
  • Highlight the active account — use a border, badge, or checkmark so users can see which account is selected at a glance.
  • Handle the single-account case — if only one account is authorized, you can skip the switcher or show it as informational without a dropdown.
  • Handle the empty stateaccounts is an empty array until the wallet is connected. Show a connect prompt instead of an empty list.

What's Next

  • Sign Transactions — Build and sign transactions with the active account
  • SDK Events — Full event reference including accountChanged, connect, disconnect
  • Error Handling — Handle ACCOUNT_NOT_FOUND and other errors