Skip to content

Commit

Permalink
Merge pull request #190 from lidofinance/feature/si-1122-banner-about…
Browse files Browse the repository at this point in the history
…-deprecated-hash-for-ipfs-version

Banner about deprecated hash for ipfs version
  • Loading branch information
jake4take authored Feb 20, 2024
2 parents 05312a6 + af711aa commit 9ff174e
Show file tree
Hide file tree
Showing 17 changed files with 226 additions and 17 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,4 @@ WALLETCONNECT_PROJECT_ID=

# ETH Stake Widget API for IPFS mode
WIDGET_API_BASE_PATH_FOR_IPFS=

3 changes: 2 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
"useTabs": false,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "all"
"trailingComma": "all",
"printWidth": 80
}
4 changes: 4 additions & 0 deletions IPFS.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"__warning__": "For testing purposes only",
"cid": "bafybeightexodcodz3srlseidd6olah7lezz4tmyeiy7qod6oz2ol45r3i"
}
3 changes: 3 additions & 0 deletions assets/icons/attention-triangle-ipfs.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 8 additions & 4 deletions env-dynamics.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,17 @@ export const walletconnectProjectId = process.env.WALLETCONNECT_PROJECT_ID;
export const ipfsMode = toBoolean(process.env.IPFS_MODE);

/** @type string[] */
export const prefillUnsafeElRpcUrls1 = process.env.PREFILL_UNSAFE_EL_RPC_URLS_1?.split(',') ?? [];
export const prefillUnsafeElRpcUrls1 =
process.env.PREFILL_UNSAFE_EL_RPC_URLS_1?.split(',') ?? [];

/** @type string[] */
export const prefillUnsafeElRpcUrls5 = process.env.PREFILL_UNSAFE_EL_RPC_URLS_5?.split(',') ?? [];
export const prefillUnsafeElRpcUrls5 =
process.env.PREFILL_UNSAFE_EL_RPC_URLS_5?.split(',') ?? [];

/** @type string[] */
export const prefillUnsafeElRpcUrls17000 = process.env.PREFILL_UNSAFE_EL_RPC_URLS_17000?.split(',') ?? [];
export const prefillUnsafeElRpcUrls17000 =
process.env.PREFILL_UNSAFE_EL_RPC_URLS_17000?.split(',') ?? [];

/** @type string */
export const widgetApiBasePathForIpfs = process.env.WIDGET_API_BASE_PATH_FOR_IPFS;
export const widgetApiBasePathForIpfs =
process.env.WIDGET_API_BASE_PATH_FOR_IPFS;
6 changes: 3 additions & 3 deletions features/ipfs/ipfs-base-script.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ let ipfsBaseScript = '';
// #!if IPFS_MODE === "true"
ipfsBaseScript = `
(function () {
const base = document.createElement('base')
base.href = window.location.pathname
document.head.append(base)
const base = document.createElement('base');
base.href = window.location.pathname;
document.head.append(base);
})();
`;
// #!endif
Expand Down
1 change: 1 addition & 0 deletions features/ipfs/outdated-hash-banner/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { OutdatedHashBanner } from './outdated-hash-banner';
43 changes: 43 additions & 0 deletions features/ipfs/outdated-hash-banner/outdated-hash-banner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
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 (
<NoSsrWrapper>
<Modal open={isUpdateAvailable}>
<Wrapper>
<WarningIcon />
<WarningText>
This is not the most recent version of IPFS Widget
</WarningText>
<a
href={data.remoteCidLink}
target="_self"
rel="noopener noreferrer"
>
<Button size="sm" fullwidth variant="filled">
Get to the actual version
</Button>
</a>
<Button
size="sm"
fullwidth
color="error"
variant="outlined"
onClick={() => setConditionsAccepted(true)}
>
Accept risks and use the current version
</Button>
</Wrapper>
</Modal>
</NoSsrWrapper>
);
}
: () => null;
38 changes: 38 additions & 0 deletions features/ipfs/outdated-hash-banner/styles.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import styled from 'styled-components';
import WarningIconSrc from 'assets/icons/attention-triangle-ipfs.svg';
import { Text } from '@lidofinance/lido-ui';

