Skip to content

Commit

Permalink
feat: rewards history limit default
Browse files Browse the repository at this point in the history
- default rewards history limit to 3 epochs back if not specified
  • Loading branch information
Ivaylo Andonov committed Mar 1, 2023
1 parent 23bdb6e commit 8c32be8
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@ import {
import { CommonPoolInfo, OrderedResult, PoolAPY, PoolData, PoolMetrics, PoolSortType, PoolUpdate } from './types';
import { DbSyncProvider, DbSyncProviderDependencies, Disposer, EpochMonitor } from '../../util';
import { GenesisData, InMemoryCache, StakePoolExtMetadataService, UNLIMITED_CACHE_TTL } from '../..';
import { IDS_NAMESPACE, StakePoolsSubQuery, emptyPoolsExtraInfo, getStakePoolSortType, queryCacheKey } from './util';
import {
IDS_NAMESPACE,
REWARDS_HISTORY_LIMIT_DEFAULT,
StakePoolsSubQuery,
emptyPoolsExtraInfo,
getStakePoolSortType,
queryCacheKey
} from './util';
import { RunnableModule, isNotNil } from '@cardano-sdk/util';
import { StakePoolBuilder } from './StakePoolBuilder';
import { toStakePoolResults } from './mappers';
Expand Down Expand Up @@ -166,7 +173,7 @@ export class DbSyncStakePoolProvider extends DbSyncProvider(RunnableModule) impl
}

