Skip to content

Commit

Permalink
feat: add aggregated comp
Browse files Browse the repository at this point in the history
  • Loading branch information
salimtb committed May 15, 2024
1 parent 984e7ff commit ba64f5a
Show file tree
Hide file tree
Showing 13 changed files with 429 additions and 59 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React from 'react';
import { fontStyles } from '../../../../styles/common';
import Text from '../../../../component-library/components/Texts/Text';
import { View, StyleSheet } from 'react-native';
import { useTheme } from '../../../../util/theme';
import { Colors } from '../../../../util/theme/models';
import { renderFiat } from '../../../../util/number';
import { useSelector } from 'react-redux';
import { selectCurrentCurrency } from '../../../../selectors/currencyRateController';

const createStyles = (colors: Colors) =>
StyleSheet.create({
wrapper: {
flexDirection: 'row',
alignItems: 'center',
},
balancePositiveStyle: {
color: colors.success.default,
...fontStyles.normal,
textTransform: 'uppercase',
},
balanceNegativeStyle: {
color: colors.error.default,
...fontStyles.normal,
textTransform: 'uppercase',
},
});

const isValidAmount = (amount: number | null | undefined): boolean =>
amount !== null && amount !== undefined && !Number.isNaN(amount);

const AggregatedPercentage = ({
ethFiat,
tokenFiat,
tokenFiat1dAgo,
ethFiat1dAgo,
}: {
ethFiat: number;
tokenFiat: number;
tokenFiat1dAgo: number;
ethFiat1dAgo: number;
}) => {
const { colors } = useTheme();
const styles = createStyles(colors);
const currentCurrency = useSelector(selectCurrentCurrency);
const DECIMALS_TO_SHOW = 2;

const totalBalance = ethFiat + tokenFiat;
const totalBalance1dAgo = ethFiat1dAgo + tokenFiat1dAgo;

const amountChange = totalBalance - totalBalance1dAgo;
const percentageChange =
((totalBalance - totalBalance1dAgo) / totalBalance1dAgo) * 100;

const percentageStyle =
amountChange && amountChange >= 0
? styles.balancePositiveStyle
: styles.balanceNegativeStyle;

const formattedPercentage = isValidAmount(percentageChange)
? `${(percentageChange as number) >= 0 ? '+' : ''}${(
percentageChange as number
).toFixed(2)}%`
: '';

const formattedValuePrice = isValidAmount(amountChange)
? `${(amountChange as number) >= 0 ? '+' : ''}(${renderFiat(
amountChange,
currentCurrency,
DECIMALS_TO_SHOW,
)}) `
: '';

return (
<View style={styles.wrapper}>
<Text style={percentageStyle}>{formattedValuePrice}</Text>
<Text style={percentageStyle}>{formattedPercentage}</Text>
</View>
);
};

export default AggregatedPercentage;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './AgregatedPercentage';
261 changes: 219 additions & 42 deletions app/components/UI/Tokens/__snapshots__/index.test.tsx.snap

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions app/components/UI/Tokens/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,13 @@ const initialState = {
'0x01': 0.005,
'0x02': 0.005,
},
marketData: {
'0x1': {
'0x0': { value: 0.005, pricePercentChange1d: 0.2 },
'0x01': { value: 0.005, pricePercentChange1d: 0.2 },
'0x02': { value: 0.005, pricePercentChange1d: 0.2 },
},
},
},
CurrencyRateController: {
currentCurrency: 'USD',
Expand All @@ -89,6 +96,11 @@ const initialState = {
'0x02': new BN(0),
},
},
NetworkController: {
providerConfig: {
chainId: '0x1',
},
},
},
},
settings: {
Expand Down Expand Up @@ -226,6 +238,11 @@ describe('Tokens', () => {
contractExchangeRates: {
'0x02': undefined,
},
marketData: {
'0x1': {
'0x02': { value: undefined },
},
},
},
CurrencyRateController: {
currentCurrency: 'USD',
Expand Down
12 changes: 10 additions & 2 deletions app/components/UI/Tokens/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ import { useNavigation } from '@react-navigation/native';
import { EngineState } from '../../../selectors/types';
import { StackNavigationProp } from '@react-navigation/stack';
import createStyles from './styles';
import SkeletonText from '../Ramp/components/SkeletonText';
import Routes from '../../../constants/navigation/Routes';
import { TOKEN_BALANCE_LOADING, TOKEN_RATE_UNDEFINED } from './constants';
import AppConstants from '../../../core/AppConstants';
Expand Down Expand Up @@ -108,6 +107,7 @@ import Box from '../../UI/Ramp/components/Box';
import SheetHeader from '../../../../app/component-library/components/Sheet/SheetHeader';
import { isPortfolioUrl } from '../../../../app/util/url';
import PercentageChange from '../../../component-library/components-temp/Price/PercentageChange';
import AggregatedPercentage from '../../../component-library/components-temp/Price/AggregatedPercentage';

const Tokens: React.FC<TokensI> = ({ tokens }) => {
const { colors } = useTheme();
Expand Down Expand Up @@ -356,6 +356,8 @@ const Tokens: React.FC<TokensI> = ({ tokens }) => {
balanceToFiatNumber(balance, conversionRate, exchangeRate),
);

// console.log('balanceFiatCalculation ----', balanceFiatCalculation);

const balanceFiat =
balanceFiatCalculation >= 0.01 || balanceFiatCalculation === 0
? addCurrencySymbol(balanceFiatCalculation, currentCurrency)
Expand Down Expand Up @@ -628,7 +630,13 @@ const Tokens: React.FC<TokensI> = ({ tokens }) => {
>
{fiatBalance}
</Text>
<PercentageChange value={2} />

<AggregatedPercentage
ethFiat={balance?.ethFiat}
tokenFiat={balance?.tokenFiat}
tokenFiat1dAgo={balance?.tokenFiat1dAgo}
ethFiat1dAgo={balance?.ethFiat1dAgo}
/>
</View>
<Button
variant={ButtonVariants.Secondary}
Expand Down
4 changes: 3 additions & 1 deletion app/components/Views/confirmations/Send/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,9 @@ const initialState = {
},
},
TokenRatesController: {
contractExchangeRates: {},
marketData: {
'0x1': {},
},
},
TransactionController: {
methodData: {},
Expand Down
21 changes: 21 additions & 0 deletions app/components/Views/confirmations/SendFlow/Amount/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,11 @@ describe('Amount', () => {
contractExchangeRates: {
'0x514910771AF9Ca656af840dff83E8264EcF986CA': 0.005,
},
marketData: {
'0x1': {
'0x514910771AF9Ca656af840dff83E8264EcF986CA': { value: 0.005 },
},
},
},
CurrencyRateController: {
currentCurrency: 'usd',
Expand Down Expand Up @@ -472,6 +477,11 @@ describe('Amount', () => {
contractExchangeRates: {
'0x514910771AF9Ca656af840dff83E8264EcF986CA': 0.005,
},
marketData: {
'0x1': {
'0x514910771AF9Ca656af840dff83E8264EcF986CA': { value: 0.005 },
},
},
},
CurrencyRateController: {
currentCurrency: 'usd',
Expand Down Expand Up @@ -523,6 +533,9 @@ describe('Amount', () => {
...initialState.engine.backgroundState,
TokenRatesController: {
contractExchangeRates: {},
marketData: {
'0x1': {},
},
},
CurrencyRateController: {},
},
Expand Down Expand Up @@ -564,6 +577,11 @@ describe('Amount', () => {
contractExchangeRates: {
'0x514910771AF9Ca656af840dff83E8264EcF986CA': 0.005,
},
marketData: {
'0x1': {
'0x514910771AF9Ca656af840dff83E8264EcF986CA': { value: 0.005 },
},
},
},
CurrencyRateController: {},
},
Expand Down Expand Up @@ -606,6 +624,9 @@ describe('Amount', () => {
...initialState.engine.backgroundState,
TokenRatesController: {
contractExchangeRates: {},
marketData: {
'0x1': {},
},
},
CurrencyRateController: {},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ const mockInitialState = {
'0xe64dD0AB5ad7e8C5F2bf6Ce75C34e187af8b920A': { balance: '0' },
},
},
TokenRatesController: {
marketData: {
'0x1': {},
},
},
CurrencyRateController: {
currentCurrency: 'USD',
currencyRates: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ const initialState = {
contractExchangeRates: {
'0x326836cc6cd09B5aa59B81A7F72F25FcC0136b95': 1,
},
marketData: {
'0x1': {
'0x326836cc6cd09B5aa59B81A7F72F25FcC0136b95': { value: 1 },
},
},
},
TokenBalancesController: {
contractBalances: {
Expand Down
7 changes: 7 additions & 0 deletions app/core/Engine.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ describe('Engine', () => {
lib: 'original',
},
},
TokenRatesController: {
contractExchangeRates: {},
contractExchangeRatesByChainId: {},
marketData: {
'0x1': {},
},
},
};

expect(backgroundState).toStrictEqual(initialState);
Expand Down
36 changes: 32 additions & 4 deletions app/core/Engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ import {
networkIdUpdated,
networkIdWillUpdate,
} from '../core/redux/slices/inpageProvider';
import { zeroAddress } from 'ethereumjs-util';

const NON_EMPTY = 'NON_EMPTY';

Expand Down Expand Up @@ -1426,6 +1427,8 @@ class Engine {
getTotalFiatAccountBalance = (): {
ethFiat: number;
tokenFiat: number;
tokenFiat1dAgo: number;
ethFiat1dAgo: number;
} => {
const {
CurrencyRateController,
Expand All @@ -1443,10 +1446,13 @@ class Engine {
CurrencyRateController.state?.currencyRates?.[networkProvider?.ticker]
?.conversionRate ?? 0;
const { accountsByChainId } = AccountTrackerController.state;
const { marketData: tokenExchangeRates } = TokenRatesController.state;

const { tokens } = TokensController.state;
let ethFiat = 0;
let ethFiat1dAgo = 0;
let tokenFiat = 0;
let tokenFiat1dAgo = 0;
const decimalsToShow = (currentCurrency === 'usd' && 2) || undefined;
if (
accountsByChainId?.[toHexadecimal(networkProvider.chainId)]?.[
Expand All @@ -1460,17 +1466,27 @@ class Engine {
conversionRate,
decimalsToShow,
);

ethFiat1dAgo =
ethFiat +
(ethFiat *
tokenExchangeRates?.[networkProvider.chainId]?.[zeroAddress()]

Check failure on line 1473 in app/core/Engine.ts

View workflow job for this annotation

GitHub Actions / scripts (lint:tsc)

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Record<`0x${string}`, { tokenAddress: `0x${string}`; value: number; currency: string; allTimeHigh: number; allTimeLow: number; circulatingSupply: number; dilutedMarketCap: number; high1d: number; low1d: number; ... 11 more ...; totalVolume: number; }>'.
?.pricePercentChange1d) /
100 || 0;
}
if (tokens.length > 0) {
const { contractBalances: tokenBalances } = TokenBalancesController.state;
const { contractExchangeRates: tokenExchangeRates } =
TokenRatesController.state;

tokens.forEach(
(item: { address: string; balance?: string; decimals: number }) => {
const exchangeRate =
item.address in tokenExchangeRates
? tokenExchangeRates[item.address]
item.address.toLowerCase() in
tokenExchangeRates[networkProvider.chainId]
? tokenExchangeRates?.[networkProvider.chainId]?.[

Check failure on line 1485 in app/core/Engine.ts

View workflow job for this annotation

GitHub Actions / scripts (lint:tsc)

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Record<`0x${string}`, { tokenAddress: `0x${string}`; value: number; currency: string; allTimeHigh: number; allTimeLow: number; circulatingSupply: number; dilutedMarketCap: number; high1d: number; low1d: number; ... 11 more ...; totalVolume: number; }>'.
item.address.toLowerCase()
]?.value
: undefined;

const tokenBalance =
item.balance ||
(item.address in tokenBalances
Expand All @@ -1487,14 +1503,26 @@ class Engine {
exchangeRate,
decimalsToShow,
);

const tokenBalance1dAgo =
tokenBalanceFiat +
(tokenBalanceFiat *
tokenExchangeRates?.[networkProvider.chainId]?.[

Check failure on line 1510 in app/core/Engine.ts

View workflow job for this annotation

GitHub Actions / scripts (lint:tsc)

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Record<`0x${string}`, { tokenAddress: `0x${string}`; value: number; currency: string; allTimeHigh: number; allTimeLow: number; circulatingSupply: number; dilutedMarketCap: number; high1d: number; low1d: number; ... 11 more ...; totalVolume: number; }>'.
item.address.toLowerCase()
]?.pricePercentChange1d) /
100 || 0;

tokenFiat += tokenBalanceFiat;
tokenFiat1dAgo += tokenBalance1dAgo;
},
);
}

return {
ethFiat: ethFiat ?? 0,
ethFiat1dAgo: ethFiat1dAgo ?? 0,
tokenFiat: tokenFiat ?? 0,
tokenFiat1dAgo: tokenFiat1dAgo ?? 0,
};
};

Expand Down
18 changes: 16 additions & 2 deletions app/selectors/tokenRatesController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,28 @@
import { createSelector } from 'reselect';
import { TokenRatesState } from '@metamask/assets-controllers';
import { RootState } from '../reducers';
import { selectChainId } from './networkController';

const selectTokenRatesControllerState = (state: RootState) =>
state.engine.backgroundState.TokenRatesController;

export const selectContractExchangeRates = createSelector(
selectTokenRatesControllerState,
(tokenRatesControllerState: TokenRatesState) =>
tokenRatesControllerState.contractExchangeRates,
selectChainId,
(tokenRatesControllerState: TokenRatesState, chainId: `0x${string}`) => {
const contractMarketData = tokenRatesControllerState.marketData?.[chainId];

return Object.entries(contractMarketData).reduce(
(
acc: { [address: string]: number | undefined },
[address, marketData],
) => {
acc[address] = marketData.value;
return acc;
},
{},
);
},
);

export const selectDataMarket = createSelector(
Expand Down
Loading

0 comments on commit ba64f5a

Please sign in to comment.