---
title: "Show balance & activity"
description: "How to read the Wavelength balance and subscribe to the activity stream to display transaction history in your UI."
canonical: https://wavelength.lightning.engineering/guides/show-balance-and-activity/
---

> Docs index: https://wavelength.lightning.engineering/llms.txt

[Wavelength](/)›Guides›Show balance & activity

# Show balance & activity

2 min read

Guides

Web SDK

This guide assumes your app already renders inside a [`WavelengthProvider`](/reference/wavelength-react/#WavelengthProvider) with a wallet unlocked and ready. See [Create a wallet](/guides/create-a-wallet/).

## Read the balance

[`useWalletBalance()`](/reference/wavelength-react/#useWalletBalance) is a plain selector: it returns the current [`Balance`](/reference/wavelength-core/#Balance) directly (`null` before it is known), and re-renders your component only when the balance actually changes, for example after a payment settles. There is no `pending`/`busy` flag on it; a `null` balance is your loading signal.

Display `confirmedSat` as spendable balance. Add `pendingInSat` and `pendingOutSat` when you want to show in-flight funds.

```tsx
import { useWalletBalance } from '@lightninglabs/wavelength-react';

function Balance() {
  const balance = useWalletBalance();

  if (!balance) return <p>Loading...</p>;

  return (
    <p>
      {balance.confirmedSat.toLocaleString()} sats available
    </p>
  );
}
```

## Subscribe to activity

[`useWalletActivity()`](/reference/wavelength-react/#useWalletActivity) is the same kind of selector: it returns the full transaction history array directly. Each [`Entry`](/reference/wavelength-core/#Entry) has `id`, `kind` (`send`, `receive`, `deposit`, or `exit`), `amountSat`, `status` (`pending`, `complete`, or `failed`), and timestamps. It also carries `feeSat`, `counterparty`, `note`, and `failureReason` (a human-readable message set when `status` is `failed`).

The engine stays live: new entries arrive through the activity stream and pending entries update in place when they settle. This live-update behavior comes from the [`WalletEngine`](/reference/wavelength-core/#WalletEngine) your [`WavelengthProvider`](/reference/wavelength-react/#WavelengthProvider) wraps; see [Create a wallet](/guides/create-a-wallet/) for how it is set up. No polling or manual refresh is needed.

```tsx
import { useWalletActivity } from '@lightninglabs/wavelength-react';

function ActivityFeed() {
  const activity = useWalletActivity();

  if (activity.length === 0) return <p>No activity yet.</p>;

  return (
    <ul>
      {activity.map(entry => (
        <li key={entry.id}>
          <span>{entry.kind}</span>
          <span>
            {entry.kind === 'receive' || entry.kind === 'deposit' ? '+' : ''}
            {entry.kind === 'send' || entry.kind === 'exit' ? '-' : ''}
            {entry.amountSat} sats
          </span>
          <span>
            {entry.status}
            {entry.status === 'failed' && entry.failureReason
              ? `: ${entry.failureReason}`
              : ''}
          </span>
        </li>
      ))}
    </ul>
  );
}
```

## Pull-to-refresh

[`useWalletBalance()`](/reference/wavelength-react/#useWalletBalance) and [`useWalletActivity()`](/reference/wavelength-react/#useWalletActivity) update on their own as the engine’s background processes (the activity stream, the settle reconcile, the sync poll) keep the snapshot fresh, so most UIs need nothing more. For an explicit pull-to-refresh control, call `refresh()` from [`useWalletRefresh()`](/reference/wavelength-react/#useWalletRefresh) and show its `refreshPending` flag while the call is in flight. That `refreshPending` is scoped to this hook instance’s own calls; the engine’s own background refreshes never flip it, so it only lights up when the user actually asked for a refresh.

```tsx
import { useWalletRefresh } from '@lightninglabs/wavelength-react';

function RefreshButton() {
  const { refresh, refreshPending } = useWalletRefresh();

  return (
    <button onClick={() => refresh()} disabled={refreshPending}>
      {refreshPending ? 'Refreshing...' : 'Refresh'}
    </button>
  );
}
```

## Filter and group

Filter `activity` with standard array methods to build tab views or summary cards. Use each entry’s `kind` to determine direction (`receive` and `deposit` are inbound; `send` and `exit` are outbound). `amountSat` is a plain magnitude in satoshis. Filter on `status === 'pending'` to surface in-flight payments that need user attention.

All filtering happens in memory, so you can derive multiple views from the same hook call without additional network requests.

```tsx
import { useWalletActivity } from '@lightninglabs/wavelength-react';

function FilteredFeed() {
  const activity = useWalletActivity();

  const sends = activity.filter(entry => entry.kind === 'send');
  const receives = activity.filter(entry => entry.kind === 'receive');
  const pending = activity.filter(entry => entry.status === 'pending');

  return (
    <div>
      <p>Pending: {pending.length}</p>
      <p>Received: {receives.length} txs</p>
      <p>Sent: {sends.length} txs</p>
    </div>
  );
}
```

## What’s next

Now that your UI can show balance and activity, try [Send a payment](/guides/send-a-payment/), [Receive a Lightning payment](/guides/receive-a-lightning-payment/), or [Get a deposit address](/guides/get-a-deposit-address/).
