tapyrus 0.3.8 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +2 -2
  3. data/.ruby-version +1 -1
  4. data/README.md +43 -2
  5. data/lib/tapyrus/ext_key.rb +8 -4
  6. data/lib/tapyrus/key.rb +1 -1
  7. data/lib/tapyrus/key_path.rb +17 -13
  8. data/lib/tapyrus/message/fee_filter.rb +2 -2
  9. data/lib/tapyrus/message/header_and_short_ids.rb +4 -4
  10. data/lib/tapyrus/message/inventory.rb +1 -1
  11. data/lib/tapyrus/message/network_addr.rb +2 -2
  12. data/lib/tapyrus/message/ping.rb +2 -2
  13. data/lib/tapyrus/message/pong.rb +2 -2
  14. data/lib/tapyrus/message/send_cmpct.rb +2 -2
  15. data/lib/tapyrus/message/version.rb +3 -3
  16. data/lib/tapyrus/mnemonic.rb +9 -4
  17. data/lib/tapyrus/pstt/input.rb +422 -0
  18. data/lib/tapyrus/pstt/key_origin_info.rb +63 -0
  19. data/lib/tapyrus/pstt/output.rb +129 -0
  20. data/lib/tapyrus/pstt/proprietary.rb +54 -0
  21. data/lib/tapyrus/pstt/tx.rb +658 -0
  22. data/lib/tapyrus/pstt.rb +335 -0
  23. data/lib/tapyrus/rpc.rb +0 -2
  24. data/lib/tapyrus/script/script.rb +14 -4
  25. data/lib/tapyrus/secp256k1/rfc6979.rb +6 -3
  26. data/lib/tapyrus/tip0020.rb +341 -0
  27. data/lib/tapyrus/tx.rb +6 -2
  28. data/lib/tapyrus/tx_out.rb +2 -2
  29. data/lib/tapyrus/util.rb +3 -3
  30. data/lib/tapyrus/version.rb +1 -1
  31. data/lib/tapyrus/wallet/account.rb +2 -2
  32. data/lib/tapyrus/wallet/db.rb +3 -3
  33. data/lib/tapyrus/wallet/master_key.rb +2 -2
  34. data/lib/tapyrus.rb +3 -3
  35. data/tapyrusrb.gemspec +0 -4
  36. metadata +10 -81
  37. data/exe/tapyrusrb-cli +0 -5
  38. data/exe/tapyrusrbd +0 -42
  39. data/lib/tapyrus/network/connection.rb +0 -70
  40. data/lib/tapyrus/network/message_handler.rb +0 -244
  41. data/lib/tapyrus/network/peer.rb +0 -210
  42. data/lib/tapyrus/network/peer_discovery.rb +0 -43
  43. data/lib/tapyrus/network/pool.rb +0 -135
  44. data/lib/tapyrus/network.rb +0 -11
  45. data/lib/tapyrus/node/cli.rb +0 -114
  46. data/lib/tapyrus/node/configuration.rb +0 -36
  47. data/lib/tapyrus/node/spv.rb +0 -78
  48. data/lib/tapyrus/node.rb +0 -7
  49. data/lib/tapyrus/rpc/http_server.rb +0 -64
  50. data/lib/tapyrus/rpc/request_handler.rb +0 -146
