diff --git a/packages/ui/app/_components/ResultHandler.tsx b/packages/ui/app/_components/ResultHandler.tsx
index 385a3bd366..7df8f3b05d 100644
--- a/packages/ui/app/_components/ResultHandler.tsx
+++ b/packages/ui/app/_components/ResultHandler.tsx
@@ -33,7 +33,6 @@ export default function ResultHandler({
margin: center ? 'auto' : '0px'
}}
ariaLabel="three-circles-loading"
- wrapperClass=""
/>
);
}
diff --git a/packages/ui/app/_components/popup/Amount.tsx b/packages/ui/app/_components/popup/Amount.tsx
index f34896911b..fc8db205af 100644
--- a/packages/ui/app/_components/popup/Amount.tsx
+++ b/packages/ui/app/_components/popup/Amount.tsx
@@ -4,6 +4,7 @@ import { MarketData } from '@ui/types/TokensDataMap';
import dynamic from 'next/dynamic';
import React, { useState } from 'react';
import { useAccount, useBalance } from 'wagmi';
+import ResultHandler from '../ResultHandler';
interface IAmount {
selectedMarketData: MarketData;
@@ -12,6 +13,7 @@ interface IAmount {
hintText?: string;
max?: number;
symbol: string;
+ isLoading?: boolean;
}
const Amount = ({
selectedMarketData,
@@ -19,7 +21,8 @@ const Amount = ({
amount,
hintText = 'Wallet Balance',
max = 0,
- symbol
+ symbol,
+ isLoading = false
}: IAmount) => {
const marketDataDecimals = parseInt(
selectedMarketData.underlyingDecimals.toString()
@@ -39,15 +42,25 @@ const Amount = ({
Amount
-
- {hintText} {max.toFixed(marketDataDecimals)}
-
-
+
+
+ <>
+
+ {hintText} {max.toFixed(marketDataDecimals)}
+
+
+ >
+
+
void;
};
-function LoadingButtonWithText({ text }: LoadingButtonWithTextProps) {
+function TransactionStepsHandler({
+ transactionSteps,
+ resetTransactionSteps
+}: TransactionStepsHandlerProps) {
return (
-
+
+ {transactionSteps.map((transactionStep, i) => (
+
+
+ {!transactionStep.error && !transactionStep.success && (
+
+ )}
+
+ {transactionStep.error && }
+
+ {transactionStep.success && }
+
+ {transactionStep.message}
+
+
+ {transactionStep.txHash && (
+
+ )}
+
+ ))}
+
+ {(transactionSteps.filter((step) => step.success).length ===
+ transactionSteps.length ||
+ transactionSteps.find((step) => step.error) !== undefined) && (
+
+
+
+ )}
+
);
}
@@ -61,18 +110,49 @@ const Popup = ({
selectedMarketData,
comptrollerAddress
}: IPopup) => {
- // console.log(mode);
+ const [enableCollateral, setEnableCollateral] = useState
(false);
+ const [transactionSteps, upsertTransactionStep] = useReducer(
+ (
+ prevState: TransactionStep[],
+ updatedStep:
+ | { transactionStep: TransactionStep; index: number }
+ | undefined
+ ): TransactionStep[] => {
+ if (!updatedStep) {
+ return [];
+ }
+
+ const currentSteps = prevState.slice();
+
+ currentSteps[updatedStep.index] = {
+ ...currentSteps[updatedStep.index],
+ ...updatedStep.transactionStep
+ };
+
+ if (
+ updatedStep.transactionStep.error &&
+ updatedStep.index + 1 < currentSteps.length
+ ) {
+ for (let i = updatedStep.index + 1; i < currentSteps.length; i++) {
+ currentSteps[i] = {
+ ...currentSteps[i],
+ error: true
+ };
+ }
+ }
+
+ return currentSteps;
+ },
+ []
+ );
const { currentSdk, address } = useMultiMidas();
const chainId = useChainId();
const { data: minBorrowAmount } = useBorrowMinimum(
selectedMarketData,
chainId
);
- const { data: maxSupplyAmount } = useMaxSupplyAmount(
- selectedMarketData,
- comptrollerAddress,
- chainId
- );
+ const { data: maxSupplyAmount, isLoading: isLoadingMaxSupply } =
+ useMaxSupplyAmount(selectedMarketData, comptrollerAddress, chainId);
const { data: assetsSupplyAprData } = useTotalSupplyAPYs(
[selectedMarketData],
chainId
@@ -87,7 +167,6 @@ const Popup = ({
return '0.00%';
}, [assetsSupplyAprData]);
- const [currentInfoMessage, setCurrentInfoMessage] = useState();
const [active, setActive] = useState('');
const slide = useRef(null!);
const router = useRouter();
@@ -103,29 +182,23 @@ const Popup = ({
},
undefined
);
- const { data: maxRepayAmount } = useMaxRepayAmount(
- selectedMarketData,
- chainId
- );
- const amountAsBInt = useMemo(
+ const { data: maxRepayAmount, isLoading: isLoadingMaxRepayAmount } =
+ useMaxRepayAmount(selectedMarketData, chainId);
+ const amountAsBInt = useMemo(
() =>
- amount
- ? (
- amount *
+ BigNumber.from(
+ Math.round(
+ (amount ?? 0) *
Math.pow(
10,
parseInt(selectedMarketData.underlyingDecimals.toString())
)
- ).toString()
- : '0',
+ )
+ ),
[amount]
);
- const [isExecutingAction, setIsExecutingAction] = useState(false);
- const { data: maxBorrowAmount } = useMaxBorrowAmount(
- selectedMarketData,
- comptrollerAddress,
- chainId
- );
+ const { data: maxBorrowAmount, isLoading: isLoadingMaxBorrowAmount } =
+ useMaxBorrowAmount(selectedMarketData, comptrollerAddress, chainId);
const currentBorrowAmountAsFloat = useMemo(
() => parseFloat(selectedMarketData.borrowBalance.toString()),
[selectedMarketData]
@@ -138,15 +211,13 @@ const Popup = ({
useUpdatedUserAssets({
mode: currentFundOperation,
poolChainId: chainId,
- amount: amountAsBInt as any,
+ amount: amountAsBInt,
assets: [selectedMarketData],
index: 0
});
const updatedAsset = updatedAssets ? updatedAssets[0] : undefined;
- const { data: maxWithdrawAmount } = useMaxWithdrawAmount(
- selectedMarketData,
- chainId
- );
+ const { data: maxWithdrawAmount, isLoading: isLoadingMaxWithdrawAmount } =
+ useMaxWithdrawAmount(selectedMarketData, chainId);
const {
supplyAPY,
borrowAPR,
@@ -221,6 +292,16 @@ const Popup = ({
return {};
}, [chainId, updatedAsset, selectedMarketData, updatedAssets, currentSdk]);
+ const minBorrowAmountAsNumber = useMemo(
+ () =>
+ parseFloat(
+ formatUnits(
+ minBorrowAmount?.minBorrowAsset ?? '0',
+ selectedMarketData.underlyingDecimals
+ )
+ ),
+ [minBorrowAmount]
+ );
const queryClient = useQueryClient();
/**
@@ -230,16 +311,7 @@ const Popup = ({
switch (active) {
case 'COLLATERAL':
setCurrentUtilizationPercentage(
- Math.round(
- ((amount ?? 0) /
- parseFloat(
- formatUnits(
- maxSupplyAmount?.bigNumber ?? '0',
- selectedMarketData.underlyingDecimals
- )
- )) *
- 100
- )
+ Math.round(((amount ?? 0) / (maxSupplyAmount?.number ?? 0)) * 100)
);
break;
@@ -262,16 +334,7 @@ const Popup = ({
case 'BORROW':
setCurrentUtilizationPercentage(
- Math.round(
- ((amount ?? 0) /
- parseFloat(
- formatUnits(
- maxBorrowAmount?.bigNumber ?? '0',
- selectedMarketData.underlyingDecimals
- ) ?? '1'
- )) *
- 100
- )
+ Math.round(((amount ?? 0) / (maxBorrowAmount?.number ?? 1)) * 100)
);
break;
@@ -315,6 +378,7 @@ const Popup = ({
useEffect(() => {
setAmount(0);
setCurrentUtilizationPercentage(0);
+ upsertTransactionStep(undefined);
switch (active) {
case 'COLLATERAL':
@@ -375,12 +439,7 @@ const Popup = ({
parseFloat(
(
(utilizationPercentage / 100) *
- parseFloat(
- formatUnits(
- maxSupplyAmount?.bigNumber ?? '0',
- selectedMarketData.underlyingDecimals
- ) ?? '0.0'
- )
+ (maxSupplyAmount?.number ?? 0)
).toFixed(parseInt(selectedMarketData.underlyingDecimals.toString()))
)
);
@@ -407,12 +466,7 @@ const Popup = ({
parseFloat(
(
(utilizationPercentage / 100) *
- parseFloat(
- formatUnits(
- maxBorrowAmount?.bigNumber ?? '0',
- selectedMarketData.underlyingDecimals
- ) ?? '0.0'
- )
+ (maxBorrowAmount?.number ?? 0)
).toFixed(parseInt(selectedMarketData.underlyingDecimals.toString()))
)
);
@@ -434,9 +488,39 @@ const Popup = ({
);
};
- const supplyAmount = async (collateral: boolean = false) => {
+ const addStepsForAction = (steps: TransactionStep[]) => {
+ steps.forEach((step, i) =>
+ upsertTransactionStep({ transactionStep: step, index: i })
+ );
+ };
+
+ const resetTransactionSteps = () => {
+ refetchUsedQueries();
+ upsertTransactionStep(undefined);
+ };
+
+ const refetchUsedQueries = async () => {
+ queryClient.invalidateQueries({ queryKey: ['useFusePoolData'] });
+ queryClient.invalidateQueries({ queryKey: ['useBorrowMinimum'] });
+ queryClient.invalidateQueries({ queryKey: ['useUsdPrice'] });
+ queryClient.invalidateQueries({ queryKey: ['useAllUsdPrices'] });
+ queryClient.invalidateQueries({ queryKey: ['useTotalSupplyAPYs'] });
+ queryClient.invalidateQueries({ queryKey: ['useUpdatedUserAssets'] });
+ queryClient.invalidateQueries({ queryKey: ['useMaxSupplyAmount'] });
+ queryClient.invalidateQueries({ queryKey: ['useMaxWithdrawAmount'] });
+ queryClient.invalidateQueries({ queryKey: ['useMaxBorrowAmount'] });
+ queryClient.invalidateQueries({ queryKey: ['useMaxRepayAmount'] });
+ queryClient.invalidateQueries({
+ queryKey: ['useSupplyCapsDataForPool']
+ });
+ queryClient.invalidateQueries({
+ queryKey: ['useBorrowCapsDataForAsset']
+ });
+ };
+
+ const supplyAmount = async () => {
if (
- !isExecutingAction &&
+ !transactionSteps.length &&
currentSdk &&
address &&
amount &&
@@ -444,11 +528,30 @@ const Popup = ({
maxSupplyAmount &&
amount <= maxSupplyAmount.number
) {
- setIsExecutingAction(true);
+ let currentTransactionStep = 0;
+ addStepsForAction([
+ {
+ message: INFO_MESSAGES.SUPPLY.APPROVE,
+ success: false,
+ error: false
+ },
+ ...(enableCollateral
+ ? [
+ {
+ message: INFO_MESSAGES.SUPPLY.COLLATERAL,
+ success: false,
+ error: false
+ }
+ ]
+ : []),
+ {
+ message: INFO_MESSAGES.SUPPLY.SUPPLYING,
+ success: false,
+ error: false
+ }
+ ]);
try {
- setCurrentInfoMessage(INFO_MESSAGES.SUPPLY.APPROVE);
-
const token = currentSdk.getEIP20TokenInstance(
selectedMarketData.underlyingToken,
currentSdk.signer
@@ -463,61 +566,101 @@ const Popup = ({
selectedMarketData.underlyingToken
);
+ upsertTransactionStep({
+ transactionStep: {
+ ...transactionSteps[currentTransactionStep],
+ txHash: tx.hash
+ },
+ index: currentTransactionStep
+ });
+
await tx.wait();
}
- if (collateral) {
- setCurrentInfoMessage(INFO_MESSAGES.SUPPLY.COLLATERAL);
+ upsertTransactionStep({
+ transactionStep: {
+ ...transactionSteps[currentTransactionStep],
+ success: true
+ },
+ index: currentTransactionStep
+ });
+
+ currentTransactionStep++;
+ if (enableCollateral) {
const tx = await currentSdk.enterMarkets(
selectedMarketData.cToken,
comptrollerAddress
);
+ upsertTransactionStep({
+ transactionStep: {
+ ...transactionSteps[currentTransactionStep],
+ txHash: tx.hash
+ },
+ index: currentTransactionStep
+ });
+
await tx.wait();
- }
- setCurrentInfoMessage(INFO_MESSAGES.SUPPLY.SUPPLYING);
+ upsertTransactionStep({
+ transactionStep: {
+ ...transactionSteps[currentTransactionStep],
+ success: true
+ },
+ index: currentTransactionStep
+ });
+
+ currentTransactionStep++;
+ }
const { tx, errorCode } = await currentSdk.mint(
selectedMarketData.cToken,
- amountAsBInt as any
+ amountAsBInt
);
if (errorCode) {
throw new Error('Error during supplying!');
}
+ upsertTransactionStep({
+ transactionStep: {
+ ...transactionSteps[currentTransactionStep],
+ txHash: tx?.hash
+ },
+ index: currentTransactionStep
+ });
+
await tx?.wait();
- await Promise.all([
- queryClient.refetchQueries({ queryKey: ['useFusePoolData'] }),
- queryClient.refetchQueries({ queryKey: ['useMaxSupplyAmount'] }),
- queryClient.refetchQueries({ queryKey: ['useMaxWithdrawAmount'] }),
- queryClient.refetchQueries({ queryKey: ['useMaxBorrowAmount'] }),
- queryClient.refetchQueries({ queryKey: ['useMaxRepayAmount'] }),
- queryClient.refetchQueries({
- queryKey: ['useSupplyCapsDataForPool']
- }),
- queryClient.refetchQueries({
- queryKey: ['useBorrowCapsDataForAsset']
- })
- ]);
+ upsertTransactionStep({
+ transactionStep: {
+ ...transactionSteps[currentTransactionStep],
+ success: true
+ },
+ index: currentTransactionStep
+ });
toast.success(
`Supplied ${amount} ${selectedMarketData.underlyingSymbol}`
);
} catch (error) {
toast.error('Error while supplying!');
+
+ upsertTransactionStep({
+ transactionStep: {
+ ...transactionSteps[currentTransactionStep],
+ error: true
+ },
+ index: currentTransactionStep
+ });
}
}
-
- setIsExecutingAction(false);
};
const withdrawAmount = async () => {
if (
- !isExecutingAction &&
+ !transactionSteps.length &&
currentSdk &&
address &&
amount &&
@@ -530,11 +673,16 @@ const Popup = ({
)
)
) {
- setIsExecutingAction(true);
+ let currentTransactionStep = 0;
+ addStepsForAction([
+ {
+ message: INFO_MESSAGES.WITHDRAW.WITHDRAWING,
+ success: false,
+ error: false
+ }
+ ]);
try {
- setCurrentInfoMessage(INFO_MESSAGES.WITHDRAW.WITHDRAWING);
-
if (
parseFloat(
formatUnits(
@@ -552,72 +700,110 @@ const Popup = ({
throw new Error('Error during withdrawing!');
}
+ upsertTransactionStep({
+ transactionStep: {
+ ...transactionSteps[currentTransactionStep],
+ txHash: tx?.hash
+ },
+ index: currentTransactionStep
+ });
+
await tx?.wait();
} else {
const { tx, errorCode } = await currentSdk.withdraw(
selectedMarketData.cToken,
- amountAsBInt as any
+ amountAsBInt
);
if (errorCode) {
throw new Error('Error during withdrawing!');
}
+ upsertTransactionStep({
+ transactionStep: {
+ ...transactionSteps[currentTransactionStep],
+ txHash: tx?.hash
+ },
+ index: currentTransactionStep
+ });
+
await tx?.wait();
}
+ upsertTransactionStep({
+ transactionStep: {
+ ...transactionSteps[currentTransactionStep],
+ success: true
+ },
+ index: currentTransactionStep
+ });
+
toast.success(
`Withdrawn ${amount} ${selectedMarketData.underlyingSymbol}`
);
} catch (error) {
console.error(error);
+ upsertTransactionStep({
+ transactionStep: {
+ ...transactionSteps[currentTransactionStep],
+ error: true
+ },
+ index: currentTransactionStep
+ });
+
toast.error('Error while withdrawing!');
}
}
-
- setIsExecutingAction(false);
};
const borrowAmount = async () => {
if (
- !isExecutingAction &&
+ !transactionSteps.length &&
currentSdk &&
address &&
amount &&
amount > 0 &&
minBorrowAmount &&
- amount > (minBorrowAmount?.minBorrowUSD ?? 0) &&
+ amount > minBorrowAmountAsNumber &&
maxBorrowAmount &&
amount <= maxBorrowAmount.number
) {
- setIsExecutingAction(true);
+ let currentTransactionStep = 0;
+ addStepsForAction([
+ {
+ message: INFO_MESSAGES.BORROW.BORROWING,
+ success: false,
+ error: false
+ }
+ ]);
try {
- setCurrentInfoMessage(INFO_MESSAGES.BORROW.BORROWING);
-
const { tx, errorCode } = await currentSdk.borrow(
selectedMarketData.cToken,
- amountAsBInt as any
+ amountAsBInt
);
if (errorCode) {
- throw new Error('Error during withdrawing!');
+ throw new Error('Error during borrowing!');
}
- await tx?.wait();
- await queryClient.refetchQueries({ queryKey: ['useFusePoolData'] });
- await queryClient.refetchQueries({ queryKey: ['useMaxSupplyAmount'] });
- await queryClient.refetchQueries({
- queryKey: ['useMaxWithdrawAmount']
+ upsertTransactionStep({
+ transactionStep: {
+ ...transactionSteps[currentTransactionStep],
+ txHash: tx?.hash
+ },
+ index: currentTransactionStep
});
- await queryClient.refetchQueries({ queryKey: ['useMaxBorrowAmount'] });
- await queryClient.refetchQueries({ queryKey: ['useMaxRepayAmount'] });
- await queryClient.refetchQueries({
- queryKey: ['useSupplyCapsDataForPool']
- });
- await queryClient.refetchQueries({
- queryKey: ['useBorrowCapsDataForAsset']
+
+ await tx?.wait();
+
+ upsertTransactionStep({
+ transactionStep: {
+ ...transactionSteps[currentTransactionStep],
+ success: true
+ },
+ index: currentTransactionStep
});
toast.success(
@@ -626,27 +812,43 @@ const Popup = ({
} catch (error) {
console.error(error);
+ upsertTransactionStep({
+ transactionStep: {
+ ...transactionSteps[currentTransactionStep],
+ error: true
+ },
+ index: currentTransactionStep
+ });
+
toast.error('Error while borrowing!');
}
}
-
- setIsExecutingAction(false);
};
const repayAmount = async () => {
if (
- !isExecutingAction &&
+ !transactionSteps.length &&
currentSdk &&
address &&
amount &&
amount > 0 &&
currentBorrowAmountAsFloat
) {
- setIsExecutingAction(true);
+ let currentTransactionStep = 0;
+ addStepsForAction([
+ {
+ message: INFO_MESSAGES.REPAY.APPROVE,
+ success: false,
+ error: false
+ },
+ {
+ message: INFO_MESSAGES.REPAY.REPAYING,
+ success: false,
+ error: false
+ }
+ ]);
try {
- setCurrentInfoMessage(INFO_MESSAGES.REPAY.APPROVE);
-
const token = currentSdk.getEIP20TokenInstance(
selectedMarketData.underlyingToken,
currentSdk.signer
@@ -661,53 +863,71 @@ const Popup = ({
selectedMarketData.underlyingToken
);
+ upsertTransactionStep({
+ transactionStep: {
+ ...transactionSteps[currentTransactionStep],
+ txHash: tx.hash
+ },
+ index: currentTransactionStep
+ });
+
await tx.wait();
}
- setCurrentInfoMessage(INFO_MESSAGES.REPAY.REPAYING);
+ upsertTransactionStep({
+ transactionStep: {
+ ...transactionSteps[currentTransactionStep],
+ success: true
+ },
+ index: currentTransactionStep
+ });
+
+ currentTransactionStep++;
- const isRepayingMax =
- parseInt((maxRepayAmount ?? '0').toString()) <=
- parseInt(amountAsBInt);
+ const isRepayingMax = amountAsBInt.gte(maxRepayAmount ?? '0');
const { tx, errorCode } = await currentSdk.repay(
selectedMarketData.cToken,
isRepayingMax,
- isRepayingMax
- ? selectedMarketData.borrowBalance
- : (amountAsBInt as any)
+ isRepayingMax ? selectedMarketData.borrowBalance : amountAsBInt
);
if (errorCode) {
throw new Error('Error during repaying!');
}
- await tx?.wait();
- await queryClient.refetchQueries({ queryKey: ['useFusePoolData'] });
- await queryClient.refetchQueries({ queryKey: ['useMaxSupplyAmount'] });
- await queryClient.refetchQueries({
- queryKey: ['useMaxWithdrawAmount']
+ upsertTransactionStep({
+ transactionStep: {
+ ...transactionSteps[currentTransactionStep],
+ txHash: tx?.hash
+ },
+ index: currentTransactionStep
});
- await queryClient.refetchQueries({ queryKey: ['useMaxBorrowAmount'] });
- await queryClient.refetchQueries({ queryKey: ['useMaxRepayAmount'] });
- await queryClient.refetchQueries({
- queryKey: ['useSupplyCapsDataForPool']
- });
- await queryClient.refetchQueries({
- queryKey: ['useBorrowCapsDataForAsset']
+
+ await tx?.wait();
+
+ upsertTransactionStep({
+ transactionStep: {
+ ...transactionSteps[currentTransactionStep],
+ success: true
+ },
+ index: currentTransactionStep
});
} catch (error) {
console.error(error);
+ upsertTransactionStep({
+ transactionStep: {
+ ...transactionSteps[currentTransactionStep],
+ error: true
+ },
+ index: currentTransactionStep
+ });
+
toast.error('Error while repaying!');
}
}
-
- setIsExecutingAction(false);
};
- // console.log(supplyUtilization);
- // console.log(amount);
-
return (
setAmount(val)}
amount={amount}
- max={parseFloat(
- formatUnits(
- maxSupplyAmount?.bigNumber ?? '0',
- selectedMarketData.underlyingDecimals
- ) ?? '0.0'
- )}
+ max={maxSupplyAmount?.number ?? 0}
symbol={selectedMarketData.underlyingSymbol}
+ isLoading={isLoadingMaxSupply}
/>
+
+
+ Enable collateral
+
+
+ !transactionSteps.length &&
+ setEnableCollateral(!enableCollateral)
+ }
+ />
+
+
- {isExecutingAction ? (
-
+ {transactionSteps.length > 0 ? (
+
) : (
<>
-
-
>
)}
@@ -856,6 +1081,7 @@ const Popup = ({
)}
symbol={selectedMarketData.underlyingSymbol}
hintText="Max Withdraw"
+ isLoading={isLoadingMaxWithdrawAmount}
/>
- {isExecutingAction ? (
-
+ {transactionSteps.length > 0 ? (
+
) : (
MIN BORROW
- {formatUnits(
- minBorrowAmount?.minBorrowAsset ?? '0',
- parseInt(selectedMarketData.underlyingDecimals.toString())
- )}
+ {minBorrowAmountAsNumber}
{/* this will be dynamic */}
@@ -1000,15 +1227,18 @@ const Popup = ({
- {isExecutingAction ? (
-
+ {transactionSteps.length > 0 ? (
+
) : (
@@ -105,7 +100,7 @@ export default function Market() {
className={`bg-grayone min-h-[60vh] pb-20 w-full px-[3%] mt-3 rounded-xl`}
>
-
Mode Lending & Borrowing
+ {/*
Mode Lending & Borrowing
*/}
{/*
@@ -135,7 +130,7 @@ export default function Market() {
*/}
-
+ {/* */}
diff --git a/packages/ui/hooks/useTokenBalance.ts b/packages/ui/hooks/useTokenBalance.ts
index b56f6d2167..96a24778a6 100644
--- a/packages/ui/hooks/useTokenBalance.ts
+++ b/packages/ui/hooks/useTokenBalance.ts
@@ -20,7 +20,7 @@ export const fetchTokenBalance = async (
balance = await sdk.provider.getBalance(address);
} else {
// const contract = sdk.createCTokenWithExtensions(tokenAddress);
- balance = await sdk.provider.getBalance(address, tokenAddress);
+ // balance = await sdk.provider.;
console.log(balance);
}
} catch (e) {