nano_rpc 0.14.0 → 0.15.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5424fe4a2dbca86499f38bfb5f6edc927b1b0a491e4ccb441944f7d3ce6c06c4
4
- data.tar.gz: '08345ae8d7e10c487999192e88deeea27f171926b0a9aaa86ef641ccd37ef1cb'
3
+ metadata.gz: 384dfb2767f15ba663867d79e98d771de4743b29650acf636f8dbb05ca13712b
4
+ data.tar.gz: b98fb36169c35288da75d2da4902f79d275ae9a88197ba746281baa9bfa7c6ad
5
5
  SHA512:
6
- metadata.gz: 4b01154aaded6d5f27d846f0b3147b162a26c2a6d918fd7074de848164cf32be1cc4f9ba6987784420fdf385e6feb0cbe44c09143992a09e85035191d2379739
7
- data.tar.gz: 044a5c806cf7d2661856f09068e46a9f77ccabc9e8e86700de085d1260bf603d5eece7d4d5016abafb337c6ca05a994431d0952fd50eaf2d8f13002f08953cc2
6
+ metadata.gz: d39b16abbafe3347448eca3341dcc98918149e6df0724078c2e45fdb444f4a352620b50ec2de0d8f4f40a6fa70448a5e520c6299599024fc9908ff90aede288b
7
+ data.tar.gz: 166a68643c927e662cf33372882e3978135e3ab17a9e5a276eb52e3340754f7e9414cda652b507988c6a66a6d4853737e7a5ffceb332ccdd3fb9015e254d9ba7
data/README.md CHANGED
@@ -30,55 +30,7 @@ Or install it yourself as:
30
30
 
31
31
  ## Usage
32
32
 
