import express from 'express';
import { Global } from "../global";
import { Request, Response, NextFunction } from 'express';
import { getRepository, getConnection } from 'typeorm';
import { validationMiddleware, redisMiddleware } from '../middlewares';
import {
  InternalServerErrorException,
  NoDataFoundException,
  IntegerValidationException,
} from '../exceptions';
import {
  BlockchainBlock,
  BlockchainInput,
  BlockchainOutput,
  BlockchainKernel,
} from '../entities';
import {
  BlockchainBlockCreateDto,
  BlockchainBlockSingleViewDto,
  BlockchainBlockUpdateDto,
  BlockchainBlockPaginationDto,
  TotalDifficultyNBlockDto,
} from '../dtos';
import { Paginate } from '../utils';
import {latestBlockDetails} from '../utils/common';
var moment = require('moment');
moment.updateLocale('en', {
  relativeTime: {
       future: "in %s",
       past:   "%s ago",
       s:  "seconds",
       m:  "1 minute",
       mm: "%d minutes",
       h:  "1 hour",
       hh: "%d hours",
       d:  "1 day",
       dd: "%d days",
       M:  "1 month",
       MM: "%d months",
       y:  "1 year",
       yy: "%d years"
 }
});
export class BlockchainBlockController {
  public path = '/blockchain_block';
  public router = express.Router();

  constructor() {
    this.IntializeRoutes();
  }

  nanoEpic(fee) {
    if (fee == 0) {
      return this.epic(0);
    } else if (fee < 1000) {
      return fee / 1000000000;
    } else {
      return this.microEpic(parseFloat(fee) / 1000);
    }
  }

  microEpic(fee) {
    if (fee == 0) {
      return this.epic(0);
    } else if (fee < 1000) {
      return fee / 1000000;
    } else {
      return this.milliEpic(parseFloat(fee) / 1000);
    }
  }

  milliEpic(fee) {
    if (fee == 0) {
      return this.epic(0);
    } else if (fee < 1000) {
      return fee / 1000;
    } else {
      return this.epic(parseFloat(fee) / 1000);
    }
  }

  epic(fee) {
    return fee;
  }

  dateDiff(date2, insec = false) {
    var current_date = new Date();
    // var current_date = new Date("Sat Apr 2 2018 15:04:00 GMT+0530 (IST)");

    var enddaydif =
      Math.abs(date2.getTime() - current_date.getTime()) /
      (1000 * 60 * 60 * 24);
    var enddayrnd = Math.round(enddaydif);
    // if(enddayrnd < 1) {
    var time = this.convertMinsToHrmin(
      Math.abs(date2.getTime() - current_date.getTime()),insec
    );
    return time;
    // } else if(enddayrnd == 1) {
    //   return 'Ends in ' + enddayrnd + ' day';
    // }else {
    //   return 'Ends in ' + enddayrnd + ' days';
    // }
  }

  // convertMinsToHrmin(millseconds) {
  //   var seconds = Math.floor(millseconds / 1000);
  //   var days = Math.floor(seconds / 86400);
  //   var hours = Math.floor((seconds % 86400) / 3600);
  //   var minutes = Math.floor(((seconds % 86400) % 3600) / 60);

  //   var dateTimeDurationString = '';
  //   if ((days > 0) && (hours === 0 && minutes === 0)) dateTimeDurationString += (days > 1) ? (days + ' days ') : (days + ' day ');
  //   if ((days > 0) && (hours > 0 || minutes > 0)) dateTimeDurationString += (days > 1) ? (days + ' days, ') : (days + ' day, ');
  //   if ((hours > 0) && (minutes > 0)) dateTimeDurationString += (hours > 1) ? (hours + ' hours, ') : (hours + ' hour, ');
  //   if ((hours > 0) && (minutes === 0)) dateTimeDurationString += (hours > 1) ? (hours + ' hours ') : (hours + ' hour ');
  //   if (minutes > 0) dateTimeDurationString += (minutes > 1) ? (minutes + ' minutes ') : (minutes + ' minute ');
  //   if (seconds > 0) dateTimeDurationString += (seconds > 1) ? (minutes + ' seconds ') : (minutes + ' second ');
  //   return dateTimeDurationString;
  // }

  convertMinsToHrmin(millseconds,insec) {
    var seconds = Math.floor(millseconds / 1000);
    if(insec){
      let sec = Math.floor(millseconds / 1000);
      return sec;
    }
    var days = Math.floor(seconds / 86400);
    var hours = Math.floor((seconds % 86400) / 3600);
    var minutes = Math.floor(((seconds % 86400) % 3600) / 60);
    seconds = seconds % 60;
    var dateTimeDurationString = '';

    if (days > 0 && (hours === 0 && minutes === 0))
      dateTimeDurationString += days > 1 ? days + 'd ' : days + 'd ';
    if (days > 0 && (hours > 0 || minutes > 0))
      dateTimeDurationString += days > 1 ? days + 'd ' : days + 'd ';
    if (hours > 0 && minutes > 0)
      dateTimeDurationString += hours > 1 ? hours + 'h ' : hours + 'h ';
    if (hours > 0 && minutes === 0)
      dateTimeDurationString += hours > 1 ? hours + 'h ' : hours + 'h ';
    if (minutes > 0)
      dateTimeDurationString += minutes > 1 ? minutes + 'm ' : minutes + 'm ';
    if (seconds > 0)
      dateTimeDurationString += seconds > 1 ? seconds + 's ' : seconds + 's ';
    return dateTimeDurationString;
  }

