Skip to content

Commit

Permalink
fix: fill missing positions
Browse files Browse the repository at this point in the history
  • Loading branch information
k0beLeenders committed Dec 22, 2024
1 parent 1a581ba commit 3b5bbf0
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 47 deletions.
47 changes: 2 additions & 45 deletions apps/marginfi-v2-trading/src/hooks/useExtendedPools.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";
import { useTradeStoreV2 } from "~/store";
import { ArenaPoolV2, ArenaPoolV2Extended, ArenaBank, GroupStatus } from "~/types/trade-store.types";
import { ArenaPoolV2, ArenaPoolV2Extended } from "~/types/trade-store.types";
import { getPoolPositionStatus } from "~/utils";

export function useExtendedPool(pool: ArenaPoolV2) {
const [banksByBankPk] = useTradeStoreV2((state) => [state.banksByBankPk]);
Expand Down Expand Up @@ -42,47 +43,3 @@ export function useExtendedPools() {

return extendedPools;
}

function getPoolPositionStatus(pool: ArenaPoolV2, tokenBank: ArenaBank, quoteBank: ArenaBank): GroupStatus {
let isLpPosition = true;
let hasAnyPosition = false;
let isLendingInAny = false;
let isLong = false;
let isShort = false;

if (tokenBank.isActive && tokenBank.position) {
hasAnyPosition = true;
if (tokenBank.position.isLending) {
isLendingInAny = true;
} else if (tokenBank.position.usdValue > 0) {
isShort = true;
isLpPosition = false;
}
}

if (quoteBank.isActive && quoteBank.position) {
hasAnyPosition = true;
if (quoteBank.position.isLending) {
isLendingInAny = true;
} else if (quoteBank.position.usdValue > 0) {
if (tokenBank.isActive && tokenBank.position && tokenBank.position.isLending) {
isLong = true;
}
isLpPosition = false;
}
}

let status = GroupStatus.EMPTY;

if (hasAnyPosition) {
if (isLpPosition && isLendingInAny) {
status = GroupStatus.LP;
} else if (isLong) {
status = GroupStatus.LONG;
} else if (isShort) {
status = GroupStatus.SHORT;
}
}

return status;
}
91 changes: 90 additions & 1 deletion apps/marginfi-v2-trading/src/store/tradeStoreV2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,21 @@ import {
fetchBankDataMap,
fetchInitialArenaState,
fetchUserPositions,
getPoolPositionStatus,
InitialArenaState,
resetArenaBank,
updateArenaBankWithUserData,
} from "~/utils/trade-store.utils";
import { PositionData } from "@mrgnlabs/mrgn-utils";
import { ArenaBank, ArenaPoolPositions, ArenaPoolSummary, ArenaPoolV2, BankData } from "~/types/trade-store.types";
import {
ArenaBank,
ArenaPoolPositions,
ArenaPoolSummary,
ArenaPoolV2,
ArenaPoolV2Extended,
BankData,
GroupStatus,
} from "~/types/trade-store.types";

export enum TradePoolFilterStates {
TIMESTAMP = "timestamp",
Expand Down Expand Up @@ -405,6 +414,13 @@ const stateCreator: StateCreator<TradeStoreV2State, [], []> = (set, get) => ({
return acc;
}, {} as Record<string, MarginfiGroup>);

positionsByGroupPk = fillMissingPositions(
arenaPools,
extendedBanksByBankPk,
marginfiAccountByGroupPk,
positionsByGroupPk
);

if (!lutByGroupPk || Object.keys(lutByGroupPk).length === 0) {
const lutResults: Record<string, Promise<RpcResponseAndContext<AddressLookupTableAccount | null>> | null> = {};

Expand Down Expand Up @@ -545,8 +561,14 @@ const stateCreator: StateCreator<TradeStoreV2State, [], []> = (set, get) => ({
let nativeSolBalance = 0;
let tokenAccountMap: TokenAccountMap | null = null;
let marginfiAccount: MarginfiAccount | null = null;
let positionsByGroupPk: Record<string, ArenaPoolPositions> = {};

if (wallet.publicKey && !wallet.publicKey.equals(PublicKey.default)) {
const userPositions = await fetchUserPositions(wallet.publicKey);
positionsByGroupPk = userPositions.reduce((acc, position) => {
acc[position.groupPk.toBase58()] = position;
return acc;
}, {} as Record<string, ArenaPoolPositions>);
const updatedData = await updateArenaBankWithUserData(
connection,
wallet.publicKey,
Expand Down Expand Up @@ -574,6 +596,13 @@ const stateCreator: StateCreator<TradeStoreV2State, [], []> = (set, get) => ({
const newStoreBanksByBankPk = { ...storeBanksByBankPk };
const newTokenAccountMap = new Map(storeTokenAccountMap);

positionsByGroupPk = fillMissingPositions(
get().arenaPools,
newStoreBanksByBankPk,
storeMarginfiAccountByGroupPk,
positionsByGroupPk
);

extendedBankInfos.map((bank) => {
newStoreBanksByBankPk[bank.address.toBase58()] = bank;
});
Expand All @@ -589,6 +618,7 @@ const stateCreator: StateCreator<TradeStoreV2State, [], []> = (set, get) => ({
marginfiAccountByGroupPk: storeMarginfiAccountByGroupPk,
banksByBankPk: newStoreBanksByBankPk,
tokenAccountMap: newTokenAccountMap,
positionsByGroupPk,
});
},

Expand Down Expand Up @@ -840,3 +870,62 @@ async function fetchOraclePrices() {

return oraclePrices;
}

function fillMissingPositions(
arenaPools: Record<string, ArenaPoolV2>,
banksByBankPk: Record<string, ArenaBank>,
accountByGroupPk: Record<string, MarginfiAccount>,
positions: Record<string, ArenaPoolPositions>
) {
const newPositions: Record<string, ArenaPoolPositions> = positions;

Object.values(arenaPools).map((pool) => {
const tokenBank = banksByBankPk[pool.tokenBankPk.toBase58()];
const quoteBank = banksByBankPk[pool.quoteBankPk.toBase58()];

const status = getPoolPositionStatus(pool, tokenBank, quoteBank);

if (status === GroupStatus.EMPTY) {
delete newPositions[pool.groupPk.toBase58()];
}

if (status === GroupStatus.LONG || status === GroupStatus.SHORT) {
const hasPosition = positions[pool.groupPk.toBase58()];

const account = accountByGroupPk[pool.groupPk.toBase58()];

const positionQuoteData = quoteBank.isActive && quoteBank.position;
const positionTokenData = tokenBank.isActive && tokenBank.position;

if (!hasPosition && account) {
newPositions[pool.groupPk.toBase58()] = {
groupPk: pool.groupPk,
accountPk: account.address,
quoteSummary: {
bankPk: pool.quoteBankPk,
startAmount: positionQuoteData ? positionQuoteData.amount : 0,
startUsdAmount: positionQuoteData ? positionQuoteData.usdValue : 0,
currentAmount: positionQuoteData ? positionQuoteData.amount : 0,
currentUsdAmount: positionQuoteData ? positionQuoteData.usdValue : 0,
pnl: 0,
interest: 0,
},
tokenSummary: {
bankPk: pool.tokenBankPk,
startAmount: positionTokenData ? positionTokenData.amount : 0,
startUsdAmount: positionTokenData ? positionTokenData.usdValue : 0,
currentAmount: positionTokenData ? positionTokenData.amount : 0,
currentUsdAmount: positionTokenData ? positionTokenData.usdValue : 0,
pnl: 0,
interest: 0,
},
entryPrice: tokenBank.info.oraclePrice.priceRealtime.price.toNumber(),
currentPositionValue: 0,
pnl: 0,
};
}
}
});

return newPositions;
}
46 changes: 45 additions & 1 deletion apps/marginfi-v2-trading/src/utils/trade-store.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { AccountInfo, Connection, PublicKey } from "@solana/web3.js";
import { GetStaticProps } from "next";
import { TokenData } from "~/types";
import { PoolListApiResponse, PoolPositionsApiResponse } from "~/types/api.types";
import { ArenaBank, ArenaPoolPositions, ArenaPoolSummary } from "~/types/trade-store.types";
import { ArenaBank, ArenaPoolPositions, ArenaPoolSummary, ArenaPoolV2, GroupStatus } from "~/types/trade-store.types";

/**
* Server-Side Rendering Logic
Expand Down Expand Up @@ -513,3 +513,47 @@ const parseUserPositions = (data: PoolPositionsApiResponse[]): ArenaPoolPosition
pnl: pool.pnl,
}));
};

export function getPoolPositionStatus(pool: ArenaPoolV2, tokenBank: ArenaBank, quoteBank: ArenaBank): GroupStatus {
let isLpPosition = true;
let hasAnyPosition = false;
let isLendingInAny = false;
let isLong = false;
let isShort = false;

if (tokenBank.isActive && tokenBank.position) {
hasAnyPosition = true;
if (tokenBank.position.isLending) {
isLendingInAny = true;
} else if (tokenBank.position.usdValue > 0) {
isShort = true;
isLpPosition = false;
}
}

if (quoteBank.isActive && quoteBank.position) {
hasAnyPosition = true;
if (quoteBank.position.isLending) {
isLendingInAny = true;
} else if (quoteBank.position.usdValue > 0) {
if (tokenBank.isActive && tokenBank.position && tokenBank.position.isLending) {
isLong = true;
}
isLpPosition = false;
}
}

let status = GroupStatus.EMPTY;

if (hasAnyPosition) {
if (isLpPosition && isLendingInAny) {
status = GroupStatus.LP;
} else if (isLong) {
status = GroupStatus.LONG;
} else if (isShort) {
status = GroupStatus.SHORT;
}
}

return status;
}

0 comments on commit 3b5bbf0

Please sign in to comment.