Compare commits

..
8 Commits
9 changed files with 385 additions and 51 deletions
+25 -22
View File
@@ -395,9 +395,9 @@
} }
}, },
"@psf/bch-js": { "@psf/bch-js": {
"version": "4.16.1", "version": "4.17.6",
"resolved": "https://registry.npmjs.org/@psf/bch-js/-/bch-js-4.16.1.tgz", "resolved": "https://registry.npmjs.org/@psf/bch-js/-/bch-js-4.17.6.tgz",
"integrity": "sha512-0rAOLGwxuzCrpe6dbz5nQ9KQTJIJNGzihSVSVfv0PXIeBKQKq+MuEG7u6rZXNeJlLWokosGwf6aysK2EbDGcqA==", "integrity": "sha512-dXR3S7wHZEivB/1LvvuBaAxn8FRRQpBrLtLcuL8c1J9v82xMO+qVr6AwvsOjFzHmcswuT1jlzQ3X1XPAaRgb5w==",
"requires": { "requires": {
"@psf/bip21": "^2.0.1", "@psf/bip21": "^2.0.1",
"@psf/bip32-utils": "^1.0.0", "@psf/bip32-utils": "^1.0.0",
@@ -931,23 +931,23 @@
} }
}, },
"@uppy/companion-client": { "@uppy/companion-client": {
"version": "1.8.2", "version": "1.8.3",
"resolved": "https://registry.npmjs.org/@uppy/companion-client/-/companion-client-1.8.2.tgz", "resolved": "https://registry.npmjs.org/@uppy/companion-client/-/companion-client-1.8.3.tgz",
"integrity": "sha512-FBjAJU3xaWRqYXDBlrMDQKlRBqi4Ng54Dmnoe3hGSggfgBQAl9RzRAg0WvrGjaK3QjCTZPhzSdTpBrqDP22Rng==", "integrity": "sha512-IieE5DMmJC1rJrXHB2u1cO+r3BF7VqnezFAZj8gkNm7zBuplswKALlvwnXI+KU3TNs8isU55xK5yfF0ecglIEw==",
"requires": { "requires": {
"@uppy/utils": "^3.4.1", "@uppy/utils": "^3.4.2",
"namespace-emitter": "^2.0.1", "namespace-emitter": "^2.0.1",
"qs-stringify": "^1.1.0" "qs-stringify": "^1.1.0"
} }
}, },
"@uppy/core": { "@uppy/core": {
"version": "1.16.1", "version": "1.16.2",
"resolved": "https://registry.npmjs.org/@uppy/core/-/core-1.16.1.tgz", "resolved": "https://registry.npmjs.org/@uppy/core/-/core-1.16.2.tgz",
"integrity": "sha512-GI8baCa1S21j7KoCq0LK4MLD6sII8OvWVgp+auXNcZIbKa182dOMQRtk7bXVY0OzS1TxkIq0DAzDEUnP7MbnDg==", "integrity": "sha512-JWK03gXiMMZ+lSVj+v9FIFEOUbKyvRX4v2kaYhf0NqD1MssCwMQe4mvL2MNzjOaYFBwMRacDJh8Mvz2gbu2Vqw==",
"requires": { "requires": {
"@transloadit/prettier-bytes": "0.0.7", "@transloadit/prettier-bytes": "0.0.7",
"@uppy/store-default": "^1.2.5", "@uppy/store-default": "^1.2.5",
"@uppy/utils": "^3.4.1", "@uppy/utils": "^3.4.2",
"cuid": "^2.1.1", "cuid": "^2.1.1",
"lodash.throttle": "^4.1.1", "lodash.throttle": "^4.1.1",
"mime-match": "^1.0.2", "mime-match": "^1.0.2",
@@ -961,19 +961,19 @@
"integrity": "sha512-jnf0U8cfb8Bhgt6yh86YRJO9EEnCyG9BgXZ8dPWWLybgC9Expw3Ah/s3T21tcdChgv4zzdhSACd0JKxCQowyYg==" "integrity": "sha512-jnf0U8cfb8Bhgt6yh86YRJO9EEnCyG9BgXZ8dPWWLybgC9Expw3Ah/s3T21tcdChgv4zzdhSACd0JKxCQowyYg=="
}, },
"@uppy/tus": { "@uppy/tus": {
"version": "1.8.5", "version": "1.8.6",
"resolved": "https://registry.npmjs.org/@uppy/tus/-/tus-1.8.5.tgz", "resolved": "https://registry.npmjs.org/@uppy/tus/-/tus-1.8.6.tgz",
"integrity": "sha512-a5z+bpAyKKKRWNSOYtIMd2EAKsM7BLhd6hQg2YrQNFFzdwbxaeqmrjKIVW1EUBvg1if/ZZePEm0QevJvNwQs0g==", "integrity": "sha512-axK+TzRRvSkYZUIjfe6XCjfO5NPb/k8AC73p+MOKOzth1JHSZSJHqYi8+HY7T4aXgR86vWE/cE+wHsjvPhyCZw==",
"requires": { "requires": {
"@uppy/companion-client": "^1.8.2", "@uppy/companion-client": "^1.8.3",
"@uppy/utils": "^3.4.1", "@uppy/utils": "^3.4.2",
"tus-js-client": "^2.1.1" "tus-js-client": "^2.1.1"
} }
}, },
"@uppy/utils": { "@uppy/utils": {
"version": "3.4.1", "version": "3.4.2",
"resolved": "https://registry.npmjs.org/@uppy/utils/-/utils-3.4.1.tgz", "resolved": "https://registry.npmjs.org/@uppy/utils/-/utils-3.4.2.tgz",
"integrity": "sha512-9YVKjVRK/AmX3yV0GJsD5p/eHUzqn4+eXzsjv3wHahipKCo0o7Jwpw/7kl+bv12EHOOy5jPsATWkjn40aSWW8w==", "integrity": "sha512-PWLZgX4L+0tdBqImncuATDYb1M6RHgDfGDZCh2Qg+PTG+btyyZ4/GkOEwK5fJ4Gw1gNgWF0ewAFL28+oCrD7/Q==",
"requires": { "requires": {
"abortcontroller-polyfill": "^1.4.0", "abortcontroller-polyfill": "^1.4.0",
"lodash.throttle": "^4.1.1" "lodash.throttle": "^4.1.1"
@@ -10930,9 +10930,12 @@
"dev": true "dev": true
}, },
"qs": { "qs": {
"version": "6.9.6", "version": "6.10.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz",
"integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==" "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==",
"requires": {
"side-channel": "^1.0.4"
}
}, },
"qs-stringify": { "qs-stringify": {
"version": "1.2.1", "version": "1.2.1",
+1 -1
View File
@@ -29,7 +29,7 @@
"node": ">=10.15.1" "node": ">=10.15.1"
}, },
"dependencies": { "dependencies": {
"@psf/bch-js": "^4.16.1", "@psf/bch-js": "^4.17.6",
"apidoc": "^0.26.0", "apidoc": "^0.26.0",
"axios": "^0.21.1", "axios": "^0.21.1",
"bitcore-lib-cash": "^8.23.1", "bitcore-lib-cash": "^8.23.1",
+5 -3
View File
@@ -189,9 +189,11 @@ server.listen(port)
server.on('error', onError) server.on('error', onError)
server.on('listening', onListening) server.on('listening', onListening)
// Set the time before a timeout error is generated. This impacts testing and // Set the time before a timeout error is generated.
// the handling of timeout errors. Is 10 seconds too agressive? // 10 seconds is way too agressive. 30 Seconds was used for a while, but with
server.setTimeout(30 * 1000) // being able to set a timeout between UTXOs for tokenUtxoDetails, the timeout
// needed to be extended.
server.setTimeout(1000 * 60 * 5) // 5 minutes
/** /**
* Normalize a port into a number, string, or false. * Normalize a port into a number, string, or false.
+17 -16
View File
@@ -82,11 +82,11 @@ class RateLimits {
// Determine if the call is an external or internal API call. // Determine if the call is an external or internal API call.
const isInternal = _this.checkInternalIp(req) const isInternal = _this.checkInternalIp(req)
console.log(`isInternal: ${isInternal}`) // console.log(`isInternal: ${isInternal}`)
// Determine if the call originates from another computer on the intranet. // Determine if the call originates from another computer on the intranet.
const isWhitelistOrigin = _this.isInWhitelist(req) const isWhitelistOrigin = _this.isInWhitelist(req)
console.log('isWhitelistOrigin: ', isWhitelistOrigin) // console.log('isWhitelistOrigin: ', isWhitelistOrigin)
// Handle the use case of internally-generated requests. // Handle the use case of internally-generated requests.
if (isInternal) { if (isInternal) {
@@ -94,15 +94,15 @@ class RateLimits {
// the usrObj in the body. // the usrObj in the body.
if (req.body && req.body.usrObj) { if (req.body && req.body.usrObj) {
if (req.body.usrObj.proLimit) { if (req.body.usrObj.proLimit) {
console.log('Internal call, basic auth, skipping rate limits.') // console.log('Internal call, basic auth, skipping rate limits.')
// If this is an internal call that originated from a user using // If this is an internal call that originated from a user using
// Basic Authentication, then skip rate-limits. // Basic Authentication, then skip rate-limits.
return next() return next()
} else { } else {
console.log( // console.log(
'Internal call, applying rate limits. Using JWT if available.' // 'Internal call, applying rate limits. Using JWT if available.'
) // )
// Determine if user has exceeded their rate limits. Pass in the // Determine if user has exceeded their rate limits. Pass in the
// JWT token if one exists. // JWT token if one exists.
@@ -130,10 +130,10 @@ class RateLimits {
// and avoid this code path. This code path is 'pooled': all users // and avoid this code path. This code path is 'pooled': all users
// share the same rate limits. Even at 1000 RPM, this pool will get // share the same rate limits. Even at 1000 RPM, this pool will get
// exhausted easily. // exhausted easily.
const warnMsg = // const warnMsg =
'Internal call. req.body.usrObj does not exist. Applying high-speed internal rate limits.' // 'Internal call. req.body.usrObj does not exist. Applying high-speed internal rate limits.'
console.log(warnMsg) // console.log(warnMsg)
wlogger.info(warnMsg) // wlogger.info(warnMsg)
const defaultPayload = { const defaultPayload = {
id: '98.76.54.32', id: '98.76.54.32',
@@ -168,9 +168,9 @@ class RateLimits {
// //
} else { } else {
// Handle the normal use-case of external requests // Handle the normal use-case of external requests
console.log( // console.log(
'External call, applying rate limits. Using JWT if available.' // 'External call, applying rate limits. Using JWT if available.'
) // )
// For calls originating from a whitelist domain, apply a high-RPM // For calls originating from a whitelist domain, apply a high-RPM
// JWT token to the call. // JWT token to the call.
@@ -233,7 +233,7 @@ class RateLimits {
pointsToConsume = decoded.pointsToConsume pointsToConsume = decoded.pointsToConsume
} }
console.log(`rate limit key: ${key}`) // console.log(`rate limit key: ${key}`)
// This function will throw an error if the user exceeds the rate limit. // This function will throw an error if the user exceeds the rate limit.
// The 429 error response is handled by the catch(). // The 429 error response is handled by the catch().
@@ -244,7 +244,7 @@ class RateLimits {
// Signal that the user has not exceeded their rate limits. // Signal that the user has not exceeded their rate limits.
return false return false
} catch (err) { } catch (err) {
console.log('err: ', err) // console.log('err: ', err)
const rateLimit = Math.floor(POINTS_PER_MINUTE / pointsToConsume) const rateLimit = Math.floor(POINTS_PER_MINUTE / pointsToConsume)
@@ -307,7 +307,8 @@ class RateLimits {
// Retrieve the origin. // Retrieve the origin.
const origin = req.get('origin') const origin = req.get('origin')
console.log(`origin: ${origin}`)
if (!process.env.TEST) console.log('origin:', origin)
// If the origin is not determinable, return false. // If the origin is not determinable, return false.
if (!origin) return false if (!origin) return false
+1 -1
View File
@@ -181,7 +181,7 @@ class Encryption {
publicKey: 'not found' publicKey: 'not found'
}) })
} catch (err) { } catch (err) {
console.log('Error in encryption.js/getPublicKey().', err) // console.log('Error in encryption.js/getPublicKey().', err)
wlogger.error('Error in encryption.js/getPublicKey().', err) wlogger.error('Error in encryption.js/getPublicKey().', err)
return _this.errorHandler(err, res) return _this.errorHandler(err, res)
+47
View File
@@ -53,6 +53,7 @@ class Blockchain {
this.router.post('/getTxOutProof', this.getTxOutProofBulk) this.router.post('/getTxOutProof', this.getTxOutProofBulk)
this.router.get('/verifyTxOutProof/:proof', this.verifyTxOutProofSingle) this.router.get('/verifyTxOutProof/:proof', this.verifyTxOutProofSingle)
this.router.post('/verifyTxOutProof', this.verifyTxOutProofBulk) this.router.post('/verifyTxOutProof', this.verifyTxOutProofBulk)
this.router.post('/getBlock', this.getBlock)
} }
root (req, res, next) { root (req, res, next) {
@@ -937,6 +938,52 @@ class Blockchain {
return _this.errorHandler(err, res) return _this.errorHandler(err, res)
} }
} }
/**
* @api {post} /blockchain/getBlock/ Get block details
* @apiName getBlock
* @apiGroup Blockchain
* @apiDescription Returns block details
*
* @apiExample Example usage:
* curl "https://api.fullstack.cash/v4/blockchain/getblock/" -X POST -H "Content-Type: application/json" --data-binary '{"blockhash":"000000000000000002a5fe0bdd6e3f04342a975c0f55e57f97e73bb90041676b","verbosity":0 }'
*
* @apiParam {String} blockhash Block hash (required)
* @apiParam {Number} verbosity Default 1 (optional)
*
*/
async getBlock (req, res, next) {
try {
// Validate input parameter
const blockhash = req.body.blockhash
let verbosity = req.body.verbosity
// Default to a value of 1 if another verbosity level is not defined.
if (!verbosity && verbosity !== 0) verbosity = 1
if (!blockhash || blockhash === '') {
res.status(400)
return res.json({ error: 'blockhash can not be empty' })
}
// Axios options
const options = _this.routeUtils.getAxiosOptions()
options.data.id = 'getblock'
options.data.method = 'getblock'
options.data.params = [blockhash, verbosity]
const response = await _this.axios.request(options)
return res.json(response.data.result)
} catch (err) {
// Write out error to error log.
// logger.error(`Error in rawtransactions/decodeRawTransaction: `, err)
wlogger.error('Error in blockchain.js/getBlock()', err)
return _this.errorHandler(err, res)
}
}
} }
module.exports = Blockchain module.exports = Blockchain
+200
View File
@@ -1823,4 +1823,204 @@ describe('#BlockchainRouter', () => {
assert.equal(result.length, 2) assert.equal(result.length, 2)
}) })
}) })
describe('#getBlock()', () => {
it('returns proper error when downstream service stalls', async () => {
// Mock the timeout error.
sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNABORTED' })
req.body.blockhash =
'000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700'
const result = await uut.getBlock(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' })
req.body.blockhash =
'000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700'
const result = await uut.getBlock(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 throw 400 if blockhash is empty', async () => {
const result = await uut.getBlock(req, res)
// console.log(`result: ${util.inspect(result)}`)
assert.hasAllKeys(result, ['error'])
assert.include(result.error, 'blockhash can not be empty')
})
it('should return block info with verbosity 0', async () => {
// Mock the RPC call for unit tests.
if (process.env.TEST === 'unit') {
sandbox
.stub(uut.axios, 'request')
.resolves({ data: { result: mockData.mockBlockInfo.verbosity0 } })
}
req.body.blockhash =
'0000000000000000008e8d83cba6d45a9314bc2ef4538d4e0577c6bed8593536'
req.body.verbosity = 0
const result = await uut.getBlock(req, res)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.isString(result)
})
it('should return block info with verbosity 1', async () => {
// Mock the RPC call for unit tests.
if (process.env.TEST === 'unit') {
sandbox
.stub(uut.axios, 'request')
.resolves({ data: { result: mockData.mockBlockInfo.verbosity1 } })
}
req.body.blockhash =
'0000000000000000008e8d83cba6d45a9314bc2ef4538d4e0577c6bed8593536'
req.body.verbosity = 1
const result = await uut.getBlock(req, res)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, 'hash', 'hash property expected')
assert.property(
result,
'confirmations',
'confirmations property expected'
)
assert.property(result, 'size', 'size property expected')
assert.property(result, 'height', 'height property expected')
assert.property(result, 'version', 'version property expected')
assert.property(result, 'versionHex', 'versionHex property expected')
assert.property(result, 'merkleroot', 'merkleroot property expected')
assert.property(result, 'tx', 'tx property expected')
assert.property(result, 'time', 'time property expected')
assert.property(result, 'mediantime', 'mediantime property expected')
assert.property(result, 'nonce', 'nonce property expected')
assert.property(result, 'bits', 'bits property expected')
assert.property(result, 'difficulty', 'difficulty property expected')
assert.property(result, 'chainwork', 'chainwork property expected')
assert.property(result, 'nTx', 'nTx property expected')
assert.property(
result,
'previousblockhash',
'previousblockhash property expected'
)
assert.property(
result,
'nextblockhash',
'nextblockhash property expected'
)
})
it('should return block info with verbosity 2', async () => {
// Mock the RPC call for unit tests.
if (process.env.TEST === 'unit') {
sandbox
.stub(uut.axios, 'request')
.resolves({ data: { result: mockData.mockBlockInfo.verbosity1 } })
}
req.body.blockhash =
'0000000000000000008e8d83cba6d45a9314bc2ef4538d4e0577c6bed8593536'
req.body.verbosity = 2
const result = await uut.getBlock(req, res)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, 'hash', 'hash property expected')
assert.property(
result,
'confirmations',
'confirmations property expected'
)
assert.property(result, 'size', 'size property expected')
assert.property(result, 'height', 'height property expected')
assert.property(result, 'version', 'version property expected')
assert.property(result, 'versionHex', 'versionHex property expected')
assert.property(result, 'merkleroot', 'merkleroot property expected')
assert.property(result, 'tx', 'tx property expected')
assert.property(result, 'time', 'time property expected')
assert.property(result, 'mediantime', 'mediantime property expected')
assert.property(result, 'nonce', 'nonce property expected')
assert.property(result, 'bits', 'bits property expected')
assert.property(result, 'difficulty', 'difficulty property expected')
assert.property(result, 'chainwork', 'chainwork property expected')
assert.property(result, 'nTx', 'nTx property expected')
assert.property(
result,
'previousblockhash',
'previousblockhash property expected'
)
assert.property(
result,
'nextblockhash',
'nextblockhash property expected'
)
})
it('should return block info without verbosity especified', async () => {
// Mock the RPC call for unit tests.
if (process.env.TEST === 'unit') {
sandbox
.stub(uut.axios, 'request')
.resolves({ data: { result: mockData.mockBlockInfo.verbosity1 } })
}
req.body.blockhash =
'0000000000000000008e8d83cba6d45a9314bc2ef4538d4e0577c6bed8593536'
const result = await uut.getBlock(req, res)
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.property(result, 'hash', 'hash property expected')
assert.property(
result,
'confirmations',
'confirmations property expected'
)
assert.property(result, 'size', 'size property expected')
assert.property(result, 'height', 'height property expected')
assert.property(result, 'version', 'version property expected')
assert.property(result, 'versionHex', 'versionHex property expected')
assert.property(result, 'merkleroot', 'merkleroot property expected')
assert.property(result, 'tx', 'tx property expected')
assert.property(result, 'time', 'time property expected')
assert.property(result, 'mediantime', 'mediantime property expected')
assert.property(result, 'nonce', 'nonce property expected')
assert.property(result, 'bits', 'bits property expected')
assert.property(result, 'difficulty', 'difficulty property expected')
assert.property(result, 'chainwork', 'chainwork property expected')
assert.property(result, 'nTx', 'nTx property expected')
assert.property(
result,
'previousblockhash',
'previousblockhash property expected'
)
assert.property(
result,
'nextblockhash',
'nextblockhash property expected'
)
})
})
}) })
+82 -2
View File
@@ -285,7 +285,86 @@ const mockAncestors = [
'e68dad4a7292105cfa84fcaef7f99e5d4f2ece9613ca625d4d2ebf61efa84118', 'e68dad4a7292105cfa84fcaef7f99e5d4f2ece9613ca625d4d2ebf61efa84118',
'fe94caf5da672be3772d2304a6272eb8bc3d3f5cb4a886f39b7981e1485cf74b' 'fe94caf5da672be3772d2304a6272eb8bc3d3f5cb4a886f39b7981e1485cf74b'
] ]
const mockBlockInfo = {
verbosity0: '20000000',
verbosity1: {
hash: '00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09',
confirmations: 1,
size: 3725,
strippedsize: 3725,
weight: 3725,
height: 6725,
version: 1,
versionHex: '00000000',
merkleroot: 'xxxx',
tx: [
'2afb8264508e2bf3e5288ccad01ed2ab766745b6b9747666b519d59212012c01',
'18f40b1ae56bba3fa1934b737fbe46ed8d5ca40fa9aed95073eeb5a119530cd3',
'349720d878547752607a69eb19e330592fee271fb5376cdfd811bee423558ed8',
'35571c80e7d0e9247b467454ef147d1d5833c775bc2d4164b1bebd4c1f69164f',
'480937e8efacdafeeb97d401ff0dd9ea8e8ddb27244cefa67a03621315bdb0e6',
'523327469d0b90c0de9a905c2fe6e227278fc5b55b9d9911ca151e1c26647065',
'61de4af971d94dbc741762f21dcef08b74b62863a56a1cb3496becdd8d47a858',
'69f70a288403b5bba23030ccd05d2e5cb00394620fdae3b050cff9432cc590ce',
'94472a90fbdba2eb2cba68308415181faedf3585c66b89efcbdb927a0c10ba23',
'bc6f781f9e2f2df460f89995c5e1c7224e48ccbe1aa2a575961f3f5330259864',
'f2d945a79bec5454a9ab4d570a150d81124daa308f1c81106a977d6413476944'
],
time: 111,
mediantime: 111,
nonce: 111,
bits: '1d00ffff',
difficulty: 99.999,
chainwork: 'xxxx',
nTx: 1,
previousblockhash:
'00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09',
nextblockhash:
'00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09'
},
verbosity2: {
hash: '00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09',
confirmations: 1,
size: 3725,
strippedsize: 3725,
weight: 3725,
height: 6725,
version: 1,
versionHex: '00000000',
merkleroot: 'xxxx',
tx: [
{
hex:
'01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000',
txid:
'0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098',
hash:
'0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098',
size: 134,
version: 1,
locktime: 0,
vin: [],
vout: [],
blockhash:
'00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048',
confirmations: 581882,
time: 1231469665,
blocktime: 1231469665
}
],
time: 111,
mediantime: 111,
nonce: 111,
bits: '1d00ffff',
difficulty: 99.999,
chainwork: 'xxxx',
nTx: 1,
previousblockhash:
'00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09',
nextblockhash:
'00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09'
}
}
module.exports = { module.exports = {
mockBlockHash, mockBlockHash,
mockBlockchainInfo, mockBlockchainInfo,
@@ -296,5 +375,6 @@ module.exports = {
mockBlockHeader, mockBlockHeader,
mockTxOut, mockTxOut,
mockTxOutProof, mockTxOutProof,
mockAncestors mockAncestors,
mockBlockInfo
} }
+7 -6
View File
@@ -129,7 +129,7 @@ describe('#rate-routelimit', () => {
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjVlODhhY2JmMDIyMWMxMDAxMmFkOTNmZiIsImVtYWlsIjoiY2hyaXMudHJvdXRuZXJAZ21haWwuY29tIiwiYXBpTGV2ZWwiOjQwLCJyYXRlTGltaXQiOjMsImlhdCI6MTYxNTE1NzA4NywiZXhwIjoxNjE3NzQ5MDg3fQ.RLNGuYAa-CcLdhTGD27tDeaxT6-GIdeR8T4JWZZLDZA' 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjVlODhhY2JmMDIyMWMxMDAxMmFkOTNmZiIsImVtYWlsIjoiY2hyaXMudHJvdXRuZXJAZ21haWwuY29tIiwiYXBpTGV2ZWwiOjQwLCJyYXRlTGltaXQiOjMsImlhdCI6MTYxNTE1NzA4NywiZXhwIjoxNjE3NzQ5MDg3fQ.RLNGuYAa-CcLdhTGD27tDeaxT6-GIdeR8T4JWZZLDZA'
const result = uut.decodeJwtToken(jwt) const result = uut.decodeJwtToken(jwt)
console.log('result: ', result) // console.log('result: ', result)
assert.property(result, 'id') assert.property(result, 'id')
// assert.equal(result.id, '123.456.789.10') // assert.equal(result.id, '123.456.789.10')
@@ -309,10 +309,10 @@ describe('#rate-routelimit', () => {
let val let val
for (let i = 0; i < 25; i++) { for (let i = 0; i < 25; i++) {
console.log('req.locals: ', req.locals) // console.log('req.locals: ', req.locals)
val = await uut.applyRateLimits(req, res, next) val = await uut.applyRateLimits(req, res, next)
} }
console.log('val: ', val) // console.log('val: ', val)
assert.property(val, 'error') assert.property(val, 'error')
assert.include( assert.include(
@@ -446,7 +446,7 @@ describe('#rate-routelimit', () => {
// Generate a new JWT token for the test. // Generate a new JWT token for the test.
const jwtPayload = { const jwtPayload = {
id: '5dade3f5739e6c0ff034b9a1', id: '5dade3f5739e6c0ff034b9a1',
pointsToConsume: 10 pointsToConsume: 100
} }
const jwtToken = uut.generateJwtToken(jwtPayload) const jwtToken = uut.generateJwtToken(jwtPayload)
@@ -460,7 +460,7 @@ describe('#rate-routelimit', () => {
for (let i = 0; i < 120; i++) { for (let i = 0; i < 120; i++) {
val = await uut.applyRateLimits(req, res, next) val = await uut.applyRateLimits(req, res, next)
} }
console.log('val: ', val) // console.log('val: ', val)
assert.property(val, 'error') assert.property(val, 'error')
assert.include( assert.include(
@@ -470,11 +470,12 @@ describe('#rate-routelimit', () => {
assert.equal( assert.equal(
res.locals.pointsToConsume, res.locals.pointsToConsume,
10, 100,
'User JWT rate limits applied' 'User JWT rate limits applied'
) )
} catch (err) { } catch (err) {
console.log('err: ', err) console.log('err: ', err)
assert.fail('Unexpected result')
} }
}) })