Skip to content

Wallet Operations ​

This guide provides comprehensive examples for managing wallet operations using the Flutterwave SDK. You can check balances, view statements, and resolve wallet accounts.

Overview ​

The Wallets API allows you to:

  • Check balance for a specific currency
  • Get balances for all currencies
  • View wallet statements (transaction history)
  • Resolve wallet account information

Balance Operations ​

Get Balance for Specific Currency ​

typescript
import { Flutterwave } from 'flutterwave-node-v4';

const flutterwave = new Flutterwave({
  clientId: process.env.CLIENT_ID!,
  clientSecret: process.env.CLIENT_SECRET!,
  environment: 'sandbox',
});

const balance = await flutterwave.api.wallets.balance('NGN');

console.log('Currency:', balance.currency);
console.log('Available Balance:', balance.available_balance);
console.log('Total Balance:', balance.total_balance);
console.log('Ledger Balance:', balance.ledger_balance);

Get All Currency Balances ​

typescript
const balances = await flutterwave.api.wallets.balances();

console.log(`You have balances in ${balances.length} currencies`);

balances.forEach((balance) => {
  console.log(`${balance.currency}: ${balance.available_balance}`);
});

Understanding Balance Types ​

typescript
const balance = await flutterwave.api.wallets.balance('NGN');

// Available Balance - Funds available for withdrawal/transfer
console.log('Available:', balance.available_balance);

// Total Balance - All funds in the wallet
console.log('Total:', balance.total_balance);

// Ledger Balance - Balance including pending transactions
console.log('Ledger:', balance.ledger_balance);

// The difference shows funds that are locked or pending
const locked = balance.total_balance - balance.available_balance;
console.log('Locked/Pending:', locked);

Multi-Currency Operations ​

Check Multiple Currencies ​

typescript
async function checkMultipleCurrencies(currencies: string[]) {
  const results = [];

  for (const currency of currencies) {
    try {
      const balance = await flutterwave.api.wallets.balance(currency);
      results.push({
        currency,
        available: balance.available_balance,
        total: balance.total_balance,
      });
    } catch (error) {
      results.push({
        currency,
        error: 'Unable to fetch balance',
      });
    }
  }

  return results;
}

// Usage
const balances = await checkMultipleCurrencies(['NGN', 'USD', 'GHS', 'KES']);

balances.forEach((balance) => {
  if ('error' in balance) {
    console.log(`${balance.currency}: ${balance.error}`);
  } else {
    console.log(`${balance.currency}: ${balance.available}`);
  }
});

Compare Balances Across Currencies ​

typescript
async function compareBalances() {
  const balances = await flutterwave.api.wallets.balances();

  console.log('Balance Comparison:');
  console.log('===================');

  balances
    .sort((a, b) => b.available_balance - a.available_balance)
    .forEach((balance, index) => {
      console.log(
        `${index + 1}. ${balance.currency}: ${balance.available_balance.toLocaleString()}`,
      );
    });
}

await compareBalances();

Account Resolution ​

Resolve Wallet Account ​

typescript
const resolved = await flutterwave.api.wallets.accountResolve({
  provider: 'flutterwave',
  identifier: '00118468',
});

console.log('Account Identifier:', resolved.identifier);
console.log('Account Name:', resolved.name);
console.log('Provider:', resolved.provider);

Batch Account Resolution ​

typescript
async function resolveMultipleAccounts(identifiers: string[]) {
  const results = [];

  for (const identifier of identifiers) {
    try {
      const resolved = await flutterwave.api.wallets.accountResolve({
        provider: 'flutterwave',
        identifier,
      });

      results.push({
        identifier,
        name: resolved.name,
        provider: resolved.provider,
        success: true,
      });
    } catch (error) {
      results.push({
        identifier,
        error: error instanceof Error ? error.message : 'Resolution failed',
        success: false,
      });
    }
  }

  return results;
}

// Usage
const accounts = await resolveMultipleAccounts([
  '00118468',
  '00118469',
  '00118470',
]);

accounts.forEach((account) => {
  if (account.success) {
    console.log(`${account.identifier}: ${account.name}`);
  } else {
    console.log(`${account.identifier}: Failed - ${account.error}`);
  }
});

