raiblocks_rpc 0.3.0 → 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.
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+ module Raiblocks::Proxy
3
+ attr_accessor :client
4
+
5
+ def initialize(opts = {})
6
+ @client = opts[:client] || Raiblocks.client
7
+ end
8
+
9
+ def self.included(base)
10
+ base.extend(ClassMethods)
11
+ end
12
+ module ClassMethods
13
+ attr_reader :proxy_method_def, :proxy_param_def
14
+
15
+ def proxy_params(param_def = nil)
16
+ @proxy_param_def = param_def
17
+ end
18
+
19
+ def proxy_method(name, signature = nil)
20
+ @proxy_method_def ||= {}
21
+ @proxy_method_def[name] = signature
22
+ end
23
+
24
+ def proxy_methods
25
+ proxy_method_def.keys.sort
26
+ end
27
+
28
+ def methods
29
+ (super + proxy_methods).sort
30
+ end
31
+
32
+ def define_proxy_method(m, singleton = false)
33
+ send(
34
+ singleton ? :define_singleton_method : :define_method,
35
+ method_alias(m)
36
+ ) do |opts = {}|
37
+ params = Raiblocks::ProxyContext.new(
38
+ singleton ? self : self.class, m, opts
39
+ ).populate_params(singleton ? nil : base_params)
40
+ data = Raiblocks.client.call(m, params)
41
+ data.is_a?(Hash) && data.keys.map(&:to_s) == [m.to_s] ? data[m] : data
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ # Raiblocks `send` action is also the method caller in Ruby ;)
48
+ def method_alias(m)
49
+ m == :send ? :tx_send : m
50
+ end
51
+
52
+ def method_missing(m, *args, &_block)
53
+ return super unless valid_method?(m)
54
+ define_proxy_method(m, true)
55
+ send(m, args.first)
56
+ end
57
+
58
+ def respond_to_missing?(m, include_private = false)
59
+ valid_method?(m) || super
60
+ end
61
+
62
+ def valid_method?(m)
63
+ proxy_param_def.nil? && methods.include?(m)
64
+ end
65
+
66
+ def proxy_context(m)
67
+ @proxy_context ||= {}
68
+ @proxy_context[m] ||= Raiblocks::ProxyContext.new(self, m)
69
+ end
70
+ end
71
+
72
+ def proxy_methods
73
+ self.class.proxy_methods
74
+ end
75
+
76
+ def methods
77
+ (super + proxy_methods).sort
78
+ end
79
+
80
+ private
81
+
82
+ def base_params
83
+ return if self.class.proxy_param_def.nil?
84
+ self.class
85
+ .proxy_param_def
86
+ .each_with_object({}) do |(k, v), params|
87
+ params[k] ||= send(v)
88
+ end
89
+ end
90
+
91
+ def method_missing(m, *args, &_block)
92
+ return super unless methods.include?(m)
93
+ self.class.define_proxy_method(m)
94
+ send(m, args.first)
95
+ end
96
+
97
+ def respond_to_missing?(m, include_private = false)
98
+ methods.include?(m) || super
99
+ end
100
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+ class Raiblocks::ProxyContext
3
+ def initialize(klass, m, opts = {})
4
+ @klass = klass
5
+ @method_def = klass.proxy_method_def
6
+ @param_def = klass.proxy_param_def
7
+ @m = m
8
+ @opts = opts
9
+ end
10
+
11
+ def valid_proxy_method?
12
+ rpc_action?
13
+ end
14
+
15
+ def populate_params(params)
16
+ opts = validate_opts!
17
+ opts.merge!(params) if params
18
+ validate_params!
19
+ opts.delete_if { |_k, v| v.nil? }
20
+ opts
21
+ end
22
+
23
+ def validate_opts!
24
+ return @opts if @opts.is_a?(Hash)
25
+ return {} if @opts.nil?
26
+ raise Raiblocks::InvalidParameterType,
27
+ 'You must pass a hash to an action method'
28
+ end
29
+
30
+ def validate_params!
31
+ ensure_required_params!
32
+ ensure_no_forbidden_params!
33
+ end
34
+
35
+ def ensure_required_params!
36
+ missing_params = required_params - opts_keys
37
+ return unless missing_params.any?
38
+ raise Raiblocks::MissingParameters,
39
+ "Missing required parameter(s): #{missing_params.join(', ')}"
40
+ end
41
+
42
+ def ensure_no_forbidden_params!
43
+ forbidden_params = base_param_keys + opts_keys - allowed_params
44
+ return unless forbidden_params.any?
45
+ raise Raiblocks::ForbiddenParameter,
46
+ "Forbidden parameter(s) passed: #{forbidden_params.join(', ')}"
47
+ end
48
+
49
+ private
50
+
51
+ def opts_keys
52
+ @opts.nil? ? [] : @opts.keys
53
+ end
54
+
55
+ def allowed_params
56
+ base_param_keys + required_params + optional_params
57
+ end
58
+
59
+ def required_params
60
+ return [] unless @method_def && @method_def[@m]
61
+ @method_def[@m][:required]
62
+ end
63
+
64
+ def optional_params
65
+ return [] unless @method_def && @method_def[@m]
66
+ @method_def[@m][:optional]
67
+ end
68
+
69
+ def base_param_keys
70
+ @param_def.is_a?(Hash) ? @param_def.keys : []
71
+ end
72
+
73
+ def method_expansion
74
+ "#{action_prefix}#{@m}"
75
+ end
76
+
77
+ def action_prefix
78
+ @klass.name.split('::').last.downcase + '_'
79
+ end
80
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+ require 'hashie'
3
+
4
+ class Raiblocks::Response < Hash
5
+ include ::Hashie::Extensions::MergeInitializer
6
+ include ::Hashie::Extensions::IndifferentAccess
7
+ include ::Hashie::Extensions::MethodAccess
8
+
9
+ def initialize(hash = {})
10
+ super
11
+ coerce_values
12
+ end
13
+
14
+ private
15
+
16
+ def coerce_values
17
+ merge!(self) { |_k, v| to_f_or_i_or_s(v) }
18
+ end
19
+
20
+ def to_f_or_i_or_s(v)
21
+ (float = Float(v)) && (float % 1.0).zero? ? float.to_i : float
22
+ rescue ArgumentError, TypeErrror
23
+ v
24
+ end
25
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+ module Raiblocks
3
+ VERSION = '0.4.0'
4
+ end
data/lib/raiblocks_rpc.rb CHANGED
@@ -1,18 +1,15 @@
1
1
  # frozen_string_literal: true
