There are three ways to do this.

1. From our iSEI contract with the exchange_rates call.

This is an example: https://www.seiscan.app/pacific-1/interact-contract?selectedType=query&contract=sei1e3gttzq5e5k49f9f5gzvrl0rltlav65xu6p9xc0aj7e84lantdjqp7cncc&msg=ewogICJleGNoYW5nZV9yYXRlcyI6IHt9Cn0=. You can put in "limit":30 to get the most records.

Here, you can take APR and * by 365 and that will give you the percent so for a reported APR of 0.000097441761553662, annual is 3.55%. Technically should be compounded, so that is 3.62%.

You can also manually take the first/last record and diff them (the time is in seconds), but it should be fine.

Generally this is a bit volatile due to when people mint/redeem. It has gone down to 3% and up to 6%.

telegram-cloud-photo-size-4-6048411669555691994-y.jpg

2. Directly from the Sei Validators

To do it directly, you use this endpoint: https://rest.pacific-1.sei.io/seichain/mint/v1beta1/params, and then map out what time period you are in:

import { atom } from 'jotai';
import { loadable } from 'jotai/utils';
import { fetchWithRetry } from '@/utils/helper.ts';

interface PoolResponse {
  pool: {
    not_bonded_tokens: string;
    bonded_tokens: string;
  };
}

interface TokenReleaseSchedule {
  start_date: string;
  end_date: string;
  token_release_amount: string;
}

interface StakingParams {
  mint_denom: string;
  token_release_schedule: TokenReleaseSchedule[];
}

interface MintResponse {
  params: StakingParams;
}

export const emissionsAtom = atom(async () => {
  const apiUrl = '<https://rest.pacific-1.sei.io/seichain/mint/v1beta1/params>';

  try {
    const response = (await fetchWithRetry(apiUrl)) as MintResponse;
    return response;
  } catch (error) {
    console.error('Failed to fetch staking APY:', error);
    throw error;
  }
});

export const stakingPoolAtom = atom(async () => {
  const apiUrl = '<https://rest.pacific-1.sei.io/cosmos/staking/v1beta1/pool>';

  try {
    const response = (await fetchWithRetry(apiUrl)) as PoolResponse;
    return response.pool;
  } catch (error) {
    console.error('Failed to fetch staking pool parameters:', error);
    throw error;
  }
});

export const stakingApyAtom = atom(async (get) => {
  try {
    const pool = await get(stakingPoolAtom);
    const emissions = await get(emissionsAtom);

    if (!pool || !emissions) {
      throw new Error('Failed to fetch pool or emissions data');
    }

    const bondedTokens = parseFloat(pool.bonded_tokens);
    const oneYearFromNow = new Date();
    oneYearFromNow.setFullYear(oneYearFromNow.getFullYear() + 1);

    // Note that using the end date here may not be strictly correct
    // in case the 1 year mark is between a start and end, but close enough
    const totalEmissions = emissions.params.token_release_schedule.reduce(
      (acc, schedule) => {
        const releaseDate = new Date(schedule.end_date);
        if (releaseDate <= oneYearFromNow && releaseDate >= new Date()) {
          return acc + parseFloat(schedule.token_release_amount);
        }
        return acc;
      },
      0,
    );

    if (bondedTokens === 0) {
      return 0;
    }

    const stakingApy = (totalEmissions / bondedTokens) * 100;
    return stakingApy;
  } catch (error) {
    console.error('Failed to calculate staking APY:', error);
    // Estimate
    return 4.1;
  }
});

export const loadableStakingApyAtom = loadable(stakingApyAtom);

3. You can manually pull the isei price and sei price and just divide them/annualize it this way.

https://www.coingecko.com/en/coins/silo-staked-sei