<commit_before>var WPJSApiHTTP = function(url, args, method, reqOpts) {
    var promise = new Promise(function (resolve, reject) {
        var client = new XMLHttpRequest();
        var uri = url;

        var formData = new FormData();
        if (method == 'POST') {

            uri += '?_envelope=1';

            if (args) {
                for (var key in args) {
                    if (args.hasOwnProperty(key)) {
                        formData.append(key, args[key]);
                    }
                }
            }

        } else if (args) {

            if (reqOpts.softFail === true) {
                if (args) {
                    args._envelope = 1;
                } else {
                    args = {
                        _envelope: 1
                    }
                }
            }

            uri += '?';
            var argcount = 0;
            for (var key in args) {
                if (args.hasOwnProperty(key)) {
                    if (argcount++) {
                        uri += '&';
                    }
                    uri += encodeURIComponent(key) + '=' + encodeURIComponent(args[key]);
                }
            }
        }

        client.open(method, uri);
        if (reqOpts.beforeSend) {
            client = reqOpts.beforeSend(client);
        }
        client.send(formData);
        client.onload = function () {
            if (this.status >= 200 && this.status < 300) {

                var rsp = this.response;
                if (reqOpts.onSuccess) {
                    rsp = reqOpts.onSuccess(rsp);
                }
                resolve(JSON.parse(rsp));

            } else {

                if (reqOpts.onFail) {
                    reqOpts.onFail(this.statusText);
                }
                reject(this.statusText);

            }
        };
        client.onerror = function () {

            if (reqOpts.onFail) {
                reqOpts.onFail(this.statusText);
            }
            reject(this.statusText);

        };
    });
    return promise;
}

var WPJSApiEndpoint = {
    create: function(domain, endpoint, version) {

        if (typeof version !== 'string') {
            version = 'v2';
        }

        return {
            domain: domain,
            endpoint: endpoint,
            version: version,
            listURL: function(args) { return [WPJSApi.base_url, WPJSApi.reqOpts.prefix, domain + '/' + version, endpoint].join('/') },
            getURL: function(id, args) { return [WPJSApi.base_url, WPJSApi.reqOpts.prefix, domain + '/' + version, endpoint, id, args].join('/') },
            'list': function(args) { return WPJSApi.call(domain, endpoint, args, 'GET', version) },
            'get': function(id, args) { return  WPJSApi.call(domain, [endpoint, id.toString(), args].join('/'), args, 'GET', version) },
            'post': function(args) { return WPJSApi.call(domain, endpoint, args, 'POST', version) }
        };
    }
}

var WPJSApi = {
    init: function (url, reqOpts) {
        this.base_url = url;
        this.reqOpts = {
            prefix: 'wp-json',
            softFail: false,
            beforeSend: null,
            onSuccess: null,
            onFail: null
        };

        if (reqOpts) {
            if (reqOpts.prefix)     { this.reqOpts.prefix = reqOpts.prefix; }
            if (reqOpts.softFail)   { this.reqOpts.softFail = reqOpts.softFail; }
            if (reqOpts.onSuccess)  { this.reqOpts.onSuccess = reqOpts.onSuccess; }
            if (reqOpts.onFail)     { this.reqOpts.onFail = reqOpts.onFail; }
            if (reqOpts.beforeSend) { this.reqOpts.beforeSend = reqOpts.beforeSend; }
        }
    },
    call: function (domain, endpoint, args, method, version) {
        if (typeof this.base_url !== 'string') {
            console.log('WPJSApi: No base url provided, please setup module with WPJSApi.init before usage.')
            return;
        }
        if (typeof method !== 'string') {
            method = 'GET';
        }
        var url = [this.base_url, this.reqOpts.prefix, domain + '/' + version, endpoint].join('/');
        return WPJSApiHTTP(url, args, method, this.reqOpts);
    },
    create: WPJSApiEndpoint.create
}

//Add Endpoints
WPJSApi.Pages       = WPJSApiEndpoint.create('wp', 'pages', 'v2');
WPJSApi.Posts       = WPJSApiEndpoint.create('wp', 'posts', 'v2');
WPJSApi.Media       = WPJSApiEndpoint.create('wp', 'media', 'v2');
WPJSApi.Types       = WPJSApiEndpoint.create('wp', 'types', 'v2');
WPJSApi.Statuses    = WPJSApiEndpoint.create('wp', 'statuses', 'v2');
WPJSApi.Comments    = WPJSApiEndpoint.create('wp', 'comments', 'v2');
WPJSApi.Taxonomies  = WPJSApiEndpoint.create('wp', 'taxonomies', 'v2');
WPJSApi.Categories  = WPJSApiEndpoint.create('wp', 'categories', 'v2');
WPJSApi.Tags        = WPJSApiEndpoint.create('wp', 'tags', 'v2');
WPJSApi.Users       = WPJSApiEndpoint.create('wp', 'users', 'v2');

module.exports = WPJSApi;
<commit_msg>get fix<commit_after>var WPJSApiHTTP = function(url, args, method, reqOpts) {
    var promise = new Promise(function (resolve, reject) {
        var client = new XMLHttpRequest();
        var uri = url;

        var formData = new FormData();
        if (method == 'POST') {

            uri += '?_envelope=1';

            if (args) {
                for (var key in args) {
                    if (args.hasOwnProperty(key)) {
                        formData.append(key, args[key]);
                    }
                }
            }

        } else if (args) {

            if (reqOpts.softFail === true) {
                if (args) {
                    args._envelope = 1;
                } else {
                    args = {
                        _envelope: 1
                    }
                }
            }

            uri += '?';
            var argcount = 0;
            for (var key in args) {
                if (args.hasOwnProperty(key)) {
                    if (argcount++) {
                        uri += '&';
                    }
                    uri += encodeURIComponent(key) + '=' + encodeURIComponent(args[key]);
                }
            }
        }

        client.open(method, uri);
        if (reqOpts.beforeSend) {
            client = reqOpts.beforeSend(client);
        }
        client.send(formData);
        client.onload = function () {
            if (this.status >= 200 && this.status < 300) {

                var rsp = this.response;
                if (reqOpts.onSuccess) {
                    rsp = reqOpts.onSuccess(rsp);
                }
                resolve(JSON.parse(rsp));

            } else {

                if (reqOpts.onFail) {
                    reqOpts.onFail(this.statusText);
                }
                reject(this.statusText);

            }
        };
        client.onerror = function () {

            if (reqOpts.onFail) {
                reqOpts.onFail(this.statusText);
            }
            reject(this.statusText);

        };
    });
    return promise;
}

var WPJSApiEndpoint = {
    create: function(domain, endpoint, version) {

        if (typeof version !== 'string') {
            version = 'v2';
        }

        return {
            domain: domain,
            endpoint: endpoint,
            version: version,
            listURL: function(args) { return [WPJSApi.base_url, WPJSApi.reqOpts.prefix, domain + '/' + version, endpoint].join('/') },
            getURL: function(id, args) { return [WPJSApi.base_url, WPJSApi.reqOpts.prefix, domain + '/' + version, endpoint, id, args].join('/') },
            'list': function(args) { return WPJSApi.call(domain, endpoint, args, 'GET', version) },
            'get': function(id, args) { return  WPJSApi.call(domain, [endpoint, id.toString()].join('/'), args, 'GET', version) },
            'post': function(args) { return WPJSApi.call(domain, endpoint, args, 'POST', version) }
        };
    }
}

var WPJSApi = {
    init: function (url, reqOpts) {
        this.base_url = url;
        this.reqOpts = {
            prefix: 'wp-json',
            softFail: false,
            beforeSend: null,
            onSuccess: null,
            onFail: null
        };

        if (reqOpts) {
            if (reqOpts.prefix)     { this.reqOpts.prefix = reqOpts.prefix; }
            if (reqOpts.softFail)   { this.reqOpts.softFail = reqOpts.softFail; }
            if (reqOpts.onSuccess)  { this.reqOpts.onSuccess = reqOpts.onSuccess; }
            if (reqOpts.onFail)     { this.reqOpts.onFail = reqOpts.onFail; }
            if (reqOpts.beforeSend) { this.reqOpts.beforeSend = reqOpts.beforeSend; }
        }
    },
    call: function (domain, endpoint, args, method, version) {
        if (typeof this.base_url !== 'string') {
            console.log('WPJSApi: No base url provided, please setup module with WPJSApi.init before usage.')
            return;
        }
        if (typeof method !== 'string') {
            method = 'GET';
        }
        var url = [this.base_url, this.reqOpts.prefix, domain + '/' + version, endpoint].join('/');
        return WPJSApiHTTP(url, args, method, this.reqOpts);
    },
    create: WPJSApiEndpoint.create
}

//Add Endpoints
WPJSApi.Pages       = WPJSApiEndpoint.create('wp', 'pages', 'v2');
WPJSApi.Posts       = WPJSApiEndpoint.create('wp', 'posts', 'v2');
WPJSApi.Media       = WPJSApiEndpoint.create('wp', 'media', 'v2');
WPJSApi.Types       = WPJSApiEndpoint.create('wp', 'types', 'v2');
WPJSApi.Statuses    = WPJSApiEndpoint.create('wp', 'statuses', 'v2');
WPJSApi.Comments    = WPJSApiEndpoint.create('wp', 'comments', 'v2');
WPJSApi.Taxonomies  = WPJSApiEndpoint.create('wp', 'taxonomies', 'v2');
WPJSApi.Categories  = WPJSApiEndpoint.create('wp', 'categories', 'v2');
WPJSApi.Tags        = WPJSApiEndpoint.create('wp', 'tags', 'v2');
WPJSApi.Users       = WPJSApiEndpoint.create('wp', 'users', 'v2');

module.exports = WPJSApi;
<|endoftext|>


<commit_before>
const depictsWholeNumber = require('depicts-whole-number').onlySafeNumbers
const c = {
  ESCAPE_CHAR: '\\',
  KEY_SEPARATOR: '.',
  EMPTY_STRING: '',
  REGEX: {
    SQUARE_BRACKETS: /[\[\]]/g,
    EXPLICIT_ARRAY: /\[(0|[1-9][0-9]*)\]/,
    EXPLICIT_ARRAY_GM: /\[(0|[1-9][0-9]*)\]/g
  }
}
const defaultOptions = {
  CustomDelimiter: c.KEY_SEPARATOR,
  AutocreateArrays: true,
  ExplicitArrays: false,
  CircularityCheck: false,
  MaxDepth: 0
}

/**
 * ObjectFx static class.
 * @class
 */
class ObjectFx {

  /**
   * Checks for valid array index
   * @param {String} s
   * @return {Boolean}
   */
  static _isValidArrayIndex (s) {
    return depictsWholeNumber(s)
  }

  /**
   * Checks for valid array index within square brackets (named 'explicit array' here)
   * @param {String} s
   * @return {Boolean}
   */
  static _containsValidArrayIndex (s) {
    const result = s.match(c.REGEX.EXPLICIT_ARRAY)
    if (!result) {
      return false
    }
    return depictsWholeNumber(result[1])
  }

