nanook 1.0.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +37 -3
- data/README.md +40 -10
- data/lib/nanook.rb +70 -16
- data/lib/nanook/account.rb +183 -129
- data/lib/nanook/block.rb +61 -50
- data/lib/nanook/key.rb +1 -1
- data/lib/nanook/node.rb +14 -5
- data/lib/nanook/rpc.rb +6 -6
- data/lib/nanook/util.rb +2 -2
- data/lib/nanook/version.rb +1 -1
- data/lib/nanook/wallet.rb +147 -41
- data/lib/nanook/wallet_account.rb +74 -52
- data/lib/nanook/work_peer.rb +1 -1
- metadata +14 -21
- data/.circleci/config.yml +0 -56
- data/.gitignore +0 -9
- data/.rspec +0 -1
- data/Gemfile +0 -6
- data/Gemfile.lock +0 -65
- data/Rakefile +0 -20
- data/img/qr.png +0 -0
- data/nanook.gemspec +0 -34
data/lib/nanook/block.rb
CHANGED
@@ -10,7 +10,7 @@ class Nanook
|
|
10
10
|
# Initialize this class through the convenient Nanook#block method:
|
11
11
|
#
|
12
12
|
# nanook = Nanook.new
|
13
|
-
#
|
13
|
+
# block = nanook.block("FBF8B0E...")
|
14
14
|
#
|
15
15
|
# Or compose the longhand way like this:
|
16
16
|
#
|
@@ -24,22 +24,23 @@ class Nanook
|
|
24
24
|
block_required! # All methods expect a block
|
25
25
|
end
|
26
26
|
|
27
|
-
# Returns
|
27
|
+
# Returns the {Nanook::Account} of the block.
|
28
28
|
#
|
29
|
-
# ==== Example
|
29
|
+
# ==== Example:
|
30
|
+
# block.account # => Nanook::Account
|
30
31
|
#
|
31
|
-
#
|
32
|
+
# @return [Nanook::Account] the account of the block
|
32
33
|
def account
|
33
|
-
rpc(:block_account, :hash)[:account]
|
34
|
+
Nanook::Account.new(@rpc, rpc(:block_account, :hash)[:account])
|
34
35
|
end
|
35
36
|
|
36
37
|
# Stop generating work for a block.
|
37
38
|
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
# ==== Example
|
39
|
+
# ==== Example:
|
41
40
|
#
|
42
41
|
# block.cancel_work # => true
|
42
|
+
#
|
43
|
+
# @return [Boolean] signalling if the action was successful
|
43
44
|
def cancel_work
|
44
45
|
rpc(:work_cancel, :hash).empty?
|
45
46
|
end
|
@@ -49,20 +50,17 @@ class Nanook
|
|
49
50
|
#
|
50
51
|
# See also #successors.
|
51
52
|
#
|
52
|
-
# ====
|
53
|
-
#
|
54
|
-
# [+limit:+] Maximum number of block hashes to return (default is 1000)
|
55
|
-
#
|
56
|
-
# ==== Example
|
53
|
+
# ==== Example:
|
57
54
|
#
|
58
55
|
# block.chain(limit: 2)
|
59
56
|
#
|
60
|
-
# ==== Example reponse
|
57
|
+
# ==== Example reponse:
|
61
58
|
#
|
62
59
|
# [
|
63
60
|
# "36A0FB717368BA8CF8D255B63DC207771EABC6C6FFC22A7F455EC2209464897E",
|
64
61
|
# "FBF8B0E6623A31AB528EBD839EEAA91CAFD25C12294C46754E45FD017F7939EB"
|
65
62
|
# ]
|
63
|
+
# @param limit [Integer] maximum number of block hashes to return (default is 1000)
|
66
64
|
def chain(limit: 1000)
|
67
65
|
response = rpc(:chain, :block, count: limit)[:blocks]
|
68
66
|
Nanook::Util.coerce_empty_string_to_type(response, Array)
|
@@ -70,9 +68,10 @@ class Nanook
|
|
70
68
|
|
71
69
|
# Generate work for a block.
|
72
70
|
#
|
73
|
-
#
|
74
|
-
#
|
71
|
+
# ==== Example:
|
75
72
|
# block.generate_work # => "2bf29ef00786a6bc"
|
73
|
+
#
|
74
|
+
# @return [String] the work id of the work completed.
|
76
75
|
def generate_work
|
77
76
|
rpc(:work_generate, :hash)[:work]
|
78
77
|
end
|
@@ -80,16 +79,11 @@ class Nanook
|
|
80
79
|
# Returns Array of Hashes containing information about a chain of
|
81
80
|
# send/receive blocks, starting from this block.
|
82
81
|
#
|
83
|
-
# ====
|
84
|
-
#
|
85
|
-
# [+limit:+] Maximum number of send/receive block hashes to return
|
86
|
-
# in the chain (default is 1000)
|
87
|
-
#
|
88
|
-
# ==== Example
|
82
|
+
# ==== Example:
|
89
83
|
#
|
90
84
|
# block.history(limit: 1)
|
91
85
|
#
|
92
|
-
# ==== Example response
|
86
|
+
# ==== Example response:
|
93
87
|
#
|
94
88
|
# [
|
95
89
|
# {
|
@@ -99,27 +93,35 @@ class Nanook
|
|
99
93
|
# :type=>"send"
|
100
94
|
# }
|
101
95
|
# ]
|
96
|
+
#
|
97
|
+
# @param limit [Integer] maximum number of send/receive block hashes
|
98
|
+
# to return in the chain (default is 1000)
|
102
99
|
def history(limit: 1000)
|
103
100
|
rpc(:history, :hash, count: limit)[:history]
|
104
101
|
end
|
105
102
|
|
106
|
-
# Returns the block hash
|
103
|
+
# Returns the block hash id.
|
104
|
+
#
|
105
|
+
# ==== Example:
|
107
106
|
#
|
108
107
|
# block.id #=> "FBF8B0E..."
|
108
|
+
#
|
109
|
+
# @return [String] the block hash id
|
109
110
|
def id
|
110
111
|
@block
|
111
112
|
end
|
112
113
|
|
113
114
|
# Returns a Hash of information about the block.
|
114
115
|
#
|
115
|
-
# ====
|
116
|
+
# ==== Examples:
|
117
|
+
#
|
118
|
+
# block.info
|
119
|
+
# block.info(allow_unchecked: true)
|
116
120
|
#
|
117
|
-
#
|
118
|
-
# information can be returned about blocks that
|
119
|
-
# are unchecked (unverified).
|
120
|
-
# ==== Example response
|
121
|
+
# ==== Example response:
|
121
122
|
#
|
122
123
|
# {
|
124
|
+
# :id=>"36A0FB717368BA8CF8D255B63DC207771EABC6C6FFC22A7F455EC2209464897E",
|
123
125
|
# :type=>"send",
|
124
126
|
# :previous=>"FBF8B0E6623A31AB528EBD839EEAA91CAFD25C12294C46754E45FD017F7939EB",
|
125
127
|
# :destination=>"xrb_3x7cjioqahgs5ppheys6prpqtb4rdknked83chf97bot1unrbdkaux37t31b",
|
@@ -127,23 +129,28 @@ class Nanook
|
|
127
129
|
# :work=>"44cc24b60705083a",
|
128
130
|
# :signature=>"42ADFEFE7C3FFF188AE92A202F8A5734DE91779C454613E446EEC93D001D6C953E9FD16730AF32C891791BA8EDAECEB059A213E2FE1EEB7ADF9D5D0815464D06"
|
129
131
|
# }
|
132
|
+
#
|
133
|
+
# @param allow_unchecked [Boolean] (default is +false+). If +true+,
|
134
|
+
# information can be returned about blocks that are unchecked (unverified).
|
130
135
|
def info(allow_unchecked: false)
|
131
136
|
if allow_unchecked
|
132
|
-
# TODO not actually sure what this response looks like when it's not an unchecked block, assuming its blank
|
133
137
|
response = rpc(:unchecked_get, :hash)
|
134
|
-
|
135
|
-
return _parse_info_response(response
|
138
|
+
unless response.has_key?(:error)
|
139
|
+
return _parse_info_response(response)
|
136
140
|
end
|
137
|
-
#
|
141
|
+
# If unchecked not found, continue to checked block
|
138
142
|
end
|
139
143
|
|
140
144
|
response = rpc(:block, :hash)
|
141
145
|
_parse_info_response(response)
|
142
146
|
end
|
143
147
|
|
144
|
-
#
|
148
|
+
# ==== Example:
|
145
149
|
#
|
146
150
|
# block.is_valid_work?("2bf29ef00786a6bc") # => true
|
151
|
+
#
|
152
|
+
# @param work [String] the work id to check is valid
|
153
|
+
# @return [Boolean] signalling if work is valid for the block
|
147
154
|
def is_valid_work?(work)
|
148
155
|
response = rpc(:work_validate, :hash, work: work)
|
149
156
|
!response.empty? && response[:valid] == 1
|
@@ -152,13 +159,14 @@ class Nanook
|
|
152
159
|
# Republish blocks starting at this block up the account chain
|
153
160
|
# back to the nano network.
|
154
161
|
#
|
155
|
-
#
|
162
|
+
# @return [Array<String>] block hashes that were republished
|
156
163
|
#
|
157
|
-
# ==== Example
|
164
|
+
# ==== Example:
|
158
165
|
#
|
159
166
|
# block.republish
|
160
167
|
#
|
161
|
-
# ==== Example response
|
168
|
+
# ==== Example response:
|
169
|
+
#
|
162
170
|
# ["36A0FB717368BA8CF8D255B63DC207771EABC6C6FFC22A7F455EC2209464897E"]
|
163
171
|
def republish(destinations:nil, sources:nil)
|
164
172
|
if !destinations.nil? && !sources.nil?
|
@@ -174,9 +182,11 @@ class Nanook
|
|
174
182
|
rpc(:republish, :hash, params)[:blocks]
|
175
183
|
end
|
176
184
|
|
177
|
-
#
|
185
|
+
# ==== Example:
|
178
186
|
#
|
179
187
|
# block.pending? #=> false
|
188
|
+
#
|
189
|
+
# @return [Boolean] signalling if the block is a pending block.
|
180
190
|
def pending?
|
181
191
|
response = rpc(:pending_exists, :hash)
|
182
192
|
!response.empty? && response[:exists] == 1
|
@@ -186,12 +196,13 @@ class Nanook
|
|
186
196
|
#
|
187
197
|
# Note, if block has previously been published, use #republish instead.
|
188
198
|
#
|
189
|
-
#
|
199
|
+
# ==== Examples:
|
190
200
|
#
|
191
201
|
# block.publish # => "FBF8B0E..."
|
202
|
+
#
|
203
|
+
# @return [String] the block hash, or false.
|
192
204
|
def publish
|
193
|
-
|
194
|
-
rpc(:process, :block)[:hash]
|
205
|
+
rpc(:process, :block)[:hash] || false
|
195
206
|
end
|
196
207
|
alias_method :process, :publish
|
197
208
|
|
@@ -200,24 +211,23 @@ class Nanook
|
|
200
211
|
#
|
201
212
|
# See also #chain.
|
202
213
|
#
|
203
|
-
# ====
|
204
|
-
#
|
205
|
-
# [+limit:+] Maximum number of send/receive block hashes to return
|
206
|
-
# in the chain (default is 1000)
|
207
|
-
#
|
208
|
-
# ==== Example
|
214
|
+
# ==== Example:
|
209
215
|
#
|
210
216
|
# block.successors
|
211
217
|
#
|
212
|
-
# ==== Example response
|
218
|
+
# ==== Example response:
|
213
219
|
#
|
214
220
|
# ["36A0FB717368BA8CF8D255B63DC207771EABC6C6FFC22A7F455EC2209464897E"]
|
221
|
+
#
|
222
|
+
# @param limit [Integer] maximum number of send/receive block hashes
|
223
|
+
# to return in the chain (default is 1000)
|
224
|
+
# @return [Array<String>] block hashes in the account chain ending at this block
|
215
225
|
def successors(limit: 1000)
|
216
226
|
response = rpc(:successors, :block, count: limit)[:blocks]
|
217
227
|
Nanook::Util.coerce_empty_string_to_type(response, Array)
|
218
228
|
end
|
219
229
|
|
220
|
-
def inspect
|
230
|
+
def inspect
|
221
231
|
"#{self.class.name}(id: \"#{id}\", object_id: \"#{"0x00%x" % (object_id << 1)}\")"
|
222
232
|
end
|
223
233
|
|
@@ -240,7 +250,8 @@ class Nanook
|
|
240
250
|
def _parse_info_response(response)
|
241
251
|
# The contents is a stringified JSON
|
242
252
|
if response[:contents]
|
243
|
-
|
253
|
+
r = JSON.parse(response[:contents]).to_symbolized_hash
|
254
|
+
return r.merge(id: id)
|
244
255
|
end
|
245
256
|
|
246
257
|
response
|
data/lib/nanook/key.rb
CHANGED
data/lib/nanook/node.rb
CHANGED
@@ -5,6 +5,11 @@ class Nanook
|
|
5
5
|
@rpc = rpc
|
6
6
|
end
|
7
7
|
|
8
|
+
def account_count
|
9
|
+
rpc(:frontier_count)[:count]
|
10
|
+
end
|
11
|
+
alias_method :frontier_count, :account_count
|
12
|
+
|
8
13
|
def block_count
|
9
14
|
rpc(:block_count)
|
10
15
|
end
|
@@ -21,11 +26,7 @@ class Nanook
|
|
21
26
|
rpc(:bootstrap_any).has_key?(:success)
|
22
27
|
end
|
23
28
|
|
24
|
-
def
|
25
|
-
rpc(:frontier_count)[:count]
|
26
|
-
end
|
27
|
-
|
28
|
-
def inspect # :nodoc:
|
29
|
+
def inspect
|
29
30
|
"#{self.class.name}(object_id: \"#{"0x00%x" % (object_id << 1)}\")"
|
30
31
|
end
|
31
32
|
|
@@ -41,6 +42,14 @@ class Nanook
|
|
41
42
|
rpc(:stop).has_key?(:success)
|
42
43
|
end
|
43
44
|
|
45
|
+
def synchronizing_blocks(limit: 1000)
|
46
|
+
response = rpc(:unchecked, count: limit)[:blocks]
|
47
|
+
response = response.map do |block, info|
|
48
|
+
[block, JSON.parse(info).to_symbolized_hash]
|
49
|
+
end
|
50
|
+
Hash[response.sort].to_symbolized_hash
|
51
|
+
end
|
52
|
+
|
44
53
|
def sync_progress
|
45
54
|
response = rpc(:block_count)
|
46
55
|
|
data/lib/nanook/rpc.rb
CHANGED
@@ -8,15 +8,15 @@ class Nanook
|
|
8
8
|
DEFAULT_TIMEOUT = 500 # seconds
|
9
9
|
|
10
10
|
def initialize(uri=DEFAULT_URI, timeout:DEFAULT_TIMEOUT)
|
11
|
-
rpc_server = URI(uri)
|
11
|
+
@rpc_server = URI(uri)
|
12
12
|
|
13
|
-
unless ['http', 'https'].include?(rpc_server.scheme)
|
13
|
+
unless ['http', 'https'].include?(@rpc_server.scheme)
|
14
14
|
raise ArgumentError.new("URI must have http or https in it. Was given: #{uri}")
|
15
15
|
end
|
16
16
|
|
17
|
-
@http = Net::HTTP.new(rpc_server.host, rpc_server.port)
|
17
|
+
@http = Net::HTTP.new(@rpc_server.host, @rpc_server.port)
|
18
18
|
@http.read_timeout = timeout
|
19
|
-
@request = Net::HTTP::Post.new(rpc_server.request_uri, {"user-agent" => "Ruby nanook gem"})
|
19
|
+
@request = Net::HTTP::Post.new(@rpc_server.request_uri, {"user-agent" => "Ruby nanook gem"})
|
20
20
|
@request.content_type = "application/json"
|
21
21
|
end
|
22
22
|
|
@@ -36,8 +36,8 @@ class Nanook
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
def inspect
|
40
|
-
"#{self.class.name}(host: #{@
|
39
|
+
def inspect
|
40
|
+
"#{self.class.name}(host: \"#{@rpc_server}\", timeout: #{@http.read_timeout} object_id: \"#{"0x00%x" % (object_id << 1)}\")"
|
41
41
|
end
|
42
42
|
|
43
43
|
private
|
data/lib/nanook/util.rb
CHANGED
@@ -10,11 +10,11 @@ class Nanook
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.raw_to_NANO(raw)
|
13
|
-
raw.to_f / STEP
|
13
|
+
(raw.to_f / STEP).to_f
|
14
14
|
end
|
15
15
|
|
16
16
|
def self.coerce_empty_string_to_type(response, type)
|
17
|
-
if response == ""
|
17
|
+
if response == "" || response.nil?
|
18
18
|
return type.new
|
19
19
|
end
|
20
20
|
|
data/lib/nanook/version.rb
CHANGED
data/lib/nanook/wallet.rb
CHANGED
@@ -20,12 +20,12 @@ class Nanook
|
|
20
20
|
# Initialize this class through the convenient Nanook#wallet method:
|
21
21
|
#
|
22
22
|
# nanook = Nanook.new
|
23
|
-
# wallet = nanook.wallet(
|
23
|
+
# wallet = nanook.wallet(wallet_id)
|
24
24
|
#
|
25
25
|
# Or compose the longhand way like this:
|
26
26
|
#
|
27
27
|
# rpc_conn = Nanook::Rpc.new
|
28
|
-
# wallet = Nanook::Wallet.new(rpc_conn,
|
28
|
+
# wallet = Nanook::Wallet.new(rpc_conn, wallet_id)
|
29
29
|
class Wallet
|
30
30
|
|
31
31
|
def initialize(rpc, wallet)
|
@@ -58,18 +58,17 @@ class Nanook
|
|
58
58
|
Nanook::WalletAccount.new(@rpc, @wallet, account)
|
59
59
|
end
|
60
60
|
|
61
|
-
#
|
61
|
+
# ==== Example:
|
62
62
|
#
|
63
|
-
#
|
63
|
+
# wallet.accounts # => [Nanook::WalletAccount, Nanook::WalletAccount...]
|
64
64
|
#
|
65
|
-
#
|
66
|
-
# "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000",
|
67
|
-
# "xrb_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx"
|
68
|
-
# ]
|
65
|
+
# @return [Array<Nanook::WalletAccount>] all accounts in the wallet
|
69
66
|
def accounts
|
70
67
|
wallet_required!
|
71
68
|
response = rpc(:account_list)[:accounts]
|
72
|
-
Nanook::Util.coerce_empty_string_to_type(response, Array)
|
69
|
+
Nanook::Util.coerce_empty_string_to_type(response, Array).map do |account|
|
70
|
+
Nanook::WalletAccount.new(@rpc, @wallet, account)
|
71
|
+
end
|
73
72
|
end
|
74
73
|
|
75
74
|
# Returns a Hash containing the balance of all accounts in the
|
@@ -123,10 +122,10 @@ class Nanook
|
|
123
122
|
# "pending"=>0
|
124
123
|
# },
|
125
124
|
# }
|
126
|
-
def balance(account_break_down: false, unit: Nanook
|
125
|
+
def balance(account_break_down: false, unit: Nanook.default_unit)
|
127
126
|
wallet_required!
|
128
127
|
|
129
|
-
unless Nanook::
|
128
|
+
unless Nanook::UNITS.include?(unit)
|
130
129
|
raise ArgumentError.new("Unsupported unit: #{unit}")
|
131
130
|
end
|
132
131
|
|
@@ -149,31 +148,28 @@ class Nanook
|
|
149
148
|
end
|
150
149
|
end
|
151
150
|
|
152
|
-
#
|
153
|
-
#
|
154
|
-
# Nanook.new.wallet.create
|
151
|
+
# Changes a wallet's seed.
|
155
152
|
#
|
156
|
-
#
|
157
|
-
#
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
# wallet
|
153
|
+
# @param seed [String] the seed to change to.
|
154
|
+
# @return [Boolean] indicating whether the change was successful.
|
155
|
+
def change_seed(seed)
|
156
|
+
wallet_required!
|
157
|
+
rpc(:wallet_change_seed, seed: seed).has_key?(:success)
|
158
|
+
end
|
159
|
+
|
160
|
+
# Creates a new wallet.
|
164
161
|
#
|
165
|
-
#
|
166
|
-
# you
|
167
|
-
#
|
168
|
-
# the seed over secure (SSH or SSL) networks and do not store it where
|
169
|
-
# it is able to be easily comprised by a hacker, which includes your
|
170
|
-
# personal computer.
|
162
|
+
# The wallet will be created only on this node. It's important that
|
163
|
+
# if you intend to add funds to accounts in this wallet that you
|
164
|
+
# backup the wallet *seed* in order to restore the wallet in future.
|
171
165
|
#
|
172
|
-
# ==== Example
|
166
|
+
# ==== Example:
|
167
|
+
# Nanook.new.wallet.create # => Nanook::Wallet
|
173
168
|
#
|
174
|
-
#
|
169
|
+
# @return [Nanook::Wallet]
|
175
170
|
def create
|
176
|
-
rpc(:wallet_create)[:wallet]
|
171
|
+
@wallet = rpc(:wallet_create)[:wallet]
|
172
|
+
self
|
177
173
|
end
|
178
174
|
|
179
175
|
# Destroy the wallet. Returns a boolean indicating whether the action
|
@@ -214,8 +210,9 @@ class Nanook
|
|
214
210
|
def id
|
215
211
|
@wallet
|
216
212
|
end
|
213
|
+
alias_method :seed, :id
|
217
214
|
|
218
|
-
def inspect
|
215
|
+
def inspect
|
219
216
|
"#{self.class.name}(id: \"#{id}\", object_id: \"#{"0x00%x" % (object_id << 1)}\")"
|
220
217
|
end
|
221
218
|
|
@@ -252,12 +249,94 @@ class Nanook
|
|
252
249
|
# Or:
|
253
250
|
#
|
254
251
|
# "Account not found"
|
255
|
-
def pay(from:, to:, amount:, unit: Nanook
|
252
|
+
def pay(from:, to:, amount:, unit: Nanook.default_unit, id:)
|
256
253
|
wallet_required!
|
257
254
|
validate_wallet_contains_account!(from)
|
258
255
|
account(from).pay(to: to, amount: amount, unit: unit, id: id)
|
259
256
|
end
|
260
257
|
|
258
|
+
# Returns information about pending blocks (payments) that are waiting
|
259
|
+
# to be received by accounts in this wallet.
|
260
|
+
#
|
261
|
+
# See also the #receive method of this class for how to receive a pending payment.
|
262
|
+
#
|
263
|
+
# @param limit [Integer] number of accounts with pending payments to return (default is 1000)
|
264
|
+
# @param detailed [Boolean]return a more complex Hash of pending block information (default is +false+)
|
265
|
+
# @param unit (see Nanook::Account#balance)
|
266
|
+
#
|
267
|
+
# ==== Example 1:
|
268
|
+
#
|
269
|
+
# wallet.pending
|
270
|
+
#
|
271
|
+
# ==== Example 1 response:
|
272
|
+
# {
|
273
|
+
# :xrb_1111111111111111111111111111111111111111111111111117353trpda=>[
|
274
|
+
# "142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D",
|
275
|
+
# "718CC2121C3E641059BC1C2CFC45666C99E8AE922F7A807B7D07B62C995D79E2"
|
276
|
+
# ],
|
277
|
+
# :xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3=>[
|
278
|
+
# "4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74"
|
279
|
+
# ]
|
280
|
+
# }
|
281
|
+
# ==== Example 2:
|
282
|
+
#
|
283
|
+
# wallet.pending(detailed: true)
|
284
|
+
#
|
285
|
+
# ==== Example 2 response:
|
286
|
+
# {
|
287
|
+
# :xrb_1111111111111111111111111111111111111111111111111117353trpda=>[
|
288
|
+
# {
|
289
|
+
# :amount=>6.0,
|
290
|
+
# :source=>"xrb_3dcfozsmekr1tr9skf1oa5wbgmxt81qepfdnt7zicq5x3hk65fg4fqj58mbr",
|
291
|
+
# :block=>:"142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D"
|
292
|
+
# },
|
293
|
+
# {
|
294
|
+
# :amount=>12.0,
|
295
|
+
# :source=>"xrb_3dcfozsmekr1tr9skf1oa5wbgmxt81qepfdnt7zicq5x3hk65fg4fqj58mbr",
|
296
|
+
# :block=>:"242A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D"
|
297
|
+
# }
|
298
|
+
# ],
|
299
|
+
# :xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3=>[
|
300
|
+
# {
|
301
|
+
# :amount=>106.370018,
|
302
|
+
# :source=>"xrb_13ezf4od79h1tgj9aiu4djzcmmguendtjfuhwfukhuucboua8cpoihmh8byo",
|
303
|
+
# :block=>:"4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74"
|
304
|
+
# }
|
305
|
+
# ]
|
306
|
+
# }
|
307
|
+
def pending(limit:1000, detailed:false, unit:Nanook.default_unit)
|
308
|
+
wallet_required!
|
309
|
+
|
310
|
+
unless Nanook::UNITS.include?(unit)
|
311
|
+
raise ArgumentError.new("Unsupported unit: #{unit}")
|
312
|
+
end
|
313
|
+
|
314
|
+
params = { count: limit }
|
315
|
+
params[:source] = true if detailed
|
316
|
+
|
317
|
+
response = rpc(:wallet_pending, params)[:blocks]
|
318
|
+
response = Nanook::Util.coerce_empty_string_to_type(response, Hash)
|
319
|
+
|
320
|
+
return response unless detailed
|
321
|
+
|
322
|
+
# Map the RPC response, which is:
|
323
|
+
# account=>block=>[amount|source] into
|
324
|
+
# account=>[block|amount|source]
|
325
|
+
x = response.map do |account, data|
|
326
|
+
new_data = data.map do |block, amount_and_source|
|
327
|
+
d = amount_and_source.merge(block: block.to_s)
|
328
|
+
if unit == :nano
|
329
|
+
d[:amount] = Nanook::Util.raw_to_NANO(d[:amount])
|
330
|
+
end
|
331
|
+
d
|
332
|
+
end
|
333
|
+
|
334
|
+
[account, new_data]
|
335
|
+
end
|
336
|
+
|
337
|
+
Hash[x].to_symbolized_hash
|
338
|
+
end
|
339
|
+
|
261
340
|
# Receives a pending payment into an account in the wallet.
|
262
341
|
#
|
263
342
|
# When called with no +block+ argument, the latest pending payment
|
@@ -294,6 +373,33 @@ class Nanook
|
|
294
373
|
account(into).receive(block)
|
295
374
|
end
|
296
375
|
|
376
|
+
# Restore a previously created wallet by its seed.
|
377
|
+
# A new wallet will be created on your node (with a new wallet id)
|
378
|
+
# and will have its seed set to the given seed.
|
379
|
+
#
|
380
|
+
# ==== Example:
|
381
|
+
#
|
382
|
+
# Nanook.new.wallet.restore(seed) # => Nanook::Wallet
|
383
|
+
#
|
384
|
+
# @param seed [String] the wallet seed to restore.
|
385
|
+
# @param accounts [Integer] optionally restore the given number of accounts for the wallet.
|
386
|
+
#
|
387
|
+
# @return [Nanook::Wallet] a new wallet
|
388
|
+
# @raise [Nanook::Error] if unsuccessful
|
389
|
+
def restore(seed, accounts:0)
|
390
|
+
create
|
391
|
+
|
392
|
+
unless change_seed(seed)
|
393
|
+
raise Nanook::Error.new("Unable to set seed for wallet")
|
394
|
+
end
|
395
|
+
|
396
|
+
if accounts > 0
|
397
|
+
account.create(accounts)
|
398
|
+
end
|
399
|
+
|
400
|
+
self
|
401
|
+
end
|
402
|
+
|
297
403
|
# Returns a boolean to indicate if the wallet is locked.
|
298
404
|
#
|
299
405
|
# ==== Example response
|
@@ -305,23 +411,23 @@ class Nanook
|
|
305
411
|
!response.empty? && response[:locked] != 0
|
306
412
|
end
|
307
413
|
|
308
|
-
# Unlocks a previously locked wallet.
|
309
|
-
# if the action was successful.
|
414
|
+
# Unlocks a previously locked wallet.
|
310
415
|
#
|
311
|
-
# ==== Example
|
416
|
+
# ==== Example:
|
312
417
|
#
|
313
|
-
# true
|
418
|
+
# wallet.unlock("new_pass") #=> true
|
419
|
+
# @return [Boolean] indicates if the action was successful
|
314
420
|
def unlock(password)
|
315
421
|
wallet_required!
|
316
422
|
rpc(:password_enter, password: password)[:valid] == 1
|
317
423
|
end
|
318
424
|
|
319
|
-
# Changes the password for a wallet.
|
320
|
-
# if the action was successful.
|
425
|
+
# Changes the password for a wallet.
|
321
426
|
#
|
322
|
-
# ==== Example
|
427
|
+
# ==== Example:
|
323
428
|
#
|
324
|
-
# true
|
429
|
+
# wallet.change_password("new_pass") #=> true
|
430
|
+
# @return [Boolean] indicates if the action was successful
|
325
431
|
def change_password(password)
|
326
432
|
wallet_required!
|
327
433
|
rpc(:password_change, password: password)[:changed] == 1
|