Utility for unit conversion

This commit is contained in:
Yemel Jardi 2014-12-01 12:33:45 -03:00
parent 4e5e8e1169
commit d978160ddb
4 changed files with 346 additions and 0 deletions

59
docs/Unit.md Normal file
View File

@ -0,0 +1,59 @@
# Unit
Unit it's a utility for handling and converting bitcoins units. We strongly
recommend you to always use satoshis to represent amount inside your application
and only convert them to other units in the front-end.
The supported units are BTC, mBTC, bits and satoshis. The codes for each unit
can be found as members of the Unit class.
```javascript
var btcCode = Unit.BTC;
var mbtcCode = Unit.mBTC;
var bitsCode = Unit.bits;
var satsCode = Unit.satoshis;
```
There are two ways for creating a unit instance. You can instanciate the class
using a value and a unit code; alternatively if the unit it's fixed you could
you some of the static methods. Check some examples below:
```javascript
var unit;
var amount = 100;
// using a unit code
var unitPreference = Unit.BTC;
unit = new Unit(amount, unitPreference);
// using a known unit
unit = Unit.fromBTC(amount);
unit = Unit.fromMilis(amount);
unit = Unit.fromBits(amount);
unit = Unit.fromSatoshis(amount);
```
Once you have a unit instance, you can check it's representantion in all the
available units. For your convinience the classes expose three ways to acomplish
this. Using the `.to(unitCode)` method, using a fixed unit like `.toSatoshis()`
or by using the accessors.
```javascript
var unit;
// using a unit code
var unitPreference = Unit.BTC;
value = Unit.fromSatoshis(amount).to(unitPreference);
// using a known unit
value = Unit.fromBTC(amount).toBTC();
value = Unit.fromBTC(amount).toMilis();
value = Unit.fromBTC(amount).toBits();
value = Unit.fromBTC(amount).toSatoshis();
// using accessors
value = Unit.fromBTC(amount).BTC;
value = Unit.fromBTC(amount).mBTC;
value = Unit.fromBTC(amount).bits;
value = Unit.fromBTC(amount).satoshis;
```

View File

@ -18,6 +18,7 @@ bitcore.encoding.BufferWriter = require('./lib/encoding/bufferwriter');
bitcore.encoding.Varint = require('./lib/encoding/varint');
// main bitcoin library
bitcore.Unit = require('./lib/unit');
bitcore.Address = require('./lib/address');
bitcore.BIP32 = require('./lib/bip32');
bitcore.Block = require('./lib/block');

175
lib/unit.js Normal file
View File

@ -0,0 +1,175 @@
'use strict';
/**
*
* Bitcore Unit
*
* Utility for handling and converting bitcoins units. The supported units are
* BTC, mBTC, bits and satoshis. A unit instance can be created with an
* amount and a unit code, or alternatively using static methods like {fromBTC}.
* You can consult for different representation of a unit instance using it's
* {to} method, the fixed unit methods like {toSatoshis} or alternatively using
* the unit accessors.
*
* @example
*
* var sats = Unit.fromBTC(1.3).toSatoshis();
* var mili = Unit.fromBits(1.3).to(Unit.mBTC);
* var btc = new Unit(1.3, Unit.bits).BTC;
*
* @param {Number} amount - The amount to be represented
* @param {String} code - The unit of the amount
* @returns {Unit} A new instance of an Unit
*/
function Unit(amount, code) {
this._value = this._from(amount, code);
var self = this;
var defineAccesor = function(key) {
Object.defineProperty(self, key, {
get: function() { return self.to(key); },
enumerable: true,
});
};
Object.keys(UNITS).forEach(defineAccesor);
};
var UNITS = {
"BTC" : [1e8, 8],
"mBTC" : [1e5, 5],
"bits" : [1e2, 2],
"satoshis" : [1, 0]
};
Object.keys(UNITS).forEach(function(key) {
Unit[key] = key;
});
/**
*
* Will return a Unit instance created from an amount in BTC
*
* @param {Number} amount - The amount in BTC
* @returns {Unit} A Unit instance
*/
Unit.fromBTC = function(amount) {
return new Unit(amount, Unit.BTC);
};
/**
*
* Will return a Unit instance created from an amount in mBTC
*
* @param {Number} amount - The amount in mBTC
* @returns {Unit} A Unit instance
*/
Unit.fromMilis = function(amount) {
return new Unit(amount, Unit.mBTC);
};
/**
*
* Will return a Unit instance created from an amount in bits
*
* @param {Number} amount - The amount in bits
* @returns {Unit} A Unit instance
*/
Unit.fromBits = function(amount) {
return new Unit(amount, Unit.bits);
};
/**
*
* Will return a Unit instance created from an amount in satoshis
*
* @param {Number} amount - The amount in satoshis
* @returns {Unit} A Unit instance
*/
Unit.fromSatoshis = function(amount) {
return new Unit(amount, Unit.satoshis);
};
Unit.prototype._from = function(amount, code) {
if (!UNITS[code]) throw Error('Unknown unit code');
return parseInt((amount * UNITS[code][0]).toFixed());
};
/**
*
* Will return the value represented in the specified unit
*
* @param {string} code - The unit code
* @returns {Number} The converted value
*/
Unit.prototype.to = function(code) {
if (!UNITS[code]) throw Error('Unknown unit code');
var value = this._value / UNITS[code][0];
return parseFloat(value.toFixed(UNITS[code][1]));
};
/**
*
* Will return the value represented in BTC
*
* @returns {Number} The value converted to BTC
*/
Unit.prototype.toBTC = function() {
return this.to(Unit.BTC);
};
/**
*
* Will return the value represented in mBTC
*
* @returns {Number} The value converted to mBTC
*/
Unit.prototype.toMilis = function(code) {
return this.to(Unit.mBTC);
};
/**
*
* Will return the value represented in bits
*
* @returns {Number} The value converted to bits
*/
Unit.prototype.toBits = function(code) {
return this.to(Unit.bits);
};
/**
*
* Will return the value represented in satoshis
*
* @returns {Number} The value converted to satoshis
*/
Unit.prototype.toSatoshis = function() {
return this.to(Unit.satoshis);
};
/**
*
* Will return a the string representation of the value in satoshis
*
* @returns {String} the value in satoshis
*/
Unit.prototype.toString = function() {
return this.satoshis + ' satoshis';
};
/**
*
* Will return a string formatted for the console
*
* @returns {String} the value in satoshis
*/
Unit.prototype.inspect = function() {
return '<Unit: ' + this.toString() + '>';
};
module.exports = Unit;

