# All files / src/indexer-management/resolvers cost-models.ts

95.56% Statements 43/45
91.18% Branches 31/34
100% Functions 9/9
95.45% Lines 42/44

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113

    3x

    3x

    3x
    44x
    3x

    41x
    41x
    9x

    13x

    19x

    3x

    4x

    4x
    4x
    4x

    3x

    3x
    3x

    3x

    8x
    8x

    11x

    27x
    27x

    27x
    27x
    27x
    27x

    3x

    24x

    24x
    24x

    24x

    24x
    22x
    22x

    22x
    2x
    20x

    2x

    24x

    24x

     /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
    /* eslint-disable @typescript-eslint/ban-types */

    import { CostModelVariables, GraphQLCostModel, parseGraphQLCostModel } from '../models'
    import { IndexerManagementResolverContext } from '../client'
    import { compileAsync } from '@graphprotocol/cost-model'

    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const getVariable = (vars: CostModelVariables | null, name: string): any | undefined => {
      if (vars === null) {
        return undefined
      } else {
        try {
          if (Object.prototype.hasOwnProperty.call(vars, name)) {
            return vars[name]
          } else {
            return undefined
          }
        } catch (e) {
          return undefined
        }
      }
    }

    const setVariable = (
      vars: CostModelVariables | null,
      name: string,
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      value: any,
    ): CostModelVariables => {
      Iif (vars === null) {
        return { [name]: value }
      } else {
        try {
          vars[name] = value
          return vars
        } catch (e) {
          return vars
        }
      }
    }

    export default {
      costModel: async (
        { deployment }: { deployment: string },
        { models }: IndexerManagementResolverContext,
      ): Promise<object | null> => {
        const model = await models.CostModel.findOne({
          where: { deployment },
        })
        return model?.toGraphQL() || null
      },

      costModels: async (
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        { deployments }: { deployments: string[] | null | undefined },
        { models }: IndexerManagementResolverContext,
      ): Promise<object[]> => {
        const costModels = await models.CostModel.findAll({
          where: deployments ? { deployment: deployments } : undefined,
          order: [['deployment', 'ASC']],
        })
        return costModels.map((model) => model.toGraphQL())
      },

      setCostModel: async (
        { costModel }: { deployment: string; costModel: GraphQLCostModel },
        { models, features, dai }: IndexerManagementResolverContext,
      ): Promise<object> => {
        const update = parseGraphQLCostModel(costModel)

        // Validate cost model
        try {
          const modelForValidation = update.model || 'default => 1;'
          const variablesForValidation = JSON.stringify(update.variables || {})
          await compileAsync(modelForValidation, variablesForValidation)
        } catch (err) {
          throw new Error(`Invalid cost model or variables: ${err.message}`)
        }

        const [model] = await models.CostModel.findOrBuild({
          where: { deployment: update.deployment },
        })
        model.deployment = costModel.deployment || model.deployment
        model.model =
          costModel.model !== null && costModel.model !== undefined
            ? costModel.model
            : model.model

        // Update the model variables (fall back to current value if unchanged)
        let variables = update.variables || model.variables

        if (features.injectDai) {
          const oldDai = getVariable(model.variables, 'DAI')
          const newDai = getVariable(update.variables, 'DAI')

          // Inject the latest DAI value if available
          if (dai.valueReady) {
            variables = setVariable(variables, 'DAI', await dai.value())
          } else if (newDai === undefined && oldDai !== undefined) {
            // Otherwise preserve the old DAI value if there is one;
            // this ensures it's never dropped
            variables = setVariable(variables, 'DAI', oldDai)
          }
        }

        // Apply new variables
        model.variables = variables

        return (await model.save()).toGraphQL()
      },
    }