Skip to content

Commit

Permalink
jailed status fix
Browse files Browse the repository at this point in the history
  • Loading branch information
mikecot committed Jan 16, 2025
1 parent d2678b5 commit 0b1477e
Show file tree
Hide file tree
Showing 16 changed files with 182 additions and 72 deletions.
21 changes: 16 additions & 5 deletions PUBLICAPI.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,27 @@ Returns a comprehensive list of all Lava Network providers, including:
- Supported chains and specifications
- Staking details (amounts, delegation limits)
- Commission rates and current status
- And for each stake - the stakestatus (active/frozen/jailed)

#### `/providers`

Returns list of all providers
Returns list of all providers (addresses only)

#### `/active_providers`

Returns list of all active providers (addresses only)

#### `/consumers`

Returns list of all consumers
Returns list of all consumers (addresses only)

#### `/specs`

Returns list of all specs/chains
Returns list of all specs/chains (spec names only)

#### `/validators`

Returns list of all validators
Returns list of all validators (full info)

### Example Response

Expand All @@ -70,6 +75,10 @@ Returns list of all validators
}
```

#### `/active_validators`

Returns list of all active validators (addresses only)

## Supply Endpoints

#### `/supply/circulating`
Expand Down Expand Up @@ -109,7 +118,8 @@ Returns list of all validators
- Empty provider delegations are excluded from restaker counts

3. Monthly Metrics:
- Represent unique users over the trailing 30-day period

- Represent unique users over 30-day period back from today
- Updated continuously based on blockchain data

## APR (Annual Percentage Rewards) Endpoint
Expand Down Expand Up @@ -248,3 +258,4 @@ Both staking and restaking APRs are calculated similarly:
- APR values represent potential returns before fees and slashing
- Actual returns may vary based on validator/provider performance
- Calculations include all reward types (LAVA + other tokens)
- APR calculation only considers active validators/providers (not jailed or frozen)
36 changes: 35 additions & 1 deletion src/indexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ if (!IsIndexerProcess()) {

import * as consts from './indexer/indexerConsts';
import { IndexerThreadCallerStart } from './indexer/indexerThreadCaller';
import { APRMonitor } from './indexer/restrpc_agregators/AprMonitor';

// import { APRMonitor } from './indexer/restrpc_agregators/AprMonitor';
// import { queryRpc } from './indexer/utils/lavajsRpc';
// import { LavaClient } from './indexer/lavaTypes';
// import { SpecAndConsumerService } from './redis/resources/global/SpecAndConsumerResource';
// import { JSONStringify } from './utils/fmt';

const indexer = async (): Promise<void> => {
logger.info(`Starting indexer, rpc: ${consts.JSINFO_INDEXER_LAVA_RPC}, start height: ${consts.JSINFO_INDEXER_START_BLOCK}`);
Expand All @@ -21,6 +26,35 @@ const indexer = async (): Promise<void> => {
}
}

// const allSpecs = await SpecAndConsumerService.GetAllSpecs();
// for (const spec of allSpecs) {
// const response = await queryRpc(
// async (_, __, lavaClient: LavaClient) => lavaClient.lavanet.lava.pairing.providers({ chainID: spec, showFrozen: true }),
// 'pairing.getProviders'
// );

// for (const provider of response.stakeEntry) {
// const jailEndTime = Number(provider.jailEndTime);
// const now = Math.floor(Date.now() / 1000);

// const jailEndDate = new Date(jailEndTime * 1000).toISOString();
// const isJailed = jailEndTime > now;

// if (!isJailed) continue;
// console.log({
// provider: provider.address,
// jail_info: {
// end_timestamp: jailEndTime,
// end_date: jailEndDate,
// is_currently_jailed: isJailed,
// time_remaining: isJailed ?
// `${((jailEndTime - now) / (24 * 60 * 60)).toFixed(2)} days` :
// 'Not jailed'
// }
// });
// }
// }

// const aprMonitor = APRMonitor;
// console.log("stating apr monitor")
// aprMonitor.start();
Expand Down
26 changes: 19 additions & 7 deletions src/indexer/blockchainEntities/blockchainEntitiesStakeUpdater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import { logger } from '@jsinfo/utils/logger';
import { queryRpc } from '../utils/lavajsRpc';
import { SpecAndConsumerService } from '@jsinfo/redis/resources/global/SpecAndConsumerResource';
import { LavaClient } from '../lavaTypes';
import { IsMeaningfulText } from '@jsinfo/utils/fmt';

function processStakeEntry(
height: number,
dbStakes: Map<string, JsinfoSchema.InsertProviderStake[]>,
providerStake: StakeEntry,
isUnstaking: boolean,
) {
// Log the start of processing for the provider stake

Expand All @@ -35,15 +35,27 @@ function processStakeEntry(
let stakeArr: JsinfoSchema.InsertProviderStake[] = dbStakes.get(providerStake.address)!


// status
// Explanation 16/01/25:
// In provider who is not active is either Frozen of Jailed
// Frozen : stakeAppliedBlock is MAX_INT (parsed here as -1)
// Jailed : jailedEndTime is bigger then now

const appliedHeight = ToSignedIntOrMinusOne(providerStake.stakeAppliedBlock)

let status = JsinfoSchema.LavaProviderStakeStatus.Active
if (isUnstaking) {
status = JsinfoSchema.LavaProviderStakeStatus.Unstaking
} else if (appliedHeight == -1) {
if (appliedHeight == -1) {
status = JsinfoSchema.LavaProviderStakeStatus.Frozen
}

if (providerStake.jailEndTime && IsMeaningfulText(providerStake.jailEndTime + "")) {
const jailEndTime = Number(providerStake.jailEndTime);
const now = Math.floor(Date.now() / 1000);
const isJailed = jailEndTime > now;
if (isJailed) {
status = JsinfoSchema.LavaProviderStakeStatus.Jailed
}
}

let data: JsinfoSchema.InsertProviderStake = {
provider: providerStake.address,
blockId: height,
Expand All @@ -53,7 +65,7 @@ function processStakeEntry(
extensions: extensionsStr,
status: status,
stake: ToSignedBigIntOrMinusOne(providerStake.stake.amount),
delegateLimit: 0n,//ToSignedBigIntOrMinusOne(providerStake.delegateLimit.amount),
delegateLimit: 0n,
delegateTotal: ToSignedBigIntOrMinusOne(providerStake.delegateTotal.amount),
delegateCommission: ToSignedBigIntOrMinusOne(providerStake.delegateCommission),
appliedHeight: ToSignedIntOrMinusOne(appliedHeight),
Expand All @@ -79,7 +91,7 @@ export async function UpdateStakeInformation(
'pairing.getProviders'
);
providers.stakeEntry.forEach(stake => {
processStakeEntry(height, dbStakes, stake, false);
processStakeEntry(height, dbStakes, stake);
});
}

Expand Down
12 changes: 9 additions & 3 deletions src/indexer/restrpc_agregators/AprMonitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { queryJsinfo } from '@jsinfo/utils/db';
import { HashJson } from '@jsinfo/utils/fmt';
import { sql } from 'drizzle-orm';
import { IsTestnet } from '@jsinfo/utils/env';
import { ActiveProvidersService } from '@jsinfo/redis/resources/index/ActiveProvidersResource';

// Constants
const LAVA_RPC_BENCHMARK_AMOUNT = 10000 * 1000000;
Expand Down Expand Up @@ -459,9 +460,15 @@ class APRMonitorClass {

// 1) Calculate Restaking APR and update the database
logger.info('Calculating Restaking APR...');
const providers = await ActiveProvidersService.fetch();
if (!providers) {
logger.error('No providers found');
return;
}

promises.push(
retry(() => this.calculateAPROnLavaAddresses(
() => RpcPeriodicEndpointCache.GetProviders(),
() => Promise.resolve(providers),
(provider) => RpcOnDemandEndpointCache.GetEstimatedProviderRewards(provider, LAVA_RPC_BENCHMARK_AMOUNT, LAVA_RPC_BENCHMARK_DENOM),
'Restaking APR'
)).then(aprRestaking => {
Expand All @@ -473,7 +480,6 @@ class APRMonitorClass {
// 2) Update APR for each provider concurrently
const updateRestakingAPR = async () => {
logger.info('Updating APR for each provider...');
const providers = await RpcPeriodicEndpointCache.GetProviders();
for (const provider of providers) {
const estimatedRewards = await RpcOnDemandEndpointCache.GetEstimatedProviderRewards(provider, LAVA_RPC_BENCHMARK_AMOUNT, LAVA_RPC_BENCHMARK_DENOM);
const apr = await retry(() => this.calculateAPROnLavaAddresses(
Expand All @@ -490,7 +496,7 @@ class APRMonitorClass {
// 3) Calculate Staking APR and update the database
promises.push(
retry(() => this.calculateAPROnLavaAddresses(
() => RpcPeriodicEndpointCache.GetAllValidatorsAddresses(),
() => RpcPeriodicEndpointCache.GetAllActiveValidatorsAddresses(),
(validator) => RpcOnDemandEndpointCache.GetEstimatedValidatorRewards(validator, LAVA_RPC_BENCHMARK_AMOUNT, LAVA_RPC_BENCHMARK_DENOM),
'Staking APR',
6
Expand Down
21 changes: 21 additions & 0 deletions src/query/handlers/ajax/providersHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import { FastifyRequest, FastifyReply, RouteShorthandOptions } from 'fastify';
import { ProviderMonikerService } from '@jsinfo/redis/resources/global/ProviderMonikerSpecResource'
import { ActiveProvidersService } from '@jsinfo/redis/resources/index/ActiveProvidersResource';

export const ProvidersPaginatedHandlerOpts: RouteShorthandOptions = {
schema: {
Expand All @@ -25,3 +26,23 @@ export async function ProvidersPaginatedHandler(request: FastifyRequest, reply:
providers: providers,
}
}

export const ActiveProvidersPaginatedHandlerOpts: RouteShorthandOptions = {
schema: {
response: {
200: {
type: 'object',
properties: {
providers: { type: 'array' },
}
}
}
}
}

export async function ActiveProvidersPaginatedHandler(request: FastifyRequest, reply: FastifyReply) {
const providers = await ActiveProvidersService.fetch();
return {
providers: providers,
}
}
2 changes: 0 additions & 2 deletions src/query/handlers/ajax/specsHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ export const SpecsPaginatedHandlerOpts: RouteShorthandOptions = {
}

export async function SpecsPaginatedHandler(request: FastifyRequest, reply: FastifyReply) {


const res = await SpecAndConsumerService.GetAllSpecs();
return {
specs: res,
Expand Down
20 changes: 20 additions & 0 deletions src/query/handlers/ajax/validatorsHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,24 @@ export async function ValidatorsPaginatedHandler(request: FastifyRequest, reply:
datetime: latestDatetime,
validators: validatorInfo
};
}

export const ActiveValidatorsPaginatedHandlerOpts: RouteShorthandOptions = {
schema: {
response: {
200: {
type: 'object',
properties: {
validators: { type: 'array' },
}
}
}
}
}

export async function ActiveValidatorsPaginatedHandler(request: FastifyRequest, reply: FastifyReply) {
const validators = await RpcPeriodicEndpointCache.GetAllActiveValidatorsAddresses();
return {
validators: validators,
}
}
13 changes: 12 additions & 1 deletion src/query/handlers/spec/specChartsHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { ProviderMonikerService } from '@jsinfo/redis/resources/global/ProviderM
import { PgColumn } from 'drizzle-orm/pg-core';
import { JSONStringifySpaced } from '@jsinfo/utils/fmt';
import { queryJsinfo } from '@jsinfo/utils/db';
import { ActiveProvidersService } from '@jsinfo/redis/resources/index/ActiveProvidersResource';

type SpecChartCuRelay = {
provider: string;
Expand Down Expand Up @@ -106,13 +107,23 @@ class SpecChartsData extends RequestHandlerBase<SpecChartResponse> {
return this.specTop10ProvidersCache;
}

let activeProviders = await ActiveProvidersService.fetch();
if (GetDataLength(activeProviders) === 0 || !activeProviders) {
return {};
}

// First query to get top 10 providers
let top10Providers = await queryJsinfo(
async (db) => await db.select({
provider: JsinfoSchema.providerStakes.provider,
})
.from(JsinfoSchema.providerStakes)
.where(eq(JsinfoSchema.providerStakes.specId, this.spec))
.where(
and(
eq(JsinfoSchema.providerStakes.specId, this.spec),
inArray(JsinfoSchema.providerStakes.provider, activeProviders)
)
)
.orderBy(desc(JsinfoSchema.providerStakes.stake))
.limit(10),
`SpecCharts_getSpecTop10Providers_${this.spec}`
Expand Down
6 changes: 4 additions & 2 deletions src/query/queryRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { AllProviderAPRRawHandlerOpts, AllProviderAPRRawHandler } from './handle
import { ListProvidersRawHandlerOpts, ListProvidersRawHandler } from './handlers/ajax/listProvidersHandler';

// -- Server meta ajax --
import { ProvidersPaginatedHandler, ProvidersPaginatedHandlerOpts } from './handlers/ajax/providersHandler';
import { ActiveProvidersPaginatedHandler, ActiveProvidersPaginatedHandlerOpts, ProvidersPaginatedHandler, ProvidersPaginatedHandlerOpts } from './handlers/ajax/providersHandler';
import { SpecsPaginatedHandler, SpecsPaginatedHandlerOpts } from './handlers/ajax/specsHandler';
import { ConsumersPaginatedHandler, ConsumersPaginatedHandlerOpts } from './handlers/ajax/consumersHandler';

Expand Down Expand Up @@ -98,7 +98,7 @@ import {
// -- Internal data endpoints --
import { ConsumerV2CahcedHandler, ConsumerV2CahcedHandlerOpts } from './handlers/consumer/consumerV2Handler';
import { ChainWalletApiHandlerOpts, LavaChainRestakersHandler, LavaChainStakersHandler } from './handlers/ajax/chainWalletApiHandlers';
import { ValidatorsPaginatedHandler, ValidatorsPaginatedHandlerOpts } from './handlers/ajax/validatorsHandler';
import { ActiveValidatorsPaginatedHandler, ActiveValidatorsPaginatedHandlerOpts, ValidatorsPaginatedHandler, ValidatorsPaginatedHandlerOpts } from './handlers/ajax/validatorsHandler';
import { TotalLockedValueHandler, TotalLockedValueHandlerOpts } from './handlers/ajax/totalLockedValueHandler';
import { TotalLockedValuesComponentsHandler, TotalLockedValuesComponentsHandlerOpts } from './handlers/ajax/totalLockedValuesComponentsHandler';
import { AllLockedValuesHandler, AllLockedValuesHandlerOpts } from './handlers/ajax/allLockedValuesHandler';
Expand Down Expand Up @@ -131,9 +131,11 @@ GetServerInstance().get('/listProviders', ListProvidersRawHandlerOpts, ListProvi

// -- Server meta ajax --
GetServerInstance().get('/providers', ProvidersPaginatedHandlerOpts, ProvidersPaginatedHandler);
GetServerInstance().get('/active_providers', ActiveProvidersPaginatedHandlerOpts, ActiveProvidersPaginatedHandler);
GetServerInstance().get('/specs', SpecsPaginatedHandlerOpts, SpecsPaginatedHandler);
GetServerInstance().get('/consumers', ConsumersPaginatedHandlerOpts, ConsumersPaginatedHandler);
GetServerInstance().get('/validators', ValidatorsPaginatedHandlerOpts, ValidatorsPaginatedHandler);
GetServerInstance().get('/active_validators', ActiveValidatorsPaginatedHandlerOpts, ActiveValidatorsPaginatedHandler);

// -- All pages ajax --
GetServerInstance().get('/autoCompleteLinksV2Handler', AutoCompleteLinksV2PaginatedHandlerOpts, AutoCompleteLinksV2PaginatedHandler);
Expand Down
4 changes: 2 additions & 2 deletions src/redis/classes/IndexerRedisResourceCaller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { IndexProvidersResource } from '../resources/index/IndexProvidersResourc
import { ProviderStakesAndDelegationResource } from '../resources/global/ProviderStakesAndDelegationResource';
import { IndexTopChainsResource } from '../resources/index/IndexTopChainsResource';
import { IndexTotalCuResource } from '../resources/index/IndexTotalCuResource';
import { ActiveProvidersResource } from '../resources/index/ActiveProvidersResource';
import { ActiveProvidersService } from '../resources/index/ActiveProvidersResource';
import { AllProviderAPRResource } from '../resources/ajax/AllProviderAprResource';
import { LockedTokenValuesResource } from '../resources/ajax/LockedTokenValuesResource';
import { LockedVestingTokensService } from '../resources/global/LockedVestingTokensResource';
Expand Down Expand Up @@ -216,7 +216,7 @@ export class IndexerRedisResourceCaller {

private static async refreshProviderIndexResources(): Promise<void> {
await this.safeFetch('ActiveProviders',
() => new ActiveProvidersResource().fetch(),
() => ActiveProvidersService.fetch(),
this.currentFetches
).catch(e => logger.error('Failed to refresh active providers:', e));

Expand Down
Loading

0 comments on commit 0b1477e

Please sign in to comment.