Skip to content

Commit

Permalink
Some improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
alexkeating committed Nov 28, 2023
1 parent 2972c88 commit b036405
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 32 deletions.
2 changes: 1 addition & 1 deletion components/ErrorBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default function ErrorBox({ heading, children }: { heading: string; child
<div className="flex-shrink-0">
<XCircleIcon className="h-5 w-5 text-red-400" aria-hidden="true" />
</div>
<div className="ml-3 w-full overflow-scroll">
<div className="ml-3 w-full">
<h3 className="text-sm font-medium text-red-800">{heading}</h3>
<div className="mt-2 text-sm text-red-700">{children}</div>
</div>
Expand Down
4 changes: 4 additions & 0 deletions config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import { goerli, optimismGoerli } from 'wagmi/chains';

export const chains = [goerli, optimismGoerli];

declare global {
function isNaN(number: number | string): boolean;
}

export enum DaoId {
PoolTogether = 'pool-together',
Gitcoin = 'gitcoin',
Expand Down
6 changes: 6 additions & 0 deletions hooks/useEasyWrite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ export const useEasyWrite = (
data: writeData,
error: writeError,
isLoading: writeIsLoading,
isSuccess: writeIsSuccess,
write: contractWrite,
status,
} = useContractWrite(config);
console.log('In hook');
console.log(contractWrite);
const {
error: waitError,
data: transactionData,
Expand All @@ -37,6 +40,7 @@ export const useEasyWrite = (
isTransactionDataLoading,
waitError,
});
console.log('Waitint ended');

useEffect(() => {
// The different statuses that we intend to show are:
Expand Down Expand Up @@ -113,5 +117,7 @@ export const useEasyWrite = (
isTransactionDataLoading,
error,
write: contractWrite,
isSuccess: writeIsSuccess,
status,
};
};
94 changes: 63 additions & 31 deletions pages/[id]/bridge.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import Head from 'next/head';
import Image from 'next/image';
import { useState } from 'react';
import { useForm } from 'react-hook-form';
import { formatUnits, maxUint256, parseAbi, parseUnits } from 'viem';
import { useAccount, useContractRead, useNetwork, useWalletClient } from 'wagmi';

import CardWithHeader from '@/components/CardWithHeader';
import { ExclamationCircleIcon } from '@heroicons/react/20/solid';
import { useHasMounted } from '@/hooks/useHasMounted';
import { useConfig } from '@/hooks/useConfig';
import { useState } from 'react';
import { formatUnits, maxUint256, parseAbi, parseUnits } from 'viem';
import { classNames, switchChain } from '@/util';
import { ZERO_ADDRESS } from '@/util/constants';
import { ArrowLongDownIcon } from '@heroicons/react/20/solid';
import { useBalances } from '@/hooks/useBalances';
import { useFees } from '@/hooks/useFees';
import { useAccount, useContractRead, useNetwork } from 'wagmi';
import { useEasyWrite } from '@/hooks/useEasyWrite';
import ErrorBox from '@/components/ErrorBox';
import Spinner from '@/components/Spinner';
import { useWalletClient } from 'wagmi';
import Image from 'next/image';
import { useTokenInfo } from '@/hooks/useTokenInfo';

enum BridgeTarget {
Expand All @@ -33,6 +34,10 @@ enum ErrorType {

type ErrorReturnType = { errorType?: ErrorType; errorReason?: string };

type FormData = {
amount: string;
};

const Bridge = () => {
const mounted = useHasMounted();
const { fees } = useFees();
Expand All @@ -44,9 +49,19 @@ const Bridge = () => {
const { chain } = useNetwork();
const { data: walletClient, isLoading: walletIsLoading } = useWalletClient();

const {
register,
handleSubmit,
formState: { errors, isValid },
watch,
} = useForm<FormData>({ mode: 'onChange' });

// State for amount input
const [amount, setAmount] = useState<string>('0');
const rawAmount = parseUnits(amount, l1.token?.decimals || 18);
const amount = watch('amount', '0');
const rawAmount = parseUnits(
Boolean(errors.amount?.message) || isNaN(amount) ? '0' : amount,
l1.token?.decimals || 18
);
const isNonZeroInput = rawAmount !== BigInt(0);
const source =
bridgeTarget === BridgeTarget.L2
Expand Down Expand Up @@ -105,10 +120,10 @@ const Bridge = () => {
const {
write: bridgeToL2,
isLoading: bridgeToL2IsLoading,
isSuccess,
error: bridgeToL2Error,
} = useEasyWrite({
enabled:
isNonZeroInput &&
bridgeTarget === BridgeTarget.L2 &&
!needsAllowanceL1 &&
!approveL1IsLoading &&
Expand All @@ -123,14 +138,20 @@ const Bridge = () => {
value: fees?.l1 || BigInt(0),
isCrossChain: true,
});
console.log('Nrp');
console.log(bridgeToL2);
console.log(bridgeToL2IsLoading);
console.log(isSuccess);
console.log(amount);
console.log(isValid);

// 2️⃣ l2 bridge to l1
const {
write: bridgeToL1,
isLoading: bridgeToL1IsLoading,
error: bridgeToL1Error,
} = useEasyWrite({
enabled: isNonZeroInput && bridgeTarget === BridgeTarget.L1 && source.chain.id === chain?.id,
enabled: bridgeTarget === BridgeTarget.L1 && source.chain.id === chain?.id,
address: l2Config.tokenAddress,
chainId: l2Config.chain.id,
abi: parseAbi(['function l1Unlock(address to, uint256 amount) public payable']),
Expand All @@ -144,17 +165,15 @@ const Bridge = () => {
setBridgeTarget(bridgeTarget === BridgeTarget.L2 ? BridgeTarget.L1 : BridgeTarget.L2);
};

const handleInputChange = (e: React.FormEvent<HTMLInputElement>) => {
setAmount(e.currentTarget.value);
};

const handleAllowance = () => {
if (!approveL1) return;
approveL1();
};

const handleBridge = () => {
if (bridgeTarget === BridgeTarget.L2) {
console.log('Handle');
console.log(bridgeToL2);
if (!bridgeToL2) throw new Error('bridgeToL2 is not defined');
bridgeToL2();
} else {
Expand All @@ -163,6 +182,10 @@ const Bridge = () => {
}
};

const onSubmit = handleSubmit(async () => {
handleBridge();
});

const formatError = (e: Error | null): ErrorReturnType => {
if (!isSufficientBalance) {
return {
Expand Down Expand Up @@ -204,7 +227,8 @@ const Bridge = () => {
e.message?.includes(errorSearchString)
);
if (!foundError) {
return { errorType: ErrorType.Unknown, errorReason: `Can't parse error.\n\n${e.message}.` };
console.error(e.message);
return { errorType: ErrorType.Unknown, errorReason: `Error cannot be parsed` };
}
return { errorType: foundError.errorType, errorReason: foundError.prettyReason };
};
Expand All @@ -217,7 +241,6 @@ const Bridge = () => {
const { errorType, errorReason } = formatError(error);
// Helpers for different parts of UI state
const isAmountError = errorType === ErrorType.ERC20AmountError;
const isEthError = errorType === ErrorType.InsufficientNativeCurrencyError;

return (
<>
Expand Down Expand Up @@ -261,37 +284,48 @@ const Bridge = () => {
/>
</div>
{/* Bottom row: Input form */}
<div className="mt-7 mx-2">
<form onSubmit={onSubmit} className="mt-7 mx-2">
<label htmlFor="amount" className="block text-sm font-medium leading-6 text-gray-900">
Amount
</label>
<div className="relative mt-2 rounded-md shadow-sm">
<input
type="number"
min="0"
name="amount"
id="amount"
className={classNames(
errorType === ErrorType.ERC20AmountError
errorType === ErrorType.ERC20AmountError || !isValid
? 'text-red-900 ring-red-300 placeholder:text-red-300 focus:ring-red-500'
: 'text-gray-900',
'block w-full rounded-md border-0 py-1.5 pr-10 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-500 sm:text-sm sm:leading-6'
)}
placeholder="0.00"
defaultValue=""
aria-invalid={errorType === ErrorType.ERC20AmountError}
aria-invalid={errorType === ErrorType.ERC20AmountError || !isValid}
aria-describedby="amount"
onChange={handleInputChange}
{...register('amount', {
validate: async (value) => {
// isNan coerces to a number
if (isNaN(value)) {
return 'Amount needs to be a number';
}
if (parseFloat(value) <= 0) {
return 'Amount must be positive';
}
return true;
},
})}
/>
<div
className={classNames(
'pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3',
isAmountError ? '' : 'invisible'
isAmountError || !isValid ? '' : 'invisible'
)}
>
<ExclamationCircleIcon className="h-5 w-5 text-red-500" aria-hidden="true" />
</div>
</div>
{mounted && errors?.amount && (
<p className="text-sm text-red-600">{errors.amount.message}</p>
)}

<p
className={classNames(
'mt-2 text-sm text-red-600',
Expand Down Expand Up @@ -348,14 +382,12 @@ const Bridge = () => {
mounted && (
/* ⚪️ Finally, we can show the bridge button. */
<button
type="button"
type="submit"
className="mt-5 mx-auto flex flex-row items-center rounded-md bg-indigo-600 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 disabled:bg-gray-300 disabled:cursor-not-allowed"
onClick={handleBridge}
disabled={
rawAmount === BigInt(0) ||
(bridgeTarget === BridgeTarget.L2
? !bridgeToL2 || bridgeToL2IsLoading || isEthError
: !bridgeToL1 || bridgeToL1IsLoading || isEthError)
bridgeTarget === BridgeTarget.L2
? !bridgeToL2 || bridgeToL2IsLoading || !isNonZeroInput || !isValid
: bridgeToL1IsLoading || !isValid
}
>
Bridge to {target.chain.name}
Expand All @@ -375,7 +407,7 @@ const Bridge = () => {
</ErrorBox>
)}
</div>
</div>
</form>
</div>
</CardWithHeader>
</div>
Expand Down

0 comments on commit b036405

Please sign in to comment.