nano_rpc 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 31ae67733c43baa9c7abad5602ce086a4869f97b758b2fc6dfa2936fe2e1faac
4
- data.tar.gz: 65972b80fc7b29dc8e1dd8d01897f3ef3758f32cca06bece13048a1253d343ea
3
+ metadata.gz: 4a14ad62aa7895381a7d304358397e3e0c84895e98a910d6958d8f89f0caf80c
4
+ data.tar.gz: f873b576248b45a70bcddca71721215dde596950c9ce1833918b1dfa66a72133
5
5
  SHA512:
6
- metadata.gz: 8320b2affa49d105293af12ffdf551928d5f5242a04087d3ef45714d74e8f18a9db6cfe6c0e4b612a55bc649df14077ade65dc70c1cae667c87d2afff9418a06
7
- data.tar.gz: a23042ec1d7ce8fb19b19f10ba621f1e8dfa94461327d3b813df7def5db131f6bdd9ef5bbcf8262eee459566cf2e801d7d570753a44e4d9129e508de7a6921c6
6
+ metadata.gz: baef53c6d16c0ffc55bc649335dbf61c339a7e3638bf5d05bf199b9de990e108938af88ec01888275efe99e61f96dfb8ef7862b3b861a8264297adec1ba6534a
7
+ data.tar.gz: 583673b49fc417a05d8b0c08d9caa8ad9bfad57eabb26bbaff0e735222b27ea6f6f5c564c76cc1ee256024412c0e4416dcce7b5428a5483a9c253b9d862b1dda
data/.rubocop.yml CHANGED
@@ -1,8 +1,15 @@
1
1
  AllCops:
2
2
  TargetRubyVersion: 2.5.0
3
3
  Exclude:
4
- - 'bin/*'
4
+ - bin/*
5
5
  DisplayCopNames: true
6
+ Metrics/BlockLength:
7
+ Exclude:
8
+ - spec/**/*
9
+ Metrics/ModuleLength:
10
+ Max: 200
11
+ Metrics/ClassLength:
12
+ Max: 200
6
13
  Style/ClassAndModuleChildren:
7
14
  EnforcedStyle: compact
