Skip to content

Commit

Permalink
refactoring: joining local sign pages
Browse files Browse the repository at this point in the history
  • Loading branch information
dianasavvatina committed Mar 3, 2025
1 parent e770f38 commit 82be481
Show file tree
Hide file tree
Showing 11 changed files with 216 additions and 233 deletions.
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
import { Modal } from "@chakra-ui/react";
import {
type FA12TokenBalance,
type FA2TokenBalance,
makeAccountOperations,
mockFA2Token,
mockImplicitAccount,
mockMnemonicAccount,
} from "@umami/core";
import { type UmamiStore, addTestAccount, makeStore } from "@umami/state";
import { executeParams } from "@umami/test-utils";
import { TEZ, parseContractPkh } from "@umami/tezos";
import { TEZ, mockImplicitAddress, parseContractPkh } from "@umami/tezos";

import { SignPage } from "./SignPage";
import { render, screen, waitFor } from "../../../testUtils";
import { type SignPageProps } from "../utils";
import { LocalSignPage } from "./LocalSignPage";
import { type LocalSignPageProps } from "./utils";
import { render, screen, waitFor } from "../../testUtils";

jest.mock("@chakra-ui/react", () => ({
...jest.requireActual("@chakra-ui/react"),
useBreakpointValue: jest.fn(),
}));

