Skip to content

Commit 8e958b8

Browse files
authored
Merge branch 'main' into feat/roll-mainnet-adapters-debt-and-repay
2 parents d994589 + 752adbd commit 8e958b8

File tree

10 files changed

+144
-4
lines changed

10 files changed

+144
-4
lines changed

public/icons/tokens/musd.svg

Lines changed: 1 addition & 0 deletions
Loading

src/components/transactions/Swap/errors/SwapErrors.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React, { Dispatch, useEffect } from 'react';
2+
import { useAppDataContext } from 'src/hooks/app-data-provider/useAppDataProvider';
23
import { useZeroLTVBlockingWithdraw } from 'src/hooks/useZeroLTVBlockingWithdraw';
34

45
import { useModalContext } from '../../../../hooks/useModal';
@@ -16,6 +17,10 @@ import {
1617
hasInsufficientBalance,
1718
InsufficientBalanceGuard,
1819
} from './shared/InsufficientBalanceGuard';
20+
import {
21+
hasInsufficientBorrowPower,
22+
InsufficientBorrowPowerBlockingGuard,
23+
} from './shared/InsufficientBorrowPowerBlockingGuard';
1924
import {
2025
hasInsufficientLiquidity,
2126
InsufficientLiquidityBlockingGuard,
@@ -37,6 +42,7 @@ export const SwapErrors = ({
3742
}) => {
3843
const { txError } = useModalContext();
3944
const assetsBlockingWithdraw = useZeroLTVBlockingWithdraw();
45+
const { user: extendedUser } = useAppDataContext();
4046

4147
useEffect(() => {
4248
if (txError) {
@@ -124,6 +130,21 @@ export const SwapErrors = ({
124130
);
125131
}
126132

133+
if (
134+
isProtocolSwapState(state) &&
135+
state.swapType === SwapType.DebtSwap &&
136+
(hasInsufficientBorrowPower(state, extendedUser?.availableBorrowsUSD) ||
137+
state.actionsBlocked?.[ActionsBlockedReason.INSUFFICIENT_BORROW_POWER])
138+
) {
139+
return (
140+
<InsufficientBorrowPowerBlockingGuard
141+
state={state}
142+
setState={setState}
143+
isSwapFlowSelected={state.isSwapFlowSelected}
144+
/>
145+
);
146+
}
147+
127148
if (!state.error) {
128149
return null;
129150
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Trans } from '@lingui/macro';
2+
import { SxProps, Typography } from '@mui/material';
3+
import { Warning } from 'src/components/primitives/Warning';
4+
5+
export const InsufficientBorrowPowerBlockingError = ({ sx }: { sx?: SxProps }) => {
6+
return (
7+
<Warning severity="error" sx={{ mt: 4, ...sx }} icon={false}>
8+
<Typography variant="caption">
9+
<Trans>
10+
Insufficient collateral to cover new borrow position. Wallet must have borrowing power
11+
remaining to perform debt switch.
12+
</Trans>
13+
</Typography>
14+
</Warning>
15+
);
16+
};
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import { SxProps } from '@mui/material';
2+
import { Dispatch, useEffect } from 'react';
3+
import { useAppDataContext } from 'src/hooks/app-data-provider/useAppDataProvider';
4+
5+
import {
6+
ActionsBlockedReason,
7+
ProtocolSwapState,
8+
SwapError,
9+
SwapState,
10+
SwapType,
11+
} from '../../types';
12+
import { InsufficientBorrowPowerBlockingError } from './InsufficientBorrowPowerBlockingError';
13+
14+
export const hasInsufficientBorrowPower = (state: SwapState, availableBorrowsUSD?: string) => {
15+
if (state.swapType !== SwapType.DebtSwap) return false;
16+
17+
const buyAmount = state.buyAmountFormatted;
18+
const sellAmount = state.sellAmountFormatted;
19+
const sourceReserve = state.sourceReserve?.reserve;
20+
const destinationReserve = state.destinationReserve?.reserve;
21+
if (!buyAmount || !sellAmount || !sourceReserve || !destinationReserve) return false;
22+
23+
const repayUsd = Number(buyAmount) * Number(sourceReserve.priceInUSD);
24+
const newDebtUsd = Number(sellAmount) * Number(destinationReserve.priceInUSD);
25+
const priceImpactDifference = newDebtUsd - repayUsd;
26+
27+
const available = Number(availableBorrowsUSD || '0');
28+
29+
return available === 0 || priceImpactDifference > available;
30+
};
31+
32+
export const InsufficientBorrowPowerBlockingGuard = ({
33+
state,
34+
setState,
35+
sx,
36+
isSwapFlowSelected,
37+
}: {
38+
state: ProtocolSwapState;
39+
setState: Dispatch<Partial<SwapState>>;
40+
sx?: SxProps;
41+
isSwapFlowSelected: boolean;
42+
}) => {
43+
const { user: extendedUser } = useAppDataContext();
44+
45+
useEffect(() => {
46+
const isBlocking = hasInsufficientBorrowPower(state, extendedUser?.availableBorrowsUSD);
47+
48+
if (isBlocking) {
49+
const isAlreadyBlockingError =
50+
state.error?.rawError instanceof Error &&
51+
state.error.rawError.message === 'InsufficientBorrowPowerError';
52+
53+
if (!isAlreadyBlockingError) {
54+
const blockingError: SwapError = {
55+
rawError: new Error('InsufficientBorrowPowerError'),
56+
message:
57+
'Insufficient collateral to cover new borrow position. Wallet must have borrowing power remaining to perform debt switch.',
58+
actionBlocked: true,
59+
};
60+
setState({
61+
error: blockingError,
62+
actionsBlocked: {
63+
[ActionsBlockedReason.INSUFFICIENT_BORROW_POWER]: true,
64+
},
65+
});
66+
}
67+
} else {
68+
const isBlockingError =
69+
state.error?.rawError instanceof Error &&
70+
state.error.rawError.message === 'InsufficientBorrowPowerError';
71+
const isBorrowPowerBlocked =
72+
state.actionsBlocked?.[ActionsBlockedReason.INSUFFICIENT_BORROW_POWER];
73+
if (isBlockingError || isBorrowPowerBlocked) {
74+
setState({
75+
...(isBlockingError ? { error: undefined } : {}),
76+
actionsBlocked: {
77+
[ActionsBlockedReason.INSUFFICIENT_BORROW_POWER]: undefined,
78+
},
79+
});
80+
}
81+
}
82+
}, [
83+
state.sellAmountFormatted,
84+
state.buyAmountFormatted,
85+
state.destinationReserve?.reserve?.priceInUSD,
86+
state.sourceReserve?.reserve?.priceInUSD,
87+
extendedUser?.availableBorrowsUSD,
88+
state.error,
89+
state.actionsBlocked,
90+
]);
91+
92+
if (hasInsufficientBorrowPower(state, extendedUser?.availableBorrowsUSD)) {
93+
return <InsufficientBorrowPowerBlockingError sx={{ mb: !isSwapFlowSelected ? 0 : 4, ...sx }} />;
94+
}
95+
96+
return null;
97+
};

src/components/transactions/Swap/types/state.types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export enum ActionsBlockedReason {
2525
INSUFFICIENT_LIQUIDITY = 'INSUFFICIENT_LIQUIDITY',
2626
FLASH_LOAN_DISABLED = 'FLASH_LOAN_DISABLED',
2727
IS_LIQUIDATABLE = 'IS_LIQUIDATABLE',
28+
INSUFFICIENT_BORROW_POWER = 'INSUFFICIENT_BORROW_POWER',
2829
}
2930

3031
/**

src/locales/el/messages.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/locales/en/messages.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/locales/en/messages.po

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3766,6 +3766,10 @@ msgstr "This asset is eligible for Kernel points incentive program. Aave Labs do
37663766
msgid "You have no rewards to claim at this time."
37673767
msgstr "You have no rewards to claim at this time."
37683768

3769+
#: src/components/transactions/Swap/errors/shared/InsufficientBorrowPowerBlockingError.tsx
3770+
msgid "Insufficient collateral to cover new borrow position. Wallet must have borrowing power remaining to perform debt switch."
3771+
msgstr "Insufficient collateral to cover new borrow position. Wallet must have borrowing power remaining to perform debt switch."
3772+
37693773
#: src/components/transactions/StakeRewardClaimRestake/StakeRewardClaimRestakeModalContent.tsx
37703774
msgid "Restaked"
37713775
msgstr "Restaked"

src/locales/es/messages.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/locales/fr/messages.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)