Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into affan/revshare-logic
Browse files Browse the repository at this point in the history
  • Loading branch information
affanv14 committed Sep 16, 2024
2 parents a6c1f99 + 2882271 commit 36b8725
Show file tree
Hide file tree
Showing 103 changed files with 10,429 additions and 704 deletions.
162 changes: 162 additions & 0 deletions indexer/packages/postgres/__tests__/stores/pnl-ticks-table.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import {
IsoString,
LeaderboardPnlCreateObject,
Ordering,
PnlTickInterval,
PnlTicksColumns,
PnlTicksCreateObject,
PnlTicksFromDatabase,
} from '../../src/types';
import * as PnlTicksTable from '../../src/stores/pnl-ticks-table';
import * as BlockTable from '../../src/stores/block-table';
Expand Down Expand Up @@ -439,6 +441,51 @@ describe('PnlTicks store', () => {
expect(leaderboardRankedData.length).toEqual(2);
});

it.each([
{
description: 'Get hourly pnl ticks',
interval: PnlTickInterval.hour,
},
{
description: 'Get daily pnl ticks',
interval: PnlTickInterval.day,
},
])('$description', async ({
interval,
}: {
interval: PnlTickInterval,
}) => {
const createdTicks: PnlTicksFromDatabase[] = await setupIntervalPnlTicks();
const pnlTicks: PnlTicksFromDatabase[] = await PnlTicksTable.getPnlTicksAtIntervals(
interval,
7 * 24 * 60 * 60, // 1 week
[defaultSubaccountId, defaultSubaccountIdWithAlternateAddress],
);
// See setup function for created ticks.
// Should exclude tick that is within the same hour except the first.
const expectedHourlyTicks: PnlTicksFromDatabase[] = [
createdTicks[8],
createdTicks[7],
createdTicks[5],
createdTicks[3],
createdTicks[2],
createdTicks[0],
];
// Should exclude ticks that is within the same day except for the first.
const expectedDailyTicks: PnlTicksFromDatabase[] = [
createdTicks[8],
createdTicks[7],
createdTicks[3],
createdTicks[2],
];

if (interval === PnlTickInterval.day) {
expect(pnlTicks).toEqual(expectedDailyTicks);
} else if (interval === PnlTickInterval.hour) {
expect(pnlTicks).toEqual(expectedHourlyTicks);
}
});

});

async function setupRankedPnlTicksData() {
Expand Down Expand Up @@ -544,3 +591,118 @@ async function setupRankedPnlTicksData() {
},
]);
}

async function setupIntervalPnlTicks(): Promise<PnlTicksFromDatabase[]> {
const currentTime: DateTime = DateTime.utc().startOf('day');
const tenMinAgo: string = currentTime.minus({ minute: 10 }).toISO();
const almostTenMinAgo: string = currentTime.minus({ second: 603 }).toISO();
const twoHoursAgo: string = currentTime.minus({ hour: 2 }).toISO();
const twoDaysAgo: string = currentTime.minus({ day: 2 }).toISO();
const monthAgo: string = currentTime.minus({ day: 30 }).toISO();
await Promise.all([
BlockTable.create({
blockHeight: '3',
time: monthAgo,
}),
BlockTable.create({
blockHeight: '4',
time: twoDaysAgo,
}),
BlockTable.create({
blockHeight: '6',
time: twoHoursAgo,
}),
BlockTable.create({
blockHeight: '8',
time: almostTenMinAgo,
}),
BlockTable.create({
blockHeight: '10',
time: tenMinAgo,
}),
]);
const createdTicks: PnlTicksFromDatabase[] = await PnlTicksTable.createMany([
{
subaccountId: defaultSubaccountId,
equity: '1100',
createdAt: almostTenMinAgo,
totalPnl: '1200',
netTransfers: '50',
blockHeight: '10',
blockTime: almostTenMinAgo,
},
{
subaccountId: defaultSubaccountId,
equity: '1090',
createdAt: tenMinAgo,
totalPnl: '1190',
netTransfers: '50',
blockHeight: '8',
blockTime: tenMinAgo,
},
{
subaccountId: defaultSubaccountId,
equity: '1080',
createdAt: twoHoursAgo,
totalPnl: '1180',
netTransfers: '50',
blockHeight: '6',
blockTime: twoHoursAgo,
},
{
subaccountId: defaultSubaccountId,
equity: '1070',
createdAt: twoDaysAgo,
totalPnl: '1170',
netTransfers: '50',
blockHeight: '4',
blockTime: twoDaysAgo,
},
{
subaccountId: defaultSubaccountId,
equity: '1200',
createdAt: monthAgo,
totalPnl: '1170',
netTransfers: '50',
blockHeight: '3',
blockTime: monthAgo,
},
{
subaccountId: defaultSubaccountIdWithAlternateAddress,
equity: '200',
createdAt: almostTenMinAgo,
totalPnl: '300',
netTransfers: '50',
blockHeight: '10',
blockTime: almostTenMinAgo,
},
{
subaccountId: defaultSubaccountIdWithAlternateAddress,
equity: '210',
createdAt: tenMinAgo,
totalPnl: '310',
netTransfers: '50',
blockHeight: '8',
blockTime: tenMinAgo,
},
{
subaccountId: defaultSubaccountIdWithAlternateAddress,
equity: '220',
createdAt: twoHoursAgo,
totalPnl: '320',
netTransfers: '50',
blockHeight: '6',
blockTime: twoHoursAgo,
},
{
subaccountId: defaultSubaccountIdWithAlternateAddress,
equity: '230',
createdAt: twoDaysAgo,
totalPnl: '330',
netTransfers: '50',
blockHeight: '4',
blockTime: twoDaysAgo,
},
]);
return createdTicks;
}
57 changes: 57 additions & 0 deletions indexer/packages/postgres/src/stores/pnl-ticks-table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
PaginationFromDatabase,
LeaderboardPnlCreateObject,
LeaderboardPnlTimeSpan,
PnlTickInterval,
} from '../types';

export function uuid(
Expand Down Expand Up @@ -448,3 +449,59 @@ async function getAllTimeRankedPnlTicks(): Promise<LeaderboardPnlCreateObject[]>

return result.rows;
}

/**
* Constructs a query to get pnl ticks at a specific interval for a set of subaccounts
* within a time range.
* Uses a windowing function in the raw query to get the first row of each window of the specific
* interval time.
* Currently only supports hourly / daily as the interval.
* @param interval 'day' or 'hour'.
* @param timeWindowSeconds Window of time to get pnl ticks for at the specified interval.
* @param subaccountIds Set of subaccounts to get pnl ticks for.
* @returns
*/
export async function getPnlTicksAtIntervals(
interval: PnlTickInterval,
timeWindowSeconds: number,
subaccountIds: string[],
): Promise <PnlTicksFromDatabase[]> {
const result: {
rows: PnlTicksFromDatabase[],
} = await knexReadReplica.getConnection().raw(
`
SELECT
"id",
"subaccountId",
"equity",
"totalPnl",
"netTransfers",
"createdAt",
"blockHeight",
"blockTime"
FROM (
SELECT
pnl_ticks.*,
ROW_NUMBER() OVER (
PARTITION BY
"subaccountId",
DATE_TRUNC(
'${interval}',
"blockTime"
) ORDER BY "blockTime"
) AS r
FROM pnl_ticks
WHERE
"subaccountId" IN (${subaccountIds.map((id: string) => { return `'${id}'`; }).join(',')}) AND
"blockTime" > NOW() - INTERVAL '${timeWindowSeconds} second'
) AS pnl_intervals
WHERE
r = 1
ORDER BY "subaccountId";
`,
) as unknown as {
rows: PnlTicksFromDatabase[],
};

return result.rows;
}
5 changes: 5 additions & 0 deletions indexer/packages/postgres/src/types/pnl-ticks-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,8 @@ export enum PnlTicksColumns {
blockHeight = 'blockHeight',
blockTime = 'blockTime',
}

export enum PnlTickInterval {
hour = 'hour',
day = 'day',
}
Loading

0 comments on commit 36b8725

Please sign in to comment.