33
- There are two ways to use this gem. You can make direct RPC calls using Ruby hashes or you can use proxy objects for terser code.
34
-
35
- ### Raw RPC Calls
36
-
37
- The NanoRpc::Node object exposes raw Remote Procedure Call methods according to the [Nano RPC Docs](https://github.com/clemahieu/raiblocks/wiki/RPC-protocol).
38
-
39
- Every method requires an `action`, which is passed as the first argument to `call`. Depending on the action, there may be additional required or optional parameters that are passed as an options hash.
40
-
41
- First setup the node connection:
42
-
43
- ```ruby
44
- # Connect to the default node (localhost:7076)
45
- node = NanoRpc.node
46
-
47
- # or connect to a custom node
48
- node = NanoRpc::Node.new(host: 'mynanonode', port: 1234)
49
- ```
50
-
51
- If you're using [Nanode](https://www.nanode.co/) or similar service that requires `Authorization` key in HTTP header, you can specify it using `auth`.
52
-
53
- ```ruby
54
- node = NanoRpc::Node.new(auth: 'someauthkey')
55
- ```
56
-
57
- You can also specify custom headers as a hash. These will be sent with every RPC request.
58
-
59
- ```ruby
60
- node = NanoRpc::Node.new(headers: { 'Authorization' => 'someauthkey' })
61
- ```
62
-
63
- Once the node is setup, make a `call`, passing the action and data:
64
-
65
- ```ruby
66
- node.call(:account_balance, account: 'xrb_1234')
67
- # => {"balance"=>100, "pending"=>0}
68
- ```
69
-
70
- Response data are provided as [Hashie](https://github.com/intridea/hashie) objects with integer coercion, indifferent access, and method access.
71
-
72
- ```ruby
73
- data = node.call(:account_balance, account: 'xrb_1234')
74
- # => {"balance"=>100, "pending"=>0}
75
- data.balance
76
- # => 100
77
- data[:balance]
78
- # => 100
79
- data['balance']
80
- # => 100
81
- ```
33
+ There are two ways to use this gem. You can use proxy objects that expose helper methods or you make direct RPC calls using Ruby hashes.
82
34
 
83
35
  ### Proxy Objects / Helper Methods
84
36
 
@@ -127,6 +79,58 @@ To convert from Nano to raw and back, use `#to_raw` and `#to_nano`, available on
127
79
 
128
80
  For a comprehensive guide, see the [Wiki](https://github.com/jcraigk/ruby_nano_rpc/wiki).
129
81
 
82
+ ### Direct RPC Calls
83
+
84
+ The NanoRpc::Node object exposes raw Remote Procedure Call methods according to the [Nano RPC Docs](https://github.com/clemahieu/raiblocks/wiki/RPC-protocol).
85
+
86
+ Every method requires an `action`, which is passed as the first argument to `call`. Depending on the action, there may be additional required or optional parameters that are passed as an options hash.
87
+
88
+ First setup the node connection:
89
+
90
+ ```ruby
91
+ # Connect to the default node (localhost:7076)
92
+ node = NanoRpc.node
93
+
94
+ # or connect to a custom node
95
+ node = NanoRpc::Node.new(host: 'mynanonode', port: 1234)
96
+ ```
97
+
98
+ If you're using [Nanode](https://www.nanode.co/) or similar service that requires `Authorization` key in HTTP header, you can specify it using `auth`:
99
+
100
+ ```ruby
101
+ node = NanoRpc::Node.new(auth: 'someauthkey')
102
+ ```
103
+
104
+ You can also specify custom headers as a hash and they will be sent with every RPC request:
105
+
106
+ ```ruby
107
+ node = NanoRpc::Node.new(headers: { 'Authorization' => 'someauthkey' })
108
+ ```
109
+
110
+ The default timeout for each request is 20 seconds but you can specify a custom value:
111
+
112
+ ```ruby
113
+ node = NanoRpc::Node.new(timeout: 10)
114
+ ```
115
+
116
+ Once the node is setup, use the `call` method, passing in action and params:
117
+
118
+ ```ruby
119
+ node.call(:account_balance, account: 'xrb_1234')
120
+ # => {"balance"=>100, "pending"=>0}
121
+ ```
122
+
123
+ Response data are provided as [Hashie](https://github.com/intridea/hashie) objects with integer coercion, indifferent access, and method access.
124
+
125
+ ```ruby
126
+ data.balance
127
+ # => 100
128
+ data[:balance]
129
+ # => 100
130
+ data['balance']
131
+ # => 100
132
+ ```
133
+
130
134
  ## Credits
131
135
 
132
136
  Logo created by Andrei Luca ([Twitter](https://twitter.com/lucandrei_))
data/lib/nano_rpc/node.rb CHANGED
@@ -6,159 +6,194 @@ module NanoRpc
6
6
  def self.node
7
7
  @node ||= Node.new
8
8
  end
9
+ end
9
10
 
10
- class Node
11
- include NanoRpc::Proxy
12
- include NanoRpc::NodeHelper
13
-
14
- attr_reader :host, :port, :auth, :headers, :node
15
-
16
- def initialize(host: 'localhost', port: 7076, auth: nil, headers: nil)
17
- @host = host
18
- @port = port
19
- @auth = auth
20
- @headers = headers
21
- @node = self
11
+ class NanoRpc::Node
12
+ include NanoRpc::Proxy
13
+ include NanoRpc::NodeHelper
14
+
15
+ attr_reader :host, :port, :auth, :headers, :node, :timeout
16
+
17
+ DEFAULT_TIMEOUT = 60
18
+
19
+ def initialize(
20
+ host: 'localhost',
21
+ port: 7076,
22
+ auth: nil,
23
+ headers: nil,
24
+ timeout: DEFAULT_TIMEOUT
25
+ )
26
+ @host = host
27
+ @port = port
28
+ @auth = auth
29
+ @headers = headers
30
+ @timeout = timeout
31
+ @node = self
32
+
33
+ super
34
+ end
22
35
 
23
- super
24
- end
36
+ def call(action, params = {})
37
+ args = { action: action }
38
+ args.merge!(params) if params.is_a?(Hash)
39
+ args = extract_proxy_args(args)
40
+ rpc_post(args)
41
+ end
25
42
 
26
- # Condense host/port on object inspection
27
- def inspect
28
- "#{inspect_prefix}, @url=\"#{@host}:#{port}\">"
29
- end
43
+ # Condense host/port on object inspection
44
+ def inspect
45
+ "#{inspect_prefix}, @url=\"#{@host}:#{port}\">"
46
+ end
30
47
 
31
- def call(action, params = {})
32
- args = { action: action }
33
- args.merge!(params) if params.is_a?(Hash)
34
- args = extract_proxy_args(args)
35
- rpc_post(args)
48
+ proxy_method :available_supply
49
+ proxy_method :block, required: %i[hash]
50
+ proxy_method :block_account, required: %i[hash]
51
+ proxy_method :block_confirm, required: %i[hash]
52
+ proxy_method :block_count
53
+ proxy_method :block_count_type
54
+ proxy_method :block_create,
55
+ required: %i[type key representative source],
56
+ optional: %i[work]
57
+ proxy_method :blocks, required: %i[hashes]
58
+ proxy_method :blocks_info,
59
+ required: %i[hashes],
60
+ optional: %i[pending source balance]
61
+ proxy_method :bootstrap, required: %i[address port]
62
+ proxy_method :bootstrap_any
63
+ proxy_method :chain, required: %i[block count]
64
+ proxy_method :confirmation_history
65
+ proxy_method :deterministic_key, required: %i[seed index]
66
+ proxy_method :frontier_count
67
+ proxy_method :history, required: %i[hash count]
68
+ proxy_method :keepalive, required: %i[address port]
69
+ proxy_method :key_create
70
+ proxy_method :key_expand, required: %i[key]
71
+ proxy_method :krai_from_raw, required: %i[amount]
72
+ proxy_method :krai_to_raw, required: %i[amount]
73
+ proxy_method :mrai_from_raw, required: %i[amount]
74
+ proxy_method :mrai_to_raw, required: %i[amount]
75
+ proxy_method :payment_wait, required: %i[account amount timeout]
76
+ proxy_method :peers
77
+ proxy_method :pending_exists, required: %i[hash]
78
+ proxy_method :process, required: %i[block]
79
+ proxy_method :rai_from_raw, required: %i[amount]
80
+ proxy_method :rai_to_raw, required: %i[amount]
81
+ proxy_method :receive_minimum
82
+ proxy_method :receive_minimum_set, required: %i[amount]
83
+ proxy_method :representatives
84
+ proxy_method :representatives_online
85
+ proxy_method :republish,
86
+ required: %i[hash],
87
+ optional: %i[count sources destinations]
88
+ proxy_method :search_pending, required: %i[wallet]
89
+ proxy_method :search_pending_all
90
+ proxy_method :stats, required: %i[type]
91
+ proxy_method :stop
92
+ proxy_method :successors, required: %i[block count]
93
+ proxy_method :unchecked, required: %i[count]
94
+ proxy_method :unchecked_clear
95
+ proxy_method :unchecked_get, required: %i[hash]
96
+ proxy_method :unchecked_keys, required: %i[key count]
97
+ proxy_method :receive_minimum
98
+ proxy_method :receive_minimum_set, required: %i[amount]
99
+ proxy_method :representatives
100
+ proxy_method :representatives_online
101
+ proxy_method :republish,
102
+ required: %i[hash],
103
+ optional: %i[count sources destinations]
104
+ proxy_method :search_pending, required: %i[wallet]
105
+ proxy_method :search_pending_all
106
+ proxy_method :stats, required: %i[type]
107
+ proxy_method :stop
108
+ proxy_method :successors, required: %i[block count]
109
+ proxy_method :unchecked, required: %i[count]
110
+ proxy_method :unchecked_clear
111
+ proxy_method :unchecked_get, required: %i[hash]
112
+ proxy_method :unchecked_keys, required: %i[key count]
113
+ proxy_method :version
114
+ proxy_method :wallet_create
115
+ proxy_method :work_cancel, required: %i[hash]
116
+ proxy_method :work_generate,
117
+ required: %i[hash],
118
+ optional: %i[use_peers]
119
+ proxy_method :work_peer_add, required: %i[address port]
120
+ proxy_method :work_peers
121
+ proxy_method :work_peers_clear
122
+ proxy_method :work_validate, required: %i[work hash]
123
+
124
+ private
125
+
126
+ def extract_proxy_args(args)
127
+ args.each do |k, v|
128
+ m = proxy_method(v)
129
+ args[k] = v.send(m) if m
36
130
  end
131
+ args
132
+ end
37
133
 
38
- proxy_method :available_supply
39
- proxy_method :block, required: %i[hash]
40
- proxy_method :block_account, required: %i[hash]
41
- proxy_method :block_confirm, required: %i[hash]
42
- proxy_method :block_count
43
- proxy_method :block_count_type
44
- proxy_method :block_create,
45
- required: %i[type key representative source],
46
- optional: %i[work]
47
- proxy_method :blocks, required: %i[hashes]
48
- proxy_method :blocks_info,
49
- required: %i[hashes],
50
- optional: %i[pending source balance]
51
- proxy_method :bootstrap, required: %i[address port]
52
- proxy_method :bootstrap_any
53
- proxy_method :chain, required: %i[block count]
54
- proxy_method :confirmation_history
55
- proxy_method :deterministic_key, required: %i[seed index]
56
- proxy_method :frontier_count
57
- proxy_method :history, required: %i[hash count]
58
- proxy_method :keepalive, required: %i[address port]
59
- proxy_method :key_create
60
- proxy_method :key_expand, required: %i[key]
61
- proxy_method :krai_from_raw, required: %i[amount]
62
- proxy_method :krai_to_raw, required: %i[amount]
63
- proxy_method :mrai_from_raw, required: %i[amount]
64
- proxy_method :mrai_to_raw, required: %i[amount]
65
- proxy_method :payment_wait, required: %i[account amount timeout]
66
- proxy_method :peers
67
- proxy_method :pending_exists, required: %i[hash]
68
- proxy_method :process, required: %i[block]
69
- proxy_method :rai_from_raw, required: %i[amount]
70
- proxy_method :rai_to_raw, required: %i[amount]
71
- proxy_method :receive_minimum
72
- proxy_method :receive_minimum_set, required: %i[amount]
73
- proxy_method :representatives
74
- proxy_method :representatives_online
75
- proxy_method :republish,
76
- required: %i[hash],
77
- optional: %i[count sources destinations]
78
- proxy_method :search_pending, required: %i[wallet]
79
- proxy_method :search_pending_all
80
- proxy_method :stats, required: %i[type]
81
- proxy_method :stop
82
- proxy_method :successors, required: %i[block count]
83
- proxy_method :unchecked, required: %i[count]
84
- proxy_method :unchecked_clear
85
- proxy_method :unchecked_get, required: %i[hash]
86
- proxy_method :unchecked_keys, required: %i[key count]
87
- proxy_method :version
88
- proxy_method :wallet_create
89
- proxy_method :work_cancel, required: %i[hash]
90
- proxy_method :work_generate,
91
- required: %i[hash],
92
- optional: %i[use_peers]
93
- proxy_method :work_peer_add, required: %i[address port]
94
- proxy_method :work_peers
95
- proxy_method :work_peers_clear
96
- proxy_method :work_validate, required: %i[work hash]
97
-
98
- private
99
-
100
- def extract_proxy_args(args)
101
- args.each do |k, v|
102
- m = proxy_method(v)
103
- args[k] = v.send(m) if m
104
- end
105
- args
134
+ def proxy_method(obj)
135
+ if obj.is_a?(NanoRpc::Wallet)
136
+ :seed
137
+ elsif obj.is_a?(NanoRpc::Accounts)
138
+ :addresses
139
+ elsif obj.is_a?(NanoRpc::Account)
140
+ :address
106
141
  end
142
+ end
107
143
 
108
- def proxy_method(obj)
109
- if obj.is_a?(NanoRpc::Wallet)
110
- :seed
111
- elsif obj.is_a?(NanoRpc::Accounts)
112
- :addresses
113
- elsif obj.is_a?(NanoRpc::Account)
114
- :address
115
- end
116
- end
144
+ def rpc_post(params)
145
+ response = rest_client_post(params)
146
+ ensure_status_success(response)
147
+ data = NanoRpc::Response.new(JSON[response&.body])
148
+ ensure_valid_response(data)
117
149
 
118
- def rpc_post(params)
119
- response = rest_client_post(url, params)
120
- ensure_status_success(response)
121
- data = NanoRpc::Response.new(JSON[response&.body])
122
- ensure_valid_response(data)
150
+ data
151
+ end
123
152
 
124
- data
125
- end
153
+ def request_headers
154
+ h = headers || {}
155
+ h['Content-Type'] = 'json'
156
+ h['Authorization'] = auth unless auth.nil?
157
+ h
158
+ end
126
159
 
127
- def request_headers
128
- h = headers || {}
129
- h['Content-Type'] = 'json'
130
- h['Authorization'] = auth unless auth.nil?
131
- h
132
- end
160
+ def rest_client_post(params)
161
+ execute_post(params)
162
+ rescue Errno::ECONNREFUSED
163
+ raise NanoRpc::NodeConnectionFailure,
164
+ "Node connection failure at #{url}"
165
+ rescue RestClient::Exceptions::OpenTimeout
166
+ raise NanoRpc::NodeOpenTimeout,
167
+ 'Node failed to respond in time'
168
+ end
133
169
 
134
- def rest_client_post(url, params)
135
- RestClient.post(url, params.to_json, request_headers)
136
- rescue Errno::ECONNREFUSED
137
- raise NanoRpc::NodeConnectionFailure,
138
- "Node connection failure at #{url}"
139
- rescue RestClient::Exceptions::OpenTimeout
140
- raise NanoRpc::NodeOpenTimeout,
141
- 'Node failed to respond in time'
142
- end
170
+ def execute_post(params)
171
+ RestClient::Request.execute(
172
+ method: :post,
173
+ url: url,
174
+ headers: request_headers,
175
+ payload: params.to_json,
176
+ timeout: timeout
177
+ )
178
+ end
143
179
 
144
- def url
145
- if host.start_with?('http://', 'https://')
146
- "#{host}:#{port}"
147
- else
148
- "http://#{host}:#{port}"
149
- end
180
+ def url
181
+ if host.start_with?('http://', 'https://')
182
+ "#{host}:#{port}"
183
+ else
184
+ "http://#{host}:#{port}"
150
185
  end
186
+ end
151
187
 
152
- def ensure_status_success(response)
153
- return if response&.code == 200
154
- raise NanoRpc::BadRequest,
155
- "Error response from node: #{JSON[response&.body]}"
156
- end
188
+ def ensure_status_success(response)
189
+ return if response&.code == 200
190
+ raise NanoRpc::BadRequest,
191
+ "Error response from node: #{JSON[response&.body]}"
192
+ end
157
193
 
158
- def ensure_valid_response(data)
159
- return unless data['error']
160
- raise NanoRpc::InvalidRequest,
161
- "Invalid request: #{data['error']}"
162
- end
194
+ def ensure_valid_response(data)
195
+ return unless data['error']
196
+ raise NanoRpc::InvalidRequest,
197
+ "Invalid request: #{data['error']}"
163
198
  end
164
199
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module NanoRpc
3
- VERSION = '0.14.0'
3
+ VERSION = '0.15.0'
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nano_rpc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Craig-Kuhn (JCK)