Skip to content

Commit

Permalink
Merge branch 'develop' into notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeljscript authored Oct 16, 2024
2 parents 9bab602 + c170ce0 commit d703287
Show file tree
Hide file tree
Showing 17 changed files with 415 additions and 558 deletions.
1 change: 0 additions & 1 deletion apps/wallet-mobile/.storybook/storybook.requires.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const TokenItem = ({
style={[styles.sentTokenItem, !isPrimaryToken && styles.notPrimarySentTokenItem]}
disabled={isPrimaryToken}
>
<Text style={[styles.tokenSentItemText, !isPrimaryToken && styles.notPrimarySentTokenItemText]}>{label}</Text>
<Text style={[styles.tokenSentItemText, !isPrimaryToken && styles.notPrimarySentTokenItemText]}>-{label}</Text>
</TouchableOpacity>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand All @@ -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) {
Expand All @@ -35,7 +35,10 @@ export const useOnConfirm = ({
onCancel={closeModal}
unsignedTx={unsignedTx}
onSuccess={(signedTx) => onSuccess?.(signedTx)}
onNotSupportedCIP1694={onNotSupportedCIP1694}
onNotSupportedCIP1694={() => {
closeModal()
navigateTo.notSupportedVersion()
}}
/>,
400,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -44,12 +43,6 @@ export const GovernanceNavigator = () => {
options={{title: strings.governanceCentreTitle}}
/>

<Stack.Screen
name="staking-gov-confirm-tx"
component={ConfirmTxScreen}
options={{title: strings.confirmTxTitle}}
/>

<Stack.Screen name="staking-gov-tx-success" component={SuccessTxScreen} options={txStatusOptions} />

<Stack.Screen name="staking-gov-tx-failed" component={FailedTxScreen} options={txStatusOptions} />
Expand Down

This file was deleted.

250 changes: 250 additions & 0 deletions apps/wallet-mobile/src/features/Staking/Governance/common/helpers.tsx
Original file line number Diff line number Diff line change
@@ -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 = [
<GovernanceProvider key="0" manager={manager}>
<DelegateOperation drepID={drepID} />
</GovernanceProvider>,
]

if (hasStakeCert) operations = [<RegisterStakingKeyOperation key="-1" />, ...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 = [<AbstainOperation key="0" />]
if (hasStakeCert) operations = [<RegisterStakingKeyOperation key="-1" />, ...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 = [<NoConfidenceOperation key="0" />]
if (hasStakeCert) operations = [<RegisterStakingKeyOperation key="-1" />, ...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 (
<View style={styles.operation}>
<Text style={styles.operationLabel}>{strings.registerStakingKey}</Text>

<Space width="lg" />

<Text style={styles.operationValue}>
{formatTokenWithText(asQuantity(wallet.protocolParams.keyDeposit), wallet.portfolioPrimaryTokenInfo)}
</Text>
</View>
)
}

const AbstainOperation = () => {
const {styles} = useStyles()
const strings = useStrings()

return (
<View style={styles.operation}>
<Text style={styles.operationLabel}>{strings.selectAbstain}</Text>
</View>
)
}

const NoConfidenceOperation = () => {
const {styles} = useStyles()
const strings = useStrings()

return (
<View style={styles.operation}>
<Text style={styles.operationLabel}>{strings.selectNoConfidence}</Text>
</View>
)
}

const DelegateOperation = ({drepID}: {drepID: string}) => {
const {styles} = useStyles()
const strings = useStrings()

const {data: bech32DrepId} = useBech32DRepID(drepID)

return (
<View style={styles.operation}>
<Text style={styles.operationLabel}>{strings.delegateVotingToDRep}</Text>

<Space width="lg" />

<Text style={styles.operationValue}>{bech32DrepId ?? drepID}</Text>
</View>
)
}

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
}
Loading

0 comments on commit d703287

Please sign in to comment.