2020-07-27 21:25:31 -07:00
|
|
|
/*
|
|
|
|
|
TODO:
|
|
|
|
|
-getRawMempool
|
|
|
|
|
--Add tests for 'verbose' input values
|
|
|
|
|
-getMempoolEntry & getMempoolEntryBulk
|
|
|
|
|
--Needs e2e test to create unconfirmed tx, for real-world test.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
'use strict'
|
|
|
|
|
|
|
|
|
|
const chai = require('chai')
|
|
|
|
|
const assert = chai.assert
|
|
|
|
|
const sinon = require('sinon')
|
|
|
|
|
|
|
|
|
|
const Blockchain = require('../../src/routes/v3/full-node/blockchain')
|
|
|
|
|
const uut = new Blockchain()
|
|
|
|
|
|
|
|
|
|
const util = require('util')
|
|
|
|
|
util.inspect.defaultOptions = { depth: 1 }
|
|
|
|
|
|
|
|
|
|
if (!process.env.TEST) process.env.TEST = 'unit'
|
|
|
|
|
|
|
|
|
|
// Mocking data.
|
|
|
|
|
const { mockReq, mockRes } = require('./mocks/express-mocks')
|
|
|
|
|
const mockData = require('./mocks/blockchain-mock')
|
|
|
|
|
|
|
|
|
|
let originalEnvVars // Used during transition from integration to unit tests.
|
|
|
|
|
|
|
|
|
|
describe('#BlockchainRouter', () => {
|
|
|
|
|
let req, res
|
|
|
|
|
let sandbox
|
|
|
|
|
|
|
|
|
|
// local node will be started in regtest mode on the port 48332
|
|
|
|
|
// before(panda.runLocalNode)
|
|
|
|
|
|
|
|
|
|
before(() => {
|
|
|
|
|
// Save existing environment variables.
|
|
|
|
|
originalEnvVars = {
|
|
|
|
|
BITCOINCOM_BASEURL: process.env.BITCOINCOM_BASEURL,
|
|
|
|
|
RPC_BASEURL: process.env.RPC_BASEURL,
|
|
|
|
|
RPC_USERNAME: process.env.RPC_USERNAME,
|
|
|
|
|
RPC_PASSWORD: process.env.RPC_PASSWORD
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set default environment variables for unit tests.
|
|
|
|
|
if (process.env.TEST === 'unit') {
|
|
|
|
|
process.env.BITCOINCOM_BASEURL = 'http://fakeurl/api/'
|
|
|
|
|
process.env.RPC_BASEURL = 'http://fakeurl/api'
|
|
|
|
|
process.env.RPC_USERNAME = 'fakeusername'
|
|
|
|
|
process.env.RPC_PASSWORD = 'fakepassword'
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Setup the mocks before each test.
|
|
|
|
|
beforeEach(() => {
|
|
|
|
|
// Mock the req and res objects used by Express routes.
|
|
|
|
|
req = mockReq
|
|
|
|
|
res = mockRes
|
|
|
|
|
|
|
|
|
|
// Explicitly reset the parmas and body.
|
|
|
|
|
req.params = {}
|
|
|
|
|
req.body = {}
|
|
|
|
|
sandbox = sinon.createSandbox()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
|
// Restore Sandbox
|
|
|
|
|
sandbox.restore()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
after(() => {
|
|
|
|
|
// otherwise the panda will run forever
|
|
|
|
|
// process.exit()
|
|
|
|
|
|
|
|
|
|
// Restore any pre-existing environment variables.
|
|
|
|
|
process.env.BITCOINCOM_BASEURL = originalEnvVars.BITCOINCOM_BASEURL
|
|
|
|
|
process.env.RPC_BASEURL = originalEnvVars.RPC_BASEURL
|
|
|
|
|
process.env.RPC_USERNAME = originalEnvVars.RPC_USERNAME
|
|
|
|
|
process.env.RPC_PASSWORD = originalEnvVars.RPC_PASSWORD
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe('#root', () => {
|
|
|
|
|
it('should respond to GET for base route', async () => {
|
|
|
|
|
const result = uut.root(req, res)
|
|
|
|
|
|
|
|
|
|
assert.equal(result.status, 'blockchain', 'Returns static string')
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe('getBestBlockHash()', () => {
|
|
|
|
|
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.getBestBlockHash(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 /getBestBlockHash', async () => {
|
|
|
|
|
// Mock the RPC call for unit tests.
|
|
|
|
|
if (process.env.TEST === 'unit') {
|
|
|
|
|
sandbox
|
|
|
|
|
.stub(uut.axios, 'request')
|
|
|
|
|
.resolves({ data: { result: mockData.mockBlockHash } })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const result = await uut.getBestBlockHash(req, res)
|
|
|
|
|
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
|
|
|
|
|
|
|
|
assert.isString(result)
|
|
|
|
|
assert.equal(result.length, 64, 'Hash string is fixed length')
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe('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') {
|
|
|
|
|
sandbox
|
|
|
|
|
.stub(uut.axios, 'request')
|
|
|
|
|
.resolves({ data: { 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()', () => {
|
|
|
|
|
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.getBlockCount(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.getBlockCount(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.getBlockCount(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 /getBlockCount', async () => {
|
|
|
|
|
// Mock the RPC call for unit tests.
|
|
|
|
|
if (process.env.TEST === 'unit') {
|
|
|
|
|
sandbox
|
|
|
|
|
.stub(uut.axios, 'request')
|
|
|
|
|
.resolves({ data: { result: 126769 } })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const result = await uut.getBlockCount(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.isNumber(result)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe('getBlockHeaderSingle()', async () => {
|
|
|
|
|
it('should throw 400 error if hash is missing', async () => {
|
|
|
|
|
const result = await uut.getBlockHeaderSingle(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.hasAllKeys(result, ['error'])
|
|
|
|
|
assert.include(result.error, 'hash can not be empty')
|
|
|
|
|
})
|
|
|
|
|
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/'
|
|
|
|
|
|
|
|
|
|
req.params.hash =
|
|
|
|
|
'00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900'
|
|
|
|
|
|
|
|
|
|
const result = await uut.getBlockHeaderSingle(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,
|
|
|
|
|
'Network 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' })
|
|
|
|
|
|
|
|
|
|
req.params.hash =
|
|
|
|
|
'00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900'
|
|
|
|
|
|
|
|
|
|
const result = await uut.getBlockHeaderSingle(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.params.hash =
|
|
|
|
|
'00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900'
|
|
|
|
|
|
|
|
|
|
const result = await uut.getBlockHeaderSingle(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 block header', async () => {
|
|
|
|
|
// Mock the RPC call for unit tests.
|
|
|
|
|
if (process.env.TEST === 'unit') {
|
|
|
|
|
sandbox.stub(uut.axios, 'request').resolves({
|
|
|
|
|
data: {
|
|
|
|
|
result:
|
|
|
|
|
'000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c'
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
req.params.hash =
|
|
|
|
|
'000000000000000002fa9d7851b284c53a5831651b04211c266badf2ad2d8ef0'
|
|
|
|
|
|
|
|
|
|
const result = await uut.getBlockHeaderSingle(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.isString(result)
|
|
|
|
|
assert.equal(
|
|
|
|
|
result,
|
|
|
|
|
'000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c'
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should GET verbose block header', async () => {
|
|
|
|
|
// Mock the RPC call for unit tests.
|
|
|
|
|
if (process.env.TEST === 'unit') {
|
|
|
|
|
sandbox
|
|
|
|
|
.stub(uut.axios, 'request')
|
|
|
|
|
.resolves({ data: { result: mockData.mockBlockHeader } })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
req.query.verbose = true
|
|
|
|
|
req.params.hash =
|
|
|
|
|
'000000000000000002fa9d7851b284c53a5831651b04211c266badf2ad2d8ef0'
|
|
|
|
|
|
|
|
|
|
const result = await uut.getBlockHeaderSingle(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.hasAllKeys(result, [
|
|
|
|
|
'hash',
|
|
|
|
|
'confirmations',
|
|
|
|
|
'height',
|
|
|
|
|
'version',
|
|
|
|
|
'versionHex',
|
|
|
|
|
'merkleroot',
|
|
|
|
|
'time',
|
|
|
|
|
'mediantime',
|
|
|
|
|
'nonce',
|
|
|
|
|
'bits',
|
|
|
|
|
'difficulty',
|
|
|
|
|
'chainwork',
|
|
|
|
|
'previousblockhash',
|
|
|
|
|
'nextblockhash',
|
|
|
|
|
'nTx'
|
|
|
|
|
])
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
describe('#getBlockHeaderBulk', () => {
|
|
|
|
|
it('should throw an error for an empty body', async () => {
|
|
|
|
|
req.body = {}
|
|
|
|
|
|
|
|
|
|
const result = await uut.getBlockHeaderBulk(req, res)
|
|
|
|
|
|
|
|
|
|
assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.')
|
|
|
|
|
assert.include(
|
|
|
|
|
result.error,
|
|
|
|
|
'hashes needs to be an array',
|
|
|
|
|
'Proper error message'
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should error on non-array single hash', async () => {
|
|
|
|
|
req.body.hashes =
|
|
|
|
|
'00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900'
|
|
|
|
|
|
|
|
|
|
const result = await uut.getBlockHeaderBulk(req, res)
|
|
|
|
|
|
|
|
|
|
assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.')
|
|
|
|
|
assert.include(
|
|
|
|
|
result.error,
|
|
|
|
|
'hashes needs to be an array',
|
|
|
|
|
'Proper error message'
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should throw 400 error if addresses array is too large', async () => {
|
|
|
|
|
const testArray = []
|
|
|
|
|
for (var i = 0; i < 25; i++) testArray.push('')
|
|
|
|
|
|
|
|
|
|
req.body.hashes = testArray
|
|
|
|
|
|
|
|
|
|
const result = await uut.getBlockHeaderBulk(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.hasAllKeys(result, ['error'])
|
|
|
|
|
assert.include(result.error, 'Array too large')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should throw a 400 error for an invalid hash', async () => {
|
|
|
|
|
req.body.hashes = ['badHash']
|
|
|
|
|
|
|
|
|
|
await uut.getBlockHeaderBulk(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should throw 500 when network issues', async () => {
|
|
|
|
|
const savedUrl = process.env.BITCOINCOM_BASEURL
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
req.body.hashes = [
|
|
|
|
|
'00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900'
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
// Switch the Insight URL to something that will error out.
|
|
|
|
|
process.env.BITCOINCOM_BASEURL = 'http://fakeurl/api/'
|
|
|
|
|
|
|
|
|
|
const result = await uut.getBlockHeaderBulk(req, res)
|
|
|
|
|
|
|
|
|
|
// Restore the saved URL.
|
|
|
|
|
process.env.BITCOINCOM_BASEURL = savedUrl
|
|
|
|
|
|
|
|
|
|
assert.equal(res.statusCode, 500, 'HTTP status code 500 expected.')
|
|
|
|
|
assert.include(result.error, 'ENOTFOUND', 'Error message expected')
|
|
|
|
|
} catch (err) {
|
|
|
|
|
// Restore the saved URL.
|
|
|
|
|
process.env.BITCOINCOM_BASEURL = savedUrl
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('returns proper error when downstream service stalls', async () => {
|
|
|
|
|
// Mock the timeout error.
|
|
|
|
|
sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNABORTED' })
|
|
|
|
|
|
|
|
|
|
req.body.hashes = [
|
|
|
|
|
'000000000000000002fa9d7851b284c53a5831651b04211c266badf2ad2d8ef0'
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
const result = await uut.getBlockHeaderBulk(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.hashes = [
|
|
|
|
|
'000000000000000002fa9d7851b284c53a5831651b04211c266badf2ad2d8ef0'
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
const result = await uut.getBlockHeaderBulk(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 concise block header for a single hash', async () => {
|
|
|
|
|
req.body.hashes = [
|
|
|
|
|
'000000000000000002fa9d7851b284c53a5831651b04211c266badf2ad2d8ef0'
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
// Mock the RPC call for unit tests.
|
|
|
|
|
if (process.env.TEST === 'unit') {
|
|
|
|
|
sandbox
|
|
|
|
|
.stub(uut.axios, 'request')
|
|
|
|
|
.resolves({ data: { result: mockData.mockBlockHeaderConcise } })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Call the details API.
|
|
|
|
|
const result = await uut.getBlockHeaderBulk(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
// Assert that required fields exist in the returned object.
|
|
|
|
|
assert.isArray(result)
|
|
|
|
|
assert.equal(
|
|
|
|
|
result[0],
|
|
|
|
|
'000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c'
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should get verbose block header for a single hash', async () => {
|
|
|
|
|
req.body = {
|
|
|
|
|
hashes: [
|
|
|
|
|
'000000000000000002fa9d7851b284c53a5831651b04211c266badf2ad2d8ef0'
|
|
|
|
|
],
|
|
|
|
|
verbose: true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Mock the RPC call for unit tests.
|
|
|
|
|
if (process.env.TEST === 'unit') {
|
|
|
|
|
sandbox
|
|
|
|
|
.stub(uut.axios, 'request')
|
|
|
|
|
.resolves({ data: { result: mockData.mockBlockHeader } })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Call the details API.
|
|
|
|
|
const result = await uut.getBlockHeaderBulk(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
// Assert that required fields exist in the returned object.
|
|
|
|
|
assert.isArray(result)
|
|
|
|
|
assert.hasAllKeys(result[0], [
|
|
|
|
|
'hash',
|
|
|
|
|
'confirmations',
|
|
|
|
|
'height',
|
|
|
|
|
'version',
|
|
|
|
|
'versionHex',
|
|
|
|
|
'merkleroot',
|
|
|
|
|
'time',
|
|
|
|
|
'mediantime',
|
|
|
|
|
'nonce',
|
|
|
|
|
'bits',
|
|
|
|
|
'difficulty',
|
|
|
|
|
'chainwork',
|
|
|
|
|
'previousblockhash',
|
|
|
|
|
'nextblockhash',
|
|
|
|
|
'nTx'
|
|
|
|
|
])
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should get details for multiple block heights', async () => {
|
|
|
|
|
req.body.hashes = [
|
|
|
|
|
'000000000000000002fa9d7851b284c53a5831651b04211c266badf2ad2d8ef0',
|
|
|
|
|
'000000000000000002fa9d7851b284c53a5831651b04211c266badf2ad2d8ef0'
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
// Mock the RPC call for unit tests.
|
|
|
|
|
if (process.env.TEST === 'unit') {
|
|
|
|
|
sandbox
|
|
|
|
|
.stub(uut.axios, 'request')
|
|
|
|
|
.resolves({ data: { result: mockData.mockBlockHeaderConcise } })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Call the details API.
|
|
|
|
|
const result = await uut.getBlockHeaderBulk(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.isArray(result)
|
|
|
|
|
assert.equal(result.length, 2, '2 outputs for 2 inputs')
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
describe('getChainTips()', () => {
|
|
|
|
|
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.getChainTips(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.getChainTips(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.getChainTips(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 /getChainTips', async () => {
|
|
|
|
|
// Mock the RPC call for unit tests.
|
|
|
|
|
if (process.env.TEST === 'unit') {
|
|
|
|
|
sandbox
|
|
|
|
|
.stub(uut.axios, 'request')
|
|
|
|
|
.resolves({ data: { result: mockData.mockChainTips } })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const result = await uut.getChainTips(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.isArray(result)
|
|
|
|
|
assert.hasAnyKeys(result[0], ['height', 'hash', 'branchlen', 'status'])
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
describe('getDifficulty()', () => {
|
|
|
|
|
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.getDifficulty(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.getDifficulty(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.getDifficulty(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 /getDifficulty', async () => {
|
|
|
|
|
// Mock the RPC call for unit tests.
|
|
|
|
|
if (process.env.TEST === 'unit') {
|
|
|
|
|
sandbox
|
|
|
|
|
.stub(uut.axios, 'request')
|
|
|
|
|
.resolves({ data: { result: 4049809.205246544 } })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const result = await uut.getDifficulty(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.isNumber(result)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
describe('getMempoolInfo()', () => {
|
|
|
|
|
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.getMempoolInfo(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.getMempoolInfo(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.getMempoolInfo(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 /getMempoolInfo', async () => {
|
|
|
|
|
// Mock the RPC call for unit tests.
|
|
|
|
|
if (process.env.TEST === 'unit') {
|
|
|
|
|
sandbox
|
|
|
|
|
.stub(uut.axios, 'request')
|
|
|
|
|
.resolves({ data: { result: mockData.mockMempoolInfo } })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const result = await uut.getMempoolInfo(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.hasAnyKeys(result, [
|
|
|
|
|
'result',
|
|
|
|
|
'bytes',
|
|
|
|
|
'usage',
|
|
|
|
|
'maxmempool',
|
|
|
|
|
'mempoolminfree'
|
|
|
|
|
])
|
|
|
|
|
})
|
|
|
|
|
})
|
2020-11-21 11:35:01 -08:00
|
|
|
|
2020-07-27 21:25:31 -07:00
|
|
|
describe('getRawMempool()', () => {
|
|
|
|
|
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.getRawMempool(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'
|
|
|
|
|
)
|
|
|
|
|
})
|
2020-11-21 11:35:01 -08:00
|
|
|
|
2020-07-27 21:25:31 -07:00
|
|
|
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.getRawMempool(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'
|
|
|
|
|
)
|
|
|
|
|
})
|
2020-11-21 11:35:01 -08:00
|
|
|
|
2020-07-27 21:25:31 -07:00
|
|
|
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.getRawMempool(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'
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
|
2020-11-21 11:35:01 -08:00
|
|
|
it('should GET /getRawMempool', async () => {
|
2020-07-27 21:25:31 -07:00
|
|
|
// Mock the RPC call for unit tests.
|
|
|
|
|
if (process.env.TEST === 'unit') {
|
|
|
|
|
sandbox
|
|
|
|
|
.stub(uut.axios, 'request')
|
|
|
|
|
.resolves({ data: { result: mockData.mockRawMempool } })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const result = await uut.getRawMempool(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.isArray(result)
|
|
|
|
|
// Not sure what other assertions should be made here.
|
|
|
|
|
})
|
|
|
|
|
})
|
2020-11-21 11:35:01 -08:00
|
|
|
|
2020-07-27 21:25:31 -07:00
|
|
|
describe('getMempoolEntrySingle()', () => {
|
|
|
|
|
it('should throw 400 if txid is empty', async () => {
|
|
|
|
|
const result = await uut.getMempoolEntrySingle(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.hasAllKeys(result, ['error'])
|
|
|
|
|
assert.include(result.error, 'txid can not be empty')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
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/'
|
|
|
|
|
|
|
|
|
|
req.params.txid =
|
|
|
|
|
'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde'
|
|
|
|
|
|
|
|
|
|
const result = await uut.getMempoolEntrySingle(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' })
|
|
|
|
|
|
|
|
|
|
req.params.txid =
|
|
|
|
|
'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde'
|
|
|
|
|
|
|
|
|
|
const result = await uut.getMempoolEntrySingle(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.params.txid =
|
|
|
|
|
'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde'
|
|
|
|
|
|
|
|
|
|
const result = await uut.getMempoolEntrySingle(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 /getMempoolEntry', async () => {
|
|
|
|
|
// Mock the RPC call for unit tests.
|
|
|
|
|
if (process.env.TEST === 'unit') {
|
|
|
|
|
sandbox.stub(uut.axios, 'request').resolves({
|
|
|
|
|
data: { result: { error: 'Transaction not in mempool' } }
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
req.params.txid =
|
|
|
|
|
'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde'
|
|
|
|
|
|
|
|
|
|
const result = await uut.getMempoolEntrySingle(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.hasAllKeys(result, ['error'])
|
|
|
|
|
assert.isString(result.error)
|
|
|
|
|
assert.equal(result.error, 'Transaction not in mempool')
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
describe('#getMempoolEntryBulk', () => {
|
|
|
|
|
it('should throw an error for an empty body', async () => {
|
|
|
|
|
req.body = {}
|
|
|
|
|
|
|
|
|
|
const result = await uut.getMempoolEntryBulk(req, res)
|
|
|
|
|
|
|
|
|
|
assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.')
|
|
|
|
|
assert.include(
|
|
|
|
|
result.error,
|
|
|
|
|
'txids needs to be an array',
|
|
|
|
|
'Proper error message'
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should error on non-array single txid', async () => {
|
|
|
|
|
req.body.txids =
|
|
|
|
|
'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde'
|
|
|
|
|
|
|
|
|
|
const result = await uut.getMempoolEntryBulk(req, res)
|
|
|
|
|
|
|
|
|
|
assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.')
|
|
|
|
|
assert.include(
|
|
|
|
|
result.error,
|
|
|
|
|
'txids needs to be an array',
|
|
|
|
|
'Proper error message'
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should throw 400 error if addresses array is too large', async () => {
|
|
|
|
|
const testArray = []
|
|
|
|
|
for (var i = 0; i < 25; i++) testArray.push('')
|
|
|
|
|
|
|
|
|
|
req.body.txids = testArray
|
|
|
|
|
|
|
|
|
|
const result = await uut.getMempoolEntryBulk(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.hasAllKeys(result, ['error'])
|
|
|
|
|
assert.include(result.error, 'Array too large')
|
|
|
|
|
})
|
|
|
|
|
it('returns proper error when downstream service stalls', async () => {
|
|
|
|
|
// Mock the timeout error.
|
|
|
|
|
sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNABORTED' })
|
|
|
|
|
|
|
|
|
|
req.body.txids = [
|
|
|
|
|
'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde'
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
const result = await uut.getMempoolEntryBulk(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.txids = [
|
|
|
|
|
'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde'
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
const result = await uut.getMempoolEntryBulk(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'
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
// Only execute on integration tests.
|
|
|
|
|
if (process.env.TEST !== 'unit') {
|
|
|
|
|
// Dev-note: This test passes because it expects an error. TXIDs do not
|
|
|
|
|
// stay in the mempool for long, so it does not work well for a unit or
|
|
|
|
|
// integration test.
|
|
|
|
|
it('should retrieve single mempool entry', async () => {
|
|
|
|
|
req.body.txids = [
|
|
|
|
|
'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde'
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
const result = await uut.getMempoolEntryBulk(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.hasAllKeys(result, ['error'])
|
|
|
|
|
assert.isString(result.error)
|
|
|
|
|
assert.equal(result.error, 'Transaction not in mempool')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Dev-note: This test passes because it expects an error. TXIDs do not
|
|
|
|
|
// stay in the mempool for long, so it does not work well for a unit or
|
|
|
|
|
// integration test.
|
|
|
|
|
it('should retrieve multiple mempool entries', async () => {
|
|
|
|
|
req.body.txids = [
|
|
|
|
|
'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde',
|
|
|
|
|
'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde'
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
const result = await uut.getMempoolEntryBulk(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.hasAllKeys(result, ['error'])
|
|
|
|
|
assert.isString(result.error)
|
|
|
|
|
assert.equal(result.error, 'Transaction not in mempool')
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
describe('getMempoolAncestorsSingle()', () => {
|
|
|
|
|
it('should throw 400 if txid is empty', async () => {
|
|
|
|
|
const result = await uut.getMempoolAncestorsSingle(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.hasAllKeys(result, ['error'])
|
|
|
|
|
assert.include(result.error, 'txid can not be empty')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
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/'
|
|
|
|
|
|
|
|
|
|
req.params.txid =
|
|
|
|
|
'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde'
|
|
|
|
|
|
|
|
|
|
const result = await uut.getMempoolAncestorsSingle(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' })
|
|
|
|
|
|
|
|
|
|
req.params.txid =
|
|
|
|
|
'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde'
|
|
|
|
|
|
|
|
|
|
const result = await uut.getMempoolAncestorsSingle(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.params.txid =
|
|
|
|
|
'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde'
|
|
|
|
|
|
|
|
|
|
const result = await uut.getMempoolAncestorsSingle(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 /getMempoolAncestorsSingle', async () => {
|
|
|
|
|
sandbox
|
|
|
|
|
.stub(uut.axios, 'request')
|
|
|
|
|
.resolves({ data: { result: mockData.mockAncestors } })
|
|
|
|
|
|
|
|
|
|
req.params.txid =
|
|
|
|
|
'bb0d349892d351da2767f8c45f6f7949713ff09bd12838d53e76158ddee3ce93'
|
|
|
|
|
|
|
|
|
|
const result = await uut.getMempoolAncestorsSingle(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.isArray(result)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe('getTxOut()', () => {
|
|
|
|
|
it('should throw 400 if txid is empty', async () => {
|
|
|
|
|
const result = await uut.getTxOut(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.hasAllKeys(result, ['error'])
|
|
|
|
|
assert.include(result.error, 'txid can not be empty')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should throw 400 if n is empty', async () => {
|
|
|
|
|
req.params.txid = 'sometxid'
|
|
|
|
|
const result = await uut.getTxOut(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.hasAllKeys(result, ['error'])
|
|
|
|
|
assert.include(result.error, 'n can not be empty')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
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/'
|
|
|
|
|
|
|
|
|
|
req.params.txid =
|
|
|
|
|
'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde'
|
|
|
|
|
req.params.n = 0
|
|
|
|
|
|
|
|
|
|
const result = await uut.getTxOut(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' })
|
|
|
|
|
|
|
|
|
|
req.params.txid =
|
|
|
|
|
'197dcda59864b1eee05498fd3c52cad787ec56ab7e635503cb39f9ab6f295d5d'
|
|
|
|
|
req.params.n = 0
|
|
|
|
|
req.query.include_mempool = 'true'
|
|
|
|
|
|
|
|
|
|
const result = await uut.getTxOut(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.params.txid =
|
|
|
|
|
'197dcda59864b1eee05498fd3c52cad787ec56ab7e635503cb39f9ab6f295d5d'
|
|
|
|
|
req.params.n = 0
|
|
|
|
|
req.query.include_mempool = 'true'
|
|
|
|
|
|
|
|
|
|
const result = await uut.getTxOut(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'
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// This test can only run for unit tests. See TODO at the top of this file.
|
|
|
|
|
it('should GET /getTxOut', async () => {
|
|
|
|
|
// Mock the RPC call for unit tests.
|
|
|
|
|
if (process.env.TEST === 'unit') {
|
|
|
|
|
sandbox
|
|
|
|
|
.stub(uut.axios, 'request')
|
|
|
|
|
.resolves({ data: { result: mockData.mockTxOut } })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
req.params.txid =
|
|
|
|
|
'197dcda59864b1eee05498fd3c52cad787ec56ab7e635503cb39f9ab6f295d5d'
|
|
|
|
|
req.params.n = 0
|
|
|
|
|
req.query.include_mempool = 'true'
|
|
|
|
|
|
|
|
|
|
const result = await uut.getTxOut(req, res)
|
|
|
|
|
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
|
|
|
|
|
|
|
|
assert.hasAllKeys(result, [
|
|
|
|
|
'bestblock',
|
|
|
|
|
'confirmations',
|
|
|
|
|
'value',
|
|
|
|
|
'scriptPubKey',
|
|
|
|
|
'coinbase'
|
|
|
|
|
])
|
|
|
|
|
assert.hasAllKeys(result.scriptPubKey, [
|
|
|
|
|
'asm',
|
|
|
|
|
'hex',
|
|
|
|
|
'reqSigs',
|
|
|
|
|
'type',
|
|
|
|
|
'addresses'
|
|
|
|
|
])
|
|
|
|
|
assert.isArray(result.scriptPubKey.addresses)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe('getTxOutPost()', () => {
|
|
|
|
|
it('should throw 400 if txid is empty', async () => {
|
|
|
|
|
const result = await uut.getTxOutPost(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.hasAllKeys(result, ['error'])
|
|
|
|
|
assert.include(result.error, 'txid can not be empty')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should throw 400 if n is empty', async () => {
|
|
|
|
|
req.body.txid = 'sometxid'
|
|
|
|
|
const result = await uut.getTxOutPost(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.hasAllKeys(result, ['error'])
|
|
|
|
|
assert.include(result.error, 'vout can not be empty')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
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/'
|
|
|
|
|
|
|
|
|
|
req.body.txid =
|
|
|
|
|
'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde'
|
|
|
|
|
req.body.vout = 0
|
|
|
|
|
|
|
|
|
|
const result = await uut.getTxOutPost(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' })
|
|
|
|
|
|
|
|
|
|
req.body.txid =
|
|
|
|
|
'197dcda59864b1eee05498fd3c52cad787ec56ab7e635503cb39f9ab6f295d5d'
|
|
|
|
|
req.body.vout = 0
|
|
|
|
|
req.body.mempool = true
|
|
|
|
|
|
|
|
|
|
const result = await uut.getTxOutPost(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.txid =
|
|
|
|
|
'197dcda59864b1eee05498fd3c52cad787ec56ab7e635503cb39f9ab6f295d5d'
|
|
|
|
|
req.body.vout = 0
|
|
|
|
|
req.body.mempool = true
|
|
|
|
|
|
|
|
|
|
const result = await uut.getTxOutPost(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 POST /getTxOut', async () => {
|
|
|
|
|
// Mock the RPC call for unit tests.
|
|
|
|
|
if (process.env.TEST === 'unit') {
|
|
|
|
|
sandbox
|
|
|
|
|
.stub(uut.axios, 'request')
|
|
|
|
|
.resolves({ data: { result: mockData.mockTxOut } })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
req.body.txid =
|
|
|
|
|
'197dcda59864b1eee05498fd3c52cad787ec56ab7e635503cb39f9ab6f295d5d'
|
|
|
|
|
req.body.vout = 0
|
|
|
|
|
req.body.mempool = true
|
|
|
|
|
|
|
|
|
|
const result = await uut.getTxOutPost(req, res)
|
|
|
|
|
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
|
|
|
|
|
|
|
|
assert.hasAllKeys(result, [
|
|
|
|
|
'bestblock',
|
|
|
|
|
'confirmations',
|
|
|
|
|
'value',
|
|
|
|
|
'scriptPubKey',
|
|
|
|
|
'coinbase'
|
|
|
|
|
])
|
|
|
|
|
assert.hasAllKeys(result.scriptPubKey, [
|
|
|
|
|
'asm',
|
|
|
|
|
'hex',
|
|
|
|
|
'reqSigs',
|
|
|
|
|
'type',
|
|
|
|
|
'addresses'
|
|
|
|
|
])
|
|
|
|
|
assert.isArray(result.scriptPubKey.addresses)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe('getTxOutProofSingle()', () => {
|
|
|
|
|
it('should throw 400 if txid is empty', async () => {
|
|
|
|
|
const result = await uut.getTxOutProofSingle(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.hasAllKeys(result, ['error'])
|
|
|
|
|
assert.include(result.error, 'txid can not be empty')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
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/'
|
|
|
|
|
|
|
|
|
|
req.params.txid =
|
|
|
|
|
'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde'
|
|
|
|
|
|
|
|
|
|
const result = await uut.getTxOutProofSingle(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' })
|
|
|
|
|
|
|
|
|
|
req.params.txid =
|
|
|
|
|
'197dcda59864b1eee05498fd3c52cad787ec56ab7e635503cb39f9ab6f295d5d'
|
|
|
|
|
req.params.n = 0
|
|
|
|
|
req.query.include_mempool = 'true'
|
|
|
|
|
|
|
|
|
|
const result = await uut.getTxOutProofSingle(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.params.txid =
|
|
|
|
|
'197dcda59864b1eee05498fd3c52cad787ec56ab7e635503cb39f9ab6f295d5d'
|
|
|
|
|
req.params.n = 0
|
|
|
|
|
req.query.include_mempool = 'true'
|
|
|
|
|
|
|
|
|
|
const result = await uut.getTxOutProofSingle(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 /getTxOutProof', async () => {
|
|
|
|
|
// Mock the RPC call for unit tests.
|
|
|
|
|
if (process.env.TEST === 'unit') {
|
|
|
|
|
sandbox
|
|
|
|
|
.stub(uut.axios, 'request')
|
|
|
|
|
.resolves({ data: { result: mockData.mockTxOutProof } })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
req.params.txid =
|
|
|
|
|
'2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266'
|
|
|
|
|
|
|
|
|
|
const result = await uut.getTxOutProofSingle(req, res)
|
|
|
|
|
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
|
|
|
|
|
|
|
|
assert.isString(result)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe('#getTxOutProofBulk', () => {
|
|
|
|
|
it('should throw an error for an empty body', async () => {
|
|
|
|
|
req.body = {}
|
|
|
|
|
|
|
|
|
|
const result = await uut.getTxOutProofBulk(req, res)
|
|
|
|
|
|
|
|
|
|
assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.')
|
|
|
|
|
assert.include(
|
|
|
|
|
result.error,
|
|
|
|
|
'txids needs to be an array',
|
|
|
|
|
'Proper error message'
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should error on non-array single txid', async () => {
|
|
|
|
|
req.body.txids =
|
|
|
|
|
'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde'
|
|
|
|
|
|
|
|
|
|
const result = await uut.getTxOutProofBulk(req, res)
|
|
|
|
|
|
|
|
|
|
assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.')
|
|
|
|
|
assert.include(
|
|
|
|
|
result.error,
|
|
|
|
|
'txids needs to be an array',
|
|
|
|
|
'Proper error message'
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should throw 400 error if addresses array is too large', async () => {
|
|
|
|
|
const testArray = []
|
|
|
|
|
for (var i = 0; i < 25; i++) testArray.push('')
|
|
|
|
|
|
|
|
|
|
req.body.txids = testArray
|
|
|
|
|
|
|
|
|
|
const result = await uut.getTxOutProofBulk(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.hasAllKeys(result, ['error'])
|
|
|
|
|
assert.include(result.error, 'Array too large')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('returns proper error when downstream service stalls', async () => {
|
|
|
|
|
// Mock the timeout error.
|
|
|
|
|
sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNABORTED' })
|
|
|
|
|
|
|
|
|
|
req.body.txids = [
|
|
|
|
|
'2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266'
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
const result = await uut.getTxOutProofBulk(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.txids = [
|
|
|
|
|
'2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266'
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
const result = await uut.getTxOutProofBulk(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 proof for single txid', async () => {
|
|
|
|
|
// Mock the RPC call for unit tests.
|
|
|
|
|
if (process.env.TEST === 'unit') {
|
|
|
|
|
sandbox
|
|
|
|
|
.stub(uut.axios, 'request')
|
|
|
|
|
.resolves({ data: { result: mockData.mockTxOutProof } })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
req.body.txids = [
|
|
|
|
|
'2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266'
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
const result = await uut.getTxOutProofBulk(req, res)
|
|
|
|
|
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
|
|
|
|
|
|
|
|
assert.isArray(result)
|
|
|
|
|
assert.isString(result[0])
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should GET proof for multiple txids', async () => {
|
|
|
|
|
// Mock the RPC call for unit tests.
|
|
|
|
|
if (process.env.TEST === 'unit') {
|
|
|
|
|
sandbox
|
|
|
|
|
.stub(uut.axios, 'request')
|
|
|
|
|
.resolves({ data: { result: mockData.mockTxOutProof } })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
req.body.txids = [
|
|
|
|
|
'2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266',
|
|
|
|
|
'2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266'
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
const result = await uut.getTxOutProofBulk(req, res)
|
|
|
|
|
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
|
|
|
|
|
|
|
|
assert.isArray(result)
|
|
|
|
|
assert.equal(result.length, 2, 'Correct length of returned array')
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
describe('verifyTxOutProofSingle()', () => {
|
|
|
|
|
it('should throw 400 if proof is empty', async () => {
|
|
|
|
|
const result = await uut.verifyTxOutProofSingle(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.hasAllKeys(result, ['error'])
|
|
|
|
|
assert.include(result.error, 'proof can not be empty')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
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/'
|
|
|
|
|
|
|
|
|
|
req.params.proof = mockData.mockTxOutProof
|
|
|
|
|
|
|
|
|
|
const result = await uut.verifyTxOutProofSingle(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' })
|
|
|
|
|
|
|
|
|
|
req.params.proof =
|
|
|
|
|
'000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700'
|
|
|
|
|
|
|
|
|
|
const result = await uut.verifyTxOutProofSingle(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.params.proof =
|
|
|
|
|
'000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700'
|
|
|
|
|
|
|
|
|
|
const result = await uut.verifyTxOutProofSingle(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 /verifyTxOutProof', async () => {
|
|
|
|
|
const expected =
|
|
|
|
|
'2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266'
|
|
|
|
|
|
|
|
|
|
// Mock the RPC call for unit tests.
|
|
|
|
|
if (process.env.TEST === 'unit') {
|
|
|
|
|
sandbox
|
|
|
|
|
.stub(uut.axios, 'request')
|
|
|
|
|
.resolves({ data: { result: [expected] } })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
req.params.proof =
|
|
|
|
|
'000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700'
|
|
|
|
|
|
|
|
|
|
const result = await uut.verifyTxOutProofSingle(req, res)
|
|
|
|
|
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
|
|
|
|
|
|
|
|
assert.isArray(result)
|
|
|
|
|
assert.isString(result[0])
|
|
|
|
|
assert.equal(result[0], expected)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
describe('#verifyTxOutProofBulk', () => {
|
|
|
|
|
it('should throw an error for an empty body', async () => {
|
|
|
|
|
req.body = {}
|
|
|
|
|
|
|
|
|
|
const result = await uut.verifyTxOutProofBulk(req, res)
|
|
|
|
|
|
|
|
|
|
assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.')
|
|
|
|
|
assert.include(
|
|
|
|
|
result.error,
|
|
|
|
|
'proofs needs to be an array',
|
|
|
|
|
'Proper error message'
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should error on non-array single txid', async () => {
|
|
|
|
|
req.body.proofs = mockData.mockTxOutProof
|
|
|
|
|
|
|
|
|
|
const result = await uut.verifyTxOutProofBulk(req, res)
|
|
|
|
|
|
|
|
|
|
assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.')
|
|
|
|
|
assert.include(
|
|
|
|
|
result.error,
|
|
|
|
|
'proofs needs to be an array',
|
|
|
|
|
'Proper error message'
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should throw 400 error if addresses array is too large', async () => {
|
|
|
|
|
const testArray = []
|
|
|
|
|
for (var i = 0; i < 25; i++) testArray.push('')
|
|
|
|
|
|
|
|
|
|
req.body.proofs = testArray
|
|
|
|
|
|
|
|
|
|
const result = await uut.verifyTxOutProofBulk(req, res)
|
|
|
|
|
// console.log(`result: ${util.inspect(result)}`)
|
|
|
|
|
|
|
|
|
|
assert.hasAllKeys(result, ['error'])
|
|
|
|
|
assert.include(result.error, 'Array too large')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('returns proper error when downstream service stalls', async () => {
|
|
|
|
|
// Mock the timeout error.
|
|
|
|
|
sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNABORTED' })
|
|
|
|
|
|
|
|
|
|
req.body.proofs = [
|
|
|
|
|
'000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700'
|
|
|
|
|
]
|
|
|
|
|
const result = await uut.verifyTxOutProofBulk(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.proofs = [
|
|
|
|
|
'000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700'
|
|
|
|
|
]
|
|
|
|
|
const result = await uut.verifyTxOutProofBulk(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 single proof', async () => {
|
|
|
|
|
const expected =
|
|
|
|
|
'2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266'
|
|
|
|
|
|
|
|
|
|
// Mock the RPC call for unit tests.
|
|
|
|
|
if (process.env.TEST === 'unit') {
|
|
|
|
|
sandbox
|
|
|
|
|
.stub(uut.axios, 'request')
|
|
|
|
|
.resolves({ data: { result: [expected] } })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
req.body.proofs = [
|
|
|
|
|
'000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700'
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
const result = await uut.verifyTxOutProofBulk(req, res)
|
|
|
|
|
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
|
|
|
|
|
|
|
|
assert.isArray(result)
|
|
|
|
|
assert.isString(result[0])
|
|
|
|
|
assert.equal(result[0], expected)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should get multiple proofs', async () => {
|
|
|
|
|
const expected =
|
|
|
|
|
'2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266'
|
|
|
|
|
|
|
|
|
|
// Mock the RPC call for unit tests.
|
|
|
|
|
if (process.env.TEST === 'unit') {
|
|
|
|
|
sandbox
|
|
|
|
|
.stub(uut.axios, 'request')
|
|
|
|
|
.resolves({ data: { result: [expected] } })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
req.body.proofs = [
|
|
|
|
|
'000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700',
|
|
|
|
|
'000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700'
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
const result = await uut.verifyTxOutProofBulk(req, res)
|
|
|
|
|
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
|
|
|
|
|
|
|
|
|
assert.isArray(result)
|
|
|
|
|
assert.isString(result[0])
|
|
|
|
|
assert.equal(result[0], expected)
|
|
|
|
|
assert.equal(result.length, 2)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
})
|