DEX Lido integrations
diff --git a/features/wsteth/shared/wrap-faq/list/how-can-i-use-wsteth.tsx b/features/wsteth/shared/wrap-faq/list/how-can-i-use-wsteth.tsx
index e563deb1a..a3265bcb6 100644
--- a/features/wsteth/shared/wrap-faq/list/how-can-i-use-wsteth.tsx
+++ b/features/wsteth/shared/wrap-faq/list/how-can-i-use-wsteth.tsx
@@ -1,5 +1,7 @@
import { FC } from 'react';
import { Accordion, Link } from '@lidofinance/lido-ui';
+
+import { config } from 'config';
import { MATOMO_CLICK_EVENTS_TYPES } from 'consts/matomo-click-events';
export const HowCanIUseWsteth: FC = () => {
@@ -8,14 +10,14 @@ export const HowCanIUseWsteth: FC = () => {
wstETH is useful across{' '}
L2
{' '}
and other{' '}
{
+ const { vaultsBannerIsEnabled } = useFeatureFlag(VAULTS_BANNER_IS_ENABLED);
return (
@@ -20,7 +23,11 @@ export const UnwrapForm: FC = memo(() => {
-
+ {vaultsBannerIsEnabled ? (
+
+ ) : (
+
+ )}
diff --git a/features/wsteth/wrap/wrap-form/wrap-form.tsx b/features/wsteth/wrap/wrap-form/wrap-form.tsx
index c31999dc5..5ecafbdfc 100644
--- a/features/wsteth/wrap/wrap-form/wrap-form.tsx
+++ b/features/wsteth/wrap/wrap-form/wrap-form.tsx
@@ -1,6 +1,8 @@
import { memo } from 'react';
+import { useFeatureFlag, VAULTS_BANNER_IS_ENABLED } from 'config/feature-flags';
import { L2Wsteth } from 'shared/banners/l2-banners/l2-wsteth';
+import { VaultsBannerInfo } from 'shared/banners/vaults-banner-info';
import { FormController } from 'shared/hook-form/form-controller';
import { MATOMO_CLICK_EVENTS } from 'consts/matomo-click-events';
@@ -11,6 +13,7 @@ import { InputGroupWrap } from '../wrap-form-controls/input-group-wrap';
import { SubmitButtonWrap } from '../wrap-form-controls/submit-button-wrap';
export const WrapForm: React.FC = memo(() => {
+ const { vaultsBannerIsEnabled } = useFeatureFlag(VAULTS_BANNER_IS_ENABLED);
return (
@@ -18,7 +21,11 @@ export const WrapForm: React.FC = memo(() => {
-
+ {vaultsBannerIsEnabled ? (
+
+ ) : (
+
+ )}
diff --git a/next.config.mjs b/next.config.mjs
index 90ce35a8b..35741393f 100644
--- a/next.config.mjs
+++ b/next.config.mjs
@@ -8,7 +8,7 @@ buildDynamics();
const basePath = process.env.BASE_PATH;
const developmentMode = process.env.NODE_ENV === 'development';
-const isIPFSMode = process.env.IPFS_MODE;
+const isIPFSMode = process.env.IPFS_MODE === 'true';
// cache control
export const CACHE_CONTROL_HEADER = 'x-cache-control';
diff --git a/package.json b/package.json
index b8bbc0fc5..0737100b0 100644
--- a/package.json
+++ b/package.json
@@ -6,11 +6,11 @@
"license": "GPL-3.0-or-later",
"scripts": {
"dev": "NODE_ENV=development node server.mjs",
- "build": "next build",
- "build:analyze": "ANALYZE_BUNDLE=true next build",
- "start": "NODE_OPTIONS='-r next-logger' NODE_ENV=production node server.mjs",
- "dev-ipfs": "cross-env IPFS_MODE=true next dev",
- "build-ipfs": "cross-env IPFS_MODE=true next build && cross-env IPFS_MODE=true next export",
+ "dev:ipfs": "IPFS_MODE=true next dev",
+ "build": "NODE_OPTIONS='--no-warnings=ExperimentalWarning' next build",
+ "build:analyze": "ANALYZE_BUNDLE=true yarn build",
+ "build:ipfs": "IPFS_MODE=true yarn build && IPFS_MODE=true next export",
+ "start": "NODE_ENV=production node -r next-logger --no-warnings=ExperimentalWarning server.mjs",
"lint": "eslint --ext ts,tsx,js,mjs .",
"lint:fix": "yarn lint --fix",
"types": "tsc --noEmit",
@@ -38,7 +38,7 @@
"@lidofinance/api-rpc": "^0.41.0",
"@lidofinance/eth-api-providers": "^0.41.0",
"@lidofinance/eth-providers": "^0.41.0",
- "@lidofinance/lido-ui": "^3.24.0",
+ "@lidofinance/lido-ui": "^3.26.0",
"@lidofinance/next-api-wrapper": "^0.41.0",
"@lidofinance/next-ip-rate-limit": "^0.41.0",
"@lidofinance/next-pages": "^0.41.0",
@@ -103,7 +103,6 @@
"@types/winston": "^2.4.4",
"@typescript-eslint/eslint-plugin": "^6.2.1",
"@typescript-eslint/parser": "^6.2.1",
- "cross-env": "^7.0.3",
"eslint": "^8.46.0",
"eslint-config-prettier": "^9.0.0",
"eslint-import-resolver-typescript": "^3.5.5",
diff --git a/pages/_app.tsx b/pages/_app.tsx
index 2ae16e58f..e016045d4 100644
--- a/pages/_app.tsx
+++ b/pages/_app.tsx
@@ -15,6 +15,7 @@ import { withCsp } from 'config/csp';
import { SecurityStatusBanner } from 'features/ipfs';
import { Providers } from 'providers';
import { BackgroundGradient } from 'shared/components/background-gradient/background-gradient';
+import NoSsrWrapper from 'shared/components/no-ssr-wrapper';
import { nprogress, COOKIES_ALLOWED_FULL_KEY } from 'utils';
// Migrations old theme cookies to new cross domain cookies
@@ -55,7 +56,11 @@ const AppWrapper = (props: AppProps): JSX.Element => {
/>
-
+
+
+
+
+
);
diff --git a/pages/_document.tsx b/pages/_document.tsx
index 9080492cd..b19106b27 100644
--- a/pages/_document.tsx
+++ b/pages/_document.tsx
@@ -14,8 +14,6 @@ import { config } from 'config';
import { contentSecurityPolicy } from 'config/csp';
import { InsertIpfsBaseScript } from 'features/ipfs/ipfs-base-script';
-let host = 'https://stake.lido.fi';
-
const secureHeaders = createHeadersObject({ contentSecurityPolicy });
const cspMetaTagContent =
secureHeaders['Content-Security-Policy'] ??
@@ -28,10 +26,6 @@ export default class MyDocument extends Document {
const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;
- if (ctx?.req?.headers?.host) {
- host = `https://${ctx?.req?.headers?.host}`;
- }
-
try {
ctx.renderPage = () =>
originalRenderPage({
@@ -68,7 +62,10 @@ export default class MyDocument extends Document {
}
get metaPreviewImgUrl(): string {
- return `${host}/lido-preview.png`;
+ const origin = config.ipfsMode
+ ? 'https://stake.lido.fi'
+ : config.selfOrigin;
+ return `${origin}/lido-preview.png`;
}
render(): JSX.Element {
diff --git a/pages/index.tsx b/pages/index.tsx
index 3cea362e5..4a2b17c67 100644
--- a/pages/index.tsx
+++ b/pages/index.tsx
@@ -1,11 +1,13 @@
+import { GetStaticProps } from 'next';
import { config } from 'config';
-
import { StakePage } from 'features/stake';
import { HomePageIpfs } from 'features/ipfs';
-import { GetStaticProps } from 'next';
+
+export default config.ipfsMode ? HomePageIpfs : StakePage;
export const getStaticProps: GetStaticProps = async () => {
- return { props: {} };
+ return {
+ props: {},
+ revalidate: 60,
+ };
};
-
-export default config.ipfsMode ? HomePageIpfs : StakePage;
diff --git a/pages/referral.tsx b/pages/referral.tsx
index 40dff0604..f60165f9a 100644
--- a/pages/referral.tsx
+++ b/pages/referral.tsx
@@ -1,4 +1,5 @@
import { FC } from 'react';
+import { GetStaticProps } from 'next';
import { Banner } from 'features/referral';
import { Layout } from 'shared/components';
@@ -11,3 +12,10 @@ const Referral: FC = () => {
};
export default Referral;
+
+export const getStaticProps: GetStaticProps = async () => {
+ return {
+ props: {},
+ revalidate: 60,
+ };
+};
diff --git a/pages/rewards.tsx b/pages/rewards.tsx
index b197c291e..f48f377e2 100644
--- a/pages/rewards.tsx
+++ b/pages/rewards.tsx
@@ -1,4 +1,5 @@
import { FC } from 'react';
+import { GetStaticProps } from 'next';
import Head from 'next/head';
import { Layout } from 'shared/components';
import { TopCard, RewardsList } from 'features/rewards/features';
@@ -32,3 +33,10 @@ const Rewards: FC = () => {
};
export default Rewards;
+
+export const getStaticProps: GetStaticProps = async () => {
+ return {
+ props: {},
+ revalidate: 60,
+ };
+};
diff --git a/pages/settings.tsx b/pages/settings.tsx
index bd584333c..9d88b7d4a 100644
--- a/pages/settings.tsx
+++ b/pages/settings.tsx
@@ -18,5 +18,8 @@ export default Settings;
export const getStaticProps: GetStaticProps = async () => {
if (!config.ipfsMode) return { notFound: true };
- return { props: {} };
+ return {
+ props: {},
+ revalidate: 60,
+ };
};
diff --git a/pages/withdrawals/[mode].tsx b/pages/withdrawals/[mode].tsx
index 7aada07a3..54a5af0b1 100644
--- a/pages/withdrawals/[mode].tsx
+++ b/pages/withdrawals/[mode].tsx
@@ -3,7 +3,6 @@ import { GetStaticPaths, GetStaticProps } from 'next';
import Head from 'next/head';
import { Layout } from 'shared/components';
-import NoSSRWrapper from 'shared/components/no-ssr-wrapper';
import { WithdrawalsTabs } from 'features/withdrawals';
import { WithdrawalsProvider } from 'features/withdrawals/contexts/withdrawals-context';
@@ -21,9 +20,7 @@ const Withdrawals: FC = ({ mode }) => {
Withdrawals | Lido
-
-
-
+
);
@@ -49,5 +46,5 @@ export const getStaticProps: GetStaticProps<
WithdrawalsModePageParams
> = async ({ params }) => {
if (!params?.mode) return { notFound: true };
- return { props: { mode: params.mode } };
+ return { props: { mode: params.mode }, revalidate: 60 };
};
diff --git a/pages/wrap/[[...mode]].tsx b/pages/wrap/[[...mode]].tsx
index 97a695c2d..34255198c 100644
--- a/pages/wrap/[[...mode]].tsx
+++ b/pages/wrap/[[...mode]].tsx
@@ -43,8 +43,9 @@ export const getStaticProps: GetStaticProps<
WrapModePageParams
> = async ({ params }) => {
const mode = params?.mode;
- if (!mode) return { props: { mode: 'wrap' } };
- if (mode[0] === 'unwrap') return { props: { mode: 'unwrap' } };
+ if (!mode) return { props: { mode: 'wrap' }, revalidate: 60 };
+ if (mode[0] === 'unwrap')
+ return { props: { mode: 'unwrap' }, revalidate: 60 };
return { notFound: true };
};
diff --git a/shared/banners/banner-link-button/banner-link-button.tsx b/shared/banners/banner-link-button/banner-link-button.tsx
new file mode 100644
index 000000000..dc121aac3
--- /dev/null
+++ b/shared/banners/banner-link-button/banner-link-button.tsx
@@ -0,0 +1,35 @@
+import { ButtonLinkWrap, ButtonLinkWrapLocal, ButtonStyle } from './styles';
+
+type BannerLinkButtonProps = {
+ href: string;
+ testId?: string;
+ onClick?: () => void;
+ isLocalLink?: boolean;
+ children: React.ReactNode;
+};
+
+export const BannerLinkButton = ({
+ href,
+ testId,
+ onClick,
+ isLocalLink,
+ children,
+}: BannerLinkButtonProps) => {
+ const buttonEl = (
+
+ {children}
+
+ );
+
+ const linkProps = {
+ href,
+ onClick,
+ children: buttonEl,
+ };
+
+ if (isLocalLink) {
+ return ;
+ }
+
+ return ;
+};
diff --git a/shared/banners/banner-link-button/index.ts b/shared/banners/banner-link-button/index.ts
new file mode 100644
index 000000000..8ef569614
--- /dev/null
+++ b/shared/banners/banner-link-button/index.ts
@@ -0,0 +1 @@
+export * from './banner-link-button';
diff --git a/shared/banners/banner-link-button/styles.ts b/shared/banners/banner-link-button/styles.ts
new file mode 100644
index 000000000..91e237b79
--- /dev/null
+++ b/shared/banners/banner-link-button/styles.ts
@@ -0,0 +1,33 @@
+import styled, { css } from 'styled-components';
+import { Button, Link } from '@lidofinance/lido-ui';
+import { LocalLink } from 'shared/components/local-link';
+
+const buttonLinkWrapCss = css`
+ display: block;
+
+ ${({ theme }) => theme.mediaQueries.md} {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ }
+`;
+
+export const ButtonLinkWrap = styled(Link)`
+ ${buttonLinkWrapCss};
+`;
+
+export const ButtonLinkWrapLocal = styled(LocalLink)`
+ ${buttonLinkWrapCss};
+`;
+
+export const ButtonStyle = styled(Button)`
+ padding: 7px 16px;
+ font-size: 12px;
+ line-height: 20px;
+
+ ${({ theme }) => theme.mediaQueries.md} {
+ display: none;
+ }
+`;
diff --git a/shared/banners/goerli-sunset/goerli-sunset-banner.tsx b/shared/banners/goerli-sunset/goerli-sunset-banner.tsx
index 9e9edc680..79100437b 100644
--- a/shared/banners/goerli-sunset/goerli-sunset-banner.tsx
+++ b/shared/banners/goerli-sunset/goerli-sunset-banner.tsx
@@ -1,11 +1,13 @@
import { CHAINS } from '@lido-sdk/constants';
import { useSDK } from '@lido-sdk/react';
import { Text, Link } from '@lidofinance/lido-ui';
+
+import { config } from 'config';
+
import { SunsetMessageStyle } from './styles';
-const URL_INFORMATION = 'https://docs.lido.fi/deployed-contracts/goerli/';
-const URL_HOLESKY =
- 'https://docs.lido.fi/deployed-contracts/holesky/#hole%C5%A1ky-testnet';
+const URL_INFORMATION = `${config.docsOrigin}/deployed-contracts/goerli/`;
+const URL_HOLESKY = `${config.docsOrigin}/deployed-contracts/holesky/#hole%C5%A1ky-testnet`;
export const GoerliSunsetBanner = () => {
const { chainId } = useSDK();
diff --git a/shared/banners/l2-banner/l2-banner.tsx b/shared/banners/l2-banner/l2-banner.tsx
index 623aaf5ab..79594f0d9 100644
--- a/shared/banners/l2-banner/l2-banner.tsx
+++ b/shared/banners/l2-banner/l2-banner.tsx
@@ -1,13 +1,7 @@
-import {
- Wrapper,
- L2Icons,
- TextWrap,
- ButtonLinkWrap,
- ButtonLinkWrapLocal,
- ButtonStyle,
- TextHeader,
- FooterWrap,
-} from './styles';
+import { config } from 'config';
+
+import { BannerLinkButton } from '../banner-link-button';
+import { Wrapper, L2Icons, TextWrap, TextHeader, FooterWrap } from './styles';
type L2BannerProps = {
title?: React.ReactNode;
@@ -20,7 +14,7 @@ type L2BannerProps = {
onClickButton?: () => void;
};
-export const L2_DISCOVERY_LINK = 'https://lido.fi/lido-on-l2';
+export const L2_DISCOVERY_LINK = `${config.rootOrigin}/lido-on-l2`;
export const L2Banner = ({
title,
@@ -32,31 +26,20 @@ export const L2Banner = ({
testidButton,
onClickButton,
}: L2BannerProps) => {
- const buttonEl = (
-
- {buttonText}
-
- );
-
- const linkProps = {
- href: buttonHref,
- onClick: onClickButton,
- children: buttonEl,
- };
-
- const linkEl = isLocalLink ? (
-
- ) : (
-
- );
-
return (
{title && {title} }
{text}
- {linkEl}
+
+ {buttonText}
+
);
diff --git a/shared/banners/l2-banner/styles.ts b/shared/banners/l2-banner/styles.ts
index 498a5301f..1b0ed9218 100644
--- a/shared/banners/l2-banner/styles.ts
+++ b/shared/banners/l2-banner/styles.ts
@@ -1,8 +1,6 @@
import styled, { css } from 'styled-components';
-import { Button, Link } from '@lidofinance/lido-ui';
import IconsLight from 'assets/icons/l2-swap-light.svg';
import IconsDark from 'assets/icons/l2-swap-dark.svg';
-import { LocalLink } from 'shared/components/local-link';
export const Wrapper = styled.div`
position: relative;
@@ -76,33 +74,3 @@ export const TextWrap = styled.div`
font-weight: 400;
position: relative;
`;
-
-const buttonLinkWrapCss = css`
- display: block;
-
- ${({ theme }) => theme.mediaQueries.md} {
- position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- right: 0;
- }
-`;
-
-export const ButtonLinkWrap = styled(Link)`
- ${buttonLinkWrapCss};
-`;
-
-export const ButtonLinkWrapLocal = styled(LocalLink)`
- ${buttonLinkWrapCss};
-`;
-
-export const ButtonStyle = styled(Button)`
- padding: 7px 16px;
- font-size: 12px;
- line-height: 20px;
-
- ${({ theme }) => theme.mediaQueries.md} {
- display: none;
- }
-`;
diff --git a/shared/banners/l2-banners/l2-after-wrap.tsx b/shared/banners/l2-banners/l2-after-wrap.tsx
index 7cfaf84d1..55caf55b3 100644
--- a/shared/banners/l2-banners/l2-after-wrap.tsx
+++ b/shared/banners/l2-banners/l2-after-wrap.tsx
@@ -1,11 +1,13 @@
import { trackEvent } from '@lidofinance/analytics-matomo';
+
+import { config } from 'config';
import { MATOMO_CLICK_EVENTS } from 'consts/matomo-click-events';
+
import { L2Banner } from '../l2-banner';
const linkClickHandler = () => trackEvent(...MATOMO_CLICK_EVENTS.l2LowFeeWrap);
-const L2_LEARN_MORE_AFTER_WRAP_LINK =
- 'https://lido.fi/lido-ecosystem?networks=arbitrum%2Coptimism%2Cbase%2Czksync+era%2Cmantle%2Clinea%2Cpolygon&criteria=or&tokens=wsteth';
+const L2_LEARN_MORE_AFTER_WRAP_LINK = `${config.rootOrigin}/lido-ecosystem?networks=arbitrum%2Coptimism%2Cbase%2Czksync+era%2Cmantle%2Clinea%2Cpolygon&criteria=or&tokens=wsteth`;
export const L2AfterWrap = () => {
return (
diff --git a/shared/banners/modal-pool-banners/modal-pool-banners.tsx b/shared/banners/modal-pool-banners/modal-pool-banners.tsx
index 16c0f1786..40c394bf4 100644
--- a/shared/banners/modal-pool-banners/modal-pool-banners.tsx
+++ b/shared/banners/modal-pool-banners/modal-pool-banners.tsx
@@ -1,10 +1,12 @@
import { trackEvent } from '@lidofinance/analytics-matomo';
-import { Curve } from 'shared/banners/curve';
+
+import { config } from 'config';
import { MATOMO_CLICK_EVENTS } from 'consts/matomo-click-events';
+import { Curve } from 'shared/banners/curve';
import { TextStyles, DescStyles, ButtonLinkWrap, ButtonStyled } from './styles';
-const ECOSYSTEM_LINK = 'https://lido.fi/lido-ecosystem';
+const ECOSYSTEM_LINK = `${config.rootOrigin}/lido-ecosystem`;
const linkClickHandler = () =>
trackEvent(...MATOMO_CLICK_EVENTS.clickExploreDeFi);
diff --git a/shared/banners/vaults-banner-info/index.ts b/shared/banners/vaults-banner-info/index.ts
new file mode 100644
index 000000000..6618838bc
--- /dev/null
+++ b/shared/banners/vaults-banner-info/index.ts
@@ -0,0 +1 @@
+export * from './vaults-banner-info';
diff --git a/shared/banners/vaults-banner-info/styles.ts b/shared/banners/vaults-banner-info/styles.ts
new file mode 100644
index 000000000..baff3cffc
--- /dev/null
+++ b/shared/banners/vaults-banner-info/styles.ts
@@ -0,0 +1,39 @@
+import styled from 'styled-components';
+
+export const Wrap = styled.div`
+ position: relative;
+ padding: 16px;
+ border-radius: 16px;
+ background-color: ${({ theme }) =>
+ theme.name === 'dark' ? '#28282f' : '#f2f3fc'};
+`;
+
+export const Title = styled.div`
+ margin-bottom: 8px;
+ font-size: 20px;
+ line-height: 20px;
+ font-weight: 700;
+ color: var(--lido-color-text);
+`;
+
+export const Description = styled.div`
+ margin-bottom: 15px;
+ font-size: 12px;
+ font-weight: 400;
+ line-height: 20px;
+ color: var(--lido-color-textSecondary);
+`;
+
+export const Footer = styled.div`
+ display: flex;
+ justify-content: space-between;
+`;
+
+export const Logos = styled.div`
+ display: flex;
+ gap: 8px;
+
+ svg {
+ display: block;
+ }
+`;
diff --git a/shared/banners/vaults-banner-info/vaults-banner-info.tsx b/shared/banners/vaults-banner-info/vaults-banner-info.tsx
new file mode 100644
index 000000000..044c39678
--- /dev/null
+++ b/shared/banners/vaults-banner-info/vaults-banner-info.tsx
@@ -0,0 +1,51 @@
+import { useThemeToggle } from '@lidofinance/lido-ui';
+import { trackEvent } from '@lidofinance/analytics-matomo';
+
+import { ReactComponent as IconMevDark } from 'assets/vault-banner/icon-mev-dark.svg';
+import { ReactComponent as IconP2PDark } from 'assets/vault-banner/icon-p2p-dark.svg';
+import { ReactComponent as IconRe7Dark } from 'assets/vault-banner/icon-re7-dark.svg';
+import { ReactComponent as IconStakehouseDark } from 'assets/vault-banner/icon-stakehouse-dark.svg';
+
+import { ReactComponent as IconMevLight } from 'assets/vault-banner/icon-mev-light.svg';
+import { ReactComponent as IconP2PLight } from 'assets/vault-banner/icon-p2p-light.svg';
+import { ReactComponent as IconRe7Light } from 'assets/vault-banner/icon-re7-light.svg';
+import { ReactComponent as IconStakehouseLight } from 'assets/vault-banner/icon-stakehouse-light.svg';
+
+import { config } from 'config';
+import { MATOMO_CLICK_EVENTS } from 'consts/matomo-click-events';
+
+import { BannerLinkButton } from '../banner-link-button';
+import { Wrap, Title, Description, Footer, Logos } from './styles';
+
+const LINK_LEARN_MORE = `${config.rootOrigin}/#defi-strategies`;
+
+const linkClickHandler = () =>
+ trackEvent(...MATOMO_CLICK_EVENTS.vaultsBannerLearnMore);
+
+export const VaultsBannerInfo = () => {
+ const { themeName } = useThemeToggle();
+ return (
+
+ Explore restaking opportunities
+
+ Use stETH to unlock restaking rewards through a set of carefully curated
+ vaults
+
+
+
+ {themeName === 'dark' ? : }
+ {themeName === 'dark' ? (
+
+ ) : (
+
+ )}
+ {themeName === 'dark' ? : }
+ {themeName === 'dark' ? : }
+
+
+ Learn more
+
+
+
+ );
+};
diff --git a/shared/banners/vaults-banner-strategies/index.ts b/shared/banners/vaults-banner-strategies/index.ts
new file mode 100644
index 000000000..b87bcf90e
--- /dev/null
+++ b/shared/banners/vaults-banner-strategies/index.ts
@@ -0,0 +1 @@
+export * from './vaults-banner-strategies';
diff --git a/shared/banners/vaults-banner-strategies/styles.ts b/shared/banners/vaults-banner-strategies/styles.ts
new file mode 100644
index 000000000..2f384e8cb
--- /dev/null
+++ b/shared/banners/vaults-banner-strategies/styles.ts
@@ -0,0 +1,112 @@
+import styled from 'styled-components';
+
+export const Wrap = styled.div`
+ position: relative;
+ margin-bottom: 20px;
+ padding: 16px;
+ border-radius: 16px;
+ background-color: ${({ theme }) =>
+ theme.name === 'dark' ? '#28282f' : '#f2f3fc'};
+`;
+
+export const Header = styled.div`
+ display: flex;
+ align-items: center;
+ margin-bottom: 15px;
+`;
+
+export const Icon = styled.div`
+ margin-right: 15px;
+
+ &,
+ svg {
+ display: block;
+ weight: 75px;
+ height: 75px;
+ }
+
+ ${({ theme }) => theme.mediaQueries.md} {
+ order: 2;
+ margin-right: 0;
+
+ &,
+ svg {
+ weight: 48px;
+ height: 48px;
+ }
+ }
+`;
+
+export const Title = styled.div`
+ text-align: left;
+
+ ${({ theme }) => theme.mediaQueries.md} {
+ flex: 1 1 auto;
+ order: 1;
+ }
+`;
+
+export const TitleText = styled.div`
+ font-size: 20px;
+ line-height: 28px;
+ font-weight: 700;
+ color: var(--lido-color-text);
+
+ ${({ theme }) => theme.mediaQueries.md} {
+ font-size: 16px;
+ line-height: 24px;
+ }
+`;
+
+export const TitleDescription = styled.div`
+ font-size: 12px;
+ line-height: 20px;
+ font-weight: 400;
+ color: var(--lido-color-textSecondary);
+`;
+
+export const Strategies = styled.div`
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ flex-wrap: wrap;
+ gap: 10px;
+
+ ${({ theme }) => theme.mediaQueries.md} {
+ display: grid;
+ width: fit-content;
+ grid-template-columns: repeat(3, auto);
+
+ & > *:nth-child(4) {
+ display: none;
+ }
+ }
+`;
+
+export const StrategyItem = styled.div`
+ flex: 0 0 auto;
+ text-align: left;
+ font-size: 12px;
+ line-height: 16px;
+ font-weight: 400;
+ color: var(--lido-color-text);
+
+ b {
+ font-weight: 700;
+ }
+ ${({ theme }) => theme.mediaQueries.md} {
+ br {
+ display: none;
+ }
+ }
+`;
+
+export const StrategyDivider = styled.div`
+ svg {
+ display: block;
+ fill: ${({ theme }) =>
+ theme.name === 'dark'
+ ? 'var(--lido-color-text)'
+ : 'var(--lido-color-textSecondary)'};
+ }
+`;
diff --git a/shared/banners/vaults-banner-strategies/vaults-banner-strategies.tsx b/shared/banners/vaults-banner-strategies/vaults-banner-strategies.tsx
new file mode 100644
index 000000000..9534fc54e
--- /dev/null
+++ b/shared/banners/vaults-banner-strategies/vaults-banner-strategies.tsx
@@ -0,0 +1,80 @@
+import { Button, Link } from '@lidofinance/lido-ui';
+import { trackEvent } from '@lidofinance/analytics-matomo';
+
+import { ReactComponent as IconStakehouse } from 'assets/vault-banner/strategy-stakehouse.svg';
+import { ReactComponent as SymbolPlus } from 'assets/vault-banner/symbol-plus.svg';
+
+import { config } from 'config';
+import { MATOMO_CLICK_EVENTS } from 'consts/matomo-click-events';
+
+import {
+ Wrap,
+ Header,
+ Icon,
+ Title,
+ TitleText,
+ TitleDescription,
+ Strategies,
+ StrategyItem,
+ StrategyDivider,
+} from './styles';
+
+const LINK_LEARN_MORE = `${config.rootOrigin}/#defi-strategies`;
+
+const linkClickHandler = () =>
+ trackEvent(...MATOMO_CLICK_EVENTS.vaultsBannerExploreAll);
+
+export const VaultsBannerStrategies = () => {
+ const divider = (
+
+
+
+ );
+ return (
+ <>
+
+
+
+
+
+
+ Restaking Vault
+ Curated by Steakhouse Financial
+
+
+
+
+ stETH
+ APR
+
+
+ {divider}
+
+
+ Symbiotic
+ Points
+
+
+ {divider}
+
+
+ Mellow
+ Points
+
+
+ {divider}
+
+
+ Restaking
+ APR TBD
+
+
+
+
+
+ Explore all strategies
+
+
+ >
+ );
+};
diff --git a/shared/components/layout/footer/footer.tsx b/shared/components/layout/footer/footer.tsx
index c4d95004e..b044d04f6 100644
--- a/shared/components/layout/footer/footer.tsx
+++ b/shared/components/layout/footer/footer.tsx
@@ -1,5 +1,6 @@
import { FC } from 'react';
import buildInfo from 'build-info.json';
+import { config } from 'config';
import {
FooterStyle,
@@ -42,13 +43,16 @@ export const Footer: FC = () => {
return (
-
+
Terms of Use
Privacy Notice
diff --git a/shared/components/logos/logos.tsx b/shared/components/logos/logos.tsx
index b85e8d81d..ac6e5fbde 100644
--- a/shared/components/logos/logos.tsx
+++ b/shared/components/logos/logos.tsx
@@ -2,6 +2,8 @@ import { FC, HTMLAttributes, SVGProps } from 'react';
import Link from 'next/link';
import { LidoLogo } from '@lidofinance/lido-ui';
+import { config } from 'config';
+
import { LogoLDOPLStyle, LogoLDOStyle, LogoLidoStyle } from './styles';
export type LogoComponent = FC, 'ref'>>;
@@ -16,7 +18,7 @@ export const LogoLDOPL: LogoComponent = (props) => {
export const LogoLido: FC> = (props) => (
-
+
diff --git a/shared/transaction-modal/tx-stages-composed/tx-stage-operation-succeed-balance-shown.tsx b/shared/transaction-modal/tx-stages-composed/tx-stage-operation-succeed-balance-shown.tsx
index 8b2bd7fdc..6589234b7 100644
--- a/shared/transaction-modal/tx-stages-composed/tx-stage-operation-succeed-balance-shown.tsx
+++ b/shared/transaction-modal/tx-stages-composed/tx-stage-operation-succeed-balance-shown.tsx
@@ -3,11 +3,13 @@ import styled from 'styled-components';
import { InlineLoader } from '@lidofinance/lido-ui';
import { L2AfterStake } from 'shared/banners/l2-banners/l2-after-stake';
import { L2AfterWrap } from 'shared/banners/l2-banners/l2-after-wrap';
+import { VaultsBannerStrategies } from 'shared/banners/vaults-banner-strategies';
import { TxAmount } from '../tx-stages-parts/tx-amount';
import { SuccessText } from '../tx-stages-parts/success-text';
import { TxStageSuccess } from '../tx-stages-basic';
import type { BigNumber } from 'ethers';
+import { useFeatureFlag, VAULTS_BANNER_IS_ENABLED } from 'config/feature-flags';
export const SkeletonBalance = styled(InlineLoader).attrs({
color: 'text',
@@ -29,10 +31,19 @@ export const TxStageOperationSucceedBalanceShown = ({
operationText,
txHash,
}: TxStageOperationSucceedBalanceShownProps) => {
+ const { vaultsBannerIsEnabled } = useFeatureFlag(VAULTS_BANNER_IS_ENABLED);
+
const balanceEl = balance && (
);
+ const renderBanner = () => {
+ if (vaultsBannerIsEnabled) return ;
+ if (balanceToken === 'stETH') return ;
+ if (balanceToken === 'wstETH') return ;
+ return undefined;
+ };
+
return (
}
showEtherscan={false}
- footer={
- balanceToken === 'stETH' ? (
-
- ) : balanceToken === 'wstETH' ? (
-
- ) : undefined
- }
+ footer={renderBanner()}
/>
);
};
diff --git a/shared/wallet/connect-wallet-modal/connect-wallet-modal.tsx b/shared/wallet/connect-wallet-modal/connect-wallet-modal.tsx
index 8aac208cf..56dfe19a6 100644
--- a/shared/wallet/connect-wallet-modal/connect-wallet-modal.tsx
+++ b/shared/wallet/connect-wallet-modal/connect-wallet-modal.tsx
@@ -1,6 +1,8 @@
import { useThemeToggle } from '@lidofinance/lido-ui';
import { WalletsModalForEth } from 'reef-knot/connect-wallet-modal';
import { WalletIdsEthereum } from 'reef-knot/wallets';
+
+import { config } from 'config';
import { walletsMetrics } from 'consts/matomo-wallets-events';
const WALLETS_PINNED: WalletIdsEthereum[] = ['okx', 'browserExtension'];
@@ -13,6 +15,8 @@ export const ConnectWalletModal = () => {
shouldInvertWalletIcon={themeName === 'dark'}
metrics={walletsMetrics}
walletsPinned={WALLETS_PINNED}
+ termsLink={`${config.rootOrigin}/terms-of-use`}
+ privacyNoticeLink={`${config.rootOrigin}/privacy-notice`}
/>
);
};
diff --git a/test/consts.ts b/test/consts.ts
index eee68f600..d3de48077 100644
--- a/test/consts.ts
+++ b/test/consts.ts
@@ -98,6 +98,9 @@ const LIDO_STATS_SCHEMA = {
bid: {
type: 'number',
},
+ tsAdded: {
+ type: 'number',
+ },
currency: {
type: 'string',
},
diff --git a/utils/getErrorMessage.ts b/utils/getErrorMessage.ts
index 0b42a3edd..1678bb215 100644
--- a/utils/getErrorMessage.ts
+++ b/utils/getErrorMessage.ts
@@ -2,6 +2,7 @@ export enum ErrorMessage {
NOT_ENOUGH_ETHER = 'Not enough ether for gas.',
DENIED_SIG = 'User denied the transaction signature.',
SOMETHING_WRONG = 'Something went wrong.',
+ TRANSACTION_REVERTED = 'Transaction was included into block but reverted during execution',
ENABLE_BLIND_SIGNING = 'Please enable blind signing on your Ledger hardware wallet.',
LIMIT_REACHED = 'Transaction could not be completed because stake limit is exhausted. Please wait until the stake limit restores and try again. Otherwise, you can swap your Ethereum on 1inch platform instantly.',
DEVICE_LOCKED = 'Please unlock your Ledger hardware wallet',
@@ -32,6 +33,8 @@ export const getErrorMessage = (error: unknown): ErrorMessage => {
return ErrorMessage.LIMIT_REACHED;
case 'INVALID_REFERRAL':
return ErrorMessage.INVALID_REFERRAL;
+ case 'TRANSACTION_REVERTED':
+ return ErrorMessage.TRANSACTION_REVERTED;
case 'ENABLE_BLIND_SIGNING':
return ErrorMessage.ENABLE_BLIND_SIGNING;
case 'DEVICE_LOCKED':
@@ -49,6 +52,15 @@ export const extractCodeFromError = (
// early exit on non object error
if (!error || typeof error != 'object') return 0;
+ if (
+ 'code' in error &&
+ error.code === 'CALL_EXCEPTION' &&
+ 'receipt' in error
+ ) {
+ const receipt = error.receipt as { blockHash?: string };
+ if (receipt.blockHash?.startsWith('0x')) return 'TRANSACTION_REVERTED';
+ }
+
if ('reason' in error && typeof error.reason == 'string') {
if (error.reason.includes('STAKE_LIMIT')) return 'LIMIT_REACHED';
if (error.reason.includes('INVALID_REFERRAL')) return 'INVALID_REFERRAL';
diff --git a/yarn.lock b/yarn.lock
index 8e74363a1..e85d5b36e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2199,10 +2199,10 @@
ua-parser-js "^1.0.35"
use-callback-ref "1.2.5"
-"@lidofinance/lido-ui@^3.24.0":
- version "3.24.0"
- resolved "https://registry.yarnpkg.com/@lidofinance/lido-ui/-/lido-ui-3.24.0.tgz#2abcd5637423e672386769781c7b5dfd40b51a1e"
- integrity sha512-z43M04ZOxW0ul96MFbXOcitioGxLyo9a4TMRqMzW8Va8CeYeFwPyUbdzBuRQ/kj8Tsw0vVGGIzRqlcy1doSvBg==
+"@lidofinance/lido-ui@^3.26.0":
+ version "3.26.0"
+ resolved "https://registry.yarnpkg.com/@lidofinance/lido-ui/-/lido-ui-3.26.0.tgz#44c65abbbc3aaa84f805ca8e99dcddd4010c975e"
+ integrity sha512-W990IJAZBuaJfxh8RxZRPUFwT/+xQ93uYAr/0/8an3IIGoX+lUKmyHn22r1FCZLK19xYR8Ikm6zLr3lvCM0t2w==
dependencies:
"@styled-system/should-forward-prop" "5.1.5"
react-collapsed "3.0.2"
@@ -5101,13 +5101,6 @@ create-require@^1.1.0:
resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
-cross-env@^7.0.3:
- version "7.0.3"
- resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf"
- integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==
- dependencies:
- cross-spawn "^7.0.1"
-
cross-fetch@^3.1.4:
version "3.1.8"
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82"
@@ -5115,7 +5108,7 @@ cross-fetch@^3.1.4:
dependencies:
node-fetch "^2.6.12"
-cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
+cross-spawn@^7.0.2, cross-spawn@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==