diff --git a/apps/wallet-mobile/.storybook/storybook.requires.js b/apps/wallet-mobile/.storybook/storybook.requires.js index 41fde2e017..ce14bcbce3 100644 --- a/apps/wallet-mobile/.storybook/storybook.requires.js +++ b/apps/wallet-mobile/.storybook/storybook.requires.js @@ -227,7 +227,6 @@ const getStories = () => { "./src/features/Staking/Governance/common/Action/Action.stories.tsx": require("../src/features/Staking/Governance/common/Action/Action.stories.tsx"), "./src/features/Staking/Governance/common/LearnMoreLink/LearnMoreLink.stories.tsx": require("../src/features/Staking/Governance/common/LearnMoreLink/LearnMoreLink.stories.tsx"), "./src/features/Staking/Governance/useCases/ChangeVote/ChangeVoteScreen.stories.tsx": require("../src/features/Staking/Governance/useCases/ChangeVote/ChangeVoteScreen.stories.tsx"), - "./src/features/Staking/Governance/useCases/ConfirmTx/ConfirmTxScreen.stories.tsx": require("../src/features/Staking/Governance/useCases/ConfirmTx/ConfirmTxScreen.stories.tsx"), "./src/features/Staking/Governance/useCases/EnterDrepIdModal/EnterDrepIdModal.stories.tsx": require("../src/features/Staking/Governance/useCases/EnterDrepIdModal/EnterDrepIdModal.stories.tsx"), "./src/features/Staking/Governance/useCases/FailedTx/FailedTxScreen.stories.tsx": require("../src/features/Staking/Governance/useCases/FailedTx/FailedTxScreen.stories.tsx"), "./src/features/Staking/Governance/useCases/Home/HomeScreen.stories.tsx": require("../src/features/Staking/Governance/useCases/Home/HomeScreen.stories.tsx"), diff --git a/apps/wallet-mobile/src/features/ReviewTx/common/TokenItem.tsx b/apps/wallet-mobile/src/features/ReviewTx/common/TokenItem.tsx index fabea93b81..51ec99bbaa 100644 --- a/apps/wallet-mobile/src/features/ReviewTx/common/TokenItem.tsx +++ b/apps/wallet-mobile/src/features/ReviewTx/common/TokenItem.tsx @@ -48,7 +48,7 @@ export const TokenItem = ({ style={[styles.sentTokenItem, !isPrimaryToken && styles.notPrimarySentTokenItem]} disabled={isPrimaryToken} > - {label} + -{label} ) } diff --git a/apps/wallet-mobile/src/features/ReviewTx/common/hooks/useOnConfirm.tsx b/apps/wallet-mobile/src/features/ReviewTx/common/hooks/useOnConfirm.tsx index 38188b6e93..871badd91b 100644 --- a/apps/wallet-mobile/src/features/ReviewTx/common/hooks/useOnConfirm.tsx +++ b/apps/wallet-mobile/src/features/ReviewTx/common/hooks/useOnConfirm.tsx @@ -5,6 +5,7 @@ import {ConfirmTxWithOsModal} from '../../../../components/ConfirmTxWithOsModal/ import {ConfirmTxWithSpendingPasswordModal} from '../../../../components/ConfirmTxWithSpendingPasswordModal/ConfirmTxWithSpendingPasswordModal' import {useModal} from '../../../../components/Modal/ModalContext' import {YoroiSignedTx, YoroiUnsignedTx} from '../../../../yoroi-wallets/types/yoroi' +import {useNavigateTo} from '../../../Staking/Governance/common/navigation' import {useSelectedWallet} from '../../../WalletManager/common/hooks/useSelectedWallet' import {useStrings} from './useStrings' @@ -13,19 +14,18 @@ export const useOnConfirm = ({ unsignedTx, onSuccess, onError, - onNotSupportedCIP1694, }: { onSuccess?: ((txId: YoroiSignedTx) => void) | null onError?: (() => void) | null cbor?: string unsignedTx?: YoroiUnsignedTx - onNotSupportedCIP1694?: () => void }) => { if (unsignedTx === undefined) throw new Error('useOnConfirm: unsignedTx missing') const {meta} = useSelectedWallet() const {openModal, closeModal} = useModal() const strings = useStrings() + const navigateTo = useNavigateTo() const onConfirm = () => { if (meta.isHW) { @@ -35,7 +35,10 @@ export const useOnConfirm = ({ onCancel={closeModal} unsignedTx={unsignedTx} onSuccess={(signedTx) => onSuccess?.(signedTx)} - onNotSupportedCIP1694={onNotSupportedCIP1694} + onNotSupportedCIP1694={() => { + closeModal() + navigateTo.notSupportedVersion() + }} />, 400, ) diff --git a/apps/wallet-mobile/src/features/Staking/Governance/GovernanceNavigator.tsx b/apps/wallet-mobile/src/features/Staking/Governance/GovernanceNavigator.tsx index 5df15e523e..865e67fbf0 100644 --- a/apps/wallet-mobile/src/features/Staking/Governance/GovernanceNavigator.tsx +++ b/apps/wallet-mobile/src/features/Staking/Governance/GovernanceNavigator.tsx @@ -9,7 +9,6 @@ import {useGovernanceManagerMaker} from './common/helpers' import {NavigationStack} from './common/navigation' import {useStrings} from './common/strings' import {ChangeVoteScreen} from './useCases/ChangeVote/ChangeVoteScreen' -import {ConfirmTxScreen} from './useCases/ConfirmTx/ConfirmTxScreen' import {FailedTxScreen} from './useCases/FailedTx/FailedTxScreen' import {HomeScreen} from './useCases/Home/HomeScreen' import {NoFundsScreen} from './useCases/NoFunds/NoFundsScreen' @@ -44,12 +43,6 @@ export const GovernanceNavigator = () => { options={{title: strings.governanceCentreTitle}} /> - - diff --git a/apps/wallet-mobile/src/features/Staking/Governance/common/helpers.ts b/apps/wallet-mobile/src/features/Staking/Governance/common/helpers.ts deleted file mode 100644 index 304f619fbb..0000000000 --- a/apps/wallet-mobile/src/features/Staking/Governance/common/helpers.ts +++ /dev/null @@ -1,60 +0,0 @@ -import {useAsyncStorage} from '@yoroi/common' -import {type StakingKeyState, governanceApiMaker, governanceManagerMaker, useStakingKeyState} from '@yoroi/staking' -import * as React from 'react' - -import {governaceAfterBlock} from '../../../../kernel/config' -import {YoroiWallet} from '../../../../yoroi-wallets/cardano/types' -import {useStakingKey} from '../../../../yoroi-wallets/hooks' -import {CardanoMobile} from '../../../../yoroi-wallets/wallets' -import {useBestBlock} from '../../../WalletManager/common/hooks/useBestBlock' -import {useSelectedWallet} from '../../../WalletManager/common/hooks/useSelectedWallet' -import {GovernanceVote} from '../types' - -export const useIsParticipatingInGovernance = (wallet: YoroiWallet) => { - const stakingKeyHash = useStakingKey(wallet) - const {data: stakingStatus} = useStakingKeyState(stakingKeyHash, { - suspense: true, - useErrorBoundary: false, - retry: false, - }) - return stakingStatus ? mapStakingKeyStateToGovernanceAction(stakingStatus) !== null : false -} - -export const mapStakingKeyStateToGovernanceAction = (state: StakingKeyState): GovernanceVote | null => { - if (!state.drepDelegation) return null - const vote = state.drepDelegation - return vote.action === 'abstain' - ? {kind: 'abstain'} - : vote.action === 'no-confidence' - ? {kind: 'no-confidence'} - : {kind: 'delegate', drepID: vote.drepID} -} - -export const useIsGovernanceFeatureEnabled = (wallet: YoroiWallet) => { - const bestBlock = useBestBlock({options: {suspense: true}}) - return bestBlock.height >= governaceAfterBlock[wallet.networkManager.network] -} - -export const useGovernanceManagerMaker = () => { - const { - wallet: { - networkManager: {network}, - id: walletId, - }, - } = useSelectedWallet() - - const storage = useAsyncStorage() - const governanceStorage = storage.join(`wallet/${walletId}/staking-governance/`) - - return React.useMemo( - () => - governanceManagerMaker({ - walletId, - network, - api: governanceApiMaker({network}), - cardano: CardanoMobile, - storage: governanceStorage, - }), - [governanceStorage, network, walletId], - ) -} diff --git a/apps/wallet-mobile/src/features/Staking/Governance/common/helpers.tsx b/apps/wallet-mobile/src/features/Staking/Governance/common/helpers.tsx new file mode 100644 index 0000000000..8e02078802 --- /dev/null +++ b/apps/wallet-mobile/src/features/Staking/Governance/common/helpers.tsx @@ -0,0 +1,250 @@ +import {useAsyncStorage} from '@yoroi/common' +import { + type StakingKeyState, + governanceApiMaker, + governanceManagerMaker, + GovernanceProvider, + useBech32DRepID, + useGovernance, + useStakingKeyState, + useUpdateLatestGovernanceAction, +} from '@yoroi/staking' +import {useTheme} from '@yoroi/theme' +import * as React from 'react' +import {StyleSheet, Text, View} from 'react-native' + +import {Space} from '../../../../components/Space/Space' +import {governaceAfterBlock} from '../../../../kernel/config' +import {useWalletNavigation} from '../../../../kernel/navigation' +import {YoroiWallet} from '../../../../yoroi-wallets/cardano/types' +import {useStakingKey} from '../../../../yoroi-wallets/hooks' +import {YoroiUnsignedTx} from '../../../../yoroi-wallets/types/yoroi' +import {formatTokenWithText} from '../../../../yoroi-wallets/utils/format' +import {asQuantity} from '../../../../yoroi-wallets/utils/utils' +import {CardanoMobile} from '../../../../yoroi-wallets/wallets' +import {useReviewTx} from '../../../ReviewTx/common/ReviewTxProvider' +import {useBestBlock} from '../../../WalletManager/common/hooks/useBestBlock' +import {useSelectedWallet} from '../../../WalletManager/common/hooks/useSelectedWallet' +import {GovernanceVote} from '../types' +import {useNavigateTo} from './navigation' +import {useStrings} from './strings' + +export const useIsParticipatingInGovernance = (wallet: YoroiWallet) => { + const stakingKeyHash = useStakingKey(wallet) + const {data: stakingStatus} = useStakingKeyState(stakingKeyHash, { + suspense: true, + useErrorBoundary: false, + retry: false, + }) + return stakingStatus ? mapStakingKeyStateToGovernanceAction(stakingStatus) !== null : false +} + +export const mapStakingKeyStateToGovernanceAction = (state: StakingKeyState): GovernanceVote | null => { + if (!state.drepDelegation) return null + const vote = state.drepDelegation + return vote.action === 'abstain' + ? {kind: 'abstain'} + : vote.action === 'no-confidence' + ? {kind: 'no-confidence'} + : {kind: 'delegate', drepID: vote.drepID} +} + +export const useIsGovernanceFeatureEnabled = (wallet: YoroiWallet) => { + const bestBlock = useBestBlock({options: {suspense: true}}) + return bestBlock.height >= governaceAfterBlock[wallet.networkManager.network] +} + +export const useGovernanceManagerMaker = () => { + const { + wallet: { + networkManager: {network}, + id: walletId, + }, + } = useSelectedWallet() + + const storage = useAsyncStorage() + const governanceStorage = storage.join(`wallet/${walletId}/staking-governance/`) + + return React.useMemo( + () => + governanceManagerMaker({ + walletId, + network, + api: governanceApiMaker({network}), + cardano: CardanoMobile, + storage: governanceStorage, + }), + [governanceStorage, network, walletId], + ) +} + +export const useGovernanceActions = () => { + const {manager} = useGovernance() + const {wallet} = useSelectedWallet() + const navigateTo = useNavigateTo() + const {unsignedTxChanged, onSuccessChanged, onErrorChanged, operationsChanged} = useReviewTx() + const {updateLatestGovernanceAction} = useUpdateLatestGovernanceAction(wallet.id) + const {navigateToTxReview} = useWalletNavigation() + + const handleDelegateAction = ({ + drepID, + unsignedTx, + hasStakeCert = false, + navigateToStakingOnSuccess = false, + }: { + drepID: string + unsignedTx: YoroiUnsignedTx + hasStakeCert?: boolean + navigateToStakingOnSuccess?: boolean + }) => { + let operations = [ + + + , + ] + + if (hasStakeCert) operations = [, ...operations] + + operationsChanged(operations) + onSuccessChanged((signedTx) => { + updateLatestGovernanceAction({kind: 'delegate-to-drep', drepID, txID: signedTx.signedTx.id}) + navigateTo.txSuccess({navigateToStaking: navigateToStakingOnSuccess ?? false, kind: 'delegate'}) + }) + onErrorChanged(() => navigateTo.txFailed()) + unsignedTxChanged(unsignedTx) + + navigateToTxReview() + } + + const handleAbstainAction = ({ + unsignedTx, + hasStakeCert = false, + navigateToStakingOnSuccess = false, + }: { + unsignedTx: YoroiUnsignedTx + hasStakeCert?: boolean + navigateToStakingOnSuccess?: boolean + }) => { + let operations = [] + if (hasStakeCert) operations = [, ...operations] + + operationsChanged(operations) + onSuccessChanged((signedTx) => { + updateLatestGovernanceAction({kind: 'vote', vote: 'abstain', txID: signedTx.signedTx.id}) + navigateTo.txSuccess({navigateToStaking: navigateToStakingOnSuccess ?? false, kind: 'abstain'}) + }) + onErrorChanged(() => navigateTo.txFailed()) + unsignedTxChanged(unsignedTx) + + navigateToTxReview() + } + + const handleNoConfidenceAction = ({ + unsignedTx, + hasStakeCert = false, + navigateToStakingOnSuccess = false, + }: { + unsignedTx: YoroiUnsignedTx + hasStakeCert?: boolean + navigateToStakingOnSuccess?: boolean + }) => { + let operations = [] + if (hasStakeCert) operations = [, ...operations] + + operationsChanged(operations) + onSuccessChanged((signedTx) => { + updateLatestGovernanceAction({kind: 'vote', vote: 'no-confidence', txID: signedTx.signedTx.id}) + navigateTo.txSuccess({ + navigateToStaking: navigateToStakingOnSuccess ?? false, + kind: 'no-confidence', + }) + }) + onErrorChanged(() => navigateTo.txFailed()) + unsignedTxChanged(unsignedTx) + + navigateToTxReview() + } + + return {handleDelegateAction, handleAbstainAction, handleNoConfidenceAction} as const +} + +const RegisterStakingKeyOperation = () => { + const {styles} = useStyles() + const strings = useStrings() + const {wallet} = useSelectedWallet() + + return ( + + {strings.registerStakingKey} + + + + + {formatTokenWithText(asQuantity(wallet.protocolParams.keyDeposit), wallet.portfolioPrimaryTokenInfo)} + + + ) +} + +const AbstainOperation = () => { + const {styles} = useStyles() + const strings = useStrings() + + return ( + + {strings.selectAbstain} + + ) +} + +const NoConfidenceOperation = () => { + const {styles} = useStyles() + const strings = useStrings() + + return ( + + {strings.selectNoConfidence} + + ) +} + +const DelegateOperation = ({drepID}: {drepID: string}) => { + const {styles} = useStyles() + const strings = useStrings() + + const {data: bech32DrepId} = useBech32DRepID(drepID) + + return ( + + {strings.delegateVotingToDRep} + + + + {bech32DrepId ?? drepID} + + ) +} + +const useStyles = () => { + const {color, atoms} = useTheme() + + const styles = StyleSheet.create({ + operation: { + ...atoms.flex_row, + ...atoms.justify_between, + ...atoms.align_start, + }, + operationLabel: { + ...atoms.body_2_md_regular, + color: color.text_gray_low, + }, + operationValue: { + ...atoms.flex_1, + ...atoms.text_right, + ...atoms.body_2_md_regular, + color: color.text_gray_medium, + }, + }) + + return {styles} as const +} diff --git a/apps/wallet-mobile/src/features/Staking/Governance/common/navigation.ts b/apps/wallet-mobile/src/features/Staking/Governance/common/navigation.ts index 62b7b4e91c..fc20cd6c4a 100644 --- a/apps/wallet-mobile/src/features/Staking/Governance/common/navigation.ts +++ b/apps/wallet-mobile/src/features/Staking/Governance/common/navigation.ts @@ -2,7 +2,6 @@ import {useNavigation} from '@react-navigation/native' import {createStackNavigator, StackNavigationProp} from '@react-navigation/stack' import {useRef} from 'react' -import {YoroiUnsignedTx} from '../../../../yoroi-wallets/types/yoroi' import {GovernanceVote} from '../types' export type Routes = { @@ -10,12 +9,6 @@ export type Routes = { navigateToStakingOnSuccess?: boolean } 'staking-gov-change-vote': undefined - 'staking-gov-confirm-tx': { - vote: GovernanceVote - unsignedTx: YoroiUnsignedTx - registerStakingKey?: boolean - navigateToStakingOnSuccess?: boolean - } 'staking-gov-tx-success'?: {navigateToStaking?: boolean; kind: GovernanceVote['kind']} 'staking-gov-tx-failed': undefined 'staking-gov-not-supported-version': undefined @@ -29,7 +22,6 @@ export const useNavigateTo = () => { return useRef({ home: () => navigation.navigate('staking-gov-home'), changeVote: () => navigation.navigate('staking-gov-change-vote'), - confirmTx: (params: Routes['staking-gov-confirm-tx']) => navigation.navigate('staking-gov-confirm-tx', params), txSuccess: (params?: Routes['staking-gov-tx-success']) => navigation.navigate('staking-gov-tx-success', params), txFailed: () => navigation.navigate('staking-gov-tx-failed'), notSupportedVersion: () => navigation.navigate('staking-gov-not-supported-version'), diff --git a/apps/wallet-mobile/src/features/Staking/Governance/common/strings.ts b/apps/wallet-mobile/src/features/Staking/Governance/common/strings.ts index 2280cb83df..b53ad73cd3 100644 --- a/apps/wallet-mobile/src/features/Staking/Governance/common/strings.ts +++ b/apps/wallet-mobile/src/features/Staking/Governance/common/strings.ts @@ -18,7 +18,7 @@ export const useStrings = () => { drepKey: intl.formatMessage(messages.drepKey), delegatingToADRep: intl.formatMessage(messages.delegatingToADRep), abstaining: intl.formatMessage(messages.abstaining), - delegateVotingToDRep: (drepID: string) => intl.formatMessage(messages.delegateVotingToDRep, {drepID}), + delegateVotingToDRep: intl.formatMessage(messages.delegateVotingToDRep), selectAbstain: intl.formatMessage(messages.selectAbstain), selectNoConfidence: intl.formatMessage(messages.selectNoConfidence), operations: intl.formatMessage(messages.operations), @@ -124,7 +124,7 @@ const messages = defineMessages({ }, delegateVotingToDRep: { id: 'components.governance.delegateVotingToDRep', - defaultMessage: '!!!Delegate voting to \n{drepID}', + defaultMessage: '!!!Delegate voting to', }, selectAbstain: { id: 'components.governance.selectAbstain', @@ -255,7 +255,7 @@ const messages = defineMessages({ }, registerStakingKey: { id: 'components.governance.registerStakingKey', - defaultMessage: '!!!Register staking key', + defaultMessage: '!!!Register staking key deposit', }, enterDrepIDInfo: { id: 'components.governance.enterDrepIDInfo', diff --git a/apps/wallet-mobile/src/features/Staking/Governance/useCases/ChangeVote/ChangeVoteScreen.tsx b/apps/wallet-mobile/src/features/Staking/Governance/useCases/ChangeVote/ChangeVoteScreen.tsx index 7180a1c471..093fa90e44 100644 --- a/apps/wallet-mobile/src/features/Staking/Governance/useCases/ChangeVote/ChangeVoteScreen.tsx +++ b/apps/wallet-mobile/src/features/Staking/Governance/useCases/ChangeVote/ChangeVoteScreen.tsx @@ -15,9 +15,8 @@ import {Spacer} from '../../../../../components/Spacer/Spacer' import {useCreateGovernanceTx, useStakingKey} from '../../../../../yoroi-wallets/hooks' import {useSelectedWallet} from '../../../../WalletManager/common/hooks/useSelectedWallet' import {Action} from '../../common/Action/Action' -import {mapStakingKeyStateToGovernanceAction} from '../../common/helpers' +import {mapStakingKeyStateToGovernanceAction, useGovernanceActions} from '../../common/helpers' import {LearnMoreLink} from '../../common/LearnMoreLink/LearnMoreLink' -import {useNavigateTo} from '../../common/navigation' import {useStrings} from '../../common/strings' import {GovernanceVote} from '../../types' import {EnterDrepIdModal} from '../EnterDrepIdModal/EnterDrepIdModal' @@ -25,7 +24,6 @@ import {EnterDrepIdModal} from '../EnterDrepIdModal/EnterDrepIdModal' export const ChangeVoteScreen = () => { const strings = useStrings() const {wallet, meta} = useSelectedWallet() - const navigateTo = useNavigateTo() const stakingKeyHash = useStakingKey(wallet) const {data: stakingStatus} = useStakingKeyState(stakingKeyHash, {suspense: true}) const action = stakingStatus ? mapStakingKeyStateToGovernanceAction(stakingStatus) : null @@ -33,6 +31,7 @@ export const ChangeVoteScreen = () => { const {manager} = useGovernance() const [pendingVote, setPendingVote] = React.useState(null) const {styles} = useStyles() + const governanceActions = useGovernanceActions() const {createCertificate: createDelegationCertificate, isLoading: isCreatingDelegationCertificate} = useDelegationCertificate({ @@ -73,7 +72,11 @@ export const ChangeVoteScreen = () => { certificates: [certificate], addressMode: meta.addressMode, }) - navigateTo.confirmTx({unsignedTx, vote}) + + governanceActions.handleDelegateAction({ + unsignedTx, + drepID, + }) }, }, ) @@ -93,7 +96,10 @@ export const ChangeVoteScreen = () => { certificates: [certificate], addressMode: meta.addressMode, }) - navigateTo.confirmTx({unsignedTx, vote}) + + governanceActions.handleAbstainAction({ + unsignedTx, + }) }, }, ) @@ -112,7 +118,10 @@ export const ChangeVoteScreen = () => { certificates: [certificate], addressMode: meta.addressMode, }) - navigateTo.confirmTx({unsignedTx, vote}) + + governanceActions.handleNoConfidenceAction({ + unsignedTx, + }) }, }, ) diff --git a/apps/wallet-mobile/src/features/Staking/Governance/useCases/ConfirmTx/ConfirmTxScreen.stories.tsx b/apps/wallet-mobile/src/features/Staking/Governance/useCases/ConfirmTx/ConfirmTxScreen.stories.tsx deleted file mode 100644 index 6e0a8327f9..0000000000 --- a/apps/wallet-mobile/src/features/Staking/Governance/useCases/ConfirmTx/ConfirmTxScreen.stories.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import {NavigationRouteContext} from '@react-navigation/core' -import {storiesOf} from '@storybook/react-native' -import {GovernanceProvider} from '@yoroi/staking' -import React from 'react' - -import {SafeArea} from '../../../../../components/SafeArea' -import {mocks} from '../../../../../yoroi-wallets/mocks/wallet' -import {WalletManagerProviderMock} from '../../../../../yoroi-wallets/mocks/WalletManagerProviderMock' -import {mocks as governanceMocks} from '../../common/mocks' -import {Routes} from '../../common/navigation' -import {ConfirmTxScreen} from './ConfirmTxScreen' - -storiesOf('Governance/ConfirmTxScreen', module) - .addDecorator((story) => {story()}) - .addDecorator((story) => ( - - {story()} - - )) - .add('Abstain', () => ( - - - - )) - .add('No Confidence', () => ( - - - - )) - .add('Delegate', () => ( - - - - )) - .add('Delegate And Register Staking Key', () => ( - - - - )) - -const getContextValue = (vote: Routes['staking-gov-confirm-tx']['vote'], registerStakingKey = false) => ({ - key: 'key', - name: 'name', - params: { - vote, - unsignedTx: mocks.yoroiUnsignedTx, - registerStakingKey, - }, -}) diff --git a/apps/wallet-mobile/src/features/Staking/Governance/useCases/ConfirmTx/ConfirmTxScreen.tsx b/apps/wallet-mobile/src/features/Staking/Governance/useCases/ConfirmTx/ConfirmTxScreen.tsx deleted file mode 100644 index 3cc7acdff6..0000000000 --- a/apps/wallet-mobile/src/features/Staking/Governance/useCases/ConfirmTx/ConfirmTxScreen.tsx +++ /dev/null @@ -1,293 +0,0 @@ -import {useFocusEffect} from '@react-navigation/native' -import {useBech32DRepID, useUpdateLatestGovernanceAction} from '@yoroi/staking' -import {useTheme} from '@yoroi/theme' -import React from 'react' -import {StyleSheet, View} from 'react-native' -import {TouchableOpacity} from 'react-native-gesture-handler' - -import {Button} from '../../../../../components/Button/Button' -import {ConfirmTxWithHwModal} from '../../../../../components/ConfirmTxWithHwModal/ConfirmTxWithHwModal' -import {ConfirmTxWithOsModal} from '../../../../../components/ConfirmTxWithOsModal/ConfirmTxWithOsModal' -import {ConfirmTxWithSpendingPasswordModal} from '../../../../../components/ConfirmTxWithSpendingPasswordModal/ConfirmTxWithSpendingPasswordModal' -import {Icon} from '../../../../../components/Icon' -import {useModal} from '../../../../../components/Modal/ModalContext' -import {PairedBalance} from '../../../../../components/PairedBalance/PairedBalance' -import {Space} from '../../../../../components/Space/Space' -import {Spacer} from '../../../../../components/Spacer/Spacer' -import {Text} from '../../../../../components/Text' -import {useMetrics} from '../../../../../kernel/metrics/metricsManager' -import {useUnsafeParams} from '../../../../../kernel/navigation' -import {formatTokenWithText} from '../../../../../yoroi-wallets/utils/format' -import {Amounts} from '../../../../../yoroi-wallets/utils/utils' -import {useSelectedWallet} from '../../../../WalletManager/common/hooks/useSelectedWallet' -import {Routes, useNavigateTo} from '../../common/navigation' -import {useStrings} from '../../common/strings' -import {GovernanceKindMap} from '../../types' - -export const ConfirmTxScreen = () => { - const strings = useStrings() - const {wallet, meta} = useSelectedWallet() - const params = useUnsafeParams() - const navigateTo = useNavigateTo() - const {updateLatestGovernanceAction} = useUpdateLatestGovernanceAction(wallet.id) - const {openModal, closeModal} = useModal() - const [operationsOpen, setOperationsOpen] = React.useState(true) - const {track} = useMetrics() - const {styles} = useStyles() - - useFocusEffect( - React.useCallback(() => { - track.governanceConfirmTransactionPageViewed({ - governance_selection: GovernanceKindMap[params.vote.kind], - }) - }, [params.vote.kind, track]), - ) - - const {data: bech32DrepId} = useBech32DRepID(params.vote.kind === 'delegate' ? params.vote.drepID : '', { - enabled: params.vote.kind === 'delegate', - }) - - const titles = { - abstain: strings.actionAbstainTitle, - 'no-confidence': strings.actionNoConfidenceTitle, - delegate: strings.actionDelegateToADRepTitle, - } - - const descriptions = { - abstain: strings.actionAbstainDescription, - 'no-confidence': strings.actionNoConfidenceDescription, - delegate: strings.actionDelegateToADRepDescription, - } - - const operations = { - abstain: strings.selectAbstain, - 'no-confidence': strings.selectNoConfidence, - delegate: strings.delegateVotingToDRep(params.vote.kind === 'delegate' ? bech32DrepId ?? params.vote.drepID : ''), - } - - const title = titles[params.vote.kind] - const description = descriptions[params.vote.kind] - const operation = operations[params.vote.kind] - - const fee = params.unsignedTx.fee - const feeAmount = Amounts.getAmount(fee, wallet.portfolioPrimaryTokenInfo.id) - const feeText = formatTokenWithText(feeAmount.quantity, wallet.portfolioPrimaryTokenInfo) - - const onSuccess = (txID: string) => { - if (params.vote.kind === 'delegate') { - updateLatestGovernanceAction({kind: 'delegate-to-drep', drepID: params.vote.drepID, txID}) - } - - if (params.vote.kind === 'abstain') { - updateLatestGovernanceAction({kind: 'vote', vote: 'abstain', txID}) - } - - if (params.vote.kind === 'no-confidence') { - updateLatestGovernanceAction({kind: 'vote', vote: 'no-confidence', txID}) - } - - navigateTo.txSuccess({navigateToStaking: params.navigateToStakingOnSuccess ?? false, kind: params.vote.kind}) - } - - const onSubmit = () => { - if (meta.isHW) { - openModal( - strings.signTransaction, - onSuccess(signedTx.signedTx.id)} - onNotSupportedCIP1694={() => { - closeModal() - navigateTo.notSupportedVersion() - }} - />, - 400, - ) - return - } - - if (!meta.isHW && !meta.isEasyConfirmationEnabled) { - openModal( - strings.signTransaction, - onSuccess(signedTx.signedTx.id)} - onError={() => navigateTo.txFailed()} - />, - ) - return - } - - if (!meta.isHW && meta.isEasyConfirmationEnabled) { - openModal( - strings.signTransaction, - onSuccess(signedTx.signedTx.id)} - onError={() => navigateTo.txFailed()} - />, - ) - return - } - } - - return ( - - - - {title} - - - - {description} - - - - - - {strings.total} - - {feeText} - - - - - - - - - - - - {strings.transactionDetails} - - - - setOperationsOpen(!operationsOpen)}> - {strings.operations} - - - - - {operationsOpen && ( - <> - {params.registerStakingKey && ( - <> - - - {strings.registerStakingKey} - - )} - - - - {operation} - - )} - - - - - - {strings.txFees} - - - {feeText} - - - - -