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

refactor: enable address options when multiple addresses selected #934

Merged
merged 32 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
0705644
refactor: enable address options when multiple addresses selected
shahin-hq Jan 31, 2025
b57d5a0
Merge branch 'feat/evm' into refactor/enable-address-options
shahin-hq Jan 31, 2025
53f87ce
refactor: enable address options when multiple addresses selected
shahin-hq Jan 31, 2025
94a8445
refactor: enable address options when multiple addresses selected
shahin-hq Jan 31, 2025
ead140e
style: resolve style guide violations
shahin-hq Jan 31, 2025
43a1a99
refactor: enable address options when multiple addresses selected
shahin-hq Jan 31, 2025
912b480
refactor: enable address options when multiple addresses selected
shahin-hq Jan 31, 2025
430ad58
refactor: validator registration
shahin-hq Feb 3, 2025
dfc91f1
Merge branch 'feat/evm' into refactor/enable-address-options
shahin-hq Feb 3, 2025
3bc166e
refactor: validator registration
shahin-hq Feb 3, 2025
b9ffeb9
Merge remote-tracking branch 'origin/refactor/enable-address-options'…
shahin-hq Feb 3, 2025
a75c413
refactor: validator registration
shahin-hq Feb 3, 2025
255293a
refactor: validator registration
shahin-hq Feb 3, 2025
486c14e
style: resolve style guide violations
shahin-hq Feb 3, 2025
505595d
refactor: validator registration
shahin-hq Feb 3, 2025
ad19545
Merge remote-tracking branch 'origin/refactor/enable-address-options'…
shahin-hq Feb 3, 2025
1efae28
style: resolve style guide violations
shahin-hq Feb 3, 2025
712cbcb
refactor: validator registration
shahin-hq Feb 3, 2025
7d26ad8
style: resolve style guide violations
shahin-hq Feb 3, 2025
2fa88a6
refactor: validator registration
shahin-hq Feb 3, 2025
e3d6465
Merge remote-tracking branch 'origin/refactor/enable-address-options'…
shahin-hq Feb 3, 2025
7a509e4
style: resolve style guide violations
shahin-hq Feb 3, 2025
70b2952
refactor: add tests
shahin-hq Feb 3, 2025
dd97f78
refactor: add tests
shahin-hq Feb 3, 2025
4c9285b
Merge branch 'feat/evm' into refactor/enable-address-options
shahin-hq Feb 3, 2025
65125c8
style: resolve style guide violations
shahin-hq Feb 3, 2025
3c55ebd
wip
shahin-hq Feb 3, 2025
b8d65fa
Merge remote-tracking branch 'origin/refactor/enable-address-options'…
shahin-hq Feb 3, 2025
f823a59
refactor: enable validator resignation in multiple-address view
shahin-hq Feb 3, 2025
efb48c9
refactor: enable validator resignation in multiple-address view
shahin-hq Feb 3, 2025
b61fb89
Merge branch 'feat/evm' into refactor/enable-address-options
shahin-hq Feb 3, 2025
58e6f77
wip
shahin-hq Feb 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ export const ReceiverItemMobile: React.FC<ReceiverItemMobileProperties> = ({

export const ButtonsCell: React.VFC<ButtonsCellProperties> = ({ wallet, onSend, onSelectOption }) => {
const { t } = useTranslation();
const { primaryOptions, secondaryOptions } = useWalletOptions(wallet);
const { primaryOptions, secondaryOptions } = useWalletOptions([wallet]);

const isRestoring = !wallet.hasBeenFullyRestored();
const isButtonDisabled =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { WalletActions } from "@/domains/wallet/pages/WalletDetails/components/W
import { Skeleton } from "@/app/components/Skeleton";
import { AddressesSidePanel } from "@/domains/wallet/pages/WalletDetails/components/AddressesSidePanel";
import { ViewingAddressInfo } from "./PortfolioHeader.blocks";
import { Tooltip } from "@/app/components/Tooltip";
import { assertWallet } from "@/utils/assertions";
import { usePortfolio } from "@/domains/portfolio/hooks/use-portfolio";
import { useEnvironmentContext } from "@/app/contexts";
Expand Down Expand Up @@ -47,7 +46,8 @@ export const PortfolioHeader = ({
const isRestored = wallet.hasBeenFullyRestored();
const { convert } = useExchangeRate({ exchangeTicker: wallet.exchangeCurrency(), ticker: wallet.currency() });
const { handleImport, handleCreate, handleSelectOption, handleSend } = useWalletActions(...selectedWallets);
const { primaryOptions, secondaryOptions, additionalOptions, registrationOptions } = useWalletOptions(wallet);
const { primaryOptions, secondaryOptions, additionalOptions, registrationOptions } =
useWalletOptions(selectedWallets);

const { persist } = useEnvironmentContext();

Expand Down Expand Up @@ -273,21 +273,13 @@ export const PortfolioHeader = ({
secondaryOptions,
]}
toggleContent={
<Tooltip
content={t("COMMON.SWITCH_TO_SINGLE_VIEW")}
disabled={selectedWallets.length === 1}
<Button
variant="secondary"
size="icon"
className="text-theme-primary-600 dark:hover:bg-theme-dark-navy-700"
>
<span>
<Button
variant="secondary"
size="icon"
className="text-theme-primary-600 dark:hover:bg-theme-dark-navy-700"
disabled={selectedWallets.length > 1}
>
<Icon name="EllipsisVerticalFilled" size="lg" />
</Button>
</span>
</Tooltip>
<Icon name="EllipsisVerticalFilled" size="lg" />
</Button>
}
onSelect={handleSelectOption}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { FormStepProperties } from "@/domains/transaction/pages/SendRegistration
import { StepHeader } from "@/app/components/StepHeader";
import { ThemeIcon } from "@/app/components/Icon";
import { TransactionAddresses } from "@/domains/transaction/components/TransactionDetail";
import { assertWallet } from "@/utils/assertions";

const MINIMUM_PARTICIPANTS = 2;

Expand All @@ -20,6 +21,8 @@ export const FormStep = ({ profile, wallet }: FormStepProperties) => {
const { errors, setValue, register, watch } = useFormContext();
const { participants, minParticipants } = watch();

assertWallet(wallet);
Copy link
Contributor Author

@shahin-hq shahin-hq Feb 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the registration form is a wrapper for both musig and validator registration forms, when we have multiple wallets we don't know the selected wallet, this forced me to loosen types, since we haven't touched anything related to musig I ended up adding assert to please linter.


const { common, multiSignatureRegistration } = useValidation();

useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const StepsComponent = ({ activeTab, wallet, profile }: SendRegistrationComponen
<FormStep wallet={wallet} profile={profile} />
</TabPanel>
<TabPanel tabId={2}>
<ReviewStep wallet={wallet} profile={profile} />
<ReviewStep wallet={wallet!} profile={profile} />
</TabPanel>
</Tabs>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import { useTranslation } from "react-i18next";

import { FormField, FormLabel } from "@/app/components/Form";
import { InputDefault } from "@/app/components/Input";
import { useValidation } from "@/app/hooks";
import { useNetworks, useValidation } from "@/app/hooks";
import { FeeField } from "@/domains/transaction/components/FeeField";
import { TransactionAddresses } from "@/domains/transaction/components/TransactionDetail";
import { FormStepProperties } from "@/domains/transaction/pages/SendRegistration/SendRegistration.contracts";
import { StepHeader } from "@/app/components/StepHeader";
import { ThemeIcon } from "@/app/components/Icon";
import { SelectAddress } from "@/domains/profile/components/SelectAddress";

export const FormStep: React.FC<FormStepProperties> = ({ wallet, profile }: FormStepProperties) => {
const { t } = useTranslation();
Expand All @@ -19,12 +19,26 @@ export const FormStep: React.FC<FormStepProperties> = ({ wallet, profile }: Form
const { getValues, register, setValue } = useFormContext();
const validatorPublicKey = getValues("validatorPublicKey");

const network = useMemo(() => wallet.network(), [wallet]);
const [network] = useNetworks({ profile });
const feeTransactionData = useMemo(() => ({ validatorPublicKey }), [validatorPublicKey]);

useEffect(() => {
register("validatorPublicKey", validatorRegistration.validatorPublicKey(wallet));
}, [register, validatorRegistration]);
if (wallet) {
register("validatorPublicKey", validatorRegistration.validatorPublicKey(wallet));
}
}, [register, validatorRegistration, wallet]);

const handleSelectSender = (address: any) => {
setValue("senderAddress", address, { shouldDirty: true, shouldValidate: false });

const newSenderWallet = profile.wallets().findByAddressWithNetwork(address, network.id());
const isFullyRestoredAndSynced =
newSenderWallet?.hasBeenFullyRestored() && newSenderWallet.hasSyncedWithNetwork();

if (!isFullyRestoredAndSynced) {
newSenderWallet?.synchroniser().identity();
}
};

return (
<section data-testid="ValidatorRegistrationForm_form-step">
Expand All @@ -36,9 +50,23 @@ export const FormStep: React.FC<FormStepProperties> = ({ wallet, profile }: Form
}
/>

<div className="-mx-3 mt-6 sm:mx-0 sm:mt-4">
<TransactionAddresses senderAddress={wallet.address()} profile={profile} network={network} />
</div>
<FormField name="senderAddress" className="-mx-3 mt-6 sm:mx-0 sm:mt-4">
<SelectAddress
showWalletAvatar={false}
wallet={
wallet
? {
address: wallet.address(),
network: wallet.network(),
}
: undefined
}
wallets={profile.wallets().values()}
profile={profile}
disabled={profile.wallets().count() === 0}
onChange={handleSelectSender}
/>
</FormField>

<div className="mt-3 space-y-4 sm:mt-4">
<FormField name="validatorPublicKey">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ const component = ({
profile,
}: {
activeTab: number;
wallet: Contracts.IReadWriteWallet;
wallet?: Contracts.IReadWriteWallet;
profile: Contracts.IProfile;
}) => (
<Tabs activeId={activeTab}>
<TabPanel tabId={1}>
<FormStep wallet={wallet} profile={profile} />
</TabPanel>
<TabPanel tabId={2}>
<ReviewStep wallet={wallet} profile={profile} />
<ReviewStep wallet={wallet!} profile={profile} />
</TabPanel>
</Tabs>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export interface SendRegistrationDetailsOptions {

export interface SendRegistrationComponent {
activeTab: number;
wallet: Contracts.IReadWriteWallet;
wallet?: Contracts.IReadWriteWallet;
profile: Contracts.IProfile;
}

Expand All @@ -27,7 +27,7 @@ export interface SendRegistrationSignOptions {
}

export interface FormStepProperties {
wallet: Contracts.IReadWriteWallet;
wallet?: Contracts.IReadWriteWallet;
profile: Contracts.IProfile;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Networks } from "@ardenthq/sdk";
import { Contracts, DTO } from "@ardenthq/sdk-profiles";
import React, { useEffect, useLayoutEffect, useState } from "react";
import React, { useEffect, useLayoutEffect, useMemo, useState } from "react";
import { useForm } from "react-hook-form";
import { useHistory, useParams } from "react-router-dom";

Expand All @@ -11,7 +11,13 @@ import { Page, Section } from "@/app/components/Layout";
import { StepNavigation } from "@/app/components/StepNavigation";
import { TabPanel, Tabs } from "@/app/components/Tabs";
import { StepsProvider, useEnvironmentContext, useLedgerContext } from "@/app/contexts";
import { useActiveProfile, useActiveWallet, useLedgerModelStatus, useValidation } from "@/app/hooks";
import {
useActiveProfile,
useActiveWalletWhenNeeded,
useLedgerModelStatus,
useNetworks,
useValidation,
} from "@/app/hooks";
import { useKeydown } from "@/app/hooks/use-keydown";
import { AuthenticationStep } from "@/domains/transaction/components/AuthenticationStep";
import {
Expand All @@ -23,6 +29,8 @@ import { FeeWarning } from "@/domains/transaction/components/FeeWarning";
import { MultiSignatureRegistrationForm } from "@/domains/transaction/components/MultiSignatureRegistrationForm";
import { useFeeConfirmation, useMultiSignatureRegistration } from "@/domains/transaction/hooks";
import { TransactionSuccessful } from "@/domains/transaction/components/TransactionSuccessful";
import { assertWallet } from "@/utils/assertions";
import { GasLimit, MIN_GAS_PRICE } from "@/domains/transaction/components/FeeField/FeeField";

export const SendRegistration = () => {
const history = useHistory();
Expand All @@ -37,7 +45,6 @@ export const SendRegistration = () => {

const { env } = useEnvironmentContext();
const activeProfile = useActiveProfile();
const activeWallet = useActiveWallet();
const { sendMultiSignature, abortReference } = useMultiSignatureRegistration();
const { common } = useValidation();

Expand All @@ -53,15 +60,36 @@ export const SendRegistration = () => {
const { formState, register, setValue, watch, getValues } = form;
const { isDirty, isSubmitting, isValid } = formState;

const { fee, fees, isLoading } = watch();
const { fee, fees, isLoading, senderAddress } = watch();

const stepCount = registrationForm ? registrationForm.tabSteps + 2 : 1;
const authenticationStep = stepCount - 1;
const isAuthenticationStep = activeTab === authenticationStep;

const activeWalletFromUrl = useActiveWalletWhenNeeded(false);

const [network] = useNetworks({ profile: activeProfile });

const activeWallet = useMemo(() => {
if (senderAddress) {
return activeProfile.wallets().findByAddressWithNetwork(senderAddress, network.id());
}

if (activeWalletFromUrl) {
return activeWalletFromUrl;
}
}, [activeProfile, activeWalletFromUrl, network, senderAddress]);

useEffect(() => {
register("fees");
register("fee", common.fee(activeWallet.balance(), activeWallet.network(), fees));

const walletBalance = activeWallet?.balance() ?? 0;

const type = registrationType === "validatorRegistration" ? "delegateRegistration" : "multiSignature";

register("gasPrice", common.gasPrice(walletBalance, getValues, MIN_GAS_PRICE, activeWallet?.network()));
register("gasLimit", common.gasLimit(walletBalance, getValues, GasLimit[type], activeWallet?.network()));

register("inputFeeSettings");

register("network", { required: true });
Expand All @@ -75,6 +103,10 @@ export const SendRegistration = () => {
useFeeConfirmation(fee, fees);

useEffect(() => {
if (!activeWallet) {
return;
}

setValue("senderAddress", activeWallet.address(), { shouldDirty: true, shouldValidate: true });

const network = env
Expand Down Expand Up @@ -102,7 +134,7 @@ export const SendRegistration = () => {
return;
}

if (isAuthenticationStep && activeWallet.isLedger() && isLedgerModelSupported) {
if (isAuthenticationStep && activeWallet?.isLedger() && isLedgerModelSupported) {
handleSubmit();
}
}, [ledgerDevice]); // eslint-disable-line react-hooks/exhaustive-deps
Expand All @@ -118,6 +150,8 @@ export const SendRegistration = () => {
});

const handleSubmit = async () => {
assertWallet(activeWallet);

try {
const { mnemonic, encryptionPassword, wif, privateKey, secret, participants, minParticipants, fee } =
getValues();
Expand Down Expand Up @@ -171,7 +205,7 @@ export const SendRegistration = () => {
abortReference.current.abort();

if (activeTab === 1) {
return history.push(`/profiles/${activeProfile.id()}/wallets/${activeWallet.id()}`);
return history.push(`/profiles/${activeProfile.id()}/dashboard`);
}

setActiveTab(activeTab - 1);
Expand All @@ -188,14 +222,14 @@ export const SendRegistration = () => {
}

// Skip authentication step
if (isNextStepAuthentication && activeWallet.isLedger() && isLedgerModelSupported) {
if (isNextStepAuthentication && activeWallet?.isLedger() && isLedgerModelSupported) {
handleSubmit();
}

setActiveTab(nextStep);
};

const hideStepNavigation = activeTab === 10 || (isAuthenticationStep && activeWallet.isLedger());
const hideStepNavigation = activeTab === 10 || (isAuthenticationStep && activeWallet?.isLedger());

const isNextDisabled = isDirty ? !isValid || !!isLoading : true;

Expand All @@ -218,9 +252,7 @@ export const SendRegistration = () => {
<Tabs activeId={activeTab}>
<TabPanel tabId={10}>
<ErrorStep
onClose={() =>
history.push(`/profiles/${activeProfile.id()}/wallets/${activeWallet.id()}`)
}
onClose={() => history.push(`/profiles/${activeProfile.id()}/dashboard`)}
isBackDisabled={isSubmitting}
onBack={() => {
setActiveTab(1);
Expand All @@ -239,7 +271,7 @@ export const SendRegistration = () => {

<TabPanel tabId={authenticationStep}>
<AuthenticationStep
wallet={activeWallet}
wallet={activeWallet!}
ledgerIsAwaitingDevice={!hasDeviceAvailable}
ledgerIsAwaitingApp={!isConnected}
ledgerSupportedModels={[Contracts.WalletLedgerModel.NanoX]}
Expand All @@ -248,7 +280,7 @@ export const SendRegistration = () => {
</TabPanel>

<TabPanel tabId={stepCount}>
<TransactionSuccessful transaction={transaction} senderWallet={activeWallet} />
<TransactionSuccessful transaction={transaction} senderWallet={activeWallet!} />
</TabPanel>
</>
)}
Expand All @@ -257,7 +289,7 @@ export const SendRegistration = () => {
<StepNavigation
onBackClick={handleBack}
onBackToWalletClick={() =>
history.push(`/profiles/${activeProfile.id()}/wallets/${activeWallet.id()}`)
history.push(`/profiles/${activeProfile.id()}/dashboard`)
}
onContinueClick={() => handleNext()}
isLoading={isSubmitting || isLoading}
Expand Down
5 changes: 5 additions & 0 deletions src/domains/transaction/routing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ export const TransactionRoutes: RouteItem[] = [
exact: true,
path: ProfilePaths.SendRegistration,
},
{
component: SendRegistration,
exact: true,
path: ProfilePaths.SendValidatorRegistrationProfile,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New route item to handle validator registration without a selected wallet

},
{
component: SendValidatorResignation,
exact: true,
Expand Down
6 changes: 6 additions & 0 deletions src/domains/wallet/hooks/use-wallet-actions.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ describe("useWalletActions", () => {
});

expect(history.location.pathname).toBe(`/profiles/${profile.id()}/send-transfer`);

act(() => {
current.handleSelectOption({ value: "delegate-registration" } as DropdownOption);
});

expect(history.location.pathname).toBe(`/profiles/${profile.id()}/send-registration/validatorRegistration`);
});

it("should push right urls to history", () => {
Expand Down
Loading