//
// 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 { Token } from './entity/Token';
import { PoolFactory } from './entity/PoolFactory';
import { Pool } from './entity/Pool';
import { Bucket } from './entity/Bucket';
import { Lend } from './entity/Lend';
import { Loan } from './entity/Loan';
import { Account } from './entity/Account';
import { LiquidationAuction } from './entity/LiquidationAuction';
import { ReserveAuction } from './entity/ReserveAuction';
import { LPTransferorList } from './entity/LPTransferorList';
import { LPAllowance } from './entity/LPAllowance';
import { LPAllowanceList } from './entity/LPAllowanceList';
import { AddCollateral } from './entity/AddCollateral';
import { AddQuoteToken } from './entity/AddQuoteToken';
import { AuctionSettle } from './entity/AuctionSettle';
import { BondWithdrawn } from './entity/BondWithdrawn';
import { BucketBankruptcy } from './entity/BucketBankruptcy';
import { BucketTake } from './entity/BucketTake';
import { BucketTakeLPAwarded } from './entity/BucketTakeLPAwarded';
import { DrawDebt } from './entity/DrawDebt';
import { Flashloan } from './entity/Flashloan';
import { Kick } from './entity/Kick';
import { LoanStamped } from './entity/LoanStamped';
import { MoveQuoteToken } from './entity/MoveQuoteToken';
import { RemoveCollateral } from './entity/RemoveCollateral';
import { RemoveQuoteToken } from './entity/RemoveQuoteToken';
import { RepayDebt } from './entity/RepayDebt';
import { ReserveAuctionKick } from './entity/ReserveAuctionKick';
import { ReserveAuctionTake } from './entity/ReserveAuctionTake';
import { ResetInterestRate } from './entity/ResetInterestRate';
import { Settle } from './entity/Settle';
import { Take } from './entity/Take';
import { TransferLP } from './entity/TransferLP';
import { UpdateInterestRate } from './entity/UpdateInterestRate';
import { Approval } from './entity/Approval';
import { ApprovalForAll } from './entity/ApprovalForAll';
import { MoveLiquidity } from './entity/MoveLiquidity';
import { Transfer } from './entity/Transfer';
import { PoolCreated } from './entity/PoolCreated';
import { AddCollateralNFT } from './entity/AddCollateralNFT';
import { AuctionNFTSettle } from './entity/AuctionNFTSettle';
import { DrawDebtNFT } from './entity/DrawDebtNFT';
import { MergeOrRemoveCollateralNFT } from './entity/MergeOrRemoveCollateralNFT';
import { Position } from './entity/Position';
import { PositionLend } from './entity/PositionLend';
import { Burn } from './entity/Burn';
import { MemorializePosition } from './entity/MemorializePosition';
import { Mint } from './entity/Mint';
import { RedeemPosition } from './entity/RedeemPosition';
import { GrantFund } from './entity/GrantFund';
import { DistributionPeriod } from './entity/DistributionPeriod';
import { Proposal } from './entity/Proposal';
import { ProposalParams } from './entity/ProposalParams';
import { DistributionPeriodVote } from './entity/DistributionPeriodVote';
import { ScreeningVote } from './entity/ScreeningVote';
import { FundingVote } from './entity/FundingVote';
import { FundedSlate } from './entity/FundedSlate';
import { DelegateRewardClaimed } from './entity/DelegateRewardClaimed';
import { FundTreasury } from './entity/FundTreasury';
import { FundedSlateUpdated } from './entity/FundedSlateUpdated';
import { ProposalCreated } from './entity/ProposalCreated';
import { ProposalExecuted } from './entity/ProposalExecuted';
import { DistributionPeriodStarted } from './entity/DistributionPeriodStarted';
import { VoteCast } from './entity/VoteCast';
import { DelegateChanged } from './entity/DelegateChanged';
import { DelegateVotesChanged } from './entity/DelegateVotesChanged';
import { BurnWrap } from './entity/BurnWrap';

