Skip to content

Commit

Permalink
fix: display error when connect to wrong network
Browse files Browse the repository at this point in the history
  • Loading branch information
Wagalidoom committed May 15, 2024
1 parent 00a5055 commit b31afaf
Show file tree
Hide file tree
Showing 10 changed files with 143 additions and 137 deletions.
2 changes: 1 addition & 1 deletion app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default function RootLayout({
return (
<html lang="en">
<body className={inter.className}>
<div className="bg-[url('../public/background.jpg')] bg-cover bg-center w-full h-full">
<div className="bg-[url('../public/background.jpg')] bg-cover bg-center w-full h-full text-white">
<Providers>{children}</Providers>
</div>
</body>
Expand Down
16 changes: 12 additions & 4 deletions components/dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ export default function Dashboard() {
const [connectionAttempted, setConnectionAttemped] = useState(false);
const { disconnect } = useDisconnect();
const router = useRouter();
const { balance } = useDeposit();
const { balance, isWrongNetwork } = useDeposit();
const [address, setAddress] = useState("");
const [networkMessage, setNetworkMessage] = useState("");
const [network, setNetwork] = useState("");

useEffect(() => {
Expand All @@ -28,6 +29,12 @@ export default function Dashboard() {
}
}, [account.address]);

useEffect(() => {
if (isWrongNetwork) {
setNetworkMessage("Wrong Network. Please connect to Gnosis Chain");
}
}, [isWrongNetwork]);

useEffect(() => {
if (account.chain?.name) {
setNetwork(account.chain.name);
Expand All @@ -37,10 +44,10 @@ export default function Dashboard() {
useEffect(() => {
if (account.isConnecting) {
setConnectionAttemped(true);
} else if(connectionAttempted && !account.isConnected) {
} else if (connectionAttempted && !account.isConnected) {
router.push("/");
}
}, [account.isConnecting]);
}, [account.isConnecting, connectionAttempted, account.isConnected]);

const handleCopyAddress = async () => {
if (account.address) {
Expand All @@ -61,14 +68,15 @@ export default function Dashboard() {
<p className="font-bold text-xl lg:text-2xl">{searchParams.get("state") == "validator" ? "Check Validators Status" : "Gnosis Beacon Chain Deposit"}</p>
<div className="w-full flex mt-4">
<div className="w-full lg:w-2/6 flex flex-col text-base">
<p className="text-red-400 text-sm rounded-md">{networkMessage}</p>
<div className="w-min bg-[#133629] hidden lg:flex items-center rounded-full mt-4 mb-2 lg:mb-7 text-white p-2 hover:cursor-pointer hover:bg-[#2a4a3e]" onClick={handleCopyAddress}>
{truncateAddress(address)} {isCopied ? <CheckIcon className="ml-2 h-5 w-5" /> : <DocumentDuplicateIcon className="ml-2 h-5 w-5" />}
</div>
<div className="flex lg:hidden">{searchParams.get("state") == "deposit" ? <Deposit /> : searchParams.get("state") == "withdrawal" ? <Withdrawal /> : searchParams.get("state") == "validator" ? <Validator /> : "no route"}</div>
<div className="flex flex-col gap-y-4 justify-between items-start mt-4 lg:mt-0">
<div>
Balance:
<p className="font-bold text-2xl lg:text-4xl">{Math.round(Number(formatEther(balance || BigInt(0))))} GNO</p>
<p className="font-bold text-xl lg:text-3xl">{Math.round(Number(formatEther(balance || BigInt(0))))} GNO</p>
</div>
<div>
Network:
Expand Down
3 changes: 2 additions & 1 deletion components/deposit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ export default function Deposit() {
};
reader.readAsText(acceptedFiles[0]);
}
}, []);
}, [setDepositData]);

const { getRootProps, getInputProps } = useDropzone({ onDrop, accept: { "application/json": [] }, maxFiles: 1 });

const onDeposit = useCallback(async () => {
Expand Down
2 changes: 1 addition & 1 deletion components/validator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export default function Validator() {
}
}
}
}, []);
}, [validateStatus]);
const { getRootProps, getInputProps } = useDropzone({ onDrop, accept: { "application/json": [] } });

