Skip to content

Commit

Permalink
feat(mobile): staking
Browse files Browse the repository at this point in the history
  • Loading branch information
Nodonisko committed Sep 27, 2024
1 parent 33ed1aa commit 097a050
Show file tree
Hide file tree
Showing 45 changed files with 971 additions and 112 deletions.
3 changes: 2 additions & 1 deletion suite-native/accounts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@
"@suite-native/intl": "workspace:*",
"@suite-native/navigation": "workspace:*",
"@suite-native/settings": "workspace:*",
"@suite-native/tokens": "workspace:*",
"@suite-native/staking": "workspace:*",
"@suite-native/toasts": "workspace:*",
"@suite-native/tokens": "workspace:*",
"@trezor/styles": "workspace:*",
"jotai": "1.9.1",
"proxy-memoize": "2.0.2",
Expand Down
16 changes: 11 additions & 5 deletions suite-native/accounts/src/components/AccountSectionTitle.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import React, { useMemo } from 'react';
import { useSelector } from 'react-redux';

import { HStack, VStack, Text } from '@suite-native/atoms';
import { CryptoAmountFormatter, FiatAmountFormatter } from '@suite-native/formatters';
import { selectCurrentFiatRates } from '@suite-common/wallet-core';
import { Account } from '@suite-common/wallet-types';
import { getAccountFiatBalance } from '@suite-common/wallet-utils';
import { getCryptoBalanceWithStaking } from '@suite-native/staking';
import { HStack, Text, VStack } from '@suite-native/atoms';
import { CryptoAmountFormatter, FiatAmountFormatter } from '@suite-native/formatters';
import { selectFiatCurrencyCode } from '@suite-native/settings';
import { selectCurrentFiatRates } from '@suite-common/wallet-core';
import {
NativeStakingRootState,
selectAccountCryptoBalanceWithStaking,
} from '@suite-native/staking';

