Skip to content

Commit

Permalink
Pw/refinance-portfolio-support-fix (#3941)
Browse files Browse the repository at this point in the history
* removed LUSD from emode stablecoin tokens list

* wip

* Added Morpho support

* Debug cleanup

* wip

* cleanup

* Fixed review comments

* Fixed
  • Loading branch information
piotrwitek authored Jun 10, 2024
1 parent 12334c4 commit 7c109f3
Show file tree
Hide file tree
Showing 18 changed files with 290 additions and 46 deletions.
8 changes: 3 additions & 5 deletions components/portfolio/positions/PortfolioPositionBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,9 @@ export const PortfolioPositionBlock = ({ position }: { position: PortfolioPositi
},
}}
>
{position.availableToRefinance &&
isRefinanceEnabled &&
position.netValue >= emptyPortfolioPositionNetValueThreshold &&
// Position handler only supports Maker for now, we need to add support in other protocol handlers
position.protocol === LendingProtocol.Maker && (
{isRefinanceEnabled &&
position.availableToRefinance &&
position.netValue >= emptyPortfolioPositionNetValueThreshold && (
<RefinancePortfolioBanner position={position} />
)}
<AppLink href={position.url}>
Expand Down
2 changes: 1 addition & 1 deletion features/omni-kit/helpers/isShortPosition.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { stablecoinTokensUpperCase } from 'features/refinance/stablecoinTokensUpperCase'
import { stablecoinTokensUpperCase } from 'features/refinance/stablecoinTokens'

export function isShortPosition({ collateralToken }: { collateralToken: string }): boolean {
return stablecoinTokensUpperCase.includes(collateralToken.toUpperCase())
Expand Down
8 changes: 4 additions & 4 deletions features/refinance/components/RefinancePortfolioBanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@ export const RefinancePortfolioBanner: FC<RefinancePortfolioBannerProps> = ({ po
poolId,
positionId,
pairId,
collateral,
collateralAmount,
collateralPrice,
debt,
debtAmount,
debtPrice,
liquidationPrice,
ethPrice,
Expand Down Expand Up @@ -205,8 +205,8 @@ export const RefinancePortfolioBanner: FC<RefinancePortfolioBannerProps> = ({ po
network,
address: wallet?.address,
slippage: userSettingsData.slippage.toNumber(),
collateral,
debt,
collateralAmount,
debtAmount,
positionId,
liquidationPrice,
ltv,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const ethCorrelatedUpperCase = [
export const emodeEthCorrelatedTokensUpperCase = [
'AETHCBETH',
'AETHRETH',
'AETHWETH',
Expand Down
27 changes: 27 additions & 0 deletions features/refinance/emodeStablecoinTokens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export const emodeStablecoinTokensUpperCase = [
'ADAI',
'AETHDAI',
'AETHLUSD',
'AETHPYUSD',
'AETHSDAI',
'AETHUSDC',
'AETHUSDT',
'AUSDC',
'AUSDT',
'CDAI',
'CRVUSD',
'CUSDC',
'CUSDCV3',
'DAI',
'FRAX',
'GHO',
'GUSD',
'PYUSD',
'SDAI',
'SUSD',
'SUSDE',
'USDC.E',
'USDC',
'USDE',
'USDT',
]
12 changes: 6 additions & 6 deletions features/refinance/helpers/getEmode.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { EmodeType } from '@summer_fi/summerfi-sdk-client'
import type { IToken } from '@summer_fi/summerfi-sdk-common'
import { ethCorrelatedUpperCase } from 'features/refinance/ethCorrelatedUpperCase'
import { stablecoinTokensUpperCase } from 'features/refinance/stablecoinTokensUpperCase'
import { emodeEthCorrelatedTokensUpperCase } from 'features/refinance/emodeEthCorrelatedTokens'
import { emodeStablecoinTokensUpperCase } from 'features/refinance/emodeStablecoinTokens'

export function getEmode(collateralToken: IToken, debtToken: IToken) {
const collateralTokenSymbolUpperCase = collateralToken.symbol.toUpperCase()
const debtTokenSymbolUpperCase = debtToken.symbol.toUpperCase()

if (
stablecoinTokensUpperCase.includes(collateralTokenSymbolUpperCase) &&
stablecoinTokensUpperCase.includes(debtTokenSymbolUpperCase)
emodeStablecoinTokensUpperCase.includes(collateralTokenSymbolUpperCase) &&
emodeStablecoinTokensUpperCase.includes(debtTokenSymbolUpperCase)
) {
return EmodeType.Stablecoins
} else if (
ethCorrelatedUpperCase.includes(collateralTokenSymbolUpperCase) &&
ethCorrelatedUpperCase.includes(debtTokenSymbolUpperCase)
emodeEthCorrelatedTokensUpperCase.includes(collateralTokenSymbolUpperCase) &&
emodeEthCorrelatedTokensUpperCase.includes(debtTokenSymbolUpperCase)
) {
return EmodeType.ETHCorrelated
}
Expand Down
8 changes: 4 additions & 4 deletions features/refinance/helpers/getRefinanceContextInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ export const getRefinanceContextInput = ({
network,
address,
slippage,
collateral,
debt,
collateralAmount: collateral,
debtAmount: debt,
liquidationPrice,
ltv,
maxLtv,
Expand All @@ -58,8 +58,8 @@ export const getRefinanceContextInput = ({
network: NetworkNames
address?: string
slippage: number
collateral: string
debt: string
collateralAmount: string
debtAmount: string
liquidationPrice: string
ltv: string
maxLtv: string
Expand Down
6 changes: 3 additions & 3 deletions features/refinance/hooks/useAaveLikeRefinanceContextInputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,9 @@ export const useAaveLikeRefinanceContextInputs = ({
network,
address,
slippage,
collateral: collateralAmount,
debt: debtAmount,
positionId: positionId,
collateralAmount,
debtAmount,
positionId,
liquidationPrice,
ltv,
maxLtv,
Expand Down
4 changes: 2 additions & 2 deletions features/refinance/hooks/useMakerRefinanceContextInputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ export const useMakerRefinanceContextInputs = ({
network,
address,
slippage,
collateral: collateralAmount,
debt: debtAmount,
collateralAmount: collateralAmount,
debtAmount: debtAmount,
positionId,
liquidationPrice,
ltv,
Expand Down
6 changes: 3 additions & 3 deletions features/refinance/hooks/useMorphoRefinanceContextInputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,9 @@ export const useMorphoRefinanceContextInputs = ({
network,
address,
slippage,
collateral: collateralAmount,
debt: debtAmount,
positionId: positionId,
collateralAmount,
debtAmount,
positionId,
liquidationPrice,
ltv,
maxLtv,
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { RiskRatio } from '@oasisdex/dma-library'
import { getChainInfoByChainId } from '@summer_fi/summerfi-sdk-common'
import BigNumber from 'bignumber.js'
import { NetworkIds, type NetworkNames } from 'blockchain/networks'
import type { OmniProductType } from 'features/omni-kit/types'
import { getAaveLikePoolId, getAaveLikePositionId } from 'features/refinance/helpers'
import { getEmode } from 'features/refinance/helpers/getEmode'
import { mapTokenToSdkToken } from 'features/refinance/helpers/mapTokenToSdkToken'
import type { TokensPricesList } from 'handlers/portfolio/positions/helpers'
import type { DpmSubgraphData } from 'handlers/portfolio/positions/helpers/getAllDpmsForWallet'
import type { PortfolioPosition } from 'handlers/portfolio/types'
import { zero } from 'helpers/zero'
import type { LendingProtocol } from 'lendingProtocols'

export function getRawPositionDetails(
dpm: DpmSubgraphData,
calculations: {
collateral: BigNumber
debt: BigNumber
buyingPower: BigNumber
netValue: BigNumber
netValueInCollateralToken: BigNumber
netValueInDebtToken: BigNumber
totalExposure: BigNumber
netBorrowCostPercentage: BigNumber
collateralLiquidityRate: BigNumber
debtVariableBorrowRate: BigNumber
},
liquidationPrice: string,
primaryTokenPrice: BigNumber,
secondaryTokenPrice: BigNumber,
onChainPositionData: any,
commonData: {
positionId: string | number
type: OmniProductType
network: NetworkNames
protocol: LendingProtocol
primaryToken: string
secondaryToken: string
url: string
automations: {
autoBuy?: { enabled: boolean; price?: number | undefined } | undefined
autoSell?: { enabled: boolean; price?: number | undefined } | undefined
constantMultiple?: { enabled: boolean; price?: number | undefined } | undefined
stopLoss?: { enabled: boolean; price?: number | undefined } | undefined
takeProfit?: { enabled: boolean; price?: number | undefined } | undefined
}
availableToRefinance: boolean
},
lendingProtocol: LendingProtocol,
prices: TokensPricesList,
) {
const chainFamily = getChainInfoByChainId(dpm.networkId)
if (!chainFamily) {
throw new Error(`ChainId ${NetworkIds.MAINNET} is not supported`)
}
const collateral = calculations.collateral
const debt = calculations.debt
const collateralPrice = primaryTokenPrice.toString()
const debtPrice = secondaryTokenPrice.toString()

const riskRatio = new RiskRatio(
Number(collateral) > 0
? new BigNumber(debt).times(debtPrice).div(new BigNumber(collateral).times(collateralPrice))
: zero,
RiskRatio.TYPE.LTV,
)

const borrowRate = calculations.netBorrowCostPercentage
const maxRiskRatio = new RiskRatio(
onChainPositionData.category.maxLoanToValue,
RiskRatio.TYPE.LTV,
)

const collateralToken = mapTokenToSdkToken(chainFamily.chainInfo, commonData.primaryToken)
const debtToken = mapTokenToSdkToken(chainFamily.chainInfo, commonData.secondaryToken)
const emodeType = getEmode(collateralToken, debtToken)

const poolId = getAaveLikePoolId(
lendingProtocol,
chainFamily.chainInfo,
collateralToken,
debtToken,
emodeType,
)
const positionId = getAaveLikePositionId(lendingProtocol, dpm.vaultId)

const rawPositionDetails: PortfolioPosition['rawPositionDetails'] = {
collateralAmount: collateral.toString(),
debtAmount: debt.toString(),
collateralPrice,
debtPrice,
ethPrice: prices['ETH'].toString(),
liquidationPrice: liquidationPrice,
ltv: riskRatio.loanToValue.toString(),
maxLtv: maxRiskRatio.loanToValue.toString(),
borrowRate: borrowRate.toString(),
positionId,
poolId,
pairId: 1, // TODO: investigate what used for
}
return rawPositionDetails
}
1 change: 1 addition & 0 deletions handlers/portfolio/positions/handlers/aave-like/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ export const commonDataMapper = ({
}
: {}),
},
availableToRefinance: true,
},
primaryTokenPrice: primaryTokenOraclePrice || primaryTokenTickerPrice,
secondaryTokenPrice: secondaryTokenOraclePrice || secondaryTokenTickerPrice,
Expand Down
52 changes: 42 additions & 10 deletions handlers/portfolio/positions/handlers/aave-like/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import { zero } from 'helpers/zero'
import { isAaveLikeLendingProtocol, LendingProtocol } from 'lendingProtocols'
import { getAaveWstEthYield } from 'lendingProtocols/aave-v3/calculations/wstEthYield'

import { getRawPositionDetails } from './getRawPositionDetails'

const getAaveLikeBorrowPosition: GetAaveLikePositionHandlerType = async ({
dpm,
prices,
Expand Down Expand Up @@ -78,8 +80,25 @@ const getAaveLikeBorrowPosition: GetAaveLikePositionHandlerType = async ({
? `${commonData.secondaryToken}/${commonData.primaryToken}`
: `${commonData.primaryToken}/${commonData.secondaryToken}`

const liquidationPrice = isShort
? calculations.liquidationPriceInCollateral
: calculations.liquidationPriceInDebt

const rawPositionDetails = getRawPositionDetails(
dpm,
calculations,
liquidationPrice.toString(),
primaryTokenPrice,
secondaryTokenPrice,
onChainPositionData,
commonData,
commonData.protocol,
prices,
)

return {
...commonData,
rawPositionDetails,
details: [
{
type: 'collateralLocked',
Expand All @@ -91,9 +110,7 @@ const getAaveLikeBorrowPosition: GetAaveLikePositionHandlerType = async ({
},
{
type: 'liquidationPrice',
value: `${formatCryptoBalance(
isShort ? calculations.liquidationPriceInCollateral : calculations.liquidationPriceInDebt,
)} ${tokensLabel}`,
value: `${formatCryptoBalance(liquidationPrice)} ${tokensLabel}`,
subvalue: `Now ${formatCryptoBalance(
isShort
? secondaryTokenPrice.div(primaryTokenPrice)
Expand Down Expand Up @@ -138,7 +155,7 @@ const getAaveLikeMultiplyPosition: GetAaveLikePositionHandlerType = async ({
debug,
})

const protocol = commonData.protocol
const lendingProtocol = commonData.protocol

const [
primaryTokenReserveConfiguration,
Expand All @@ -153,7 +170,7 @@ const getAaveLikeMultiplyPosition: GetAaveLikePositionHandlerType = async ({
networkId: dpm.networkId,
collateralToken: commonData.primaryToken,
debtToken: commonData.secondaryToken,
protocol,
protocol: lendingProtocol,
proxyAddress: dpm.id.toLowerCase(),
}),
])
Expand All @@ -170,13 +187,13 @@ const getAaveLikeMultiplyPosition: GetAaveLikePositionHandlerType = async ({
RiskRatio.TYPE.LTV,
)

if (!isAaveLikeLendingProtocol(protocol)) {
if (!isAaveLikeLendingProtocol(lendingProtocol)) {
throw Error('Given protocol is not aave-like')
}

const positionHistory = getFilteredAaveLikePortfolioPositionHistory({
history: allPositionsHistory,
protocol,
protocol: lendingProtocol,
proxy: dpm.id,
})
const isShort = isShortPosition({ collateralToken: commonData.primaryToken })
Expand All @@ -202,8 +219,25 @@ const getAaveLikeMultiplyPosition: GetAaveLikePositionHandlerType = async ({
useDebtTokenAsPnL: isCorrelatedPosition(commonData.primaryToken, commonData.secondaryToken),
})

const liquidationPrice = isShort
? calculations.liquidationPriceInCollateral
: calculations.liquidationPriceInDebt

const rawPositionDetails = getRawPositionDetails(
dpm,
calculations,
liquidationPrice.toString(),
primaryTokenPrice,
secondaryTokenPrice,
onChainPositionData,
commonData,
lendingProtocol,
prices,
)

return {
...commonData,
rawPositionDetails,
details: [
{
type: 'netValue',
Expand All @@ -225,9 +259,7 @@ const getAaveLikeMultiplyPosition: GetAaveLikePositionHandlerType = async ({
},
{
type: 'liquidationPrice',
value: `${formatCryptoBalance(
isShort ? calculations.liquidationPriceInCollateral : calculations.liquidationPriceInDebt,
)} ${tokensLabel}`,
value: `${formatCryptoBalance(liquidationPrice)} ${tokensLabel}`,
subvalue: `Now ${formatCryptoBalance(
isShort
? secondaryTokenPrice.div(primaryTokenPrice)
Expand Down
Loading

0 comments on commit 7c109f3

Please sign in to comment.