Skip to content

Commit

Permalink
feat(suite-native): device switcher wallet has fiat balance
Browse files Browse the repository at this point in the history
  • Loading branch information
vytick committed Jul 2, 2024
1 parent 07e393d commit 42bcc90
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 26 deletions.
2 changes: 2 additions & 0 deletions suite-native/device-manager/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
"@suite-common/wallet-core": "workspace:*",
"@suite-native/analytics": "workspace:*",
"@suite-native/atoms": "workspace:*",
"@suite-native/device": "workspace:*",
"@suite-native/feature-flags": "workspace:*",
"@suite-native/formatters": "workspace:*",
"@suite-native/intl": "workspace:*",
"@suite-native/link": "workspace:*",
"@suite-native/navigation": "workspace:*",
Expand Down
63 changes: 43 additions & 20 deletions suite-native/device-manager/src/components/WalletItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,52 @@ import { Icon } from '@suite-common/icons';
import { TrezorDevice } from '@suite-common/suite-types';
import { prepareNativeStyle, useNativeStyles } from '@trezor/styles';
import { selectDevice, selectDeviceByState } from '@suite-common/wallet-core';
import { FiatAmountFormatter } from '@suite-native/formatters';
import { selectDeviceTotalFiatBalanceNative } from '@suite-native/device';

type WalletItemProps = {
deviceState: NonNullable<TrezorDevice['state']>;
onPress: () => void;
isSelectable?: boolean;
};

const walletItemStyle = prepareNativeStyle<{ isSelected: boolean }>((utils, { isSelected }) => ({
paddingHorizontal: utils.spacings.medium,
justifyContent: 'space-between',
alignItems: 'center',
height: 60,
gap: 12,
backgroundColor: utils.colors.backgroundSurfaceElevation1,
borderWidth: utils.borders.widths.small,
borderRadius: 12,
borderColor: utils.colors.borderElevation1,
extend: {
condition: isSelected,
style: {
borderWidth: utils.borders.widths.large,
borderColor: utils.colors.borderSecondary,
},
},
}));
type WalletItemStyleProps = { isSelected: boolean; isSelectable: boolean };

const walletItemStyle = prepareNativeStyle<WalletItemStyleProps>(
(utils, { isSelected, isSelectable }) => ({
justifyContent: 'space-between',
alignItems: 'center',
height: 60,
gap: 12,
borderRadius: 12,
borderColor: utils.colors.borderElevation1,
extend: [
{
condition: isSelected,
style: {
borderWidth: utils.borders.widths.large,
borderColor: utils.colors.borderSecondary,
},
},
{
condition: isSelectable,
style: {
paddingHorizontal: utils.spacings.medium,
backgroundColor: utils.colors.backgroundSurfaceElevation1,
borderWidth: utils.borders.widths.small,
},
},
],
}),
);

