Skip to content

Commit 823090c

Browse files
authored
Merge pull request #1762 from balancednetwork/fix/fix-network-issues
Fix collateral handling after governance
2 parents 9cdf88e + 770b43b commit 823090c

12 files changed

Lines changed: 744 additions & 72 deletions

File tree

‎apps/web/src/app/components/home/CollateralPanel.tsx‎

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,12 @@ import { useICXUnstakingTime } from '@/store/application/hooks';
2929
import {
3030
useCollateralActionHandlers,
3131
useCollateralState,
32+
useCollateralTokens,
3233
useDerivedCollateralInfo,
3334
useIsHandlingICX,
3435
useSupportedCollateralTokens,
3536
} from '@/store/collateral/hooks';
37+
import { getActionMaximum, isCollateralEnabled, isIncreaseAllowed } from '@/store/collateral/eligibility';
3638
import { Field } from '@/store/collateral/reducer';
3739
import { useLoanActionHandlers, useLockedCollateralAmount } from '@/store/loan/hooks';
3840
import { useRatio } from '@/store/ratio/hooks';
@@ -150,7 +152,12 @@ const CollateralPanel = () => {
150152
const { isAdjusting, inputType } = useCollateralState();
151153
const ratio = useRatio();
152154
const isHandlingICX = useIsHandlingICX();
155+
const { data: collateralTokens } = useCollateralTokens();
153156
const { data: supportedCollateralTokens } = useSupportedCollateralTokens();
157+
const contractSymbol = useWrongSymbol(collateralType);
158+
const increaseEnabled = isCollateralEnabled(supportedCollateralTokens, contractSymbol);
159+
const actionMaximum = getActionMaximum(collateralDeposit, collateralTotal, increaseEnabled);
160+
const canAdjustCollateral = increaseEnabled || collateralDeposit.isGreaterThan(0);
154161
const [ICXWithdrawOption, setICXWithdrawOption] = useState<ICXWithdrawOptions>(ICXWithdrawOptions.KEEPSICX);
155162
const { data: icxUnstakingTime } = useICXUnstakingTime();
156163
const isSuperSmall = useMedia(`(max-width: 359px)`);
@@ -177,6 +184,7 @@ const CollateralPanel = () => {
177184
});
178185