  /**
   * Expands (unflattens) a flattened object
   * @param {Object} objFlat - flattened object
   * @param {Object} userOptions - options
   * @return {Object}
   */
  static unflatten (objFlat, userOptions) {
    return this.expand(objFlat, userOptions)
  }
  static expand (objFlat, userOptions) {
    if (Object.prototype.toString.call(objFlat) !== '[object Object]') {
      return null
    }
    const options = Object.prototype.toString.call(userOptions) === '[object Object]' ? Object.assign({}, defaultOptions, userOptions) : defaultOptions
    const prefix = 'root' + options.CustomDelimiter
    const regexConsecutiveSeparators = new RegExp('\\' + options.CustomDelimiter.split('').join('\\') + '{2,}', 'g')
    const regexSurroundingSeparators = new RegExp('^\\' + options.CustomDelimiter.split('').join('\\') + '+|\\' + options.CustomDelimiter.split('').join('\\') + '+$', 'g')
    const objExp = {}
    let keys = Object.keys(objFlat)
    for (let i = 0, kln = keys.length; i < kln; i++) {
      const origKey = keys[i]
      let currKey = prefix + origKey
      if (options.ExplicitArrays) {
        currKey = currKey
          .replace(c.REGEX.EXPLICIT_ARRAY_GM, options.CustomDelimiter + '[$1]' + options.CustomDelimiter)
          .replace(regexConsecutiveSeparators, options.CustomDelimiter)
          .replace(regexSurroundingSeparators, c.EMPTY_STRING)
      }
      const chunks = currKey.split(options.CustomDelimiter)
      let obj = objExp
      for (let j = 0, cln = chunks.length; j < cln; j++) {
        let currChunk = chunks[j]
        let nextChunk = chunks[j + 1]
        if (options.ExplicitArrays) {
          currChunk = currChunk.replace(c.REGEX.SQUARE_BRACKETS, c.EMPTY_STRING)
        }
        if (!obj[currChunk]) {
          if (j > cln - 2) {
            obj[currChunk] = objFlat[origKey]
          } else {
            if ((options.AutocreateArrays && this._isValidArrayIndex(nextChunk)) ||
              (options.ExplicitArrays && this._containsValidArrayIndex(nextChunk))) {
              obj[currChunk] = []
            } else {
              obj[currChunk] = {}
            }
          }
        }
        /* if (options.ExplicitArrays && this._containsValidArrayIndex(currChunk)) {
          currChunk.replace(c.REGEX.SQUARE_BRACKETS, c.EMPTY_STRING)
        } */
        obj = obj[currChunk]
      }
    }
    return objExp.root
  }

  /**
   * Flattens an object
   * @param {Object} objExp
   * @param {Object} userOptions - options
   * @return {Object}
   */
  static flatten (objExp, userOptions) {
    if (Object.prototype.toString.call(objExp) !== '[object Object]') {
      return null
    }
    const options = Object.prototype.toString.call(userOptions) === '[object Object]' ? Object.assign({}, defaultOptions, userOptions) : defaultOptions
    if (options.CircularityCheck) {
      try {
        JSON.stringify(objExp)
      } catch (err) {
        if (err.message.match(/circular structure/ig)) {
          // throw TypeError('Unable to flatten circular structure')
          return null
        }
      }
    }

    let result = {}
    const recurse = (cur, prop, lev) => {
      if (options.MaxDepth > 0 && lev >= options.MaxDepth) {
        result[prop] = cur
        return
      }
      lev++
      if (typeof cur !== 'object') { // Object(cur) !== cur
        result[prop] = cur
      } else if (Array.isArray(cur)) { // https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
        for (var i = 0, l = cur.length; i < l; i++) {
          if (options.ExplicitArrays) {
            recurse(cur[i], prop + '[' + i + ']', lev)
          } else {
            let prefix = prop
            if (prefix) {
              prefix += options.CustomDelimiter
            }
            recurse(cur[i], prefix + i, lev)
          }
        }
        /* if (l === 0) {
          result[prop] = []
        } */
      } else {
        if (Object.prototype.toString.call(cur) === '[object Object]') { // cur && cur.toString() === '[object Object]'
          for (var p in cur) {
            recurse(cur[p], prop ? prop + options.CustomDelimiter + p : p, lev)
          }
        } else {
          result[prop] = cur
        }
      }
    }
    recurse(objExp, c.EMPTY_STRING, 0)
    return result
  }

}

module.exports = ObjectFx
<commit_msg>add strict mode for node 4+5<commit_after>
'use strict'
const depictsWholeNumber = require('depicts-whole-number').onlySafeNumbers
const c = {
  ESCAPE_CHAR: '\\',
  KEY_SEPARATOR: '.',
  EMPTY_STRING: '',
  REGEX: {
    SQUARE_BRACKETS: /[\[\]]/g,
    EXPLICIT_ARRAY: /\[(0|[1-9][0-9]*)\]/,
    EXPLICIT_ARRAY_GM: /\[(0|[1-9][0-9]*)\]/g
  }
}
const defaultOptions = {
  CustomDelimiter: c.KEY_SEPARATOR,
  AutocreateArrays: true,
  ExplicitArrays: false,
  CircularityCheck: false,
  MaxDepth: 0
}

/**
 * ObjectFx static class.
 * @class
 */
class ObjectFx {

  /**
   * Checks for valid array index
   * @param {String} s
   * @return {Boolean}
   */
  static _isValidArrayIndex (s) {
    return depictsWholeNumber(s)
  }

  /**
   * Checks for valid array index within square brackets (named 'explicit array' here)
   * @param {String} s
   * @return {Boolean}
   */
  static _containsValidArrayIndex (s) {
    const result = s.match(c.REGEX.EXPLICIT_ARRAY)
    if (!result) {
      return false
    }
    return depictsWholeNumber(result[1])
  }

  /**
   * Expands (unflattens) a flattened object
   * @param {Object} objFlat - flattened object
   * @param {Object} userOptions - options
   * @return {Object}
   */
  static unflatten (objFlat, userOptions) {
    return this.expand(objFlat, userOptions)
  }
  static expand (objFlat, userOptions) {
    if (Object.prototype.toString.call(objFlat) !== '[object Object]') {
      return null
    }
    const options = Object.prototype.toString.call(userOptions) === '[object Object]' ? Object.assign({}, defaultOptions, userOptions) : defaultOptions
    const prefix = 'root' + options.CustomDelimiter
    const regexConsecutiveSeparators = new RegExp('\\' + options.CustomDelimiter.split('').join('\\') + '{2,}', 'g')
    const regexSurroundingSeparators = new RegExp('^\\' + options.CustomDelimiter.split('').join('\\') + '+|\\' + options.CustomDelimiter.split('').join('\\') + '+$', 'g')
    const objExp = {}
    let keys = Object.keys(objFlat)
    for (let i = 0, kln = keys.length; i < kln; i++) {
      const origKey = keys[i]
      let currKey = prefix + origKey
      if (options.ExplicitArrays) {
        currKey = currKey
          .replace(c.REGEX.EXPLICIT_ARRAY_GM, options.CustomDelimiter + '[$1]' + options.CustomDelimiter)
          .replace(regexConsecutiveSeparators, options.CustomDelimiter)
          .replace(regexSurroundingSeparators, c.EMPTY_STRING)
      }
      const chunks = currKey.split(options.CustomDelimiter)
      let obj = objExp
      for (let j = 0, cln = chunks.length; j < cln; j++) {
        let currChunk = chunks[j]
        let nextChunk = chunks[j + 1]
        if (options.ExplicitArrays) {
          currChunk = currChunk.replace(c.REGEX.SQUARE_BRACKETS, c.EMPTY_STRING)
        }
        if (!obj[currChunk]) {
          if (j > cln - 2) {
            obj[currChunk] = objFlat[origKey]
          } else {
            if ((options.AutocreateArrays && this._isValidArrayIndex(nextChunk)) ||
              (options.ExplicitArrays && this._containsValidArrayIndex(nextChunk))) {
              obj[currChunk] = []
            } else {
              obj[currChunk] = {}
            }
          }
        }
        /* if (options.ExplicitArrays && this._containsValidArrayIndex(currChunk)) {
          currChunk.replace(c.REGEX.SQUARE_BRACKETS, c.EMPTY_STRING)
        } */
        obj = obj[currChunk]
      }
    }
    return objExp.root
  }

  /**
   * Flattens an object
   * @param {Object} objExp
   * @param {Object} userOptions - options
   * @return {Object}
   */
  static flatten (objExp, userOptions) {
    if (Object.prototype.toString.call(objExp) !== '[object Object]') {
      return null
    }
    const options = Object.prototype.toString.call(userOptions) === '[object Object]' ? Object.assign({}, defaultOptions, userOptions) : defaultOptions
    if (options.CircularityCheck) {
      try {
        JSON.stringify(objExp)
      } catch (err) {
        if (err.message.match(/circular structure/ig)) {
          // throw TypeError('Unable to flatten circular structure')
          return null
        }
      }
    }

    let result = {}
    const recurse = (cur, prop, lev) => {
      if (options.MaxDepth > 0 && lev >= options.MaxDepth) {
        result[prop] = cur
        return
      }
      lev++
      if (typeof cur !== 'object') { // Object(cur) !== cur
        result[prop] = cur
      } else if (Array.isArray(cur)) { // https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
        for (var i = 0, l = cur.length; i < l; i++) {
          if (options.ExplicitArrays) {
            recurse(cur[i], prop + '[' + i + ']', lev)
          } else {
            let prefix = prop
            if (prefix) {
              prefix += options.CustomDelimiter
            }
            recurse(cur[i], prefix + i, lev)
          }
        }
        /* if (l === 0) {
          result[prop] = []
        } */
      } else {
        if (Object.prototype.toString.call(cur) === '[object Object]') { // cur && cur.toString() === '[object Object]'
          for (var p in cur) {
            recurse(cur[p], prop ? prop + options.CustomDelimiter + p : p, lev)
          }
        } else {
          result[prop] = cur
        }
      }
    }
    recurse(objExp, c.EMPTY_STRING, 0)
    return result
  }

}

module.exports = ObjectFx
<|endoftext|>


<commit_before>var noble = require('noble');

var events = require('events');
var util = require('util');

var EXPECTED_MANUFACTURER_DATA_LENGTH = 25;
var APPLE_COMPANY_IDENTIFIER = 0x004c; // https://www.bluetooth.org/en-us/specification/assigned-numbers/company-identifiers
var IBEACON_TYPE = 0x02;
var EXPECTED_IBEACON_DATA_LENGTH = 0x15;

var BLEManager = function () {
    this._subscribedPaths = [];
    this._characteristicsForPaths = {};
    this._connectedPeripheral = {};

};

util.inherits(BLEManager, events.EventEmitter);

BLEManager.prototype.pathsTree = function() {
    var result = {};
    this._subscribedPaths.forEach(function(topic){
        var splitTopic = topic.split('/');
        var deviceID = splitTopic[0];
        var serviceID = splitTopic[1];
        var charID = splitTopic[2];

        if (!(deviceID in result)){
            result[deviceID] = {};
        }
        var device = result[deviceID];

        if (serviceID) {
            if (!(serviceID in device)) {
                device[serviceID] = {};
            }
            var service = device[serviceID];
            if (charID) {
                if (!(charID in service)) {
                    service[charID] = {};
                }
                var char = service[charID];
                char.topicName = topic;

            }

        }

    });

    return result;
};
BLEManager.prototype.discover = function(blePath, callback) {
    this._subscribedPaths.push(blePath);
    if (callback) {
        var self = this;
        var listener = function(discoveredBlePath, characteristic) {
            if (discoveredBlePath==blePath) {
                self.removeListener("characteristicDiscovered", listener);
                callback(null, characteristic);
            }
        };
        this.on("characteristicDiscovered", listener);
    }
};

BLEManager.prototype.write = function(blePath, data) {
    var characteristic = this._characteristicsForPaths[blePath];
    if (characteristic){
        console.log("writing "+data + " to "+characteristic);
        characteristic.write(data);
    } else {
        this.discover(blePath, function(error, characteristic) {
            if (!error) {
                if (characteristic) {
                    console.log("writing "+data + " to "+characteristic);

                    characteristic.write(data);
                }
            }
        });
    }
};

