Skip to content

Commit

Permalink
feat: coll swap
Browse files Browse the repository at this point in the history
  • Loading branch information
rhlsthrm committed Oct 11, 2024
1 parent 3d12862 commit 24263c0
Show file tree
Hide file tree
Showing 4 changed files with 203 additions and 48 deletions.
226 changes: 182 additions & 44 deletions packages/ui/app/_components/dashboards/CollateralSwapPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,10 @@ import {
Title,
Tooltip
} from 'chart.js';
// import { usePathname, useRouter} from 'next/navigation';
import { useSearchParams } from 'next/navigation';
import { useEffect, useMemo, useState } from 'react';
// import { useCallback, useEffect, useState } from 'react';
import { Doughnut } from 'react-chartjs-2';
import toast from 'react-hot-toast';
import {
type Address,
formatEther,
Expand All @@ -38,10 +37,13 @@ import { useAccount, useChainId, useWriteContract } from 'wagmi';
import MaxDeposit from './MaxDeposit';
import SwapTo from './SwapTo';

// import { useDebounce } from '@ui/hooks/useDebounce';
import SliderComponent from '@ui/app/_components/popup/Slider';
import TransactionStepsHandler, {
useTransactionSteps
} from '@ui/app/_components/popup/TransactionStepsHandler';
import type { IBal } from '@ui/app/_components/stake/MaxDeposit';
import { donutoptions, getDonutData } from '@ui/app/_constants/mock';
import { INFO_MESSAGES } from '@ui/constants/index';
import { useMultiIonic } from '@ui/context/MultiIonicContext';
import { useDebounce } from '@ui/hooks/useDebounce';
import { useSupplyCap } from '@ui/hooks/useSupplyCap';
Expand Down Expand Up @@ -87,6 +89,7 @@ export default function CollateralSwapPopup({
const [swapFromAmount, setSwapFromAmount] = useState<string>('');
const [swapToAmount, setSwapToAmount] = useState<string>('');
const [lifiQuote, setLifiQuote] = useState<LiFiStep>();
const [isLoadingLifiQuote, setIsLoadingLifiQuote] = useState<boolean>(false);
const [conversionRate, setConversionRate] = useState<string>('100');
const [maxTokens, setMaxTokens] = useState<IBal>({
value: BigInt(0),
Expand All @@ -98,7 +101,7 @@ export default function CollateralSwapPopup({
const chain = querychain ? querychain : String(chainId);
const queryToken = searchParams.get('token');

const { getSdk } = useMultiIonic();
const { getSdk, currentSdk, address } = useMultiIonic();
const sdk = getSdk(+chain);
const collateralSwapContract =
sdk?.chainDeployment[`CollateralSwap-${comptroller}`];
Expand Down Expand Up @@ -142,6 +145,12 @@ export default function CollateralSwapPopup({
comptroller
});

const resetTransactionSteps = () => {
// refetchUsedQueries();
upsertTransactionStep(undefined);
// initiateCloseAnimation();
};

// const router = useRouter();
// const createQueryString = useCallback(
// (name: string, value: string) => {
Expand Down Expand Up @@ -207,22 +216,34 @@ export default function CollateralSwapPopup({
swappedFromAsset?.underlyingDecimals ?? 18
), // 10 USDC needs to get delayed
// The address from which the tokens are being transferred.
fromAddress: collateralSwapContract?.address,
fromAddress: collateralSwapContract.address,
skipSimulation: true,
integrator: 'ionic'
integrator: 'ionic',
fee: '0.005'
};
const quote = await getQuote(quoteRequest);
// eslint-disable-next-line no-console
console.log('🚀 ~ fetchQuote ~ quote:', quote);
setLifiQuote(quote);
setSwapToAmount(quote?.estimate?.toAmount);
setConversionRate(
(
(Number(quote?.estimate?.fromAmountUSD) /
Number(quote?.estimate?.toAmountUSD)) *
100
).toLocaleString('en-US', { maximumFractionDigits: 2 })
);
try {
setIsLoadingLifiQuote(true);
const quote = await getQuote(quoteRequest);
setLifiQuote(quote);
setSwapToAmount(quote?.estimate?.toAmount);
setConversionRate(
(
((Number(quote?.estimate?.toAmountUSD) -
Number(quote?.estimate?.fromAmountUSD)) /
Number(quote?.estimate?.fromAmountUSD)) *
100
).toLocaleString('en-US', { maximumFractionDigits: 2 })
);
} catch (error) {
console.error('Quote Error: ', error);
if ((error as Error).message.includes('429')) {
toast.error('Rate limit exceeded, try again later');
} else {
toast.error('Error while fetching quote!');
}
} finally {
setIsLoadingLifiQuote(false);
}
};
fetchQuote();
}, [
Expand All @@ -236,23 +257,126 @@ export default function CollateralSwapPopup({
]);

const { writeContractAsync, isPending } = useWriteContract();
const { addStepsForAction, transactionSteps, upsertTransactionStep } =
useTransactionSteps();

const handleSwitch = async () => {
console.log('Switching');
await writeContractAsync({
address: collateralSwapContract!.address as Address,
abi: collateralSwapAbi,
functionName: 'swapCollateral',
args: [
parseUnits(
swapFromAmountUnderlying,
swappedFromAsset.underlyingDecimals
),
swappedFromAsset!.cToken,
swappedToAsset!.cToken,
lifiQuote!.transactionRequest!.to as Address,
lifiQuote!.transactionRequest!.data as Hex
]
});
if (!currentSdk || !collateralSwapContract?.address || !address) return;
let currentTransactionStep = 0;

const _amount = parseUnits(
swapFromAmount,
swappedFromAsset.underlyingDecimals
);
console.log('🚀 ~ handleSwitch ~ _amount:', _amount);

addStepsForAction([
{
error: false,
message: INFO_MESSAGES.SWAP.APPROVE,
success: false
},
{
error: false,
message: INFO_MESSAGES.SWAP.SWAPPING,
success: false
}
]);

try {
const token = currentSdk.getEIP20TokenInstance(
swappedFromAsset.cToken,
currentSdk.publicClient as any
);
const hasApprovedEnough =
(await token.read.allowance([
address,
collateralSwapContract.address as Address
])) >= _amount;

if (!hasApprovedEnough) {
const tx = await currentSdk.approve(
collateralSwapContract.address as Address,
swappedFromAsset.cToken,
(_amount * 105n) / 100n
);

upsertTransactionStep({
index: currentTransactionStep,
transactionStep: {
...transactionSteps[currentTransactionStep],
txHash: tx
}
});

await currentSdk.publicClient.waitForTransactionReceipt({
hash: tx,
confirmations: 2
});

// wait for 5 seconds to resolve timing issue
await new Promise((resolve) => setTimeout(resolve, 5000));
}

upsertTransactionStep({
index: currentTransactionStep,
transactionStep: {
...transactionSteps[currentTransactionStep],
success: true
}
});
currentTransactionStep++;

const tx = await writeContractAsync({
address: collateralSwapContract!.address as Address,
abi: collateralSwapAbi,
functionName: 'swapCollateral',
args: [
parseUnits(
swapFromAmountUnderlying,
swappedFromAsset.underlyingDecimals
),
swappedFromAsset!.cToken,
swappedToAsset!.cToken,
lifiQuote!.transactionRequest!.to as Address,
lifiQuote!.transactionRequest!.data as Hex
]
});
upsertTransactionStep({
index: currentTransactionStep,
transactionStep: {
...transactionSteps[currentTransactionStep],
txHash: tx
}
});

await currentSdk.publicClient.waitForTransactionReceipt({
hash: tx
});

upsertTransactionStep({
index: currentTransactionStep,
transactionStep: {
...transactionSteps[currentTransactionStep],
success: true
}
});

toast.success(
`Swapped ${swappedFromAsset.underlyingSymbol} to ${swappedToAsset?.underlyingSymbol}`
);
} catch (error) {
console.error('handleSwitch ~ error:', error);
toast.error('Error while supplying!');

upsertTransactionStep({
index: currentTransactionStep,
transactionStep: {
...transactionSteps[currentTransactionStep],
error: true
}
});
}
};

return (
Expand All @@ -273,13 +397,18 @@ export default function CollateralSwapPopup({
/>
</div>
<div className={` text-xs flex items-center justify-between w-full`}>
<span className=" text-white/50 ">CONVERSION RATE</span>
<span className=" text-white/50 ">PRICE IMPACT</span>
<span className=" ">{conversionRate}%</span>
</div>
<div className={` text-xs flex items-center justify-between w-full`}>
<span className=" text-white/50 ">FEES</span>
<span className=" ">
{lifiQuote ? lifiQuote?.estimate?.feeCosts?.[0]?.amountUSD : ''} USD
{lifiQuote
? lifiQuote?.estimate?.feeCosts?.reduce(
(acc, curr) => acc + Number(curr.amountUSD),
0
) + ' USD'
: '-'}
</span>
</div>
<div className="h-[2px] w-full mx-auto bg-white/10 my-2.5 " />
Expand All @@ -301,6 +430,7 @@ export default function CollateralSwapPopup({
BigInt(swapToAmount),
swappedToAsset?.underlyingDecimals ?? 18
)}
isLoading={isLoadingLifiQuote}
tokenName={swappedToTokenQuery}
token={swappedToAsset?.cToken}
// handleInput={(val?: string) => setSwapToToken(val as string)}
Expand Down Expand Up @@ -402,14 +532,22 @@ export default function CollateralSwapPopup({
<span className=" ">0.2%</span>
</div> */}
<p className={`text-xs mb-3`}>0.01% Slippage Tolerance</p>
<button
className={`bg-accent py-1 px-3 w-full text-sm rounded-md text-black`}
onClick={handleSwitch}
disabled={isPending}
>
SWITCH {swappedFromAsset?.underlyingSymbol} TO{' '}
{swappedToAsset?.underlyingSymbol}{' '}
</button>
{transactionSteps.length > 0 ? (
<TransactionStepsHandler
chainId={chainId}
resetTransactionSteps={resetTransactionSteps}
transactionSteps={transactionSteps}
/>
) : (
<button
className={`bg-accent py-1 px-3 w-full text-sm rounded-md text-black disabled:opacity-50`}
onClick={handleSwitch}
disabled={isPending || !lifiQuote || !swapToAmount}
>
SWITCH {swappedFromAsset?.underlyingSymbol} TO{' '}
{swappedToAsset?.underlyingSymbol}{' '}
</button>
)}
</div>
</div>
);
Expand Down
8 changes: 5 additions & 3 deletions packages/ui/app/_components/dashboards/SwapTo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ interface ISwapTo {
headerText?: string;
tokenSelector?: boolean;
tokenArr?: string[];
isLoading: boolean;
}

export interface IBal {
Expand All @@ -25,7 +26,8 @@ function SwapTo({
amount,
tokenName = 'eth',
tokenSelector = false,
tokenArr
tokenArr,
isLoading
}: ISwapTo) {
const newRef = useRef(null!);
const [open, setOpen] = useState<boolean>(false);
Expand Down Expand Up @@ -56,8 +58,8 @@ function SwapTo({
<input
className={`focus:outline-none amount-field font-bold bg-transparent disabled:text-white/60 flex-auto flex w-full trucnate`}
placeholder={`0.0`}
type="number"
value={amount}
type={isLoading ? 'text' : 'number'}
value={isLoading ? '...' : amount}
disabled={true}
/>
<div
Expand Down
13 changes: 12 additions & 1 deletion packages/ui/app/dashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ import { useTotalSupplyAPYs } from '@ui/hooks/useTotalSupplyAPYs';
import { useUserNetApr } from '@ui/hooks/useUserNetApr';
import type { MarketData } from '@ui/types/TokensDataMap';
import { getBlockTimePerMinuteByChainId } from '@ui/utils/networkData';
import { handleSwitchOriginChain } from '@ui/utils/NetworkChecker';
import { useChainId } from 'wagmi';

export default function Dashboard() {
const { currentSdk } = useMultiIonic();
Expand All @@ -61,6 +63,7 @@ export default function Dashboard() {
const [popupMode, setPopupMode] = useState<PopupMode>();
const [collateralSwapFromAsset, setCollateralSwapFromAsset] =
useState<MarketData>();
const walletChain = useChainId();

const { data: marketData, isLoading: isLoadingMarketData } = useFusePoolData(
pool ? pool : pools[+chain].pools[0].id,
Expand Down Expand Up @@ -701,7 +704,15 @@ export default function Dashboard() {
setPopupMode={setPopupMode}
setSelectedSymbol={setSelectedSymbol}
// utilization={utilizations[i]}
toggler={() => swapToggle()}
toggler={async () => {
const result = await handleSwitchOriginChain(
+chain,
walletChain
);
if (result) {
swapToggle();
}
}}
setCollateralSwapFromAsset={() =>
setCollateralSwapFromAsset(asset)
}
Expand Down
4 changes: 4 additions & 0 deletions packages/ui/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -685,5 +685,9 @@ export const INFO_MESSAGES = {
},
WITHDRAW: {
WITHDRAWING: 'Withdrawing funds'
},
SWAP: {
APPROVE: 'Approve amount for spending',
SWAPPING: 'Swapping'
}
};

0 comments on commit 24263c0

Please sign in to comment.