nanook 2.4.0 → 3.1.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 +4 -4
- data/CHANGELOG.md +139 -0
- data/README.md +158 -99
- data/bin/console +4 -3
- data/lib/nanook.rb +77 -21
- data/lib/nanook/account.rb +238 -168
- data/lib/nanook/block.rb +380 -149
- data/lib/nanook/errors.rb +10 -0
- data/lib/nanook/node.rb +218 -83
- data/lib/nanook/private_key.rb +115 -0
- data/lib/nanook/public_key.rb +55 -0
- data/lib/nanook/rpc.rb +104 -44
- data/lib/nanook/util.rb +68 -19
- data/lib/nanook/version.rb +3 -1
- data/lib/nanook/wallet.rb +369 -167
- data/lib/nanook/wallet_account.rb +151 -91
- data/lib/nanook/work_peer.rb +14 -7
- metadata +28 -27
- data/lib/nanook/error.rb +0 -5
- data/lib/nanook/key.rb +0 -46
data/lib/nanook/block.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'util'
|
2
4
|
|
5
|
+
class Nanook
|
3
6
|
# The <tt>Nanook::Block</tt> class contains methods to discover
|
4
7
|
# publicly-available information about blocks on the nano network.
|
5
8
|
#
|
@@ -17,21 +20,38 @@ class Nanook
|
|
17
20
|
# rpc_conn = Nanook::Rpc.new
|
18
21
|
# block = Nanook::Block.new(rpc_conn, "FBF8B0E...")
|
19
22
|
class Block
|
23
|
+
include Nanook::Util
|
20
24
|
|
21
25
|
def initialize(rpc, block)
|
22
26
|
@rpc = rpc
|
23
|
-
@block = block
|
24
|
-
block_required! # All methods expect a block
|
27
|
+
@block = block.to_s
|
25
28
|
end
|
26
29
|
|
27
|
-
# Returns the
|
30
|
+
# Returns the block hash id.
|
28
31
|
#
|
29
32
|
# ==== Example:
|
30
|
-
# block.account # => Nanook::Account
|
31
33
|
#
|
32
|
-
#
|
33
|
-
|
34
|
-
|
34
|
+
# block.id #=> "FBF8B0E..."
|
35
|
+
#
|
36
|
+
# @return [String] the block hash id
|
37
|
+
def id
|
38
|
+
@block
|
39
|
+
end
|
40
|
+
|
41
|
+
# @param other [Nanook::Block] block to compare
|
42
|
+
# @return [Boolean] true if blocks are equal
|
43
|
+
def ==(other)
|
44
|
+
other.class == self.class &&
|
45
|
+
other.id == id
|
46
|
+
end
|
47
|
+
alias eql? ==
|
48
|
+
|
49
|
+
# The hash value is used along with #eql? by the Hash class to determine if two objects
|
50
|
+
# reference the same hash key.
|
51
|
+
#
|
52
|
+
# @return [Integer]
|
53
|
+
def hash
|
54
|
+
id.hash
|
35
55
|
end
|
36
56
|
|
37
57
|
# Stop generating work for a block.
|
@@ -45,64 +65,52 @@ class Nanook
|
|
45
65
|
rpc(:work_cancel, :hash).empty?
|
46
66
|
end
|
47
67
|
|
48
|
-
# Returns
|
49
|
-
#
|
68
|
+
# Returns a consecutive list of block hashes in the account chain
|
69
|
+
# from (but not including) block back to +count+ (direction from frontier back to
|
70
|
+
# open block, from newer blocks to older). Will list all blocks back
|
71
|
+
# to the open block of this chain when count is set to "-1".
|
50
72
|
#
|
51
|
-
# See also #
|
73
|
+
# See also #descendants.
|
52
74
|
#
|
53
75
|
# ==== Example:
|
54
76
|
#
|
55
|
-
# block.
|
77
|
+
# block.ancestors(limit: 2)
|
56
78
|
#
|
57
79
|
# ==== Example reponse:
|
58
80
|
#
|
59
|
-
# [
|
60
|
-
#
|
61
|
-
# "FBF8B0E6623A31AB528EBD839EEAA91CAFD25C12294C46754E45FD017F7939EB"
|
62
|
-
# ]
|
81
|
+
# [Nanook::Block, ...]
|
82
|
+
#
|
63
83
|
# @param limit [Integer] maximum number of block hashes to return (default is 1000)
|
64
|
-
|
65
|
-
|
66
|
-
|
84
|
+
# @param offset [Integer] return the account chain block hashes offset by the specified number of blocks (default is 0)
|
85
|
+
def chain(limit: 1000, offset: 0)
|
86
|
+
# The RPC includes this block in its response, and Nanook will remove it from the results.
|
87
|
+
# Increment the limit by 1 to account for this (a limit of -1 is valid and means no limit).
|
88
|
+
limit += 1 if limit > 0
|
89
|
+
params = {
|
90
|
+
count: limit,
|
91
|
+
offset: offset,
|
92
|
+
_access: :blocks,
|
93
|
+
_coerce: Array
|
94
|
+
}
|
95
|
+
|
96
|
+
response = rpc(:chain, :block, params)[1..].to_a
|
97
|
+
response.map { |block| as_block(block) }
|
67
98
|
end
|
99
|
+
alias ancestors chain
|
68
100
|
|
69
101
|
# Request confirmation for a block from online representative nodes.
|
70
102
|
# Will return immediately with a boolean to indicate if the request for
|
71
103
|
# confirmation was successful. Note that this boolean does not indicate
|
72
|
-
# the confirmation status of the block.
|
73
|
-
# appear in {Nanook::Node#confirmation_history} within a short amount of
|
74
|
-
# time, or you can use the convenience method {Nanook::Block#confirmed_recently?}
|
104
|
+
# the confirmation status of the block.
|
75
105
|
#
|
76
106
|
# ==== Example:
|
77
107
|
# block.confirm # => true
|
78
108
|
#
|
79
109
|
# @return [Boolean] if the confirmation request was sent successful
|
80
110
|
def confirm
|
81
|
-
rpc(:block_confirm, :hash
|
111
|
+
rpc(:block_confirm, :hash, _access: :started) == 1
|
82
112
|
end
|
83
113
|
|
84
|
-
# Check if the block appears in the list of recently confirmed blocks by
|
85
|
-
# online representatives. The full list of blocks can be queried for with {Nanook::Node#confirmation_history}.
|
86
|
-
#
|
87
|
-
# This method can work in conjunction with {Nanook::Block#confirm},
|
88
|
-
# whereby you can send any block (old or new) out to online representatives to
|
89
|
-
# confirm. The confirmation process can take up to a couple of minutes.
|
90
|
-
#
|
91
|
-
# The method returning +false+ can indicate that the block is still in the process of being
|
92
|
-
# confirmed and that you should call the method again soon, or that it
|
93
|
-
# was confirmed earlier than the list available in {Nanook::Node#confirmation_history},
|
94
|
-
# or that it was not confirmed.
|
95
|
-
#
|
96
|
-
# ==== Example:
|
97
|
-
# block.confirmed_recently? # => true
|
98
|
-
#
|
99
|
-
# @return [Boolean] +true+ if the block has been recently confirmed by
|
100
|
-
# online representatives.
|
101
|
-
def confirmed_recently?
|
102
|
-
@rpc.call(:confirmation_history)[:confirmations].map{|h| h[:hash]}.include?(@block)
|
103
|
-
end
|
104
|
-
alias_method :recently_confirmed?, :confirmed_recently?
|
105
|
-
|
106
114
|
# Generate work for a block.
|
107
115
|
#
|
108
116
|
# ==== Example:
|
@@ -113,42 +121,7 @@ class Nanook
|
|
113
121
|
# When +false+, the node will only generate work locally (default is +false+)
|
114
122
|
# @return [String] the work id of the work completed.
|
115
123
|
def generate_work(use_peers: false)
|
116
|
-
rpc(:work_generate, :hash, use_peers: use_peers
|
117
|
-
end
|
118
|
-
|
119
|
-
# Returns Array of Hashes containing information about a chain of
|
120
|
-
# send/receive blocks, starting from this block.
|
121
|
-
#
|
122
|
-
# ==== Example:
|
123
|
-
#
|
124
|
-
# block.history(limit: 1)
|
125
|
-
#
|
126
|
-
# ==== Example response:
|
127
|
-
#
|
128
|
-
# [
|
129
|
-
# {
|
130
|
-
# :account=>"xrb_3x7cjioqahgs5ppheys6prpqtb4rdknked83chf97bot1unrbdkaux37t31b",
|
131
|
-
# :amount=>539834279601145558517940224,
|
132
|
-
# :hash=>"36A0FB717368BA8CF8D255B63DC207771EABC6C6FFC22A7F455EC2209464897E",
|
133
|
-
# :type=>"send"
|
134
|
-
# }
|
135
|
-
# ]
|
136
|
-
#
|
137
|
-
# @param limit [Integer] maximum number of send/receive block hashes
|
138
|
-
# to return in the chain (default is 1000)
|
139
|
-
def history(limit: 1000)
|
140
|
-
rpc(:history, :hash, count: limit)[:history]
|
141
|
-
end
|
142
|
-
|
143
|
-
# Returns the block hash id.
|
144
|
-
#
|
145
|
-
# ==== Example:
|
146
|
-
#
|
147
|
-
# block.id #=> "FBF8B0E..."
|
148
|
-
#
|
149
|
-
# @return [String] the block hash id
|
150
|
-
def id
|
151
|
-
@block
|
124
|
+
rpc(:work_generate, :hash, use_peers: use_peers, _access: :work)
|
152
125
|
end
|
153
126
|
|
154
127
|
# Returns a Hash of information about the block.
|
@@ -161,141 +134,399 @@ class Nanook
|
|
161
134
|
# ==== Example response:
|
162
135
|
#
|
163
136
|
# {
|
164
|
-
#
|
165
|
-
#
|
166
|
-
#
|
167
|
-
#
|
168
|
-
#
|
169
|
-
#
|
170
|
-
# :
|
137
|
+
# "account": Nanook::Account,
|
138
|
+
# "amount": 34.2,
|
139
|
+
# "balance": 2.3
|
140
|
+
# "height": 58,
|
141
|
+
# "local_timestamp": Time,
|
142
|
+
# "confirmed": true,
|
143
|
+
# "type": "send",
|
144
|
+
# "account": Nanook::Account,
|
145
|
+
# "previous": Nanook::Block,
|
146
|
+
# "representative": Nanook::Account,
|
147
|
+
# "link": Nanook::Block,
|
148
|
+
# "link_as_account": Nanook::Account,
|
149
|
+
# "signature": "82D41BC16F313E4B2243D14DFFA2FB04679C540C2095FEE7EAE0F2F26880AD56DD48D87A7CC5DD760C5B2D76EE2C205506AA557BF00B60D8DEE312EC7343A501",
|
150
|
+
# "work": "8a142e07a10996d5"
|
171
151
|
# }
|
172
152
|
#
|
173
153
|
# @param allow_unchecked [Boolean] (default is +false+). If +true+,
|
174
154
|
# information can be returned about blocks that are unchecked (unverified).
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
155
|
+
# @raise [Nanook::NanoUnitError] if `unit` is invalid
|
156
|
+
# @raise [Nanook::NodeRpcError] if block is not found on the node.
|
157
|
+
def info(allow_unchecked: false, unit: Nanook.default_unit)
|
158
|
+
validate_unit!(unit)
|
159
|
+
|
160
|
+
# Params for both `unchecked_get` and `block_info` calls
|
161
|
+
params = {
|
162
|
+
json_block: true,
|
163
|
+
_coerce: Hash
|
164
|
+
}
|
165
|
+
|
166
|
+
begin
|
167
|
+
response = rpc(:block_info, :hash, params)
|
168
|
+
response.merge!(confirmed: true)
|
169
|
+
rescue Nanook::NodeRpcError => e
|
170
|
+
raise e unless allow_unchecked
|
171
|
+
|
172
|
+
response = rpc(:unchecked_get, :hash, params)
|
173
|
+
response.merge!(confirmed: false)
|
182
174
|
end
|
183
175
|
|
184
|
-
response
|
185
|
-
_parse_info_response(response)
|
176
|
+
parse_info_response(response, unit)
|
186
177
|
end
|
187
178
|
|
179
|
+
# Returns true if work is valid for the block.
|
180
|
+
#
|
188
181
|
# ==== Example:
|
189
182
|
#
|
190
|
-
# block.
|
183
|
+
# block.valid_work?("2bf29ef00786a6bc") # => true
|
191
184
|
#
|
192
185
|
# @param work [String] the work id to check is valid
|
193
186
|
# @return [Boolean] signalling if work is valid for the block
|
194
|
-
def
|
187
|
+
def valid_work?(work)
|
195
188
|
response = rpc(:work_validate, :hash, work: work)
|
196
|
-
|
189
|
+
response[:valid_all] == 1 || response[:valid_receive] == 1
|
197
190
|
end
|
198
191
|
|
199
192
|
# Republish blocks starting at this block up the account chain
|
200
193
|
# back to the nano network.
|
201
194
|
#
|
202
|
-
# @return [Array<
|
195
|
+
# @return [Array<Nanook::Block>] blocks that were republished
|
203
196
|
#
|
204
197
|
# ==== Example:
|
205
198
|
#
|
206
|
-
# block.republish
|
207
|
-
|
208
|
-
# ==== Example response:
|
209
|
-
#
|
210
|
-
# ["36A0FB717368BA8CF8D255B63DC207771EABC6C6FFC22A7F455EC2209464897E"]
|
211
|
-
def republish(destinations:nil, sources:nil)
|
199
|
+
# block.republish # => [Nanook::Block, ...]
|
200
|
+
def republish(destinations: nil, sources: nil)
|
212
201
|
if !destinations.nil? && !sources.nil?
|
213
|
-
raise ArgumentError
|
202
|
+
raise ArgumentError, 'You must provide either destinations or sources but not both'
|
214
203
|
end
|
215
204
|
|
216
|
-
|
217
|
-
|
205
|
+
params = {
|
206
|
+
_access: :blocks,
|
207
|
+
_coerce: Array
|
208
|
+
}
|
209
|
+
|
218
210
|
params[:destinations] = destinations unless destinations.nil?
|
219
211
|
params[:sources] = sources unless sources.nil?
|
220
|
-
params[:count] = 1
|
212
|
+
params[:count] = 1 if destinations || sources
|
221
213
|
|
222
|
-
rpc(:republish, :hash, params)
|
214
|
+
rpc(:republish, :hash, params).map do |block|
|
215
|
+
as_block(block)
|
216
|
+
end
|
223
217
|
end
|
224
218
|
|
219
|
+
# Returns true if block is a pending block.
|
220
|
+
#
|
225
221
|
# ==== Example:
|
226
222
|
#
|
227
223
|
# block.pending? #=> false
|
228
224
|
#
|
229
225
|
# @return [Boolean] signalling if the block is a pending block.
|
230
226
|
def pending?
|
231
|
-
|
232
|
-
!response.empty? && response[:exists] == 1
|
227
|
+
rpc(:pending_exists, :hash, _access: :exists) == 1
|
233
228
|
end
|
234
229
|
|
235
|
-
#
|
230
|
+
# Returns an Array of block hashes in the account chain from (but not including) this block up to +count+
|
231
|
+
# (direction from open block up to frontier, from older blocks to newer). Will list all
|
232
|
+
# blocks up to frontier (latest block) of this chain when +count+ is set to +-1+.
|
236
233
|
#
|
237
|
-
#
|
234
|
+
# See also #ancestors.
|
238
235
|
#
|
239
|
-
# ====
|
236
|
+
# ==== Example:
|
240
237
|
#
|
241
|
-
# block.
|
238
|
+
# block.descendants # => [Nanook::Block, .. ]
|
242
239
|
#
|
243
|
-
# @
|
244
|
-
|
245
|
-
|
240
|
+
# @param limit [Integer] maximum number of send/receive block hashes
|
241
|
+
# to return in the chain (default is 1000)
|
242
|
+
# @param offset [Integer] return the account chain block hashes offset
|
243
|
+
# by the specified number of blocks (default is 0)
|
244
|
+
# @return [Array<Nanook::Block>] blocks in the account chain ending at this block
|
245
|
+
def successors(limit: 1000, offset: 0)
|
246
|
+
# The RPC includes this block in its response, and Nanook will remove it from the results.
|
247
|
+
# Increment the limit by 1 to account for this (a limit of -1 is valid and means no limit).
|
248
|
+
limit += 1 if limit > 0
|
249
|
+
|
250
|
+
params = {
|
251
|
+
count: limit,
|
252
|
+
offset: offset,
|
253
|
+
_access: :blocks,
|
254
|
+
_coerce: Array
|
255
|
+
}
|
256
|
+
|
257
|
+
response = rpc(:successors, :block, params)[1..].to_a
|
258
|
+
response.map { |block| as_block(block) }
|
246
259
|
end
|
247
|
-
|
260
|
+
alias descendants successors
|
248
261
|
|
249
|
-
# Returns
|
250
|
-
# this block.
|
262
|
+
# Returns the {Nanook::Account} of the block representative.
|
251
263
|
#
|
252
|
-
#
|
264
|
+
# ==== Example:
|
265
|
+
# block.representative # => Nanook::Account
|
266
|
+
#
|
267
|
+
# @return [Nanook::Account] representative account of the block. Can be nil.
|
268
|
+
def representative
|
269
|
+
memoized_info[:representative]
|
270
|
+
end
|
271
|
+
|
272
|
+
# Returns the {Nanook::Account} of the block.
|
253
273
|
#
|
254
274
|
# ==== Example:
|
275
|
+
# block.account # => Nanook::Account
|
255
276
|
#
|
256
|
-
#
|
277
|
+
# @return [Nanook::Account] the account of the block. Can be nil.
|
278
|
+
def account
|
279
|
+
memoized_info[:account]
|
280
|
+
end
|
281
|
+
|
282
|
+
# Returns the amount of the block.
|
257
283
|
#
|
258
|
-
# ==== Example
|
284
|
+
# ==== Example:
|
285
|
+
# block.amount # => 3.01
|
259
286
|
#
|
260
|
-
#
|
287
|
+
# @param unit (see Nanook::Account#balance)
|
288
|
+
# @raise [Nanook::NanoUnitError] if `unit` is invalid
|
289
|
+
# @return [Float]
|
290
|
+
def amount(unit: Nanook.default_unit)
|
291
|
+
validate_unit!(unit)
|
292
|
+
|
293
|
+
amount = memoized_info[:amount]
|
294
|
+
return amount unless unit == :nano
|
295
|
+
|
296
|
+
raw_to_NANO(amount)
|
297
|
+
end
|
298
|
+
|
299
|
+
# Returns the balance of the account at the time the block was created.
|
261
300
|
#
|
262
|
-
#
|
263
|
-
#
|
264
|
-
#
|
265
|
-
|
266
|
-
|
267
|
-
|
301
|
+
# ==== Example:
|
302
|
+
# block.balance # => 3.01
|
303
|
+
#
|
304
|
+
# @param unit (see Nanook::Account#balance)
|
305
|
+
# @raise [Nanook::NanoUnitError] if `unit` is invalid
|
306
|
+
# @return [Float]
|
307
|
+
def balance(unit: Nanook.default_unit)
|
308
|
+
validate_unit!(unit)
|
309
|
+
|
310
|
+
balance = memoized_info[:balance]
|
311
|
+
return balance unless unit == :nano
|
312
|
+
|
313
|
+
raw_to_NANO(balance)
|
268
314
|
end
|
269
315
|
|
270
|
-
|
271
|
-
|
316
|
+
# Returns true if block is confirmed.
|
317
|
+
#
|
318
|
+
# ==== Example:
|
319
|
+
# block.confirmed # => true
|
320
|
+
#
|
321
|
+
# @return [Boolean]
|
322
|
+
def confirmed?
|
323
|
+
memoized_info[:confirmed]
|
324
|
+
end
|
325
|
+
alias checked? confirmed?
|
326
|
+
|
327
|
+
# Returns true if block is unconfirmed.
|
328
|
+
#
|
329
|
+
# ==== Example:
|
330
|
+
# block.unconfirmed? # => true
|
331
|
+
#
|
332
|
+
# @return [Boolean]
|
333
|
+
def unconfirmed?
|
334
|
+
!confirmed?
|
335
|
+
end
|
336
|
+
alias unchecked? unconfirmed?
|
337
|
+
|
338
|
+
# Returns true if block exists in the node's ledger. This will return
|
339
|
+
# false for blocks that exist on the nano ledger but have not yet
|
340
|
+
# synchronized to the node.
|
341
|
+
#
|
342
|
+
# ==== Example:
|
343
|
+
#
|
344
|
+
# block.exists? # => false
|
345
|
+
# block.exists?(allow_unchecked: true) # => true
|
346
|
+
#
|
347
|
+
# @param allow_unchecked [Boolean] defaults to +false+
|
348
|
+
# @return [Boolean]
|
349
|
+
def exists?(allow_unchecked: false)
|
350
|
+
begin
|
351
|
+
allow_unchecked ? memoized_info : info
|
352
|
+
rescue Nanook::NodeRpcError
|
353
|
+
return false
|
354
|
+
end
|
355
|
+
|
356
|
+
true
|
357
|
+
end
|
358
|
+
|
359
|
+
# Returns the {Nanook::Block} of the next (newer) block in the account chain.
|
360
|
+
#
|
361
|
+
# ==== Example:
|
362
|
+
# block.next # => Nanook::Block
|
363
|
+
#
|
364
|
+
# @return [Nanook::Block] next (newer) block in the account chain. Can be nil.
|
365
|
+
def next
|
366
|
+
successors(limit: 1).first
|
367
|
+
end
|
368
|
+
|
369
|
+
# Returns the height of the block.
|
370
|
+
#
|
371
|
+
# ==== Example:
|
372
|
+
# block.height # => 5
|
373
|
+
#
|
374
|
+
# @return [Integer]
|
375
|
+
def height
|
376
|
+
memoized_info[:height]
|
377
|
+
end
|
378
|
+
|
379
|
+
# Returns the block work.
|
380
|
+
#
|
381
|
+
# ==== Example:
|
382
|
+
# block.work # => "8a142e07a10996d5"
|
383
|
+
#
|
384
|
+
# @return [String]
|
385
|
+
def work
|
386
|
+
memoized_info[:work]
|
387
|
+
end
|
388
|
+
|
389
|
+
# Returns the block signature.
|
390
|
+
#
|
391
|
+
# ==== Example:
|
392
|
+
# block.signature # => "82D41BC16F313E4B2243D14DFFA2FB04679C540C2095FEE7EAE0F2F26880AD56DD48D87A7CC5DD760C5B2D76EE2C205506AA557BF00B60D8DEE312EC7343A501"
|
393
|
+
#
|
394
|
+
# @return [String]
|
395
|
+
def signature
|
396
|
+
memoized_info[:signature]
|
397
|
+
end
|
398
|
+
|
399
|
+
# Returns the timestamp of when the node saw the block.
|
400
|
+
#
|
401
|
+
# ==== Example:
|
402
|
+
# block.timestamp # => 2018-05-30 16:41:48 UTC
|
403
|
+
#
|
404
|
+
# @return [Time] Time in UTC of when the node saw the block. Can be nil.
|
405
|
+
def timestamp
|
406
|
+
memoized_info[:local_timestamp]
|
407
|
+
end
|
408
|
+
|
409
|
+
# Returns the {Nanook::Block} of the previous (older) block in the account chain.
|
410
|
+
#
|
411
|
+
# ==== Example:
|
412
|
+
# block.previous # => Nanook::Block
|
413
|
+
#
|
414
|
+
# @return [Nanook::Block] previous (older) block in the account chain. Can be nil.
|
415
|
+
def previous
|
416
|
+
memoized_info[:previous]
|
417
|
+
end
|
418
|
+
|
419
|
+
# Returns the type of the block. One of "open", "send", "receive", "change", "epoch".
|
420
|
+
#
|
421
|
+
# ==== Example:
|
422
|
+
# block.type # => "open"
|
423
|
+
#
|
424
|
+
# @return [String] type of block. Returns nil for unconfirmed blocks.
|
425
|
+
def type
|
426
|
+
memoized_info[:type]
|
427
|
+
end
|
428
|
+
|
429
|
+
# Returns true if block is type "send".
|
430
|
+
#
|
431
|
+
# ==== Example:
|
432
|
+
# block.send? # => true
|
433
|
+
#
|
434
|
+
# @return [Boolean]
|
435
|
+
def send?
|
436
|
+
type == 'send'
|
437
|
+
end
|
438
|
+
|
439
|
+
# Returns true if block is type "open".
|
440
|
+
#
|
441
|
+
# ==== Example:
|
442
|
+
# block.open? # => true
|
443
|
+
#
|
444
|
+
# @return [Boolean]
|
445
|
+
def open?
|
446
|
+
type == 'open'
|
447
|
+
end
|
448
|
+
|
449
|
+
# Returns true if block is type "receive".
|
450
|
+
#
|
451
|
+
# ==== Example:
|
452
|
+
# block.receive? # => true
|
453
|
+
#
|
454
|
+
# @return [Boolean]
|
455
|
+
def receive?
|
456
|
+
type == 'receive'
|
272
457
|
end
|
273
458
|
|
459
|
+
# Returns true if block is type "change" (change of representative).
|
460
|
+
#
|
461
|
+
# ==== Example:
|
462
|
+
# block.change? # => true
|
463
|
+
#
|
464
|
+
# @return [Boolean]
|
465
|
+
def change?
|
466
|
+
type == 'change'
|
467
|
+
end
|
468
|
+
|
469
|
+
# Returns true if block is type "epoch".
|
470
|
+
#
|
471
|
+
# ==== Example:
|
472
|
+
# block.epoch? # => true
|
473
|
+
#
|
474
|
+
# @return [Boolean]
|
475
|
+
def epoch?
|
476
|
+
type == 'epoch'
|
477
|
+
end
|
478
|
+
|
479
|
+
# @return [String]
|
480
|
+
def to_s
|
481
|
+
"#{self.class.name}(id: \"#{short_id}\")"
|
482
|
+
end
|
483
|
+
alias inspect to_s
|
484
|
+
|
274
485
|
private
|
275
486
|
|
276
487
|
# Some RPC calls expect the param that represents the block to be named
|
277
488
|
# "hash", and others "block".
|
278
489
|
# The param_name argument allows us to specify which it should be for this call.
|
279
|
-
def rpc(action, param_name, params={})
|
280
|
-
p =
|
490
|
+
def rpc(action, param_name, params = {})
|
491
|
+
p = { param_name.to_sym => @block }
|
281
492
|
@rpc.call(action, p.merge(params))
|
282
493
|
end
|
283
494
|
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
end
|
495
|
+
# Memoize the `#info` response as we can refer to it for other methods (`type`, `#open?`, `#send?` etc.)
|
496
|
+
def memoized_info
|
497
|
+
@memoized_info ||= info(allow_unchecked: true, unit: :raw)
|
288
498
|
end
|
289
499
|
|
290
|
-
def
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
500
|
+
def parse_info_response(response, unit)
|
501
|
+
response.merge!(id: id)
|
502
|
+
contents = response.delete(:contents)
|
503
|
+
response.merge!(contents) if contents
|
504
|
+
|
505
|
+
response.delete(:block_account) # duplicate of contents.account
|
506
|
+
response[:last_modified_at] = response.delete(:modified_timestamp) # rename key
|
507
|
+
|
508
|
+
# `type` can be "open", "send", "receive", "change", "epoch" or "state".
|
509
|
+
# blocks with `type` == "state" may have a `subtype` that gives more information
|
510
|
+
# about the block ("send", "receive", "change", "epoch"), in which case replace
|
511
|
+
# the `type` with this value.
|
512
|
+
if response[:type] == 'state' && (subtype = response.delete(:subtype))
|
513
|
+
response[:type] = subtype
|
295
514
|
end
|
296
515
|
|
297
|
-
response
|
298
|
-
|
516
|
+
response[:account] = as_account(response[:account]) if response[:account]
|
517
|
+
response[:representative] = as_account(response[:representative]) if response[:representative]
|
518
|
+
response[:previous] = as_block(response[:previous]) if response[:previous]
|
519
|
+
response[:link] = as_block(response[:link]) if response[:link]
|
520
|
+
response[:link_as_account] = as_account(response[:link_as_account]) if response[:link_as_account]
|
521
|
+
response[:local_timestamp] = as_time(response[:local_timestamp])
|
522
|
+
response[:last_modified_at] = as_time(response[:last_modified_at])
|
299
523
|
|
524
|
+
if unit == :nano
|
525
|
+
response[:amount] = raw_to_NANO(response[:amount])
|
526
|
+
response[:balance] = raw_to_NANO(response[:balance])
|
527
|
+
end
|
528
|
+
|
529
|
+
response.compact
|
530
|
+
end
|
300
531
|
end
|
301
532
|
end
|