Skip to content

Commit 4d1033e

Browse files
committed
Implement ability to delegate all at the same time
1 parent dc03567 commit 4d1033e

File tree

4 files changed

+137
-65
lines changed

4 files changed

+137
-65
lines changed

src/components/Dot.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1+
import { Color } from '@theme/theme'
12
import React, { memo } from 'react'
23
import Box from './Box'
34

4-
type Props = { filled?: boolean }
5-
const dotSize = 16
6-
const Dot = ({ filled }: Props) => {
5+
type Props = { filled?: boolean; color?: Color; size?: number }
6+
const defaultSize = 16
7+
const Dot = ({ filled, color = 'purple500', size = defaultSize }: Props) => {
78
return (
89
<Box
910
borderWidth={1}
1011
marginHorizontal="xs"
11-
borderColor={filled ? 'purple500' : 'surfaceSecondaryText'}
12-
width={dotSize}
13-
height={dotSize}
12+
borderColor={filled ? color : 'surfaceSecondaryText'}
13+
width={size}
14+
height={size}
1415
borderRadius="round"
15-
backgroundColor={filled ? 'purple500' : undefined}
16+
backgroundColor={filled ? color : undefined}
1617
/>
1718
)
1819
}

src/features/governance/AssignProxyScreen.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { MAX_TRANSACTIONS_PER_SIGNATURE_BATCH } from '@utils/constants'
2222
import sleep from '@utils/sleep'
2323
import { getBasePriorityFee } from '@utils/walletApiV2'
2424
import BN from 'bn.js'
25-
import React, { useCallback, useMemo, useState } from 'react'
25+
import React, { useCallback, useEffect, useMemo, useState } from 'react'
2626
import { useTranslation } from 'react-i18next'
2727
import { FlatList } from 'react-native'
2828
import { Edge } from 'react-native-safe-area-context'

src/features/governance/PositionsScreen.tsx

Lines changed: 126 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,19 @@ import {
2424
} from '@helium/voter-stake-registry-hooks'
2525
import { useCurrentWallet } from '@hooks/useCurrentWallet'
2626
import { useMetaplexMetadata } from '@hooks/useMetaplexMetadata'
27-
import { Keypair, TransactionInstruction } from '@solana/web3.js'
27+
import { Keypair, TransactionInstruction, PublicKey } from '@solana/web3.js'
2828
import { useGovernance } from '@storage/GovernanceProvider'
2929
import { MAX_TRANSACTIONS_PER_SIGNATURE_BATCH } from '@utils/constants'
3030
import { daysToSecs, getFormattedStringFromDays } from '@utils/dateTools'
3131
import { getBasePriorityFee } from '@utils/walletApiV2'
3232
import BN from 'bn.js'
3333
import React, { useCallback, useMemo, useState } from 'react'
3434
import { useTranslation } from 'react-i18next'
35+
import Dot from '@components/Dot'
36+
import BlurActionSheet from '@components/BlurActionSheet'
37+
import ListItem from '@components/ListItem'
38+
import { useNavigation } from '@react-navigation/native'
39+
import { GovernanceNavigationProp } from './governanceTypes'
3540
import { MessagePreview } from '../../solana/MessagePreview'
3641
import { useSolana } from '../../solana/SolanaProvider'
3742
import { useWalletSign } from '../../solana/WalletSignProvider'
@@ -264,8 +269,9 @@ export const PositionsScreen = () => {
264269
() =>
265270
positions?.filter(
266271
(p) =>
267-
p.lockup.kind.constant ||
268-
p.lockup.endTs.gt(new BN(now?.toString() || '0')),
272+
(p.lockup.kind.constant ||
273+
p.lockup.endTs.gt(new BN(now?.toString() || '0'))) &&
274+
!p.isProxiedToMe,
269275
),
270276
[positions, now],
271277
)
@@ -298,6 +304,62 @@ export const PositionsScreen = () => {
298304
refetchState()
299305
}
300306

307+
const [isManageSheetOpen, setIsManageSheetOpen] = useState(false)
308+
309+
const navigation = useNavigation<GovernanceNavigationProp>()
310+
const unproxiedPositions = useMemo(
311+
() =>
312+
positions?.filter(
313+
(p) => !p.proxy || p.proxy.nextVoter.equals(PublicKey.default),
314+
) || [],
315+
[positions],
316+
)
317+
318+
// Prepare action sheet data for ListItem
319+
const manageActions = [
320+
{
321+
label: t('gov.transactions.lockTokens'),
322+
value: 'lock',
323+
onPress: () => {
324+
setIsManageSheetOpen(false)
325+
setIsLockModalOpen(true)
326+
},
327+
disabled: claimingAllRewards || loading,
328+
},
329+
{
330+
label: t('gov.positions.delegateAll'),
331+
value: 'delegate',
332+
onPress: () => {
333+
setIsManageSheetOpen(false)
334+
setIsDelegateAllModalOpen(true)
335+
},
336+
disabled: loading || delegateAllLoading,
337+
},
338+
{
339+
label: t('gov.positions.proxyAll'),
340+
value: 'proxyAll',
341+
onPress: () => {
342+
setIsManageSheetOpen(false)
343+
navigation.navigate('AssignProxyScreen', {
344+
mint: mint.toBase58(),
345+
})
346+
},
347+
disabled: unproxiedPositions.length === 0,
348+
},
349+
{
350+
label: t('gov.transactions.claimRewards'),
351+
value: 'claim',
352+
onPress: async () => {
353+
setIsManageSheetOpen(false)
354+
await handleClaimRewards()
355+
},
356+
disabled: !positionsWithRewards?.length || claimingAllRewards || loading,
357+
SecondaryIcon: positionsWithRewards?.length ? (
358+
<Dot filled color="green500" size={8} />
359+
) : undefined,
360+
},
361+
]
362+
301363
return (
302364
<GovernanceWrapper selectedTab="positions">
303365
<Box flexDirection="column" flex={1}>
@@ -316,61 +378,68 @@ export const PositionsScreen = () => {
316378
</Text>
317379
</Box>
318380
)}
319-
<Box flexDirection="row" padding="m">
381+
<Box flexDirection="row" paddingTop="m">
320382
{HNT_MINT.equals(mint) && (
321-
<>
322-
<ButtonPressable
323-
flex={1}
324-
height={44}
325-
fontSize={12}
326-
borderRadius="round"
327-
borderWidth={2}
328-
borderColor="white"
329-
backgroundColorOpacityPressed={0.7}
330-
title={t('gov.transactions.lockTokens')}
331-
titleColor="white"
332-
onPress={() => setIsLockModalOpen(true)}
333-
disabled={claimingAllRewards || loading}
334-
/>
335-
<Box paddingHorizontal="xs" />
336-
<ButtonPressable
337-
height={44}
338-
flex={1}
339-
fontSize={12}
340-
borderRadius="round"
341-
borderWidth={2}
342-
borderColor="white"
343-
titleColor="white"
344-
backgroundColorOpacityPressed={0.7}
345-
backgroundColorDisabled="surfaceSecondary"
346-
backgroundColorDisabledOpacity={0.9}
347-
titleColorDisabled="secondaryText"
348-
title={t('gov.positions.delegateAll')}
349-
onPress={() => setIsDelegateAllModalOpen(true)}
350-
disabled={loading || delegateAllLoading}
351-
/>
352-
<Box paddingHorizontal="xs" />
353-
<ButtonPressable
354-
flex={1}
355-
height={44}
356-
fontSize={12}
357-
borderRadius="round"
358-
borderWidth={2}
359-
borderColor="white"
360-
backgroundColorOpacityPressed={0.7}
361-
backgroundColorDisabled="surfaceSecondary"
362-
backgroundColorDisabledOpacity={0.9}
363-
titleColorDisabled="secondaryText"
364-
title={
365-
claimingAllRewards ? '' : t('gov.transactions.claimRewards')
366-
}
367-
titleColor="white"
368-
onPress={handleClaimRewards}
369-
disabled={
370-
!positionsWithRewards?.length || claimingAllRewards || loading
371-
}
372-
/>
373-
</>
383+
<Box flex={1} alignItems="center" flexDirection="row">
384+
{positions?.length === 0 ? (
385+
<ButtonPressable
386+
height={44}
387+
fontSize={12}
388+
borderRadius="round"
389+
borderWidth={2}
390+
borderColor="white"
391+
backgroundColorOpacityPressed={0.7}
392+
title={t('gov.transactions.lockTokens')}
393+
titleColor="white"
394+
onPress={() => setIsLockModalOpen(true)}
395+
flexDirection="row"
396+
justifyContent="center"
397+
alignItems="center"
398+
innerContainerProps={{ justifyContent: 'center' }}
399+
/>
400+
) : (
401+
<>
402+
<ButtonPressable
403+
height={44}
404+
fontSize={12}
405+
borderRadius="round"
406+
borderWidth={2}
407+
borderColor="white"
408+
backgroundColorOpacityPressed={0.7}
409+
title={t('gov.manage')}
410+
titleColor="white"
411+
onPress={() => setIsManageSheetOpen(true)}
412+
flexDirection="row"
413+
justifyContent="center"
414+
alignItems="center"
415+
innerContainerProps={{ justifyContent: 'center' }}
416+
Icon={
417+
positionsWithRewards?.length
418+
? () => <Dot filled color="green500" size={8} />
419+
: undefined
420+
}
421+
/>
422+
<BlurActionSheet
423+
title={t('gov.manage')}
424+
open={isManageSheetOpen}
425+
onClose={() => setIsManageSheetOpen(false)}
426+
>
427+
<Box>
428+
{manageActions.map((action) => (
429+
<ListItem
430+
key={action.value}
431+
title={action.label}
432+
onPress={action.onPress}
433+
disabled={action.disabled}
434+
SecondaryIcon={action.SecondaryIcon}
435+
hasDivider
436+
/>
437+
))}
438+
</Box>
439+
</BlurActionSheet>
440+
</>
441+
)}
442+
</Box>
374443
)}
375444
</Box>
376445
{claimingAllRewards && <ClaimingRewardsModal status={statusOfClaim} />}

src/locales/en.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,6 +1285,7 @@ export default {
12851285
autoGasConvertHeader: 'Auto Fee Conversion: Low on SOL',
12861286
},
12871287
gov: {
1288+
manage: 'Manage',
12881289
title: 'Governance',
12891290
tutorial: {
12901291
goToVote: 'Go To Vote',
@@ -1378,6 +1379,7 @@ export default {
13781379
dataUsageRevenue: 'Data Usage Revenue (30 days)',
13791380
},
13801381
positions: {
1382+
proxyAll: 'Proxy All',
13811383
renewDelegation: 'Renew Delegation',
13821384
delegationExpiringSoon: 'Delegation Expiring Soon',
13831385
delegationExpired: 'Delegation Expired',

0 commit comments

Comments
 (0)