public async queryStakePools(options: QueryStakePoolsArgs): Promise<Paginated<Cardano.StakePool>> {
const { filters, pagination, rewardsHistoryLimit } = options;
const { filters, pagination, rewardsHistoryLimit = REWARDS_HISTORY_LIMIT_DEFAULT } = options;

if (pagination.limit > this.#paginationPageSizeLimit) {
throw new ProviderError(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {
} from '@cardano-sdk/core';
import BigNumber from 'bignumber.js';

export const REWARDS_HISTORY_LIMIT_DEFAULT = 3;

export const getStakePoolSortType = (field: string): PoolSortType => {
if (isPoolDataSortField(field)) return 'data';
if (isPoolMetricsSortField(field)) return 'metrics';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { LedgerTipModel, findLedgerTip } from '../../src/util/DbSyncProvider';
import { OgmiosCardanoNode } from '@cardano-sdk/ogmios';
import { Pool } from 'pg';
import { PoolInfo, PoolWith, StakePoolFixtureBuilder } from './fixtures/FixtureBuilder';
import { REWARDS_HISTORY_LIMIT_DEFAULT } from '../../src/StakePool/DbSyncStakePoolProvider/util';
import { getPort } from 'get-port-please';
import { healthCheckResponseMock, mockCardanoNode } from '../../../core/test/CardanoNode/mocks';
import { ingestDbData, sleep, wrapWithTransaction } from '../util';
Expand Down Expand Up @@ -458,62 +459,67 @@ describe('StakePoolHttpService', () => {
);

describe('pagination', () => {
const historyLimitDefault = REWARDS_HISTORY_LIMIT_DEFAULT;
const baseArgs = { pagination: { limit: 2, startAt: 0 } };
const argsWithHistoryLimit = { ...baseArgs, rewardsHistoryLimit: 5 };

it('should paginate response', async () => {
const req: QueryStakePoolsArgs = { pagination };
const reqWithPagination: QueryStakePoolsArgs = { pagination: { limit: 2, startAt: 1 } };
const responseWithPagination = await provider.queryStakePools(reqWithPagination);
const response = await provider.queryStakePools(req);
expect(response.pageResults.length).toBeGreaterThan(0);
expect(responseWithPagination.pageResults.length).toEqual(2);
expect(response.pageResults[0]).not.toEqual(responseWithPagination.pageResults[0]);
const paginatedResponse = await provider.queryStakePools(baseArgs);
expect(paginatedResponse.pageResults.length).toEqual(baseArgs.pagination.limit);

const responseWithPaginationCached = await provider.queryStakePools(reqWithPagination);
expect(responseWithPagination.pageResults).toEqual(responseWithPaginationCached.pageResults);
const paginatedResponseCached = await provider.queryStakePools(baseArgs);
expect(paginatedResponse.pageResults).toEqual(paginatedResponseCached.pageResults);
});

it('should paginate response with or condition', async () => {
const req: QueryStakePoolsArgs = { filters: { _condition: 'or' }, pagination };
const reqWithPagination: QueryStakePoolsArgs = { ...req, pagination: { limit: 2, startAt: 1 } };
const responseWithPagination = await provider.queryStakePools(reqWithPagination);
const response = await provider.queryStakePools(req);
expect(response.pageResults.length).toBeGreaterThan(0);
expect(responseWithPagination.pageResults.length).toEqual(2);
expect(response.pageResults[0]).not.toEqual(responseWithPagination.pageResults[0]);
const reqWithPagination: QueryStakePoolsArgs = { ...baseArgs, filters: { _condition: 'or' } };

const paginatedResponse = await provider.queryStakePools(reqWithPagination);
expect(paginatedResponse.pageResults.length).toEqual(baseArgs.pagination.limit);

const responseWithPaginationCached = await provider.queryStakePools(reqWithPagination);
expect(responseWithPagination.pageResults).toEqual(responseWithPaginationCached.pageResults);
const paginatedResponseCached = await provider.queryStakePools(reqWithPagination);
expect(paginatedResponse.pageResults).toEqual(paginatedResponseCached.pageResults);
});

it('should paginate rewards response', async () => {
const req = { pagination: { limit: 1, startAt: 1 } };
const reqWithRewardsPagination = { pagination: { limit: 1, startAt: 1 }, rewardsHistoryLimit: 0 };
const responseWithPagination = await provider.queryStakePools(reqWithRewardsPagination);
const response = await provider.queryStakePools(req);
expect(response.pageResults[0].epochRewards.length).toBeGreaterThanOrEqual(1);
expect(responseWithPagination.pageResults[0].epochRewards.length).toEqual(0);
const resWithoutRewardsHistoryLimit = await provider.queryStakePools(baseArgs);
const resWithRewardsHistoryLimit = await provider.queryStakePools(argsWithHistoryLimit);

const responseCached = await provider.queryStakePools(req);
expect(response.pageResults).toEqual(responseCached.pageResults);
const responsePaginatedCached = await provider.queryStakePools(reqWithRewardsPagination);
expect(responseWithPagination.pageResults).toEqual(responsePaginatedCached.pageResults);
expect(resWithoutRewardsHistoryLimit.pageResults[0].epochRewards).toHaveLength(historyLimitDefault);
expect(resWithRewardsHistoryLimit.pageResults[0].epochRewards).toHaveLength(
argsWithHistoryLimit.rewardsHistoryLimit
);

const resWithoutRewardsHistoryLimitCached = await provider.queryStakePools(baseArgs);
const resWithRewardsHistoryLimitCached = await provider.queryStakePools(argsWithHistoryLimit);

expect(resWithoutRewardsHistoryLimit.pageResults).toEqual(resWithoutRewardsHistoryLimitCached.pageResults);
expect(resWithRewardsHistoryLimit.pageResults).toEqual(resWithRewardsHistoryLimitCached.pageResults);
});

it('should paginate rewards response with or condition', async () => {
const req: QueryStakePoolsArgs = { filters: { _condition: 'or' }, pagination: { limit: 1, startAt: 1 } };
const reqWithRewardsPagination = { pagination: { limit: 1, startAt: 1 }, rewardsHistoryLimit: 0 };
const responseWithPagination = await provider.queryStakePools(reqWithRewardsPagination);
const response = await provider.queryStakePools(req);
expect(response.pageResults[0].epochRewards.length).toBeGreaterThanOrEqual(1);
expect(responseWithPagination.pageResults[0].epochRewards.length).toEqual(0);
const reqWithoutRewardsHistory: QueryStakePoolsArgs = { ...baseArgs, filters: { _condition: 'or' } };

const responseCached = await provider.queryStakePools(req);
expect(response.pageResults).toEqual(responseCached.pageResults);
const responsePaginatedCached = await provider.queryStakePools(reqWithRewardsPagination);
expect(responseWithPagination.pageResults).toEqual(responsePaginatedCached.pageResults);
const resWithRewardsHistoryLimit = await provider.queryStakePools(argsWithHistoryLimit);
const resWithoutRewardsHistoryLimit = await provider.queryStakePools(reqWithoutRewardsHistory);

expect(resWithoutRewardsHistoryLimit.pageResults[0].epochRewards).toHaveLength(historyLimitDefault);
expect(resWithRewardsHistoryLimit.pageResults[0].epochRewards).toHaveLength(
argsWithHistoryLimit.rewardsHistoryLimit
);

const resWithoutRewardsHistoryLimitCached = await provider.queryStakePools(reqWithoutRewardsHistory);
expect(resWithoutRewardsHistoryLimit.pageResults).toEqual(resWithoutRewardsHistoryLimitCached.pageResults);

const resWithRewardsHistoryLimitCached = await provider.queryStakePools(argsWithHistoryLimit);
expect(resWithRewardsHistoryLimit.pageResults).toEqual(resWithRewardsHistoryLimitCached.pageResults);
});

it('should cache paginated response', async () => {
const reqWithPagination: QueryStakePoolsArgs = { pagination: { limit: 3, startAt: 0 } };
const firstResponseWithPagination = await provider.queryStakePools(reqWithPagination);
const firstResponseWithPagination = await provider.queryStakePools(baseArgs);
expect(dbConnectionQuerySpy).toHaveBeenCalledTimes(cachedSubQueriesCount + nonCacheableSubQueriesCount);
dbConnectionQuerySpy.mockClear();
const secondResponseWithPaginationCached = await provider.queryStakePools(reqWithPagination);
const secondResponseWithPaginationCached = await provider.queryStakePools(baseArgs);
expect(firstResponseWithPagination.pageResults).toEqual(secondResponseWithPaginationCached.pageResults);
expect(firstResponseWithPagination.totalResultCount).toEqual(
secondResponseWithPaginationCached.totalResultCount
Expand Down Expand Up @@ -1377,12 +1383,17 @@ describe('StakePoolHttpService', () => {
});

it('rewardsHistoryLimit is correctly honored', async () => {
const noLimitResponse = await provider.queryStakePools({ pagination });
const limitOneResponse = await provider.queryStakePools({ pagination, rewardsHistoryLimit: 1 });
const limitThreeResponse = await provider.queryStakePools({ pagination, rewardsHistoryLimit: 3 });
const limitFiveResponse = await provider.queryStakePools({ pagination, rewardsHistoryLimit: 5 });
expect(limitThreeResponse.pageResults[0].metrics.apy).not.toBe(limitFiveResponse.pageResults[0].metrics.apy);
});

expect(noLimitResponse.pageResults[0].metrics.apy).not.toBe(limitOneResponse.pageResults[0].metrics.apy);
it('rewardsHistoryLimit defaults to 3 correctly', async () => {
const response = await provider.queryStakePools({ pagination });
expect(response.pageResults[0].epochRewards).toHaveLength(3);
});
});

describe('/stats', () => {
const url = '/stats';
describe('with Http Server', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export interface QueryStakePoolsArgs {
status?: Cardano.StakePoolStatus[];
};
/**
* Will fetch all stake pool reward history if not specified
* Will fetch stake pool reward history up to 3 epochs back if not specified
*/
rewardsHistoryLimit?: number;
/**
Expand Down

0 comments on commit 8c32be8

Please sign in to comment.