1 | ;
|
2 |
|
3 | var _ = require('lodash');
|
4 |
|
5 | var errors = require('./errors');
|
6 | var $ = require('./util/preconditions');
|
7 |
|
8 | var 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 | */
|
40 | function 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 |
|
67 | Object.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 | */
|
77 | Unit.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 | */
|
88 | Unit.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 | */
|
98 | Unit.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 | */
|
108 | Unit.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 | */
|
118 | Unit.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 | */
|
129 | Unit.fromFiat = function(amount, rate) {
|
130 | return new Unit(amount, rate);
|
131 | };
|
132 |
|
133 | Unit.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 | */
|
146 | Unit.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 | */
|
167 | Unit.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 | */
|
176 | Unit.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 | */
|
185 | Unit.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 | */
|
194 | Unit.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 | */
|
204 | Unit.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 | */
|
213 | Unit.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 | */
|
222 | Unit.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 | */
|
234 | Unit.prototype.inspect = function() {
|
235 | return '<Unit: ' + this.toString() + '>';
|
236 | };
|
237 |
|
238 | module.exports = Unit;
|