initial commit
This commit is contained in:
parent
c1b06022f7
commit
70ee2495de
@ -1,5 +0,0 @@
|
||||
# node-electrum-client
|
||||
|
||||
## electrum protocol
|
||||
|
||||
* http://docs.electrum.org/en/latest/protocol.html
|
||||
25
example/ex.js
Normal file
25
example/ex.js
Normal file
@ -0,0 +1,25 @@
|
||||
const Client = require("../lib/electrum_cli")
|
||||
|
||||
const proc = async(cl) => {
|
||||
try{
|
||||
const version = await cl.server_version("2.7.11", "1.0")
|
||||
console.log(version)
|
||||
const balance = await cl.blockchainAddress_getBalance("MS43dMzRKfEs99Q931zFECfUhdvtWmbsPt")
|
||||
console.log(balance)
|
||||
const utxo = await cl.blockchainAddress_listunspent("MS43dMzRKfEs99Q931zFECfUhdvtWmbsPt")
|
||||
console.log(utxo)
|
||||
}catch(e){
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
|
||||
const main = async(port, host) => {
|
||||
const cl = new Client(port, host);
|
||||
await cl.connect()
|
||||
for(let i = 0; i<100; ++i){
|
||||
await proc(cl)
|
||||
}
|
||||
await cl.close()
|
||||
}
|
||||
|
||||
main(4444, "localhost")
|
||||
92
lib/client.js
Normal file
92
lib/client.js
Normal file
@ -0,0 +1,92 @@
|
||||
'use strict'
|
||||
const net = require('net');
|
||||
const util = require('./util');
|
||||
|
||||
class MessageParser{
|
||||
constructor(callback){
|
||||
this.buffer = ''
|
||||
this.callback = callback
|
||||
}
|
||||
run(chunk){
|
||||
this.buffer += chunk
|
||||
while(true){
|
||||
const res = util.recursiveParser(0, this.buffer, this.callback)
|
||||
this.buffer = res.buffer
|
||||
if(res.code === 0){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Client{
|
||||
constructor(port, host){
|
||||
this.port = port
|
||||
this.host = host
|
||||
this.hostname = [host, port].join(':')
|
||||
this.callback_message_queue = {}
|
||||
this.id = 0;
|
||||
|
||||
this.mp = new MessageParser((body, n) => {
|
||||
this.onMessageRecv(JSON.parse(body));
|
||||
});
|
||||
|
||||
const conn = this.conn = new net.Socket()
|
||||
conn.setEncoding('utf8')
|
||||
conn.setKeepAlive(true, 0)
|
||||
conn.setNoDelay(true)
|
||||
conn.on('connect', () => {
|
||||
})
|
||||
conn.on('close', () => {
|
||||
Object.keys(this.callback_message_queue).forEach((key) => {
|
||||
this.callback_message_queue[key](new Error('close connect'))
|
||||
delete this.callback_message_queue[key]
|
||||
})
|
||||
})
|
||||
conn.on('data', (chunk) => {
|
||||
this.mp.run(chunk)
|
||||
})
|
||||
conn.on('end', () => {
|
||||
})
|
||||
}
|
||||
|
||||
connect(){
|
||||
return new Promise((resolve, reject) => {
|
||||
this.conn.connect(this.port, this.host, () => {
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
close(){
|
||||
this.conn.end();
|
||||
this.conn.destroy();
|
||||
}
|
||||
|
||||
onMessageRecv(msg){
|
||||
if(msg instanceof Array){
|
||||
; // don't support batch request
|
||||
} else {
|
||||
const callback = this.callback_message_queue[msg.id]
|
||||
if(callback){
|
||||
delete this.callback_message_queue[msg.id]
|
||||
if(msg.error){
|
||||
callback(msg.error)
|
||||
}else{
|
||||
callback(null, msg.result)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
request(method, params){
|
||||
return new Promise((resolve, reject) => {
|
||||
const id = ++this.id;
|
||||
const content = util.makeRequest(method, params, id);
|
||||
this.callback_message_queue[id] = util.createPromiseResult(resolve, reject);
|
||||
this.conn.write(content + '\n');
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Client
|
||||
65
lib/electrum_cli.js
Normal file
65
lib/electrum_cli.js
Normal file
@ -0,0 +1,65 @@
|
||||
const Client = require("./client")
|
||||
class ElectrumCli extends Client{
|
||||
constructor(port, host){
|
||||
super(port, host)
|
||||
}
|
||||
server_version(client_name, protocol_version){
|
||||
return this.request('server.version', [client_name, protocol_version])
|
||||
}
|
||||
server_banner(){
|
||||
return this.request('server.banner', [])
|
||||
}
|
||||
serverDonation_address(){
|
||||
return this.request('server.donation_address', [])
|
||||
}
|
||||
serverPeers_subscribe(){
|
||||
return this.request('server.peers.subscribe', [])
|
||||
}
|
||||
blockchainAddress_getBalance(address){
|
||||
return this.request('blockchain.address.get_balance', [address])
|
||||
}
|
||||
blockchainAddress_getHistory(address){
|
||||
return this.request('blockchain.address.get_history', [address])
|
||||
}
|
||||
blockchainAddress_getMempool(address){
|
||||
return this.request('blockchain.address.get_mempool', [address])
|
||||
}
|
||||
blockchainAddress_getProof(address){
|
||||
return this.request('blockchain.address.get_proof', [address])
|
||||
}
|
||||
blockchainAddress_listunspent(address){
|
||||
return this.request('blockchain.address.listunspent', [address])
|
||||
}
|
||||
blockchainBlock_getHeader(height){
|
||||
return this.request('blockchain.block.get_header', [height])
|
||||
}
|
||||
blockchainBlock_getChunk(index){
|
||||
return this.request('blockchain.block.get_chunk', [index])
|
||||
}
|
||||
blockchainEstimatefee(number){
|
||||
return this.request('blockchain.estimatefee', [number])
|
||||
}
|
||||
blockchainHeaders_subscribe(){
|
||||
return this.request('blockchain.headers.subscribe', [])
|
||||
}
|
||||
blockchainNumblocks_subscribe(){
|
||||
return this.request('blockchain.numblocks.subscribe', [])
|
||||
}
|
||||
blockchain_relayfee(){
|
||||
return this.request('blockchain.relayfee', [])
|
||||
}
|
||||
blockchainTransaction_broadcast(rawtx){
|
||||
return this.request('blockchain.transaction.broadcast', [rawtx])
|
||||
}
|
||||
blockchainTransaction_get(tx_hash, height){
|
||||
return this.request('blockchain.transaction.get', [tx_hash, height])
|
||||
}
|
||||
blockchainTransaction_getMerkle(tx_hash, height){
|
||||
return this.request('blockchain.transaction.get_merkle', [tx_hash, height])
|
||||
}
|
||||
blockchainUtxo_getAddress(tx_hash, index){
|
||||
return this.request('blockchain.utxo.get_address', [tx_hash, index])
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ElectrumCli
|
||||
36
lib/util.js
Normal file
36
lib/util.js
Normal file
@ -0,0 +1,36 @@
|
||||
'use strict'
|
||||
|
||||
const makeRequest = exports.makeRequest = (method, params, id) => {
|
||||
return JSON.stringify({
|
||||
jsonrpc : "2.0",
|
||||
method : method,
|
||||
params : params,
|
||||
id : id,
|
||||
})
|
||||
}
|
||||
|
||||
const recursiveParser = exports.recursiveParser = (n, buffer, callback) => {
|
||||
const MAX_DEPTH = 20;
|
||||
if(buffer.length === 0) {
|
||||
return {code:0, buffer:buffer}
|
||||
}
|
||||
if(n > MAX_DEPTH) {
|
||||
return {code:1, buffer:buffer}
|
||||
}
|
||||
const xs = buffer.split('\n')
|
||||
if(xs.length === 1){
|
||||
return {code:0, buffer:buffer}
|
||||
}
|
||||
const content = xs.shift()
|
||||
|
||||
callback(content, n)
|
||||
return recursiveParser(n + 1, xs.join('\n'), callback)
|
||||
}
|
||||
|
||||
const createPromiseResult = exports.createPromiseResult = (resolve, reject) => {
|
||||
return (err, result) => {
|
||||
if(err) reject(err)
|
||||
else resolve(result)
|
||||
}
|
||||
}
|
||||
|
||||
17
package.json
17
package.json
@ -1,22 +1,13 @@
|
||||
{
|
||||
"name": "electrum-client",
|
||||
"version": "1.0.0",
|
||||
"description": "## electrum protocol",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/you21979/node-electrum-client.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"stratum": ""
|
||||
},
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/you21979/node-electrum-client/issues"
|
||||
},
|
||||
"homepage": "https://github.com/you21979/node-electrum-client#readme"
|
||||
"author": "Yuki Akiyama",
|
||||
"license": "MIT"
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user