Skip to content

Commit

Permalink
Incorporate defaultFunding into nextFunding
Browse files Browse the repository at this point in the history
  • Loading branch information
teddyding committed Jan 23, 2025
1 parent 3535b68 commit b9472f8
Show file tree
Hide file tree
Showing 7 changed files with 216 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export interface PerpetualMarketUpdateObject {
subticksPerTick?: number,
stepBaseQuantums?: number,
liquidityTierId?: number,
defaultFundingRate1H?: string,
}

export enum PerpetualMarketColumns {
Expand Down
26 changes: 21 additions & 5 deletions indexer/packages/redis/__tests__/caches/next-funding-cache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,14 @@ describe('nextFundingCache', () => {
await addFundingSample('BTC', new Big('0.0001'), client);
await addFundingSample('BTC', new Big('0.0002'), client); // avg = 0.00015
await addFundingSample('ETH', new Big('0.0005'), client); // avg = 0.0005
expect(await getNextFunding(client, ['BTC', 'ETH'])).toEqual(
{ BTC: new Big('0.00015'), ETH: new Big('0.0005') },
expect(await getNextFunding(client, [
['BTC', '0.0001'],
['ETH', '0'],
])).toEqual(
{
BTC: new Big('0.00025'), // 0.00015 + 0.0001
ETH: new Big('0.0005'), // 0.0005 + 0
},
);
});

Expand All @@ -27,13 +33,23 @@ describe('nextFundingCache', () => {
await addFundingSample('BTC', new Big('0.0002'), client); // avg = 0.00015
await clearFundingSamples('BTC', client);
await addFundingSample('ETH', new Big('0.0005'), client); // avg = 0.0005
expect(await getNextFunding(client, ['BTC', 'ETH'])).toEqual(
{ BTC: undefined, ETH: new Big('0.0005') },
expect(await getNextFunding(client, [
['BTC', '0.0001'],
['ETH', '0.00015'],
])).toEqual(
{
BTC: undefined, // no samples
ETH: new Big('0.00065'), // 0.0005 + 0.00015
},
);
});

it('get next funding with no values', async () => {
expect(await getNextFunding(client, ['BTC'])).toEqual(
expect(await getNextFunding(client, [
['BTC', '0.001'],
])).toEqual(
// Even though default funding rate is 0.001,
// return undefined since there are no samples
{ BTC: undefined },
);
});
Expand Down
7 changes: 4 additions & 3 deletions indexer/packages/redis/src/caches/next-funding-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ function getKey(ticker: string): string {
*/
export async function getNextFunding(
client: RedisClient,
tickers: string[],
tickerDefaultFundingRate1HPairs: [string, string][],
): Promise<{ [ticker: string]: Big | undefined }> {
const fundingRates: { [ticker: string]: Big | undefined } = {};

await Promise.all(
tickers.map(async (ticker: string) => {
tickerDefaultFundingRate1HPairs.map(async ([ticker, defaultFundingRate1H]) => {
const rates: string[] = await lRangeAsync(
getKey(ticker),
client,
Expand All @@ -36,7 +37,7 @@ export async function getNextFunding(
new Big(0),
);
const avg: Big = sum.div(rates.length);
fundingRates[ticker] = avg;
fundingRates[ticker] = avg.plus(new Big(defaultFundingRate1H));
} else {
fundingRates[ticker] = undefined;
}
Expand Down
79 changes: 68 additions & 11 deletions indexer/services/ender/__tests__/handlers/funding-handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
FundingIndexUpdatesColumns,
FundingIndexUpdatesFromDatabase,
FundingIndexUpdatesTable,
PerpetualMarketTable,
OraclePriceTable,
Ordering,
perpetualMarketRefresher,
Expand Down Expand Up @@ -42,6 +43,7 @@ import Big from 'big.js';
import { redisClient } from '../../src/helpers/redis/redis-controller';
import { bigIntToBytes } from '@dydxprotocol-indexer/v4-proto-parser';
import { createPostgresFunctions } from '../../src/helpers/postgres/postgres-functions';
import { defaultPerpetualMarket } from '@dydxprotocol-indexer/postgres/build/__tests__/helpers/constants';

describe('fundingHandler', () => {
beforeAll(async () => {
Expand Down Expand Up @@ -127,10 +129,65 @@ describe('fundingHandler', () => {
await onMessage(kafkaMessage);

await expectNextFundingRate(
'BTC-USD',
new Big(protocolTranslations.funding8HourValuePpmTo1HourRate(
defaultFundingUpdateSampleEvent.updates[0].fundingValuePpm,
)),
'BTC-USD',
);
});

it.each([
[
'Non-zero sample',
'TEST-USD',
'0.0001',
120,
new Big('0.000115'), // 0.000120 / 8 + default 0.0001
],
[
'Sample is zero',
'TEST-USD',
'0.0001',
0,
new Big('0.0001'), // 0 + default 0.0001
],
])('(%s) Non-zero default funding: successfully handle premium sample', async (
_name: string,
ticker: string,
defaultFundingRate1H: string,
fundingValuePpm: number,
expectedNextFundingRate: Big,
) => {
const testPerpetualMarket = await PerpetualMarketTable.create({
...defaultPerpetualMarket,
id: '1000', // Different id than `defaultPerpeptualMarket` to avoid conflict
ticker,
defaultFundingRate1H,
});

const fundingUpdateSampleEvent: FundingEventV1 = {
type: FundingEventV1_Type.TYPE_PREMIUM_SAMPLE,
updates: [
{
perpetualId: parseInt(testPerpetualMarket.id, 10),
fundingValuePpm,
fundingIndex: bigIntToBytes(BigInt(0)),
},
],
};

const kafkaMessage: KafkaMessage = createKafkaMessageFromFundingEvents({
fundingEvents: [fundingUpdateSampleEvent],
height: defaultHeight,
time: defaultTime,
});

await onMessage(kafkaMessage);

await expectNextFundingRate(
expectedNextFundingRate,
ticker,
defaultFundingRate1H,
);
});

Expand Down Expand Up @@ -160,14 +217,14 @@ describe('fundingHandler', () => {
await onMessage(kafkaMessage);

await expectNextFundingRate(
'BTC-USD',
new Big('0.000006875'),
'BTC-USD',
);
await expectNextFundingRate(
'ETH-USD',
new Big(protocolTranslations.funding8HourValuePpmTo1HourRate(
fundingUpdateSampleEvent2.updates[1].fundingValuePpm,
)),
'ETH-USD',
);
});

Expand Down Expand Up @@ -204,10 +261,10 @@ describe('fundingHandler', () => {
await onMessage(kafkaMessage);

await expectNextFundingRate(
'BTC-USD',
new Big(protocolTranslations.funding8HourValuePpmTo1HourRate(
defaultFundingUpdateSampleEvent.updates[0].fundingValuePpm,
)),
'BTC-USD',
);

const kafkaMessage2: KafkaMessage = createKafkaMessageFromFundingEvents({
Expand All @@ -218,8 +275,8 @@ describe('fundingHandler', () => {

await onMessage(kafkaMessage2);
await expectNextFundingRate(
'BTC-USD',
undefined,
'BTC-USD',
);
const fundingIndices: FundingIndexUpdatesFromDatabase[] = await
FundingIndexUpdatesTable.findAll({}, [], {});
Expand Down Expand Up @@ -253,10 +310,10 @@ describe('fundingHandler', () => {
await onMessage(kafkaMessage);

await expectNextFundingRate(
'BTC-USD',
new Big(protocolTranslations.funding8HourValuePpmTo1HourRate(
defaultFundingUpdateSampleEvent.updates[0].fundingValuePpm,
)),
'BTC-USD',
);

const kafkaMessage2: KafkaMessage = createKafkaMessageFromFundingEvents({
Expand All @@ -267,8 +324,8 @@ describe('fundingHandler', () => {

await onMessage(kafkaMessage2);
await expectNextFundingRate(
'BTC-USD',
undefined,
'BTC-USD',
);
const fundingIndices: FundingIndexUpdatesFromDatabase[] = await
FundingIndexUpdatesTable.findAll({}, [], {});
Expand Down Expand Up @@ -310,16 +367,16 @@ describe('fundingHandler', () => {

await Promise.all([
expectNextFundingRate(
'BTC-USD',
new Big(protocolTranslations.funding8HourValuePpmTo1HourRate(
fundingSampleEvent.updates[0].fundingValuePpm,
)),
'BTC-USD',
),
expectNextFundingRate(
'ETH-USD',
new Big(protocolTranslations.funding8HourValuePpmTo1HourRate(
fundingSampleEvent.updates[1].fundingValuePpm,
)),
'ETH-USD',
),
]);

Expand Down Expand Up @@ -347,12 +404,12 @@ describe('fundingHandler', () => {
await onMessage(kafkaMessage2);
await Promise.all([
expectNextFundingRate(
'BTC-USD',
undefined,
'BTC-USD',
),
expectNextFundingRate(
'ETH-USD',
undefined,
'ETH-USD',
),
]);
const fundingIndices: FundingIndexUpdatesFromDatabase[] = await
Expand Down
7 changes: 4 additions & 3 deletions indexer/services/ender/__tests__/helpers/redis-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ import Big from 'big.js';
import { redisClient } from '../../src/helpers/redis/redis-controller';

export async function expectNextFundingRate(
expectedRate: Big | undefined,
ticker: string,
rate: Big | undefined,
defaultFundingRate1H: string = '0',
): Promise<void> {
const rates: { [ticker: string]: Big | undefined } = await NextFundingCache.getNextFunding(
redisClient,
[ticker],
[[ticker, defaultFundingRate1H]],
);
expect(rates[ticker]).toEqual(rate);
expect(rates[ticker]).toEqual(expectedRate);
}

export async function expectStateFilledQuantums(
Expand Down
Loading

0 comments on commit b9472f8

Please sign in to comment.