BLEManager.prototype.startScanning = function() {

    noble.on('stateChange', function(state) {
        if (state === 'poweredOn') {
            noble.startScanning([], true);
        } else {
            noble.stopScanning();
        }
    });

    noble.on('discover', this.onDiscover.bind(this));
    noble.on('notify', this.onNotify.bind(this));

};

BLEManager.prototype.onNotify = function(characteristic, data) {

};

BLEManager.prototype.onDiscover = function(peripheral) {
    console.log('DEVICE ' + peripheral.advertisement.localName + ' id: '+peripheral.uuid);

    if (peripheral.uuid in this.pathsTree()) {
        this.connectToPeripheral(peripheral);
    };

    var manufacturerData = peripheral.advertisement.manufacturerData;
    var rssi = peripheral.rssi;

    if (manufacturerData &&
        EXPECTED_MANUFACTURER_DATA_LENGTH <= manufacturerData.length &&
        APPLE_COMPANY_IDENTIFIER === manufacturerData.readUInt16LE(0) &&
        IBEACON_TYPE === manufacturerData.readUInt8(2) &&
        EXPECTED_IBEACON_DATA_LENGTH === manufacturerData.readUInt8(3)) {
        var uuid = manufacturerData.slice(4, 20).toString('hex');
        var major = manufacturerData.readUInt16BE(20);
        var minor = manufacturerData.readUInt16BE(22);
        var measuredPower = manufacturerData.readInt8(24);

        var accuracy = Math.pow(12.0, 1.5 * ((rssi / measuredPower) - 1));
        this.emit("ibeaconFound", uuid+"/"+major+"/"+minor, accuracy);
    }
};

BLEManager.prototype.connectToPeripheral = function connectToPeripheral(peripheral) {
    var self = this;
    if (!(peripheral.uuid in this._connectedPeripheral)) {
        this._connectedPeripheral[peripheral.uuid] = peripheral;
        peripheral.connect(function (error) {
            if (error) { console.error("BLE ERROR: "+error); return; }
            console.log("CONNECT: "+peripheral.uuid);
            peripheral.discoverServices(null, function(error, services) {
                if (error) { console.error("BLE ERROR: "+error); return; }

                for (var i in services) {
                    console.log('SERVICE discovered:  ' + i + ' uuid: ' + services[i].uuid);
                    if (services[i].uuid in self.pathsTree()[peripheral.uuid]) {
                        console.log('SERVICE CONNECTED:  ' + i + ' uuid: ' + services[i].uuid);
                        (function(service) {
                            service.discoverCharacteristics(null, function(error, characteristics){
                                if (error) { console.error("BLE ERROR: "+error); return; }

                                for (var i in characteristics) {
                                    var char = characteristics[i];
                                    console.log('CHAR discovered: ' + i + ' uuid: ' + char.uuid);

                                    if (char.uuid in self.pathsTree()[peripheral.uuid][service.uuid]) {

                                        console.log('CHAR CONNECTED: ' + i + ' uuid: ' + char.uuid);
                                        var topicName = self.pathsTree()[peripheral.uuid][service.uuid][char.uuid].topicName;

                                        self._characteristicsForPaths[topicName] = char;
                                        self.emit("characteristicDiscovered", topicName, char);

                                        char.notify(true);
                                    }

                                }

                            });
                        })(services[i]);
                    }

                }
            });

        });
    }

}

module.exports = BLEManager;
<commit_msg>debug<commit_after>var noble = require('noble');

var events = require('events');
var util = require('util');

var EXPECTED_MANUFACTURER_DATA_LENGTH = 25;
var APPLE_COMPANY_IDENTIFIER = 0x004c; // https://www.bluetooth.org/en-us/specification/assigned-numbers/company-identifiers
var IBEACON_TYPE = 0x02;
var EXPECTED_IBEACON_DATA_LENGTH = 0x15;

var BLEManager = function () {
    this._subscribedPaths = [];
    this._characteristicsForPaths = {};
    this._connectedPeripheral = {};

};

util.inherits(BLEManager, events.EventEmitter);

BLEManager.prototype.pathsTree = function() {
    var result = {};
    this._subscribedPaths.forEach(function(topic){
        var splitTopic = topic.split('/');
        var deviceID = splitTopic[0];
        var serviceID = splitTopic[1];
        var charID = splitTopic[2];

        if (!(deviceID in result)){
            result[deviceID] = {};
        }
        var device = result[deviceID];

        if (serviceID) {
            if (!(serviceID in device)) {
                device[serviceID] = {};
            }
            var service = device[serviceID];
            if (charID) {
                if (!(charID in service)) {
                    service[charID] = {};
                }
                var char = service[charID];
                char.topicName = topic;

            }

        }

    });

    return result;
};
BLEManager.prototype.discover = function(blePath, callback) {
    this._subscribedPaths.push(blePath);
    if (callback) {
        var self = this;
        var listener = function(discoveredBlePath, characteristic) {
            if (discoveredBlePath==blePath) {
                self.removeListener("characteristicDiscovered", listener);
                callback(null, characteristic);
            }
        };
        this.on("characteristicDiscovered", listener);
    }
};

BLEManager.prototype.write = function(blePath, data) {
    var characteristic = this._characteristicsForPaths[blePath];
    if (characteristic){
        console.log("writing "+data + " to "+characteristic);
        characteristic.write(data);
    } else {
        this.discover(blePath, function(error, characteristic) {
            if (!error) {
                if (characteristic) {
                    console.log("writing "+data + " to "+characteristic);

                    characteristic.write(data);
                }
            }
        });
    }
};

BLEManager.prototype.startScanning = function() {

    noble.on('stateChange', function(state) {
        if (state === 'poweredOn') {
            noble.startScanning([], true);
        } else {
            noble.stopScanning();
        }
    });

    noble.on('discover', this.onDiscover.bind(this));
    noble.on('notify', this.onNotify.bind(this));

};

BLEManager.prototype.onNotify = function(characteristic, data) {

};

BLEManager.prototype.onDiscover = function(peripheral) {
    console.log('DEVICE ' + peripheral.advertisement.localName + ' id: '+peripheral.uuid);

    if (peripheral.uuid in this.pathsTree()) {
        this.connectToPeripheral(peripheral);
    };

    var manufacturerData = peripheral.advertisement.manufacturerData;
    var rssi = peripheral.rssi;

    if (manufacturerData &&
        EXPECTED_MANUFACTURER_DATA_LENGTH <= manufacturerData.length &&
        APPLE_COMPANY_IDENTIFIER === manufacturerData.readUInt16LE(0) &&
        IBEACON_TYPE === manufacturerData.readUInt8(2) &&
        EXPECTED_IBEACON_DATA_LENGTH === manufacturerData.readUInt8(3)) {
        var uuid = manufacturerData.slice(4, 20).toString('hex');
        var major = manufacturerData.readUInt16BE(20);
        var minor = manufacturerData.readUInt16BE(22);
        var measuredPower = manufacturerData.readInt8(24);

        var accuracy = Math.pow(12.0, 1.5 * ((rssi / measuredPower) - 1));
        this.emit("ibeaconFound", uuid+"/"+major+"/"+minor, accuracy);
    }
};

BLEManager.prototype.connectToPeripheral = function connectToPeripheral(peripheral) {
    var self = this;
    if (!(peripheral.uuid in this._connectedPeripheral)) {
        this._connectedPeripheral[peripheral.uuid] = peripheral;
        peripheral.connect(function (error) {
            if (error) { console.error("BLE ERROR: "+error); return; }
            console.log("CONNECT: "+peripheral.uuid);
            peripheral.discoverServices(null, function(error, services) {
                if (error) { console.error("BLE ERROR: "+error); return; }

                for (var i in services) {
                    console.log('SERVICE discovered:  ' + i + ' uuid: ' + services[i].uuid);
                    if (services[i].uuid in self.pathsTree()[peripheral.uuid]) {
                        console.log('SERVICE CONNECTED:  ' + i + ' uuid: ' + services[i].uuid);
                        (function(service) {
                            service.discoverCharacteristics(null, function(error, characteristics){
                                if (error) { console.error("BLE ERROR: "+error); return; }

                                for (var i in characteristics) {
                                    var char = characteristics[i];
                                    console.log('CHAR discovered: ' + i + ' uuid: ' + char.uuid);

                                    if (char.uuid in self.pathsTree()[peripheral.uuid][service.uuid]) {

                                        console.log('CHAR CONNECTED: ' + i + ' uuid: ' + char.uuid);
                                        var topicName = self.pathsTree()[peripheral.uuid][service.uuid][char.uuid].topicName;

                                        self._characteristicsForPaths[topicName] = char;
                                        self.emit("characteristicDiscovered", topicName, char);

                                        //char.notify(true);
                                    }

                                }

                            });
                        })(services[i]);
                    }

                }
            });

        });
    }

}

module.exports = BLEManager;
<|endoftext|>


<commit_before>#!/usr/bin/env node
const inquirer = require('inquirer')
const Listr = require('listr')

const steps = [{
  type: 'input',
  name: 'userName',
  message: 'Whats your name?'
}]

const tasks = [{
  title: 'Preparing',
  task: (context, task) => new Promise((resolve, reject) => {
    setTimeout(() => resolve(), 1000)
  })
},{
  title: 'Ask for name',
  task: (context, task) => new Promise((resolve, reject) => {
    task.output = 'Starting'

    setTimeout(() => {
      task.output = 'Calculating'
      resolve()
    }, 500)

    // setTimeout(() => {
    // }, 2000)
  })
}]

// Test change for release
// Test change for release
// Test change for release

const listrObject = new Listr(tasks)

listrObject.run().then(res => {
  inquirer
    .prompt(steps).then(output => {
    console.log(
      'Hello',
      output.userName
    )
  }).catch(err => console.log(err))
})
<commit_msg>Add test change for release 5<commit_after>#!/usr/bin/env node
const inquirer = require('inquirer')
const Listr = require('listr')

const steps = [{
  type: 'input',
  name: 'userName',
  message: 'Whats your name?'
}]

const tasks = [{
  title: 'Preparing',
  task: (context, task) => new Promise((resolve, reject) => {
    setTimeout(() => resolve(), 1000)
  })
},{
  title: 'Ask for name',
  task: (context, task) => new Promise((resolve, reject) => {
    task.output = 'Starting'

    setTimeout(() => {
      task.output = 'Calculating'
      resolve()
    }, 500)

    // setTimeout(() => {
    // }, 2000)
  })
}]

// Test change for release
// Test change for release
// Test change for release
// Test change for release

const listrObject = new Listr(tasks)

listrObject.run().then(res => {
  inquirer
    .prompt(steps).then(output => {
    console.log(
      'Hello',
      output.userName
    )
  }).catch(err => console.log(err))
})
<|endoftext|>


