Skip to content

useWallet Hook

⚠️ Development Version - Not Production Ready

This documentation reflects the latest development version. Some features may be incomplete or subject to change. Do not use in production environments.

The useWallet hook is the primary interface for interacting with LazorKit wallets in React applications.

Import

import { useWallet } from '@lazorkit/wallet';

Quick Start

import { useWallet } from '@lazorkit/wallet';
import { SystemProgram, LAMPORTS_PER_SOL } from '@solana/web3.js';
 
function WalletComponent() {
  const { 
    account, 
    isConnected, 
    connect, 
    disconnect, 
    signAndSendTransaction 
  } = useWallet();
 
  const handleConnect = () => connect();
  const handleSend = async () => {
    if (!account) return;
    
    const instruction = SystemProgram.transfer({
      fromPubkey: account.smartWallet,
      toPubkey: 'RECIPIENT_ADDRESS',
      lamports: 0.1 * LAMPORTS_PER_SOL,
    });
    
    const signature = await signAndSendTransaction(instruction);
    console.log('Sent:', signature);
  };
 
  return (
    <div>
      {!isConnected ? (
        <button onClick={handleConnect}>Connect Wallet</button>
      ) : (
        <div>
          <p>Connected: {account.smartWallet}</p>
          <button onClick={handleSend}>Send SOL</button>
          <button onClick={disconnect}>Disconnect</button>
        </div>
      )}
    </div>
  );
}

Complete Interface

const {
  // State
  account,                    // WalletAccount | null
  smartWalletPubkey,         // PublicKey | null  
  isConnected,               // boolean
  isConnecting,              // boolean
  isSigning,                 // boolean
  error,                     // Error | null
 
  // Core Actions
  connect,                   // () => Promise<WalletAccount>
  disconnect,                // () => Promise<void>
  signAndSendTransaction,    // (instruction) => Promise<string>
 
  // Advanced Actions  
  signTransaction,           // (instruction) => Promise<Transaction>
  buildSmartWalletTransaction, // (payer, instruction) => Promise<{...}>
  createPasskeyOnly,         // () => Promise<ConnectResponse>
  createSmartWalletOnly,     // (passkey) => Promise<{...}>
} = useWallet();

State Properties

PropertyTypeDescription
accountWalletAccount | nullComplete wallet info when connected
smartWalletPubkeyPublicKey | nullSmart wallet public key
isConnectedboolean!!account - connection status
isConnectingbooleanConnection operation in progress
isSigningbooleanTransaction signing in progress
errorError | nullLast error that occurred

WalletAccount Type

interface WalletAccount {
  publicKey: string;      // Passkey public key (base64)
  smartWallet: string;    // Smart wallet address (base58)
  isConnected: boolean;   // Always true when account exists
  isCreated: boolean;     // True if just created
}

Core Actions

connect()

Returns: Promise<WalletAccount>
Throws: Error with specific error codes

Connects wallet with auto-reconnection fallback.

try {
  const account: WalletAccount = await connect();
  // account = {
  //   publicKey: "base64-encoded-passkey-public-key",
  //   smartWallet: "base58-wallet-address", 
  //   isConnected: true,
  //   isCreated: boolean // true if just created
  // }
  console.log('Connected:', account.smartWallet);
} catch (error: Error) {
  // error.code will be one of:
  // 'NO_STORED_CREDENTIALS' | 'USER_CANCELLED' | 'CONNECTION_FAILED'
  console.error('Connection failed:', error.code, error.message);
}

disconnect()

Returns: Promise<void>
Throws: Rarely throws, logs errors internally

Disconnects wallet but preserves session for reconnection.

try {
  await disconnect(); // Always resolves
  // State after disconnect:
  // account = null, isConnected = false
} catch (error) {
  // Usually logs internally, rarely throws
}

signAndSendTransaction()

Returns: Promise<string> (transaction signature)
Throws: Error with transaction-specific codes

Signs and sends transaction, returns signature.

try {
  const signature: string = await signAndSendTransaction(instruction);
  // signature = "base58-transaction-signature"
  console.log('Transaction sent:', signature);
  
  // Verify on explorer: 
  // https://explorer.solana.com/tx/${signature}?cluster=devnet
} catch (error: Error) {
  // error.code possibilities:
  // 'NOT_CONNECTED' - no wallet connected
  // 'USER_CANCELLED' - user cancelled signing
  // 'TRANSACTION_FAILED' - network/execution error
  // 'INSUFFICIENT_FUNDS' - not enough SOL/tokens
  
  switch (error.code) {
    case 'NOT_CONNECTED':
      console.log('Please connect wallet first');
      break;
    case 'USER_CANCELLED':
      console.log('User cancelled transaction');
      break;
    case 'INSUFFICIENT_FUNDS':
      console.log('Not enough balance');
      break;
    default:
      console.error('Transaction failed:', error.message);
  }
}

Advanced Actions

signTransaction()

Returns: Promise<Transaction> (signed but not sent)
Throws: Error with signing-specific codes

Signs transaction without sending to network.

try {
  const signedTx: Transaction = await signTransaction(instruction);
  // signedTx is a fully signed Solana Transaction object
  // You can inspect: signedTx.signatures, signedTx.instructions
  
  // Send later manually if needed:
  // const signature = await connection.sendTransaction(signedTx);
} catch (error: Error) {
  // Same error codes as signAndSendTransaction except 'TRANSACTION_FAILED'
  console.error('Signing failed:', error.code);
}

buildSmartWalletTransaction()

Returns: Promise<{createSessionTx: VersionedTransaction, executeSessionTx: VersionedTransaction}>
Throws: Error if wallet not connected or instruction invalid

