Guest User

Untitled

a guest
May 27th, 2018
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.49 KB | None | 0 0
  1. 'use strict';
  2.  
  3. const joi = require('joi');
  4.  
  5. const api = require('./api');
  6. const Exchange = require('./exchange');
  7. const xmlParser = require('./parse-xml');
  8.  
  9. const schema = joi
  10. .object({
  11. source: joi.string().required().min(3).max(3).example('EUR'),
  12. target: joi.string().required().min(3).max(3).example('GBP')
  13. })
  14. .unknown()
  15. .required();
  16.  
  17. const defaults = {
  18. timeout: 1000 // 1 sec
  19. };
  20.  
  21. const exchange = async (pair, options = {}) => {
  22. options = Object.assign({}, defaults, options);
  23. const {source, target} = joi.attempt(pair, schema);
  24.  
  25. const {requestApi = api, parser = xmlParser} = options;
  26.  
  27. const exchange = new Exchange(requestApi, parser, options);
  28. const rate = await exchange.convert({source, target});
  29. return {source, target, rate};
  30. };
  31.  
  32. module.exports = exchange;
  33.  
  34. 'use strict';
  35.  
  36. const URL = 'https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml';
  37.  
  38. class Exchange {
  39. constructor(api, parser, options = {}) {
  40. this.api = api;
  41. this.options = options;
  42. this.parser = parser;
  43. }
  44.  
  45. async convert({source, target}) {
  46. if (!this.xml) {
  47. await this.fetch();
  48. this.euroToAll = this.parser(this.xml);
  49. }
  50. const euroToSource = this.euroToAll[source];
  51. const euroToTarget = this.euroToAll[target];
  52. return exchange(euroToSource, euroToTarget);
  53. }
  54.  
  55. async fetch() {
  56. const response = await this.api.fetch(URL, this.options);
  57. this.xml = response.body || '';
  58. }
  59. }
  60.  
  61. function exchange(from, to) {
  62. return round(parseFloat(to) / parseFloat(from));
  63. }
  64.  
  65. function round(result, digits = 4) {
  66. return Math.round(result * (10 ** digits)) / (10 ** digits);
  67. }
  68.  
  69. module.exports = Exchange;
  70.  
  71. 'use strict';
  72.  
  73. const xmldoc = require('xmldoc');
  74. const debug = require('debug')('exchange-rate:parse');
  75.  
  76. const currencies = require('./currencies');
  77.  
  78. const parse = xml => {
  79. const doc = new xmldoc.XmlDocument(xml);
  80. const cube = doc.childNamed('Cube').childNamed('Cube');
  81.  
  82. const rates = currencies.reduce(
  83. (accumulator, currency) => {
  84. const exchange = cube.childWithAttribute('currency', currency);
  85. if (exchange) {
  86. const {rate} = exchange.attr;
  87. accumulator[currency] = rate;
  88. } else {
  89. debug(`Node not found for currency: ${currency}`);
  90. }
  91. return accumulator;
  92. },
  93. {}
  94. );
  95. // Add EUR rate to make it consistent
  96. rates.EUR = '1.0';
  97. return rates;
  98. };
  99.  
  100. module.exports = parse;
  101.  
  102. 'use strict';
  103.  
  104. const got = require('got');
  105.  
  106. module.exports = {
  107. async fetch(url, options = {}) {
  108. return got(url, options);
  109. }
  110. };
Add Comment
Please, Sign In to add comment