import { ApolloClient , NormalizedCacheObject } from '@apollo/client' ; import dayjs from 'dayjs' ; import utc from 'dayjs/plugin/utc' ; import weekOfYear from 'dayjs/plugin/weekOfYear' ; import gql from 'graphql-tag' ; import { getBlocksFromTimestamps } from 'hooks/useBlocksFromTimestamps' ; import { PriceChartEntry } from 'types' ; dayjs . extend ( utc ) ; dayjs . extend ( weekOfYear ) ; export const PRICES_BY_BLOCK = ( tokenAddress , blocks ) => { let queryString = 'query blocks {' ; queryString += blocks . map ( ( block ) => `
      t${ block . timestamp }:token(id:"${ tokenAddress }", block: { number: ${ block . number } }, subgraphError: allow) { 
        derivedETH
      }
    ` ) ; queryString += ',' ; queryString += blocks . map ( ( block ) => `
      b${ block . timestamp }: bundle(id:"1", block: { number: ${ block . number } }, subgraphError: allow) { 
        ethPriceUSD
      }
    ` ) ; queryString += '}' ; return gql ( queryString ) ; } ; const PRICE_CHART = gql `
  query tokenHourDatas($startTime: Int!, $skip: Int!, $address: Bytes!) {
    tokenHourDatas(
      first: 100
      skip: $skip
      where: { token: $address, periodStartUnix_gt: $startTime }
      orderBy: periodStartUnix
      orderDirection: asc
    ) {
      periodStartUnix
      high
      low
      open
      close
    }
  }
` ; interface PriceResults { tokenHourDatas : { periodStartUnix : number ; high : string ; low : string ; open : string ; close : string ; } [ ] ; } export async function fetchTokenPriceData ( address , interval , startTimestamp , dataClient , blockClient ) { try { const endTimestamp = dayjs . utc ( ) . unix ( ) ; if ( ! startTimestamp ) { console . log ( 'Error constructing price start timestamp' ) ; return { data : [ ] , error : false , } ; } const timestamps = [ ] ; let time = startTimestamp ; while ( time <= endTimestamp ) { timestamps . push ( time ) ; time += interval ; } if ( timestamps . length === 0 ) { return { data : [ ] , error : false , } ; } const blocks = await getBlocksFromTimestamps ( timestamps , blockClient , 500 ) ; if ( ! blocks || blocks . length === 0 ) { console . log ( 'Error fetching blocks' ) ; return { data : [ ] , error : false , } ; } let data = [ ] ; let skip = 0 ; let allFound = false ; while ( ! allFound ) { const { data : priceData , errors , loading } = await dataClient . query < PriceResults > ( { query : PRICE_CHART , variables : { address : address , startTime : startTimestamp , skip , } , fetchPolicy : 'no-cache' , } ) ; if ( ! loading ) { skip += 100 ; if ( ( priceData && priceData . tokenHourDatas . length < 100 ) || errors ) { allFound = true ; } if ( priceData ) { data = data . concat ( priceData . tokenHourDatas ) ; } } } const formattedHistory = data . map ( ( d ) => { return { time : d . periodStartUnix , open : parseFloat ( d . open ) , close : parseFloat ( d . close ) , high : parseFloat ( d . high ) , low : parseFloat ( d . low ) , } ; } ) ; return { data : formattedHistory , error : false , } ; } catch ( e ) { console . log ( e ) ; return { data : [ ] , error : true , } ; } }