nanook 2.4.0 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,10 @@
1
- class Nanook
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'util'
2
4
 
3
- # The <tt>Nanook::WalletAccount</tt> class lets you manage your nano accounts,
4
- # including paying and receiving payment.
5
+ class Nanook
6
+ # The <tt>Nanook::WalletAccount</tt> class lets you manage your nano accounts
7
+ # that are on your node, including paying and receiving payment.
5
8
  #
6
9
  # === Initializing
7
10
  #
@@ -14,17 +17,27 @@ class Nanook
14
17
  # rpc_conn = Nanook::Rpc.new
15
18
  # account = Nanook::WalletAccount.new(rpc_conn, wallet_id, account_id)
16
19
  class WalletAccount
17
-
20
+ include Nanook::Util
18
21
  extend Forwardable
22
+ # @!method ==
23
+ # (see Nanook::Account#==)
19
24
  # @!method balance(unit: Nanook.default_unit)
20
25
  # (see Nanook::Account#balance)
21
26
  # @!method block_count
22
27
  # (see Nanook::Account#block_count)
28
+ # @!method blocks(limit: 1000, sort: :desc)
29
+ # (see Nanook::Account#blocks)
23
30
  # @!method delegators(unit: Nanook.default_unit)
24
31
  # (see Nanook::Account#delegators)
32
+ # @!method delegators_count
33
+ # (see Nanook::Account#delegators_count)
34
+ # @!method eql?
35
+ # (see Nanook::Account#eql?)
25
36
  # @!method exists?
26
37
  # (see Nanook::Account#exists?)
27
- # @!method history(limit: 1000, unit: Nanook.default_unit)
38
+ # @!method hash
39
+ # (see Nanook::Account#hash)
40
+ # @!method history(limit: 1000, unit: Nanook.default_unit, sort: :desc)
28
41
  # (see Nanook::Account#history)
29
42
  # @!method id
30
43
  # (see Nanook::Account#id)
@@ -32,8 +45,10 @@ class Nanook
32
45
  # (see Nanook::Account#info)
33
46
  # @!method last_modified_at
34
47
  # (see Nanook::Account#last_modified_at)
35
- # @!method ledger(limit: 1, modified_since: nil, unit: Nanook.default_unit)
48
+ # @!method ledger(limit: 1, modified_since: nil, unit: Nanook.default_unit, sort: :desc)
36
49
  # (see Nanook::Account#ledger)
50
+ # @!method open_block
51
+ # (see Nanook::Account#open_block)
37
52
  # @!method pending(limit: 1000, detailed: false, unit: Nanook.default_unit)
38
53
  # (see Nanook::Account#pending)
39
54
  # @!method public_key
@@ -42,26 +57,45 @@ class Nanook
42
57
  # (see Nanook::Account#representative)
43
58
  # @!method weight
44
59
  # (see Nanook::Account#weight)
45
- def_delegators :@nanook_account_instance, :balance, :delegators, :exists?, :history, :id, :info, :last_modified_at, :ledger, :pending, :public_key, :representative, :weight
46
- alias_method :open?, :exists?
60
+ def_delegators :@nanook_account_instance,
61
+ :==, :balance, :block_count, :blocks, :delegators, :delegators_count,
62
+ :eql?, :exists?, :hash, :history, :id, :info, :last_modified_at, :ledger,
63
+ :open_block, :pending, :public_key, :representative, :weight
64
+ alias open? exists?
47
65
 
48
- def initialize(rpc, wallet, account)
66
+ def initialize(rpc, wallet, account = nil)
49
67
  @rpc = rpc
50
- @wallet = wallet
51
- @account = account
68
+ @wallet = wallet.to_s
69
+ @account = account.to_s if account
70
+
71
+ # Initialize an instance to delegate the RPC commands that do not
72
+ # need `enable_control` enabled (the read-only RPC commands).
52
73
  @nanook_account_instance = nil
53
74
 
54
- unless @account.nil?
55
- # Wallet must contain the account
56
- unless Nanook::Wallet.new(@rpc, @wallet).contains?(@account)
57
- raise ArgumentError.new("Account does not exist in wallet. Account: #{@account}, wallet: #{@wallet}")
58
- end
75
+ return if @account.nil?
59
76
 
