mirror of
https://github.com/fullstack-cash/bch-api.git
synced 2026-09-22 17:22:04 -07:00
Merge pull request #127 from christroutner/unstable
Adding ElectrumX Route Library
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Config settings for working with an ElectrumX or Fulcrum server.
|
||||
*/
|
||||
|
||||
const config = {
|
||||
port: 8000,
|
||||
electrum: {
|
||||
application: 'bch-api',
|
||||
version: '1.4.1',
|
||||
confidence: 2,
|
||||
distribution: 3,
|
||||
// servers: [
|
||||
// 'fulcrum.fountainhead.cash:50002',
|
||||
// 'electrum.imaginary.cash:50002',
|
||||
// 'bch.imaginary.cash:50002',
|
||||
// 'electroncash.de:50002',
|
||||
// 'electroncash.dk:50002',
|
||||
// 'electron.jochen-hoenicke.de:51002'
|
||||
// ]
|
||||
serverUrl: 'fulcrum.fountainhead.cash',
|
||||
// serverUrl: 'badurl.com',
|
||||
serverPort: '50002'
|
||||
},
|
||||
ratelimit: {
|
||||
windowMs: 1 * 60 * 1000,
|
||||
max: 100
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = config
|
||||
+7
-2
@@ -2,6 +2,11 @@
|
||||
Common configuration settings.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
apiTokenSecret: process.env.TOKENSECRET ? process.env.TOKENSECRET : 'secret-jwt-token'
|
||||
const electrumxConfig = require('./electrumx')
|
||||
|
||||
const config = {
|
||||
apiTokenSecret: process.env.TOKENSECRET ? process.env.TOKENSECRET : 'secret-jwt-token',
|
||||
electrumx: electrumxConfig
|
||||
}
|
||||
|
||||
module.exports = config
|
||||
|
||||
Generated
+83
@@ -2255,6 +2255,76 @@
|
||||
"varuint-bitcoin": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"bitcore-lib": {
|
||||
"version": "8.16.2",
|
||||
"resolved": "https://registry.npmjs.org/bitcore-lib/-/bitcore-lib-8.16.2.tgz",
|
||||
"integrity": "sha512-wyiys24QYbj8CjeQvV0D0oMXJAEeIBJYf+ubob0d2sIno1P4hLkTkj/Yu4RGnUeePLVVWXcjnSR2micHimvU8w==",
|
||||
"requires": {
|
||||
"bech32": "=1.1.3",
|
||||
"bn.js": "=4.11.8",
|
||||
"bs58": "^4.0.1",
|
||||
"buffer-compare": "=1.1.1",
|
||||
"elliptic": "=6.4.0",
|
||||
"inherits": "=2.0.1",
|
||||
"lodash": "=4.17.15"
|
||||
},
|
||||
"dependencies": {
|
||||
"elliptic": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz",
|
||||
"integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=",
|
||||
"requires": {
|
||||
"bn.js": "^4.4.0",
|
||||
"brorand": "^1.0.1",
|
||||
"hash.js": "^1.0.0",
|
||||
"hmac-drbg": "^1.0.0",
|
||||
"inherits": "^2.0.1",
|
||||
"minimalistic-assert": "^1.0.0",
|
||||
"minimalistic-crypto-utils": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
|
||||
"integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE="
|
||||
}
|
||||
}
|
||||
},
|
||||
"bitcore-lib-cash": {
|
||||
"version": "8.16.2",
|
||||
"resolved": "https://registry.npmjs.org/bitcore-lib-cash/-/bitcore-lib-cash-8.16.2.tgz",
|
||||
"integrity": "sha512-WmREw2XkoEFKmIbJjhSmRgQUCh9XNfmJz6fdoVMReuqpQuzNWJtTueXmxDYMBvYDOmS4RNZq8SbBfkUOEqLTUQ==",
|
||||
"requires": {
|
||||
"bitcore-lib": "^8.16.2",
|
||||
"bn.js": "=4.11.8",
|
||||
"bs58": "^4.0.1",
|
||||
"buffer-compare": "=1.1.1",
|
||||
"elliptic": "=6.4.0",
|
||||
"inherits": "=2.0.1",
|
||||
"lodash": "=4.17.15"
|
||||
},
|
||||
"dependencies": {
|
||||
"elliptic": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz",
|
||||
"integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=",
|
||||
"requires": {
|
||||
"bn.js": "^4.4.0",
|
||||
"brorand": "^1.0.1",
|
||||
"hash.js": "^1.0.0",
|
||||
"hmac-drbg": "^1.0.0",
|
||||
"inherits": "^2.0.1",
|
||||
"minimalistic-assert": "^1.0.0",
|
||||
"minimalistic-crypto-utils": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
|
||||
"integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE="
|
||||
}
|
||||
}
|
||||
},
|
||||
"bl": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
|
||||
@@ -2503,6 +2573,11 @@
|
||||
"ieee754": "^1.1.4"
|
||||
}
|
||||
},
|
||||
"buffer-compare": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-compare/-/buffer-compare-1.1.1.tgz",
|
||||
"integrity": "sha1-W+e+hTr4kZjR9N3AkNHWakiu9ZY="
|
||||
},
|
||||
"buffer-equal-constant-time": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
|
||||
@@ -3912,6 +3987,14 @@
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
|
||||
},
|
||||
"electrum-cash": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/electrum-cash/-/electrum-cash-1.0.1.tgz",
|
||||
"integrity": "sha512-snMgRt6JzsHdCdf+Un1rLj4RXjje1WuFVTx3Xx+6mitEibYalmD+x0ts146VF4Ki3+42DQKXtQXl0bzCAY7Jtw==",
|
||||
"requires": {
|
||||
"debug": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"elliptic": {
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.1.tgz",
|
||||
|
||||
@@ -30,11 +30,13 @@
|
||||
"@chris.troutner/bch-js": "^2.0.0",
|
||||
"apidoc": "^0.20.0",
|
||||
"axios": "^0.19.0",
|
||||
"bitcore-lib-cash": "^8.16.2",
|
||||
"body-parser": "^1.18.3",
|
||||
"cookie-parser": "~1.4.3",
|
||||
"cors": "^2.8.3",
|
||||
"debug": "~4.1.1",
|
||||
"dotenv": "^8.0.0",
|
||||
"electrum-cash": "^1.0.1",
|
||||
"express": "^4.15.5",
|
||||
"express-basic-auth": "^1.1.3",
|
||||
"express-rate-limit": "^5.0.0",
|
||||
|
||||
@@ -104,7 +104,7 @@ class Blockbook {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/blockbook/balance/bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf" -H "accept: application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/blockbook/balance/bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf" -H "accept: application/json"
|
||||
*
|
||||
*/
|
||||
// GET handler for single balance
|
||||
@@ -173,7 +173,7 @@ class Blockbook {
|
||||
* Limited to 20 items per request.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X POST "https://mainnet.bchjs.cash/v3/blockbook/balance" -H "accept: application/json" -H "Content-Type: application/json" -d '{"addresses":["bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf","bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf"]}'
|
||||
* curl -X POST "https://api.fullstack.cash/v3/blockbook/balance" -H "accept: application/json" -H "Content-Type: application/json" -d '{"addresses":["bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf","bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf"]}'
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -292,7 +292,7 @@ class Blockbook {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/blockbook/utxos/bitcoincash:qr69kyzha07dcecrsvjwsj4s6slnlq4r8c30lxnur3" -H "accept: application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/blockbook/utxos/bitcoincash:qr69kyzha07dcecrsvjwsj4s6slnlq4r8c30lxnur3" -H "accept: application/json"
|
||||
*
|
||||
*/
|
||||
// GET handler for single balance
|
||||
@@ -360,7 +360,7 @@ class Blockbook {
|
||||
* Limited to 20 items per request.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X POST "https://mainnet.bchjs.cash/v3/blockbook/utxos" -H "accept: application/json" -H "Content-Type: application/json" -d '{"addresses":["bitcoincash:qr69kyzha07dcecrsvjwsj4s6slnlq4r8c30lxnur3","bitcoincash:qzy8wnj0dz927eu6kvh8v2pqsr5w8jh33ys757tdtq"]}'
|
||||
* curl -X POST "https://api.fullstack.cash/v3/blockbook/utxos" -H "accept: application/json" -H "Content-Type: application/json" -d '{"addresses":["bitcoincash:qr69kyzha07dcecrsvjwsj4s6slnlq4r8c30lxnur3","bitcoincash:qzy8wnj0dz927eu6kvh8v2pqsr5w8jh33ys757tdtq"]}'
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -469,7 +469,7 @@ class Blockbook {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/blockbook/tx/6181c669614fa18039a19b23eb06806bfece1f7514ab457c3bb82a40fe171a6d" -H "accept: application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/blockbook/tx/6181c669614fa18039a19b23eb06806bfece1f7514ab457c3bb82a40fe171a6d" -H "accept: application/json"
|
||||
*
|
||||
*/
|
||||
// GET handler for single transaction details.
|
||||
@@ -522,7 +522,7 @@ class Blockbook {
|
||||
* Limited to 20 items per request.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X POST "https://mainnet.bchjs.cash/v3/blockbook/tx" -H "accept: application/json" -H "Content-Type: application/json" -d '{"txids":["6181c669614fa18039a19b23eb06806bfece1f7514ab457c3bb82a40fe171a6d","6181c669614fa18039a19b23eb06806bfece1f7514ab457c3bb82a40fe171a6d"]}'
|
||||
* curl -X POST "https://api.fullstack.cash/v3/blockbook/tx" -H "accept: application/json" -H "Content-Type: application/json" -d '{"txids":["6181c669614fa18039a19b23eb06806bfece1f7514ab457c3bb82a40fe171a6d","6181c669614fa18039a19b23eb06806bfece1f7514ab457c3bb82a40fe171a6d"]}'
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
Electrum API route
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
const express = require('express')
|
||||
const router = express.Router()
|
||||
const axios = require('axios')
|
||||
const util = require('util')
|
||||
const bitcore = require('bitcore-lib-cash')
|
||||
const ElectrumCash = require('electrum-cash').Client
|
||||
|
||||
const wlogger = require('../../util/winston-logging')
|
||||
const config = require('../../../config')
|
||||
|
||||
const RouteUtils = require('../../util/route-utils')
|
||||
const routeUtils = new RouteUtils()
|
||||
|
||||
const BCHJS = require('@chris.troutner/bch-js')
|
||||
const bchjs = new BCHJS()
|
||||
|
||||
let _this
|
||||
|
||||
class Electrum {
|
||||
constructor () {
|
||||
_this = this
|
||||
|
||||
_this.config = config
|
||||
_this.axios = axios
|
||||
_this.routeUtils = routeUtils
|
||||
_this.bchjs = bchjs
|
||||
_this.bitcore = bitcore
|
||||
|
||||
// Configure the ElectrumX/Fulcrum server.
|
||||
// _this.electrumx = new ElectrumCash(
|
||||
// config.electrumx.application,
|
||||
// config.electrumx.version,
|
||||
// config.electrumx.confidence,
|
||||
// config.electrumx.distribution,
|
||||
// ElectrumCash.ORDER.PRIORITY
|
||||
// )
|
||||
_this.electrumx = new ElectrumCash(
|
||||
config.electrumx.electrum.application,
|
||||
config.electrumx.electrum.version,
|
||||
config.electrumx.electrum.serverUrl,
|
||||
config.electrumx.electrum.serverPort
|
||||
)
|
||||
|
||||
_this.isReady = false
|
||||
// _this.connectToServers()
|
||||
|
||||
_this.router = router
|
||||
_this.router.get('/', _this.root)
|
||||
_this.router.get('/utxos/:address', _this.getUtxos)
|
||||
}
|
||||
|
||||
// Initializes a connection to electrum servers.
|
||||
async connect () {
|
||||
try {
|
||||
console.log('Entering connectToServers()')
|
||||
|
||||
// Return immediately if a connection has already been established.
|
||||
if (_this.isReady) return true
|
||||
|
||||
// Connect to the server.
|
||||
await _this.electrumx.connect()
|
||||
|
||||
// Set the connection flag.
|
||||
_this.isReady = true
|
||||
|
||||
// console.log(`_this.isReady: ${_this.isReady}`)
|
||||
return _this.isReady
|
||||
} catch (err) {
|
||||
// console.log(`err: `, err)
|
||||
wlogger.error('Error in electrumx.js/connect()')
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
// Disconnect from the ElectrumX server.
|
||||
async disconnect () {
|
||||
try {
|
||||
// Return immediately if the isReady flag is false.
|
||||
if (!_this.isReady) return true
|
||||
|
||||
// Disconnect from the server.
|
||||
await _this.electrumx.disconnect()
|
||||
|
||||
// Clear the isReady flag.
|
||||
_this.isReady = false
|
||||
|
||||
// Return true to signal that the disconnection happened successfully.
|
||||
return true
|
||||
} catch (err) {
|
||||
// console.log(`err: `, err)
|
||||
wlogger.error('Error in electrumx.js/disconnect()')
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
// DRY error handler.
|
||||
errorHandler (err, res) {
|
||||
// Attempt to decode the error message.
|
||||
const { msg, status } = _this.routeUtils.decodeError(err)
|
||||
if (msg) {
|
||||
res.status(status)
|
||||
return res.json({ error: msg })
|
||||
}
|
||||
|
||||
// Handle error patterns specific to this route.
|
||||
if (err.message) {
|
||||
res.status(400)
|
||||
return res.json({ success: false, error: err.message })
|
||||
}
|
||||
|
||||
// If error can be handled, return the stack trace
|
||||
res.status(500)
|
||||
return res.json({ error: util.inspect(err) })
|
||||
}
|
||||
|
||||
// Root API endpoint. Simply acknowledges that it exists.
|
||||
root (req, res, next) {
|
||||
return res.json({ status: 'electrumx' })
|
||||
}
|
||||
|
||||
async getUtxos (req, res, next) {
|
||||
try {
|
||||
const address = req.params.address
|
||||
|
||||
// Reject if address is an array.
|
||||
if (Array.isArray(address)) {
|
||||
res.status(400)
|
||||
return res.json({
|
||||
success: false,
|
||||
error: 'address can not be an array. Use POST for bulk upload.'
|
||||
})
|
||||
}
|
||||
|
||||
const cashAddr = _this.bchjs.Address.toCashAddress(address)
|
||||
|
||||
// Prevent a common user error. Ensure they are using the correct network address.
|
||||
const networkIsValid = _this.routeUtils.validateNetwork(cashAddr)
|
||||
if (!networkIsValid) {
|
||||
res.status(400)
|
||||
return res.json({
|
||||
success: false,
|
||||
error:
|
||||
'Invalid network. Trying to use a testnet address on mainnet, or vice versa.'
|
||||
})
|
||||
}
|
||||
|
||||
wlogger.debug('Executing electrumx/getUtxos with this address: ', address)
|
||||
|
||||
// Convert the address to a scripthash.
|
||||
const scripthash = _this.addressToScripthash(cashAddr)
|
||||
|
||||
if (!_this.isReady) {
|
||||
throw new Error(
|
||||
'ElectrumX server connection is not ready. Call await connectToServer() first.'
|
||||
)
|
||||
}
|
||||
|
||||
// Query the utxos from the ElectrumX server.
|
||||
var electrumResponse = await _this.electrumx.request(
|
||||
'blockchain.scripthash.listunspent',
|
||||
scripthash
|
||||
)
|
||||
// console.log(
|
||||
// `electrumResponse: ${JSON.stringify(electrumResponse, null, 2)}`
|
||||
// )
|
||||
|
||||
// Pass the error message if ElectrumX reports an error.
|
||||
if (Object.prototype.hasOwnProperty.call(electrumResponse, 'code')) {
|
||||
res.status(400)
|
||||
return res.json({
|
||||
success: false,
|
||||
message: electrumResponse.message
|
||||
})
|
||||
}
|
||||
|
||||
res.status(200)
|
||||
return res.json({
|
||||
success: true,
|
||||
utxos: electrumResponse
|
||||
})
|
||||
} catch (err) {
|
||||
// Write out error to error log.
|
||||
wlogger.error('Error in elecrumx.js/getUtxos().', err)
|
||||
|
||||
return _this.errorHandler(err, res)
|
||||
}
|
||||
}
|
||||
|
||||
// Convert a 'bitcoincash:...' address to a script hash used by ElectrumX.
|
||||
addressToScripthash (addrStr) {
|
||||
try {
|
||||
// console.log(`addrStr: ${addrStr}`)
|
||||
|
||||
const address = _this.bitcore.Address.fromString(addrStr)
|
||||
// console.log(`address: ${address}`)
|
||||
|
||||
const script = _this.bitcore.Script.buildPublicKeyHashOut(address)
|
||||
// console.log(`script: ${script}`)
|
||||
|
||||
const scripthash = _this.bitcore.crypto.Hash.sha256(script.toBuffer())
|
||||
.reverse()
|
||||
.toString('hex')
|
||||
// console.log(`scripthash: ${scripthash}`)
|
||||
|
||||
return scripthash
|
||||
} catch (err) {
|
||||
wlogger.error('Error in electrumx.js/addressToScripthash()')
|
||||
throw err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Electrum
|
||||
@@ -79,7 +79,7 @@ class Blockchain {
|
||||
* block chain.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/blockchain/getBestBlockHash" -H "accept: application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/blockchain/getBestBlockHash" -H "accept: application/json"
|
||||
*
|
||||
* @apiSuccess {String} bestBlockHash 000000000000000002bc884334336d99c9a9c616670a9244c6a8c1fc35aa91a1
|
||||
*/
|
||||
@@ -110,7 +110,7 @@ class 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"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/blockchain/getBlockchainInfo" -H "accept: application/json"
|
||||
*
|
||||
* @apiSuccess {Object} object Object containing data
|
||||
* @apiSuccess {String} object.chain "main"
|
||||
@@ -154,7 +154,7 @@ class Blockchain {
|
||||
* @apiDescription Returns the number of blocks in the longest blockchain.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/blockchain/getBlockCount" -H "accept: application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/blockchain/getBlockCount" -H "accept: application/json"
|
||||
*
|
||||
* @apiSuccess {Number} bestBlockCount 587665
|
||||
*/
|
||||
@@ -187,7 +187,7 @@ class Blockchain {
|
||||
* returns an Object with information about blockheader hash.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/blockchain/getBlockHeader/000000000000000005e14d3f9fdfb70745308706615cfa9edca4f4558332b201?verbose=true" -H "accept: application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/blockchain/getBlockHeader/000000000000000005e14d3f9fdfb70745308706615cfa9edca4f4558332b201?verbose=true" -H "accept: application/json"
|
||||
*
|
||||
* @apiParam {String} hash block hash
|
||||
* @apiParam {Boolean} verbose Return verbose data
|
||||
@@ -340,7 +340,7 @@ class Blockchain {
|
||||
* including the main chain as well as orphaned branches.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/blockchain/getChainTips" -H "accept: application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/blockchain/getChainTips" -H "accept: application/json"
|
||||
*
|
||||
*/
|
||||
async getChainTips (req, res, next) {
|
||||
@@ -371,7 +371,7 @@ class Blockchain {
|
||||
* power on the network.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/blockchain/getDifficulty" -H "accept: application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/blockchain/getDifficulty" -H "accept: application/json"
|
||||
*
|
||||
*/
|
||||
async getDifficulty (req, res, next) {
|
||||
@@ -403,7 +403,7 @@ class Blockchain {
|
||||
* mempool (unconfirmed)
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/blockchain/getMempoolEntry/fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33" -H "accept: application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/blockchain/getMempoolEntry/fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33" -H "accept: application/json"
|
||||
*
|
||||
*/
|
||||
async getMempoolEntrySingle (req, res, next) {
|
||||
@@ -441,7 +441,7 @@ class Blockchain {
|
||||
* @apiDescription Returns mempool data for multiple transactions
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X POST https://mainnet.bchjs.cash/v3/blockchain/getMempoolEntry -H "Content-Type: application/json" -d "{\"txids\":[\"a5f972572ee1753e2fd2457dd61ce5f40fa2f8a30173d417e49feef7542c96a1\",\"5165dc531aad05d1149bb0f0d9b7bda99c73e2f05e314bcfb5b4bb9ca5e1af5e\"]}"
|
||||
* curl -X POST https://api.fullstack.cash/v3/blockchain/getMempoolEntry -H "Content-Type: application/json" -d "{\"txids\":[\"a5f972572ee1753e2fd2457dd61ce5f40fa2f8a30173d417e49feef7542c96a1\",\"5165dc531aad05d1149bb0f0d9b7bda99c73e2f05e314bcfb5b4bb9ca5e1af5e\"]}"
|
||||
*/
|
||||
async getMempoolEntryBulk (req, res, next) {
|
||||
try {
|
||||
@@ -514,7 +514,7 @@ class Blockchain {
|
||||
* against the 25 ancestor chain-limit.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/blockchain/getMempoolAncestors/fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33" -H "accept: application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/blockchain/getMempoolAncestors/fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33" -H "accept: application/json"
|
||||
*
|
||||
*/
|
||||
async getMempoolAncestorsSingle (req, res, next) {
|
||||
@@ -556,7 +556,7 @@ class Blockchain {
|
||||
* @apiDescription Returns details on the active state of the TX memory pool.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET https://mainnet.bchjs.cash/v3/getMempoolInfo -H "accept: application/json"
|
||||
* curl -X GET https://api.fullstack.cash/v3/getMempoolInfo -H "accept: application/json"
|
||||
*
|
||||
*/
|
||||
async getMempoolInfo (req, res, next) {
|
||||
@@ -586,7 +586,7 @@ class Blockchain {
|
||||
* @apiDescription Returns details on the active state of the TX memory pool.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET https://mainnet.bchjs.cash/v3/getMempoolInfo -H "accept: application/json"
|
||||
* curl -X GET https://api.fullstack.cash/v3/getMempoolInfo -H "accept: application/json"
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -598,7 +598,7 @@ class Blockchain {
|
||||
* of string transaction ids.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/getRawMempool/?verbose=true" -H "accept: application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/getRawMempool/?verbose=true" -H "accept: application/json"
|
||||
*
|
||||
* @apiParam {Boolean} verbose Return verbose data
|
||||
*
|
||||
@@ -634,7 +634,7 @@ class Blockchain {
|
||||
* @apiDescription Returns details about an unspent transaction output.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/blockchain/getTxOut/fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33/0?mempool=false" -H "accept: application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/blockchain/getTxOut/fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33/0?mempool=false" -H "accept: application/json"
|
||||
*
|
||||
* @apiParam {String} txid Transaction id (required)
|
||||
* @apiParam {Number} n Output number (required)
|
||||
@@ -691,7 +691,7 @@ class Blockchain {
|
||||
* @apiDescription Returns a hex-encoded proof that 'txid' was included in a block.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/blockchain/getTxOutProofSingle/fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33" -H "accept: application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/blockchain/getTxOutProofSingle/fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33" -H "accept: application/json"
|
||||
*
|
||||
* @apiParam {String} txid Transaction id (required)
|
||||
*
|
||||
|
||||
@@ -53,7 +53,7 @@ class Control {
|
||||
* @apiDescription RPC call which gets basic full node information.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/control/getnetworkinfo" -H "accept: application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/control/getnetworkinfo" -H "accept: application/json"
|
||||
*
|
||||
*/
|
||||
async getNetworkInfo (req, res, next) {
|
||||
|
||||
@@ -77,7 +77,7 @@ class Mining {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/mining/getMiningInfo" -H "accept: application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/mining/getMiningInfo" -H "accept: application/json"
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -107,7 +107,7 @@ class Mining {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/mining/getNetworkHashps?nblocks=120&height=-1" -H "accept: application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/mining/getNetworkHashps?nblocks=120&height=-1" -H "accept: application/json"
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -65,7 +65,7 @@ class RawTransactions {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/rawtransactions/decodeRawTransaction/02000000010e991f7ccec410f27d333f737f149b5d3be6728687da81072e638aed0063a176010000006b483045022100cd20443b0af090053450bc4ab00d563d4ac5955bb36e0135b00b8a96a19f233302205047f2c70a08c6ef4b76f2d198b33a31d17edfaa7e1e9e865894da0d396009354121024d4e7f522f67105b7bf5f9dbe557e7b2244613fdfcd6fe09304f93877328f6beffffffff02a0860100000000001976a9140ee020c07f39526ac5505c54fa1ab98490979b8388acb5f0f70b000000001976a9143a9b2b0c12fe722fcf653b6ef5dcc38732d6ff5188ac00000000" -H "accept: application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/rawtransactions/decodeRawTransaction/02000000010e991f7ccec410f27d333f737f149b5d3be6728687da81072e638aed0063a176010000006b483045022100cd20443b0af090053450bc4ab00d563d4ac5955bb36e0135b00b8a96a19f233302205047f2c70a08c6ef4b76f2d198b33a31d17edfaa7e1e9e865894da0d396009354121024d4e7f522f67105b7bf5f9dbe557e7b2244613fdfcd6fe09304f93877328f6beffffffff02a0860100000000001976a9140ee020c07f39526ac5505c54fa1ab98490979b8388acb5f0f70b000000001976a9143a9b2b0c12fe722fcf653b6ef5dcc38732d6ff5188ac00000000" -H "accept: application/json"
|
||||
*/
|
||||
async decodeRawTransactionSingle (req, res, next) {
|
||||
try {
|
||||
@@ -103,7 +103,7 @@ class RawTransactions {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X POST "https://mainnet.bchjs.cash/v3/rawtransactions/decodeRawTransaction" -H "accept: application/json" -H "Content-Type: application/json" -d '{"hexes":["01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000","01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000"]}'
|
||||
* curl -X POST "https://api.fullstack.cash/v3/rawtransactions/decodeRawTransaction" -H "accept: application/json" -H "Content-Type: application/json" -d '{"hexes":["01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000","01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000"]}'
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -177,7 +177,7 @@ class RawTransactions {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/rawtransactions/decodeScript/4830450221009a51e00ec3524a7389592bc27bea4af5104a59510f5f0cfafa64bbd5c164ca2e02206c2a8bbb47eabdeed52f17d7df668d521600286406930426e3a9415fe10ed592012102e6e1423f7abde8b70bca3e78a7d030e5efabd3eb35c19302542b5fe7879c1a16" -H "accept: application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/rawtransactions/decodeScript/4830450221009a51e00ec3524a7389592bc27bea4af5104a59510f5f0cfafa64bbd5c164ca2e02206c2a8bbb47eabdeed52f17d7df668d521600286406930426e3a9415fe10ed592012102e6e1423f7abde8b70bca3e78a7d030e5efabd3eb35c19302542b5fe7879c1a16" -H "accept: application/json"
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -218,7 +218,7 @@ class RawTransactions {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
*curl -X POST "https://mainnet.bchjs.cash/v3/rawtransactions/decodeScript" -H "accept:" -H "Content-Type: application/json" -d '{"hexes":["01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000","01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000"]}'
|
||||
*curl -X POST "https://api.fullstack.cash/v3/rawtransactions/decodeScript" -H "accept:" -H "Content-Type: application/json" -d '{"hexes":["01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000","01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000"]}'
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -308,7 +308,7 @@ class RawTransactions {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X POST "https://mainnet.bchjs.cash/v3/rawtransactions/getRawTransaction" -H "accept: application/json" -H "Content-Type: application/json" -d '{"txids":["a5f972572ee1753e2fd2457dd61ce5f40fa2f8a30173d417e49feef7542c96a1","5165dc531aad05d1149bb0f0d9b7bda99c73e2f05e314bcfb5b4bb9ca5e1af5e"],"verbose":true}'
|
||||
* curl -X POST "https://api.fullstack.cash/v3/rawtransactions/getRawTransaction" -H "accept: application/json" -H "Content-Type: application/json" -d '{"txids":["a5f972572ee1753e2fd2457dd61ce5f40fa2f8a30173d417e49feef7542c96a1","5165dc531aad05d1149bb0f0d9b7bda99c73e2f05e314bcfb5b4bb9ca5e1af5e"],"verbose":true}'
|
||||
*
|
||||
*/
|
||||
async getRawTransactionBulk (req, res, next) {
|
||||
@@ -383,7 +383,7 @@ class RawTransactions {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/rawtransactions/getRawTransaction/fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33?verbose=true" -H "accept: application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/rawtransactions/getRawTransaction/fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33?verbose=true" -H "accept: application/json"
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -429,7 +429,7 @@ class RawTransactions {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X POST "https://mainnet.bchjs.cash/v3/rawtransactions/sendRawTransaction" -H "accept:application/json" -H "Content-Type: application/json" -d '{"hexes":["01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000","01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000"]}'
|
||||
* curl -X POST "https://api.fullstack.cash/v3/rawtransactions/sendRawTransaction" -H "accept:application/json" -H "Content-Type: application/json" -d '{"hexes":["01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000","01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000"]}'
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -522,7 +522,7 @@ class RawTransactions {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/rawtransactions/sendRawTransaction/01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000" -H "accept: "
|
||||
* curl -X GET "https://api.fullstack.cash/v3/rawtransactions/sendRawTransaction/01000000013ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000006a4730440220540986d1c58d6e76f8f05501c520c38ce55393d0ed7ed3c3a82c69af04221232022058ea43ed6c05fec0eccce749a63332ed4525460105346f11108b9c26df93cd72012103083dfc5a0254613941ddc91af39ff90cd711cdcde03a87b144b883b524660c39ffffffff01807c814a000000001976a914d7e7c4e0b70eaa67ceff9d2823d1bbb9f6df9a5188ac00000000" -H "accept: "
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
+13
-13
@@ -130,7 +130,7 @@ class Slp {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/slp/list/259908ae44f46ef585edef4bcc1e50dc06e4c391ac4be929fae27235b8158cf1" -H "accept:application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/slp/list/259908ae44f46ef585edef4bcc1e50dc06e4c391ac4be929fae27235b8158cf1" -H "accept:application/json"
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -163,7 +163,7 @@ class Slp {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X POST "https://mainnet.bchjs.cash/v3/slp/list" -H "accept:application/json" -H "Content-Type: application/json" -d '{"tokenIds":["7380843cd1089a1a01783f86af37734dc99667a1cdc577391b5f6ea42fc1bfb4","9ba379fe8171176d4e7e6771d9a24cd0e044c7b788d5f86a3fdf80904832b2c0"]}'
|
||||
* curl -X POST "https://api.fullstack.cash/v3/slp/list" -H "accept:application/json" -H "Content-Type: application/json" -d '{"tokenIds":["7380843cd1089a1a01783f86af37734dc99667a1cdc577391b5f6ea42fc1bfb4","9ba379fe8171176d4e7e6771d9a24cd0e044c7b788d5f86a3fdf80904832b2c0"]}'
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -311,7 +311,7 @@ class Slp {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/slp/balancesForAddress/simpleledger:qz9tzs6d5097ejpg279rg0rnlhz546q4fsnck9wh5m" -H "accept:application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/slp/balancesForAddress/simpleledger:qz9tzs6d5097ejpg279rg0rnlhz546q4fsnck9wh5m" -H "accept:application/json"
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -496,7 +496,7 @@ class Slp {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X POST "https://mainnet.bchjs.cash/v3/slp/balancesForAddress" -d "{\"addresses\":[\"simpleledger:qqss4zp80hn6szsa4jg2s9fupe7g5tcg5ucdyl3r57\"]}" -H "accept:application/json"
|
||||
* curl -X POST "https://api.fullstack.cash/v3/slp/balancesForAddress" -d "{\"addresses\":[\"simpleledger:qqss4zp80hn6szsa4jg2s9fupe7g5tcg5ucdyl3r57\"]}" -H "accept:application/json"
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -713,7 +713,7 @@ class Slp {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/slp/balancesForToken/9ba379fe8171176d4e7e6771d9a24cd0e044c7b788d5f86a3fdf80904832b2c0" -H "accept:application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/slp/balancesForToken/9ba379fe8171176d4e7e6771d9a24cd0e044c7b788d5f86a3fdf80904832b2c0" -H "accept:application/json"
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -821,7 +821,7 @@ class Slp {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/slp/balance/simpleledger:qz9tzs6d5097ejpg279rg0rnlhz546q4fsnck9wh5m/1cda254d0a995c713b7955298ed246822bee487458cd9747a91d9e81d9d28125" -H "accept:application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/slp/balance/simpleledger:qz9tzs6d5097ejpg279rg0rnlhz546q4fsnck9wh5m/1cda254d0a995c713b7955298ed246822bee487458cd9747a91d9e81d9d28125" -H "accept:application/json"
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -986,7 +986,7 @@ class Slp {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/slp/convert/simpleledger:qz9tzs6d5097ejpg279rg0rnlhz546q4fsnck9wh5m" -H "accept:application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/slp/convert/simpleledger:qz9tzs6d5097ejpg279rg0rnlhz546q4fsnck9wh5m" -H "accept:application/json"
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -1030,7 +1030,7 @@ class Slp {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X POST "https://mainnet.bchjs.cash/v3/slp/convert" -H "accept:application/json" -H "Content-Type: application/json" -d '{"addresses":["simpleledger:qrxa0unrn67rtn85v7asfddhhth43ecnxua0antk2l"]}'
|
||||
* curl -X POST "https://api.fullstack.cash/v3/slp/convert" -H "accept:application/json" -H "Content-Type: application/json" -d '{"addresses":["simpleledger:qrxa0unrn67rtn85v7asfddhhth43ecnxua0antk2l"]}'
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -1090,7 +1090,7 @@ class Slp {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X POST "https://mainnet.bchjs.cash/v3/slp/validateTxid" -H "accept:application/json" -H "Content-Type: application/json" -d '{"txids":["f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a","fb0eeaa501a6e1acb721669c62a3f70741f48ae0fd7f4b8e1d72088785c51952"]}'
|
||||
* curl -X POST "https://api.fullstack.cash/v3/slp/validateTxid" -H "accept:application/json" -H "Content-Type: application/json" -d '{"txids":["f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a","fb0eeaa501a6e1acb721669c62a3f70741f48ae0fd7f4b8e1d72088785c51952"]}'
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -1211,7 +1211,7 @@ class Slp {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/slp/validateTxid/f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a" -H "accept:application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/slp/validateTxid/f7e5199ef6669ad4d078093b3ad56e355b6ab84567e59ad0f08a5ad0244f783a" -H "accept:application/json"
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -1293,7 +1293,7 @@ class Slp {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/slp/txDetails/8ab4ac5dea3f9024e3954ee5b61452955d659a34561f79ef62ac44e133d0980e" -H "accept:application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/slp/txDetails/8ab4ac5dea3f9024e3954ee5b61452955d659a34561f79ef62ac44e133d0980e" -H "accept:application/json"
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -1381,7 +1381,7 @@ class Slp {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/slp/tokenStats/9ba379fe8171176d4e7e6771d9a24cd0e044c7b788d5f86a3fdf80904832b2c0" -H "accept:application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/slp/tokenStats/9ba379fe8171176d4e7e6771d9a24cd0e044c7b788d5f86a3fdf80904832b2c0" -H "accept:application/json"
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -1443,7 +1443,7 @@ class Slp {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/slp/transactions/9ba379fe8171176d4e7e6771d9a24cd0e044c7b788d5f86a3fdf80904832b2c0/simpleledger:qrxa0unrn67rtn85v7asfddhhth43ecnxua0antk2l" -H "accept:application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/slp/transactions/9ba379fe8171176d4e7e6771d9a24cd0e044c7b788d5f86a3fdf80904832b2c0/simpleledger:qrxa0unrn67rtn85v7asfddhhth43ecnxua0antk2l" -H "accept:application/json"
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -56,7 +56,7 @@ class UtilRoute {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X GET "https://mainnet.bchjs.cash/v3/util/validateAddress/bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c" -H "accept: application/json"
|
||||
* curl -X GET "https://api.fullstack.cash/v3/util/validateAddress/bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c" -H "accept: application/json"
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -105,8 +105,8 @@ class UtilRoute {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X POST "https://mainnet.bchjs.cash/v3/util/validateAddress" -H "accept: application/json" -H "Content-Type: application/json" -d '{"addresses":["bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c","bitcoincash:qrehqueqhw629p6e57994436w730t4rzasnly00ht0"]}'
|
||||
* curl -X POST "https://mainnet.bchjs.cash/v3/util/validateAddress" -H "accept: application/json" -H "Content-Type: application/json" -d '{"addresses":["bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c","bitcoincash:qrehqueqhw629p6e57994436w730t4rzasnly00ht0"],"from": 1, "to": 5}'
|
||||
* curl -X POST "https://api.fullstack.cash/v3/util/validateAddress" -H "accept: application/json" -H "Content-Type: application/json" -d '{"addresses":["bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c","bitcoincash:qrehqueqhw629p6e57994436w730t4rzasnly00ht0"]}'
|
||||
* curl -X POST "https://api.fullstack.cash/v3/util/validateAddress" -H "accept: application/json" -H "Content-Type: application/json" -d '{"addresses":["bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c","bitcoincash:qrehqueqhw629p6e57994436w730t4rzasnly00ht0"],"from": 1, "to": 5}'
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -208,8 +208,8 @@ class UtilRoute {
|
||||
*
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -X POST "https://mainnet.bchjs.cash/v3/util/sweep" -H "accept: application/json" -H "Content-Type: application/json" -d '{"wif":"Kz52sdXLAiKtH82iAFRi6aTZanWtW5Eyv37KWdpY6tTv7pjoHste", "balanceOnly": true}'
|
||||
* curl -X POST "https://mainnet.bchjs.cash/v3/util/sweep" -H "accept: application/json" -H "Content-Type: application/json" -d '{"wif":"Kz52sdXLAiKtH82iAFRi6aTZanWtW5Eyv37KWdpY6tTv7pjoHste", "toAddr": "bitcoincash:qpt8m4kqu963geedyrur6pdggqmv5kxwnq0rn322qu"}'
|
||||
* curl -X POST "https://api.fullstack.cash/v3/util/sweep" -H "accept: application/json" -H "Content-Type: application/json" -d '{"wif":"Kz52sdXLAiKtH82iAFRi6aTZanWtW5Eyv37KWdpY6tTv7pjoHste", "balanceOnly": true}'
|
||||
* curl -X POST "https://api.fullstack.cash/v3/util/sweep" -H "accept: application/json" -H "Content-Type: application/json" -d '{"wif":"Kz52sdXLAiKtH82iAFRi6aTZanWtW5Eyv37KWdpY6tTv7pjoHste", "toAddr": "bitcoincash:qpt8m4kqu963geedyrur6pdggqmv5kxwnq0rn322qu"}'
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
TESTS FOR THE ELECTRUMX.JS LIBRARY
|
||||
|
||||
This test file uses the environment variable TEST to switch between unit
|
||||
and integration tests. By default, TEST is set to 'unit'. Set this variable
|
||||
to 'integration' to run the tests against BCH mainnet.
|
||||
|
||||
To-Do:
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
const chai = require('chai')
|
||||
const assert = chai.assert
|
||||
|
||||
const sinon = require('sinon')
|
||||
|
||||
let originalUrl // Used during transition from integration to unit tests.
|
||||
|
||||
// Set default environment variables for unit tests.
|
||||
if (!process.env.TEST) process.env.TEST = 'unit'
|
||||
if (process.env.TEST === 'unit') {
|
||||
process.env.BLOCKBOOK_URL = 'http://fakeurl/api/'
|
||||
}
|
||||
|
||||
// Only load blockbook library after setting BLOCKBOOK_URL env var.
|
||||
const ElecrumxRoute = require('../../src/routes/v3/electrumx')
|
||||
const electrumxRoute = new ElecrumxRoute()
|
||||
|
||||
// Mocking data.
|
||||
const { mockReq, mockRes } = require('./mocks/express-mocks')
|
||||
const mockData = require('./mocks/electrumx-mock')
|
||||
|
||||
// Used for debugging.
|
||||
const util = require('util')
|
||||
util.inspect.defaultOptions = { depth: 1 }
|
||||
|
||||
describe('#ElectrumX Router', () => {
|
||||
let req, res
|
||||
let sandbox
|
||||
|
||||
before(async () => {
|
||||
// console.log(`Testing type is: ${process.env.TEST}`)
|
||||
|
||||
if (!process.env.NETWORK) process.env.NETWORK = 'testnet'
|
||||
|
||||
// Connect to electrumx servers if this is an integration test.
|
||||
if (process.env.TEST === 'integration') {
|
||||
await electrumxRoute.connect()
|
||||
console.log('Connected to ElectrumX server')
|
||||
}
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
// Disconnect from the electrumx server if this is an integration test.
|
||||
if (process.env.TEST === 'integration') {
|
||||
await electrumxRoute.disconnect()
|
||||
console.log('Disconnected from ElectrumX server')
|
||||
}
|
||||
})
|
||||
|
||||
// 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 = {}
|
||||
req.query = {}
|
||||
|
||||
sandbox = sinon.createSandbox()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
sandbox.restore()
|
||||
})
|
||||
|
||||
after(() => {
|
||||
process.env.BLOCKBOOK_URL = originalUrl
|
||||
})
|
||||
|
||||
describe('#root', () => {
|
||||
// root route handler.
|
||||
const root = electrumxRoute.root
|
||||
|
||||
it('should respond to GET for base route', async () => {
|
||||
const result = root(req, res)
|
||||
|
||||
assert.equal(result.status, 'electrumx', 'Returns static string')
|
||||
})
|
||||
})
|
||||
|
||||
describe('#addressToScripthash', () => {
|
||||
it('should accurately return a scripthash', () => {
|
||||
const addr = 'bitcoincash:qpr270a5sxphltdmggtj07v4nskn9gmg9yx4m5h7s4'
|
||||
|
||||
const scripthash = electrumxRoute.addressToScripthash(addr)
|
||||
|
||||
const expectedOutput =
|
||||
'bce4d5f2803bd1ed7c1ba00dcb3edffcbba50524af7c879d6bb918d04f138965'
|
||||
|
||||
assert.equal(scripthash, expectedOutput)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#UTXO', () => {
|
||||
it('should throw 400 if address is empty', async () => {
|
||||
const result = await electrumxRoute.getUtxos(req, res)
|
||||
// console.log(`result: ${util.inspect(result)}`)
|
||||
|
||||
assert.equal(res.statusCode, 400, 'Expect 400 status code')
|
||||
|
||||
assert.property(result, 'error')
|
||||
assert.include(result.error, 'Unsupported address format')
|
||||
|
||||
assert.property(result, 'success')
|
||||
assert.equal(result.success, false)
|
||||
})
|
||||
|
||||
it('should throw 400 on array input', async () => {
|
||||
req.params.address = ['qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c']
|
||||
|
||||
const result = await electrumxRoute.getUtxos(req, res)
|
||||
// console.log(`result: ${util.inspect(result)}`)
|
||||
|
||||
assert.equal(res.statusCode, 400, 'Expect 400 status code')
|
||||
|
||||
assert.property(result, 'error')
|
||||
assert.include(result.error, 'address can not be an array')
|
||||
|
||||
assert.property(result, 'success')
|
||||
assert.equal(result.success, false)
|
||||
})
|
||||
|
||||
it('should throw an error for an invalid address', async () => {
|
||||
req.params.address =
|
||||
'02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c'
|
||||
|
||||
const result = await electrumxRoute.getUtxos(req, res)
|
||||
// console.log(`result: ${util.inspect(result)}`)
|
||||
|
||||
assert.equal(res.statusCode, 400, 'Expect 400 status code')
|
||||
|
||||
assert.property(result, 'error')
|
||||
assert.include(result.error, 'Unsupported address format')
|
||||
|
||||
assert.property(result, 'success')
|
||||
assert.equal(result.success, false)
|
||||
})
|
||||
|
||||
it('should detect a network mismatch', async () => {
|
||||
req.params.address =
|
||||
'bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4'
|
||||
|
||||
const result = await electrumxRoute.getUtxos(req, res)
|
||||
// console.log(`result: ${util.inspect(result)}`)
|
||||
|
||||
assert.equal(res.statusCode, 400, 'Expect 400 status code')
|
||||
|
||||
assert.property(result, 'error')
|
||||
assert.include(result.error, 'Invalid network', 'Proper error message')
|
||||
|
||||
assert.property(result, 'success')
|
||||
assert.equal(result.success, false)
|
||||
})
|
||||
|
||||
// it('should throw 500 when network issues', async () => {
|
||||
// const savedUrl = process.env.BLOCKBOOK_URL
|
||||
//
|
||||
// try {
|
||||
// req.params.address = 'qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c'
|
||||
//
|
||||
// // Switch the Insight URL to something that will error out.
|
||||
// process.env.BLOCKBOOK_URL = 'http://fakeurl/api/'
|
||||
//
|
||||
// const result = await blockbookRoute.balanceSingle(req, res)
|
||||
//
|
||||
// // Restore the saved URL.
|
||||
// process.env.BLOCKBOOK_URL = 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.BLOCKBOOK_URL = savedUrl
|
||||
// }
|
||||
// })
|
||||
|
||||
// it('returns proper error when downstream service stalls', async () => {
|
||||
// req.params.address =
|
||||
// 'bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf'
|
||||
//
|
||||
// // Mock the timeout error.
|
||||
// sandbox.stub(blockbookRoute.axios, 'request').throws({
|
||||
// code: 'ECONNABORTED'
|
||||
// })
|
||||
//
|
||||
// const result = await blockbookRoute.balanceSingle(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 () => {
|
||||
// req.params.address =
|
||||
// 'bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf'
|
||||
//
|
||||
// // Mock the timeout error.
|
||||
// sandbox.stub(blockbookRoute.axios, 'request').throws({
|
||||
// code: 'ECONNREFUSED'
|
||||
// })
|
||||
//
|
||||
// const result = await blockbookRoute.balanceSingle(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 balance for a single address', async () => {
|
||||
req.params.address =
|
||||
'bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf'
|
||||
|
||||
// Mock unit tests to prevent live network calls.
|
||||
if (process.env.TEST === 'unit') {
|
||||
electrumxRoute.isReady = true // Force flag.
|
||||
|
||||
sandbox
|
||||
.stub(electrumxRoute.electrumx, 'request')
|
||||
.resolves(mockData.utxos)
|
||||
}
|
||||
|
||||
// Call the details API.
|
||||
const result = await electrumxRoute.getUtxos(req, res)
|
||||
// console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||
|
||||
assert.property(result, 'success')
|
||||
assert.equal(result.success, true)
|
||||
|
||||
assert.property(result, 'utxos')
|
||||
assert.isArray(result.utxos)
|
||||
|
||||
assert.property(result.utxos[0], 'height')
|
||||
assert.property(result.utxos[0], 'tx_hash')
|
||||
assert.property(result.utxos[0], 'tx_pos')
|
||||
assert.property(result.utxos[0], 'value')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
Mocking data for electrumx unit tests
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
const utxos = [
|
||||
{
|
||||
height: 604392,
|
||||
tx_hash: '7774e449c5a3065144cefbc4c0c21e6b69c987f095856778ef9f45ddd8ae1a41',
|
||||
tx_pos: 0,
|
||||
value: 1000
|
||||
}
|
||||
]
|
||||
|
||||
module.exports = {
|
||||
utxos
|
||||
}
|
||||
Reference in New Issue
Block a user