  public IntializeRoutes() {
    /**
     * @swagger
     * /epic_explorer/v1/blockchain_block:
     *   post:
     *     tags:
     *       - name: BLOCKCHAIN_BLOCK | BLOCKCHAIN_BLOCK CONTROLLER
     *     summary: create a blockchain_block
     *     description: create a blockchain_block
     *     consumes:
     *       - application/json
     *     produces:
     *       - application/json
     *     parameters:
     *       - name: BlockchainBlock
     *         description: create a blockchain_block
     *         in: body
     *         required: true
     *         schema:
     *           $ref: '#/definitions/BlockchainBlockDto'
     *     responses:
     *       200:
     *         description: blockchain_block created successfully
     * definitions:
     *   BlockchainBlockDto:
     *    description: Dto
     *    properties:
     *      Hash:
     *           type: string
     *      Version:
     *           type: integer
     *      Height:
     *           type: integer
     *      Timestamp:
     *           type: string
     *      OutputRoot:
     *           type: string
     *      RangeProofRoot:
     *           type: string
     *      KernelRoot:
     *           type: string
     *      Nonce:
     *           type: string
     *      TotalDifficulty:
     *           type: string
     *      Previous:
     *           type: string
     *      TotalKernelOffset:
     *           type: string
     *      EdgeBits:
     *           type: integer
     *      CuckooSolution:
     *           type: string
     *      PrevRoot:
     *           type: string
     *      SecondaryScaling:
     *           type: integer
     */

    this.router.post(
      `${this.path}`,
      validationMiddleware(BlockchainBlockCreateDto),
      redisMiddleware(process.env.REDIS_EXPIRY),
      this.BlockchainBlockCreate,
    );

    /**
     * @swagger
     * /epic_explorer/v1/blockchain_block/totaldiff:
     *   get:
     *     tags:
     *       - name: BLOCKCHAIN_BLOCK | BLOCKCHAIN_BLOCK CONTROLLER
     *     description: To get Total Difficulty and Number of Blocks
     *     summary: To get Total Difficulty and Number of Blocks
     *     consumes:
     *       - application/json
     *     produces:
     *       - application/json
     *     parameters:
     *       - name: FromDate
     *         description: Enter the From date
     *         in: query
     *         type: string
     *       - name: ToDate
     *         description: Enter the To date
     *         in: query
     *         type: string
     *       - name: Interval
     *         description: Try to give Intevals such as 1 week/ 15 days/ 30 days/ 60 days/ 3 months
     *         in: query
     *         type: string
     *       - name: Type
     *         description: Enter the Algorithm Type
     *         in: query
     *         type: string
     *       - name: Difftype
     *         description: Enter the Difficulty Type
     *         in: query
     *         type: string
     *     responses:
     *       200:
     *         description: Total Difficulty fetched successfully
     */
    this.router.get(
      `${this.path}/totaldiff`,
      validationMiddleware(TotalDifficultyNBlockDto, true),
      redisMiddleware(process.env.REDIS_EXPIRY),
      this.TotalDifficultyNBlock,
    );

       /**
     * @swagger
     * /epic_explorer/v1/blockchain_block/blockcount:
     *   get:
     *     tags:
     *       - name: BLOCKCHAIN_BLOCK | BLOCKCHAIN_BLOCK CONTROLLER
     *     description: To get Total Difficulty and Number of Blocks
     *     summary: To get Total Difficulty and Number of Blocks
     *     consumes:
     *       - application/json
     *     produces:
     *       - application/json
     *     parameters:
     *       - name: FromDate
     *         description: Enter the From date
     *         in: query
     *         type: string
     *       - name: ToDate
     *         description: Enter the To date
     *         in: query
     *         type: string
     *       - name: Interval
     *         description: Try to give Intevals such as 1 week/ 15 days/ 30 days/ 60 days/ 3 months
     *         in: query
     *         type: string
     *     responses:
     *       200:
     *         description: Total Difficulty fetched successfully
     */
    this.router.get(
      `${this.path}/blockcount`,
      validationMiddleware(TotalDifficultyNBlockDto, true),
      redisMiddleware(process.env.REDIS_EXPIRY),
      this.BlockCount,
    );



         /**
     * @swagger
     * /epic_explorer/v1/blockchain_block/blockinterval:
     *   get:
     *     tags:
     *       - name: BLOCKCHAIN_BLOCK | BLOCKCHAIN_BLOCK CONTROLLER
     *     description: To get Block Interval
     *     summary: To get Block Interval
     *     consumes:
     *       - application/json
     *     produces:
     *       - application/json
     *     parameters:
     *       - name: Interval
     *         description: try to get Date
     *         in: query
     *         type: string
     *     responses:
     *       200:
     *         description: Block Interval fetched successfully
     */
    this.router.get(
      `${this.path}/blockinterval`,
      validationMiddleware(TotalDifficultyNBlockDto, true),
      redisMiddleware(process.env.REDIS_EXPIRY),
      this.BlockInterval,
    );

    /**
     * @swagger
     * /epic_explorer/v1/blockchain_block/stackblock:
     *   get:
     *     tags:
     *       - name: STACK_BLOCK | STACK_BLOCK CONTROLLER
     *     description: To get Total Difficulty and Number of Blocks
     *     summary: To get Total Difficulty and Number of Blocks
     *     consumes:
     *       - application/json
     *     produces:
     *       - application/json
     *     parameters:
     *       - name: FromDate
     *         description: Enter the From date
     *         in: query
     *         type: string
     *       - name: ToDate
     *         description: Enter the To date
     *         in: query
     *         type: string
     *       - name: Interval
     *         description: Try to give Intevals such as 1 week/ 15 days/ 30 days/ 60 days/ 3 months
     *         in: query
     *         type: string
     *     responses:
     *       200:
     *         description: Total Difficulty and No. of blocks   fetched successfully
     */
    this.router.get(
      `${this.path}/stackblock`,
      validationMiddleware(TotalDifficultyNBlockDto, true),
      redisMiddleware(process.env.REDIS_EXPIRY),
      this.StackBlock,
    );

        /**
     * @swagger
     * /epic_explorer/v1/blockchain_block/blockpiechart:
     *   get:
     *     tags:
     *       - name: STACK_BLOCK | STACK_BLOCK CONTROLLER
     *     description: To get Total Difficulty and Number of Blocks
     *     summary: To get Total Difficulty and Number of Blocks
     *     consumes:
     *       - application/json
     *     produces:
     *       - application/json
     *     parameters:
     *       - name: FromDate
     *         description: Enter the From date
     *         in: query
     *         type: string
     *       - name: ToDate
     *         description: Enter the To date
     *         in: query
     *         type: string
     *       - name: Interval
     *         description: Try to give Intevals such as 1 week/ 15 days/ 30 days/ 60 days/ 3 months
     *         in: query
     *         type: string
     *     responses:
     *       200:
     *         description: Total Difficulty and No. of blocks   fetched successfully
     */
    this.router.get(
      `${this.path}/blockpiechart`,
      validationMiddleware(TotalDifficultyNBlockDto, true),
      redisMiddleware(process.env.REDIS_EXPIRY),
      this.BlockPieChart,
    );

    // /**
    //  * @swagger
    //  * /epic_explorer/v1/blockchain_block/hashrate:
    //  *   get:
    //  *     tags:
    //  *       - name: BLOCKCHAIN_BLOCK | BLOCKCHAIN_BLOCK CONTROLLER
    //  *     description: To get Hash Rate of AR29 abd AT31
    //  *     summary: To get Hash Rate of AR29 abd AT31
    //  *     consumes:
    //  *       - application/json
    //  *     produces:
    //  *       - application/json
    //  *     parameters:
    //  *       - name: FromDate
    //  *         description: Enter the From date
    //  *         in: query
    //  *         type: string
    //  *       - name: ToDate
    //  *         description: Enter the To date
    //  *         in: query
    //  *         type: string
    //  *       - name: Interval
    //  *         description: Try to give Intevals such as 1 week/ 15 days/ 30 days/ 60 days/ 3 months
    //  *         in: query
    //  *         type: string
    //  *     responses:
    //  *       200:
    //  *         description: Hash Rate of AR29 abd AT31 fetched successfully
    //  */
    // this.router.get(
    //   `${this.path}/hashrate`,
    //   validationMiddleware(TotalDifficultyNBlockDto, true),
    //   redisMiddleware(process.env.REDIS_EXPIRY),
    //   this.HashRate,
    // );

    /**
     * @swagger
     * /epic_explorer/v1/blockchain_block/latesblockdetails:
     *   get:
     *     tags:
     *       - name: BLOCKCHAIN_BLOCK | BLOCKCHAIN_BLOCK CONTROLLER
     *     description: To get Latest Block Height and Coin in Existence
     *     summary: To get Latest Block Height and Coin in Existence
     *     consumes:
     *       - application/json
     *     produces:
     *       - application/json
     *     responses:
     *       200:
     *         description: Total Difficulty and No. of blocks   fetched successfully
     */
    this.router.get(
      `${this.path}/latesblockdetails`,
      validationMiddleware(TotalDifficultyNBlockDto, true),
      redisMiddleware(process.env.REDIS_EXPIRY),
      this.LatestDifficultyNBlock,
    );

    /**
     * @swagger
     * /epic_explorer/v1/blockchain_block/blockspersec:
     *   get:
     *     tags:
     *       - name: BLOCKCHAIN_BLOCK | BLOCKCHAIN_BLOCK CONTROLLER
     *     description: period of blocks generation per unit(second)
     *     summary: period of blocks generation per unit(second)
     *     consumes:
     *       - application/json
     *     produces:
     *       - application/json
     *     parameters:
     *       - name: FromDate
     *         description: Enter the From date
     *         in: query
     *         type: string
     *       - name: ToDate
     *         description: Enter the To date
     *         in: query
     *         type: string
     *       - name: Interval
     *         description: Try to give Intevals such as 1 week/ 15 days/ 30 days/ 60 days/ 3 months
     *         in: query
     *         type: string
     *     responses:
     *       200:
     *         description: period of blocks generation per second fetched Successfully
     */
    this.router.get(
      `${this.path}/blockspersec`,
      validationMiddleware(TotalDifficultyNBlockDto, true),
      redisMiddleware(process.env.REDIS_EXPIRY),
      this.BlockchainBlockPerSecond,
    );

    /**
     * @swagger
     * /epic_explorer/v1/blockchain_block/supplygrowth:
     *   get:
     *     tags:
     *       - name: BLOCKCHAIN_BLOCK | BLOCKCHAIN_BLOCK CONTROLLER
     *     description: Supply growth
     *     summary: Supply growth
     *     consumes:
     *       - application/json
     *     produces:
     *       - application/json
     *     parameters:
     *       - name: FromDate
     *         description: Enter the From date
     *         in: query
     *         type: string
     *       - name: ToDate
     *         description: Enter the To date
     *         in: query
     *         type: string
     *       - name: Interval
     *         description: Try to give Intevals such as 1 week/ 15 days/ 30 days/ 60 days/ 3 months
     *         in: query
     *         type: string
     *     responses:
     *       200:
     *         description: period of blocks generation per second fetched Successfully
     */
    this.router.get(
      `${this.path}/supplygrowth`,
      validationMiddleware(TotalDifficultyNBlockDto, true),
      redisMiddleware(process.env.REDIS_EXPIRY),
      this.SupplyGrowth,
    );

    /**
     * @swagger
     * /epic_explorer/v1/blockchain_block/blockminedchart:
     *   get:
     *     tags:
     *       - name: BLOCKCHAIN_BLOCK | BLOCKCHAIN_BLOCK CONTROLLER
     *     description: To get Total Difficulty and Number of Blocks
     *     summary: To get Block Mined
     *     consumes:
     *       - application/json
     *     produces:
     *       - application/json
     *     parameters:
     *       - name: FromDate
     *         description: Enter the From date
     *         in: query
     *         type: string
     *       - name: ToDate
     *         description: Enter the To date
     *         in: query
     *         type: string
     *       - name: Interval
     *         description: Try to give Intevals such as 1 week/ 15 days/ 30 days/ 60 days/ 3 months
     *         in: query
     *         type: string
     *     responses:
     *       200:
     *         description: Block Mined chart data fetched successfully
     */
    this.router.get(
      `${this.path}/blockminedchart`,
      validationMiddleware(TotalDifficultyNBlockDto, true),
      redisMiddleware(process.env.REDIS_EXPIRY),
      this.BlockMineChart,
    );

    /**
     * @swagger
     * /epic_explorer/v1/blockchain_block/list:
     *   get:
     *     tags:
     *       - name: BLOCKCHAIN_BLOCK | BLOCKCHAIN_BLOCK CONTROLLER
     *     description: pagination blockchain_block
     *     summary: pagination blockchain_block
     *     consumes:
     *       - application/json
     *     produces:
     *       - application/json
     *     parameters:
     *       - name: CurrentPage
     *         description: current page specification
     *         in: query
     *         type: integer
     *         required: true
     *       - name: PageSize
     *         description: page size specification
     *         in: query
     *         type: integer
     *         required: true
     *     responses:
     *       200:
     *         description: blockchain_block list fetched successfully
     */
    this.router.get(
      `${this.path}/list`,
      validationMiddleware(BlockchainBlockPaginationDto),
      redisMiddleware(process.env.REDIS_EXPIRY),
      this.BlockchainBlockPagination,
    );

    /**
     * @swagger
     * /epic_explorer/v1/blockchain_block/{hash}:
     *   get:
     *     tags:
     *       - name: BLOCKCHAIN_BLOCK | BLOCKCHAIN_BLOCK CONTROLLER
     *     summary:  get single blockchain_block
     *     description: get single blockchain_block
     *     consumes:
     *       - application/json
     *     produces:
     *       - application/json
     *     parameters:
     *       - name: hash
     *         in: path
     *         description: blockchain_block hash
     *         required: true
     *         type: string
     *     responses:
     *       200:
     *         description: blockchain_block successfully fetched for given hash..
     */
    this.router.get(
      `${this.path}/:hash`,
      validationMiddleware(BlockchainBlockSingleViewDto, true),
      redisMiddleware(process.env.REDIS_EXPIRY),
      this.BlockchainBlockFetch,
    );

    /**
     * @swagger
     * /epic_explorer/v1/blockchain_block:
     *   patch:
     *     tags:
     *       - name: BLOCKCHAIN_BLOCK | BLOCKCHAIN_BLOCK CONTROLLER
     *     summary:  update a blockchain_block
     *     description:  update a blockchain_block
     *     consumes:
     *       - application/json
     *     produces:
     *       - application/json
     *     parameters:
     *       - name: blockchain_block
     *         description:
     *         in: body
     *         required: true
     *         schema:
     *           $ref: '#/definitions/BlockchainBlockDto'
     *     responses:
     *       200:
     *         description: blockchain_block updated successfully
     */
    this.router.patch(
      `${this.path}`,
      validationMiddleware(BlockchainBlockUpdateDto),
      redisMiddleware(process.env.REDIS_EXPIRY),
      this.BlockchainBlockUpdate,
    );

    /**
     * @swagger
     * /epic_explorer/v1/blockchain_block/hash:
     *   delete:
     *     tags:
     *       - name: BLOCKCHAIN_BLOCK | BLOCKCHAIN_BLOCK CONTROLLER
     *     summary:  delete a blockchain_block
     *     description: delete a blockchain_block
     *     consumes:
     *       - application/json
     *     produces:
     *       - application/json
     *     parameters:
     *       - name: Hash
     *         in: path
     *         description: blockchain_block hash
     *         required: true
     *         type: string
     *     responses:
     *       200:
     *         description: blockchain_block successfully deleted for given hash..
     */
    this.router.delete(
      `${this.path}/:hash`,
      validationMiddleware(BlockchainBlockSingleViewDto),
      redisMiddleware(process.env.REDIS_EXPIRY),
      this.BlockchainBlockDelete,
    );
  }

