diff --git a/src/@context/Web3Legacy.tsx b/src/@context/Web3Legacy.tsx new file mode 100644 index 000000000..4723c1cf3 --- /dev/null +++ b/src/@context/Web3Legacy.tsx @@ -0,0 +1,63 @@ +// init web3.js object for compatibility with ocean.js + +import React, { + useContext, + useState, + useEffect, + createContext, + ReactElement, + ReactNode +} from 'react' +import Web3 from 'web3' +import { LoggerInstance } from '@oceanprotocol/lib' +import { useAccount, useNetwork, useProvider } from 'wagmi' + +interface Web3LegacyProviderValue { + web3: Web3 + web3Loading: boolean +} + +const Web3LegacyContext = createContext({} as Web3LegacyProviderValue) + +function Web3LegacyProvider({ + children +}: { + children: ReactNode +}): ReactElement { + const { address } = useAccount() + const { chain } = useNetwork() + const web3Provider = useProvider() + + const [web3, setWeb3] = useState() + const [web3Loading, setWeb3Loading] = useState(true) + + useEffect(() => { + const init = async () => { + if (!web3Provider || !address || !chain?.id) return + + try { + setWeb3Loading(true) + const web3 = new Web3(web3Provider as any) + setWeb3(web3) + } catch (error) { + LoggerInstance.error(error.message) + } finally { + setWeb3Loading(false) + } + } + init() + }, [web3Provider, address, chain?.id]) + + return ( + + {children} + + ) +} + +// Helper hook to access the provider values +const useWeb3Legacy = (): Web3LegacyProviderValue => + useContext(Web3LegacyContext) + +export { Web3LegacyProvider, useWeb3Legacy, Web3LegacyContext } +export default Web3LegacyProvider diff --git a/src/@hooks/useNftFactory.ts b/src/@hooks/useNftFactory.ts index 660332c2b..4411a3264 100644 --- a/src/@hooks/useNftFactory.ts +++ b/src/@hooks/useNftFactory.ts @@ -2,9 +2,11 @@ import { useEffect, useState } from 'react' import { NftFactory } from '@oceanprotocol/lib' import { getOceanConfig } from '@utils/ocean' import { useNetwork } from 'wagmi' +import { useWeb3Legacy } from '@context/Web3Legacy' function useNftFactory(): NftFactory { const { chain } = useNetwork() + const { web3 } = useWeb3Legacy() const [nftFactory, setNftFactory] = useState() useEffect(() => { diff --git a/src/components/Asset/AssetActions/ButtonBuy/index.test.tsx b/src/components/Asset/AssetActions/ButtonBuy/index.test.tsx index dd0a2b3b9..0d4edd612 100644 --- a/src/components/Asset/AssetActions/ButtonBuy/index.test.tsx +++ b/src/components/Asset/AssetActions/ButtonBuy/index.test.tsx @@ -16,7 +16,8 @@ const downloadProps: ButtonBuyProps = { priceType: 'fixed', isConsumable: true, isBalanceSufficient: true, - consumableFeedback: 'TEST: consumableFeedback' + consumableFeedback: 'TEST: consumableFeedback', + isAccountConnected: true } const computeProps: ButtonBuyProps = { diff --git a/src/components/Asset/AssetActions/ButtonBuy/index.tsx b/src/components/Asset/AssetActions/ButtonBuy/index.tsx index 9bb264ba0..5517de802 100644 --- a/src/components/Asset/AssetActions/ButtonBuy/index.tsx +++ b/src/components/Asset/AssetActions/ButtonBuy/index.tsx @@ -2,7 +2,6 @@ import React, { FormEvent, ReactElement } from 'react' import Button from '../../../@shared/atoms/Button' import styles from './index.module.css' import Loader from '../../../@shared/atoms/Loader' -import Web3 from 'web3' export interface ButtonBuyProps { action: 'download' | 'compute' @@ -30,6 +29,7 @@ export interface ButtonBuyProps { algorithmPriceType?: string isAlgorithmConsumable?: boolean isSupportedOceanNetwork?: boolean + isAccountConnected?: boolean hasProviderFee?: boolean retry?: boolean } @@ -45,13 +45,13 @@ function getConsumeHelpText( isBalanceSufficient: boolean, consumableFeedback: string, isSupportedOceanNetwork: boolean, - web3: Web3, + isAccountConnected: boolean, priceType: string ) { const text = isConsumable === false ? consumableFeedback - : hasPreviousOrder && web3 && isSupportedOceanNetwork + : hasPreviousOrder && isAccountConnected && isSupportedOceanNetwork ? `You bought this ${assetType} already allowing you to use it without paying again.` : hasDatatoken ? `You own ${dtBalance} ${dtSymbol} allowing you to use this dataset by spending 1 ${dtSymbol}, but without paying ${btSymbol} again.` @@ -73,7 +73,7 @@ function getAlgoHelpText( hasDatatokenSelectedComputeAsset: boolean, isBalanceSufficient: boolean, isSupportedOceanNetwork: boolean, - web3: Web3, + isAccountConnected: boolean, algorithmPriceType: string ) { const text = @@ -81,11 +81,13 @@ function getAlgoHelpText( isConsumable === false || isAlgorithmConsumable === false ? '' - : hasPreviousOrderSelectedComputeAsset && web3 && isSupportedOceanNetwork + : hasPreviousOrderSelectedComputeAsset && + isAccountConnected && + isSupportedOceanNetwork ? `You already bought the selected ${selectedComputeAssetType}, allowing you to use it without paying again.` : hasDatatokenSelectedComputeAsset ? `You own ${dtBalanceSelectedComputeAsset} ${dtSymbolSelectedComputeAsset} allowing you to use the selected ${selectedComputeAssetType} by spending 1 ${dtSymbolSelectedComputeAsset}, but without paying OCEAN again.` - : web3 && !isSupportedOceanNetwork + : isAccountConnected && !isSupportedOceanNetwork ? `Connect to the correct network to interact with this asset.` : isBalanceSufficient === false ? '' @@ -114,7 +116,7 @@ function getComputeAssetHelpText( selectedComputeAssetType?: string, isAlgorithmConsumable?: boolean, isSupportedOceanNetwork?: boolean, - web3?: Web3, + isAccountConnected?: boolean, hasProviderFee?: boolean ) { const computeAssetHelpText = getConsumeHelpText( @@ -128,7 +130,7 @@ function getComputeAssetHelpText( isBalanceSufficient, consumableFeedback, isSupportedOceanNetwork, - web3, + isAccountConnected, priceType ) @@ -142,7 +144,7 @@ function getComputeAssetHelpText( hasDatatokenSelectedComputeAsset, isBalanceSufficient, isSupportedOceanNetwork, - web3, + isAccountConnected, algorithmPriceType ) @@ -182,7 +184,8 @@ export default function ButtonBuy({ isAlgorithmConsumable, hasProviderFee, retry, - isSupportedOceanNetwork + isSupportedOceanNetwork, + isAccountConnected }: ButtonBuyProps): ReactElement { const buttonText = retry ? 'Retry' @@ -214,7 +217,7 @@ export default function ButtonBuy({ isBalanceSufficient, consumableFeedback, isSupportedOceanNetwork, - web3, + isAccountConnected, priceType ) } else { @@ -237,7 +240,7 @@ export default function ButtonBuy({ selectedComputeAssetType, isAlgorithmConsumable, isSupportedOceanNetwork, - web3, + isAccountConnected, hasProviderFee ) } diff --git a/src/components/Asset/AssetActions/Compute/FormComputeDataset.tsx b/src/components/Asset/AssetActions/Compute/FormComputeDataset.tsx index 41cc94b58..5d32306bc 100644 --- a/src/components/Asset/AssetActions/Compute/FormComputeDataset.tsx +++ b/src/components/Asset/AssetActions/Compute/FormComputeDataset.tsx @@ -79,7 +79,7 @@ export default function FormStartCompute({ retry: boolean }): ReactElement { const { siteContent } = useMarketMetadata() - const { address: accountId } = useAccount() + const { address: accountId, isConnected } = useAccount() const { balance } = useBalance() const { isSupportedOceanNetwork } = useNetworkMetadata() const { isValid, values }: FormikContextType<{ algorithm: string }> = @@ -312,6 +312,7 @@ export default function FormStartCompute({ isSupportedOceanNetwork={isSupportedOceanNetwork} hasProviderFee={providerFeeAmount && providerFeeAmount !== '0'} retry={retry} + isAccountConnected={isConnected} /> ) diff --git a/src/components/Asset/AssetActions/Compute/index.tsx b/src/components/Asset/AssetActions/Compute/index.tsx index 19b1c8fbd..471313ec8 100644 --- a/src/components/Asset/AssetActions/Compute/index.tsx +++ b/src/components/Asset/AssetActions/Compute/index.tsx @@ -44,8 +44,8 @@ import { handleComputeOrder } from '@utils/order' import { getComputeFeedback } from '@utils/feedback' import { initializeProviderForCompute } from '@utils/provider' import { useUserPreferences } from '@context/UserPreferences' -import { useAsset } from '@context/Asset' import { useAccount } from 'wagmi' +import { useWeb3Legacy } from '@context/Web3Legacy' const refreshInterval = 10000 // 10 sec. @@ -64,7 +64,7 @@ export default function Compute({ }): ReactElement { const { address: accountId } = useAccount() const { chainIds } = useUserPreferences() - const { isAssetNetwork } = useAsset() + const { web3 } = useWeb3Legacy() const newAbortController = useAbortController() const newCancelToken = useCancelToken() @@ -187,6 +187,7 @@ export default function Compute({ const datasetPriceAndFees = await getOrderPriceAndFees( asset, ZERO_ADDRESS, + web3, initializedProvider?.datasets?.[0]?.providerFee ) if (!datasetPriceAndFees) @@ -210,6 +211,7 @@ export default function Compute({ const algorithmOrderPriceAndFees = await getOrderPriceAndFees( selectedAlgorithmAsset, ZERO_ADDRESS, + web3, initializedProvider.algorithm.providerFee ) if (!algorithmOrderPriceAndFees) diff --git a/src/components/Asset/AssetActions/Download.tsx b/src/components/Asset/AssetActions/Download.tsx index 574450012..f2ae5550d 100644 --- a/src/components/Asset/AssetActions/Download.tsx +++ b/src/components/Asset/AssetActions/Download.tsx @@ -18,7 +18,7 @@ import Alert from '@shared/atoms/Alert' import Loader from '@shared/atoms/Loader' import { useAccount } from 'wagmi' import useNetworkMetadata from '@hooks/useNetworkMetadata' -import Web3 from 'web3' +import { useWeb3Legacy } from '@context/Web3Legacy' export default function Download({ asset, @@ -35,7 +35,8 @@ export default function Download({ fileIsLoading?: boolean consumableFeedback?: string }): ReactElement { - const { address: accountId, connector, isConnected } = useAccount() + const { address: accountId, isConnected } = useAccount() + const { web3 } = useWeb3Legacy() const { isSupportedOceanNetwork } = useNetworkMetadata() const { getOpcFeeForToken } = useMarketMetadata() const { isInPurgatory, isAssetNetwork } = useAsset() @@ -52,7 +53,6 @@ export default function Download({ const [orderPriceAndFees, setOrderPriceAndFees] = useState() const [retry, setRetry] = useState(false) - const [web3, setWeb3] = useState() const isUnsupportedPricing = !asset?.accessDetails || @@ -62,21 +62,6 @@ export default function Download({ (asset?.accessDetails?.type === 'fixed' && !asset?.accessDetails?.baseToken?.symbol) - // init web3.js object for compatibility with ocean.js - useEffect(() => { - const init = async () => { - if (!connector || !isConnected) return - - try { - const web3 = new Web3(await connector.getProvider()) - setWeb3(web3) - } catch (error) { - LoggerInstance.error(error.message) - } - } - init() - }, [connector, isConnected]) - useEffect(() => { Number(asset?.nft.state) === 4 && setIsOrderDisabled(true) }, [asset?.nft.state]) @@ -219,6 +204,7 @@ export default function Download({ consumableFeedback={consumableFeedback} retry={retry} isSupportedOceanNetwork={isSupportedOceanNetwork} + isAccountConnected={isConnected} /> ) diff --git a/src/components/Asset/AssetContent/MetaFull.tsx b/src/components/Asset/AssetContent/MetaFull.tsx index e7f3dfdcf..6a147b3f0 100644 --- a/src/components/Asset/AssetContent/MetaFull.tsx +++ b/src/components/Asset/AssetContent/MetaFull.tsx @@ -4,15 +4,18 @@ import styles from './MetaFull.module.css' import Publisher from '@shared/Publisher' import { useAsset } from '@context/Asset' import { Asset, Datatoken, LoggerInstance } from '@oceanprotocol/lib' +import { useWeb3Legacy } from '@context/Web3Legacy' export default function MetaFull({ ddo }: { ddo: Asset }): ReactElement { + const { web3 } = useWeb3Legacy() const [paymentCollector, setPaymentCollector] = useState() const { isInPurgatory, assetState } = useAsset() useEffect(() => { + if (!ddo || !web3) return + async function getInitialPaymentCollector() { try { - if (!ddo) return const datatoken = new Datatoken(web3) setPaymentCollector( await datatoken.getPaymentCollector(ddo.datatokens[0].address) @@ -22,7 +25,7 @@ export default function MetaFull({ ddo }: { ddo: Asset }): ReactElement { } } getInitialPaymentCollector() - }, [ddo]) + }, [ddo, web3]) function DockerImage() { const containerInfo = ddo?.metadata?.algorithm?.container diff --git a/src/components/Asset/Edit/EditComputeDataset.tsx b/src/components/Asset/Edit/EditComputeDataset.tsx index 7a4ecc0dd..b058979bc 100644 --- a/src/components/Asset/Edit/EditComputeDataset.tsx +++ b/src/components/Asset/Edit/EditComputeDataset.tsx @@ -24,6 +24,7 @@ import EditFeedback from './EditFeedback' import { setNftMetadata } from '@utils/nft' import { ComputeEditForm } from './_types' import { useAccount } from 'wagmi' +import { useWeb3Legacy } from '@context/Web3Legacy' export default function EditComputeDataset({ asset @@ -33,6 +34,8 @@ export default function EditComputeDataset({ const { debug } = useUserPreferences() const { address: accountId } = useAccount() const { fetchAsset, isAssetNetwork } = useAsset() + const { web3 } = useWeb3Legacy() + const [success, setSuccess] = useState() const [error, setError] = useState() const newAbortController = useAbortController() diff --git a/src/components/Asset/Edit/EditMetadata.tsx b/src/components/Asset/Edit/EditMetadata.tsx index f1cf3f535..97dd996bf 100644 --- a/src/components/Asset/Edit/EditMetadata.tsx +++ b/src/components/Asset/Edit/EditMetadata.tsx @@ -28,6 +28,7 @@ import { sanitizeUrl } from '@utils/url' import { getEncryptedFiles } from '@utils/provider' import { assetStateToNumber } from '@utils/assetState' import { useAccount } from 'wagmi' +import { useWeb3Legacy } from '@context/Web3Legacy' export default function Edit({ asset @@ -37,7 +38,9 @@ export default function Edit({ const { debug } = useUserPreferences() const { fetchAsset, isAssetNetwork, assetState } = useAsset() const { address: accountId } = useAccount() + const { web3 } = useWeb3Legacy() const newAbortController = useAbortController() + const [success, setSuccess] = useState() const [paymentCollector, setPaymentCollector] = useState() const [error, setError] = useState() diff --git a/src/components/Profile/History/ComputeJobs/Results.tsx b/src/components/Profile/History/ComputeJobs/Results.tsx index d7c4d42be..1b2ba08de 100644 --- a/src/components/Profile/History/ComputeJobs/Results.tsx +++ b/src/components/Profile/History/ComputeJobs/Results.tsx @@ -13,6 +13,7 @@ import content from '../../../../../content/pages/history.json' import { useCancelToken } from '@hooks/useCancelToken' import { getAsset } from '@utils/aquarius' import { useAccount } from 'wagmi' +import { useWeb3Legacy } from '@context/Web3Legacy' export default function Results({ job @@ -21,11 +22,13 @@ export default function Results({ }): ReactElement { const providerInstance = new Provider() const { address: accountId } = useAccount() - const isFinished = job.dateFinished !== null + const { web3 } = useWeb3Legacy() const [datasetProvider, setDatasetProvider] = useState() const newCancelToken = useCancelToken() + const isFinished = job.dateFinished !== null + useEffect(() => { async function getAssetMetadata() { const ddo = await getAsset(job.inputDID[0], newCancelToken()) diff --git a/src/components/Publish/index.tsx b/src/components/Publish/index.tsx index 92bc98021..64b7f0e17 100644 --- a/src/components/Publish/index.tsx +++ b/src/components/Publish/index.tsx @@ -19,6 +19,7 @@ import { validationSchema } from './_validation' import { useAbortController } from '@hooks/useAbortController' import { setNFTMetadataAndTokenURI } from '@utils/nft' import { useAccount, useNetwork } from 'wagmi' +import { useWeb3Legacy } from '@context/Web3Legacy' export default function PublishPage({ content @@ -28,6 +29,7 @@ export default function PublishPage({ const { debug } = useUserPreferences() const { address: accountId } = useAccount() const { chain } = useNetwork() + const { web3 } = useWeb3Legacy() const { isInPurgatory, purgatoryData } = useAccountPurgatory(accountId) const scrollToRef = useRef() const nftFactory = useNftFactory() diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index bd63be0e5..873fa977a 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -13,25 +13,28 @@ import MarketMetadataProvider from '@context/MarketMetadata' import { WagmiConfig } from 'wagmi' import { Web3Modal } from '@web3modal/react' import { wagmiClient, ethereumClient } from '@utils/wallet' +import Web3LegacyProvider from '@context/Web3Legacy' function MyApp({ Component, pageProps }: AppProps): ReactElement { Decimal.set({ rounding: 1 }) return ( <> - - - - - - - - - - - - - + + + + + + + + + + + + + + +