Skip to content

Commit b164c3f

Browse files
Merge branch 'develop' into feat/delegation-banner
2 parents 399d4b0 + d70cdbf commit b164c3f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1442
-51
lines changed

apps/wallet-mobile/ios/Podfile.lock

-11
Original file line numberDiff line numberDiff line change
@@ -153,15 +153,9 @@ PODS:
153153
- libwebp/sharpyuv (1.3.2)
154154
- libwebp/webp (1.3.2):
155155
- libwebp/sharpyuv
156-
<<<<<<< Updated upstream
157-
- MMKV (1.3.3):
158-
- MMKVCore (~> 1.3.3)
159-
- MMKVCore (1.3.3)
160-
=======
161156
- MMKV (2.0.0):
162157
- MMKVCore (~> 2.0.0)
163158
- MMKVCore (2.0.0)
164-
>>>>>>> Stashed changes
165159
- MultiplatformBleAdapter (0.1.9)
166160
- nanopb (3.30910.0):
167161
- nanopb/decode (= 3.30910.0)
@@ -964,13 +958,8 @@ SPEC CHECKSUMS:
964958
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
965959
libvmaf: 27f523f1e63c694d14d534cd0fddd2fab0ae8711
966960
libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009
967-
<<<<<<< Updated upstream
968-
MMKV: f902fb6719da13c2ab0965233d8963a59416f911
969-
MMKVCore: d26e4d3edd5cb8588c2569222cbd8be4231374e9
970-
=======
971961
MMKV: f7d1d5945c8765f97f39c3d121f353d46735d801
972962
MMKVCore: c04b296010fcb1d1638f2c69405096aac12f6390
973-
>>>>>>> Stashed changes
974963
MultiplatformBleAdapter: 5a6a897b006764392f9cef785e4360f54fb9477d
975964
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
976965
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47