2
- require 'raiblocks_rpc/version'
3
- require 'raiblocks_rpc/client'
4
- require 'raiblocks_rpc/errors'
5
- require 'raiblocks_rpc/proxy'
6
- require 'raiblocks_rpc/response'
7
- require 'raiblocks_rpc/proxies/account'
8
- require 'raiblocks_rpc/proxies/accounts'
9
- require 'raiblocks_rpc/proxies/network'
10
- require 'raiblocks_rpc/proxies/node'
11
- require 'raiblocks_rpc/proxies/util'
12
- require 'raiblocks_rpc/proxies/wallet'
13
-
14
- module RaiblocksRpc
15
- def self.client
16
- @client ||= Client.new
17
- end
18
- end
2
+ require 'raiblocks/version'
3
+ require 'raiblocks/client'
4
+ require 'raiblocks/errors'
5
+ require 'raiblocks/proxy'
6
+ require 'raiblocks/proxy_context'
7
+ require 'raiblocks/response'
8
+ require 'raiblocks/helpers/account_proxy_helper'
9
+ require 'raiblocks/helpers/accounts_proxy_helper'
10
+ require 'raiblocks/helpers/node_proxy_helper'
11
+ require 'raiblocks/helpers/wallet_proxy_helper'
12
+ require 'raiblocks/proxies/account'
13
+ require 'raiblocks/proxies/accounts'
14
+ require 'raiblocks/proxies/node'
15
+ require 'raiblocks/proxies/wallet'
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'raiblocks_rpc/version'
4
+ require 'raiblocks/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'raiblocks_rpc'
8
- spec.version = RaiblocksRpc::VERSION
8
+ spec.version = Raiblocks::VERSION
9
9
  spec.authors = ['Justin Craig-Kuhn (JCK)']