export const WalletItem = ({ deviceState, onPress, isSelectable = true }: WalletItemProps) => {
const { applyStyle } = useNativeStyles();
const device = useSelector((state: any) => selectDeviceByState(state, deviceState));
const selectedDevice = useSelector(selectDevice);
const fiatBalance = useSelector((state: any) =>
selectDeviceTotalFiatBalanceNative(state, deviceState),
);

if (!device) {
return null;
Expand All @@ -60,7 +76,7 @@ export const WalletItem = ({ deviceState, onPress, isSelectable = true }: Wallet
<Pressable onPress={onPress}>
<HStack
key={device.instance}
style={applyStyle(walletItemStyle, { isSelected: showAsSelected })}
style={applyStyle(walletItemStyle, { isSelected: showAsSelected, isSelectable })}
>
<HStack alignItems="center">
<Icon
Expand All @@ -69,7 +85,14 @@ export const WalletItem = ({ deviceState, onPress, isSelectable = true }: Wallet
/>
<Text variant="callout">{walletNameLabel}</Text>
</HStack>
{isSelectable && <Radio value="" onPress={onPress} isChecked={isSelected} />}
<HStack alignItems="center" spacing={12}>
<FiatAmountFormatter
value={String(fiatBalance)}
variant="hint"
color="textSubdued"
/>
{isSelectable && <Radio value="" onPress={onPress} isChecked={isSelected} />}
</HStack>
</HStack>
</Pressable>
);
Expand Down
5 changes: 0 additions & 5 deletions suite-native/device-manager/src/components/WalletList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@ type WalletListProps = {
export const WalletList = ({ onSelectDevice }: WalletListProps) => {
const devices = useSelector(selectDeviceInstances);

// If there are less than 2 device instances(wallets), do not show wallet list
if (devices.length < 2) {
return null;
}

return (
<VStack spacing={12} paddingHorizontal="medium">
{devices.map(device => {
Expand Down
2 changes: 2 additions & 0 deletions suite-native/device-manager/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
},
{ "path": "../analytics" },
{ "path": "../atoms" },
{ "path": "../device" },
{ "path": "../feature-flags" },
{ "path": "../formatters" },
{ "path": "../intl" },
{ "path": "../link" },
{ "path": "../navigation" },
Expand Down
7 changes: 7 additions & 0 deletions suite-native/device/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@
"@reduxjs/toolkit": "1.9.5",
"@sentry/react-native": "5.22.3",
"@suite-common/redux-utils": "workspace:*",
"@suite-common/suite-config": "workspace:*",
"@suite-common/suite-types": "workspace:*",
"@suite-common/wallet-config": "workspace:*",
"@suite-common/wallet-core": "workspace:*",
"@suite-common/wallet-types": "workspace:*",
"@suite-common/wallet-utils": "workspace:*",
"@suite-native/alerts": "workspace:*",
"@suite-native/analytics": "workspace:*",
"@suite-native/atoms": "workspace:*",
Expand All @@ -31,7 +36,9 @@
"@trezor/connect": "workspace:*",
"@trezor/device-utils": "workspace:*",
"@trezor/styles": "workspace:*",
"bignumber.js": "^9.1.2",
"lottie-react-native": "6.7.2",
"proxy-memoize": "2.0.2",
"react": "18.2.0",
"react-native": "0.74.1",
"react-redux": "8.0.7",
Expand Down
27 changes: 26 additions & 1 deletion suite-native/device/src/selectors.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
import { memoizeWithArgs } from 'proxy-memoize';

import {
AccountsRootState,
DeviceRootState,
DiscoveryRootState,
selectDevice,
FiatRatesRootState,
selectAccountsByDeviceState,
selectCurrentFiatRates,
selectDeviceFirmwareVersion,
selectDeviceModel,
selectIsConnectedDeviceUninitialized,
selectIsDeviceConnectedAndAuthorized,
selectIsEmptyDevice,
selectIsUnacquiredDevice,
} from '@suite-common/wallet-core';
import { SettingsSliceRootState, selectFiatCurrencyCode } from '@suite-native/settings';

import { isFirmwareVersionSupported } from './utils';
import { getTotalFiatBalanceNative, isFirmwareVersionSupported } from './utils';

export const selectIsDeviceFirmwareSupported = (state: DeviceRootState) => {
const deviceFwVersion = selectDeviceFirmwareVersion(state);
Expand Down Expand Up @@ -47,3 +53,22 @@ export const selectDeviceError = (

return device?.error;
};

export const selectDeviceTotalFiatBalanceNative = memoizeWithArgs(
(
state: AccountsRootState & FiatRatesRootState & SettingsSliceRootState,
deviceState: string,
) => {
const accounts = deviceState ? selectAccountsByDeviceState(state, deviceState) : [];

const rates = selectCurrentFiatRates(state);
const fiatCurrencyCode = selectFiatCurrencyCode(state);
const fiatBalance = getTotalFiatBalanceNative(accounts, fiatCurrencyCode, rates);

return fiatBalance;
},
{
// reasonably high cache size for a lot of devices and passphrases
size: 20,
},
);
50 changes: 50 additions & 0 deletions suite-native/device/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { G } from '@mobily/ts-belt';
import * as semver from 'semver';
import BigNumber from 'bignumber.js';

import { FiatCurrencyCode } from '@suite-common/suite-config';
import { NetworkSymbol } from '@suite-common/wallet-config';
import { Account, RatesByKey } from '@suite-common/wallet-types';
import { getFiatRateKey, toFiatCurrency } from '@suite-common/wallet-utils';
import { DeviceModelInternal, VersionArray } from '@trezor/connect';

export const minimalSupportedFirmwareVersion = {
Expand All @@ -25,3 +30,48 @@ export const isFirmwareVersionSupported = (

return semver.satisfies(versionString, `>=${minimalVersionString}`);
};

// TODO: once we start including token balance in the account balance, we should use
// getAccountFiatBalance from wallet-utils and DELETE this function

// only counts native coin balance
export const getAccountFiatBalanceNative = (
account: Account,
localCurrency: string,
rates?: RatesByKey,
) => {
const coinFiatRateKey = getFiatRateKey(
account.symbol as NetworkSymbol,
localCurrency as FiatCurrencyCode,
);
const coinFiatRate = rates?.[coinFiatRateKey];
if (!coinFiatRate?.rate) return null;

let totalBalance = new BigNumber(0);

// account fiat balance
const accountBalance = toFiatCurrency(account.formattedBalance, coinFiatRate.rate, 2);

totalBalance = totalBalance.plus(accountBalance ?? 0);

return totalBalance.toFixed();
};

// TODO: once we start including token balance in the account balance, we should use
// getTotalFiatBalance from wallet-utils and DELETE this function

// only counts native coin balance
// balance of all accounts in the device without tokens
export const getTotalFiatBalanceNative = (
deviceAccounts: Account[],
localCurrency: string,
rates?: RatesByKey,
) => {
let instanceBalance = new BigNumber(0);
deviceAccounts.forEach(a => {
const accountFiatBalance = getAccountFiatBalanceNative(a, localCurrency, rates) ?? '0';
instanceBalance = instanceBalance.plus(accountFiatBalance);
});

return instanceBalance;
};
15 changes: 15 additions & 0 deletions suite-native/device/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,24 @@
{
"path": "../../suite-common/redux-utils"
},
{
"path": "../../suite-common/suite-config"
},
{
"path": "../../suite-common/suite-types"
},
{
"path": "../../suite-common/wallet-config"
},
{
"path": "../../suite-common/wallet-core"
},
{
"path": "../../suite-common/wallet-types"
},
{
"path": "../../suite-common/wallet-utils"
},
{ "path": "../alerts" },
{ "path": "../analytics" },
{ "path": "../atoms" },
Expand Down
9 changes: 9 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9219,7 +9219,9 @@ __metadata:
"@suite-common/wallet-core": "workspace:*"
"@suite-native/analytics": "workspace:*"
"@suite-native/atoms": "workspace:*"
"@suite-native/device": "workspace:*"
"@suite-native/feature-flags": "workspace:*"
"@suite-native/formatters": "workspace:*"
"@suite-native/intl": "workspace:*"
"@suite-native/link": "workspace:*"
"@suite-native/navigation": "workspace:*"
Expand Down Expand Up @@ -9251,7 +9253,12 @@ __metadata:
"@reduxjs/toolkit": "npm:1.9.5"
"@sentry/react-native": "npm:5.22.3"
"@suite-common/redux-utils": "workspace:*"
"@suite-common/suite-config": "workspace:*"
"@suite-common/suite-types": "workspace:*"
"@suite-common/wallet-config": "workspace:*"
"@suite-common/wallet-core": "workspace:*"
"@suite-common/wallet-types": "workspace:*"
"@suite-common/wallet-utils": "workspace:*"
"@suite-native/alerts": "workspace:*"
"@suite-native/analytics": "workspace:*"
"@suite-native/atoms": "workspace:*"
Expand All @@ -9266,7 +9273,9 @@ __metadata:
"@trezor/connect": "workspace:*"
"@trezor/device-utils": "workspace:*"
"@trezor/styles": "workspace:*"
bignumber.js: "npm:^9.1.2"
lottie-react-native: "npm:6.7.2"
proxy-memoize: "npm:2.0.2"
react: "npm:18.2.0"
react-native: "npm:0.74.1"
react-redux: "npm:8.0.7"
Expand Down

0 comments on commit 42bcc90

Please sign in to comment.