Commit 5b9b78c3 authored by Max Alekseenko's avatar Max Alekseenko

create DeFi dropdown

parent 7f742762
......@@ -3,9 +3,10 @@ import type { Feature } from './types';
import { getEnvValue } from '../utils';
import marketplace from './marketplace';
const value = getEnvValue('NEXT_PUBLIC_SWAP_BUTTON_URL');
const swapButtonUrl = getEnvValue('NEXT_PUBLIC_SWAP_BUTTON_URL');
const paymentLinkUrl = getEnvValue('NEXT_PUBLIC_PAYMENT_LINK_URL');
const title = 'Swap button';
const title = 'Blockscout DeFi';
function isValidUrl(string: string) {
try {
......@@ -16,27 +17,35 @@ function isValidUrl(string: string) {
}
}
const config: Feature<{ dappId: string } | { url: string }> = (() => {
function createFeatureDetails(value: string | undefined) {
if (value) {
if (isValidUrl(value)) {
return Object.freeze({
title,
isEnabled: true,
url: value,
});
return { url: value };
} else if (marketplace.isEnabled) {
return Object.freeze({
title,
isEnabled: true,
dappId: value,
});
return { dappId: value };
}
}
return undefined;
}
const swapButton = createFeatureDetails(swapButtonUrl);
const paymentLink = createFeatureDetails(paymentLinkUrl);
return Object.freeze({
const isEnabled = Boolean(swapButton) || Boolean(paymentLink);
const config: Feature<{
swapButton?: { dappId: string } | { url: string };
paymentLink?: { dappId: string } | { url: string };
}> = isEnabled ?
Object.freeze({
title,
isEnabled: true,
swapButton,
paymentLink,
}) :
Object.freeze({
title,
isEnabled: false,
});
})();
export default config;
......@@ -23,7 +23,7 @@ export { default as sentry } from './sentry';
export { default as sol2uml } from './sol2uml';
export { default as stats } from './stats';
export { default as suave } from './suave';
export { default as swapButton } from './swapButton';
export { default as deFi } from './deFi';
export { default as txInterpretation } from './txInterpretation';
export { default as userOps } from './userOps';
export { default as validators } from './validators';
......
......@@ -53,6 +53,8 @@ NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL=https://raw.githubusercontent.com/blocksc
NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6uMGPKjj1DK7NL
NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form
NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
NEXT_PUBLIC_SWAP_BUTTON_URL=uniswap
NEXT_PUBLIC_PAYMENT_LINK_URL=peanut-protocol
#meta
NEXT_PUBLIC_OG_IMAGE_URL=https://github.com/blockscout/frontend-configs/blob/main/configs/og-images/eth.jpg?raw=true
......
......@@ -669,13 +669,14 @@ OpenTelemetry SDK for Node.js app could be enabled by passing `OTEL_SDK_ENABLED=
&nbsp;
### Swap button
### Blockscout DeFi
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.
If the feature is enabled, a single button or a dropdown (if more than 1 variable is provided) 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` |
| NEXT_PUBLIC_PAYMENT_LINK_URL | `string` | Application ID in the marketplace or website URL | - | - | `peanut-protocol` |
&nbsp;
......
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.293 8.074a1 1 0 0 0 1.414 0l2.122-2.121a.666.666 0 1 1 .942.942L8.707 9.96a1 1 0 0 1-1.414 0L4.229 6.895a.667.667 0 1 1 .942-.942l2.122 2.121Z" fill="currentColor"/>
</svg>
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.339 1.271a4.518 4.518 0 0 1 7.66 3.214 4.524 4.524 0 0 1-1.269 3.18l-.012.013-2.111 2.114a4.402 4.402 0 0 1-.115.11c.325-.488.508-1.112.508-1.9 0-.473-.065-.886-.188-1.246l.485-.485a2.524 2.524 0 0 0-1.796-4.27 2.518 2.518 0 0 0-1.767.704L8.528 3.904a1 1 0 1 1-1.41-1.418l1.21-1.205.01-.01Zm-4.825 4.82a4.524 4.524 0 0 0-.122.117L1.281 8.322l-.013.012a4.524 4.524 0 0 0 3.212 7.664 4.518 4.518 0 0 0 3.18-1.27l.012-.011 1.204-1.205a1 1 0 0 0-1.415-1.414l-1.197 1.198A2.518 2.518 0 0 1 2 11.498a2.524 2.524 0 0 1 .702-1.77l.485-.484A3.859 3.859 0 0 1 3 8c0-.793.185-1.42.514-1.91Z" fill="currentColor" fill-opacity=".8"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.45 10.064V9.051h2.474c.06 0 .116-.026.159-.074a.27.27 0 0 0 .065-.179.27.27 0 0 0-.065-.179.213.213 0 0 0-.16-.074H7.125c-.298 0-.584-.133-.795-.37C6.12 7.936 6 7.614 6 7.278c0-.336.118-.658.33-.895.21-.238.496-.371.794-.371h.45V5h.9v1.013h1.124v1.013H7.124a.213.213 0 0 0-.159.074.27.27 0 0 0-.065.179.27.27 0 0 0 .065.179c.043.047.1.074.16.074h1.799c.298 0 .584.133.795.37.21.238.329.56.329.896 0 .336-.119.658-.33.895-.21.238-.496.371-.794.371h-.45v1.013h-.9v-1.013H6.45Z" fill="currentColor" fill-opacity=".8"/>
</svg>
......@@ -128,7 +128,7 @@ Type extends EventTypes.FILTERS ? {
'Filter name': string;
} :
Type extends EventTypes.BUTTON_CLICK ? {
'Content': 'Swap button';
'Content': 'Swap button' | 'Payment link';
'Source': string;
} :
Type extends EventTypes.PROMO_BANNER ? {
......
......@@ -12,6 +12,7 @@
| "arrows/east"
| "arrows/north-east"
| "arrows/south-east"
| "arrows/south-mini"
| "arrows/up-down"
| "beta_xs"
| "beta"
......@@ -87,6 +88,7 @@
| "networks/logo-placeholder"
| "nft_shield"
| "output_roots"
| "payment_link"
| "plus"
| "privattags"
| "profile"
......
import { Button, Box, Menu, MenuButton, MenuList, MenuItem, Flex } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import React from 'react';
import { route } from 'nextjs-routes';
import config from 'configs/app';
import useIsMobile from 'lib/hooks/useIsMobile';
import getPageType from 'lib/mixpanel/getPageType';
import * as mixpanel from 'lib/mixpanel/index';
import IconSvg from 'ui/shared/IconSvg';
const feature = config.features.deFi;
function getHrefAndTarget(feature: { url: string } | { dappId: string }) {
return 'url' in feature ? {
href: feature.url,
target: '_blank',
} : {
href: route({ pathname: '/apps/[id]', query: { id: feature.dappId, action: 'connect' } }),
target: '_self',
};
}
const DeFiDropdown = () => {
const router = useRouter();
const source = getPageType(router.pathname);
const isMobile = useIsMobile();
const handleClick = React.useCallback((content: 'Swap button' | 'Payment link') => {
mixpanel.logEvent(mixpanel.EventTypes.BUTTON_CLICK, { Content: content, Source: source });
}, [ source ]);
const items = React.useMemo(() => {
if (!feature.isEnabled) {
return [];
}
const items = [];
if (feature.swapButton) {
const { href, target } = getHrefAndTarget(feature.swapButton);
items.push({
icon: 'swap' as const,
text: 'Swap',
href,
target,
onClick: () => handleClick('Swap button'),
});
}
if (feature.paymentLink) {
const { href, target } = getHrefAndTarget(feature.paymentLink);
items.push({
icon: 'payment_link' as const,
text: 'Payment link',
href,
target,
onClick: () => handleClick('Payment link'),
});
}
return items;
}, [ handleClick ]);
if (items.length === 0) {
return null;
}
const buttonStyles = {
variant: 'solid',
size: 'xs',
borderRadius: 'sm',
height: 5,
px: 1.5,
fontWeight: '500',
};
return items.length > 1 ? (
<Menu>
<MenuButton as={ Button } { ...buttonStyles }>
<Flex alignItems="center">
{ !isMobile && 'Blockscout' } DeFi
<IconSvg name="arrows/south-mini" boxSize={ 4 } ml={ 1 }/>
</Flex>
</MenuButton>
<MenuList minWidth="150px" zIndex="popover" overflow="hidden">
{ items.map((item, index) => (
<MenuItem
key={ index }
as="a"
href={ item.href }
target={ item.target }
onClick={ item.onClick }
px={ 4 }
py={ 2 }
>
<IconSvg name={ item.icon } boxSize={ 4 } mr={ 2 }/>
<span>{ item.text }</span>
</MenuItem>
)) }
</MenuList>
</Menu>
) : (
<Button
as="a"
href={ items[0].href }
target={ items[0].target }
onClick={ items[0].onClick }
{ ...buttonStyles }
>
<IconSvg name={ items[0].icon } boxSize={ 3 } mr={{ base: 0, sm: 1 }}/>
<Box display={{ base: 'none', sm: 'inline' }}>
{ items[0].text }
</Box>
</Button>
);
};
export default React.memo(DeFiDropdown);
import { Button, Box } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import React from 'react';
import { route } from 'nextjs-routes';
import config from 'configs/app';
import getPageType from 'lib/mixpanel/getPageType';
import * as mixpanel from 'lib/mixpanel/index';
import IconSvg from 'ui/shared/IconSvg';
const feature = config.features.swapButton;
const SwapButton = () => {
const router = useRouter();
const source = getPageType(router.pathname);
const handleClick = React.useCallback(() => {
mixpanel.logEvent(mixpanel.EventTypes.BUTTON_CLICK, { Content: 'Swap button', Source: source });
}, [ source ]);
if (!feature.isEnabled) {
return null;
}
const href = 'url' in feature ?
feature.url :
route({ pathname: '/apps/[id]', query: { id: feature.dappId, action: 'connect' } });
return (
<Button
as="a"
href={ href }
target={ 'url' in feature ? '_blank' : '_self' }
variant="solid"
size="xs"
borderRadius="sm"
height={ 5 }
px={ 1.5 }
onClick={ handleClick }
>
<IconSvg name="swap" boxSize={ 3 } mr={{ base: 0, sm: 1 }}/>
<Box display={{ base: 'none', sm: 'inline' }}>
Swap
</Box>
</Button>
);
};
export default React.memo(SwapButton);
......@@ -3,11 +3,11 @@ import React from 'react';
import config from 'configs/app';
import DeFiDropdown from './DeFiDropdown';
import Settings from './settings/Settings';
import SwapButton from './SwapButton';
import TopBarStats from './TopBarStats';
const feature = config.features.swapButton;
const feature = config.features.deFi;
const TopBar = () => {
const bgColor = useColorModeValue('gray.50', 'whiteAlpha.100');
......@@ -24,7 +24,7 @@ const TopBar = () => {
<Flex alignItems="center">
{ feature.isEnabled && (
<>
<SwapButton/>
<DeFiDropdown/>
<Divider mr={ 3 } ml={{ base: 2, sm: 3 }} height={ 4 } orientation="vertical"/>
</>
) }
......
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