// // Copyright 2021 Vulcanize, Inc. // import assert from 'assert'; import debug from 'debug'; import { GraphQLResolveInfo } from 'graphql'; import { ExpressContext } from 'apollo-server-express'; import winston from 'winston'; import { gqlTotalQueryCount, gqlQueryCount, gqlQueryDuration, getResultState, IndexerInterface, GraphQLBigInt, GraphQLBigDecimal, BlockHeight, OrderDirection, jsonBigIntStringReplacer, EventWatcher, // eslint-disable-next-line @typescript-eslint/no-unused-vars setGQLCacheHints } from '@cerc-io/util'; import { Indexer } from './indexer'; import { Factory } from './entity/Factory'; import { Bundle } from './entity/Bundle'; import { Token } from './entity/Token'; import { Pool } from './entity/Pool'; import { Tick } from './entity/Tick'; import { Position } from './entity/Position'; import { PositionSnapshot } from './entity/PositionSnapshot'; import { Transaction } from './entity/Transaction'; import { Mint } from './entity/Mint'; import { Burn } from './entity/Burn'; import { Swap } from './entity/Swap'; import { Collect } from './entity/Collect'; import { Flash } from './entity/Flash'; import { UniswapDayData } from './entity/UniswapDayData'; import { PoolDayData } from './entity/PoolDayData'; import { PoolHourData } from './entity/PoolHourData'; import { TickHourData } from './entity/TickHourData'; import { TickDayData } from './entity/TickDayData'; import { TokenDayData } from './entity/TokenDayData'; import { TokenHourData } from './entity/TokenHourData'; import { IncreaseEvent } from './entity/IncreaseEvent'; import { DecreaseEvent } from './entity/DecreaseEvent'; import { SetProtocolFeeEvent } from './entity/SetProtocolFeeEvent'; const log = debug('vulcanize:resolver'); const executeAndRecordMetrics = async ( indexer: Indexer, gqlLogger: winston.Logger, opName: string, expressContext: ExpressContext, operation: () => Promise ) => { gqlTotalQueryCount.inc(1); gqlQueryCount.labels(opName).inc(1); const endTimer = gqlQueryDuration.labels(opName).startTimer(); try { const [result, syncStatus] = await Promise.all([ operation(), indexer.getSyncStatus() ]); gqlLogger.info({ opName, query: expressContext.req.body.query, variables: expressContext.req.body.variables, latestIndexedBlockNumber: syncStatus?.latestIndexedBlockNumber, urlPath: expressContext.req.path, apiKey: expressContext.req.header('x-api-key'), origin: expressContext.req.headers.origin }); return result; } catch (error) { gqlLogger.error({ opName, error, query: expressContext.req.body.query, variables: expressContext.req.body.variables, urlPath: expressContext.req.path, apiKey: expressContext.req.header('x-api-key'), origin: expressContext.req.headers.origin }); throw error; } finally { endTimer(); } }; export const createResolvers = async ( indexerArg: IndexerInterface, eventWatcher: EventWatcher, gqlLogger: winston.Logger ): Promise => { const indexer = indexerArg as Indexer; // eslint-disable-next-line @typescript-eslint/no-unused-vars const gqlCacheConfig = indexer.serverConfig.gql.cache; return { BigInt: GraphQLBigInt, BigDecimal: GraphQLBigDecimal, Event: { __resolveType: (obj: any) => { assert(obj.__typename); return obj.__typename; } }, Subscription: { onEvent: { subscribe: () => eventWatcher.getEventIterator() } }, Mutation: { watchContract: async (_: any, { address, kind, checkpoint, startingBlock = 1 }: { address: string, kind: string, checkpoint: boolean, startingBlock: number }): Promise => { log('watchContract', address, kind, checkpoint, startingBlock); await indexer.watchContract(address, kind, checkpoint, startingBlock); return true; } }, Query: { factory: async ( _: any, { id, block = {} }: { id: string, block: BlockHeight }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('factory', id, JSON.stringify(block, jsonBigIntStringReplacer)); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'factory', expressContext, async () => indexer.getSubgraphEntity(Factory, id, block, info) ); }, factories: async ( _: any, { block = {}, where, first, skip, orderBy, orderDirection }: { block: BlockHeight, where: { [key: string]: any }, first: number, skip: number, orderBy: string, orderDirection: OrderDirection }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('factories', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'factories', expressContext, async () => indexer.getSubgraphEntities( Factory, block, where, { limit: first, skip, orderBy, orderDirection }, info ) ); }, bundle: async ( _: any, { id, block = {} }: { id: string, block: BlockHeight }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('bundle', id, JSON.stringify(block, jsonBigIntStringReplacer)); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'bundle', expressContext, async () => indexer.getSubgraphEntity(Bundle, id, block, info) ); }, bundles: async ( _: any, { block = {}, where, first, skip, orderBy, orderDirection }: { block: BlockHeight, where: { [key: string]: any }, first: number, skip: number, orderBy: string, orderDirection: OrderDirection }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('bundles', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'bundles', expressContext, async () => indexer.getSubgraphEntities( Bundle, block, where, { limit: first, skip, orderBy, orderDirection }, info ) ); }, token: async ( _: any, { id, block = {} }: { id: string, block: BlockHeight }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('token', id, JSON.stringify(block, jsonBigIntStringReplacer)); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'token', expressContext, async () => indexer.getSubgraphEntity(Token, id, block, info) ); }, tokens: async ( _: any, { block = {}, where, first, skip, orderBy, orderDirection }: { block: BlockHeight, where: { [key: string]: any }, first: number, skip: number, orderBy: string, orderDirection: OrderDirection }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('tokens', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'tokens', expressContext, async () => indexer.getSubgraphEntities( Token, block, where, { limit: first, skip, orderBy, orderDirection }, info ) ); }, pool: async ( _: any, { id, block = {} }: { id: string, block: BlockHeight }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('pool', id, JSON.stringify(block, jsonBigIntStringReplacer)); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'pool', expressContext, async () => indexer.getSubgraphEntity(Pool, id, block, info) ); }, pools: async ( _: any, { block = {}, where, first, skip, orderBy, orderDirection }: { block: BlockHeight, where: { [key: string]: any }, first: number, skip: number, orderBy: string, orderDirection: OrderDirection }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('pools', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'pools', expressContext, async () => indexer.getSubgraphEntities( Pool, block, where, { limit: first, skip, orderBy, orderDirection }, info ) ); }, tick: async ( _: any, { id, block = {} }: { id: string, block: BlockHeight }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('tick', id, JSON.stringify(block, jsonBigIntStringReplacer)); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'tick', expressContext, async () => indexer.getSubgraphEntity(Tick, id, block, info) ); }, ticks: async ( _: any, { block = {}, where, first, skip, orderBy, orderDirection }: { block: BlockHeight, where: { [key: string]: any }, first: number, skip: number, orderBy: string, orderDirection: OrderDirection }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('ticks', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'ticks', expressContext, async () => indexer.getSubgraphEntities( Tick, block, where, { limit: first, skip, orderBy, orderDirection }, info ) ); }, position: async ( _: any, { id, block = {} }: { id: string, block: BlockHeight }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('position', id, JSON.stringify(block, jsonBigIntStringReplacer)); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'position', expressContext, async () => indexer.getSubgraphEntity(Position, id, block, info) ); }, positions: async ( _: any, { block = {}, where, first, skip, orderBy, orderDirection }: { block: BlockHeight, where: { [key: string]: any }, first: number, skip: number, orderBy: string, orderDirection: OrderDirection }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('positions', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'positions', expressContext, async () => indexer.getSubgraphEntities( Position, block, where, { limit: first, skip, orderBy, orderDirection }, info ) ); }, positionSnapshot: async ( _: any, { id, block = {} }: { id: string, block: BlockHeight }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('positionSnapshot', id, JSON.stringify(block, jsonBigIntStringReplacer)); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'positionSnapshot', expressContext, async () => indexer.getSubgraphEntity(PositionSnapshot, id, block, info) ); }, positionSnapshots: async ( _: any, { block = {}, where, first, skip, orderBy, orderDirection }: { block: BlockHeight, where: { [key: string]: any }, first: number, skip: number, orderBy: string, orderDirection: OrderDirection }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('positionSnapshots', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'positionSnapshots', expressContext, async () => indexer.getSubgraphEntities( PositionSnapshot, block, where, { limit: first, skip, orderBy, orderDirection }, info ) ); }, transaction: async ( _: any, { id, block = {} }: { id: string, block: BlockHeight }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('transaction', id, JSON.stringify(block, jsonBigIntStringReplacer)); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'transaction', expressContext, async () => indexer.getSubgraphEntity(Transaction, id, block, info) ); }, transactions: async ( _: any, { block = {}, where, first, skip, orderBy, orderDirection }: { block: BlockHeight, where: { [key: string]: any }, first: number, skip: number, orderBy: string, orderDirection: OrderDirection }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('transactions', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'transactions', expressContext, async () => indexer.getSubgraphEntities( Transaction, block, where, { limit: first, skip, orderBy, orderDirection }, info ) ); }, mint: async ( _: any, { id, block = {} }: { id: string, block: BlockHeight }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('mint', id, JSON.stringify(block, jsonBigIntStringReplacer)); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'mint', expressContext, async () => indexer.getSubgraphEntity(Mint, id, block, info) ); }, mints: async ( _: any, { block = {}, where, first, skip, orderBy, orderDirection }: { block: BlockHeight, where: { [key: string]: any }, first: number, skip: number, orderBy: string, orderDirection: OrderDirection }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('mints', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'mints', expressContext, async () => indexer.getSubgraphEntities( Mint, block, where, { limit: first, skip, orderBy, orderDirection }, info ) ); }, burn: async ( _: any, { id, block = {} }: { id: string, block: BlockHeight }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('burn', id, JSON.stringify(block, jsonBigIntStringReplacer)); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'burn', expressContext, async () => indexer.getSubgraphEntity(Burn, id, block, info) ); }, burns: async ( _: any, { block = {}, where, first, skip, orderBy, orderDirection }: { block: BlockHeight, where: { [key: string]: any }, first: number, skip: number, orderBy: string, orderDirection: OrderDirection }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('burns', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'burns', expressContext, async () => indexer.getSubgraphEntities( Burn, block, where, { limit: first, skip, orderBy, orderDirection }, info ) ); }, swap: async ( _: any, { id, block = {} }: { id: string, block: BlockHeight }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('swap', id, JSON.stringify(block, jsonBigIntStringReplacer)); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'swap', expressContext, async () => indexer.getSubgraphEntity(Swap, id, block, info) ); }, swaps: async ( _: any, { block = {}, where, first, skip, orderBy, orderDirection }: { block: BlockHeight, where: { [key: string]: any }, first: number, skip: number, orderBy: string, orderDirection: OrderDirection }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('swaps', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'swaps', expressContext, async () => indexer.getSubgraphEntities( Swap, block, where, { limit: first, skip, orderBy, orderDirection }, info ) ); }, collect: async ( _: any, { id, block = {} }: { id: string, block: BlockHeight }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('collect', id, JSON.stringify(block, jsonBigIntStringReplacer)); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'collect', expressContext, async () => indexer.getSubgraphEntity(Collect, id, block, info) ); }, collects: async ( _: any, { block = {}, where, first, skip, orderBy, orderDirection }: { block: BlockHeight, where: { [key: string]: any }, first: number, skip: number, orderBy: string, orderDirection: OrderDirection }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('collects', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'collects', expressContext, async () => indexer.getSubgraphEntities( Collect, block, where, { limit: first, skip, orderBy, orderDirection }, info ) ); }, flash: async ( _: any, { id, block = {} }: { id: string, block: BlockHeight }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('flash', id, JSON.stringify(block, jsonBigIntStringReplacer)); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'flash', expressContext, async () => indexer.getSubgraphEntity(Flash, id, block, info) ); }, flashes: async ( _: any, { block = {}, where, first, skip, orderBy, orderDirection }: { block: BlockHeight, where: { [key: string]: any }, first: number, skip: number, orderBy: string, orderDirection: OrderDirection }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('flashes', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'flashes', expressContext, async () => indexer.getSubgraphEntities( Flash, block, where, { limit: first, skip, orderBy, orderDirection }, info ) ); }, uniswapDayData: async ( _: any, { id, block = {} }: { id: string, block: BlockHeight }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('uniswapDayData', id, JSON.stringify(block, jsonBigIntStringReplacer)); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'uniswapDayData', expressContext, async () => indexer.getSubgraphEntity(UniswapDayData, id, block, info) ); }, uniswapDayDatas: async ( _: any, { block = {}, where, first, skip, orderBy, orderDirection }: { block: BlockHeight, where: { [key: string]: any }, first: number, skip: number, orderBy: string, orderDirection: OrderDirection }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('uniswapDayDatas', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'uniswapDayDatas', expressContext, async () => indexer.getSubgraphEntities( UniswapDayData, block, where, { limit: first, skip, orderBy, orderDirection }, info ) ); }, poolDayData: async ( _: any, { id, block = {} }: { id: string, block: BlockHeight }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('poolDayData', id, JSON.stringify(block, jsonBigIntStringReplacer)); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'poolDayData', expressContext, async () => indexer.getSubgraphEntity(PoolDayData, id, block, info) ); }, poolDayDatas: async ( _: any, { block = {}, where, first, skip, orderBy, orderDirection }: { block: BlockHeight, where: { [key: string]: any }, first: number, skip: number, orderBy: string, orderDirection: OrderDirection }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('poolDayDatas', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'poolDayDatas', expressContext, async () => indexer.getSubgraphEntities( PoolDayData, block, where, { limit: first, skip, orderBy, orderDirection }, info ) ); }, poolHourData: async ( _: any, { id, block = {} }: { id: string, block: BlockHeight }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('poolHourData', id, JSON.stringify(block, jsonBigIntStringReplacer)); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'poolHourData', expressContext, async () => indexer.getSubgraphEntity(PoolHourData, id, block, info) ); }, poolHourDatas: async ( _: any, { block = {}, where, first, skip, orderBy, orderDirection }: { block: BlockHeight, where: { [key: string]: any }, first: number, skip: number, orderBy: string, orderDirection: OrderDirection }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('poolHourDatas', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'poolHourDatas', expressContext, async () => indexer.getSubgraphEntities( PoolHourData, block, where, { limit: first, skip, orderBy, orderDirection }, info ) ); }, tickHourData: async ( _: any, { id, block = {} }: { id: string, block: BlockHeight }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('tickHourData', id, JSON.stringify(block, jsonBigIntStringReplacer)); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'tickHourData', expressContext, async () => indexer.getSubgraphEntity(TickHourData, id, block, info) ); }, tickHourDatas: async ( _: any, { block = {}, where, first, skip, orderBy, orderDirection }: { block: BlockHeight, where: { [key: string]: any }, first: number, skip: number, orderBy: string, orderDirection: OrderDirection }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('tickHourDatas', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'tickHourDatas', expressContext, async () => indexer.getSubgraphEntities( TickHourData, block, where, { limit: first, skip, orderBy, orderDirection }, info ) ); }, tickDayData: async ( _: any, { id, block = {} }: { id: string, block: BlockHeight }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('tickDayData', id, JSON.stringify(block, jsonBigIntStringReplacer)); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'tickDayData', expressContext, async () => indexer.getSubgraphEntity(TickDayData, id, block, info) ); }, tickDayDatas: async ( _: any, { block = {}, where, first, skip, orderBy, orderDirection }: { block: BlockHeight, where: { [key: string]: any }, first: number, skip: number, orderBy: string, orderDirection: OrderDirection }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('tickDayDatas', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'tickDayDatas', expressContext, async () => indexer.getSubgraphEntities( TickDayData, block, where, { limit: first, skip, orderBy, orderDirection }, info ) ); }, tokenDayData: async ( _: any, { id, block = {} }: { id: string, block: BlockHeight }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('tokenDayData', id, JSON.stringify(block, jsonBigIntStringReplacer)); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'tokenDayData', expressContext, async () => indexer.getSubgraphEntity(TokenDayData, id, block, info) ); }, tokenDayDatas: async ( _: any, { block = {}, where, first, skip, orderBy, orderDirection }: { block: BlockHeight, where: { [key: string]: any }, first: number, skip: number, orderBy: string, orderDirection: OrderDirection }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('tokenDayDatas', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'tokenDayDatas', expressContext, async () => indexer.getSubgraphEntities( TokenDayData, block, where, { limit: first, skip, orderBy, orderDirection }, info ) ); }, tokenHourData: async ( _: any, { id, block = {} }: { id: string, block: BlockHeight }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('tokenHourData', id, JSON.stringify(block, jsonBigIntStringReplacer)); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'tokenHourData', expressContext, async () => indexer.getSubgraphEntity(TokenHourData, id, block, info) ); }, tokenHourDatas: async ( _: any, { block = {}, where, first, skip, orderBy, orderDirection }: { block: BlockHeight, where: { [key: string]: any }, first: number, skip: number, orderBy: string, orderDirection: OrderDirection }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('tokenHourDatas', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'tokenHourDatas', expressContext, async () => indexer.getSubgraphEntities( TokenHourData, block, where, { limit: first, skip, orderBy, orderDirection }, info ) ); }, increaseEvent: async ( _: any, { id, block = {} }: { id: string, block: BlockHeight }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('increaseEvent', id, JSON.stringify(block, jsonBigIntStringReplacer)); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'increaseEvent', expressContext, async () => indexer.getSubgraphEntity(IncreaseEvent, id, block, info) ); }, increaseEvents: async ( _: any, { block = {}, where, first, skip, orderBy, orderDirection }: { block: BlockHeight, where: { [key: string]: any }, first: number, skip: number, orderBy: string, orderDirection: OrderDirection }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('increaseEvents', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'increaseEvents', expressContext, async () => indexer.getSubgraphEntities( IncreaseEvent, block, where, { limit: first, skip, orderBy, orderDirection }, info ) ); }, decreaseEvent: async ( _: any, { id, block = {} }: { id: string, block: BlockHeight }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('decreaseEvent', id, JSON.stringify(block, jsonBigIntStringReplacer)); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'decreaseEvent', expressContext, async () => indexer.getSubgraphEntity(DecreaseEvent, id, block, info) ); }, decreaseEvents: async ( _: any, { block = {}, where, first, skip, orderBy, orderDirection }: { block: BlockHeight, where: { [key: string]: any }, first: number, skip: number, orderBy: string, orderDirection: OrderDirection }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('decreaseEvents', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'decreaseEvents', expressContext, async () => indexer.getSubgraphEntities( DecreaseEvent, block, where, { limit: first, skip, orderBy, orderDirection }, info ) ); }, setProtocolFeeEvent: async ( _: any, { id, block = {} }: { id: string, block: BlockHeight }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('setProtocolFeeEvent', id, JSON.stringify(block, jsonBigIntStringReplacer)); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'setProtocolFeeEvent', expressContext, async () => indexer.getSubgraphEntity(SetProtocolFeeEvent, id, block, info) ); }, setProtocolFeeEvents: async ( _: any, { block = {}, where, first, skip, orderBy, orderDirection }: { block: BlockHeight, where: { [key: string]: any }, first: number, skip: number, orderBy: string, orderDirection: OrderDirection }, expressContext: ExpressContext, info: GraphQLResolveInfo ) => { log('setProtocolFeeEvents', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection); // Set cache-control hints // setGQLCacheHints(info, block, gqlCacheConfig); return executeAndRecordMetrics( indexer, gqlLogger, 'setProtocolFeeEvents', expressContext, async () => indexer.getSubgraphEntities( SetProtocolFeeEvent, block, where, { limit: first, skip, orderBy, orderDirection }, info ) ); }, events: async ( _: any, { blockHash, contractAddress, name }: { blockHash: string, contractAddress: string, name?: string }, expressContext: ExpressContext ) => { log('events', blockHash, contractAddress, name); return executeAndRecordMetrics( indexer, gqlLogger, 'events', expressContext, async () => { const block = await indexer.getBlockProgress(blockHash); if (!block || !block.isComplete) { throw new Error(`Block hash ${blockHash} number ${block?.blockNumber} not processed yet`); } const events = await indexer.getEventsByFilter(blockHash, contractAddress, name); return events.map(event => indexer.getResultEvent(event)); } ); }, eventsInRange: async ( _: any, { fromBlockNumber, toBlockNumber }: { fromBlockNumber: number, toBlockNumber: number }, expressContext: ExpressContext ) => { log('eventsInRange', fromBlockNumber, toBlockNumber); return executeAndRecordMetrics( indexer, gqlLogger, 'eventsInRange', expressContext, async () => { const syncStatus = await indexer.getSyncStatus(); if (!syncStatus) { throw new Error('No blocks processed yet'); } if ((fromBlockNumber < syncStatus.initialIndexedBlockNumber) || (toBlockNumber > syncStatus.latestProcessedBlockNumber)) { throw new Error(`Block range should be between ${syncStatus.initialIndexedBlockNumber} and ${syncStatus.latestProcessedBlockNumber}`); } const events = await indexer.getEventsInRange(fromBlockNumber, toBlockNumber); return events.map(event => indexer.getResultEvent(event)); } ); }, getStateByCID: async ( _: any, { cid }: { cid: string }, expressContext: ExpressContext ) => { log('getStateByCID', cid); return executeAndRecordMetrics( indexer, gqlLogger, 'getStateByCID', expressContext, async () => { const state = await indexer.getStateByCID(cid); return state && state.block.isComplete ? getResultState(state) : undefined; } ); }, getState: async ( _: any, { blockHash, contractAddress, kind }: { blockHash: string, contractAddress: string, kind: string }, expressContext: ExpressContext ) => { log('getState', blockHash, contractAddress, kind); return executeAndRecordMetrics( indexer, gqlLogger, 'getState', expressContext, async () => { const state = await indexer.getPrevState(blockHash, contractAddress, kind); return state && state.block.isComplete ? getResultState(state) : undefined; } ); }, _meta: async ( _: any, { block = {} }: { block: BlockHeight }, expressContext: ExpressContext ) => { log('_meta'); return executeAndRecordMetrics( indexer, gqlLogger, '_meta', expressContext, async () => indexer.getMetaData(block) ); }, getSyncStatus: async ( _: any, __: Record, expressContext: ExpressContext ) => { log('getSyncStatus'); return executeAndRecordMetrics( indexer, gqlLogger, 'getSyncStatus', expressContext, async () => indexer.getSyncStatus() ); } } }; };