Introducing RabbitStream⚡, earliest transaction detection from Solana Shreds with gRPC style filtering. Explore Now
shyft logo
Get API Key

Blogs

Transactions & Callbacks

How to track votes for realms proposal on Solana

Shyft Logo

Team Shyft

· January 22, 2026

Governance programs on Solana typically involve tokens, which holders use to decide proposals, upgrades, and other important matters. In this article, we will explore the most convenient method of tracking all the votes of a governance proposal on Solana.

Governance programs on the Solana blockchain are a fundamental component of its decentralized ecosystem, enabling collective decision-making and management of critical network aspects. These programs rely on governance tokens, which users hold to exercise their voting power in the network’s governance processes. Solana’s governance framework is characterized by transparency, participation, and adaptability. In this article, we will explore one of the simplest ways of tracking all votes cast in a particular governance proposal on Solana. In short, we aim to create a tracker similar to the media below.

View this project on our GitHub

Dashboard vote tracker

A dashboard to track votes in a governance proposal powered by SHYFT APIs

Before Getting Started

To get started, we will need a few things.

Authentication: Getting your Shyft API key

x-api-key is an authentication parameter, which gives you access to SHYFT APIs. You can get your own API Key from the SHYFT website. Just sign up with your email ID here and you can get it for free.

NextJs or any dev environment/stack that supports API calls

We have used Next JS for this project, but this can be done in any application development environment.

Steps Involved: Summary

The entire process can be divided into three simple steps. Suppose we have the proposal address for a particular proposal,

  • First, we read all the transactions related to that particular proposal.
  • Once that is successful, we go on to check each transaction and filter out all the transactions that are of type CAST_VOTE. Each CAST_VOTE transaction, once parsed, should contain all the information related to a particular vote. This information may include governance address, governing token, realm address, and most importantly the type of votes cast.
  • Now comes the final part, aggregating the transactions, which is calculating the number of votes that were of type “Approve” or “Disapprove”, thus calculating if the motion was passed or not.

Getting Transactions Data

Suppose we have a governance proposal, say address xtb….pos and we want to track all votes cast and also understand if the proposal has been approved or not. The first and foremost step involves getting all the transactions for the raffle and parsing them, and we will explore one of the most convenient ways of getting transactions on Solana, which is using the SHYFT API.

Read SHYFT API Documentation here.

We are pleased to introduce SHYFT’s comprehensive collection of exclusive APIs designed specifically for the Solana Blockchain ecosystem. Our suite of APIs encompasses a wide array of functionalities, including those catering to Non-Fungible Tokens (NFTs), Fungible Tokens (cryptocurrencies), crypto-wallet management, and efficient transaction processing. For this particular case, we will utilize SHYFT’s efficient transaction APIs to get all transactions related to that particular proposal. The API endpoint:

GET https://api.shyft.to/sol/v1/transaction/history

Parameters Required for this API request

All SHYFT APIs require the _x-api-key_ parameter in the header, which is used as an authorization parameter by SHYFT. You can get your own API key here for free. This API supports pagination, and the other parameters are as follows:

  • network : can be devnet, testnet or mainnet-beta.
  • account: The account address whose transactions we are attempting to fetch, in our case this is the proposal address.
  • tx_num(optional): Indicates the number of transactions to be fetched at a time.
  • before_tx_signature(optional): Transactions are fetched in the order of the most recent transaction first. This field accepts a transaction signature and will fetch all the transactions before this transaction (in time).
  • enable_raw: All transactions returned from this endpoint are “Human-readable” parsed Transactions from Solana. If this is set to true, raw transactions are also returned along with parsed transactions.

To find out more about this API and its parameters, please visit SHYFT Transaction Docs.

Once successfully executed, we should receive an array of transactions from this endpoint in a paginated manner (newest transaction first). The next step involves parsing the transactions. Thanks to SHYFT, we can skip this step, as all the transactions received via this endpoint are pre-parsed by SHYFT. The response received looks somewhat like the example below. Please note that since we are fetching transactions in a paginated manner, it is important we do so repeatedly until no transactions are received i.e. the number of transactions received from the endpoint is 0.

[{
    "timestamp": "2023-08-28T13:30:00.000Z",
    "fee": 0.0000066,
    "fee_payer": "sjiQ7dDVKgCM2gTWQQbVkFEeeJRGd37NKjKvZebrGs7",
    "signers": [
        "sjiQ7dDVKgCM2gTWQQbVkFEeeJRGd37NKjKvZebrGs7"
    ],
    "signatures": [
        "45KAyQtwbDzzKfpPGAynRpcq4gVjweV75FFybMqvobxDbUbzCemrjHS4ZpN2xDenCJaDiSAzt8wk5d5qGskfEE9U"
    ],
    "protocol": {
        "address": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw",
        "name": "SPL_GOVERNANCE"
    },
    "type": "CAST_VOTE",
    "status": "Success",
    "actions": [
        {
            "info": {
                "realm_address": "GBXLYo4ycRNfzuzYeudu6y2ng4afNeW14WcpM2E4JJSL",
                "governance": "7M6TSEkRiXiYmpRCcCDSdJGTGxAPem2HBqjW4gLQ2KoE",
                "proposal": "8EcSzJeg8S4pvzMUt7JrMPsyCyQ2s1nycwaptGgiKAWE",
                "proposal_owner_record": "2TMp4yvH5QWUhpwFgKq27J2vxCrscwBjiRKg1TT3BwLR",
                "voter_token_owner_record": "2TMp4yvH5Q2UhpwFgKq26J2vxCrscwBjiRKg1TT3BwLR",
                "governance_authority": "sjiQ7dDVKgCM2gTWQQbVkFEeeJRGd37NKjKvZebrGs7",
                "vote_record_address": "G8R3oKyUDLFjuPoyFcxXy1MwVv1679BrhBk5jaEU67rJ",
                "vote_governing_token": "39qcqpaiLivyFLBLh4wvPmLrs336BBpXkKYb88i8dSiJ",
                "payer": "sjiQ7dDVKgCM3gTWQQbVkFEeeJRGd37NKjKvZebrGs7",
                "vote_type": "Approve",
                "rank": 0,
                "weight_percentage": 100
            },
            "source_protocol": {
                "address": "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw",
                "name": "SPL_GOVERNANCE"
            },
            "type": "CAST_VOTE"
        }
    ]
},
{
    "timestamp": "2023-08-28T13:30:00.000Z",
    "fee": 0.0000066,
    "fee_payer": "pxsiQ7dDVKgCM2gTWQQbVkFEeeJRGd37NKjKvahdajh",
    "signers": [
        "dkwiQ7dDVKgCM2gTWQQbVkFEeeJRGd37NKjKvZahb6ba"
    ],
.......//shortened response
}
]

Filtering Transactions according to our Use-Case: Getting Vote data

The next step involves filtering all the transactions so that we can select the transactions relevant to our use-case. Since all transactions received are pre-parsed by SHYFT, we can directly check for transactions that have the **type** field as **CAST_VOTE** . These transactions indicate a vote has been cast related to the proposal and contains all the information related to it, such as realm_address, governance, governing_token, and most importantly the type of vote that had been cast, was it to “Approve” or “Disapprove” the proposal. We can filter the transactions based on the type field. These filtered transactions can now be stored in an array or database for further processing.

for (let index = 0; index < transactions.length; index++) {
   const eachTransaction = transactions[index];
        
   if(eachTransaction.type === "CAST_VOTE") {
      //checking for cast vote transaction
      castVoteTransactions.push(eachTransaction);
   }
}

