Ported getBestBlockHash()

This commit is contained in:
Chris Troutner
2020-01-27 17:04:47 -08:00
parent 57f3454e88
commit 24c9a93750
2 changed files with 145 additions and 65 deletions
+60 -10
View File
@@ -29,12 +29,27 @@ class Blockchain {
this.router = router
this.router.get("/", this.root)
this.router.get("/getBestBlockHash", this.getBestBlockHash)
this.router.get("/getBlockchainInfo", this.getBlockchainInfo)
}
root(req, res, next) {
return res.json({ status: "blockchain" })
}
// DRY error handler.
errorHandler(err, res) {
// Attempt to decode the error message.
const { msg, status } = routeUtils.decodeError(err)
if (msg) {
res.status(status)
return res.json({ error: msg })
}
res.status(500)
return res.json({ error: util.inspect(err) })
}
/**
* @api {get} /blockchain/getBestBlockHash Get best block hash
* @apiName GetBestBlockHash
@@ -60,19 +75,54 @@ class Blockchain {
return res.json(response.data.result)
} catch (err) {
// Attempt to decode the error message.
const { msg, status } = routeUtils.decodeError(err)
if (msg) {
res.status(status)
return res.json({ error: msg })
}
// Write out error to error log.
//logger.error(`Error in rawtransactions/decodeRawTransaction: `, err)
wlogger.error(`Error in blockchain.ts/getBestBlockHash().`, err)
res.status(500)
return res.json({ error: util.inspect(err) })
return this.errorHandler(err, res)
}
}
/**
* @api {get} /blockchain/getBlockchainInfo Get blockchain info
* @apiName GetBlockchainInfo
* @apiGroup Blockchain
* @apiDescription Returns an object containing various state info regarding blockchain processing.
*
* @apiExample Example usage:
* curl -X GET "https://mainnet.bchjs.cash/v3/blockchain/getBlockchainInfo" -H "accept: application/json"
*
* @apiSuccess {Object} object Object containing data
* @apiSuccess {String} object.chain "main"
* @apiSuccess {Number} object.blocks 561838
* @apiSuccess {Number} object.headers 561838
* @apiSuccess {String} object.bestblockhash "000000000000000002307dd38cd01c7308b8febfcdf5772cf087b5bb023d55bc"
* @apiSuccess {Number} object.difficulty 246585566638.1496
* @apiSuccess {String} object.mediantime 1545402693
* @apiSuccess {Number} object.verificationprogress 0.999998831622689
* @apiSuccess {Boolean} object.chainwork "000000000000000000000000000000000000000000d8c09a8ab7262080266b3e"
* @apiSuccess {Number} object.pruned false
* @apiSuccess {Array} object.softforks Array of objects
* @apiSuccess {String} object.softforks.id "bip34"
* @apiSuccess {String} object.softforks.version 2
* @apiSuccess {Object} object.softforks.reject
* @apiSuccess {String} object.softforks.reject.status true
*/
async getBlockchainInfo(req, res, next) {
try {
// Axios options
const options = routeUtils.getAxiosOptions()
options.data.id = "getblockchaininfo"
options.data.method = "getblockchaininfo"
options.data.params = []
const response = await this.axios.request(options)
return res.json(response.data.result)
} catch (err) {
// Write out error to error log.
wlogger.error(`Error in blockchain.ts/getBlockchainInfo().`, err)
return this.errorHandler(err, res)
}
}
}
+85 -55
View File
@@ -121,7 +121,7 @@ describe("#BlockchainRouter", () => {
)
})
it("returns proper error downstream service stalls", async () => {
it("returns proper error when downstream service stalls", async () => {
// Mock the timeout error.
sandbox.stub(uut.axios, "request").throws({ code: "ECONNABORTED" })
@@ -136,7 +136,7 @@ describe("#BlockchainRouter", () => {
)
})
it("returns proper error downstream is down", async () => {
it("returns proper error when downstream service is down", async () => {
// Mock the timeout error.
sandbox.stub(uut.axios, "request").throws({ code: "ECONNREFUSED" })
@@ -167,59 +167,89 @@ describe("#BlockchainRouter", () => {
})
})
// describe("getBlockchainInfo()", () => {
// // block route handler.
// const getBlockchainInfo =
// blockchainRoute.testableComponents.getBlockchainInfo
//
// it("should throw 503 when network issues", async () => {
// // Save the existing RPC URL.
// const savedUrl2 = process.env.RPC_BASEURL
//
// // Manipulate the URL to cause a 500 network error.
// process.env.RPC_BASEURL = "http://fakeurl/api/"
//
// const result = await getBlockchainInfo(req, res)
// //console.log(`result: ${util.inspect(result)}`)
//
// // Restore the saved URL.
// process.env.RPC_BASEURL = savedUrl2
//
// 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 /getBlockchainInfo", async () => {
// // Mock the RPC call for unit tests.
// if (process.env.TEST === "unit") {
// nock(`${process.env.RPC_BASEURL}`)
// .post(uri => uri.includes("/"))
// .reply(200, { result: mockData.mockBlockchainInfo })
// }
//
// const result = await getBlockchainInfo(req, res)
// //console.log(`result: ${util.inspect(result)}`)
//
// assert.hasAnyKeys(result, [
// "chain",
// "blocks",
// "headers",
// "bestblockhash",
// "difficulty",
// "mediantime",
// "verificationprogress",
// "chainwork",
// "pruned",
// "softforks",
// "bip9_softforks"
// ])
// })
// })
//
describe("getBlockchainInfo()", () => {
// block route handler.
// const getBlockchainInfo =
// blockchainRoute.testableComponents.getBlockchainInfo
it("should throw 503 when network issues", async () => {
// Save the existing RPC URL.
const savedUrl2 = process.env.RPC_BASEURL
// Manipulate the URL to cause a 500 network error.
process.env.RPC_BASEURL = "http://fakeurl/api/"
const result = await uut.getBlockchainInfo(req, res)
//console.log(`result: ${util.inspect(result)}`)
// Restore the saved URL.
process.env.RPC_BASEURL = savedUrl2
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 stalls", async () => {
// Mock the timeout error.
sandbox.stub(uut.axios, "request").throws({ code: "ECONNABORTED" })
const result = await uut.getBestBlockHash(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.getBestBlockHash(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 /getBlockchainInfo", async () => {
// Mock the RPC call for unit tests.
if (process.env.TEST === "unit") {
nock(`${process.env.RPC_BASEURL}`)
.post(uri => uri.includes("/"))
.reply(200, { result: mockData.mockBlockchainInfo })
}
const result = await uut.getBlockchainInfo(req, res)
//console.log(`result: ${util.inspect(result)}`)
assert.hasAnyKeys(result, [
"chain",
"blocks",
"headers",
"bestblockhash",
"difficulty",
"mediantime",
"verificationprogress",
"chainwork",
"pruned",
"softforks",
"bip9_softforks"
])
})
})
// describe("getBlockCount()", () => {
// // block route handler.
// const getBlockCount = blockchainRoute.testableComponents.getBlockCount