From 68bbb7d7d30dfeafb779b84b396821c5e7a0a36e Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Fri, 1 Mar 2024 16:48:45 +0700 Subject: [PATCH 01/15] feat: support IPFS manifest subpath --- .env.example | 3 +++ env-dynamics.mjs | 3 +++ .../use-ipfs-hash-check.ts | 21 ++++++++++++++----- next.config.mjs | 2 ++ 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/.env.example b/.env.example index de3cfaa3e..25ed575d6 100644 --- a/.env.example +++ b/.env.example @@ -61,3 +61,6 @@ WALLETCONNECT_PROJECT_ID= # ETH Stake Widget API for IPFS mode WIDGET_API_BASE_PATH_FOR_IPFS= +# subpath in IPFS.json, leave empty for mainnet +IPFS_MANIFEST_SUBPATH= + diff --git a/env-dynamics.mjs b/env-dynamics.mjs index 7c97639b1..84412bd9c 100644 --- a/env-dynamics.mjs +++ b/env-dynamics.mjs @@ -36,6 +36,9 @@ export const walletconnectProjectId = process.env.WALLETCONNECT_PROJECT_ID; /** @type boolean */ export const ipfsMode = toBoolean(process.env.IPFS_MODE); +/** @type string */ +export const ipfsManifestSubpath = process.env.IPFS_MANIFEST_SUBPATH ?? ''; + /** @type string[] */ export const prefillUnsafeElRpcUrls1 = process.env.PREFILL_UNSAFE_EL_RPC_URLS_1?.split(',') ?? []; diff --git a/features/ipfs/outdated-hash-banner/use-ipfs-hash-check.ts b/features/ipfs/outdated-hash-banner/use-ipfs-hash-check.ts index 026e2d4ab..0bc0737a2 100644 --- a/features/ipfs/outdated-hash-banner/use-ipfs-hash-check.ts +++ b/features/ipfs/outdated-hash-banner/use-ipfs-hash-check.ts @@ -11,6 +11,8 @@ type EnsHashCheckReturn = { link: string; } | null; +type ReleaseInfoData = ReleaseInfo & Record; + type ReleaseInfo = { cid?: string; ens?: string; @@ -46,10 +48,19 @@ export const useIpfsHashCheck = () => { const remoteCidSWR = useLidoSWR( ['swr:ipfs-hash-check'], async (): Promise => { - const releaseInfo = await standardFetcher(IPFS_RELEASE_URL, { - headers: { Accept: 'application/json' }, - }); - if (releaseInfo.ens) { + const releaseInfoData = await standardFetcher( + IPFS_RELEASE_URL, + { + headers: { Accept: 'application/json' }, + }, + ); + + // look up for subpath + const releaseInfo = dynamics.ipfsManifestSubpath + ? releaseInfoData[dynamics.ipfsManifestSubpath] + : releaseInfoData; + + if (releaseInfo?.ens) { const resolver = await provider.getResolver(releaseInfo.ens); if (resolver) { const contentHash = await resolver.getContentHash(); @@ -62,7 +73,7 @@ export const useIpfsHashCheck = () => { } } } - if (releaseInfo.cid) { + if (releaseInfo?.cid) { return { cid: releaseInfo.cid, link: `https://${releaseInfo.cid}.ipfs.cf-ipfs.com`, diff --git a/next.config.mjs b/next.config.mjs index 5ea7889eb..768a45880 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -5,6 +5,7 @@ import generateBuildId from './scripts/generate-build-id.mjs'; buildDynamics(); const ipfsMode = process.env.IPFS_MODE == 'true'; +const ipfsManifestSubpath = process.env.IPFS_MANIFEST_SUBPATH; // https://nextjs.org/docs/pages/api-reference/next-config-js/basePath const basePath = process.env.BASE_PATH; @@ -183,5 +184,6 @@ export default withBundleAnalyzer({ rewardsBackendAPI, defaultChain, developmentMode, + ipfsManifestSubpath, }, }); From c859ba983712bf897a0d84425adeaf2ed3d19a82 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Fri, 1 Mar 2024 18:55:33 +0700 Subject: [PATCH 02/15] feat: add upgrade promt banner --- .env.example | 4 -- IPFS.json | 6 +- env-dynamics.mjs | 3 - features/ipfs/outdated-hash-banner/index.ts | 1 - .../outdated-hash-banner.tsx | 43 ------------- features/ipfs/update-promt-banner/index.ts | 1 + .../styles.tsx | 0 .../update-promt-banner.tsx | 59 +++++++++++++++++ .../use-version-check.ts} | 64 ++++++++++++++++--- next.config.mjs | 2 - 10 files changed, 119 insertions(+), 64 deletions(-) delete mode 100644 features/ipfs/outdated-hash-banner/index.ts delete mode 100644 features/ipfs/outdated-hash-banner/outdated-hash-banner.tsx create mode 100644 features/ipfs/update-promt-banner/index.ts rename features/ipfs/{outdated-hash-banner => update-promt-banner}/styles.tsx (100%) create mode 100644 features/ipfs/update-promt-banner/update-promt-banner.tsx rename features/ipfs/{outdated-hash-banner/use-ipfs-hash-check.ts => update-promt-banner/use-version-check.ts} (64%) diff --git a/.env.example b/.env.example index 25ed575d6..c62f16bdc 100644 --- a/.env.example +++ b/.env.example @@ -60,7 +60,3 @@ WALLETCONNECT_PROJECT_ID= # ETH Stake Widget API for IPFS mode WIDGET_API_BASE_PATH_FOR_IPFS= - -# subpath in IPFS.json, leave empty for mainnet -IPFS_MANIFEST_SUBPATH= - diff --git a/IPFS.json b/IPFS.json index 362732f14..6b8bc2743 100644 --- a/IPFS.json +++ b/IPFS.json @@ -1,4 +1,6 @@ { - "__warning__": "For testing purposes only", - "ens": "app.jeday.eth" + "17000": { + "__warning__": "For testing purposes only", + "ens": "app.jeday.eth" + } } diff --git a/env-dynamics.mjs b/env-dynamics.mjs index 84412bd9c..7c97639b1 100644 --- a/env-dynamics.mjs +++ b/env-dynamics.mjs @@ -36,9 +36,6 @@ export const walletconnectProjectId = process.env.WALLETCONNECT_PROJECT_ID; /** @type boolean */ export const ipfsMode = toBoolean(process.env.IPFS_MODE); -/** @type string */ -export const ipfsManifestSubpath = process.env.IPFS_MANIFEST_SUBPATH ?? ''; - /** @type string[] */ export const prefillUnsafeElRpcUrls1 = process.env.PREFILL_UNSAFE_EL_RPC_URLS_1?.split(',') ?? []; diff --git a/features/ipfs/outdated-hash-banner/index.ts b/features/ipfs/outdated-hash-banner/index.ts deleted file mode 100644 index 2c9cc7d86..000000000 --- a/features/ipfs/outdated-hash-banner/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { OutdatedHashBanner } from './outdated-hash-banner'; diff --git a/features/ipfs/outdated-hash-banner/outdated-hash-banner.tsx b/features/ipfs/outdated-hash-banner/outdated-hash-banner.tsx deleted file mode 100644 index 98e1a4028..000000000 --- a/features/ipfs/outdated-hash-banner/outdated-hash-banner.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { Button, Modal } from '@lidofinance/lido-ui'; -import { dynamics } from 'config'; -import { WarningIcon, Wrapper, WarningText } from './styles'; -import { useIpfsHashCheck } from './use-ipfs-hash-check'; -import NoSsrWrapper from 'shared/components/no-ssr-wrapper'; - -export const OutdatedHashBanner = dynamics.ipfsMode - ? () => { - const { isUpdateAvailable, data, setConditionsAccepted } = - useIpfsHashCheck(); - - return ( - - - - - - This is not the most recent version of IPFS Widget - - - - - - - - - ); - } - : () => null; diff --git a/features/ipfs/update-promt-banner/index.ts b/features/ipfs/update-promt-banner/index.ts new file mode 100644 index 000000000..350fff007 --- /dev/null +++ b/features/ipfs/update-promt-banner/index.ts @@ -0,0 +1 @@ +export { UpgradePromtBanner as OutdatedHashBanner } from './update-promt-banner'; diff --git a/features/ipfs/outdated-hash-banner/styles.tsx b/features/ipfs/update-promt-banner/styles.tsx similarity index 100% rename from features/ipfs/outdated-hash-banner/styles.tsx rename to features/ipfs/update-promt-banner/styles.tsx diff --git a/features/ipfs/update-promt-banner/update-promt-banner.tsx b/features/ipfs/update-promt-banner/update-promt-banner.tsx new file mode 100644 index 000000000..df10a2c92 --- /dev/null +++ b/features/ipfs/update-promt-banner/update-promt-banner.tsx @@ -0,0 +1,59 @@ +import { Button, Modal } from '@lidofinance/lido-ui'; +import { dynamics } from 'config'; +import { WarningIcon, Wrapper, WarningText } from './styles'; +import { useVersionCheck } from './use-version-check'; +import NoSsrWrapper from 'shared/components/no-ssr-wrapper'; + +const warningTextContent = ( + isUpdateAvailable: boolean, + isVersionUnsafe: boolean, +) => { + switch (true) { + case dynamics.ipfsMode && isUpdateAvailable && isVersionUnsafe: + return 'This version of IPFS Widget is deemed not safe to use'; + case dynamics.ipfsMode && isUpdateAvailable: + return 'This is not the most recent version of IPFS Widget'; + case isVersionUnsafe: + return 'Staking Widget is not safe to use right now'; + default: + return ''; + } +}; + +export const UpgradePromtBanner = () => { + const { isUpdateAvailable, data, setConditionsAccepted, isVersionUnsafe } = + useVersionCheck(); + + return ( + + + + + + {warningTextContent(isUpdateAvailable, isVersionUnsafe)} + + {isUpdateAvailable && ( + + + + )} + + + + + ); +}; diff --git a/features/ipfs/outdated-hash-banner/use-ipfs-hash-check.ts b/features/ipfs/update-promt-banner/use-version-check.ts similarity index 64% rename from features/ipfs/outdated-hash-banner/use-ipfs-hash-check.ts rename to features/ipfs/update-promt-banner/use-version-check.ts index 0bc0737a2..c61bfff3f 100644 --- a/features/ipfs/outdated-hash-banner/use-ipfs-hash-check.ts +++ b/features/ipfs/update-promt-banner/use-version-check.ts @@ -1,21 +1,28 @@ +import { useEffect, useState } from 'react'; import { useLidoSWR } from '@lido-sdk/react'; +import { useDisconnect } from 'reef-knot/web3-react'; +import { useDisconnect as useDisconnectWagmi } from 'wagmi'; + import { BASE_PATH_ASSET, dynamics } from 'config'; -import { useState } from 'react'; import { useMainnetStaticRpcProvider } from 'shared/hooks/use-mainnet-static-rpc-provider'; import { standardFetcher } from 'utils/standardFetcher'; import { STRATEGY_IMMUTABLE, STRATEGY_LAZY } from 'utils/swrStrategies'; +import buildInfo from 'build-info.json'; + type EnsHashCheckReturn = { cid: string; ens?: string; + leastSafeVersion?: string; link: string; } | null; -type ReleaseInfoData = ReleaseInfo & Record; +type ReleaseInfoData = Record; type ReleaseInfo = { cid?: string; ens?: string; + leastSafeVersion?: string; }; // works with any type of IPFS hash @@ -26,7 +33,32 @@ const URL_CID_REGEX = const IPFS_RELEASE_URL = 'https://raw.githubusercontent.com/lidofinance/ethereum-staking-widget/main/IPFS.json'; -export const useIpfsHashCheck = () => { +const isVersionLess = (versionA: string, versionB: string): boolean => { + const verA = versionA + .trim() + .split('.') + .map((v) => parseInt(v)); + const verB = versionB + .trim() + .split('.') + .map((v) => parseInt(v)); + + // eslint-disable-next-line unicorn/no-for-loop + for (let index = 0; index < verA.length; index++) { + const a = verA[index]; + const b = verB[index]; + // validation + if (b === undefined || isNaN(a) || isNaN(b)) return false; + if (a > b) return false; + if (a < b) return true; + } + // versions are equal + return false; +}; + +export const useVersionCheck = () => { + const { disconnect } = useDisconnect(); + const { disconnect: wagmiDisconnect } = useDisconnectWagmi(); const [areConditionsAccepted, setConditionsAccepted] = useState(false); const provider = useMainnetStaticRpcProvider(); @@ -55,11 +87,7 @@ export const useIpfsHashCheck = () => { }, ); - // look up for subpath - const releaseInfo = dynamics.ipfsManifestSubpath - ? releaseInfoData[dynamics.ipfsManifestSubpath] - : releaseInfoData; - + const releaseInfo = releaseInfoData[dynamics.defaultChain.toString()]; if (releaseInfo?.ens) { const resolver = await provider.getResolver(releaseInfo.ens); if (resolver) { @@ -69,6 +97,7 @@ export const useIpfsHashCheck = () => { cid: contentHash, ens: releaseInfo.ens, link: `https://${releaseInfo.ens}.limo`, + leastSafeVersion: releaseInfo.leastSafeVersion, }; } } @@ -77,11 +106,12 @@ export const useIpfsHashCheck = () => { return { cid: releaseInfo.cid, link: `https://${releaseInfo.cid}.ipfs.cf-ipfs.com`, + leastSafeVersion: releaseInfo.leastSafeVersion, }; } return null; }, - { ...STRATEGY_LAZY, isPaused: () => !dynamics.ipfsMode }, + { ...STRATEGY_LAZY }, ); const isUpdateAvailable = Boolean( @@ -91,9 +121,25 @@ export const useIpfsHashCheck = () => { remoteCidSWR.data.cid !== currentCidSWR.data, ); + const isVersionUnsafe = Boolean( + !areConditionsAccepted && + remoteCidSWR.data?.leastSafeVersion && + (remoteCidSWR.data.leastSafeVersion === 'none' || + isVersionLess(buildInfo.version, remoteCidSWR.data.leastSafeVersion)), + ); + + // disconnect wallet + useEffect(() => { + if (isVersionUnsafe) { + disconnect?.(); + wagmiDisconnect(); + } + }, [disconnect, isVersionUnsafe, wagmiDisconnect]); + return { isUpdateAvailable, setConditionsAccepted, + isVersionUnsafe, get data() { return { remoteCid: remoteCidSWR.data?.cid, diff --git a/next.config.mjs b/next.config.mjs index 768a45880..5ea7889eb 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -5,7 +5,6 @@ import generateBuildId from './scripts/generate-build-id.mjs'; buildDynamics(); const ipfsMode = process.env.IPFS_MODE == 'true'; -const ipfsManifestSubpath = process.env.IPFS_MANIFEST_SUBPATH; // https://nextjs.org/docs/pages/api-reference/next-config-js/basePath const basePath = process.env.BASE_PATH; @@ -184,6 +183,5 @@ export default withBundleAnalyzer({ rewardsBackendAPI, defaultChain, developmentMode, - ipfsManifestSubpath, }, }); From b7d1f6a6335c4c7416605b1e818409cb383ff897 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Fri, 1 Mar 2024 18:57:02 +0700 Subject: [PATCH 03/15] fix: imports --- features/ipfs/update-promt-banner/index.ts | 2 +- pages/_app.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/features/ipfs/update-promt-banner/index.ts b/features/ipfs/update-promt-banner/index.ts index 350fff007..066a337a8 100644 --- a/features/ipfs/update-promt-banner/index.ts +++ b/features/ipfs/update-promt-banner/index.ts @@ -1 +1 @@ -export { UpgradePromtBanner as OutdatedHashBanner } from './update-promt-banner'; +export { UpgradePromtBanner } from './update-promt-banner'; diff --git a/pages/_app.tsx b/pages/_app.tsx index 93f714ebf..7b83a9613 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -15,7 +15,7 @@ import { Providers } from 'providers'; import { BackgroundGradient } from 'shared/components/background-gradient/background-gradient'; import { nprogress, COOKIES_ALLOWED_FULL_KEY } from 'utils'; import { withCsp } from 'utilsApi/withCSP'; -import { OutdatedHashBanner } from 'features/ipfs/outdated-hash-banner'; +import { UpgradePromtBanner } from 'features/ipfs/update-promt-banner'; // Migrations old theme cookies to new cross domain cookies migrationThemeCookiesToCrossDomainCookiesClientSide(); @@ -56,7 +56,7 @@ const AppWrapper = (props: AppProps): JSX.Element => { - + ); }; From 58d148ed0b5d35d13f0cce0affcf997f98f7b277 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Fri, 1 Mar 2024 19:14:57 +0700 Subject: [PATCH 04/15] fix: condition --- features/ipfs/update-promt-banner/update-promt-banner.tsx | 2 +- features/ipfs/update-promt-banner/use-version-check.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/features/ipfs/update-promt-banner/update-promt-banner.tsx b/features/ipfs/update-promt-banner/update-promt-banner.tsx index df10a2c92..cb66dafd6 100644 --- a/features/ipfs/update-promt-banner/update-promt-banner.tsx +++ b/features/ipfs/update-promt-banner/update-promt-banner.tsx @@ -9,7 +9,7 @@ const warningTextContent = ( isVersionUnsafe: boolean, ) => { switch (true) { - case dynamics.ipfsMode && isUpdateAvailable && isVersionUnsafe: + case dynamics.ipfsMode && isVersionUnsafe: return 'This version of IPFS Widget is deemed not safe to use'; case dynamics.ipfsMode && isUpdateAvailable: return 'This is not the most recent version of IPFS Widget'; diff --git a/features/ipfs/update-promt-banner/use-version-check.ts b/features/ipfs/update-promt-banner/use-version-check.ts index c61bfff3f..3ef72997c 100644 --- a/features/ipfs/update-promt-banner/use-version-check.ts +++ b/features/ipfs/update-promt-banner/use-version-check.ts @@ -118,7 +118,8 @@ export const useVersionCheck = () => { !areConditionsAccepted && remoteCidSWR.data && currentCidSWR.data && - remoteCidSWR.data.cid !== currentCidSWR.data, + remoteCidSWR.data.cid !== currentCidSWR.data && + remoteCidSWR.data.leastSafeVersion !== 'none', ); const isVersionUnsafe = Boolean( From 1d6c4c1377b31f13234c5e435edfaf9d09d2ace0 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Tue, 5 Mar 2024 19:34:38 +0700 Subject: [PATCH 05/15] feat: text from update promt banner --- features/ipfs/faq-placeholder.tsx | 5 + features/ipfs/home-page-ipfs.tsx | 4 +- features/ipfs/index.ts | 5 + features/ipfs/update-promt-banner/styles.tsx | 13 +- .../update-promt-banner.tsx | 129 ++++++++++++++---- .../update-promt-banner/use-version-check.ts | 36 +++-- features/stake/stake.tsx | 7 +- features/withdrawals/claim/claim.tsx | 7 +- features/withdrawals/request/request.tsx | 10 +- features/wsteth/wrap-unwrap-tabs.tsx | 7 +- pages/_app.tsx | 2 +- pages/_document.tsx | 2 +- pages/index.tsx | 2 +- .../only-infra-render/only-infra-render.tsx | 11 +- 14 files changed, 180 insertions(+), 60 deletions(-) create mode 100644 features/ipfs/faq-placeholder.tsx create mode 100644 features/ipfs/index.ts diff --git a/features/ipfs/faq-placeholder.tsx b/features/ipfs/faq-placeholder.tsx new file mode 100644 index 000000000..abe24ec58 --- /dev/null +++ b/features/ipfs/faq-placeholder.tsx @@ -0,0 +1,5 @@ +import styled from 'styled-components'; + +export const FaqPlaceholder = styled.div` + margin-top: 32px; +`; diff --git a/features/ipfs/home-page-ipfs.tsx b/features/ipfs/home-page-ipfs.tsx index 0c9a85fb2..aabf9b06e 100644 --- a/features/ipfs/home-page-ipfs.tsx +++ b/features/ipfs/home-page-ipfs.tsx @@ -37,7 +37,7 @@ const IPFS_ROUTABLE_PAGES = [ getPathWithoutFirstSlash(SETTINGS_PATH), ]; -const HomePageIpfs: FC = () => { +export const HomePageIpfs: FC = () => { const router = useRouter(); const { asPath } = router; @@ -114,5 +114,3 @@ const HomePageIpfs: FC = () => { // Fix for runtime of `dev-ipfs` (see: package.json scripts) return {spaPage}; }; - -export default HomePageIpfs; diff --git a/features/ipfs/index.ts b/features/ipfs/index.ts new file mode 100644 index 000000000..d723af8a2 --- /dev/null +++ b/features/ipfs/index.ts @@ -0,0 +1,5 @@ +export { HomePageIpfs } from './home-page-ipfs'; + +export { FaqPlaceholder } from './faq-placeholder'; +export { UpgradePromtBanner } from './update-promt-banner'; +export { InsertIpfsBaseScript } from './ipfs-base-script'; diff --git a/features/ipfs/update-promt-banner/styles.tsx b/features/ipfs/update-promt-banner/styles.tsx index 41fd9ad68..2529f9724 100644 --- a/features/ipfs/update-promt-banner/styles.tsx +++ b/features/ipfs/update-promt-banner/styles.tsx @@ -30,9 +30,20 @@ export const Wrapper = styled.div` export const WarningText = styled(Text).attrs({ weight: 700, - size: 'lg', })` + font-size: 26px; text-align: center; margin: 12px 0 28px; text-wrap: balance; `; + +export const WarningSubText = styled(Text).attrs({ + weight: 400, + size: 'xs', + color: 'secondary', +})` + text-align: center; + margin: 0; + margin-top: 12px; + text-wrap: wrap; +`; diff --git a/features/ipfs/update-promt-banner/update-promt-banner.tsx b/features/ipfs/update-promt-banner/update-promt-banner.tsx index cb66dafd6..25add3646 100644 --- a/features/ipfs/update-promt-banner/update-promt-banner.tsx +++ b/features/ipfs/update-promt-banner/update-promt-banner.tsx @@ -1,37 +1,110 @@ import { Button, Modal } from '@lidofinance/lido-ui'; + import { dynamics } from 'config'; -import { WarningIcon, Wrapper, WarningText } from './styles'; + +import { WarningIcon, Wrapper, WarningText, WarningSubText } from './styles'; import { useVersionCheck } from './use-version-check'; import NoSsrWrapper from 'shared/components/no-ssr-wrapper'; -const warningTextContent = ( - isUpdateAvailable: boolean, - isVersionUnsafe: boolean, -) => { +const LIDO_TWITTER_LINK = 'https://twitter.com/LidoFinance'; + +type WarningContentOptions = { + isUpdateAvailable: boolean; + isVersionUnsafe: boolean; + isNotVerifiable: boolean; + isIpfs: boolean; +}; + +const warningContent = ({ + isUpdateAvailable, + isVersionUnsafe, + isNotVerifiable, + isIpfs, +}: WarningContentOptions) => { switch (true) { - case dynamics.ipfsMode && isVersionUnsafe: - return 'This version of IPFS Widget is deemed not safe to use'; - case dynamics.ipfsMode && isUpdateAvailable: - return 'This is not the most recent version of IPFS Widget'; - case isVersionUnsafe: - return 'Staking Widget is not safe to use right now'; + case isIpfs && isNotVerifiable: + return { + content: ( + + We could not verify security of this IPFS version + + ), + canClose: true, + }; + case isIpfs && isVersionUnsafe && isUpdateAvailable: + return { + content: ( + + This IPFS version has issues that could impact your experience + + ), + canClose: false, + }; + case isVersionUnsafe && !isUpdateAvailable: + return { + content: ( + + The staking widget is currently down. Resolving is in progress + + ), + canClose: false, + showTwitterLink: true, + }; + case isIpfs && isUpdateAvailable: + return { + content: ( + + This is not the most recent version of IPFS Widget +
+ + Note that you may not find new features or functionality in this + version + +
+ ), + canClose: true, + }; default: - return ''; + return { content: null }; } }; export const UpgradePromtBanner = () => { - const { isUpdateAvailable, data, setConditionsAccepted, isVersionUnsafe } = - useVersionCheck(); + const { + areConditionsAccepted, + setConditionsAccepted, + isUpdateAvailable, + isVersionUnsafe, + isNotVerifiable, + data, + } = useVersionCheck(); + + const { content, canClose, showTwitterLink } = warningContent({ + isUpdateAvailable, + isVersionUnsafe, + isNotVerifiable, + isIpfs: dynamics.ipfsMode, + }); + + const showModal = !!content && !(canClose && areConditionsAccepted); return ( - + - - {warningTextContent(isUpdateAvailable, isVersionUnsafe)} - + {content} + {showTwitterLink && ( + + + + )} {isUpdateAvailable && ( { )} - + {canClose && ( + + )} diff --git a/features/ipfs/update-promt-banner/use-version-check.ts b/features/ipfs/update-promt-banner/use-version-check.ts index 3ef72997c..108005229 100644 --- a/features/ipfs/update-promt-banner/use-version-check.ts +++ b/features/ipfs/update-promt-banner/use-version-check.ts @@ -77,7 +77,7 @@ export const useVersionCheck = () => { ); // ens cid extraction - const remoteCidSWR = useLidoSWR( + const remoteVersionSWR = useLidoSWR( ['swr:ipfs-hash-check'], async (): Promise => { const releaseInfoData = await standardFetcher( @@ -115,20 +115,23 @@ export const useVersionCheck = () => { ); const isUpdateAvailable = Boolean( - !areConditionsAccepted && - remoteCidSWR.data && + remoteVersionSWR.data && currentCidSWR.data && - remoteCidSWR.data.cid !== currentCidSWR.data && - remoteCidSWR.data.leastSafeVersion !== 'none', + remoteVersionSWR.data.cid !== currentCidSWR.data && + remoteVersionSWR.data.leastSafeVersion !== 'none', ); const isVersionUnsafe = Boolean( - !areConditionsAccepted && - remoteCidSWR.data?.leastSafeVersion && - (remoteCidSWR.data.leastSafeVersion === 'none' || - isVersionLess(buildInfo.version, remoteCidSWR.data.leastSafeVersion)), + remoteVersionSWR.data?.leastSafeVersion && + (remoteVersionSWR.data.leastSafeVersion === 'none' || + isVersionLess( + buildInfo.version, + remoteVersionSWR.data.leastSafeVersion, + )), ); + const isNotVerifiable = !!remoteVersionSWR.error; + // disconnect wallet useEffect(() => { if (isVersionUnsafe) { @@ -138,24 +141,27 @@ export const useVersionCheck = () => { }, [disconnect, isVersionUnsafe, wagmiDisconnect]); return { - isUpdateAvailable, setConditionsAccepted, + areConditionsAccepted, + isNotVerifiable, isVersionUnsafe, + isUpdateAvailable, + get data() { return { - remoteCid: remoteCidSWR.data?.cid, + remoteCid: remoteVersionSWR.data?.cid, currentCid: currentCidSWR.data, - remoteCidLink: remoteCidSWR.data?.link, + remoteCidLink: remoteVersionSWR.data?.link, }; }, get initialLoading() { - return remoteCidSWR.initialLoading || currentCidSWR.initialLoading; + return remoteVersionSWR.initialLoading || currentCidSWR.initialLoading; }, get loading() { - return remoteCidSWR.loading || currentCidSWR.loading; + return remoteVersionSWR.loading || currentCidSWR.loading; }, get error() { - return remoteCidSWR.error || currentCidSWR.error; + return remoteVersionSWR.error || currentCidSWR.error; }, }; }; diff --git a/features/stake/stake.tsx b/features/stake/stake.tsx index 7f89b7f2a..103226bcb 100644 --- a/features/stake/stake.tsx +++ b/features/stake/stake.tsx @@ -1,7 +1,8 @@ -import { dynamics } from 'config'; +import { FaqPlaceholder } from 'features/ipfs'; import { useWeb3Key } from 'shared/hooks/useWeb3Key'; import NoSSRWrapper from 'shared/components/no-ssr-wrapper'; import { GoerliSunsetBanner } from 'shared/banners/goerli-sunset'; +import { OnlyInfraRender } from 'shared/components/only-infra-render'; import { StakeFaq } from './stake-faq/stake-faq'; import { LidoStats } from './lido-stats/lido-stats'; @@ -16,7 +17,9 @@ export const Stake = () => { - {!dynamics.ipfsMode && } + }> + + ); }; diff --git a/features/withdrawals/claim/claim.tsx b/features/withdrawals/claim/claim.tsx index 19f0c6b98..af869e14a 100644 --- a/features/withdrawals/claim/claim.tsx +++ b/features/withdrawals/claim/claim.tsx @@ -1,11 +1,12 @@ -import { dynamics } from 'config'; import { TransactionModalProvider } from 'shared/transaction-modal/transaction-modal-context'; import { ClaimFaq } from 'features/withdrawals/withdrawals-faq/claim-faq'; +import { FaqPlaceholder } from 'features/ipfs'; import { ClaimForm } from './form'; import { TxClaimModal } from './tx-modal'; import { ClaimWallet } from './wallet'; import { ClaimFormProvider } from './claim-form-context'; +import { OnlyInfraRender } from 'shared/components/only-infra-render'; export const Claim = () => { return ( @@ -13,7 +14,9 @@ export const Claim = () => { - {!dynamics.ipfsMode && } + }> + + diff --git a/features/withdrawals/request/request.tsx b/features/withdrawals/request/request.tsx index 08b1bf5db..7b6b34581 100644 --- a/features/withdrawals/request/request.tsx +++ b/features/withdrawals/request/request.tsx @@ -1,10 +1,12 @@ -import { dynamics } from 'config'; +import { TransactionModalProvider } from 'shared/transaction-modal'; +import { FaqPlaceholder } from 'features/ipfs'; +import { OnlyInfraRender } from 'shared/components/only-infra-render'; + import { RequestFormProvider } from './request-form-context'; import { RequestFaq } from '../withdrawals-faq/request-faq'; import { RequestForm } from './form'; import { TxRequestModal } from './tx-modal'; import { RequestWallet } from './wallet'; -import { TransactionModalProvider } from 'shared/transaction-modal'; export const Request = () => { return ( @@ -12,7 +14,9 @@ export const Request = () => { - {!dynamics.ipfsMode && } + }> + + diff --git a/features/wsteth/wrap-unwrap-tabs.tsx b/features/wsteth/wrap-unwrap-tabs.tsx index 3e8f860b7..76e01abda 100644 --- a/features/wsteth/wrap-unwrap-tabs.tsx +++ b/features/wsteth/wrap-unwrap-tabs.tsx @@ -1,4 +1,3 @@ -import { dynamics } from 'config'; import { WRAP_PATH, WRAP_UNWRAP_PATH } from 'config/urls'; import { Wallet } from 'features/wsteth/shared/wallet'; import { WrapForm } from 'features/wsteth/wrap/wrap-form/wrap-form'; @@ -8,6 +7,8 @@ import NoSsrWrapper from 'shared/components/no-ssr-wrapper'; import { WrapFaq } from './shared/wrap-faq/wrap-faq'; import { UnwrapForm } from './unwrap/unwrap-form'; import { GoerliSunsetBanner } from 'shared/banners/goerli-sunset'; +import { OnlyInfraRender } from 'shared/components/only-infra-render'; +import { FaqPlaceholder } from 'features/ipfs'; const NAV_ROUTES = [ { name: 'Wrap', path: WRAP_PATH }, @@ -28,7 +29,9 @@ export const WrapUnwrapTabs = ({ mode }: WrapUnwrapLayoutProps) => { {isUnwrapMode ? : } - {!dynamics.ipfsMode && } + }> + + ); }; diff --git a/pages/_app.tsx b/pages/_app.tsx index 7b83a9613..ac857f959 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -15,7 +15,7 @@ import { Providers } from 'providers'; import { BackgroundGradient } from 'shared/components/background-gradient/background-gradient'; import { nprogress, COOKIES_ALLOWED_FULL_KEY } from 'utils'; import { withCsp } from 'utilsApi/withCSP'; -import { UpgradePromtBanner } from 'features/ipfs/update-promt-banner'; +import { UpgradePromtBanner } from 'features/ipfs'; // Migrations old theme cookies to new cross domain cookies migrationThemeCookiesToCrossDomainCookiesClientSide(); diff --git a/pages/_document.tsx b/pages/_document.tsx index 67d48a51c..ea242fc36 100644 --- a/pages/_document.tsx +++ b/pages/_document.tsx @@ -11,7 +11,7 @@ import { ServerStyleSheet } from 'styled-components'; import { Fonts, LidoUIHead } from '@lidofinance/lido-ui'; import { dynamics, BASE_PATH_ASSET } from 'config'; -import { InsertIpfsBaseScript } from 'features/ipfs/ipfs-base-script'; +import { InsertIpfsBaseScript } from 'features/ipfs'; import { contentSecurityPolicy } from 'utilsApi/withCSP'; let host = 'https://stake.lido.fi'; diff --git a/pages/index.tsx b/pages/index.tsx index 7f1467a67..dabc54c2b 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,6 +1,6 @@ import { dynamics } from 'config'; import { StakePage } from 'features/stake'; -import HomePageIpfs from 'features/ipfs/home-page-ipfs'; +import { HomePageIpfs } from 'features/ipfs'; export default dynamics.ipfsMode ? HomePageIpfs : StakePage; diff --git a/shared/components/only-infra-render/only-infra-render.tsx b/shared/components/only-infra-render/only-infra-render.tsx index 16f7083e8..ad6a6d19f 100644 --- a/shared/components/only-infra-render/only-infra-render.tsx +++ b/shared/components/only-infra-render/only-infra-render.tsx @@ -1,5 +1,12 @@ import { dynamics } from 'config'; -export const OnlyInfraRender = ({ children }: React.PropsWithChildren) => { - return !dynamics.ipfsMode ? <>{children} : null; +type OnlyInfraRenderProps = { + placeholder?: React.ReactNode; +}; + +export const OnlyInfraRender = ({ + children, + placeholder = null, +}: React.PropsWithChildren) => { + return !dynamics.ipfsMode ? <>{children} : placeholder; }; From b7dacbde51b338800c8ae467a7e4c4971b1cd884 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Wed, 6 Mar 2024 13:42:24 +0700 Subject: [PATCH 06/15] fix: switch to force disconnect --- .../update-promt-banner/use-version-check.ts | 23 ++++++++++++------- providers/client-config.tsx | 8 ++++++- shared/wallet/connect/connect.tsx | 9 +++++++- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/features/ipfs/update-promt-banner/use-version-check.ts b/features/ipfs/update-promt-banner/use-version-check.ts index 108005229..6c6f353fd 100644 --- a/features/ipfs/update-promt-banner/use-version-check.ts +++ b/features/ipfs/update-promt-banner/use-version-check.ts @@ -1,7 +1,6 @@ import { useEffect, useState } from 'react'; import { useLidoSWR } from '@lido-sdk/react'; -import { useDisconnect } from 'reef-knot/web3-react'; -import { useDisconnect as useDisconnectWagmi } from 'wagmi'; +import { useForceDisconnect } from 'reef-knot/web3-react'; import { BASE_PATH_ASSET, dynamics } from 'config'; import { useMainnetStaticRpcProvider } from 'shared/hooks/use-mainnet-static-rpc-provider'; @@ -9,6 +8,7 @@ import { standardFetcher } from 'utils/standardFetcher'; import { STRATEGY_IMMUTABLE, STRATEGY_LAZY } from 'utils/swrStrategies'; import buildInfo from 'build-info.json'; +import { useClientConfig } from 'providers/client-config'; type EnsHashCheckReturn = { cid: string; @@ -57,8 +57,8 @@ const isVersionLess = (versionA: string, versionB: string): boolean => { }; export const useVersionCheck = () => { - const { disconnect } = useDisconnect(); - const { disconnect: wagmiDisconnect } = useDisconnectWagmi(); + const { setIsWalletConnectionAllowed } = useClientConfig(); + const { disconnect } = useForceDisconnect(); const [areConditionsAccepted, setConditionsAccepted] = useState(false); const provider = useMainnetStaticRpcProvider(); @@ -132,13 +132,20 @@ export const useVersionCheck = () => { const isNotVerifiable = !!remoteVersionSWR.error; - // disconnect wallet + // disconnect wallet and disallow connection for unsafe versions useEffect(() => { if (isVersionUnsafe) { - disconnect?.(); - wagmiDisconnect(); + setIsWalletConnectionAllowed(false); } - }, [disconnect, isVersionUnsafe, wagmiDisconnect]); + if (isVersionUnsafe || (dynamics.ipfsMode && isNotVerifiable)) { + disconnect(); + } + }, [ + disconnect, + isNotVerifiable, + isVersionUnsafe, + setIsWalletConnectionAllowed, + ]); return { setConditionsAccepted, diff --git a/providers/client-config.tsx b/providers/client-config.tsx index f5e40f737..fb1f5119d 100644 --- a/providers/client-config.tsx +++ b/providers/client-config.tsx @@ -23,6 +23,8 @@ type SavedClientConfig = { type ClientConfigContext = EnvConfigParsed & { savedClientConfig: SavedClientConfig; setSavedClientConfig: (config: SavedClientConfig) => void; + isWalletConnectionAllowed: boolean; + setIsWalletConnectionAllowed: (isAllowed: boolean) => void; }; export const ClientConfigContext = createContext( @@ -44,6 +46,8 @@ export const ClientConfigProvider = ({ children }: PropsWithChildren) => { STORAGE_CLIENT_CONFIG, DEFAULT_STATE, ); + const [isWalletConnectionAllowed, setIsWalletConnectionAllowed] = + useState(true); const [savedClientConfig, setSavedClientConfig] = useState(restoredSettings); @@ -63,8 +67,10 @@ export const ClientConfigProvider = ({ children }: PropsWithChildren) => { ...envConfig, savedClientConfig, setSavedClientConfig: setSavedConfigAndRemember, + isWalletConnectionAllowed, + setIsWalletConnectionAllowed, }; - }, [savedClientConfig, setSavedConfigAndRemember]); + }, [isWalletConnectionAllowed, savedClientConfig, setSavedConfigAndRemember]); return ( diff --git a/shared/wallet/connect/connect.tsx b/shared/wallet/connect/connect.tsx index f7276520d..509033270 100644 --- a/shared/wallet/connect/connect.tsx +++ b/shared/wallet/connect/connect.tsx @@ -4,8 +4,10 @@ import { wrapWithEventTrack } from '@lidofinance/analytics-matomo'; import { useModal } from 'shared/hooks'; import { MODAL } from 'providers'; import { MATOMO_CLICK_EVENTS } from 'config'; +import { useClientConfig } from 'providers/client-config'; export const Connect: FC = (props) => { + const { isWalletConnectionAllowed } = useClientConfig(); const { onClick, ...rest } = props; const { openModal } = useModal(MODAL.connect); @@ -15,7 +17,12 @@ export const Connect: FC = (props) => { ); return ( - ); From 0b43040fe8fafd205a82ccab56647aa497312fc9 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Wed, 6 Mar 2024 13:44:10 +0700 Subject: [PATCH 07/15] fix: infra render --- shared/components/only-infra-render/only-infra-render.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/components/only-infra-render/only-infra-render.tsx b/shared/components/only-infra-render/only-infra-render.tsx index ad6a6d19f..d33a32db8 100644 --- a/shared/components/only-infra-render/only-infra-render.tsx +++ b/shared/components/only-infra-render/only-infra-render.tsx @@ -8,5 +8,5 @@ export const OnlyInfraRender = ({ children, placeholder = null, }: React.PropsWithChildren) => { - return !dynamics.ipfsMode ? <>{children} : placeholder; + return <>{dynamics.ipfsMode ? placeholder : children}; }; From 346ce39b16626e5d62b870290860182e948bc9c9 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Mon, 11 Mar 2024 18:39:28 +0700 Subject: [PATCH 08/15] fix: banner conditions --- .../update-promt-banner.tsx | 25 +++++++++++-------- .../update-promt-banner/use-version-check.ts | 6 +++-- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/features/ipfs/update-promt-banner/update-promt-banner.tsx b/features/ipfs/update-promt-banner/update-promt-banner.tsx index 25add3646..ea1d9ad1c 100644 --- a/features/ipfs/update-promt-banner/update-promt-banner.tsx +++ b/features/ipfs/update-promt-banner/update-promt-banner.tsx @@ -22,15 +22,19 @@ const warningContent = ({ isIpfs, }: WarningContentOptions) => { switch (true) { + // not veryfiable, only for IPFS case isIpfs && isNotVerifiable: return { content: ( - We could not verify security of this IPFS version + This IPFS version can’t be verified +
+ Please try again later
), - canClose: true, + canClose: false, }; + // IPFS ver is less than leastSafeVersion, but new version is available case isIpfs && isVersionUnsafe && isUpdateAvailable: return { content: ( @@ -40,25 +44,26 @@ const warningContent = ({ ), canClose: false, }; - case isVersionUnsafe && !isUpdateAvailable: + // we can show this banner on both infra and IPFS + case isVersionUnsafe && (!isIpfs || !isUpdateAvailable): return { content: ( - The staking widget is currently down. Resolving is in progress + The Lido staking widget is currently down. A fix is in progress ), canClose: false, showTwitterLink: true, }; + // outdated IPFS case isIpfs && isUpdateAvailable: return { content: ( - This is not the most recent version of IPFS Widget + This is not the most up to date version of the IPFS widget
- Note that you may not find new features or functionality in this - version + Please note that the functionality of this version may be lacking
), @@ -101,7 +106,7 @@ export const UpgradePromtBanner = () => { rel="noopener noreferrer" > )} @@ -112,7 +117,7 @@ export const UpgradePromtBanner = () => { rel="noopener noreferrer" > )} @@ -124,7 +129,7 @@ export const UpgradePromtBanner = () => { variant="outlined" onClick={() => setConditionsAccepted(true)} > - Accept possible issues and proceed + Accept the possible issues and proceed )} diff --git a/features/ipfs/update-promt-banner/use-version-check.ts b/features/ipfs/update-promt-banner/use-version-check.ts index 6c6f353fd..29213736a 100644 --- a/features/ipfs/update-promt-banner/use-version-check.ts +++ b/features/ipfs/update-promt-banner/use-version-check.ts @@ -10,6 +10,8 @@ import { STRATEGY_IMMUTABLE, STRATEGY_LAZY } from 'utils/swrStrategies'; import buildInfo from 'build-info.json'; import { useClientConfig } from 'providers/client-config'; +export const NO_SAFE_VERSION = 'NONE_AVAILABLE'; + type EnsHashCheckReturn = { cid: string; ens?: string; @@ -118,12 +120,12 @@ export const useVersionCheck = () => { remoteVersionSWR.data && currentCidSWR.data && remoteVersionSWR.data.cid !== currentCidSWR.data && - remoteVersionSWR.data.leastSafeVersion !== 'none', + remoteVersionSWR.data.leastSafeVersion !== NO_SAFE_VERSION, ); const isVersionUnsafe = Boolean( remoteVersionSWR.data?.leastSafeVersion && - (remoteVersionSWR.data.leastSafeVersion === 'none' || + (remoteVersionSWR.data.leastSafeVersion === NO_SAFE_VERSION || isVersionLess( buildInfo.version, remoteVersionSWR.data.leastSafeVersion, From 410a98a0de9f7eb582eda0ff886b37a789a7b9a6 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Mon, 11 Mar 2024 20:42:47 +0700 Subject: [PATCH 09/15] fix: add disconnect support --- features/ipfs/update-promt-banner/styles.tsx | 1 + features/ipfs/update-promt-banner/use-version-check.ts | 8 ++++---- providers/web3.tsx | 2 ++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/features/ipfs/update-promt-banner/styles.tsx b/features/ipfs/update-promt-banner/styles.tsx index 2529f9724..d75d911b7 100644 --- a/features/ipfs/update-promt-banner/styles.tsx +++ b/features/ipfs/update-promt-banner/styles.tsx @@ -40,6 +40,7 @@ export const WarningText = styled(Text).attrs({ export const WarningSubText = styled(Text).attrs({ weight: 400, size: 'xs', + as: 'span', color: 'secondary', })` text-align: center; diff --git a/features/ipfs/update-promt-banner/use-version-check.ts b/features/ipfs/update-promt-banner/use-version-check.ts index 29213736a..1ed8db08e 100644 --- a/features/ipfs/update-promt-banner/use-version-check.ts +++ b/features/ipfs/update-promt-banner/use-version-check.ts @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react'; import { useLidoSWR } from '@lido-sdk/react'; -import { useForceDisconnect } from 'reef-knot/web3-react'; +import { useForceDisconnect } from 'reef-knot/core-react'; import { BASE_PATH_ASSET, dynamics } from 'config'; import { useMainnetStaticRpcProvider } from 'shared/hooks/use-mainnet-static-rpc-provider'; @@ -60,7 +60,7 @@ const isVersionLess = (versionA: string, versionB: string): boolean => { export const useVersionCheck = () => { const { setIsWalletConnectionAllowed } = useClientConfig(); - const { disconnect } = useForceDisconnect(); + const { forceDisconnect } = useForceDisconnect(); const [areConditionsAccepted, setConditionsAccepted] = useState(false); const provider = useMainnetStaticRpcProvider(); @@ -140,10 +140,10 @@ export const useVersionCheck = () => { setIsWalletConnectionAllowed(false); } if (isVersionUnsafe || (dynamics.ipfsMode && isNotVerifiable)) { - disconnect(); + forceDisconnect(); } }, [ - disconnect, + forceDisconnect, isNotVerifiable, isVersionUnsafe, setIsWalletConnectionAllowed, diff --git a/providers/web3.tsx b/providers/web3.tsx index c1998f9b3..dd7a27208 100644 --- a/providers/web3.tsx +++ b/providers/web3.tsx @@ -11,6 +11,7 @@ import { useGetRpcUrlByChainId } from 'config'; import { SDKLegacyProvider } from './sdk-legacy'; const Web3Provider: FC = ({ children }) => { + const { isWalletConnectionAllowed } = useClientConfig(); const { defaultChain: defaultChainId, supportedChainIds, @@ -95,6 +96,7 @@ const Web3Provider: FC = ({ children }) => { return ( Date: Mon, 11 Mar 2024 21:11:42 +0700 Subject: [PATCH 10/15] fix: disconnect --- .../update-promt-banner/use-version-check.ts | 3 ++ providers/web3.tsx | 3 +- shared/wallet/wallet-modal/wallet-modal.tsx | 28 ++++++++----------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/features/ipfs/update-promt-banner/use-version-check.ts b/features/ipfs/update-promt-banner/use-version-check.ts index 1ed8db08e..6508b8505 100644 --- a/features/ipfs/update-promt-banner/use-version-check.ts +++ b/features/ipfs/update-promt-banner/use-version-check.ts @@ -9,6 +9,7 @@ import { STRATEGY_IMMUTABLE, STRATEGY_LAZY } from 'utils/swrStrategies'; import buildInfo from 'build-info.json'; import { useClientConfig } from 'providers/client-config'; +import { useWeb3 } from 'reef-knot/web3-react'; export const NO_SAFE_VERSION = 'NONE_AVAILABLE'; @@ -59,6 +60,7 @@ const isVersionLess = (versionA: string, versionB: string): boolean => { }; export const useVersionCheck = () => { + const { active } = useWeb3(); const { setIsWalletConnectionAllowed } = useClientConfig(); const { forceDisconnect } = useForceDisconnect(); const [areConditionsAccepted, setConditionsAccepted] = useState(false); @@ -143,6 +145,7 @@ export const useVersionCheck = () => { forceDisconnect(); } }, [ + active, forceDisconnect, isNotVerifiable, isVersionUnsafe, diff --git a/providers/web3.tsx b/providers/web3.tsx index dd7a27208..2cbcb5dd6 100644 --- a/providers/web3.tsx +++ b/providers/web3.tsx @@ -81,11 +81,12 @@ const Web3Provider: FC = ({ children }) => { return createClient({ connectors, - autoConnect: true, + autoConnect: isWalletConnectionAllowed, provider, webSocketProvider, }); }, [ + isWalletConnectionAllowed, supportedChains, defaultChain, backendRPC, diff --git a/shared/wallet/wallet-modal/wallet-modal.tsx b/shared/wallet/wallet-modal/wallet-modal.tsx index 08c54b9d6..33361423b 100644 --- a/shared/wallet/wallet-modal/wallet-modal.tsx +++ b/shared/wallet/wallet-modal/wallet-modal.tsx @@ -1,3 +1,4 @@ +import { useCallback } from 'react'; import { ButtonIcon, Modal, @@ -6,12 +7,12 @@ import { Copy, Address, } from '@lidofinance/lido-ui'; +import { useEtherscanOpen } from '@lido-sdk/react'; +import { useConnectorInfo, useDisconnect } from 'reef-knot/core-react'; +import { useWeb3 } from 'reef-knot/web3-react'; + import type { ModalComponentType } from 'providers/modal-provider'; -import { useEtherscanOpen, useSDK } from '@lido-sdk/react'; -import { useConnectorInfo, useDisconnect } from 'reef-knot/web3-react'; import { useCopyToClipboard } from 'shared/hooks'; -import { useCallback } from 'react'; -import { useDisconnect as useDisconnectWagmi } from 'wagmi'; import { WalletModalContentStyle, WalletModalConnectedStyle, @@ -22,31 +23,26 @@ import { WalletModalActionsStyle, } from './styles'; -export const WalletModal: ModalComponentType = (props) => { - const { onClose } = props; - const { account } = useSDK(); - const { providerName } = useConnectorInfo(); +export const WalletModal: ModalComponentType = ({ onClose, ...props }) => { + const { account } = useWeb3(); + const { connectorName } = useConnectorInfo(); const { disconnect } = useDisconnect(); - const { disconnect: wagmiDisconnect } = useDisconnectWagmi(); const handleDisconnect = useCallback(() => { - // disconnect wallets connected through web3-react connectors disconnect?.(); - // disconnect wallets connected through wagmi connectors - wagmiDisconnect(); onClose?.(); - }, [disconnect, onClose, wagmiDisconnect]); + }, [disconnect, onClose]); const handleCopy = useCopyToClipboard(account ?? ''); const handleEtherscan = useEtherscanOpen(account ?? '', 'address'); return ( - + - {providerName && ( + {connectorName && ( - Connected with {providerName} + Connected with {connectorName} )} From 406e11c8e894b82a0f1fb050104a7f1945cca8eb Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Mon, 11 Mar 2024 22:45:09 +0700 Subject: [PATCH 11/15] fix: styles and naming --- features/ipfs/index.ts | 2 +- features/ipfs/security-status-banner/index.ts | 1 + .../security-status-banner.tsx} | 27 ++++++++++------- .../styles.tsx | 14 ++++++++- .../use-version-check.ts | 29 +++---------------- features/ipfs/security-status-banner/utils.ts | 22 ++++++++++++++ features/ipfs/update-promt-banner/index.ts | 1 - features/stake/stake.tsx | 2 +- features/withdrawals/claim/claim.tsx | 2 +- features/withdrawals/request/request.tsx | 2 +- features/wsteth/wrap-unwrap-tabs.tsx | 2 +- pages/_app.tsx | 4 +-- .../only-infra-render/only-infra-render.tsx | 6 ++-- 13 files changed, 67 insertions(+), 47 deletions(-) create mode 100644 features/ipfs/security-status-banner/index.ts rename features/ipfs/{update-promt-banner/update-promt-banner.tsx => security-status-banner/security-status-banner.tsx} (87%) rename features/ipfs/{update-promt-banner => security-status-banner}/styles.tsx (79%) rename features/ipfs/{update-promt-banner => security-status-banner}/use-version-check.ts (89%) create mode 100644 features/ipfs/security-status-banner/utils.ts delete mode 100644 features/ipfs/update-promt-banner/index.ts diff --git a/features/ipfs/index.ts b/features/ipfs/index.ts index d723af8a2..4476ae5a7 100644 --- a/features/ipfs/index.ts +++ b/features/ipfs/index.ts @@ -1,5 +1,5 @@ export { HomePageIpfs } from './home-page-ipfs'; export { FaqPlaceholder } from './faq-placeholder'; -export { UpgradePromtBanner } from './update-promt-banner'; +export { SecurityStatusBanner } from './security-status-banner'; export { InsertIpfsBaseScript } from './ipfs-base-script'; diff --git a/features/ipfs/security-status-banner/index.ts b/features/ipfs/security-status-banner/index.ts new file mode 100644 index 000000000..be8166971 --- /dev/null +++ b/features/ipfs/security-status-banner/index.ts @@ -0,0 +1 @@ +export { SecurityStatusBanner } from './security-status-banner'; diff --git a/features/ipfs/update-promt-banner/update-promt-banner.tsx b/features/ipfs/security-status-banner/security-status-banner.tsx similarity index 87% rename from features/ipfs/update-promt-banner/update-promt-banner.tsx rename to features/ipfs/security-status-banner/security-status-banner.tsx index ea1d9ad1c..cd7a3d02d 100644 --- a/features/ipfs/update-promt-banner/update-promt-banner.tsx +++ b/features/ipfs/security-status-banner/security-status-banner.tsx @@ -2,7 +2,14 @@ import { Button, Modal } from '@lidofinance/lido-ui'; import { dynamics } from 'config'; -import { WarningIcon, Wrapper, WarningText, WarningSubText } from './styles'; +import { + WarningIcon, + Wrapper, + WarningText, + WarningSubText, + WarningBlock, + WarningTitle, +} from './styles'; import { useVersionCheck } from './use-version-check'; import NoSsrWrapper from 'shared/components/no-ssr-wrapper'; @@ -26,11 +33,10 @@ const warningContent = ({ case isIpfs && isNotVerifiable: return { content: ( - - This IPFS version can’t be verified -
+ + This IPFS version can’t be verified Please try again later -
+ ), canClose: false, }; @@ -59,13 +65,14 @@ const warningContent = ({ case isIpfs && isUpdateAvailable: return { content: ( - - This is not the most up to date version of the IPFS widget -
+ + + This is not the most up to date version of the IPFS widget + Please note that the functionality of this version may be lacking -
+ ), canClose: true, }; @@ -74,7 +81,7 @@ const warningContent = ({ } }; -export const UpgradePromtBanner = () => { +export const SecurityStatusBanner = () => { const { areConditionsAccepted, setConditionsAccepted, diff --git a/features/ipfs/update-promt-banner/styles.tsx b/features/ipfs/security-status-banner/styles.tsx similarity index 79% rename from features/ipfs/update-promt-banner/styles.tsx rename to features/ipfs/security-status-banner/styles.tsx index d75d911b7..80f38dc95 100644 --- a/features/ipfs/update-promt-banner/styles.tsx +++ b/features/ipfs/security-status-banner/styles.tsx @@ -37,10 +37,22 @@ export const WarningText = styled(Text).attrs({ text-wrap: balance; `; +export const WarningBlock = styled.p` + text-align: center; + margin: 12px 0 28px; +`; + +export const WarningTitle = styled(Text).attrs({ + weight: 700, +})` + font-size: 26px; + text-align: center; + text-wrap: balance; +`; + export const WarningSubText = styled(Text).attrs({ weight: 400, size: 'xs', - as: 'span', color: 'secondary', })` text-align: center; diff --git a/features/ipfs/update-promt-banner/use-version-check.ts b/features/ipfs/security-status-banner/use-version-check.ts similarity index 89% rename from features/ipfs/update-promt-banner/use-version-check.ts rename to features/ipfs/security-status-banner/use-version-check.ts index 6508b8505..408aa6e01 100644 --- a/features/ipfs/update-promt-banner/use-version-check.ts +++ b/features/ipfs/security-status-banner/use-version-check.ts @@ -1,15 +1,17 @@ import { useEffect, useState } from 'react'; import { useLidoSWR } from '@lido-sdk/react'; +import { useWeb3 } from 'reef-knot/web3-react'; import { useForceDisconnect } from 'reef-knot/core-react'; import { BASE_PATH_ASSET, dynamics } from 'config'; import { useMainnetStaticRpcProvider } from 'shared/hooks/use-mainnet-static-rpc-provider'; import { standardFetcher } from 'utils/standardFetcher'; import { STRATEGY_IMMUTABLE, STRATEGY_LAZY } from 'utils/swrStrategies'; +import { useClientConfig } from 'providers/client-config'; + +import { isVersionLess } from './utils'; import buildInfo from 'build-info.json'; -import { useClientConfig } from 'providers/client-config'; -import { useWeb3 } from 'reef-knot/web3-react'; export const NO_SAFE_VERSION = 'NONE_AVAILABLE'; @@ -36,29 +38,6 @@ const URL_CID_REGEX = const IPFS_RELEASE_URL = 'https://raw.githubusercontent.com/lidofinance/ethereum-staking-widget/main/IPFS.json'; -const isVersionLess = (versionA: string, versionB: string): boolean => { - const verA = versionA - .trim() - .split('.') - .map((v) => parseInt(v)); - const verB = versionB - .trim() - .split('.') - .map((v) => parseInt(v)); - - // eslint-disable-next-line unicorn/no-for-loop - for (let index = 0; index < verA.length; index++) { - const a = verA[index]; - const b = verB[index]; - // validation - if (b === undefined || isNaN(a) || isNaN(b)) return false; - if (a > b) return false; - if (a < b) return true; - } - // versions are equal - return false; -}; - export const useVersionCheck = () => { const { active } = useWeb3(); const { setIsWalletConnectionAllowed } = useClientConfig(); diff --git a/features/ipfs/security-status-banner/utils.ts b/features/ipfs/security-status-banner/utils.ts new file mode 100644 index 000000000..634b71d03 --- /dev/null +++ b/features/ipfs/security-status-banner/utils.ts @@ -0,0 +1,22 @@ +export const isVersionLess = (versionA: string, versionB: string): boolean => { + const verA = versionA + .trim() + .split('.') + .map((v) => parseInt(v)); + const verB = versionB + .trim() + .split('.') + .map((v) => parseInt(v)); + + // eslint-disable-next-line unicorn/no-for-loop + for (let index = 0; index < verA.length; index++) { + const a = verA[index]; + const b = verB[index]; + // validation + if (b === undefined || isNaN(a) || isNaN(b)) return false; + if (a > b) return false; + if (a < b) return true; + } + // versions are equal + return false; +}; diff --git a/features/ipfs/update-promt-banner/index.ts b/features/ipfs/update-promt-banner/index.ts deleted file mode 100644 index 066a337a8..000000000 --- a/features/ipfs/update-promt-banner/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { UpgradePromtBanner } from './update-promt-banner'; diff --git a/features/stake/stake.tsx b/features/stake/stake.tsx index 103226bcb..bdf554b15 100644 --- a/features/stake/stake.tsx +++ b/features/stake/stake.tsx @@ -17,7 +17,7 @@ export const Stake = () => { - }> + }> diff --git a/features/withdrawals/claim/claim.tsx b/features/withdrawals/claim/claim.tsx index 729564202..31d2c9c3f 100644 --- a/features/withdrawals/claim/claim.tsx +++ b/features/withdrawals/claim/claim.tsx @@ -11,7 +11,7 @@ export const Claim = () => { - }> + }> diff --git a/features/withdrawals/request/request.tsx b/features/withdrawals/request/request.tsx index a367f908a..18ab97783 100644 --- a/features/withdrawals/request/request.tsx +++ b/features/withdrawals/request/request.tsx @@ -11,7 +11,7 @@ export const Request = () => { - }> + }> diff --git a/features/wsteth/wrap-unwrap-tabs.tsx b/features/wsteth/wrap-unwrap-tabs.tsx index 76e01abda..f6801bedf 100644 --- a/features/wsteth/wrap-unwrap-tabs.tsx +++ b/features/wsteth/wrap-unwrap-tabs.tsx @@ -29,7 +29,7 @@ export const WrapUnwrapTabs = ({ mode }: WrapUnwrapLayoutProps) => { {isUnwrapMode ? : } - }> + }> diff --git a/pages/_app.tsx b/pages/_app.tsx index ac857f959..fe9fd183e 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -15,7 +15,7 @@ import { Providers } from 'providers'; import { BackgroundGradient } from 'shared/components/background-gradient/background-gradient'; import { nprogress, COOKIES_ALLOWED_FULL_KEY } from 'utils'; import { withCsp } from 'utilsApi/withCSP'; -import { UpgradePromtBanner } from 'features/ipfs'; +import { SecurityStatusBanner } from 'features/ipfs'; // Migrations old theme cookies to new cross domain cookies migrationThemeCookiesToCrossDomainCookiesClientSide(); @@ -56,7 +56,7 @@ const AppWrapper = (props: AppProps): JSX.Element => { - + ); }; diff --git a/shared/components/only-infra-render/only-infra-render.tsx b/shared/components/only-infra-render/only-infra-render.tsx index d33a32db8..d286f762a 100644 --- a/shared/components/only-infra-render/only-infra-render.tsx +++ b/shared/components/only-infra-render/only-infra-render.tsx @@ -1,12 +1,12 @@ import { dynamics } from 'config'; type OnlyInfraRenderProps = { - placeholder?: React.ReactNode; + renderIPFS?: React.ReactNode; }; export const OnlyInfraRender = ({ children, - placeholder = null, + renderIPFS = null, }: React.PropsWithChildren) => { - return <>{dynamics.ipfsMode ? placeholder : children}; + return <>{dynamics.ipfsMode ? renderIPFS : children}; }; From 8f0601aa09d12975b31d73f54882b7f127357ee0 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Tue, 12 Mar 2024 13:25:49 +0700 Subject: [PATCH 12/15] fix: add qa helpers --- .../use-version-check.ts | 36 ++++++++++++------- utils/qa.ts | 20 +++++++++++ 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/features/ipfs/security-status-banner/use-version-check.ts b/features/ipfs/security-status-banner/use-version-check.ts index 408aa6e01..460013622 100644 --- a/features/ipfs/security-status-banner/use-version-check.ts +++ b/features/ipfs/security-status-banner/use-version-check.ts @@ -8,6 +8,7 @@ import { useMainnetStaticRpcProvider } from 'shared/hooks/use-mainnet-static-rpc import { standardFetcher } from 'utils/standardFetcher'; import { STRATEGY_IMMUTABLE, STRATEGY_LAZY } from 'utils/swrStrategies'; import { useClientConfig } from 'providers/client-config'; +import { overrideWithQAMockBoolean } from 'utils/qa'; import { isVersionLess } from './utils'; @@ -97,23 +98,32 @@ export const useVersionCheck = () => { { ...STRATEGY_LAZY }, ); - const isUpdateAvailable = Boolean( - remoteVersionSWR.data && - currentCidSWR.data && - remoteVersionSWR.data.cid !== currentCidSWR.data && - remoteVersionSWR.data.leastSafeVersion !== NO_SAFE_VERSION, + const isUpdateAvailable = overrideWithQAMockBoolean( + Boolean( + remoteVersionSWR.data && + currentCidSWR.data && + remoteVersionSWR.data.cid !== currentCidSWR.data && + remoteVersionSWR.data.leastSafeVersion !== NO_SAFE_VERSION, + ), + 'mock-qa-helpers-security-banner-is-update-available', ); - const isVersionUnsafe = Boolean( - remoteVersionSWR.data?.leastSafeVersion && - (remoteVersionSWR.data.leastSafeVersion === NO_SAFE_VERSION || - isVersionLess( - buildInfo.version, - remoteVersionSWR.data.leastSafeVersion, - )), + const isVersionUnsafe = overrideWithQAMockBoolean( + Boolean( + remoteVersionSWR.data?.leastSafeVersion && + (remoteVersionSWR.data.leastSafeVersion === NO_SAFE_VERSION || + isVersionLess( + buildInfo.version, + remoteVersionSWR.data.leastSafeVersion, + )), + ), + 'mock-qa-helpers-security-banner-is-version-unsafe', ); - const isNotVerifiable = !!remoteVersionSWR.error; + const isNotVerifiable = overrideWithQAMockBoolean( + !!remoteVersionSWR.error, + 'mock-qa-helpers-security-banner-is-not-verifiable', + ); // disconnect wallet and disallow connection for unsafe versions useEffect(() => { diff --git a/utils/qa.ts b/utils/qa.ts index 022bc263a..f16f4c4a8 100644 --- a/utils/qa.ts +++ b/utils/qa.ts @@ -1,3 +1,23 @@ import { dynamics } from 'config'; export const enableQaHelpers = dynamics.enableQaHelpers; + +export const overrideWithQAMockBoolean = (value: boolean, key: string) => { + if (enableQaHelpers) { + const mock = localStorage.getItem(key); + if (mock) { + return mock === 'true'; + } + } + return value; +}; + +export const overrideWithQAMockNumber = (value: number, key: string) => { + if (enableQaHelpers) { + const mock = localStorage.getItem(key); + if (mock && !isNaN(Number(mock))) { + return Number(mock); + } + } + return value; +}; From d884376e2a60f488f65c15b7cfddb9162ed84745 Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Tue, 12 Mar 2024 14:50:53 +0700 Subject: [PATCH 13/15] fix: add autoconnect handling --- shared/wallet/connect/connect.tsx | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/shared/wallet/connect/connect.tsx b/shared/wallet/connect/connect.tsx index f250d2c6a..1aa222649 100644 --- a/shared/wallet/connect/connect.tsx +++ b/shared/wallet/connect/connect.tsx @@ -4,15 +4,30 @@ import { wrapWithEventTrack } from '@lidofinance/analytics-matomo'; import { MATOMO_CLICK_EVENTS } from 'config'; import { useClientConfig } from 'providers/client-config'; import { useConnectWalletModal } from '../connect-wallet-modal/use-connect-wallet-modal'; +import { useConnectorInfo, useEagerConnect } from 'reef-knot/core-react'; export const Connect: FC = (props) => { const { isWalletConnectionAllowed } = useClientConfig(); const { onClick, ...rest } = props; const { openModal } = useConnectWalletModal(); + const { isAutoConnectionSuitable } = useConnectorInfo(); + const { eagerConnect } = useEagerConnect(); const handleClick = wrapWithEventTrack( MATOMO_CLICK_EVENTS.connectWallet, - useCallback(() => openModal({}), [openModal]), + useCallback(() => { + if (!isWalletConnectionAllowed) return; + if (isAutoConnectionSuitable) { + void eagerConnect(); + } else { + openModal({}); + } + }, [ + eagerConnect, + isAutoConnectionSuitable, + isWalletConnectionAllowed, + openModal, + ]), ); return ( From 234c42b544b5f74513a970fb0025e9ecbb8829af Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Tue, 12 Mar 2024 14:51:12 +0700 Subject: [PATCH 14/15] docs: comment --- shared/wallet/connect/connect.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/wallet/connect/connect.tsx b/shared/wallet/connect/connect.tsx index 1aa222649..dc104f304 100644 --- a/shared/wallet/connect/connect.tsx +++ b/shared/wallet/connect/connect.tsx @@ -17,6 +17,7 @@ export const Connect: FC = (props) => { MATOMO_CLICK_EVENTS.connectWallet, useCallback(() => { if (!isWalletConnectionAllowed) return; + // for auto-connect skip modal and try reconnect if (isAutoConnectionSuitable) { void eagerConnect(); } else { From 92c3a257cd856bbaf771f053cac76b65af7de2fd Mon Sep 17 00:00:00 2001 From: Evgeny Taktarov Date: Tue, 12 Mar 2024 20:10:51 +0700 Subject: [PATCH 15/15] fix: build --- utils/qa.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/qa.ts b/utils/qa.ts index f16f4c4a8..3f215d463 100644 --- a/utils/qa.ts +++ b/utils/qa.ts @@ -3,7 +3,7 @@ import { dynamics } from 'config'; export const enableQaHelpers = dynamics.enableQaHelpers; export const overrideWithQAMockBoolean = (value: boolean, key: string) => { - if (enableQaHelpers) { + if (enableQaHelpers && typeof window !== 'undefined') { const mock = localStorage.getItem(key); if (mock) { return mock === 'true'; @@ -13,7 +13,7 @@ export const overrideWithQAMockBoolean = (value: boolean, key: string) => { }; export const overrideWithQAMockNumber = (value: number, key: string) => { - if (enableQaHelpers) { + if (enableQaHelpers && typeof window !== 'undefined') { const mock = localStorage.getItem(key); if (mock && !isNaN(Number(mock))) { return Number(mock);