60
- # An object to delegate account methods that don't
61
- # expect a wallet param in the RPC call, to allow this
62
- # class to support all methods that can be called on Nanook::Account
63
- @nanook_account_instance = Nanook::Account.new(@rpc, @account)
77
+ # Wallet must contain the account
78
+ unless Nanook::Wallet.new(@rpc, @wallet).contains?(@account)
79
+ raise ArgumentError, "Account does not exist in wallet. Account: #{@account}, wallet: #{@wallet}"
64
80
  end
81
+
82
+ @nanook_account_instance = as_account(@account)
83
+ end
84
+
85
+ # @param other [Nanook::WalletAccount] wallet account to compare
86
+ # @return [Boolean] true if accounts are equal
87
+ def ==(other)
88
+ other.class == self.class &&
89
+ other.id == @account
90
+ end
91
+ alias eql? ==
92
+
93
+ # The hash value is used along with #eql? by the Hash class to determine if two objects
94
+ # reference the same hash key.
95
+ #
96
+ # @return [Integer]
97
+ def hash
98
+ [@wallet, @account].join('+').hash
65
99
  end
66
100
 
67
101
  # Creates a new account, or multiple new accounts, in this wallet.
@@ -71,23 +105,22 @@ class Nanook
71
105
  # wallet.create # => Nanook::WalletAccount
72
106
  # wallet.create(2) # => [Nanook::WalletAccount, Nanook::WalletAccount]
73
107
  #
74
- # @param n [Integer] number of accounts to create
108
+ # @param n_accounts [Integer] number of accounts to create
75
109
  #
76
110
  # @return [Nanook::WalletAccount] returns a single {Nanook::WalletAccount}
77
111
  # if invoked with no argument
78
112
  # @return [Array<Nanook::WalletAccount>] returns an Array of {Nanook::WalletAccount}
79
113
  # if method was called with argument +n+ > 1
80
114
  # @raise [ArgumentError] if +n+ is less than 1
81
- def create(n=1)
82
- if n < 1
83
- raise ArgumentError.new("number of accounts must be greater than 0")
84
- end
115
+ def create(n_accounts = 1)
116
+ skip_account_required!
117
+ raise ArgumentError, 'number of accounts must be greater than 0' if n_accounts < 1
85
118
 
86
- if n == 1
87
- Nanook::WalletAccount.new(@rpc, @wallet, rpc(:account_create)[:account])
119
+ if n_accounts == 1
120
+ as_wallet_account(rpc(:account_create, _access: :account))
88
121
  else
89
- Array(rpc(:accounts_create, count: n)[:accounts]).map do |account|
90
- Nanook::WalletAccount.new(@rpc, @wallet, account)
122
+ rpc(:accounts_create, count: n_accounts, _access: :accounts, _coerce: Array).map do |account|
123
+ as_wallet_account(account)
91
124
  end
92
125
  end
93
126
  end
@@ -100,27 +133,28 @@ class Nanook
100
133
  #
101
134
  # @return [Boolean] +true+ if action was successful, otherwise +false+
102
135
  def destroy
103
- rpc(:account_remove)[:removed] == 1
136
+ rpc(:account_remove, _access: :removed) == 1
104
137
  end
105
138
 
106
139
  # @return [String]
107
- def inspect
108
- "#{self.class.name}(wallet_id: #{@wallet}, account_id: #{id}, object_id: \"#{"0x00%x" % (object_id << 1)}\")"
140
+ def to_s
141
+ "#{self.class.name}(id: \"#{short_id}\")"
109
142
  end
143
+ alias inspect to_s
110
144
 
111
145
  # Makes a payment from this account to another account
112
146
  # on the nano network. Returns a <i>send</i> block hash
113
- # if successful, or a {Nanook::Error} if unsuccessful.
147
+ # if successful, or a {Nanook::NodeRpcError} if unsuccessful.
114
148
  #
115
149
  # Note, there may be a delay in receiving a response due to Proof