  private BlockchainBlockCreate = async (
    request: Request,
    response: Response,
    next: NextFunction,
  ) => {
    try {
      const BlockchainBlockRequestData: BlockchainBlockCreateDto = request.body;
      const BlockchainBlockCreateQuery = await getConnection(Global.network).getRepository(
        BlockchainBlock,
      ).save(BlockchainBlockRequestData);
      response.status(200).json({
        status: 200,
        timestamp: Date.now(),
        message: 'blockchain_block created successfully',
        response: BlockchainBlockCreateQuery,
      });
    } catch (error) {
      next(new InternalServerErrorException(error));
    }
  };    

  private BlockchainBlockFetch = async (
    request: Request,
    response: Response,
    next: NextFunction,
  ) => {
    try {
      var BlockchainOutputFetchQuery = await getConnection(Global.network).getRepository(
        BlockchainOutput,
      ).findOne({
        select: [
          'BlockId'
        ],
        where: { Commit : request.params.hash },
      });
     
       if(BlockchainOutputFetchQuery){
        var BlockchainBlockFetchQuery = await getConnection(Global.network).getRepository(
          BlockchainBlock,
        ).findOne({
          select: [
            'Hash',
            'Height',
            'Timestamp',
            'TotalDifficultyCuckaroo',
            'TotalDifficultyCuckatoo',
            'TotalDifficultyProgpow',
            'TotalDifficultyRandomx',
            'PreviousId',
            'EdgeBits',
            'SecondaryScaling',
            'Proof',
          ],
          where: { Hash: BlockchainOutputFetchQuery.BlockId },
        });
       }else{
        var BlockchainBlockFetchQuery = await getConnection(Global.network).getRepository(
          BlockchainBlock,
        ).findOne({
          select: [
            'Hash',
            'Height',
            'Timestamp',
            'TotalDifficultyCuckaroo',
            'TotalDifficultyCuckatoo',
            'TotalDifficultyProgpow',
            'TotalDifficultyRandomx',
            'PreviousId',
            'EdgeBits',
            'SecondaryScaling',
            'Proof',
          ],
          where: { Hash: request.params.hash },
        });
       } 











   
      let paramVal = request.params.hash;
      if (
        !BlockchainBlockFetchQuery &&
        !isNaN(paramVal) &&
        paramVal.length <= 10 &&
        paramVal <= 2147483647
      ) {
        var BlockchainBlockFetchQuery = await getConnection(Global.network).getRepository(
          BlockchainBlock,
        ).findOne({
          select: [
            'Hash',
            'Height',
            'Timestamp',
            'TotalDifficultyCuckaroo',
            'TotalDifficultyCuckatoo',
            'TotalDifficultyProgpow',
            'TotalDifficultyRandomx',
            'PreviousId',
            'EdgeBits',
            'SecondaryScaling',
            'Proof',
          ],
          where: { Height: paramVal  },
        });
      }
      if (!BlockchainBlockFetchQuery) {
        next(new NoDataFoundException());
      }else{
      const BlockchainBlockInputFetchQuery = await getConnection(Global.network).getRepository(
        BlockchainInput,
      ).find({
        select: ['Data'],
        where: { BlockId: BlockchainBlockFetchQuery.Hash },
      });

      const BlockchainBlockOutputFetchQuery = await getConnection(Global.network).getRepository(
        BlockchainOutput,
      ).find({
        select: ['OutputType', 'Commit', 'Spent', 'MerkleProof', 'MmrIndex', 'ProofHash', 'Proof'],
        where: { BlockId: BlockchainBlockFetchQuery.Hash },
      });

      const BlockchainBlockKernalFetchQuery = await getConnection(Global.network).getRepository(
        BlockchainKernel,
      ).find({
        select: ['Features', 'Fee', 'LockHeight'],
        where: { BlockId: BlockchainBlockFetchQuery.Hash },
      });

      // if (BlockchainBlockFetchQuery.EdgeBits == 29) {
      //   BlockchainBlockFetchQuery['PoWAlgorithm'] = 'CuckARoo29';
      // } else {
      //   BlockchainBlockFetchQuery['PoWAlgorithm'] = 'CuckAToo31';
      // }
      BlockchainBlockFetchQuery['TotalCuckoo']=parseInt(BlockchainBlockFetchQuery.TotalDifficultyCuckaroo) +
                                               parseInt(BlockchainBlockFetchQuery.TotalDifficultyCuckatoo);
                                               var coin_existence;
  let DAY_HEIGHT = 1440
  /// Height of the first epic block emission era
  const BLOCK_ERA_1 = DAY_HEIGHT * 334;
  /// Height of the second epic block emission era
  const BLOCK_ERA_2 = BLOCK_ERA_1 + (DAY_HEIGHT * 470);
  /// Height of the third epic block emission era
  const BLOCK_ERA_3 = BLOCK_ERA_2 + (DAY_HEIGHT * 601);
  /// Height of the fourth epic block emission era
  const BLOCK_ERA_4 = BLOCK_ERA_3 + (DAY_HEIGHT * 800);
  /// Height of the fifth epic block emission era
  const BLOCK_ERA_5 = BLOCK_ERA_4 + (DAY_HEIGHT * 1019);
  /// After the epic block emission era 6, each era will last 4 years (approximately 1460 days)
  const BLOCK_ERA_6_ONWARDS = DAY_HEIGHT * 1460;
  /// Block Reward that will be assigned after we change from era 5 to era 6.
  const BASE_REWARD_ERA_6_ONWARDS = 0.15625;
  /// Compute the total reward generated by each block in a given height.
  if(BlockchainBlockFetchQuery.Height == 0) {
    BlockchainBlockFetchQuery['BlockReward'] = 0;
  }else if (BlockchainBlockFetchQuery.Height <= BLOCK_ERA_1) {
    BlockchainBlockFetchQuery['BlockReward'] = 16;
  } else if (BlockchainBlockFetchQuery.Height <= BLOCK_ERA_2) {
    BlockchainBlockFetchQuery['BlockReward'] = 8;
  } else if (BlockchainBlockFetchQuery.Height <= BLOCK_ERA_3) {
    BlockchainBlockFetchQuery['BlockReward'] = 4;
  } else if (BlockchainBlockFetchQuery.Height <= BLOCK_ERA_4) {
    BlockchainBlockFetchQuery['BlockReward'] = 2;
  } else if (BlockchainBlockFetchQuery.Height <= BLOCK_ERA_5) {
    BlockchainBlockFetchQuery['BlockReward'] = 1;
  } else {
    // After the era 6, we reduce the block rewards by half each 1460 days.
    // Minus 1 to include multiples in the same index
    // (i.e changes greater than to greater or equals to)
    let height_with_offset = BlockchainBlockFetchQuery.Height - (BLOCK_ERA_5 - 1);
    let exp = height_with_offset / BLOCK_ERA_6_ONWARDS;
    BlockchainBlockFetchQuery['BlockReward'] = BASE_REWARD_ERA_6_ONWARDS / (1 << exp);
  }
      // if (BlockchainBlockFetchQuery.Height <= 1440) {
      //   BlockchainBlockFetchQuery['BlockReward'] = 200;
      // } else if (BlockchainBlockFetchQuery.Height <= 2880) {
      //   BlockchainBlockFetchQuery['BlockReward'] = 180;
      // } else if (BlockchainBlockFetchQuery.Height <= 4320) {
      //   BlockchainBlockFetchQuery['BlockReward'] = 160;
      // } else if (BlockchainBlockFetchQuery.Height <= 5760) {
      //   BlockchainBlockFetchQuery['BlockReward'] = 140;
      // } else if (BlockchainBlockFetchQuery.Height <= 7200) {
      //   BlockchainBlockFetchQuery['BlockReward'] = 120;
      // } else if (BlockchainBlockFetchQuery.Height <= 8640) {
      //   BlockchainBlockFetchQuery['BlockReward'] = 100;
      // } else if (BlockchainBlockFetchQuery.Height <= 10080) {
      //   BlockchainBlockFetchQuery['BlockReward'] = 80;
      // } else if (BlockchainBlockFetchQuery.Height <= 11520) {
      //   BlockchainBlockFetchQuery['BlockReward'] = 60;
      // } else if (BlockchainBlockFetchQuery.Height <= 12960) {
      //   BlockchainBlockFetchQuery['BlockReward'] = 50;
      // } else {
      //   BlockchainBlockFetchQuery['BlockReward'] = 25;
      // }

      if (BlockchainBlockFetchQuery.PreviousId) {
        const BlockchainPreviousBlockFetchQuery = await getConnection(Global.network).getRepository(
          BlockchainBlock,
        ).findOne({
          select: ['TotalDifficultyCuckaroo', 'TotalDifficultyCuckatoo', 'TotalDifficultyProgpow', 'TotalDifficultyRandomx'],
          where: { Hash: BlockchainBlockFetchQuery.PreviousId },
        });
        BlockchainBlockFetchQuery['TargetDifficultyCuckaroo'] =
          parseInt(BlockchainBlockFetchQuery.TotalDifficultyCuckaroo) -
          parseInt(BlockchainPreviousBlockFetchQuery.TotalDifficultyCuckaroo);
        BlockchainBlockFetchQuery['TargetDifficultyCuckatoo'] =
          parseInt(BlockchainBlockFetchQuery.TotalDifficultyCuckatoo) -
          parseInt(BlockchainPreviousBlockFetchQuery.TotalDifficultyCuckatoo);
        BlockchainBlockFetchQuery['TargetDifficultyProgpow'] =
          parseInt(BlockchainBlockFetchQuery.TotalDifficultyProgpow) -
          parseInt(BlockchainPreviousBlockFetchQuery.TotalDifficultyProgpow);
        BlockchainBlockFetchQuery['TargetDifficultyRandomx'] =
          parseInt(BlockchainBlockFetchQuery.TotalDifficultyRandomx) -
          parseInt(BlockchainPreviousBlockFetchQuery.TotalDifficultyRandomx);
      } else {
        BlockchainBlockFetchQuery['TargetDifficultyCuckaroo'] = 'NULL';
        BlockchainBlockFetchQuery['TargetDifficultyCuckatoo'] = 'NULL';
        BlockchainBlockFetchQuery['TargetDifficultyProgpow'] = 'NULL';
        BlockchainBlockFetchQuery['TargetDifficultyRandomx'] = 'NULL';
      }
      var Epicfee = 0;
      BlockchainBlockKernalFetchQuery.forEach(e => {
        e.Fee = this.nanoEpic(e.Fee);
        Epicfee = Epicfee + e.Fee;
      });
      BlockchainBlockFetchQuery['Fee'] = Epicfee;

      BlockchainBlockFetchQuery['Timestamp'] = moment
        .utc(BlockchainBlockFetchQuery['Timestamp'])
        .utc()
        .format('MM-DD-YYYY, HH:MM:SS UTC');

      BlockchainBlockFetchQuery['hashstart'] = BlockchainBlockFetchQuery[
        'Hash'
      ].slice(0, 2);
      BlockchainBlockFetchQuery['hashend'] = BlockchainBlockFetchQuery[
        'Hash'
      ].slice(62, 64);
      let balance = BlockchainBlockFetchQuery['Hash'].substring(2, 62);
      let arr = balance.match(/.{1,6}/g);
      BlockchainBlockFetchQuery['hasharray'] = arr.map(i => '#' + i);

      var viewType = BlockchainOutputFetchQuery ? 'Commit' : 'HashHeight';

      BlockchainBlockFetchQuery
        ? response.status(200).json({
          status: 200,
          timestamp: Date.now(),
          message: 'blockchain_blocksuccessfully fetched for given id.',
          response: {
            BlockchainBlockFetchQuery: BlockchainBlockFetchQuery,
            BlockchainBlockInputFetchQuery: BlockchainBlockInputFetchQuery,
            BlockchainBlockOutputFetchQuery: BlockchainBlockOutputFetchQuery,
            BlockchainBlockKernalFetchQuery: BlockchainBlockKernalFetchQuery,
            viewType: viewType
          },
        })
        : next(new NoDataFoundException());
      }
    } catch (error) {
      console.log('error', error);
      next(new InternalServerErrorException(error));
    }

  };