Wallet Statements ​

Get Transaction Statement ​

typescript
const statement = await flutterwave.api.wallets.statement({
  page: 1,
  size: 20,
  currency: 'NGN',
});

console.log(`Total Transactions: ${statement.meta.total}`);
console.log(`Current Page: ${statement.meta.current_page}`);

statement.data.forEach((transaction) => {
  console.log(
    `${transaction.date}: ${transaction.type} - ${transaction.amount} ${transaction.currency}`,
  );
});

Filter Statements by Date Range ​

typescript
async function getStatementByDateRange(
  startDate: Date,
  endDate: Date,
  currency: string = 'NGN',
) {
  const statement = await flutterwave.api.wallets.statement({
    page: 1,
    size: 100,
    currency,
    from: startDate.toISOString(),
    to: endDate.toISOString(),
  });

  return statement;
}

// Usage - Get last 30 days
const endDate = new Date();
const startDate = new Date();
startDate.setDate(startDate.getDate() - 30);

const recentTransactions = await getStatementByDateRange(startDate, endDate);
console.log('Transactions in last 30 days:', recentTransactions.data.length);

Paginated Statement Retrieval ​

typescript
async function getAllStatementPages(currency: string = 'NGN') {
  const allTransactions = [];
  let currentPage = 1;
  let hasMore = true;

  while (hasMore) {
    const statement = await flutterwave.api.wallets.statement({
      page: currentPage,
      size: 50,
      currency,
    });

    allTransactions.push(...statement.data);

    hasMore = currentPage < statement.meta.total_pages;
    currentPage++;
  }

  return allTransactions;
}

// Usage
const allTransactions = await getAllStatementPages('NGN');
console.log('Total transactions:', allTransactions.length);

Balance Monitoring ​

Monitor Balance Changes ​

typescript
interface BalanceSnapshot {
  timestamp: Date;
  currency: string;
  available: number;
  total: number;
  ledger: number;
}

const balanceHistory: BalanceSnapshot[] = [];

async function takeBalanceSnapshot(currency: string): Promise<BalanceSnapshot> {
  const balance = await flutterwave.api.wallets.balance(currency);

  const snapshot: BalanceSnapshot = {
    timestamp: new Date(),
    currency: balance.currency,
    available: balance.available_balance,
    total: balance.total_balance,
    ledger: balance.ledger_balance,
  };

  balanceHistory.push(snapshot);

  return snapshot;
}

// Take snapshots every hour
setInterval(
  async () => {
    await takeBalanceSnapshot('NGN');
    console.log('Balance snapshot taken');
  },
  60 * 60 * 1000,
);

Alert on Low Balance ​

typescript
async function checkBalanceAndAlert(
  currency: string,
  threshold: number,
  alertCallback: (balance: number) => void,
) {
  const balance = await flutterwave.api.wallets.balance(currency);

  if (balance.available_balance < threshold) {
    console.warn(`Low balance alert for ${currency}!`);
    console.warn(
      `Current: ${balance.available_balance}, Threshold: ${threshold}`,
    );
    alertCallback(balance.available_balance);
  }

  return balance;
}

// Usage
await checkBalanceAndAlert('NGN', 100000, (balance) => {
  // Send email, SMS, or push notification
  console.log(`ALERT: Balance is ${balance}, please top up!`);
});
typescript
interface BalanceTrend {
  currency: string;
  startBalance: number;
  endBalance: number;
  change: number;
  changePercentage: number;
  period: string;
}

async function analyzeBalanceTrend(
  currency: string,
  periodDays: number = 7,
): Promise<BalanceTrend> {
  // Get current balance
  const currentBalance = await flutterwave.api.wallets.balance(currency);

  // Get balance from history (in a real app, fetch from database)
  const startSnapshot = balanceHistory.find(
    (s) =>
      s.currency === currency &&
      s.timestamp.getTime() <= Date.now() - periodDays * 24 * 60 * 60 * 1000,
  );

  if (!startSnapshot) {
    throw new Error('No historical data available');
  }

  const change = currentBalance.available_balance - startSnapshot.available;
  const changePercentage = (change / startSnapshot.available) * 100;

  return {
    currency,
    startBalance: startSnapshot.available,
    endBalance: currentBalance.available_balance,
    change,
    changePercentage,
    period: `${periodDays} days`,
  };
}

