Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add error UX #29

Merged
merged 1 commit into from
Aug 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,19 @@ import { AddressInput, InputBase } from "~~/components/scaffold-eth";
import { ERC1155Tx } from "~~/types/business";
import { ERC1155_ABI } from "~~/utils/constants";
import { getTargetNetwork } from "~~/utils/scaffold-eth";
import { useShowError } from "~~/hooks/flashbotRecoveryBundle/useShowError";


const erc1155Interface = new ethers.utils.Interface(ERC1155_ABI);

export const ERC1155Form = ({ hackedAddress, safeAddress, addAsset, close }: ITokenForm) => {
const [contractAddress, setContractAddress] = useState<string>("");
const [tokenIds, setTokenIds] = useState<string>("");
const publicClient = usePublicClient({ chainId: getTargetNetwork().id });

const {showError} = useShowError()
const addErc1155TxToBasket = async () => {
if (!isAddress(contractAddress) || !tokenIds) {
alert("Provide an ERC1155 contract and token IDs");
showError("Provide an ERC1155 contract and token IDs");
return;
}

Expand All @@ -44,7 +46,7 @@ export const ERC1155Form = ({ hackedAddress, safeAddress, addAsset, close }: ITo
}
}
if (tokenIdsWithInvalidBalances.length > 0) {
alert(
showError(
`Remove following tokenIds as hacked account does not own them: ${tokenIdsWithInvalidBalances.toString()}`,
);
return;
Expand Down Expand Up @@ -73,7 +75,7 @@ export const ERC1155Form = ({ hackedAddress, safeAddress, addAsset, close }: ITo
addAsset(newErc1155Tx);
} catch (e) {
console.error(e);
alert(`Couldn't read the contract. See the console for the error.`);
showError(`Couldn't read the contract. See the console for the error.`);
return;
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ import { AddressInput } from "~~/components/scaffold-eth";
import { ERC20Tx } from "~~/types/business";
import { ERC20_ABI } from "~~/utils/constants";
import { getTargetNetwork } from "~~/utils/scaffold-eth";
import { useShowError } from "~~/hooks/flashbotRecoveryBundle/useShowError";

const erc20Interface = new ethers.utils.Interface(ERC20_ABI);

export const ERC20Form = ({ hackedAddress, safeAddress, addAsset, close }: ITokenForm) => {
const [contractAddress, setContractAddress] = useState<string>("");

const {showError} = useShowError()
let erc20Balance: string = "NO INFO";
try {
let { data } = useContractRead({
Expand All @@ -35,14 +36,15 @@ export const ERC20Form = ({ hackedAddress, safeAddress, addAsset, close }: IToke
// Most probably the contract address is not valid as user is
// still typing, so ignore.
}


const addErc20TxToBasket = (balance: string) => {
if (!isAddress(contractAddress)) {
alert("Provide a contract first");
showError("Provide a contract first");
return;
}
if (balance == "NO INFO") {
alert("Hacked account has no balance in given erc20 contract");
showError("Hacked account has no balance in given erc20 contract");
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,19 @@ import { AddressInput, InputBase } from "~~/components/scaffold-eth";
import { ERC721Tx } from "~~/types/business";
import { ERC721_ABI } from "~~/utils/constants";
import { getTargetNetwork } from "~~/utils/scaffold-eth";
import { useShowError } from "~~/hooks/flashbotRecoveryBundle/useShowError";


const erc721Interface = new ethers.utils.Interface(ERC721_ABI);

export const ERC721Form = ({ hackedAddress, safeAddress, addAsset, close }: ITokenForm) => {
const [contractAddress, setContractAddress] = useState<string>("");
const [tokenId, setTokenId] = useState<string>("");
const publicClient = usePublicClient({ chainId: getTargetNetwork().id });

const {showError} = useShowError()
const addErc721TxToBasket = async () => {
if (!isAddress(contractAddress) || !tokenId) {
alert("Provide a contract and a token ID");
showError("Provide a contract and a token ID");
return;
}

Expand All @@ -36,7 +38,7 @@ export const ERC721Form = ({ hackedAddress, safeAddress, addAsset, close }: ITok
} catch (e) {}

if (!ownerOfGivenTokenId || ownerOfGivenTokenId.toString() != hackedAddress) {
alert(`Couldn't verify hacked account's ownership. Cannot add to the basket...`);
showError(`Couldn't verify hacked account's ownership. Cannot add to the basket...`);
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,28 @@ import { isAddress } from "ethers/lib/utils";
import { motion } from "framer-motion";
import { CustomButton } from "~~/components/CustomButton/CustomButton";
import { AddressInput } from "~~/components/scaffold-eth";
import { useShowError } from "~~/hooks/flashbotRecoveryBundle/useShowError";

interface IProps {
isVisible: boolean;
safeAddress: string;
onSubmit: (address: string) => void;
}
export const HackedAddressStep = ({ isVisible, safeAddress, onSubmit }: IProps) => {
if (!isVisible) {
return <></>;
}

const {showError} = useShowError();
const [hackedAddress, setHackedAddressCore] = useState<string>("");
const setHackedAddress = (hackedAddress: string) => {
if (safeAddress == hackedAddress) {
//TODO: modal
alert("Cannot select safe and hacked addresses the same");
showError("Cannot select safe and hacked addresses the same");
setHackedAddressCore("");
return;
}
setHackedAddressCore(hackedAddress);
};

if (!isVisible) {
return <></>;
}

return (
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} className={styles.container}>
Expand All @@ -43,7 +44,7 @@ export const HackedAddressStep = ({ isVisible, safeAddress, onSubmit }: IProps)
text={"Continue"}
onClick={() => {
if (!isAddress(hackedAddress)) {
alert("Given hacked address is not a valid address");
showError("Given hacked address is not a valid address");
return;
}
onSubmit(hackedAddress);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from "react";
import { CustomPortal } from "~~/components/CustomPortal/CustomPortal";
import { useShowError } from "~~/hooks/flashbotRecoveryBundle/useShowError";
import ClockSvg from "~~/public/assets/flashbotRecovery/clock.svg";
import LogoSvg from "~~/public/assets/flashbotRecovery/logo.svg";
import SuccessSvg from "~~/public/assets/flashbotRecovery/success.svg";
Expand All @@ -16,6 +17,7 @@ interface IProps {
hackedAddress: string;
blockCountdown: number;
}

export const RecoveryProcess = ({
recoveryStatus,
startSigning,
Expand All @@ -26,12 +28,14 @@ export const RecoveryProcess = ({
safeAddress,
hackedAddress,
}: IProps) => {
const {showError} = useShowError();

if (recoveryStatus == RecoveryProcessStatus.INITIAL) {
return <></>;
}

if (recoveryStatus == RecoveryProcessStatus.GAS_PAID) {
alert("you already covered the gas. If you're in a confussy situation, clear cookies and refresh page.");
showError("you already covered the gas. If you're in a confussy situation, clear cookies and refresh page.");
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { AbiFunction } from "abitype";
import { ethers } from "ethers";
import { FunctionFragment } from "ethers/lib/utils";
import { Address } from "viem";

import {
ContractInput,
IntegerInput,
Expand All @@ -13,6 +14,7 @@ import {
} from "~~/components/scaffold-eth";
import { CustomTx, RecoveryTx } from "~~/types/business";
import { notification } from "~~/utils/scaffold-eth";
import { useShowError } from "~~/hooks/flashbotRecoveryBundle/useShowError";

type WriteOnlyFunctionFormProps = {
abiFunction: AbiFunction;
Expand All @@ -31,6 +33,8 @@ export const CustomContractWriteForm = ({
hackedAddress,
contractAddress,
}: WriteOnlyFunctionFormProps) => {
const {showError} = useShowError();

const [form, setForm] = useState<Record<string, any>>(() => getInitialFormState(abiFunction));
const [txValue, setTxValue] = useState<string | bigint>("");

Expand Down Expand Up @@ -74,7 +78,7 @@ export const CustomContractWriteForm = ({
onClick={async () => {
try {
if (!fragmentString) {
alert("refresh page and try again");
showError("refresh page and try again");
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from "~~/types/business";
import { ERC20_ABI, ERC721_ABI, ERC1155_ABI } from "~~/utils/constants";
import { getTargetNetwork } from "~~/utils/scaffold-eth";
import { useShowError } from "./useShowError";

const erc20Interface = new ethers.utils.Interface(ERC20_ABI);
const erc721Interface = new ethers.utils.Interface(ERC721_ABI);
Expand All @@ -24,6 +25,7 @@ export const useAutodetectAssets = () => {
[account: string]: RecoveryTx[];
}>("autoDetectedAssets", {});

const {showError} = useShowError();
const targetNetwork = getTargetNetwork();
const [alchemy] = useState<Alchemy>(
new Alchemy({
Expand Down Expand Up @@ -51,6 +53,7 @@ export const useAutodetectAssets = () => {
.map(res => res.transfers)
.flat();


const getAutodetectedAssets = async (
hackedAddress: string,
safeAddress: string,
Expand All @@ -65,7 +68,7 @@ export const useAutodetectAssets = () => {
return;
}
if (!alchemy) {
alert("Seems Alchemy API rate limit has been reached. Contact [email protected]");
showError("Seems Alchemy API rate limit has been reached. Contact [email protected]");
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { BigNumber, ethers } from "ethers";
import { usePublicClient } from "wagmi";
import { RecoveryTx } from "~~/types/business";
import { getTargetNetwork } from "~~/utils/scaffold-eth";
import { useShowError } from "./useShowError";

const BLOCKS_IN_THE_FUTURE: { [i: number]: number } = {
1: 7,
Expand All @@ -12,7 +13,7 @@ const BLOCKS_IN_THE_FUTURE: { [i: number]: number } = {
export const useGasEstimation = () => {
const targetNetwork = getTargetNetwork();
const publicClient = usePublicClient({ chainId: targetNetwork.id });

const {showError} = useShowError();
const estimateTotalGasPrice = async (txs: RecoveryTx[], deleteTransaction: (id: number) => void) => {
const tempProvider = new ethers.providers.InfuraProvider(targetNetwork.id, "416f5398fa3d4bb389f18fd3fa5fb58c");
try {
Expand All @@ -32,13 +33,14 @@ export const useGasEstimation = () => {
}),
);


return estimates
.reduce((acc: BigNumber, val: BigNumber) => acc.add(val), BigNumber.from("0"))
.mul(await maxBaseFeeInFuture())
.mul(105)
.div(100);
} catch (e) {
alert(
showError(
"Error estimating gas prices. Something can be wrong with one of the transactions. Check the console and remove problematic tx.",
);
console.error(e);
Expand Down
19 changes: 11 additions & 8 deletions packages/nextjs/hooks/flashbotRecoveryBundle/useRecoveryProcess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useAccount, usePublicClient, useWalletClient } from "wagmi";
import { RecoveryTx } from "~~/types/business";
import { RecoveryProcessStatus } from "~~/types/enums";
import { getTargetNetwork } from "~~/utils/scaffold-eth";
import { useShowError } from "./useShowError";

interface IStartProcessPops {
safeAddress: string;
Expand All @@ -31,6 +32,7 @@ export const useRecoveryProcess = () => {
const [sentTxHash, setSentTxHash] = useLocalStorage<string>("sentTxHash", "");
const [sentBlock, setSentBlock] = useLocalStorage<number>("sentBlock", 0);
const [blockCountdown, setBlockCountdown] = useLocalStorage<number>("blockCountdown", 0);
const {showError} = useShowError();

const [stepActive, setStepActive] = useState<RecoveryProcessStatus>(RecoveryProcessStatus.INITIAL);
const publicClient = usePublicClient({ chainId: targetNetwork.id });
Expand All @@ -53,6 +55,7 @@ export const useRecoveryProcess = () => {
})();
}, [targetNetwork.id]);


useInterval(async () => {
const isNotAbleToListenBundle = stepActive != RecoveryProcessStatus.LISTEN_BUNDLE || !sentTxHash || sentBlock == 0;
try {
Expand All @@ -63,7 +66,7 @@ export const useRecoveryProcess = () => {
setBlockCountdown(blockDelta);

if (blockDelta < 0) {
alert("Error, try again");
showError("Error, try again");
setSentBlock(0);
setSentTxHash("");
resetStatus();
Expand Down Expand Up @@ -122,7 +125,7 @@ export const useRecoveryProcess = () => {
surpass: boolean = false,
) => {
if (!surpass && !gasCovered) {
alert("How did you come here without covering the gas fee first??");
showError("How did you come here without covering the gas fee first??");
resetStatus();
return;
}
Expand All @@ -141,14 +144,14 @@ export const useRecoveryProcess = () => {
setGasCovered(false);
await sendBundle(currentBundleId);
} catch (e) {
alert(`FAILED TO SIGN TXS Error: ${e}`);
showError(`FAILED TO SIGN TXS Error: ${e}`);
resetStatus();
}
};

const sendBundle = async (currentBundleId: string) => {
if (!flashbotsProvider) {
alert("Flashbot provider not available");
showError("Flashbot provider not available");
resetStatus();
return;
}
Expand All @@ -160,7 +163,7 @@ export const useRecoveryProcess = () => {
)
).json();
if (!finalBundle || !finalBundle.rawTxs) {
alert("Couldn't fetch latest bundle");
showError("Couldn't fetch latest bundle");
resetStatus();
return;
}
Expand Down Expand Up @@ -188,14 +191,14 @@ export const useRecoveryProcess = () => {
console.error(e);
setSentTxHash("");
setSentBlock(0);
alert("Error submitting bundles. Check console for details.");
showError("Error submitting bundles. Check console for details.");
resetStatus();
}
} catch (e) {
console.error(e);
setSentTxHash("");
setSentBlock(0);
alert("Error submitting bundles. Check console for details.");
showError("Error submitting bundles. Check console for details.");
resetStatus();
}
};
Expand Down Expand Up @@ -223,7 +226,7 @@ export const useRecoveryProcess = () => {
return;
} catch (e) {
resetStatus();
alert(`Error while adding a custom RPC and signing the funding transaction with the safe account. Error: ${e}`);
showError(`Error while adding a custom RPC and signing the funding transaction with the safe account. Error: ${e}`);
}
};

Expand Down
Loading