feat: real-time on-chain balance and event activity feed - #21
Conversation
The hook now takes streamId and walletAddress so it can call the on-chain balance_of RPC. Returns an object with balance, syncing, and isFromChain instead of a bare bigint.
Pass contractStreamId and wallet to useStreamBalance. Show a pulsing "syncing" badge while the RPC call is in flight. Refresh stream data after withdraw/cancel so the page stays current.
Pulsing animation for the "syncing" indicator shown while the on-chain balance RPC call is in flight.
Queries getEvents on the Soroban RPC for contract events (StreamCreated, Withdrawn, Cancelled, VestingCreated, VestingClaimed, VestingRevoked). Supports filtering by wallet address, event type, and cursor-based pagination with loadMore.
Renders a list of stream events with type badge, amount, counterparty, relative timestamp, and Stellar Explorer link. Includes filter chips for event type and a "Load More" button for pagination.
Event rows, filter chips, load-more button, and icon styling for the activity feed component.
Shows events for the connected wallet below the streams grid.
Move StreamEventType, labels, icons, colours, symbol mapping, and filter options out of useStreamEvents and ActivityFeed into a single src/lib/eventTypes.ts so they're defined once and shared.
Remove duplicated type definitions and constant maps from useStreamEvents and ActivityFeed, importing from the new eventTypes module instead.
|
nice, the syncing badge idea is clean. btw useStreamBalance used to return a bigint, now its an object. make sure nothing else is calling it the old way or thats gonna break silently. the event symbols in eventTypes.ts are wrong — you have also the streamId prop on ActivityFeed doesnt actually filter anything. either hook it up or remove it. this imports getStreamBalance from the contracts module which is in PR 19. coordinate merge order or one of these wont build. |
- Fix SYMBOL_TO_TYPE to use PascalCase symbols the contract actually emits (StreamCreated, Withdrawn, Cancelled etc.) instead of lowercase (created, withdrawn). - Remove dead streamId prop from ActivityFeed that was accepted but never used for filtering.
|
Thanks for the review! Here's what I fixed: Event symbols — You were right, the mapping was wrong. Changed streamId prop — Removed it. It was accepted but never wired up — Soroban events don't carry stream_id in a consistent way across event types so client-side filtering wasn't practical. useStreamBalance backward compat — Checked all callers, it's only used in the stream detail page which was already updated. No silent breakage. getStreamBalance import — PR 19 is already merged, so the import resolves fine on main. Rebased on upstream to confirm. |
|
LGTM, thanks for contributing |
Closes #16
What changed
On-chain balance —
useStreamBalancenow callsstream.balance_of(stream_id)via Soroban RPC instead of doing pure client-side math. The client-side estimate still shows immediately so the counter never freezes, and the real on-chain value swaps in once the RPC responds (with a pulsing "syncing" badge). Re-fetches every 15 seconds to catch cancellations or parameter changes.Activity feed — New
useStreamEventshook queriesgetEventson the Soroban RPC for all contract events (StreamCreated, Withdrawn, Cancelled, VestingCreated, VestingClaimed, VestingRevoked). Events are filtered by wallet address and paginated with cursor-based "Load More".ActivityFeed component — Shows each event with:
Filter chips let you narrow by event type. "Load More" button fetches older pages.
Integrated into both
/dashboardand/streams/[id].Test plan