diff --git a/content/site.json b/content/site.json index 4f319282a..6b6556de2 100644 --- a/content/site.json +++ b/content/site.json @@ -16,8 +16,13 @@ "link": "/history" } ], - "warning": "We are in beta. Please familiarize yourself with [the market](https://oceanprotocol.com/technology/marketplaces), [the risks](https://blog.oceanprotocol.com/on-staking-on-data-in-ocean-market-3d8e09eb0a13), and the [Terms of Use](/terms).", - "warningPolygon": "Polygon/Matic EVM support is in early stages. Use the Matic bridge to [get mOCEAN](https://docs.oceanprotocol.com/tutorials/polygon-bridge/).", - "warningPolygonPublish": "Only republish data sets with a pool from ETH Mainnet into Polygon/Matic if the liquidity is **less than or equal to 1000 OCEAN in the original pool**. Doing otherwise will lead to [purgatory](https://github.com/oceanprotocol/list-purgatory) for the data set in Polygon/Matic." + "warning": { + "main": "We are in beta. Please familiarize yourself with [the market](https://oceanprotocol.com/technology/marketplaces), [the risks](https://blog.oceanprotocol.com/on-staking-on-data-in-ocean-market-3d8e09eb0a13), and the [Terms of Use](/terms).", + "polygonPublish": "Only republish data sets with a pool from ETH Mainnet into Polygon/Matic if the liquidity is **less than or equal to 1000 OCEAN in the original pool**. Doing otherwise will lead to [purgatory](https://github.com/oceanprotocol/list-purgatory) for the data set in Polygon/Matic." + }, + "announcement": { + "main": "Ocean Market is [available on Polygon](https://blog.oceanprotocol.com/ocean-on-polygon-network-8abad19cbf47).", + "polygon": "Polygon/Matic EVM support is in early stages. [Use the Polygon Bridge](https://docs.oceanprotocol.com/tutorials/polygon-bridge/) to get mOCEAN." + } } } diff --git a/src/components/App.tsx b/src/components/App.tsx index 4ab47db40..0818321bb 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -7,6 +7,7 @@ import { useSiteMetadata } from '../hooks/useSiteMetadata' import Alert from './atoms/Alert' import { graphql, PageProps, useStaticQuery } from 'gatsby' import { useAccountPurgatory } from '../hooks/useAccountPurgatory' +import AnnouncementBanner from './molecules/AnnouncementBanner' import { useWeb3 } from '../providers/Web3' const contentQuery = graphql` @@ -35,20 +36,17 @@ export default function App({ const data = useStaticQuery(contentQuery) const purgatory = data.purgatory.edges[0].node.childContentJson.account - const { warning, warningPolygon } = useSiteMetadata() + const { warning } = useSiteMetadata() const { accountId } = useWeb3() const { isInPurgatory, purgatoryData } = useAccountPurgatory(accountId) - const { networkId } = useWeb3() return (
+ {!location.pathname.includes('/asset/did') && }
{(props as PageProps).uri === '/' && ( - + )} {isInPurgatory && ( div { + display: inline-block; +} + +.banner button { + font-size: calc(var(--font-size-small) / 1.1); +} + +.text { + font-size: var(--font-size-small); + font-weight: var(--font-weight-bold); + margin: 0; + margin-right: calc(var(--spacer) / 4); + text-align: center; +} + +.text a { + color: inherit; + text-decoration: underline; +} + +.text p:last-child { + margin-bottom: 0; +} diff --git a/src/components/molecules/AnnouncementBanner.tsx b/src/components/molecules/AnnouncementBanner.tsx new file mode 100644 index 000000000..3aaacb237 --- /dev/null +++ b/src/components/molecules/AnnouncementBanner.tsx @@ -0,0 +1,103 @@ +import React, { ReactElement, useEffect, useState } from 'react' +import styles from './AnnouncementBanner.module.css' +import Markdown from '../atoms/Markdown' +import { useWeb3 } from '../../providers/Web3' +import { addCustomNetwork, NetworkObject } from '../../utils/web3' +import { getOceanConfig } from '../../utils/ocean' +import { getProviderInfo } from 'web3modal' +import { useOcean } from '../../providers/Ocean' +import { useSiteMetadata } from '../../hooks/useSiteMetadata' +import Button from '../atoms/Button' + +export interface AnnouncementAction { + name: string + style?: string + handleAction: () => void +} + +const network: NetworkObject = { + chainId: 137, + name: 'Matic Network', + urlList: [ + 'https://rpc-mainnet.matic.network', + 'https://rpc-mainnet.maticvigil.com/' + ] +} + +export default function AnnouncementBanner(): ReactElement { + const { web3Provider } = useWeb3() + const { config, connect } = useOcean() + const { announcement } = useSiteMetadata() + + const [text, setText] = useState(announcement.main) + const [action, setAction] = useState() + + const addCustomNetworkAction = { + name: 'Add custom network', + handleAction: () => addCustomNetwork(web3Provider, network) + } + const switchToPolygonAction = { + name: 'Switch to Polygon', + handleAction: async () => { + const config = getOceanConfig('polygon') + await connect(config) + } + } + const switchToEthAction = { + name: 'Switch to ETH', + handleAction: async () => { + const config = getOceanConfig('mainnet') + await connect(config) + } + } + + function setBannerForMatic() { + setText(announcement.polygon) + setAction(undefined) + } + + useEffect(() => { + if (!web3Provider && !config) return + + const providerInfo = getProviderInfo(web3Provider) + switch (providerInfo?.name) { + case 'Web3': + if (config.networkId !== 137) { + setText(announcement.main) + setAction(switchToPolygonAction) + } else { + setText(announcement.polygon) + setAction(switchToEthAction) + } + break + case 'MetaMask': + if (config.networkId === 137) { + setBannerForMatic() + } else { + setText(announcement.main) + setAction(addCustomNetworkAction) + } + break + default: + if (config.networkId === 137) { + setBannerForMatic() + } else { + setText(announcement.main) + setAction(undefined) + } + } + }, [web3Provider, config, announcement]) + + return ( +
+
+ {text && } + {action && ( + + )} +
+
+ ) +} diff --git a/src/components/molecules/Wallet/Details.tsx b/src/components/molecules/Wallet/Details.tsx index 8349727a0..39247c642 100644 --- a/src/components/molecules/Wallet/Details.tsx +++ b/src/components/molecules/Wallet/Details.tsx @@ -8,6 +8,7 @@ import Conversion from '../../atoms/Price/Conversion' import { formatCurrency } from '@coingecko/cryptoformat' import { useUserPreferences } from '../../../providers/UserPreferences' import { useWeb3 } from '../../../providers/Web3' +import { addOceanToWallet } from '../../../utils/web3' import { Logger } from '@oceanprotocol/lib' export default function Details(): ReactElement { @@ -27,39 +28,6 @@ export default function Details(): ReactElement { setProviderInfo(providerInfo) }, [web3Provider]) - async function addOceanToWallet() { - const tokenMetadata = { - type: 'ERC20', - options: { - address: config.oceanTokenAddress, - symbol: config.oceanTokenSymbol, - decimals: 18, - image: - 'https://raw.githubusercontent.com/oceanprotocol/art/main/logo/token.png' - } - } - web3Provider.sendAsync( - { - method: 'wallet_watchAsset', - params: tokenMetadata, - id: Math.round(Math.random() * 100000) - }, - (err: string, added: any) => { - if (err || 'error' in added) { - Logger.error( - `Couldn't add ${tokenMetadata.options.symbol} (${ - tokenMetadata.options.address - }) to MetaMask, error: ${err || added.error}` - ) - } else { - Logger.log( - `Added ${tokenMetadata.options.symbol} (${tokenMetadata.options.address}) to MetaMask` - ) - } - } - ) - } - useEffect(() => { if (!networkData) return @@ -112,7 +80,7 @@ export default function Details(): ReactElement { style="text" size="small" onClick={() => { - addOceanToWallet() + addOceanToWallet(config, web3Provider) }} > {`Add ${config.oceanTokenSymbol}`} diff --git a/src/components/organisms/AssetActions/Pool/Add/index.tsx b/src/components/organisms/AssetActions/Pool/Add/index.tsx index 555f4266f..7af8d4eb6 100644 --- a/src/components/organisms/AssetActions/Pool/Add/index.tsx +++ b/src/components/organisms/AssetActions/Pool/Add/index.tsx @@ -174,7 +174,7 @@ export default function Add({ ) : ( () @@ -114,10 +112,7 @@ export default function PublishPage({ ) : ( <> diff --git a/src/hooks/useSiteMetadata.ts b/src/hooks/useSiteMetadata.ts index c88be60cf..3abf2bbd4 100644 --- a/src/hooks/useSiteMetadata.ts +++ b/src/hooks/useSiteMetadata.ts @@ -13,9 +13,14 @@ const query = graphql` name link } - warning - warningPolygon - warningPolygonPublish + warning { + main + polygonPublish + } + announcement { + main + polygon + } appConfig { infuraProjectId network diff --git a/src/utils/web3.ts b/src/utils/web3.ts index f0f78d91a..73c64b8ac 100644 --- a/src/utils/web3.ts +++ b/src/utils/web3.ts @@ -1,3 +1,6 @@ +import { Logger } from '@oceanprotocol/lib' +import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper' + export interface EthereumListsChain { name: string chainId: number @@ -11,6 +14,12 @@ export interface EthereumListsChain { infoURL: string } +export interface NetworkObject { + chainId: number + name: string + urlList: string[] +} + export function accountTruncate(account: string): string { if (!account) return const middle = account.substring(6, 38) @@ -40,3 +49,68 @@ export function getNetworkData( )[0] return networkData.node } + +export function addCustomNetwork( + web3Provider: any, + network: NetworkObject +): void { + const newNewtworkData = { + chainId: `0x${network.chainId.toString(16)}`, + rpcUrls: network.urlList + } + web3Provider.request( + { + method: 'wallet_addEthereumChain', + params: [newNewtworkData] + }, + (err: string, added: any) => { + if (err || 'error' in added) { + Logger.error( + `Couldn't add ${network.name} (0x${ + network.chainId + }) netowrk to MetaMask, error: ${err || added.error}` + ) + } else { + Logger.log( + `Added ${network.name} (0x${network.chainId}) network to MetaMask` + ) + } + } + ) +} + +export function addOceanToWallet( + config: ConfigHelperConfig, + web3Provider: any +): void { + const tokenMetadata = { + type: 'ERC20', + options: { + address: config.oceanTokenAddress, + symbol: config.oceanTokenSymbol, + decimals: 18, + image: + 'https://raw.githubusercontent.com/oceanprotocol/art/main/logo/token.png' + } + } + web3Provider.sendAsync( + { + method: 'wallet_watchAsset', + params: tokenMetadata, + id: Math.round(Math.random() * 100000) + }, + (err: string, added: any) => { + if (err || 'error' in added) { + Logger.error( + `Couldn't add ${tokenMetadata.options.symbol} (${ + tokenMetadata.options.address + }) to MetaMask, error: ${err || added.error}` + ) + } else { + Logger.log( + `Added ${tokenMetadata.options.symbol} (${tokenMetadata.options.address}) to MetaMask` + ) + } + } + ) +}