116
- # of Work being done. From the {Nano RPC}[https://github.com/nanocurrency/raiblocks/wiki/RPC-protocol#account-create]:
150
+ # of Work being done. From the {Nano RPC}[https://docs.nano.org/commands/rpc-protocol/#send]:
117
151
  #
118
152
  # <i>Proof of Work is precomputed for one transaction in the background. If it has been a while since your last transaction it will send instantly, the next one will need to wait for Proof of Work to be generated.</i>
119
153
  #
120
154
  # ==== Examples:
121
155
  #
122
- # account.pay(to: "xrb_...", amount: 1.1, id: "myUniqueId123") # => "9AE2311..."
123
- # account.pay(to: "xrb_...", amount: 54000000000000, id: "myUniqueId123", unit: :raw) # => "9AE2311..."
156
+ # account.pay(to: "nano_...", amount: 1.1, id: "myUniqueId123") # => "9AE2311..."
157
+ # account.pay(to: "nano_...", amount: 54000000000000, id: "myUniqueId123", unit: :raw) # => "9AE2311..."
124
158
  #
125
159
  # @param to [String] account id of the recipient of your payment
126
160
  # @param amount [Integer|Float]
@@ -129,42 +163,34 @@ class Nanook
129
163
  # purpose; it allows you to make the same call multiple times with
130
164
  # the same +id+ and be reassured that you will only ever send this
131
165
  # nano payment once
132
- # @return [String] the send block id for the payment
133
- # @raise [Nanook::Error] if unsuccessful
134
- def pay(to:, amount:, unit: Nanook::default_unit, id:)
135
- unless Nanook::UNITS.include?(unit)
136
- raise ArgumentError.new("Unsupported unit: #{unit}")
137
- end
166
+ # @return [Nanook::Block] the send block for the payment
167
+ # @raise [Nanook::NodeRpcError] if unsuccessful
168
+ # @raise [Nanook::NanoUnitError] if `unit` is invalid
169
+ def pay(to:, amount:, id:, unit: Nanook.default_unit)
170
+ validate_unit!(unit)
138
171
 
139
172
  # Check that to account is a valid address
140
- response = @rpc.call(:validate_account_number, account: to)
141
- unless response[:valid] == 1
142
- raise ArgumentError.new("Account address is invalid: #{to}")
143
- end
173
+ valid = @rpc.call(:validate_account_number, account: to, _access: :valid) == 1
174
+ raise ArgumentError, "Account address is invalid: #{to}" unless valid
144
175
 
145
- # Determin amount in raw
176
+ # Determine amount in raw
146
177
  raw = if unit.to_sym.eql?(:nano)
147
- Nanook::Util.NANO_to_raw(amount)
148
- else
149
- amount
150
- end
178
+ NANO_to_raw(amount)
179
+ else
180
+ amount
181
+ end
151
182
 
152
183
  # account is called source, so don't use the normal rpc method
