diff --git a/apps/wallet-mobile/.storybook/storybook.requires.js b/apps/wallet-mobile/.storybook/storybook.requires.js index c820f86bef..242a8c4a84 100644 --- a/apps/wallet-mobile/.storybook/storybook.requires.js +++ b/apps/wallet-mobile/.storybook/storybook.requires.js @@ -136,6 +136,7 @@ const getStories = () => { "./src/features/Settings/WalletSettings/WalletSettingsScreen.stories.tsx": require("../src/features/Settings/WalletSettings/WalletSettingsScreen.stories.tsx"), "./src/features/Swap/common/AmountCard/AmountCard.stories.tsx": require("../src/features/Swap/common/AmountCard/AmountCard.stories.tsx"), "./src/features/Swap/common/ButtonGroup/ButtonGroup.stories.tsx": require("../src/features/Swap/common/ButtonGroup/ButtonGroup.stories.tsx"), + "./src/features/Swap/common/ConfirmRawTx/ConfirmRawTx.stories.tsx": require("../src/features/Swap/common/ConfirmRawTx/ConfirmRawTx.stories.tsx"), "./src/features/Swap/common/ConfirmWithSpendingPassword/ConfirmWithSpendingPassword.stories.tsx": require("../src/features/Swap/common/ConfirmWithSpendingPassword/ConfirmWithSpendingPassword.stories.tsx"), "./src/features/Swap/common/SelectPool/SelectPoolFromList/SelectPoolFromList.stories.tsx": require("../src/features/Swap/common/SelectPool/SelectPoolFromList/SelectPoolFromList.stories.tsx"), "./src/features/Swap/useCases/ConfirmTxScreen/ConfirmTxScreen.stories.tsx": require("../src/features/Swap/useCases/ConfirmTxScreen/ConfirmTxScreen.stories.tsx"), diff --git a/apps/wallet-mobile/src/features/Swap/common/ConfirmRawTx/ConfirmRawTx.stories.tsx b/apps/wallet-mobile/src/features/Swap/common/ConfirmRawTx/ConfirmRawTx.stories.tsx new file mode 100644 index 0000000000..b65ea4543e --- /dev/null +++ b/apps/wallet-mobile/src/features/Swap/common/ConfirmRawTx/ConfirmRawTx.stories.tsx @@ -0,0 +1,55 @@ +import {storiesOf} from '@storybook/react-native' +import {mockSwapManager, mockSwapStateDefault, SwapProvider} from '@yoroi/swap' +import React from 'react' +import {StyleSheet, View} from 'react-native' + +import {SelectedWalletProvider} from '../../../../SelectedWallet' +import {YoroiWallet} from '../../../../yoroi-wallets/cardano/types' +import {mocks as walletMocks} from '../../../../yoroi-wallets/mocks' +import {mocks} from '../mocks' +import {SwapFormProvider} from '../SwapFormProvider' +import {ConfirmRawTx} from './ConfirmRawTx' + +storiesOf('ConfirmRawTx', module) + .addDecorator((story) => {story()}) + .add('ConfirmRawTxWithPassword', () => ( + + + + )) + .add('ConfirmRawTxWithOs', () => ( + + + + )) + .add('ConfirmRawTxWithHw', () => ( + + + + )) + +const styles = StyleSheet.create({ + container: { + flex: 1, + padding: 16, + }, +}) + +const Provider = ({children, wallet}: {children: React.ReactNode; wallet: YoroiWallet}) => { + return ( + + + {children} + + + ) +} diff --git a/apps/wallet-mobile/src/features/Swap/common/ConfirmRawTx/ConfirmRawTx.tsx b/apps/wallet-mobile/src/features/Swap/common/ConfirmRawTx/ConfirmRawTx.tsx new file mode 100644 index 0000000000..3685037542 --- /dev/null +++ b/apps/wallet-mobile/src/features/Swap/common/ConfirmRawTx/ConfirmRawTx.tsx @@ -0,0 +1,20 @@ +import React from 'react' + +import {useSelectedWallet} from '../../../../SelectedWallet' +import {ConfirmRawTxWithHW} from './ConfirmRawTxWithHW' +import {ConfirmRawTxWithOs} from './ConfirmRawTxWithOs' +import {ConfirmRawTxWithPassword} from './ConfirmRawTxWithPassword' + +export const ConfirmRawTx = ({onConfirm}: {onConfirm?: (rootKey: string) => Promise}) => { + const wallet = useSelectedWallet() + + if (wallet.isHW) { + return + } + + if (wallet.isEasyConfirmationEnabled) { + return + } + + return +} diff --git a/apps/wallet-mobile/src/features/Swap/common/ConfirmRawTx/ConfirmRawTxWithHW.tsx b/apps/wallet-mobile/src/features/Swap/common/ConfirmRawTx/ConfirmRawTxWithHW.tsx new file mode 100644 index 0000000000..56697d7792 --- /dev/null +++ b/apps/wallet-mobile/src/features/Swap/common/ConfirmRawTx/ConfirmRawTxWithHW.tsx @@ -0,0 +1,4 @@ +export const ConfirmRawTxWithHW = () => { + // TODO: Needs to be implemented + return null +} diff --git a/apps/wallet-mobile/src/features/Swap/common/ConfirmRawTx/ConfirmRawTxWithOs.tsx b/apps/wallet-mobile/src/features/Swap/common/ConfirmRawTx/ConfirmRawTxWithOs.tsx new file mode 100644 index 0000000000..290c69993a --- /dev/null +++ b/apps/wallet-mobile/src/features/Swap/common/ConfirmRawTx/ConfirmRawTxWithOs.tsx @@ -0,0 +1,47 @@ +import React, {useEffect} from 'react' +import {ActivityIndicator, StyleSheet, Text, View} from 'react-native' + +import {useSelectedWallet} from '../../../../SelectedWallet' +import {COLORS} from '../../../../theme' +import {useAuthOsWithEasyConfirmation} from '../../../../yoroi-wallets/auth' + +export const ConfirmRawTxWithOs = ({onConfirm}: {onConfirm?: (rootKey: string) => Promise}) => { + const wallet = useSelectedWallet() + + const {authWithOs, error} = useAuthOsWithEasyConfirmation( + {id: wallet.id}, + {onSuccess: (rootKey) => onConfirm?.(rootKey)}, + ) + + useEffect(() => { + if (!wallet.isEasyConfirmationEnabled) return + authWithOs() + }, [wallet.isEasyConfirmationEnabled, authWithOs]) + + if (error) { + return ( + + + {error.message} + + + ) + } + + return ( + + + + ) +} + +const styles = StyleSheet.create({ + center: { + alignItems: 'center', + justifyContent: 'center', + }, + errorMessage: { + color: COLORS.ERROR_TEXT_COLOR, + textAlign: 'center', + }, +}) diff --git a/apps/wallet-mobile/src/features/Swap/common/ConfirmRawTx/ConfirmRawTxWithPassword.tsx b/apps/wallet-mobile/src/features/Swap/common/ConfirmRawTx/ConfirmRawTxWithPassword.tsx new file mode 100644 index 0000000000..56922cd9bf --- /dev/null +++ b/apps/wallet-mobile/src/features/Swap/common/ConfirmRawTx/ConfirmRawTxWithPassword.tsx @@ -0,0 +1,42 @@ +import React, {useState} from 'react' + +import {Spacer} from '../../../../components' +import {useSelectedWallet} from '../../../../SelectedWallet' +import {ConfirmWithSpendingPassword} from '../ConfirmWithSpendingPassword' + +export const ConfirmRawTxWithPassword = ({onConfirm}: {onConfirm?: (rootKey: string) => Promise}) => { + const wallet = useSelectedWallet() + + const handlePasswordConfirm = async (password: string) => { + const rootKey = await wallet.encryptedStorage.rootKey.read(password) + return onConfirm?.(rootKey) + } + + return +} + +const PasswordInput = ({onConfirm}: {onConfirm: (password: string) => Promise}) => { + const [error, setError] = useState(null) + const [loading, setLoading] = useState(false) + + const onConfirmPress = async (password: string) => { + setError(null) + setLoading(true) + try { + await onConfirm(password) + } catch (e: unknown) { + if (e instanceof Error) { + setError(e) + } + } + setLoading(false) + } + + return ( + <> + + + + + ) +} diff --git a/apps/wallet-mobile/src/features/Swap/common/ConfirmWithSpendingPassword/ConfirmWithSpendingPassword.tsx b/apps/wallet-mobile/src/features/Swap/common/ConfirmWithSpendingPassword/ConfirmWithSpendingPassword.tsx index b1570251c9..395e9d5413 100644 --- a/apps/wallet-mobile/src/features/Swap/common/ConfirmWithSpendingPassword/ConfirmWithSpendingPassword.tsx +++ b/apps/wallet-mobile/src/features/Swap/common/ConfirmWithSpendingPassword/ConfirmWithSpendingPassword.tsx @@ -74,11 +74,13 @@ const styles = StyleSheet.create({ }, errorMessage: { color: COLORS.ERROR_TEXT_COLOR, + textAlign: 'center', }, loading: { position: 'absolute', height: '100%', - width: '100%', + left: 0, + right: 0, alignItems: 'center', justifyContent: 'center', }, diff --git a/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/ListOrders/OpenOrders.tsx b/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/ListOrders/OpenOrders.tsx index c47a900dbe..2059700aaf 100644 --- a/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/ListOrders/OpenOrders.tsx +++ b/apps/wallet-mobile/src/features/Swap/useCases/StartSwapScreen/ListOrders/OpenOrders.tsx @@ -2,7 +2,7 @@ import {useFocusEffect} from '@react-navigation/native' import {useSwap, useSwapOrdersByStatusOpen} from '@yoroi/swap' import {Buffer} from 'buffer' import _ from 'lodash' -import React, {Suspense, useState} from 'react' +import React, {Suspense} from 'react' import {useIntl} from 'react-intl' import {ActivityIndicator, Alert, Linking, ScrollView, StyleSheet, TouchableOpacity, View} from 'react-native' @@ -29,7 +29,7 @@ import {useSelectedWallet} from '../../../../../SelectedWallet' import {COLORS} from '../../../../../theme' import {createRawTxSigningKey, generateCIP30UtxoCbor} from '../../../../../yoroi-wallets/cardano/utils' import {useTokenInfos, useTransactionInfos} from '../../../../../yoroi-wallets/hooks' -import {ConfirmWithSpendingPassword} from '../../../common/ConfirmWithSpendingPassword' +import {ConfirmRawTx} from '../../../common/ConfirmRawTx/ConfirmRawTx' import {Counter} from '../../../common/Counter/Counter' import {useNavigateTo} from '../../../common/navigation' import {PoolIcon} from '../../../common/PoolIcon/PoolIcon' @@ -107,10 +107,10 @@ export const OpenOrders = () => { }) } - const handlePasswordConfirm = async (password: string, orderId: string) => { + const onRawTxConfirm = async (rootKey: string, orderId: string) => { const order = normalizedOrders.find((o) => o.id === orderId) if (!order || order.owner === undefined || order.utxo === undefined) return - const tx = await createCancellationTxAndSign(order.id, password) + const tx = await createCancellationTxAndSign(order.id, rootKey) if (!tx) return await wallet.submitTransaction(tx.txBase64) trackCancellationSubmitted(order) @@ -122,7 +122,7 @@ export const OpenOrders = () => { setBottomSheetState({ openId: id, title: strings.signTransaction, - content: wallet.isHW ? null : handlePasswordConfirm(password, id)} />, + content: onRawTxConfirm(rootKey, id)} />, height: 350, }) } @@ -146,7 +146,7 @@ export const OpenOrders = () => { const createCancellationTxAndSign = async ( orderId: string, - password: string, + rootKey: string, ): Promise<{txBase64: string} | undefined> => { const order = normalizedOrders.find((o) => o.id === orderId) if (!order || order.owner === undefined || order.utxo === undefined) return @@ -157,7 +157,6 @@ export const OpenOrders = () => { utxos: {collateral: collateralUtxo, order: utxo}, address: addressHex, }) - const rootKey = await wallet.encryptedStorage.rootKey.read(password) const {cbor, signers} = await getMuesliSwapTransactionAndSigners(originalCbor, wallet) const keys = await Promise.all(signers.map(async (signer) => createRawTxSigningKey(rootKey, signer))) @@ -369,32 +368,6 @@ const HiddenInfo = ({ ) } -const PasswordModal = ({onConfirm}: {onConfirm: (password: string) => Promise}) => { - const [error, setError] = useState(null) - const [loading, setLoading] = useState(false) - - const onConfirmPress = async (password) => { - setError(null) - setLoading(true) - try { - await onConfirm(password) - } catch (e: unknown) { - if (e instanceof Error) { - setError(e) - } - } - setLoading(false) - } - - return ( - <> - - - - - ) -} - const MainInfo = ({tokenPrice, tokenAmount}: {tokenPrice: string; tokenAmount: string}) => { const strings = useStrings() return ( diff --git a/apps/wallet-mobile/translations/messages/src/yoroi-wallets/auth/auth.json b/apps/wallet-mobile/translations/messages/src/yoroi-wallets/auth/auth.json index e048120d6d..de9c073a1f 100644 --- a/apps/wallet-mobile/translations/messages/src/yoroi-wallets/auth/auth.json +++ b/apps/wallet-mobile/translations/messages/src/yoroi-wallets/auth/auth.json @@ -4,14 +4,14 @@ "defaultMessage": "!!!Authorize", "file": "src/yoroi-wallets/auth/auth.ts", "start": { - "line": 254, + "line": 255, "column": 13, - "index": 8406 + "index": 8429 }, "end": { - "line": 257, + "line": 258, "column": 3, - "index": 8513 + "index": 8536 } }, { @@ -19,14 +19,14 @@ "defaultMessage": "!!!Too many attempts", "file": "src/yoroi-wallets/auth/auth.ts", "start": { - "line": 258, + "line": 259, "column": 19, - "index": 8534 + "index": 8557 }, "end": { - "line": 261, + "line": 262, "column": 3, - "index": 8645 + "index": 8668 } }, { @@ -34,14 +34,14 @@ "defaultMessage": "!!!Unknown error!", "file": "src/yoroi-wallets/auth/auth.ts", "start": { - "line": 262, + "line": 263, "column": 16, - "index": 8663 + "index": 8686 }, "end": { - "line": 265, + "line": 266, "column": 3, - "index": 8770 + "index": 8793 } } ] \ No newline at end of file