Skip to content

Commit

Permalink
fixup! feat(coinmarket): possibility to proceed with unverified address
Browse files Browse the repository at this point in the history
  • Loading branch information
adderpositive committed Sep 18, 2024
1 parent c4411a3 commit 903290f
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 154 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,48 +1,29 @@
import { useEffect } from 'react';
import styled from 'styled-components';

import { applySettings } from 'src/actions/settings/deviceSettingsActions';
import { Translation, Modal } from 'src/components/suite';
import { Translation } from 'src/components/suite';
import { TranslationKey } from 'src/components/suite/Translation';
import { useDevice, useDispatch } from 'src/hooks/suite';
import { ThunkAction } from 'src/types/suite';
import { Button } from '@trezor/components';
import { TrezorDevice } from 'src/types/suite';
import { Button, H3, NewModal, Paragraph } from '@trezor/components';
import { onCancel } from 'src/actions/suite/modalActions';

const StyledModal = styled(Modal)`
width: 520px;
`;

// eslint-disable-next-line local-rules/no-override-ds-component
const StyledButton = styled(Button)`
flex-grow: 1;
`;

interface ConfirmUnverifiedModalProps {
showUnverifiedButtonText: TranslationKey;
showUnverified: () => ThunkAction;
verify: () => ThunkAction;
action: {
event: () => void;
title: TranslationKey;
closeAfterEventTriggered?: boolean;
};
warningText: TranslationKey;
device: TrezorDevice;
enablePassphraseAndContinue: () => Promise<void>;
}

