UNPKG

bluzelle-binary-codec

Version:
91 lines (78 loc) 2.55 kB
'use strict';var _ = require('lodash'); var makeClass = require('../utils/make-class');var _require = require('../utils/bytes-utils'),slice = _require.slice;var _require2 = require('./hash-160'),Hash160 = _require2.Hash160; var ISO_REGEX = /^[A-Z0-9]{3}$/; var HEX_REGEX = /^[A-F0-9]{40}$/; function isoToBytes(iso) { var bytes = new Uint8Array(20); if (iso !== 'XPA') { var isoBytes = iso.split('').map(function (c) {return c.charCodeAt(0);}); bytes.set(isoBytes, 12); } return bytes; } function isISOCode(val) { return val.length === 3; // ISO_REGEX.test(val); } function isHex(val) { return HEX_REGEX.test(val); } function isStringRepr(val) { return _.isString(val) && (isISOCode(val) || isHex(val)); } function isBytesArray(val) { return val.length === 20; } function isValidRepr(val) { return isStringRepr(val) || isBytesArray(val); } function bytesFromRepr(val) { if (isValidRepr(val)) { // We assume at this point that we have an object with a length, either 3, // 20 or 40. return val.length === 3 ? isoToBytes(val) : val; } throw new Error('Unsupported Currency repr: ' + val); } var $uper = Hash160.prototype; var Currency = makeClass({ inherits: Hash160, getters: ['isNative', 'iso'], statics: { init: function init() { this.XPA = new this(new Uint8Array(20)); }, from: function from(val) { return val instanceof this ? val : new this(bytesFromRepr(val)); } }, Currency: function Currency(bytes) { Hash160.call(this, bytes); this.classify(); }, classify: function classify() { // We only have a non null iso() property available if the currency can be // losslessly represented by the 3 letter iso code. If none is available a // hex encoding of the full 20 bytes is the canonical representation. var onlyISO = true; var bytes = this._bytes; var code = slice(this._bytes, 12, 15, Array); var iso = code.map(function (c) {return String.fromCharCode(c);}).join(''); for (var i = bytes.length - 1; i >= 0; i--) { if (bytes[i] !== 0 && !(i === 12 || i === 13 || i === 14)) { onlyISO = false; break; } } var lossLessISO = onlyISO && iso !== 'XPA' && ISO_REGEX.test(iso); this._isNative = onlyISO && _.isEqual(code, [0, 0, 0]); this._iso = this._isNative ? 'XPA' : lossLessISO ? iso : null; }, toJSON: function toJSON() { if (this.iso()) { return this.iso(); } return $uper.toJSON.call(this); } }); module.exports = { Currency: Currency };