Merge pull request #859 from yemel/feature/fiat-units
Add from/to fiat methods on Unit class
This commit is contained in:
commit
4428eb9eff
|
@ -61,3 +61,19 @@ value = Unit.fromBTC(amount).mBTC;
|
|||
value = Unit.fromBTC(amount).bits;
|
||||
value = Unit.fromBTC(amount).satoshis;
|
||||
```
|
||||
|
||||
## Using a fiat currency
|
||||
|
||||
The unit class also provides a convenient alternative to create an instance from a fiat amount and the corresponding BTC/fiat exchange rate. Any unit instance can be converted to a fiat amount by providing the current exchange rate. Check the example below:
|
||||
|
||||
```javascript
|
||||
var unit, fiat;
|
||||
var amount = 100;
|
||||
var exchangeRate = 350;
|
||||
|
||||
unit = new Unit(amount, exchangeRate);
|
||||
unit = Unit.fromFiat(amount, exchangeRate);
|
||||
|
||||
fiat = Unit.fromBits(amount).atRate(exchangeRate);
|
||||
fiat = Unit.fromBits(amount).to(exchangeRate);
|
||||
```
|
||||
|
|
|
@ -40,6 +40,9 @@ module.exports = [{
|
|||
errors: [{
|
||||
'name': 'UnknownCode',
|
||||
'message': format('Unrecognized unit code: {0}')
|
||||
},{
|
||||
'name': 'InvalidRate',
|
||||
'message': format('Invalid exchange rate: {0}')
|
||||
}]
|
||||
}, {
|
||||
name: 'Transaction',
|
||||
|
|
54
lib/unit.js
54
lib/unit.js
|
@ -1,5 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
var _ = require('lodash');
|
||||
|
||||
var errors = require('./errors');
|
||||
var JSUtil = require('./util/js');
|
||||
|
||||
|
@ -15,19 +17,23 @@ var UNITS = {
|
|||
* Utility for handling and converting bitcoins units. The supported units are
|
||||
* BTC, mBTC, bits (also named uBTC) and satoshis. A unit instance can be created with an
|
||||
* amount and a unit code, or alternatively using static methods like {fromBTC}.
|
||||
* It also allows to be created from a fiat amount and the exchange rate, or
|
||||
* alternatively using the {fromFiat} static method.
|
||||
* 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.
|
||||
* the unit accessors. It also can be converted to a fiat amount by providing the
|
||||
* corresponding BTC/fiat exchange rate.
|
||||
*
|
||||
* @example
|
||||
* ```javascript
|
||||
* var sats = Unit.fromBTC(1.3).toSatoshis();
|
||||
* var mili = Unit.fromBits(1.3).to(Unit.mBTC);
|
||||
* var bits = Unit.fromFiat(1.3, 350).bits;
|
||||
* 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
|
||||
* @param {String|Number} code - The unit of the amount or the exchange rate
|
||||
* @returns {Unit} A new instance of an Unit
|
||||
* @constructor
|
||||
*/
|
||||
|
@ -36,8 +42,14 @@ function Unit(amount, code) {
|
|||
return new Unit(amount, code);
|
||||
}
|
||||
|
||||
this._amount = amount;
|
||||
this._code = code;
|
||||
// convert fiat to BTC
|
||||
if (_.isNumber(code)) {
|
||||
if (code <= 0) {
|
||||
throw new errors.Unit.InvalidRate(code);
|
||||
}
|
||||
amount = amount / code;
|
||||
code = Unit.BTC;
|
||||
}
|
||||
|
||||
this._value = this._from(amount, code);
|
||||
|
||||
|
@ -109,6 +121,17 @@ Unit.fromSatoshis = function(amount) {
|
|||
return new Unit(amount, Unit.satoshis);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a Unit instance created from a fiat amount and exchange rate.
|
||||
*
|
||||
* @param {Number} amount - The amount in fiat
|
||||
* @param {Number} rate - The exchange rate BTC/fiat
|
||||
* @returns {Unit} A Unit instance
|
||||
*/
|
||||
Unit.fromFiat = function(amount, rate) {
|
||||
return new Unit(amount, rate);
|
||||
};
|
||||
|
||||
Unit.prototype._from = function(amount, code) {
|
||||
if (!UNITS[code]) {
|
||||
throw new errors.Unit.UnknownCode(code);
|
||||
|
@ -119,10 +142,17 @@ Unit.prototype._from = function(amount, code) {
|
|||
/**
|
||||
* Returns the value represented in the specified unit
|
||||
*
|
||||
* @param {string} code - The unit code
|
||||
* @param {String|Number} code - The unit code or exchange rate
|
||||
* @returns {Number} The converted value
|
||||
*/
|
||||
Unit.prototype.to = function(code) {
|
||||
if (_.isNumber(code)) {
|
||||
if (code <= 0) {
|
||||
throw new errors.Unit.InvalidRate(code);
|
||||
}
|
||||
return parseFloat((this.BTC * code).toFixed(2));
|
||||
}
|
||||
|
||||
if (!UNITS[code]) {
|
||||
throw new errors.Unit.UnknownCode(code);
|
||||
}
|
||||
|
@ -167,6 +197,16 @@ Unit.prototype.toSatoshis = function() {
|
|||
return this.to(Unit.satoshis);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the value represented in fiat
|
||||
*
|
||||
* @param {string} rate - The exchange rate between BTC/currency
|
||||
* @returns {Number} The value converted to satoshis
|
||||
*/
|
||||
Unit.prototype.atRate = function(rate) {
|
||||
return this.to(rate);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a the string representation of the value in satoshis
|
||||
*
|
||||
|
@ -183,8 +223,8 @@ Unit.prototype.toString = function() {
|
|||
*/
|
||||
Unit.prototype.toObject = function toObject() {
|
||||
return {
|
||||
amount: this._amount,
|
||||
code: this._code
|
||||
amount: this.BTC,
|
||||
code: Unit.BTC
|
||||
};
|
||||
};
|
||||
|
||||
|
|
34
test/unit.js
34
test/unit.js
|
@ -15,10 +15,20 @@ describe('Unit', function() {
|
|||
}).to.not.throw();
|
||||
});
|
||||
|
||||
it('can be created from a number and exchange rate', function() {
|
||||
expect(function() {
|
||||
return new Unit(1.2, 350);
|
||||
}).to.not.throw();
|
||||
});
|
||||
|
||||
it('no "new" is required for creating an instance', function() {
|
||||
expect(function() {
|
||||
return Unit(1.2, 'BTC');
|
||||
}).to.not.throw();
|
||||
|
||||
expect(function() {
|
||||
return Unit(1.2, 350);
|
||||
}).to.not.throw();
|
||||
});
|
||||
|
||||
it('has property accesors "BTC", "mBTC", "uBTC", "bits", and "satoshis"', function() {
|
||||
|
@ -44,6 +54,9 @@ describe('Unit', function() {
|
|||
|
||||
unit = Unit.fromSatoshis('8999');
|
||||
unit.satoshis.should.equal(8999);
|
||||
|
||||
unit = Unit.fromFiat('43', 350);
|
||||
unit.BTC.should.equal(0.12285714);
|
||||
});
|
||||
|
||||
it('should have constructor helpers', function() {
|
||||
|
@ -60,6 +73,9 @@ describe('Unit', function() {
|
|||
|
||||
unit = Unit.fromSatoshis(8999);
|
||||
unit.satoshis.should.equal(8999);
|
||||
|
||||
unit = Unit.fromFiat(43, 350);
|
||||
unit.BTC.should.equal(0.12285714);
|
||||
});
|
||||
|
||||
it('converts to satoshis correctly', function() {
|
||||
|
@ -124,6 +140,15 @@ describe('Unit', function() {
|
|||
unit.toSatoshis().should.equal(unit.satoshis);
|
||||
});
|
||||
|
||||
it('can convert to fiat', function() {
|
||||
var unit = new Unit(1.3, 350);
|
||||
unit.atRate(350).should.equal(1.3);
|
||||
unit.to(350).should.equal(1.3);
|
||||
|
||||
unit = Unit.fromBTC(0.0123);
|
||||
unit.atRate(10).should.equal(0.12);
|
||||
});
|
||||
|
||||
it('toString works as expected', function() {
|
||||
var unit = new Unit(1.3, 'BTC');
|
||||
should.exist(unit.toString);
|
||||
|
@ -156,4 +181,13 @@ describe('Unit', function() {
|
|||
}).to.throw(errors.Unit.UnknownCode);
|
||||
});
|
||||
|
||||
it('fails when the exchange rate is invalid', function() {
|
||||
expect(function() {
|
||||
return new Unit(100, -123);
|
||||
}).to.throw(errors.Unit.InvalidRate);
|
||||
expect(function() {
|
||||
return new Unit(100, 'BTC').atRate(-123);
|
||||
}).to.throw(errors.Unit.InvalidRate);
|
||||
});
|
||||
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue