nanook 2.5.1 → 3.0.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 +99 -0
- data/README.md +135 -85
- data/bin/console +4 -3
- data/lib/nanook.rb +76 -20
- data/lib/nanook/account.rb +232 -164
- data/lib/nanook/block.rb +343 -150
- data/lib/nanook/errors.rb +10 -0
- data/lib/nanook/node.rb +164 -132
- 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 +67 -18
- data/lib/nanook/version.rb +3 -1
- data/lib/nanook/wallet.rb +348 -161
- data/lib/nanook/wallet_account.rb +148 -88
- data/lib/nanook/work_peer.rb +14 -7
- metadata +20 -18
- data/lib/nanook/error.rb +0 -5
- data/lib/nanook/key.rb +0 -46
data/lib/nanook/node.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::Node</tt> class contains methods to manage your nano
|
4
7
|
# node and query its data of the nano network.
|
5
8
|
#
|
@@ -25,6 +28,7 @@ class Nanook
|
|
25
28
|
# rpc_conn = Nanook::Rpc.new
|
26
29
|
# node = Nanook::Node.new(rpc_conn)
|
27
30
|
class Node
|
31
|
+
include Nanook::Util
|
28
32
|
|
29
33
|
def initialize(rpc)
|
30
34
|
@rpc = rpc
|
@@ -38,56 +42,46 @@ class Nanook
|
|
38
42
|
#
|
39
43
|
# @return [Integer] number of accounts with _open_ blocks.
|
40
44
|
def account_count
|
41
|
-
rpc(:frontier_count
|
45
|
+
rpc(:frontier_count, _access: :count)
|
42
46
|
end
|
43
|
-
|
47
|
+
alias frontier_count account_count
|
44
48
|
|
45
49
|
# The count of all blocks downloaded to the node, and
|
46
50
|
# blocks still to be synchronized by the node.
|
47
51
|
#
|
48
52
|
# ==== Example:
|
49
53
|
#
|
50
|
-
#
|
54
|
+
# {
|
55
|
+
# count: 100,
|
56
|
+
# unchecked: 10,
|
57
|
+
# cemented: 25
|
58
|
+
# }
|
51
59
|
#
|
52
60
|
# @return [Hash{Symbol=>Integer}] number of blocks and unchecked
|
53
61
|
# synchronizing blocks
|
54
62
|
def block_count
|
55
|
-
rpc(:block_count)
|
63
|
+
rpc(:block_count, _coerce: Hash)
|
56
64
|
end
|
57
65
|
|
58
|
-
#
|
59
|
-
#
|
60
|
-
# ==== Example:
|
61
|
-
#
|
62
|
-
# node.block_count_by_type
|
66
|
+
# Tells the node to send a keepalive packet to a specific IP address and port.
|
63
67
|
#
|
64
|
-
#
|
65
|
-
|
66
|
-
|
67
|
-
# send: 1000,
|
68
|
-
# receive: 900,
|
69
|
-
# open: 900,
|
70
|
-
# change: 50
|
71
|
-
# }
|
72
|
-
#
|
73
|
-
# @return [Hash{Symbol=>Integer}] number of blocks by type
|
74
|
-
def block_count_by_type
|
75
|
-
rpc(:block_count_type)
|
68
|
+
# @return [Boolean] indicating if the action was successful
|
69
|
+
def keepalive(address:, port:)
|
70
|
+
rpc(:keepalive, address: address, port: port).key?(:started)
|
76
71
|
end
|
77
|
-
alias_method :block_count_type, :block_count_by_type
|
78
72
|
|
79
73
|
# Initialize bootstrap to a specific IP address and port.
|
80
74
|
#
|
81
75
|
# @return [Boolean] indicating if the action was successful
|
82
76
|
def bootstrap(address:, port:)
|
83
|
-
rpc(:bootstrap, address: address, port: port).
|
77
|
+
rpc(:bootstrap, address: address, port: port).key?(:success)
|
84
78
|
end
|
85
79
|
|
86
80
|
# Initialize multi-connection bootstrap to random peers
|
87
81
|
#
|
88
82
|
# @return [Boolean] indicating if the action was successful
|
89
83
|
def bootstrap_any
|
90
|
-
rpc(:bootstrap_any).
|
84
|
+
rpc(:bootstrap_any).key?(:success)
|
91
85
|
end
|
92
86
|
|
93
87
|
# Initialize lazy bootstrap with given block hash
|
@@ -97,79 +91,49 @@ class Nanook
|
|
97
91
|
# of all current bootstraps
|
98
92
|
# @return [Boolean] indicating if the action was successful
|
99
93
|
def bootstrap_lazy(hash, force: false)
|
100
|
-
rpc(:bootstrap_lazy, hash: hash, force: force
|
94
|
+
rpc(:bootstrap_lazy, hash: hash, force: force, _access: :started) == 1
|
101
95
|
end
|
102
96
|
|
103
|
-
#
|
104
|
-
#
|
105
|
-
#
|
106
|
-
#
|
97
|
+
# Returns information about node elections settings and observed network state:
|
98
|
+
#
|
99
|
+
# - `quorum_delta`: delta tally required to rollback block
|
100
|
+
# - `online_weight_quorum_percent`: percentage of online weight for delta
|
101
|
+
# - `online_weight_minimum`: minimum online weight to confirm block
|
102
|
+
# - `online_stake_total`: currently observed online total weight
|
103
|
+
# - `peers_stake_total`: known peers total weight
|
104
|
+
# - `peers_stake_required`: effective stake needed from directly connected peers for quorum
|
107
105
|
#
|
108
106
|
# ==== Example:
|
109
107
|
#
|
110
|
-
# node.
|
108
|
+
# node.confirmation_quorum
|
111
109
|
#
|
112
110
|
# Example response:
|
113
111
|
#
|
114
112
|
# {
|
115
|
-
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
#
|
119
|
-
#
|
120
|
-
#
|
121
|
-
# total_blocks: 536820,
|
122
|
-
# lazy_mode: true,
|
123
|
-
# lazy_blocks: 423388,
|
124
|
-
# lazy_state_unknown: 2,
|
125
|
-
# lazy_balances: 0,
|
126
|
-
# lazy_pulls: 0,
|
127
|
-
# lazy_stopped: 644,
|
128
|
-
# lazy_keys: 449,
|
129
|
-
# lazy_key_1: "A86EB2B479AAF3CD531C8356A1FBE3CB500DFBF5BF292E5E6B8D1048DE199C32"
|
113
|
+
# "quorum_delta": 43216377.43025059,
|
114
|
+
# "online_weight_quorum_percent": 50,
|
115
|
+
# "online_weight_minimum": 60000000.0",
|
116
|
+
# "online_stake_total": 86432754.86050119,
|
117
|
+
# "peers_stake_total": 84672338.52479072,
|
118
|
+
# "peers_stake_required": 60000000.0"
|
130
119
|
# }
|
131
120
|
#
|
132
|
-
# @return [Hash{Symbol=>String|Integer|Boolean}]
|
133
|
-
def bootstrap_status
|
134
|
-
rpc(:bootstrap_status)
|
135
|
-
end
|
136
|
-
|
137
|
-
# This call is for internal diagnostics/debug purposes only.
|
138
|
-
# Do not rely on this interface being stable and do not use in a
|
139
|
-
# production system.
|
140
|
-
#
|
141
|
-
# Returns block and tally weight (in raw) election duration (in
|
142
|
-
# milliseconds), election confirmation timestamp for recent elections
|
143
|
-
# winners.
|
144
|
-
#
|
145
|
-
# ==== Example:
|
146
|
-
#
|
147
|
-
# node.confirmation_history
|
148
|
-
#
|
149
|
-
# Example response:
|
150
|
-
#
|
151
|
-
# [
|
152
|
-
# {
|
153
|
-
# block: "EA70B32C55C193345D625F766EEA2FCA52D3F2CCE0B3A30838CC543026BB0FEA",
|
154
|
-
# tally: 80394786589602980996311817874549318248,
|
155
|
-
# duration: 4000,
|
156
|
-
# time: 1544819986,
|
157
|
-
# },
|
158
|
-
# {
|
159
|
-
# block: "F2F8DA6D2CA0A4D78EB043A7A29E12BDE5B4CE7DE1B99A93A5210428EE5B8667",
|
160
|
-
# tally: 68921714529890443063672782079965877749,
|
161
|
-
# duration: 6000,
|
162
|
-
# time: 1544819988,
|
163
|
-
# }
|
164
|
-
# ]
|
165
|
-
#
|
166
121
|
# @return [Hash{Symbol=>String|Integer}]
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
122
|
+
# @raise [Nanook::NanoUnitError] if `unit` is invalid
|
123
|
+
def confirmation_quorum(unit: Nanook.default_unit)
|
124
|
+
validate_unit!(unit)
|
125
|
+
|
126
|
+
response = rpc(:confirmation_quorum, _coerce: Hash)
|
127
|
+
|
128
|
+
return response unless unit == :nano
|
129
|
+
|
130
|
+
response[:quorum_delta] = raw_to_NANO(response[:quorum_delta])
|
131
|
+
response[:online_weight_minimum] = raw_to_NANO(response[:online_weight_minimum])
|
132
|
+
response[:online_stake_total] = raw_to_NANO(response[:online_stake_total])
|
133
|
+
response[:peers_stake_total] = raw_to_NANO(response[:peers_stake_total])
|
134
|
+
response[:peers_stake_required] = raw_to_NANO(response[:peers_stake_required])
|
135
|
+
|
136
|
+
response.compact
|
173
137
|
end
|
174
138
|
|
175
139
|
# Returns the difficulty values (16 hexadecimal digits string, 64 bit)
|
@@ -205,22 +169,35 @@ class Nanook
|
|
205
169
|
# that the first value is the most recent sample.
|
206
170
|
# @return [Hash{Symbol=>String|Float|Array}]
|
207
171
|
def difficulty(include_trend: false)
|
208
|
-
rpc(:active_difficulty, include_trend: include_trend).tap do |response|
|
172
|
+
rpc(:active_difficulty, include_trend: include_trend, _coerce: Hash).tap do |response|
|
209
173
|
response[:multiplier] = response[:multiplier].to_f
|
210
174
|
|
211
|
-
if response.key?(:difficulty_trend)
|
212
|
-
response[:difficulty_trend].map!(&:to_f)
|
213
|
-
end
|
175
|
+
response[:difficulty_trend].map!(&:to_f) if response.key?(:difficulty_trend)
|
214
176
|
end
|
215
177
|
end
|
216
178
|
|
217
179
|
# @return [String]
|
218
|
-
def
|
219
|
-
|
180
|
+
def to_s
|
181
|
+
self.class.name
|
220
182
|
end
|
183
|
+
alias inspect to_s
|
221
184
|
|
185
|
+
# Returns peers information.
|
186
|
+
#
|
187
|
+
# Example response:
|
188
|
+
#
|
189
|
+
# {
|
190
|
+
# :"[::ffff:104.131.102.132]:7075" => {
|
191
|
+
# protocol_version: 20,
|
192
|
+
# node_id: "node_1y7j5rdqhg99uyab1145gu3yur1ax35a3b6qr417yt8cd6n86uiw3d4whty3",
|
193
|
+
# type: "udp"
|
194
|
+
# },
|
195
|
+
# :"[::ffff:104.131.114.102]:7075" => { ... }
|
196
|
+
# }
|
197
|
+
#
|
198
|
+
# @return [Hash{Symbol=>Hash{Symbol=>Integer|String}}]
|
222
199
|
def peers
|
223
|
-
rpc(:peers
|
200
|
+
rpc(:peers, peer_details: true, _access: :peers, _coerce: Hash)
|
224
201
|
end
|
225
202
|
|
226
203
|
# All representatives and their voting weight.
|
@@ -232,59 +209,86 @@ class Nanook
|
|
232
209
|
# Example response:
|
233
210
|
#
|
234
211
|
# {
|
235
|
-
#
|
236
|
-
#
|
237
|
-
#
|
212
|
+
# Nanook::Account: 3822372327060170000000000000000000000,
|
213
|
+
# Nanook::Account: 30999999999999999999999999000000,
|
214
|
+
# Nanook::Account: 0
|
238
215
|
# }
|
239
216
|
#
|
240
|
-
# @return [Hash{
|
217
|
+
# @return [Hash{Nanook::Account=>Float|Integer}] known representatives and their voting weight
|
218
|
+
# @raise [Nanook::NanoUnitError] if `unit` is invalid
|
241
219
|
def representatives(unit: Nanook.default_unit)
|
242
|
-
|
243
|
-
raise ArgumentError.new("Unsupported unit: #{unit}")
|
244
|
-
end
|
220
|
+
validate_unit!(unit)
|
245
221
|
|
246
|
-
response = rpc(:representatives
|
247
|
-
return response if unit == :raw
|
222
|
+
response = rpc(:representatives, _access: :representatives, _coerce: Hash)
|
248
223
|
|
249
|
-
r = response.map do |account_id,
|
250
|
-
|
224
|
+
r = response.map do |account_id, weight|
|
225
|
+
weight = raw_to_NANO(weight) if unit == :nano
|
251
226
|
|
252
|
-
[account_id,
|
227
|
+
[as_account(account_id), weight]
|
253
228
|
end
|
254
229
|
|
255
|
-
Hash[r]
|
230
|
+
Hash[r]
|
256
231
|
end
|
257
232
|
|
258
|
-
# All online representatives that have voted recently
|
259
|
-
# design of the nano RPC, this method cannot return the voting weight
|
260
|
-
# of the representatives.
|
233
|
+
# All online representatives that have voted recently and their weight.
|
261
234
|
#
|
262
235
|
# ==== Example:
|
263
236
|
#
|
264
|
-
# node.representatives_online # => [
|
237
|
+
# node.representatives_online # => [Nanook::Account, ...]
|
265
238
|
#
|
266
|
-
# @return [
|
239
|
+
# @return [Nanook::Account] array of representative accounts
|
267
240
|
def representatives_online
|
268
|
-
rpc(:representatives_online
|
241
|
+
rpc(:representatives_online, _access: :representatives, _coerce: Array).map do |representative|
|
242
|
+
as_account(representative)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
# Tells the node to look for any account in all available wallets.
|
247
|
+
#
|
248
|
+
# ==== Example:
|
249
|
+
#
|
250
|
+
# node.search_pending #=> true
|
251
|
+
# @return [Boolean] indicates if the action was successful
|
252
|
+
def search_pending
|
253
|
+
rpc(:search_pending_all).key?(:success)
|
269
254
|
end
|
270
255
|
|
271
256
|
# Safely shuts down the node.
|
272
257
|
#
|
273
258
|
# @return [Boolean] indicating if action was successful
|
274
259
|
def stop
|
275
|
-
rpc(:stop).
|
260
|
+
rpc(:stop).key?(:success)
|
276
261
|
end
|
277
262
|
|
278
263
|
# @param limit [Integer] number of synchronizing blocks to return
|
264
|
+
# @param unit (see Nanook::Account#balance)
|
265
|
+
#
|
279
266
|
# @return [Hash{Symbol=>String}] information about the synchronizing blocks for this node
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
267
|
+
# @raise [Nanook::NanoUnitError] if `unit` is invalid
|
268
|
+
def synchronizing_blocks(limit: 1000, unit: Nanook.default_unit)
|
269
|
+
validate_unit!(unit)
|
270
|
+
|
271
|
+
params = {
|
272
|
+
count: limit,
|
273
|
+
json_block: true,
|
274
|
+
_access: :blocks,
|
275
|
+
_coerce: Hash
|
276
|
+
}
|
277
|
+
|
278
|
+
response = rpc(:unchecked, params).map do |block, info|
|
279
|
+
info[:account] = as_account(info[:account]) if info[:account]
|
280
|
+
info[:link_as_account] = as_account(info[:link_as_account]) if info[:link_as_account]
|
281
|
+
info[:representative] = as_account(info[:representative]) if info[:representative]
|
282
|
+
info[:previous] = as_block(info[:previous]) if info[:previous]
|
283
|
+
info[:link] = as_block(info[:link]) if info[:link]
|
284
|
+
info[:balance] = raw_to_NANO(info[:balance]) if unit == :nano && info[:balance]
|
285
|
+
|
286
|
+
[as_block(block), info]
|
284
287
|
end
|
285
|
-
|
288
|
+
|
289
|
+
Hash[response]
|
286
290
|
end
|
287
|
-
|
291
|
+
alias unchecked synchronizing_blocks
|
288
292
|
|
289
293
|
# The percentage completeness of the synchronization process for
|
290
294
|
# your node as it downloads the nano ledger. Note, it's normal for
|
@@ -295,11 +299,11 @@ class Nanook
|
|
295
299
|
# @return [Float] the percentage completeness of the synchronization
|
296
300
|
# process for your node
|
297
301
|
def sync_progress
|
298
|
-
response = rpc(:block_count)
|
302
|
+
response = rpc(:block_count, _coerce: Hash)
|
299
303
|
|
300
304
|
count = response[:count]
|
301
305
|
unchecked = response[:unchecked]
|
302
|
-
total =
|
306
|
+
total = count + unchecked
|
303
307
|
|
304
308
|
count.to_f * 100 / total.to_f
|
305
309
|
end
|
@@ -308,29 +312,57 @@ class Nanook
|
|
308
312
|
#
|
309
313
|
# @return [Integer] seconds of uptime
|
310
314
|
def uptime
|
311
|
-
rpc(:uptime)
|
315
|
+
rpc(:uptime, _access: :seconds, _coerce: Hash)
|
316
|
+
end
|
317
|
+
|
318
|
+
# Sets the receive minimum for wallets on the node. The value is in +Nano+ by default.
|
319
|
+
# To specify an amount in +raw+, pass the argument +unit: :raw+.
|
320
|
+
#
|
321
|
+
# ==== Example:
|
322
|
+
#
|
323
|
+
# account.change_receive_minimum(0.01) # true
|
324
|
+
#
|
325
|
+
# @return [Boolean] true if the action was successful
|
326
|
+
# @param minimum Amount to set as the receive minimum
|
327
|
+
# @param unit optional. Specify +raw+ if you want to set the amount in +raw+. (See Nanook::Account#balance)
|
328
|
+
# @raise [Nanook::NanoUnitError] if `unit` is invalid
|
329
|
+
def change_receive_minimum(minimum, unit: Nanook.default_unit)
|
330
|
+
validate_unit!(unit)
|
331
|
+
|
332
|
+
minimum = NANO_to_raw(minimum) if unit == :nano
|
333
|
+
|
334
|
+
rpc(:receive_minimum_set, amount: minimum).key?(:success)
|
312
335
|
end
|
313
336
|
|
314
|
-
#
|
315
|
-
#
|
337
|
+
# Returns receive minimum for wallets on the node.
|
338
|
+
#
|
339
|
+
# ==== Example:
|
340
|
+
#
|
341
|
+
# account.receive_minimum # => 0.01
|
316
342
|
#
|
317
|
-
# @return [
|
318
|
-
|
319
|
-
|
320
|
-
|
343
|
+
# @return [Integer|Float] the receive minimum
|
344
|
+
# @param unit (see Nanook::Account#balance)
|
345
|
+
# @raise [Nanook::NanoUnitError] if `unit` is invalid
|
346
|
+
def receive_minimum(unit: Nanook.default_unit)
|
347
|
+
validate_unit!(unit)
|
348
|
+
|
349
|
+
amount = rpc(:receive_minimum, _access: :amount)
|
350
|
+
|
351
|
+
return amount unless unit == :nano
|
352
|
+
|
353
|
+
raw_to_NANO(amount)
|
321
354
|
end
|
322
355
|
|
323
356
|
# @return [Hash{Symbol=>Integer|String}] version information for this node
|
324
357
|
def version
|
325
|
-
rpc(:version)
|
358
|
+
rpc(:version, _coerce: Hash)
|
326
359
|
end
|
327
|
-
|
360
|
+
alias info version
|
328
361
|
|
329
362
|
private
|
330
363
|
|
331
|
-
def rpc(action, params={})
|
364
|
+
def rpc(action, params = {})
|
332
365
|
@rpc.call(action, params)
|
333
366
|
end
|
334
|
-
|
335
367
|
end
|
336
368
|
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'util'
|
4
|
+
|
5
|
+
class Nanook
|
6
|
+
# The <tt>Nanook::PrivateKey</tt> class lets you manage your node's keys.
|
7
|
+
class PrivateKey
|
8
|
+
include Nanook::Util
|
9
|
+
|
10
|
+
def initialize(rpc, key = nil)
|
11
|
+
@rpc = rpc
|
12
|
+
@key = key.to_s if key
|
13
|
+
end
|
14
|
+
|
15
|
+
def id
|
16
|
+
@key
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param other [Nanook::PrivateKey] private key to compare
|
20
|
+
# @return [Boolean] true if keys are equal
|
21
|
+
def ==(other)
|
22
|
+
other.class == self.class &&
|
23
|
+
other.id == id
|
24
|
+
end
|
25
|
+
alias eql? ==
|
26
|
+
|
27
|
+
# The hash value is used along with #eql? by the Hash class to determine if two objects
|
28
|
+
# reference the same hash key.
|
29
|
+
#
|
30
|
+
# @return [Integer]
|
31
|
+
def hash
|
32
|
+
id.hash
|
33
|
+
end
|
34
|
+
|
35
|
+
# Generate a new private public key pair. Returns the new {Nanook::PrivateKey}.
|
36
|
+
# The public key can be retrieved by calling `#public_key` on the private key.
|
37
|
+
#
|
38
|
+
# ==== Examples:
|
39
|
+
#
|
40
|
+
# private_key = nanook.private_key.create
|
41
|
+
# private_key.public_key # => Nanook::PublicKey pair for the private key
|
42
|
+
#
|
43
|
+
# deterministic_private_key = nanook.private_key.create(seed: seed, index: 0)
|
44
|
+
#
|
45
|
+
# @param seed [String] optional seed to generate a deterministic private key.
|
46
|
+
# @param index [Integer] optional (but required if +seed+ is given) index to generate a deterministic private key.
|
47
|
+
# @return Nanook::PrivateKey
|
48
|
+
def create(seed: nil, index: nil)
|
49
|
+
skip_key_required!
|
50
|
+
|
51
|
+
params = {
|
52
|
+
_access: :private,
|
53
|
+
_coerce: Hash
|
54
|
+
}
|
55
|
+
|
56
|
+
@key = if seed.nil?
|
57
|
+
rpc(:key_create, params)
|
58
|
+
else
|
59
|
+
raise ArgumentError, 'index argument is required when seed is given' if index.nil?
|
60
|
+
|
61
|
+
rpc(:deterministic_key, params.merge(seed: seed, index: index))
|
62
|
+
end
|
63
|
+
|
64
|
+
self
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns the {Nanook::Account} that matches this private key. The
|
68
|
+
# account may not exist yet in the ledger.
|
69
|
+
#
|
70
|
+
# @return Nanook::Account
|
71
|
+
def account
|
72
|
+
as_account(memoized_key_expand[:account])
|
73
|
+
end
|
74
|
+
|
75
|
+
# Returns the {Nanook::PublicKey} pair for this private key.
|
76
|
+
#
|
77
|
+
# @return Nanook::PublicKey
|
78
|
+
def public_key
|
79
|
+
as_public_key(memoized_key_expand[:public])
|
80
|
+
end
|
81
|
+
|
82
|
+
# @return [String]
|
83
|
+
def to_s
|
84
|
+
"#{self.class.name}(id: \"#{short_id}\")"
|
85
|
+
end
|
86
|
+
alias inspect to_s
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def memoized_key_expand
|
91
|
+
@memoized_key_expand ||= rpc(:key_expand, _coerce: Hash)
|
92
|
+
end
|
93
|
+
|
94
|
+
def rpc(action, params = {})
|
95
|
+
check_key_required!
|
96
|
+
|
97
|
+
p = { key: @key }.compact
|
98
|
+
@rpc.call(action, p.merge(params)).tap { reset_skip_key_required! }
|
99
|
+
end
|
100
|
+
|
101
|
+
def skip_key_required!
|
102
|
+
@skip_key_required_check = true
|
103
|
+
end
|
104
|
+
|
105
|
+
def reset_skip_key_required!
|
106
|
+
@skip_key_required_check = false
|
107
|
+
end
|
108
|
+
|
109
|
+
def check_key_required!
|
110
|
+
return if @key || @skip_key_required_check
|
111
|
+
|
112
|
+
raise ArgumentError, 'Key must be present'
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|