153
- p = {
184
+ params = {
154
185
  wallet: @wallet,
155
186
  source: @account,
156
187
  destination: to,
157
188
  amount: raw,
158
- id: id
189
+ id: id,
190
+ _access: :block
159
191
  }
160
192
 
161
- response = @rpc.call(:send, p)
162
-
163
- if response.has_key?(:error)
164
- return Nanook::Error.new(response[:error])
165
- end
166
-
167
- response[:block]
193
+ as_block(@rpc.call(:send, params))
168
194
  end
169
195
 
170
196
  # Receives a pending payment for this account.
@@ -181,19 +207,17 @@ class Nanook
181
207
  #
182
208
  # ==== Examples:
183
209
  #
184
- # account.receive # => "9AE2311..."
185
- # account.receive("718CC21...") # => "9AE2311..."
210
+ # account.receive # => Nanook::Block
211
+ # account.receive("718CC21...") # => Nanook::Block
186
212
  #
187
213
  # @param block [String] optional block id of pending payment. If
188
214
  # not provided, the latest pending payment will be received
189
- # @return [String] the receive block id
215
+ # @return [Nanook::Block] the receive block
190
216
  # @return [false] if there was no block to receive
191
- def receive(block=nil)
192
- if block.nil?
193
- _receive_without_block
194
- else
195
- _receive_with_block(block)
196
- end
217
+ def receive(block = nil)
218
+ return receive_without_block if block.nil?
219
+
220
+ receive_with_block(block)
197
221
  end
198
222
 
199
223
  # Sets the representative for the account.
@@ -211,48 +235,84 @@ class Nanook
211
235
  #
212
236
  # ==== Example:
213
237
  #
214
- # account.change_representative("xrb_...") # => "000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F"
238
+ # account.change_representative("nano_...") # => Nanook::Block
215
239
  #
216
- # @param [String] representative the id of the representative account
240
+ # @param representative [String] the id of the representative account
217
241
  # to set as this account's representative
218
- # @return [String] id of the <i>change</i> block created
219
- # @raise [ArgumentError] if the representative account does not exist
242
+ # @return [Nanook::Block] <i>change</i> block created
243
+ # @raise [Nanook::Error] if setting the representative account fails
220
244
  def change_representative(representative)
221
- unless Nanook::Account.new(@rpc, representative).exists?
222
- raise ArgumentError.new("Representative account does not exist: #{representative}")
245
+ unless as_account(representative).exists?
246
+ raise Nanook::Error, "Representative account does not exist: #{representative}"
223
247
  end
224
248
 
225
- rpc(:account_representative_set, representative: representative)[:block]
249
+ params = {
250
+ representative: representative,
251
+ _access: :block
252
+ }
253
+
254
+ as_block(rpc(:account_representative_set, params))
255
+ end
256
+
257
+ # Returns the work for the account.
258
+ #
259
+ # ==== Example:
260
+ #
261
+ # account.work # => "432e5cf728c90f4f"
262
+ #
263
+ # @return [String] work
264
+ def work
265
+ rpc(:work_get, _access: :work)
266
+ end
267
+
268
+ # Set work for account.
269
+ #
270
+ # ==== Example:
271
+ #
272
+ # account.set_work("432e5cf728c90f4f") # => true
273
+ #
274
+ # @return [Boolean] true if action was successful
275
+ def set_work(work)
276
+ rpc(:work_set, work: work).key?(:success)
226
277
  end
227
278
 
228
279
  private
229
280
 
230
- def _receive_without_block
281
+ def receive_without_block
231
282
  # Discover the first pending block
232
- pending_blocks = @rpc.call(:pending, { account: @account, count: 1 })
283
+ block = @rpc.call(:pending, { account: @account, count: 1, _access: :blocks, _coerce: Array }).first
233
284
 
234
- if pending_blocks[:blocks].empty?
235
- return false
236
- end
285
+ return false unless block
237
286
 
238
287
  # Then call receive_with_block as normal
239
- block = pending_blocks[:blocks][0]
240
- _receive_with_block(block)
288
+ receive_with_block(block)
241
289
  end
242
290
 
243
291
  # Returns block if successful, otherwise false
244
- def _receive_with_block(block)
245
- response = rpc(:receive, block: block)[:block]
246
- response.nil? ? false : response
292
+ def receive_with_block(block)
293
+ response = rpc(:receive, block: block, _access: :block)
294
+ response ? as_block(response) : false
247
295
  end
248
296
 
249
- def rpc(action, params={})
250
- p = {}
251
- p[:wallet] = @wallet unless @wallet.nil?
252
- p[:account] = @account unless @account.nil?
297
+ def rpc(action, params = {})
298
+ check_account_required!
253
299
 
254
- @rpc.call(action, p.merge(params))
300
+ p = { wallet: @wallet, account: @account }.compact
301
+ @rpc.call(action, p.merge(params)).tap { reset_skip_account_required! }
255
302
  end
256
303
 
304
+ def skip_account_required!
305
+ @skip_account_required_check = true
306
+ end
307
+
308
+ def reset_skip_account_required!
309
+ @skip_account_required_check = false
310
+ end
311
+
312
+ def check_account_required!
313
+ return if @account || @skip_account_required_check
314
+
315
+ raise ArgumentError, 'Account must be present'
316
+ end
257
317
  end
258
318
  end
@@ -1,31 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'util'
4
+
1
5
  class Nanook
6
+ # The <tt>Nanook::WorkPeer</tt> class lets you manage your node's work peers.
2
7
  class WorkPeer
8
+ include Nanook::Util
3
9
 
4
10
  def initialize(rpc)
5
11
  @rpc = rpc
6
12
  end
7
13
 
8
14
  def add(address:, port:)
9
- rpc(:work_peer_add, address: address, port: port).has_key?(:success)
15
+ rpc(:work_peer_add, address: address, port: port).key?(:success)
10
16
  end
11
17
 
12
18
  def clear
13
- rpc(:work_peers_clear).has_key?(:success)
19
+ rpc(:work_peers_clear).key?(:success)
14
20
  end
15
21
 
16
- def inspect
17
- "#{self.class.name}(object_id: \"#{"0x00%x" % (object_id << 1)}\")"
22
+ # @return [String]
23
+ def to_s
24
+ self.class.name
18
25
  end
26
+ alias inspect to_s
19
27
 
20
28
  def list
21
- rpc(:work_peers)[:work_peers]
29
+ rpc(:work_peers, _access: :work_peers, _coerce: Array)
22
30
  end
23
31
 
24
32
  private
25
33
 
26
- def rpc(action, params={})
34
+ def rpc(action, params = {})
27
35
  @rpc.call(action, params)
28
36
  end
29
-
30
37
  end
31
38
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nanook
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luke Duncalfe
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-07-05 00:00:00.000000000 Z
11
+ date: 2021-05-02 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: '2.2'
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: '2.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: pry
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -44,84 +44,84 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '10.0'
47
+ version: '12.3'
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'
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.2'
61
+ version: '3.10'
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.2'
68
+ version: '3.10'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec-collection_matchers
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '1.1'
75
+ version: '1.2'
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: '1.1'
82
+ version: '1.2'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rspec_junit_formatter
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0.3'
89
+ version: '0.4'
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.3'
96
+ version: '0.4'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: webmock
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '3.3'
103
+ version: '3.12'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '3.3'
110
+ version: '3.12'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: yard
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - "~>"
115
+ - - ">="
116
116
  - !ruby/object:Gem::Version
117
- version: '0'
117
+ version: 0.9.20
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - "~>"
122
+ - - ">="
123
123
  - !ruby/object:Gem::Version
124
- version: '0'
124
+ version: 0.9.20
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: symbolized
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -136,8 +136,9 @@ dependencies:
136
136
  - - '='
137
137
  - !ruby/object:Gem::Version
138
138
  version: 0.0.1
139
- description: Library for managing a nano currency node, including making and receiving
140
- payments, using the nano RPC protocol
139
+ description: |
140
+ Library for managing a nano currency node, including making and
141
+ receiving payments, using the nano RPC protocol
141
142
  email:
142
143
  - lduncalfe@eml.cc
143
144
  executables: []
@@ -152,9 +153,10 @@ files:
152
153
  - lib/nanook.rb
153
154
  - lib/nanook/account.rb
154
155
  - lib/nanook/block.rb
155
- - lib/nanook/error.rb
156
- - lib/nanook/key.rb
156
+ - lib/nanook/errors.rb
157
157
  - lib/nanook/node.rb
158
+ - lib/nanook/private_key.rb
159
+ - lib/nanook/public_key.rb
158
160
  - lib/nanook/rpc.rb
159
161
  - lib/nanook/util.rb
160
162
  - lib/nanook/version.rb
@@ -166,7 +168,7 @@ licenses:
166
168
  - MIT
167
169
  metadata:
168
170
  yard.run: yri
169
- post_install_message:
171
+ post_install_message:
170
172
  rdoc_options: []
171
173
  require_paths:
172
174
  - lib
@@ -181,9 +183,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
181
183
  - !ruby/object:Gem::Version
182
184
  version: '0'
183
185
  requirements: []
184
- rubyforge_project:
185
- rubygems_version: 2.7.7
186
- signing_key:
186
+ rubygems_version: 3.2.3
187
+ signing_key:
187
188
  specification_version: 4
188
189
  summary: Library for managing a nano currency node, including making and receiving
189
190
  payments, using the nano RPC protocol