Merge pull request #2564 from mempool/junderw/search-blocktime
[Feature] Search for block by timestamp
This commit is contained in:
		
						commit
						e051758ca7
					
				@ -27,6 +27,7 @@ class MiningRoutes {
 | 
			
		||||
      .get(config.MEMPOOL.API_URL_PREFIX + 'mining/difficulty-adjustments/:interval', this.$getDifficultyAdjustments)
 | 
			
		||||
      .get(config.MEMPOOL.API_URL_PREFIX + 'mining/blocks/predictions/:interval', this.$getHistoricalBlockPrediction)
 | 
			
		||||
      .get(config.MEMPOOL.API_URL_PREFIX + 'mining/blocks/audit/:hash', this.$getBlockAudit)
 | 
			
		||||
      .get(config.MEMPOOL.API_URL_PREFIX + 'mining/blocks/timestamp/:timestamp', this.$getHeightFromTimestamp)
 | 
			
		||||
    ;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -252,6 +253,29 @@ class MiningRoutes {
 | 
			
		||||
      res.status(500).send(e instanceof Error ? e.message : e);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async $getHeightFromTimestamp(req: Request, res: Response) {
 | 
			
		||||
    try {
 | 
			
		||||
      const timestamp = parseInt(req.params.timestamp, 10);
 | 
			
		||||
      // This will prevent people from entering milliseconds etc.
 | 
			
		||||
      // Block timestamps are allowed to be up to 2 hours off, so 24 hours
 | 
			
		||||
      // will never put the maximum value before the most recent block
 | 
			
		||||
      const nowPlus1day = Math.floor(Date.now() / 1000) + 60 * 60 * 24;
 | 
			
		||||
      // Prevent non-integers that are not seconds
 | 
			
		||||
      if (!/^[1-9][0-9]*$/.test(req.params.timestamp) || timestamp > nowPlus1day) {
 | 
			
		||||
        throw new Error(`Invalid timestamp, value must be Unix seconds`);
 | 
			
		||||
      }
 | 
			
		||||
      const result = await BlocksRepository.$getBlockHeightFromTimestamp(
 | 
			
		||||
        timestamp,
 | 
			
		||||
      );
 | 
			
		||||
      res.header('Pragma', 'public');
 | 
			
		||||
      res.header('Cache-control', 'public');
 | 
			
		||||
      res.setHeader('Expires', new Date(Date.now() + 1000 * 300).toUTCString());
 | 
			
		||||
      res.json(result);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      res.status(500).send(e instanceof Error ? e.message : e);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default new MiningRoutes();
 | 
			
		||||
 | 
			
		||||
@ -392,6 +392,36 @@ class BlocksRepository {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get the first block at or directly after a given timestamp
 | 
			
		||||
   * @param timestamp number unix time in seconds
 | 
			
		||||
   * @returns The height and timestamp of a block (timestamp might vary from given timestamp)
 | 
			
		||||
   */
 | 
			
		||||
  public async $getBlockHeightFromTimestamp(
 | 
			
		||||
    timestamp: number,
 | 
			
		||||
  ): Promise<{ height: number; hash: string; timestamp: number }> {
 | 
			
		||||
    try {
 | 
			
		||||
      // Get first block at or after the given timestamp
 | 
			
		||||
      const query = `SELECT height, hash, blockTimestamp as timestamp FROM blocks
 | 
			
		||||
        WHERE blockTimestamp <= FROM_UNIXTIME(?)
 | 
			
		||||
        ORDER BY blockTimestamp DESC
 | 
			
		||||
        LIMIT 1`;
 | 
			
		||||
      const params = [timestamp];
 | 
			
		||||
      const [rows]: any[][] = await DB.query(query, params);
 | 
			
		||||
      if (rows.length === 0) {
 | 
			
		||||
        throw new Error(`No block was found before timestamp ${timestamp}`);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return rows[0];
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      logger.err(
 | 
			
		||||
        'Cannot get block height from timestamp from the db. Reason: ' +
 | 
			
		||||
          (e instanceof Error ? e.message : e),
 | 
			
		||||
      );
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Return blocks height
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user