UNPKG

5.94 kBJavaScriptView Raw
1'use strict';
2
3var _ = require('lodash');
4
5var errors = require('./errors');
6var $ = require('./util/preconditions');
7
8var UNITS = {
9 'BTC' : [1e8, 8],
10 'mBTC' : [1e5, 5],
11 'uBTC' : [1e2, 2],
12 'bits' : [1e2, 2],
13 'satoshis' : [1, 0]
14};
15
16/**
17 * Utility for handling and converting bitcoins units. The supported units are
18 * BTC, mBTC, bits (also named uBTC) and satoshis. A unit instance can be created with an
19 * amount and a unit code, or alternatively using static methods like {fromBTC}.
20 * It also allows to be created from a fiat amount and the exchange rate, or
21 * alternatively using the {fromFiat} static method.
22 * You can consult for different representation of a unit instance using it's
23 * {to} method, the fixed unit methods like {toSatoshis} or alternatively using
24 * the unit accessors. It also can be converted to a fiat amount by providing the
25 * corresponding BTC/fiat exchange rate.
26 *
27 * @example
28 * ```javascript
29 * var sats = Unit.fromBTC(1.3).toSatoshis();
30 * var mili = Unit.fromBits(1.3).to(Unit.mBTC);
31 * var bits = Unit.fromFiat(1.3, 350).bits;
32 * var btc = new Unit(1.3, Unit.bits).BTC;
33 * ```
34 *
35 * @param {Number} amount - The amount to be represented
36 * @param {String|Number} code - The unit of the amount or the exchange rate
37 * @returns {Unit} A new instance of an Unit
38 * @constructor
39 */
40function Unit(amount, code) {
41 if (!(this instanceof Unit)) {
42 return new Unit(amount, code);
43 }
44
45 // convert fiat to BTC
46 if (_.isNumber(code)) {
47 if (code <= 0) {
48 throw new errors.Unit.InvalidRate(code);
49 }
50 amount = amount / code;
51 code = Unit.BTC;
52 }
53
54 this._value = this._from(amount, code);
55
56 var self = this;
57 var defineAccesor = function(key) {
58 Object.defineProperty(self, key, {
59 get: function() { return self.to(key); },
60 enumerable: true,
61 });
62 };
63
64 Object.keys(UNITS).forEach(defineAccesor);
65}
66
67Object.keys(UNITS).forEach(function(key) {
68 Unit[key] = key;
69});
70
71/**
72 * Returns a Unit instance created from JSON string or object
73 *
74 * @param {String|Object} json - JSON with keys: amount and code
75 * @returns {Unit} A Unit instance
76 */
77Unit.fromObject = function fromObject(data){
78 $.checkArgument(_.isObject(data), 'Argument is expected to be an object');
79 return new Unit(data.amount, data.code);
80};
81
82/**
83 * Returns a Unit instance created from an amount in BTC
84 *
85 * @param {Number} amount - The amount in BTC
86 * @returns {Unit} A Unit instance
87 */
88Unit.fromBTC = function(amount) {
89 return new Unit(amount, Unit.BTC);
90};
91
92/**
93 * Returns a Unit instance created from an amount in mBTC
94 *
95 * @param {Number} amount - The amount in mBTC
96 * @returns {Unit} A Unit instance
97 */
98Unit.fromMillis = Unit.fromMilis = function(amount) {
99 return new Unit(amount, Unit.mBTC);
100};
101
102/**
103 * Returns a Unit instance created from an amount in bits
104 *
105 * @param {Number} amount - The amount in bits
106 * @returns {Unit} A Unit instance
107 */
108Unit.fromMicros = Unit.fromBits = function(amount) {
109 return new Unit(amount, Unit.bits);
110};
111
112/**
113 * Returns a Unit instance created from an amount in satoshis
114 *
115 * @param {Number} amount - The amount in satoshis
116 * @returns {Unit} A Unit instance
117 */
118Unit.fromSatoshis = function(amount) {
119 return new Unit(amount, Unit.satoshis);
120};
121
122/**
123 * Returns a Unit instance created from a fiat amount and exchange rate.
124 *
125 * @param {Number} amount - The amount in fiat
126 * @param {Number} rate - The exchange rate BTC/fiat
127 * @returns {Unit} A Unit instance
128 */
129Unit.fromFiat = function(amount, rate) {
130 return new Unit(amount, rate);
131};
132
133Unit.prototype._from = function(amount, code) {
134 if (!UNITS[code]) {
135 throw new errors.Unit.UnknownCode(code);
136 }
137 return parseInt((amount * UNITS[code][0]).toFixed());
138};
139
140/**
141 * Returns the value represented in the specified unit
142 *
143 * @param {String|Number} code - The unit code or exchange rate
144 * @returns {Number} The converted value
145 */
146Unit.prototype.to = function(code) {
147 if (_.isNumber(code)) {
148 if (code <= 0) {
149 throw new errors.Unit.InvalidRate(code);
150 }
151 return parseFloat((this.BTC * code).toFixed(2));
152 }
153
154 if (!UNITS[code]) {
155 throw new errors.Unit.UnknownCode(code);
156 }
157
158 var value = this._value / UNITS[code][0];
159 return parseFloat(value.toFixed(UNITS[code][1]));
160};
161
162/**
163 * Returns the value represented in BTC
164 *
165 * @returns {Number} The value converted to BTC
166 */
167Unit.prototype.toBTC = function() {
168 return this.to(Unit.BTC);
169};
170
171/**
172 * Returns the value represented in mBTC
173 *
174 * @returns {Number} The value converted to mBTC
175 */
176Unit.prototype.toMillis = Unit.prototype.toMilis = function() {
177 return this.to(Unit.mBTC);
178};
179
180/**
181 * Returns the value represented in bits
182 *
183 * @returns {Number} The value converted to bits
184 */
185Unit.prototype.toMicros = Unit.prototype.toBits = function() {
186 return this.to(Unit.bits);
187};
188
189/**
190 * Returns the value represented in satoshis
191 *
192 * @returns {Number} The value converted to satoshis
193 */
194Unit.prototype.toSatoshis = function() {
195 return this.to(Unit.satoshis);
196};
197
198/**
199 * Returns the value represented in fiat
200 *
201 * @param {string} rate - The exchange rate between BTC/currency
202 * @returns {Number} The value converted to satoshis
203 */
204Unit.prototype.atRate = function(rate) {
205 return this.to(rate);
206};
207
208/**
209 * Returns a the string representation of the value in satoshis
210 *
211 * @returns {string} the value in satoshis
212 */
213Unit.prototype.toString = function() {
214 return this.satoshis + ' satoshis';
215};
216
217/**
218 * Returns a plain object representation of the Unit
219 *
220 * @returns {Object} An object with the keys: amount and code
221 */
222Unit.prototype.toObject = Unit.prototype.toJSON = function toObject() {
223 return {
224 amount: this.BTC,
225 code: Unit.BTC
226 };
227};
228
229/**
230 * Returns a string formatted for the console
231 *
232 * @returns {string} the value in satoshis
233 */
234Unit.prototype.inspect = function() {
235 return '<Unit: ' + this.toString() + '>';
236};
237
238module.exports = Unit;