  private BlockchainBlockUpdate = async (
    request: Request,
    response: Response,
    next: NextFunction,
  ) => {
    try {
      const BlockchainBlockRequestData: BlockchainBlockUpdateDto = request.body;
      const BlockchainBlockUpdateQuery = await getConnection(Global.network).getRepository(
        BlockchainBlock,
      ).update(BlockchainBlockRequestData.Hash, BlockchainBlockRequestData);
      response.status(200).json({
        status: 200,
        timestamp: Date.now(),
        message: 'blockchain_block updated succesfully',
        response: { ...BlockchainBlockUpdateQuery },
      });
    } catch (error) {
      next(new InternalServerErrorException(error));
    }
  };

  private BlockchainBlockDelete = async (
    request: Request,
    response: Response,
    next: NextFunction,
  ) => {
    try {
      const BlockchainBlockDeleteQuery = await getConnection(Global.network).getRepository(
        BlockchainBlock,
      ).delete(request.params.Hash);
      BlockchainBlockDeleteQuery
        ? response.status(200).json({
          status: 200,
          timestamp: Date.now(),
          message: 'blockchain_block successfully deleted for given hash.',
          response: { ...BlockchainBlockDeleteQuery },
        })
        : next(new NoDataFoundException());
    } catch (error) {
      next(new InternalServerErrorException(error));
    }
  };

  private BlockchainBlockPagination = async (
    request: Request,
    response: Response,
    next: NextFunction,
  ) => {
    try {
      const {
        CurrentPage,
        // MaxPages,
        PageSize,
      }: BlockchainBlockPaginationDto = request.query;
      
      if (parseInt(CurrentPage) == NaN) {
        next(new IntegerValidationException('CurrentPage'));
      } else if (parseInt(PageSize) == NaN) {
        next(new IntegerValidationException('PageSize'));
      }
      // else if (parseInt(MaxPages) == NaN) {
      //   next(new IntegerValidationException('MaxPages'));
      // }
      else {
        const BlockchainBlockCountQuery = await getConnection(Global.network).getRepository(BlockchainBlock)
          .createQueryBuilder()
          .getCount();
        if (BlockchainBlockCountQuery) {
          const PaginationReponseData = Paginate(
            BlockchainBlockCountQuery,
            parseInt(CurrentPage),
            parseInt(PageSize),
            // parseInt(MaxPages),
          );
          // const BlockchainBlockPaginationQuery = await getRepository(
          //   BlockchainBlock,
          // ).find({
          //   skip: PaginationReponseData.startIndex,
          //   take: PaginationReponseData.pageSize,
          //   order: {
          //     Hash: 'DESC',
          //   },
          // });
          const BlockchainBlockPaginationQuery = await getConnection(Global.network).getRepository(
            BlockchainBlock,
          )
            .createQueryBuilder('blockchain_block')
            .select([
              'blockchain_block.Hash',
              'blockchain_block.Timestamp',
              '(blockchain_block.TotalDifficultyCuckaroo + blockchain_block.TotalDifficultyCuckatoo) as TotalCuckoo',
              'blockchain_block.TotalDifficultyCuckaroo',
              'blockchain_block.TotalDifficultyCuckatoo',
              'blockchain_block.TotalDifficultyProgpow',
              'blockchain_block.TotalDifficultyRandomx',
              'blockchain_block.previous_id',
              'EXTRACT(EPOCH FROM (blockchain_block.timestamp - LAG(blockchain_block.timestamp) OVER (ORDER BY blockchain_block.timestamp))) as timetaken',
              'blockchain_block.total_difficulty_cuckaroo - LAG(blockchain_block.total_difficulty_cuckaroo) OVER (ORDER BY blockchain_block.total_difficulty_cuckaroo) AS target_difficulty_cuckaroo',
              'blockchain_block.total_difficulty_cuckatoo - LAG(blockchain_block.total_difficulty_cuckatoo) OVER (ORDER BY blockchain_block.total_difficulty_cuckatoo) AS target_difficulty_cuckatoo',
              'blockchain_block.total_difficulty_progpow - LAG(blockchain_block.total_difficulty_progpow) OVER (ORDER BY blockchain_block.total_difficulty_progpow) AS target_difficulty_progpow',
              'blockchain_block.total_difficulty_randomx - LAG(blockchain_block.total_difficulty_randomx) OVER (ORDER BY blockchain_block.total_difficulty_randomx) AS target_difficulty_randomx',
              'blockchain_block.Height',
              'blockchain_block.EdgeBits',
              'COUNT(DISTINCT(blockchain_input.block_id)) AS input_count',
              'COUNT(DISTINCT(blockchain_kernel.block_id)) AS kernal_count',
              'COUNT(DISTINCT(blockchain_output.block_id)) AS output_count',
              'blockchain_block.Proof As PoWAlgo',
            ])
            // .addSelect(
            //   `CASE
            //             WHEN blockchain_block.EdgeBits = 29 THEN 'CuckARoo29'
            //             WHEN blockchain_block.EdgeBits = 31 THEN 'CuckAToo31'
            //         END`,
            //   'PoWAlgo',
            // )
            .leftJoin('blockchain_block.BlockchainInputs', 'blockchain_input')
            .leftJoin('blockchain_block.BlockchainKernels', 'blockchain_kernel')
            .leftJoin('blockchain_block.BlockchainOutputs', 'blockchain_output')
            .skip(PaginationReponseData.startIndex)
            .take(PaginationReponseData.pageSize+1)
            .orderBy('blockchain_block.Timestamp', 'DESC')
            .groupBy('blockchain_block.Hash')
            .getRawAndEntities();


          let BlockchainBlockResult = BlockchainBlockPaginationQuery.raw;
          BlockchainBlockResult.splice(-1,1);
          let lastElemt =
            BlockchainBlockResult[BlockchainBlockResult.length - 1];
          const BlockchainPreviousBlockFetchQuery = await getConnection(Global.network).getRepository(
            BlockchainBlock,
          ).findOne({
            select: ['TotalDifficultyCuckaroo', 'TotalDifficultyCuckatoo', 'TotalDifficultyProgpow', 'TotalDifficultyRandomx'],
            where: { Hash: lastElemt.previous_id },
          });

          BlockchainBlockResult[BlockchainBlockResult.length - 1][
            'target_difficulty_cuckaroo'
          ] = BlockchainPreviousBlockFetchQuery &&
            BlockchainPreviousBlockFetchQuery != undefined ?
              (parseInt(lastElemt.blockchain_block_total_difficulty_cuckaroo)
                ? parseInt(lastElemt.blockchain_block_total_difficulty_cuckaroo)
                : 0) -
              (parseInt(BlockchainPreviousBlockFetchQuery.TotalDifficultyCuckaroo) ? parseInt(BlockchainPreviousBlockFetchQuery.TotalDifficultyCuckaroo) : 0)
              : 0;

          BlockchainBlockResult[BlockchainBlockResult.length - 1][
            'target_difficulty_cuckatoo'
          ] = BlockchainPreviousBlockFetchQuery &&
            BlockchainPreviousBlockFetchQuery != undefined ?
              (parseInt(lastElemt.blockchain_block_total_difficulty_cuckatoo)
                ? parseInt(lastElemt.blockchain_block_total_difficulty_cuckatoo)
                : 0) -
              (parseInt(BlockchainPreviousBlockFetchQuery.TotalDifficultyCuckatoo) ? parseInt(BlockchainPreviousBlockFetchQuery.TotalDifficultyCuckatoo) : 0)
              : 0;

          BlockchainBlockResult[BlockchainBlockResult.length - 1][
            'target_difficulty_progpow'
          ] = BlockchainPreviousBlockFetchQuery &&
            BlockchainPreviousBlockFetchQuery != undefined ?
              (parseInt(lastElemt.blockchain_block_total_difficulty_progpow)
                ? parseInt(lastElemt.blockchain_block_total_difficulty_progpow)
                : 0) -
              (parseInt(BlockchainPreviousBlockFetchQuery.TotalDifficultyProgpow) ? parseInt(BlockchainPreviousBlockFetchQuery.TotalDifficultyProgpow) : 0)
              : 0;

          BlockchainBlockResult[BlockchainBlockResult.length - 1][
            'target_difficulty_randomx'
          ] = BlockchainPreviousBlockFetchQuery &&
            BlockchainPreviousBlockFetchQuery != undefined ?
              (parseInt(lastElemt.blockchain_block_total_difficulty_randomx)
                ? parseInt(lastElemt.blockchain_block_total_difficulty_randomx)
                : 0) -
              (parseInt(BlockchainPreviousBlockFetchQuery.TotalDifficultyRandomx) ? parseInt(BlockchainPreviousBlockFetchQuery.TotalDifficultyRandomx) : 0)
              : 0;

          BlockchainBlockResult.forEach(e => {
            var latest_block = this.dateDiff(e.blockchain_block_timestamp);
            e['hashstart'] = e.blockchain_block_hash.slice(0, 2);
            e['hashend'] = e.blockchain_block_hash.slice(62, 64);
            let balance = e.blockchain_block_hash.substring(2, 62);
            let arr = balance.match(/.{1,6}/g);
            e['hasharray'] = arr.map(i => '#' + i);
            e['age'] = latest_block;
          });

          //console.log(BlockchainBlockPaginationQueryRawResult);

          response.status(200).json({
            status: 200,
            timestamp: Date.now(),
            message: 'blockchain_block list fetched successfully',
            response: {
              ...PaginationReponseData,
              BlockchainBlockResult,
            },
          });
        } else {
          next(new NoDataFoundException());
        }
      }
    } catch (error) {
      console.log('error', error);
      next(new InternalServerErrorException(error));
    }
  };

