Skip to content

Commit

Permalink
Merge pull request #297 from lidofinance/feature/si-1299-add-link-to-…
Browse files Browse the repository at this point in the history
…ipfs-version-to-footer

feat: add link to ipfs
  • Loading branch information
jake4take authored Mar 20, 2024
2 parents 7e41366 + 56d52d3 commit 1f5acd2
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 88 deletions.
7 changes: 5 additions & 2 deletions features/ipfs/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
export { HomePageIpfs } from './home-page-ipfs';

export { IPFS_INFO_URL } from './rpc-availability-check-result-box';
export { FaqPlaceholder } from './faq-placeholder';
export { SecurityStatusBanner } from './security-status-banner';
export {
SecurityStatusBanner,
useRemoteVersion,
} from './security-status-banner';
export { InsertIpfsBaseScript } from './ipfs-base-script';
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { LinkArrow } from 'shared/components/link-arrow/link-arrow';

import { Wrap, RpcStatusBox, Button, Text } from './styles';

const IPFS_INFO_URL = 'https://docs.lido.fi/ipfs/about';
export const IPFS_INFO_URL = 'https://docs.lido.fi/ipfs/about';

export const RPCAvailabilityCheckResultBox = () => {
const { isRPCAvailable, handleClickDismiss } = useIPFSInfoBoxStatuses();
Expand Down
1 change: 1 addition & 0 deletions features/ipfs/security-status-banner/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { SecurityStatusBanner } from './security-status-banner';
export { useRemoteVersion } from './use-remote-version';
66 changes: 66 additions & 0 deletions features/ipfs/security-status-banner/use-remote-version.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { useLidoSWR } from '@lido-sdk/react';
import { dynamics } from 'config';
import { useMainnetStaticRpcProvider } from 'shared/hooks/use-mainnet-static-rpc-provider';
import { standardFetcher } from 'utils/standardFetcher';
import { STRATEGY_LAZY } from 'utils/swrStrategies';

type EnsHashCheckReturn = {
cid: string;
ens?: string;
leastSafeVersion?: string;
link: string;
} | null;

type ReleaseInfoData = Record<string, ReleaseInfo>;

type ReleaseInfo = {
cid?: string;
ens?: string;
leastSafeVersion?: string;
};

// for dev and local testing you can set to '/runtime/IPFS.json' and have file at /public/runtime/
const IPFS_RELEASE_URL =
'https://raw.githubusercontent.com/lidofinance/ethereum-staking-widget/main/IPFS.json';

export const useRemoteVersion = () => {
const provider = useMainnetStaticRpcProvider();
// ens cid extraction
return useLidoSWR<EnsHashCheckReturn>(
['swr:use-remote-version'],
async (): Promise<EnsHashCheckReturn> => {
const releaseInfoData = await standardFetcher<ReleaseInfoData>(
IPFS_RELEASE_URL,
{
headers: { Accept: 'application/json' },
},
);

const releaseInfo = releaseInfoData[dynamics.defaultChain.toString()];
if (releaseInfo?.ens) {
const resolver = await provider.getResolver(releaseInfo.ens);
if (resolver) {
const contentHash = await resolver.getContentHash();
if (contentHash) {
return {
cid: contentHash,
ens: releaseInfo.ens,
link: `https://${releaseInfo.ens}.limo`,
leastSafeVersion: releaseInfo.leastSafeVersion,
};
}
}
}
if (releaseInfo?.cid) {
return {
cid: releaseInfo.cid,
link: `https://${releaseInfo.cid}.ipfs.cf-ipfs.com`,
leastSafeVersion: releaseInfo.leastSafeVersion,
};
}

throw new Error('invalid IPFS manifest content');
},
{ ...STRATEGY_LAZY },
);
};
63 changes: 3 additions & 60 deletions features/ipfs/security-status-banner/use-version-check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,26 @@ 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 { STRATEGY_IMMUTABLE } from 'utils/swrStrategies';
import { useClientConfig } from 'providers/client-config';
import { overrideWithQAMockBoolean } from 'utils/qa';

import { isVersionLess } from './utils';

import buildInfo from 'build-info.json';
import { useRemoteVersion } from './use-remote-version';

export const NO_SAFE_VERSION = 'NONE_AVAILABLE';

type EnsHashCheckReturn = {
cid: string;
ens?: string;
leastSafeVersion?: string;
link: string;
} | null;

type ReleaseInfoData = Record<string, ReleaseInfo>;

type ReleaseInfo = {
cid?: string;
ens?: string;
leastSafeVersion?: string;
};

// works with any type of IPFS hash
const URL_CID_REGEX =
/[/.](?<cid>Qm[1-9A-HJ-NP-Za-km-z]{44,}|b[A-Za-z2-7]{58,}|B[A-Z2-7]{58,}|z[1-9A-HJ-NP-Za-km-z]{48,}|F[0-9A-F]{50,})([./#?]|$)/;

// for dev and local testing you can set to '/runtime/IPFS.json' and have file at /public/runtime/
const IPFS_RELEASE_URL =
'https://raw.githubusercontent.com/lidofinance/ethereum-staking-widget/main/IPFS.json';

export const useVersionCheck = () => {
const { active } = useWeb3();
const { setIsWalletConnectionAllowed } = useClientConfig();
const { forceDisconnect } = useForceDisconnect();
const [areConditionsAccepted, setConditionsAccepted] = useState(false);
const provider = useMainnetStaticRpcProvider();

// local cid extraction
const currentCidSWR = useLidoSWR(
Expand All @@ -61,43 +40,7 @@ export const useVersionCheck = () => {
);

// ens cid extraction
const remoteVersionSWR = useLidoSWR<EnsHashCheckReturn>(
['swr:ipfs-hash-check'],
async (): Promise<EnsHashCheckReturn> => {
const releaseInfoData = await standardFetcher<ReleaseInfoData>(
IPFS_RELEASE_URL,
{
headers: { Accept: 'application/json' },
},
);

const releaseInfo = releaseInfoData[dynamics.defaultChain.toString()];
if (releaseInfo?.ens) {
const resolver = await provider.getResolver(releaseInfo.ens);
if (resolver) {
const contentHash = await resolver.getContentHash();
if (contentHash) {
return {
cid: contentHash,
ens: releaseInfo.ens,
link: `https://${releaseInfo.ens}.limo`,
leastSafeVersion: releaseInfo.leastSafeVersion,
};
}
}
}
if (releaseInfo?.cid) {
return {
cid: releaseInfo.cid,
link: `https://${releaseInfo.cid}.ipfs.cf-ipfs.com`,
leastSafeVersion: releaseInfo.leastSafeVersion,
};
}

throw new Error('invalid IPFS manifest content');
},
{ ...STRATEGY_LAZY },
);
const remoteVersionSWR = useRemoteVersion();

const isUpdateAvailable = overrideWithQAMockBoolean(
Boolean(
Expand Down
1 change: 0 additions & 1 deletion features/withdrawals/request/form/options/dex-options.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
DexOptionLoader,
DexWarning,
} from './styles';
// @ts-expect-error https://www.npmjs.com/package/@svgr/webpack
import { ReactComponent as AttentionTriangle } from 'assets/icons/attention-triangle.svg';

type DexOptionProps = {
Expand Down
13 changes: 13 additions & 0 deletions global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,16 @@ interface Window {
// see _document.js for definition
_paq: undefined | [string, ...unknown[]][];
}

declare module '*.svg' {
/**
* Use `any` to avoid conflicts with
* `@svgr/webpack` plugin or
* `babel-plugin-inline-react-svg` plugin.
*/
const content: any;
export const ReactComponent: React.FunctionComponent<
React.ComponentProps<'svg'>
>;
export default content;
}
43 changes: 24 additions & 19 deletions shared/components/layout/footer/footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
Version,
LinkDivider,
} from './styles';
import { LinkToIpfs } from './link-to-ipfs';

const getVersionInfo = () => {
const { version, branch } = buildInfo;
Expand Down Expand Up @@ -37,22 +38,26 @@ const getVersionInfo = () => {

const { label, link } = getVersionInfo();

export const Footer: FC = () => (
<FooterStyle size="full" forwardedAs="footer">
<LogoLidoStyle />
<FooterLink data-testid="termsOfUse" href="https://lido.fi/terms-of-use">
Terms of Use
</FooterLink>
<LinkDivider />
<FooterLink
data-testid="privacyNotice"
href="https://lido.fi/privacy-notice"
>
Privacy Notice
</FooterLink>
<Version data-testid="appVersion" href={link}>
{label}
</Version>
<FooterDivider />
</FooterStyle>
);
export const Footer: FC = () => {
return (
<FooterStyle size="full" forwardedAs="footer">
<LogoLidoStyle />
<FooterLink data-testid="termsOfUse" href="https://lido.fi/terms-of-use">
Terms of Use
</FooterLink>
<LinkDivider />
<FooterLink
data-testid="privacyNotice"
href="https://lido.fi/privacy-notice"
$marginRight="auto"
>
Privacy Notice
</FooterLink>
<LinkToIpfs />
<Version data-testid="appVersion" href={link}>
{label}
</Version>
<FooterDivider />
</FooterStyle>
);
};
15 changes: 15 additions & 0 deletions shared/components/layout/footer/link-to-ipfs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { IPFS_INFO_URL, useRemoteVersion } from 'features/ipfs';

import { OnlyInfraRender } from 'shared/components/only-infra-render';
import { ExternalLink } from './styles';

export const LinkToIpfs = () => {
const { data } = useRemoteVersion();
return (
<OnlyInfraRender
renderIPFS={<ExternalLink href={IPFS_INFO_URL}>IPFS Docs</ExternalLink>}
>
{data && <ExternalLink href={data?.link}>IPFS</ExternalLink>}
</OnlyInfraRender>
);
};
54 changes: 50 additions & 4 deletions shared/components/layout/footer/styles.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import styled from 'styled-components';

import { Container, Link } from '@lidofinance/lido-ui';

import { LogoLido } from 'shared/components/logos/logos';
import { NAV_MOBILE_MEDIA } from 'styles/constants';

import { ReactComponent as ExternalLinkIcon } from 'assets/icons/external-link-icon.svg';
import React from 'react';

export const FooterStyle = styled(Container)`
position: relative;
box-sizing: border-box;
color: var(--lido-color-text);
display: flex;
row-gap: 44px;
row-gap: 12px;
flex-wrap: wrap;
width: 100%;
Expand All @@ -23,7 +26,11 @@ export const FooterStyle = styled(Container)`
}
`;

export const FooterLink = styled(Link)`
type FooterLinkProps = {
$marginRight?: string;
};

export const FooterLink = styled(Link)<FooterLinkProps>`
display: flex;
align-items: center;
line-height: 20px;
Expand All @@ -32,11 +39,26 @@ export const FooterLink = styled(Link)`
font-size: ${({ theme }) => theme.fontSizesMap.xxs}px;
font-weight: 400;
${({ $marginRight }) => ($marginRight ? `margin-right:${$marginRight}` : '')};
&:visited {
color: var(--lido-color-textSecondary);
&:hover {
color: var(--lido-color-text);
opacity: 1;
svg {
path {
fill: var(--lido-color-text);
}
}
}
}
&:hover {
svg {
path {
color: var(--lido-color-primaryHover);
}
}
}
`;
Expand Down Expand Up @@ -66,8 +88,32 @@ export const FooterDivider = styled.div`
`;

export const Version = styled(FooterLink)`
margin-left: auto;
margin-left: 20px;
padding: 2px 5px;
border-radius: ${({ theme }) => theme.borderRadiusesMap.xs}px;
background: rgba(122, 138, 160, 0.1);
`;

export const ExternalLinkIconFooter = styled(ExternalLinkIcon).attrs({
width: 10,
height: 10,
viewBox: '0 0 12 12',
})`
padding: 5px;
width: 20px;
height: 20px;
box-sizing: border-box;
path {
fill: var(--lido-color-textSecondary);
}
`;

export const ExternalLink = ({
children,
...props
}: React.ComponentProps<typeof FooterLink>) => (
<FooterLink target="_blank" rel="noopener noreferrer" {...props}>
{children}
<ExternalLinkIconFooter />
</FooterLink>
);
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { useCallback } from 'react';

// @ts-expect-error https://www.npmjs.com/package/@svgr/webpack
import { ReactComponent as GearIcon } from 'assets/icons/gear.svg';
import { SETTINGS_PATH } from 'config/urls';
import { useRouterPath } from 'shared/hooks/use-router-path';
Expand Down

0 comments on commit 1f5acd2

Please sign in to comment.