Last active
March 27, 2018 01:27
-
-
Save suissa/8126ad8c68e9cd1db7c15860e3b423d0 to your computer and use it in GitHub Desktop.
Refatorando uma LIB para retirar o this + prototype + new | Ainda falta a parte do jsonrpc.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module.exports = { | |
addMultiSigAddress: 'addmultisigaddress', | |
addNode: 'addnode', // litecoind v0.8+ | |
backupWallet: 'backupwallet', | |
banNode: 'bannode', // OMG2 only | |
createMultisig: 'createmultisig', | |
createRawTransaction: 'createrawtransaction', | |
decodeRawTransaction: 'decoderawtransaction', | |
dumpPrivKey: 'dumpprivkey', | |
encryptWallet: 'encryptwallet', | |
getAccount: 'getaccount', | |
getAccountAddress: 'getaccountaddress', | |
getAddedNodeInfo: 'getaddednodeinfo', // litecoind v0.8+ | |
getAddressesByAccount: 'getaddressesbyaccount', | |
getBalance: 'getbalance', | |
getbestblockhash: 'getbestblockhash', // litecoind v0.8.6.1+ | |
getBlock: 'getblock', | |
getBlockCount: 'getblockcount', | |
getBlockHash: 'getblockhash', | |
getBlockTemplate: 'getblocktemplate', | |
getConnectionCount: 'getconnectioncount', | |
getDifficulty: 'getdifficulty', | |
getInfo: 'getinfo', | |
getMiningInfo: 'getmininginfo', | |
getNetworkHashPs: 'getnetworkhashps', // litecoind v0.8.4+ | |
getNewAddress: 'getnewaddress', | |
getPeerInfo: 'getpeerinfo', | |
getRawMempool: 'getrawmempool', | |
getRawTransaction: 'getrawtransaction', | |
getReceivedByAccount: 'getreceivedbyaccount', // litecoind v0.3.24+ | |
getReceivedByAddress: 'getreceivedbyaddress', | |
getTransaction: 'gettransaction', | |
getTxOut: 'gettxout', | |
getTxOutSetInfo: 'gettxoutsetinfo', | |
getWork: 'getwork', | |
help: 'help', | |
importPrivKey: 'importprivkey', // litecoind v0.8+ | |
keyPoolRefill: 'keypoolrefill', | |
listAccounts: 'listaccounts', | |
listAddressGroupings: 'listaddressgroupings', | |
listBannedNodes: 'listbannednodes', // OMG2 only | |
listLockUnspent: 'listlockunspent', | |
listReceivedByAccount: 'listreceivedbyaccount', | |
listReceivedByAddress: 'listreceivedbyaddress', | |
listSinceBlock: 'listsinceblock', | |
listTransactions: 'listtransactions', | |
listUnspent: 'listunspent', | |
lockUnspent: 'lockunspent', // litecoind v0.8+ | |
move: 'move', | |
sendFrom: 'sendfrom', | |
sendMany: 'sendmany', | |
sendRawTransaction: 'sendrawtransaction', | |
sendToAddress: 'sendtoaddress', | |
setAccount: 'setaccount', | |
setMininput: 'setmininput', | |
setTxFee: 'settxfee', | |
signMessage: 'signmessage', | |
signRawTransaction: 'signrawtransaction', | |
stop: 'stop', | |
submitBlock: 'submitblock', | |
validateAddress: 'validateaddress', | |
verifyChain: 'verifychain', // litecoind v0.8.6.1+ | |
verifyMessage: 'verifymessage', | |
walletLock: 'walletlock', | |
walletPassphrase: 'walletpassphrase', | |
walletPassphraseChange: 'walletpassphrasechange' | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const commands = require('./commands') | |
const rpc = require('./jsonrpc') | |
const handleError = (err) => console.error(err) | |
const error = (fn) => (err) => fn(err) | |
const getFn = (cb, args) => (cb === undefined) ? args : cb | |
const toArg = (prev, cur, i) => [...prev, cur] | |
const getArgs = (_args) => [ | |
null, | |
..._args.reduce(toArg, []) | |
] | |
const success = ({cb, args, self}) => (..._args) => | |
getFn(cb, args).apply( | |
self, | |
getArgs(_args) | |
) | |
const callRpc = ({ cmd, args, cb, rpc }) => | |
rpc.call( | |
cmd, | |
args, | |
success({ cb, args, self: this}), | |
error(handleError) | |
) | |
const getAction = ({actions, i, cmd, rpc}) => ({ | |
[actions[i]]: (args, cb) => callRpc({ cmd, args, cb, rpc }) }) | |
const toClientActions = ({actions, rpc}) => (result, cmd, i) => | |
Object.assign( | |
result, | |
getAction({ actions, i, cmd, rpc}) | |
) | |
const toActions = (opts, commands) => toClientActions({ | |
actions: Object.keys(commands), | |
rpc: new rpc.Client(opts) | |
}) | |
const Client = (opts) => | |
Object.values(commands) | |
.reduce(toActions(opts, commands), {}) | |
module.exports.Client = Client |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var commands = require('./commands'); | |
var rpc = require('./jsonrpc'); | |
// ===----------------------------------------------------------------------===// | |
// Client | |
// ===----------------------------------------------------------------------===// | |
function Client (opts) { | |
this.rpc = new rpc.Client(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 () {}; | |
} | |
rpc.call(cmd, args, function () { | |
var args = [].slice.call(arguments); | |
args.unshift(null); | |
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); | |
callRpc(commands[protoFn], args, this.rpc); | |
}; | |
})(protoFn); | |
} | |
})(); | |
// Export! | |
module.exports.Client = Client; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const http = require('http') | |
const https = require('https') | |
const Client = (opts) => ({ | |
opts: opts || {}, | |
http: opts.ssl ? https : http | |
}) | |
let cbCalled = false | |
const ERRORS = { | |
'-32602': (statusCode) => Object.assign( | |
new Error('Invalid params, response status code: ' + statusCode), | |
{ code: -32603 } | |
), | |
'-32603': (...args) => Object.assign( | |
new Error('Problem parsing JSON response from server'), | |
{ code: -32603 } | |
) | |
} | |
const isTrue = (...conditions) => | |
conditions.reduce((result, cond) => result && cond, true) | |
const reqOnError = ({cbCalled, reqTimeout, errback}) => (err) => { | |
if (cbCalled) return true | |
clearTimeout(reqTimeout) | |
return errback(err) | |
} | |
const getReject = (self) => self.opts.ssl && self.opts.sslStrict !== false | |
const getRequestJSONArray = (method, time) => | |
method.map((batchCall, i) => ({ | |
id: time + '-' + i, | |
method: batchCall.method, | |
params: batchCall.params | |
}) | |
) | |
const getRequestJSONObject = (method, time, params) => ({ | |
method, | |
params | |
}) | |
const getRequestJSON = (method, time, params) => | |
JSON.stringify((Array.isArray(method)) | |
? getRequestJSONArray(method, time) | |
: getRequestJSONObject(method, time, params)) | |
const getRequestOptions = ( | |
self, | |
path = '/', | |
requestJSON, | |
method = 'POST', | |
agent = false) => ({ | |
host: self.opts.host || 'localhost', | |
port: self.opts.port || 9332, | |
method, | |
path, | |
headers: { | |
'Host': self.opts.host || 'localhost', | |
'Content-Length': requestJSON.length | |
}, | |
agent, | |
rejectUnauthorized: getReject(self) | |
}) | |
const getTimetout = (self, cbCalled, request, errback, errMsg = 'ETIMEDOUT') => | |
setTimeout( () => { | |
if (cbCalled) return true | |
cbCalled = true | |
request.abort() | |
var err = new Error(errMsg) | |
err.code = errMsg | |
return errback(err) | |
}, self.opts.timeout || 30000) | |
const cbErrorBack = (decodedResponse, errback) => { | |
const err = new Error(decodedResponse.error.message || '') | |
if (decodedResponse.error.code) { | |
err.code = decodedResponse.error.code | |
} | |
return errback(err) | |
} | |
const getErrorBack = ({ code, statusCode = false }) => | |
ERRORS[code](statusCode) | |
const responseCbResult = (callback, decodedResponse, response) => | |
(callback) | |
? callback(decodedResponse.result, response.headers) | |
: false | |
const responseCbError = (errback, decodedResponse) => | |
(errback) | |
? cbErrorBack(decodedResponse, errback) | |
: false | |
const toDecodedResponse = (response, callback, errback) => (decodedResponse, i) => { | |
if (isTrue( | |
decodedResponse.hasOwnProperty('error'), | |
decodedResponse.error != null)) { | |
return responseCbError(errback, decodedResponse) | |
} else if (decodedResponse.hasOwnProperty('result')) { | |
return responseCbResult(callback, decodedResponse, response) | |
} else | |
return responseCbError(errback, decodedResponse) | |
} | |
const returnError = (res, err, errback) => | |
(res.statusCode !== 200) | |
? errback(getErrorBack({ code: '-32602', statusCode: res.statusCode })) | |
: errback(getErrorBack({ code: '-32603'})) | |
const decodedResponseFinal = (buffer, response, callback, errback) => { | |
let decoded = JSON.parse(buffer) | |
if (!Array.isArray(decoded)) decoded = [decoded] | |
return decoded.map(toDecodedResponse(response, callback, errback)) | |
} | |
const reqOnResponse = ({cbCalled = false, reqTimeout, callback, errback}) => | |
(response) => { | |
clearTimeout(reqTimeout) | |
let buffer = '' | |
response.on('data', (chunk) => { | |
buffer = buffer + chunk | |
}) | |
response.on('end', () => { | |
if (cbCalled) return true | |
try { | |
return decodedResponseFinal(buffer, response, callback, errback) | |
} catch (e) { | |
return returnError(response, e, errback) | |
} | |
}) | |
} | |
const call = (self) => async function ({method, params, callback, errback, path}) { | |
const time = Date.now() | |
const requestJSON = getRequestJSON(method, time, params) | |
const requestOptions = getRequestOptions(self, path, requestJSON) | |
path = '/' | |
if (isTrue(self.opts.ssl, self.opts.sslCa)) { | |
requestOptions.ca = self.opts.sslCa | |
} | |
if (isTrue(self.opts.user, self.opts.pass)) { | |
requestOptions.auth = self.opts.user + ':' + self.opts.pass | |
} | |
const request = self.http.request(requestOptions) | |
const reqTimeout = getTimetout(self, cbCalled, request, errback) | |
request.on('error', reqOnError({cbCalled, reqTimeout, errback})) | |
request.on('response', reqOnResponse({cbCalled, reqTimeout, callback, errback})) | |
request.end(requestJSON) | |
} | |
module.exports.Client = (opts) => { | |
const client = Client(opts) | |
return Object.assign( | |
client, | |
{ call: call(client) } | |
) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var http = require('http'); | |
var https = require('https'); | |
var Client = function (opts) { | |
this.opts = opts || {}; | |
this.http = this.opts.ssl ? https : http; | |
}; | |
Client.prototype.call = function (method, params, callback, errback, path) { | |
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 || 9332, | |
method: 'POST', | |
path: 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) { | |
requestOptions.ca = this.opts.sslCa; | |
} | |
// use HTTP auth if user and password set | |
if (this.opts.user && this.opts.pass) { | |
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'); | |
err.code = 'ETIMEDOUT'; | |
errback(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'); | |
err.code = 'ESOCKETTIMEDOUT'; | |
errback(err); | |
}); | |
request.on('error', function (err) { | |
if (cbCalled) return; | |
cbCalled = true; | |
clearTimeout(reqTimeout); | |
errback(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; | |
errback(err); | |
} else { | |
err = new Error('Problem parsing JSON response from server'); | |
err.code = -32603; | |
errback(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 (errback) { | |
err = new Error(decodedResponse.error.message || ''); | |
if (decodedResponse.error.code) { | |
err.code = decodedResponse.error.code; | |
} | |
errback(err); | |
} | |
} else if (decodedResponse.hasOwnProperty('result')) { | |
if (callback) { | |
callback(decodedResponse.result, response.headers); | |
} | |
} else { | |
if (errback) { | |
err = new Error(decodedResponse.error.message || '') | |
if (decodedResponse.error.code) { | |
err.code = decodedResponse.error.code; | |
} | |
errback(err); | |
} | |
} | |
}); | |
}); | |
}); | |
request.end(requestJSON); | |
}; | |
module.exports.Client = Client; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment