-
Notifications
You must be signed in to change notification settings - Fork 2
feat: Activity Feed v1 #1562
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
feat: Activity Feed v1 #1562
Conversation
- Add feed_event table with type, relevance, timestamp, txHash, logIndex - Add FeedEventTypeEnum and FeedEventRelevanceEnum as shared enums - Add RELEVANCE_THRESHOLDS config for ENS, UNI, TEST DAOs - Create feed event records in voting, delegation, and transfer handlers - Add REST endpoint GET /feed with filters for timestamp, type, relevance - Add repository with join queries to fetch related vote/proposal/transfer/delegation data - Add logIndex parameter to all DAO governor indexers for feed event tracking
- Add activity feed types (FeedEvent, FeedEventType, FeedEventRelevance) - Create useActivityFeed hook for REST API data fetching with pagination - Create FeedEventItem component with support for vote, proposal, transfer, delegation events - Create FeedEventSkeleton for loading states - Create ActivityFeedFilters for filtering by event type and relevance - Create ActivityFeedSection as the main feature component
- Refactor ActivityFeedFilters to ActivityFeedFiltersDrawer component - Use existing design system components: Drawer, Checkbox, RadioButton, Button, Input - Add sort by date (newest/oldest first) with RadioButton - Add type filters (delegation, transfer, vote, proposal) with Checkbox - Add relevance filters (high, medium, low) with Checkbox - Add time frame date range inputs - Add Apply/Clear filters buttons in drawer footer - Update ActivityFeedSection to use filter drawer with icon button trigger - Add active filter count badge on filter button
These fields have a different semantic meaning (transaction affecting supply) vs address type identification. Address type identification will be handled by a separate service in the future.
- Add activityFeed to PAGES_CONSTANTS - Create activity-feed page at /[daoId]/activity-feed - Add Activity Feed to sidebar navigation (HeaderDAOSidebar) - Add Activity Feed to mobile navigation (HeaderNavMobile)
- Update header with icon, title, description, and Filters button - Group events by date (TODAY, YESTERDAY, date) with high relevance count - Redesign FeedEventItem layout: - Single line action description with inline elements - Metadata line: Relevance Label • Event Type • Time - Update event content format: - Vote: 'Actor (voting power) voted Yes/No on proposal Title' - Proposal: 'Actor (voting power) created the proposal Title' - Transfer: 'Actor transferred Amount to Recipient' - Delegation: 'Actor delegated/redelegated Amount to Delegate' - Add token symbol to amounts - Show colored relevance labels (High/Medium/Low/No Relevance)
- Remove colored circle background from event icons - Use subtle dimmed icon color for all event types - Reduce padding and gaps for more compact layout - Remove bordered container around event groups - Update skeleton to match new compact layout
Date headers now show the year for events from previous years: - Current year: 'SUNDAY, OCT 2' - Previous years: 'SUNDAY, OCT 2, 2024'
Use config.name (DAO name) as token symbol instead of non-existent config.daoOverview.token.symbol property
…sholds - Move computeRelevance function from constants.ts to utils.ts - Update imports in event handlers (delegation, transfer, voting) - Adjust ENS delegation thresholds: medium 10k, high 100k - Adjust ENS vote thresholds: low 1k, medium 10k, high 100k
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
| }); | ||
|
|
||
| return groups; | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you're grouping events by date on the frontend? it probably should be done on the query
| const { data, error, isLoading, mutate } = useSWR( | ||
| swrKey, | ||
| () => fetchActivityFeed(daoId, { ...filters, limit, offset: 0 }), | ||
| { | ||
| revalidateOnFocus: false, | ||
| dedupingInterval: 30000, | ||
| }, | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use react-query
| export const useActivityFeed = ({ | ||
| daoId, | ||
| filters = {}, | ||
| enabled = true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like this params is not used at all
| interface PaginationInfo { | ||
| totalCount: number; | ||
| hasNextPage: boolean; | ||
| hasPreviousPage: boolean; | ||
| currentPage: number; | ||
| itemsPerPage: number; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should be using type safe queries (currently using apollo for that)
Expose activity feed endpoint through the API gateway
Use local timezone consistently for date grouping instead of mixing local time with UTC (toISOString). This ensures events are grouped correctly based on the user's local date.
Add USE_MOCK_DATA toggle in mockData.ts to test frontend without backend. Includes sample transfer events with pagination support.
Replace 'Load more' button with Intersection Observer-based infinite scroll. Starts loading 200px before reaching the bottom for smooth UX.
Use nuqs library to sync filter state with URL query parameters: - sort: asc/desc - types: comma-separated list (vote,proposal,transfer,delegation) - relevances: comma-separated list (none,low,medium,high) - from/to: date strings Allows sharing filtered views and maintains state on refresh.
- Replace SWR with manual fetch to avoid revalidation overwriting accumulated items - Add deduplication helper to prevent duplicate keys when appending pages - Use ref guard to prevent multiple simultaneous fetches - Simplify state management for more predictable behavior
Include all 4 event types with various relevance levels: - Proposals (always high relevance) - Votes (for, against, abstain with different voting power) - Delegations (new, changed, with different amounts) - Transfers (various sizes) Uses dynamic timestamps relative to current time for realistic testing.
Replace synthetic mock data with actual API responses: - 5 proposals (all high relevance) - 8 votes (high, medium, low relevance) - 8 delegations (medium, low relevance) - 10 transfers (low relevance) Uses real transaction hashes, addresses, and timestamps from ENS DAO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bug with infinite scroll
https://jam.dev/c/cc1b9d7a-b084-4954-b78e-b3b815156ad9
| }: ActivityFeedFiltersDrawerProps) => { | ||
| const { isMobile } = useScreenSize(); | ||
| const [localFilters, setLocalFilters] = | ||
| useState<ActivityFeedFilterState>(filters); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can use useQueryState from nuqs so your filters will be in the url and it could be shareable
| const hasRedelegation = | ||
| event.delegation.previousDelegate && | ||
| event.delegation.previousDelegate !== | ||
| "0x0000000000000000000000000000000000000000"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use zeroAddress from viem
| interface PaginationInfo { | ||
| totalCount: number; | ||
| hasNextPage: boolean; | ||
| hasPreviousPage: boolean; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is no reason to have previous page if you are using infinite scroll
- Adjusted spacing in ActivityFeedSection for improved layout. - Updated FeedEventItem to use consistent styling and improved readability. - Enhanced ActivityFeedFilters to apply filters and close drawer on reset. - Added isCollapsed prop to HeaderDAOSidebar for better state management.
Overview
Add an Activity Feed feature to track governance activities (votes, proposals, transfers, delegations) with relevance scoring across DAOs.
Architecture
flowchart LR subgraph Indexing[Event Indexing] VoteCast --> feedEvent[feed_event table] ProposalCreated --> feedEvent Transfer --> feedEvent DelegateChanged --> feedEvent end subgraph API[REST API] feedEvent --> Repository Repository --> Service Service --> Controller Controller --> Response[JSON Response] endBackend Changes (Indexer)
Schema
feed_eventtable with composite PK (txHash + logIndex)feed_event_type(vote, proposal, transfer, delegation)feed_event_relevance(none, low, medium, high)Relevance Scoring
computeRelevance()in utilsEvent Handlers
voting.ts: Inserts feed events for votes and proposalsdelegation.ts: Inserts feed events for delegationstransfer.ts: Inserts feed events for transfersREST API
GET /feedendpoint with filters:fromTimestamp,toTimestamp- time rangetypes[]- filter by event typesrelevances[]- filter by relevance levelssortOrder- asc/desclimit,offset- paginationFrontend Changes (Dashboard)
Activity Feed Feature
ActivityFeedcomponent with infinite scrollUI/UX
Commits
feat(indexer): add activity feed feature- Backend implementationfeat(dashboard): add activity feed feature- Frontend implementationrefactor(dashboard): use drawer pattern for activity feed filtersrefactor: remove isCex/isDex/isLending from feed event transfersfeat(dashboard): add Activity Feed as sidebar navigation itemrefactor(dashboard): redesign Activity Feed to match Figma designfix(dashboard): improve Activity Feed layout and spacingfeat(dashboard): show year in date label if not current yearfix(dashboard): fix tokenSymbol type error in FeedEventItemrefactor(indexer): move computeRelevance to utils and adjust ENS thresholds