111
test/unit.js Normal file
View File

@ -0,0 +1,111 @@
'use strict';
var should = require('chai').should();
var bitcore = require('..');
var Unit = bitcore.Unit;
describe('Unit', function() {
it('should create an instance', function() {
var unit = new Unit(1.2, "BTC");
should.exist(unit);
});
it('should have property accesors', function() {
var unit = new Unit(1.2, "BTC");
should.exist(unit.BTC);
should.exist(unit.mBTC);
should.exist(unit.bits);
should.exist(unit.satoshis);
});
it('should have constructor helpers', function() {
var unit;
unit = Unit.fromBTC(1.00001);
unit.BTC.should.equal(1.00001);
unit = Unit.fromMilis(1.00001);
unit.mBTC.should.equal(1.00001);
unit = Unit.fromBits(100);
unit.bits.should.equal(100);
unit = Unit.fromSatoshis(8999);
unit.satoshis.should.equal(8999);
});
it('should convert to satoshis correctly', function() {
var unit;
unit = Unit.fromBTC(1.3);
unit.mBTC.should.equal(1300);
unit.bits.should.equal(1300000);
unit.satoshis.should.equal(130000000);
unit = Unit.fromMilis(1.3);
unit.BTC.should.equal(0.0013);
unit.bits.should.equal(1300);
unit.satoshis.should.equal(130000);
unit = Unit.fromBits(1.3);
unit.BTC.should.equal(0.0000013);
unit.mBTC.should.equal(0.0013);
unit.satoshis.should.equal(130);
unit = Unit.fromSatoshis(3);
unit.BTC.should.equal(0.00000003);
unit.mBTC.should.equal(0.00003);
unit.bits.should.equal(0.03);
});
it('should take in count floating point problems', function() {
var unit = Unit.fromBTC(0.00000003);
unit.mBTC.should.equal(0.00003);
unit.bits.should.equal(0.03);
unit.satoshis.should.equal(3);
});
it('should expose unit codes', function() {
should.exist(Unit.BTC);
Unit.BTC.should.equal('BTC');
should.exist(Unit.mBTC);
Unit.mBTC.should.equal('mBTC');
should.exist(Unit.bits);
Unit.bits.should.equal('bits');
should.exist(Unit.satoshis);
Unit.satoshis.should.equal('satoshis');
});
it('should expose shorthand conversion methods', function() {
var unit = new Unit(1.3, "BTC");
unit.toBTC().should.equal(unit.BTC);
unit.toMilis().should.equal(unit.mBTC);
unit.toBits().should.equal(unit.bits);
unit.toSatoshis().should.equal(unit.satoshis);
});
it('should expose a general conversion method', function() {
var unit = new Unit(1.3, "BTC");
unit.to(Unit.BTC).should.equal(unit.BTC);
unit.to(Unit.mBTC).should.equal(unit.mBTC);
unit.to(Unit.bits).should.equal(unit.bits);
unit.to(Unit.satoshis).should.equal(unit.satoshis);
});
it('should have a toString method', function() {
var unit = new Unit(1.3, "BTC");
should.exist(unit.toString);
unit.toString().should.be.a('string');
});
it('should have an inspect method', function() {
var unit = new Unit(1.3, "BTC");
should.exist(unit.inspect);
unit.inspect().should.be.a('string');
});
});