Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions indexer/packages/postgres/__tests__/stores/pnl-table.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -853,4 +853,68 @@ describe('Pnl store', () => {
expect(minHeight).toBeGreaterThanOrEqual(2000);
expect(maxHeight).toBeLessThanOrEqual(4000);
});

it('Returns empty array when no data exists for multiple subaccounts with date filter', async () => {
const subaccountIds = [defaultSubaccountId, defaultSubaccountId2];

// Create some records but with dates after our filter
const records = [];
for (let i = 0; i < subaccountIds.length; i++) {
records.push({
...defaultPnl,
subaccountId: subaccountIds[i],
createdAt: '2024-01-01T00:00:00.000Z',
createdAtHeight: (1000 + i).toString(),
equity: (1000 + i).toString(),
});
}

await Promise.all(records.map((record) => PnlTable.create(record)));

// Query with a date filter that excludes all records
const hourlyResults = await PnlTable.findAllHourlyAggregate(
{
subaccountId: subaccountIds,
createdBeforeOrAt: '2023-01-01T00:00:00.000Z', // Before any records exist
},
[],
{},
);

expect(hourlyResults.results).toEqual([]);

const dailyResults = await PnlTable.findAllDailyAggregate(
{
subaccountId: subaccountIds,
createdBeforeOrAt: '2023-01-01T00:00:00.000Z', // Before any records exist
},
[],
{},
);

expect(dailyResults.results).toEqual([]);
});

it('Returns empty array when no data exists for multiple subaccounts', async () => {
// Use subaccount IDs that have no PNL records at all
const subaccountIds = [defaultSubaccountId, defaultSubaccountId2];

// Don't create any records - just query

const hourlyResults = await PnlTable.findAllHourlyAggregate(
{ subaccountId: subaccountIds },
[],
{},
);

expect(hourlyResults.results).toEqual([]);

const dailyResults = await PnlTable.findAllDailyAggregate(
{ subaccountId: subaccountIds },
[],
{},
);

expect(dailyResults.results).toEqual([]);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -979,7 +979,7 @@ describe('pnl-controller#V4', () => {
expect(response.body).toEqual({
errors: [
{
msg: 'No PnL data found for address nonexistentaddress and parentSubaccountNumber 0',
msg: 'No subaccount found with address nonexistentaddress and parentSubaccountNumber 0',
},
],
});
Expand Down Expand Up @@ -1222,5 +1222,92 @@ describe('pnl-controller#V4', () => {
expect(Number(lastDailyRecord.totalPnl)).toEqual(expectedTotalPnl);
expect(Number(lastDailyRecord.netTransfers)).toEqual(expectedNetTransfers);
}, 120000);

it('Get /pnl/parentSubaccountNumber returns empty array when date filter excludes all data', async () => {
await testMocks.seedData();

// Create PNL records with dates AFTER the filter date
const records = [];
const subaccountIds = [
testConstants.defaultSubaccountId,
testConstants.isolatedSubaccountId,
];

// Create records in 2024 (after our filter date of 2023-12-10)
for (const subaccountId of subaccountIds) {
records.push({
...testConstants.defaultPnl,
subaccountId,
createdAt: '2024-01-01T00:00:00.000Z',
createdAtHeight: '1000',
equity: '1000',
totalPnl: '100',
netTransfers: '500',
});
}

await Promise.all(records.map((record) => PnlTable.create(record)));

// Test with daily=true and createdBeforeOrAt that excludes all data
const dailyResponse: request.Response = await sendRequest({
type: RequestMethod.GET,
path: `/v4/pnl/parentSubaccountNumber?${getQueryString({
address: testConstants.defaultAddress,
parentSubaccountNumber: 0,
daily: 'true',
createdBeforeOrAt: '2023-12-10T23:59:59.000Z',
})}`,
});

// Should return 200 with empty array, not an error
expect(dailyResponse.status).toBe(200);
expect(dailyResponse.body.pnl).toEqual([]);

// Test with daily=false (hourly) and same filter
const hourlyResponse: request.Response = await sendRequest({
type: RequestMethod.GET,
path: `/v4/pnl/parentSubaccountNumber?${getQueryString({
address: testConstants.defaultAddress,
parentSubaccountNumber: 0,
daily: 'false',
createdBeforeOrAt: '2023-12-10T23:59:59.000Z',
})}`,
});

expect(hourlyResponse.status).toBe(200);
expect(hourlyResponse.body.pnl).toEqual([]);
});

it('Get /pnl/parentSubaccountNumber returns empty array when no PNL records exist', async () => {
await testMocks.seedData();

// Don't create any PNL records - subaccounts exist but have no PNL data

// Test with daily=true
const dailyResponse: request.Response = await sendRequest({
type: RequestMethod.GET,
path: `/v4/pnl/parentSubaccountNumber?${getQueryString({
address: testConstants.defaultAddress,
parentSubaccountNumber: 0,
daily: 'true',
})}`,
});

expect(dailyResponse.status).toBe(200);
expect(dailyResponse.body.pnl).toEqual([]);

// Test with daily=false (hourly)
const hourlyResponse: request.Response = await sendRequest({
type: RequestMethod.GET,
path: `/v4/pnl/parentSubaccountNumber?${getQueryString({
address: testConstants.defaultAddress,
parentSubaccountNumber: 0,
daily: 'false',
})}`,
});

expect(hourlyResponse.status).toBe(200);
expect(hourlyResponse.body.pnl).toEqual([]);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,16 @@ class PnlController extends Controller {
@Query() createdOnOrAfter?: IsoString,
@Query() daily?: boolean,
): Promise<PnlResponse> {
// Check if the parent subaccount exists first
const parentSubaccountId: string = SubaccountTable.uuid(address, parentSubaccountNumber);
const parentSubaccount = await SubaccountTable.findById(parentSubaccountId);

if (parentSubaccount === undefined) {
throw new NotFoundError(
`No subaccount found with address ${address} and parentSubaccountNumber ${parentSubaccountNumber}`,
);
}

const childSubaccountIds: string[] = getChildSubaccountIds(address, parentSubaccountNumber);

const queryParams = {
Expand Down Expand Up @@ -158,12 +168,6 @@ class PnlController extends Controller {
);
}

if (pnlData.results.length === 0) {
throw new NotFoundError(
`No PnL data found for address ${address} and parentSubaccountNumber ${parentSubaccountNumber}`,
);
}

return {
pnl: pnlData.results.map(pnlToResponseObject),
totalResults: pnlData.total,
Expand Down
Loading