10
10
  spec.email = ['jcraigk@gmail.com']
11
11
 
@@ -29,8 +29,8 @@ Gem::Specification.new do |spec|
29
29
  spec.add_development_dependency 'pry', '~> 0.11.3'
30
30
  spec.add_development_dependency 'rake', '~> 10.0'
31
31
  spec.add_development_dependency 'rspec', '~> 3.0'
32
- spec.add_development_dependency 'simplecov', '~> 0.15.1'
33
32
  spec.add_development_dependency 'rubocop', '~> 0.52.1'
33
+ spec.add_development_dependency 'simplecov', '~> 0.15.1'
34
34
 
35
35
  spec.add_runtime_dependency 'hashie', '~> 3.5', '>= 3.5.7'
36
36
  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: raiblocks_rpc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.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-01-22 00:00:00.000000000 Z
11
+ date: 2018-01-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -67,33 +67,33 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '3.0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: simplecov
70
+ name: rubocop
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 0.15.1
75
+ version: 0.52.1
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.15.1
82
+ version: 0.52.1
83
83
  - !ruby/object:Gem::Dependency
84
- name: rubocop
84
+ name: simplecov
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 0.52.1
89
+ version: 0.15.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.52.1
96
+ version: 0.15.1
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: hashie
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -152,18 +152,21 @@ files:
152
152
  - Rakefile
153
153
  - bin/console
154
154
  - bin/setup
155
+ - lib/raiblocks/client.rb
156
+ - lib/raiblocks/errors.rb
157
+ - lib/raiblocks/helpers/account_proxy_helper.rb
158
+ - lib/raiblocks/helpers/accounts_proxy_helper.rb
159
+ - lib/raiblocks/helpers/node_proxy_helper.rb
160
+ - lib/raiblocks/helpers/wallet_proxy_helper.rb
161
+ - lib/raiblocks/proxies/account.rb
162
+ - lib/raiblocks/proxies/accounts.rb
163
+ - lib/raiblocks/proxies/node.rb
164
+ - lib/raiblocks/proxies/wallet.rb
165
+ - lib/raiblocks/proxy.rb
166
+ - lib/raiblocks/proxy_context.rb
167
+ - lib/raiblocks/response.rb
168
+ - lib/raiblocks/version.rb
155
169
  - lib/raiblocks_rpc.rb
156
- - lib/raiblocks_rpc/client.rb
157
- - lib/raiblocks_rpc/errors.rb
158
- - lib/raiblocks_rpc/proxies/account.rb
159
- - lib/raiblocks_rpc/proxies/accounts.rb
160
- - lib/raiblocks_rpc/proxies/network.rb
161
- - lib/raiblocks_rpc/proxies/node.rb
162
- - lib/raiblocks_rpc/proxies/util.rb
163
- - lib/raiblocks_rpc/proxies/wallet.rb
164
- - lib/raiblocks_rpc/proxy.rb
165
- - lib/raiblocks_rpc/response.rb
166
- - lib/raiblocks_rpc/version.rb
167
170
  - raiblocks_rpc.gemspec
168
171
  homepage: https://github.com/jcraigk/ruby_raiblocks_rpc
