From 2180b14e1ff13e01dee2bf14ff5b6468110e1785 Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Mon, 19 Oct 2020 19:36:55 -0700 Subject: [PATCH] feat(price): Added additional endpoints for retrieving market price of BCH --- src/bch-js.js | 2 +- src/price.js | 139 ++++++++++++++++--- test/integration/price.js | 11 +- test/unit/fixtures/price-mocks.js | 214 ++++++++++++++++++++++++++++++ test/unit/price.js | 67 +++++++--- 5 files changed, 391 insertions(+), 42 deletions(-) create mode 100644 test/unit/fixtures/price-mocks.js diff --git a/src/bch-js.js b/src/bch-js.js index 7cbf12a..62d0cc8 100644 --- a/src/bch-js.js +++ b/src/bch-js.js @@ -90,7 +90,7 @@ class BCHJS { this.Generating = new Generating(libConfig) this.HDNode = new HDNode(this.Address) this.Mnemonic = new Mnemonic(this.Address) - this.Price = new Price() + this.Price = new Price(libConfig) this.Script = new Script() this.TransactionBuilder = TransactionBuilder this.TransactionBuilder.setAddress(this.Address) diff --git a/src/price.js b/src/price.js index d14e7b3..d9fe90e 100644 --- a/src/price.js +++ b/src/price.js @@ -1,32 +1,127 @@ const axios = require("axios") -/** - * @api price.current() current() - * @apiName Price. - * @apiGroup Price - * @apiDescription Return current price of BCH in multiple currencies. - * - * @apiExample Example usage: - *(async () => { - * try { - * let current = await bchjs.Price.current('usd'); - * console.log(current); - * } catch(error) { - * console.error(error) - * } - *})() - * - * // 26681 - */ + +let _this + class Price { + constructor(config) { + _this = this + + if (config) { + this.restURL = config.restURL + this.apiToken = config.apiToken + } + + // Add JWT token to the authorization header. + this.axiosOptions = { + headers: { + authorization: `Token ${this.apiToken}` + } + } + + this.axios = axios + } + + /** + * @api price.current() current() + * @apiName Price. + * @apiGroup Price + * @apiDescription Return current price of BCH in multiple currencies. + * This endpoint will be deprecated in favor of getUSD. It uses the Bitcoin.com + * price feed. + * + * @apiExample Example usage: + *(async () => { + * try { + * let current = await bchjs.Price.current('usd'); + * console.log(current); + * } catch(err) { + * console.err(err) + * } + *})() + * + * // 26681 + */ async current(currency = "usd") { try { - const response = await axios.get( + const response = await this.axios.get( `https://index-api.bitcoin.com/api/v0/cash/price/${currency.toLowerCase()}` ) + // console.log(`response.data: ${JSON.stringify(response.data, null, 2)}`) + return response.data.price - } catch (error) { - if (error.response && error.response.data) throw error.response.data - else throw error + } catch (err) { + if (err.response && err.response.data) throw err.response.data + else throw err + } + } + + /** + * @api price.getUsd() getUsd() + * @apiName Price getUsd() + * @apiGroup Price + * @apiDescription Return current price of BCH in USD. + * This endpoint gets the USD price of BCH from the Coinbase API. The price + * comes from bch-api, so it has a better chance of working in Tor. + * + * @apiExample Example usage: + *(async () => { + * try { + * let current = await bchjs.Price.getUsd(); + * console.log(current); + * } catch(err) { + * console.err(err) + * } + *})() + * + * // 266.81 + */ + async getUsd() { + try { + const response = await this.axios.get( + `${this.restURL}price/usd`, + _this.axiosOptions + ) + // console.log(`response.data: ${JSON.stringify(response.data, null, 2)}`) + + return response.data.usd + } catch (err) { + if (err.response && err.response.data) throw err.response.data + else throw err + } + } + + /** + * @api price.rates() rates() + * @apiName Price rates() + * @apiGroup Price + * @apiDescription Return current price of BCH in several different currencies. + * This endpoint gets the price of BCH from the Coinbase API in many different + * currencies. The price + * comes from bch-api, so it has a better chance of working in Tor. + * + * @apiExample Example usage: + *(async () => { + * try { + * let current = await bchjs.Price.rates(); + * console.log(current); + * } catch(err) { + * console.err(err) + * } + *})() + * + */ + async rates() { + try { + const response = await this.axios.get( + `${this.restURL}price/rates`, + _this.axiosOptions + ) + // console.log(`response.data: ${JSON.stringify(response.data, null, 2)}`) + + return response.data + } catch (err) { + if (err.response && err.response.data) throw err.response.data + else throw err } } } diff --git a/test/integration/price.js b/test/integration/price.js index f6e325d..fcc92d9 100644 --- a/test/integration/price.js +++ b/test/integration/price.js @@ -1,4 +1,4 @@ -const assert = require("assert") +const assert = require("chai").assert const BCHJS = require("../../src/bch-js") const bchjs = new BCHJS() @@ -11,4 +11,13 @@ describe("#price", () => { }) }) }) + + describe("#getUsd", () => { + it("should get the USD price of BCH", async () => { + const result = await bchjs.Price.getUsd() + // console.log(result) + + assert.isNumber(result.usd) + }) + }) }) diff --git a/test/unit/fixtures/price-mocks.js b/test/unit/fixtures/price-mocks.js new file mode 100644 index 0000000..ade76b4 --- /dev/null +++ b/test/unit/fixtures/price-mocks.js @@ -0,0 +1,214 @@ +/* + Mocks for price. +*/ + +const mockRates = { + AED: "915.049218", + AFN: "19144.48874646", + ALGO: "826.6633482661356600405", + ALL: "26221.96098759", + AMD: "119977.82663822", + ANG: "446.841810455", + AOA: "162269.774275", + ARS: "19322.704621", + ATOM: "45.5920571010248851205", + AUD: "353.78913716", + AWG: "448.407", + AZN: "424.1182875", + BAL: "18.9361216125975755781", + BAM: "413.75759465", + BAND: "40.84187228461349099275", + BAT: "1169.75444148879972951", + BBD: "498.23", + BCH: "1.0", + BDT: "21107.92000745", + BGN: "413.93197515", + BHD: "93.93578597", + BIF: "481540.76228735", + BMD: "249.115", + BND: "337.84677362", + BOB: "1718.851399565", + BRL: "1396.737982", + BSD: "249.115", + BSV: "1.555324933590611026515", + BTC: "0.021265", + BTN: "18249.513962505", + BWP: "2848.17713393", + BYN: "637.963336685", + BYR: "6379633.36685000049823", + BZD: "501.752236985", + CAD: "328.80838319", + CDF: "488848.679106575", + CGLD: "121.0412516398620018305", + CHF: "226.8989243", + CLF: "7.110489445", + CLP: "196202.978234955", + CNH: "1664.25510705", + CNY: "1666.429881", + COMP: "2.4706436576415750709", + COP: "958730.858397465", + CRC: "150173.845981", + CUC: "248.997666835", + CVE: "23541.3675", + CZK: "5770.848621", + DAI: "247.0463573269230002455", + DASH: "3.327367317363110236645", + DJF: "44315.31795969", + DKK: "1575.7370741", + DOP: "14529.76988648", + DZD: "32107.28592277", + EEK: "3640.489633465", + EGP: "3911.404438", + EOS: "96.6873665825732601419", + ERN: "3736.727740265", + ETB: "9302.454572035", + ETC: "44.91795888928957612395", + ETH: "0.6574429621419051422355", + EUR: "211.595", + FJD: "533.11855575", + FKP: "192.55642863", + GBP: "192.87", + GEL: "804.64145", + GGP: "192.55642863", + GHS: "1448.776859925", + GIP: "192.55642863", + GMD: "12891.70125", + GNF: "2438630.43574976", + GTQ: "1936.689014855", + GYD: "52047.88891278", + HKD: "1930.67861725", + HNL: "6126.43736492", + HRK: "1605.40119007", + HTG: "15682.48428085", + HUF: "77261.419177275", + IDR: "3666848.2425", + ILS: "843.29662455", + IMP: "192.55642863", + INR: "18275.43761675", + IQD: "297176.65680577", + ISK: "34639.44075", + JEP: "192.55642863", + JMD: "36261.061070375", + JOD: "176.622535", + JPY: "26304.9247525", + KES: "27093.7474", + KGS: "20240.23303148", + KHR: "1021526.66327067", + KMF: "104678.164103975", + KNC: "275.5392102643512742545", + KRW: "284115.6575", + KWD: "76.196555935", + KYD: "207.44852333", + KZT: "106578.169689505", + LAK: "2300372.70137523", + LBP: "376426.60931701", + LINK: "22.8704181013371177476", + LKR: "45903.840861165", + LRC: "1428.4116972477063306", + LRD: "48689.521020355", + LSL: "4093.68786226", + LTC: "5.182877353583689269445", + LTL: "803.357262175", + LVL: "163.484459015", + LYD: "340.470203685", + MAD: "2290.86403115", + MDL: "4231.74490411", + MGA: "978918.42727237", + MKD: "13034.71219274", + MKR: "0.43727565410331105846", + MMK: "321367.16219401", + MNT: "706980.17312004", + MOP: "1987.157222705", + MRO: "88934.055", + MTL: "170.32939187", + MUR: "9942.18014823", + MVR: "3836.371", + MWK: "187533.350248305", + MXN: "5285.574344805", + MYR: "1033.2044625", + MZN: "18168.45667469", + NAD: "4120.3621", + NGN: "95465.8503", + NIO: "8675.07065117", + NMR: "8.6886689628111785348", + NOK: "2328.95371465", + NPR: "29198.52701022", + NZD: "378.934057915", + OMG: "74.27621574882972595255", + OMR: "95.913509955", + OXT: "1023.479868529169993565", + PAB: "249.115", + PEN: "892.41413087", + PGK: "870.976539545", + PHP: "12100.979598855", + PKR: "40413.26181118", + PLN: "968.71705891", + PYG: "1750259.579863715", + QAR: "907.08999375", + REN: "758.802924154736515935", + REP: "18.2168190127970744169", + REPV2: "18.225711080673967324", + RON: "1032.33256", + RSD: "24895.307525", + RUB: "19351.4774035", + RWF: "243426.179717085", + SAR: "934.309544225", + SBD: "2013.0584566", + SCR: "4561.388071665", + SEK: "2201.10291435", + SGD: "338.356712025", + SHP: "192.55642863", + SLL: "2482430.971263275", + SOS: "144000.839307095", + SRD: "3525.97371", + SSP: "32449.7199", + STD: "5232524.31108792", + SVC: "2178.147216215", + SZL: "4091.741526765", + THB: "7785.4665375", + TJS: "2568.96954016", + TMT: "871.9025", + TND: "686.00043125", + TOP: "578.0165522", + TRY: "1963.587954325", + TTD: "1689.460313635", + TWD: "7158.9423125", + TZS: "577510.41827928", + UAH: "7061.44019619", + UGX: "931508.2111739", + UMA: "30.09543944427665349095", + UNI: "79.18593747516647884725", + USD: "249.115", + USDC: "249.115", + UYU: "10688.478117885", + UZS: "2582693.606121005", + VEF: "61901998.996866715", + VES: "112695476.713406465", + VND: "5773814.12282902", + VUV: "28486.73470656", + WST: "653.35042289", + XAF: "138884.3079243", + XAG: "10.22661168355", + XAU: "0.1312935696", + XCD: "673.24574325", + XDR: "176.50246157", + XLM: "2936.20532162536435083", + XOF: "138884.3079243", + XPD: "0.1061030608", + XPF: "25265.84267069", + XPT: "0.2910211253", + XRP: "1014.931757995518373565", + XTZ: "113.8135051169590628124", + YER: "62365.930534515", + YFI: "0.0178703370267443543872", + ZAR: "4122.31765275", + ZEC: "3.87305659203980154283", + ZMK: "1308619.842149325", + ZMW: "5027.95231667", + ZRX: "644.844402797695193656", + ZWL: "80215.03" +} + +module.exports = { + mockRates +} diff --git a/test/unit/price.js b/test/unit/price.js index b60a646..a5dce78 100644 --- a/test/unit/price.js +++ b/test/unit/price.js @@ -1,28 +1,59 @@ -const chai = require("chai") -const assert = require("assert") +const assert = require("chai").assert const BCHJS = require("../../src/bch-js") -const bchjs = new BCHJS() -const axios = require("axios") const sinon = require("sinon") +const mockDataLib = require("./fixtures/price-mocks") +let mockData + describe("#Price", () => { + let sandbox + let bchjs + + beforeEach(() => { + sandbox = sinon.createSandbox() + + bchjs = new BCHJS() + + mockData = Object.assign({}, mockDataLib) + }) + + afterEach(() => sandbox.restore()) + describe("#current", () => { - describe("#single currency", () => { - let sandbox - beforeEach(() => (sandbox = sinon.createSandbox())) - afterEach(() => sandbox.restore()) + it("should get current price for single currency", async () => { + sandbox + .stub(bchjs.Price.axios, "get") + .resolves({ data: { price: 24905 } }) - it("should get current price for single currency", done => { - const data = 46347 - const resolved = new Promise(r => r({ data: data })) - sandbox.stub(axios, "get").returns(resolved) + const result = await bchjs.Price.current("usd") + // console.log(result) - bchjs.Price.current("usd") - .then(result => { - assert.deepEqual(data.price, result) - }) - .then(done, done) - }) + assert.isNumber(result) + }) + }) + + describe("#getUsd", () => { + it("should get the USD price of BCH", async () => { + sandbox.stub(bchjs.Price.axios, "get").resolves({ data: { usd: 249.87 } }) + + const result = await bchjs.Price.getUsd() + // console.log(result) + + assert.isNumber(result) + }) + }) + + describe("#rates", () => { + it("should get the price of BCH in several currencies", async () => { + sandbox + .stub(bchjs.Price.axios, "get") + .resolves({ data: mockData.mockRates }) + + const result = await bchjs.Price.rates() + // console.log(result) + + assert.property(result, "USD") + assert.property(result, "CAD") }) }) })