import { atom, useRecoilState } from "recoil"; import { BigNumber } from "ethers"; import { __, add, assoc, evolve, subtract } from "ramda"; import { useWeb3Provider } from "../useWeb3Provider/useWeb3Provider"; import { weiBigNumAsFloat } from "../../utils/parse/parse"; import { formatUnits } from "ethers/lib/utils"; import { Erc20ABI__factory } from "digit-shared/src/types/generatedContractTypes"; import { config } from "../../config"; type TokenDetail = { address: string; allowance: number; depositHelperAllowance: number; decimalPlaces: number; userBalance: string; }; export const tokenDetailState = atom>({ key: "tokenDetailState", default: {}, }); export const useTokenDetails = () => { const [tokenDetails, setTokenDetails] = useRecoilState(tokenDetailState); const { account, signer, provider } = useWeb3Provider(); const approveTokenSpend = (contractAddress: string, amount: number) => setTokenDetails( evolve({ [contractAddress]: { allowance: add(amount), }, }) ); const creditUserTokenBalance = (contractAddress: string, amount: number) => setTokenDetails( evolve({ [contractAddress]: { userBalance: (balance: string) => BigNumber.from(balance).add(amount).toString(), }, }) ); const debitUserTokenBalance = (contractAddress: string, amount: number) => setTokenDetails( evolve({ [contractAddress]: { allowance: subtract(__, amount), userBalance: (balance: string) => BigNumber.from(balance).sub(amount).toString(), }, }) ); const fetchNativeTokenDetails = async () => { const balance = await provider!.getBalance(account!); setTokenDetails( assoc("0x", { address: "0x", allowance: 999999999, depositHelperAllowance: 999999999, decimalPlaces: 18, userBalance: formatUnits(balance, 18), }) ); }; const fetchTokenDetails = async (contractAddress: string) => { if (contractAddress === "0x") return fetchNativeTokenDetails(); fetchNativeTokenDetails(); //shouldn't do this const contract = Erc20ABI__factory.connect(contractAddress, signer!); const [balance, decimals, allowance, depositHelperAllowance] = await Promise.all([ contract.balanceOf(account!), contract.decimals(), contract.allowance( account!, config!.reliquaryContractAddress ), contract.allowance( account!, config!.reliquaryHelperContractAddress ), ]); const decimalPlaces = decimals; setTokenDetails( assoc(contractAddress, { address: contractAddress, allowance: weiBigNumAsFloat(allowance, decimalPlaces), depositHelperAllowance: weiBigNumAsFloat( depositHelperAllowance, decimalPlaces ), decimalPlaces, userBalance: formatUnits(balance, decimalPlaces), }) ); }; return { approveTokenSpend, creditUserTokenBalance, debitUserTokenBalance, fetchTokenDetails, fetchNativeTokenDetails, tokenDetails, }; };