diff --git a/config/electrumx.js b/config/electrumx.js deleted file mode 100644 index a49e502..0000000 --- a/config/electrumx.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - 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', - serverPort: '50002' - }, - ratelimit: { - windowMs: 1 * 60 * 1000, - max: 100 - } -} - -if (process.env.NETWORK === 'testnet') { - config.electrum.serverUrl = 'blackie.c3-soft.com' - config.electrum.serverPort = '60002' - - // config.electrum.serverUrl = '192.168.0.6' - // config.electrum.serverPort = '50001' -} - -module.exports = config diff --git a/config/index.js b/config/index.js index 0f7087d..2f47cea 100644 --- a/config/index.js +++ b/config/index.js @@ -2,11 +2,8 @@ Common configuration settings. */ -const electrumxConfig = require('./electrumx') - const config = { - apiTokenSecret: process.env.TOKENSECRET ? process.env.TOKENSECRET : 'secret-jwt-token', - electrumx: electrumxConfig + apiTokenSecret: process.env.TOKENSECRET ? process.env.TOKENSECRET : 'secret-jwt-token' } module.exports = config diff --git a/docker/mainnet/start-local-mainnet.sh.save b/docker/mainnet/start-local-mainnet.sh.save new file mode 100755 index 0000000..6eb943a --- /dev/null +++ b/docker/mainnet/start-local-mainnet.sh.save @@ -0,0 +1,28 @@ +#!/bin/bash + +# test + +# Full node +export RPC_BASEURL=http://142.93.13.2:8332/ +export RPC_USERNAME=bitcoin +export RPC_PASSWORD=password +export NETWORK=mainnet + +# SLPDB +#export SLPDB_URL=https://slpdb.bitcoin.com/ +#export SLPDB_URL=http://172.17.0.1:12300/ +export SLPDB_URL=https://slpdb2.bchtest.net/ +export SLPDB_PASS=owmvgnsksoapwhrnvu + +# Blockbook Indexer +export BLOCKBOOK_URL=https://157.230.214.175:9131/ +# Allow node.js to make network calls to https using self-signed certificate. +export NODE_TLS_REJECT_UNAUTHORIZED=0 + +export JWT_AUTH_SERVER=http://172.17.0.1:5001/ + +# Redis DB +export REDIS_PORT=6379 +export REDIS_HOST=172.17.0.1 + +npm start diff --git a/package.json b/package.json index 48cbd24..879f52c 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "dev": "nodemon ./dist/app.js", "test": "npm run lint && npm run test-v3", "lint": "standard --env mocha --fix", - "test-v3": "export NETWORK=mainnet && nyc --reporter=text mocha --timeout 60000 test/v3/", + "test-v3": "export NETWORK=mainnet && nyc --reporter=text mocha --timeout 60000 test/v3/electrumx.js", "test:temp": "export NETWORK=mainnet && mocha --timeout 25000 test/v3/blockchain.js", "test:integration": "mocha test/v3/integration", "coverage": "nyc report --reporter=text-lcov | coveralls", diff --git a/src/routes/v3/electrumx.js b/src/routes/v3/electrumx.js index ae40442..0bf400e 100644 --- a/src/routes/v3/electrumx.js +++ b/src/routes/v3/electrumx.js @@ -33,10 +33,10 @@ class Electrum { _this.bitcore = bitcore _this.electrumx = new ElectrumCash( - config.electrumx.electrum.application, - config.electrumx.electrum.version, - config.electrumx.electrum.serverUrl, - config.electrumx.electrum.serverPort + 'bch-api', + '1.4.1', + process.env.FULCRUM_URL, + process.env.FULCRUM_PORT ) _this.isReady = false @@ -61,12 +61,12 @@ class Electrum { // Set the connection flag. _this.isReady = true - console.log(`...Successfully connected to ElectrumX server.`) + console.log('...Successfully connected to ElectrumX server.') // console.log(`_this.isReady: ${_this.isReady}`) return _this.isReady } catch (err) { - console.log(`err: `, err) + console.log('err: ', err) wlogger.error('Error in electrumx.js/connect(): ', err) // throw err } @@ -118,11 +118,34 @@ class Electrum { return res.json({ status: 'electrumx' }) } - async utxosFromElectrumx (address) { + // Returns a promise that resolves to UTXO data for an address. Expects input + // to be a cash address, and input validation to have already been done by + // calling function. + async _utxosFromElectrumx (address) { try { + // Convert the address to a scripthash. + const scripthash = _this.addressToScripthash(address) + if (!_this.isReady) { + throw new Error( + 'ElectrumX server connection is not ready. Call await connectToServer() first.' + ) + } + + // Query the utxos from the ElectrumX server. + const electrumResponse = await _this.electrumx.request( + 'blockchain.scripthash.listunspent', + scripthash + ) + // console.log( + // `electrumResponse: ${JSON.stringify(electrumResponse, null, 2)}` + // ) + + return electrumResponse } catch (err) { - + // Write out error to error log. + wlogger.error('Error in elecrumx.js/_utxosFromElectrumx().') + throw err } } @@ -164,25 +187,11 @@ class Electrum { }) } - wlogger.debug('Executing electrumx/getUtxos with this address: ', address) + wlogger.debug('Executing electrumx/getUtxos with this address: ', cashAddr) - // 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)}` - // ) + // Get data from ElectrumX server. + const electrumResponse = await _this._utxosFromElectrumx(cashAddr) + console.log(`electrumResponse: ${JSON.stringify(electrumResponse, null, 2)}`) // Pass the error message if ElectrumX reports an error. if (Object.prototype.hasOwnProperty.call(electrumResponse, 'code')) { diff --git a/start-dev-example.sh b/start-dev-example.sh index 4d0ae09..5034068 100755 --- a/start-dev-example.sh +++ b/start-dev-example.sh @@ -14,4 +14,10 @@ export BLOCKBOOK_URL=https://:9131/ # Allow node.js to make network calls to https using self-signed certificate. export NODE_TLS_REJECT_UNAUTHORIZED=0 +# Mainnet Fulcrum / ElectrumX +export FULCRUM_URL=192.168.0.6 +export FULCRUM_PORT=50002 + +export TOKENSECRET=somelongpassword + npm start diff --git a/test/v3/electrumx.js b/test/v3/electrumx.js index 15b19cd..244a58a 100644 --- a/test/v3/electrumx.js +++ b/test/v3/electrumx.js @@ -135,8 +135,7 @@ describe('#ElectrumX Router', () => { }) it('should throw an error for an invalid address', async () => { - req.params.address = - '02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c' + req.params.address = '02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c' const result = await electrumxRoute.getUtxos(req, res) // console.log(`result: ${util.inspect(result)}`) @@ -151,8 +150,7 @@ describe('#ElectrumX Router', () => { }) it('should detect a network mismatch', async () => { - req.params.address = - 'bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4' + req.params.address = 'bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4' const result = await electrumxRoute.getUtxos(req, res) // console.log(`result: ${util.inspect(result)}`) @@ -165,68 +163,22 @@ describe('#ElectrumX Router', () => { 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 - // } - // }) + describe('#_utxosFromElectrumx', () => { + // Unit test only. + if (process.env.TEST === 'unit') { + it('should pass errors from ElectrumX to user', async () => { + req.params.address = + 'bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf' - // 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' - // ) - // }) + electrumxRoute.isReady = true // Force flag. - // 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' - // ) - // }) + sandbox + .stub(electrumxRoute.electrumx, 'request') + .resolves(mockData.utxos) + }) + } it('should get balance for a single address', async () => { req.params.address =