<commit_before>module.exports = {
	extends: [
		'./lib/es2015-basic'
	].map(require.resolve),

	env: {
		node: true
	},

	rules: {

		// Possible errors
		'comma-dangle': [2, 'never'],
		'no-cond-assign': [2, 'except-parens'],
		'no-console': 0,
		'no-constant-condition': 2,
		'no-control-regex': 1,
		'no-debugger': 2,
		'no-dupe-args': 2,
		'no-dupe-keys': 2,
		'no-duplicate-case': 2,
		'no-empty-character-class': 2,
		'no-empty': 1,
		'no-ex-assign': 2,
		'no-extra-boolean-cast': 2,
		'no-extra-parens': [1, 'all'],
		'no-extra-semi': 1,
		'no-func-assign': 2,
		'no-inner-declarations': [2, 'both'],
		'no-invalid-regexp': 2,
		'no-irregular-whitespace': 2,
		'no-negated-in-lhs': 2,
		'no-obj-calls': 2,
		'no-regex-spaces': 2,
		'no-sparse-arrays': 2,
		'no-unexpected-multiline': 2,
		'no-unreachable': 2,
		'use-isnan': 2,
		'valid-jsdoc': [1, {
			'prefer': {
				'return': 'return'
			},
			'requireReturn': false,
			'requireParamDescription': false,
			'requireReturnDescription': false,
			'requireReturnType': true
		}],
		'valid-typeof': 2,
		'no-unsafe-finally': 1,

		// Best practices
		'accessor-pairs': [2, {
			'getWithoutSet': true
		}],
		'block-scoped-var': 2,
		'complexity': [1, 10],
		'consistent-return': 1,
		'curly': [2, 'all'],
		'default-case': 1,
		'dot-location': [1, 'property'],
		'dot-notation': 1,
		'eqeqeq': 2,
		'guard-for-in': 2,
		'no-alert': 0,
		'no-caller': 2,
		'no-case-declarations': 2,
		'no-div-regex': 2,
		'no-else-return': 1,
		'no-empty-pattern': 2,
		'no-eq-null': 2,
		'no-eval': 1,
		'no-extend-native': 1,
		'no-extra-bind': 1,
		'no-fallthrough': 2,
		'no-floating-decimal': 2,
		'no-implicit-coercion': 2,
		'no-implied-eval': 2,
		'no-invalid-this': 1,
		'no-iterator': 2,
		'no-labels': 2,
		'no-lone-blocks': 2,
		'no-loop-func': 2,
		'no-magic-numbers': 0,
		'no-multi-spaces': [1, {
			'exceptions': {
				'Property': true,
				'VariableDeclarator': true,
				'ImportDeclaration': true
			}
		}],
		'no-multi-str': 2,
		'no-native-reassign': 2,
		'no-new-func': 1,
		'no-new-wrappers': 2,
		'no-new': 1,
		'no-octal-escape': 2,
		'no-octal': 2,
		'no-param-reassign': [1, {
			'props': true
		}],
		'no-process-env': 1,
		'no-proto': 2,
		'no-redeclare': [2, {
			'builtinGlobals': true
		}],
		'no-return-assign': [2, 'always'],
		'no-script-url': 1,
		'no-self-compare': 1,
		'no-sequences': 1,
		'no-throw-literal': 2,
		'no-unused-expressions': 1,
		'no-useless-call': 0,
		'no-useless-concat': 1,
		'no-void': 2,
		'no-warning-comments': 0,
		'no-with': 2,
		'radix': [2, 'always'],
		'vars-on-top': 2,
		'wrap-iife': [2, 'inside'],
		'yoda': 1,
		'array-callback-return': 1,
		'no-empty-function': 0,
		'no-extra-label': 2,
		'no-self-assign': 0,
		'no-unmodified-loop-condition': 1,
		'no-unused-labels': 2,
		'no-implicit-globals': 0,
		'no-useless-escape': 1,

		// Strict mode
		'strict': 0,

		// Variables
		'init-declarations': 0,
		'no-catch-shadow': 2,
		'no-delete-var': 2,
		'no-label-var': 2,
		'no-shadow-restricted-names': 2,
		'no-shadow': [1, {
			'builtinGlobals': true,
			'hoist': 'all',
			'allow': ['cb', 'done']
		}],
		'no-undef-init': 2,
		'no-undef': 2,
		'no-undefined': 2,
		'no-unused-vars': 1,
		'no-use-before-define': [2, 'nofunc'],
		'no-restricted-globals': 0,

		// Node.js and CommonJS
		'callback-return': 0,
		'global-require': 1,
		'handle-callback-err': 1,
		'no-mixed-requires': [1, {
			'grouping': true
		}],
		'no-new-require': 2,
		'no-path-concat': 2,
		'no-process-exit': 2,
		'no-restricted-modules': 0,
		'no-sync': 0,

		// Stylistic issues
		'array-bracket-spacing': [1, 'never'],
		'block-spacing': [1, 'always'],
		'brace-style': [2, '1tbs', {
			'allowSingleLine': true
		}],
		'camelcase': [2, {
			'properties': 'always'
		}],
		'comma-spacing': [2, {
			'before': false,
			'after': true
		}],
		'comma-style': [2, 'last'],
		'computed-property-spacing': [2, 'never'],
		'consistent-this': [2, 'self'],
		'eol-last': [2, 'unix'],
		'func-names': 0,
		'func-style': [1, 'declaration', {
			'allowArrowFunctions': true
		}],
		'id-length': 0,
		'id-match': 0,
		'indent': [2, 'tab', {
			'SwitchCase': 1
		}],
		'jsx-quotes': [2, 'prefer-double'],
		'key-spacing': [2, {
			'beforeColon': false,
			'afterColon': true
		}],
		'linebreak-style': [2, 'unix'],
		'lines-around-comment': 0,
		'max-depth': [1, 3],
		'max-len': 0,
		'max-nested-callbacks': [1, 3],
		'max-params': [1, 4],
		'max-statements': 0,
		'max-statements-per-line': [1, {
			'max': 4
		}],
		'new-cap': 2,
		'new-parens': 2,
		'newline-after-var': 0,
		'newline-before-return': 0,
		'no-array-constructor': 1,
		'no-bitwise': 1,
		'no-continue': 1,
		'no-inline-comments': 0,
		'no-lonely-if': 1,
		'no-mixed-spaces-and-tabs': [2, 'smart-tabs'],
		'no-multiple-empty-lines': [2, {
			'max': 5,
			'maxEOF': 1
		}],
		'no-negated-condition': 0,
		'no-nested-ternary': 2,
		'no-new-object': 1,
		'no-plusplus': 0,
		'no-restricted-syntax': 0,
		'no-spaced-func': 2,
		'no-ternary': 0,
		'no-trailing-spaces': 2,
		'no-underscore-dangle': 0,
		'no-unneeded-ternary': 1,
		'object-curly-spacing': [1, 'always'],
		'one-var': [1, {
			'uninitialized': 'always',
			'initialized': 'never'
		}],
		'operator-assignment': 0,
		'operator-linebreak': [2, 'after'],
		'padded-blocks': 0,
		'quote-props': [1, 'as-needed', {
			'keywords': true
		}],
		'quotes': [2, 'single'],
		'require-jsdoc': 0,
		'semi-spacing': [1, {
			'before': false,
			'after': true
		}],
		'semi': [2, 'always'],
		'sort-vars': 0,
		'keyword-spacing': [2, {
			'before': true,
			'after': true
		}],
		'space-before-blocks': [2, 'always'],
		'space-before-function-paren': [2, 'always'],
		'space-in-parens': 0,
		'space-infix-ops': 1,
		'space-unary-ops': [1, {
			'words': true,
			'nonwords': false
		}],
		'spaced-comment': [1, 'always', {
			'line': {
				'exceptions': ['-']
			},
			'block': {
				'exceptions': ['-']
			}
		}],
		'wrap-regex': 0,
		'id-blacklist': 0,
		'newline-per-chained-call': [1, {
			'ignoreChainWithDepth': 4
		}],
		'no-whitespace-before-property': 1,
		'one-var-declaration-per-line': 0
	}
};
<commit_msg>Add "object-property-newline"<commit_after>module.exports = {
	extends: [
		'./lib/es2015-basic'
	].map(require.resolve),

	env: {
		node: true
	},

	rules: {

		// Possible errors
		'comma-dangle': [2, 'never'],
		'no-cond-assign': [2, 'except-parens'],
		'no-console': 0,
		'no-constant-condition': 2,
		'no-control-regex': 1,
		'no-debugger': 2,
		'no-dupe-args': 2,
		'no-dupe-keys': 2,
		'no-duplicate-case': 2,
		'no-empty-character-class': 2,
		'no-empty': 1,
		'no-ex-assign': 2,
		'no-extra-boolean-cast': 2,
		'no-extra-parens': [1, 'all'],
		'no-extra-semi': 1,
		'no-func-assign': 2,
		'no-inner-declarations': [2, 'both'],
		'no-invalid-regexp': 2,
		'no-irregular-whitespace': 2,
		'no-negated-in-lhs': 2,
		'no-obj-calls': 2,
		'no-regex-spaces': 2,
		'no-sparse-arrays': 2,
		'no-unexpected-multiline': 2,
		'no-unreachable': 2,
		'use-isnan': 2,
		'valid-jsdoc': [1, {
			'prefer': {
				'return': 'return'
			},
			'requireReturn': false,
			'requireParamDescription': false,
			'requireReturnDescription': false,
			'requireReturnType': true
		}],
		'valid-typeof': 2,
		'no-unsafe-finally': 1,

		// Best practices
		'accessor-pairs': [2, {
			'getWithoutSet': true
		}],
		'block-scoped-var': 2,
		'complexity': [1, 10],
		'consistent-return': 1,
		'curly': [2, 'all'],
		'default-case': 1,
		'dot-location': [1, 'property'],
		'dot-notation': 1,
		'eqeqeq': 2,
		'guard-for-in': 2,
		'no-alert': 0,
		'no-caller': 2,
		'no-case-declarations': 2,
		'no-div-regex': 2,
		'no-else-return': 1,
		'no-empty-pattern': 2,
		'no-eq-null': 2,
		'no-eval': 1,
		'no-extend-native': 1,
		'no-extra-bind': 1,
		'no-fallthrough': 2,
		'no-floating-decimal': 2,
		'no-implicit-coercion': 2,
		'no-implied-eval': 2,
		'no-invalid-this': 1,
		'no-iterator': 2,
		'no-labels': 2,
		'no-lone-blocks': 2,
		'no-loop-func': 2,
		'no-magic-numbers': 0,
		'no-multi-spaces': [1, {
			'exceptions': {
				'Property': true,
				'VariableDeclarator': true,
				'ImportDeclaration': true
			}
		}],
		'no-multi-str': 2,
		'no-native-reassign': 2,
		'no-new-func': 1,
		'no-new-wrappers': 2,
		'no-new': 1,
		'no-octal-escape': 2,
		'no-octal': 2,
		'no-param-reassign': [1, {
			'props': true
		}],
		'no-process-env': 1,
		'no-proto': 2,
		'no-redeclare': [2, {
			'builtinGlobals': true
		}],
		'no-return-assign': [2, 'always'],
		'no-script-url': 1,
		'no-self-compare': 1,
		'no-sequences': 1,
		'no-throw-literal': 2,
		'no-unused-expressions': 1,
		'no-useless-call': 0,
		'no-useless-concat': 1,
		'no-void': 2,
		'no-warning-comments': 0,
		'no-with': 2,
		'radix': [2, 'always'],
		'vars-on-top': 2,
		'wrap-iife': [2, 'inside'],
		'yoda': 1,
		'array-callback-return': 1,
		'no-empty-function': 0,
		'no-extra-label': 2,
		'no-self-assign': 0,
		'no-unmodified-loop-condition': 1,
		'no-unused-labels': 2,
		'no-implicit-globals': 0,
		'no-useless-escape': 1,

		// Strict mode
		'strict': 0,

		// Variables
		'init-declarations': 0,
		'no-catch-shadow': 2,
		'no-delete-var': 2,
		'no-label-var': 2,
		'no-shadow-restricted-names': 2,
		'no-shadow': [1, {
			'builtinGlobals': true,
			'hoist': 'all',
			'allow': ['cb', 'done']
		}],
		'no-undef-init': 2,
		'no-undef': 2,
		'no-undefined': 2,
		'no-unused-vars': 1,
		'no-use-before-define': [2, 'nofunc'],
		'no-restricted-globals': 0,

		// Node.js and CommonJS
		'callback-return': 0,
		'global-require': 1,
		'handle-callback-err': 1,
		'no-mixed-requires': [1, {
			'grouping': true
		}],
		'no-new-require': 2,
		'no-path-concat': 2,
		'no-process-exit': 2,
		'no-restricted-modules': 0,
		'no-sync': 0,

		// Stylistic issues
		'array-bracket-spacing': [1, 'never'],
		'block-spacing': [1, 'always'],
		'brace-style': [2, '1tbs', {
			'allowSingleLine': true
		}],
		'camelcase': [2, {
			'properties': 'always'
		}],
		'comma-spacing': [2, {
			'before': false,
			'after': true
		}],
		'comma-style': [2, 'last'],
		'computed-property-spacing': [2, 'never'],
		'consistent-this': [2, 'self'],
		'eol-last': [2, 'unix'],
		'func-names': 0,
		'func-style': [1, 'declaration', {
			'allowArrowFunctions': true
		}],
		'id-length': 0,
		'id-match': 0,
		'indent': [2, 'tab', {
			'SwitchCase': 1
		}],
		'jsx-quotes': [2, 'prefer-double'],
		'key-spacing': [2, {
			'beforeColon': false,
			'afterColon': true
		}],
		'linebreak-style': [2, 'unix'],
		'lines-around-comment': 0,
		'max-depth': [1, 3],
		'max-len': 0,
		'max-nested-callbacks': [1, 3],
		'max-params': [1, 4],
		'max-statements': 0,
		'max-statements-per-line': [1, {
			'max': 4
		}],
		'new-cap': 2,
		'new-parens': 2,
		'newline-after-var': 0,
		'newline-before-return': 0,
		'no-array-constructor': 1,
		'no-bitwise': 1,
		'no-continue': 1,
		'no-inline-comments': 0,
		'no-lonely-if': 1,
		'no-mixed-spaces-and-tabs': [2, 'smart-tabs'],
		'no-multiple-empty-lines': [2, {
			'max': 5,
			'maxEOF': 1
		}],
		'no-negated-condition': 0,
		'no-nested-ternary': 2,
		'no-new-object': 1,
		'no-plusplus': 0,
		'no-restricted-syntax': 0,
		'no-spaced-func': 2,
		'no-ternary': 0,
		'no-trailing-spaces': 2,
		'no-underscore-dangle': 0,
		'no-unneeded-ternary': 1,
		'object-curly-spacing': [1, 'always'],
		'one-var': [1, {
			'uninitialized': 'always',
			'initialized': 'never'
		}],
		'operator-assignment': 0,
		'operator-linebreak': [2, 'after'],
		'padded-blocks': 0,
		'quote-props': [1, 'as-needed', {
			'keywords': true
		}],
		'quotes': [2, 'single'],
		'require-jsdoc': 0,
		'semi-spacing': [1, {
			'before': false,
			'after': true
		}],
		'semi': [2, 'always'],
		'sort-vars': 0,
		'keyword-spacing': [2, {
			'before': true,
			'after': true
		}],
		'space-before-blocks': [2, 'always'],
		'space-before-function-paren': [2, 'always'],
		'space-in-parens': 0,
		'space-infix-ops': 1,
		'space-unary-ops': [1, {
			'words': true,
			'nonwords': false
		}],
		'spaced-comment': [1, 'always', {
			'line': {
				'exceptions': ['-']
			},
			'block': {
				'exceptions': ['-']
			}
		}],
		'wrap-regex': 0,
		'id-blacklist': 0,
		'newline-per-chained-call': [1, {
			'ignoreChainWithDepth': 4
		}],
		'no-whitespace-before-property': 1,
		'one-var-declaration-per-line': 0,
		'object-property-newline': 1
	}
};
<|endoftext|>