// Usage
const trend = await analyzeBalanceTrend('NGN', 30);
console.log(
  `Balance changed by ${trend.change} (${trend.changePercentage.toFixed(2)}%) over ${trend.period}`,
);

Transaction Analysis ​

Calculate Total Income and Expenses ​

typescript
async function analyzeTransactions(currency: string = 'NGN') {
  const statement = await flutterwave.api.wallets.statement({
    page: 1,
    size: 1000,
    currency,
  });

  let income = 0;
  let expenses = 0;

  statement.data.forEach((transaction) => {
    if (transaction.type === 'credit') {
      income += transaction.amount;
    } else if (transaction.type === 'debit') {
      expenses += transaction.amount;
    }
  });

  return {
    currency,
    income,
    expenses,
    net: income - expenses,
    transactionCount: statement.data.length,
  };
}

// Usage
const analysis = await analyzeTransactions('NGN');
console.log('Income:', analysis.income);
console.log('Expenses:', analysis.expenses);
console.log('Net:', analysis.net);

Group Transactions by Type ​

typescript
async function groupTransactionsByType(currency: string = 'NGN') {
  const statement = await flutterwave.api.wallets.statement({
    page: 1,
    size: 1000,
    currency,
  });

  const grouped = statement.data.reduce(
    (acc, transaction) => {
      const type = transaction.type || 'unknown';
      if (!acc[type]) {
        acc[type] = {
          count: 0,
          total: 0,
          transactions: [],
        };
      }

      acc[type].count++;
      acc[type].total += transaction.amount;
      acc[type].transactions.push(transaction);

      return acc;
    },
    {} as Record<string, { count: number; total: number; transactions: any[] }>,
  );

  return grouped;
}

// Usage
const grouped = await groupTransactionsByType('NGN');

Object.entries(grouped).forEach(([type, data]) => {
  console.log(`${type}: ${data.count} transactions, Total: ${data.total}`);
});

Balance Reconciliation ​

Reconcile Expected vs Actual Balance ​

typescript
interface ExpectedTransaction {
  amount: number;
  type: 'credit' | 'debit';
  description: string;
}

async function reconcileBalance(
  currency: string,
  expectedTransactions: ExpectedTransaction[],
) {
  const actualBalance = await flutterwave.api.wallets.balance(currency);

  // Calculate expected balance
  const expectedChange = expectedTransactions.reduce((sum, tx) => {
    return sum + (tx.type === 'credit' ? tx.amount : -tx.amount);
  }, 0);

  // Get statement to verify
  const statement = await flutterwave.api.wallets.statement({
    page: 1,
    size: 100,
    currency,
  });

  return {
    currency,
    actualAvailable: actualBalance.available_balance,
    actualTotal: actualBalance.total_balance,
    expectedChange,
    matchedTransactions: statement.data.length,
    reconciled: true, // Add your reconciliation logic
  };
}

// Usage
const reconciliation = await reconcileBalance('NGN', [
  { amount: 10000, type: 'credit', description: 'Payment received' },
  { amount: 5000, type: 'debit', description: 'Transfer sent' },
]);

console.log('Reconciliation Result:', reconciliation);

Error Handling ​

Robust Balance Check ​

typescript
import {
  BadRequestException,
  UnauthorizedRequestException,
} from 'flutterwave-node-v4';

async function safeGetBalance(currency: string) {
  try {
    const balance = await flutterwave.api.wallets.balance(currency);

    return {
      success: true,
      data: balance,
    };
  } catch (error) {
    if (error instanceof BadRequestException) {
      console.error('Invalid currency:', error.message);
      return {
        success: false,
        error: 'Invalid currency code',
        message: 'Please provide a valid currency code',
      };
    } else if (error instanceof UnauthorizedRequestException) {
      console.error('Authentication failed:', error.message);
      return {
        success: false,
        error: 'Authentication error',
        message: 'Please check your credentials',
      };
    } else {
      console.error('Failed to get balance:', error);
      return {
        success: false,
        error: 'Balance fetch failed',
        message: 'An unexpected error occurred',
      };
    }
  }
}