Creates unsigned transactions for external payer integration.

try {
  const externalPayer = new PublicKey('EXTERNAL_PAYER_ADDRESS');
  const result = await buildSmartWalletTransaction(externalPayer, instruction);
  
  // result = {
  //   createSessionTx: VersionedTransaction, // Creates session account
  //   executeSessionTx: VersionedTransaction // Executes your instruction
  // }
  
  // Both transactions are UNSIGNED - external payer must sign
  const serializedSessionTx = result.createSessionTx.serialize();
  const serializedExecuteTx = result.executeSessionTx.serialize();
  
  // Send to backend service that controls external payer
  await sendToBackend({
    sessionTx: Buffer.from(serializedSessionTx).toString('base64'),
    executeTx: Buffer.from(serializedExecuteTx).toString('base64')
  });
} catch (error: Error) {
  // error.code: 'NOT_CONNECTED' | 'INVALID_INSTRUCTION'
  console.error('Build failed:', error.message);
}

createPasskeyOnly()

Returns: Promise<ConnectResponse>
Throws: Error if WebAuthn fails

Creates passkey without deploying smart wallet.

try {
  const passkeyData: ConnectResponse = await createPasskeyOnly();
  // passkeyData = {
  //   publicKey: "base64-encoded-public-key",
  //   credentialId: "webauthn-credential-id", 
  //   isCreated: true, // true = new, false = existing
  //   connectionType: "create" | "get",
  //   timestamp: 1640995200000
  // }
  
  // Store passkeyData for later wallet deployment
  localStorage.setItem('tempPasskey', JSON.stringify(passkeyData));
} catch (error: Error) {
  // error.code: 'USER_CANCELLED' | 'PASSKEY_CREATION_FAILED'
  console.error('Passkey creation failed:', error.code);
}

createSmartWalletOnly()

Returns: Promise<{smartWalletAddress: string, account: WalletAccount}>
Throws: Error if deployment fails

Deploys smart wallet using existing passkey data.

try {
  const result = await createSmartWalletOnly(passkeyData);
  // result = {
  //   smartWalletAddress: "base58-wallet-address",
  //   account: WalletAccount // Same as connect() return
  // }
  
  console.log('Wallet deployed at:', result.smartWalletAddress);
  // Now account.isConnected = true and hook state updates
} catch (error: Error) {
  // error.code: 'INVALID_PASSKEY_DATA' | 'SMART_WALLET_CREATION_FAILED'
  console.error('Wallet deployment failed:', error.code);
}

Common Examples

Error Handling

try {
  const account = await connect();
} catch (error) {
  switch (error.code) {
    case 'NO_STORED_CREDENTIALS':
      console.log('First time user');
      break;
    case 'USER_CANCELLED':
      console.log('User cancelled authentication');
      break;
    default:
      console.error('Connection failed:', error);
  }
}

Step-by-Step Creation

// Step 1: Create passkey
const passkeyData = await createPasskeyOnly();
 
// Step 2: Deploy wallet (can be done later)
const { account } = await createSmartWalletOnly(passkeyData);
console.log('Wallet ready:', account.smartWallet);

External Payer Pattern

const { createSessionTx, executeSessionTx } = await buildSmartWalletTransaction(
  externalPayerPubkey,
  instruction
);
// Send serialized transactions to backend for signing

Loading States

<button 
  onClick={handleTransfer} 
  disabled={!isConnected || isSigning}
>
  {isSigning ? 'Sending...' : 'Transfer SOL'}
</button>

Complete Error Reference

All LazorKit errors extend the base Error class with an additional code property:

interface LazorkitError extends Error {
  code: string;           // Specific error code
  message: string;        // Human-readable message
  details?: any;          // Additional error context
}

Connection Errors

CodeMethodDescriptionAction
NO_STORED_CREDENTIALSconnect()First time userShow onboarding
USER_CANCELLEDconnect()User cancelled WebAuthnRetry or alternative
INVALID_CREDENTIALSconnect()Corrupted stored dataAuto-cleared, retry
CONNECTION_FAILEDconnect()Network/service errorCheck network, retry

Transaction Errors

CodeMethodDescriptionAction
NOT_CONNECTEDsignAndSendTransaction()No wallet connectedCall connect() first
USER_CANCELLEDsignAndSendTransaction()User cancelled signingUser choice, no action
INSUFFICIENT_FUNDSsignAndSendTransaction()Not enough balanceShow balance, request funds
TRANSACTION_FAILEDsignAndSendTransaction()Network/execution errorCheck network, retry

Creation Errors

CodeMethodDescriptionAction
PASSKEY_CREATION_FAILEDcreatePasskeyOnly()WebAuthn device errorCheck device, retry
SMART_WALLET_CREATION_FAILEDcreateSmartWalletOnly()Deployment failedCheck network, retry
INVALID_PASSKEY_DATAcreateSmartWalletOnly()Bad passkey inputRecreate passkey

Error Handling Pattern

const handleWalletError = (error: LazorkitError) => {
  switch (error.code) {
    case 'NO_STORED_CREDENTIALS':
      return 'Welcome! Let\'s create your first wallet.';
    case 'USER_CANCELLED':
      return 'Authentication cancelled. Try again when ready.';
    case 'INSUFFICIENT_FUNDS':
      return `Not enough balance. Need ${error.details?.required} SOL.`;
    case 'CONNECTION_FAILED':
      return 'Network error. Please check connection and retry.';
    default:
      return `Unexpected error: ${error.message}`;
  }
};
 
// Usage
try {
  await connect();
} catch (error) {
  const userMessage = handleWalletError(error);
  setErrorMessage(userMessage);
}

See Type Definitions for complete interfaces.