<commit_before>var Account = require('ethereumjs-account');
var Block = require('ethereumjs-block');
var VM = require('ethereumjs-vm');
var Trie = require('merkle-patricia-tree');
var Transaction = require('ethereumjs-tx');
var utils = require('ethereumjs-util');
var crypto = require('crypto');

Blockchain = function() {
  this.stateTrie = new Trie();
  this.vm = new VM(this.stateTrie);
  this.nonces = {};
  this.blockNumber = -1;
  this.accounts = {};
  this.blocks = [];
  this.blockNum = 0;
  this.coinbase = null;
  this.contracts = {};
  this.blockHashes = {};
  this.transactions = {};
  this.latest_filter_id = 1;
  this.transaction_queue = [];
  this.transaction_processing == false;
  this.pendingBlock = this.createBlock();
  this.lastBlockHash = "0x0000000000000000000000000000000000000000000000000000000000000000";

  this.mine();
}

Blockchain.prototype.toHex = function(val) {
  if (typeof val == "number") {
    val = utils.intToHex(val);
  }

  if (val instanceof Buffer) {
    val = val.toString("hex");

    if (val == "") {
      val = "0";
    }
  }

  return utils.addHexPrefix(val);
}

Blockchain.prototype.addAccount = function(callback) {
  var self = this;

  var secretKey = crypto.randomBytes(32);
  var publicKey = utils.privateToPublic(new Buffer(secretKey));
  var address = utils.pubToAddress(new Buffer(publicKey));

  account = new Account();
  account.balance = "0xffffffffffffff00000000000000001";

  this.stateTrie.put(address, account.serialize(), function(err, result) {
    if (err != null) {
      callback(err);
      return;
    }

    var data = {
      secretKey: secretKey,
      publicKey: publicKey,
      address: self.toHex(address),
      account: account
    };

    if (self.coinbase == null) {
      self.coinbase = self.toHex(address);
    }

    self.accounts[self.toHex(address)] = data;

    callback();
  });
}

Blockchain.prototype.accountAddresses = function() {
  return Object.keys(this.accounts);
}

Blockchain.prototype.createBlock = function() {
  var block = new Block();
  block.header.gasLimit = '0x2fefd8';
  return block;
}

Blockchain.prototype.mine = function() {
  this.blockNumber += 1;
  var block = this.pendingBlock;
  var parent = this.blocks.length != 0 ? this.blocks[this.blocks.length - 1] : null;

  // Update the header for when the block was mined.
  block.header.timestamp = this.toHex(new Date().getTime());
  block.header.number = this.toHex(this.blockNumber);

  if (parent != null) {
    block.header.parentHash = this.toHex(parent.hash());
  }

  this.blocks.push(block);

  // Update our caches.
  this.blockHashes[this.toHex(block.hash())] = block;
  this.lastBlockHash = this.toHex(block.hash());

  this.pendingBlock = this.createBlock();
}

Blockchain.prototype.latestBlock = function() {
  return this.blocks[this.blocks.length - 1];
}

Blockchain.prototype.gasPrice = function() {
  return '1';
}

Blockchain.prototype.getBalance = function(address, callback) {
  var self = this;

  address = new Buffer(utils.stripHexPrefix(address), "hex");
  this.vm.stateManager.getAccountBalance(address, function(err, result) {
    if (err != null) {
      callback(err);
    } else {
      callback(null, self.toHex(result));
    }
  });
}

Blockchain.prototype.getTransactionCount = function(address, callback) {
  var self = this;
  address = new Buffer(utils.stripHexPrefix(address));
  this.vm.stateManager.getAccount(address, function(err, result) {
    if (err != null) {
      callback(err);
    } else {
      callback(null, self.toHex(result.nonce));
    }
  });
}

Blockchain.prototype.getCode = function(address) {
  address = this.toHex(address);
  return this.contracts[address] || "";
}

Blockchain.prototype.getBlockByNumber = function(number) {

  if (number == "latest" || number == "pending") {
    block = this.latestBlock();
    number = this.blocks.length - 1;
  } else {
    block = this.blocks[utils.bufferToInt(number)];
  }

  var self = this;
  return {
    number: self.toHex(number),
    hash: self.toHex(block.hash()),
    parentHash: self.toHex(block.header.parentHash),
    nonce: self.toHex(block.header.nonce),
    sha3Uncles: self.toHex(block.header.uncleHash),
    logsBloom: self.toHex(block.header.bloom),
    transactionsRoot: self.toHex(block.header.transactionTrie),
    stateRoot: self.toHex(block.header.stateRoot),
    receiptsRoot: self.toHex(block.header.receiptTrie),
    miner: self.toHex(block.header.coinbase),
    difficulty: self.toHex(block.header.difficulty),
    totalDifficulty: self.toHex(block.header.difficulty), // TODO: Figure out what to do here.
    extraData: self.toHex(block.header.extraData),
    size: self.toHex(1000), // TODO: Do something better here
    gasLimit: self.toHex(block.header.gasLimit),
    gasUsed: self.toHex(block.header.gasUsed),
    timestamp: self.toHex(block.header.timestamp),
    transactions: [], //block.transactions.map(function(tx) {return tx.toJSON(true)}),
    uncles: [], // block.uncleHeaders.map(function(uncleHash) {return self.toHex(uncleHash)})
  };
}

Blockchain.prototype.getBlockByHash = function(hash) {
  var block = this.blockHashes[this.toHex(hash)];
  return this.getBlockByNumber(this.toHex(block.header.number));
}

Blockchain.prototype.getTransactionReceipt = function(hash) {
  var result = this.transactions[hash];

  if (result !== undefined) {
    return {
      transactionHash: hash,
      transactionIndex: this.toHex(utils.intToHex(0)),
      blockHash: this.toHex(result.block.hash()),
      blockNumber: result.block_number,
      cumulativeGasUsed: result.gasUsed,  // TODO: What should this be?
      gasUsed: result.gasUsed,
      contractAddress: result.createdAddress,
      logs: result.logs
    };
  }
  else {
    return null;
  }
}

Blockchain.prototype.getTransactionByHash = function(hash) {
  var result = this.transactions[hash];

  if (result !== undefined) {
    var tx = result.tx;

    return {
      hash: hash,
      nonce: this.toHex(tx.nonce),
      blockHash: this.toHex(result.block.hash()),
      blockNumber: result.block_number,
      transactionIndex:  "0x0",
      from: this.toHex(tx.getSenderAddress()),
      to: this.toHex(tx.to),
      value: this.toHex(tx.value), // 520464
      gas: this.toHex(tx.gasLimit), // 520464
      gasPrice: this.toHex(tx.gasPrice),
      input: this.toHex(tx.data),
    };
  }
  else {
    return null;
  }
}

Blockchain.prototype.queueTransaction = function(tx_params, callback) {
  this.queueAction("eth_sendTransaction", tx_params, callback);
};

Blockchain.prototype.queueCall = function(tx_params, callback) {
  this.queueAction("eth_call", tx_params, callback);
};

Blockchain.prototype.queueAction = function(method, tx_params, callback) {
  if (tx_params.from == null) {
    callback(new Error("from not found; is required"));
    return;
  }

  tx_params.from = this.toHex(tx_params.from);

  var rawTx = {
      gasPrice: "0x1",
      gasLimit: "0x2fefd8",
      value: '0x0',
      data: ''
  };

  if (tx_params.gasPrice != null) {
    rawTx.gasPrice = this.toHex(tx_params.gasPrice);
  }

  if (tx_params.gas != null) {
    rawTx.gasLimit = this.toHex(tx_params.gas);
  }

  if (tx_params.gasPrice != null) {
    rawTx.gasPrice = this.toHex(tx_params.gasPrice);
  }

  if (tx_params.to != null) {
    rawTx.to = this.toHex(tx_params.to);
  }

  if (tx_params.value != null) {
    rawTx.value = this.toHex(tx_params.value);
  }

  if (tx_params.data != null) {
    rawTx.data = this.toHex(tx_params.data);
  }

  if (tx_params.nonce != null) {
    rawTx.nonce = this.toHex(tx_params.nonce);
  }

  this.transaction_queue.push({
    method: method,
    from: tx_params.from,
    rawTx: rawTx,
    callback: callback
  });

  // We know there's work, so get started.
  this.processNextAction();
};

