import {
  ATTESTATION_SUBNET_COUNT,
  ATTESTATION_SUBNET_EXTRA_BITS,
  ATTESTATION_SUBNET_PREFIX_BITS,
  BASE_REWARDS_PER_EPOCH,
  BLOB_TX_TYPE,
  BLS_WITHDRAWAL_PREFIX,
  BUILDER_INDEX_FLAG,
  BUILDER_INDEX_SELF_BUILD,
  BUILDER_PAYMENT_THRESHOLD_DENOMINATOR,
  BUILDER_PAYMENT_THRESHOLD_NUMERATOR,
  BUILDER_WITHDRAWAL_PREFIX,
  COMPOUNDING_WITHDRAWAL_PREFIX,
  CONSOLIDATION_REQUEST_TYPE,
  DEPOSIT_CONTRACT_TREE_DEPTH,
  DEPOSIT_REQUEST_TYPE,
  DOMAIN_AGGREGATE_AND_PROOF,
  DOMAIN_APPLICATION_BUILDER,
  DOMAIN_APPLICATION_MASK,
  DOMAIN_BEACON_ATTESTER,
  DOMAIN_BEACON_BUILDER,
  DOMAIN_BEACON_PROPOSER,
  DOMAIN_BLS_TO_EXECUTION_CHANGE,
  DOMAIN_CONTRIBUTION_AND_PROOF,
  DOMAIN_DEPOSIT,
  DOMAIN_PROPOSER_PREFERENCES,
  DOMAIN_PTC_ATTESTER,
  DOMAIN_RANDAO,
  DOMAIN_SELECTION_PROOF,
  DOMAIN_SYNC_COMMITTEE,
  DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF,
  DOMAIN_VOLUNTARY_EXIT,
  ETH1_ADDRESS_WITHDRAWAL_PREFIX,
  FAR_FUTURE_EPOCH,
  FULL_EXIT_REQUEST_AMOUNT,
  GENESIS_EPOCH,
  GENESIS_SLOT,
  JUSTIFICATION_BITS_LENGTH,
  MAX_CONCURRENT_REQUESTS,
  NODE_ID_BITS,
  PROPOSER_WEIGHT,
  SYNC_COMMITTEE_SUBNET_COUNT,
  SYNC_REWARD_WEIGHT,
  TARGET_AGGREGATORS_PER_COMMITTEE,
  TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE,
  TIMELY_HEAD_FLAG_INDEX,
  TIMELY_HEAD_WEIGHT,
  TIMELY_SOURCE_FLAG_INDEX,
  TIMELY_SOURCE_WEIGHT,
  TIMELY_TARGET_FLAG_INDEX,
  TIMELY_TARGET_WEIGHT,
  UNSET_DEPOSIT_REQUESTS_START_INDEX,
  VERSIONED_HASH_VERSION_KZG,
  WEIGHT_DENOMINATOR,
  WITHDRAWAL_REQUEST_TYPE,
} from "@lodestar/params";

/**
 * Hand-picked list of constants declared in consensus-spec .md files.
 * This list is asserted to be up-to-date with the test `test/e2e/api/impl/config.test.ts`
 */
export const specConstants = {
  // phase0/beacon-chain.md
  // ## misc
  GENESIS_SLOT,
  GENESIS_EPOCH,
  FAR_FUTURE_EPOCH,
  BASE_REWARDS_PER_EPOCH,
  DEPOSIT_CONTRACT_TREE_DEPTH,
  JUSTIFICATION_BITS_LENGTH,
  ENDIANNESS: "little",
  // ## Withdrawal prefixes
  BLS_WITHDRAWAL_PREFIX: toHexByte(BLS_WITHDRAWAL_PREFIX),
  ETH1_ADDRESS_WITHDRAWAL_PREFIX: toHexByte(ETH1_ADDRESS_WITHDRAWAL_PREFIX),
  COMPOUNDING_WITHDRAWAL_PREFIX: toHexByte(COMPOUNDING_WITHDRAWAL_PREFIX),
  BUILDER_WITHDRAWAL_PREFIX: toHexByte(BUILDER_WITHDRAWAL_PREFIX),
  // ## Domain types
  DOMAIN_BEACON_PROPOSER,
  DOMAIN_BEACON_ATTESTER,
  DOMAIN_RANDAO,
  DOMAIN_DEPOSIT,
  DOMAIN_VOLUNTARY_EXIT,
  DOMAIN_SELECTION_PROOF,
  DOMAIN_AGGREGATE_AND_PROOF,
  DOMAIN_APPLICATION_MASK,
  DOMAIN_APPLICATION_BUILDER,
  DOMAIN_BEACON_BUILDER,
  DOMAIN_PROPOSER_PREFERENCES,
  DOMAIN_PTC_ATTESTER,

  // phase0/validator.md
  TARGET_AGGREGATORS_PER_COMMITTEE,

  // phase0/p2p-interface.md
  NODE_ID_BITS,
  MAX_CONCURRENT_REQUESTS,
  ATTESTATION_SUBNET_COUNT,
  ATTESTATION_SUBNET_EXTRA_BITS,
  ATTESTATION_SUBNET_PREFIX_BITS,

  // altair/beacon-chain.md
  // ## Participation flag indices
  TIMELY_SOURCE_FLAG_INDEX,
  TIMELY_TARGET_FLAG_INDEX,
  TIMELY_HEAD_FLAG_INDEX,
  // ## Incentivization weights
  TIMELY_SOURCE_WEIGHT,
  TIMELY_TARGET_WEIGHT,
  TIMELY_HEAD_WEIGHT,
  SYNC_REWARD_WEIGHT,
  PROPOSER_WEIGHT,
  WEIGHT_DENOMINATOR,
  // ## Domain types
  DOMAIN_SYNC_COMMITTEE,
  DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF,
  DOMAIN_CONTRIBUTION_AND_PROOF,

  // altair/validator.md
  TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE,
  SYNC_COMMITTEE_SUBNET_COUNT,

  // ## Capella domain types
  DOMAIN_BLS_TO_EXECUTION_CHANGE,

  // Deneb types
  BLOB_TX_TYPE: toHexByte(BLOB_TX_TYPE),
  VERSIONED_HASH_VERSION_KZG: toHexByte(VERSIONED_HASH_VERSION_KZG),

  // electra
  UNSET_DEPOSIT_REQUESTS_START_INDEX,
  FULL_EXIT_REQUEST_AMOUNT,
  DEPOSIT_REQUEST_TYPE: toHexByte(DEPOSIT_REQUEST_TYPE),
  WITHDRAWAL_REQUEST_TYPE: toHexByte(WITHDRAWAL_REQUEST_TYPE),
  CONSOLIDATION_REQUEST_TYPE: toHexByte(CONSOLIDATION_REQUEST_TYPE),

  // gloas
  BUILDER_INDEX_FLAG,
  BUILDER_INDEX_SELF_BUILD,
  BUILDER_PAYMENT_THRESHOLD_NUMERATOR,
  BUILDER_PAYMENT_THRESHOLD_DENOMINATOR,
};

/** Convert single-byte numbers to hex strings for API spec compliance */
function toHexByte(n: number): string {
  if (n < 0 || n > 255 || !Number.isInteger(n)) {
    throw new Error("toHexByte expected a single-byte integer, but received " + n);
  }
  return "0x" + n.toString(16).padStart(2, "0");
}