8
15
  Style/EmptyMethod:
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ [![Maintainability](https://api.codeclimate.com/v1/badges/a99a88d28ad37a79dbf6/maintainability)](https://codeclimate.com/github/codeclimate/codeclimate/maintainability)
2
+
1
3
  ![Ruby Nano RPC Logo](https://i.imgur.com/ihmmYcp.png)
2
4
 
3
5
  Nano RPC is a Ruby wrapper for making Remote Procedure Calls against Nano digital currency nodes. Arbitrary RPC access is provided along with proxy objects that expose helper methods ([Wiki](https://github.com/jcraigk/ruby_nano_rpc/wiki)).
@@ -22,90 +24,89 @@ Or install it yourself as:
22
24
 
23
25
  ## Usage
24
26
 
25
- There are two ways to use this gem. You can make direct calls to the RPC client using Ruby hashes or you can use proxy objects for terser code.
27
+ 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.
26
28
 
27
29
  ### Raw RPC Calls
28
30
 
29
- The RCP client exposes raw Remote Procedure Call methods according to the [Nano RPC Docs](https://github.com/clemahieu/raiblocks/wiki/RPC-protocol).
31
+ The NanoRpc::Node object exposes raw Remote Procedure Call methods according to the [Nano RPC Docs](https://github.com/clemahieu/raiblocks/wiki/RPC-protocol).
30
32
 
31
33
  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.
32
34
 
33
- First setup the client:
35
+ First setup the node connection:
34
36
 
35
37
  ```ruby
36
38
  # Connect to the default node (localhost:7076)
37
- client = Nano.client
39
+ node = NanoRpc.node
38
40
 
39
41
  # or connect to a custom node
40
- client = Nano::Client.new(host: 'mynanonode', port: 1234)
42
+ node = NanoRpc::Node.new(host: 'mynanonode', port: 1234)
41
43
  ```
42
44
 
43
45
  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`.
44
46
 
45
47
  ```ruby
46
- client = Nano::Client.new(auth: 'someauthkey')
48
+ node = NanoRpc::Node.new(auth: 'someauthkey')
47
49
  ```
48
50
 
49
51
  You can also specify custom headers as a hash. These will be sent with every RPC request.
50
52
 
51
53
  ```ruby
52
- client = Nano::Client.new(headers: { 'Authorization' => 'someauthkey' })
54
+ node = NanoRpc::Node.new(headers: { 'Authorization' => 'someauthkey' })
53
55
  ```
54
56
 
55
- Once the client is created, make a `call`, passing the action and data:
57
+ Once the node is setup, make a `call`, passing the action and data:
56
58
 
57
59
  ```ruby
58
- client.call(:account_balance, account: 'xrb_someaddress1234')
59
- # => {"balance"=>100, "pending"=>0}
60
- ````
60
+ node.call(:account_balance, account: 'xrb_1234')
61
+ # => {"balance"=>100, "pending"=>0}
62
+ ```
61
63
 
62
64
  Response data are provided as [Hashie](https://github.com/intridea/hashie) objects with integer coercion, indifferent access, and method access.
63
65
 
64
66
  ```ruby
65
- data = client.call(:account_balance, account: 'xrb_someaddress1234')
66
- # => {"balance"=>100, "pending"=>0}
67
- data.balance
68
- # => 100
69
- data[:balance]
70
- # => 100
71
- data['balance']
72
- # => 100
73
- ````
67
+ data = node.call(:account_balance, account: 'xrb_1234')
68
+ # => {"balance"=>100, "pending"=>0}
69
+ data.balance
70
+ # => 100
71
+ data[:balance]
72
+ # => 100
73
+ data['balance']
74
+ # => 100
75
+ ```
74
76
 
75
77
  ### Proxy Objects / Helper Methods
76
78
 
77
79
  Proxy objects are provided to ease interaction with the API by providing logically grouped helper methods. Here we do not strictly follow the grouping as expressed in the [Nano RPC Docs](https://github.com/clemahieu/raiblocks/wiki/RPC-protocol). Instead, the following objects are provided:
78
80
 
79
- * [Nano::Account](https://github.com/jcraigk/ruby_nano_rpc/wiki/Nano::Account)
80
- * [Nano::Accounts](https://github.com/jcraigk/ruby_nano_rpc/wiki/Nano::Accounts)
81
- * [Nano::Node](https://github.com/jcraigk/ruby_nano_rpc/wiki/Nano::Node)
82
- * [Nano::Wallet](https://github.com/jcraigk/ruby_nano_rpc/wiki/Nano::Wallet)
81
+ * [NanoRpc::Account](https://github.com/jcraigk/ruby_nano_rpc/wiki/NanoRpc::Account)
82
+ * [NanoRpc::Accounts](https://github.com/jcraigk/ruby_nano_rpc/wiki/NanoRpc::Accounts)
83
+ * [NanoRpc::Node](https://github.com/jcraigk/ruby_nano_rpc/wiki/NanoRpc::Node)
84
+ * [NanoRpc::Wallet](https://github.com/jcraigk/ruby_nano_rpc/wiki/NanoRpc::Wallet)
83
85
 
84
86
  `Account`, `Accounts`, and `Wallet` each require a single parameter to be passed during initialization (`address`, `addresses`, and `seed`, respectively). This parameter is persisted for subsequent calls. All RPC methods are provided directly as methods.
85
87
 
86
88
  ```ruby
87
- account = Nano::Account.new('xrb_someaddress1234')
88
-
89
- account.account_balance
90
- # => {"balance"=>100, "pending"=>5}
91
- account.account_balance.balance
92
- # => 100
89
+ account = node.account('xrb_1234') # Account address required
90
+ accounts = node.accounts(['xrb_1234', 'xrb_456']) # Array of account addresses required
91
+ wallet = node.wallet('3AF91AE') # Wallet seed required
93
92
  ```
94
93
 
95
- There are also helper methods to bypass repetitive nested calls:
94
+ You can call standard RPC methods on each object:
96
95
 
97
96
  ```ruby
98
- account.balance
99
- # => 100
100
- account.pending_balance
101
- # => 5
97
+ account.account_balance
98
+ # => {"balance"=>100, "pending"=>5}
99
+ account.account_balance.balance
100
+ # => 100
102
101
  ```
103
102
 
104
- You can point each proxy object at its own node by passing in a client instance:
103
+ There are also helper methods to bypass repetitive nested calls:
105
104
 
106
105
  ```ruby
107
- client = Nano::Client.new(host: 'mynanonode', port: 1234)
108
- account = Nano::Account.new('xrb_someaddress1234', client: client)
106
+ account.balance
107
+ # => 100
108
+ account.pending_balance
109
+ # => 5
109
110
  ```
110
111
 
111
112
  For a comprehensive guide, see the [Wiki](https://github.com/jcraigk/ruby_nano_rpc/wiki).
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- module Nano
2
+ module NanoRpc
3
3
  class Error < StandardError; end
4
4
 
5
5
  class NodeConnectionFailure < Error; end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
- module Nano::AccountHelper
3
- include Nano::ApplicationHelper
2
+ module NanoRpc::AccountHelper
3
+ include NanoRpc::ApplicationHelper
4
4
 
5
5
  def balance
6
6
  account_balance.balance
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
- module Nano::AccountsHelper
3
- include Nano::ApplicationHelper
2
+ module NanoRpc::AccountsHelper
3
+ include NanoRpc::ApplicationHelper
4
4
 
5
5
  def balances
6
6
  accounts_balances
@@ -36,11 +36,11 @@ module Nano::AccountsHelper
36
36
  end
37
37
  alias pending_blocks pending
38
38
 
39
- # Array-like access for Nano::Account
39
+ # Array-like access for NanoRpc::Account
40
40
  def [](idx)
41
41
  return unless @addresses[idx]
42
42
  @account_objects ||= []
43
- @account_objects[idx] ||= Nano::Account.new(@addresses[idx], client: client)
43
+ @account_objects[idx] ||= NanoRpc::Account.new(@addresses[idx], node: node)
44
44
  end
45
45
 
46
46
  def <<(val)
@@ -49,7 +49,7 @@ module Nano::AccountsHelper
49
49
 
50
50
  def each(&_block)
51
51
  @addresses.each do |address|
52
- yield Nano::Account.new(address, client: client)
52
+ yield NanoRpc::Account.new(address, node: node)
53
53
  end
54
54
  end
55
55
 
@@ -1,8 +1,12 @@
1
1
  # frozen_string_literal: true
2
- module Nano::ApplicationHelper
2
+ module NanoRpc::ApplicationHelper
3
3
  private
4
4
 
5
5
  def inspect_prefix
6
- "#<#{self.class}:#{format('0x00%x', object_id << 1)}"
6
+ "#<#{self.class}:#{obj_id}"
7
+ end
8
+
9
+ def obj_id
10
+ format('0x00%<object_id>x', object_id: object_id << 1)
7
11
  end
8
12
  end
@@ -1,13 +1,21 @@
1
1
  # frozen_string_literal: true
2
- module Nano::NodeHelper
3
- include Nano::ApplicationHelper
2
+ module NanoRpc::NodeHelper
3
+ include NanoRpc::ApplicationHelper
4
4
 
5
5
  def account_containing_block(hash:)
6
6
  block_account(hash: hash).account
7
7
  end
8
8
 
9
+ def account(address)
10
+ NanoRpc::Account.new(address, node: self)
11
+ end
12
+
13
+ def accounts(addresses)
14
+ NanoRpc::Accounts.new(addresses, node: self)
15
+ end
16
+
9
17
  def create_wallet
10
- Nano::Wallet.new(wallet_create.wallet, client: client)
18
+ NanoRpc::Wallet.new(wallet_create.wallet, node: self)
11
19
  end
12
20
 
13
21
  def knano_from_raw(amount:)
@@ -46,6 +54,10 @@ module Nano::NodeHelper
46
54
  available_supply.available
47
55
  end
48
56
 
57
+ def wallet(seed)
58
+ NanoRpc::Wallet.new(seed, node: self)
59
+ end
60
+
49
61
  def work_valid?(work:, hash:)
50
62
  work_validate(work: work, hash: hash).valid == 1
51
63
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
- module Nano::WalletHelper
3
- include Nano::ApplicationHelper
2
+ module NanoRpc::WalletHelper
3
+ include NanoRpc::ApplicationHelper
4
4
 
5
5
  def account_work(account:)
6
6
  work_get(account: account).work
@@ -8,7 +8,7 @@ module Nano::WalletHelper
8
8
 
9
9
  def accounts
10
10
  return [] unless account_list.accounts.size.positive?
11
- Nano::Accounts.new(account_list.accounts, client: client)
11
+ NanoRpc::Accounts.new(account_list.accounts, node: node)
12
12
  end
13
13
 
14
14
  def add_key(key:, work: true)
@@ -49,12 +49,12 @@ module Nano::WalletHelper
49
49
 
50
50
  def create_account(work: true)
51
51
  address = account_create(work: work).account
52
- Nano::Account.new(address, client: client)
52
+ NanoRpc::Account.new(address, node: node)
53
53
  end
54
54
 
55
55
  def create_accounts(count:, work: true)
56
56
  addresses = accounts_create(count: count, work: work).accounts
57
- Nano::Accounts.new(addresses, client: client)
57
+ NanoRpc::Accounts.new(addresses, node: node)
58
58
  end
59
59
 
60
60
  def destroy
@@ -67,7 +67,7 @@ module Nano::WalletHelper
67
67
  alias unlock enter_password
68
68
 
69
69
  def export
70
- Nano::Response.new(JSON[wallet_export.json])
70
+ NanoRpc::Response.new(JSON[wallet_export.json])
71
71
  end
72
72
 
73
73
  def frontiers
@@ -79,7 +79,7 @@ module Nano::WalletHelper
79
79
  end
80
80
 
81
81
  def ledger
82
- wallet_ledger
82
+ wallet_ledger.accounts
83
83
  end
84
84
 
85
85
  def locked?
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+ require 'rest-client'
3
+ require 'json'
4
+
5
+ module NanoRpc
6
+ def self.node
7
+ @node ||= Node.new
8
+ end
9
+
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
22
+
23
+ super
24
+ end
25
+
26
+ # Condense host/port on object inspection
27
+ def inspect
28
+ "#{inspect_prefix}, @url=\"#{@host}:#{port}\">"
29
+ end
30
+
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)
36
+ end
37
+
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, required: %i[hash]
91
+ proxy_method :work_peer_add, required: %i[address port]
92
+ proxy_method :work_peers
93
+ proxy_method :work_peers_clear
94
+ proxy_method :work_validate, required: %i[work hash]
95
+
96
+ private
97
+
98
+ def extract_proxy_args(args)
99
+ args.each do |k, v|
100
+ m = proxy_method(v)
101
+ args[k] = v.send(m) if m
102
+ end
103
+ args
104
+ end
105
+
106
+ def proxy_method(obj)
107
+ if obj.is_a?(NanoRpc::Wallet)
108
+ :seed
109
+ elsif obj.is_a?(NanoRpc::Accounts)
110
+ :addresses
111
+ elsif obj.is_a?(NanoRpc::Account)
112
+ :address
113
+ end
114
+ end
115
+
116
+ def rpc_post(params)
117
+ response = rest_client_post(url, params)
118
+ ensure_status_success!(response)
119
+ data = NanoRpc::Response.new(JSON[response&.body])
120
+ ensure_valid_response!(data)
121
+
122
+ data
123
+ end
124
+
125
+ def request_headers
126
+ h = headers || {}
127
+ h['Content-Type'] = 'json'
128
+ h['Authorization'] = auth unless auth.nil?
129
+ h
130
+ end
131
+
132
+ def rest_client_post(url, params)
133
+ RestClient.post(url, params.to_json, request_headers)
134
+ rescue Errno::ECONNREFUSED
135
+ raise NanoRpc::NodeConnectionFailure,
136
+ "Node connection failure at #{url}"
137
+ rescue RestClient::Exceptions::OpenTimeout
138
+ raise NanoRpc::NodeOpenTimeout,
139
+ 'Node failed to respond in time'
140
+ end
141
+
142
+ def url
143
+ if host.start_with?('http://', 'https://')
144
+ "#{host}:#{port}"
145
+ else
146
+ "http://#{host}:#{port}"
147
+ end
148
+ end
149
+
150
+ def ensure_status_success!(response)
151
+ return if response&.code == 200
152
+ raise NanoRpc::BadRequest,
153
+ "Error response from node: #{JSON[response&.body]}"
154
+ end
155
+
156
+ def ensure_valid_response!(data)
157
+ return unless data['error']
158
+ raise NanoRpc::InvalidRequest,
159
+ "Invalid request: #{data['error']}"
160
+ end
161
+ end
162
+ end
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
- class Nano::Account
3
- include Nano::Proxy
4
- include Nano::AccountHelper
2
+ class NanoRpc::Account
3
+ include NanoRpc::Proxy
4
+ include NanoRpc::AccountHelper
5
5
 
6
6
  attr_reader :address
7
7
 
8
8
  def initialize(address = nil, opts = {})
9
9
  unless address.is_a?(String)
10
- raise Nano::MissingParameters,
10
+ raise NanoRpc::MissingParameters,
11
11
  'Missing argument: address (str)'
12
12
  end
13
13
 
@@ -33,7 +33,9 @@ class Nano::Account
33
33
  proxy_method :frontiers, required: %i[count]
34
34
  proxy_method :ledger,
35
35
  required: %i[count],
36
- optional: %i[representative weight pending modified_since sorting]
36
+ optional: %i[
37
+ representative weight pending modified_since sorting
38
+ ]
37
39
  proxy_method :validate_account_number
38
40
  proxy_method :pending, required: %i[count], optional: %i[threshold exists]
39
41
  proxy_method :payment_wait, required: %i[amount timeout]
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
- class Nano::Accounts
3
- include Nano::Proxy
4
- include Nano::AccountsHelper
2
+ class NanoRpc::Accounts
3
+ include NanoRpc::Proxy
4
+ include NanoRpc::AccountsHelper
5
5
 
6
6
  attr_reader :addresses
7
7
 
8
8
  def initialize(addresses = nil, opts = {})
9
9
  unless addresses.is_a?(Array)
10
- raise Nano::MissingParameters,
10
+ raise NanoRpc::MissingParameters,
11
11
  'Missing argument: addresses (str[])'
12
12
  end
13
13
 
@@ -19,7 +19,9 @@ class Nano::Accounts
19
19
 
20
20
  proxy_method :account_move, required: %i[wallet source]
21
21
  proxy_method :accounts_balances
22
- proxy_method :accounts_create, required: %i[wallet count], optional: %i[work]
22
+ proxy_method :accounts_create,
23
+ required: %i[wallet count],
24
+ optional: %i[work]
23
25
  proxy_method :accounts_frontiers
24
26
  proxy_method :accounts_pending,
25
27
  required: %i[count], optional: %i[threshold source]
@@ -1,14 +1,14 @@
1
1
  # frozen_string_literal: true
2
- class Nano::Wallet
3
- include Nano::Proxy
4
- include Nano::WalletHelper
2
+ class NanoRpc::Wallet
3
+ include NanoRpc::Proxy
4
+ include NanoRpc::WalletHelper
5
5
 
6
6
  attr_reader :seed
7
7
 
8
8
  def initialize(seed = nil, opts = {})
9
9
  unless seed.is_a?(String)
10
- raise Nano::MissingParameters,
11
- 'Missing argument: address (str)'
10
+ raise NanoRpc::MissingParameters,
11
+ 'Missing argument: seed (str)'
12
12
  end
13
13
 
14
14
  @seed = seed
@@ -17,7 +17,7 @@ class Nano::Wallet
17
17
 
18
18
  # Hide secret seed on object inspection
19
19
  def inspect
20
- "#{inspect_prefix}, @client=#{@client.inspect}>"
20
+ "#{inspect_prefix}, @node=#{@node.inspect}>"
21
21
  end
22
22
 
23
23
  proxy_params wallet: :seed
@@ -1,11 +1,9 @@
1
1
  # frozen_string_literal: true
2
- module Nano::Proxy
3
- include Nano::ApplicationHelper
4
-
5
- attr_accessor :client
2
+ module NanoRpc::Proxy
3
+ attr_reader :node
6
4
 
7
5
  def initialize(opts = {})
8
- @client = opts[:client] || Nano.client
6
+ @node ||= opts[:node] || NanoRpc.node
9
7
  self.class.proxy_methods&.each { |m| define_proxy_method(m) }
10
8
  end
11
9
 
@@ -35,9 +33,9 @@ module Nano::Proxy
35
33
 
36
34
  private
37
35
 
38
- def define_proxy_method(m)
39
- self.class.send(:define_method, method_alias(m)) do |args = {}|
40
- @m = m
36
+ def define_proxy_method(meth)
37
+ self.class.send(:define_method, method_alias(meth)) do |args = {}|
38
+ @meth = meth
41
39
  @call_args = args
42
40
 
43
41
  validate_params!
@@ -46,7 +44,7 @@ module Nano::Proxy
46
44
  end
47
45
 
48
46
  def execute_call
49
- expose_nested_data(@client.call(@m, @call_args))
47
+ expose_nested_data(node.call(@meth, @call_args))
50
48
  end
51
49
 
52
50
  def base_params
@@ -61,13 +59,16 @@ module Nano::Proxy
61
59
  end
62
60
 
63
61
  # Nano `send` action is also the method caller in Ruby ;)
64
- def method_alias(m)
65
- m == :send ? :send_currency : m
62
+ def method_alias(meth)
63
+ meth == :send ? :send_currency : meth
66
64
  end
67
65
 
68
66
  # If single-key response matches method name, expose nested data
69
67
  def expose_nested_data(data)
70
- data.is_a?(Hash) && data.keys.map(&:to_s) == [@m.to_s] ? data[@m] : data
68
+ if data.is_a?(Hash) && data.keys.map(&:to_s) == [@meth.to_s]
69
+ return data[@meth]
70
+ end
71
+ data
71
72
  end
72
73
 
73
74
  def validate_params!
@@ -91,14 +92,14 @@ module Nano::Proxy
91
92
  def ensure_required_params!
92
93
  missing_params = required_params - opts_keys
93
94
  return unless missing_params.any?
94
- raise Nano::MissingParameters,
95
+ raise NanoRpc::MissingParameters,
95
96
  "Missing required parameter(s): #{missing_params.join(', ')}"
96
97
  end
97
98
 
98
99
  def prevent_forbidden_params!
99
100
  forbidden_params = base_param_keys + opts_keys - allowed_params
100
101
  return unless forbidden_params.any?
101
- raise Nano::ForbiddenParameter,
102
+ raise NanoRpc::ForbiddenParameter,
102
103
  "Forbidden parameter(s) passed: #{forbidden_params.join(', ')}"
103
104
  end
104
105
 
@@ -115,13 +116,13 @@ module Nano::Proxy
115
116
  end
116
117
 
117
118
  def required_params
118
- return [] unless method_def && method_def[@m]
119
- method_def[@m][:required] || []
119
+ return [] unless method_def && method_def[@meth]
120
+ method_def[@meth][:required] || []
120
121
  end
121
122
 
122
123
  def optional_params
123
- return [] unless method_def && method_def[@m]
124
- method_def[@m][:optional] || []
124
+ return [] unless method_def && method_def[@meth]
125
+ method_def[@meth][:optional] || []
125
126
  end
126
127
 
127
128
  def base_param_keys
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  require 'hashie'
3
3
 
4
- class Nano::Response < Hash
4
+ class NanoRpc::Response < Hash
5
5
  include ::Hashie::Extensions::MergeInitializer
6
6
  include ::Hashie::Extensions::IndifferentAccess
7
7
  include ::Hashie::Extensions::MethodAccess
@@ -17,15 +17,15 @@ class Nano::Response < Hash
17
17
  merge!(self) { |_k, v| to_f_or_i_or_s(v) }
18
18
  end
19
19
 
20
- def to_f_or_i_or_s(v)
21
- return if v.nil?
22
- return v.to_i if big_integer?(v)
23
- (float = Float(v)) && (float % 1.0).zero? ? float.to_i : float
20
+ def to_f_or_i_or_s(val)
21
+ return if val.nil?
22
+ return val.to_i if big_integer?(val)
23
+ (float = Float(val)) && (float % 1.0).zero? ? float.to_i : float
24
24
  rescue ArgumentError, TypeError
25
- v
25
+ val
26
26
  end
27
27
 
28
- def big_integer?(v)
29
- v.respond_to?(:to_i) && v.to_i > 1_000_000_000_000_000
28
+ def big_integer?(val)
29
+ val.respond_to?(:to_i) && val.to_i > 1_000_000_000_000_000
30
30
  end
31
31
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
- module Nano
3
- VERSION = '0.9.0'
2
+ module NanoRpc
3
+ VERSION = '0.10.0'
4
4
  end
data/lib/nano_rpc.rb CHANGED
@@ -1,15 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
  require 'nano_rpc/version'
3
+
3
4
  require 'nano_rpc/helpers/application_helper'
4
5
  require 'nano_rpc/helpers/account_helper'
5
6
  require 'nano_rpc/helpers/accounts_helper'
6
7
  require 'nano_rpc/helpers/node_helper'
7
8
  require 'nano_rpc/helpers/wallet_helper'
8
- require 'nano_rpc/client'
9
- require 'nano_rpc/errors'
9
+
10
10
  require 'nano_rpc/proxy'
11
+ require 'nano_rpc/node'
12
+ require 'nano_rpc/errors'
11
13
  require 'nano_rpc/response'
12
14
  require 'nano_rpc/proxies/account'
13
15
  require 'nano_rpc/proxies/accounts'
14
- require 'nano_rpc/proxies/node'
15
16
  require 'nano_rpc/proxies/wallet'
data/nano_rpc.gemspec CHANGED
@@ -5,7 +5,7 @@ require 'nano_rpc/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'nano_rpc'
8
- spec.version = Nano::VERSION
8
+ spec.version = NanoRpc::VERSION
9
9
  spec.authors = ['Justin Craig-Kuhn (JCK)']
10
10
  spec.email = ['jcraigk@gmail.com']
11
11
 
@@ -23,12 +23,12 @@ Gem::Specification.new do |spec|
23
23
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
24
  spec.require_paths = %w[lib]
25
25
 
26
- spec.add_development_dependency 'bundler', '~> 1.16'
26
+ spec.add_development_dependency 'bundler', '~> 1.16.1'
27
27
  spec.add_development_dependency 'pry', '~> 0.11.3'
28
- spec.add_development_dependency 'rake', '~> 10.0'
29
- spec.add_development_dependency 'rspec', '~> 3.0'
30
- spec.add_development_dependency 'rubocop', '~> 0.52.1'
31
- spec.add_development_dependency 'simplecov', '~> 0.15.1'
28
+ spec.add_development_dependency 'rake', '~> 12.3.1'
29
+ spec.add_development_dependency 'rspec', '~> 3.7.0'
30
+ spec.add_development_dependency 'rubocop', '~> 0.56.0'
31
+ spec.add_development_dependency 'simplecov', '~> 0.16.1'
32
32
 
33
33
  spec.add_runtime_dependency 'hashie', '~> 3.5', '>= 3.5.7'
34
34
  spec.add_runtime_dependency 'rest-client', '~> 2.0', '>= 2.0.2'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nano_rpc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Craig-Kuhn (JCK)
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-05-11 00:00:00.000000000 Z
11
+ date: 2018-05-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.16'
19
+ version: 1.16.1
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.16'
26
+ version: 1.16.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: pry
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -44,56 +44,56 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '10.0'
47
+ version: 12.3.1
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '10.0'
54
+ version: 12.3.1
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '3.0'
61
+ version: 3.7.0
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '3.0'
68
+ version: 3.7.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rubocop
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 0.52.1
75
+ version: 0.56.0
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 0.52.1
82
+ version: 0.56.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: simplecov
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 0.15.1
89
+ version: 0.16.1
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 0.15.1
96
+ version: 0.16.1
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: hashie
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -152,16 +152,15 @@ files:
152
152
  - bin/console
153
153
  - bin/setup
154
154
  - lib/nano_rpc.rb
155
- - lib/nano_rpc/client.rb
156
155
  - lib/nano_rpc/errors.rb
157
156
  - lib/nano_rpc/helpers/account_helper.rb
158
157
  - lib/nano_rpc/helpers/accounts_helper.rb
159
158
  - lib/nano_rpc/helpers/application_helper.rb
160
159
  - lib/nano_rpc/helpers/node_helper.rb
161
160
  - lib/nano_rpc/helpers/wallet_helper.rb
161
+ - lib/nano_rpc/node.rb
162
162
  - lib/nano_rpc/proxies/account.rb
163
163
  - lib/nano_rpc/proxies/accounts.rb
164
- - lib/nano_rpc/proxies/node.rb
165
164
  - lib/nano_rpc/proxies/wallet.rb
166
165
  - lib/nano_rpc/proxy.rb
167
166
  - lib/nano_rpc/response.rb
@@ -1,100 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'rest-client'
3
- require 'json'
4
-
5
- module Nano
6
- def self.client
7
- @client ||= Client.new
8
- end
9
-
10
- class Client
11
- include Nano::ApplicationHelper
12
-
13
- attr_reader :host, :port, :auth, :headers
14
-
15
- def initialize(host: 'localhost', port: 7076, auth: nil, headers: nil)
16
- @host = host
17
- @port = port
18
- @auth = auth
19
- @headers = headers
20
- end
21
-
22
- # Condense host/port on object inspection
23
- def inspect
24
- "#{inspect_prefix}, @url=\"#{@host}:#{port}\">"
25
- end
26
-
27
- def call(action, params = {})
28
- args = { action: action }
29
- args.merge!(params) if params.is_a?(Hash)
30
- args = extract_proxy_args(args)
31
- rpc_post(args)
32
- end
33
-
34
- private
35
-
36
- def extract_proxy_args(args)
37
- args.each do |k, v|
38
- m = proxy_method(v)
39
- args[k] = v.send(m) if m
40
- end
41
- args
42
- end
43
-
44
- def proxy_method(v)
45
- if v.is_a?(Nano::Wallet)
46
- :seed
47
- elsif v.is_a?(Nano::Accounts)
48
- :addresses
49
- elsif v.is_a?(Nano::Account)
50
- :address
51
- end
52
- end
53
-
54
- def rpc_post(params)
55
- response = rest_client_post(url, params)
56
- ensure_status_success!(response)
57
- data = Nano::Response.new(JSON[response&.body])
58
- ensure_valid_response!(data)
59
-
60
- data
61
- end
62
-
63
- def request_headers
64
- h = headers || {}
65
- h['Content-Type'] = 'json'
66
- h['Authorization'] = auth unless auth.nil?
67
- h
68
- end
69
-
70
- def rest_client_post(url, params)
71
- RestClient.post(url, params.to_json, request_headers)
72
- rescue Errno::ECONNREFUSED
73
- raise Nano::NodeConnectionFailure,
74
- "Node connection failure at #{url}"
75
- rescue RestClient::Exceptions::OpenTimeout
76
- raise Nano::NodeOpenTimeout,
77
- 'Node failed to respond in time'
78
- end
79
-
80
- def url
81
- if host.start_with?('http://', 'https://')
82
- "#{host}:#{port}"
83
- else
84
- "http://#{host}:#{port}"
85
- end
86
- end
87
-
88
- def ensure_status_success!(response)
89
- return if response&.code == 200
90
- raise Nano::BadRequest,
91
- "Error response from node: #{JSON[response&.body]}"
92
- end
93
-
94
- def ensure_valid_response!(data)
95
- return unless data['error']
96
- raise Nano::InvalidRequest,
97
- "Invalid request: #{data['error']}"
98
- end
99
- end
100
- end
@@ -1,63 +0,0 @@
1
- # frozen_string_literal: true
2
- class Nano::Node
3
- include Nano::Proxy
4
- include Nano::NodeHelper
5
-
6
- proxy_method :available_supply
7
- proxy_method :block, required: %i[hash]
8
- proxy_method :block_account, required: %i[hash]
9
- proxy_method :block_confirm, required: %i[hash]
10
- proxy_method :block_count
11
- proxy_method :block_count_type
12
- proxy_method :block_create,
13
- required: %i[type key representative source],
14
- optional: %i[work]
15
- proxy_method :blocks, required: %i[hashes]
16
- proxy_method :blocks_info,
17
- required: %i[hashes],
18
- optional: %i[pending source balance]
19
- proxy_method :bootstrap, required: %i[address port]
20
- proxy_method :bootstrap_any
21
- proxy_method :chain, required: %i[block count]
22
- proxy_method :confirmation_history
23
- proxy_method :deterministic_key, required: %i[seed index]
24
- proxy_method :frontier_count
25
- proxy_method :history, required: %i[hash count]
26
- proxy_method :keepalive, required: %i[address port]
27
- proxy_method :key_create
28
- proxy_method :key_expand, required: %i[key]
29
- proxy_method :krai_from_raw, required: %i[amount]
30
- proxy_method :krai_to_raw, required: %i[amount]
31
- proxy_method :mrai_from_raw, required: %i[amount]
32
- proxy_method :mrai_to_raw, required: %i[amount]
33
- proxy_method :payment_wait, required: %i[account amount timeout]
34
- proxy_method :peers
35
- proxy_method :pending_exists, required: %i[hash]
36
- proxy_method :process, required: %i[block]
37
- proxy_method :rai_from_raw, required: %i[amount]
38
- proxy_method :rai_to_raw, required: %i[amount]
39
- proxy_method :receive_minimum
40
- proxy_method :receive_minimum_set, required: %i[amount]
41
- proxy_method :representatives
42
- proxy_method :representatives_online
43
- proxy_method :republish,
44
- required: %i[hash],
45
- optional: %i[count sources destinations]
46
- proxy_method :search_pending, required: %i[wallet]
47
- proxy_method :search_pending_all
48
- proxy_method :stats, required: %i[type]
49
- proxy_method :stop
50
- proxy_method :successors, required: %i[block count]
51
- proxy_method :unchecked, required: %i[count]
52
- proxy_method :unchecked_clear
53
- proxy_method :unchecked_get, required: %i[hash]
54
- proxy_method :unchecked_keys, required: %i[key count]
55
- proxy_method :version
56
- proxy_method :wallet_create
57
- proxy_method :work_cancel, required: %i[hash]
58
- proxy_method :work_generate, required: %i[hash]
59
- proxy_method :work_peer_add, required: %i[address port]
60
- proxy_method :work_peers
61
- proxy_method :work_peers_clear
62
- proxy_method :work_validate, required: %i[work hash]
63
- end