export const ConfirmUnverifiedModal = ({
showUnverifiedButtonText,
showUnverified,
verify,
action,
warningText,
device,
enablePassphraseAndContinue,
}: ConfirmUnverifiedModalProps) => {
const dispatch = useDispatch();
const { device, isLocked } = useDevice();

// Device connected while the modal is open -> switch to verification modal.
useEffect(() => {
if (device?.connected) {
dispatch(verify());
}
}, [device?.connected, dispatch, verify]);

// just to make TS happy
if (!device) return null;
const { isLocked } = useDevice();

const isDeviceLocked = isLocked();
const isPassphraseRequired = device.connected && !device.available;
Expand All @@ -53,47 +34,50 @@ export const ConfirmUnverifiedModal = ({
? 'TR_PLEASE_ENABLE_PASSPHRASE'
: 'TR_PLEASE_CONNECT_YOUR_DEVICE';

const enablePassphraseAndContinue = async () => {
if (!device.available) {
const result = await dispatch(applySettings({ use_passphrase: true }));
if (!result || !result.success) return;
const handleClose = () => dispatch(onCancel());
const handleEvent = () => {
action.event();

if (action.closeAfterEventTriggered) {
handleClose();
}
dispatch(verify());
};
const continueUnverified = () => dispatch(showUnverified());
const close = () => dispatch(onCancel());

return (
<StyledModal
heading={<Translation id={deviceStatus} values={{ deviceLabel: device.label }} />}
isCancelable
onCancel={close}
description={
<Translation
id={warningText}
values={{ claim: <Translation id={description} /> }}
/>
}
bottomBarComponents={
<NewModal
variant="warning"
size="small"
icon="shieldWarning"
onCancel={handleClose}
bottomContent={
<>
<Button variant="warning" onClick={continueUnverified}>
<Translation id={showUnverifiedButtonText} />
<Button variant="warning" onClick={handleEvent}>
<Translation id={action.title} />
</Button>

{isPassphraseRequired && (
<StyledButton
<Button
variant="primary"
onClick={enablePassphraseAndContinue}
isDisabled={isDeviceLocked}
>
<Translation id="TR_ACCOUNT_ENABLE_PASSPHRASE" />
</StyledButton>
</Button>
)}
<Button onClick={close} variant="tertiary">
<Button onClick={handleClose} variant="tertiary">
<Translation id="TR_BACK" />
</Button>
</>
}
/>
>
<H3>
<Translation id={deviceStatus} values={{ deviceLabel: device.label }} />
</H3>
<Paragraph>
<Translation
id={warningText}
values={{ claim: <Translation id={description} /> }}
/>
</Paragraph>
</NewModal>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import React, { useCallback, useEffect } from 'react';

import { openAddressModal, showAddress } from 'src/actions/wallet/receiveActions';
import { ConfirmUnverifiedModal } from './ConfirmUnverifiedModal';
import { useDevice, useDispatch } from 'src/hooks/suite';
import { openXpubModal, showXpub } from 'src/actions/wallet/publicKeyActions';
import { COINMARKET_BUY } from 'src/actions/wallet/constants';
import { ModalProps } from '@trezor/components';
import { applySettings } from 'src/actions/settings/deviceSettingsActions';

interface ConfirmUnverifiedModalContainerProps extends Required<Pick<ModalProps, 'onCancel'>> {
type: 'unverified-address' | 'unverified-xpub' | 'unverified-address-proceed';
addressPath?: string;
value?: string;
}

export const ConfirmUnverifiedModalContainer = ({
type,
addressPath,
value,
}: ConfirmUnverifiedModalContainerProps) => {
const { device } = useDevice();
const dispatch = useDispatch();

const showUnverifiedAddress = () => {
if (addressPath && value) {
dispatch(openAddressModal({ addressPath, value }));
}
};

const verifyProcess = useCallback(() => {
if (type === 'unverified-address' && addressPath && value) {
dispatch(showAddress(addressPath, value));
}

if (type === 'unverified-xpub') {
dispatch(showXpub());
}
}, [addressPath, value, type, dispatch]);

const enablePassphraseAndContinue = async () => {
if (!device?.available) {
const result = await dispatch(applySettings({ use_passphrase: true }));
if (!result || !result.success) return;
}
};

// Device connected while the modal is open -> switch to verification modal.
useEffect(() => {
if (device?.connected) {
verifyProcess();
}
}, [device?.connected, dispatch, verifyProcess]);

if (!device) return null;

if (type === 'unverified-address-proceed') {
return (
<ConfirmUnverifiedModal
action={{
event: () => {
if (value) {
dispatch({
type: COINMARKET_BUY.VERIFY_ADDRESS,
addressVerified: value,
});
}
},
title: 'TR_PROCEED_UNVERIFIED_ADDRESS',
closeAfterEventTriggered: true,
}}
warningText="TR_ADDRESS_PHISHING_WARNING"
device={device}
enablePassphraseAndContinue={enablePassphraseAndContinue}
/>
);
}

if (type === 'unverified-xpub') {
return (
<ConfirmUnverifiedModal
action={{
event: () => {
dispatch(openXpubModal());
},
title: 'TR_SHOW_UNVERIFIED_XPUB',
}}
warningText="TR_XPUB_PHISHING_WARNING"
device={device}
enablePassphraseAndContinue={enablePassphraseAndContinue}
/>
);
}

return (
<ConfirmUnverifiedModal
action={{
event: showUnverifiedAddress,
title: 'TR_SHOW_UNVERIFIED_ADDRESS',
}}
warningText="TR_ADDRESS_PHISHING_WARNING"
device={device}
enablePassphraseAndContinue={enablePassphraseAndContinue}
/>
);
};

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ import {
CriticalCoinjoinPhaseModal,
CoinjoinSuccessModal,
MoreRoundsNeededModal,
ConfirmUnverifiedModal,
ConfirmUnverifiedAddressModal,
UnecoCoinjoinModal,
AuthenticateDeviceModal,
AuthenticateDeviceFailModal,
Expand All @@ -41,13 +39,12 @@ import {
UnhideTokenModal,
} from 'src/components/suite/modals';
import type { AcquiredDevice } from 'src/types/suite';
import { openXpubModal, showXpub } from 'src/actions/wallet/publicKeyActions';
import type { ReduxModalProps } from '../ReduxModal';
import { CryptoId } from 'invity-api';
import { EverstakeModal } from './UnstakeModal/EverstakeModal';
import { PassphraseMismatchModal } from './PassphraseMismatchModal';
import { FirmwareRevisionOptOutModal } from './FirmwareRevisionOptOutModal';
import { ProceedUnverifiedAddressModal } from 'src/components/suite/modals/ReduxModal/UserContextModal/ProceedUnverifiedAddressModal';
import { ConfirmUnverifiedModalContainer } from 'src/components/suite/modals/ReduxModal/UserContextModal/ConfirmUnverifiedModalContainer';

/** Modals opened as a result of user action */
export const UserContextModal = ({
Expand All @@ -70,23 +67,23 @@ export const UserContextModal = ({
);
case 'unverified-address':
return (
<ConfirmUnverifiedAddressModal
<ConfirmUnverifiedModalContainer
type={payload.type}
addressPath={payload.addressPath}
value={payload.value}
onCancel={onCancel}
/>
);
case 'unverified-xpub':
return <ConfirmUnverifiedModalContainer type={payload.type} onCancel={onCancel} />;
case 'unverified-address-proceed':
return (
<ConfirmUnverifiedModal
showUnverifiedButtonText="TR_SHOW_UNVERIFIED_XPUB"
warningText="TR_XPUB_PHISHING_WARNING"
verify={showXpub}
showUnverified={openXpubModal}
<ConfirmUnverifiedModalContainer
type={payload.type}
value={payload.value}
onCancel={onCancel}
/>
);
case 'unverified-address-proceed':
return <ProceedUnverifiedAddressModal {...payload} onCancel={onCancel} />;
case 'address':
return <ConfirmAddressModal {...payload} onCancel={onCancel} />;
case 'xpub':
Expand Down
2 changes: 1 addition & 1 deletion packages/suite/src/components/suite/modals/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export { TransactionReviewModal } from './ReduxModal/TransactionReviewModal/Tran
export { ImportTransactionModal } from './ReduxModal/UserContextModal/ImportTransactionModal/ImportTransactionModal';
export { ConfirmEvmExplanationModal } from './ConfirmEvmExplanationModal';
export { ConfirmUnverifiedModal } from './ReduxModal/UserContextModal/ConfirmUnverifiedModal';
export { ConfirmUnverifiedAddressModal } from './ReduxModal/UserContextModal/ConfirmUnverifiedAddressModal';
export { ConfirmUnverifiedModalContainer } from './ReduxModal/UserContextModal/ConfirmUnverifiedModalContainer';
export { AddAccountModal } from './ReduxModal/UserContextModal/AddAccountModal/AddAccountModal';
export { QrScannerModal } from './ReduxModal/UserContextModal/QrScannerModal';
export { BackgroundGalleryModal } from './ReduxModal/UserContextModal/BackgroundGalleryModal';
Expand Down

0 comments on commit 903290f

Please sign in to comment.