External Wallet
Connect and interact with external wallets (MetaMask, WalletConnect) alongside embarkAI smart accounts.
embarkAI supports two wallet modes: linked (external wallet controls a smart account) and direct (use the external wallet directly). These hooks let you manage both modes.
Import
import {
useWalletMode,
useDirectWallet,
useSendDirectTransaction,
useTransferToLinkedWallet,
} from '@embarkai/ui-kit'useWalletMode
Returns the configured and the active wallet mode. In 'linked' mode, the external wallet is paired with an embarkAI smart account. In 'direct' mode, the external wallet is used as-is without account abstraction. When the Provider is configured with wallet.mode: 'both', the user (or your code) can switch between them.
import { useWalletMode } from '@embarkai/ui-kit'
function WalletModeIndicator() {
const { activeMode, configMode, isDirect, switchMode } = useWalletMode()
return (
<div>
<span>{isDirect ? 'Direct Wallet' : 'Smart Account (AA)'}</span>
{configMode === 'both' && (
<button onClick={() => switchMode(activeMode === 'direct' ? 'linked' : 'direct')}>
Switch mode
</button>
)}
</div>
)
}Return Value
| Property | Type | Description |
|---|---|---|
configMode | 'linked' | 'direct' | 'both' | Mode from wallet.mode in the Provider config. |
activeMode | 'linked' | 'direct' | 'both' | Mode currently in effect. |
switchMode | (mode: 'linked' | 'direct') => void | Switch the active mode; meaningful when configMode is 'both'. |
isDirect | boolean | true when transactions bypass account abstraction. |
useDirectWallet
Access the connected external wallet and its connect/disconnect actions. The hook always returns an object; check isConnected.
import { useDirectWallet } from '@embarkai/ui-kit'
function DirectWalletInfo() {
const wallet = useDirectWallet()
if (!wallet.isConnected) {
return <button onClick={() => wallet.connect()}>Connect external wallet</button>
}
return (
<div>
<p>External address: {wallet.address}</p>
<p>Connector: {wallet.connectorName}</p>
<p>Chain: {wallet.chainId}</p>
<button onClick={wallet.disconnect}>Disconnect</button>
</div>
)
}Return Value
| Property | Type | Description |
|---|---|---|
address | `0x${string}` | null | The external wallet address. |
chainId | number | null | Chain the external wallet is on. |
isConnected | boolean | Whether an external wallet is connected. |
connectorName | string | null | Name of the wallet connector (e.g., 'MetaMask', 'WalletConnect'). |
connect(flow?) / reconnect(flow?) | (flow?: 'link' | 'connect' | 'auth') => void | Open the wallet connection flow. |
disconnect | () => void | Disconnect the external wallet. |
useSendDirectTransaction
Send a transaction directly from the external wallet, bypassing account abstraction. Useful when the user needs to interact with contracts that don’t support smart accounts.
import { useSendDirectTransaction } from '@embarkai/ui-kit'
function DirectSend() {
const { sendTransaction, isPending, error, txHash } = useSendDirectTransaction()
const handleSend = async () => {
await sendTransaction({
to: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
value: '0.01',
})
}
return (
<div>
<button onClick={handleSend} disabled={isPending}>
{isPending ? 'Sending...' : 'Send (Direct)'}
</button>
{error && <p className="error">{error}</p>}
{txHash && <p>Tx: {txHash}</p>}
</div>
)
}Return Value
| Property | Type | Description |
|---|---|---|
sendTransaction | (params: { to: 0x; value: string; data?: 0x; chainId?: number }) => Promise<0x | null> | Submit a direct transaction. Returns the tx hash. |
isPending | boolean | true while the transaction is pending. |
error | string | null | Error message if the transaction failed. |
txHash | `0x${string}` | null | The transaction hash after submission. |
reset | () => void | Clear error and txHash. |
useTransferToLinkedWallet
Transfer assets from the smart account to a linked external wallet. Only available in 'linked' mode.
import { useActiveChainId, useTransferToLinkedWallet } from '@embarkai/ui-kit'
function FundLinkedWallet() {
const chainId = useActiveChainId()
const { transfer, isPending, error, userOpHash, linkedWallets } = useTransferToLinkedWallet()
const handleTransfer = async () => {
await transfer({
token: 'native',
amount: '0.5',
chainId,
})
}
if (!linkedWallets.length) return <p>No external wallet linked.</p>
return (
<div>
<button onClick={handleTransfer} disabled={isPending}>
{isPending ? 'Transferring...' : 'Send to linked wallet'}
</button>
{error && <p className="error">{error}</p>}
{userOpHash && <p>Sent! UserOp: {userOpHash}</p>}
</div>
)
}Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
token | `0x${string}` | 'native' | Yes | ERC-20 token address, or 'native' for the chain’s native token. |
amount | string | Yes | Amount to transfer (human-readable). |
chainId | number | Yes | Chain to transfer on. |
decimals | number | No | Token decimals for ERC-20. Defaults to 18. |
toAddress | `0x${string}` | No | Destination; defaults to the first entry of linkedWallets. |
Return Value
| Property | Type | Description |
|---|---|---|
transfer | (params) => Promise<string | null> | Execute the transfer. Returns the UserOperation hash. |
isPending | boolean | true while the transfer is pending. |
error | string | null | Error message if the transfer failed. |
userOpHash | string | null | The UserOperation hash after submission. |
linkedWallets | `0x${string}`[] | External wallets linked to this account. |
reset | () => void | Clear error and userOpHash. |
Full Example
import {
useActiveChainId,
useWalletMode,
useDirectWallet,
useTransferToLinkedWallet,
} from '@embarkai/ui-kit'
function ExternalWalletPanel() {
const chainId = useActiveChainId()
const { activeMode } = useWalletMode()
const wallet = useDirectWallet()
const { transfer, isPending } = useTransferToLinkedWallet()
if (!wallet.isConnected) return <p>Connect an external wallet to use these features.</p>
return (
<div>
<p>Mode: {activeMode}</p>
<p>External: {wallet.address}</p>
{activeMode === 'linked' && (
<button
onClick={() => transfer({ token: 'native', amount: '0.1', chainId })}
disabled={isPending}
>
Send 0.1 to linked wallet
</button>
)}
</div>
)
}Next Steps
- Hooks Overview — all available hooks
- useSendTransaction — send transactions via account abstraction
- Provider — configure external wallet connectors