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

#119 Tweak warning for undeployed application #124

Merged
25 changes: 14 additions & 11 deletions packages/ui/src/ERC20DepositForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import {
import { useAccount, useContractReads, useWaitForTransaction } from "wagmi";
import { TransactionProgress } from "./TransactionProgress";
import { TransactionStageStatus } from "./TransactionStatus";
import useUndeployedApplication from "./hooks/useUndeployedApplication";

export const transactionButtonState = (
prepare: TransactionStageStatus,
Expand Down Expand Up @@ -241,6 +242,10 @@ export const ERC20DepositForm: FC<ERC20DepositFormProps> = (props) => {
deposit.write,
true,
);
const isUndeployedApp = useUndeployedApplication(
applicationAddress,
applications,
);

useEffect(() => {
if (depositWait.status === "success") {
Expand Down Expand Up @@ -268,17 +273,15 @@ export const ERC20DepositForm: FC<ERC20DepositFormProps> = (props) => {
}}
/>

{isAddress(applicationAddress) &&
applicationAddress !== zeroAddress &&
!applications.length && (
<Alert
variant="light"
color="yellow"
icon={<TbAlertCircle />}
>
This is a deposit to an undeployed application.
</Alert>
)}
{!form.errors.application && isUndeployedApp && (
<Alert
variant="light"
color="yellow"
icon={<TbAlertCircle />}
>
This is a deposit to an undeployed application.
</Alert>
)}

<Autocomplete
label="ERC-20"
Expand Down
29 changes: 14 additions & 15 deletions packages/ui/src/ERC721DepositForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import {
import { useAccount, useContractReads, useWaitForTransaction } from "wagmi";
import { TransactionProgress } from "./TransactionProgress";
import { TransactionStageStatus } from "./TransactionStatus";
import useUndeployedApplication from "./hooks/useUndeployedApplication";
import useTokensOfOwnerByIndex from "./hooks/useTokensOfOwnerByIndex";

export const transactionButtonState = (
Expand Down Expand Up @@ -215,6 +216,10 @@ export const ERC721DepositForm: FC<ERC721DepositFormProps> = (props) => {
approveWait.status !== "success";
const isApproveDisabled =
approveDisabled || !needApproval || !isDepositDisabled;
const isUndeployedApp = useUndeployedApplication(
applicationAddress,
applications,
);

useEffect(() => {
if (tokensOfOwnerByIndex.tokenIds.length === 0) {
Expand Down Expand Up @@ -256,21 +261,15 @@ export const ERC721DepositForm: FC<ERC721DepositFormProps> = (props) => {
}}
/>

{!form.errors.application &&
applicationAddress !== zeroAddress &&
!applications.some(
(a) =>
a.toLowerCase() ===
applicationAddress.toLowerCase(),
) && (
<Alert
variant="light"
color="yellow"
icon={<TbAlertCircle />}
>
This is a deposit to an undeployed application.
</Alert>
)}
{!form.errors.application && isUndeployedApp && (
<Alert
variant="light"
color="yellow"
icon={<TbAlertCircle />}
>
This is a deposit to an undeployed application.
</Alert>
)}

<TextInput
label="ERC-721"
Expand Down
24 changes: 11 additions & 13 deletions packages/ui/src/EtherDepositForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
} from "viem";
import { useNetwork, useWaitForTransaction } from "wagmi";
import { TransactionProgress } from "./TransactionProgress";
import useUndeployedApplication from "./hooks/useUndeployedApplication";

export interface EtherDepositFormProps {
applications: string[];
Expand Down Expand Up @@ -87,6 +88,7 @@ export const EtherDepositForm: FC<EtherDepositFormProps> = (props) => {
const canSubmit =
form.isValid() && !prepare.isLoading && prepare.error === null;
const loading = execute.status === "loading" || wait.status === "loading";
const isUndeployedApp = useUndeployedApplication(address, applications);

useEffect(() => {
if (wait.status === "success") {
Expand Down Expand Up @@ -121,19 +123,15 @@ export const EtherDepositForm: FC<EtherDepositFormProps> = (props) => {
}}
/>

{!form.errors.application &&
address !== zeroAddress &&
!applications.some(
(a) => a.toLowerCase() === address.toLowerCase(),
) && (
<Alert
variant="light"
color="yellow"
icon={<TbAlertCircle />}
>
This is a deposit to an undeployed application.
</Alert>
)}
{!form.errors.application && isUndeployedApp && (
<Alert
variant="light"
color="yellow"
icon={<TbAlertCircle />}
>
This is a deposit to an undeployed application.
</Alert>
)}

<TextInput
type="number"
Expand Down
22 changes: 11 additions & 11 deletions packages/ui/src/RawInputForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
} from "viem";
import { useWaitForTransaction } from "wagmi";
import { TransactionProgress } from "./TransactionProgress";
import useUndeployedApplication from "./hooks/useUndeployedApplication";

export interface RawInputFormProps {
applications: string[];
Expand Down Expand Up @@ -65,6 +66,7 @@ export const RawInputForm: FC<RawInputFormProps> = (props) => {
const wait = useWaitForTransaction(execute.data);
const loading = execute.status === "loading" || wait.status === "loading";
const canSubmit = form.isValid() && prepare.error === null;
const isUndeployedApp = useUndeployedApplication(address, applications);

useEffect(() => {
if (wait.status === "success") {
Expand Down Expand Up @@ -99,17 +101,15 @@ export const RawInputForm: FC<RawInputFormProps> = (props) => {
}}
/>

{!form.errors.application &&
address !== zeroAddress &&
!addresses.includes(address) && (
<Alert
variant="light"
color="yellow"
icon={<TbAlertCircle />}
>
This is an undeployed application.
</Alert>
)}
{!form.errors.application && isUndeployedApp && (
<Alert
variant="light"
color="yellow"
icon={<TbAlertCircle />}
>
This is an undeployed application.
</Alert>
)}

<Textarea
label="Raw input"
Expand Down
19 changes: 19 additions & 0 deletions packages/ui/src/hooks/useUndeployedApplication.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Address, isAddress, zeroAddress } from "viem";
import { useDebouncedValue } from "@mantine/hooks";

export default function useUndeployedApplication(
address: Address,
applications: string[],
delay = 1000,
) {
const [isUndeployedApp] = useDebouncedValue(
isAddress(address) &&
address !== zeroAddress &&
!applications.some(
(a) => a.toLowerCase() === address.toLowerCase(),
),
delay,
);

return isUndeployedApp;
}
20 changes: 13 additions & 7 deletions packages/ui/test/ERC20DepositForm.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { fireEvent, render, screen } from "@testing-library/react";
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import { describe, it } from "vitest";
import { ERC20DepositForm } from "../src";
import withMantineTheme from "./utils/WithMantineTheme";
Expand Down Expand Up @@ -122,7 +122,7 @@ describe("Rollups ERC20DepositForm", () => {
expect(input?.getAttribute("placeholder")).toBe("0x");
});

it("should display alert for undeployed application", () => {
it("should display alert for undeployed application", async () => {
const customProps = { ...defaultProps, applications: [] };
const { container } = render(<Component {...customProps} />);
const input = screen.getByTestId("application") as HTMLInputElement;
Expand All @@ -133,11 +133,17 @@ describe("Rollups ERC20DepositForm", () => {
},
});

expect(
screen.getByText(
"This is a deposit to an undeployed application.",
),
).toBeInTheDocument();
await waitFor(
() =>
expect(
screen.getByText(
"This is a deposit to an undeployed application.",
),
).toBeInTheDocument(),
{
timeout: 1100,
},
);
});

it("should display error when application is invalid", () => {
Expand Down
20 changes: 13 additions & 7 deletions packages/ui/test/EtherDepositForm.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { fireEvent, render, screen } from "@testing-library/react";
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import { afterAll, describe, it } from "vitest";
import { EtherDepositForm } from "../src/EtherDepositForm";
import withMantineTheme from "./utils/WithMantineTheme";
Expand Down Expand Up @@ -376,7 +376,7 @@ describe("Rollups EtherDepositForm", () => {
expect(input?.getAttribute("placeholder")).toBe("0x");
});

it("should display alert for unemployed application", () => {
it("should display alert for unemployed application", async () => {
const { container } = render(<Component {...defaultProps} />);
const input = container.querySelector("input") as HTMLInputElement;

Expand All @@ -386,11 +386,17 @@ describe("Rollups EtherDepositForm", () => {
},
});

expect(
screen.getByText(
"This is a deposit to an undeployed application.",
),
).toBeInTheDocument();
await waitFor(
() =>
expect(
screen.getByText(
"This is a deposit to an undeployed application.",
),
).toBeInTheDocument(),
{
timeout: 1100,
},
);
});

it("should display error when application is invalid", () => {
Expand Down
16 changes: 11 additions & 5 deletions packages/ui/test/RawInputForm.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { fireEvent, render, screen } from "@testing-library/react";
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import { afterAll, describe, it } from "vitest";
import { RawInputForm } from "../src/RawInputForm";
import withMantineTheme from "./utils/WithMantineTheme";
Expand Down Expand Up @@ -304,7 +304,7 @@ describe("Rollups RawInputForm", () => {
expect(input?.getAttribute("placeholder")).toBe("0x");
});

it("should display alert for unemployed application", () => {
it("should display alert for unemployed application", async () => {
const { container } = render(<Component {...defaultProps} />);
const input = container.querySelector("input") as HTMLInputElement;

Expand All @@ -314,9 +314,15 @@ describe("Rollups RawInputForm", () => {
},
});

expect(
screen.getByText("This is an undeployed application."),
).toBeInTheDocument();
await waitFor(
() =>
expect(
screen.getByText("This is an undeployed application."),
).toBeInTheDocument(),
{
timeout: 1100,
},
);
});

it("should display error when application is invalid", () => {
Expand Down
60 changes: 60 additions & 0 deletions packages/ui/test/hooks/useUndeployedApplication.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { describe, it } from "vitest";
import { renderHook, waitFor } from "@testing-library/react";
import useUndeployedApplication from "../../src/hooks/useUndeployedApplication";
import { zeroAddress } from "viem";

const applications = ["0x60a7048c3136293071605a4eaffef49923e981cc"];
const delay = 1000;
const waitTimeout = delay + 100;

describe("useUndeployedApplication hook", () => {
it('should return "false" when address is invalid', async () => {
const invalidAddress = "0x60a7048c3136293071605a4eaffef49923e981ccaaa";

const { result } = renderHook(() =>
useUndeployedApplication(invalidAddress, applications, delay),
);

await waitFor(() => expect(result.current).toBe(false), {
timeout: waitTimeout,
});
});

it('should return "false" when address is "zeroAddress"', async () => {
const { result } = renderHook(() =>
useUndeployedApplication(zeroAddress, applications, delay),
);

await waitFor(() => expect(result.current).toBe(false), {
timeout: waitTimeout,
});
});

it('should return "false" when address exists in applications', async () => {
const [address] = applications;

const { result } = renderHook(() =>
useUndeployedApplication(
address as `0x${string}`,
applications,
delay,
),
);

await waitFor(() => expect(result.current).toBe(false), {
timeout: waitTimeout,
});
});

it("should return 'true' when address is valid and non-zero and address doesn't exist in applications", async () => {
const address = "0x60a7048c3136293071605a4eaffef49923e981ce";

const { result } = renderHook(() =>
useUndeployedApplication(address, applications, delay),
);

await waitFor(() => expect(result.current).toBe(true), {
timeout: waitTimeout,
});
});
});
Loading