The Base Account SDK provides several core utility functions for managing cryptographic keys and accessing account information. These functions are essential for advanced integrations and Sub Account management.

Core Functions

generateKeyPair

Generates a new P256 key pair for use with Base Account.
import { generateKeyPair } from '@base-org/account';

const keyPair = await generateKeyPair();
console.log('New key pair generated:', keyPair);

getKeypair

Retrieves an existing P256 key pair if one has been previously generated and stored.
import { getKeypair } from '@base-org/account';

const existingKeyPair = await getKeypair();
if (existingKeyPair) {
  console.log('Found existing key pair');
} else {
  console.log('No existing key pair found');
}

getCryptoKeyAccount

import { getCryptoKeyAccount } from '@base-org/account';

const cryptoAccount = await getCryptoKeyAccount();
if (cryptoAccount?.account) {
  console.log('Account address:', cryptoAccount.account.address);
  console.log('Public key:', cryptoAccount.account.publicKey);
}

Complete Integration Example

Here’s how these utilities work together in a typical application:
import { 
  generateKeyPair, 
  getKeypair, 
  getCryptoKeyAccount,
  createBaseAccountSDK 
} from '@base-org/account';

class AccountManager {
  private sdk: any;
  
  constructor() {
    this.sdk = createBaseAccountSDK({
      appName: 'My App',
      appLogoUrl: 'https://example.com/logo.png',
      appChainIds: [8453], // Base mainnet
    });
  }
  
  // Initialize account management
  async initialize() {
    const account = await this.getCurrentAccount();
    
    if (!account) {
      console.log('No account found, user needs to connect');
      return null;
    }
    
    return account;
  }
  
  // Get current account or prompt connection
  async getCurrentAccount() {
    const cryptoAccount = await getCryptoKeyAccount();
    return cryptoAccount?.account || null;
  }
  
  // Get or generate key pair for advanced operations
  async getKeyPair() {
    let keyPair = await getKeypair();
    
    if (!keyPair) {
      console.log('Generating new key pair...');
      keyPair = await generateKeyPair();
    }
    
    return keyPair;
  }
  
  // Example: Use account for Sub Account creation
  async createSubAccount() {
    const account = await this.getCurrentAccount();
    const keyPair = await this.getKeyPair();
    
    if (!account || !keyPair) {
      throw new Error('Account and key pair required');
    }
    
    // Use the SDK to create sub account
    const subAccount = await this.sdk.subAccount.create({
      type: 'create',
      keys: [{
        type: 'webauthn-p256',
        publicKey: keyPair.publicKey,
      }],
    });
    
    return subAccount;
  }
  
  // Get account address for transactions
  getAccountAddress(): string | null {
    // This would be called after initialization
    const account = this.getCurrentAccount();
    return account?.address || null;
  }
}

// Usage
const accountManager = new AccountManager();

// Initialize and get account
const account = await accountManager.initialize();

if (account) {
  console.log('User is connected:', account.address);
  
  // Create sub account if needed
  const subAccount = await accountManager.createSubAccount();
  console.log('Sub account created:', subAccount.address);
} else {
  console.log('User needs to connect their account');
}

Error Handling

Handle common errors when using these utilities:
async function safeGetAccount() {
  try {
    const cryptoAccount = await getCryptoKeyAccount();
    return cryptoAccount?.account;
  } catch (error) {
    console.error('Error getting crypto account:', error);
    
    if (error.message.includes('not initialized')) {
      // SDK not properly initialized
      throw new Error('Base Account SDK not initialized');
    } else if (error.message.includes('permission denied')) {
      // User denied access
      throw new Error('User denied account access');
    } else {
      // Unknown error
      throw new Error('Failed to access account');
    }
  }
}

Best Practices

  1. Check for existing accounts: Always use getCryptoKeyAccount() first to check if a user is already connected
  2. Handle null returns: These functions can return null - always check before using the results
  3. Secure key management: If using generateKeyPair() or getKeypair(), handle private keys securely
  4. Error handling: Wrap calls in try-catch blocks to handle authentication and network errors
  5. User experience: Provide clear feedback when accounts aren’t found or need to be created
These utilities provide the foundation for advanced Base Account integrations, particularly when working with Sub Accounts and custom authentication flows.