diff --git a/suite-native/intl/src/en.ts b/suite-native/intl/src/en.ts index 2f7cc3ab27..f012aaa3d5 100644 --- a/suite-native/intl/src/en.ts +++ b/suite-native/intl/src/en.ts @@ -537,7 +537,7 @@ export const en = { title: 'Your Trezor wallet is not backed up', subtitle: 'If your Trezor is lost or damaged, your funds may be irreversibly lost.', cta: 'Create wallet backup', - continue: 'Continue anyway' + continue: 'Continue anyway', }, confirmOnDeviceSheetTitle: 'Confirm on Trezor', }, diff --git a/suite-native/module-accounts-management/package.json b/suite-native/module-accounts-management/package.json index faed9f6f6a..955e83db7b 100644 --- a/suite-native/module-accounts-management/package.json +++ b/suite-native/module-accounts-management/package.json @@ -32,10 +32,12 @@ "@suite-native/graph": "workspace:*", "@suite-native/icons": "workspace:*", "@suite-native/intl": "workspace:*", + "@suite-native/module-device-onboarding": "workspace:*", "@suite-native/navigation": "workspace:*", "@suite-native/qr-code": "workspace:*", "@suite-native/tokens": "workspace:*", "@suite-native/transactions": "workspace:*", + "@trezor/connect": "workspace:*", "@trezor/styles": "workspace:*", "@trezor/utils": "workspace:*", "date-fns": "^4.1.0", diff --git a/suite-native/module-accounts-management/src/components/AccountSettingsShowXpubButton.tsx b/suite-native/module-accounts-management/src/components/AccountSettingsShowXpubButton.tsx index 67770372de..3073a3c7bb 100644 --- a/suite-native/module-accounts-management/src/components/AccountSettingsShowXpubButton.tsx +++ b/suite-native/module-accounts-management/src/components/AccountSettingsShowXpubButton.tsx @@ -1,19 +1,75 @@ -import { useState } from 'react'; +import { useCallback, useState } from 'react'; import { useSelector } from 'react-redux'; -import { AccountsRootState, selectAccountByKey } from '@suite-common/wallet-core'; -import { isAddressBasedNetwork } from '@suite-common/wallet-utils'; -import { Button } from '@suite-native/atoms'; +import { TrezorDevice } from '@suite-common/suite-types'; +import { + AccountsRootState, + selectAccountByKey, + selectIsDeviceBackupRequired, + selectSelectedDevice, +} from '@suite-common/wallet-core'; +import { Account } from '@suite-common/wallet-types'; +import { getDerivationType, isAddressBasedNetwork } from '@suite-common/wallet-utils'; +import { Button, useBottomSheetModal } from '@suite-native/atoms'; import { Translation } from '@suite-native/intl'; +import { WalletBackupNotSetWarningBottomSheet } from '@suite-native/module-device-onboarding'; import { XpubQRCodeBottomSheet } from '@suite-native/qr-code'; +import TrezorConnect, { Success, Unsuccessful } from '@trezor/connect'; import { convertTaprootXpub } from '@trezor/utils'; +export const showXpubOnDevice = async (device: TrezorDevice, account: Account) => { + if (!device || !account) return; + + const params = { + device, + path: account.path, + useEmptyPassphrase: device.useEmptyPassphrase, + showOnTrezor: true, + derivationType: getDerivationType(account.accountType), + coin: account.symbol, + }; + + let response: Success | Unsuccessful; + switch (account.networkType) { + case 'bitcoin': + response = await TrezorConnect.getPublicKey(params); + break; + case 'cardano': + response = await TrezorConnect.cardanoGetPublicKey(params); + break; + case 'solana': + response = await TrezorConnect.solanaGetPublicKey(params); + break; + default: + response = { + success: false, + payload: { error: 'Method for getPublicKey not defined', code: undefined }, + }; + } + + return response; +}; + export const AccountSettingsShowXpubButton = ({ accountKey }: { accountKey: string }) => { const account = useSelector((state: AccountsRootState) => selectAccountByKey(state, accountKey), ); - const [isXpubVisible, setIsXpubVisible] = useState(false); + const { bottomSheetRef, openModal, closeModal } = useBottomSheetModal(); + + const isDeviceBackupRequired = useSelector(selectIsDeviceBackupRequired); + const device = useSelector(selectSelectedDevice); + + const showXpub = useCallback(() => { + if (!device || !account) return; + + showXpubOnDevice(device, account); + if (isDeviceBackupRequired) { + openModal(); + } else { + setIsXpubVisible(true); + } + }, [isDeviceBackupRequired, device, account, openModal]); if (!account) return null; @@ -39,11 +95,17 @@ export const AccountSettingsShowXpubButton = ({ accountKey }: { accountKey: stri return ( <> - - - diff --git a/suite-native/receive/src/screens/ReceiveAddressScreen.tsx b/suite-native/receive/src/screens/ReceiveAddressScreen.tsx index b3b974e752..00e5d2b02e 100644 --- a/suite-native/receive/src/screens/ReceiveAddressScreen.tsx +++ b/suite-native/receive/src/screens/ReceiveAddressScreen.tsx @@ -1,18 +1,30 @@ +import { useCallback } from 'react'; import { useSelector } from 'react-redux'; import { G } from '@mobily/ts-belt'; import { getDisplaySymbol } from '@suite-common/wallet-config'; -import { AccountsRootState, selectAccountByKey } from '@suite-common/wallet-core'; +import { + AccountsRootState, + selectAccountByKey, + selectIsDeviceBackupRequired, +} from '@suite-common/wallet-core'; import { AccountKey, TokenAddress } from '@suite-common/wallet-types'; import { AccountDetailsCard } from '@suite-native/accounts'; -import { Box, ErrorMessage, InlineAlertBox, VStack } from '@suite-native/atoms'; +import { + Box, + ErrorMessage, + InlineAlertBox, + VStack, + useBottomSheetModal, +} from '@suite-native/atoms'; import { ConfirmOnTrezorImage, selectHasFirmwareAuthenticityCheckHardFailed, } from '@suite-native/device'; import { Translation } from '@suite-native/intl'; import { Link } from '@suite-native/link'; +import { WalletBackupNotSetWarningBottomSheet } from '@suite-native/module-device-onboarding'; import { CloseActionType, Screen } from '@suite-native/navigation'; import { ReceiveBlockedDeviceCompromisedScreen } from './ReceiveBlockedDeviceCompromisedScreen'; @@ -35,11 +47,26 @@ export const ReceiveAddressScreen = ({ const account = useSelector((state: AccountsRootState) => selectAccountByKey(state, accountKey), ); + const isDeviceBackupRequired = useSelector(selectIsDeviceBackupRequired); + const hasReceiveButtonRequest = useSelector(hasReceiveAddressButtonRequest); + const { bottomSheetRef, openModal, closeModal } = useBottomSheetModal(); const { address, isReceiveApproved, isUnverifiedAddressRevealed, handleShowAddress } = useAccountReceiveAddress(accountKey); + const handleShowReceiveAddress = useCallback(() => { + handleShowAddress(); + + if (isDeviceBackupRequired) { + openModal(); + } + }, [handleShowAddress, openModal, isDeviceBackupRequired]); + + const closeNoBackupBottomSheet = useCallback(() => { + closeModal(); + }, [closeModal]); + const hasFirmwareAuthenticityCheckHardFailed = useSelector( selectHasFirmwareAuthenticityCheckHardFailed, ); @@ -110,10 +137,17 @@ export const ReceiveAddressScreen = ({ isTokenAddress={!!tokenContract} isReceiveApproved={isReceiveApproved} isUnverifiedAddressRevealed={isUnverifiedAddressRevealed} - onShowAddress={handleShowAddress} + onShowAddress={handleShowReceiveAddress} /> + {isDeviceBackupRequired && ( + + )} ); }; diff --git a/yarn.lock b/yarn.lock index 897adb880d..8264ab542e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10668,10 +10668,12 @@ __metadata: "@suite-native/graph": "workspace:*" "@suite-native/icons": "workspace:*" "@suite-native/intl": "workspace:*" + "@suite-native/module-device-onboarding": "workspace:*" "@suite-native/navigation": "workspace:*" "@suite-native/qr-code": "workspace:*" "@suite-native/tokens": "workspace:*" "@suite-native/transactions": "workspace:*" + "@trezor/connect": "workspace:*" "@trezor/styles": "workspace:*" "@trezor/utils": "workspace:*" date-fns: "npm:^4.1.0"