Commit cd6c555d authored by Max Alekseenko's avatar Max Alekseenko

add swap button

parent 037499a6
...@@ -19,6 +19,7 @@ export { default as sentry } from './sentry'; ...@@ -19,6 +19,7 @@ export { default as sentry } from './sentry';
export { default as sol2uml } from './sol2uml'; export { default as sol2uml } from './sol2uml';
export { default as stats } from './stats'; export { default as stats } from './stats';
export { default as suave } from './suave'; export { default as suave } from './suave';
export { default as swapButton } from './swapButton';
export { default as txInterpretation } from './txInterpretation'; export { default as txInterpretation } from './txInterpretation';
export { default as userOps } from './userOps'; export { default as userOps } from './userOps';
export { default as verifiedTokens } from './verifiedTokens'; export { default as verifiedTokens } from './verifiedTokens';
......
import type { Feature } from './types';
import { getEnvValue } from '../utils';
const appUrl = getEnvValue('NEXT_PUBLIC_SWAP_BUTTON_URL');
const title = 'Swap button';
const config: Feature<{ appUrl: string }> = (() => {
if (appUrl) {
return Object.freeze({
title,
isEnabled: true,
appUrl,
});
}
return Object.freeze({
title,
isEnabled: false,
});
})();
export default config;
...@@ -52,3 +52,4 @@ NEXT_PUBLIC_STATS_API_HOST=https://stats-goerli.k8s-dev.blockscout.com ...@@ -52,3 +52,4 @@ NEXT_PUBLIC_STATS_API_HOST=https://stats-goerli.k8s-dev.blockscout.com
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.k8s-dev.blockscout.com NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.k8s-dev.blockscout.com
NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info-test.k8s-dev.blockscout.com NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info-test.k8s-dev.blockscout.com
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs-test.k8s-dev.blockscout.com NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs-test.k8s-dev.blockscout.com
NEXT_PUBLIC_SWAP_BUTTON_URL=uniswap
...@@ -467,6 +467,7 @@ const schema = yup ...@@ -467,6 +467,7 @@ const schema = yup
NEXT_PUBLIC_OG_IMAGE_URL: yup.string().test(urlTest), NEXT_PUBLIC_OG_IMAGE_URL: yup.string().test(urlTest),
NEXT_PUBLIC_IS_SUAVE_CHAIN: yup.boolean(), NEXT_PUBLIC_IS_SUAVE_CHAIN: yup.boolean(),
NEXT_PUBLIC_HAS_USER_OPS: yup.boolean(), NEXT_PUBLIC_HAS_USER_OPS: yup.boolean(),
NEXT_PUBLIC_SWAP_BUTTON_URL: yup.string(),
// 6. External services envs // 6. External services envs
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID: yup.string(), NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID: yup.string(),
......
...@@ -53,3 +53,4 @@ NEXT_PUBLIC_VIEWS_TX_HIDDEN_FIELDS=['value','fee_currency','gas_price','tx_fee', ...@@ -53,3 +53,4 @@ NEXT_PUBLIC_VIEWS_TX_HIDDEN_FIELDS=['value','fee_currency','gas_price','tx_fee',
NEXT_PUBLIC_VISUALIZE_API_HOST=https://example.com NEXT_PUBLIC_VISUALIZE_API_HOST=https://example.com
NEXT_PUBLIC_WEB3_DISABLE_ADD_TOKEN_TO_WALLET=false NEXT_PUBLIC_WEB3_DISABLE_ADD_TOKEN_TO_WALLET=false
NEXT_PUBLIC_WEB3_WALLETS=['coinbase','metamask','token_pocket'] NEXT_PUBLIC_WEB3_WALLETS=['coinbase','metamask','token_pocket']
NEXT_PUBLIC_SWAP_BUTTON_URL=uniswap
...@@ -195,6 +195,7 @@ frontend: ...@@ -195,6 +195,7 @@ frontend:
NEXT_PUBLIC_L1_BASE_URL: https://eth-goerli.blockscout.com/ NEXT_PUBLIC_L1_BASE_URL: https://eth-goerli.blockscout.com/
NEXT_PUBLIC_OPTIMISTIC_L2_WITHDRAWAL_URL: https://app.optimism.io/bridge/withdraw NEXT_PUBLIC_OPTIMISTIC_L2_WITHDRAWAL_URL: https://app.optimism.io/bridge/withdraw
NEXT_PUBLIC_GRAPHIQL_TRANSACTION: 0x4a0ed8ddf751a7cb5297f827699117b0f6d21a0b2907594d300dc9fed75c7e62 NEXT_PUBLIC_GRAPHIQL_TRANSACTION: 0x4a0ed8ddf751a7cb5297f827699117b0f6d21a0b2907594d300dc9fed75c7e62
NEXT_PUBLIC_SWAP_BUTTON_URL: sushiswap
envFromSecret: envFromSecret:
NEXT_PUBLIC_AUTH0_CLIENT_ID: ref+vault://deployment-values/blockscout/dev/front-main?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_AUTH0_CLIENT_ID NEXT_PUBLIC_AUTH0_CLIENT_ID: ref+vault://deployment-values/blockscout/dev/front-main?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_AUTH0_CLIENT_ID
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID: ref+vault://deployment-values/blockscout/dev/front-main?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID: ref+vault://deployment-values/blockscout/dev/front-main?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID
......
...@@ -163,6 +163,7 @@ frontend: ...@@ -163,6 +163,7 @@ frontend:
NEXT_PUBLIC_WEB3_WALLETS: "['token_pocket','coinbase','metamask']" NEXT_PUBLIC_WEB3_WALLETS: "['token_pocket','coinbase','metamask']"
NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES: "[{'name':'LooksRare','collection_url':'https://goerli.looksrare.org/collections/{hash}','instance_url':'https://goerli.looksrare.org/collections/{hash}/{id}','logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/nft-marketplace-logos/looks-rare.png'}]" NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES: "[{'name':'LooksRare','collection_url':'https://goerli.looksrare.org/collections/{hash}','instance_url':'https://goerli.looksrare.org/collections/{hash}/{id}','logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/nft-marketplace-logos/looks-rare.png'}]"
NEXT_PUBLIC_CONTRACT_CODE_IDES: "[{'title':'Remix IDE','url':'https://remix.blockscout.com/?address={hash}&blockscout=eth-goerli.blockscout.com','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]" NEXT_PUBLIC_CONTRACT_CODE_IDES: "[{'title':'Remix IDE','url':'https://remix.blockscout.com/?address={hash}&blockscout=eth-goerli.blockscout.com','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]"
NEXT_PUBLIC_SWAP_BUTTON_URL: uniswap
envFromSecret: envFromSecret:
NEXT_PUBLIC_SENTRY_DSN: ref+vault://deployment-values/blockscout/dev/front-main?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_SENTRY_DSN NEXT_PUBLIC_SENTRY_DSN: ref+vault://deployment-values/blockscout/dev/front-main?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_SENTRY_DSN
SENTRY_CSP_REPORT_URI: ref+vault://deployment-values/blockscout/dev/front-main?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/SENTRY_CSP_REPORT_URI SENTRY_CSP_REPORT_URI: ref+vault://deployment-values/blockscout/dev/front-main?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/SENTRY_CSP_REPORT_URI
......
...@@ -70,6 +70,7 @@ frontend: ...@@ -70,6 +70,7 @@ frontend:
NEXT_PUBLIC_L1_BASE_URL: https://blockscout-main.k8s-dev.blockscout.com NEXT_PUBLIC_L1_BASE_URL: https://blockscout-main.k8s-dev.blockscout.com
NEXT_PUBLIC_GRAPHIQL_TRANSACTION: 0x4a0ed8ddf751a7cb5297f827699117b0f6d21a0b2907594d300dc9fed75c7e62 NEXT_PUBLIC_GRAPHIQL_TRANSACTION: 0x4a0ed8ddf751a7cb5297f827699117b0f6d21a0b2907594d300dc9fed75c7e62
NEXT_PUBLIC_USE_NEXT_JS_PROXY: true NEXT_PUBLIC_USE_NEXT_JS_PROXY: true
NEXT_PUBLIC_SWAP_BUTTON_URL: sushiswap
envFromSecret: envFromSecret:
NEXT_PUBLIC_SENTRY_DSN: ref+vault://deployment-values/blockscout/dev/review-l2?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_SENTRY_DSN NEXT_PUBLIC_SENTRY_DSN: ref+vault://deployment-values/blockscout/dev/review-l2?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_SENTRY_DSN
SENTRY_CSP_REPORT_URI: ref+vault://deployment-values/blockscout/dev/review-l2?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/SENTRY_CSP_REPORT_URI SENTRY_CSP_REPORT_URI: ref+vault://deployment-values/blockscout/dev/review-l2?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/SENTRY_CSP_REPORT_URI
......
...@@ -76,6 +76,7 @@ frontend: ...@@ -76,6 +76,7 @@ frontend:
NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES: "[{'name':'LooksRare','collection_url':'https://goerli.looksrare.org/collections/{hash}','instance_url':'https://goerli.looksrare.org/collections/{hash}/{id}','logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/nft-marketplace-logos/looks-rare.png'}]" NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES: "[{'name':'LooksRare','collection_url':'https://goerli.looksrare.org/collections/{hash}','instance_url':'https://goerli.looksrare.org/collections/{hash}/{id}','logo_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/nft-marketplace-logos/looks-rare.png'}]"
NEXT_PUBLIC_HAS_USER_OPS: true NEXT_PUBLIC_HAS_USER_OPS: true
NEXT_PUBLIC_CONTRACT_CODE_IDES: "[{'title':'Remix IDE','url':'https://remix.blockscout.com/?address={hash}&blockscout=eth-goerli.blockscout.com','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]" NEXT_PUBLIC_CONTRACT_CODE_IDES: "[{'title':'Remix IDE','url':'https://remix.blockscout.com/?address={hash}&blockscout=eth-goerli.blockscout.com','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]"
NEXT_PUBLIC_SWAP_BUTTON_URL: uniswap
envFromSecret: envFromSecret:
NEXT_PUBLIC_SENTRY_DSN: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_SENTRY_DSN NEXT_PUBLIC_SENTRY_DSN: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/NEXT_PUBLIC_SENTRY_DSN
SENTRY_CSP_REPORT_URI: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/SENTRY_CSP_REPORT_URI SENTRY_CSP_REPORT_URI: ref+vault://deployment-values/blockscout/dev/review?token_env=VAULT_TOKEN&address=https://vault.k8s.blockscout.com#/SENTRY_CSP_REPORT_URI
......
...@@ -54,6 +54,7 @@ Please be aware that all environment variables prefixed with `NEXT_PUBLIC_` will ...@@ -54,6 +54,7 @@ Please be aware that all environment variables prefixed with `NEXT_PUBLIC_` will
- [SUAVE chain](ENVS.md#suave-chain) - [SUAVE chain](ENVS.md#suave-chain)
- [Sentry error monitoring](ENVS.md#sentry-error-monitoring) - [Sentry error monitoring](ENVS.md#sentry-error-monitoring)
- [OpenTelemetry](ENVS.md#opentelemetry) - [OpenTelemetry](ENVS.md#opentelemetry)
- [Swap button](ENVS.md#swap-button)
- [3rd party services configuration](ENVS.md#external-services-configuration) - [3rd party services configuration](ENVS.md#external-services-configuration)
&nbsp; &nbsp;
...@@ -600,6 +601,16 @@ OpenTelemetry SDK for Node.js app could be enabled by passing `OTEL_SDK_ENABLED= ...@@ -600,6 +601,16 @@ OpenTelemetry SDK for Node.js app could be enabled by passing `OTEL_SDK_ENABLED=
&nbsp; &nbsp;
### Swap button
If the feature is enabled, a Swap button will be displayed at the top of the explorer page, which will take you to the specified application in the marketplace or to an external site.
| Variable | Type| Description | Compulsoriness | Default value | Example value |
| --- | --- | --- | --- | --- | --- |
| NEXT_PUBLIC_SWAP_BUTTON_URL | `string` | Application ID in the marketplace or website URL | - | - | `uniswap` |
&nbsp;
## External services configuration ## External services configuration
### Google ReCaptcha ### Google ReCaptcha
......
<svg viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.98 5.36c-.387 0-.645.258-.645.645a4.485 4.485 0 0 1-4.512 4.512h-.451c-.13 0-.194 0-.322-.064-.13 0-.194-.065-.323-.065-.064 0-.129-.064-.193-.064-.451-.129-.903-.387-1.29-.645-.064-.064-.128-.064-.128-.129-.065-.064-.13-.129-.194-.129-.129-.064-.258-.193-.322-.257l-.129-.13 1.16-.193a.669.669 0 0 0 .516-.773.669.669 0 0 0-.773-.516l-2.128.387-.515.129a.435.435 0 0 0-.387.258 1.195 1.195 0 0 0-.13.45l.517 2.708c.064.323.322.516.644.516h.13a.669.669 0 0 0 .515-.774l-.194-1.095c.13.128.323.257.452.386h.064c.065.065.129.13.193.13.13.128.258.193.452.257.129.258.322.322.515.451h.065c.064.065.193.065.322.13.258.064.516.128.71.193.128 0 .257.064.386.064h.774a5.778 5.778 0 0 0 5.801-5.801c.065-.323-.258-.58-.58-.58ZM.73 6.65c.387 0 .645-.258.645-.645a4.485 4.485 0 0 1 4.513-4.512h.45c.13 0 .194 0 .323.064.13 0 .194.065.323.065.064 0 .128.064.193.064.451.129.902.322 1.29.645.064.064.128.064.193.129.064.064.129.064.193.128.064.065.129.194.258.258l.129.13-1.16.193a.669.669 0 0 0-.516.773c.064.322.322.516.644.516h.13l2.707-.516a.669.669 0 0 0 .515-.773L11.045.526A.669.669 0 0 0 10.27.01a.669.669 0 0 0-.516.773L9.95 1.88c-.13-.129-.322-.322-.451-.386h-.065c-.064-.065-.129-.13-.193-.13-.13-.128-.258-.193-.451-.322-.194-.129-.387-.193-.58-.322h-.065C8.079.655 7.95.655 7.822.59a10.574 10.574 0 0 1-.71-.193c-.128 0-.257-.065-.386-.065h-.773A5.778 5.778 0 0 0 .15 6.134c-.064.258.194.516.58.516Z" fill="currentColor"/>
</svg>
...@@ -70,7 +70,7 @@ Type extends EventTypes.VERIFY_TOKEN ? { ...@@ -70,7 +70,7 @@ Type extends EventTypes.VERIFY_TOKEN ? {
'Action': 'Form opened' | 'Submit'; 'Action': 'Form opened' | 'Submit';
} : } :
Type extends EventTypes.WALLET_CONNECT ? { Type extends EventTypes.WALLET_CONNECT ? {
'Source': 'Header' | 'Smart contracts'; 'Source': 'Header' | 'Smart contracts' | 'Swap button';
'Status': 'Started' | 'Connected'; 'Status': 'Started' | 'Connected';
} : } :
Type extends EventTypes.WALLET_ACTION ? { Type extends EventTypes.WALLET_ACTION ? {
......
import type { NextRouter } from 'next/router';
export default function removeQueryParam(router: NextRouter, param: string) {
const { pathname, query } = router;
delete router.query[param];
router.replace({ pathname, query }, undefined, { shallow: true });
}
import type { NextRouter } from 'next/router';
export default function updateQueryParam(router: NextRouter, param: string, newValue: string) {
const { pathname, query } = router;
query[param] = newValue;
router.replace({ pathname, query }, undefined, { shallow: true });
}
...@@ -115,6 +115,7 @@ ...@@ -115,6 +115,7 @@
| "status/success" | "status/success"
| "status/warning" | "status/warning"
| "sun" | "sun"
| "swap"
| "testnet" | "testnet"
| "token-placeholder" | "token-placeholder"
| "token" | "token"
......
import { useRouter } from 'next/router';
import { useEffect, useRef } from 'react';
import removeQueryParam from 'lib/router/removeQueryParam';
import updateQueryParam from 'lib/router/updateQueryParam';
import useWallet from 'ui/snippets/walletMenu/useWallet';
export default function useMarketplaceWallet() {
const router = useRouter();
const { isWalletConnected, isModalOpen, connect } = useWallet({ source: 'Swap button' });
const isConnectionStarted = useRef(false);
useEffect(() => {
if (router.query.action !== 'connect') {
return;
}
let timer: ReturnType<typeof setTimeout>;
if (!isWalletConnected && !isModalOpen) {
if (!isConnectionStarted.current) {
timer = setTimeout(() => {
if (!isWalletConnected) {
connect();
isConnectionStarted.current = true;
}
}, 500);
} else {
isConnectionStarted.current = false;
updateQueryParam(router, 'action', 'tooltip');
}
} else if (isWalletConnected) {
isConnectionStarted.current = false;
removeQueryParam(router, 'action');
}
return () => clearTimeout(timer);
}, [ isWalletConnected, isModalOpen, connect, router ]);
}
...@@ -17,6 +17,7 @@ import getQueryParamString from 'lib/router/getQueryParamString'; ...@@ -17,6 +17,7 @@ import getQueryParamString from 'lib/router/getQueryParamString';
import ContentLoader from 'ui/shared/ContentLoader'; import ContentLoader from 'ui/shared/ContentLoader';
import useMarketplaceWallet from '../marketplace/useMarketplaceWallet'; import useMarketplaceWallet from '../marketplace/useMarketplaceWallet';
import useWalletConnection from '../marketplace/useWalletConnection';
const feature = config.features.marketplace; const feature = config.features.marketplace;
const configUrl = feature.isEnabled ? feature.configUrl : ''; const configUrl = feature.isEnabled ? feature.configUrl : '';
...@@ -96,6 +97,7 @@ const MarketplaceAppContent = ({ address, data, isPending }: Props) => { ...@@ -96,6 +97,7 @@ const MarketplaceAppContent = ({ address, data, isPending }: Props) => {
const MarketplaceApp = () => { const MarketplaceApp = () => {
const { address, sendTransaction, signMessage, signTypedData } = useMarketplaceWallet(); const { address, sendTransaction, signMessage, signTypedData } = useMarketplaceWallet();
useWalletConnection();
const apiFetch = useApiFetch(); const apiFetch = useApiFetch();
const router = useRouter(); const router = useRouter();
......
...@@ -10,9 +10,10 @@ interface Props { ...@@ -10,9 +10,10 @@ interface Props {
children: React.ReactNode; children: React.ReactNode;
isLoading?: boolean; isLoading?: boolean;
variant?: 'subtle'; variant?: 'subtle';
hideIcon?: boolean;
} }
const LinkExternal = ({ href, children, className, isLoading, variant }: Props) => { const LinkExternal = ({ href, children, className, isLoading, variant, hideIcon }: Props) => {
const subtleLinkBg = useColorModeValue('gray.100', 'gray.700'); const subtleLinkBg = useColorModeValue('gray.100', 'gray.700');
const styleProps: ChakraProps = (() => { const styleProps: ChakraProps = (() => {
...@@ -59,7 +60,9 @@ const LinkExternal = ({ href, children, className, isLoading, variant }: Props) ...@@ -59,7 +60,9 @@ const LinkExternal = ({ href, children, className, isLoading, variant }: Props)
return ( return (
<Link className={ className } { ...styleProps } target="_blank" href={ href }> <Link className={ className } { ...styleProps } target="_blank" href={ href }>
{ children } { children }
<IconSvg name="arrows/north-east" boxSize={ 4 } verticalAlign="middle" color="gray.400" flexShrink={ 0 }/> { !hideIcon && (
<IconSvg name="arrows/north-east" boxSize={ 4 } verticalAlign="middle" color="gray.400" flexShrink={ 0 }/>
) }
</Link> </Link>
); );
}; };
......
import { Button, Box } from '@chakra-ui/react';
import React from 'react';
import { route } from 'nextjs-routes';
import * as regexp from 'lib/regexp';
import IconSvg from 'ui/shared/IconSvg';
import LinkExternal from 'ui/shared/LinkExternal';
import LinkInternal from 'ui/shared/LinkInternal';
const SwapButton = ({ appUrl }: { appUrl: string }) => {
const button = (
<Button variant="solid" size="xs" borderRadius="sm" height={ 5 } px={ 1.5 }>
<IconSvg name="swap" boxSize={ 3 } mr={{ base: 0, sm: 1 }}/>
<Box display={{ base: 'none', sm: 'inline' }}>
Swap
</Box>
</Button>
);
return regexp.URL_PREFIX.test(appUrl) ? (
<LinkExternal href={ appUrl } hideIcon>
{ button }
</LinkExternal>
) : (
<LinkInternal
href={ route({ pathname: '/apps/[id]', query: { id: appUrl, action: 'connect' } }) }
display="contents"
>
{ button }
</LinkInternal>
);
};
export default React.memo(SwapButton);
import { Flex, useColorModeValue } from '@chakra-ui/react'; import { Flex, Divider, useColorModeValue } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import config from 'configs/app';
import ColorModeSwitch from './ColorModeSwitch'; import ColorModeSwitch from './ColorModeSwitch';
import SwapButton from './SwapButton';
import TopBarStats from './TopBarStats'; import TopBarStats from './TopBarStats';
const feature = config.features.swapButton;
const appUrl = feature.isEnabled && feature.appUrl;
const TopBar = () => { const TopBar = () => {
const bgColor = useColorModeValue('gray.50', 'whiteAlpha.100'); const bgColor = useColorModeValue('gray.50', 'whiteAlpha.100');
return ( return (
<Flex <Flex
py={ 2 } height="34px"
px={ 6 } px={ 6 }
bgColor={ bgColor } bgColor={ bgColor }
justifyContent="space-between" justifyContent="space-between"
alignItems="center"
> >
<TopBarStats/> <TopBarStats/>
<ColorModeSwitch/> <Flex alignItems="center">
{ appUrl && (
<>
<SwapButton appUrl={ appUrl }/>
<Divider mr={ 3 } ml={{ base: 2, sm: 3 }} height={ 4 } orientation="vertical"/>
</>
) }
<ColorModeSwitch/>
</Flex>
</Flex> </Flex>
); );
}; };
......
...@@ -3,6 +3,7 @@ import { useRouter } from 'next/router'; ...@@ -3,6 +3,7 @@ import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import { SECOND } from 'lib/consts'; import { SECOND } from 'lib/consts';
import removeQueryParam from 'lib/router/removeQueryParam';
type Props = { type Props = {
children: React.ReactNode; children: React.ReactNode;
...@@ -29,14 +30,19 @@ const WalletTooltip = ({ children, isDisabled, isMobile }: Props) => { ...@@ -29,14 +30,19 @@ const WalletTooltip = ({ children, isDisabled, isMobile }: Props) => {
React.useEffect(() => { React.useEffect(() => {
const wasShown = window.localStorage.getItem(localStorageKey); const wasShown = window.localStorage.getItem(localStorageKey);
const isMarketplacePage = [ '/apps', '/apps/[id]' ].includes(router.pathname); const isMarketplacePage = [ '/apps', '/apps/[id]' ].includes(router.pathname);
if (!isDisabled && !wasShown && isMarketplacePage) { const isTooltipShowAction = router.query.action === 'tooltip';
if (!isDisabled && isMarketplacePage && (!wasShown || isTooltipShowAction)) {
setTimeout(() => { setTimeout(() => {
setIsTooltipShown.on(); setIsTooltipShown.on();
window.localStorage.setItem(localStorageKey, 'true'); window.localStorage.setItem(localStorageKey, 'true');
setTimeout(() => setIsTooltipShown.off(), 5 * SECOND); setTimeout(() => setIsTooltipShown.off(), 5 * SECOND);
}, SECOND); if (isTooltipShowAction) {
removeQueryParam(router, 'action');
}
}, isTooltipShowAction ? 0 : SECOND);
} }
}, [ setIsTooltipShown, localStorageKey, isDisabled, router.pathname ]); }, [ setIsTooltipShown, localStorageKey, isDisabled, router ]);
return ( return (
<Tooltip <Tooltip
......
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