{
 //.....response shortened
    "type": "CAST_VOTE", //indicates the type of transaction
    "status": "Success",
    "actions": [
        {
            "info": {
                "realm_address": "GBXLYo4ycRNfzuzYeudu6y2ng4afNeW14WcpM2E4JJSL",
                //....response shortened
                "payer": "sjiQ7dDVKgCM3gTWQQbVkFEeeJRGd37NKjKvZebrGs7",
                "vote_type": "Approve",
                "rank": 0,
                "weight_percentage": 100
            },
            "type": "CAST_VOTE" //indicates the type of action
        }
    ]
//.....response shortened
}

Processing information: Calculating votes

Once we have all the CAST_VOTE transactions, we can easily calculate the total number of votes cast, which is the number of cast vote transactions. Each CAST_VOTE transaction has a vote_type field that indicates the type of votes cast i.e. a vote to approve the proposal or a vote to reject the proposal.

for (let index = 0; index < transactions.length; index++) {
  const eachTransaction = transactions[index];
  const voteAction = eachTransaction.actions.filter((action) => action.type === "CAST_VOTE");
  //alternatively, you can also view the first action in the actions array
  // const voteAction = eachTransaction.actions[0];
  
  if(voteAction[0].info?.vote_type === "Approve") //checking for approved transactions
    approved++;
  else
    disapproved++;

  totalVotes++;
}

Press enter or click to view image in full size

Approve vote transaction

We can count the approved votes and generate a pie chart in the front end

If the number of votes of type “approve” is more than that of the number of votes of type “disapprove/deny”, it would indicate the proposal has been approved.

Miscellaneous: more information out of parsed transactions

Apart from calculating the number of votes, we can also get a ton of more useful information from SHYFT’s parsed transactions. We can get the name of the proposal in the first step, where we get all the transactions. There should be a CREATE_PROPOSAL transaction that contains most of the information about the proposal, including the name of the proposal.

Also, various other details, such as governance address, realm address, governing token, etc. are also available in the parsed transactions received. Furthermore, we can also make a tokens/get_info request on the governing token address to get the token details. Find out more about this API here.

Press enter or click to view image in full size

Information available in parsed transactions by Solana

The information available in the parsed transactions by SHYFT

Conclusion

There can be various ways of getting transactions on Solana, but most of them require a lot of coding and understanding of the Solana blockchain, and a lot of time is spent reinventing the wheel. SHYFT aims to reduce these efforts, by providing low-code, API-based solutions for performing several operations on the Solana Blockchain. By leveraging SHYFT’s APIs, you can seamlessly engage with the Solana Blockchain, harnessing its capabilities to enhance your blockchain interactions.

If you liked this article, feel free to explore other articles on tracking cNFT marketplace events or building a discord bot for cNFTs on Solana. The above project is also available on our GitHub here. A big thank you for the read time, we really hope you enjoy building with SHYFT.

Resources

Realms Proposal
Solana Tracker
Votes on Solana
Web3 Live Feed

Related Posts

How to track all $Booty token swaps in one hour on Orca
Shyft

How to track all $Booty token swaps in one hour on Orca

In this article, we will explore an intuitive way of tracking all $Booty token swaps in an hour on Orca, powered by SHYF...

January 22, 2026

How to track ticket purchased for a Famous fox raffle on Solana
Shyft

How to track ticket purchased for a Famous fox raffle on Solana

In this article, we explore a way to track the number of tickets purchased for a particular Famous Fox Raffle on Solana,...

January 22, 2026

Managing Callbacks in a Web3 activity feed (Part 2)
Shyft

Managing Callbacks in a Web3 activity feed (Part 2)

Efficiently handle real-time data updates on Solana-powered dApps with smart callback management APIs. Callback APIs can...

January 22, 2026

Get in touch with our discord community and keep up with the latest feature
releases. Get help from our developers who are always here to help you take off.

GithubTwitterLinked inDiscordTelegramBlogsBlogs

Products

RabbitStreamgRPC NetworkSuperIndexerSolana APIs
Contact Us|Email: genesis@shyft.to