<commit_before>
'use strict'

var assert = require('assert')
var Blockchain = require('cb-blockr')
var bitcoin = require('bitcoinjs-lib')
var EventEmitter = require('events').EventEmitter
var inherits = require('util').inherits

/**
 *  options             {object} (optional)
 *  options.networkName {String} (optional, default: 'bitcoin')
 *  options.batchSize   {Number} (optional, default: 20)
 *    how many blocks to ask for in a request to whatever the provider is
 *  options.throttle    {Number} (optional, default: 2000)
 *    how many milliseconds to wait between requests
 */
function TransactionWalker(options) {
  var self = this

  EventEmitter.call(this)

  options = options || {}
  this._networkName = options.networkName || 'bitcoin'
  this._blockchain = new Blockchain(this._networkName)
  this._batchSize = options.batchSize || 20
  this._throttle = options.throttle || 2000
  this._running = false

  this.on('tx', this._onTx)
}

inherits(TransactionWalker, EventEmitter)

TransactionWalker.prototype.start = function(height) {
  var self = this

  if (this._stopped) throw new Error('I\'m dead, create a new instance')

  if (typeof height === 'undefined') height = this._fromHeight;
  else this.from(height);

  assert(typeof height === 'number', 'Starting height is required')
  this._height = height - 1

  if (this._running) return
  this._running = true

  ;(function loop() {
    if (!self._running) return

    self._processNextBatch(loop)
  })()

  return this;
}

TransactionWalker.prototype._processNextBatch = function(cb) {
  var self = this
  var heights = []
  for (var i = 1; i <= this._batchSize; i++) {
    heights.push(this._height + i)
  }

  this._blockchain.blocks.get(heights, function(err, blocks) {
    if (err) {
      self.emit('error', err)
      return self.stop()
    }

    blocks.every(function(block, i) {
      self._height = heights[i]
      return self._readBlock(block)
    })

    setTimeout(cb, self._throttle)
  })
}

TransactionWalker.prototype._readBlock = function(block) {
  if (!block) return this.stop()

  block = bitcoin.Block.fromHex(block)

  this.emit('blockstart', block, this._height)
  this.emit('block', block, this._height)

  var txs = block.transactions

  for (var i = 0; i < txs.length; i++) {
    this.emit('tx', txs[i])
    if (!this._running) return
  }

  this.emit('blockend', block, this._height)
  if (this._height === this._toHeight) return this.stop();

  return true
}

TransactionWalker.prototype._onTx = function(tx) {
  if (!this.listeners('OP_RETURN').length) return

  for (var i = 0; i < tx.outs.length; i++) {
    var out = tx.outs[i];
    if (bitcoin.scripts.isNullDataOutput(out.script))
      this.emit('OP_RETURN', tx, out.script.chunks[1]);
  }
}

TransactionWalker.prototype.from = function(height) {<commit_msg>fix end-bound support, allow passing in cb-api<commit_after>
'use strict'

var assert = require('assert')
var Blockchain = require('cb-blockr')
var bitcoin = require('bitcoinjs-lib')
var EventEmitter = require('events').EventEmitter
var inherits = require('util').inherits

/**
 *  options             {object} (optional)
 *  options.networkName {String} (optional, default: 'bitcoin')
 *  options.batchSize   {Number} (optional, default: 20)
 *    how many blocks to ask for in a request to whatever the provider is
 *  options.throttle    {Number} (optional, default: 2000)
 *    how many milliseconds to wait between requests
 */
function TransactionWalker(options) {
  var self = this

  EventEmitter.call(this)

  options = options || {}
  this._networkName = options.networkName || 'bitcoin'
  this._blockchain = options.api || new Blockchain(this._networkName)
  this._batchSize = options.batchSize || 20
  this._throttle = options.throttle || 2000
  this._running = false

  this.on('tx', this._onTx)
}

inherits(TransactionWalker, EventEmitter)

TransactionWalker.prototype.start = function(height) {
  var self = this

  if (this._stopped) throw new Error('I\'m dead, create a new instance')

  if (typeof height === 'undefined') height = this._fromHeight;
  else this.from(height);

  assert(typeof height === 'number', 'Starting height is required')
  this._height = height - 1

  if (this._running) return
  this._running = true

  ;(function loop() {
    if (!self._running) return

    self._processNextBatch(loop)
  })()

  return this;
}

TransactionWalker.prototype._processNextBatch = function(cb) {
  var self = this
  var heights = []
  var batchSize = this._batchSize
  if ('_toHeight' in this) {
    batchSize = Math.min(batchSize, this._toHeight - this._height)
  }

  for (var i = 1; i <= batchSize; i++) {
    heights.push(this._height + i)
  }

  if (!heights.length) return this.stop()

  this._blockchain.blocks.get(heights, function(err, blocks) {
    if (err) {
      self.emit('error', err)
      return self.stop()
    }

    blocks.every(function(block, i) {
      self._height = heights[i]
      return self._readBlock(block)
    })

    setTimeout(cb, self._throttle)
  })
}

TransactionWalker.prototype._readBlock = function(block) {
  if (!block) return this.stop()

  block = bitcoin.Block.fromHex(block)

  this.emit('blockstart', block, this._height)
  this.emit('block', block, this._height)

  var txs = block.transactions

  for (var i = 0; i < txs.length; i++) {
    this.emit('tx', txs[i])
    if (!this._running) return
  }

  this.emit('blockend', block, this._height)
  return true
}

TransactionWalker.prototype._onTx = function(tx) {
  if (!this.listeners('OP_RETURN').length) return

  for (var i = 0; i < tx.outs.length; i++) {
    var out = tx.outs[i];
    if (bitcoin.scripts.isNullDataOutput(out.script))
      this.emit('OP_RETURN', tx, out.script.chunks[1]);
  }
}

TransactionWalker.prototype.from = function(height) {
{'fraction_non_alphanumeric': 0.13859164653089404, 'fraction_numerical': 0.005868139454608215, 'mean_word_length': 3.6961102106969204, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 3, 'https://': 0, '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': '3881338', 'n_tokens_mistral': 1921, 'n_tokens_neox': 1827, 'n_words': 463}