Skip to content

Commit

Permalink
Bugfix/liquidity withdraw (#729)
Browse files Browse the repository at this point in the history
* fix: using exchange in max withdraw

* fix: ntoken withdraw direction

* fix: liquidity withdraw issues
  • Loading branch information
jeffywu authored Apr 3, 2024
1 parent 26af288 commit 4c864a9
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ import { LiquidityContext } from '../../liquidity';
import { ErrorMessage } from '@notional-finance/mui';
import { useQueryParams } from '@notional-finance/notionable-hooks';
import { TABLE_WARNINGS } from '@notional-finance/util';
import { DepositInput, TransactionSidebar } from '@notional-finance/trade';
import {
DepositInput,
TransactionSidebar,
useMaxLiquidityWithdraw,
} from '@notional-finance/trade';
import { defineMessage, FormattedMessage, defineMessages } from 'react-intl';
import { LiquidityDetailsTable } from '../components/liquidity-details-table';
import { useMaxLiquidityWithdraw } from '../hooks/use-max-liquidity-withdraw';

const messages = {
[TABLE_WARNINGS.HIGH_UTILIZATION_NTOKEN]: defineMessages({
Expand All @@ -31,7 +34,7 @@ export const Withdraw = () => {
const context = useContext(LiquidityContext);
const search = useQueryParams();
const warning = search.get('warning') as TABLE_WARNINGS | undefined;
const { currencyInputRef, onMaxValue, maxWithdraw } =
const { currencyInputRef, onMaxValue, maxWithdrawUnderlying } =
useMaxLiquidityWithdraw(context);

return (
Expand All @@ -50,7 +53,7 @@ export const Withdraw = () => {
ref={currencyInputRef}
context={context}
inputRef={currencyInputRef}
maxWithdraw={maxWithdraw}
maxWithdraw={maxWithdrawUnderlying}
onMaxValue={onMaxValue}
inputLabel={defineMessage({
defaultMessage: 'Enter amount to withdraw',
Expand Down
14 changes: 14 additions & 0 deletions packages/shared/notionable-hooks/src/use-market.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
Registry,
TokenBalance,
TokenDefinition,
YieldData,
} from '@notional-finance/core-entities';
Expand All @@ -11,6 +12,7 @@ import {
} from '@notional-finance/util';
import { useCallback, useMemo } from 'react';
import { useNotionalContext } from './use-notional';
import { exchangeToLocalPrime } from '@notional-finance/transaction';

export interface MaturityData {
token: TokenDefinition;
Expand Down Expand Up @@ -327,3 +329,15 @@ export const useSpotMaturityData = (
);
}, [tokens, nonLeveragedYields]);
};

export function useTradedValue(amount: TokenBalance | undefined) {
const fCashMarket = useFCashMarket(amount?.token);
const primeCash = usePrimeCash(amount?.network, amount?.currencyId);
return primeCash && fCashMarket
? exchangeToLocalPrime(
amount,
fCashMarket,
primeCash
).localPrime.toUnderlying()
: undefined;
}
15 changes: 1 addition & 14 deletions packages/shared/notionable-hooks/src/use-summary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -411,11 +411,8 @@ export function useTradeSummary(state: VaultTradeState | TradeState) {
tradeType,
inputsSatisfied,
calculationSuccess,
maxWithdraw,
debtFee,
collateralFee,
} = state;
let depositBalance = _d;
const depositBalance = _d;

// TODO: if underlying is not all the same the convert to fiat currency instead
const underlying =
Expand Down Expand Up @@ -594,16 +591,6 @@ export function useTradeSummary(state: VaultTradeState | TradeState) {

if (tradeType === 'RollVaultPosition') {
// No-Op: value is set above
} else if (
tradeType === 'DeleverageWithdraw' &&
maxWithdraw &&
debtFee &&
collateralFee
) {
// The deposit balance is slightly incorrect when calculating deleverage withdraw
// because we do not account for slippage and fees when we trigger a max withdraw
feeValue = debtFee.toUnderlying().add(collateralFee.toUnderlying()).neg();
depositBalance = depositBalance?.sub(feeValue);
} else if (isLeverageOrRoll) {
// Do not include roll vault position because the margin will be
// incorrectly included in the fee value
Expand Down
1 change: 1 addition & 0 deletions packages/shared/trade/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ export * from './use-variable-totals';
export * from './use-interest-rate-utilization-chart';
export * from './use-max-repay';
export * from './use-max-withdraw';
export * from './use-max-liquidity-withdraw';
export * from './use-max-yield';
export * from './use-leveraged-ntoken-positions';
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useCurrencyInputRef } from '@notional-finance/mui';
import {
BaseTradeContext,
usePortfolioRiskProfile,
useTradedValue,
} from '@notional-finance/notionable-hooks';
import { useCallback } from 'react';

Expand All @@ -16,31 +17,39 @@ export function useMaxLiquidityWithdraw(context: BaseTradeContext) {

// NOTE: this will show a liquidation risk error if the PNL on the liquidity
// is being used to collateralize some other debt.
const maxWithdraw =
nTokenBalance && maxRepayBalance
? nTokenBalance.toUnderlying().add(maxRepayBalance.toUnderlying())
const maxNTokenUnderlying = useTradedValue(nTokenBalance?.neg());
// useTradedValue always returns a positive number
const maxRepayUnderlying = useTradedValue(maxRepayBalance?.neg());
const maxWithdrawUnderlying =
maxNTokenUnderlying && maxRepayUnderlying
? maxNTokenUnderlying.sub(maxRepayUnderlying)
: undefined;
const { setCurrencyInput, currencyInputRef } = useCurrencyInputRef();

const onMaxValue = useCallback(() => {
if (maxWithdraw) {
setCurrencyInput(maxWithdraw?.toUnderlying().toExactString(), false);
if (maxWithdrawUnderlying) {
setCurrencyInput(maxWithdrawUnderlying?.toExactString(), false);

updateState({
maxWithdraw: true,
calculationSuccess: true,
depositBalance: maxWithdraw.toUnderlying().neg(),
depositBalance: maxWithdrawUnderlying.neg(),
collateralBalance: maxRepayBalance?.neg(),
debtBalance: nTokenBalance?.neg(),
});
}
}, [
maxWithdrawUnderlying,
maxRepayBalance,
nTokenBalance,
maxWithdraw,
setCurrencyInput,
updateState,
]);

return { onMaxValue, currencyInputRef, setCurrencyInput, maxWithdraw };
return {
onMaxValue,
currencyInputRef,
setCurrencyInput,
maxWithdrawUnderlying,
};
}
11 changes: 7 additions & 4 deletions packages/shared/trade/src/hooks/use-max-withdraw.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
BaseTradeContext,
usePortfolioRiskProfile,
usePrimeCash,
useTradedValue,
} from '@notional-finance/notionable-hooks';
import { useCallback } from 'react';

Expand All @@ -11,11 +12,13 @@ export function useMaxWithdraw(context: BaseTradeContext) {
const { debt, selectedNetwork } = state;
const profile = usePortfolioRiskProfile(selectedNetwork);
const primeCash = usePrimeCash(debt?.network, debt?.currencyId);
const { setCurrencyInput, currencyInputRef } = useCurrencyInputRef();

const withdrawToken = debt?.tokenType === 'PrimeDebt' ? primeCash : debt;
const maxWithdraw = withdrawToken
? profile?.maxWithdraw(withdrawToken)
: undefined;
const { setCurrencyInput, currencyInputRef } = useCurrencyInputRef();
const maxWithdrawUnderlying = useTradedValue(maxWithdraw?.neg());

const onMaxValue = useCallback(() => {
if (maxWithdraw) {
Expand All @@ -24,19 +27,19 @@ export function useMaxWithdraw(context: BaseTradeContext) {
updateState({
maxWithdraw: true,
calculationSuccess: true,
depositBalance: maxWithdraw.toUnderlying().neg(),
depositBalance: maxWithdrawUnderlying?.neg(),
debtBalance:
debt?.tokenType === 'PrimeDebt'
? maxWithdraw.toToken(debt).neg()
: maxWithdraw.neg(),
});
}
}, [maxWithdraw, updateState, setCurrencyInput, debt]);
}, [maxWithdraw, updateState, setCurrencyInput, debt, maxWithdrawUnderlying]);

return {
onMaxValue,
currencyInputRef,
setCurrencyInput,
maxWithdrawUnderlying: maxWithdraw?.toUnderlying(),
maxWithdrawUnderlying,
};
}

0 comments on commit 4c864a9

Please sign in to comment.