@@ -1,210 +0,0 @@
1
- module Tapyrus
2
- module Network
3
- # remote peer class.
4
- class Peer
5
- # Interval for pinging peers.
6
- PING_INTERVAL = 2 * 60
7
-
8
- attr_reader :logger
9
- attr_accessor :id
10
- attr_accessor :local_version
11
- attr_accessor :last_send
12
- attr_accessor :last_recv
13
- attr_accessor :bytes_sent
14
- attr_accessor :bytes_recv
15
- attr_accessor :conn_time
16
- attr_accessor :last_ping
17
- attr_accessor :last_ping_nonce
18
- attr_accessor :last_pong
19
- attr_accessor :min_ping
20
- attr_accessor :outbound # TODO need implements to accept inbound connection
21
- attr_accessor :best_hash
22
- attr_accessor :best_height
23
-
24
- # remote peer info
25
- attr_reader :host
26
- attr_reader :port
27
-
28
- # remote peer connection
29
- attr_accessor :conn
30
- attr_accessor :connected
31
- attr_accessor :primary
32
-
33
- # parent pool
34
- attr_reader :pool
35
- attr_reader :chain
36
- attr_accessor :fee_rate
37
-
38
- def initialize(host, port, pool, configuration)
39
- @host = host
40
- @port = port
41
- @pool = pool
42
- @chain = pool.chain
43
- @connected = false
44
- @primary = false
45
- @logger = Tapyrus::Logger.create(:debug)
46
- @outbound = true
47
- @best_hash = -1
48
- @best_height = -1
49
- @min_ping = -1
50
- @bytes_sent = 0
51
- @bytes_recv = 0
52
- @relay = configuration.conf[:relay]
53
- current_height = @chain.latest_block.height
54
- remote_addr = Tapyrus::Message::NetworkAddr.new(ip: host, port: port, time: nil)
55
- @local_version =
56
- Tapyrus::Message::Version.new(remote_addr: remote_addr, start_height: current_height, relay: @relay)
57
- end
58
-
59
- def connect
60
- self.conn ||= EM.connect(host, port, Tapyrus::Network::Connection, self)
61
- end
62
-
63
- def connected?
64
- @connected
65
- end
66
-
67
- def outbound?
68
- @outbound
69
- end
70
-
71
- def addr
72
- "#{host}:#{port}"
73
- end
74
-
75
- # calculate ping-pong time.
76
- def ping_time
77
- last_pong ? (last_pong - last_ping) / 1e6 : -1
78
- end
79
-
80
- # set last pong
81
- def last_pong=(time)
82
- @last_pong = time
83
- @min_ping = ping_time if min_ping == -1 || ping_time < min_ping
84
- end
85
-
86
- def post_handshake
87
- @connected = true
88
- pool.handle_new_peer(self)
89
-
90
- # require remote peer to use headers message instead fo inv message.
91
- conn.send_message(Tapyrus::Message::SendHeaders.new)
92
- EM.add_periodic_timer(PING_INTERVAL) { send_ping }
93
- end
94
-
95
- # start block header download
96
- def start_block_header_download
97
- logger.info("[#{addr}] start block header download.")
98
- get_headers =
99
- Tapyrus::Message::GetHeaders.new(Tapyrus.chain_params.protocol_version, [chain.latest_block.block_hash])
100
- conn.send_message(get_headers)
101
- end
102
-
103
- # broadcast tx.
104
- def broadcast_tx(tx)
105
- conn.send_message(Tapyrus::Message::Tx.new(tx))
106
- end
107
-
108
- # get peer's block type.
109
- def block_type
110
- Tapyrus::Message::Inventory::MSG_FILTERED_BLOCK # TODO need other implementation
111
- end
112
-
113
- # get remote peer's version message.
114
- # @return [Tapyrus::Message::Version]
115
- def remote_version
116
- conn.version
117
- end
118
-
119
- # Whether to try and download blocks and transactions from this peer.
120
- def primary?
121
- primary
122
- end
123
-
124
- # handle headers message
125
- # @params [Tapyrus::Message::Headers]
126
- def handle_headers(headers)
127
- headers.headers.each do |header|
128
- break unless header.valid?
129
- entry = chain.append_header(header)
130
- next unless entry
131
- @best_hash = entry.block_hash
132
- @best_height = entry.height
133
- end
134
- pool.changed
135
- pool.notify_observers(:header, { hash: @best_hash, height: @best_height })
136
- start_block_header_download if headers.headers.size > 0 # next header download
137
- end
138
-
139
- # handle error
140
- def handle_error(e)
141
- pool.handle_error(e)
142
- end
143
-
144
- def unbind
145
- pool.handle_close_peer(self)
146
- end
147
-
148
- # close peer connection.
149
- def close(msg = "")
150
- conn.close(msg)
151
- end
152
-
153
- # generate Tapyrus::Message::NetworkAddr object from this peer info.
154
- # @return [Tapyrus::Message::NetworkAddr]
155
- def to_network_addr
156
- v = remote_version
157
- Tapyrus::Message::NetworkAddr.new(ip: host, port: port, services: v.services, time: v.timestamp)
158
- end
159
-
160
- # send +addr+ message to remote peer
161
- def send_addrs
162
- addrs = pool.peers.select { |p| p != self }.map(&:to_network_addr)
163
- conn.send_message(Tapyrus::Message::Addr.new(addrs))
164
- end
165
-
166
- # handle block inv message.
167
- def handle_block_inv(hashes)
168
- getdata = Tapyrus::Message::GetData.new(hashes.map { |h| Tapyrus::Message::Inventory.new(block_type, h) })
169
- conn.send_message(getdata)
170
- end
171
-
172
- def handle_tx(tx)
173
- pool.changed
174
- pool.notify_observers(:tx, tx)
175
- end
176
-
177
- def handle_merkle_block(merkle_block)
178
- pool.changed
179
- pool.notify_observers(:merkleblock, merkle_block)
180
- end
181
-
182
- # send ping message.
183
- def send_ping
184
- ping = Tapyrus::Message::Ping.new
185
- @last_ping = Time.now.to_i
186
- @last_pong = -1
187
- @last_ping_nonce = ping.nonce
188
- conn.send_message(ping)
189
- end
190
-
191
- # send filterload message.
192
- def send_filter_load(bloom)
193
- filter_load = Tapyrus::Message::FilterLoad.new(bloom, Tapyrus::Message::FilterLoad::BLOOM_UPDATE_ALL)
194
- conn.send_message(filter_load)
195
- end
196
-
197
- # send filteradd message.
198
- def send_filter_add(element)
199
- filter_add = Tapyrus::Message::FilterAdd.new(element)
200
- conn.send_message(filter_add)
201
- end
202
-
203
- # send filterclear message.
204
- def send_filter_clear
205
- filter_clear = Tapyrus::Message::FilterClear.new
206
- conn.send_message(filter_clear)
207
- end
208
- end
209
- end
210
- end
@@ -1,43 +0,0 @@
1
- module Tapyrus
2
- module Network
3
- class PeerDiscovery
4
- attr_reader :logger, :configuration
5
-
6
- def initialize(configuration)
7
- @logger = Tapyrus::Logger.create(:debug)
8
- @configuration = configuration
9
- end
10
-
11
- # get peer addresses, from DNS seeds.
12
- def peers
13
- # TODO add find from previous connected peer at first.
14
- (find_from_dns_seeds + seeds).uniq
15
- end
16
-
17
- private
18
-
19
- def dns_seeds
20
- Tapyrus.chain_params.dns_seeds || []
21
- end
22
-
23
- def seeds
24
- [*configuration.conf[:connect]]
25
- end
26
-
27
- def find_from_dns_seeds
28
- logger.debug "discover peer address from DNS seeds."
29
- dns_seeds
30
- .map do |seed|
31
- begin
32
- Socket.getaddrinfo(seed, Tapyrus.chain_params.default_port).map { |a| a[2] }.uniq
33
- rescue SocketError => e
34
- logger.error "SocketError occurred when load DNS seed: #{seed}, error: #{e.message}"
35
- nil
36
- end
37
- end
38
- .flatten
39
- .compact
40
- end
41
- end
42
- end
43
- end
@@ -1,135 +0,0 @@
1
- module Tapyrus
2
- module Network
3
- # Time between pings automatically sent out for latency probing and keepalive (in seconds).
4
- PING_INTERVAL = 2 * 60
5
-
6
- # Time after which to disconnect, after waiting for a ping response (or inactivity).
7
- TIMEOUT_INTERVAL = 20 * 60
8
-
9
- # Maximum number of automatic outgoing nodes
10
- MAX_OUTBOUND_CONNECTIONS = 4
11
-
12
- # peer pool class.
13
- class Pool
14
- include Observable
15
-
16
- attr_reader :peers # active peers
17
- attr_reader :pending_peers # currently connecting peer
18
- attr_reader :node
19
- attr_reader :chain
20
- attr_reader :max_outbound
21
- attr_reader :logger
22
- attr_reader :peer_discovery
23
- attr_accessor :started
24
- attr_reader :mutex
25
-
26
- def initialize(node, chain, configuration)
27
- @node = node
28
- @peers = []
29
- @pending_peers = []
30
- @max_outbound = MAX_OUTBOUND_CONNECTIONS
31
- @chain = chain
32
- @logger = Tapyrus::Logger.create(:debug)
33
- @configuration = configuration
34
- @peer_discovery = PeerDiscovery.new(configuration)
35
- @started = false
36
- @mutex = Mutex.new
37
- end
38
-
39
- # connecting other peers and begin network activity.
40
- def start
41
- raise "Cannot start a peer pool twice." if started
42
- logger.debug "Start connecting other pears."
43
- addr_list = peer_discovery.peers
44
-
45
- connect(addr_list)
46
-
47
- @started = true
48
- end
49
-
50
- # detect new peer connection.
51
- def handle_new_peer(peer)
52
- logger.debug "connected new peer #{peer.addr}."
53
- mutex.synchronize do
54
- peer.id = allocate_peer_id
55
- unless peers.find(&:primary?)
56
- peer.primary = true
57
- peer.start_block_header_download
58
- end
59
- peers << peer
60
- end
61
- pending_peers.delete(peer)
62
- filter_load(peer) if node.wallet
63
- end
64
-
65
- def handle_close_peer(peer)
66
- return unless started
67
- peers.delete(peer)
68
- pending_peers.delete(peer)
69
- addr_list = peer_discovery.peers - peers.map(&:host) - pending_peers.map(&:host) - [peer.host]
70
- connect(addr_list)
71
- end
72
-
73
- # terminate peers.
74
- def terminate
75
- peers.each { |peer| peer.close("terminate") }
76
- pending_peers.each { |peer| peer.close("terminate") }
77
- @peers = []
78
- @started = false
79
- end
80
-
81
- # broadcast tx to connecting peer.
82
- def broadcast(tx)
83
- peers.each { |peer| peer.broadcast_tx(tx) }
84
- end
85
-
86
- # new bloom filter.
87
- def filter_load(peer)
88
- peer.send_filter_load(node.bloom)
89
- end
90
-
91
- # add element to bloom filter.
92
- def filter_add(element)
93
- peers.each { |peer| peer.send_filter_add(element) }
94
- end
95
-
96
- # clear bloom filter.
97
- def filter_clear
98
- peers.each { |peer| peer.send_filter_clear }
99
- end
100
-
101
- def handle_error(e)
102
- terminate
103
- end
104
-
105
- private
106
-
107
- # get primary peer
108
- def primary_peer
109
- peers.find(&:primary?)
110
- end
111
-
112
- # allocate new peer id
113
- def allocate_peer_id
114
- id = 0
115
- id += 1 until peers.empty? || peers.find { |p| p.id == id }.nil?
116
- id
117
- end
118
-
119
- def connect(addr_list)
120
- port = Tapyrus.chain_params.default_port
121
-
122
- EM::Iterator
123
- .new(addr_list, Tapyrus::PARALLEL_THREAD)
124
- .each do |ip, iter|
125
- if pending_peers.size + peers.size < MAX_OUTBOUND_CONNECTIONS
126
- peer = Peer.new(ip, port, self, @configuration)
127
- pending_peers << peer
128
- peer.connect
129
- iter.next
130
- end
131
- end
132
- end
133
- end
134
- end
135
- end
@@ -1,11 +0,0 @@
1
- require "eventmachine"
2
-
3
- module Tapyrus
4
- module Network
5
- autoload :MessageHandler, "tapyrus/network/message_handler"
6
- autoload :Connection, "tapyrus/network/connection"
7
- autoload :Pool, "tapyrus/network/pool"
8
- autoload :Peer, "tapyrus/network/peer"
9
- autoload :PeerDiscovery, "tapyrus/network/peer_discovery"
10
- end
11
- end
@@ -1,114 +0,0 @@
1
- require "net/http"
2
- require "thor"
3
- require "json"
4
-
5
- module Tapyrus
6
- module Node
7
- class CLI < Thor
8
- class_option :network, aliases: "-n", default: :prod
9
-
10
- desc "getblockchaininfo", "Returns an object containing various state info regarding blockchain processing."
11
- def getblockchaininfo
12
- request("getblockchaininfo")
13
- end
14
-
15
- desc "stop", "Stop Tapyrus server."
16
- def stop
17
- request("stop")
18
- end
19
-
20
- desc 'getblockheader "hash" ( verbose )',
21
- 'If verbose is false, returns a string that is serialized, hex-encoded data for blockheader "hash". If verbose is true, returns an Object with information about blockheader <hash>.'
22
- def getblockheader(hash, verbose = true)
23
- verbose = verbose.is_a?(String) ? (verbose == "true") : verbose
24
- request("getblockheader", hash, verbose)
25
- end
26
-
27
- desc "getpeerinfo", "Returns data about each connected network node as a json array of objects."
28
- def getpeerinfo
29
- request("getpeerinfo")
30
- end
31
-
32
- desc 'decoderawtransaction "hexstring"',
33
- "Return a JSON object representing the serialized, hex-encoded transaction."
34
- def decoderawtransaction(hexstring)
35
- request("decoderawtransaction", hexstring)
36
- end
37
-
38
- desc 'decodescript "hexstring"', "Decode a hex-encoded script."
39
- def decodescript(hexstring)
40
- request("decodescript", hexstring)
41
- end
42
-
43
- # wallet cli
44
-
45
- desc "sendrawtransaction", "Submits raw transaction (serialized, hex-encoded) to local node and network."
46
- def sendrawtransaction(hex_tx)
47
- request("sendrawtransaction", hex_tx)
48
- end
49
-
50
- desc 'createwallet "wallet_id"',
51
- "Create new HD wallet. It returns an error if an existing wallet_id is specified. "
52
- def createwallet(wallet_id)
53
- request("createwallet", wallet_id)
54
- end
55
-
56
- desc "listwallets",
57
- 'Returns a list of currently loaded wallets. For full information on the wallet, use "getwalletinfo"'
58
- def listwallets
59
- request("listwallets")
60
- end
61
-
62
- desc "getwalletinfo", "Returns an object containing various wallet state info."
63
- def getwalletinfo
64
- request("getwalletinfo")
65
- end
66
-
67
- desc "listaccounts", "[WIP]Returns Object that has account names as keys, account balances as values."
68
- def listaccounts
69
- request("listaccounts")
70
- end
71
-
72
- desc 'encryptwallet "passphrase"',
73
- 'Encrypts the wallet with "passphrase". This is for first time encryption.After this, any calls that interact with private keys such as sending or signing will require the passphrase to be set prior the making these calls.'
74
- def encryptwallet(passhphrase)
75
- request("encryptwallet", passhphrase)
76
- end
77
-
78
- desc 'getnewaddress "account"', "Returns a new Tapyrus address for receiving payments."
79
- def getnewaddress(account)
80
- request("getnewaddress", account)
81
- end
82
-
83
- private
84
-
85
- def config
86
- opts = {}
87
- opts[:network] = options["network"] if options["network"]
88
- @conf ||= Tapyrus::Node::Configuration.new(opts)
89
- end
90
-
91
- def request(command, *params)
92
- data = { method: command, params: params, id: "jsonrpc" }
93
- begin
94
- uri = URI.parse(config.server_url)
95
- http = Net::HTTP.new(uri.hostname, uri.port)
96
- http.use_ssl = uri.scheme === "https"
97
- request = Net::HTTP::Post.new("/")
98
- request.content_type = "application/json"
99
- request.body = data.to_json
100
- response = http.request(request)
101
- body = response.body
102
- begin
103
- json = JSON.parse(body.to_str)
104
- puts JSON.pretty_generate(json)
105
- rescue Exception
106
- puts body.to_str
107
- end
108
- rescue Exception => e
109
- puts e.message
110
- end
111
- end
112
- end
113
- end
114
- end
@@ -1,36 +0,0 @@
1
- require "iniparse"
2
-
3
- module Tapyrus
4
- module Node
5
- class Configuration
6
- attr_reader :conf
7
-
8
- def initialize(opts = {})
9
- # TODO apply configuration file.
10
- opts[:network] = :prod unless opts[:network]
11
- opts[:relay] = false unless opts[:relay]
12
- Tapyrus.chain_params = opts[:network]
13
-
14
- begin
15
- ini_file = IniParse.parse(File.read("#{Tapyrus.base_dir}/tapyrusrb.conf"))
16
- @conf = Hash[ini_file.to_h["__anonymous__"].map { |k, v| [k.to_sym, v] }]
17
- rescue => e
18
- @conf = {}
19
- end
20
- @conf.merge!(opts)
21
- end
22
-
23
- def host
24
- "localhost"
25
- end
26
-
27
- def port
28
- Tapyrus.chain_params.default_port - 1
29
- end
30
-
31
- def server_url
32
- "http://#{host}:#{port}"
33
- end
34
- end
35
- end
36
- end
@@ -1,78 +0,0 @@
1
- module Tapyrus
2
- module Node
3
- # SPV class
4
- class SPV
5
- attr_reader :chain
6
- attr_reader :pool
7
- attr_reader :logger
8
- attr_accessor :running
9
- attr_reader :configuration
10
- attr_accessor :server
11
- attr_accessor :wallet
12
- attr_accessor :bloom
13
-
14
- def initialize(configuration)
15
- @chain = Tapyrus::Store::SPVChain.new
16
- @configuration = configuration
17
- @pool = Tapyrus::Network::Pool.new(self, @chain, @configuration)
18
- @logger = Tapyrus::Logger.create(:debug)
19
- @running = false
20
- @wallet = Tapyrus::Wallet::Base.current_wallet
21
-
22
- # TODO : optimize bloom filter parameters
23
- setup_filter
24
- end
25
-
26
- # open the node.
27
- def run
28
- # TODO need process running check.
29
- return if running
30
- logger.debug "SPV node start running."
31
- EM.run do
32
- # EM.start_server('0.0.0.0', Tapyrus.chain_params.default_port, Tapyrus::Network::InboundConnector, self)
33
- pool.start
34
- @server = Tapyrus::RPC::HttpServer.run(self, configuration.port)
35
- end
36
- end
37
-
38
- # close the node.
39
- def shutdown
40
- pool.terminate
41
- logger.debug "SPV node shutdown."
42
- end
43
-
44
- # broadcast a transaction
45
- def broadcast(tx)
46
- pool.broadcast(tx)
47
- logger.debug "broadcast tx: #{tx.to_hex}"
48
- end
49
-
50
- # add filter element to bloom filter.
51
- # [String] element. the hex string of txid, public key, public key hash or outpoint.
52
- def filter_add(element)
53
- bloom.add(element)
54
- pool.filter_add(element)
55
- end
56
-
57
- # clear bloom filter.
58
- def filter_clear
59
- pool.filter_clear
60
- end
61
-
62
- def add_observer(observer)
63
- pool.add_observer(observer)
64
- end
65
-
66
- def delete_observer(observer)
67
- pool.delete_observer(observer)
68
- end
69
-
70
- private
71
-
72
- def setup_filter
73
- @bloom = Tapyrus::BloomFilter.create_filter(512, 0.01)
74
- wallet.watch_targets.each { |t| bloom.add(t.htb) } if wallet
75
- end
76
- end
77
- end
78
- end
data/lib/tapyrus/node.rb DELETED
@@ -1,7 +0,0 @@
1
- module Tapyrus
2
- module Node
3
- autoload :SPV, "tapyrus/node/spv"
4
- autoload :CLI, "tapyrus/node/cli"
5
- autoload :Configuration, "tapyrus/node/configuration"
6
- end
7
- end
@@ -1,64 +0,0 @@
1
- require "evma_httpserver"
2
- require "json"
3
-
4
- module Tapyrus
5
- module RPC
6
- # Tapyrusrb RPC server.
7
- class HttpServer < EM::Connection
8
- include EM::HttpServer
9
- include RequestHandler
10
-
11
- attr_reader :node
12
- attr_accessor :logger
13
-
14
- def initialize(node)
15
- @node = node
16
- @logger = Tapyrus::Logger.create(:debug)
17
- end
18
-
19
- def post_init
20
- super
21
- logger.debug "start http server."
22
- end
23
-
24
- def self.run(node, port = 8332)
25
- EM.start_server("0.0.0.0", port, HttpServer, node)
26
- end
27
-
28
- # process http request.
29
- def process_http_request
30
- operation =
31
- proc do
32
- command, args = parse_json_params
33
- logger.debug("process http request. command = #{command}")
34
- begin
35
- send(command, *args).to_json
36
- rescue Exception => e
37
- e
38
- end
39
- end
40
- callback =
41
- proc do |result|
42
- response = EM::DelegatedHttpResponse.new(self)
43
- if result.is_a?(Exception)
44
- response.status = 500
45
- response.content = result.message
46
- else
47
- response.status = 200
48
- response.content = result
49
- end
50
- response.content_type "application/json"
51
- response.send_response
52
- end
53
- EM.defer(operation, callback)
54
- end
55
-
56
- # parse request parameter.
57
- # @return [Array] the array of command and args
58
- def parse_json_params
59
- params = JSON.parse(@http_post_content)
60
- [params["method"], params["params"]]
61
- end
62
- end
63
- end
64
- end