export const WarningIcon = styled.img.attrs({
src: WarningIconSrc,
alt: 'warning',
})`
display: block;
width: 58px;
height: 51px;
`;

export const Wrapper = styled.div`
display: flex;
align-items: center;
flex-direction: column;
gap: 12px;
padding: 0px;
button {
white-space: unset;
}
a {
align-self: stretch;
width: 100%;
}
`;

export const WarningText = styled(Text).attrs({
weight: 700,
size: 'lg',
})`
text-align: center;
margin: 12px 0 28px;
text-wrap: balance;
`;
103 changes: 103 additions & 0 deletions features/ipfs/outdated-hash-banner/use-ipfs-hash-check.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { useLidoSWR } from '@lido-sdk/react';
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';

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

type ReleaseInfo = {
cid?: string;
ens?: 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 useIpfsHashCheck = () => {
const [areConditionsAccepted, setConditionsAccepted] = useState(false);
const provider = useMainnetStaticRpcProvider();

// local cid extraction
const currentCidSWR = useLidoSWR(
['swr:ipfs-cid-extraction'],
async () => {
const urlCid = URL_CID_REGEX.exec(window.location.href)?.groups?.cid;
if (urlCid) return urlCid;
const headers = await fetch(`${BASE_PATH_ASSET}/runtime/window-env.js`, {
method: 'HEAD',
});
return headers.headers.get('X-Ipfs-Roots');
},
{ ...STRATEGY_IMMUTABLE, isPaused: () => !dynamics.ipfsMode },
);

// ens cid extraction
const remoteCidSWR = useLidoSWR<EnsHashCheckReturn>(
['swr:ipfs-hash-check'],
async (): Promise<EnsHashCheckReturn> => {
const releaseInfo = await standardFetcher<ReleaseInfo>(IPFS_RELEASE_URL, {
headers: { Accept: 'application/json' },
});
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}.link`,
};
}
}
}
if (releaseInfo.cid) {
return {
cid: releaseInfo.cid,
link: `https://${releaseInfo.cid}.ipfs.cf-ipfs.com`,
};
}
return null;
},
{ ...STRATEGY_LAZY, isPaused: () => !dynamics.ipfsMode },
);

const isUpdateAvailable = Boolean(
!areConditionsAccepted &&
remoteCidSWR.data &&
currentCidSWR.data &&
remoteCidSWR.data.cid !== currentCidSWR.data,
);

return {
isUpdateAvailable,
setConditionsAccepted,
get data() {
return {
remoteCid: remoteCidSWR.data?.cid,
currentCid: currentCidSWR.data,
remoteCidLink: remoteCidSWR.data?.link,
};
},
get initialLoading() {
return remoteCidSWR.initialLoading || currentCidSWR.initialLoading;
},
get loading() {
return remoteCidSWR.loading || currentCidSWR.loading;
},
get error() {
return remoteCidSWR.error || currentCidSWR.error;
},
};
};
5 changes: 3 additions & 2 deletions features/stake/stake.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { dynamics } from 'config';
import { useWeb3Key } from 'shared/hooks/useWeb3Key';
import NoSSRWrapper from 'shared/components/no-ssr-wrapper';
import { GoerliSunsetBanner } from 'shared/banners/goerli-sunset';

import { StakeFaq } from './stake-faq/stake-faq';
import { LidoStats } from './lido-stats/lido-stats';
import { StakeForm } from './stake-form';
import { GoerliSunsetBanner } from 'shared/banners/goerli-sunset';