169
172
  licenses:
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'singleton'
3
- require 'rest-client'
4
- require 'json'
5
-
6
- class RaiblocksRpc::Client
7
- attr_accessor :host, :port
8
-
9
- def initialize(host: 'localhost', port: 7076)
10
- @host = host
11
- @port = port
12
- end
13
-
14
- def call(action, params = {})
15
- post({ action: action }.merge(params))
16
- end
17
-
18
- private
19
-
20
- def post(params)
21
- response = RestClient.post(url, params.to_json)
22
- ensure_status_success!(response)
23
-
24
- data = RaiblocksRpc::Response.new(JSON[response.body])
25
- ensure_valid_response!(data)
26
-
27
- data
28
- end
29
-
30
- def url
31
- "http://#{host}:#{port}"
32
- end
33
-
34
- def ensure_status_success!(response)
35
- return if response.code == 200
36
- raise RaiblocksRpc::BadRequest,
37
- "Error response from node: #{JSON[response.body]}"
38
- end
39
-
40
- def ensure_valid_response!(data)
41
- return unless data['error']
42
- raise RaiblocksRpc::InvalidRequest,
43
- "Invalid request: #{data['error']}"
44
- end
45
- end
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
- class RaiblocksRpc::Account < RaiblocksRpc::Proxy
3
- attr_accessor :address
4
-
5
- def initialize(address)
6
- unless address
7
- raise RaiblocksRpc::MissingArguments,
8
- 'Missing argument: address (str)'
9
- end
10
-
11
- self.address = address
12
- end
13
-
14
- def proxy_params
15
- { account: :address }
16
- end
17
-
18
- def proxy_methods
19
- {
20
- account_balance: nil,
21
- account_block_count: nil,
22
- account_info: nil,
23
- account_create: { required: %i[wallet] },
24
- account_history: { required: %i[count] },
25
- account_list: nil,
26
- account_move: { required: %i[wallet source accounts] },
27
- account_key: nil,
28
- account_remove: { required: %i[wallet] },
29
- account_representative: nil,
30
- account_representative_set: { required: %i[wallet representative] },
31
- account_weight: nil,
32
- delegators: nil,
33
- delegators_count: nil,
34
- frontiers: { required: %i[count] },
35
- frontier_count: nil,
36
- ledger: { required: %i[count] },
37
- validate_account_number: nil,
38
- pending: { required: %i[count], optional: %i[threshold exists] },
39
- payment_wait: { required: %i[amount timeout] },
40
- accounts_balances: { required: %i[accounts] },
41
- accounts_create: {
42
- required: %i[accounts wallet count], optional: %i[work]
43
- },
44
- accounts_frontiers: { required: %i[accounts] },
45
- accounts_pending: {
46
- required: %i[accounts count], optional: %i[threshold source]
47
- }
48
- }
49
- end
50
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
- class RaiblocksRpc::Accounts < RaiblocksRpc::Proxy
3
- attr_accessor :addresses
4
-
5
- def initialize(addresses)
6
- unless addresses.is_a?(Array)
7
- raise RaiblocksRpc::MissingArguments,
8
- 'Missing argument: addresses (str[])'
9
- end
10
-
11
- self.addresses = addresses
12
- end
13
-
14
- def proxy_params
15
- { accounts: :addresses }
16
- end
17
-
18
- def proxy_methods
19
- {
20
- accounts_balances: nil,
21
- accounts_create: { required: %i[wallet count], optional: %i[work] },
22
- accounts_frontiers: nil,
23
- accounts_pending: { required: %i[count], optional: %i[threshold source] }
24
- }
25
- end
26
-
27
- # TODO implement ability to instantiate Account instances like
28
- # accounts = Accounts.new(['abc', 'def'])
29
- # accounts.first
30
- # => RaiblocksRpc::Account address='abc'
31
- # [], each (more iterators?)
32
- end
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
- class RaiblocksRpc::Network < RaiblocksRpc::Proxy
3
- def proxy_methods
4
- {
5
- available_supply: nil,
6
- block: { required: %i[hash] },
7
- blocks: { required: %i[hashes] },
8
- blocks_info: { required: %i[hashes], optional: %i[pending source] },
9
- block_account: { required: %i[hash] },
10
- block_count: nil,
11
- block_count_type: nil,
12
- chain: { required: %i[block count] },
13
- history: { required: %i[hash count] },
14
- block_create: {
15
- required: %i[type key representative source], optional: %i[work]
16
- },
17
- process: { required: %i[block] },
18
- republish: {
19
- required: %i[hash], optional: %i[count sources destinations]
20
- },
21
- successors: { required: %i[block count] },
22
- pending_exists: { required: %i[hash] },
23
- unchecked: { required: %i[count] },
24
- unchecked_clear: nil,
25
- unchecked_get: { required: %i[hash] },
26
- unchecked_keys: { required: %i[key count] },
27
- work_cancel: { required: %i[hash] },
28
- work_generate: { required: %i[hash] },
29
- payment_wait: { required: %i[account amount timeout] },
30
- work_validate: { required: %i[work hash] },
31
- bootstrap: { required: %i[address port] },
32
- keepalive: { required: %i[address port] },
33
- work_peer_add: { required: %i[address port] },
34
- bootstrap_any: nil
35
- }
36
- end
37
- end
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
- class RaiblocksRpc::Node < RaiblocksRpc::Proxy
3
- def proxy_methods
4
- {
5
- bootstrap: { required: %i[address port] },
6
- bootstrap_any: nil,
7
- keepalive: { required: %i[address port] },
8
- work_peer_add: { required: %i[address port] },
9
- deterministic_key: { required: %i[seed index] },
10
- receive_minimum: nil,
11
- receive_minimum_set: { required: %i[amount] },
12
- representatives: nil,
13
- stop: nil,
14
- version: nil,
15
- peers: nil,
16
- work_peers: nil,
17
- work_peers_clear: nil,
18
- work_validate: { required: %i[work hash] },
19
- search_pending: { required: %i[wallet] },
20
- search_pending_all: nil,
21
- available_supply: nil,
22
- block: { required: %i[hash] },
23
- blocks: { required: %i[hashes] },
24
- blocks_info: { required: %i[hashes], optional: %i[pending source] },
25
- block_account: { required: %i[hash] },
26
- block_count: nil,
27
- block_count_type: nil,
28
- unchecked: { required: %i[count] },
29
- unchecked_clear: nil,
30
- unchecked_get: { required: %i[hash] },
31
- unchecked_keys: { required: %i[key count] },
32
- payment_wait: { required: %i[account amount timeout] }
33
- }
34
- end
35
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
- class RaiblocksRpc::Util < RaiblocksRpc::Proxy
3
- def proxy_methods
4
- {
5
- mrai_from_raw: { required: %i[amount] },
6
- mrai_to_raw: { required: %i[amount] },
7
- krai_from_raw: { required: %i[amount] },
8
- krai_to_raw: { required: %i[amount] },
9
- rai_from_raw: { required: %i[amount] },
10
- rai_to_raw: { required: %i[amount] },
11
- key_create: nil,
12
- key_expand: { required: %i[key] },
13
- work_validate: { required: %i[work hash] }
14
- }
15
- end
16
- end
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
- class RaiblocksRpc::Wallet < RaiblocksRpc::Proxy
3
- attr_accessor :seed
4
-
5
- def initialize(wallet_seed)
6
- unless wallet_address.is_a?(String) || public_key.is_a?(Symbol)
7
- raise RaiblocksRpc::MissingArguments,
8
- 'Missing argument: wallet_seed (str)'
9
- end
10
-
11
- self.seed = wallet_seed
12
- end
13
-
14
- def proxy_params
15
- { wallet: :seed }
16
- end
17
-
18
- def proxy_methods
19
- {
20
- wallet_balances: nil,
21
- wallet_add: { required: %i[key], optional: %i[work] },
22
- password_change: { required: %i[password] },
23
- wallet_change_seed: { required: %i[seed] },
24
- wallet_contains: { required: %i[account] },
25
- wallet_create: nil,
26
- wallet_destroy: nil,
27
- wallet_export: nil,
28
- wallet_frontiers: nil,
29
- wallet_locked: nil,
30
- password_enter: { required: %i[password] },
31
- wallet_pending: { required: %i[count], optional: %i[threshold source] },
32
- wallet_republish: { required: %i[count] },
33
- wallet_balance_total: nil,
34
- password_valid: nil,
35
- wallet_work_get: nil,
36
- send: { required: %[wallet source destination amount] },
37
- work_get: nil,
38
- work_set: nil,
39
- search_pending: nil,
40
- wallet_representative: nil,
41
- wallet_representative_set: %i[representative],
42
- payment_begin: nil,
43
- payment_init: nil,
44
- payment_end: { required: %i[account] },
45
- receive: { required: %i[account block] }
46
- }
47
- end
48
- end