"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createIndexerManagementClient = exports.IndexerManagementClient = void 0;
const graphql_1 = require("graphql");
const graphql_tag_1 = __importDefault(require("graphql-tag"));
const exchange_execute_1 = require("@urql/exchange-execute");
const core_1 = require("@urql/core");
const common_ts_1 = require("@graphprotocol/common-ts");
const indexing_rules_1 = __importDefault(require("./resolvers/indexing-rules"));
const indexer_status_1 = __importDefault(require("./resolvers/indexer-status"));
const cost_models_1 = __importDefault(require("./resolvers/cost-models"));
const poi_disputes_1 = __importDefault(require("./resolvers/poi-disputes"));
const sequelize_1 = require("sequelize");
const SCHEMA_SDL = graphql_tag_1.default `
  scalar BigInt

  enum IndexingDecisionBasis {
    rules
    never
    always
  }

  type POIDispute {
    allocationID: String!
    subgraphDeploymentID: String!
    allocationIndexer: String!
    allocationAmount: BigInt!
    allocationProof: String!
    closedEpoch: Int!
    closedEpochStartBlockHash: String!
    closedEpochStartBlockNumber: Int!
    closedEpochReferenceProof: String!
    previousEpochStartBlockHash: String!
    previousEpochStartBlockNumber: Int!
    previousEpochReferenceProof: String!
    status: String!
  }

  input POIDisputeInput {
    allocationID: String!
    subgraphDeploymentID: String!
    allocationIndexer: String!
    allocationAmount: BigInt!
    allocationProof: String!
    closedEpoch: Int!
    closedEpochStartBlockHash: String!
    closedEpochStartBlockNumber: Int!
    closedEpochReferenceProof: String!
    previousEpochStartBlockHash: String!
    previousEpochStartBlockNumber: Int!
    previousEpochReferenceProof: String!
    status: String!
  }

  type IndexingRule {
    deployment: String!
    allocationAmount: BigInt
    parallelAllocations: Int
    maxAllocationPercentage: Float
    minSignal: BigInt
    maxSignal: BigInt
    minStake: BigInt
    minAverageQueryFees: BigInt
    custom: String
    decisionBasis: IndexingDecisionBasis!
  }

  input IndexingRuleInput {
    deployment: String!
    allocationAmount: BigInt
    parallelAllocations: Int
    maxAllocationPercentage: Float
    minSignal: BigInt
    maxSignal: BigInt
    minStake: BigInt
    minAverageQueryFees: BigInt
    custom: String
    decisionBasis: IndexingDecisionBasis
  }

  type GeoLocation {
    latitude: String!
    longitude: String!
  }

  type IndexerRegistration {
    url: String
    address: String
    registered: Boolean!
    location: GeoLocation
  }

  type IndexingError {
    handler: String
    message: String!
  }

  type BlockPointer {
    number: Int!
    hash: String!
  }

  type ChainIndexingStatus {
    network: String!
    latestBlock: BlockPointer!
    chainHeadBlock: BlockPointer!
    earliestBlock: BlockPointer!
  }

  type IndexerDeployment {
    subgraphDeployment: String!
    synced: Boolean!
    health: String!
    fatalError: IndexingError
    node: String!
    chains: [ChainIndexingStatus]
  }

  type IndexerAllocation {
    id: String!
    allocatedTokens: BigInt!
    createdAtEpoch: Int!
    closedAtEpoch: Int
    subgraphDeployment: String!
    signalAmount: BigInt!
    stakedTokens: BigInt!
  }

  type IndexerEndpointTest {
    test: String!
    error: String
    possibleActions: [String]!
  }

  type IndexerEndpoint {
    url: String
    healthy: Boolean!
    tests: [IndexerEndpointTest!]!
  }

  type IndexerEndpoints {
    service: IndexerEndpoint!
    status: IndexerEndpoint!
  }

  type CostModel {
    deployment: String!
    model: String
    variables: String
  }

  input CostModelInput {
    deployment: String!
    model: String
    variables: String
  }

  type Query {
    indexingRule(deployment: String!, merged: Boolean! = false): IndexingRule
    indexingRules(merged: Boolean! = false): [IndexingRule!]!
    indexerRegistration: IndexerRegistration!
    indexerDeployments: [IndexerDeployment]!
    indexerAllocations: [IndexerAllocation]!
    indexerEndpoints: IndexerEndpoints!

    costModels(deployments: [String!]): [CostModel!]!
    costModel(deployment: String!): CostModel

    dispute(allocationID: String!): POIDispute
    disputes(status: String!, minClosedEpoch: Int!): [POIDispute]!
    disputesClosedAfter(closedAfterBlock: BigInt!): [POIDispute]!
  }

  type Mutation {
    setIndexingRule(rule: IndexingRuleInput!): IndexingRule!
    deleteIndexingRule(deployment: String!): Boolean!
    deleteIndexingRules(deployments: [String!]!): Boolean!

    setCostModel(costModel: CostModelInput!): CostModel!

    storeDisputes(disputes: [POIDisputeInput!]!): [POIDispute!]
    deleteDisputes(allocationIDs: [String!]!): Int!
  }
`;
class IndexerManagementClient extends core_1.Client {
    constructor(clientOptions, options, featureOptions) {
        super(clientOptions);
        this.logger = options.logger;
        this.models = options.models;
        this.dai = featureOptions.dai;
    }
    setDai(value) {
        return __awaiter(this, void 0, void 0, function* () {
            // Get current value
            const oldValue = this.dai.valueReady ? yield this.dai.value() : undefined;
            // Don't do anything if there is no change
            if (common_ts_1.equal(oldValue, value)) {
                return;
            }
            // Notify others of the new value
            this.dai.push(value);
            // Update DAI in all cost models
            const update = `'${JSON.stringify({ DAI: value })}'::jsonb`;
            yield this.models.CostModel.update({
                // This merges DAI into the variables, overwriting existing values
                variables: sequelize_1.Sequelize.literal(`coalesce(variables, '{}'::jsonb) || ${update}`),
            }, {
                // This is just a non-obvious way to match all models
                where: { deployment: { [sequelize_1.Op.not]: null } },
            });
        });
    }
}
exports.IndexerManagementClient = IndexerManagementClient;
exports.createIndexerManagementClient = (options) => __awaiter(void 0, void 0, void 0, function* () {
    const { models, address, contracts, indexingStatusResolver, networkSubgraph, logger, defaults, features, } = options;
    const schema = graphql_1.buildSchema(graphql_1.print(SCHEMA_SDL));
    const resolvers = Object.assign(Object.assign(Object.assign(Object.assign({}, indexing_rules_1.default), indexer_status_1.default), cost_models_1.default), poi_disputes_1.default);
    const dai = common_ts_1.mutable();
    const exchange = exchange_execute_1.executeExchange({
        schema,
        rootValue: resolvers,
        context: {
            models,
            address,
            contracts,
            indexingStatusResolver,
            networkSubgraph,
            logger: logger ? logger.child({ component: 'IndexerManagementClient' }) : undefined,
            defaults,
            features,
            dai,
        },
    });
    return new IndexerManagementClient({ url: 'no-op', exchanges: [exchange] }, options, {
        dai,
    });
});
//# sourceMappingURL=client.js.map