Blockchain.prototype.processNextAction = function(override) {
  var self = this;

  if (override != true) {
    if (this.transaction_processing == true || this.transaction_queue.length == 0) {
      return;
    }
  }

  var queued = this.transaction_queue.shift();

  this.transaction_processing = true;

  var intermediary = function(err, result) {
    queued.callback(err, result);

    if (self.transaction_queue.length > 0) {
      self.processNextAction(true);
    } else {
      self.transaction_processing = false;
    }
  };

  if (queued.method == "eth_sendTransaction") {
    this.processTransaction(queued.from, queued.rawTx, intermediary);
  } else {
    this.processCall(queued.from, queued.rawTx, intermediary);
  }
};

Blockchain.prototype.processTransaction = function(from, rawTx, callback) {
  var self = this;

  var block = this.pendingBlock;
  var address = new Buffer(utils.stripHexPrefix(from), "hex");
  var privateKey = new Buffer(this.accounts[from].secretKey, 'hex');

  this.stateTrie.get(address, function(err, val) {
    var account = new Account(val);

    // If the user specified a nonce, use that instead.
    if (rawTx.nonce == null) {
      rawTx.nonce = self.toHex(account.nonce);
    }

    var tx = new Transaction(rawTx);

    tx.sign(privateKey);

    var tx_hash = self.toHex(tx.hash());

    // Add the transaction to the block.
    block.transactions.push(tx);

    // Ensure we have the right block number for the VM.
    block.header.number = self.blockNumber + 1;

    self.vm.runBlock({
      block: block,
      generate: true
    }, function(err, results) {
      if (err) {
        callback(err);
        return;
      }

      if (results.error != null) {
        callback(new Error("VM error: " + results.error));
        return;
      }

      var receipt = results.receipts[0];
      var result = results.results[0];

      if (result.vm.exception != 1) {
        callback(new Error("VM Exception while executing transaction: " + result.vm.exceptionError));
        return;
      }

      var logs = [];

      for (var i = 0; i < receipt.logs.length; i++) {
        var log = receipt.logs[i];
        var address = self.toHex(log[0]);
        var topics = []

        for (var j = 0; j < log[1].length; j++) {
          topics.push(self.toHex(log[1][j]));
        }

        var data = self.toHex(log[2]);

        logs.push({
          logIndex: self.toHex(i),
          transactionIndex: "0x0",
          transactionHash: tx_hash,
          blockHash: self.toHex(block.hash()),
          blockNumber: self.toHex(self.blockNumber + 1),
          address: address,
          data: data,
          topics: topics,
          type: "mined"
        });
      }

      var tx_result = {
        tx: tx,
        block_number: self.toHex(self.blockNumber + 1),
        block: block,
        stateRoot: self.toHex(receipt.stateRoot),
        gasUsed: self.toHex(receipt.gasUsed),
        bitvector: self.toHex(receipt.bitvector),
        logs: logs,
        createdAddress: result.createdAddress != null ? self.toHex(result.createdAddress) : null,
        bloom: result.bloom,
        amountSpent: result.amountSpent
      };

      self.transactions[tx_hash] = tx_result;

      console.log("");

      if (tx_result.createdAddress != null) {
        console.log("  Contract created: " + tx_result.createdAddress);
        self.contracts[tx_result.createdAddress] = rawTx.data;
      }

      console.log("  Gas usage: " + utils.bufferToInt(self.toHex(tx_result.gasUsed)));
      console.log("");

      self.mine();

      callback(null, tx_hash);
    });
  });
};

Blockchain.prototype.processCall = function(from, rawTx, callback) {
  var self = this;

  var block = this.latestBlock();
  var address = new Buffer(utils.stripHexPrefix(from), "hex");
  var privateKey = new Buffer(this.accounts[from].secretKey, 'hex');

  this.stateTrie.get(address, function(err, val) {
    var account = new Account(val);

    // If the user specified a nonce, use that instead.
    if (rawTx.nonce == null) {
      rawTx.nonce = self.toHex(account.nonce);
    }

    var tx = new Transaction(rawTx);
    tx.sign(privateKey);

    var tx_hash = self.toHex(tx.hash());

    self.stateTrie.checkpoint();

    self.vm.runTx({
      tx: tx,
      block: block
    }, function(err, results) {
      self.stateTrie.revert();

      if (err) {
        callback(err);
        return;
      }

      if (results.error != null) {
        callback(new Error("VM error: " + results.error));
        return;
      }

      if (results.vm.exception != 1) {
        callback(new Error("VM Exception while executing transaction: " + results.vm.exceptionError));
        return;
      }

      callback(null, self.toHex(results.vm.return || "0x0"));
    });
  });
};

module.exports = Blockchain;
<commit_msg>set block header in createBlock()<commit_after>var Account = require('ethereumjs-account');
var Block = require('ethereumjs-block');
var VM = require('ethereumjs-vm');
var Trie = require('merkle-patricia-tree');
var Transaction = require('ethereumjs-tx');
var utils = require('ethereumjs-util');
var crypto = require('crypto');

Blockchain = function() {
  this.stateTrie = new Trie();
  this.vm = new VM(this.stateTrie);
  this.nonces = {};
  this.blockNumber = -1;
  this.accounts = {};
  this.blocks = [];
  this.blockNum = 0;
  this.coinbase = null;
  this.contracts = {};
  this.blockHashes = {};
  this.transactions = {};
  this.latest_filter_id = 1;
  this.transaction_queue = [];
  this.transaction_processing == false;
  this.pendingBlock = this.createBlock();
  this.lastBlockHash = "0x0000000000000000000000000000000000000000000000000000000000000000";

  this.mine();
}

Blockchain.prototype.toHex = function(val) {
  if (typeof val == "number") {
    val = utils.intToHex(val);
  }

  if (val instanceof Buffer) {
    val = val.toString("hex");

    if (val == "") {
      val = "0";
    }
  }

  return utils.addHexPrefix(val);
}

Blockchain.prototype.addAccount = function(callback) {
  var self = this;

  var secretKey = crypto.randomBytes(32);
  var publicKey = utils.privateToPublic(new Buffer(secretKey));
  var address = utils.pubToAddress(new Buffer(publicKey));

  account = new Account();
  account.balance = "0xffffffffffffff00000000000000001";

  this.stateTrie.put(address, account.serialize(), function(err, result) {
    if (err != null) {
      callback(err);
      return;
    }

    var data = {
      secretKey: secretKey,
      publicKey: publicKey,
      address: self.toHex(address),
      account: account
    };

    if (self.coinbase == null) {
      self.coinbase = self.toHex(address);
    }

    self.accounts[self.toHex(address)] = data;

    callback();
  });
}

Blockchain.prototype.accountAddresses = function() {
  return Object.keys(this.accounts);
}

Blockchain.prototype.createBlock = function() {
  var block = new Block();
  var parent = this.blocks.length != 0 ? this.blocks[this.blocks.length - 1] : null;

  block.header.gasLimit = '0x2fefd8';

  // Ensure we have the right block number for the VM.
  block.header.number = this.toHex(this.blockNumber + 1);

  // Set the timestamp before processing txs
  block.header.timestamp = this.toHex(new Date().getTime() / 1000 | 0);

  if (parent != null) {
    block.header.parentHash = this.toHex(parent.hash());
  }

  return block;
}

Blockchain.prototype.mine = function() {
  this.blockNumber += 1;
  var block = this.pendingBlock;

  this.blocks.push(block);

  // Update our caches.
  this.blockHashes[this.toHex(block.hash())] = block;
  this.lastBlockHash = this.toHex(block.hash());

  this.pendingBlock = this.createBlock();
}

Blockchain.prototype.latestBlock = function() {
  return this.blocks[this.blocks.length - 1];
}

Blockchain.prototype.gasPrice = function() {
  return '1';
}

Blockchain.prototype.getBalance = function(address, callback) {
  var self = this;

  address = new Buffer(utils.stripHexPrefix(address), "hex");
  this.vm.stateManager.getAccountBalance(address, function(err, result) {
    if (err != null) {
      callback(err);
    } else {
      callback(null, self.toHex(result));
    }
  });
}

Blockchain.prototype.getTransactionCount = function(address, callback) {
  var self = this;
  address = new Buffer(utils.stripHexPrefix(address));
  this.vm.stateManager.getAccount(address, function(err, result) {
    if (err != null) {
      callback(err);
    } else {
      callback(null, self.toHex(result.nonce));
    }
  });
}

Blockchain.prototype.getCode = function(address) {
  address = this.toHex(address);
  return this.contracts[address] || "";
}

Blockchain.prototype.getBlockByNumber = function(number) {

  if (number == "latest" || number == "pending") {
    block = this.latestBlock();
    number = this.blocks.length - 1;
  } else {
    block = this.blocks[utils.bufferToInt(number)];
  }

  var self = this;
  return {
    number: self.toHex(number),
    hash: self.toHex(block.hash()),
    parentHash: self.toHex(block.header.parentHash),
    nonce: self.toHex(block.header.nonce),
    sha3Uncles: self.toHex(block.header.uncleHash),
    logsBloom: self.toHex(block.header.bloom),
    transactionsRoot: self.toHex(block.header.transactionTrie),
    stateRoot: self.toHex(block.header.stateRoot),
    receiptsRoot: self.toHex(block.header.receiptTrie),
    miner: self.toHex(block.header.coinbase),
    difficulty: self.toHex(block.header.difficulty),
    totalDifficulty: self.toHex(block.header.difficulty), // TODO: Figure out what to do here.
    extraData: self.toHex(block.header.extraData),
    size: self.toHex(1000), // TODO: Do something better here
    gasLimit: self.toHex(block.header.gasLimit),
    gasUsed: self.toHex(block.header.gasUsed),
    timestamp: self.toHex(block.header.timestamp),
    transactions: [], //block.transactions.map(function(tx) {return tx.toJSON(true)}),
    uncles: [], // block.uncleHeaders.map(function(uncleHash) {return self.toHex(uncleHash)})
  };
}

Blockchain.prototype.getBlockByHash = function(hash) {
  var block = this.blockHashes[this.toHex(hash)];
  return this.getBlockByNumber(this.toHex(block.header.number));
}

Blockchain.prototype.getTransactionReceipt = function(hash) {
  var result = this.transactions[hash];

  if (result !== undefined) {
    return {
      transactionHash: hash,
      transactionIndex: this.toHex(utils.intToHex(0)),
      blockHash: this.toHex(result.block.hash()),
      blockNumber: result.block_number,
      cumulativeGasUsed: result.gasUsed,  // TODO: What should this be?
      gasUsed: result.gasUsed,
      contractAddress: result.createdAddress,
      logs: result.logs
    };
  }
  else {
    return null;
  }
}

Blockchain.prototype.getTransactionByHash = function(hash) {
  var result = this.transactions[hash];

  if (result !== undefined) {
    var tx = result.tx;

    return {
      hash: hash,
      nonce: this.toHex(tx.nonce),
      blockHash: this.toHex(result.block.hash()),
      blockNumber: result.block_number,
      transactionIndex:  "0x0",
      from: this.toHex(tx.getSenderAddress()),
      to: this.toHex(tx.to),
      value: this.toHex(tx.value), // 520464
      gas: this.toHex(tx.gasLimit), // 520464
      gasPrice: this.toHex(tx.gasPrice),
      input: this.toHex(tx.data),
    };
  }
  else {
    return null;
  }
}

Blockchain.prototype.queueTransaction = function(tx_params, callback) {
  this.queueAction("eth_sendTransaction", tx_params, callback);
};

Blockchain.prototype.queueCall = function(tx_params, callback) {
  this.queueAction("eth_call", tx_params, callback);
};

