Skip to content

Commit

Permalink
[TRA-569] Add positions endpoint for vaults (#2159)
Browse files Browse the repository at this point in the history
  • Loading branch information
vincentwschau authored Aug 27, 2024
1 parent da1c05d commit 6cd770f
Show file tree
Hide file tree
Showing 5 changed files with 640 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,21 @@ import {
BlockTable,
liquidityTierRefresher,
SubaccountTable,
PositionSide,
PerpetualPositionTable,
AssetPositionTable,
FundingIndexUpdatesTable,
} from '@dydxprotocol-indexer/postgres';
import { PnlTicksResponseObject, RequestMethod, VaultHistoricalPnl } from '../../../../src/types';
import request from 'supertest';
import { sendRequest } from '../../../helpers/helpers';
import { getFixedRepresentation, sendRequest } from '../../../helpers/helpers';
import config from '../../../../src/config';

describe('vault-controller#V4', () => {
const experimentVaultsPrevVal: string = config.EXPERIMENT_VAULTS;
const experimentVaultMarketsPrevVal: string = config.EXPERIMENT_VAULT_MARKETS;
const blockHeight: string = '3';
const initialFundingIndex: string = '10000';

beforeAll(async () => {
await dbHelpers.migrate();
Expand Down Expand Up @@ -47,6 +52,18 @@ describe('vault-controller#V4', () => {
await dbHelpers.clearData();
});

it('Get /megavault/historicalPnl with no vault subaccounts', async () => {
config.EXPERIMENT_VAULTS = '';
config.EXPERIMENT_VAULT_MARKETS = '';

const response: request.Response = await sendRequest({
type: RequestMethod.GET,
path: '/v4/vault/v1/megavault/historicalPnl',
});

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

it('Get /megavault/historicalPnl with single vault subaccount', async () => {
const createdAt: string = '2000-05-25T00:00:00.000Z';
const pnlTick2: PnlTicksCreateObject = {
Expand Down Expand Up @@ -140,6 +157,18 @@ describe('vault-controller#V4', () => {
);
});

it('Get /vaults/historicalPnl with no vault subaccounts', async () => {
config.EXPERIMENT_VAULTS = '';
config.EXPERIMENT_VAULT_MARKETS = '';

const response: request.Response = await sendRequest({
type: RequestMethod.GET,
path: '/v4/vault/v1/vaults/historicalPnl',
});

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

it('Get /vaults/historicalPnl with single vault subaccount', async () => {
const createdAt: string = '2000-05-25T00:00:00.000Z';
const pnlTick2: PnlTicksCreateObject = {
Expand Down Expand Up @@ -190,7 +219,7 @@ describe('vault-controller#V4', () => {
});
});

it('Get /vault/v1/vaults/historicalPnl with 2 vault subaccounts', async () => {
it('Get /vaults/historicalPnl with 2 vault subaccounts', async () => {
config.EXPERIMENT_VAULTS = [
testConstants.defaultPnlTick.subaccountId,
testConstants.vaultSubaccountId,
Expand Down Expand Up @@ -251,5 +280,170 @@ describe('vault-controller#V4', () => {
]),
);
});

it('Get /megavault/positions with no vault subaccount', async () => {
config.EXPERIMENT_VAULTS = '';
config.EXPERIMENT_VAULT_MARKETS = '';

const response: request.Response = await sendRequest({
type: RequestMethod.GET,
path: '/v4/vault/v1/megavault/positions',
});

expect(response.body).toEqual({
positions: [],
});
});

it('Get /megavault/positions with 1 vault subaccount', async () => {
await Promise.all([
PerpetualPositionTable.create(
testConstants.defaultPerpetualPosition,
),
AssetPositionTable.upsert(testConstants.defaultAssetPosition),
FundingIndexUpdatesTable.create({
...testConstants.defaultFundingIndexUpdate,
fundingIndex: initialFundingIndex,
effectiveAtHeight: testConstants.createdHeight,
}),
FundingIndexUpdatesTable.create({
...testConstants.defaultFundingIndexUpdate,
eventId: testConstants.defaultTendermintEventId2,
effectiveAtHeight: blockHeight,
}),
]);

const response: request.Response = await sendRequest({
type: RequestMethod.GET,
path: '/v4/vault/v1/megavault/positions',
});

expect(response.body).toEqual({
positions: [
{
equity: getFixedRepresentation(159500),
perpetualPosition: {
market: testConstants.defaultPerpetualMarket.ticker,
size: testConstants.defaultPerpetualPosition.size,
side: testConstants.defaultPerpetualPosition.side,
entryPrice: getFixedRepresentation(
testConstants.defaultPerpetualPosition.entryPrice!,
),
maxSize: testConstants.defaultPerpetualPosition.maxSize,
// 200000 + 10*(10000-10050)=199500
netFunding: getFixedRepresentation('199500'),
// sumClose=0, so realized Pnl is the same as the net funding of the position.
// Unsettled funding is funding payments that already "happened" but not reflected
// in the subaccount's balance yet, so it's considered a part of realizedPnl.
realizedPnl: getFixedRepresentation('199500'),
// size * (index-entry) = 10*(15000-20000) = -50000
unrealizedPnl: getFixedRepresentation(-50000),
status: testConstants.defaultPerpetualPosition.status,
sumOpen: testConstants.defaultPerpetualPosition.sumOpen,
sumClose: testConstants.defaultPerpetualPosition.sumClose,
createdAt: testConstants.defaultPerpetualPosition.createdAt,
createdAtHeight: testConstants.defaultPerpetualPosition.createdAtHeight,
exitPrice: null,
closedAt: null,
subaccountNumber: testConstants.defaultSubaccount.subaccountNumber,
},
assetPosition: {
symbol: testConstants.defaultAsset.symbol,
size: '9500',
side: PositionSide.LONG,
assetId: testConstants.defaultAssetPosition.assetId,
subaccountNumber: testConstants.defaultSubaccount.subaccountNumber,
},
ticker: testConstants.defaultPerpetualMarket.ticker,
},
],
});
});

it('Get /megavault/positions with 2 vault subaccount, 1 with no perpetual', async () => {
config.EXPERIMENT_VAULTS = [
testConstants.defaultPnlTick.subaccountId,
testConstants.vaultSubaccountId,
].join(',');
config.EXPERIMENT_VAULT_MARKETS = [
testConstants.defaultPerpetualMarket.clobPairId,
testConstants.defaultPerpetualMarket2.clobPairId,
].join(',');

await Promise.all([
PerpetualPositionTable.create(
testConstants.defaultPerpetualPosition,
),
AssetPositionTable.upsert(testConstants.defaultAssetPosition),
AssetPositionTable.upsert({
...testConstants.defaultAssetPosition,
subaccountId: testConstants.vaultSubaccountId,
}),
FundingIndexUpdatesTable.create({
...testConstants.defaultFundingIndexUpdate,
fundingIndex: initialFundingIndex,
effectiveAtHeight: testConstants.createdHeight,
}),
FundingIndexUpdatesTable.create({
...testConstants.defaultFundingIndexUpdate,
eventId: testConstants.defaultTendermintEventId2,
effectiveAtHeight: blockHeight,
}),
]);

const response: request.Response = await sendRequest({
type: RequestMethod.GET,
path: '/v4/vault/v1/megavault/positions',
});

expect(response.body).toEqual({
positions: [
// Same position as test with a single vault subaccount.
{
equity: getFixedRepresentation(159500),
perpetualPosition: {
market: testConstants.defaultPerpetualMarket.ticker,
size: testConstants.defaultPerpetualPosition.size,
side: testConstants.defaultPerpetualPosition.side,
entryPrice: getFixedRepresentation(
testConstants.defaultPerpetualPosition.entryPrice!,
),
maxSize: testConstants.defaultPerpetualPosition.maxSize,
netFunding: getFixedRepresentation('199500'),
realizedPnl: getFixedRepresentation('199500'),
unrealizedPnl: getFixedRepresentation(-50000),
status: testConstants.defaultPerpetualPosition.status,
sumOpen: testConstants.defaultPerpetualPosition.sumOpen,
sumClose: testConstants.defaultPerpetualPosition.sumClose,
createdAt: testConstants.defaultPerpetualPosition.createdAt,
createdAtHeight: testConstants.defaultPerpetualPosition.createdAtHeight,
exitPrice: null,
closedAt: null,
subaccountNumber: testConstants.defaultSubaccount.subaccountNumber,
},
assetPosition: {
symbol: testConstants.defaultAsset.symbol,
size: '9500',
side: PositionSide.LONG,
assetId: testConstants.defaultAssetPosition.assetId,
subaccountNumber: testConstants.defaultSubaccount.subaccountNumber,
},
ticker: testConstants.defaultPerpetualMarket.ticker,
},
{
equity: getFixedRepresentation(10000),
perpetualPosition: undefined,
assetPosition: {
symbol: testConstants.defaultAsset.symbol,
size: testConstants.defaultAssetPosition.size,
side: PositionSide.LONG,
assetId: testConstants.defaultAssetPosition.assetId,
subaccountNumber: testConstants.defaultSubaccount.subaccountNumber,
},
ticker: testConstants.defaultPerpetualMarket2.ticker,
},
],
});
});
});
});
Loading

0 comments on commit 6cd770f

Please sign in to comment.