mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
4331c24c0d
* get poolShares dt addresses * style fixes * class names fix * remove useless changes * fix * try/catch blocks, loading fix * show pool shares fix * delete logs, fix build * more try/catch blocks * check subgraph url, add try/catch block * fixes * pool fields fix * minor code fixes * fix subgraph fetch Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * remove unused function, fixes * use LoggerInstance, remove useless setter * error messages fix, get rid of dt column * small tweaks and tests * fixes * fixes * modified flow for pool shares * loading UX fixes * unified calculations for pool liquidity * stop the refetch madness * profile provider already sets interval fetching for pool shares * pool shares will change when chainIds, accountId is changed so no need to listen for changes again * calculation tweaks * pool stats tweak * fix pool transactions * fix data display in pool shares section * minor fix, delete comment * subgraph typings generation fix * pool stats display tweaks * price sizing fix * rabbit hole fixes * more price UI fixes * cleanup * wording consistency * render all frontpage sections by default, load in assets after Co-authored-by: ClaudiaHolhos <claudia@oceanprotocol.com> Co-authored-by: mihaisc <mihai.scarlat@smartcontrol.ro> Co-authored-by: mihaisc <mihai@oceanprotocol.com> Co-authored-by: Matthias Kretschmann <m@kretschmann.io>
324 lines
8.6 KiB
TypeScript
324 lines
8.6 KiB
TypeScript
import React, {
|
|
useContext,
|
|
useState,
|
|
useEffect,
|
|
createContext,
|
|
ReactElement,
|
|
useCallback,
|
|
ReactNode
|
|
} from 'react'
|
|
import {
|
|
getPoolSharesData,
|
|
getUserSales,
|
|
getUserTokenOrders
|
|
} from '@utils/subgraph'
|
|
import { useUserPreferences } from './UserPreferences'
|
|
import { PoolShares_poolShares as PoolShare } from '../@types/subgraph/PoolShares'
|
|
import { Asset, LoggerInstance } from '@oceanprotocol/lib'
|
|
import { getDownloadAssets, getPublishedAssets } from '@utils/aquarius'
|
|
import { useSiteMetadata } from '@hooks/useSiteMetadata'
|
|
import { accountTruncate } from '@utils/web3'
|
|
import axios, { CancelToken } from 'axios'
|
|
import get3BoxProfile from '@utils/profile'
|
|
import web3 from 'web3'
|
|
|
|
interface ProfileProviderValue {
|
|
profile: Profile
|
|
poolShares: PoolShare[]
|
|
isPoolSharesLoading: boolean
|
|
assets: Asset[]
|
|
assetsTotal: number
|
|
isEthAddress: boolean
|
|
downloads: DownloadedAsset[]
|
|
downloadsTotal: number
|
|
isDownloadsLoading: boolean
|
|
sales: number
|
|
}
|
|
|
|
const ProfileContext = createContext({} as ProfileProviderValue)
|
|
|
|
const refreshInterval = 10000 // 10 sec.
|
|
|
|
function ProfileProvider({
|
|
accountId,
|
|
accountEns,
|
|
children
|
|
}: {
|
|
accountId: string
|
|
accountEns: string
|
|
children: ReactNode
|
|
}): ReactElement {
|
|
const { chainIds } = useUserPreferences()
|
|
const { appConfig } = useSiteMetadata()
|
|
|
|
const [isEthAddress, setIsEthAddress] = useState<boolean>()
|
|
|
|
//
|
|
// Do nothing in all following effects
|
|
// when accountId is no ETH address
|
|
//
|
|
useEffect(() => {
|
|
const isEthAddress = web3.utils.isAddress(accountId)
|
|
setIsEthAddress(isEthAddress)
|
|
}, [accountId])
|
|
|
|
//
|
|
// User profile: ENS + 3Box
|
|
//
|
|
const [profile, setProfile] = useState<Profile>()
|
|
|
|
useEffect(() => {
|
|
if (!accountEns) return
|
|
LoggerInstance.log(`[profile] ENS name found for ${accountId}:`, accountEns)
|
|
}, [accountId, accountEns])
|
|
|
|
useEffect(() => {
|
|
const clearedProfile: Profile = {
|
|
name: null,
|
|
accountEns: null,
|
|
image: null,
|
|
description: null,
|
|
links: null
|
|
}
|
|
|
|
if (!accountId || !isEthAddress) {
|
|
setProfile(clearedProfile)
|
|
return
|
|
}
|
|
|
|
const cancelTokenSource = axios.CancelToken.source()
|
|
|
|
async function getInfo() {
|
|
setProfile({ name: accountEns || accountTruncate(accountId), accountEns })
|
|
|
|
const profile3Box = await get3BoxProfile(
|
|
accountId,
|
|
cancelTokenSource.token
|
|
)
|
|
if (profile3Box) {
|
|
const { name, emoji, description, image, links } = profile3Box
|
|
const newName = `${emoji || ''} ${name || accountTruncate(accountId)}`
|
|
const newProfile = {
|
|
name: newName,
|
|
image,
|
|
description,
|
|
links
|
|
}
|
|
setProfile((prevState) => ({
|
|
...prevState,
|
|
...newProfile
|
|
}))
|
|
LoggerInstance.log('[profile] Found and set 3box profile.', newProfile)
|
|
} else {
|
|
// setProfile(clearedProfile)
|
|
LoggerInstance.log('[profile] No 3box profile found.')
|
|
}
|
|
}
|
|
getInfo()
|
|
|
|
return () => {
|
|
cancelTokenSource.cancel()
|
|
}
|
|
}, [accountId, accountEns, isEthAddress])
|
|
|
|
//
|
|
// POOL SHARES
|
|
//
|
|
const [poolShares, setPoolShares] = useState<PoolShare[]>()
|
|
const [isPoolSharesLoading, setIsPoolSharesLoading] = useState<boolean>(false)
|
|
const [poolSharesInterval, setPoolSharesInterval] = useState<NodeJS.Timeout>()
|
|
|
|
const fetchPoolShares = useCallback(
|
|
async (accountId, chainIds, isEthAddress) => {
|
|
if (!accountId || !chainIds || !isEthAddress) return
|
|
|
|
try {
|
|
setIsPoolSharesLoading(true)
|
|
const poolShares = await getPoolSharesData(accountId, chainIds)
|
|
setPoolShares(poolShares)
|
|
LoggerInstance.log(
|
|
`[profile] Fetched ${poolShares.length} pool shares.`,
|
|
poolShares
|
|
)
|
|
} catch (error) {
|
|
LoggerInstance.error('Error fetching pool shares: ', error.message)
|
|
} finally {
|
|
setIsPoolSharesLoading(false)
|
|
}
|
|
},
|
|
[]
|
|
)
|
|
|
|
useEffect(() => {
|
|
async function init() {
|
|
await fetchPoolShares(accountId, chainIds, isEthAddress)
|
|
|
|
if (poolSharesInterval) return
|
|
|
|
const interval = setInterval(async () => {
|
|
LoggerInstance.log(
|
|
`[profile] Re-fetching pool shares after ${refreshInterval / 1000}s.`
|
|
)
|
|
await fetchPoolShares(accountId, chainIds, isEthAddress)
|
|
}, refreshInterval)
|
|
setPoolSharesInterval(interval)
|
|
}
|
|
init()
|
|
|
|
return () => {
|
|
clearInterval(poolSharesInterval)
|
|
}
|
|
}, [poolSharesInterval, fetchPoolShares, accountId, chainIds, isEthAddress])
|
|
|
|
//
|
|
// PUBLISHED ASSETS
|
|
//
|
|
const [assets, setAssets] = useState<Asset[]>()
|
|
const [assetsTotal, setAssetsTotal] = useState(0)
|
|
// const [assetsWithPrices, setAssetsWithPrices] = useState<AssetListPrices[]>()
|
|
|
|
useEffect(() => {
|
|
if (!accountId || !isEthAddress) return
|
|
|
|
const cancelTokenSource = axios.CancelToken.source()
|
|
|
|
async function getAllPublished() {
|
|
try {
|
|
const result = await getPublishedAssets(
|
|
accountId,
|
|
chainIds,
|
|
cancelTokenSource.token
|
|
)
|
|
setAssets(result.results)
|
|
setAssetsTotal(result.totalResults)
|
|
LoggerInstance.log(
|
|
`[profile] Fetched ${result.totalResults} assets.`,
|
|
result.results
|
|
)
|
|
|
|
// Hint: this would only make sense if we "search" in all subcomponents
|
|
// against this provider's state, meaning filtering via js rather then sending
|
|
// more queries to Aquarius.
|
|
// const assetsWithPrices = await getAssetsBestPrices(result.results)
|
|
// setAssetsWithPrices(assetsWithPrices)
|
|
} catch (error) {
|
|
LoggerInstance.error(error.message)
|
|
}
|
|
}
|
|
getAllPublished()
|
|
|
|
return () => {
|
|
cancelTokenSource.cancel()
|
|
}
|
|
}, [accountId, appConfig.metadataCacheUri, chainIds, isEthAddress])
|
|
|
|
//
|
|
// DOWNLOADS
|
|
//
|
|
const [downloads, setDownloads] = useState<DownloadedAsset[]>()
|
|
const [downloadsTotal, setDownloadsTotal] = useState(0)
|
|
const [isDownloadsLoading, setIsDownloadsLoading] = useState<boolean>()
|
|
const [downloadsInterval, setDownloadsInterval] = useState<NodeJS.Timeout>()
|
|
|
|
const fetchDownloads = useCallback(
|
|
async (cancelToken: CancelToken) => {
|
|
if (!accountId || !chainIds) return
|
|
|
|
const dtList: string[] = []
|
|
const tokenOrders = await getUserTokenOrders(accountId, chainIds)
|
|
|
|
for (let i = 0; i < tokenOrders?.length; i++) {
|
|
dtList.push(tokenOrders[i].datatoken.address)
|
|
}
|
|
const downloads = await getDownloadAssets(
|
|
dtList,
|
|
tokenOrders,
|
|
chainIds,
|
|
cancelToken
|
|
)
|
|
setDownloads(downloads)
|
|
setDownloadsTotal(downloads.length)
|
|
LoggerInstance.log(
|
|
`[profile] Fetched ${downloads.length} download orders.`,
|
|
downloads
|
|
)
|
|
},
|
|
[accountId, chainIds]
|
|
)
|
|
|
|
useEffect(() => {
|
|
const cancelTokenSource = axios.CancelToken.source()
|
|
|
|
async function getDownloadAssets() {
|
|
if (!appConfig?.metadataCacheUri) return
|
|
|
|
try {
|
|
setIsDownloadsLoading(true)
|
|
await fetchDownloads(cancelTokenSource.token)
|
|
} catch (err) {
|
|
LoggerInstance.log(err.message)
|
|
} finally {
|
|
setIsDownloadsLoading(false)
|
|
}
|
|
}
|
|
getDownloadAssets()
|
|
|
|
if (downloadsInterval) return
|
|
const interval = setInterval(async () => {
|
|
await fetchDownloads(cancelTokenSource.token)
|
|
}, refreshInterval)
|
|
setDownloadsInterval(interval)
|
|
|
|
return () => {
|
|
cancelTokenSource.cancel()
|
|
clearInterval(downloadsInterval)
|
|
}
|
|
}, [fetchDownloads, appConfig.metadataCacheUri, downloadsInterval])
|
|
|
|
//
|
|
// SALES NUMBER
|
|
//
|
|
const [sales, setSales] = useState(0)
|
|
useEffect(() => {
|
|
if (!accountId || chainIds.length === 0) {
|
|
setSales(0)
|
|
return
|
|
}
|
|
async function getUserSalesNumber() {
|
|
try {
|
|
const result = await getUserSales(accountId, chainIds)
|
|
setSales(result)
|
|
LoggerInstance.log(`[profile] Fetched sales number: ${result}.`, result)
|
|
} catch (error) {
|
|
LoggerInstance.error(error.message)
|
|
}
|
|
}
|
|
getUserSalesNumber()
|
|
}, [accountId, chainIds])
|
|
|
|
return (
|
|
<ProfileContext.Provider
|
|
value={{
|
|
profile,
|
|
poolShares,
|
|
isPoolSharesLoading,
|
|
assets,
|
|
assetsTotal,
|
|
isEthAddress,
|
|
downloads,
|
|
downloadsTotal,
|
|
isDownloadsLoading,
|
|
sales
|
|
}}
|
|
>
|
|
{children}
|
|
</ProfileContext.Provider>
|
|
)
|
|
}
|
|
|
|
// Helper hook to access the provider values
|
|
const useProfile = (): ProfileProviderValue => useContext(ProfileContext)
|
|
|
|
export { ProfileProvider, useProfile, ProfileContext }
|
|
export default ProfileProvider
|