179186
const handleEnableAdjusting = () => {
187+
if (!canAdjustCollateral) return;
180188
adjust(true);
181189
adjustLoan(false);
182190
};
@@ -193,6 +201,11 @@ const CollateralPanel = () => {
193201
const isCrossChain = !(sourceChain === '0x1.icon' || sourceChain === '0x2.icon');
194202

195203
const toggleOpen = () => {
204+
if (open) {
205+
setOpen(false);
206+
return;
207+
}
208+
if (!isIncreaseAllowed(collateralDeposit, parsedAmount[Field.LEFT], increaseEnabled)) return;
196209
if (isCrossChain) {
197210
setStoredModalValues({
198211
amount: `${differenceAmount.dp(collateralDecimalPlaces).toFormat()} ${formatSymbol(collateralType)}`,
@@ -209,10 +222,12 @@ const CollateralPanel = () => {
209222
const addTransaction = useTransactionAdder();
210223

211224
const handleCollateralConfirm = async () => {
225+
if (shouldDeposit && !increaseEnabled) return;
226+
const collateralTokenAddress = collateralTokens?.[contractSymbol];
227+
if (!collateralTokenAddress) return;
228+
212229
window.addEventListener('beforeunload', showMessageOnBeforeUnload);
213-
const collateralTokenAddress =
214-
supportedCollateralTokens && supportedCollateralTokens[useWrongSymbol(collateralType)];
215-
const cx = bnJs.inject({ account }).getContract(collateralTokenAddress!);
230+
const cx = bnJs.inject({ account }).getContract(collateralTokenAddress);
216231
const decimals: string = await cx.decimals();
217232

218233
if (shouldDeposit) {
@@ -356,8 +371,8 @@ const CollateralPanel = () => {
356371

357372
// add small amount of collateral to lock to avoid tx errors.
358373
const tLockedAmount = React.useMemo(
359-
() => BigNumber.min(lockedCollateral.times(shouldShowLock ? 1.005 : 1), collateralTotal),
360-
[lockedCollateral, collateralTotal, shouldShowLock],
374+
() => BigNumber.min(lockedCollateral.times(shouldShowLock ? 1.005 : 1), actionMaximum),
375+
[lockedCollateral, actionMaximum, shouldShowLock],
361376
);
362377

363378
const percent = collateralTotal.isZero() ? 0 : tLockedAmount.div(collateralTotal).times(100).toNumber();
@@ -391,7 +406,7 @@ const CollateralPanel = () => {
391406
<CollateralTypeSwitcher width={width} containerRef={ref.current} />
392407
</CollateralTypeSwitcherWrap>
393408

394-
{account && collateralTotal?.isGreaterThan(0) && (
409+
{account && collateralTotal?.isGreaterThan(0) && canAdjustCollateral && (
395410
<Flex flexDirection={isSuperSmall ? 'column' : 'row'} ml="auto" paddingTop={isSuperSmall ? '4px' : '0'}>
396411
{isAdjusting ? (
397412
<>
@@ -403,7 +418,11 @@ const CollateralPanel = () => {
403418
>
404419
<Trans>Cancel</Trans>
405420
</TextButton>
406-
<Button onClick={toggleOpen} fontSize={14} disabled={!isSliderStateChanged}>
421+
<Button
422+
onClick={toggleOpen}
423+
fontSize={14}
424+
disabled={!isSliderStateChanged || (shouldDeposit && !increaseEnabled)}
425+
>
407426
<Trans>Confirm</Trans>
408427
</Button>
409428
</>
@@ -451,9 +470,9 @@ const CollateralPanel = () => {
451470
range={{
452471
min: [0],
453472
max: [
454-
collateralTotal.isZero()
473+
actionMaximum.isZero()
455474
? SLIDER_RANGE_MAX_BOTTOM_THRESHOLD
456-
: collateralTotal.dp(collateralDecimalPlaces).toNumber(),
475+
: actionMaximum.dp(collateralDecimalPlaces).toNumber(),
457476
],
458477
}}
459478
instanceRef={instance => {
@@ -475,14 +494,14 @@ const CollateralPanel = () => {
475494
value={formattedAmounts[Field.LEFT]}
476495
decimalPlaces={collateralDecimalPlaces}
477496
currency={isHandlingICX ? 'ICX' : formatSymbol(collateralType)}
478-
maxValue={collateralTotal}
497+
maxValue={actionMaximum}
479498
onUserInput={onFieldAInput}
480499
/>
481500
</PanelInfoItem>
482501

483502
<PanelInfoItem>
484503
<CurrencyField
485-
editable={isAdjusting}
504+
editable={isAdjusting && increaseEnabled}
486505
isActive={false}
487506
label="Wallet"
488507
tooltipText={
@@ -510,6 +529,7 @@ const CollateralPanel = () => {
510529
<XCollateralModal
511530
account={account}
512531
currencyAmount={xTokenAmount}
532+
increaseEnabled={increaseEnabled}
513533
sourceChain={sourceChain}
514534
storedModalValues={storedModalValues}
515535
/>
@@ -617,7 +637,9 @@ const CollateralPanel = () => {
617637
onClick={handleCollateralConfirm}
618638
fontSize={14}
619639
disabled={
620-
!hasEnoughICX || (isHandlingICX && !shouldDeposit && ICXWithdrawOption === ICXWithdrawOptions.EMPTY)
640+
!hasEnoughICX ||
641+
(shouldDeposit && !increaseEnabled) ||
642+
(isHandlingICX && !shouldDeposit && ICXWithdrawOption === ICXWithdrawOptions.EMPTY)
621643
}
622644
>
623645
{shouldDeposit ? t`Deposit` : t`Withdraw`}

‎apps/web/src/app/components/home/LoanPanel.tsx‎

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ import { Typography } from '@/app/theme';
1414
import { SLIDER_RANGE_MAX_BOTTOM_THRESHOLD } from '@/constants/index';
1515
import { useActiveLocale } from '@/hooks/useActiveLocale';
1616
import useInterval from '@/hooks/useInterval';
17-
import { useCollateralActionHandlers, useDerivedCollateralInfo } from '@/store/collateral/hooks';
17+
import {
18+
useCollateralActionHandlers,
19+
useDerivedCollateralInfo,
20+
useSupportedCollateralTokens,
21+
} from '@/store/collateral/hooks';
22+
import { getActionMaximum, isCollateralEnabled, isIncreaseAllowed } from '@/store/collateral/eligibility';
1823
import {
1924
useActiveLoanAddress,
2025
useDerivedLoanInfo,
@@ -56,6 +61,10 @@ const LoanPanel = () => {
5661
totalBorrowableAmount,
5762
bnUSDAmount,
5863
} = useDerivedLoanInfo();
64+
const { data: supportedCollateralTokens } = useSupportedCollateralTokens();
65+
const increaseEnabled = isCollateralEnabled(supportedCollateralTokens, useWrongSymbol(collateralType));
66+
const actionMaximum = getActionMaximum(borrowedAmount, borrowableAmountWithReserve, increaseEnabled);
67+
const canAdjustLoan = increaseEnabled || borrowedAmount.isGreaterThan(0);
5968

6069
const { isAdjusting, inputType } = useLoanState();
6170

@@ -95,6 +104,7 @@ const LoanPanel = () => {
95104
const addTransaction = useTransactionAdder();
96105

97106
const handleEnableAdjusting = () => {
107+
if (!canAdjustLoan) return;
98108
adjust(true);
99109
adjustCollateral(false);
100110
};
@@ -124,6 +134,11 @@ const LoanPanel = () => {
124134
(loanNetwork !== ICON_XCALL_NETWORK_ID || sourceChain !== ICON_XCALL_NETWORK_ID);
125135

126136
const toggleOpen = () => {
137+
if (open) {
138+
setOpen(false);
139+
return;
140+
}
141+
if (!isIncreaseAllowed(borrowedAmount, parsedAmount[Field.LEFT], increaseEnabled)) return;
127142
if (isCrossChain) {
128143
setStoredModalValues({
129144
amount: roundedDisplayDiffAmount.dp(2).toFormat(),
@@ -139,6 +154,7 @@ const LoanPanel = () => {
139154
};
140155

141156
const handleLoanConfirm = () => {
157+
if (shouldBorrow && !increaseEnabled) return;
142158
if (!iconAccount) return;
143159
window.addEventListener('beforeunload', showMessageOnBeforeUnload);
144160

@@ -261,7 +277,7 @@ const LoanPanel = () => {
261277
<Typography variant="h2">
262278
<Trans>Loan</Trans>
263279
</Typography>
264-
{account && (
280+
{account && canAdjustLoan && (
265281
<Flex flexDirection={isSuperSmall ? 'column' : 'row'} paddingTop={isSuperSmall ? '4px' : '0'}>
266282
{isAdjusting ? (
267283
<>
@@ -276,6 +292,7 @@ const LoanPanel = () => {
276292
<Button
277293
disabled={
278294
!isSliderStateChanged ||
295+
(shouldBorrow && !increaseEnabled) ||
279296
(borrowedAmount.isLessThanOrEqualTo(0)
280297
? currentValue >= 0 && currentValue < 10
281298
: currentValue < 0)
@@ -311,10 +328,9 @@ const LoanPanel = () => {
311328
min: [0],
312329
// https://github.com/balancednetwork/balanced-network-interface/issues/50
313330
max: [
314-
Number.isNaN(borrowableAmountWithReserve.dp(2).toNumber()) ||
315-
borrowableAmountWithReserve.dp(2).isZero()
331+
Number.isNaN(borrowableAmountWithReserve.dp(2).toNumber()) || actionMaximum.dp(2).isZero()
316332
? SLIDER_RANGE_MAX_BOTTOM_THRESHOLD
317-
: borrowableAmountWithReserve.dp(2).toNumber(),
333+
: actionMaximum.dp(2).toNumber(),
318334
],
319335
}}
320336
instanceRef={instance => {
@@ -337,6 +353,7 @@ const LoanPanel = () => {
337353
noticeText={'10 bnUSD minimum'}
338354
value={formattedAmounts[Field.LEFT]}
339355
currency={'bnUSD'}
356+
maxValue={actionMaximum}
340357
onUserInput={onFieldAInput}
341358
/>
342359
) : (
@@ -347,14 +364,15 @@ const LoanPanel = () => {
347364
tooltipText="Your collateral balance. It earns interest from staking, but is also sold over time to repay your loan."
348365
value={formattedAmounts[Field.LEFT]}
349366
currency={'bnUSD'}
367+
maxValue={actionMaximum}
350368
onUserInput={onFieldAInput}
351369
/>
352370
)}
353371
</PanelInfoItem>
354372

355373
<PanelInfoItem>
356374
<CurrencyField
357-
editable={isAdjusting}
375+
editable={isAdjusting && increaseEnabled}
358376
isActive={false}
359377
label="Available"
360378
tooltipText="The amount of ICX available to deposit from your wallet."
@@ -375,6 +393,7 @@ const LoanPanel = () => {
375393
<XLoanModal
376394
collateralAccount={account}
377395
bnUSDAmount={bnUSDAmount}
396+
increaseEnabled={increaseEnabled}
378397
sourceChain={sourceChain}
379398
interestRate={interestRate}
380399
storedModalValues={storedModalValues}
@@ -430,7 +449,11 @@ const LoanPanel = () => {
430449
<TextButton onClick={toggleOpen} fontSize={14}>
431450
<Trans>Cancel</Trans>
432451
</TextButton>
433-
<Button disabled={!hasEnoughICX} onClick={handleLoanConfirm} fontSize={14}>
452+
<Button
453+
disabled={!hasEnoughICX || (shouldBorrow && !increaseEnabled)}
454+
onClick={handleLoanConfirm}
455+
fontSize={14}
456+
>
434457
<Trans>{shouldBorrow ? t`Borrow` : t`Repay`}</Trans>
435458
</Button>
436459
</Flex>

‎apps/web/src/app/components/home/_components/xCollateralModal/index.tsx‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export enum XCollateralAction {
3434
type XCollateralModalProps = {
3535
modalId?: MODAL_ID;
3636
account: string | undefined;
37+
increaseEnabled: boolean;
3738
sourceChain: XChainId;
3839
storedModalValues: {
3940
amount: string;
@@ -48,6 +49,7 @@ const XCollateralModal = ({
4849
modalId = MODAL_ID.XCOLLATERAL_CONFIRM_MODAL,
4950
account,
5051
currencyAmount,
52+
increaseEnabled,
5153
sourceChain,
5254
storedModalValues,
5355
}: XCollateralModalProps) => {
@@ -102,6 +104,7 @@ const XCollateralModal = ({
102104

103105
const sendXTransaction = useSendXTransaction();
104106
const handleXCollateralAction = async () => {
107+
if (storedModalValues.action === XCollateralAction.DEPOSIT && !increaseEnabled) return;
105108
if (!account) return;
106109
if (!xCallFee) return;
107110
if (!_inputAmount) return;
@@ -140,6 +143,7 @@ const XCollateralModal = ({
140143

141144
useLoanWalletServiceHandler();
142145
const { isWrongChain, handleSwitchChain } = useEvmSwitchChain(sourceChain);
146+
const increaseDisabled = storedModalValues.action === XCollateralAction.DEPOSIT && !increaseEnabled;
143147

144148
return (
145149
<>
@@ -216,7 +220,10 @@ const XCollateralModal = ({
216220
) : (
217221
<>
218222
{approvalState !== ApprovalState.APPROVED ? (
219-
<Button onClick={approveCallback} disabled={approvalState === ApprovalState.PENDING}>
223+
<Button
224+
onClick={approveCallback}
225+
disabled={approvalState === ApprovalState.PENDING || increaseDisabled}
226+
>
220227
{approvalState === ApprovalState.PENDING ? (
221228
<Trans>Approving</Trans>
222229
) : (
@@ -226,7 +233,7 @@ const XCollateralModal = ({
226233
) : (
227234
<StyledButton
228235
onClick={handleXCollateralAction}
229-
disabled={!gasChecker.hasEnoughGas || isWalletPrompting}
236+
disabled={!gasChecker.hasEnoughGas || isWalletPrompting || increaseDisabled}
230237
>
231238
{isWalletPrompting ? (
232239
<Trans>Waiting for wallet...</Trans>

‎apps/web/src/app/components/home/_components/xLoanModal/index.tsx‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export enum XLoanAction {
3636
type XLoanModalProps = {
3737
modalId?: MODAL_ID;
3838
collateralAccount: string | undefined;
39+
increaseEnabled: boolean;
3940
sourceChain: XChainId;
4041
storedModalValues: {
4142
amount: string;
@@ -52,6 +53,7 @@ const XLoanModal = ({
5253
modalId = MODAL_ID.XLOAN_CONFIRM_MODAL,
5354
collateralAccount,
5455
bnUSDAmount,
56+
increaseEnabled,
5557
sourceChain,
5658
interestRate,
5759
storedModalValues,
@@ -116,6 +118,7 @@ const XLoanModal = ({
116118

117119
const sendXTransaction = useSendXTransaction();
118120
const handleXLoanAction = async () => {
121+
if (storedModalValues.action === XLoanAction.BORROW && !increaseEnabled) return;
119122
if (!collateralAccount) return;
120123
if (!loanNetworkAddress) return;
121124
if (!xCallFee) return;
@@ -147,6 +150,7 @@ const XLoanModal = ({
147150
const gasChecker = useXCallGasChecker(activeChain, _inputAmount);
148151

149152
const { isWrongChain, handleSwitchChain } = useEvmSwitchChain(activeChain);
153+
const increaseDisabled = storedModalValues.action === XLoanAction.BORROW && !increaseEnabled;
150154

151155
return (
152156
<>
@@ -247,7 +251,7 @@ const XLoanModal = ({
247251
) : (
248252
<StyledButton
249253
onClick={handleXLoanAction}
250-
disabled={!gasChecker.hasEnoughGas || isWalletPrompting}
254+
disabled={!gasChecker.hasEnoughGas || isWalletPrompting || increaseDisabled}
251255
>
252256
{isWalletPrompting ? (
253257
<Trans>Waiting for wallet...</Trans>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import BigNumber from 'bignumber.js';
2+
3+
export type CollateralTokenMap = Record<string, string>;
4+
5+
export function hasPositiveDebtCeiling(ceiling: string | null | undefined): boolean {
6+
return ceiling != null && new BigNumber(ceiling).isGreaterThan(0);
7+
}
8+
9+
export function selectEnabledCollateralTokens(
10+
tokens: CollateralTokenMap,
11+
enabledSymbols: ReadonlySet<string>,
12+
): CollateralTokenMap {
13+
return Object.fromEntries(Object.entries(tokens).filter(([symbol]) => enabledSymbols.has(symbol)));
14+
}
15+
16+
export function isCollateralEnabled(tokens: CollateralTokenMap | undefined, symbol: string): boolean {
17+
return Boolean(tokens?.[symbol]);
18+
}
19+
20+
export function getActionMaximum(
21+
currentAmount: BigNumber,
22+
availableMaximum: BigNumber,
23+
increaseEnabled: boolean,
24+
): BigNumber {
25+
return increaseEnabled ? availableMaximum : currentAmount;
26+
}
27+
28+
export function isIncreaseAllowed(currentAmount: BigNumber, nextAmount: BigNumber, increaseEnabled: boolean): boolean {
29+
return increaseEnabled || nextAmount.isLessThanOrEqualTo(currentAmount);
30+
}

0 commit comments

Comments
 (0)