diff --git a/src/components/AssetTable.tsx b/src/components/AssetTable.tsx index f886d90..f7a5761 100644 --- a/src/components/AssetTable.tsx +++ b/src/components/AssetTable.tsx @@ -2,7 +2,6 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react' import { tooltipOptions, tooltipsText } from '../metadata/tootltips' import { usePredictoorsContext } from '@/contexts/PredictoorsContext' -import { useSocketContext } from '@/contexts/SocketContext' import LiveTime from '@/elements/LiveTime' import { TableRowWrapper } from '@/elements/TableRowWrapper' import Tooltip from '@/elements/Tooltip' @@ -42,7 +41,7 @@ export type TAssetTableState = { export const AssetTable: React.FC = ({ contracts }) => { const { subscribedPredictoors, currentEpoch, secondsPerEpoch } = usePredictoorsContext() - const { epochData } = useSocketContext() + const [tableColumns, setTableColumns] = useState(assetTableColumns) const [assetsData, setAssetsData] = useState( [] ) @@ -111,12 +110,13 @@ export const AssetTable: React.FC = ({ contracts }) => { useEffect(() => { if (!currentEpoch) return - assetTableColumns[1].Header = formatTime( + let newAssetTableColumns = JSON.parse(JSON.stringify(assetTableColumns)) + newAssetTableColumns[1].Header = formatTime( new Date((currentEpoch - secondsPerEpoch) * 1000) ) - assetTableColumns[2].Header = formatTime(new Date(currentEpoch * 1000)) - assetTableColumns[3].Header = - assetTableColumns[4].Header = ( + newAssetTableColumns[2].Header = formatTime(new Date(currentEpoch * 1000)) + newAssetTableColumns[3].Header = + newAssetTableColumns[4].Header = (
{formatTime(new Date((currentEpoch + secondsPerEpoch) * 1000))} @@ -124,55 +124,60 @@ export const AssetTable: React.FC = ({ contracts }) => { Predictions
) - assetTableColumns[5].Header = ( + newAssetTableColumns[5].Header = (
Accuracy {` 24h`}
) + setTableColumns(newAssetTableColumns) }, [currentEpoch]) return ( - - - - {assetTableColumns.map((item) => ( -
- {item.Header} - +
+ + {tableColumns.map((item: any) => ( +
+ {item.Header} + +
+ ))} +
+ + {assetsData.length > 0 ? ( + + {assetsData.map((item) => ( + - - ))} - - - {assetsData.length > 0 ? ( - - {assetsData.map((item) => ( - - ))} - - ) : ( - - - - - - )} -
No contracts found
+ ))} + + ) : ( + + + No contracts found + + + )} + + ) ) } diff --git a/src/contexts/PredictoorsContext.tsx b/src/contexts/PredictoorsContext.tsx index 415327d..bdedd38 100644 --- a/src/contexts/PredictoorsContext.tsx +++ b/src/contexts/PredictoorsContext.tsx @@ -83,7 +83,7 @@ export const PredictoorsProvider: React.FC = ({ const { setEpochData, initialEpochData } = useSocketContext() const [currentChainTime, setCurrentChainTime] = useState(0) - const [currentEpoch, setCurrentEpoch] = useState(new Date().getTime()) + const [currentEpoch, setCurrentEpoch] = useState(0) const [secondsPerEpoch, setSecondsPerEpoch] = useState(0) const [predictoorInstances, setPredictorInstances] = useState< @@ -260,13 +260,13 @@ export const PredictoorsProvider: React.FC = ({ tempSigner = randomSigner as any as ethers.providers.JsonRpcSigner } - let cEpoch: number - let sPerEpoch: number + var cEpoch: number + var sPerEpoch: number const contractsToWatch = Object.values(contracts) const contractsResult = await Promise.all( - contractsToWatch.map(async (contract) => { + contractsToWatch.map(async (contract, key) => { const predictoor = new Predictoor( contract.address, networkProvider.getProvider(), @@ -275,7 +275,7 @@ export const PredictoorsProvider: React.FC = ({ isSapphireNetwork() ) await predictoor.init() - if (!sPerEpoch) { + if (key == 0) { cEpoch = await predictoor.getCurrentEpoch() sPerEpoch = await predictoor.getSecondsPerEpoch() setCurrentEpoch(cEpoch) @@ -333,107 +333,122 @@ export const PredictoorsProvider: React.FC = ({ predictedEpochs.current[contractAddress].push(item) }, []) - const addChainListener = useCallback(async () => { - if (!setEpochData || !address || !contracts || !signer) return - const SPE = await subscribedPredictoors[0]?.getSecondsPerEpoch() - const provider = networkProvider.getProvider() - provider.on('block', async (blockNumber) => { - const block = await provider.getBlock(blockNumber) - const currentTs = block.timestamp - const newCurrentEpoch = Math.floor(currentTs / SPE) - const authorizationData = - authorizationDataInstance.current?.getAuthorizationData() - if ( - currentTs - lastCheckedEpoch.current * SPE < - SPE + PREDICTION_FETCH_EPOCHS_DELAY || - !authorizationData - ) - return - lastCheckedEpoch.current = newCurrentEpoch - const predictionEpochs = calculatePredictionEpochs(newCurrentEpoch, SPE) - - const newEpochs = detectNewEpochs({ - subscribedPredictoors, - predictionEpochs, - predictedEpochs: predictedEpochs.current - }) - - const subscribedContractAddresses = subscribedPredictoors.map( - (contract) => contract.address - ) + const addChainListener = useCallback( + async (secondsPerEpoch: number, currentEpoch: number) => { + if (!predictoorInstances || currentEpoch == 0) return + const SPE = secondsPerEpoch + const provider = networkProvider.getProvider() + let cEpoch = currentEpoch + provider.on('block', async (blockNumber) => { + const block = await provider.getBlock(blockNumber) + const currentTs = block.timestamp + const newCurrentEpoch = Math.floor(currentTs / SPE) + if ( + currentTs - lastCheckedEpoch.current * SPE < + SPE + PREDICTION_FETCH_EPOCHS_DELAY + ) + return - const cachedValues = subscribedContractAddresses.flatMap( - (contractAddress) => { - const cachedValue = getPredictedEpochsByContract(contractAddress) - return cachedValue.map((item) => { - return { - ...item, - contractAddress - } - }) + if (currentTs > cEpoch + SPE) { + cEpoch = newCurrentEpoch * SPE + setCurrentEpoch(cEpoch) } - ) - if (currentTs > currentEpoch + secondsPerEpoch) { - setCurrentEpoch(newCurrentEpoch * secondsPerEpoch) - } + const authorizationData = + authorizationDataInstance.current?.getAuthorizationData() - getMultiplePredictions({ - currentTs: currentTs, - epochs: newEpochs, - contracts: subscribedPredictoors, - userWallet: signer, - registerPrediction: addItemToPredictedEpochs, - authorizationData - }).then((result) => { - subscribedPredictoors.forEach((contract) => { - const pickedResults = result.filter( - (item) => item !== null && item.contractAddress === contract.address - ) as DeepNonNullable> - - //get the epoch numbers from pickedResults - const pickedResultsEpochs = pickedResults.map((item) => item?.epoch) - - //clear the same epoch data from pickedCache - const pickedCaches = cachedValues.filter( - (cachedValue) => - cachedValue.contractAddress === contract.address && - !pickedResultsEpochs.includes(cachedValue.epoch) - ) + if ( + subscribedPredictoors.length === 0 || + !address || + !signer || + !authorizationData + ) + return - const items = [...pickedCaches, ...pickedResults] + lastCheckedEpoch.current = newCurrentEpoch + const predictionEpochs = calculatePredictionEpochs(newCurrentEpoch, SPE) - const dataPredictions = items.map((item) => - omit(item, ['contractAddress']) - ) + const newEpochs = detectNewEpochs({ + subscribedPredictoors, + predictionEpochs, + predictedEpochs: predictedEpochs.current + }) + + const subscribedContractAddresses = subscribedPredictoors.map( + (contract) => contract.address + ) - const blockchainFeedData: any = { - contractInfo: contracts[contract.address], - predictions: dataPredictions + const cachedValues = subscribedContractAddresses.flatMap( + (contractAddress) => { + const cachedValue = getPredictedEpochsByContract(contractAddress) + return cachedValue.map((item) => { + return { + ...item, + contractAddress + } + }) } + ) - setEpochData((prev) => { - if (!prev) return [blockchainFeedData] + getMultiplePredictions({ + currentTs: currentTs, + epochs: newEpochs, + contracts: subscribedPredictoors, + userWallet: signer, + registerPrediction: addItemToPredictedEpochs, + authorizationData + }).then((result) => { + subscribedPredictoors.forEach((contract) => { + const pickedResults = result.filter( + (item) => + item !== null && item.contractAddress === contract.address + ) as DeepNonNullable> + + //get the epoch numbers from pickedResults + const pickedResultsEpochs = pickedResults.map((item) => item?.epoch) + + //clear the same epoch data from pickedCache + const pickedCaches = cachedValues.filter( + (cachedValue) => + cachedValue.contractAddress === contract.address && + !pickedResultsEpochs.includes(cachedValue.epoch) + ) - const prevItems = prev.filter( - (item) => item.contractInfo.address !== contract.address + const items = [...pickedCaches, ...pickedResults] + + const dataPredictions = items.map((item) => + omit(item, ['contractAddress']) ) - return [...prevItems, blockchainFeedData] + const blockchainFeedData: any = { + contractInfo: contracts ? contracts[contract.address] : null, + predictions: dataPredictions + } + + setEpochData((prev) => { + if (!prev) return [blockchainFeedData] + + const prevItems = prev.filter( + (item) => item.contractInfo.address !== contract.address + ) + + return [...prevItems, blockchainFeedData] + }) }) }) + //await contract.getAggPredval(epoch, predictoorWallet) }) - //await contract.getAggPredval(epoch, predictoorWallet) - }) - }, [ - setEpochData, - address, - contracts, - subscribedPredictoors, - getPredictedEpochsByContract, - addItemToPredictedEpochs, - signer - ]) + }, + [ + setEpochData, + address, + contracts, + subscribedPredictoors.length, + getPredictedEpochsByContract, + addItemToPredictedEpochs, + signer + ] + ) useEffect(() => { if (!contracts) return @@ -441,13 +456,23 @@ export const PredictoorsProvider: React.FC = ({ }, [initializeContracts, contracts, signer]) useEffect(() => { - if (subscribedPredictoors.length === 0) return + if ( + predictoorInstances.length == 0 || + secondsPerEpoch == 0 || + currentEpoch == 0 + ) + return const provider = networkProvider.getProvider() - addChainListener() + addChainListener(secondsPerEpoch, currentEpoch) return () => { provider.removeAllListeners('block') } - }, [subscribedPredictoors, addChainListener]) + }, [ + predictoorInstances, + secondsPerEpoch, + currentEpoch, + subscribedPredictoors + ]) useEffect(() => { getAllInterestingPredictionContracts(currentConfig.subgraph).then( diff --git a/src/elements/TableRowWrapper.tsx b/src/elements/TableRowWrapper.tsx index 105cb90..b3e87e8 100644 --- a/src/elements/TableRowWrapper.tsx +++ b/src/elements/TableRowWrapper.tsx @@ -24,22 +24,24 @@ export const TableRowWrapper: React.FC = ({ ...rest }) => { return ( - - {React.Children.map(children, (child: any, index) => { - const isHeader = cellType === 'th' - const cellKeyIndex = { - key: `${isHeader ? 'header' : 'cell'}${index}` - } - return React.createElement( - cellType, - { - ...cellProps, - ...cellKeyIndex, - id: child?.props?.id === 'asset' ? styles.alignStart : '' - }, - child - ) - })} - + children && ( + + {React.Children.map(children, (child: any, index) => { + const isHeader = cellType === 'th' + const cellKeyIndex = { + key: `${isHeader ? 'header' : 'cell'}${index}` + } + return React.createElement( + cellType, + { + ...cellProps, + ...cellKeyIndex, + id: child?.props?.id === 'asset' ? styles.alignStart : '' + }, + child + ) + })} + + ) ) }