import { AppState , AppDispatch } from './../index' ; import { TokenData , TokenChartEntry } from './reducer' ; import { useCallback , useEffect , useState , useMemo } from 'react' ; import { useDispatch , useSelector } from 'react-redux' ; import { updateTokenData , addTokenKeys , addPoolAddresses , updateChartData , updatePriceData , updateTransactions , } from './actions' ; import { isAddress } from 'ethers/lib/utils' ; import { fetchPoolsForToken } from 'data/tokens/poolsForToken' ; import { fetchTokenChartData } from 'data/tokens/chartData' ; import { fetchTokenPriceData } from 'data/tokens/priceData' ; import { fetchTokenTransactions } from 'data/tokens/transactions' ; import { PriceChartEntry , Transaction } from 'types' ; import { notEmpty } from 'utils' ; import dayjs , { OpUnitType } from 'dayjs' ; import utc from 'dayjs/plugin/utc' ; import { useActiveNetworkVersion , useClients } from 'state/application/hooks' ; dayjs . extend ( utc ) ; export function useAllTokenData ( ) { const [ activeNetwork ] = useActiveNetworkVersion ( ) ; return useSelector ( ( state ) => state . tokens . byAddress [ activeNetwork . id ] ?? { } ) ; } export function useUpdateTokenData ( ) { const dispatch = useDispatch < AppDispatch > ( ) ; const [ activeNetwork ] = useActiveNetworkVersion ( ) ; return useCallback ( ( tokens ) => { dispatch ( updateTokenData ( { tokens , networkId : activeNetwork . id } ) ) ; } , [ activeNetwork . id , dispatch ] ) ; } export function useAddTokenKeys ( ) { const dispatch = useDispatch < AppDispatch > ( ) ; const [ activeNetwork ] = useActiveNetworkVersion ( ) ; return useCallback ( ( tokenAddresses ) => dispatch ( addTokenKeys ( { tokenAddresses , networkId : activeNetwork . id } ) ) , [ activeNetwork . id , dispatch ] ) ; } export function useTokenDatas ( addresses ) { const allTokenData = useAllTokenData ( ) ; const addTokenKeys = useAddTokenKeys ( ) ; addresses ?. map ( ( a ) => { if ( ! allTokenData [ a ] ) { addTokenKeys ( [ a ] ) ; } } ) ; const data = useMemo ( ( ) => { if ( ! addresses ) { return undefined ; } return addresses . map ( ( a ) => { return allTokenData [ a ] ?. data ; } ) . filter ( notEmpty ) ; } , [ addresses , allTokenData ] ) ; return data ; } export function useTokenData ( address ) { const allTokenData = useAllTokenData ( ) ; const addTokenKeys = useAddTokenKeys ( ) ; if ( ! address || ! isAddress ( address ) ) { return undefined ; } if ( ! allTokenData [ address ] ) { addTokenKeys ( [ address ] ) ; } return allTokenData [ address ] ?. data ; } param address export function usePoolsForToken ( address ) { const dispatch = useDispatch < AppDispatch > ( ) ; const [ activeNetwork ] = useActiveNetworkVersion ( ) ; const token = useSelector ( ( state ) => state . tokens . byAddress [ activeNetwork . id ] ?. [ address ] ) ; const poolsForToken = token . poolAddresses ; const [ error , setError ] = useState ( false ) ; const { dataClient } = useClients ( ) ; useEffect ( ( ) => { async function fetch ( ) { const { loading , error , addresses } = await fetchPoolsForToken ( address , dataClient ) ; if ( ! loading && ! error && addresses ) { dispatch ( addPoolAddresses ( { tokenAddress : address , poolAddresses : addresses , networkId : activeNetwork . id } ) ) ; } if ( error ) { setError ( error ) ; } } if ( ! poolsForToken && ! error ) { fetch ( ) ; } } , [ address , dispatch , error , poolsForToken , dataClient , activeNetwork . id ] ) ; return poolsForToken ; } param address export function useTokenChartData ( address ) { const dispatch = useDispatch < AppDispatch > ( ) ; const [ activeNetwork ] = useActiveNetworkVersion ( ) ; const token = useSelector ( ( state ) => state . tokens . byAddress [ activeNetwork . id ] ?. [ address ] ) ; const chartData = token . chartData ; const [ error , setError ] = useState ( false ) ; const { dataClient } = useClients ( ) ; useEffect ( ( ) => { async function fetch ( ) { const { error , data } = await fetchTokenChartData ( address , dataClient ) ; if ( ! error && data ) { dispatch ( updateChartData ( { tokenAddress : address , chartData : data , networkId : activeNetwork . id } ) ) ; } if ( error ) { setError ( error ) ; } } if ( ! chartData && ! error ) { fetch ( ) ; } } , [ address , dispatch , error , chartData , dataClient , activeNetwork . id ] ) ; return chartData ; } param address export function useTokenPriceData ( address , interval , timeWindow ) { const dispatch = useDispatch < AppDispatch > ( ) ; const [ activeNetwork ] = useActiveNetworkVersion ( ) ; const token = useSelector ( ( state ) => state . tokens . byAddress [ activeNetwork . id ] ?. [ address ] ) ; const priceData = token . priceData [ interval ] ; const [ error , setError ] = useState ( false ) ; const { dataClient , blockClient } = useClients ( ) ; const oldestTimestampFetched = token . priceData . oldestFetchedTimestamp ; const utcCurrentTime = dayjs ( ) ; const startTimestamp = utcCurrentTime . subtract ( 1 , timeWindow ) . startOf ( 'hour' ) . unix ( ) ; useEffect ( ( ) => { async function fetch ( ) { const { data , error : fetchingError } = await fetchTokenPriceData ( address , interval , startTimestamp , dataClient , blockClient ) ; if ( data ) { dispatch ( updatePriceData ( { tokenAddress : address , secondsInterval : interval , priceData : data , oldestFetchedTimestamp : startTimestamp , networkId : activeNetwork . id , } ) ) ; } if ( fetchingError ) { setError ( true ) ; } } if ( ! priceData && ! error ) { fetch ( ) ; } } , [ activeNetwork . id , address , blockClient , dataClient , dispatch , error , interval , oldestTimestampFetched , priceData , startTimestamp , timeWindow , ] ) ; return priceData ; } param address export function useTokenTransactions ( address ) { const dispatch = useDispatch < AppDispatch > ( ) ; const [ activeNetwork ] = useActiveNetworkVersion ( ) ; const token = useSelector ( ( state ) => state . tokens . byAddress [ activeNetwork . id ] ?. [ address ] ) ; const transactions = token . transactions ; const [ error , setError ] = useState ( false ) ; const { dataClient } = useClients ( ) ; useEffect ( ( ) => { async function fetch ( ) { const { error , data } = await fetchTokenTransactions ( address , dataClient ) ; if ( error ) { setError ( true ) ; } else if ( data ) { dispatch ( updateTransactions ( { tokenAddress : address , transactions : data , networkId : activeNetwork . id } ) ) ; } } if ( ! transactions && ! error ) { fetch ( ) ; } } , [ activeNetwork . id , address , dataClient , dispatch , error , transactions ] ) ; return transactions ; }