const log = debug('vulcanize:resolver');

const executeAndRecordMetrics = async (
  indexer: Indexer,
  gqlLogger: winston.Logger,
  opName: string,
  expressContext: ExpressContext,
  operation: () => Promise<any>
) => {
  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
    });
  } finally {
    endTimer();
  }
};

export const createResolvers = async (
  indexerArg: IndexerInterface,
  eventWatcher: EventWatcher,
  gqlLogger: winston.Logger
): Promise<any> => {
  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<boolean> => {
        log('watchContract', address, kind, checkpoint, startingBlock);
        await indexer.watchContract(address, kind, checkpoint, startingBlock);

        return true;
      }
    },

    Query: {
      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
          )
        );
      },

      poolFactory: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('poolFactory', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'poolFactory',
          expressContext,
          async () => indexer.getSubgraphEntity(PoolFactory, id, block, info)
        );
      },

      poolFactories: 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('poolFactories', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'poolFactories',
          expressContext,
          async () => indexer.getSubgraphEntities(
            PoolFactory,
            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
          )
        );
      },

      bucket: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('bucket', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'bucket',
          expressContext,
          async () => indexer.getSubgraphEntity(Bucket, id, block, info)
        );
      },

      buckets: 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('buckets', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'buckets',
          expressContext,
          async () => indexer.getSubgraphEntities(
            Bucket,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      lend: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('lend', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'lend',
          expressContext,
          async () => indexer.getSubgraphEntity(Lend, id, block, info)
        );
      },

      lends: 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('lends', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'lends',
          expressContext,
          async () => indexer.getSubgraphEntities(
            Lend,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      loan: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('loan', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'loan',
          expressContext,
          async () => indexer.getSubgraphEntity(Loan, id, block, info)
        );
      },

      loans: 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('loans', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'loans',
          expressContext,
          async () => indexer.getSubgraphEntities(
            Loan,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      account: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('account', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'account',
          expressContext,
          async () => indexer.getSubgraphEntity(Account, id, block, info)
        );
      },

      accounts: 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('accounts', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'accounts',
          expressContext,
          async () => indexer.getSubgraphEntities(
            Account,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      liquidationAuction: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('liquidationAuction', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'liquidationAuction',
          expressContext,
          async () => indexer.getSubgraphEntity(LiquidationAuction, id, block, info)
        );
      },

      liquidationAuctions: 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('liquidationAuctions', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'liquidationAuctions',
          expressContext,
          async () => indexer.getSubgraphEntities(
            LiquidationAuction,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      reserveAuction: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('reserveAuction', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'reserveAuction',
          expressContext,
          async () => indexer.getSubgraphEntity(ReserveAuction, id, block, info)
        );
      },

      reserveAuctions: 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('reserveAuctions', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'reserveAuctions',
          expressContext,
          async () => indexer.getSubgraphEntities(
            ReserveAuction,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      lptransferorList: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('lptransferorList', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'lptransferorList',
          expressContext,
          async () => indexer.getSubgraphEntity(LPTransferorList, id, block, info)
        );
      },

      lptransferorLists: 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('lptransferorLists', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'lptransferorLists',
          expressContext,
          async () => indexer.getSubgraphEntities(
            LPTransferorList,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      lpallowance: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('lpallowance', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'lpallowance',
          expressContext,
          async () => indexer.getSubgraphEntity(LPAllowance, id, block, info)
        );
      },

      lpallowances: 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('lpallowances', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'lpallowances',
          expressContext,
          async () => indexer.getSubgraphEntities(
            LPAllowance,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      lpallowanceList: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('lpallowanceList', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'lpallowanceList',
          expressContext,
          async () => indexer.getSubgraphEntity(LPAllowanceList, id, block, info)
        );
      },

      lpallowanceLists: 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('lpallowanceLists', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'lpallowanceLists',
          expressContext,
          async () => indexer.getSubgraphEntities(
            LPAllowanceList,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      addCollateral: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('addCollateral', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'addCollateral',
          expressContext,
          async () => indexer.getSubgraphEntity(AddCollateral, id, block, info)
        );
      },

      addCollaterals: 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('addCollaterals', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'addCollaterals',
          expressContext,
          async () => indexer.getSubgraphEntities(
            AddCollateral,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      addQuoteToken: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('addQuoteToken', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'addQuoteToken',
          expressContext,
          async () => indexer.getSubgraphEntity(AddQuoteToken, id, block, info)
        );
      },

      addQuoteTokens: 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('addQuoteTokens', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'addQuoteTokens',
          expressContext,
          async () => indexer.getSubgraphEntities(
            AddQuoteToken,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      auctionSettle: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('auctionSettle', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'auctionSettle',
          expressContext,
          async () => indexer.getSubgraphEntity(AuctionSettle, id, block, info)
        );
      },

      auctionSettles: 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('auctionSettles', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'auctionSettles',
          expressContext,
          async () => indexer.getSubgraphEntities(
            AuctionSettle,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      bondWithdrawn: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('bondWithdrawn', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'bondWithdrawn',
          expressContext,
          async () => indexer.getSubgraphEntity(BondWithdrawn, id, block, info)
        );
      },

      bondWithdrawns: 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('bondWithdrawns', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'bondWithdrawns',
          expressContext,
          async () => indexer.getSubgraphEntities(
            BondWithdrawn,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      bucketBankruptcy: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('bucketBankruptcy', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'bucketBankruptcy',
          expressContext,
          async () => indexer.getSubgraphEntity(BucketBankruptcy, id, block, info)
        );
      },

      bucketBankruptcies: 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('bucketBankruptcies', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'bucketBankruptcies',
          expressContext,
          async () => indexer.getSubgraphEntities(
            BucketBankruptcy,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      bucketTake: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('bucketTake', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'bucketTake',
          expressContext,
          async () => indexer.getSubgraphEntity(BucketTake, id, block, info)
        );
      },

      bucketTakes: 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('bucketTakes', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'bucketTakes',
          expressContext,
          async () => indexer.getSubgraphEntities(
            BucketTake,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      bucketTakeLPAwarded: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('bucketTakeLPAwarded', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'bucketTakeLPAwarded',
          expressContext,
          async () => indexer.getSubgraphEntity(BucketTakeLPAwarded, id, block, info)
        );
      },

      bucketTakeLPAwardeds: 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('bucketTakeLPAwardeds', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'bucketTakeLPAwardeds',
          expressContext,
          async () => indexer.getSubgraphEntities(
            BucketTakeLPAwarded,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      drawDebt: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('drawDebt', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'drawDebt',
          expressContext,
          async () => indexer.getSubgraphEntity(DrawDebt, id, block, info)
        );
      },

      drawDebts: 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('drawDebts', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'drawDebts',
          expressContext,
          async () => indexer.getSubgraphEntities(
            DrawDebt,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      flashloan: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('flashloan', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'flashloan',
          expressContext,
          async () => indexer.getSubgraphEntity(Flashloan, id, block, info)
        );
      },

      flashloans: 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('flashloans', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'flashloans',
          expressContext,
          async () => indexer.getSubgraphEntities(
            Flashloan,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      kick: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('kick', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'kick',
          expressContext,
          async () => indexer.getSubgraphEntity(Kick, id, block, info)
        );
      },

      kicks: 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('kicks', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'kicks',
          expressContext,
          async () => indexer.getSubgraphEntities(
            Kick,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      loanStamped: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('loanStamped', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'loanStamped',
          expressContext,
          async () => indexer.getSubgraphEntity(LoanStamped, id, block, info)
        );
      },

      loanStampeds: 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('loanStampeds', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'loanStampeds',
          expressContext,
          async () => indexer.getSubgraphEntities(
            LoanStamped,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      moveQuoteToken: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('moveQuoteToken', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'moveQuoteToken',
          expressContext,
          async () => indexer.getSubgraphEntity(MoveQuoteToken, id, block, info)
        );
      },

      moveQuoteTokens: 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('moveQuoteTokens', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'moveQuoteTokens',
          expressContext,
          async () => indexer.getSubgraphEntities(
            MoveQuoteToken,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      removeCollateral: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('removeCollateral', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'removeCollateral',
          expressContext,
          async () => indexer.getSubgraphEntity(RemoveCollateral, id, block, info)
        );
      },

      removeCollaterals: 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('removeCollaterals', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'removeCollaterals',
          expressContext,
          async () => indexer.getSubgraphEntities(
            RemoveCollateral,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      removeQuoteToken: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('removeQuoteToken', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'removeQuoteToken',
          expressContext,
          async () => indexer.getSubgraphEntity(RemoveQuoteToken, id, block, info)
        );
      },

      removeQuoteTokens: 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('removeQuoteTokens', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'removeQuoteTokens',
          expressContext,
          async () => indexer.getSubgraphEntities(
            RemoveQuoteToken,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      repayDebt: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('repayDebt', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'repayDebt',
          expressContext,
          async () => indexer.getSubgraphEntity(RepayDebt, id, block, info)
        );
      },

      repayDebts: 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('repayDebts', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'repayDebts',
          expressContext,
          async () => indexer.getSubgraphEntities(
            RepayDebt,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      reserveAuctionKick: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('reserveAuctionKick', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'reserveAuctionKick',
          expressContext,
          async () => indexer.getSubgraphEntity(ReserveAuctionKick, id, block, info)
        );
      },

      reserveAuctionKicks: 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('reserveAuctionKicks', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'reserveAuctionKicks',
          expressContext,
          async () => indexer.getSubgraphEntities(
            ReserveAuctionKick,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      reserveAuctionTake: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('reserveAuctionTake', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'reserveAuctionTake',
          expressContext,
          async () => indexer.getSubgraphEntity(ReserveAuctionTake, id, block, info)
        );
      },

      reserveAuctionTakes: 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('reserveAuctionTakes', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'reserveAuctionTakes',
          expressContext,
          async () => indexer.getSubgraphEntities(
            ReserveAuctionTake,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      resetInterestRate: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('resetInterestRate', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'resetInterestRate',
          expressContext,
          async () => indexer.getSubgraphEntity(ResetInterestRate, id, block, info)
        );
      },

      resetInterestRates: 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('resetInterestRates', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'resetInterestRates',
          expressContext,
          async () => indexer.getSubgraphEntities(
            ResetInterestRate,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      settle: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('settle', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'settle',
          expressContext,
          async () => indexer.getSubgraphEntity(Settle, id, block, info)
        );
      },

      settles: 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('settles', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'settles',
          expressContext,
          async () => indexer.getSubgraphEntities(
            Settle,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      take: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('take', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'take',
          expressContext,
          async () => indexer.getSubgraphEntity(Take, id, block, info)
        );
      },

      takes: 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('takes', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'takes',
          expressContext,
          async () => indexer.getSubgraphEntities(
            Take,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      transferLP: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('transferLP', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'transferLP',
          expressContext,
          async () => indexer.getSubgraphEntity(TransferLP, id, block, info)
        );
      },

      transferLPS: 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('transferLPS', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'transferLPS',
          expressContext,
          async () => indexer.getSubgraphEntities(
            TransferLP,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      updateInterestRate: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('updateInterestRate', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'updateInterestRate',
          expressContext,
          async () => indexer.getSubgraphEntity(UpdateInterestRate, id, block, info)
        );
      },

      updateInterestRates: 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('updateInterestRates', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'updateInterestRates',
          expressContext,
          async () => indexer.getSubgraphEntities(
            UpdateInterestRate,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      approval: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('approval', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'approval',
          expressContext,
          async () => indexer.getSubgraphEntity(Approval, id, block, info)
        );
      },

      approvals: 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('approvals', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'approvals',
          expressContext,
          async () => indexer.getSubgraphEntities(
            Approval,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      approvalForAll: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('approvalForAll', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'approvalForAll',
          expressContext,
          async () => indexer.getSubgraphEntity(ApprovalForAll, id, block, info)
        );
      },

      approvalForAlls: 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('approvalForAlls', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'approvalForAlls',
          expressContext,
          async () => indexer.getSubgraphEntities(
            ApprovalForAll,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      moveLiquidity: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('moveLiquidity', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'moveLiquidity',
          expressContext,
          async () => indexer.getSubgraphEntity(MoveLiquidity, id, block, info)
        );
      },

      moveLiquidities: 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('moveLiquidities', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'moveLiquidities',
          expressContext,
          async () => indexer.getSubgraphEntities(
            MoveLiquidity,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      transfer: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('transfer', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'transfer',
          expressContext,
          async () => indexer.getSubgraphEntity(Transfer, id, block, info)
        );
      },

      transfers: 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('transfers', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'transfers',
          expressContext,
          async () => indexer.getSubgraphEntities(
            Transfer,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      poolCreated: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('poolCreated', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'poolCreated',
          expressContext,
          async () => indexer.getSubgraphEntity(PoolCreated, id, block, info)
        );
      },

      poolCreateds: 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('poolCreateds', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'poolCreateds',
          expressContext,
          async () => indexer.getSubgraphEntities(
            PoolCreated,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      addCollateralNFT: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('addCollateralNFT', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'addCollateralNFT',
          expressContext,
          async () => indexer.getSubgraphEntity(AddCollateralNFT, id, block, info)
        );
      },

      addCollateralNFTS: 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('addCollateralNFTS', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'addCollateralNFTS',
          expressContext,
          async () => indexer.getSubgraphEntities(
            AddCollateralNFT,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      auctionNFTSettle: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('auctionNFTSettle', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'auctionNFTSettle',
          expressContext,
          async () => indexer.getSubgraphEntity(AuctionNFTSettle, id, block, info)
        );
      },

      auctionNFTSettles: 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('auctionNFTSettles', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'auctionNFTSettles',
          expressContext,
          async () => indexer.getSubgraphEntities(
            AuctionNFTSettle,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      drawDebtNFT: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('drawDebtNFT', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'drawDebtNFT',
          expressContext,
          async () => indexer.getSubgraphEntity(DrawDebtNFT, id, block, info)
        );
      },

      drawDebtNFTS: 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('drawDebtNFTS', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'drawDebtNFTS',
          expressContext,
          async () => indexer.getSubgraphEntities(
            DrawDebtNFT,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      mergeOrRemoveCollateralNFT: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('mergeOrRemoveCollateralNFT', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'mergeOrRemoveCollateralNFT',
          expressContext,
          async () => indexer.getSubgraphEntity(MergeOrRemoveCollateralNFT, id, block, info)
        );
      },

      mergeOrRemoveCollateralNFTS: 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('mergeOrRemoveCollateralNFTS', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'mergeOrRemoveCollateralNFTS',
          expressContext,
          async () => indexer.getSubgraphEntities(
            MergeOrRemoveCollateralNFT,
            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
          )
        );
      },

      positionLend: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('positionLend', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'positionLend',
          expressContext,
          async () => indexer.getSubgraphEntity(PositionLend, id, block, info)
        );
      },

      positionLends: 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('positionLends', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'positionLends',
          expressContext,
          async () => indexer.getSubgraphEntities(
            PositionLend,
            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
          )
        );
      },

      memorializePosition: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('memorializePosition', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'memorializePosition',
          expressContext,
          async () => indexer.getSubgraphEntity(MemorializePosition, id, block, info)
        );
      },

      memorializePositions: 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('memorializePositions', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'memorializePositions',
          expressContext,
          async () => indexer.getSubgraphEntities(
            MemorializePosition,
            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
          )
        );
      },

      redeemPosition: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('redeemPosition', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'redeemPosition',
          expressContext,
          async () => indexer.getSubgraphEntity(RedeemPosition, id, block, info)
        );
      },

      redeemPositions: 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('redeemPositions', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'redeemPositions',
          expressContext,
          async () => indexer.getSubgraphEntities(
            RedeemPosition,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      grantFund: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('grantFund', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'grantFund',
          expressContext,
          async () => indexer.getSubgraphEntity(GrantFund, id, block, info)
        );
      },

      grantFunds: 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('grantFunds', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'grantFunds',
          expressContext,
          async () => indexer.getSubgraphEntities(
            GrantFund,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      distributionPeriod: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('distributionPeriod', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'distributionPeriod',
          expressContext,
          async () => indexer.getSubgraphEntity(DistributionPeriod, id, block, info)
        );
      },

      distributionPeriods: 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('distributionPeriods', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'distributionPeriods',
          expressContext,
          async () => indexer.getSubgraphEntities(
            DistributionPeriod,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      proposal: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('proposal', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'proposal',
          expressContext,
          async () => indexer.getSubgraphEntity(Proposal, id, block, info)
        );
      },

      proposals: 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('proposals', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'proposals',
          expressContext,
          async () => indexer.getSubgraphEntities(
            Proposal,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      proposalParams: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('proposalParams', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'proposalParams',
          expressContext,
          async () => indexer.getSubgraphEntity(ProposalParams, id, block, info)
        );
      },

      proposalParamss: 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('proposalParamss', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'proposalParamss',
          expressContext,
          async () => indexer.getSubgraphEntities(
            ProposalParams,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      distributionPeriodVote: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('distributionPeriodVote', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'distributionPeriodVote',
          expressContext,
          async () => indexer.getSubgraphEntity(DistributionPeriodVote, id, block, info)
        );
      },

      distributionPeriodVotes: 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('distributionPeriodVotes', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'distributionPeriodVotes',
          expressContext,
          async () => indexer.getSubgraphEntities(
            DistributionPeriodVote,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      screeningVote: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('screeningVote', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'screeningVote',
          expressContext,
          async () => indexer.getSubgraphEntity(ScreeningVote, id, block, info)
        );
      },

      screeningVotes: 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('screeningVotes', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'screeningVotes',
          expressContext,
          async () => indexer.getSubgraphEntities(
            ScreeningVote,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      fundingVote: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('fundingVote', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'fundingVote',
          expressContext,
          async () => indexer.getSubgraphEntity(FundingVote, id, block, info)
        );
      },

      fundingVotes: 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('fundingVotes', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'fundingVotes',
          expressContext,
          async () => indexer.getSubgraphEntities(
            FundingVote,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      fundedSlate: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('fundedSlate', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'fundedSlate',
          expressContext,
          async () => indexer.getSubgraphEntity(FundedSlate, id, block, info)
        );
      },

      fundedSlates: 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('fundedSlates', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'fundedSlates',
          expressContext,
          async () => indexer.getSubgraphEntities(
            FundedSlate,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      delegateRewardClaimed: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('delegateRewardClaimed', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'delegateRewardClaimed',
          expressContext,
          async () => indexer.getSubgraphEntity(DelegateRewardClaimed, id, block, info)
        );
      },

      delegateRewardClaimeds: 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('delegateRewardClaimeds', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'delegateRewardClaimeds',
          expressContext,
          async () => indexer.getSubgraphEntities(
            DelegateRewardClaimed,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      fundTreasury: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('fundTreasury', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'fundTreasury',
          expressContext,
          async () => indexer.getSubgraphEntity(FundTreasury, id, block, info)
        );
      },

      fundTreasuries: 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('fundTreasuries', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'fundTreasuries',
          expressContext,
          async () => indexer.getSubgraphEntities(
            FundTreasury,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      fundedSlateUpdated: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('fundedSlateUpdated', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'fundedSlateUpdated',
          expressContext,
          async () => indexer.getSubgraphEntity(FundedSlateUpdated, id, block, info)
        );
      },

      fundedSlateUpdateds: 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('fundedSlateUpdateds', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'fundedSlateUpdateds',
          expressContext,
          async () => indexer.getSubgraphEntities(
            FundedSlateUpdated,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      proposalCreated: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('proposalCreated', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'proposalCreated',
          expressContext,
          async () => indexer.getSubgraphEntity(ProposalCreated, id, block, info)
        );
      },

      proposalCreateds: 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('proposalCreateds', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'proposalCreateds',
          expressContext,
          async () => indexer.getSubgraphEntities(
            ProposalCreated,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      proposalExecuted: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('proposalExecuted', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'proposalExecuted',
          expressContext,
          async () => indexer.getSubgraphEntity(ProposalExecuted, id, block, info)
        );
      },

      proposalExecuteds: 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('proposalExecuteds', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'proposalExecuteds',
          expressContext,
          async () => indexer.getSubgraphEntities(
            ProposalExecuted,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      distributionPeriodStarted: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('distributionPeriodStarted', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'distributionPeriodStarted',
          expressContext,
          async () => indexer.getSubgraphEntity(DistributionPeriodStarted, id, block, info)
        );
      },

      distributionPeriodStarteds: 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('distributionPeriodStarteds', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'distributionPeriodStarteds',
          expressContext,
          async () => indexer.getSubgraphEntities(
            DistributionPeriodStarted,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      voteCast: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('voteCast', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'voteCast',
          expressContext,
          async () => indexer.getSubgraphEntity(VoteCast, id, block, info)
        );
      },

      voteCasts: 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('voteCasts', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'voteCasts',
          expressContext,
          async () => indexer.getSubgraphEntities(
            VoteCast,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      delegateChanged: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('delegateChanged', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'delegateChanged',
          expressContext,
          async () => indexer.getSubgraphEntity(DelegateChanged, id, block, info)
        );
      },

      delegateChangeds: 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('delegateChangeds', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'delegateChangeds',
          expressContext,
          async () => indexer.getSubgraphEntities(
            DelegateChanged,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      delegateVotesChanged: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('delegateVotesChanged', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'delegateVotesChanged',
          expressContext,
          async () => indexer.getSubgraphEntity(DelegateVotesChanged, id, block, info)
        );
      },

      delegateVotesChangeds: 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('delegateVotesChangeds', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'delegateVotesChangeds',
          expressContext,
          async () => indexer.getSubgraphEntities(
            DelegateVotesChanged,
            block,
            where,
            { limit: first, skip, orderBy, orderDirection },
            info
          )
        );
      },

      burnWrap: async (
        _: any,
        { id, block = {} }: { id: string, block: BlockHeight },
        expressContext: ExpressContext,
        info: GraphQLResolveInfo
      ) => {
        log('burnWrap', id, JSON.stringify(block, jsonBigIntStringReplacer));

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'burnWrap',
          expressContext,
          async () => indexer.getSubgraphEntity(BurnWrap, id, block, info)
        );
      },

      burnWraps: 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('burnWraps', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);

        // Set cache-control hints
        // setGQLCacheHints(info, block, gqlCacheConfig);

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'burnWraps',
          expressContext,
          async () => indexer.getSubgraphEntities(
            BurnWrap,
            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<string, never>,
        expressContext: ExpressContext
      ) => {
        log('getSyncStatus');

        return executeAndRecordMetrics(
          indexer,
          gqlLogger,
          'getSyncStatus',
          expressContext,
          async () => indexer.getSyncStatus()
        );
      }
    }
  };
};