Blockchain.prototype.queueAction = function(method, tx_params, callback) {
  if (tx_params.from == null) {
    callback(new Error("from not found; is required"));
    return;
  }

  tx_params.from = this.toHex(tx_params.from);

  var rawTx = {
      gasPrice: "0x1",
      gasLimit: "0x2fefd8",
      value: '0x0',
      data: ''
  };

  if (tx_params.gasPrice != null) {
    rawTx.gasPrice = this.toHex(tx_params.gasPrice);
  }

  if (tx_params.gas != null) {
    rawTx.gasLimit = this.toHex(tx_params.gas);
  }

  if (tx_params.gasPrice != null) {
    rawTx.gasPrice = this.toHex(tx_params.gasPrice);
  }

  if (tx_params.to != null) {
    rawTx.to = this.toHex(tx_params.to);
  }

  if (tx_params.value != null) {
    rawTx.value = this.toHex(tx_params.value);
  }

  if (tx_params.data != null) {
    rawTx.data = this.toHex(tx_params.data);
  }

  if (tx_params.nonce != null) {
    rawTx.nonce = this.toHex(tx_params.nonce);
  }

  this.transaction_queue.push({
    method: method,
    from: tx_params.from,
    rawTx: rawTx,
    callback: callback
  });

  // We know there's work, so get started.
  this.processNextAction();
};

Blockchain.prototype.processNextAction = function(override) {
  var self = this;

  if (override != true) {
    if (this.transaction_processing == true || this.transaction_queue.length == 0) {
      return;
    }
  }

  var queued = this.transaction_queue.shift();

  this.transaction_processing = true;

  var intermediary = function(err, result) {
    queued.callback(err, result);

    if (self.transaction_queue.length > 0) {
      self.processNextAction(true);
    } else {
      self.transaction_processing = false;
    }
  };

  if (queued.method == "eth_sendTransaction") {
    this.processTransaction(queued.from, queued.rawTx, intermediary);
  } else {
    this.processCall(queued.from, queued.rawTx, intermediary);
  }
};

Blockchain.prototype.processTransaction = function(from, rawTx, callback) {
  var self = this;

  var block = this.pendingBlock;
  var address = new Buffer(utils.stripHexPrefix(from), "hex");
  var privateKey = new Buffer(this.accounts[from].secretKey, 'hex');

  this.stateTrie.get(address, function(err, val) {
    var account = new Account(val);

    // If the user specified a nonce, use that instead.
    if (rawTx.nonce == null) {
      rawTx.nonce = self.toHex(account.nonce);
    }

    var tx = new Transaction(rawTx);

    tx.sign(privateKey);

    var tx_hash = self.toHex(tx.hash());

    // Add the transaction to the block.
    block.transactions.push(tx);

    self.vm.runBlock({
      block: block,
      generate: true
    }, function(err, results) {
      if (err) {
        callback(err);
        return;
      }

      if (results.error != null) {
        callback(new Error("VM error: " + results.error));
        return;
      }

      var receipt = results.receipts[0];
      var result = results.results[0];

      if (result.vm.exception != 1) {
        callback(new Error("VM Exception while executing transaction: " + result.vm.exceptionError));
        return;
      }

      var logs = [];

      for (var i = 0; i < receipt.logs.length; i++) {
        var log = receipt.logs[i];
        var address = self.toHex(log[0]);
        var topics = []

        for (var j = 0; j < log[1].length; j++) {
          topics.push(self.toHex(log[1][j]));
        }

        var data = self.toHex(log[2]);

        logs.push({
          logIndex: self.toHex(i),
          transactionIndex: "0x0",
          transactionHash: tx_hash,
          blockHash: self.toHex(block.hash()),
          blockNumber: self.toHex(self.blockNumber + 1),
          address: address,
          data: data,
          topics: topics,
          type: "mined"
        });
      }

      var tx_result = {
        tx: tx,
        block_number: self.toHex(self.blockNumber + 1),
        block: block,
        stateRoot: self.toHex(receipt.stateRoot),
        gasUsed: self.toHex(receipt.gasUsed),
        bitvector: self.toHex(receipt.bitvector),
        logs: logs,
        createdAddress: result.createdAddress != null ? self.toHex(result.createdAddress) : null,
        bloom: result.bloom,
        amountSpent: result.amountSpent
      };

      self.transactions[tx_hash] = tx_result;

      console.log("");

      if (tx_result.createdAddress != null) {
        console.log("  Contract created: " + tx_result.createdAddress);
        self.contracts[tx_result.createdAddress] = rawTx.data;
      }

      console.log("  Gas usage: " + utils.bufferToInt(self.toHex(tx_result.gasUsed)));
      console.log("");

      self.mine();

      callback(null, tx_hash);
    });
  });
};

Blockchain.prototype.processCall = function(from, rawTx, callback) {
  var self = this;

  var block = this.latestBlock();
  var address = new Buffer(utils.stripHexPrefix(from), "hex");
  var privateKey = new Buffer(this.accounts[from].secretKey, 'hex');

  this.stateTrie.get(address, function(err, val) {
    var account = new Account(val);

    // If the user specified a nonce, use that instead.
    if (rawTx.nonce == null) {
      rawTx.nonce = self.toHex(account.nonce);
    }

    var tx = new Transaction(rawTx);
    tx.sign(privateKey);

    var tx_hash = self.toHex(tx.hash());

    self.stateTrie.checkpoint();

    self.vm.runTx({
      tx: tx,
      block: block
    }, function(err, results) {
      self.stateTrie.revert();

      if (err) {
        callback(err);
        return;
      }

      if (results.error != null) {
        callback(new Error("VM error: " + results.error));
        return;
      }

      if (results.vm.exception != 1) {
        callback(new Error("VM Exception while executing transaction: " + results.vm.exceptionError));
        return;
      }

      callback(null, self.toHex(results.vm.return || "0x0"));
    });
  });
};

module.exports = Blockchain;
<|endoftext|>


<commit_before>'use strict';

// Module dependencies
var path = require('path');

// Set module root directory
process.rootTest = __dirname;
process.requireTest = function(filePath) {
  return require(path.normalize(process.rootTest + '/' + filePath));
};

module.exports.generator = process.requireTest('lib/generator.js');
<commit_msg>Replace wrong use of path.normalize<commit_after>'use strict';

// Module dependencies
var path = require('path');

// Set module root directory
process.rootTest = __dirname;
process.requireTest = function(filePath) {
  return require(path.join(process.rootTest, filePath));
};

module.exports.generator = process.requireTest('lib/generator.js');
<|endoftext|>


<commit_before>var csv = require('fast-csv');
var async = require('async');
var redis = require('redis-url');
var request = require('request');

var fs = require('fs');
var querystring = require('querystring');
var stream = require('stream');
var util = require('util');

var package = JSON.parse(fs.readFileSync(__dirname+'/package.json', 'utf8'));

var blackholeCacheQueue = async.queue(function(task, callback){
  setTimeout(function(){
    task.callback(null, 'null');
    callback();
  }, 100);
}, 512);
blackholeCacheQueue.set = function(key, value, callback){
  if (callback) process.nextTick(callback);
};

var redisClient;
var redisCacheQueue = async.queue(function(task, callback){
  redisClient.get(task.key, function(err, reply){
    process.nextTick(function(){
      task.callback(err, reply);
      callback();
    });
  });
}, 64);
redisCacheQueue.set = function(key, value, callback){
  redisClient.set(key, value, callback);
};

var zip5 = function(inputZip){
  var zip = inputZip;
  if (!zip) return '';

  zip = zip.split('-')[0];

  if (zip.length >= 7) {
    zip = zip.substr(0, zip.length-4);
  }

  while (zip.length < 5) {
    zip = '0'+zip;
  }

  var intZip = zip*1;

  if (zip.length != 5 || intZip < 501 || intZip > 99950) {
    throw new Error('bad zip: '+inputZip);
  }

  return zip;
};

var cacheKeyGenerator = function(row, options){
  var zipCode = row[options.zipcodeCol];
  if (zipCode) {
    try {
      zipCode = zip5(zipCode);
    } catch (err) {
      zipCode = '';
    }
  }
  var key = package.version + ':' + row[options.streetCol] + ':' + (
    zipCode
      ? zipCode
      : row[options.cityCol] + ':' +
        row[options.stateCol]
  );
  key = key.toUpperCase();
  return key;
};

var structuredRow = function(structure, row, prefix, suffix){
  var output = {};
  var addField = function(header, value){
    if (prefix) {
      header = prefix+header;
    }
    if (suffix) {
      header = header+suffix;
    }
    output[header] = value || null;
  };

  for (var key in structure) {
    var value = structure[key];
    if (typeof value == 'object') {
      for (var subkey in value) {
        var subvalue = value[subkey];
        if (subvalue) {
          var header = (subvalue === true) ? subkey : subvalue;
          var rowValue = (typeof row[key] == 'object') ? row[key][subkey] : null;
          addField(header, rowValue);
        }
      }
    } else if (value) {
      var header = (value === true) ? key : value;
      addField(header, row[key]);
    }
  }
  return output;
};

