Skip to content

Commit

Permalink
Add support for pagination at controller level. (#1420)
Browse files Browse the repository at this point in the history
* feat: ✨ add pagination for getFills

* feat: ✨ add pagination support for getTrades

* feat: ✨ add pagination support for getTransfers

* test(comlink): ✅ add trades controller pagination tests

* test(comlink): ✅ add transfers controller pagination tests

* test(comlink): ✅ add fills controller pagination tests

* feat: ✨ add pagination check schema

* test(comlink): ✅ update pagination tests

* feat: ✨ add default orderBy for pagination
  • Loading branch information
DavideSegullo authored May 16, 2024
1 parent 5177509 commit 1aa9e26
Show file tree
Hide file tree
Showing 10 changed files with 721 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,91 @@ describe('fills-controller#V4', () => {
);
});

it('Get /fills with market gets fills ordered by createdAtHeight descending and paginated', async () => {
// Order and fill for BTC-USD
await OrderTable.create(testConstants.defaultOrder);
await FillTable.create(testConstants.defaultFill);

// Order and fill for ETH-USD
const ethOrder: OrderFromDatabase = await OrderTable.create({
...testConstants.defaultOrder,
clientId: '3',
clobPairId: testConstants.defaultPerpetualMarket2.clobPairId,
});
const ethFill: FillFromDatabase = await FillTable.create({
...testConstants.defaultFill,
orderId: ethOrder.id,
clobPairId: testConstants.defaultPerpetualMarket2.clobPairId,
eventId: testConstants.defaultTendermintEventId2,
createdAtHeight: '1',
});

const responsePage1: request.Response = await sendRequest({
type: RequestMethod.GET,
path: `/v4/fills?address=${testConstants.defaultAddress}` +
`&subaccountNumber=${testConstants.defaultSubaccount.subaccountNumber}&page=1&limit=1`,
});

const responsePage2: request.Response = await sendRequest({
type: RequestMethod.GET,
path: `/v4/fills?address=${testConstants.defaultAddress}` +
`&subaccountNumber=${testConstants.defaultSubaccount.subaccountNumber}&page=2&limit=1`,
});

const expected: Partial<FillResponseObject>[] = [
{
side: testConstants.defaultFill.side,
liquidity: testConstants.defaultFill.liquidity,
market: testConstants.defaultPerpetualMarket.ticker,
marketType: MarketType.PERPETUAL,
price: testConstants.defaultFill.price,
size: testConstants.defaultFill.size,
fee: testConstants.defaultFill.fee,
type: testConstants.defaultFill.type,
orderId: testConstants.defaultFill.orderId,
createdAt: testConstants.defaultFill.createdAt,
createdAtHeight: testConstants.defaultFill.createdAtHeight,
},
{
side: ethFill.side,
liquidity: ethFill.liquidity,
market: testConstants.defaultPerpetualMarket2.ticker,
marketType: MarketType.PERPETUAL,
price: ethFill.price,
size: ethFill.size,
fee: ethFill.fee,
type: ethFill.type,
orderId: ethOrder.id,
createdAt: ethFill.createdAt,
createdAtHeight: ethFill.createdAtHeight,
},
];

expect(responsePage1.body.pageSize).toStrictEqual(1);
expect(responsePage1.body.offset).toStrictEqual(0);
expect(responsePage1.body.totalResults).toStrictEqual(2);
expect(responsePage1.body.fills).toHaveLength(1);
expect(responsePage1.body.fills).toEqual(
expect.arrayContaining([
expect.objectContaining({
...expected[0],
}),
]),
);

expect(responsePage2.body.pageSize).toStrictEqual(1);
expect(responsePage2.body.offset).toStrictEqual(1);
expect(responsePage2.body.totalResults).toStrictEqual(2);
expect(responsePage2.body.fills).toHaveLength(1);
expect(responsePage2.body.fills).toEqual(
expect.arrayContaining([
expect.objectContaining({
...expected[1],
}),
]),
);
});

it('Get /fills with market with no fills', async () => {
// Order and fill for BTC-USD
await OrderTable.create(testConstants.defaultOrder);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,73 @@ describe('trades-controller#V4', () => {
);
});

it('Get /:ticker gets trades for a ticker in descending order by createdAtHeight and paginated', async () => {
await testMocks.seedData();
await perpetualMarketRefresher.updatePerpetualMarkets();
// Order and fill for BTC-USD (maker and taker)
const fills1: {
makerFill: FillFromDatabase,
takerFill: FillFromDatabase,
} = await createMakerTakerOrderAndFill(
testConstants.defaultOrder,
testConstants.defaultFill,
);

const btcSize2: string = '600';
const fills2: {
makerFill: FillFromDatabase,
takerFill: FillFromDatabase,
} = await createMakerTakerOrderAndFill(
testConstants.defaultOrder,
{
...testConstants.defaultFill,
size: btcSize2,
eventId: testConstants.defaultTendermintEventId2,
createdAtHeight: '1',
},
);

const responsePage1: request.Response = await sendRequest({
type: RequestMethod.GET,
path: `/v4/trades/perpetualMarket/${testConstants.defaultPerpetualMarket.ticker}?page=1&limit=1`,
});

const responsePage2: request.Response = await sendRequest({
type: RequestMethod.GET,
path: `/v4/trades/perpetualMarket/${testConstants.defaultPerpetualMarket.ticker}?page=2&limit=1`,
});

const expected: TradeResponseObject[] = [
fillToTradeResponseObject(fills1.takerFill),
fillToTradeResponseObject(fills2.takerFill),
];

// Expect both trades, ordered by createdAtHeight in descending order
expect(responsePage1.body.pageSize).toStrictEqual(1);
expect(responsePage1.body.offset).toStrictEqual(0);
expect(responsePage1.body.totalResults).toStrictEqual(2);
expect(responsePage1.body.trades).toHaveLength(1);
expect(responsePage1.body.trades).toEqual(
expect.arrayContaining([
expect.objectContaining({
...expected[0],
}),
]),
);

expect(responsePage1.body.pageSize).toStrictEqual(1);
expect(responsePage1.body.offset).toStrictEqual(0);
expect(responsePage2.body.totalResults).toStrictEqual(2);
expect(responsePage2.body.trades).toHaveLength(1);
expect(responsePage2.body.trades).toEqual(
expect.arrayContaining([
expect.objectContaining({
...expected[1],
}),
]),
);
});

it('Get /:ticker for ticker with no fills', async () => {
await testMocks.seedData();
await perpetualMarketRefresher.updatePerpetualMarkets();
Expand All @@ -138,6 +205,21 @@ describe('trades-controller#V4', () => {
expect(response.body.trades).toEqual([]);
});

it('Get /:ticker for ticker with no fills and paginated', async () => {
await testMocks.seedData();
await perpetualMarketRefresher.updatePerpetualMarkets();
// Order and fill for BTC-USD
await OrderTable.create(testConstants.defaultOrder);
await FillTable.create(testConstants.defaultFill);

const response: request.Response = await sendRequest({
type: RequestMethod.GET,
path: `/v4/trades/perpetualMarket/${testConstants.defaultPerpetualMarket2.ticker}?page=1&limit=1`,
});

expect(response.body.trades).toEqual([]);
});

it('Get /:ticker for ticker with price < 1e-6', async () => {
await testMocks.seedData();
await perpetualMarketRefresher.updatePerpetualMarkets();
Expand Down
Loading

0 comments on commit 1aa9e26

Please sign in to comment.