From 16383f145ccec4b76315218210a00663513d4092 Mon Sep 17 00:00:00 2001 From: Chris <krzysztof@ssvlabs.io> Date: Mon, 1 Jul 2024 21:18:23 +0200 Subject: [PATCH] Implementation of Network Switch and Clean up of Prater & Goerli --- .env.development | 2 +- public/images/networks/holesky_dark.svg | 15 ++++ public/images/networks/holesky_light.svg | 15 ++++ public/images/networks/mainnet_dark.svg | 15 ++++ public/images/networks/mainnet_light.svg | 15 ++++ .../common/components/AppBar/AppBar.styles.ts | 13 +--- src/app/common/components/AppBar/AppBar.tsx | 6 +- .../components/NetworkIcon/NetworkIcon.tsx | 16 ++++ .../common/components/NetworkIcon/index.ts | 1 + .../NetworkSelect/NetworkSelect.tsx | 77 +++++++++++++++++++ .../NetworkSelect/NeworkSelect.styles.ts | 57 ++++++++++++++ .../common/components/NetworkSelect/index.tsx | 1 + src/lib/utils/ChainService.ts | 4 - 13 files changed, 220 insertions(+), 17 deletions(-) create mode 100644 public/images/networks/holesky_dark.svg create mode 100644 public/images/networks/holesky_light.svg create mode 100644 public/images/networks/mainnet_dark.svg create mode 100644 public/images/networks/mainnet_light.svg create mode 100644 src/app/common/components/NetworkIcon/NetworkIcon.tsx create mode 100644 src/app/common/components/NetworkIcon/index.ts create mode 100644 src/app/common/components/NetworkSelect/NetworkSelect.tsx create mode 100644 src/app/common/components/NetworkSelect/NeworkSelect.styles.ts create mode 100644 src/app/common/components/NetworkSelect/index.tsx diff --git a/.env.development b/.env.development index 4e536bf..2e0abeb 100644 --- a/.env.development +++ b/.env.development @@ -1,5 +1,5 @@ REACT_APP_DEBUG=true -REACT_APP_API_BASE_URL=https://api.stage.ssv.network/api/v4/prater +REACT_APP_API_BASE_URL=https://api.stage.ssv.network/api/v4/holesky REACT_APP_LINK_SSV_WEBAPP=https://app.stage.ssv.network/ REACT_APP_GOOGLE_TAG_SECRET= REACT_APP_GOOGLE_TAG_URL= diff --git a/public/images/networks/holesky_dark.svg b/public/images/networks/holesky_dark.svg new file mode 100644 index 0000000..82117cb --- /dev/null +++ b/public/images/networks/holesky_dark.svg @@ -0,0 +1,15 @@ +<svg width="16" height="24" viewBox="0 0 16 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g id="Frame" clip-path="url(#clip0_21118_537)"> +<path id="Vector" opacity="0.54" d="M7.9704 0V8.9L0.604253 12.2225L7.9704 0Z" fill="#76C8FB"/> +<path id="Vector_2" opacity="0.7" d="M7.9704 0L15.3367 12.2225L7.9704 8.9V0Z" fill="#76C8FB"/> +<path id="Vector_3" opacity="0.54" d="M7.97046 17.9714V23.9999L0.599816 13.6195L7.97046 17.9714Z" fill="#76C8FB"/> +<path id="Vector_4" opacity="0.7" d="M7.9704 23.9999V17.9714L15.3367 13.6195L7.9704 23.9999Z" fill="#76C8FB"/> +<path id="Vector_5" opacity="0.4" d="M7.97046 16.5767L0.604313 12.2225L7.97046 8.90002V16.5767Z" fill="#76C8FB"/> +<path id="Vector_6" opacity="0.5" d="M15.3367 12.2225L7.9704 16.5767V8.90002L15.3367 12.2225Z" fill="#76C8FB"/> +</g> +<defs> +<clipPath id="clip0_21118_537"> +<rect width="14.7369" height="23.9999" fill="white" transform="matrix(-1 0 0 1 15.3367 0)"/> +</clipPath> +</defs> +</svg> diff --git a/public/images/networks/holesky_light.svg b/public/images/networks/holesky_light.svg new file mode 100644 index 0000000..dc674a0 --- /dev/null +++ b/public/images/networks/holesky_light.svg @@ -0,0 +1,15 @@ +<svg width="16" height="24" viewBox="0 0 16 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g id="Frame" clip-path="url(#clip0_21118_1191)"> +<path id="Vector" opacity="0.54" d="M7.9704 0V8.9L0.604253 12.2225L7.9704 0Z" fill="#76C8FB"/> +<path id="Vector_2" opacity="0.7" d="M7.9704 0L15.3367 12.2225L7.9704 8.9V0Z" fill="#76C8FB"/> +<path id="Vector_3" opacity="0.54" d="M7.97046 17.9714V23.9999L0.599816 13.6195L7.97046 17.9714Z" fill="#76C8FB"/> +<path id="Vector_4" opacity="0.7" d="M7.9704 23.9999V17.9714L15.3367 13.6195L7.9704 23.9999Z" fill="#76C8FB"/> +<path id="Vector_5" opacity="0.4" d="M7.97046 16.5767L0.604313 12.2225L7.97046 8.90002V16.5767Z" fill="#76C8FB"/> +<path id="Vector_6" opacity="0.5" d="M15.3367 12.2225L7.9704 16.5767V8.90002L15.3367 12.2225Z" fill="#76C8FB"/> +</g> +<defs> +<clipPath id="clip0_21118_1191"> +<rect width="14.7369" height="23.9999" fill="white" transform="matrix(-1 0 0 1 15.3367 0)"/> +</clipPath> +</defs> +</svg> diff --git a/public/images/networks/mainnet_dark.svg b/public/images/networks/mainnet_dark.svg new file mode 100644 index 0000000..4b924d4 --- /dev/null +++ b/public/images/networks/mainnet_dark.svg @@ -0,0 +1,15 @@ +<svg width="16" height="24" viewBox="0 0 16 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g id="Frame" clip-path="url(#clip0_21111_1165)"> +<path id="Vector" opacity="0.6" d="M7.9704 0V8.9L0.604252 12.2225L7.9704 0Z" fill="#011627"/> +<path id="Vector_2" opacity="0.8" d="M7.9704 0L15.3367 12.2225L7.9704 8.9V0Z" fill="#011627"/> +<path id="Vector_3" opacity="0.6" d="M7.97046 17.9715V23.9999L0.599816 13.6195L7.97046 17.9715Z" fill="#011627"/> +<path id="Vector_4" opacity="0.8" d="M7.9704 23.9999V17.9715L15.3367 13.6195L7.9704 23.9999Z" fill="#011627"/> +<path id="Vector_5" opacity="0.8" d="M7.97046 16.5767L0.604313 12.2225L7.97046 8.90002V16.5767Z" fill="#011627"/> +<path id="Vector_6" d="M15.3367 12.2225L7.9704 16.5767V8.90002L15.3367 12.2225Z" fill="#011627"/> +</g> +<defs> +<clipPath id="clip0_21111_1165"> +<rect width="14.7369" height="23.9999" fill="white" transform="matrix(-1 0 0 1 15.3367 0)"/> +</clipPath> +</defs> +</svg> diff --git a/public/images/networks/mainnet_light.svg b/public/images/networks/mainnet_light.svg new file mode 100644 index 0000000..7be232b --- /dev/null +++ b/public/images/networks/mainnet_light.svg @@ -0,0 +1,15 @@ +<svg width="16" height="24" viewBox="0 0 16 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g id="Frame" clip-path="url(#clip0_21111_511)"> +<path id="Vector" opacity="0.64" d="M7.96613 0V8.9L15.3323 12.2225L7.96613 0Z" fill="#FDFEFE"/> +<path id="Vector_2" opacity="0.84" d="M7.96613 0L0.599792 12.2225L7.96613 8.9V0Z" fill="#FDFEFE"/> +<path id="Vector_3" opacity="0.64" d="M7.96606 17.9714V23.9999L15.3367 13.6195L7.96606 17.9714Z" fill="#FDFEFE"/> +<path id="Vector_4" opacity="0.84" d="M7.96613 23.9999V17.9714L0.599792 13.6195L7.96613 23.9999Z" fill="#FDFEFE"/> +<path id="Vector_5" opacity="0.84" d="M7.96606 16.5767L15.3322 12.2225L7.96606 8.90002V16.5767Z" fill="#FDFEFE"/> +<path id="Vector_6" d="M0.599792 12.2225L7.96613 16.5767V8.90002L0.599792 12.2225Z" fill="#FDFEFE"/> +</g> +<defs> +<clipPath id="clip0_21111_511"> +<rect width="14.7369" height="23.9999" fill="white" transform="translate(0.599792)"/> +</clipPath> +</defs> +</svg> diff --git a/src/app/common/components/AppBar/AppBar.styles.ts b/src/app/common/components/AppBar/AppBar.styles.ts index 3731bc1..6e7cd7c 100644 --- a/src/app/common/components/AppBar/AppBar.styles.ts +++ b/src/app/common/components/AppBar/AppBar.styles.ts @@ -132,6 +132,9 @@ export const useStyles = makeStyles((theme) => ({ textDecoration: 'none', }, }, + networkSwitchWrapper: { + paddingRight: 12, + }, drawer: { '& > .MuiDrawer-paper': { backgroundColor: '#A1ABBE', @@ -167,14 +170,4 @@ export const useStyles = makeStyles((theme) => ({ backgroundColor: 'lightgreen', }, }, - PraterButton: { - backgroundColor: theme.colors.tint80, - color: theme.colors.primary, - '&:hover': { - cursor: 'default', - }, - '&:active': { - backgroundColor: theme.colors.tint80, - }, - }, })); diff --git a/src/app/common/components/AppBar/AppBar.tsx b/src/app/common/components/AppBar/AppBar.tsx index b9deded..0142a27 100644 --- a/src/app/common/components/AppBar/AppBar.tsx +++ b/src/app/common/components/AppBar/AppBar.tsx @@ -25,6 +25,7 @@ import { useStyles as useAppStyles } from '~app/components/Styles'; import ApplicationStore from '~app/common/stores/Application.store'; import DarkModeSwitcher from '~app/common/components/DarkModeSwitcher'; import Grid from '@material-ui/core/Grid'; +import NetworkSelect from '~app/common/components/NetworkSelect'; const DrawerButtonsContainers = styled.div` font-size: 12px; @@ -165,11 +166,12 @@ const AppBarComponent = () => { display={{ xs: 'none', sm: 'none', md: 'none', lg: 'block' }}> <div className={classes.toolbarButtons}> {!isOverviewPage() && <SmartSearch placeholder={'Search...'} inAppBar />} + <div className={classes.networkSwitchWrapper}> + <NetworkSelect /> + </div> <Link href={joinSsvLink} target="_blank"> <Button disable={false} type={'primary'} text={'Join SSV Network'} /> </Link> - <Button disable={false} extendClass={classes.PraterButton} type={'secondary'} - text={`${capitalize(currentNetwork)}`} /> <DarkModeSwitcher style={{ marginLeft: 'auto', marginRight: 0, minWidth: 'auto', width: 70 }} /> </div> </Box> diff --git a/src/app/common/components/NetworkIcon/NetworkIcon.tsx b/src/app/common/components/NetworkIcon/NetworkIcon.tsx new file mode 100644 index 0000000..683758a --- /dev/null +++ b/src/app/common/components/NetworkIcon/NetworkIcon.tsx @@ -0,0 +1,16 @@ +import React, { ImgHTMLAttributes } from 'react'; +import { useStores } from '~app/hooks/useStores'; +import ApplicationStore from '~app/common/stores/Application.store'; +import { EChain } from '~lib/utils/ChainService'; + +const NetworkIcon = (props: { network: EChain } & ImgHTMLAttributes<unknown>) => { + const stores = useStores(); + const applicationStore: ApplicationStore = stores.Application; + const imgSrc = `/images/networks/${props.network}${applicationStore.isDarkMode ? '_light' : '_dark'}.svg`; + + return ( + <img width="24" height="24" src={imgSrc} alt={props.network} {...props} /> + ); +}; + +export default NetworkIcon; diff --git a/src/app/common/components/NetworkIcon/index.ts b/src/app/common/components/NetworkIcon/index.ts new file mode 100644 index 0000000..3f03632 --- /dev/null +++ b/src/app/common/components/NetworkIcon/index.ts @@ -0,0 +1 @@ +export { default } from './NetworkIcon'; diff --git a/src/app/common/components/NetworkSelect/NetworkSelect.tsx b/src/app/common/components/NetworkSelect/NetworkSelect.tsx new file mode 100644 index 0000000..9821775 --- /dev/null +++ b/src/app/common/components/NetworkSelect/NetworkSelect.tsx @@ -0,0 +1,77 @@ +import React, { ChangeEvent } from 'react'; +import Box from '@material-ui/core/Box'; +import MenuItem from '@material-ui/core/MenuItem'; +import Select from '@material-ui/core/Select'; +import chainService, { EChain } from '~lib/utils/ChainService'; +import NetworkIcon from '~app/common/components/NetworkIcon'; +import { useStyles } from './NeworkSelect.styles'; +import { KeyboardArrowDown } from '@material-ui/icons'; + +const availableNetworks = [EChain.Ethereum, EChain.Holesky]; + +const networkToConfigMap = { + [EChain.Ethereum]: { + url: 'https://explorer.ssv.network', + label: 'Ethereum Mainnet', + }, + [EChain.Holesky]: { + url: 'https://holesky.explorer.ssv.network', + label: 'Holesky Testnet', + }, +}; + +export default function NetworkSelect() { + const currentNetwork: EChain = chainService().getNetwork() as EChain; + + const classes = useStyles(); + + const handleChange = ( + event: ChangeEvent<{ name?: string; value: unknown }>, + ) => { + const urlToGo = networkToConfigMap[event.target.value as EChain].url; + if (urlToGo) { + window.open(urlToGo, '_self'); + } + }; + + return ( + <Box className={classes.Wrapper}> + <Select + variant="standard" + autoWidth + value={currentNetwork} + onChange={handleChange} + IconComponent={KeyboardArrowDown} + className={classes.Root} + classes={{ + select: classes.Select, + icon: classes.Icon, + }} + MenuProps={{ + anchorOrigin: { + vertical: 'bottom', + horizontal: -16, + }, + transformOrigin: { + vertical: 'top', + horizontal: 'left', + }, + getContentAnchorEl: null, + classes: { + paper: classes.ItemListWrapper, + list: classes.ItemList, + }, + }} + > + {availableNetworks.map((net) => ( + <MenuItem value={net}> + <div className={classes.ItemWrapper}> + <NetworkIcon network={net} className={classes.ItemIcon} /> + {networkToConfigMap[net].label} + </div> + </MenuItem> + ))} + </Select> + </Box> + ); +} diff --git a/src/app/common/components/NetworkSelect/NeworkSelect.styles.ts b/src/app/common/components/NetworkSelect/NeworkSelect.styles.ts new file mode 100644 index 0000000..2af6be1 --- /dev/null +++ b/src/app/common/components/NetworkSelect/NeworkSelect.styles.ts @@ -0,0 +1,57 @@ +import { makeStyles } from '@material-ui/core/styles'; + +export const useStyles = makeStyles((theme) => ({ + Wrapper: { + borderRadius: 8, + background: theme.colors.gray0, + padding: '0 16px', + }, + Root: { + minWidth: 205, + '&:after, &:before': { + display: 'none !important', + }, + }, + Select: { + backgroundColor: 'initial !important', + }, + Icon: { + boxSizing: 'content-box', + width: 24, + height: 24, + }, + + ItemListWrapper: { + width: 240, + boxShadow: 'none', + border: `1px solid ${theme.colors.gray20}`, + }, + + ItemList: { + backgroundColor: `${theme.colors.white}`, + padding: 0, + '& li:hover': { + backgroundColor: `${theme.colors.gray20} !important`, + }, + '& li': { + backgroundColor: `${theme.colors.white} !important`, + }, + '& li:not(:last-child)': { + borderBottom: `1px solid ${theme.colors.gray20}`, + }, + }, + + ItemWrapper: { + display: 'flex', + 'align-items': 'center', + padding: '6px 0', + paddingRight: '6px', + + fontSize: 16, + fontWeight: 600, + }, + ItemIcon: { + boxSizing: 'content-box', + paddingRight: '12px', + }, +})); diff --git a/src/app/common/components/NetworkSelect/index.tsx b/src/app/common/components/NetworkSelect/index.tsx new file mode 100644 index 0000000..e9ee2d3 --- /dev/null +++ b/src/app/common/components/NetworkSelect/index.tsx @@ -0,0 +1 @@ +export { default } from './NetworkSelect'; diff --git a/src/lib/utils/ChainService.ts b/src/lib/utils/ChainService.ts index af4d2f3..767074c 100644 --- a/src/lib/utils/ChainService.ts +++ b/src/lib/utils/ChainService.ts @@ -4,15 +4,11 @@ import config from '~app/common/config'; export enum EChain { Holesky = 'holesky', Ethereum = 'mainnet', // ethereum - Goerli = 'goerli', - Prater = 'prater', } export const CHAIN = { HOLESKY: EChain.Holesky, ETHEREUM: EChain.Ethereum, - PRATER: EChain.Prater, // Goerli was merged with Prater. The combined network retained the Goerli name post-merge. - GOERLI: EChain.Goerli, }; function extractChain(apiUrl: string): string {