Commit 79fa0642 authored by tom goriunov's avatar tom goriunov Committed by GitHub

Merge pull request #662 from blockscout/chors

chores: better types and eslint rules
parents a0857b28 9a99b613
......@@ -30,6 +30,7 @@ module.exports = {
'jsx-a11y',
'eslint-plugin-import-helpers',
'jest',
'eslint-plugin-no-cyrillic-string',
],
parser: '@typescript-eslint/parser',
parserOptions: {
......@@ -117,7 +118,7 @@ module.exports = {
'@typescript-eslint/type-annotation-spacing': 'error',
'@typescript-eslint/no-explicit-any': [ 'error', { ignoreRestArgs: true } ],
// отключены в пользу @typescript-eslint
// disabled in favor of @typescript-eslint
'brace-style': 'off',
camelcase: 'off',
indent: 'off',
......@@ -269,7 +270,7 @@ module.exports = {
'regexp/no-empty-capturing-group': 'error',
'regexp/no-lazy-ends': 'error',
'regexp/no-obscure-range': [ 'error', {
allowed: [ 'alphanumeric', 'А-Я', 'а-я' ],
allowed: [ 'alphanumeric' ],
} ],
'regexp/no-optional-assertion': 'error',
'regexp/no-unused-capturing-group': [ 'error', {
......@@ -277,6 +278,8 @@ module.exports = {
} ],
'regexp/no-useless-character-class': 'error',
'regexp/no-useless-dollar-replacements': 'error',
'no-cyrillic-string/no-cyrillic-string': 'error',
},
overrides: [
{
......
......@@ -6,7 +6,7 @@ import type { ChainIndicatorId } from 'ui/home/indicators/types';
const getEnvValue = (env: string | undefined) => env?.replaceAll('\'', '"');
const parseEnvJson = <DataType>(env: string | undefined): DataType | null => {
try {
return JSON.parse(env || 'null');
return JSON.parse(env || 'null') as DataType | null;
} catch (error) {
return null;
}
......
import type { MetaMaskInpageProvider } from '@metamask/providers';
type CPreferences = {
zone: string;
width: string;
height: string;
}
declare global {
interface Window {
ethereum: MetaMaskInpageProvider;
coinzilla_display: Array<CPreferences>;
}
}
......@@ -6,7 +6,7 @@ import type { Params as ApiFetchParams } from './useApiFetch';
import useApiFetch from './useApiFetch';
export interface Params<R extends ResourceName, E = unknown> extends ApiFetchParams<R> {
queryOptions?: Omit<UseQueryOptions<unknown, ResourceError<E>, ResourcePayload<R>>, 'queryKey' | 'queryFn'>;
queryOptions?: Omit<UseQueryOptions<ResourcePayload<R>, ResourceError<E>, ResourcePayload<R>>, 'queryKey' | 'queryFn'>;
}
export function getResourceKey<R extends ResourceName>(resource: R, { pathParams, queryParams }: Params<R> = {}) {
......@@ -23,9 +23,12 @@ export default function useApiQuery<R extends ResourceName, E = unknown>(
) {
const apiFetch = useApiFetch();
return useQuery<unknown, ResourceError<E>, ResourcePayload<R>>(
return useQuery<ResourcePayload<R>, ResourceError<E>, ResourcePayload<R>>(
getResourceKey(resource, { pathParams, queryParams }),
async() => {
return apiFetch<R, ResourcePayload<R>, ResourceError>(resource, { pathParams, queryParams, fetchParams });
// all errors and error typing is handled by react-query
// so error response will never go to the data
// that's why we are safe here to do type conversion "as Promise<ResourcePayload<R>>"
return apiFetch(resource, { pathParams, queryParams, fetchParams }) as Promise<ResourcePayload<R>>;
}, queryOptions);
}
export default function getErrorStatusCode(error: Error | undefined): number | undefined {
return (
error && 'cause' in error &&
typeof error.cause === 'object' && error.cause !== null &&
'status' in error.cause && typeof error.cause.status === 'number' &&
error.cause.status
) ||
undefined;
}
export default function formatNumberToMetricPrefix(number: number) {
return Intl.NumberFormat('en-US', {
notation: 'compact',
maximumFractionDigits: 3,
}).format(number);
}
export function shortenNumberWithLetter(
x: number,
params?: {
unitSeparator: string;
},
_options?: Intl.NumberFormatOptions,
) {
const options = _options || { maximumFractionDigits: 2 };
const unitSeparator = params?.unitSeparator || '';
if (x > 1_000_000_000) {
return (x / 1_000_000_000).toLocaleString('en', options) + unitSeparator + 'B';
}
if (x > 1_000_000) {
return (x / 1_000_000).toLocaleString('en', options) + unitSeparator + 'M';
}
if (x > 1_000) {
return (x / 1_000).toLocaleString('en', options) + unitSeparator + 'K';
}
return x.toLocaleString('en', options);
}
export default function getFilterValue<FilterType>(filterValues: ReadonlyArray<FilterType>, val: string | Array<string> | undefined) {
if (typeof val === 'string' && filterValues.includes(val as unknown as FilterType)) {
return val as unknown as FilterType;
export default function getFilterValue<FilterType>(filterValues: ReadonlyArray<FilterType>, val: string | Array<string> | undefined): FilterType | undefined {
if (typeof val === 'string' && filterValues.includes(val as FilterType)) {
return val as FilterType;
}
}
import BigNumber from 'bignumber.js';
import type { Unit } from 'types/unit';
import { WEI, GWEI } from 'lib/consts';
export default function getValueWithUnit(value: string | number, unit: 'wei' | 'gwei' | 'ether' = 'wei') {
export default function getValueWithUnit(value: string | number, unit: Unit = 'wei') {
let unitBn: BigNumber.Value;
switch (unit) {
case 'wei':
......
......@@ -2,7 +2,6 @@ import React from 'react';
import type { Address } from 'types/api/address';
import notEmpty from 'lib/notEmpty';
import ContractCode from 'ui/address/contract/ContractCode';
import ContractRead from 'ui/address/contract/ContractRead';
import ContractWrite from 'ui/address/contract/ContractWrite';
......@@ -33,6 +32,6 @@ export default function useContractTabs(data: Address | undefined) {
data?.has_custom_methods_write ?
{ id: 'write_custom_methods', title: 'Write custom', component: <ContractWrite addressHash={ data?.hash } isCustomAbi/> } :
undefined,
].filter(notEmpty);
].filter(Boolean);
}, [ data ]);
}
......@@ -23,7 +23,6 @@ import transactionsIcon from 'icons/transactions.svg';
import verifiedIcon from 'icons/verified.svg';
import watchlistIcon from 'icons/watchlist.svg';
// import { rightLineArrow } from 'lib/html-entities';
import notEmpty from 'lib/notEmpty';
export interface NavItem {
text: string;
......@@ -106,7 +105,7 @@ export default function useNavItems(): ReturnType {
} : null,
// FIXME: need icon for this item
{ text: 'GraphQL', nextRoute: { pathname: '/graphiql' as const }, icon: topAccountsIcon, isActive: false, isNewUi: false },
].filter(notEmpty);
].filter(Boolean);
const mainNavItems = [
{
......@@ -125,7 +124,7 @@ export default function useNavItems(): ReturnType {
// at this stage custom menu items is under development, we will implement it later
otherNavItems.length > 0 ?
{ text: 'Other', icon: gearIcon, isActive: otherNavItems.some(item => item.isActive), subItems: otherNavItems } : null,
].filter(notEmpty) as Array<NavItem | NavGroupItem>;
].filter(Boolean);
const accountNavItems = [
{
......
// https://unicode-table.com
export const asymp = String.fromCharCode(8776); // приблизительно
export const hellip = String.fromCharCode(8230); // многоточие
export const nbsp = String.fromCharCode(160); // неразрывный пробел
export const thinsp = String.fromCharCode(8201); // короткий пробел
export const space = String.fromCharCode(32); // обычный пробел
export const nbdash = String.fromCharCode(8209); // неразрывное тире
export const mdash = String.fromCharCode(8212); // длинное тире
export const ndash = String.fromCharCode(8211); // среднее тире
export const laquo = String.fromCharCode(171); // кавычки-ёлочки (левые)
export const raquo = String.fromCharCode(187); // кавычки-ёлочки (правые)
export const middot = String.fromCharCode(183); // точка по центру строки (в вертикальном смысле)
export const blackCircle = String.fromCharCode(9679); // жирная точка по центру строки (в вертикальном смысле)
export const asymp = String.fromCharCode(8776); // ~
export const hellip = String.fromCharCode(8230); //
export const nbsp = String.fromCharCode(160); // no-break Space
export const thinsp = String.fromCharCode(8201); // thin Space
export const space = String.fromCharCode(32); // space
export const nbdash = String.fromCharCode(8209); // non-breaking hyphen
export const mdash = String.fromCharCode(8212); // em dash
export const ndash = String.fromCharCode(8211); // en dash
export const laquo = String.fromCharCode(171); // «
export const raquo = String.fromCharCode(187); // »
export const middot = String.fromCharCode(183); // ·
export const blackCircle = String.fromCharCode(9679); //
export const blackRightwardsArrowhead = String.fromCharCode(10148); // ➤
export const degree = String.fromCharCode(176); // градус °
export const times = String.fromCharCode(215); // мультипликатор ×
export const disk = String.fromCharCode(8226); // диск
export const minus = String.fromCharCode(8722); // минус
export const leftLineArrow = String.fromCharCode(8592); // стрелка
export const rightLineArrow = String.fromCharCode(8594); // стрелка
export const apos = String.fromCharCode(39); // апостроф '
export const degree = String.fromCharCode(176); // °
export const times = String.fromCharCode(215); // ×
export const disk = String.fromCharCode(8226); // •
export const minus = String.fromCharCode(8722); // −
export const leftLineArrow = String.fromCharCode(8592); // ←
export const rightLineArrow = String.fromCharCode(8594); // →
export const apos = String.fromCharCode(39); // apostrophe '
export default function notEmpty<TValue>(value: TValue | null | undefined): value is TValue {
return value !== null && value !== undefined;
}
import type { Channel } from 'phoenix';
import { useEffect, useRef, useState } from 'react';
import notEmpty from 'lib/notEmpty';
import { useSocket } from './context';
const CHANNEL_REGISTRY: Record<string, Channel> = {};
......@@ -27,7 +25,7 @@ export default function useSocketChannel({ topic, params, isDisabled, onJoin, on
useEffect(() => {
const cleanUpRefs = () => {
const refs = [ onCloseRef.current, onErrorRef.current ].filter(notEmpty);
const refs = [ onCloseRef.current, onErrorRef.current ].filter(Boolean);
refs.length > 0 && socket?.off(refs);
};
......
......@@ -9,6 +9,7 @@ import type { ResourceError } from 'lib/api/resources';
import { AppContextProvider } from 'lib/appContext';
import { Chakra } from 'lib/Chakra';
import { ScrollDirectionProvider } from 'lib/contexts/scrollDirection';
import getErrorStatusCode from 'lib/errors/getErrorStatusCode';
import useConfigSentry from 'lib/hooks/useConfigSentry';
import { SocketProvider } from 'lib/socket/context';
import theme from 'theme';
......@@ -36,12 +37,11 @@ function MyApp({ Component, pageProps }: AppProps) {
}));
const renderErrorScreen = React.useCallback((error?: Error) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const statusCode = (error?.cause as any)?.status || 500;
const statusCode = getErrorStatusCode(error);
return (
<AppError
statusCode={ statusCode }
statusCode={ statusCode || 500 }
height="100vh"
display="flex"
flexDirection="column"
......
......@@ -35,7 +35,7 @@ export const joinChannel = async(socket: WebSocket, channelName: string) => {
return new Promise<[string, string, string]>((resolve, reject) => {
socket.on('message', (msg) => {
try {
const payload: Array<string> = JSON.parse(msg.toString());
const payload = JSON.parse(msg.toString()) as Array<string>;
if (channelName === payload[2] && payload[3] === 'phx_join') {
socket.send(JSON.stringify([
......
import '@total-typescript/ts-reset';
import type { AddressParam } from './addressParams';
export type TransactionReward = {
types: Array<string>;
emission_reward: string;
block_hash: string;
from: AddressParam;
to: AddressParam;
}
......@@ -7,7 +7,6 @@ import type { AppItemPreview } from 'types/client/apps';
import northEastIcon from 'icons/arrows/north-east.svg';
import starFilledIcon from 'icons/star_filled.svg';
import starOutlineIcon from 'icons/star_outline.svg';
import notEmpty from 'lib/notEmpty';
import AppCardLink from './AppCardLink';
import { APP_CATEGORIES } from './constants';
......@@ -30,7 +29,7 @@ const AppCard = ({
isFavorite,
onFavoriteClick,
}: Props) => {
const categoriesLabel = categories.map(c => APP_CATEGORIES[c]).filter(notEmpty).join(', ');
const categoriesLabel = categories.map(c => APP_CATEGORIES[c]).filter(Boolean).join(', ');
const handleInfoClick = useCallback((event: MouseEvent) => {
event.preventDefault();
......
......@@ -15,7 +15,6 @@ import starFilledIcon from 'icons/star_filled.svg';
import starOutlineIcon from 'icons/star_outline.svg';
import useIsMobile from 'lib/hooks/useIsMobile';
import { nbsp } from 'lib/html-entities';
import notEmpty from 'lib/notEmpty';
import AppModalLink from './AppModalLink';
import { APP_CATEGORIES } from './constants';
......@@ -60,7 +59,7 @@ const AppModal = ({
icon: ghIcon,
url: github,
} : null,
].filter(notEmpty);
].filter(Boolean);
const handleFavoriteClick = useCallback(() => {
onFavoriteClick(id, isFavorite);
......
......@@ -9,7 +9,7 @@ const favoriteAppsLocalStorageKey = 'favoriteApps';
function getFavoriteApps() {
try {
return JSON.parse(localStorage.getItem(favoriteAppsLocalStorageKey) || '[]');
return JSON.parse(localStorage.getItem(favoriteAppsLocalStorageKey) || '[]') as Array<string>;
} catch (e) {
return [];
}
......
......@@ -101,7 +101,7 @@ export const DEFAULT_VALUES = {
};
export function isValidVerificationMethod(method?: string): method is SmartContractVerificationMethod {
return method && SUPPORTED_VERIFICATION_METHODS.includes(method as SmartContractVerificationMethod) ? true : false;
return method && SUPPORTED_VERIFICATION_METHODS.includes(method) ? true : false;
}
export function sortVerificationMethods(methodA: SmartContractVerificationMethod, methodB: SmartContractVerificationMethod) {
......
import type { TooltipProps } from '@chakra-ui/react';
import type { SystemStyleObject, TooltipProps } from '@chakra-ui/react';
import { Flex, Icon, Text, useColorModeValue, chakra, LightMode } from '@chakra-ui/react';
import React from 'react';
......@@ -25,13 +25,13 @@ const TOOLTIP_PROPS: Partial<TooltipProps> = {
};
const StatsItem = ({ icon, title, value, className, tooltipLabel, url }: Props) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const sxContainer = {} as any;
sxContainer[`@media screen and (min-width: ${ breakpoints.lg }) and (max-width: ${ LARGEST_BREAKPOINT })`] = { flexDirection: 'column' };
const sxContainer: SystemStyleObject = {
[`@media screen and (min-width: ${ breakpoints.lg }) and (max-width: ${ LARGEST_BREAKPOINT })`]: { flexDirection: 'column' },
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const sxText = {} as any;
sxText[`@media screen and (min-width: ${ breakpoints.lg }) and (max-width: ${ LARGEST_BREAKPOINT })`] = { alignItems: 'center' };
const sxText: SystemStyleObject = {
[`@media screen and (min-width: ${ breakpoints.lg }) and (max-width: ${ LARGEST_BREAKPOINT })`]: { alignItems: 'center' },
};
const infoColor = useColorModeValue('gray.600', 'gray.400');
......
......@@ -6,14 +6,13 @@ import type { TChainIndicator } from '../types';
import appConfig from 'configs/app/config';
import globeIcon from 'icons/globe.svg';
import txIcon from 'icons/transactions.svg';
import { shortenNumberWithLetter } from 'lib/formatters';
import { sortByDateDesc } from 'ui/shared/chart/utils/sorts';
import TokenLogo from 'ui/shared/TokenLogo';
const dailyTxsIndicator: TChainIndicator<'homepage_chart_txs'> = {
id: 'daily_txs',
title: 'Daily transactions',
value: (stats) => shortenNumberWithLetter(Number(stats.transactions_today), undefined, { maximumFractionDigits: 2 }),
value: (stats) => Number(stats.transactions_today).toLocaleString('en', { maximumFractionDigits: 2, notation: 'compact' }),
icon: <Icon as={ txIcon } boxSize={ 6 } bgColor="#56ACD1" borderRadius="base" color="white"/>,
hint: `The total daily number of transactions on the blockchain for the last month.`,
api: {
......@@ -23,7 +22,7 @@ const dailyTxsIndicator: TChainIndicator<'homepage_chart_txs'> = {
.map((item) => ({ date: new Date(item.date), value: item.tx_count }))
.sort(sortByDateDesc),
name: 'Tx/day',
valueFormatter: (x: number) => shortenNumberWithLetter(x, undefined, { maximumFractionDigits: 2 }),
valueFormatter: (x: number) => x.toLocaleString('en', { maximumFractionDigits: 2, notation: 'compact' }),
} ]),
},
};
......@@ -49,7 +48,7 @@ const coinPriceIndicator: TChainIndicator<'homepage_chart_market'> = {
const marketPriceIndicator: TChainIndicator<'homepage_chart_market'> = {
id: 'market_cup',
title: 'Market cap',
value: (stats) => '$' + shortenNumberWithLetter(Number(stats.market_cap), undefined, { maximumFractionDigits: 0 }),
value: (stats) => '$' + Number(stats.market_cap).toLocaleString('en', { maximumFractionDigits: 0, notation: 'compact' }),
icon: <Icon as={ globeIcon } boxSize={ 6 } bgColor="#6A5DCC" borderRadius="base" color="white"/>,
// eslint-disable-next-line max-len
hint: 'The total market value of a cryptocurrency\'s circulating supply. It is analogous to the free-float capitalization in the stock market. Market Cap = Current Price x Circulating Supply.',
......@@ -60,7 +59,7 @@ const marketPriceIndicator: TChainIndicator<'homepage_chart_market'> = {
.map((item) => ({ date: new Date(item.date), value: Number(item.closing_price) * Number(response.available_supply) }))
.sort(sortByDateDesc),
name: 'Market cap',
valueFormatter: (x: number) => '$' + shortenNumberWithLetter(x, undefined, { maximumFractionDigits: 0 }),
valueFormatter: (x: number) => '$' + x.toLocaleString('en', { maximumFractionDigits: 0 }),
} ]),
},
};
......
......@@ -9,7 +9,6 @@ import iconSuccess from 'icons/status/success.svg';
import useApiQuery from 'lib/api/useApiQuery';
import { useAppContext } from 'lib/appContext';
import useContractTabs from 'lib/hooks/useContractTabs';
import notEmpty from 'lib/notEmpty';
import getQueryParamString from 'lib/router/getQueryParamString';
import AddressBlocksValidated from 'ui/address/AddressBlocksValidated';
import AddressCoinBalance from 'ui/address/AddressCoinBalance';
......@@ -57,7 +56,7 @@ const AddressPageContent = () => {
...(addressQuery.data?.public_tags || []),
...(addressQuery.data?.watchlist_names || []),
]
.filter(notEmpty)
.filter(Boolean)
.map((tag) => <Tag key={ tag.label }>{ tag.display_name }</Tag>);
const contractTabs = useContractTabs(addressQuery.data);
......@@ -92,7 +91,7 @@ const AddressPageContent = () => {
component: <AddressContract tabs={ contractTabs } addressHash={ hash }/>,
subTabs: contractTabs.map(tab => tab.id),
} : undefined,
].filter(notEmpty);
].filter(Boolean);
}, [ addressQuery.data, contractTabs, hash ]);
const tagsNode = tags.length > 0 ? <Flex columnGap={ 2 }>{ tags }</Flex> : null;
......
......@@ -2,7 +2,7 @@ import { Text } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import React from 'react';
import type { SmartContractVerificationConfigRaw, SmartContractVerificationMethod } from 'types/api/contract';
import type { SmartContractVerificationMethod } from 'types/api/contract';
import useApiQuery from 'lib/api/useApiQuery';
import { useAppContext } from 'lib/appContext';
......@@ -39,11 +39,10 @@ const ContractVerification = () => {
const configQuery = useApiQuery('contract_verification_config', {
queryOptions: {
select: (data: unknown) => {
const _data = data as SmartContractVerificationConfigRaw;
select: (data) => {
return {
..._data,
verification_options: _data.verification_options.filter(isValidVerificationMethod).sort(sortVerificationMethods),
...data,
verification_options: data.verification_options.filter(isValidVerificationMethod).sort(sortVerificationMethods),
};
},
enabled: Boolean(hash),
......
......@@ -10,7 +10,6 @@ import { useAppContext } from 'lib/appContext';
import useContractTabs from 'lib/hooks/useContractTabs';
import useIsMobile from 'lib/hooks/useIsMobile';
import useQueryWithPages from 'lib/hooks/useQueryWithPages';
import notEmpty from 'lib/notEmpty';
import trimTokenSymbol from 'lib/token/trimTokenSymbol';
import AddressContract from 'ui/address/AddressContract';
import TextAd from 'ui/shared/ad/TextAd';
......@@ -118,7 +117,7 @@ const TokenPageContent = () => {
component: <AddressContract tabs={ contractTabs } addressHash={ hashString }/>,
subTabs: contractTabs.map(tab => tab.id),
} : undefined,
].filter(notEmpty);
].filter(Boolean);
let hasPagination;
let pagination;
......
import { Flex } from '@chakra-ui/react';
import React from 'react';
import getErrorStatusCode from 'lib/errors/getErrorStatusCode';
import useGetCsrfToken from 'lib/hooks/useGetCsrfToken';
import AppError from 'ui/shared/AppError/AppError';
import ErrorBoundary from 'ui/shared/ErrorBoundary';
......@@ -26,8 +27,7 @@ const Page = ({
useGetCsrfToken();
const renderErrorScreen = React.useCallback((error?: Error) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const statusCode = (error?.cause as any)?.status || 500;
const statusCode = getErrorStatusCode(error) || 500;
const isInvalidTxHash = error?.message.includes('Invalid tx hash');
if (wrapChildren) {
......
......@@ -4,29 +4,17 @@ import React from 'react';
import isBrowser from 'lib/isBrowser';
declare global {
interface Window {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
coinzilla_display: any;
}
}
type CPreferences = {
zone: string;
width: string;
height: string;
}
const CoinzillaBanner = ({ className }: { className?: string }) => {
const isInBrowser = isBrowser();
React.useEffect(() => {
if (isInBrowser) {
window.coinzilla_display = window.coinzilla_display || [];
const cDisplayPreferences = {} as CPreferences;
cDisplayPreferences.zone = '26660bf627543e46851';
cDisplayPreferences.width = '728';
cDisplayPreferences.height = '90';
const cDisplayPreferences = {
zone: '26660bf627543e46851',
width: '728',
height: '90',
};
window.coinzilla_display.push(cDisplayPreferences);
}
}, [ isInBrowser ]);
......
......@@ -31,7 +31,8 @@ const CoinzillaTextAd = ({ className }: {className?: string}) => {
useEffect(() => {
fetch('https://request-global.czilladx.com/serve/native.php?z=19260bf627546ab7242')
.then(res => res.status === 200 ? res.json() : null)
.then((data) => {
.then((_data) => {
const data = _data as AdData;
setAdData(data);
if (data?.ad?.impressionUrl) {
fetch(data.ad.impressionUrl);
......
......@@ -27,7 +27,7 @@ const AddressContractIcon = ({ className }: Props) => {
transitionDuration="normal"
transitionTimingFunction="ease"
>
С
C
</Box>
</Tooltip>
);
......
......@@ -4,7 +4,6 @@ import { useMemo } from 'react';
import type { TimeChartData } from 'ui/shared/chart/types';
import { WEEK, MONTH, YEAR } from 'lib/consts';
import formatNumberToMetricPrefix from 'lib/formatNumberToMetricPrefix';
interface Props {
data: TimeChartData;
......@@ -73,7 +72,7 @@ export default function useTimeChartController({ data, width, height }: Props) {
return format(d as Date);
};
const yTickFormat = () => (d: d3.AxisDomain) => formatNumberToMetricPrefix(Number(d));
const yTickFormat = () => (d: d3.AxisDomain) => Number(d).toLocaleString('en', { maximumFractionDigits: 3, notation: 'compact' });
return {
xTickFormat,
......
......@@ -7,7 +7,6 @@ import placeholderIcon from 'icons/files/placeholder.svg';
import solIcon from 'icons/files/sol.svg';
import yulIcon from 'icons/files/yul.svg';
import infoIcon from 'icons/info.svg';
import { shortenNumberWithLetter } from 'lib/formatters';
const FILE_ICONS: Record<string, React.FunctionComponent<React.SVGAttributes<SVGElement>>> = {
'.json': jsonIcon,
......@@ -101,7 +100,9 @@ const FileSnippet = ({ file, className, index, onRemove, isDisabled, error }: Pr
alignSelf="flex-start"
/>
</Flex>
<Text variant="secondary" mt={ 1 }>{ shortenNumberWithLetter(file.size) }B</Text>
<Text variant="secondary" mt={ 1 }>
{ file.size.toLocaleString('en', { notation: 'compact', maximumFractionDigits: 2, unit: 'byte', unitDisplay: 'narrow', style: 'unit' }) }
</Text>
</Box>
</Flex>
);
......
......@@ -6,7 +6,6 @@ import type { Log } from 'types/api/log';
// import searchIcon from 'icons/search.svg';
import { space } from 'lib/html-entities';
import notEmpty from 'lib/notEmpty';
import Address from 'ui/shared/address/Address';
import AddressIcon from 'ui/shared/address/AddressIcon';
import AddressLink from 'ui/shared/address/AddressLink';
......@@ -83,7 +82,7 @@ const LogItem = ({ address, index, topics, data, decoded, type, tx_hash: txHash
) }
<RowHeader>Topics</RowHeader>
<GridItem>
{ topics.filter(notEmpty).map((item, index) => (
{ topics.filter(Boolean).map((item, index) => (
<LogTopic
key={ index }
hex={ item }
......
......@@ -70,8 +70,9 @@ const NavLinkGroupDesktop = ({ text, subItems, icon, isCollapsed, isActive }: Pr
{ text }
</Text>
<VStack spacing={ 1 } alignItems="start">
{ subItems.map(item => Array.isArray(item) ? (
{ subItems.map((item, index) => Array.isArray(item) ? (
<Box
key={ index }
w="100%"
as="ul"
_notLast={{
......
......@@ -93,8 +93,9 @@ const NavigationMobile = () => {
as="ul"
>
{ isGroupItem(openedItem) && openedItem.subItems?.map(
item => Array.isArray(item) ? (
(item, index) => Array.isArray(item) ? (
<Box
key={ index }
w="100%"
as="ul"
_notLast={{
......
......@@ -2,7 +2,6 @@ import { Grid } from '@chakra-ui/react';
import React from 'react';
import useApiQuery from 'lib/api/useApiQuery';
import formatNumberToMetricPrefix from 'lib/formatNumberToMetricPrefix';
import DataFetchAlert from '../shared/DataFetchAlert';
import NumberWidget from './NumberWidget';
......@@ -32,7 +31,7 @@ const NumberWidgetsList = () => {
<NumberWidget
key={ id }
label={ title }
value={ `${ formatNumberToMetricPrefix(Number(value)) } ${ units ? units : '' }` }
value={ `${ Number(value).toLocaleString('en', { maximumFractionDigits: 3, notation: 'compact' }) } ${ units ? units : '' }` }
/>
);
}) }
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment