Skip to content

Commit

Permalink
fix: add approve button aave-like
Browse files Browse the repository at this point in the history
  • Loading branch information
jeanbenoit-richez committed Feb 1, 2024
1 parent e26eac1 commit be3204f
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 4 deletions.
18 changes: 15 additions & 3 deletions src/components/Modals/BuyModal/BuyModalWithPermit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
} from 'react';
import { useTranslation } from 'react-i18next';
import { Web3Provider } from '@ethersproject/providers';
import { Button, Divider, Flex, Group, Stack, Text, Tooltip, SegmentedControl } from '@mantine/core';
import { Button, Divider, Flex, Stack, Text, Tooltip, SegmentedControl } from '@mantine/core';
import { useForm } from '@mantine/form';
import { ContextModalProps } from '@mantine/modals';
import BigNumber from 'bignumber.js';
Expand All @@ -28,6 +28,7 @@ import { providerAtom } from 'src/states';
import { BUY_METHODS, buy } from '../../../utils/tx/buy';
import { Erc20, Erc20ABI } from '../../../abis';
import { AvailableConnectors, ConnectorsDatas } from '@realtoken/realt-commons';
import { useApproveOffer } from '../../../hooks/useApproveOffer';

type BuyModalWithPermitProps = {
offer: Offer,
Expand Down Expand Up @@ -118,7 +119,6 @@ export const BuyModalWithPermit: FC<
const total = values?.amount * values?.price;

const connector = useAtomValue(providerAtom);
console.log('connector: ', connector)

const onHandleSubmit = useCallback(
async (formValues: BuyWithPermitFormValues) => {
Expand Down Expand Up @@ -153,6 +153,9 @@ export const BuyModalWithPermit: FC<
return max.isGreaterThanOrEqualTo(new BigNumber(offer.amount)) ? new BigNumber(offer.amount).toNumber() : parseFloat(max.toString());
},[balance,offer]);

const { approveNeeded, approve, approveLoading } = useApproveOffer(offer, values.amount);
console.log('approveNeeded: ', approveNeeded)

const priceTranslation: Map<OFFER_TYPE,string> = new Map<OFFER_TYPE,string>([
[OFFER_TYPE.BUY,t("buyOfferTypePrice")],
[OFFER_TYPE.SELL,t("sellOfferTypePrice")],
Expand Down Expand Up @@ -250,11 +253,20 @@ export const BuyModalWithPermit: FC<
/>
</Flex>
): undefined}
{values.buyMethod == BUY_METHODS.buyWithApprove && approveNeeded ? (
<Button
loading={approveLoading}
aria-label={t('confirm')}
onClick={() => approve()}
>
{'Approve token'}
</Button>
): undefined}
<Button
type={'submit'}
loading={isSubmitting}
aria-label={t('confirm')}
disabled={process.env.NEXT_PUBLIC_ENV == "development" ? false : (values?.amount == 0 || !values.amount)}
disabled={process.env.NEXT_PUBLIC_ENV == "development" ? false : (values?.amount == 0 || !values.amount || approveNeeded)}
>
{values.buyMethod == BUY_METHODS.buyWithPermit ? t('buyButtons.permit.text') : t('buyButtons.approve.text')}
</Button>
Expand Down
134 changes: 134 additions & 0 deletions src/hooks/useApproveOffer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import { useEffect, useMemo, useState } from "react";
import { Offer } from "../types/offer";
import BigNumber from "bignumber.js";
import { getContract } from "@realtoken/realt-commons";
import { CoinBridgeToken, coinBridgeTokenABI } from "../abis";
import { useContract } from "./useContract";
import { ContractsID, NOTIFICATIONS, NotificationsID } from "../constants";
import { useWeb3React } from '@web3-react/core';
import { Web3Provider } from "@ethersproject/providers";
import { useActiveChain } from "./useActiveChain";
import { showNotification, updateNotification } from "@mantine/notifications";

type UseOffersComputedDatas = (
offer: Offer,
amount: number
) => {
amountInWei: BigNumber;
buyerTokenAmount: BigNumber;
priceInWei: BigNumber;
}
export const useOffersComputedDatas: UseOffersComputedDatas = (offer, amount) => {

const price = parseFloat(offer.price);
const priceInWei = new BigNumber(price.toString()).shiftedBy(Number(offer.buyerTokenDecimals));

const amountInWei = new BigNumber(parseInt(new BigNumber(amount.toString()).shiftedBy(Number(offer.offerTokenDecimals)).toString()));
const buyerTokenAmount = new BigNumber(parseInt(amountInWei.multipliedBy(priceInWei).shiftedBy(-offer.offerTokenDecimals).toString()));

return{
amountInWei,
buyerTokenAmount,
priceInWei
}
}

type UseApproveOffer = (
offer: Offer,
amountToCheck: number
) => {
approveNeeded: boolean;
approve: () => Promise<void>;
approveLoading: boolean;
}
export const useApproveOffer: UseApproveOffer = (offer, amount) => {

const [approveNeeded, setApproveNeeded] = useState<boolean>(false);
const [approveLoading, setApproveLoading] = useState<boolean>(false);

const { buyerTokenAmount } = useOffersComputedDatas(offer, amount);
const { account, provider } = useWeb3React();
const activeChain = useActiveChain();

const realTokenYamUpgradeable = useContract(ContractsID.realTokenYamUpgradeable);

const buyerToken = useMemo(() => getContract<CoinBridgeToken>(
offer.buyerTokenAddress,
coinBridgeTokenABI,
provider as Web3Provider,
account
),[offer, account, provider]);

const checkApproval = async () => {
if(!buyerToken || !realTokenYamUpgradeable || !account || buyerTokenAmount.isNaN()) return;
try{

const allowance = await buyerToken.allowance(account, realTokenYamUpgradeable.address);
console.log("ALLOWANCE: ", allowance.toString());
console.log("buyerTokenAmount: ", buyerTokenAmount.toString(10));

setApproveNeeded(allowance.lt(buyerTokenAmount.toString(10)));
}catch(err){
console.error('Cannot check approval: ', err);
}
}

const approve = async () => {
if(!buyerToken || !realTokenYamUpgradeable) return;
try{

setApproveLoading(true);

const approveTx = await buyerToken.approve(
realTokenYamUpgradeable.address,
buyerTokenAmount.toString(10)
);

const notificationApprove = {
key: approveTx.hash,
href: `${activeChain?.blockExplorerUrl}tx/${approveTx.hash}`,
hash: approveTx.hash,
};

showNotification(
NOTIFICATIONS[NotificationsID.approveOfferLoading](
notificationApprove
)
);

approveTx
.wait()
.then(({ status }) =>
updateNotification(
NOTIFICATIONS[
status === 1
? NotificationsID.approveOfferSuccess
: NotificationsID.approveOfferError
](notificationApprove)
)
);

approveTx.wait(1)
.then(({ status }) => {
if(status == 1){
setApproveNeeded(false);
setApproveLoading(false)
}
});

}catch(err){
console.error('Cannot approve: ', err);
setApproveLoading(false);
}
}

useEffect(() => {
checkApproval();
},[offer, amount]);

return{
approveNeeded: approveNeeded,
approve,
approveLoading
}
}
14 changes: 13 additions & 1 deletion src/utils/tx/buy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@ export enum BUY_METHODS{
buyWithPermit = "buyWithPermit"
}

export const approve = async (

) => {
try{



}catch(err){
console.error(err);
}
}

export const buy = async (
account: string|undefined,
provider: Web3Provider|undefined,
Expand Down Expand Up @@ -272,7 +284,7 @@ export const buy = async (
);

await approveTx.wait(1);

}

const buyTx = await realTokenYamUpgradeable.buy(
Expand Down

0 comments on commit be3204f

Please sign in to comment.