Skip to content

Commit

Permalink
Merge branch 'main' of github.com:blockscout/frontend into tom2drum/i…
Browse files Browse the repository at this point in the history
…ssue-1414
  • Loading branch information
tom2drum committed Dec 21, 2023
2 parents 754e319 + ea9e0cd commit f8d8b7f
Show file tree
Hide file tree
Showing 19 changed files with 997 additions and 216 deletions.
1 change: 1 addition & 0 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const moduleExports = {
},
);
config.resolve.fallback = { fs: false, net: false, tls: false };
config.externals.push('pino-pretty', 'lokijs', 'encoding');

return config;
},
Expand Down
4 changes: 4 additions & 0 deletions nextjs/csp/policies/walletConnect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,22 @@ import type CspDev from 'csp-dev';

import config from 'configs/app';

import { KEY_WORDS } from '../utils';

export function walletConnect(): CspDev.DirectiveDescriptor {
if (!config.features.blockchainInteraction.isEnabled) {
return {};
}

return {
'connect-src': [
'*.web3modal.com',
'*.walletconnect.com',
'wss://relay.walletconnect.com',
'wss://www.walletlink.org',
],
'img-src': [
KEY_WORDS.BLOB,
'*.walletconnect.com',
],
};
Expand Down
7 changes: 3 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@
"@tanstack/react-query-devtools": "^5.4.3",
"@types/papaparse": "^5.3.5",
"@types/react-scroll": "^1.8.4",
"@web3modal/ethereum": "^2.6.2",
"@web3modal/react": "^2.6.2",
"@web3modal/wagmi": "3.5.0",
"bignumber.js": "^9.1.0",
"blo": "^1.1.1",
"chakra-react-select": "^4.4.3",
Expand Down Expand Up @@ -93,8 +92,8 @@
"react-scroll": "^1.8.7",
"swagger-ui-react": "^5.9.0",
"use-font-face-observer": "^1.2.1",
"viem": "^1.1.8",
"wagmi": "^1.3.3",
"viem": "1.20.1",
"wagmi": "1.4.12",
"xss": "^1.0.14"
},
"devDependencies": {
Expand Down
25 changes: 13 additions & 12 deletions playwright/TestApp.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { ChakraProvider } from '@chakra-ui/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { w3mProvider } from '@web3modal/ethereum';
import { createWeb3Modal, defaultWagmiConfig } from '@web3modal/wagmi/react';
import React from 'react';
import { configureChains, createConfig, WagmiConfig } from 'wagmi';
import { WagmiConfig } from 'wagmi';
import { mainnet } from 'wagmi/chains';

import type { Props as PageProps } from 'nextjs/getServerSideProps';
Expand Down Expand Up @@ -33,17 +33,18 @@ const defaultAppContext = {
};

// >>> Web3 stuff
const { publicClient } = configureChains(
[ mainnet ],
[
w3mProvider({ projectId: '' }),
],
);
const chains = [ mainnet ];
const WALLET_CONNECT_PROJECT_ID = 'PROJECT_ID';

const wagmiConfig = createConfig({
autoConnect: false,
connectors: [ ],
publicClient,
const wagmiConfig = defaultWagmiConfig({
chains,
projectId: WALLET_CONNECT_PROJECT_ID,
});

createWeb3Modal({
wagmiConfig,
projectId: WALLET_CONNECT_PROJECT_ID,
chains,
});
// <<<<

Expand Down
5 changes: 3 additions & 2 deletions ui/address/contract/ContractConnectWallet.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Alert, Button, Flex } from '@chakra-ui/react';
import { useWeb3Modal } from '@web3modal/react';
import { useWeb3Modal, useWeb3ModalState } from '@web3modal/wagmi/react';
import React from 'react';
import { useAccount, useDisconnect } from 'wagmi';

Expand All @@ -8,7 +8,8 @@ import * as mixpanel from 'lib/mixpanel/index';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';

const ContractConnectWallet = () => {
const { open, isOpen } = useWeb3Modal();
const { open } = useWeb3Modal();
const { open: isOpen } = useWeb3ModalState();
const { disconnect } = useDisconnect();
const isMobile = useIsMobile();
const [ isModalOpening, setIsModalOpening ] = React.useState(false);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Alert, Box, Button, chakra, Flex, Link, Radio, RadioGroup } from '@chakra-ui/react';
import { useWeb3Modal } from '@web3modal/react';
import { useWeb3Modal } from '@web3modal/wagmi/react';
import React from 'react';
import type { SubmitHandler } from 'react-hook-form';
import { useForm } from 'react-hook-form';
Expand Down
4 changes: 2 additions & 2 deletions ui/home/Stats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import config from 'configs/app';
import useApiQuery from 'lib/api/useApiQuery';
import { WEI } from 'lib/consts';
import { HOMEPAGE_STATS } from 'stubs/stats';
import GasInfoTooltipContent from 'ui/shared/GasInfoTooltipContent/GasInfoTooltipContent';

import StatsGasPrices from './StatsGasPrices';
import StatsItem from './StatsItem';

const hasGasTracker = config.UI.homepage.showGasTracker;
Expand Down Expand Up @@ -45,7 +45,7 @@ const Stats = () => {
!data.gas_prices && itemsCount--;
data.rootstock_locked_btc && itemsCount++;
const isOdd = Boolean(itemsCount % 2);
const gasLabel = hasGasTracker && data.gas_prices ? <StatsGasPrices gasPrices={ data.gas_prices }/> : null;
const gasLabel = hasGasTracker && data.gas_prices ? <GasInfoTooltipContent gasPrices={ data.gas_prices }/> : null;

content = (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from 'react';

import type { GasPrices } from 'types/api/stats';

const StatsGasPrices = ({ gasPrices }: {gasPrices: GasPrices}) => {
const GasInfoTooltipContent = ({ gasPrices }: {gasPrices: GasPrices}) => {
const nameStyleProps = {
color: useColorModeValue('blue.100', 'blue.600'),
};
Expand All @@ -20,4 +20,4 @@ const StatsGasPrices = ({ gasPrices }: {gasPrices: GasPrices}) => {
);
};

export default StatsGasPrices;
export default React.memo(GasInfoTooltipContent);
91 changes: 53 additions & 38 deletions ui/shared/Web3ModalProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { useColorModeValue, useToken } from '@chakra-ui/react';
import { useColorMode } from '@chakra-ui/react';
import { jsonRpcProvider } from '@wagmi/core/providers/jsonRpc';
import { EthereumClient, w3mConnectors } from '@web3modal/ethereum';
import { Web3Modal } from '@web3modal/react';
import { createWeb3Modal, useWeb3ModalTheme, defaultWagmiConfig } from '@web3modal/wagmi/react';
import React from 'react';
import type { Chain } from 'wagmi';
import { configureChains, createConfig, WagmiConfig } from 'wagmi';
import { configureChains, WagmiConfig } from 'wagmi';

import config from 'configs/app';
import colors from 'theme/foundations/colors';
import { BODY_TYPEFACE } from 'theme/foundations/typography';
import zIndices from 'theme/foundations/zIndices';

const feature = config.features.blockchainInteraction;

Expand Down Expand Up @@ -41,58 +43,71 @@ const getConfig = () => {
},
};

const chains = [ currentChain ];

const { publicClient } = configureChains(chains, [
jsonRpcProvider({
rpc: () => ({
http: config.chain.rpcUrl || '',
const { chains } = configureChains(
[ currentChain ],
[
jsonRpcProvider({
rpc: () => ({
http: config.chain.rpcUrl || '',
}),
}),
}),
]);
const wagmiConfig = createConfig({
autoConnect: true,
connectors: w3mConnectors({ projectId: feature.walletConnect.projectId, chains }),
publicClient,
],
);

const wagmiConfig = defaultWagmiConfig({
chains,
projectId: feature.walletConnect.projectId,
});

createWeb3Modal({
wagmiConfig,
projectId: feature.walletConnect.projectId,
chains,
themeVariables: {
'--w3m-font-family': `${ BODY_TYPEFACE }, sans-serif`,
'--w3m-accent': colors.blue[600],
'--w3m-border-radius-master': '2px',
'--w3m-z-index': zIndices.modal,
},
});
const ethereumClient = new EthereumClient(wagmiConfig, chains);

return { wagmiConfig, ethereumClient };
return { wagmiConfig };
} catch (error) {
return { wagmiConfig: undefined, ethereumClient: undefined };
return { };
}
};

const { wagmiConfig, ethereumClient } = getConfig();
const { wagmiConfig } = getConfig();

interface Props {
children: React.ReactNode;
fallback?: JSX.Element | (() => JSX.Element);
}

const Web3ModalProvider = ({ children, fallback }: Props) => {
const modalZIndex = useToken<string>('zIndices', 'modal');
const web3ModalTheme = useColorModeValue('light', 'dark');
const Fallback = ({ children, fallback }: Props) => {
return typeof fallback === 'function' ? fallback() : (fallback || <>{ children }</>); // eslint-disable-line react/jsx-no-useless-fragment
};

const Provider = ({ children, fallback }: Props) => {
const { colorMode } = useColorMode();
const { setThemeMode } = useWeb3ModalTheme();

if (!wagmiConfig || !ethereumClient || !feature.isEnabled) {
return typeof fallback === 'function' ? fallback() : (fallback || <>{ children }</>); // eslint-disable-line react/jsx-no-useless-fragment
React.useEffect(() => {
setThemeMode(colorMode);
}, [ colorMode, setThemeMode ]);

// not really necessary, but we have to make typescript happy
if (!wagmiConfig || !feature.isEnabled) {
return <Fallback fallback={ fallback }>{ children }</Fallback>;
}

return (
<>
<WagmiConfig config={ wagmiConfig }>
{ children }
</WagmiConfig>
<Web3Modal
projectId={ feature.walletConnect.projectId }
ethereumClient={ ethereumClient }
themeMode={ web3ModalTheme }
themeVariables={{
'--w3m-z-index': modalZIndex,
}}
/>
</>
<WagmiConfig config={ wagmiConfig }>
{ children }
</WagmiConfig>
);
};

const Web3ModalProvider = wagmiConfig && feature.isEnabled ? Provider : Fallback;

export default Web3ModalProvider;
4 changes: 3 additions & 1 deletion ui/snippets/topBar/TopBar.pw.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ test('default view +@dark-mode +@mobile', async({ mount, page }) => {
</TestApp>,
);

await component.getByLabel('color mode switch').click();
await component.getByText(/gwei/i).hover();
await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 1500, height: 220 } });

await component.getByLabel('color mode switch').click();
await expect(page).toHaveScreenshot({ clip: { x: 0, y: 0, width: 1500, height: 220 } });
});
35 changes: 32 additions & 3 deletions ui/snippets/topBar/TopBarStats.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import { Flex, Skeleton } from '@chakra-ui/react';
import { Flex, LightMode, Link, Skeleton, Tooltip, chakra, useDisclosure } from '@chakra-ui/react';
import React from 'react';

import config from 'configs/app';
import useApiQuery from 'lib/api/useApiQuery';
import { HOMEPAGE_STATS } from 'stubs/stats';
import GasInfoTooltipContent from 'ui/shared/GasInfoTooltipContent/GasInfoTooltipContent';
import TextSeparator from 'ui/shared/TextSeparator';

const TopBarStats = () => {
// have to implement controlled tooltip because of the issue - https://github.com/chakra-ui/chakra-ui/issues/7107
const { isOpen, onOpen, onToggle, onClose } = useDisclosure();

const handleClick = React.useCallback((event: React.MouseEvent) => {
event.stopPropagation();
onToggle();
}, [ onToggle ]);

const { data, isPlaceholderData, isError } = useApiQuery('homepage_stats', {
queryOptions: {
placeholderData: HOMEPAGE_STATS,
Expand All @@ -26,14 +35,34 @@ const TopBarStats = () => {
>
{ data?.coin_price && (
<Skeleton isLoaded={ !isPlaceholderData }>
<span>{ config.chain.governanceToken.symbol || config.chain.currency.symbol }: </span>
<chakra.span color="text_secondary">{ config.chain.governanceToken.symbol || config.chain.currency.symbol } </chakra.span>
<span>${ Number(data.coin_price).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 6 }) }</span>
</Skeleton>
) }
{ data?.coin_price && config.UI.homepage.showGasTracker && <TextSeparator color="divider"/> }
{ data?.gas_prices && config.UI.homepage.showGasTracker && (
<Skeleton isLoaded={ !isPlaceholderData }>
<span>Gas: { data.gas_prices.average } Gwei</span>
<chakra.span color="text_secondary">Gas </chakra.span>
<LightMode>
<Tooltip
label={ <GasInfoTooltipContent gasPrices={ data.gas_prices }/> }
hasArrow={ false }
borderRadius="md"
offset={ [ 0, 16 ] }
bgColor="blackAlpha.900"
p={ 0 }
isOpen={ isOpen }
>
<Link
_hover={{ textDecoration: 'none', color: 'link_hovered' }}
onClick={ handleClick }
onMouseEnter={ onOpen }
onMouseLeave={ onClose }
>
{ data.gas_prices.average } Gwei
</Link>
</Tooltip>
</LightMode>
</Skeleton>
) }
</Flex>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions ui/snippets/walletMenu/useWallet.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { useWeb3Modal } from '@web3modal/react';
import { useWeb3Modal, useWeb3ModalState } from '@web3modal/wagmi/react';
import React from 'react';
import { useAccount, useDisconnect } from 'wagmi';

import * as mixpanel from 'lib/mixpanel/index';

export default function useWallet() {
const { open, isOpen } = useWeb3Modal();
const { open } = useWeb3Modal();
const { open: isOpen } = useWeb3ModalState();
const { disconnect } = useDisconnect();
const [ isModalOpening, setIsModalOpening ] = React.useState(false);
const [ isClientLoaded, setIsClientLoaded ] = React.useState(false);
Expand Down
Loading

0 comments on commit f8d8b7f

Please sign in to comment.