diff --git a/modules/blockChain/ui/NetworkSwitcher/NetworkSwitcher.tsx b/modules/blockChain/ui/NetworkSwitcher/NetworkSwitcher.tsx index 8ef3b99d..67334f44 100644 --- a/modules/blockChain/ui/NetworkSwitcher/NetworkSwitcher.tsx +++ b/modules/blockChain/ui/NetworkSwitcher/NetworkSwitcher.tsx @@ -1,18 +1,14 @@ import { useErrorMessage } from 'modules/blockChain/hooks/useErrorMessage' import { Container } from '@lidofinance/lido-ui' -import { Wrap } from './NetworkSwitcherStyle' -import DangerIconSVG from 'assets/danger.com.svg.react' +import { AttentionBanner } from 'modules/shared/ui/Common/AttentionBanner' export function NetworkSwitcher() { const errorMessage = useErrorMessage() return ( - - - {errorMessage} - + {errorMessage} ) } diff --git a/modules/blockChain/ui/NetworkSwitcher/NetworkSwitcherStyle.ts b/modules/blockChain/ui/NetworkSwitcher/NetworkSwitcherStyle.ts deleted file mode 100644 index bbd30c0a..00000000 --- a/modules/blockChain/ui/NetworkSwitcher/NetworkSwitcherStyle.ts +++ /dev/null @@ -1,20 +0,0 @@ -import styled from 'styled-components' - -export const Wrap = styled.div` - display: flex; - align-items: center; - margin-bottom: ${({ theme }) => theme.spaceMap.xxl}px; - padding: ${({ theme }) => theme.spaceMap.lg}px; - color: var(--lido-color-textDark); - font-size: ${({ theme }) => theme.fontSizesMap.xxs}px; - font-weight: 400; - background-color: var(--lido-color-warningBackground); - border-radius: ${({ theme }) => theme.borderRadiusesMap.md}px; - - & svg { - display: block; - flex: 0 0 auto; - margin-right: ${({ theme }) => theme.spaceMap.sm}px; - fill: var(--lido-color-textDark); - } -` diff --git a/modules/dashboard/ui/DashboardGrid/DashboardGrid.tsx b/modules/dashboard/ui/DashboardGrid/DashboardGrid.tsx index 55889c43..8000abe8 100644 --- a/modules/dashboard/ui/DashboardGrid/DashboardGrid.tsx +++ b/modules/dashboard/ui/DashboardGrid/DashboardGrid.tsx @@ -8,6 +8,7 @@ import { DashboardVote } from '../DashboardVote' import { DashboardVoteSkeleton } from '../DashboardVoteSkeleton' import { SkeletonBar } from 'modules/shared/ui/Skeletons/SkeletonBar' import { GridWrap, PaginationWrap } from './DashboardGridStyle' +import { FetchErrorBanner } from 'modules/shared/ui/Common/FetchErrorBanner' import { ContractVoting } from 'modules/blockChain/contracts' import { getVoteStatus } from 'modules/votes/utils/getVoteStatus' import { getEventStartVote } from 'modules/votes/utils/getEventVoteStart' @@ -124,6 +125,14 @@ export function DashboardGrid({ currentPage }: Props) { return null } + if (swrVotes.error || infoSwr.error) { + return ( + + + + ) + } + return ( diff --git a/modules/shared/ui/Common/AttentionBanner/AttentionBanner.tsx b/modules/shared/ui/Common/AttentionBanner/AttentionBanner.tsx new file mode 100644 index 00000000..2a12bc6a --- /dev/null +++ b/modules/shared/ui/Common/AttentionBanner/AttentionBanner.tsx @@ -0,0 +1,16 @@ +import { Wrap } from './AttentionBannerStyle' +import DangerIconSVG from 'assets/danger.com.svg.react' + +type Props = { + type?: 'error' | 'warning' + children?: React.ReactNode +} + +export const AttentionBanner = ({ type = 'warning', children }: Props) => { + return ( + + + {children} + + ) +} diff --git a/modules/shared/ui/Common/AttentionBanner/AttentionBannerStyle.ts b/modules/shared/ui/Common/AttentionBanner/AttentionBannerStyle.ts new file mode 100644 index 00000000..2583427a --- /dev/null +++ b/modules/shared/ui/Common/AttentionBanner/AttentionBannerStyle.ts @@ -0,0 +1,52 @@ +import styled, { css } from 'styled-components' + +type WrapProps = { + type: 'error' | 'warning' +} + +export const Wrap = styled.div` + display: flex; + align-items: center; + margin-bottom: ${({ theme }) => theme.spaceMap.xxl}px; + padding: ${({ theme }) => theme.spaceMap.lg}px; + font-size: ${({ theme }) => theme.fontSizesMap.xxs}px; + font-weight: 400; + border-radius: ${({ theme }) => theme.borderRadiusesMap.md}px; + + & svg { + display: block; + flex: 0 0 auto; + margin-right: ${({ theme }) => theme.spaceMap.sm}px; + fill: var(--lido-color-textDark); + } + + ${({ type }) => + type === 'error' && + css` + background-color: var(--lido-color-error); + + &, + & a { + color: var(--lido-color-errorContrast); + } + + & svg { + fill: var(--lido-color-errorContrast); + } + `} + + ${({ type }) => + type === 'warning' && + css` + background-color: var(--lido-color-warningBackground); + + &, + & a { + color: var(--lido-color-textDark); + } + + & svg { + fill: var(--lido-color-textDark); + } + `} +` diff --git a/modules/shared/ui/Common/AttentionBanner/index.ts b/modules/shared/ui/Common/AttentionBanner/index.ts new file mode 100644 index 00000000..f7c167e5 --- /dev/null +++ b/modules/shared/ui/Common/AttentionBanner/index.ts @@ -0,0 +1 @@ +export * from './AttentionBanner' diff --git a/modules/shared/ui/Common/FetchErrorBanner/FetchErrorBanner.tsx b/modules/shared/ui/Common/FetchErrorBanner/FetchErrorBanner.tsx new file mode 100644 index 00000000..4c8b1e35 --- /dev/null +++ b/modules/shared/ui/Common/FetchErrorBanner/FetchErrorBanner.tsx @@ -0,0 +1,32 @@ +import Link from 'next/link' +import { AttentionBanner } from '../AttentionBanner' +import { ErrorMessageDisplayText } from 'modules/shared/utils/getErrorMessage' +import * as urls from 'modules/network/utils/urls' + +type Props = { + error: unknown +} + +export const FetchErrorBanner = ({ error }: Props) => { + let topLine = 'There is a problem with rpc node currently in use.' + + if ( + error && + typeof error === 'object' && + 'code' in error && + error.code === 429 + ) { + topLine = ErrorMessageDisplayText.RPC_TOO_MANY_REQUESTS + } + + return ( + + {topLine} +
+ You can set your own url on + settings + {' '} + page. +
+ ) +} diff --git a/modules/shared/ui/Common/FetchErrorBanner/index.ts b/modules/shared/ui/Common/FetchErrorBanner/index.ts new file mode 100644 index 00000000..5c6b38ac --- /dev/null +++ b/modules/shared/ui/Common/FetchErrorBanner/index.ts @@ -0,0 +1 @@ +export * from './FetchErrorBanner' diff --git a/modules/shared/utils/csp.ts b/modules/shared/utils/csp.ts index d5a3aa3e..1f47240f 100644 --- a/modules/shared/utils/csp.ts +++ b/modules/shared/utils/csp.ts @@ -32,6 +32,7 @@ export const contentSecurityPolicy = { 'https://api.thegraph.com', 'https://*.infura.io', 'https://*.alchemyapi.io', + 'https://*.alchemy.com', 'https://*.etherscan.io/api', ...trustedHosts, ], diff --git a/modules/shared/utils/getErrorMessage.ts b/modules/shared/utils/getErrorMessage.ts index 019bead3..10592d1b 100644 --- a/modules/shared/utils/getErrorMessage.ts +++ b/modules/shared/utils/getErrorMessage.ts @@ -6,6 +6,8 @@ export const ErrorMessageDisplayText = { '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.', + RPC_TOO_MANY_REQUESTS: + 'RPC service has reached its requests limit or compute capacity.', } as const // type safe error code extractor @@ -84,6 +86,8 @@ export const getErrorMessage = (error: unknown) => { return ErrorMessageDisplayText.LIMIT_REACHED case 'ENABLE_BLIND_SIGNING': return ErrorMessageDisplayText.ENABLE_BLIND_SIGNING + case 429: + return ErrorMessageDisplayText.RPC_TOO_MANY_REQUESTS default: return ErrorMessageDisplayText.SOMETHING_WRONG } diff --git a/modules/votes/ui/VoteForm/VoteForm.tsx b/modules/votes/ui/VoteForm/VoteForm.tsx index 859a0cd3..df3f6ec0 100644 --- a/modules/votes/ui/VoteForm/VoteForm.tsx +++ b/modules/votes/ui/VoteForm/VoteForm.tsx @@ -1,4 +1,3 @@ -import Link from 'next/link' import { useFormVoteInfo } from './useFormVoteInfo' import { useFormVoteSubmit } from './useFormVoteSubmit' import { useVotePassedCallback } from '../../hooks/useVotePassedCallback' @@ -13,10 +12,10 @@ import { VoteFormActions } from '../VoteFormActions' import { VoteFormMustConnect } from '../VoteFormMustConnect' import { VoteFormVoterState } from '../VoteFormVoterState' import { VoteVotersList } from '../VoteVotersList' -import { Desc, ErrorMessage, ClearButton } from './VoteFormStyle' +import { Desc, ClearButton } from './VoteFormStyle' +import { FetchErrorBanner } from 'modules/shared/ui/Common/FetchErrorBanner' import { VoteStatus } from 'modules/votes/types' -import * as urls from 'modules/network/utils/urls' type Props = { voteId?: string @@ -104,13 +103,7 @@ export function VoteForm({ voteId }: Props) { )} {!isLoading && swrVote.error && !isNotFound && ( - -

There is a problem with rpc node currently in use.

-

- You can set your own url on{' '} - settings page. -

-
+ )} {isFound && ( diff --git a/modules/votes/ui/VoteForm/VoteFormStyle.ts b/modules/votes/ui/VoteForm/VoteFormStyle.ts index dfd811f8..0bbce070 100644 --- a/modules/votes/ui/VoteForm/VoteFormStyle.ts +++ b/modules/votes/ui/VoteForm/VoteFormStyle.ts @@ -10,17 +10,6 @@ export const Desc = styled.div` } ` -export const ErrorMessage = styled.div` - padding: ${({ theme }) => theme.spaceMap.lg}px; - color: #fff; - background-color: var(--lido-color-error); - border-radius: ${({ theme }) => theme.borderRadiusesMap.xl}px; - - & a { - color: #fff; - } -` - export const ClearButton = styled(Text).attrs({ size: 'xs', weight: 700,