Skip to content

Commit

Permalink
feat: Add rollup-v2 support for EtherPortal deposit form.
Browse files Browse the repository at this point in the history
  • Loading branch information
brunomenezes committed Nov 28, 2024
1 parent e356742 commit 658a6fd
Show file tree
Hide file tree
Showing 13 changed files with 1,093 additions and 587 deletions.
66 changes: 50 additions & 16 deletions apps/web/src/components/sendTransaction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import {
GenericInputForm,
GenericInputFormSpecification,
TransactionFormSuccessData,
type RollupVersion as RollupVersionUI,
} from "@cartesi/rollups-explorer-ui";
import { Select } from "@mantine/core";
import { useDebouncedValue } from "@mantine/hooks";
import { notifications } from "@mantine/notifications";
import { FC, useCallback, useState } from "react";
import { RollupVersion } from "../graphql/explorer/types";
import { useSearchApplications } from "../hooks/useSearchApplications";
import { useSearchMultiTokens } from "../hooks/useSearchMultiTokens";
import { useSearchTokens } from "../hooks/useSearchTokens";
Expand All @@ -36,28 +38,42 @@ interface DepositProps {

const DEBOUNCE_TIME = 400 as const;

type ApplicationSearchableParams = {
address: string;
rollupVersion?: RollupVersion;
};

const SendTransaction: FC<DepositProps> = ({
initialDepositType = "ether",
}) => {
const [depositType, setDepositType] =
useState<DepositType>(initialDepositType);
const [applicationSearchableParams, setApplicationSearchableParams] =
useState<ApplicationSearchableParams>({ address: "" });

// TODO: Replace this by the above one in every form.
const [applicationId, setApplicationId] = useState<string>("");
const [multiTokenId, setMultiTokenId] = useState<string>("");
const [tokenId, setTokenId] = useState<string>("");
const [debouncedApplicationId] = useDebouncedValue(
applicationId,

const [debouncedApplicationSearchableParams] = useDebouncedValue(
applicationSearchableParams,
DEBOUNCE_TIME,
);

const [debouncedTokenId] = useDebouncedValue(tokenId, DEBOUNCE_TIME);
const [debouncedMultiTokenId] = useDebouncedValue(
multiTokenId,
DEBOUNCE_TIME,
);

const chainId = getConfiguredChainId();
const { applications, fetching } = useSearchApplications({
address: debouncedApplicationId,
address: debouncedApplicationSearchableParams.address,
rollupVersion: debouncedApplicationSearchableParams.rollupVersion,
chainId,
});

const { tokens } = useSearchTokens({
address: debouncedTokenId,
chainId,
Expand Down Expand Up @@ -97,6 +113,24 @@ const SendTransaction: FC<DepositProps> = ({
[],
);

const applicationAddressList = applications.map((a) => a.address);

const updateApplicationSearchParams = useCallback(
(address: string, rollupVersion?: RollupVersionUI) =>
setApplicationSearchableParams({
address,
rollupVersion: rollupVersion as RollupVersion,
}),
[],
);

// TODO: Fixup and remove after upgrading last form
const setOldApplicationCB = useCallback((address: string) => {
setApplicationSearchableParams({
address,
});
}, []);

return (
<>
<Select
Expand Down Expand Up @@ -140,60 +174,60 @@ const SendTransaction: FC<DepositProps> = ({
<EtherDepositForm
applications={applications}
isLoadingApplications={fetching}
onSearchApplications={setApplicationId}
onSearchApplications={updateApplicationSearchParams}
onSuccess={onSuccess}
/>
) : depositType === "erc20" ? (
<ERC20DepositForm
tokens={tokens}
applications={applications}
applications={applicationAddressList}
isLoadingApplications={fetching}
onSearchApplications={setApplicationId}
onSearchApplications={setOldApplicationCB}
onSearchTokens={setTokenId}
onSuccess={onSuccess}
/>
) : depositType === "erc721" ? (
<ERC721DepositForm
applications={applications}
applications={applicationAddressList}
isLoadingApplications={fetching}
onSearchApplications={setApplicationId}
onSearchApplications={setOldApplicationCB}
onSuccess={onSuccess}
/>
) : depositType === "input" ? (
<GenericInputForm
applications={applications}
applications={applicationAddressList}
specifications={
specifications as GenericInputFormSpecification[]
}
isLoadingApplications={fetching}
onSearchApplications={setApplicationId}
onSearchApplications={setOldApplicationCB}
onSuccess={onSuccess}
/>
) : depositType === "erc1155" ? (
<ERC1155DepositForm
mode="single"
tokens={multiTokens}
applications={applications}
applications={applicationAddressList}
isLoadingApplications={fetching}
onSearchApplications={setApplicationId}
onSearchApplications={setOldApplicationCB}
onSearchTokens={setMultiTokenId}
onSuccess={onSuccess}
/>
) : depositType === "erc1155Batch" ? (
<ERC1155DepositForm
mode="batch"
tokens={multiTokens}
applications={applications}
applications={applicationAddressList}
isLoadingApplications={fetching}
onSearchApplications={setApplicationId}
onSearchApplications={setOldApplicationCB}
onSearchTokens={setMultiTokenId}
onSuccess={onSuccess}
/>
) : depositType === "relay" ? (
<AddressRelayForm
applications={applications}
applications={applicationAddressList}
isLoadingApplications={fetching}
onSearchApplications={setApplicationId}
onSearchApplications={setOldApplicationCB}
onSuccess={onSuccess}
/>
) : null}
Expand Down
103 changes: 103 additions & 0 deletions packages/ui/src/ApplicationAutocomplete.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import {
AutocompleteProps,
Combobox,
InputBase,
Stack,
Text,
useCombobox,
} from "@mantine/core";
import { useUncontrolled } from "@mantine/hooks";
import { FC } from "react";
import { Application } from "./commons/interfaces";

export interface ApplicationAutocompleteProps extends AutocompleteProps {
onApplicationSelected: (app: Application) => void;
applications: Application[];
}

const ApplicationAutocomplete: FC<ApplicationAutocompleteProps> = (props) => {
const {
applications,
onApplicationSelected,
value,
defaultValue,
onChange,
...rest
} = props;
const combobox = useCombobox();
const [_value, setValue] = useUncontrolled({
value,
defaultValue,
finalValue: "",
onChange,
});

const options = applications.map((app) => (
<Combobox.Option
value={app.address}
onClick={() => {
onApplicationSelected(app);
}}
key={`${app.address}-${app.rollupVersion}`}
>
<Stack
gap={0}
style={{
borderInlineStart:
".3px solid var(--mantine-primary-color-filled)",
}}
px="xs"
>
<Text size="sm">{app.address}</Text>
<Text size="xs" c="dimmed">
Rollup {app.rollupVersion}
</Text>
</Stack>
</Combobox.Option>
));

return (
<Combobox
onOptionSubmit={(optVal) => {
setValue(optVal);
combobox.closeDropdown();
}}
store={combobox}
>
<Combobox.Target>
<InputBase
{...rest}
value={_value}
onBlur={(evt) => {
combobox.closeDropdown();
rest.onBlur?.(evt);
}}
onFocus={(evt) => {
combobox.openDropdown();
rest.onFocus?.(evt);
}}
onChange={(evt) => {
setValue(evt.currentTarget.value);
combobox.openDropdown();
combobox.updateSelectedOptionIndex();
}}
/>
</Combobox.Target>

<Combobox.Dropdown
mah="calc(13.75rem * var(--mantine-scale))"
style={{ overflow: "scroll" }}
>
<Combobox.Options>
{options.length === 0 ? (
<Combobox.Empty>No Applications found!</Combobox.Empty>
) : (
options
)}
</Combobox.Options>
</Combobox.Dropdown>
</Combobox>
);
};

export default ApplicationAutocomplete;
Loading

0 comments on commit 658a6fd

Please sign in to comment.