+28
-23
| #!/usr/bin/env node | ||
| 'use strict'; | ||
| var pkg = require('./package.json'); | ||
| var currency = require('./'); | ||
| var argv = process.argv.slice(2); | ||
| const currency = require('./') | ||
| const argv = process.argv.slice(2) | ||
| const updateNotifier = require('update-notifier'); | ||
| updateNotifier({pkg}).notify(); | ||
| const updateNotifier = require('update-notifier') | ||
| const pkg = require('./package.json') | ||
| updateNotifier({pkg}).notify() | ||
| function help() { | ||
| console.log([ | ||
| '', | ||
| ' ' + pkg.description, | ||
| ' ' + pkg.description, | ||
| '', | ||
| ' Example', | ||
| ' currency 10 usd dkk', | ||
| ' $ currency 10 usd dkk', | ||
| ' => 10 USD = 62.208 DKK', | ||
| '', | ||
| ' => 57.75516' | ||
| ].join('\n')); | ||
| ' See readme.md for detailed usage.' | ||
| ].join('\n')) | ||
| } | ||
| if (argv.indexOf('--help') !== -1) { | ||
| help(); | ||
| return; | ||
| help() | ||
| return | ||
| } | ||
| if (argv.indexOf('--version') !== -1) { | ||
| console.log(pkg.version); | ||
| return; | ||
| console.log(pkg.version) | ||
| return | ||
| } | ||
| var opts = { | ||
| amount: argv[0], | ||
| from: argv[1], | ||
| to: argv[2] | ||
| }; | ||
| let opts = { | ||
| amount: argv[0] || 1, | ||
| from: (argv[1] || 'USD').toUpperCase(), | ||
| to: (argv[2] || 'BTC').toUpperCase() | ||
| } | ||
| currency(opts).then(console.log).catch(err => { | ||
| console.log(err); | ||
| currency(opts) | ||
| .then(result => { | ||
| console.log(`${opts.amount} ${opts.from} = ${result} ${opts.to}`) | ||
| }) | ||
| .catch(err => { | ||
| console.log(err) | ||
| process.exit(1); | ||
| }); | ||
| process.exit(1) | ||
| }) |
+83
-21
@@ -1,32 +0,94 @@ | ||
| 'use strict'; | ||
| const got = require('got') | ||
| const money = require('money') | ||
| const got = require('got'); | ||
| const money = require('money'); | ||
| const FIXER_URL = 'https://api.fixer.io/latest' | ||
| const BLOCKCHAIN_URL = 'https://blockchain.info/ticker' | ||
| const ETHERCHAIN_URL = 'https://etherchain.org/api/statistics/price' | ||
| const path = 'https://api.fixer.io/latest'; | ||
| const CURRENCY_BITCOIN = 'BTC' | ||
| const CURRENCY_ETHEREUM = 'ETH' | ||
| let isAnyBTC = (from, to) => [from, to].includes(CURRENCY_BITCOIN) | ||
| let isAnyETH = (from, to) => [from, to].includes(CURRENCY_ETHEREUM) | ||
| const httpOpts = { | ||
| json: true | ||
| } | ||
| module.exports = (opts) => { | ||
| if (opts.amount === void 0) { | ||
| opts.amount = 1; | ||
| } | ||
| let { | ||
| amount = 1, | ||
| from = 'USD', | ||
| to = CURRENCY_BITCOIN | ||
| } = opts | ||
| if (opts.from === void 0) { | ||
| opts.from = 'usd'; | ||
| let base = from | ||
| let promises = [] | ||
| const anyBTC = isAnyBTC(from, to) | ||
| const anyETH = isAnyETH(from, to) | ||
| if (anyBTC) { | ||
| base = (from === CURRENCY_BITCOIN) ? to : from | ||
| promises.push(got(BLOCKCHAIN_URL, httpOpts)) | ||
| } | ||
| if (opts.to === void 0) { | ||
| opts.to = 'dkk'; | ||
| if (anyETH) { | ||
| // always default base to USD when dealing with Etherum | ||
| base = 'USD' | ||
| promises.push(got(ETHERCHAIN_URL, httpOpts)) | ||
| } | ||
| return got(path, {json:true}).then(response => { | ||
| money.base = response.body.base; | ||
| money.rates = response.body.rates; | ||
| promises.unshift(got(`${FIXER_URL}?base=${base}`, httpOpts)) | ||
| const converted = money.convert(opts.amount, { | ||
| from: opts.from.toUpperCase(), | ||
| to: opts.to.toUpperCase() | ||
| }); | ||
| return Promise.all(promises).then(result => { | ||
| let [fixer] = result | ||
| return Number(converted.toFixed(3)); | ||
| }); | ||
| }; | ||
| money.base = fixer.body.base | ||
| money.rates = fixer.body.rates | ||
| let conversionOpts = { | ||
| from, | ||
| to | ||
| } | ||
| if (anyBTC) { | ||
| let blockchain = result.find(r => r.body.hasOwnProperty(base)) | ||
| Object.assign(money.rates, { | ||
| BTC: blockchain.body[base].last | ||
| }) | ||
| } | ||
| if (anyETH) { | ||
| let etherchain = result.find(r => r.body.hasOwnProperty('data') && r.body.status === 1) | ||
| let {usd} = etherchain.body.data[etherchain.body.data.length - 1] | ||
| let ethTo = to === CURRENCY_ETHEREUM ? from : to | ||
| let etherumConversionOpts = { | ||
| from: 'USD', // always convert from USD | ||
| to: ethTo | ||
| } | ||
| let eth = money.convert(usd, etherumConversionOpts) | ||
| // set proper base | ||
| money.base = ethTo | ||
| Object.assign(money.rates, { | ||
| ETH: eth | ||
| }) | ||
| } | ||
| if (anyBTC || anyETH) { | ||
| // swap the conversion opts | ||
| Object.assign(conversionOpts, { | ||
| from: to, | ||
| to: from | ||
| }) | ||
| } | ||
| return money.convert(amount, conversionOpts) | ||
| }) | ||
| } |
+9
-7
| { | ||
| "name": "currency", | ||
| "version": "3.0.0", | ||
| "description": "simple currency conversion cli using openexchangerates.org", | ||
| "version": "4.0.0", | ||
| "description": "simple currency conversion cli", | ||
| "main": "index.js", | ||
@@ -10,3 +10,5 @@ "keywords": [ | ||
| "rates", | ||
| "convert" | ||
| "convert", | ||
| "bitcoin", | ||
| "etherum" | ||
| ], | ||
@@ -21,5 +23,5 @@ "license": "MIT", | ||
| "dependencies": { | ||
| "got": "6.1.1", | ||
| "got": "7.1.0", | ||
| "money": "0.2.0", | ||
| "update-notifier": "0.6.0" | ||
| "update-notifier": "2.2.0" | ||
| }, | ||
@@ -40,5 +42,5 @@ "author": { | ||
| "devDependencies": { | ||
| "ava": "0.12.0", | ||
| "nock": "7.2.2" | ||
| "ava": "0.22.0", | ||
| "nock": "9.0.19" | ||
| } | ||
| } |
+24
-3
| # currency [](https://travis-ci.org/srn/currency) | ||
| > simple currency conversion cli using [fixer.io](http://fixer.io/) | ||
| > simple currency conversion cli using [fixer.io](http://fixer.io), [blockchain.info](https://blockchain.info) and [etherchain.org](https://etherchain.org) | ||
@@ -11,2 +11,8 @@ ## Install | ||
| ## Currencies | ||
| - All currencies listed in the [European Central Bank](https://www.ecb.europa.eu/stats/policy_and_exchange_rates/euro_reference_exchange_rates/html/index.en.html) API | ||
| - Bitcoin using [blockchain.info](https://blockchain.info) | ||
| - Ethereum using [etherchain.org](https://etherchain.org) | ||
| ## CLI | ||
@@ -20,9 +26,24 @@ | ||
| Example | ||
| currency 10 usd dkk | ||
| $ currency 10 usd dkk | ||
| => 10 USD = 62.208 DKK | ||
| => 57.75516 | ||
| $ currency 1 btc usd | ||
| => 1 BTC = 3746.18 USD | ||
| $ currency 500 usd btc | ||
| => 500 USD = 0.13358982579886716 BTC | ||
| $ currency 1 eth usd | ||
| => 1 ETH = 282.81 USD | ||
| $ currency 500 usd eth | ||
| => 500 USD = 1.767971429581698 ETH | ||
| ``` | ||
| ## API | ||
| ## License | ||
| MIT © [Søren Brokær](http://srn.io) |
+115
-22
@@ -1,30 +0,123 @@ | ||
| import test from 'ava'; | ||
| import nock from 'nock'; | ||
| import test from 'ava' | ||
| import nock from 'nock' | ||
| import currency from './'; | ||
| import currency from './' | ||
| test.beforeEach(t => { | ||
| const exchangeRates = { | ||
| base: 'USD', | ||
| rates: { | ||
| DKK: 5.775516, | ||
| MYR: 3.230421 | ||
| } | ||
| }; | ||
| nock('https://api.fixer.io') | ||
| .get('/latest?base=USD') | ||
| .reply(200, { | ||
| base: 'USD', | ||
| rates: { | ||
| DKK: 6.2208 | ||
| } | ||
| }) | ||
| nock('https://api.fixer.io') | ||
| .get('/latest') | ||
| .reply(200, exchangeRates); | ||
| }); | ||
| .get('/latest?base=DKK') | ||
| .reply(200, { | ||
| base: 'DKK', | ||
| rates: { | ||
| USD: 0.16075 | ||
| } | ||
| }) | ||
| test('convert 10 usd to dkk', async t => { | ||
| var opts = { | ||
| amount: 10, | ||
| from: 'usd', | ||
| to: 'dkk' | ||
| }; | ||
| nock('https://blockchain.info') | ||
| .get('/ticker') | ||
| .reply(200, { | ||
| "USD" : {"15m" : 3755.12, "last" : 3755.12, "buy" : 3755.29, "sell" : 3754.95, "symbol" : "$"}, | ||
| "DKK" : {"15m" : 23383.98, "last" : 23383.98, "buy" : 23385.04, "sell" : 23382.92, "symbol" : "kr"} | ||
| }) | ||
| const converted = currency(opts); | ||
| nock('https://etherchain.org') | ||
| .get('/api/statistics/price') | ||
| .reply(200, { | ||
| "status": 1, | ||
| "data": [ | ||
| { | ||
| "time": "2017-09-23T16:10:56.000Z", | ||
| "usd": 278.91 | ||
| } | ||
| ] | ||
| }) | ||
| }) | ||
| t.is(await converted, 57.755); | ||
| }); | ||
| test('convert 1 USD to DKK', async t => { | ||
| const converted = currency({ | ||
| amount: 1, | ||
| from: 'USD', | ||
| to: 'DKK' | ||
| }) | ||
| t.is(await converted, 6.2208) | ||
| }) | ||
| test('convert 1 DKK to USD', async t => { | ||
| const converted = currency({ | ||
| amount: 1, | ||
| from: 'DKK', | ||
| to: 'USD' | ||
| }) | ||
| t.is(await converted, 0.16075) | ||
| }) | ||
| test('convert 1 BTC to USD', async t => { | ||
| const converted = currency({ | ||
| amount: 1, | ||
| from: 'BTC', | ||
| to: 'USD' | ||
| }) | ||
| t.is(await converted, 3755.12) | ||
| }) | ||
| test('convert 1 BTC to DKK', async t => { | ||
| const converted = currency({ | ||
| amount: 1, | ||
| from: 'BTC', | ||
| to: 'DKK' | ||
| }) | ||
| t.is(await converted, 23383.98) | ||
| }) | ||
| test('convert 1 DKK to BTC', async t => { | ||
| const converted = currency({ | ||
| amount: 1, | ||
| from: 'DKK', | ||
| to: 'BTC' | ||
| }) | ||
| t.is(await converted, 0.00004276431984632214) | ||
| }) | ||
| test('convert 1 ETH to USD', async t => { | ||
| const converted = currency({ | ||
| amount: 1, | ||
| from: 'ETH', | ||
| to: 'USD' | ||
| }) | ||
| t.is(await converted, 278.91) | ||
| }) | ||
| test('convert 1 ETH to DKK', async t => { | ||
| const converted = currency({ | ||
| amount: 1, | ||
| from: 'ETH', | ||
| to: 'DKK' | ||
| }) | ||
| t.is(await converted, 1735.043328) | ||
| }) | ||
| test('convert 1 USD to ETH', async t => { | ||
| const converted = currency({ | ||
| amount: 1, | ||
| from: 'USD', | ||
| to: 'ETH' | ||
| }) | ||
| t.is(await converted, 0.0035853859667993255) | ||
| }) |
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.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
7420
122.76%212
155.42%48
77.78%1
Infinity%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
Updated
Updated