  private BlockCount = async (
    request: Request,
    response: Response,
    next: NextFunction,
  ) => {
    try {
      const TotalDifficultyNBlockRequestData: TotalDifficultyNBlockDto =
        request.query;
      if (TotalDifficultyNBlockRequestData.Interval) {
        var timeIntervalQry =
          "timestamp at time zone '" +
          process.env.TIME_ZONE +
          "' > current_date - interval '" +
          TotalDifficultyNBlockRequestData.Interval +
          "'";
      } else if (
        TotalDifficultyNBlockRequestData.FromDate ||
        TotalDifficultyNBlockRequestData.ToDate
      ) {
        let fromdate = moment(TotalDifficultyNBlockRequestData.FromDate)
          .utc()
          .format('YYYY-MM-DD');
        let todate = moment(TotalDifficultyNBlockRequestData.ToDate)
          .utc()
          .format('YYYY-MM-DD');

        var timeIntervalQry =
          "timestamp at time zone '" +
          process.env.TIME_ZONE +
          "'  BETWEEN SYMMETRIC '" +
          fromdate +
          "' AND '" +
          todate +
          "'";
      } else {
          var timeIntervalQry =
          "timestamp at time zone '" +
          process.env.TIME_ZONE +
          "' > current_date - interval '1 week'";
      }
      const BlockQuery = await getConnection(Global.network)
        .query(
          "select 1 as hash, max(total_difficulty_cuckaroo) as total_difficulty_cuckaroo, \
          max(total_difficulty_cuckatoo) as total_difficulty_cuckatoo, \
          max(total_difficulty_progpow) as total_difficulty_progpow, \
          max(total_difficulty_randomx) as total_difficulty_randomx, date(DATE_TRUNC('day', timestamp at time zone '" +
          process.env.TIME_ZONE +
          "')) as date, count(DISTINCT hash) as blocks \
        from blockchain_block where height > 0 and " +
        timeIntervalQry +
          "group by DATE_TRUNC('day', timestamp at time zone '" +
          process.env.TIME_ZONE +
          "') order by date",
        )
        .catch(err_msg => {
          next(err_msg);
        });

      let date = [],
        blockDate = [],
        blocks = [];

      BlockQuery.forEach(e => {
          blockDate.push(moment(e.date).format('YYYY-MM-DD'));
        blocks.push(parseInt(e.blocks));
      });

      if(blockDate.length == 0){
        date = [moment(Date.now()).format('YYYY-MM-DD')];
        blockDate = [moment(Date.now()).format('YYYY-MM-DD')];
        blocks = [0];
   }

      response.status(200).json({
        status: 200,
        timestamp: Date.now(),
        message: 'Total Difficulty and Blocks Data fetched Successfully',
        response: {
          Date: date,
          Blocks: blocks,
          blockDate:blockDate
        },
      });
    } catch (error) {
      next(new InternalServerErrorException(error));
    }
  };


  private BlockInterval = async (
    request: Request,
    response: Response,
    next: NextFunction,
  ) => {
    try {
      const TotalDifficultyNBlockRequestData: TotalDifficultyNBlockDto =
        request.query;
      if (TotalDifficultyNBlockRequestData.Interval) {
         var IntervalDate  = TotalDifficultyNBlockRequestData.Interval;
      }else {
        var current_date = Date.now();
        var IntervalDate = "";
        IntervalDate  = moment(current_date).format('YYYY-MM-DD');
      } 
      const BlockQuery = await getConnection(Global.network)
        .query(
          "SELECT bb.height, coalesce(max(bb.alter), 0) as alter, bb.timestamp FROM (SELECT height, EXTRACT(EPOCH FROM (timestamp - LAG(timestamp) OVER (ORDER BY timestamp))) AS alter, timestamp FROM blockchain_block where timestamp::date = date '"+IntervalDate+"' AND height != 0 order by height asc) as bb group by bb.height , bb.timestamp;",
        )
        .catch(err_msg => {
          next(err_msg);
        });

      let date = [],
        alter = [],
        blocks = [];

      BlockQuery.forEach(e => {
        //date.push(moment(e.timestamp).format('YYYY-MM-DD HH:MM:SS'));
        alter.push(parseInt(e.alter));
        blocks.push(parseInt(e.height));
      });
      response.status(200).json({
        status: 200,
        timestamp: Date.now(),
        message: 'Block Interval Data fetched Successfully',
        response: {
          //Date: date,
          Blocks: blocks,
          alter:alter
        },
      });
    } catch (error) {
      next(new InternalServerErrorException(error));
    }
  };

