Show balance & activity

2 min read
Guides
Web SDK

This guide assumes your app already renders inside a WavelengthProvider with a wallet unlocked and ready. See Create a wallet.

Read the balance

useWalletBalance() is a plain selector: it returns the current 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.

balance.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() is the same kind of selector: it returns the full transaction history array directly. Each 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 your WavelengthProvider wraps; see Create a wallet for how it is set up. No polling or manual refresh is needed.

balance.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() and 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() 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.

balance.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.

balance.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, Receive a Lightning payment, or Get a deposit address.