<commit_before>var inherits = require('util').inherits

var bitcoin = require('../cclib').bitcoin
var _ = require('lodash')
var LRU = require('lru-cache')
var Q = require('q')
var request = require('request')
//request.debug=true

var BlockchainBase = require('./BlockchainBase')


/**
 * BlockchainState that uses [Chain.com API]{@link https://chain.com/docs}
 *
 * @class Chain
 * @extends BlockchainBase
 *
 * @param {Object} opts
 * @param {boolean} opts.testnet
 * @param {string} [opts.apiKeyId=DEMO-4a5e1e4]
 * @param {number} [opts.requestTimeout=5*1000]
 * @param {number} [opts.maxCacheSize=500]
 * @param {number} [opts.maxCacheAge=10*1000] Cache live in ms
 * @param {BaseTxDb} [opts.txDb] Get transactions from TxDb, optional
 */
function Chain(opts) {
  opts = _.extend({
    testnet: false,
    apiKeyId: 'DEMO-4a5e1e4',
    requestTimeout: 5*1000,
    maxCacheSize: 500,
    maxCacheAge: 10*1000
  }, opts)


  BlockchainBase.call(this)

  this.isTestnet = opts.testnet
  this.baseURL = 'https://api.chain.com/v1/' + (this.isTestnet ? 'testnet3' : 'bitcoin')
  this.apiKeyId = opts.apiKeyId

  this.cache = LRU({
    max: opts.maxCacheSize,
    maxAge: opts.maxCacheAge
  })

  this.requestTimeout = opts.requestTimeout + 25

  this.requestPathMap = {}

  if (!_.isUndefined(opts.txDb))
    this.txDb = opts.txDb
}

inherits(Chain, BlockchainBase)

/**
 * @callback Chain~request
 * @param {?Error} error
 * @param {string} response
 */

/**
 * Make request to the server
 *
 * @param {string} path Path to resource
 * @param {Object} [data=null] Data for POST request, may be missed
 * @param {Chain~request} cb
 */
Chain.prototype.request = function(path, data, cb) {
  if (_.isFunction(data) && _.isUndefined(cb)) {
    cb = data
    data = null
  }

  var self = this

  /** check in cache */
  var cachedValue = self.cache.get(path)
  if (!_.isUndefined(cachedValue)) {
    process.nextTick(function() { cb(null, cachedValue) })
    return
  }

  /** check already requested */
  var requestPathCallbacks = self.requestPathMap[path]
  if (_.isUndefined(requestPathCallbacks)) {
    requestPathCallbacks = []
  }
  requestPathCallbacks.push(cb)

  self.requestPathMap[path] = requestPathCallbacks;

  var doCallbacks = function(param1, param2) {
    var requestPathCallbacks = self.requestPathMap[path]
    delete self.requestPathMap[path]

    _.each(requestPathCallbacks, function (cb) {
      cb(param1, param2)
    })
  }

  /** make request */

  var requestOpts = {
    method: data === null ? 'GET' : 'POST',
    uri: self.baseURL + path + '?api-key-id=' + self.apiKeyId,
    body: JSON.stringify(data),
    timeout: self.requestTimeout,
    zip: true,
    json: true
  }

  Q.nfcall(request, requestOpts).spread(function(response, body) {

    if (response.statusCode !== 200)
      throw new Error('Request error: ' + response.statusMessage)

    return body

  }).done(function(data) {
    self.cache.set(path, data)
    doCallbacks(null, data)
  }, function(error) { doCallbacks(error) })
}

/**
 * @callback Chain~getBlockCount
 * @param {?Error} error
 * @param {number} blockCount
 */

/**
 * Get block count in blockchain
 *
 * @param {Chain~getBlockCount} cb
 */
