Skip to content

Commit

Permalink
feat(mean-finance): Use lodash to refactor positions and remove call …
Browse files Browse the repository at this point in the history
…to pairs (Zapper-fi#937)
  • Loading branch information
immasandwich committed Jul 23, 2022
1 parent 0af15de commit 016c187
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 234 deletions.
21 changes: 0 additions & 21 deletions src/apps/mean-finance/graphql/getPairs.ts

This file was deleted.

5 changes: 1 addition & 4 deletions src/apps/mean-finance/graphql/getPositions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ import { gql } from 'graphql-request';

export const GET_POSITIONS = gql`
query getPositions($first: Int, $lastId: String) {
positions(
where: { status_in: [ACTIVE, COMPLETED], id_gt: $lastId }
first: $first
) {
positions(where: { status_in: [ACTIVE, COMPLETED], id_gt: $lastId }, first: $first) {
id
executedSwaps
user
Expand Down
28 changes: 0 additions & 28 deletions src/apps/mean-finance/helpers/graph.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { TheGraphHelper } from '~app-toolkit/helpers/the-graph/the-graph.helper';

import { GET_PAIRS } from '../graphql/getPairs';
import { GET_POSITIONS } from '../graphql/getPositions';
import { GET_USER_POSITIONS } from '../graphql/getUserPositions';

Expand Down Expand Up @@ -53,30 +52,3 @@ export const getPositions = (network: string, graphHelper: TheGraphHelper) => {
dataToSearch: 'positions',
});
};

type MeanFinancePair = {
pairs: {
id: string;
tokenA: {
address: string;
decimals: string;
name: string;
symbol: string;
};
tokenB: {
address: string;
decimals: string;
name: string;
symbol: string;
};
}[];
};

export const getPairs = (network: string, graphHelper: TheGraphHelper) => {
return graphHelper.gqlFetchAll<MeanFinancePair>({
endpoint: `https://api.thegraph.com/subgraphs/name/mean-finance/dca-v2-${network}`,
query: GET_PAIRS,
variables: {},
dataToSearch: 'pairs',
});
};
Original file line number Diff line number Diff line change
@@ -1,140 +1,105 @@
import { Inject } from '@nestjs/common';
import { BigNumber } from 'ethers';
import { sumBy, keyBy } from 'lodash';
import { compact, groupBy, sumBy, values } from 'lodash';

import { IAppToolkit, APP_TOOLKIT } from '~app-toolkit/app-toolkit.interface';
import { Register } from '~app-toolkit/decorators';
import { drillBalance } from '~app-toolkit/helpers/balance/token-balance.helper';
import { getImagesFromToken } from '~app-toolkit/helpers/presentation/image.present';
import { getImagesFromToken, getLabelFromToken } from '~app-toolkit/helpers/presentation/image.present';
import { ContractType } from '~position/contract.interface';
import { WithMetaType } from '~position/display.interface';
import { BaseTokenBalance } from '~position/position-balance.interface';
import { PositionFetcher } from '~position/position-fetcher.interface';
import { ContractPosition } from '~position/position.interface';
import { BaseToken } from '~position/token.interface';
import { claimable, supplied } from '~position/position.utils';
import { Network } from '~types/network.interface';

import { getPairs, getPositions } from '../helpers/graph';
import { sortTokens } from '../helpers/tokens';
import { getPositions } from '../helpers/graph';
import { MEAN_FINANCE_DEFINITION } from '../mean-finance.definition';

const appId = MEAN_FINANCE_DEFINITION.id;
const groupId = MEAN_FINANCE_DEFINITION.groups.dcaPosition.id;
const network = Network.OPTIMISM_MAINNET;

interface ExtendedContractPosition extends ContractPosition {
tokenA?: BaseToken;
tokenB?: BaseToken;
tokenALiquidity: BigNumber;
tokenBLiquidity: BigNumber;
positions: number;
id: string;
}
type MeanFinanceDcaPositionContractPositionDataProps = {
liquidity: number;
from: string;
to: string;
};