const fixture = (props: SignPageProps<{ token: FA12TokenBalance | FA2TokenBalance }>) => (
const fixture = (props: LocalSignPageProps) => (
<Modal isOpen={true} onClose={() => {}}>
<SignPage {...props} />
<LocalSignPage {...props} />
</Modal>
);

Expand All @@ -35,7 +33,33 @@ beforeEach(() => {

const mockAccount = mockMnemonicAccount(0);
const mockFAToken = mockFA2Token(0, mockAccount);
describe("<SignPage />", () => {

describe("<LocalSignPage tez/>", () => {
describe("fee", () => {
it("displays the fee in tez", async () => {
const store = makeStore();
addTestAccount(store, mockMnemonicAccount(0));
const props: LocalSignPageProps = {
operations: {
...makeAccountOperations(mockImplicitAccount(0), mockImplicitAccount(0), [
{
type: "tez",
amount: "1000000",
recipient: mockImplicitAddress(1),
},
]),
estimates: [executeParams({ fee: 1234567 })],
},
operationType: "tez",
};
render(fixture(props), { store });

await waitFor(() => expect(screen.getByTestId("fee")).toHaveTextContent(`1.234567 ${TEZ}`));
});
});
});

describe("<LocalSignPage token/>", () => {
const sender = mockImplicitAccount(0);
const operations = {
...makeAccountOperations(sender, mockImplicitAccount(0), [
Expand All @@ -56,12 +80,10 @@ describe("<SignPage />", () => {
};
describe("fee", () => {
it("displays the fee in tez", async () => {
const props: SignPageProps<{
token: FA12TokenBalance | FA2TokenBalance;
}> = {
const props: LocalSignPageProps = {
operations,
mode: "single",
data: { token: mockFAToken },
operationType: "token",
token: mockFAToken,
};
render(fixture(props), { store });

Expand All @@ -71,12 +93,10 @@ describe("<SignPage />", () => {

describe("token", () => {
it("displays the correct symbol", async () => {
const props: SignPageProps<{
token: FA12TokenBalance | FA2TokenBalance;
}> = {
const props: LocalSignPageProps = {
operations,
mode: "single",
data: { token: mockFAToken },
operationType: "token",
token: mockFAToken,
};
render(fixture(props), { store });

Expand All @@ -88,12 +108,10 @@ describe("<SignPage />", () => {
});

it("displays the correct amount", async () => {
const props: SignPageProps<{
token: FA12TokenBalance | FA2TokenBalance;
}> = {
const props: LocalSignPageProps = {
operations,
mode: "single",
data: { token: mockFA2Token(0, mockAccount, 1, 0) },
operationType: "token",
token: mockFA2Token(0, mockAccount, 1, 0),
};
render(fixture(props), { store });

Expand Down
138 changes: 138 additions & 0 deletions apps/web/src/components/SendFlow/LocalSignPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import {
Flex,
FormControl,
FormLabel,
ModalBody,
ModalContent,
ModalFooter,
VStack,
useBreakpointValue,
} from "@chakra-ui/react";
import {
type FA12TokenBalance,
type FA2TokenBalance,
type TezTransfer,
type TokenTransfer,
} from "@umami/core";
import { type Address } from "@umami/tezos";
import { CustomError } from "@umami/utils";
import { FormProvider } from "react-hook-form";

import { SignButton } from "./SignButton";
import { SignPageFee } from "./SignPageFee";
import { SignPageHeader } from "./SignPageHeader";
import { type LocalSignPageProps, useSignPageHelpers } from "./utils";
import { AddressTile } from "../AddressTile";
import { TezTile, TokenTile } from "../AssetTiles";
import { AdvancedSettingsAccordion } from "../AdvancedSettingsAccordion";

Check warning on line 27 in apps/web/src/components/SendFlow/LocalSignPage.tsx

View workflow job for this annotation

GitHub Actions / test

`../AdvancedSettingsAccordion` import should occur before import of `../AssetTiles`

export const LocalSignPage = (props: LocalSignPageProps) => {
const { operations: initialOperations, token, operationType } = props;
const { fee, operations, estimationFailed, isLoading, form, signer, onSign } =
useSignPageHelpers(initialOperations);
const hideBalance = useBreakpointValue({ base: true, md: false });

const operation = operations.operations[0];

const fields: Record<string, any> = {};

switch (operationType) {
case "tez":
fields["mutezAmount"] = (operation as TezTransfer).amount;
fields["to"] = (operation as TezTransfer).recipient;
fields["from"] = operations.sender.address;
break;
case "token":
if (!token) {
throw new CustomError("Token is required for token operation");
}
fields["amount"] = (operation as TokenTransfer).amount;
fields["to"] = (operation as TokenTransfer).recipient;
fields["from"] = operations.sender.address;
fields["token"] = token;
break;
}

const AddressLabelAndTile = (heading: string, address: Address | undefined) => {
if (!address) {
return null;
}
return (
<Flex flexDirection="column" width="full">
<FormLabel>{heading}</FormLabel>
<AddressTile address={address} hideBalance={hideBalance} />
</Flex>
);
};

const Fee = () => (
<Flex justifyContent="end" width="full" marginTop="12px">
<SignPageFee fee={fee} />
</Flex>
);

const MutezAndFee = (mutezAmount: string | undefined) => {
if (!mutezAmount) {
return null;
}
return (
<Flex flexDirection="column" width="full">
<FormLabel width="full">Amount</FormLabel>
<TezTile mutezAmount={mutezAmount} />
<Fee />
</Flex>
);
};

const TokenAndFee = (token: FA12TokenBalance | FA2TokenBalance | undefined, amount: string) => {
if (!token) {
return null;
}
return (
<Flex flexDirection="column" width="full">
<FormLabel width="full">Amount</FormLabel>
<TokenTile amount={amount} token={token} />
<Fee />
</Flex>
);
};

const formFields = {
mutezAmount: MutezAndFee(fields["mutezAmount"]),
from: AddressLabelAndTile("From", fields["from"]),
to: AddressLabelAndTile("To", fields["to"]),
token: TokenAndFee(fields["token"], fields["amount"]),
};

const renderField = (key: keyof typeof formFields) => formFields[key];

return (
<FormProvider {...form}>
<ModalContent>
<form>
<SignPageHeader />
<FormControl>
<ModalBody gap="24px">
<VStack alignItems="start" spacing="24px">
{renderField("mutezAmount")}
{renderField("token")}
{renderField("from")}
{renderField("to")}
<AdvancedSettingsAccordion />
</VStack>
</ModalBody>
<ModalFooter>
<SignButton
isDisabled={estimationFailed}
isLoading={isLoading}
onSubmit={onSign}
signer={signer}
text="Confirm"
/>
</ModalFooter>
</FormControl>
</form>
</ModalContent>
</FormProvider>
);
};
7 changes: 3 additions & 4 deletions apps/web/src/components/SendFlow/Tez/FormPage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { CustomError } from "@umami/utils";
import { BigNumber } from "bignumber.js";

import { FormPage } from "./FormPage";
import { SignPage } from "./SignPage";
import {
act,
dynamicModalContextMock,
Expand All @@ -27,6 +26,7 @@ import {
userEvent,
waitFor,
} from "../../../testUtils";
import { LocalSignPage } from "../LocalSignPage";

jest.mock("@umami/core", () => ({
...jest.requireActual("@umami/core"),
Expand Down Expand Up @@ -262,10 +262,9 @@ describe("<Form />", () => {
await act(() => user.click(submitButton));

expect(dynamicModalContextMock.openWith).toHaveBeenCalledWith(
<SignPage
data={undefined}
<LocalSignPage
goBack={expect.any(Function)}
mode="single"
operationType="tez"
operations={operations}
/>
);
Expand Down
4 changes: 1 addition & 3 deletions apps/web/src/components/SendFlow/Tez/FormPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import { useGetAccountBalanceDetails } from "@umami/state";
import { type RawPkh, TEZ, TEZ_DECIMALS, parsePkh, tezToMutez } from "@umami/tezos";
import { FormProvider, useForm } from "react-hook-form";

import { SignPage } from "./SignPage";
import { useColor } from "../../../styles/useColor";
import { KnownAccountsAutocomplete } from "../../AddressAutocomplete";
import { TezTile } from "../../AssetTiles";
Expand All @@ -42,8 +41,7 @@ export type FormValues = {
export const FormPage = ({ ...props }: FormPageProps<FormValues>) => {
const color = useColor();
const openSignPage = useOpenSignPageFormAction({
SignPage,
signPageExtraData: undefined,
operationType: "tez",
FormPage,
defaultFormPageProps: props,
toOperation,
Expand Down
46 changes: 0 additions & 46 deletions apps/web/src/components/SendFlow/Tez/SignPage.test.tsx

This file was deleted.

Loading

0 comments on commit 82be481

Please sign in to comment.