type AccountSectionTitleProps = {
account: Account;
Expand All @@ -21,6 +24,9 @@ export const AccountSectionTitle: React.FC<AccountSectionTitleProps> = ({
}) => {
const localCurrency = useSelector(selectFiatCurrencyCode);
const rates = useSelector(selectCurrentFiatRates);
const cryptoBalanceWithStaking = useSelector((state: NativeStakingRootState) =>
selectAccountCryptoBalanceWithStaking(state, account.key),
);

const fiatBalance = useMemo(() => {
return getAccountFiatBalance({ account, localCurrency, rates });
Expand All @@ -38,7 +44,7 @@ export const AccountSectionTitle: React.FC<AccountSectionTitleProps> = ({
value={fiatBalance}
/>
<CryptoAmountFormatter
value={getCryptoBalanceWithStaking(account)}
value={cryptoBalanceWithStaking}
network={account.symbol}
numberOfLines={1}
adjustsFontSizeToFit
Expand Down
32 changes: 29 additions & 3 deletions suite-native/accounts/src/components/AccountSelectBottomSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { FlashList } from '@shopify/flash-list';

import { BottomSheet } from '@suite-native/atoms';
import { prepareNativeStyle, useNativeStyles } from '@trezor/styles';
import { useToast } from '@suite-native/toasts';

import { AccountSelectBottomSheetSection, OnSelectAccount } from '../types';
import { AccountsListItem } from './AccountsList/AccountsListItem';
Expand All @@ -14,6 +15,7 @@ import { AccountsListStakingItem } from './AccountsList/AccountsListStakingItem'
type AccountSelectBottomSheetProps = {
data: AccountSelectBottomSheetSection[];
onSelectAccount: OnSelectAccount;
isStakingPressable?: boolean;
onClose: () => void;
};

Expand All @@ -22,8 +24,14 @@ const contentContainerStyle = prepareNativeStyle(utils => ({
}));

export const AccountSelectBottomSheet = React.memo(
({ data, onSelectAccount, onClose }: AccountSelectBottomSheetProps) => {
({
data,
onSelectAccount,
isStakingPressable = false,
onClose,
}: AccountSelectBottomSheetProps) => {
const { applyStyle } = useNativeStyles();
const { showToast } = useToast();

const renderItem = useCallback(
({ item }: { item: AccountSelectBottomSheetSection }) => {
Expand All @@ -36,12 +44,30 @@ export const AccountSelectBottomSheet = React.memo(
{...item}
hasBackground
showDivider
isInModal={true}
onPress={() => onSelectAccount(item)}
/>
);
case 'staking':
return (
<AccountsListStakingItem {...item} hasBackground onPress={() => {}} />
<AccountsListStakingItem
{...item}
hasBackground
onPress={() => {
if (isStakingPressable) {
onSelectAccount({
account: item.account,
isStaking: true,
hasAnyKnownTokens: false,
});
} else {
showToast({
variant: 'warning',
message: 'Staking is not available in this context.',
});
}
}}
/>
);
case 'token':
const { token, account } = item;
Expand All @@ -63,7 +89,7 @@ export const AccountSelectBottomSheet = React.memo(
return null;
}
},
[onSelectAccount],
[isStakingPressable, onSelectAccount, showToast],
);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ type AccountsListProps = {
onSelectAccount: OnSelectAccount;
filterValue?: string;
hideTokensIntoModal?: boolean;
isStakingPressable?: boolean;
};

export const AccountsList = ({
onSelectAccount,
filterValue = '',
hideTokensIntoModal = false,
isStakingPressable = false,
}: AccountsListProps) => {
const groupedAccounts = useSelector((state: NativeAccountsRootState) =>
selectFilteredDeviceAccountsGroupedByNetworkAccountType(state, filterValue),
Expand Down Expand Up @@ -61,7 +63,6 @@ export const AccountsList = ({
<AccountsListItem
key={account.key}
account={account}
hideBadges={hideTokensIntoModal}
onPress={handleSetBottomSheetAccount}
/>
))}
Expand All @@ -71,6 +72,7 @@ export const AccountsList = ({
<TokenSelectBottomSheet
bottomSheetAccountAtom={bottomSheetAccountAtom}
onSelectAccount={onSelectAccount}
isStakingPressable={isStakingPressable}
/>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,16 @@ import {
selectNumberOfAccountTokensWithFiatRates,
TokensRootState,
} from '@suite-native/tokens';
import {
NativeStakingRootState,
selectAccountHasStaking,
StakingBadge,
} from '@suite-native/staking';
import { NativeStakingRootState, selectAccountHasStaking } from '@suite-native/staking';

import { NativeAccountsRootState, selectAccountFiatBalance } from '../../selectors';
import { OnSelectAccount } from '../../types';
import { AccountsListItemBase } from './AccountsListItemBase';
import { StakingBadge } from './StakingBadge';

export type AccountListItemProps = {
account: Account;
hideBadges?: boolean;
isInModal?: boolean;

onPress?: OnSelectAccount;
disabled?: boolean;
Expand Down Expand Up @@ -58,7 +55,7 @@ export const AccountsListItem = ({
account,
onPress,
disabled,
hideBadges = false,
isInModal = false,
hasBackground = false,
isFirst = false,
isLast = false,
Expand Down Expand Up @@ -90,9 +87,9 @@ export const AccountsListItem = ({
}, [account, accountHasAnyTokens, onPress]);

const doesCoinSupportTokens = isCoinWithTokens(account.symbol);
const shouldShowAccountLabel = !doesCoinSupportTokens || hideBadges;
const shouldShowTokenBadge = accountHasAnyTokens && hideBadges;
const shouldShowStakingBadge = accountHasStaking && hideBadges;
const shouldShowAccountLabel = !doesCoinSupportTokens || !isInModal;
const shouldShowTokenBadge = accountHasAnyTokens && !isInModal;
const shouldShowStakingBadge = accountHasStaking && !isInModal;

return (
<AccountsListItemBase
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Account } from '@suite-common/wallet-types';
import { RoundedIcon } from '@suite-native/atoms';
import { CryptoAmountFormatter, CryptoToFiatAmountFormatter } from '@suite-native/formatters';
import { Translation } from '@suite-native/intl';

import { AccountsListItemBase } from './AccountsListItemBase';

Expand All @@ -16,21 +17,17 @@ type AccountsListStakingItemProps = {

export const AccountsListStakingItem = ({
account,
onPress,
stakingCryptoBalance,
hasBackground,
isFirst,
isLast,
...props
}: AccountsListStakingItemProps) => {
return (
<AccountsListItemBase
hasBackground={hasBackground}
isFirst={isFirst}
{...props}
isLast={isLast}
showDivider={!isLast}
onPress={onPress}
icon={<RoundedIcon name="piggyBank" />}
title="Staking"
icon={<RoundedIcon name="piggyBankFilled" color="iconSubdued" />}
title={<Translation id="accountList.staking" />}
mainValue={
<CryptoToFiatAmountFormatter
value={stakingCryptoBalance}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { RoundedIcon, RoundedIconProps } from '@suite-native/atoms';

export const StakingBadge = (props: RoundedIconProps) => {
export const StakingBadge = (props: Partial<RoundedIconProps>) => {
return (
<RoundedIcon
name="piggyBank"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ import { AccountSelectBottomSheet } from './AccountSelectBottomSheet';
type TokenSelectBottomSheetProps = {
bottomSheetAccountAtom: WritableAtom<Account | null, Account | null>;
onSelectAccount: OnSelectAccount;
isStakingPressable?: boolean;
};

export const TokenSelectBottomSheet = ({
bottomSheetAccountAtom,
onSelectAccount,
isStakingPressable = false,
}: TokenSelectBottomSheetProps) => {
const [selectedAccount, setSelectedAccount] = useAtom(bottomSheetAccountAtom);

Expand Down Expand Up @@ -44,6 +46,7 @@ export const TokenSelectBottomSheet = ({
onSelectAccount={handleSelectAccount}
data={data}
onClose={handleClose}
isStakingPressable={isStakingPressable}
/>
);
};
1 change: 1 addition & 0 deletions suite-native/accounts/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * from './components/AddAccountsButton';
export * from './components/AccountsList/AccountsList';
export * from './components/AccountsList/AccountsListItem';
export * from './components/AccountsList/AccountsListItemBase';
export * from './components/AccountsList/StakingBadge';
export * from './components/SearchableAccountsListScreenHeader';
export * from './components/SelectableNetworkItem';
export * from './components/AccountsList/AccountsListTokenItem';
Expand Down
1 change: 1 addition & 0 deletions suite-native/accounts/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export type GroupedByTypeAccounts = Record<string, [Account, ...Account[]]>;

export type OnSelectAccount = (params: {
account: Account;
isStaking?: boolean;
tokenAddress?: TokenAddress;
hasAnyKnownTokens: boolean;
}) => void;
Expand Down
2 changes: 2 additions & 0 deletions suite-native/accounts/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
{ "path": "../intl" },
{ "path": "../navigation" },
{ "path": "../settings" },
{ "path": "../staking" },
{ "path": "../toasts" },
{ "path": "../tokens" },
{ "path": "../../packages/styles" }
]
Expand Down
1 change: 1 addition & 0 deletions suite-native/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
"@suite-native/module-receive": "workspace:*",
"@suite-native/module-send": "workspace:*",
"@suite-native/module-settings": "workspace:*",
"@suite-native/module-staking-management": "workspace:*",
"@suite-native/navigation": "workspace:*",
"@suite-native/notifications": "workspace:*",
"@suite-native/receive": "workspace:*",
Expand Down
6 changes: 6 additions & 0 deletions suite-native/app/src/navigation/RootStackNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { DeviceInfoModalScreen, useHandleDeviceConnection } from '@suite-native/
import { SendStackNavigator } from '@suite-native/module-send';
import { CoinEnablingInitScreen } from '@suite-native/coin-enabling';
import { ConnectPopupScreen, useConnectPopupNavigation } from '@suite-native/module-connect-popup';
import { StakingDetailScreen } from '@suite-native/module-staking-management';

import { AppTabNavigator } from './AppTabNavigator';
import { useCoinEnablingInitialCheck } from '../hooks/useCoinEnablingInitialCheck';
Expand Down Expand Up @@ -73,6 +74,11 @@ export const RootStackNavigator = () => {
name={RootStackRoutes.AccountDetail}
component={AccountDetailScreen}
/>
<RootStack.Screen
options={{ title: RootStackRoutes.StakingDetail }}
name={RootStackRoutes.StakingDetail}
component={StakingDetailScreen}
/>
<RootStack.Screen
name={RootStackRoutes.DevUtilsStack}
component={DevUtilsStackNavigator}
Expand Down
3 changes: 3 additions & 0 deletions suite-native/app/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@
{ "path": "../module-receive" },
{ "path": "../module-send" },
{ "path": "../module-settings" },
{
"path": "../module-staking-management"
},
{ "path": "../navigation" },
{ "path": "../notifications" },
{ "path": "../receive" },
Expand Down
3 changes: 1 addition & 2 deletions suite-native/assets/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@
"@suite-native/intl": "workspace:*",
"@suite-native/navigation": "workspace:*",
"@suite-native/settings": "workspace:*",
"@suite-native/tokens": "workspace:*",
"@trezor/styles": "workspace:*",
"@suite-native/staking": "workspace:*",
"@suite-native/tokens": "workspace:*",
"proxy-memoize": "2.0.2",
"react": "^18.2.0",
"react-native": "0.75.2",
Expand Down
7 changes: 6 additions & 1 deletion suite-native/assets/src/assetsSelectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ import { selectAccountListSections } from '@suite-native/accounts';
import { sortAccountsByNetworksAndAccountTypes } from '@suite-native/accounts/src/utils';
import { discoverySupportedNetworks } from '@suite-native/config';
import { selectFiatCurrencyCode, SettingsSliceRootState } from '@suite-native/settings';
import {
NativeStakingRootState,
selectAccountCryptoBalanceWithStaking,
} from '@suite-native/staking';
export interface AssetType {
symbol: NetworkSymbol;
assetBalance: string;
Expand All @@ -28,6 +32,7 @@ export type AssetsRootState = AccountsRootState &
FiatRatesRootState &
SettingsSliceRootState &
TokenDefinitionsRootState &
NativeStakingRootState &
DeviceRootState;

/*
Expand Down Expand Up @@ -93,7 +98,7 @@ const selectDeviceAssetsWithBalances = memoize((state: AssetsRootState) => {
return {
symbol: account.symbol,
fiatValue,
cryptoValue: account.formattedBalance,
cryptoValue: selectAccountCryptoBalanceWithStaking(state, account.key),
};
});

Expand Down
3 changes: 1 addition & 2 deletions suite-native/assets/src/components/AssetItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { useSelectorDeepComparison } from '@suite-common/redux-utils';
import { TokenDefinitionsRootState } from '@suite-common/token-definitions';
import { NetworkSymbol } from '@suite-common/wallet-config';
import { AccountsRootState, DeviceRootState } from '@suite-common/wallet-core';
import { AccountsListItemBase } from '@suite-native/accounts';
import { AccountsListItemBase, StakingBadge } from '@suite-native/accounts';
import { Badge, Box, Text } from '@suite-native/atoms';
import { CryptoAmountFormatter, FiatAmountFormatter } from '@suite-native/formatters';
import { Translation } from '@suite-native/intl';
Expand All @@ -24,7 +24,6 @@ import { selectHasDeviceAnyTokens } from '@suite-native/tokens';
import {
selectHasAnyDeviceAccountsWithStaking,
NativeStakingRootState,
StakingBadge,
} from '@suite-native/staking';

import {
Expand Down
Loading

0 comments on commit 097a050

Please sign in to comment.