@makerdao/currency
Advanced tools
Comparing version 0.9.0 to 0.9.3
@@ -6,4 +6,8 @@ 'use strict'; | ||
}); | ||
exports.createGetCurrency = exports.createCurrencyRatio = exports.Currency = undefined; | ||
exports.createGetCurrency = exports.Currency = undefined; | ||
var _assign = require('babel-runtime/core-js/object/assign'); | ||
var _assign2 = _interopRequireDefault(_assign); | ||
var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); | ||
@@ -13,2 +17,6 @@ | ||
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); | ||
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); | ||
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); | ||
@@ -22,228 +30,11 @@ | ||
var _getIterator2 = require('babel-runtime/core-js/get-iterator'); | ||
var _getIterator3 = _interopRequireDefault(_getIterator2); | ||
var _toArray2 = require('babel-runtime/helpers/toArray'); | ||
var _toArray3 = _interopRequireDefault(_toArray2); | ||
var _assign = require('babel-runtime/core-js/object/assign'); | ||
var _assign2 = _interopRequireDefault(_assign); | ||
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); | ||
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); | ||
var _createClass2 = require('babel-runtime/helpers/createClass'); | ||
var _createClass3 = _interopRequireDefault(_createClass2); | ||
exports.createCurrency = createCurrency; | ||
exports.createCurrencyRatio = createCurrencyRatio; | ||
var _bignumber = require('bignumber.js'); | ||
var _Currency2 = require('./Currency'); | ||
var _bignumber2 = _interopRequireDefault(_bignumber); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function amountToBigNumber(amount) { | ||
if (amount instanceof Currency) return amount.toBigNumber(); | ||
var value = (0, _bignumber2.default)(amount); | ||
if (value.lt(0)) throw new Error('amount cannot be negative'); | ||
if (value.isNaN()) throw new Error('amount "' + amount + '" is not a number'); | ||
return value; | ||
} | ||
var Currency = exports.Currency = _Currency2.Currency; | ||
var Currency = exports.Currency = function () { | ||
function Currency(amount) { | ||
var shift = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; | ||
(0, _classCallCheck3.default)(this, Currency); | ||
if (shift === 'wei') shift = -18; | ||
if (shift === 'ray') shift = -27; | ||
if (shift === 'rad') shift = -45; | ||
this._amount = shift ? amountToBigNumber(amount).shiftedBy(shift) : amountToBigNumber(amount); | ||
this.symbol = '???'; | ||
} | ||
(0, _createClass3.default)(Currency, [{ | ||
key: 'isEqual', | ||
value: function isEqual(other) { | ||
return this._amount.eq(other._amount) && this.symbol == other.symbol; | ||
} | ||
}, { | ||
key: 'toString', | ||
value: function toString() { | ||
var decimals = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 2; | ||
return this._amount.toFixed(decimals) + ' ' + this.symbol; | ||
} | ||
}, { | ||
key: 'toBigNumber', | ||
value: function toBigNumber() { | ||
return this._amount; | ||
} | ||
}, { | ||
key: 'toNumber', | ||
value: function toNumber() { | ||
return this._amount.toNumber(); | ||
} | ||
}, { | ||
key: 'toFixed', | ||
value: function toFixed() { | ||
var shift = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; | ||
if (shift === 'wei') shift = 18; | ||
if (shift === 'ray') shift = 27; | ||
if (shift === 'rad') shift = 45; | ||
// always round down so that we never attempt to spend more than we have | ||
return this._amount.shiftedBy(shift).integerValue(_bignumber2.default.ROUND_DOWN).toFixed(); | ||
} | ||
}, { | ||
key: 'isSameType', | ||
value: function isSameType(other) { | ||
return this.symbol === other.symbol; | ||
} | ||
}]); | ||
return Currency; | ||
}(); | ||
var mathFunctions = [['plus'], ['minus'], ['times', 'multipliedBy'], ['div', 'dividedBy'], ['shiftedBy']]; | ||
var booleanFunctions = [['isLessThan', 'lt'], ['isLessThanOrEqualTo', 'lte'], ['isGreaterThan', 'gt'], ['isGreaterThanOrEqualTo', 'gte'], ['eq']]; | ||
function assertValidOperation(method, left, right) { | ||
var message = 'Invalid operation: ' + left.symbol + ' ' + method + ' ' + right.symbol; | ||
if (!(right instanceof Currency) || left.isSameType(right)) return; | ||
if (right instanceof CurrencyRatio) { | ||
// only supporting Currency as a left operand for now, though we could | ||
// extend this to support ratio-ratio math if needed | ||
switch (method) { | ||
case 'times': | ||
if (left.isSameType(right.denominator)) return; | ||
break; | ||
case 'div': | ||
if (left.isSameType(right.numerator)) return; | ||
break; | ||
} | ||
} else { | ||
switch (method) { | ||
// division between two different units results in a ratio, e.g. USD/DAI | ||
case 'div': | ||
return; | ||
} | ||
} | ||
throw new Error(message); | ||
} | ||
function result(method, left, right, value) { | ||
if (right instanceof CurrencyRatio) { | ||
switch (method) { | ||
case 'times': | ||
return new right.numerator(value); | ||
case 'div': | ||
return new right.denominator(value); | ||
} | ||
} | ||
if (!(right instanceof Currency) || left.isSameType(right)) { | ||
return new left.constructor(value); | ||
} | ||
return new CurrencyRatio(value, left.constructor, right.constructor); | ||
} | ||
function bigNumberFnWrapper(method, isBoolean) { | ||
return function (other) { | ||
assertValidOperation(method, this, other); | ||
var otherBigNumber = other instanceof Currency ? other.toBigNumber() : other; | ||
var value = this.toBigNumber()[method](otherBigNumber); | ||
return isBoolean ? value : result(method, this, other, value); | ||
}; | ||
} | ||
(0, _assign2.default)(Currency.prototype, mathFunctions.reduce(function (output, _ref) { | ||
var _ref2 = (0, _toArray3.default)(_ref), | ||
method = _ref2[0], | ||
aliases = _ref2.slice(1); | ||
output[method] = bigNumberFnWrapper(method); | ||
var _iteratorNormalCompletion = true; | ||
var _didIteratorError = false; | ||
var _iteratorError = undefined; | ||
try { | ||
for (var _iterator = (0, _getIterator3.default)(aliases), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { | ||
var alias = _step.value; | ||
output[alias] = output[method]; | ||
} | ||
} catch (err) { | ||
_didIteratorError = true; | ||
_iteratorError = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion && _iterator.return) { | ||
_iterator.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError) { | ||
throw _iteratorError; | ||
} | ||
} | ||
} | ||
return output; | ||
}, {}), booleanFunctions.reduce(function (output, _ref3) { | ||
var _ref4 = (0, _toArray3.default)(_ref3), | ||
method = _ref4[0], | ||
aliases = _ref4.slice(1); | ||
output[method] = bigNumberFnWrapper(method, true); | ||
var _iteratorNormalCompletion2 = true; | ||
var _didIteratorError2 = false; | ||
var _iteratorError2 = undefined; | ||
try { | ||
for (var _iterator2 = (0, _getIterator3.default)(aliases), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { | ||
var alias = _step2.value; | ||
output[alias] = output[method]; | ||
} | ||
} catch (err) { | ||
_didIteratorError2 = true; | ||
_iteratorError2 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion2 && _iterator2.return) { | ||
_iterator2.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError2) { | ||
throw _iteratorError2; | ||
} | ||
} | ||
} | ||
return output; | ||
}, {})); | ||
var makeCreatorFnWithShift = function makeCreatorFnWithShift(creatorFn, symbol, shift) { | ||
var fn = function fn(amount) { | ||
return creatorFn(amount, shift); | ||
}; | ||
// these two properties are used by getCurrency | ||
fn.symbol = symbol; | ||
fn.shift = shift; | ||
return fn; | ||
}; | ||
function createCurrency(symbol) { | ||
@@ -287,5 +78,5 @@ // This provides short syntax, e.g. ETH(6). We need a wrapper function because | ||
(0, _assign2.default)(creatorFn, { | ||
wei: makeCreatorFnWithShift(creatorFn, symbol, 'wei'), | ||
ray: makeCreatorFnWithShift(creatorFn, symbol, 'ray'), | ||
rad: makeCreatorFnWithShift(creatorFn, symbol, 'rad'), | ||
wei: makeShiftedCreatorFn(creatorFn, symbol, 'wei'), | ||
ray: makeShiftedCreatorFn(creatorFn, symbol, 'ray'), | ||
rad: makeShiftedCreatorFn(creatorFn, symbol, 'rad'), | ||
symbol: symbol, | ||
@@ -301,27 +92,3 @@ isInstance: function isInstance(obj) { | ||
// FIXME: this is not exactly analogous to Currency above, because all the | ||
// different pairs are instances of the same class rather than subclasses in | ||
// their own right. but for now it works fine, because it's the wrapper | ||
// functions that are used externally anyway. so if we want to be consistent, we | ||
// could either create subclasses for each ratio, or refactor Currency so it | ||
// also just stores its symbol in the instance rather than the subclass. | ||
var CurrencyRatio = function (_Currency2) { | ||
(0, _inherits3.default)(CurrencyRatio, _Currency2); | ||
function CurrencyRatio(amount, numerator, denominator, shift) { | ||
(0, _classCallCheck3.default)(this, CurrencyRatio); | ||
var _this2 = (0, _possibleConstructorReturn3.default)(this, (CurrencyRatio.__proto__ || (0, _getPrototypeOf2.default)(CurrencyRatio)).call(this, amount, shift)); | ||
_this2.numerator = numerator; | ||
_this2.denominator = denominator; | ||
_this2.symbol = numerator.symbol + '/' + denominator.symbol; | ||
return _this2; | ||
} | ||
return CurrencyRatio; | ||
}(Currency); | ||
var createCurrencyRatio = exports.createCurrencyRatio = function createCurrencyRatio(wrappedNumerator, wrappedDenominator) { | ||
function createCurrencyRatio(wrappedNumerator, wrappedDenominator) { | ||
var numerator = wrappedNumerator(0).constructor; | ||
@@ -331,3 +98,3 @@ var denominator = wrappedDenominator(0).constructor; | ||
var creatorFn = function creatorFn(amount, shift) { | ||
return new CurrencyRatio(amount, numerator, denominator, shift); | ||
return new _Currency2.CurrencyRatio(amount, numerator, denominator, shift); | ||
}; | ||
@@ -338,8 +105,8 @@ | ||
(0, _assign2.default)(creatorFn, { | ||
wei: makeCreatorFnWithShift(creatorFn, symbol, 'wei'), | ||
ray: makeCreatorFnWithShift(creatorFn, symbol, 'ray'), | ||
rad: makeCreatorFnWithShift(creatorFn, symbol, 'rad'), | ||
wei: makeShiftedCreatorFn(creatorFn, symbol, 'wei'), | ||
ray: makeShiftedCreatorFn(creatorFn, symbol, 'ray'), | ||
rad: makeShiftedCreatorFn(creatorFn, symbol, 'rad'), | ||
symbol: symbol, | ||
isInstance: function isInstance(obj) { | ||
return obj instanceof CurrencyRatio && obj.symbol === symbol; | ||
return obj instanceof _Currency2.CurrencyRatio && obj.symbol === symbol; | ||
} | ||
@@ -349,4 +116,23 @@ }); | ||
return creatorFn; | ||
}; | ||
} | ||
function makeShiftedCreatorFn(creatorFn, symbol, shift) { | ||
var fn = function fn(amount) { | ||
return creatorFn(amount, shift); | ||
}; | ||
// these two properties are used by getCurrency | ||
fn.symbol = symbol; | ||
fn.shift = shift; | ||
return fn; | ||
} | ||
/* | ||
this factory function produces a function that will check input values against a | ||
whitelist; it's useful if you want to accept a variety of inputs, e.g.: | ||
foo(ETH(1)) | ||
foo(1, ETH) | ||
foo(1) // if you set a default unit argument | ||
foo('1') // if you set a default unit argument | ||
*/ | ||
var createGetCurrency = exports.createGetCurrency = function createGetCurrency(currencies) { | ||
@@ -353,0 +139,0 @@ return function (amount, unit) { |
{ | ||
"name": "@makerdao/currency", | ||
"description": "Utilities for working with currency amounts", | ||
"version": "0.9.0", | ||
"version": "0.9.3", | ||
"license": "MIT", | ||
@@ -6,0 +6,0 @@ "main": "dist/index.js", |
@@ -5,1 +5,3 @@ # @makerdao/currency | ||
[dai.js](https://github.com/makerdao/dai.js). | ||
Check out the test file to see how this is used. |
202
src/index.js
@@ -1,153 +0,4 @@ | ||
import BigNumber from 'bignumber.js'; | ||
import { Currency as Currency_, CurrencyRatio } from './Currency'; | ||
export const Currency = Currency_; | ||
function amountToBigNumber(amount) { | ||
if (amount instanceof Currency) return amount.toBigNumber(); | ||
const value = BigNumber(amount); | ||
if (value.lt(0)) throw new Error('amount cannot be negative'); | ||
if (value.isNaN()) throw new Error(`amount "${amount}" is not a number`); | ||
return value; | ||
} | ||
export class Currency { | ||
constructor(amount, shift = 0) { | ||
if (shift === 'wei') shift = -18; | ||
if (shift === 'ray') shift = -27; | ||
if (shift === 'rad') shift = -45; | ||
this._amount = shift | ||
? amountToBigNumber(amount).shiftedBy(shift) | ||
: amountToBigNumber(amount); | ||
this.symbol = '???'; | ||
} | ||
isEqual(other) { | ||
return this._amount.eq(other._amount) && this.symbol == other.symbol; | ||
} | ||
toString(decimals = 2) { | ||
return `${this._amount.toFixed(decimals)} ${this.symbol}`; | ||
} | ||
toBigNumber() { | ||
return this._amount; | ||
} | ||
toNumber() { | ||
return this._amount.toNumber(); | ||
} | ||
toFixed(shift = 0) { | ||
if (shift === 'wei') shift = 18; | ||
if (shift === 'ray') shift = 27; | ||
if (shift === 'rad') shift = 45; | ||
// always round down so that we never attempt to spend more than we have | ||
return this._amount | ||
.shiftedBy(shift) | ||
.integerValue(BigNumber.ROUND_DOWN) | ||
.toFixed(); | ||
} | ||
isSameType(other) { | ||
return this.symbol === other.symbol; | ||
} | ||
} | ||
const mathFunctions = [ | ||
['plus'], | ||
['minus'], | ||
['times', 'multipliedBy'], | ||
['div', 'dividedBy'], | ||
['shiftedBy'] | ||
]; | ||
const booleanFunctions = [ | ||
['isLessThan', 'lt'], | ||
['isLessThanOrEqualTo', 'lte'], | ||
['isGreaterThan', 'gt'], | ||
['isGreaterThanOrEqualTo', 'gte'], | ||
['eq'] | ||
]; | ||
function assertValidOperation(method, left, right) { | ||
const message = `Invalid operation: ${left.symbol} ${method} ${right.symbol}`; | ||
if (!(right instanceof Currency) || left.isSameType(right)) return; | ||
if (right instanceof CurrencyRatio) { | ||
// only supporting Currency as a left operand for now, though we could | ||
// extend this to support ratio-ratio math if needed | ||
switch (method) { | ||
case 'times': | ||
if (left.isSameType(right.denominator)) return; | ||
break; | ||
case 'div': | ||
if (left.isSameType(right.numerator)) return; | ||
break; | ||
} | ||
} else { | ||
switch (method) { | ||
// division between two different units results in a ratio, e.g. USD/DAI | ||
case 'div': | ||
return; | ||
} | ||
} | ||
throw new Error(message); | ||
} | ||
function result(method, left, right, value) { | ||
if (right instanceof CurrencyRatio) { | ||
switch (method) { | ||
case 'times': | ||
return new right.numerator(value); | ||
case 'div': | ||
return new right.denominator(value); | ||
} | ||
} | ||
if (!(right instanceof Currency) || left.isSameType(right)) { | ||
return new left.constructor(value); | ||
} | ||
return new CurrencyRatio(value, left.constructor, right.constructor); | ||
} | ||
function bigNumberFnWrapper(method, isBoolean) { | ||
return function(other) { | ||
assertValidOperation(method, this, other); | ||
const otherBigNumber = | ||
other instanceof Currency ? other.toBigNumber() : other; | ||
const value = this.toBigNumber()[method](otherBigNumber); | ||
return isBoolean ? value : result(method, this, other, value); | ||
}; | ||
} | ||
Object.assign( | ||
Currency.prototype, | ||
mathFunctions.reduce((output, [method, ...aliases]) => { | ||
output[method] = bigNumberFnWrapper(method); | ||
for (let alias of aliases) { | ||
output[alias] = output[method]; | ||
} | ||
return output; | ||
}, {}), | ||
booleanFunctions.reduce((output, [method, ...aliases]) => { | ||
output[method] = bigNumberFnWrapper(method, true); | ||
for (let alias of aliases) { | ||
output[alias] = output[method]; | ||
} | ||
return output; | ||
}, {}) | ||
); | ||
const makeCreatorFnWithShift = (creatorFn, symbol, shift) => { | ||
const fn = amount => creatorFn(amount, shift); | ||
// these two properties are used by getCurrency | ||
fn.symbol = symbol; | ||
fn.shift = shift; | ||
return fn; | ||
}; | ||
export function createCurrency(symbol) { | ||
@@ -179,5 +30,5 @@ // This provides short syntax, e.g. ETH(6). We need a wrapper function because | ||
Object.assign(creatorFn, { | ||
wei: makeCreatorFnWithShift(creatorFn, symbol, 'wei'), | ||
ray: makeCreatorFnWithShift(creatorFn, symbol, 'ray'), | ||
rad: makeCreatorFnWithShift(creatorFn, symbol, 'rad'), | ||
wei: makeShiftedCreatorFn(creatorFn, symbol, 'wei'), | ||
ray: makeShiftedCreatorFn(creatorFn, symbol, 'ray'), | ||
rad: makeShiftedCreatorFn(creatorFn, symbol, 'rad'), | ||
symbol, | ||
@@ -191,19 +42,3 @@ isInstance: obj => obj instanceof CurrencyX | ||
// FIXME: this is not exactly analogous to Currency above, because all the | ||
// different pairs are instances of the same class rather than subclasses in | ||
// their own right. but for now it works fine, because it's the wrapper | ||
// functions that are used externally anyway. so if we want to be consistent, we | ||
// could either create subclasses for each ratio, or refactor Currency so it | ||
// also just stores its symbol in the instance rather than the subclass. | ||
class CurrencyRatio extends Currency { | ||
constructor(amount, numerator, denominator, shift) { | ||
super(amount, shift); | ||
this.numerator = numerator; | ||
this.denominator = denominator; | ||
this.symbol = `${numerator.symbol}/${denominator.symbol}`; | ||
} | ||
} | ||
export const createCurrencyRatio = (wrappedNumerator, wrappedDenominator) => { | ||
export function createCurrencyRatio(wrappedNumerator, wrappedDenominator) { | ||
const numerator = wrappedNumerator(0).constructor; | ||
@@ -218,5 +53,5 @@ const denominator = wrappedDenominator(0).constructor; | ||
Object.assign(creatorFn, { | ||
wei: makeCreatorFnWithShift(creatorFn, symbol, 'wei'), | ||
ray: makeCreatorFnWithShift(creatorFn, symbol, 'ray'), | ||
rad: makeCreatorFnWithShift(creatorFn, symbol, 'rad'), | ||
wei: makeShiftedCreatorFn(creatorFn, symbol, 'wei'), | ||
ray: makeShiftedCreatorFn(creatorFn, symbol, 'ray'), | ||
rad: makeShiftedCreatorFn(creatorFn, symbol, 'rad'), | ||
symbol, | ||
@@ -227,4 +62,21 @@ isInstance: obj => obj instanceof CurrencyRatio && obj.symbol === symbol | ||
return creatorFn; | ||
}; | ||
} | ||
function makeShiftedCreatorFn(creatorFn, symbol, shift) { | ||
const fn = amount => creatorFn(amount, shift); | ||
// these two properties are used by getCurrency | ||
fn.symbol = symbol; | ||
fn.shift = shift; | ||
return fn; | ||
} | ||
/* | ||
this factory function produces a function that will check input values against a | ||
whitelist; it's useful if you want to accept a variety of inputs, e.g.: | ||
foo(ETH(1)) | ||
foo(1, ETH) | ||
foo(1) // if you set a default unit argument | ||
foo('1') // if you set a default unit argument | ||
*/ | ||
export const createGetCurrency = currencies => (amount, unit) => { | ||
@@ -231,0 +83,0 @@ if (amount instanceof Currency) return amount; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
204070
11
686
7
1