Skip to content

Commit

Permalink
Merge branch 'develop' into denis/yoext-1577/dark-paper
Browse files Browse the repository at this point in the history
  • Loading branch information
Nebyt authored Dec 19, 2024
2 parents 7395525 + 05f8100 commit 280321f
Show file tree
Hide file tree
Showing 11 changed files with 171 additions and 110 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@ import {
defaultPortfolioState,
} from './state';

export const PortfolioDetailsTab = {
Performance: 'Performance',
Overview: 'Overview',
Transactions: 'Transactions',
} as const;
export type PortfolioDetailsTab = typeof PortfolioDetailsTab[keyof typeof PortfolioDetailsTab];

export const PortfolioListTab = {
Wallet: 'Wallet',
Dapps: 'Dapps',
} as const;

export type PortfolioListTab = typeof PortfolioListTab[keyof typeof PortfolioListTab];

import BuySellDialog from '../../../../components/buySell/BuySellDialog';
import { DEFAULT_FIAT_PAIR } from '../common/helpers/constants';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,18 @@ export const TokenMarketPriceOverview = ({ chartData, detailInfo, tokenInfo, isD
// Fetch data based on the selected interval

const ptActivity = useCurrencyPairing().ptActivity;
const { changeValue, changePercent } = priceChange(ptActivity.open, ptActivity.close);
const { changeValue, changePercent } = priceChange(ptActivity.open, ptActivity?.close);

const {
tokenActivity: { data24h },
} = usePortfolioTokenActivity();

const deltaPriceChange =
!isPrimaryToken &&
!isEmpty(data24h) &&
data24h[tokenInfo?.info?.id][1].price.close - data24h[tokenInfo?.info?.id][1].price.open;
const deltaPriceChange = !isPrimaryToken && !isEmpty(data24h) && data24h[tokenInfo?.info?.id][1].price?.change;

const priceChangeProcent = isPrimaryToken ? detailInfo?.changePercent || changePercent : !isEmpty(data24h) && deltaPriceChange;
const priceChangeValue = isPrimaryToken
? detailInfo?.changeValue || changeValue
: !isEmpty(data24h) && data24h[tokenInfo?.info?.id][1].price.close;
: !isEmpty(data24h) && data24h[tokenInfo?.info?.id][1].price?.close - data24h[tokenInfo?.info?.id][1].price?.open;
return (
<Stack
direction="row"
Expand Down Expand Up @@ -80,14 +77,18 @@ export const TokenMarketPriceOverview = ({ chartData, detailInfo, tokenInfo, isD
};

const TokenPrice = ({ isPrimaryToken, unitOfAccount, secondaryTokenActivity, ptActivity, detailInfo, isDragging }) => {
const tokenPrice = isPrimaryToken ? ptActivity.close : secondaryTokenActivity && secondaryTokenActivity[1].price.close;
const tokenPrice = isPrimaryToken ? ptActivity.close : secondaryTokenActivity && secondaryTokenActivity[1].price?.close;

const sPrice = secondaryTokenActivity && secondaryTokenActivity[1].price.close;
const sPrice = secondaryTokenActivity && secondaryTokenActivity[1].price?.close;

const ptPrice = isDragging ? detailInfo.value : ptActivity.close;

const ptUnitPrice = sPrice * ptPrice;

if (!isPrimaryToken && isNaN(ptUnitPrice)) {
return <Typography variant="caption">-</Typography>;
}

if (tokenPrice == null) return <Skeleton variant="text" width="50px" height="30px" />;

return (
Expand All @@ -102,6 +103,8 @@ const TokenPrice = ({ isPrimaryToken, unitOfAccount, secondaryTokenActivity, ptA

const PriceChangeChip = ({ value }: { value: number }) => {
const theme: any = useTheme();
const valueToDisplay = value >= 0 ? formatNumber(value) : formatNumber(-1 * value);

return (
<>
<Chip
Expand All @@ -114,7 +117,7 @@ const PriceChangeChip = ({ value }: { value: number }) => {
<Icon.ChipArrowDown fill={theme.palette.ds.sys_magenta_700} />
) : null}
{/* @ts-ignore */}
<Typography variant="caption1">{value >= 0 ? formatNumber(value) : formatNumber(-1 * value)}%</Typography>
<Typography variant="caption1">{valueToDisplay === 'NaN' ? '-' : valueToDisplay}%</Typography>
</Stack>
}
/>
Expand All @@ -129,7 +132,7 @@ const PriceValueChip = ({ value, unitOfAccount }: { value: number; unitOfAccount
label={
<Typography variant="caption">
{value > 0 && '+'}
{formatNumber(value)} {unitOfAccount}
{formatNumber(value) === 'NaN' ? '-' : formatNumber(value)} {unitOfAccount}
</Typography>
}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,14 @@ const HeaderSection = ({ tokenInfo }: Props): JSX.Element => {

const totaPriceCalc = React.useMemo(() => {
if (!isPrimaryToken && !isEmpty(data24h)) {
const tokenPrice = data24h && data24h[tokenInfo.info.id][1]?.price.close;
const tokenPrice = data24h && data24h[tokenInfo.info.id][1]?.price?.close;
const tokenQuantityAsBigInt = bigNumberToBigInt(new BigNumber(tokenInfo.quantity));
const tokenDecimals = !isPrimaryToken && tokenInfo.info.numberOfDecimals;

if (tokenPrice === undefined && !isPrimaryToken) {
return '-';
}

const totaPrice = atomicBreakdown(tokenQuantityAsBigInt, tokenDecimals)
.bn.times(tokenPrice ?? 1)
.times(String(ptPrice))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ const Overview = ({ tokenInfo }: Props): JSX.Element => {
}}
component="img"
src={tokenInfo.info.image || tokenPng}
onError={e => {
// @ts-ignore
e.target.src = tokenPng;
}}
></Box>

<Typography fontWeight="500" color="ds.gray_900">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { Box, Divider, Stack } from '@mui/material';
import { styled, useTheme } from '@mui/material/styles';
import React from 'react';
import React, { useEffect } from 'react';
import { ampli } from '../../../../../../ampli';
import { BackButton, Card } from '../../../../components';
import NavigationButton from '../../common/components/NavigationButton';
import { useNavigateTo } from '../../common/hooks/useNavigateTo';
import { useStrings } from '../../common/hooks/useStrings';
import { PortfolioDetailsTab } from '../../module/PortfolioContextProvider';
import { TokenChartInterval } from './ChartDetails/TokenChartInterval';
import HeaderSection from './HeaderDetails/Header';
import OverviewPerformance from './OverviewPerformanceDetails/OverviewPerformance';
Expand All @@ -28,6 +30,10 @@ const TokenDetails = ({ tokenInfo }: Props): JSX.Element => {
const strings = useStrings();
const isPrimaryToken: boolean = tokenInfo.id === '-';

useEffect(() => {
ampli.portfolioTokenDetails({ token_details_tab: PortfolioDetailsTab.Overview });
}, []);

return (
<Box sx={{ width: '100%' }}>
<Header>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,10 @@ export const TokenPriceTotal = ({ token, secondaryToken24Activity }) => {
.toFormat(decimals);

const totalTicker = isPrimary && showingAda ? accountPair?.to.name : accountPair?.from.name;
const totalTokenPrice = isPrimary && showingAda ? '' : `${totaPrice} ${totalTicker || DEFAULT_FIAT_PAIR}`;
const totalTokenPrice =
isPrimary && showingAda
? ''
: `${isPrimary ? totaPrice : tokenPrice !== undefined ? totaPrice : '-'} ${totalTicker || DEFAULT_FIAT_PAIR}`;

return (
<Stack direction="row" spacing={theme.spacing(1.5)} sx={{ float: 'right' }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ export const useProcessedTokenData = ({ data, ptActivity, data24h, data7d, data3
const unitPrice = parseFloat((tokenPrice * ptActivity?.close || 1).toFixed(4));
const primaryTokenFiatTotalAmount = formatValue(primaryTokenInfo.quantity.multipliedBy(String(ptActivity?.close)));

return { totalValue: isPrimaryToken ? primaryTokenFiatTotalAmount : totalValue, unitPrice };
const tokenValueDisplay = secondaryToken24Activity && secondaryToken24Activity[0] === 500 ? 0 : totalValue;
return { totalValue: isPrimaryToken ? primaryTokenFiatTotalAmount : tokenValueDisplay, unitPrice };
};

const getTokenActivityChange = (tokenId, activityData, isPrimaryToken) => {
Expand Down Expand Up @@ -81,9 +82,15 @@ export const useProcessedTokenData = ({ data, ptActivity, data24h, data7d, data3
'24h': changePercent24,
'1W': isPrimaryToken ? ptTokenDataInterval7d?.[167]?.changePercent : changePercent7d,
'1M': isPrimaryToken ? ptTokenDataInterval1M?.[179]?.changePercent : changePercent30d,
isSpecialName: /^[^a-zA-Z]/.test(token.info.name), // Flag for names starting with numbers or weird characters
};
})
.sort((a, b) => b.percentage - a.percentage);
.sort((a, b) => {
// Move tokens with special names to the end
if (a.isSpecialName && !b.isSpecialName) return 1;
if (!a.isSpecialName && b.isSpecialName) return -1;
return b.percentage - a.percentage;
});
}, [data, ptActivity, data24h, data7d, data30d, primaryTokenInfo, ptTokenDataInterval7d, ptTokenDataInterval1M]);

return processedData;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { Stack, Typography } from '@mui/material';
import { useTheme } from '@mui/material/styles';
import React, { useEffect, useState } from 'react';
import { ampli } from '../../../../../../ampli/index';
import PortfolioHeader from '../../common/components/PortfolioHeader';
import WelcomeBanner from '../../common/components/WelcomeBanner';
import { useStrings } from '../../common/hooks/useStrings';
import { usePortfolio } from '../../module/PortfolioContextProvider';
import { PortfolioListTab, usePortfolio } from '../../module/PortfolioContextProvider';
import StatsTable from '../TokensTable/StatsTable';

const tabs = {
[PortfolioListTab.Wallet]: 'Wallet Token',
[PortfolioListTab.Dapps]: 'Dapps Token',
} as const;

const PortfolioWallet = (): JSX.Element => {
const theme = useTheme();
const strings = useStrings();
Expand All @@ -16,6 +22,10 @@ const PortfolioWallet = (): JSX.Element => {
const [isLoading, _] = useState<boolean>(false);
const [tokenList, setTokenList] = useState(ftAssetList);

useEffect(() => {
ampli.portfolioTokensListPageViewed({ tokens_tab: tabs[PortfolioListTab.Wallet] });
}, []);

useEffect(() => {
if (!keyword || showWelcomeBanner) {
setTokenList(ftAssetList);
Expand All @@ -35,6 +45,18 @@ const PortfolioWallet = (): JSX.Element => {
} else {
setTokenList([]);
}

let timeout: ReturnType<typeof setTimeout> | undefined;
const sendMetrics = () => {
clearTimeout(timeout);
timeout = setTimeout(() => {
ampli.portfolioTokensListSearchActivated({ search_term: lowercaseKeyword });
}, 500); // 0.5s requirement
};

if (lowercaseKeyword.length > 0) sendMetrics();

return () => clearTimeout(timeout);
}, [keyword]);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ import ProgressStepBlock from '../common/ProgressStepBlock';
import HelpLinkBlock from './HelpLinkBlock';
import HWErrorBlock from '../common/HWErrorBlock';

import { ReactComponent as ExternalLinkSVG } from '../../../../assets/images/link-external.inline.svg';
import { ReactComponent as AboutPrerequisiteIconSVG } from '../../../../assets/images/hardware-wallet/check-prerequisite-header-icon.inline.svg';
import { ReactComponent as AboutPrerequisiteTrezorSVG } from '../../../../assets/images/hardware-wallet/trezor/check.inline.svg';
import { ReactComponent as AboutTrezorSvg } from '../../../../assets/images/hardware-wallet/trezor/check-modern.inline.svg';
import { ReactComponent as ExternalLinkSVG } from '../../../../assets/images/link-external.inline.svg';
import { ReactComponent as AboutPrerequisiteIconSVG } from '../../../../assets/images/hardware-wallet/check-prerequisite-header-icon.inline.svg';
import { ReactComponent as AboutPrerequisiteTrezorSVG } from '../../../../assets/images/hardware-wallet/trezor/check.inline.svg';
import { ReactComponent as AboutTrezorSvg } from '../../../../assets/images/hardware-wallet/trezor/check-modern.inline.svg';

import { ProgressInfo } from '../../../../types/HWConnectStoreTypes';
import type { $npm$ReactIntl$IntlFormat } from 'react-intl';
import styles from '../common/CheckDialog.scss';
import { Link, Box, styled, Stack, Typography } from '@mui/material';

const messages = defineMessages({
aboutPrerequisite1Part1Text: {
Expand Down Expand Up @@ -63,67 +64,74 @@ type Props = {|
+classicTheme: boolean,
|};

const IconWrapper = styled(Box)(({ theme }) => ({
'& svg': {
'& path': {
fill: theme.palette.ds.el_gray_medium,
},
},
}));

@observer
export default class CheckDialog extends Component<Props> {

static contextTypes: {|intl: $npm$ReactIntl$IntlFormat|} = {
intl: intlShape.isRequired
static contextTypes: {| intl: $npm$ReactIntl$IntlFormat |} = {
intl: intlShape.isRequired,
};

render(): Node {
const { intl } = this.context;
const {
progressInfo,
isActionProcessing,
error,
onExternalLinkClick,
submit,
cancel,
classicTheme,
} = this.props;
const { progressInfo, isActionProcessing, error, onExternalLinkClick, submit, cancel, classicTheme } = this.props;

const middleBlock = (
<div className={classnames([styles.middleBlock, styles.component])}>
{!classicTheme && <AboutTrezorSvg />}

<div className={styles.prerequisiteBlock}>
<div>
<AboutPrerequisiteIconSVG />
<span className={styles.prerequisiteHeaderText}>
<Stack direction="row" gap="8px">
<IconWrapper>
<AboutPrerequisiteIconSVG />
</IconWrapper>
<Typography className={styles.prerequisiteHeaderText} color="ds.text_gray_low">
{intl.formatMessage(globalMessages.hwConnectDialogAboutPrerequisiteHeader)}
</span>
</div>
<ul>
<li key="1">
<a
href={intl.formatMessage(messages.aboutPrerequisite1Part1Link)}
onClick={event => onExternalLinkClick(event)}
>
{intl.formatMessage(messages.aboutPrerequisite1Part1Text) + ' '}
<ExternalLinkSVG />
</a>
{intl.formatMessage(messages.aboutPrerequisite1Part2)}
</li>
<li key="2">{intl.formatMessage(messages.aboutPrerequisite2)}</li>
<li key="3">{intl.formatMessage(messages.aboutPrerequisite3)}</li>
<li key="4">{intl.formatMessage(globalMessages.hwConnectDialogAboutPrerequisite4)}</li>
<li key="5">{intl.formatMessage(messages.aboutPrerequisite5)}</li>
</ul>
</Typography>
</Stack>
<Stack>
<Stack direction="row" alignItems="center" gap="8px">
<Typography color="ds.text_gray_low">
&#x2022; {intl.formatMessage(messages.aboutPrerequisite1Part1Text) + ' '}
</Typography>
<Link href={intl.formatMessage(messages.aboutPrerequisite1Part1Link)} onClick={event => onExternalLinkClick(event)}>
<IconWrapper>
<ExternalLinkSVG />
</IconWrapper>
</Link>
<Typography color="ds.text_gray_low">{intl.formatMessage(messages.aboutPrerequisite1Part2)}</Typography>
</Stack>
<Typography color="ds.text_gray_low"> &#x2022; {intl.formatMessage(messages.aboutPrerequisite2)}</Typography>
<Typography color="ds.text_gray_low">&#x2022; {intl.formatMessage(messages.aboutPrerequisite3)}</Typography>
<Typography color="ds.text_gray_low">
&#x2022; {intl.formatMessage(globalMessages.hwConnectDialogAboutPrerequisite4)}
</Typography>
<Typography color="ds.text_gray_low">&#x2022; {intl.formatMessage(messages.aboutPrerequisite5)}</Typography>
</Stack>
</div>

{classicTheme && (
<div className={styles.hwImageBlock}>
<AboutPrerequisiteTrezorSVG />
</div>
)}
</div>);
</div>
);

const dailogActions = [{
label: intl.formatMessage(globalMessages.nextButtonLabel),
primary: true,
onClick: submit,
isSubmitting: isActionProcessing,
}];
const dailogActions = [
{
label: intl.formatMessage(globalMessages.nextButtonLabel),
primary: true,
onClick: submit,
isSubmitting: isActionProcessing,
},
];

return (
<Dialog
Expand All @@ -137,10 +145,9 @@ export default class CheckDialog extends Component<Props> {
>
<ProgressStepBlock progressInfo={progressInfo} classicTheme={classicTheme} />
{middleBlock}
{error &&
<HWErrorBlock progressInfo={progressInfo} error={error} classicTheme={classicTheme} />
}
{error && <HWErrorBlock progressInfo={progressInfo} error={error} classicTheme={classicTheme} />}
<HelpLinkBlock onExternalLinkClick={onExternalLinkClick} />
</Dialog>);
</Dialog>
);
}
}
Loading

0 comments on commit 280321f

Please sign in to comment.