@Register.ContractPositionFetcher({ appId, groupId, network })
export class OptimismMeanFinanceDcaPositionContractPositionFetcher implements PositionFetcher<ContractPosition> {
constructor(@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit) { }
constructor(@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit) {}

async getPositions() {
const dcaHubAddress = '0x059d306a25c4ce8d7437d25743a8b94520536bd5';
const graphHelper = this.appToolkit.helpers.theGraphHelper;
const positionsData = await getPositions(network, graphHelper);
const pairsData = await getPairs(network, graphHelper);
const baseTokens = await this.appToolkit.getBaseTokenPrices(network);
const pairs = pairsData.pairs;
const positions = positionsData.positions;
const dcaHubAddress = '0x059d306a25c4ce8d7437d25743a8b94520536bd5';

const contractPositionsByKey: Record<string, ExtendedContractPosition> = keyBy(pairs.map(pair => {
const tokenA = baseTokens.find(v => v.address === pair.tokenA.address);
const tokenB = baseTokens.find(v => v.address === pair.tokenB.address);

let images: string[] = [];

if (tokenA) {
tokenA.network = network;
images = [...images, ...getImagesFromToken(tokenA)];
}
if (tokenB) {
tokenB.network = network;
images = [...images, ...getImagesFromToken(tokenB)];
}
const position: ExtendedContractPosition = {
const maybePositions = positions.map(dcaPosition => {
const from = baseTokens.find(v => v.address === dcaPosition.from.address.toLowerCase());
const to = baseTokens.find(v => v.address === dcaPosition.to.address.toLowerCase());
if (!from || !to) return null;

const tokens = [supplied(from), claimable(to)];
const liquidityToSwapRaw = dcaPosition.current.remainingLiquidity;
const liquidityToWithdrawRaw = dcaPosition.current.idleSwapped;
const liquidityToSwap = (Number(liquidityToSwapRaw) / 10 ** from.decimals) * from.price;
const liquidityToWithdraw = (Number(liquidityToWithdrawRaw) / 10 ** to.decimals) * to.price;
const liquidity = liquidityToSwap + liquidityToWithdraw;

const label = `${getLabelFromToken(from)} to ${getLabelFromToken(to)}`;
const images = [...getImagesFromToken(from), ...getImagesFromToken(to)];

const position: ContractPosition<MeanFinanceDcaPositionContractPositionDataProps> = {
type: ContractType.POSITION,
address: dcaHubAddress,
appId,
groupId,
appId: MEAN_FINANCE_DEFINITION.id,
groupId: MEAN_FINANCE_DEFINITION.groups.dcaPosition.id,
network,
tokens: [],
id: pair.id,
tokenA,
tokenB,
tokenALiquidity: BigNumber.from('0'),
tokenBLiquidity: BigNumber.from('0'),
positions: 0,
tokens,
dataProps: {
id: pair.id,
from: from.address,
to: to.address,
liquidity,
},
displayProps: {
label: `${pair.tokenA.symbol}:${pair.tokenB.symbol} pair`,
label,
images,
},
};

position.key = this.appToolkit.getPositionKey(position, ['id']);
return position;
}), 'id');

positions.forEach(dcaPosition => {
const [tokenAAddress, tokenBAddress] = sortTokens(dcaPosition.from.address, dcaPosition.to.address);

const toWithdraw = dcaPosition.current.idleSwapped;
const remainingLiquidity = dcaPosition.current.remainingLiquidity;

contractPositionsByKey[`${tokenAAddress}-${tokenBAddress}`].positions += 1;

if (dcaPosition.from.address === tokenAAddress) {
contractPositionsByKey[`${tokenAAddress}-${tokenBAddress}`].tokenALiquidity = contractPositionsByKey[`${tokenAAddress}-${tokenBAddress}`].tokenALiquidity.add(BigNumber.from(remainingLiquidity));
} else {
contractPositionsByKey[`${tokenAAddress}-${tokenBAddress}`].tokenBLiquidity = contractPositionsByKey[`${tokenAAddress}-${tokenBAddress}`].tokenBLiquidity.add(BigNumber.from(remainingLiquidity));
}
if (dcaPosition.to.address === tokenAAddress) {
contractPositionsByKey[`${tokenAAddress}-${tokenBAddress}`].tokenALiquidity = contractPositionsByKey[`${tokenAAddress}-${tokenBAddress}`].tokenALiquidity.add(BigNumber.from(toWithdraw));
} else {
contractPositionsByKey[`${tokenAAddress}-${tokenBAddress}`].tokenBLiquidity = contractPositionsByKey[`${tokenAAddress}-${tokenBAddress}`].tokenBLiquidity.add(BigNumber.from(toWithdraw));
}
});

const contractPositions: ContractPosition[] = Object.values(contractPositionsByKey).map(position => {
const tokens: WithMetaType<BaseTokenBalance>[] = [];

if (position.tokenA) {
tokens.push(drillBalance(position.tokenA, position.tokenALiquidity.toString()));
}
if (position.tokenB) {
tokens.push(drillBalance(position.tokenB, position.tokenBLiquidity.toString()));
}
const allPositions = compact(maybePositions);
const groupedPositionsRecord = groupBy(allPositions, v => `${v.dataProps.from}:${v.dataProps.to}`);
const groupedPositions = values(groupedPositionsRecord);

const balanceUSD = sumBy(tokens, t => t.balanceUSD);
const mergedPositions = groupedPositions.map(positionsForDirectionalPair => {
const totalLiquidity = sumBy(positionsForDirectionalPair, v => v.dataProps.liquidity);

return {
const anyPosition = positionsForDirectionalPair[0];
const mergedPosition: ContractPosition<MeanFinanceDcaPositionContractPositionDataProps> = {
type: ContractType.POSITION,
address: dcaHubAddress,
appId,
groupId,
appId: MEAN_FINANCE_DEFINITION.id,
groupId: MEAN_FINANCE_DEFINITION.groups.dcaPosition.id,
network,
tokens,
tokens: anyPosition.tokens,
dataProps: {
id: position.dataProps.id,
liquidity: balanceUSD,
tokenALiquidity: position.tokenALiquidity.toString(),
tokenBLiquidity: position.tokenBLiquidity.toString(),
from: anyPosition.dataProps.from,
to: anyPosition.dataProps.to,
liquidity: totalLiquidity,
},
displayProps: {
...position.displayProps,
secondaryLabel: `${position.positions} active positions`
label: anyPosition.displayProps.label,
secondaryLabel: `${positionsForDirectionalPair.length} active positions`,
images: anyPosition.displayProps.images,
},
}
};

return mergedPosition;
});

return contractPositions;
return mergedPositions;
}
}

0 comments on commit 016c187

Please sign in to comment.