return (
Expand Down
3 changes: 1 addition & 2 deletions components/withdrawal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export default function Withdrawal() {

const handleRadioChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setTimeValue(parseFloat(event.target.value));
console.log(parseFloat(event.target.value));
};

const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
Expand All @@ -35,7 +34,7 @@ export default function Withdrawal() {
await register(timeValue, amountValue);
}
}
}, [timeValue, amountValue, register, updateConfig]);
}, [timeValue, amountValue, isRegister, register, updateConfig]);

const onClaim = useCallback(async () => {
setLoading(true);
Expand Down
20 changes: 11 additions & 9 deletions hooks/use-autoclaim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ function useAutoclaim() {
hash,
});

if (!contractConfig) {
throw Error(`No contract configuration found for chain ID ${chainId}`);
}

useEffect(() => {
async function fetchEvents() {
if (contractConfig && account.address && account.address !== "0x0") {
Expand Down Expand Up @@ -49,22 +45,28 @@ function useAutoclaim() {

const register = useCallback(
async (days: number, amount: number) => {
const timeStamp = BigInt(days * 86400000);
writeContract({ address: contractConfig.addresses.claimRegistry, abi: claimRegistryABI, functionName: "register", args: [account.address || "0x0", timeStamp, BigInt(amount)] });
if (contractConfig) {
const timeStamp = BigInt(days * 86400000);
writeContract({ address: contractConfig.addresses.claimRegistry, abi: claimRegistryABI, functionName: "register", args: [account.address || "0x0", timeStamp, BigInt(amount)] });
}
},
[account]
);

const updateConfig = useCallback(
async (days: number, amount: number) => {
const timeStamp = BigInt(days * 86400000);
writeContract({ address: contractConfig.addresses.claimRegistry, abi: claimRegistryABI, functionName: "updateConfig", args: [account.address || "0x0", timeStamp, BigInt(amount)] });
if (contractConfig) {
const timeStamp = BigInt(days * 86400000);
writeContract({ address: contractConfig.addresses.claimRegistry, abi: claimRegistryABI, functionName: "updateConfig", args: [account.address || "0x0", timeStamp, BigInt(amount)] });
}
},
[account]
);

const unregister = useCallback(async () => {
writeContract({ address: contractConfig.addresses.claimRegistry, abi: claimRegistryABI, functionName: "unregister", args: [account.address || "0x0"] });
if (contractConfig) {
writeContract({ address: contractConfig.addresses.claimRegistry, abi: claimRegistryABI, functionName: "unregister", args: [account.address || "0x0"] });
}
}, [account]);

return { register, updateConfig, unregister, isRegister, autoclaimSuccess };
Expand Down
12 changes: 5 additions & 7 deletions hooks/use-claim-balance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,11 @@ function useClaimBalance() {
hash,
});

if (!contractConfig) {
throw Error(`No contract configuration found for chain ID ${chainId}`);
}

const claim = useCallback(async() =>{
writeContract({ address: contractConfig.addresses.deposit, abi: depositABI, functionName: "claimWithdrawal", args: [account.address || "0x0"] });
}, [account])
const claim = useCallback(async () => {
if (contractConfig) {
writeContract({ address: contractConfig.addresses.deposit, abi: depositABI, functionName: "claimWithdrawal", args: [account.address || "0x0"] });
}
}, [account]);

return { claim, claimBalance, claimSuccess };
}
Expand Down
174 changes: 86 additions & 88 deletions hooks/use-deposit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,83 +36,81 @@ function useDeposit() {
functionName: "balanceOf",
args: [account.address || "0x0"],
});
const isWrongNetwork = contractConfig === undefined;
const { data: hash, writeContract } = useWriteContract();
const { isSuccess: depositSuccess } = useWaitForTransactionReceipt({
hash,
});

console.log(balance);

if (!contractConfig) {
throw Error(`No contract configuration found for chain ID ${chainId}`);
}

const validate = useCallback(
async (deposits: DepositDataJson[], balance: bigint) => {
const checkJsonStructure = (depositDataJson: DepositDataJson) => {
return depositDataJson.pubkey && depositDataJson.withdrawal_credentials && depositDataJson.amount && depositDataJson.signature && depositDataJson.deposit_message_root && depositDataJson.deposit_data_root && depositDataJson.fork_version;
};
let newDeposits = [];
let hasDuplicates = false;
if (contractConfig) {
const checkJsonStructure = (depositDataJson: DepositDataJson) => {
return depositDataJson.pubkey && depositDataJson.withdrawal_credentials && depositDataJson.amount && depositDataJson.signature && depositDataJson.deposit_message_root && depositDataJson.deposit_data_root && depositDataJson.fork_version;
};

if (!deposits.every) {
throw Error("Oops, something went wrong while parsing your json file. Please check the file and try again.");
}

if (!deposits.every) {
throw Error("Oops, something went wrong while parsing your json file. Please check the file and try again.");
}
if (deposits.length === 0 || !deposits.every((d) => checkJsonStructure(d))) {
throw Error("This is not a valid file. Please try again.");
}

if (deposits.length === 0 || !deposits.every((d) => checkJsonStructure(d))) {
throw Error("This is not a valid file. Please try again.");
}
if (!deposits.every((d) => d.fork_version === contractConfig.forkVersion)) {
throw Error("This JSON file isn't for the right network (" + deposits[0].fork_version + "). Upload a file generated for you current network: " + account.chainId);
}

if (!deposits.every((d) => d.fork_version === contractConfig.forkVersion)) {
throw Error("This JSON file isn't for the right network (" + deposits[0].fork_version + "). Upload a file generated for you current network: " + account.chainId);
}
const { deposits: existingDeposits, lastBlock: fromBlock } = await loadCachedDeposits(chainId, contractConfig.depositStartBlockNumber);

const { deposits: existingDeposits, lastBlock: fromBlock } = await loadCachedDeposits(chainId, contractConfig.depositStartBlockNumber);
const events = await fetchDeposit(contractConfig.addresses.deposit, fromBlock, client);

const events = await fetchDeposit(contractConfig.addresses.deposit, fromBlock, client);
let pks = events.map((e) => e.topics[1]);
pks = pks.concat(existingDeposits);
console.log(`Found ${pks.length} existing deposits`);

let pks = events.map((e) => e.topics[1]);
pks = pks.concat(existingDeposits);
console.log(`Found ${pks.length} existing deposits`);
const newDeposits = [];
for (const deposit of deposits) {
if (!pks.some((pk) => pk === "0x" + deposit.pubkey)) {
newDeposits.push(deposit);
for (const deposit of deposits) {
if (!pks.some((pk) => pk === "0x" + deposit.pubkey)) {
newDeposits.push(deposit);
}
}
}
const hasDuplicates = newDeposits.length !== deposits.length;
hasDuplicates = newDeposits.length !== deposits.length;

if (newDeposits.length === 0) {
throw Error("Deposits have already been made to all validators in this file.");
}
if (newDeposits.length === 0) {
throw Error("Deposits have already been made to all validators in this file.");
}

const wc = newDeposits[0].withdrawal_credentials;
const wc = newDeposits[0].withdrawal_credentials;

// batch processing necessary for both single deposit and batch deposit for same withdrawal_credentials
const isBatch = newDeposits.every((d) => d.withdrawal_credentials === wc);
// batch processing necessary for both single deposit and batch deposit for same withdrawal_credentials
const isBatch = newDeposits.every((d) => d.withdrawal_credentials === wc);

if (isBatch && newDeposits.length > 128) {
throw Error("Number of validators exceeds the maximum batch size of 128. Please upload a file with 128 or fewer validators.");
}
if (isBatch && newDeposits.length > 128) {
throw Error("Number of validators exceeds the maximum batch size of 128. Please upload a file with 128 or fewer validators.");
}

if (!newDeposits.every((d) => BigInt(d.amount) === BigInt(32000000000))) {
throw Error("Amount should be exactly 32 tokens for deposits.");
}
if (!newDeposits.every((d) => BigInt(d.amount) === BigInt(32000000000))) {
throw Error("Amount should be exactly 32 tokens for deposits.");
}

const pubKeys = newDeposits.map((d) => d.pubkey);
if (pubKeys.some((pubkey, index) => pubKeys.indexOf(pubkey) !== index)) {
throw Error("Duplicated public keys.");
}
const pubKeys = newDeposits.map((d) => d.pubkey);
if (pubKeys.some((pubkey, index) => pubKeys.indexOf(pubkey) !== index)) {
throw Error("Duplicated public keys.");
}

const totalDepositAmountBN = depositAmountBN * BigInt(newDeposits.length);
const totalDepositAmountBN = depositAmountBN * BigInt(newDeposits.length);

console.log(balance, contractConfig.addresses.token, account.address, account.chainId);
if (balance === undefined) {
throw Error("Balance not loaded.");
}
if (balance === undefined) {
throw Error("Balance not loaded.");
}

if (balance < totalDepositAmountBN) {
throw Error(`
if (balance < totalDepositAmountBN) {
throw Error(`
Unsufficient balance. ${Number(formatUnits(totalDepositAmountBN, 18))} GNO is required.
`);
}
}

return { deposits: newDeposits, hasDuplicates, isBatch };
Expand All @@ -130,9 +128,7 @@ function useDeposit() {
} catch (error) {
throw Error("Oops, something went wrong while parsing your json file. Please check the file and try again.");
}
if (balance) {
const { deposits, hasDuplicates, isBatch } = await validate(data, balance);
}
const { deposits, hasDuplicates, isBatch } = await validate(data, balance || BigInt(0));
setDeposits(deposits);
setHasDuplicates(hasDuplicates);
setIsBatch(isBatch);
Expand All @@ -146,43 +142,45 @@ function useDeposit() {
);

const deposit = useCallback(async () => {
if (isBatch) {
try {
const totalDepositAmountBN = depositAmountBN * BigInt(deposits.length);
console.log(`Sending deposit transaction for ${deposits.length} deposits`);
let data = "";
data += deposits[0].withdrawal_credentials;
deposits.forEach((deposit) => {
data += deposit.pubkey;
data += deposit.signature;
data += deposit.deposit_data_root;
});
writeContract({ address: contractConfig.addresses.token, abi: ERC677ABI, functionName: "transferAndCall", args: [contractConfig.addresses.deposit, totalDepositAmountBN, `0x${data}`] });
} catch (err) {
console.log(err);
if (contractConfig) {
if (isBatch) {
try {
const totalDepositAmountBN = depositAmountBN * BigInt(deposits.length);
console.log(`Sending deposit transaction for ${deposits.length} deposits`);
let data = "";
data += deposits[0].withdrawal_credentials;
deposits.forEach((deposit) => {
data += deposit.pubkey;
data += deposit.signature;
data += deposit.deposit_data_root;
});
writeContract({ address: contractConfig.addresses.token, abi: ERC677ABI, functionName: "transferAndCall", args: [contractConfig.addresses.deposit, totalDepositAmountBN, `0x${data}`] });
} catch (err) {
console.log(err);
}
} else {
//too much complexity by handling multiple withdrawal credential in one batch?
console.log("sending deposit transaction");
await Promise.all(
deposits.map(async (deposit) => {
let data = "0x";
data += deposit.withdrawal_credentials;
data += deposit.pubkey;
data += deposit.signature;
data += deposit.deposit_data_root;

try {
writeContract({ address: contractConfig.addresses.token, abi: ERC677ABI, functionName: "transferAndCall", args: [contractConfig.addresses.deposit, depositAmountBN, `0x${data}`] });
} catch (error) {
console.log(error);
}
})
);
}
} else {
//too much complexity by handling multiple withdrawal credential in one batch?
console.log("sending deposit transaction");
await Promise.all(
deposits.map(async (deposit) => {
let data = "0x";
data += deposit.withdrawal_credentials;
data += deposit.pubkey;
data += deposit.signature;
data += deposit.deposit_data_root;

try {
writeContract({ address: contractConfig.addresses.token, abi: ERC677ABI, functionName: "transferAndCall", args: [contractConfig.addresses.deposit, depositAmountBN, `0x${data}`] });
} catch (error) {
console.log(error);
}
})
);
}
}, [account, deposits, isBatch]);

return { deposit, depositSuccess, depositData: { deposits, filename, hasDuplicates, isBatch }, setDepositData, balance };
return { deposit, depositSuccess, depositData: { deposits, filename, hasDuplicates, isBatch }, setDepositData, balance, isWrongNetwork };
}

export default useDeposit;

0 comments on commit b31afaf

Please sign in to comment.