export const Stake = () => {
const key = useWeb3Key();
Expand All @@ -15,7 +16,7 @@ export const Stake = () => {
<StakeForm key={key} />
</NoSSRWrapper>
<LidoStats />
<StakeFaq />
{!dynamics.ipfsMode && <StakeFaq />}
</>
);
};
3 changes: 2 additions & 1 deletion features/withdrawals/claim/claim.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { dynamics } from 'config';
import { TransactionModalProvider } from 'shared/transaction-modal/transaction-modal-context';
import { ClaimFaq } from 'features/withdrawals/withdrawals-faq/claim-faq';

Expand All @@ -12,7 +13,7 @@ export const Claim = () => {
<ClaimFormProvider>
<ClaimWallet />
<ClaimForm />
<ClaimFaq />
{!dynamics.ipfsMode && <ClaimFaq />}
<TxClaimModal />
</ClaimFormProvider>
</TransactionModalProvider>
Expand Down
3 changes: 2 additions & 1 deletion features/withdrawals/request/request.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { dynamics } from 'config';
import { RequestFormProvider } from './request-form-context';
import { RequestFaq } from '../withdrawals-faq/request-faq';
import { RequestForm } from './form';
Expand All @@ -11,7 +12,7 @@ export const Request = () => {
<RequestFormProvider>
<RequestWallet />
<RequestForm />
<RequestFaq />
{!dynamics.ipfsMode && <RequestFaq />}
<TxRequestModal />
</RequestFormProvider>
</TransactionModalProvider>
Expand Down
1 change: 1 addition & 0 deletions features/withdrawals/withdrawals-tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const WithdrawalsTabs = () => {
return (
<ClaimDataProvider>
<Switch checked={isClaimTab} routes={withdrawalRoutes} />

<GoerliSunsetBanner />
{isClaimTab ? <Claim /> : <Request />}
</ClaimDataProvider>
Expand Down
3 changes: 2 additions & 1 deletion features/wsteth/wrap-unwrap-tabs.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
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';
Expand Down Expand Up @@ -27,7 +28,7 @@ export const WrapUnwrapTabs = ({ mode }: WrapUnwrapLayoutProps) => {
<Wallet />
{isUnwrapMode ? <UnwrapForm /> : <WrapForm />}
</NoSsrWrapper>
<WrapFaq />
{!dynamics.ipfsMode && <WrapFaq />}
</>
);
};
2 changes: 2 additions & 0 deletions pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,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';

// Migrations old theme cookies to new cross domain cookies
migrationThemeCookiesToCrossDomainCookiesClientSide();
Expand Down Expand Up @@ -47,6 +48,7 @@ const AppWrapper = (props: AppProps): JSX.Element => {
<ToastContainer />
<MemoApp {...rest} />
<CookiesTooltip />
<OutdatedHashBanner />
</Providers>
);
};
Expand Down
12 changes: 8 additions & 4 deletions utilsApi/withCSP.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,19 @@ export const contentSecurityPolicy: ContentSecurityPolicyOption = {
'https://*.walletconnect.org',
'https://*.walletconnect.com',
],
scriptSrc: ["'self'", "'unsafe-inline'", ...trustedHosts],
scriptSrc: [
"'self'",
"'unsafe-inline'",
...(developmentMode ? ["'unsafe-eval'"] : []), // for HMR
...trustedHosts,
],

// Allow fetch connections to any secure host
connectSrc: [
"'self'",
'https:',
'wss:',
// for HMR
...(developmentMode ? ['ws:'] : []),
...(developmentMode ? ['ws:'] : []), // for HMR
],

...(!dynamics.ipfsMode && {
Expand All @@ -48,7 +52,7 @@ export const contentSecurityPolicy: ContentSecurityPolicyOption = {
'https://*.walletconnect.com',
],
workerSrc: ["'none'"],
'base-uri': ["'none'"],
'base-uri': dynamics.ipfsMode ? undefined : ["'none'"],
},
reportOnly,
};
Expand Down

0 comments on commit 9ff174e

Please sign in to comment.