A real-time visualization of on-chain voting for the xGov council election on Algorand. This application fetches voting transactions from the xGov voting account, processes them using committed amounts from CSV, and displays interactive charts using ECharts to show voting patterns, stake distribution, and governance metrics.
Algorand on-chain governance is fully transparent, in contrast to legacy in-person secret voting in booths. In addition, a voter can change their votes during the voting period. Secret voting creates less bias, but when a voter goes on to the Algorand Governance page and is not fully committed to the context of the voting measures, it is easy to follow the crowd and vote with whatever is winning now. Algorand Governance is built around the "1 Algo = 1 vote" principle and can be heavily influenced by large stakeholders.
Here the transparency of the ledger comes in handy. By exposing the data and visualizing it in understandable charts, the user can make qualified assessments on the voting patterns from individual and bucket stakeholders of different sizes.
The popular vote chart shows that several candidates have more support from stakeholders than the stake-based voting resolves to. The data from the popularity vote chart and stake size buckets can be used to gauge the sentiment of the community on a social level.
The election of the xGov council is not incentivized, so it can be said that the participating stakeholders are based and interested in the future of the Algorand protocol. Voting data can be interpreted as showing an aligned community, mostly in consensus, with an expected amount of outliers and margins.
It will be interesting to see if the project can be adjusted and used for future voting sessions on the xGov platform.
- Real-time Data: Fetches voting data from Algorand blockchain using Nodely API
- Interactive Charts:
- Scoreboard: Animated racing bar chart showing net yes stake over time
- Stake-Weighted Chart: Bar chart per candidate with yes/no/abstain stakes (log scale)
- Popularity Chart: Pixel scatter plot showing individual votes
- Non-Voters Chart: Shows non-voters by stake
- Stake Breakdown Chart: Marimekko chart of votes by stake buckets
- Statistics Cards: Display time left, voted stake, unique voters, participation rate
- Auto-refresh: Updates data every hour automatically and on reload
- Responsive Design: Works on desktop and mobile devices
- Animations: Confetti on voting end, playback for scoreboard
- Copy Address: Click on displayed addresses to copy full voter or candidate addresses to clipboard
- Node.js (version 16 or higher)
- npm or yarn package manager
- Clone the repository:
git clone <repository-url>
cd xgov-voting-visualization- Install dependencies:
npm install- Start the development server:
npm run dev- Open your browser and navigate to
http://localhost:3000
npm run buildThe built files will be in the dist directory.
- Load Committed Amounts: Reads
commit-amount.csvfor voter stakes in Algos - Transaction Fetching: Fetches transactions from xGov voting account (
RW466IANOKLA36QARHMBX5VCY3PYDR3H2N5XHPDARG6UBOKCIK7WAMLSCA) starting from block 51363025 - Note Parsing: Decodes Base64 notes, parses JSON arrays for votes across all candidates (a=yes, b=no, c=abstain)
- Process Latest Votes: Keeps only the most recent vote per voter
- Assign Stakes: Maps stakes from CSV to votes
- Data Aggregation: Groups by candidates, calculates totals
- Visualization: Uses ECharts to render various interactive charts
The application uses the Nodely Algorand Indexer API with rate limiting:
- 20 requests per second maximum
- No API key required
- Endpoints used:
/v2/accounts/{address}/transactions- Fetch voting transactions- Governance API for voting periods
Transaction notes are Base64 encoded JSON: af/gov1:j[period, "a"/"b"/"c" for each candidate]
- Array index corresponds to candidate (1-23)
- "a" = Yes, "b" = No, "c" = Abstain
src/
├── api.ts # Algorand API service with rate limiting
├── candidates.ts # List of candidates
├── echartsService.ts # Stake-weighted chart creation
├── main.ts # Main application entry point and visualization logic
├── popularityChartService.ts # Popularity pixel chart creation
├── statistics.ts # Statistics visualization (partial overlap with main)
├── statisticsService.ts # Statistics computation
├── types.ts # TypeScript interfaces
├── votingService.ts # Voting data fetching and processing
Implements a sliding window rate limiter (20 requests/second) for Nodely API.
- Graceful handling of API failures
- User-friendly error messages
- Console logging for debugging
- Uses Maps for efficient data processing
- Chart disposal for memory management
- Rate limiting to prevent API overload
- CSV for stake data to avoid per-voter queries
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly
- Submit a pull request
MIT License - see LICENSE file for details
- Nodely for providing free Algorand API access