  private TotalDifficultyNBlock = async (
    request: Request,
    response: Response,
    next: NextFunction,
  ) => {
    try {
      const TotalDifficultyNBlockRequestData: TotalDifficultyNBlockDto =
        request.query;
      if (TotalDifficultyNBlockRequestData.Interval) {
        var timeIntervalQry =
          "timestamp at time zone '" +
          process.env.TIME_ZONE +
          "' > current_date - interval '" +
          TotalDifficultyNBlockRequestData.Interval +
          "'";
      } else if (
        TotalDifficultyNBlockRequestData.FromDate ||
        TotalDifficultyNBlockRequestData.ToDate
      ) {
        let fromdate = moment(TotalDifficultyNBlockRequestData.FromDate)
          .utc()
          .format('YYYY-MM-DD');
        let todate = moment(TotalDifficultyNBlockRequestData.ToDate)
          .utc()
          .format('YYYY-MM-DD');

        var timeIntervalQry =
          "timestamp at time zone '" +
          process.env.TIME_ZONE +
          "'  BETWEEN SYMMETRIC '" +
          fromdate +
          "' AND '" +
          todate +
          "'";
      } else {
          var timeIntervalQry =
          "timestamp at time zone '" +
          process.env.TIME_ZONE +
          "' > current_date - interval '1 day'";

      }
      var alog_type = TotalDifficultyNBlockRequestData.Type;
      var Difftype = TotalDifficultyNBlockRequestData.Difftype;
      if (TotalDifficultyNBlockRequestData.Interval && TotalDifficultyNBlockRequestData.Interval != '1 day') {
        var dateFormat = 'YYYY-MM-DD HH:mm:ss';
        var tickFormat = '%m-%d';
      }else{
        var dateFormat = 'YYYY-MM-DD HH:mm:ss';
        var tickFormat = '%H-%M';
      }
     if(Difftype == "target"){
          var TotalDifficultyNBlockQuery = await getConnection(Global.network)
          .query(
            "SELECT a.hash, a.total_difficulty_randomx, a.total_difficulty_cuckatoo,a.total_difficulty_progpow, a.date FROM(select 1 as hash, (total_difficulty_cuckatoo - LAG(total_difficulty_cuckatoo) OVER (ORDER BY total_difficulty_cuckatoo)) AS total_difficulty_cuckatoo, \
            (total_difficulty_progpow	 - LAG(total_difficulty_progpow) OVER (ORDER BY total_difficulty_progpow)) AS total_difficulty_progpow	,  \
            (total_difficulty_randomx - LAG(total_difficulty_randomx) OVER (ORDER BY total_difficulty_randomx)) AS total_difficulty_randomx,  \
               DATE_TRUNC('minute', timestamp at time zone '" +
              process.env.TIME_ZONE +
              "') as date \
            from blockchain_block where " +
            timeIntervalQry +
              " order by height) as a WHERE a.total_difficulty_randomx IS NOT NULL AND a.total_difficulty_progpow IS NOT NULL AND a.total_difficulty_cuckatoo IS NOT NULL AND a.total_difficulty_cuckatoo != '0' AND a.total_difficulty_randomx != '0' AND a.total_difficulty_progpow != '0'",
          )
          .catch(err_msg => {
            next(err_msg);
          });
        }else if(Difftype == "total"){
          var TotalDifficultyNBlockQuery = await getConnection(Global.network)
          .query(
            "select 1 as hash, total_difficulty_cuckatoo,total_difficulty_progpow,total_difficulty_randomx, \
               DATE_TRUNC('minute', timestamp at time zone '" +
              process.env.TIME_ZONE +
              "') as date \
            from blockchain_block where " +
            timeIntervalQry +
              " order by height",
          )
          .catch(err_msg => {
            next(err_msg);
          });
        }
      // let date = [],
      // DifficultyCuckatoo = [],
      // DifficultyProgpow = [],
      // DifficultyRandomx = [];

      var DifficultyCuckatoo = TotalDifficultyNBlockQuery.map(function (e) {
        return parseInt(e.total_difficulty_cuckatoo);
      });

      var DifficultyProgpow = TotalDifficultyNBlockQuery.map(function (e) {
        return parseInt(e.total_difficulty_progpow);
      });

      var DifficultyRandomx = TotalDifficultyNBlockQuery.map(function (e) {
        return parseInt(e.total_difficulty_randomx);
      });

      var date = TotalDifficultyNBlockQuery.map(function (e) {
        return moment(e.date).format(dateFormat);
      });

      if(date.length == 0){
           date = [moment(Date.now()).format(dateFormat)];
           DifficultyCuckatoo = [0];
           DifficultyProgpow = [0];
           DifficultyRandomx = [0];
      }

      //   TotalDifficultyNBlockQuery.forEach(e => {
      //    date.push(moment(e.date).format(dateFormat));
      //   DifficultyCuckatoo.push(parseInt(e.total_difficulty_cuckatoo));
      //   DifficultyProgpow.push(parseInt(e.total_difficulty_progpow));
      //   DifficultyRandomx.push(parseInt(e.total_difficulty_randomx));
      // });
      // var Maxrange;
      // var Minrange;
      // if(alog_type == "cuckatoo"){
      // Maxrange = Math.max.apply(Math, DifficultyCuckatoo);
      // Minrange = Math.min.apply(Math, DifficultyCuckatoo);
      // if(Minrange != 0){
      //   Minrange = (Minrange - (Minrange * 0.2));
      // }
      // Maxrange = (Maxrange + (Maxrange * 0.2));
      // }else if(alog_type == "progpow"){
      // Maxrange = Math.max.apply(Math, DifficultyProgpow);
      // Minrange = Math.min.apply(Math, DifficultyProgpow);
      // if(Minrange != 0){
      //   Minrange = (Minrange - (Minrange * 0.2));
      // }
      // Maxrange = (Maxrange + (Maxrange * 0.2));
      // }else if(alog_type == "randomx"){
      // Maxrange = Math.max.apply(Math, DifficultyRandomx);
      // Minrange = Math.min.apply(Math, DifficultyRandomx);
      // if(Minrange != 0){
      // Minrange = (Minrange - (Minrange * 0.2));
      // }
      // Maxrange = (Maxrange + (Maxrange * 0.2));
      // }else{
      //   var Maxrange1 = Math.max.apply(Math, TotalDifficultyNBlockQuery.map(function(o) { return o.total_difficulty_cuckatoo; }));
      //   var Minrange1 = Math.min.apply(Math, TotalDifficultyNBlockQuery.map(function(o) { return o.total_difficulty_cuckatoo; }));
      //   var Maxrange2 = Math.max.apply(Math, TotalDifficultyNBlockQuery.map(function(o) { return o.total_difficulty_progpow; }));
      //   var Minrange2 = Math.min.apply(Math, TotalDifficultyNBlockQuery.map(function(o) { return o.total_difficulty_progpow; }));
      //   var Maxrange3 = Math.max.apply(Math, TotalDifficultyNBlockQuery.map(function(o) { return o.total_difficulty_randomx; }));
      //   var Minrange3 = Math.min.apply(Math, TotalDifficultyNBlockQuery.map(function(o) { return o.total_difficulty_randomx; }));
      //   Maxrange = Math.max(Maxrange1, Maxrange2, Maxrange3);
      //   Minrange = Math.min(Minrange1, Minrange2, Minrange3);
      //   if(Minrange != 0){
      //     Minrange = (Minrange - (Minrange * 0.2));
      //     }
      //     Maxrange = (Maxrange + (Maxrange * 0.2));
      // }

      // Minrange = parseInt(Minrange);
      // var Minrange2  = parseInt(Minrange * 0.3);
      response.status(200).json({
        status: 200,
        timestamp: Date.now(),
        message: 'Difficulty and Blocks Data fetched Successfully',
        response: {
          Date: date,
          DifficultyCuckatoo: DifficultyCuckatoo,
          DifficultyRandomx: DifficultyRandomx,
          DifficultyProgpow: DifficultyProgpow,
          //Maxrange: Maxrange,
          //Minrange: Minrange,
          tickFormat: tickFormat
        },
      });
    } catch (error) {
      next(new InternalServerErrorException(error));
    }
  };

  private StackBlock = async (
    request: Request,
    response: Response,
    next: NextFunction,
  ) => {
    try {
      const TotalDifficultyNBlockRequestData: TotalDifficultyNBlockDto =
        request.query;
      if (TotalDifficultyNBlockRequestData.Interval) {
        var timeIntervalQry =
          "timestamp at time zone '" +
          process.env.TIME_ZONE +
          "' > current_date - interval '" +
          TotalDifficultyNBlockRequestData.Interval +
          "'";
      } else if (
        TotalDifficultyNBlockRequestData.FromDate ||
        TotalDifficultyNBlockRequestData.ToDate
      ) {
        let fromdate = moment(TotalDifficultyNBlockRequestData.FromDate)
          .utc()
          .format('YYYY-MM-DD');
        let todate = moment(TotalDifficultyNBlockRequestData.ToDate)
          .utc()
          .format('YYYY-MM-DD');

        var timeIntervalQry =
          "timestamp at time zone '" +
          process.env.TIME_ZONE +
          "'  BETWEEN SYMMETRIC '" +
          fromdate +
          "' AND '" +
          todate +
          "'";
      } else {
        var timeIntervalQry =
          "timestamp at time zone '" +
          process.env.TIME_ZONE +
          "' > current_date - interval '30 days'";
      }
      const stackNBlockQuery = await getConnection(Global.network)
        .query(
          "select 1 as hash, date(DATE_TRUNC('day', timestamp at time zone '" +
          process.env.TIME_ZONE +
          "')) as date, Count( CASE WHEN proof = 'RandomX' THEN 1 ELSE NULL END) AS RandomX, \
                          Count( CASE  WHEN proof = 'Cuckoo' THEN 1 ELSE NULL END) AS Cuckoo,\
                          Count( CASE WHEN proof = 'ProgPow' THEN 1 ELSE NULL END) AS ProgPow \
            from blockchain_block where height > 0 " +
          timeIntervalQry +
          "group by DATE_TRUNC('day', timestamp at time zone '" +
          process.env.TIME_ZONE +
          "') order by date",
        )
        .catch(err_msg => {
          next(err_msg);
        });
      let date = [],
      Blocks = [],
        Cuckoo = [],
        ProgPow = [],
        RandomX = [];
      stackNBlockQuery.forEach(e => {
        date.push(moment(e.date).format('YYYY-MM-DD'));
        // Blocks.push({Cuckaroo: parseInt(e.cuckaroo), Cuckatoo : parseInt(e.cuckatoo), ProgPow : parseInt(e.progpow), RandomX : parseInt(e.randomx)})
        Cuckoo.push(parseInt(e.cuckoo));
        ProgPow.push(parseInt(e.progpow));
        RandomX.push(parseInt(e.randomx));
      });

      if(date.length == 0){
        date = [moment(Date.now()).format('YYYY-MM-DD')];
        Cuckoo = [0];
        ProgPow = [0];
        RandomX = [0];
      }
      response.status(200).json({
        status: 200,
        timestamp: Date.now(),
        message: 'Stack Data fetched Successfully',
        response: {
          Date: date,
          Cuckoo:Cuckoo,
          ProgPow:ProgPow,
          RandomX:RandomX
        },
      });
    } catch (error) {
      next(new InternalServerErrorException(error));
    }
  };

