fix(streaming-widget): finalize bounty coverage and evidence#38
Conversation
|
Hi @L03TJ3, PR #38 is ready for review. I followed the assigned bounty flow, built on top of the existing AI branch, posted the handoff on #36, and included verification/evidence. Verified:
Thanks again for assigning this. |
| setStreams(result.map((s) => toStreamListItem(s, address as Address))) | ||
| const normalizedStreams = result.map((s) => toStreamListItem(s, address as Address)) | ||
| setStreams(normalizedStreams) | ||
| setStreamHistory(normalizedStreams) |
There was a problem hiding this comment.
Nice work wiring up the history state machine; the loading/empty/error/populated states all render correctly. One thing worth flagging for a follow-up: setStreamHistory here is receiving the same result as setStreams, because getActiveStreams only returns currently active (non-zero flowRate) streams. Terminated streams would need a separate subgraph query, something like a getPastStreams or getStreamHistory call, to populate a true history list. As it stands, the history section in the UI is showing the same data as the active streams list, and the "Show more" pagination is working against that same pool. Not blocking for this bounty since the UI states are all covered, but worth picking up as a follow-up so the history tab reflects actual past streams.
There was a problem hiding this comment.
Thanks, agreed. I kept this as a follow-up because the current SDK path only exposes active streams here, and added a fixture note so the Storybook history data is easy to split once a dedicated past-stream query exists.
| connect, | ||
| switchChain, | ||
| refreshStreams: fetchStreams, | ||
| refreshStreamHistory: fetchStreams, |
There was a problem hiding this comment.
Small note to go alongside the history comment above, refreshStreamHistory is pointing to fetchStreams here, so both refresh actions hit the same underlying call. When a dedicated history fetch is added, this line will need to point to the new callback. Easy to update then
There was a problem hiding this comment.
Agreed. Leaving refreshStreamHistory pointed at the current SDK-backed fetch for now; when a dedicated history callback lands this should switch to that separate fetch.
| const poolsWithClaimable = await Promise.all( | ||
| normalizedPools.map(async (pool) => { | ||
| try { | ||
| const [claimableAmount] = await viemClients.publicClient.readContract({ | ||
| address: pool.poolId, | ||
| abi: GDA_POOL_CLAIM_ABI, | ||
| functionName: 'getClaimableNow', | ||
| args: [address as Address], | ||
| }) | ||
|
|
||
| return { | ||
| ...pool, | ||
| claimableAmount: claimableAmount > 0n ? claimableAmount : 0n, | ||
| } |
There was a problem hiding this comment.
The getClaimableNow read looks good, and the claimableAmount > 0n guard correctly handles the signed int256 return. One thing to watch: if this readContract call throws (RPC timeout, contract revert, etc.), the catch silently returns the pool with claimableAmount still at 0n from the toPoolMembershipItem fallback. In the UI, that makes the Claim button appear disabled with no explanation. A user with a real claimable balance would just see a greyed-out button and have no way to tell whether it's a data error or genuinely nothing to claim. Could we add a claimableAmountError flag to PoolMembershipItem and surface a small "Could not load claimable amount, tap to retry" note in PoolCard when the read fails?
There was a problem hiding this comment.
Fixed in 3494404: PoolMembershipItem now carries claimableAmountError, successful reads clear it, and failed getClaimableNow reads set it instead of silently falling back to an unexplained 0n state.
| !state.streamHistoryError && | ||
| recentStreams.length === 0 && ( | ||
| <EmptyStateCard> | ||
| <Text secondary center> |
There was a problem hiding this comment.
This is the UI side of the silent-failure issue flagged in the adapter's getClaimableNow catch block. When that read fails, claimableAmount stays at 0n, so canClaim is false and the button renders disabled with no explanation. Pairing this with the adapter fix, surfacing a claimableAmountError on the pool item, would let us show something like "Could not load claimable amount" here instead of just a greyed-out button.
There was a problem hiding this comment.
Fixed in 3494404: PoolCard now surfaces the claimable amount load failure with a small inline “Could not load claimable amount. Tap to retry” note wired to refreshPools, while keeping Claim disabled until the amount is known.
| // Story shell — renders the widget inside a fixed-width container that mirrors | ||
| // the GoodWalletV2 sidebar / bottom-sheet form factor. | ||
| // --------------------------------------------------------------------------- | ||
| const DEMO_ADDRESS = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' |
There was a problem hiding this comment.
Is DEMO_ADDRESS intentionally Vitalik's well-known address? That's fine as a fixture, just worth confirming it's deliberate and that this address doesn't have any unexpected behaviour on Celo or Base in the test environment. If it's just a placeholder, a clearly synthetic address like 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef might be less likely to confuse future contributors.
There was a problem hiding this comment.
Good catch. Replaced the well-known address with a clearly synthetic fixture address in 3494404 to avoid confusing future contributors.
| }, | ||
| ] | ||
|
|
||
| const sampleStreamHistory: StreamListItem[] = [ |
There was a problem hiding this comment.
sampleStreamHistory spreads sampleStreams at the top, which is consistent with the current adapter behaviour (both lists come from the same getActiveStreams call). When the adapter is updated to fetch real history separately, this fixture will need updating too. In a proper history model, the two lists should be disjoint, since active streams are ongoing and past streams are terminated. Could we add a comment here noting that the fixture should diverge once the adapter is corrected? Makes the follow-up easier to find.
There was a problem hiding this comment.
Added the fixture comment in 3494404, noting that sampleStreamHistory mirrors the current SDK-backed adapter and should diverge once past-stream history is fetched separately.
pheobeayo
left a comment
There was a problem hiding this comment.
Impressive work so far @edehvictor , Kindly check through the comments and fix!
Refs #26
Refs #28
Refs #36
Builds on AI PR #31.
Summary
Finalizes the streaming widget bounty work on top of the existing AI PR branch by filling the missing runtime states, deterministic Storybook coverage, Playwright coverage, and screenshot evidence needed for human review.
Changes
WidgetTabsfor Streams, Pools, and Balances.StreamingWidgetPreviewwiring for Storybook and Playwright while preserving the liveStreamingWidgetadapter path.Show morestates.getClaimableNowfrom pool contracts and submittingclaimAll, with separate pending/success/error state.tests/widgets/streaming-widget/test-results/.pnpm lintcommand passes.Verification
pnpm install: Passedpnpm build: Passedpnpm lint: Passed with existing repo warnings onlypnpm test:demo tests/widgets/streaming-widget: Passed, 13/13 testsgit diff --check HEAD~2..HEAD: Passed, no whitespace errorsEvidence
Playwright screenshots are committed in
tests/widgets/streaming-widget/test-results/and cover:Notes
This PR intentionally targets
copilot/create-streaming-widgetso AI PR #31 can be updated before maintainer review.