apps/wallet-mobile/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@
128128
"@types/bip39": "^3.0.0",
129129
"@types/pbkdf2": "^3.1.2",
130130
"@yoroi/api": "1.5.3",
131+
"@yoroi/banners": "1.0.0",
131132
"@yoroi/blockchains": "1.0.0",
132133
"@yoroi/claim": "1.0.0",
133134
"@yoroi/common": "^1.5.4",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import * as React from 'react'
2+
import {Animated, ViewStyle} from 'react-native'
3+
4+
type Props = {
5+
isVisible: boolean
6+
children: React.ReactNode
7+
duration?: number
8+
style?: ViewStyle
9+
}
10+
11+
export const DismissibleBanner = ({isVisible, children, style, duration = 300}: Props) => {
12+
const fadeAnim = React.useRef(new Animated.Value(0)).current
13+
const [shouldRender, setShouldRender] = React.useState(isVisible)
14+
15+
React.useEffect(() => {
16+
if (isVisible) {
17+
fadeAnim.setValue(0)
18+
setShouldRender(true)
19+
Animated.timing(fadeAnim, {
20+
toValue: 1,
21+
duration,
22+
useNativeDriver: true,
23+
}).start()
24+
} else {
25+
fadeAnim.setValue(1)
26+
Animated.timing(fadeAnim, {
27+
toValue: 0,
28+
duration,
29+
useNativeDriver: true,
30+
}).start(() => setShouldRender(false))
31+
}
32+
}, [isVisible, fadeAnim, duration])
33+
34+
if (!shouldRender) return null
35+
36+
return <Animated.View style={{...style, opacity: fadeAnim}}>{children}</Animated.View>
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import {time} from '../../../kernel/constants'
2+
import {shouldShowDRepConsiderDelegating} from './should-show-drep-consider-delegating'
3+
4+
describe('shouldShowDRepConsiderDelegating', () => {
5+
const moreThanOneMonthAgo = Date.now() - time.oneMonth - time.oneSecond
6+
const lessThanOneSecondAgo = Date.now() - time.oneSecond
7+
8+
it.each`
9+
isStaking | currentDRepIdHex | yoroiDRepIdHex | dismissedAt | expected
10+
${true} | ${'DE'} | ${'AD'} | ${moreThanOneMonthAgo} | ${true}
11+
${false} | ${'DE'} | ${'AD'} | ${moreThanOneMonthAgo} | ${false}
12+
${true} | ${'DE'} | ${'AD'} | ${lessThanOneSecondAgo} | ${false}
13+
${true} | ${'AD'} | ${'AD'} | ${moreThanOneMonthAgo} | ${false}
14+
`(
15+
'returns $expected when isStaking is $isStaking, currentDRepId is $currentDRepId, yoroiDRep is $yoroiDRepId, and dismissedAt is $dismissedAt',
16+
({isStaking, currentDRepIdHex, yoroiDRepIdHex, dismissedAt, expected}) => {
17+
const result = shouldShowDRepConsiderDelegating({
18+
isStaking,
19+
currentDRepIdHex,
20+
yoroiDRepIdHex,
21+
dismissedAt,
22+
})
23+
expect(result).toBe(expected)
24+
},
25+
)
26+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import {time} from '../../../kernel/constants'
2+
3+
export const shouldShowDRepConsiderDelegating = ({
4+
isStaking,
5+
currentDRepIdHex,
6+
yoroiDRepIdHex,
7+
dismissedAt,
8+
}: Readonly<{
9+
isStaking: boolean
10+
currentDRepIdHex: string
11+
yoroiDRepIdHex: string
12+
dismissedAt: number
13+
}>) => {
14+
const isYoroiDRep = currentDRepIdHex === yoroiDRepIdHex
15+
const hasBeenThirtyDays = dismissedAt + time.oneMonth < Date.now()
16+
return !isYoroiDRep && hasBeenThirtyDays && isStaking
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export enum BannerId {
2+
DRepConsiderDelegating = 'drep-consider-delegating',
3+
}
4+
5+
export type BannerStorageKey = `${BannerId}`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import {useBanner, useBanners} from '@yoroi/banners'
2+
import {useTheme} from '@yoroi/theme'
3+
import * as React from 'react'
4+
import {Button, Text, View} from 'react-native'
5+
6+
import {yoroiDRepIdHex} from '../../../kernel/constants'
7+
import {DismissibleBanner} from '../common/DismissableBanner'
8+
import {shouldShowDRepConsiderDelegating} from '../common/should-show-drep-consider-delegating'
9+
import {BannerId, BannerStorageKey} from '../common/types'
10+
11+
type Props = {
12+
isStaking: boolean
13+
currentDRepIdHex: string
14+
}
15+
16+
export const ShowBannerDRepConsiderDelegating = ({isStaking, currentDRepIdHex}: Props) => {
17+
const {
18+
color: {gray_200},
19+
atoms: {p_lg},
20+
} = useTheme()
21+
const {manager} = useBanners<BannerStorageKey>()
22+
const {dismiss, dismissedAt} = useBanner({id: BannerId.DRepConsiderDelegating, manager})
23+
24+
const shouldShow = shouldShowDRepConsiderDelegating({
25+
yoroiDRepIdHex,
26+
currentDRepIdHex,
27+
isStaking,
28+
dismissedAt,
29+
})
30+
31+
return (
32+
<DismissibleBanner isVisible={shouldShow} style={{backgroundColor: gray_200, ...p_lg, borderRadius: 4}}>
33+
<View>
34+
<Text>Consider delegating to DREP</Text>
35+
36+
<Button onPress={() => dismiss()} title="Dismiss" />
37+
</View>
38+
</DismissibleBanner>
39+
)
40+
}
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,52 @@
1+
import {bannersManagerMaker, BannersProvider} from '@yoroi/banners'
2+
import {observableStorageMaker} from '@yoroi/common'
3+
import {useTheme} from '@yoroi/theme'
14
import * as React from 'react'
2-
import {View} from 'react-native'
5+
import {SafeAreaView} from 'react-native-safe-area-context'
6+
7+
import {Button} from '../../components/Button/Button'
8+
import {Spacer} from '../../components/Spacer/Spacer'
9+
import {logger} from '../../kernel/logger/logger'
10+
import {BannerId, BannerStorageKey} from '../Banners/common/types'
11+
import {ShowBannerDRepConsiderDelegating} from '../Banners/useCases/ShowBannerDRepConsiderDelegating'
12+
import {useSelectedWallet} from '../WalletManager/common/hooks/useSelectedWallet'
13+
14+
// --------------------------------------------------------------------------------------------------
15+
// PINEED: this component can be replaced at anytime by anyone
316

4-
// Please, clean component after use
517
export const Playground = () => {
6-
return <View></View>
7-
}
18+
const {
19+
atoms: {pl_lg, pr_lg},
20+
} = useTheme()
21+
const {wallet} = useSelectedWallet()
22+
const walletStorage = wallet.networkManager.rootStorage.join(`${wallet.id}/`)
23+
const bannersStorage = observableStorageMaker<false, BannerStorageKey>(walletStorage.join('banners/'))
24+
const bannersManager = bannersManagerMaker<BannerStorageKey>({
25+
storage: bannersStorage,
26+
})
27+
const [refresh, setRefresh] = React.useState(0)
28+
29+
bannersStorage.onChange([BannerId.DRepConsiderDelegating], () => {
30+
logger.debug(`BannersStorageKey ${BannerId.DRepConsiderDelegating}:`, {
31+
dismissedAt: bannersManager.dismissedAt(BannerId.DRepConsiderDelegating),
32+
})
33+
})
834

9-
// const styles = StyleSheet.create({})
35+
return (
36+
<SafeAreaView edges={['top', 'left', 'right']} style={[pl_lg, pr_lg]}>
37+
<Button
38+
title="Reset"
39+
onPress={() => {
40+
bannersStorage.setItem(BannerId.DRepConsiderDelegating, '0')
41+
setRefresh(() => refresh + 1)
42+
}}
43+
/>
44+
45+
<Spacer height={20} />
46+
47+
<BannersProvider manager={bannersManager} key={refresh}>
48+
<ShowBannerDRepConsiderDelegating isStaking={true} currentDRepIdHex="123" />
49+
</BannersProvider>
50+
</SafeAreaView>
51+
)
52+
}

apps/wallet-mobile/src/features/Menu/Menu.tsx

+5-10
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import {usePoolTransition} from '../../legacy/Staking/PoolTransition/usePoolTran
2828
import {useCanVote} from '../RegisterCatalyst/common/hooks'
2929
import {InsufficientFundsModal} from '../RegisterCatalyst/common/InsufficientFundsModal'
3030
import {NetworkTag} from '../Settings/useCases/changeAppSettings/ChangeNetwork/NetworkTag'
31-
import {useIsGovernanceFeatureEnabled} from '../Staking/Governance/common/helpers'
3231
import {useSelectedWallet} from '../WalletManager/common/hooks/useSelectedWallet'
3332

3433
const MenuStack = createStackNavigator()
@@ -55,7 +54,6 @@ export const Menu = () => {
5554
const strings = useStrings()
5655
const {styles, color} = useStyles()
5756
const navigateTo = useNavigateTo()
58-
const {wallet} = useSelectedWallet()
5957
const {isPoolRetiring} = usePoolTransition()
6058
const {track} = useMetrics()
6159

@@ -64,7 +62,6 @@ export const Menu = () => {
6462
track.menuPageViewed()
6563
}, [track]),
6664
)
67-
const isGovernanceFeatureEnabled = useIsGovernanceFeatureEnabled(wallet)
6865

6966
return (
7067
<SafeAreaView edges={['left', 'right', 'bottom']} style={styles.root}>
@@ -82,13 +79,11 @@ export const Menu = () => {
8279
right={isPoolRetiring ? <Icon.Warning size={24} color={color.sys_magenta_500} /> : null}
8380
/>
8481

85-
{isGovernanceFeatureEnabled && (
86-
<Governance
87-
label={strings.governanceCentre}
88-
onPress={navigateTo.governanceCentre}
89-
left={<Icon.Governance size={24} color={color.gray_600} />}
90-
/>
91-
)}
82+
<Governance
83+
label={strings.governanceCentre}
84+
onPress={navigateTo.governanceCentre}
85+
left={<Icon.Governance size={24} color={color.gray_600} />}
86+
/>
9287

9388
<React.Suspense
9489
fallback={

apps/wallet-mobile/src/features/Staking/Governance/common/helpers.tsx

-7
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,12 @@ import {
88
} from '@yoroi/staking'
99
import * as React from 'react'
1010

11-
import {governaceAfterBlock} from '../../../../kernel/config'
1211
import {useWalletNavigation} from '../../../../kernel/navigation'
1312
import {YoroiWallet} from '../../../../yoroi-wallets/cardano/types'
1413
import {useStakingKey} from '../../../../yoroi-wallets/hooks'
1514
import {YoroiUnsignedTx} from '../../../../yoroi-wallets/types/yoroi'
1615
import {CardanoMobile} from '../../../../yoroi-wallets/wallets'
1716
import {useReviewTx} from '../../../ReviewTx/common/ReviewTxProvider'
18-
import {useBestBlock} from '../../../WalletManager/common/hooks/useBestBlock'
1917
import {useSelectedWallet} from '../../../WalletManager/common/hooks/useSelectedWallet'
2018
import {GovernanceVote} from '../types'
2119
import {useNavigateTo} from './navigation'
@@ -40,11 +38,6 @@ export const mapStakingKeyStateToGovernanceAction = (state: StakingKeyState): Go
4038
: {kind: 'delegate', hash: vote.hash, type: vote.type}
4139
}
4240

43-
export const useIsGovernanceFeatureEnabled = (wallet: YoroiWallet) => {
44-
const bestBlock = useBestBlock({options: {suspense: true}})
45-
return bestBlock.height >= governaceAfterBlock[wallet.networkManager.network]
46-
}
47-
4841
export const useGovernanceManagerMaker = () => {
4942
const {
5043
wallet: {

apps/wallet-mobile/src/kernel/constants.ts

+3
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,6 @@ export const time = freeze({
7777
// session here means while the wallet is open
7878
session: Infinity,
7979
})
80+
81+
// NOTE: bech32 'drep1ygr9tuapcanc3kpeyy4dc3vmrz9cfe5q7v9wj3x9j0ap3tswtre9j'
82+
export const yoroiDRepIdHex = '220655f3a1c76788d839212adc459b188b84e680f30ae944c593fa18ae'

apps/wallet-mobile/src/legacy/Dashboard/Dashboard.tsx

+2-6
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,7 @@ import {Banner} from '../../components/Banner/Banner'
2020
import {Button} from '../../components/Button/Button'
2121
import {useModal} from '../../components/Modal/ModalContext'
2222
import {Space} from '../../components/Space/Space'
23-
import {
24-
useIsGovernanceFeatureEnabled,
25-
useIsParticipatingInGovernance,
26-
} from '../../features/Staking/Governance/common/helpers'
23+
import {useIsParticipatingInGovernance} from '../../features/Staking/Governance/common/helpers'
2724
import {useStrings} from '../../features/Staking/Governance/common/strings'
2825
import {WithdrawWarningModal} from '../../features/Staking/Governance/useCases/WithdrawWarningModal/WithdrawWarningModal'
2926
import {useSelectedNetwork} from '../../features/WalletManager/common/hooks/useSelectedNetwork'
@@ -60,7 +57,6 @@ export const Dashboard = () => {
6057
const balances = useBalances(wallet)
6158
const primaryAmount = Amounts.getAmount(balances, wallet.portfolioPrimaryTokenInfo.id)
6259
const {stakingInfo, refetch: refetchStakingInfo, error, isLoading} = useStakingInfo(wallet)
63-
const isGovernanceFeatureEnabled = useIsGovernanceFeatureEnabled(wallet)
6460

6561
const isParticipatingInGovernance = useIsParticipatingInGovernance(wallet)
6662
const walletNavigateTo = useWalletNavigation()
@@ -72,7 +68,7 @@ export const Dashboard = () => {
7268
const onWithdraw = () => {
7369
track.claimAdaTransactionInitiated()
7470

75-
if (isGovernanceFeatureEnabled && !isParticipatingInGovernance) {
71+
if (!isParticipatingInGovernance) {
7672
openModal({
7773
title: governanceStrings.withdrawWarningTitle,
7874
content: <WithdrawWarningModal onParticipatePress={handleOnParticipatePress} />,

apps/wallet-mobile/translations/messages/src/legacy/Dashboard/Dashboard.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44
"defaultMessage": "!!!Go to Staking Center",
55
"file": "src/legacy/Dashboard/Dashboard.tsx",
66
"start": {
7-
"line": 244,
7+
"line": 237,
88
"column": 23,
9-
"index": 8048
9+
"index": 7685
1010
},
1111
"end": {
12-
"line": 247,
12+
"line": 240,
1313
"column": 3,
14-
"index": 8181
14+
"index": 7818
1515
}
1616
}
1717
]

codecov.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ coverage:
33
project:
44
default:
55
threshold: 1%
6-
target: 100%
6+
target: 20%
77
if_not_found: success
88

99
component_management:

metro.config.js

+8-7
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,27 @@ const path = require("path");
33
module.exports = {
44
projectRoot: path.resolve(__dirname, "apps/wallet-mobile"),
55
watchFolders: [
6-
path.resolve(__dirname, "apps/wallet-mobile"),
7-
path.resolve(__dirname, "node_modules"),
6+
path.resolve(__dirname, "packages/types"),
7+
path.resolve(__dirname, "packages/common"),
8+
path.resolve(__dirname, "packages/theme"),
89
path.resolve(__dirname, "packages/api"),
10+
path.resolve(__dirname, "packages/links"),
11+
path.resolve(__dirname, "packages/portfolio"),
912
path.resolve(__dirname, "packages/blockchains"),
1013
path.resolve(__dirname, "packages/claim"),
11-
path.resolve(__dirname, "packages/common"),
1214
path.resolve(__dirname, "packages/dapp-connector"),
1315
path.resolve(__dirname, "packages/exchange"),
1416
path.resolve(__dirname, "packages/explorers"),
1517
path.resolve(__dirname, "packages/identicon"),
16-
path.resolve(__dirname, "packages/links"),
1718
path.resolve(__dirname, "packages/notifications"),
18-
path.resolve(__dirname, "packages/portfolio"),
1919
path.resolve(__dirname, "packages/resolver"),
2020
path.resolve(__dirname, "packages/setup-wallet"),
2121
path.resolve(__dirname, "packages/staking"),
2222
path.resolve(__dirname, "packages/swap"),
23-
path.resolve(__dirname, "packages/theme"),
2423
path.resolve(__dirname, "packages/transfer"),
25-
path.resolve(__dirname, "packages/types"),
24+
path.resolve(__dirname, "packages/banners"),
25+
path.resolve(__dirname, "apps/wallet-mobile"),
26+
path.resolve(__dirname, "node_modules"),
2627
],
2728
resolver: {
2829
resolverMainFields: ["sbmodern", "react-native", "browser", "main"],

0 commit comments

Comments
 (0)