initial commit

This commit is contained in:
you21979 2017-07-05 19:20:19 +09:00
parent c1b06022f7
commit 70ee2495de
7 changed files with 223 additions and 18 deletions

View File

@ -1,5 +0,0 @@
# node-electrum-client
## electrum protocol
* http://docs.electrum.org/en/latest/protocol.html

25
example/ex.js Normal file
View 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")

1
index.js Normal file
View File

@ -0,0 +1 @@
module.exports = require('./lib/client');

92
lib/client.js Normal file
View 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
View 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
View 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)
}
}

View File

@ -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"
}