Activity & events

The activity stream

Every deposit, payment, and exit shows up in one ordered history. Wavelength keeps that history as a stream you can snapshot once or subscribe to for live updates as operations settle.

Wallet history in Wavelength is an activity stream: a sequence of Entry objects, one per user-visible wallet operation. Deposits, Lightning receives, sends, and cooperative exits each create an entry when they start and update in place as they settle.

You can read history in two ways:

  • list({ view: 'activity' }) for a paginated snapshot. Filter with pendingOnly or kinds, and page with limit and the string list cursor:

    const result = await client.list({
    view: 'activity',
    kinds: ['receive', 'deposit'],
    });
    const { activity } = result;
    // activity.entries, activity.hasMore, activity.nextCursor
  • startActivity() for a live stream that pushes updates until you call stopActivity().

For UI work, prefer the live stream. Call subscribe() first to register a listener, then open the stream with the entry kinds you need. Persist the last numeric Entry.cursor you processed and pass it back to resume after that position:

await client.startActivity({
includeExisting: true,
kinds: ['send', 'receive'],
});
await client.startActivity({
kinds: ['send', 'receive'],
cursor: lastCursor,
});

Each update arrives as a WavelengthEvent with type: 'activity' and the changed entry as payload. Pending entries mutate (status, phase, txid, confirmation height) until they reach complete or failed.

Direct clients also receive a terminal activityStream event when a stream ends or fails. The client does not retry automatically, so a direct consumer chooses its own retry policy. The current bridges do not provide structured gap cursor or reason details.

WalletEngine manages recovery for UI consumers. It reconciles the snapshot with list(), retries from its last safe numeric stream cursor with bounded backoff, and resets that cursor with the runtime lifecycle. Replayed activity events trigger idempotent snapshot refreshes instead of direct row appends. This provides eventual snapshot consistency after reconnects without duplicating entries. The React useWalletActivity hook reads that engine snapshot, ordered newest-first, and re-renders as reconciliation completes.

Event model

Beyond activity rows, the client emits runtime and log events on the same subscription. Narrow on the event type before reading its payload.

WavelengthEvent is a discriminated union. Narrow on type before reading payload:

All five event types arrive through the same subscribe(listener) callback registered once.

type Payload Meaning
'activity' Entry A wallet operation was created or updated.
'activityStream' { state: 'ended' } or { state: 'failed', message } The activity stream ended or failed without a consumer-initiated close.
'log' { level, message } Daemon log line forwarded for debugging (debug, info, warn, error).
'runtimeReady' none The embedded runtime finished loading and can accept start().
'runtimeStopped' none The runtime stopped, including an unsolicited stop surfaced by the transport.

Activity events carry the full entry shape:

  • kind: high-level category (see below).
  • status: collapsed outcome: pending, complete, or failed.
  • amountSat / feeSat: principal and fees in satoshis (plain int64 magnitudes; use the entry’s kind to determine direction).
  • cursor: the monotonic stream position of this update. It is zero for entries returned outside the subscription path.
  • progress: optional lifecycle metadata (phase, payment hash, txid, confirmation height, VTXO outpoint, and Lightning preimage).
  • request: optional echo of what the user initiated (Lightning invoice, on-chain address, etc.).
  • failureReason / failureCode: populated when status is failed. failureCode is one of:
    • timed_out: the operation exceeded its deadline before completing.
    • expired: the underlying invoice, address, or quote expired before it was used.
    • refunded: a swap or payment failed and funds were returned to the wallet.
    • needs_intervention: the operation stalled in a state that requires manual follow-up.
    • failed: a generic failure not covered by the other codes.

When known, EntryProgress.preimage is the hex-encoded Lightning payment preimage. For a completed Lightning-backed send, it is proof of payment for the invoice.

Entry kinds group operations for filtering and display:

  • deposit: on-chain boarding (deposit() address flow).
  • receive: inbound Lightning receive settled through an atomic swap into Ark.
  • send: outbound payment (Lightning send swap, cooperative on-chain leave, or in-Ark send).
  • exit: cooperative leave of VTXOs to a plain on-chain address.

For a send entry, entry.request?.type ('lightning', 'onchain', or 'ark') tells you which rail the payment actually used; when preparing a send, PrepareSendResult.rail reports the same thing ahead of time. See the wavelength-core reference for the full field list.

Entry phases sit one level below status and describe where a pending operation is in its pipeline. They do not replace status; use both. Common phases include:

  • request_created: the wallet recorded the intent but nothing external has happened yet.
  • waiting_for_payment: waiting for a counterparty (Lightning payer, swap funder, or boarding confirmation).
  • waiting_for_confirmation: an on-chain tx is seen but not yet deep enough in the chain.
  • payment_detected / settling: value is in motion through Ark, Lightning, or swap machinery.
  • confirmed: terminal success from the backing subsystem’s perspective.
  • refunding / refunded: swap timeout or cancellation path returning funds.
  • failed: terminal failure.

You can switch on the progress phase for structured UI states, or render the phase label directly when you want the daemon’s short label without maintaining a mapping table. Field definitions live in the wavelength-core reference.

For the React hook signatures built on this stream, see the wavelength-react reference. For how activity and events relate to the client’s broader startup and connection state, see Wallet lifecycle & auth.