Chain.prototype.getBlockCount = function(cb) {
  Q.ninvoke(this, 'request', '/blocks/latest').then(function(response) {<commit_msg>clearer code in Chain request<commit_after>var inherits = require('util').inherits

var bitcoin = require('../cclib').bitcoin
var _ = require('lodash')
var LRU = require('lru-cache')
var Q = require('q')
var request = require('request')
//request.debug=true

var BlockchainBase = require('./BlockchainBase')


/**
 * BlockchainState that uses [Chain.com API]{@link https://chain.com/docs}
 *
 * @class Chain
 * @extends BlockchainBase
 *
 * @param {Object} opts
 * @param {boolean} opts.testnet
 * @param {string} [opts.apiKeyId=DEMO-4a5e1e4]
 * @param {number} [opts.requestTimeout=5*1000]
 * @param {number} [opts.maxCacheSize=500]
 * @param {number} [opts.maxCacheAge=10*1000] Cache live in ms
 * @param {BaseTxDb} [opts.txDb] Get transactions from TxDb, optional
 */
function Chain(opts) {
  opts = _.extend({
    testnet: false,
    apiKeyId: 'DEMO-4a5e1e4',
    requestTimeout: 5*1000,
    maxCacheSize: 500,
    maxCacheAge: 10*1000
  }, opts)


  BlockchainBase.call(this)

  this.isTestnet = opts.testnet
  this.baseURL = 'https://api.chain.com/v1/' + (this.isTestnet ? 'testnet3' : 'bitcoin')
  this.apiKeyId = opts.apiKeyId

  this.cache = LRU({
    max: opts.maxCacheSize,
    maxAge: opts.maxCacheAge
  })

  this.requestTimeout = opts.requestTimeout + 25

  this.requestPathMap = {}

  if (!_.isUndefined(opts.txDb))
    this.txDb = opts.txDb
}

inherits(Chain, BlockchainBase)

/**
 * @callback Chain~request
 * @param {?Error} error
 * @param {string} response
 */

/**
 * Make request to the server
 *
 * @param {string} path Path to resource
 * @param {Object} [data=null] Data for POST request, may be missed
 * @param {Chain~request} cb
 */
Chain.prototype.request = function(path, data, cb) {
  if (_.isFunction(data) && _.isUndefined(cb)) {
    cb = data
    data = null
  }

  var self = this

  /** check in cache */
  var cachedValue = self.cache.get(path)
  if (!_.isUndefined(cachedValue)) {
    process.nextTick(function() { cb(null, cachedValue) })
    return
  }

  /** check already requested */
  var requestPathCallbacks = self.requestPathMap[path]
  if (_.isUndefined(requestPathCallbacks)) {
    requestPathCallbacks = []
  }
  requestPathCallbacks.push(cb)

  self.requestPathMap[path] = requestPathCallbacks;

  /** handle answers */
  var doCallbacks = function(param1, param2) {
    var requestPathCallbacks = self.requestPathMap[path]
    delete self.requestPathMap[path]

    _.each(requestPathCallbacks, function (cb) {
      cb(param1, param2)
    })
  }

  var requestOk = function(data) {
    self.cache.set(path, data)
    doCallbacks(null, data)
  }

  var requestError = function(error) {
    doCallbacks(error)
  }

  /** make request */
  var requestOpts = {
    method: data === null ? 'GET' : 'POST',
    uri: self.baseURL + path + '?api-key-id=' + self.apiKeyId,
    body: JSON.stringify(data),
    timeout: self.requestTimeout,
    zip: true,
    json: true
  }

  Q.nfcall(request, requestOpts).spread(function(response, body) {

    if (response.statusCode !== 200)
      throw new Error('Request error: ' + response.statusMessage)

    return body

  }).done(requestOk, requestError)
}

/**
 * @callback Chain~getBlockCount
 * @param {?Error} error
 * @param {number} blockCount
 */

/**
 * Get block count in blockchain
 *
 * @param {Chain~getBlockCount} cb
 */
Chain.prototype.getBlockCount = function(cb) {
  Q.ninvoke(this, 'request', '/blocks/latest').then(function(response) {
{'fraction_non_alphanumeric': 0.14788004136504654, 'fraction_numerical': 0.013886837051263111, 'mean_word_length': 3.701388888888889, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2848009', 'n_tokens_mistral': 2389, 'n_tokens_neox': 2269, 'n_words': 510}