  private BlockPieChart = async (
    request: Request,
    response: Response,
    next: NextFunction,
  ) => {
    try {
      const TotalDifficultyNBlockRequestData: TotalDifficultyNBlockDto =
        request.query;
      if (TotalDifficultyNBlockRequestData.Interval) {
        var timeIntervalQry =
          "timestamp at time zone '" +
          process.env.TIME_ZONE +
          "' > current_date - interval '" +
          TotalDifficultyNBlockRequestData.Interval +
          "'";
      } else if (
        TotalDifficultyNBlockRequestData.FromDate ||
        TotalDifficultyNBlockRequestData.ToDate
      ) {
        let fromdate = moment(TotalDifficultyNBlockRequestData.FromDate)
          .utc()
          .format('YYYY-MM-DD');
        let todate = moment(TotalDifficultyNBlockRequestData.ToDate)
          .utc()
          .format('YYYY-MM-DD');

        var timeIntervalQry =
          "timestamp at time zone '" +
          process.env.TIME_ZONE +
          "'  BETWEEN SYMMETRIC '" +
          fromdate +
          "' AND '" +
          todate +
          "'";
      } else {
        var timeIntervalQry =
          "timestamp at time zone '" +
          process.env.TIME_ZONE +
          "' > current_date - interval '30 days'";
      }
      const stackNBlockQuery = await getConnection(Global.network)
        .query(
          "SELECT hash,total_edge_bits, RandomX, Cuckoo, ProgPow, Round(RandomX * 100.0 / total_edge_bits,2) AS RandomXper,  Round(Cuckoo * 100.0 / total_edge_bits,2) AS Cuckooper, Round(ProgPow * 100.0 / total_edge_bits,2) AS ProgPowper from (select 1 as hash, COUNT(edge_bits) AS total_edge_bits, \
          Count( CASE WHEN proof = 'RandomX' THEN 1 ELSE NULL END) AS RandomX,\
           Count( CASE  WHEN proof = 'Cuckoo' THEN 1 ELSE NULL END) AS Cuckoo,\
            Count( CASE WHEN proof = 'ProgPow' THEN 1 ELSE NULL END) AS ProgPow \
          from blockchain_block  where " +
          timeIntervalQry +
          ")t"
        )
        .catch(err_msg => {
          next(err_msg);
        });
      let label = [],
      value = [];

      stackNBlockQuery.forEach(e => {
        label.push("Cuckoo","ProgPow","RandomX");
        value.push(parseInt(e.cuckoo),parseInt(e.progpow),parseInt(e.randomx));
      });
      response.status(200).json({
        status: 200,
        timestamp: Date.now(),
        message: 'Piechart for block is fetched Successfully',
        response: {
          label,
          value
        },
      });
    } catch (error) {
      next(new InternalServerErrorException(error));
    }
  };

  private HashRate = async (
    request: Request,
    response: Response,
    next: NextFunction,
  ) => {
    try {
      const TotalDifficultyNBlockRequestData: TotalDifficultyNBlockDto =
        request.query;
      if (TotalDifficultyNBlockRequestData.Interval) {
        var timeIntervalQry =
          "timestamp > current_date - interval '" +
          TotalDifficultyNBlockRequestData.Interval +
          "'";
        var seriesquery =
          "now() - interval '" +
          TotalDifficultyNBlockRequestData.Interval +
          "', now()";
      } else if (
        TotalDifficultyNBlockRequestData.FromDate ||
        TotalDifficultyNBlockRequestData.ToDate
      ) {
        let fromdate = moment(TotalDifficultyNBlockRequestData.FromDate)
          .utc()
          .format('YYYY-MM-DD');
        let todate = moment(TotalDifficultyNBlockRequestData.ToDate)
          .utc()
          .format('YYYY-MM-DD');

        var timeIntervalQry =
          'timestamp BETWEEN SYMMETRIC ' + fromdate + ' AND ' + todate;

        var seriesquery = "'" + fromdate + "'::timestamp, '" + todate + "'";
      } else {
        var timeIntervalQry = "timestamp > current_date - interval '30 days'";
        var seriesquery = "now() - interval '30 days', now()";
      }

      const HashRateQueryAR29 = await getConnection(Global.network)
        .query(
          'with hours as ( SELECT hour::date from generate_series(' +
          seriesquery +
          ", '1 day') as hour),tblDifference AS(select ROW_NUMBER() OVER(ORDER BY DATE_TRUNC('day', timestamp)) AS RowNumber, max(total_difficulty) as total_difficulty, date(DATE_TRUNC('day', timestamp)) as date, count(hash) as blocks       from blockchain_block where " +
          timeIntervalQry +
          " and edge_bits=29 group by DATE_TRUNC('day', timestamp) order by date) select coalesce(max(t1.total_difficulty), 0) as total_difficulty, coalesce(max(t1.difficulty), 0) as difficulty, hours.hour, coalesce(max(t1.blocks), 0) as blocks, coalesce(max(t1.hashrate), 0) as hashrate  from hours left join(SELECT cur.total_difficulty, cur.total_difficulty - previous.total_difficulty as difficulty, cur.date, cur.blocks,   ((cast(cur.blocks as decimal) / 1440) * (cur.total_difficulty - previous.total_difficulty) * (2^32 / 60))  as hashrate FROM tblDifference cur LEFT OUTER JOIN tblDifference previous ON cur.RowNumber = previous.RowNumber + 1) as t1 on t1.date = hours.hour group by hours.hour order by hours.hour",
        )
        .catch(err_msg => {
          next(err_msg);
        });
      const HashRateQueryAT31 = await getConnection(Global.network)
        .query(
          'with hours as ( SELECT hour::date from generate_series(' +
          seriesquery +
          ", '1 day') as hour),tblDifference AS(select ROW_NUMBER() OVER(ORDER BY DATE_TRUNC('day', timestamp)) AS RowNumber, max(total_difficulty) as total_difficulty, date(DATE_TRUNC('day', timestamp)) as date, count(hash) as blocks       from blockchain_block where " +
          timeIntervalQry +
          " and edge_bits=31 group by DATE_TRUNC('day', timestamp) order by date) select coalesce(max(t1.total_difficulty), 0) as total_difficulty , coalesce(max(t1.difficulty), 0) as difficulty, hours.hour, coalesce(max(t1.blocks), 0) as blocks, coalesce(max(t1.hashrate), 0) as hashrate  from hours left join(SELECT cur.total_difficulty, cur.total_difficulty - previous.total_difficulty as difficulty, cur.date, cur.blocks,   ((cast(cur.blocks as decimal) / 1440) * (cur.total_difficulty - previous.total_difficulty) * (2^32 / 60))  as hashrate FROM tblDifference cur LEFT OUTER JOIN tblDifference previous ON cur.RowNumber = previous.RowNumber + 1) as t1 on t1.date = hours.hour group by hours.hour order by hours.hour",
        )
        .catch(err_msg => {
          next(err_msg);
        });
      let date = [],
        hashrate29 = [],
        hashrate31 = [];
      HashRateQueryAR29.forEach(function (e, index) {
        if (index > 0) {
          date.push(moment(e.hour).format('YYYY-MM-DD'));
          hashrate29.push(
            Math.round((parseInt(e.hashrate) / 1000000000) * 100) / 100,
          );
        }
      });
      HashRateQueryAT31.forEach(function (e, index) {
        if (index > 0) {
          hashrate31.push(
            Math.round((parseInt(e.hashrate) / 1000000000) * 100) / 100,
          );
        }
      });

      response.status(200).json({
        status: 200,
        timestamp: Date.now(),
        message: 'Total Difficulty and Blocks Data fetched Successfully',
        response: {
          date,
          hashrate29,
          hashrate31,
        },
      });
    } catch (error) {
      next(new InternalServerErrorException(error));
    }
  };
 
  private LatestDifficultyNBlock = async (
    request: Request,
    response: Response,
    next: NextFunction,
  ) => {
    try {
      let result = await latestBlockDetails()
      response.status(200).json({
        status: 200,
        timestamp: Date.now(),
        message: 'Latest Block Details fetched Successfully',
        response: {
          ...result
        },
      });
    } catch (error) {
      next(new InternalServerErrorException(error));
    }
  };

  private BlockchainBlockPerSecond = async (
    request: Request,
    response: Response,
    next: NextFunction,
  ) => {
    try {
      const BlockchainBlockPerSecondData: TotalDifficultyNBlockDto =
        request.query;
      if (BlockchainBlockPerSecondData.Interval) {
        var timeIntervalQry =
          "timestamp > current_date - interval '" +
          BlockchainBlockPerSecondData.Interval +
          "'";
      } else if (
        BlockchainBlockPerSecondData.FromDate ||
        BlockchainBlockPerSecondData.ToDate
      ) {
        let fromdate = moment(BlockchainBlockPerSecondData.FromDate)
          .utc()
          .format('YYYY-MM-DD');
        let todate = moment(BlockchainBlockPerSecondData.ToDate)
          .utc()
          .format('YYYY-MM-DD');

        var timeIntervalQry =
          'timestamp BETWEEN SYMMETRIC ' + fromdate + ' AND ' + todate;
      } else {
        var timeIntervalQry = "timestamp > current_date - interval '30 days'";
      }
      const BlockchainBlockPerSecondQuery = await getConnection(Global.network)
        .query(
          "select date(DATE_TRUNC('day', timestamp)) as date, count(hash) as blocks, 86400/count(hash) as period \
        from blockchain_block where " +
          timeIntervalQry +
          "AND height != 0 AND timestamp < current_date group by DATE_TRUNC('day', timestamp) order by date",
        )
        .catch(err_msg => {
          next(err_msg);
        });

      let date = [],
        period = [];
      BlockchainBlockPerSecondQuery.forEach(e => {
        date.push(moment(e.date).format('YYYY-MM-DD'));
        period.push(parseInt(e.period));
      });

      if(date.length == 0){
        date = [moment(Date.now()).format('YYYY-MM-DD')];
        period = [0];
      }
      response.status(200).json({
        status: 200,
        timestamp: Date.now(),
        message: 'period of blocks generation per second fetched Successfully',
        response: {
          date,
          period,
        },
      });
    } catch (error) {
      next(new InternalServerErrorException(error));
    }
  };

