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
9 changes: 9 additions & 0 deletions positions/positions.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
ApiPositionsListing,
ApiPositionsMapping,
ApiPositionsOwners,
ApiReferencePositions,
} from './positions.types';
import { ApiResponse, ApiTags } from '@nestjs/swagger';

Expand Down Expand Up @@ -78,4 +79,12 @@ export class PositionsController {
geMintingtMapping(): ApiMintingUpdateMapping {
return this.positionsService.getMintingUpdatesMapping();
}

@Get('reference')
@ApiResponse({
description: 'Returns the active position with the highest price per collateral for cooldown-free price increases',
})
getReferencePositions(): ApiReferencePositions {
return this.positionsService.getReferencePositions();
}
}
27 changes: 27 additions & 0 deletions positions/positions.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ import {
ApiPositionsListing,
ApiPositionsMapping,
ApiPositionsOwners,
ApiReferencePositions,
MintingUpdateQuery,
MintingUpdateQueryObjectArray,
OwnersPositionsObjectArray,
PositionQuery,
PositionsQueryObjectArray,
ReferencePositionsMapping,
} from './positions.types';

// Genesis position address from NPM package
Expand Down Expand Up @@ -117,6 +119,7 @@ export class PositionsService {
denied
closed
original
isChallenged

minimumCollateral
riskPremiumPPM
Expand Down Expand Up @@ -237,6 +240,7 @@ export class PositionsService {
denied: p.denied,
closed: p.closed,
original: getAddress(p.original),
isChallenged: p.isChallenged,

minimumCollateral: p.minimumCollateral,
annualInterestPPM: leadrate + p.riskPremiumPPM,
Expand Down Expand Up @@ -279,6 +283,29 @@ export class PositionsService {
return list;
}

getReferencePositions(): ApiReferencePositions {
const now = Math.floor(Date.now() / 1000);
const candidates = Object.values(this.fetchedPositions) as PositionQuery[];
const map: ReferencePositionsMapping = {};

for (const p of candidates) {
if (p.closed || p.denied) continue;
if (p.isChallenged) continue;
if (BigInt(p.principal) === 0n) continue;
if (Number(p.cooldown) >= now) continue;
if (Number(p.expiration) <= now) continue;

const collateral = p.collateral.toLowerCase() as Address;
const current = map[collateral];
if (!current || BigInt(p.price) > BigInt(current.price)) {
map[collateral] = p;
}
}

const collaterals = Object.keys(map) as Address[];
return { num: collaterals.length, collaterals, map };
}

getMintingUpdatesList(): ApiMintingUpdateListing {
const m = Object.values(this.fetchedMintingUpdates).flat(1) as MintingUpdateQuery[];
return {
Expand Down
11 changes: 11 additions & 0 deletions positions/positions.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export type PositionQuery = {
denied: boolean;
closed: boolean;
original: Address;
isChallenged: boolean;

minimumCollateral: string;
annualInterestPPM: number; // @dev: in V2, sum of leadrate and riskPremium
Expand Down Expand Up @@ -118,6 +119,16 @@ export type ApiMintingUpdateMapping = {
map: MintingUpdateQueryObjectArray;
};

export type ReferencePositionsMapping = {
[collateral: Address]: PositionQuery;
};

export type ApiReferencePositions = {
num: number;
collaterals: Address[];
map: ReferencePositionsMapping;
};

export type ApiPositionDefault = {
position: Address;
collateral: Address;
Expand Down
Loading