Compare commits

..
Author SHA1 Message Date
Chris Troutner eb0fba6924 Bumping internal rate limits 2021-03-04 19:27:31 -08:00
Chris Troutner ed6c612be9 Merge branch 'master' into basic-auth-only 2021-03-04 19:12:17 -08:00
Chris Troutner 7cafb11c0d Merge pull request #110 from Permissionless-Software-Foundation/dh-price-route
fix(route): Stablished route to get bch usd price
2021-03-04 09:42:36 -08:00
Daniel Gonzalez dce665b174 fix(route): Stablished route to get bch usd price 2021-03-04 13:35:58 -04:00
Chris Troutner 43c1ee9b69 Merge pull request #109 from Permissionless-Software-Foundation/dh-price
feat(price): Added BCH price feed to bch-api from Coinex
2021-03-03 08:26:54 -08:00
Daniel Gonzalez 4b95fa127c feat(price): Added BCH price feed to bch-api from Coinex 2021-03-02 22:02:32 -04:00
Chris Troutner 9969ccafac Testing proLimits in usrObj 2021-02-25 07:19:30 -08:00
Chris Troutner 5f1e7d88bb Merge branch 'master' into basic-auth-only 2021-02-25 07:08:16 -08:00
Chris Troutner 1a115a0012 Removing debugging line 2021-02-11 13:55:45 -08:00
Chris Troutner 442b802b79 Merge branch 'master' into basic-auth-only 2021-02-11 13:55:27 -08:00
Chris Troutner 9e895bb0bd Debugging validateTxid2 2021-02-11 13:41:08 -08:00
Chris Troutner 0a0644d05c Merge branch 'master' into basic-auth-only 2021-02-11 12:57:08 -08:00
Chris Troutner 1a57177e4a Merge branch 'master' into basic-auth-only 2021-02-11 12:52:24 -08:00
Chris Troutner 039348aa24 Merge branch 'master' into basic-auth-only 2021-02-11 12:11:13 -08:00
Chris Troutner 2c147d518e Changing Dockerfile to basic-auth-only branch 2021-02-06 23:17:58 +01:00
Chris Troutner fb78033a67 Merging from master 2021-01-26 12:41:06 -08:00
Chris Troutner 33d1c74143 Merge branch 'master' into basic-auth-only 2020-12-25 06:07:38 -08:00
Chris Troutner 7b927da53b Merge branch 'master' into basic-auth-only 2020-12-13 09:33:01 -08:00
Chris Troutner 74c8ceb962 Merge branch 'master' into basic-auth-only 2020-12-07 13:11:05 -08:00
Chris Troutner 83a5db5ac7 Merge branch 'master' into basic-auth-only 2020-11-22 10:25:51 -08:00
Chris Troutner a1366bf46f Increasing anon_limits to effectively disable JWT 2020-11-12 09:12:53 -08:00
6 changed files with 136 additions and 8 deletions
+1
View File
@@ -18,6 +18,7 @@ USER safeuser
WORKDIR /home/safeuser
RUN git clone https://github.com/Permissionless-Software-Foundation/bch-api
WORKDIR /home/safeuser/bch-api
RUN git checkout basic-auth-only
RUN npm install --silent
# Generate documentation
+9 -3
View File
@@ -8,6 +8,10 @@
The rate limits below were originially coded with the idea of charging on a
per-resource basis. However, that was confusing to end users trying to purchase
a subscription. So everything was simplied to two tiers: paid and anonymous
CT 3/4/21: I increased the total points from 1,000 to 100,000 to prevent systems
with Basic Authentication from hitting internal rate limits when calling
hydrateUtxos().
*/
'use strict'
@@ -19,7 +23,9 @@ const jwt = require('jsonwebtoken')
const wlogger = require('../util/winston-logging')
const config = require('../../config')
const ANON_LIMITS = config.anonRateLimit
// Hard coding limits since basic-authentiation is assumed to be the primary access.
const ANON_LIMITS = 333
const WHITELIST_RATE_LIMIT = config.whitelistRateLimit
const WHITELIST_DOMAINS = config.whitelistDomains
const INTERNAL_RATE_LIMIT = 1
@@ -142,7 +148,7 @@ class RateLimits {
let rateLimit = ANON_LIMITS
// Only evaluate the JWT token if the user is not using Basic Authentication.
if (!req.locals.proLimit) {
if (!req.locals.proLimit && !req.body.usrObj.proLimit) {
// Code here for the rate limiter is adapted from this example:
// https://github.com/animir/node-rate-limiter-flexible/wiki/Overall-example#authorized-and-not-authorized-users
try {
@@ -195,7 +201,7 @@ class RateLimits {
`User ${key} consuming ${pointsToConsume} point for resource ${resource}.`
)
rateLimit = Math.floor(1000 / pointsToConsume)
rateLimit = Math.floor(100000 / pointsToConsume)
// Update the key so that rate limits track both the user and the resource.
key = `${key}-${resource}`
+38
View File
@@ -27,11 +27,15 @@ class Price {
this.coinexPriceUrl =
'https://api.coinex.com/v1/market/ticker?market=bchausdt'
this.bchCoinexPriceUrl =
'https://api.coinex.com/v1/market/ticker?market=bchusdt'
this.router = express.Router()
this.router.get('/', _this.root)
this.router.get('/usd', _this.getUSD)
this.router.get('/rates', _this.getBCHRate)
this.router.get('/bchausd', _this.getBCHAUSD)
this.router.get('/bchusd', _this.getBCHUSD)
}
// DRY error handler.
@@ -150,6 +154,40 @@ class Price {
return _this.errorHandler(err, res)
}
}
/**
* @api {get} /price/bchusd Get the USD price of BCH
* @apiName Get the USD price of BCH
* @apiGroup Price
* @apiDescription Get the USD price of BCH from Coinex.
*
*
* @apiExample Example usage:
* curl -X GET "https://api.fullstack.cash/v4/price/bchusd" -H "accept: application/json"
*
*/
async getBCHUSD (req, res, next) {
try {
// Request options
const opt = {
method: 'get',
baseURL: _this.bchCoinexPriceUrl,
timeout: 15000
}
const response = await axios.request(opt)
// console.log(`response.data: ${JSON.stringify(response.data, null, 2)}`)
const price = Number(response.data.data.ticker.last)
return res.json({ usd: price })
} catch (err) {
// Write out error to error log.
wlogger.error('Error in price.js/getBCHUSD().', err)
return _this.errorHandler(err, res)
}
}
}
module.exports = Price
+14 -5
View File
@@ -36,9 +36,13 @@ util.inspect.defaultOptions = { depth: 5 }
// Determine the Access password for a private instance of SLPDB.
// https://gist.github.com/christroutner/fc717ca704dec3dded8b52fae387eab2
// Password for General Purpose (GP) SLPDB.
const SLPDB_PASS_GP = process.env.SLPDB_PASS_GP ? process.env.SLPDB_PASS_GP : 'BITBOX'
const SLPDB_PASS_GP = process.env.SLPDB_PASS_GP
? process.env.SLPDB_PASS_GP
: 'BITBOX'
// Password for Whitelist (WL) SLPDB.
const SLPDB_PASS_WL = process.env.SLPDB_PASS_WL ? process.env.SLPDB_PASS_WL : 'BITBOX'
const SLPDB_PASS_WL = process.env.SLPDB_PASS_WL
? process.env.SLPDB_PASS_WL
: 'BITBOX'
// const rawtransactions = require('./full-node/rawtransactions')
const RawTransactions = require('./full-node/rawtransactions')
@@ -46,7 +50,7 @@ const rawTransactions = new RawTransactions()
// Setup REST and TREST URLs used by slpjs
// Dev note: this allows for unit tests to mock the URL.
if (!process.env.REST_URL) process.env.REST_URL = 'https://bchn.fullstack.cash/v4/'
if (!process.env.REST_URL) { process.env.REST_URL = 'https://bchn.fullstack.cash/v4/' }
if (!process.env.TREST_URL) {
process.env.TREST_URL = 'https://testnet.fullstack.cash/v4/'
}
@@ -1213,10 +1217,13 @@ class Slp {
msg: ''
}
const path = `${process.env.SLP_API_URL}slp/validate/${txid}`
// console.log(`validate2Single path: ${path}`)
// Request options
const opt = {
method: 'get',
baseURL: `${process.env.SLP_API_URL}slp/validate/${txid}`,
baseURL: path,
timeout: 10000 // Exit after 10 seconds.
}
const tokenRes = await _this.axios.request(opt)
@@ -2117,7 +2124,9 @@ class Slp {
// console.log(`theseUtxos: ${JSON.stringify(theseUtxos, null, 2)}`)
// Get SLP token details.
const details = await _this.bchjs.SLP.Utils.tokenUtxoDetailsWL(theseUtxos)
const details = await _this.bchjs.SLP.Utils.tokenUtxoDetailsWL(
theseUtxos
)
// console.log('details : ', details)
// Replace the original UTXO data with the hydrated data.
+8
View File
@@ -39,6 +39,14 @@ describe('#price', () => {
const result = await price.getBCHAUSD(req, res)
console.log(`result: ${util.inspect(result)}`)
assert.isNumber(result.usd)
})
})
describe('#getBCHUSD', () => {
it('should get the USD price of BCH', async () => {
const result = await price.getBCHUSD(req, res)
console.log(`result: ${util.inspect(result)}`)
assert.isNumber(result.usd)
})
})
+66
View File
@@ -277,4 +277,70 @@ describe('#PriceRouter', () => {
assert.isNumber(result.usd)
})
})
describe('#getBCHUSD', () => {
// const getNetworkInfo = controlRoute.testableComponents.getNetworkInfo
it('should throw 500 when network issues', async () => {
uut.bchCoinexPriceUrl = 'http://fakeurl/api/'
await uut.getBCHUSD(req, res)
// console.log(`result: ${util.inspect(result)}`)
assert.isAbove(
res.statusCode,
499,
'HTTP status code 500 or greater expected.'
)
// console.log(res)
assert.include(
res.output.error,
'Network error: Could not communicate with full node or other external service'
)
})
it('returns proper error when downstream service stalls', async () => {
// Mock the timeout error.
sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNABORTED' })
const result = await uut.getBCHUSD(req, res)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.')
assert.include(
result.error,
'Could not communicate with full node',
'Error message expected'
)
})
it('returns proper error when downstream service is down', async () => {
// Mock the timeout error.
sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNREFUSED' })
const result = await uut.getBCHUSD(req, res)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.')
assert.include(
result.error,
'Could not communicate with full node',
'Error message expected'
)
})
it('should get the USD price of BCH', async () => {
// Mock the RPC call for unit tests.
if (process.env.TEST === 'unit') {
sandbox
.stub(uut.axios, 'request')
.resolves({ data: mockData.mockCoinexFeed })
}
const result = await uut.getBCHUSD(req, res)
// console.log(`result: ${util.inspect(result)}`)
assert.isNumber(result.usd)
})
})
})