Search code examples
pythonapicryptocurrencysolana

Am I able to get a list of delegators by validator (solana) using the JSON RPC API?


So for instance in solanabeach.io, I am able to see for validator - "staked" a list of delegators containing addresses, activation epochs, amount staked, and share %.

Is it possible to get this via the JSON RPC API, or another method?


Solution

  • Certainly! You'll have to use the get_program_accounts endpoint, fetching all of the accounts belonging to the stake program, and filtering for where the delegation's vote account is equal to the validator that you want to search for.

    Info about get_program_accounts: https://docs.solana.com/developing/clients/jsonrpc-api#getprogramaccounts

    Info about the stake structure: https://github.com/solana-labs/solana/blob/e960634909a9617fb98d5d836c9c4c5e0d9d59cc/sdk/program/src/stake/state.rs#L22

    If you count up from the enum (4 bytes), then the Meta (8 bytes for rent_exempt_reserve + 64 bytes for authorized + 48 bytes for lockup) to get to voter_pubkey, that gives an offset of 124 bytes.

    Here's a python script to do exactly that, requiring just the solana-py package:

    import asyncio
    
    from solana.publickey import PublicKey
    from solana.rpc.async_api import AsyncClient
    from solana.rpc.commitment import Confirmed
    from solana.rpc.types import MemcmpOpts
    
    STAKE_PROGRAM_ID: PublicKey = PublicKey("Stake11111111111111111111111111111111111111")
    
    
    async def main():
        client = AsyncClient("https://api.mainnet-beta.solana.com", Confirmed)
        print("Connecting...")
        await client.is_connected()
    
        memcmp_opts = [MemcmpOpts(offset=124, bytes="CAf8jfgqhia5VNrEF4A7Y9VLD3numMq9DVSceq7cPh
    NY")] # put the pubkey of the validator vote address here
        response = await client.get_program_accounts(
            STAKE_PROGRAM_ID,
            encoding="base64",
            data_size=200,
            memcmp_opts=memcmp_opts
        )
        for stake in response['result']:
            print(stake)
    
        await client.close()
    
    asyncio.run(main())