  private SupplyGrowth = async (
    request: Request,
    response: Response,
    next: NextFunction,
  ) => {
    try {
      const BlockchainBlockPerSecondData: TotalDifficultyNBlockDto =
        request.query;
      if (BlockchainBlockPerSecondData.Interval) {
        var timeIntervalQry =
          "timestamp > current_date - interval '" +
          BlockchainBlockPerSecondData.Interval +
          "'";
      } else if (
        BlockchainBlockPerSecondData.FromDate ||
        BlockchainBlockPerSecondData.ToDate
      ) {
        let fromdate = moment(BlockchainBlockPerSecondData.FromDate)
          .utc()
          .format('YYYY-MM-DD');
        let todate = moment(BlockchainBlockPerSecondData.ToDate)
          .utc()
          .format('YYYY-MM-DD');

        var timeIntervalQry =
          'timestamp BETWEEN SYMMETRIC ' + fromdate + ' AND ' + todate;
      } else {
        var timeIntervalQry = "timestamp > current_date - interval '30 days'";
      }
      let DAY_HEIGHT = 1440
      /// Height of the first epic block emission era
      const BLOCK_ERA_1 = DAY_HEIGHT * 334;
      /// Height of the second epic block emission era
      const BLOCK_ERA_2 = BLOCK_ERA_1 + (DAY_HEIGHT * 470);
      /// Height of the third epic block emission era
      const BLOCK_ERA_3 = BLOCK_ERA_2 + (DAY_HEIGHT * 601);
      /// Height of the fourth epic block emission era
      const BLOCK_ERA_4 = BLOCK_ERA_3 + (DAY_HEIGHT * 800);
      /// Height of the fifth epic block emission era
      const BLOCK_ERA_5 = BLOCK_ERA_4 + (DAY_HEIGHT * 1019);
      /// After the epic block emission era 6, each era will last 4 years (approximately 1460 days)
      const BLOCK_ERA_6_ONWARDS = DAY_HEIGHT * 1460;
      /// Block Reward that will be assigned after we change from era 5 to era 6.
      const BASE_REWARD_ERA_6_ONWARDS = 0.15625;
      const BlockchainBlockPerSecondQuery = await getConnection(Global.network)
        .query(
          'select x.timestamp, SUM(x.reward) as total_reward_per_day \
        from (SELECT DISTINCT height, hash, CAST(timestamp AS DATE), \
        CASE \
            WHEN height <= '+BLOCK_ERA_1+' THEN 16 \
            WHEN height <= '+BLOCK_ERA_2+' THEN 8 \
            WHEN height <= '+BLOCK_ERA_3+' THEN 4 \
            WHEN height <= '+BLOCK_ERA_4+' THEN 2 \
            WHEN height <= '+BLOCK_ERA_5+' THEN 1 \
            ELSE '+BASE_REWARD_ERA_6_ONWARDS+' / (1 << ((height - ('+BLOCK_ERA_5+'- 1))/'+BLOCK_ERA_6_ONWARDS+'))\
        END AS reward \
        FROM blockchain_block where height > 0 AND ' +
          timeIntervalQry +
          ') as x group by x.timestamp Order by x.timestamp ASC',
        )
        .catch(err_msg => {
          next(err_msg);
        });


       
  /// Compute the total reward generated by each block in a given height.
  // if (BlockchainBlockFetchQuery.Height <= BLOCK_ERA_1) {
  //   BlockchainBlockFetchQuery['BlockReward'] = 16;
  // } else if (BlockchainBlockFetchQuery.Height <= BLOCK_ERA_2) {
  //   BlockchainBlockFetchQuery['BlockReward'] = 8;
  // } else if (BlockchainBlockFetchQuery.Height <= BLOCK_ERA_3) {
  //   BlockchainBlockFetchQuery['BlockReward'] = 4;
  // } else if (BlockchainBlockFetchQuery.Height <= BLOCK_ERA_4) {
  //   BlockchainBlockFetchQuery['BlockReward'] = 2;
  // } else if (BlockchainBlockFetchQuery.Height <= BLOCK_ERA_5) {
  //   BlockchainBlockFetchQuery['BlockReward'] = 1;
  // } else {
  //   // After the era 6, we reduce the block rewards by half each 1460 days.
  //   // Minus 1 to include multiples in the same index
  //   // (i.e changes greater than to greater or equals to)
  //   let height_with_offset = BlockchainBlockFetchQuery.Height - (BLOCK_ERA_5 - 1);
  //   let exp = height_with_offset / BLOCK_ERA_6_ONWARDS;
  //   BlockchainBlockFetchQuery['BlockReward'] = BASE_REWARD_ERA_6_ONWARDS / (1 << exp);
  // }

      let date = [],
        total_reward_per_day = [],
        addedreward = [],
        prev_value = 0;

      BlockchainBlockPerSecondQuery.forEach(e => {
        date.push(moment(e.timestamp).format('YYYY-MM-DD'));
        total_reward_per_day.push(parseInt(e.total_reward_per_day));
        addedreward.push(prev_value + parseInt(e.total_reward_per_day));
        prev_value = prev_value + parseInt(e.total_reward_per_day);
      });

      if(date.length == 0){
        date = [moment(Date.now()).format('YYYY-MM-DD')];
        total_reward_per_day = [0];
        addedreward = [0];
      }
      response.status(200).json({
        status: 200,
        timestamp: Date.now(),
        message: 'period of blocks generation per second fetched Successfully',
        response: {
          date,
          total_reward_per_day,
          addedreward,
        },
      });
    } catch (error) {
      next(new InternalServerErrorException(error));
    }
  };

  private BlockMineChart = async (
    request: Request,
    response: Response,
    next: NextFunction,
  ) => {
    try {
      const BlockchainBlockPerSecondData: TotalDifficultyNBlockDto =
        request.query;
      if (BlockchainBlockPerSecondData.Interval) {
        var timeIntervalQry =
          "timestamp at time zone '" +
          process.env.TIME_ZONE +
          "' > current_date - interval '" +
          BlockchainBlockPerSecondData.Interval +
          "'";
      } else if (
        BlockchainBlockPerSecondData.FromDate ||
        BlockchainBlockPerSecondData.ToDate
      ) {
        let fromdate = moment(BlockchainBlockPerSecondData.FromDate)
          .utc()
          .format('YYYY-MM-DD');
        let todate = moment(BlockchainBlockPerSecondData.ToDate)
          .utc()
          .format('YYYY-MM-DD');

        var timeIntervalQry =
          "timestamp at time zone '" +
          process.env.TIME_ZONE +
          "' BETWEEN SYMMETRIC '" +
          fromdate +
          "' AND '" +
          todate +
          "'";
      } else {
        var timeIntervalQry =
          "timestamp at time zone '" +
          process.env.TIME_ZONE +
          "' > current_date - interval '30 days'";
      }
      const BlockMineChartQuery = await getConnection(Global.network)
        .query(
          "SELECT hash, date , total_edge_bits, RandomX, Cuckoo, ProgPow, Round(RandomX * 100.0 / total_edge_bits,2) AS RandomXper,  Round(Cuckoo * 100.0 / total_edge_bits,2) AS Cuckooper, Round(ProgPow * 100.0 / total_edge_bits,2) AS ProgPowper \
        FROM   (SELECT    1 as hash, \
                          date(DATE_TRUNC('day', timestamp at time zone '" +
          process.env.TIME_ZONE +
          "')) as date, \
                          COUNT(edge_bits) AS total_edge_bits, \
                          Count( CASE WHEN proof = 'RandomX' THEN 1 ELSE NULL END) AS RandomX, \
                          Count( CASE  WHEN proof = 'Cuckoo' THEN 1 ELSE NULL END) AS Cuckoo,\
                          Count( CASE WHEN proof = 'ProgPow' THEN 1 ELSE NULL END) AS ProgPow \
                 FROM     blockchain_block \
                 where height > 0 and " +
          timeIntervalQry +
          "GROUP BY DATE_TRUNC('day', timestamp at time zone '" +
          process.env.TIME_ZONE +
          "')) t order by date",
        )
        .catch(err_msg => {
          next(err_msg);
        });
      let date = [],
        RandomXper = [],
        Cuckooper = [],
        ProgPowper = [],
        RandomX = [],
        Cuckoo = [],
        ProgPow = [];

      BlockMineChartQuery.forEach(e => {
        date.push(moment(e.date).format('YYYY-MM-DD'));
        RandomXper.push(parseFloat(e.randomxper));
        Cuckooper.push(parseFloat(e.cuckooper));
        ProgPowper.push(parseFloat(e.progpowper));
        RandomX.push(parseInt(e.randomx));
        Cuckoo.push(parseInt(e.cuckoo));
        ProgPow.push(parseInt(e.progpow));
      });

      if(date.length == 0){
        date = [moment(Date.now()).format('YYYY-MM-DD')];
        RandomXper = [0];
        Cuckooper = [0];
        ProgPowper = [0];
        RandomX = [0];
        Cuckoo = [0];
        ProgPow = [0];
      }

      response.status(200).json({
        status: 200,
        timestamp: Date.now(),
        message: 'period of blocks generation per second fetched Successfully',
        response: {
          date,
          RandomXper,
          Cuckooper,
          ProgPowper,
          RandomX,
          Cuckoo,
          ProgPow
        },
      });
    } catch (error) {
      next(new InternalServerErrorException(error));
    }
  };
}