var Smartystreets = function(options){
  stream.PassThrough.apply(this);

  var inputStream = csv({headers: true});
  var outputStream = csv.createWriteStream({headers: true});

  this.on('pipe', function(source){
    //redirect pipe(this) to pipe(inputStream)
    source.unpipe(this);
    source.pipe(inputStream);
  });
  this.pipe = function(destination, pipeOptions){
    //when asked to pipe this into something, pipe outputStream instead
    return outputStream.pipe(destination, pipeOptions);
  };

  var columnList;
  var addColumns = function(row){
    var out = [];
    columnList.forEach(function(column){
      out.push(row[column]);
    });
    return out;
  };

  var progress = {
    total: 0,
    cached: 0,
    geocoded: 0
  };

  var pool = {
    maxSockets: 1024
  };

  var cacheQueue = blackholeCacheQueue;

  if (options.redis) {
    redisClient = redis.createClient( (typeof options.redis == 'string') ? options.redis : undefined );
    cacheQueue = redisCacheQueue;
  }

  var self = this;

  //geocoder is a queue which takes arrays of objects, up to 99 at a time
  var geocoder = async.queue(function(rows, callback){
    //turn the rows into something smartystreets can read
    var addressList = rows.map(function(d){
      return {
        street:   d[options.streetCol] || '',
        city:     d[options.cityCol] || '',
        state:    d[options.stateCol] || '',
        zipcode:  d[options.zipcodeCol] || ''
      };
    });

    //send the post request
    request.post({
      uri: 'https://api.smartystreets.com/street-address?'+querystring.stringify({
        'auth-id': options.authId,
        'auth-token': options.authToken
      }),
      json: addressList,
      forever: true, //use http keepAlive
      pool: pool //don't use the default connection pool (for performance)
    }, function(err, response, body){
      if (err || response.statusCode != 200) {
        if (err && err.code == 'ECONNRESET') {
          console.error('connection reset, retrying chunk');
          geocoder.push([rows], function(){
            self.emit('progress', progress);
          });
        } else {
          console.error(err || response.statusCode, 'api error, check your column names');
        }
        callback(err || response.statusCode);
        return;
      }

      var mergeRows = {};

      body.forEach(function(address){
        if (address.candidate_index == 0) {
          var mergeRow = mergeRows[address.input_index] = structuredRow(options.structure, address, options.columnPrefix, options.columnSuffix);

          for (var key in mergeRow) {
            rows[address.input_index][key] = mergeRow[key];
          }

          progress.geocoded++;
        }
      });

      rows.forEach(function(row, i){
        var mergeRow = (typeof mergeRows[i] != 'undefined') ? mergeRows[i] : {};

        for (var key in mergeRow) {
          row[key] = mergeRow[key];
        }

        var id = row.__id__;
        delete row.__id__;
        cacheQueue.set(id, (typeof mergeRows[i] == 'undefined') ? 'false' : JSON.stringify(mergeRows[i]));

        outputStream.write(addColumns(row));

        progress.total++;
      });

      callback();
    });
  }, options.concurrency);

  var checkForSaturation = function(){
    if (geocoder.length() == geocoder.concurrency || cacheQueue.length() == cacheQueue.concurrency) {
      inputStream.pause();
    } else {
      inputStream.resume();
    }
  };
  geocoder.saturated = checkForSaturation;
  geocoder.empty = checkForSaturation;
  cacheQueue.saturated = checkForSaturation;
  cacheQueue.empty = checkForSaturation;

  var rowBuffer = [];

  var firstRecord = true;

  inputStream.on("record", function(data){
    if (firstRecord) {
      var ss_columns = Object.keys(structuredRow(options.structure, {}, options.columnPrefix, options.columnSuffix));
      columnList = Object.keys(data).concat(ss_columns);
      outputStream.write(columnList);
      firstRecord = false;
    }

    data.__id__ = cacheKeyGenerator(data, options);
    cacheQueue.push({
      key: data.__id__,
      callback: function(err, reply){
        reply = JSON.parse(reply);
        if (err || (!reply && reply !== false)) {
          rowBuffer.push(data);
          //split data into chunks of 70 rows each, testing has shown this to be fastest
          if (rowBuffer.length == 70) {
            geocoder.push([rowBuffer], function(){
              self.emit('progress', progress);
            });
            rowBuffer = [];
          }
        } else {
          progress.total++;
          progress.cached++;
          if (reply !== false) {
            progress.geocoded++;
          }

          self.emit('progress', progress);
          for (var key in reply) {
            data[key] = reply[key];
          }
          delete data.__id__;
          outputStream.write(addColumns(data));
        }
      }
    });
  });

  inputStream.on("end", function(){
    var onCacheDrain = function(){
      if (rowBuffer.length > 0) {
        //flush any remaining rows that haven't been geocoded yet
        geocoder.push([rowBuffer], function(){
          self.emit('progress', progress, true);
        });
        rowBuffer = [];
      } else {
        self.emit('progress', progress, true);
      }
      if (geocoder.idle()) {
        //geocoder is done, close the output stream
        onGeocoderDrain();
      } else {
        //geocoder isn't done yet, close the output stream when it finishes
        geocoder.drain = onGeocoderDrain;
      }
    };

    var onGeocoderDrain = function(){
      for (var key in pool) {
        if (key != 'maxSockets') {
          for (var name in pool[key].sockets) {
            pool[key].sockets[name].forEach(function(socket){
              socket.end();
            });
          }
        }
      }
      outputStream.end();
      if (redisClient) {
        redisClient.end();
      }
    };

    if (cacheQueue.idle()) {
      //geocoder is done, close the output stream
      onCacheDrain();
    } else {
      //geocoder isn't done yet, close the output stream when it finishes
      cacheQueue.drain = onCacheDrain;
    }
  });
};

util.inherits(Smartystreets, stream.PassThrough);

module.exports = Smartystreets;
<commit_msg>Retry on DNS failure, don't attempt empty requests, don't attempt to geocode incomplete rows<commit_after>var csv = require('fast-csv');
var async = require('async');
var redis = require('redis-url');
var request = require('request');

var fs = require('fs');
var querystring = require('querystring');
var stream = require('stream');
var util = require('util');

var package = JSON.parse(fs.readFileSync(__dirname+'/package.json', 'utf8'));

var blackholeCacheQueue = async.queue(function(task, callback){
  setTimeout(function(){
    task.callback(null, 'null');
    callback();
  }, 100);
}, 512);
blackholeCacheQueue.set = function(key, value, callback){
  if (callback) process.nextTick(callback);
};

var redisClient;
var redisCacheQueue = async.queue(function(task, callback){
  redisClient.get(task.key, function(err, reply){
    process.nextTick(function(){
      task.callback(err, reply);
      callback();
    });
  });
}, 64);
redisCacheQueue.set = function(key, value, callback){
  redisClient.set(key, value, callback);
};

var zip5 = function(inputZip){
  var zip = inputZip;
  if (!zip) return '';

  zip = zip.split('-')[0];

  if (zip.length >= 7) {
    zip = zip.substr(0, zip.length-4);
  }

  while (zip.length < 5) {
    zip = '0'+zip;
  }

  var intZip = zip*1;

  if (zip.length != 5 || intZip < 501 || intZip > 99950) {
    throw new Error('bad zip: '+inputZip);
  }

  return zip;
};

var cacheKeyGenerator = function(row, options){
  var zipCode = row[options.zipcodeCol];
  if (zipCode) {
    try {
      zipCode = zip5(zipCode);
    } catch (err) {
      zipCode = '';
    }
  }
  var key = package.version + ':' + row[options.streetCol] + ':' + (
    zipCode
      ? zipCode
      : row[options.cityCol] + ':' +
        row[options.stateCol]
  );
  key = key.toUpperCase();
  return key;
};

var structuredRow = function(structure, row, prefix, suffix){
  var output = {};
  var addField = function(header, value){
    if (prefix) {
      header = prefix+header;
    }
    if (suffix) {
      header = header+suffix;
    }
    output[header] = value || null;
  };

  for (var key in structure) {
    var value = structure[key];
    if (typeof value == 'object') {
      for (var subkey in value) {
        var subvalue = value[subkey];
        if (subvalue) {
          var header = (subvalue === true) ? subkey : subvalue;
          var rowValue = (typeof row[key] == 'object') ? row[key][subkey] : null;
          addField(header, rowValue);
        }
      }
    } else if (value) {
      var header = (value === true) ? key : value;
      addField(header, row[key]);
    }
  }
  return output;
};

var Smartystreets = function(options){
  stream.PassThrough.apply(this);

  var inputStream = csv({headers: true});
  var outputStream = csv.createWriteStream({headers: true});

  this.on('pipe', function(source){
    //redirect pipe(this) to pipe(inputStream)
    source.unpipe(this);
    source.pipe(inputStream);
  });
  this.pipe = function(destination, pipeOptions){
    //when asked to pipe this into something, pipe outputStream instead
    return outputStream.pipe(destination, pipeOptions);
  };

  var columnList;
  var addColumns = function(row){
    var out = [];
    columnList.forEach(function(column){
      out.push(row[column]);
    });
    return out;
  };

  var progress = {
    total: 0,
    cached: 0,
    geocoded: 0
  };

  var pool = {
    maxSockets: 1024
  };

  var cacheQueue = blackholeCacheQueue;

  if (options.redis) {
    redisClient = redis.createClient( (typeof options.redis == 'string') ? options.redis : undefined );
    cacheQueue = redisCacheQueue;
  }

  var self = this;

  //geocoder is a queue which takes arrays of objects, up to 99 at a time
  var geocoder = async.queue(function(rows, callback){
    //turn the rows into something smartystreets can read
    var addressList = rows.map(function(d){
      return {
        street:   d[options.streetCol] || '',
        city:     d[options.cityCol] || '',
        state:    d[options.stateCol] || '',
        zipcode:  d[options.zipcodeCol] || ''
      };
    }).filter(function(d){
      if (!d.street) {
        return false;
      }
      if (!d.zipcode || (!d.city && !d.state)) {
        return false;
      }
      return true;
    });

    if (!addressList.length) {
      process.nextTick(callback);
      return;
    }

    //send the post request
    request.post({
      uri: 'https://api.smartystreets.com/street-address?'+querystring.stringify({
        'auth-id': options.authId,
        'auth-token': options.authToken
      }),
      json: addressList,
      forever: true, //use http keepAlive
      pool: pool //don't use the default connection pool (for performance)
    }, function(err, response, body){
      if (err || response.statusCode != 200) {
        if (err && (err.code == 'ECONNRESET' || err.code == 'ENOTFOUND')) {
          console.error('connection failed, retrying chunk');
          geocoder.push([rows], function(){
            self.emit('progress', progress);
          });
        } else {
          console.error(err || response.statusCode, 'api error, check your column names');
        }
        callback(err || response.statusCode);
        return;
      }

      var mergeRows = {};

      body.forEach(function(address){
        if (address.candidate_index == 0) {
          var mergeRow = mergeRows[address.input_index] = structuredRow(options.structure, address, options.columnPrefix, options.columnSuffix);

          for (var key in mergeRow) {
            rows[address.input_index][key] = mergeRow[key];
          }

          progress.geocoded++;
        }
      });

      rows.forEach(function(row, i){
        var mergeRow = (typeof mergeRows[i] != 'undefined') ? mergeRows[i] : {};

        for (var key in mergeRow) {
          row[key] = mergeRow[key];
        }

        var id = row.__id__;
        delete row.__id__;
        cacheQueue.set(id, (typeof mergeRows[i] == 'undefined') ? 'false' : JSON.stringify(mergeRows[i]));

        outputStream.write(addColumns(row));

        progress.total++;
      });

      callback();
    });
  }, options.concurrency);

  var checkForSaturation = function(){
    if (geocoder.length() == geocoder.concurrency || cacheQueue.length() == cacheQueue.concurrency) {
      inputStream.pause();
    } else {
      inputStream.resume();
    }
  };
  geocoder.saturated = checkForSaturation;
  geocoder.empty = checkForSaturation;
  cacheQueue.saturated = checkForSaturation;
  cacheQueue.empty = checkForSaturation;

  var rowBuffer = [];

  var firstRecord = true;

  inputStream.on("record", function(data){
    if (firstRecord) {
      var ss_columns = Object.keys(structuredRow(options.structure, {}, options.columnPrefix, options.columnSuffix));
      columnList = Object.keys(data).concat(ss_columns);
      outputStream.write(columnList);
      firstRecord = false;
    }

    data.__id__ = cacheKeyGenerator(data, options);
    cacheQueue.push({
      key: data.__id__,
      callback: function(err, reply){
        reply = JSON.parse(reply);
        if (err || (!reply && reply !== false)) {
          rowBuffer.push(data);
          //split data into chunks of 70 rows each, testing has shown this to be fastest
          if (rowBuffer.length == 70) {
            geocoder.push([rowBuffer], function(){
              self.emit('progress', progress);
            });
            rowBuffer = [];
          }
        } else {
          progress.total++;
          progress.cached++;
          if (reply !== false) {
            progress.geocoded++;
          }

          self.emit('progress', progress);
          for (var key in reply) {
            data[key] = reply[key];
          }
          delete data.__id__;
          outputStream.write(addColumns(data));
        }
      }
    });
  });

  inputStream.on("end", function(){
    var onCacheDrain = function(){
      if (rowBuffer.length > 0) {
        //flush any remaining rows that haven't been geocoded yet
        geocoder.push([rowBuffer], function(){
          self.emit('progress', progress, true);
        });
        rowBuffer = [];
      } else {
        self.emit('progress', progress, true);
      }
      if (geocoder.idle()) {
        //geocoder is done, close the output stream
        onGeocoderDrain();
      } else {
        //geocoder isn't done yet, close the output stream when it finishes
        geocoder.drain = onGeocoderDrain;
      }
    };

    var onGeocoderDrain = function(){
      for (var key in pool) {
        if (key != 'maxSockets') {
          for (var name in pool[key].sockets) {
            pool[key].sockets[name].forEach(function(socket){
              socket.end();
            });
          }
        }
      }
      outputStream.end();
      if (redisClient) {
        redisClient.end();
      }
    };

    if (cacheQueue.idle()) {
      //geocoder is done, close the output stream
      onCacheDrain();
    } else {
      //geocoder isn't done yet, close the output stream when it finishes
      cacheQueue.drain = onCacheDrain;
    }
  });
};

util.inherits(Smartystreets, stream.PassThrough);

module.exports = Smartystreets;
<|endoftext|>