// Usage
const result = await safeGetBalance('NGN');

if (result.success) {
  console.log('Balance:', result.data.available_balance);
} else {
  console.error('Error:', result.message);
}

Best Practices ​

1. Cache Balance Data ​

typescript
interface BalanceCache {
  balance: any;
  timestamp: number;
  currency: string;
}

const balanceCache: Map<string, BalanceCache> = new Map();
const CACHE_DURATION = 60 * 1000; // 1 minute

async function getCachedBalance(currency: string) {
  const cached = balanceCache.get(currency);

  if (cached && Date.now() - cached.timestamp < CACHE_DURATION) {
    console.log('Using cached balance');
    return cached.balance;
  }

  console.log('Fetching fresh balance');
  const balance = await flutterwave.api.wallets.balance(currency);

  balanceCache.set(currency, {
    balance,
    timestamp: Date.now(),
    currency,
  });

  return balance;
}

2. Handle Rate Limiting ​

typescript
async function getBalanceWithRetry(
  currency: string,
  maxRetries: number = 3,
): Promise<any> {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await flutterwave.api.wallets.balance(currency);
    } catch (error) {
      if (attempt === maxRetries) {
        throw error;
      }

      const delay = Math.pow(2, attempt) * 1000;
      console.log(`Retry attempt ${attempt} in ${delay}ms...`);
      await new Promise((resolve) => setTimeout(resolve, delay));
    }
  }
}

3. Log All Balance Checks ​

typescript
interface BalanceLog {
  timestamp: Date;
  currency: string;
  balance: number;
  operation: string;
}

const balanceLogs: BalanceLog[] = [];

async function loggedBalanceCheck(currency: string, operation: string) {
  const balance = await flutterwave.api.wallets.balance(currency);

  balanceLogs.push({
    timestamp: new Date(),
    currency,
    balance: balance.available_balance,
    operation,
  });

  return balance;
}

// Usage
await loggedBalanceCheck('NGN', 'pre-transfer-check');
// Perform transfer
await loggedBalanceCheck('NGN', 'post-transfer-check');

4. Validate Currency Codes ​

typescript
const SUPPORTED_CURRENCIES = ['NGN', 'USD', 'GHS', 'KES', 'ZAR', 'TZS', 'UGX'];

function validateCurrency(currency: string): void {
  if (!SUPPORTED_CURRENCIES.includes(currency.toUpperCase())) {
    throw new Error(
      `Unsupported currency: ${currency}. Supported: ${SUPPORTED_CURRENCIES.join(', ')}`,
    );
  }
}

// Usage
try {
  validateCurrency('NGN');
  const balance = await flutterwave.api.wallets.balance('NGN');
} catch (error) {
  console.error('Validation failed:', error.message);
}

Real-Time Balance Tracking ​

Create Balance Dashboard ​

typescript
interface BalanceDashboard {
  totalInNGN: number;
  balances: Array<{
    currency: string;
    available: number;
    total: number;
  }>;
  lastUpdated: Date;
}

async function createBalanceDashboard(): Promise<BalanceDashboard> {
  const balances = await flutterwave.api.wallets.balances();

  // Convert all to NGN for total (using exchange rates)
  const totalInNGN = balances.reduce((sum, balance) => {
    // In a real app, apply exchange rates
    const rate = getExchangeRate(balance.currency, 'NGN');
    return sum + balance.available_balance * rate;
  }, 0);

  return {
    totalInNGN,
    balances: balances.map((b) => ({
      currency: b.currency,
      available: b.available_balance,
      total: b.total_balance,
    })),
    lastUpdated: new Date(),
  };
}

function getExchangeRate(from: string, to: string): number {
  // Placeholder - implement actual exchange rate lookup
  return from === to ? 1 : 1;
}

// Usage
const dashboard = await createBalanceDashboard();
console.log('Total Balance (NGN):', dashboard.totalInNGN);
dashboard.balances.forEach((b) => {
  console.log(`${b.currency}: ${b.available}`);
});

Released under the MIT License.