mirror of
https://github.com/mempool/mempool.git
synced 2025-04-25 07:51:40 +02:00
Merge node-bitcoin into the project
This commit is contained in:
parent
622a003a2a
commit
e26beee44c
14
backend/package-lock.json
generated
14
backend/package-lock.json
generated
@ -9,7 +9,6 @@
|
||||
"version": "2.4.0-dev",
|
||||
"license": "GNU Affero General Public License v3.0",
|
||||
"dependencies": {
|
||||
"@mempool/bitcoin": "^3.0.3",
|
||||
"@mempool/electrum-client": "^1.1.7",
|
||||
"@types/ws": "8.2.2",
|
||||
"axios": "0.24.0",
|
||||
@ -56,14 +55,6 @@
|
||||
"js-tokens": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@mempool/bitcoin": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@mempool/bitcoin/-/bitcoin-3.0.3.tgz",
|
||||
"integrity": "sha512-10UdbwchnevlebDTN+Xhv75AEhDmTMy9UgWHlqx5MG2mheFG6+eqmtHsdxeYnv3IAtTtlRfA6fY0RbV/x4TNFQ==",
|
||||
"engines": {
|
||||
"node": ">= 0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@mempool/electrum-client": {
|
||||
"version": "1.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@mempool/electrum-client/-/electrum-client-1.1.8.tgz",
|
||||
@ -1515,11 +1506,6 @@
|
||||
"js-tokens": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"@mempool/bitcoin": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@mempool/bitcoin/-/bitcoin-3.0.3.tgz",
|
||||
"integrity": "sha512-10UdbwchnevlebDTN+Xhv75AEhDmTMy9UgWHlqx5MG2mheFG6+eqmtHsdxeYnv3IAtTtlRfA6fY0RbV/x4TNFQ=="
|
||||
},
|
||||
"@mempool/electrum-client": {
|
||||
"version": "1.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@mempool/electrum-client/-/electrum-client-1.1.8.tgz",
|
||||
|
@ -28,7 +28,6 @@
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@mempool/bitcoin": "^3.0.3",
|
||||
"@mempool/electrum-client": "^1.1.7",
|
||||
"@types/ws": "8.2.2",
|
||||
"axios": "0.24.0",
|
||||
|
@ -1,5 +1,5 @@
|
||||
import config from '../../config';
|
||||
import * as bitcoin from '@mempool/bitcoin';
|
||||
const bitcoin = require('../../rpc-api/index');
|
||||
import { BitcoinRpcCredentials } from './bitcoin-api-abstract-factory';
|
||||
|
||||
const nodeRpcCredentials: BitcoinRpcCredentials = {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import config from '../../config';
|
||||
import * as bitcoin from '@mempool/bitcoin';
|
||||
const bitcoin = require('../../rpc-api/index');
|
||||
import { BitcoinRpcCredentials } from './bitcoin-api-abstract-factory';
|
||||
|
||||
const nodeRpcCredentials: BitcoinRpcCredentials = {
|
||||
|
92
backend/src/rpc-api/commands.ts
Normal file
92
backend/src/rpc-api/commands.ts
Normal file
@ -0,0 +1,92 @@
|
||||
module.exports = {
|
||||
addMultiSigAddress: 'addmultisigaddress',
|
||||
addNode: 'addnode', // bitcoind v0.8.0+
|
||||
backupWallet: 'backupwallet',
|
||||
createMultiSig: 'createmultisig',
|
||||
createRawTransaction: 'createrawtransaction', // bitcoind v0.7.0+
|
||||
decodeRawTransaction: 'decoderawtransaction', // bitcoind v0.7.0+
|
||||
decodeScript: 'decodescript',
|
||||
dumpPrivKey: 'dumpprivkey',
|
||||
dumpWallet: 'dumpwallet', // bitcoind v0.9.0+
|
||||
encryptWallet: 'encryptwallet',
|
||||
estimateFee: 'estimatefee', // bitcoind v0.10.0x
|
||||
estimatePriority: 'estimatepriority', // bitcoind v0.10.0+
|
||||
generate: 'generate', // bitcoind v0.11.0+
|
||||
getAccount: 'getaccount',
|
||||
getAccountAddress: 'getaccountaddress',
|
||||
getAddedNodeInfo: 'getaddednodeinfo', // bitcoind v0.8.0+
|
||||
getAddressesByAccount: 'getaddressesbyaccount',
|
||||
getBalance: 'getbalance',
|
||||
getBestBlockHash: 'getbestblockhash', // bitcoind v0.9.0+
|
||||
getBlock: 'getblock',
|
||||
getBlockStats: 'getblockstats',
|
||||
getBlockFilter: 'getblockfilter',
|
||||
getBlockchainInfo: 'getblockchaininfo', // bitcoind v0.9.2+
|
||||
getBlockCount: 'getblockcount',
|
||||
getBlockHash: 'getblockhash',
|
||||
getBlockHeader: 'getblockheader',
|
||||
getBlockTemplate: 'getblocktemplate', // bitcoind v0.7.0+
|
||||
getChainTips: 'getchaintips', // bitcoind v0.10.0+
|
||||
getChainTxStats: 'getchaintxstats',
|
||||
getConnectionCount: 'getconnectioncount',
|
||||
getDifficulty: 'getdifficulty',
|
||||
getGenerate: 'getgenerate',
|
||||
getInfo: 'getinfo',
|
||||
getMempoolAncestors: 'getmempoolancestors',
|
||||
getMempoolDescendants: 'getmempooldescendants',
|
||||
getMempoolEntry: 'getmempoolentry',
|
||||
getMempoolInfo: 'getmempoolinfo', // bitcoind v0.10+
|
||||
getMiningInfo: 'getmininginfo',
|
||||
getNetTotals: 'getnettotals',
|
||||
getNetworkInfo: 'getnetworkinfo', // bitcoind v0.9.2+
|
||||
getNetworkHashPs: 'getnetworkhashps', // bitcoind v0.9.0+
|
||||
getNewAddress: 'getnewaddress',
|
||||
getPeerInfo: 'getpeerinfo', // bitcoind v0.7.0+
|
||||
getRawChangeAddress: 'getrawchangeaddress', // bitcoin v0.9+
|
||||
getRawMemPool: 'getrawmempool', // bitcoind v0.7.0+
|
||||
getRawTransaction: 'getrawtransaction', // bitcoind v0.7.0+
|
||||
getReceivedByAccount: 'getreceivedbyaccount',
|
||||
getReceivedByAddress: 'getreceivedbyaddress',
|
||||
getTransaction: 'gettransaction',
|
||||
getTxOut: 'gettxout', // bitcoind v0.7.0+
|
||||
getTxOutProof: 'gettxoutproof', // bitcoind v0.11.0+
|
||||
getTxOutSetInfo: 'gettxoutsetinfo', // bitcoind v0.7.0+
|
||||
getUnconfirmedBalance: 'getunconfirmedbalance', // bitcoind v0.9.0+
|
||||
getWalletInfo: 'getwalletinfo', // bitcoind v0.9.2+
|
||||
help: 'help',
|
||||
importAddress: 'importaddress', // bitcoind v0.10.0+
|
||||
importPrivKey: 'importprivkey',
|
||||
importWallet: 'importwallet', // bitcoind v0.9.0+
|
||||
keypoolRefill: 'keypoolrefill',
|
||||
keyPoolRefill: 'keypoolrefill',
|
||||
listAccounts: 'listaccounts',
|
||||
listAddressGroupings: 'listaddressgroupings', // bitcoind v0.7.0+
|
||||
listLockUnspent: 'listlockunspent', // bitcoind v0.8.0+
|
||||
listReceivedByAccount: 'listreceivedbyaccount',
|
||||
listReceivedByAddress: 'listreceivedbyaddress',
|
||||
listSinceBlock: 'listsinceblock',
|
||||
listTransactions: 'listtransactions',
|
||||
listUnspent: 'listunspent', // bitcoind v0.7.0+
|
||||
lockUnspent: 'lockunspent', // bitcoind v0.8.0+
|
||||
move: 'move',
|
||||
ping: 'ping', // bitcoind v0.9.0+
|
||||
prioritiseTransaction: 'prioritisetransaction', // bitcoind v0.10.0+
|
||||
sendFrom: 'sendfrom',
|
||||
sendMany: 'sendmany',
|
||||
sendRawTransaction: 'sendrawtransaction', // bitcoind v0.7.0+
|
||||
sendToAddress: 'sendtoaddress',
|
||||
setAccount: 'setaccount',
|
||||
setGenerate: 'setgenerate',
|
||||
setTxFee: 'settxfee',
|
||||
signMessage: 'signmessage',
|
||||
signRawTransaction: 'signrawtransaction', // bitcoind v0.7.0+
|
||||
stop: 'stop',
|
||||
submitBlock: 'submitblock', // bitcoind v0.7.0+
|
||||
validateAddress: 'validateaddress',
|
||||
verifyChain: 'verifychain', // bitcoind v0.9.0+
|
||||
verifyMessage: 'verifymessage',
|
||||
verifyTxOutProof: 'verifytxoutproof', // bitcoind v0.11.0+
|
||||
walletLock: 'walletlock',
|
||||
walletPassphrase: 'walletpassphrase',
|
||||
walletPassphraseChange: 'walletpassphrasechange'
|
||||
}
|
61
backend/src/rpc-api/index.ts
Normal file
61
backend/src/rpc-api/index.ts
Normal file
@ -0,0 +1,61 @@
|
||||
var commands = require('./commands')
|
||||
var rpc = require('./jsonrpc')
|
||||
|
||||
// ===----------------------------------------------------------------------===//
|
||||
// JsonRPC
|
||||
// ===----------------------------------------------------------------------===//
|
||||
function Client (opts) {
|
||||
// @ts-ignore
|
||||
this.rpc = new rpc.JsonRPC(opts)
|
||||
}
|
||||
|
||||
// ===----------------------------------------------------------------------===//
|
||||
// cmd
|
||||
// ===----------------------------------------------------------------------===//
|
||||
Client.prototype.cmd = function () {
|
||||
var args = [].slice.call(arguments)
|
||||
var cmd = args.shift()
|
||||
|
||||
callRpc(cmd, args, this.rpc)
|
||||
}
|
||||
|
||||
// ===----------------------------------------------------------------------===//
|
||||
// callRpc
|
||||
// ===----------------------------------------------------------------------===//
|
||||
function callRpc (cmd, args, rpc) {
|
||||
var fn = args[args.length - 1]
|
||||
|
||||
// If the last argument is a callback, pop it from the args list
|
||||
if (typeof fn === 'function') {
|
||||
args.pop()
|
||||
} else {
|
||||
fn = function () {}
|
||||
}
|
||||
|
||||
return rpc.call(cmd, args, function () {
|
||||
var args = [].slice.call(arguments)
|
||||
// @ts-ignore
|
||||
args.unshift(null)
|
||||
// @ts-ignore
|
||||
fn.apply(this, args)
|
||||
}, function (err) {
|
||||
fn(err)
|
||||
})
|
||||
}
|
||||
|
||||
// ===----------------------------------------------------------------------===//
|
||||
// Initialize wrappers
|
||||
// ===----------------------------------------------------------------------===//
|
||||
(function () {
|
||||
for (var protoFn in commands) {
|
||||
(function (protoFn) {
|
||||
Client.prototype[protoFn] = function () {
|
||||
var args = [].slice.call(arguments)
|
||||
return callRpc(commands[protoFn], args, this.rpc)
|
||||
}
|
||||
})(protoFn)
|
||||
}
|
||||
})()
|
||||
|
||||
// Export!
|
||||
module.exports.Client = Client;
|
162
backend/src/rpc-api/jsonrpc.ts
Normal file
162
backend/src/rpc-api/jsonrpc.ts
Normal file
@ -0,0 +1,162 @@
|
||||
var http = require('http')
|
||||
var https = require('https')
|
||||
|
||||
var JsonRPC = function (opts) {
|
||||
// @ts-ignore
|
||||
this.opts = opts || {}
|
||||
// @ts-ignore
|
||||
this.http = this.opts.ssl ? https : http
|
||||
}
|
||||
|
||||
JsonRPC.prototype.call = function (method, params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
var time = Date.now()
|
||||
var requestJSON
|
||||
|
||||
if (Array.isArray(method)) {
|
||||
// multiple rpc batch call
|
||||
requestJSON = []
|
||||
method.forEach(function (batchCall, i) {
|
||||
requestJSON.push({
|
||||
id: time + '-' + i,
|
||||
method: batchCall.method,
|
||||
params: batchCall.params
|
||||
})
|
||||
})
|
||||
} else {
|
||||
// single rpc call
|
||||
requestJSON = {
|
||||
id: time,
|
||||
method: method,
|
||||
params: params
|
||||
}
|
||||
}
|
||||
|
||||
// First we encode the request into JSON
|
||||
requestJSON = JSON.stringify(requestJSON)
|
||||
|
||||
// prepare request options
|
||||
var requestOptions = {
|
||||
host: this.opts.host || 'localhost',
|
||||
port: this.opts.port || 8332,
|
||||
method: 'POST',
|
||||
path: '/',
|
||||
headers: {
|
||||
'Host': this.opts.host || 'localhost',
|
||||
'Content-Length': requestJSON.length
|
||||
},
|
||||
agent: false,
|
||||
rejectUnauthorized: this.opts.ssl && this.opts.sslStrict !== false
|
||||
}
|
||||
|
||||
if (this.opts.ssl && this.opts.sslCa) {
|
||||
// @ts-ignore
|
||||
requestOptions.ca = this.opts.sslCa
|
||||
}
|
||||
|
||||
// use HTTP auth if user and password set
|
||||
if (this.opts.user && this.opts.pass) {
|
||||
// @ts-ignore
|
||||
requestOptions.auth = this.opts.user + ':' + this.opts.pass
|
||||
}
|
||||
|
||||
// Now we'll make a request to the server
|
||||
var cbCalled = false
|
||||
var request = this.http.request(requestOptions)
|
||||
|
||||
// start request timeout timer
|
||||
var reqTimeout = setTimeout(function () {
|
||||
if (cbCalled) return
|
||||
cbCalled = true
|
||||
request.abort()
|
||||
var err = new Error('ETIMEDOUT')
|
||||
// @ts-ignore
|
||||
err.code = 'ETIMEDOUT'
|
||||
reject(err)
|
||||
}, this.opts.timeout || 30000)
|
||||
|
||||
// set additional timeout on socket in case of remote freeze after sending headers
|
||||
request.setTimeout(this.opts.timeout || 30000, function () {
|
||||
if (cbCalled) return
|
||||
cbCalled = true
|
||||
request.abort()
|
||||
var err = new Error('ESOCKETTIMEDOUT')
|
||||
// @ts-ignore
|
||||
err.code = 'ESOCKETTIMEDOUT'
|
||||
reject(err)
|
||||
})
|
||||
|
||||
request.on('error', function (err) {
|
||||
if (cbCalled) return
|
||||
cbCalled = true
|
||||
clearTimeout(reqTimeout)
|
||||
reject(err)
|
||||
})
|
||||
|
||||
request.on('response', function (response) {
|
||||
clearTimeout(reqTimeout)
|
||||
|
||||
// We need to buffer the response chunks in a nonblocking way.
|
||||
var buffer = ''
|
||||
response.on('data', function (chunk) {
|
||||
buffer = buffer + chunk
|
||||
})
|
||||
// When all the responses are finished, we decode the JSON and
|
||||
// depending on whether it's got a result or an error, we call
|
||||
// emitSuccess or emitError on the promise.
|
||||
response.on('end', function () {
|
||||
var err
|
||||
|
||||
if (cbCalled) return
|
||||
cbCalled = true
|
||||
|
||||
try {
|
||||
var decoded = JSON.parse(buffer)
|
||||
} catch (e) {
|
||||
if (response.statusCode !== 200) {
|
||||
err = new Error('Invalid params, response status code: ' + response.statusCode)
|
||||
err.code = -32602
|
||||
reject(err)
|
||||
} else {
|
||||
err = new Error('Problem parsing JSON response from server')
|
||||
err.code = -32603
|
||||
reject(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (!Array.isArray(decoded)) {
|
||||
decoded = [decoded]
|
||||
}
|
||||
|
||||
// iterate over each response, normally there will be just one
|
||||
// unless a batch rpc call response is being processed
|
||||
decoded.forEach(function (decodedResponse, i) {
|
||||
if (decodedResponse.hasOwnProperty('error') && decodedResponse.error != null) {
|
||||
if (reject) {
|
||||
err = new Error(decodedResponse.error.message || '')
|
||||
if (decodedResponse.error.code) {
|
||||
err.code = decodedResponse.error.code
|
||||
}
|
||||
reject(err)
|
||||
}
|
||||
} else if (decodedResponse.hasOwnProperty('result')) {
|
||||
// @ts-ignore
|
||||
resolve(decodedResponse.result, response.headers)
|
||||
} else {
|
||||
if (reject) {
|
||||
err = new Error(decodedResponse.error.message || '')
|
||||
if (decodedResponse.error.code) {
|
||||
err.code = decodedResponse.error.code
|
||||
}
|
||||
reject(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
request.end(requestJSON);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.JsonRPC = JsonRPC
|
Loading…
x
Reference in New Issue
Block a user