3

Suppose I know the vote account and identity account for a validator. I also run the validator, in case that matters.

How do I find all the historical staking and unstaking transactions for the validator?

Options:

  1. Find all transactions involving the vote account and look for those that are staking/unstaking transactions.

The vote account has one or two transactions per block. Calling getSignaturesForAddress will give me 1K tx sigs at a time, but no detail on what each tx is. I'd then need to call getTransaction for each sign and maybe check the innerInstructions for signs of a staking/unstaking tx. Going back through all of them to find the staking/unstaking ones doesn't seem feasible. So, 1,001 API calls just to check about 7 mins worth of history. No good.

  1. Same approach but check the identity account.

Same problem - too many transactions.

  1. Can I first get a list of the stake accounts for the validator and go from there? (There's one stake account per staking transaction, AFAICT.)

I don't see anywhere I can get this from the API.

  1. The stake program has fewer transactions than the vote or identity accounts. Could I iterate over them and find the ones that involve my validator?

The stake program currently has about one tx per minute. So 1K txs would get us back about 16 hours. Still too many to go through looking for transactions involving my validator.

The reason I believe this is possible is that at least one block explorer is showing the data. See 'Epoch History' here.

What am I missing?

1 Answer 1

1

You've understood just about everything. Your best option is number 3, and finding all of the stake accounts that are delegated to your validator. Here's a python code snippet for doing that:

import asyncio

import base64
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()

    stake_memcmp_opts = [MemcmpOpts(
        offset=124, # I think this is the offset, it might be 128 though
        bytes="mpa4abUkjQoAvPzREkh5Mo75hZhPFQ2FSH6w7dWKuQ5")] # put your vote account address here
    response = await client.get_program_accounts(
        STAKE_PROGRAM_ID,
        encoding="base64",
        data_size=200,
        memcmp_opts=stake_memcmp_opts
    )
    print(response)
    for stake in response['result']:
        print(stake)
    print(len(response['result']))

    await client.close()

asyncio.run(main())

As you might imagine, this doesn't give you the history unfortunately. You could go through each of these accounts with getSignaturesForAddress, but this will not catch stake accounts that we were deleted or accounts that used to be delegated to your validator.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.