nanook 2.1.0 → 2.5.1
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 +5 -5
- data/CHANGELOG.md +79 -1
- data/README.md +47 -19
- data/lib/nanook.rb +5 -5
- data/lib/nanook/account.rb +176 -118
- data/lib/nanook/block.rb +62 -11
- data/lib/nanook/error.rb +1 -0
- data/lib/nanook/node.rb +261 -3
- data/lib/nanook/rpc.rb +23 -2
- data/lib/nanook/util.rb +21 -2
- data/lib/nanook/version.rb +1 -1
- data/lib/nanook/wallet.rb +228 -86
- data/lib/nanook/wallet_account.rb +47 -40
- metadata +14 -15
data/lib/nanook/rpc.rb
CHANGED
@@ -2,10 +2,23 @@ require 'json'
|
|
2
2
|
require 'symbolized'
|
3
3
|
|
4
4
|
class Nanook
|
5
|
+
|
6
|
+
# The <tt>Nanook::Rpc</tt> class is responsible for maintaining the
|
7
|
+
# connection to the RPC server, calling the RPC and parsing its response
|
8
|
+
# into Ruby primitives.
|
9
|
+
#
|
10
|
+
# Internally, the {Nanook} class creates an instance of this class, and
|
11
|
+
# it's generally more convenient to interact with the RPC through an
|
12
|
+
# instance of {Nanook#rpc} instead of by instantiating this class directly:
|
13
|
+
#
|
14
|
+
# nanook = Nanook.new
|
15
|
+
# nanook.rpc(:accounts_create, wallet: wallet_id, count: 2)
|
5
16
|
class Rpc
|
6
17
|
|
18
|
+
# Default RPC server and port to connect to
|
7
19
|
DEFAULT_URI = "http://localhost:7076"
|
8
|
-
|
20
|
+
# Default request timeout in seconds
|
21
|
+
DEFAULT_TIMEOUT = 60
|
9
22
|
|
10
23
|
def initialize(uri=DEFAULT_URI, timeout:DEFAULT_TIMEOUT)
|
11
24
|
@rpc_server = URI(uri)
|
@@ -20,6 +33,12 @@ class Nanook
|
|
20
33
|
@request.content_type = "application/json"
|
21
34
|
end
|
22
35
|
|
36
|
+
# Calls the RPC server and returns the response.
|
37
|
+
#
|
38
|
+
# @param action [Symbol] the "action" of the RPC to call. The RPC always
|
39
|
+
# expects an "action" param to identify what RPC action is being called.
|
40
|
+
# @param params [Hash] all other params to pass to the RPC
|
41
|
+
# @return [Hash] the response from the RPC
|
23
42
|
def call(action, params={})
|
24
43
|
# Stringify param values
|
25
44
|
params = Hash[params.map {|k, v| [k, v.to_s] }]
|
@@ -36,13 +55,14 @@ class Nanook
|
|
36
55
|
end
|
37
56
|
end
|
38
57
|
|
58
|
+
# @return [String]
|
39
59
|
def inspect
|
40
60
|
"#{self.class.name}(host: \"#{@rpc_server}\", timeout: #{@http.read_timeout} object_id: \"#{"0x00%x" % (object_id << 1)}\")"
|
41
61
|
end
|
42
62
|
|
43
63
|
private
|
44
64
|
|
45
|
-
#
|
65
|
+
# Recursively parses the RPC response, sending values to #parse_value
|
46
66
|
def process_hash(h)
|
47
67
|
new_hash = h.map do |k,v|
|
48
68
|
v = if v.is_a?(Array)
|
@@ -63,6 +83,7 @@ class Nanook
|
|
63
83
|
Hash[new_hash.sort].to_symbolized_hash
|
64
84
|
end
|
65
85
|
|
86
|
+
# Converts Strings to primitives
|
66
87
|
def parse_value(v)
|
67
88
|
return v.to_i if v.match(/^\d+\Z/)
|
68
89
|
return true if v == "true"
|
data/lib/nanook/util.rb
CHANGED
@@ -1,18 +1,37 @@
|
|
1
1
|
require 'bigdecimal'
|
2
2
|
|
3
3
|
class Nanook
|
4
|
+
|
5
|
+
# Set of class utility methods.
|
4
6
|
class Util
|
5
7
|
|
6
|
-
|
8
|
+
# Constant used to convert back and forth between raw and NANO.
|
9
|
+
STEP = BigDecimal("10")**BigDecimal("30")
|
7
10
|
|
11
|
+
# Converts an amount of NANO to an amount of raw.
|
12
|
+
#
|
13
|
+
# @param nano [Float|Integer] amount in nano
|
14
|
+
# @return [Integer] amount in raw
|
8
15
|
def self.NANO_to_raw(nano)
|
9
|
-
(BigDecimal
|
16
|
+
(BigDecimal(nano.to_s) * STEP).to_i
|
10
17
|
end
|
11
18
|
|
19
|
+
# Converts an amount of raw to an amount of NANO.
|
20
|
+
#
|
21
|
+
# @param raw [Integer] amount in raw
|
22
|
+
# @return [Float|Integer] amount in NANO
|
12
23
|
def self.raw_to_NANO(raw)
|
13
24
|
(raw.to_f / STEP).to_f
|
14
25
|
end
|
15
26
|
|
27
|
+
# Converts an empty String value into an empty version of another type.
|
28
|
+
#
|
29
|
+
# The RPC often returns an empty String (<tt>""</tt>) as a value, when a
|
30
|
+
# +nil+, or empty Array (<tt>[]</tt>), or empty Hash (<tt>{}</tt>) would be better.
|
31
|
+
# If the response might be
|
32
|
+
#
|
33
|
+
# @param response the value returned from the RPC server
|
34
|
+
# @param type the type to return an empty of
|
16
35
|
def self.coerce_empty_string_to_type(response, type)
|
17
36
|
if response == "" || response.nil?
|
18
37
|
return type.new
|
data/lib/nanook/version.rb
CHANGED
data/lib/nanook/wallet.rb
CHANGED
@@ -3,21 +3,41 @@ class Nanook
|
|
3
3
|
# The <tt>Nanook::Wallet</tt> class lets you manage your nano wallets,
|
4
4
|
# as well as some account-specific things like making and receiving payments.
|
5
5
|
#
|
6
|
-
#
|
7
|
-
#
|
6
|
+
# === Wallet seeds vs ids
|
7
|
+
#
|
8
|
+
# Your wallets each have an id as well as a seed. Both are 32-byte uppercase hex
|
9
|
+
# strings that look like this:
|
8
10
|
#
|
9
11
|
# 000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F
|
10
12
|
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
# your
|
13
|
+
# This class uses wallet _ids_ to identify your wallet. A wallet id only
|
14
|
+
# exists locally on the nano node that it was created on. The person
|
15
|
+
# who knows this id can only perform all read and write actions against
|
16
|
+
# the wallet and all accounts inside the wallet from the same nano node
|
17
|
+
# that it was created on. This makes wallet ids fairly safe to use as a
|
18
|
+
# person needs to know your wallet id as well as have access to run
|
19
|
+
# RPC commands against your nano node to be able to control your accounts.
|
20
|
+
#
|
21
|
+
# A _seed_ on the other hand can be used to link any wallet to another
|
22
|
+
# wallet's accounts, from anywhere in the nano network. This happens
|
23
|
+
# by setting a wallet's seed to be the same as a previous wallet's seed.
|
24
|
+
# When a wallet has the same seed as another wallet, any accounts
|
25
|
+
# created in the second wallet will be the same accounts as those that were
|
26
|
+
# created in the previous wallet, and the new wallet's owner will
|
27
|
+
# also gain ownership of the previous wallet's accounts. Note, that the
|
28
|
+
# two wallets will have different ids, but the same seed.
|
29
|
+
#
|
30
|
+
# Nanook is based on the Nano RPC, which uses wallet ids and not seeds.
|
31
|
+
# The RPC and therefore Nanook cannot tell you what a wallet's seed is,
|
32
|
+
# only its id. Knowing a wallet's seed is very useful for if you ever
|
33
|
+
# want to restore the wallet anywhere else on the nano network besides
|
34
|
+
# the node you originally created it on. The nano command line interface
|
35
|
+
# (CLI) is the only method for discovering a wallet's seed. See the
|
36
|
+
# {https://docs.nano.org/commands/command-line-interface/#-wallet_decrypt_unsafe-walletwallet-passwordpassword}.
|
17
37
|
#
|
18
38
|
# === Initializing
|
19
39
|
#
|
20
|
-
# Initialize this class through the convenient Nanook#wallet method:
|
40
|
+
# Initialize this class through the convenient {Nanook#wallet} method:
|
21
41
|
#
|
22
42
|
# nanook = Nanook.new
|
23
43
|
# wallet = nanook.wallet(wallet_id)
|
@@ -33,31 +53,37 @@ class Nanook
|
|
33
53
|
@wallet = wallet
|
34
54
|
end
|
35
55
|
|
36
|
-
#
|
37
|
-
#
|
56
|
+
# Returns the given account in the wallet as a {Nanook::WalletAccount} instance
|
57
|
+
# to let you start working with it.
|
38
58
|
#
|
39
|
-
#
|
59
|
+
# Call with no +account+ argument if you wish to create a new account
|
60
|
+
# in the wallet, like this:
|
40
61
|
#
|
41
|
-
#
|
62
|
+
# wallet.account.create # => Nanook::WalletAccount
|
42
63
|
#
|
43
|
-
#
|
64
|
+
# See {Nanook::WalletAccount} for all the methods you can call on the
|
65
|
+
# account object returned.
|
44
66
|
#
|
45
|
-
# ====
|
46
|
-
# [+account+] Optional String of an account (starting with
|
47
|
-
# <tt>"xrb..."</tt>) to start working with. Must be an
|
48
|
-
# account within the wallet. When
|
49
|
-
# no account is given, the instance returned only allows you to call
|
50
|
-
# +create+ on it, to create a new account. Otherwise, you
|
51
|
-
# must pass an account string for all other methods.
|
67
|
+
# ==== Examples:
|
52
68
|
#
|
53
|
-
#
|
69
|
+
# wallet.account("nano_...") # => Nanook::WalletAccount
|
70
|
+
# wallet.account.create # => Nanook::WalletAccount
|
54
71
|
#
|
55
|
-
#
|
56
|
-
#
|
72
|
+
# @param [String] account optional String of an account (starting with
|
73
|
+
# <tt>"xrb..."</tt>) to start working with. Must be an account within
|
74
|
+
# the wallet. When no account is given, the instance returned only
|
75
|
+
# allows you to call +create+ on it, to create a new account.
|
76
|
+
# @raise [ArgumentError] if the wallet does no contain the account
|
77
|
+
# @return [Nanook::WalletAccount]
|
57
78
|
def account(account=nil)
|
58
79
|
Nanook::WalletAccount.new(@rpc, @wallet, account)
|
59
80
|
end
|
60
81
|
|
82
|
+
# Array of {Nanook::WalletAccount} instances of accounts in the wallet.
|
83
|
+
#
|
84
|
+
# See {Nanook::WalletAccount} for all the methods you can call on the
|
85
|
+
# account objects returned.
|
86
|
+
#
|
61
87
|
# ==== Example:
|
62
88
|
#
|
63
89
|
# wallet.accounts # => [Nanook::WalletAccount, Nanook::WalletAccount...]
|
@@ -71,21 +97,9 @@ class Nanook
|
|
71
97
|
end
|
72
98
|
end
|
73
99
|
|
74
|
-
#
|
75
|
-
# wallet, optionally breaking the balances down by account.
|
100
|
+
# Balance of all accounts in the wallet, optionally breaking the balances down by account.
|
76
101
|
#
|
77
|
-
# ====
|
78
|
-
#
|
79
|
-
# [+account_break_down:+] Boolean (default is +false+). When +true+
|
80
|
-
# the response will contain balances per
|
81
|
-
# account.
|
82
|
-
# [+unit:+] Symbol (default is +:nano+) Represents the unit that
|
83
|
-
# the balances will be returned in.
|
84
|
-
# Must be either +:nano+ or +:raw+. (Note: this method
|
85
|
-
# interprets +:nano+ as NANO, which is technically Mnano
|
86
|
-
# See {What are Nano's Units}[https://nano.org/en/faq#what-are-nano-units-])
|
87
|
-
#
|
88
|
-
# ==== Examples
|
102
|
+
# ==== Examples:
|
89
103
|
# wallet.balance
|
90
104
|
#
|
91
105
|
# Example response:
|
@@ -113,15 +127,21 @@ class Nanook
|
|
113
127
|
# Example response:
|
114
128
|
#
|
115
129
|
# {
|
116
|
-
# "
|
130
|
+
# "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000"=>{
|
117
131
|
# "balance"=>2.5,
|
118
132
|
# "pending"=>1
|
119
133
|
# },
|
120
|
-
# "
|
134
|
+
# "nano_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx"=>{
|
121
135
|
# "balance"=>51.4,
|
122
136
|
# "pending"=>0
|
123
137
|
# },
|
124
138
|
# }
|
139
|
+
#
|
140
|
+
# @param [Boolean] account_break_down (default is +false+). When +true+
|
141
|
+
# the response will contain balances per account.
|
142
|
+
# @param unit (see Nanook::Account#balance)
|
143
|
+
#
|
144
|
+
# @return [Hash{Symbol=>Integer|Float|Hash}]
|
125
145
|
def balance(account_break_down: false, unit: Nanook.default_unit)
|
126
146
|
wallet_required!
|
127
147
|
|
@@ -150,6 +170,13 @@ class Nanook
|
|
150
170
|
|
151
171
|
# Changes a wallet's seed.
|
152
172
|
#
|
173
|
+
# It's recommended to only change the seed of a wallet that contains
|
174
|
+
# no accounts.
|
175
|
+
#
|
176
|
+
# ==== Example:
|
177
|
+
#
|
178
|
+
# wallet.change_seed("000D1BA...") # => true
|
179
|
+
#
|
153
180
|
# @param seed [String] the seed to change to.
|
154
181
|
# @return [Boolean] indicating whether the change was successful.
|
155
182
|
def change_seed(seed)
|
@@ -162,6 +189,10 @@ class Nanook
|
|
162
189
|
# The wallet will be created only on this node. It's important that
|
163
190
|
# if you intend to add funds to accounts in this wallet that you
|
164
191
|
# backup the wallet *seed* in order to restore the wallet in future.
|
192
|
+
# The nano command line interface (CLI) is the only method for
|
193
|
+
# backing up a wallet's seed. See the
|
194
|
+
# {https://github.com/nanocurrency/raiblocks/wiki/Command-line-interface
|
195
|
+
# --wallet_decrypt_unsafe CLI command}.
|
165
196
|
#
|
166
197
|
# ==== Example:
|
167
198
|
# Nanook.new.wallet.create # => Nanook::Wallet
|
@@ -172,11 +203,13 @@ class Nanook
|
|
172
203
|
self
|
173
204
|
end
|
174
205
|
|
175
|
-
#
|
176
|
-
#
|
206
|
+
# Destroys the wallet.
|
207
|
+
#
|
208
|
+
# ==== Example:
|
209
|
+
#
|
210
|
+
# wallet.destroy # => true
|
177
211
|
#
|
178
|
-
#
|
179
|
-
# true
|
212
|
+
# @return [Boolean] indicating success of the action
|
180
213
|
def destroy
|
181
214
|
wallet_required!
|
182
215
|
rpc(:wallet_destroy)
|
@@ -185,53 +218,52 @@ class Nanook
|
|
185
218
|
|
186
219
|
# Generates a String containing a JSON representation of your wallet.
|
187
220
|
#
|
188
|
-
# ==== Example
|
221
|
+
# ==== Example:
|
189
222
|
#
|
190
|
-
# "{\n \"0000000000000000000000000000000000000000000000000000000000000000\": \"0000000000000000000000000000000000000000000000000000000000000003\",\n \"0000000000000000000000000000000000000000000000000000000000000001\": \"C3A176FC3B90113277BFC91F55128FC9A1F1B6166A73E7446927CFFCA4C2C9D9\",\n \"0000000000000000000000000000000000000000000000000000000000000002\": \"3E58EC805B99C52B4715598BD332C234A1FBF1780577137E18F53B9B7F85F04B\",\n \"0000000000000000000000000000000000000000000000000000000000000003\": \"5FF8021122F3DEE0E4EC4241D35A3F41DEF63CCF6ADA66AF235DE857718498CD\",\n \"0000000000000000000000000000000000000000000000000000000000000004\": \"A30E0A32ED41C8607AA9212843392E853FCBCB4E7CB194E35C94F07F91DE59EF\",\n \"0000000000000000000000000000000000000000000000000000000000000005\": \"E707002E84143AA5F030A6DB8DD0C0480F2FFA75AB1FFD657EC22B5AA8E395D5\",\n \"0000000000000000000000000000000000000000000000000000000000000006\": \"0000000000000000000000000000000000000000000000000000000000000001\",\n \"8646C0423160DEAEAA64034F9C6858F7A5C8A329E73E825A5B16814F6CCAFFE3\": \"0000000000000000000000000000000000000000000000000000000100000000\"\n}\n"
|
223
|
+
# wallet.export # => "{\n \"0000000000000000000000000000000000000000000000000000000000000000\": \"0000000000000000000000000000000000000000000000000000000000000003\",\n \"0000000000000000000000000000000000000000000000000000000000000001\": \"C3A176FC3B90113277BFC91F55128FC9A1F1B6166A73E7446927CFFCA4C2C9D9\",\n \"0000000000000000000000000000000000000000000000000000000000000002\": \"3E58EC805B99C52B4715598BD332C234A1FBF1780577137E18F53B9B7F85F04B\",\n \"0000000000000000000000000000000000000000000000000000000000000003\": \"5FF8021122F3DEE0E4EC4241D35A3F41DEF63CCF6ADA66AF235DE857718498CD\",\n \"0000000000000000000000000000000000000000000000000000000000000004\": \"A30E0A32ED41C8607AA9212843392E853FCBCB4E7CB194E35C94F07F91DE59EF\",\n \"0000000000000000000000000000000000000000000000000000000000000005\": \"E707002E84143AA5F030A6DB8DD0C0480F2FFA75AB1FFD657EC22B5AA8E395D5\",\n \"0000000000000000000000000000000000000000000000000000000000000006\": \"0000000000000000000000000000000000000000000000000000000000000001\",\n \"8646C0423160DEAEAA64034F9C6858F7A5C8A329E73E825A5B16814F6CCAFFE3\": \"0000000000000000000000000000000000000000000000000000000100000000\"\n}\n"
|
191
224
|
def export
|
192
225
|
wallet_required!
|
193
226
|
rpc(:wallet_export)[:json]
|
194
227
|
end
|
195
228
|
|
196
|
-
#
|
229
|
+
# Will return +true+ if the account exists in the wallet.
|
197
230
|
#
|
198
|
-
# ====
|
199
|
-
#
|
200
|
-
# [+account+] String account id (will start with <tt>"xrb_..."</tt>)
|
231
|
+
# ==== Example:
|
232
|
+
# wallet.contains?("nano_...") # => true
|
201
233
|
#
|
202
|
-
#
|
203
|
-
#
|
234
|
+
# @param account [String] id (will start with <tt>"nano_..."</tt>)
|
235
|
+
# @return [Boolean] indicating if the wallet contains the given account
|
204
236
|
def contains?(account)
|
205
237
|
wallet_required!
|
206
238
|
response = rpc(:wallet_contains, account: account)
|
207
239
|
!response.empty? && response[:exists] == 1
|
208
240
|
end
|
209
241
|
|
210
|
-
# @return [String]
|
242
|
+
# @return [String] the wallet id
|
211
243
|
def id
|
212
244
|
@wallet
|
213
245
|
end
|
214
|
-
alias_method :seed, :id
|
215
246
|
|
216
247
|
# @return [String]
|
217
248
|
def inspect
|
218
249
|
"#{self.class.name}(id: \"#{id}\", object_id: \"#{"0x00%x" % (object_id << 1)}\")"
|
219
250
|
end
|
220
251
|
|
221
|
-
#
|
222
|
-
# on the nano network.
|
223
|
-
# if successful, or a {Nanook::Error} if unsuccessful.
|
224
|
-
#
|
225
|
-
# Note, there may be a delay in receiving a response due to Proof of Work being done. From the {Nano RPC}[https://github.com/nanocurrency/raiblocks/wiki/RPC-protocol#account-create]:
|
252
|
+
# Makes a payment from an account in your wallet to another account
|
253
|
+
# on the nano network.
|
226
254
|
#
|
227
|
-
#
|
255
|
+
# Note, there may be a delay in receiving a response due to Proof of
|
256
|
+
# Work being done. From the {Nano RPC}[https://docs.nano.org/commands/rpc-protocol/#send]:
|
228
257
|
#
|
229
|
-
#
|
258
|
+
# <i>Proof of Work is precomputed for one transaction in the
|
259
|
+
# background. If it has been a while since your last transaction it
|
260
|
+
# will send instantly, the next one will need to wait for Proof of
|
261
|
+
# Work to be generated.</i>
|
230
262
|
#
|
231
|
-
#
|
232
|
-
# wallet.pay(from: "xrb_...", to: "xrb_...", amount: 54000000000000, unit: :raw, id: "myUniqueId123") # => "9AE2311..."
|
263
|
+
# ==== Examples:
|
233
264
|
#
|
234
|
-
#
|
265
|
+
# wallet.pay(from: "nano_...", to: "nano_...", amount: 1.1, id: "myUniqueId123") # => "9AE2311..."
|
266
|
+
# wallet.pay(from: "nano_...", to: "nano_...", amount: 54000000000000, unit: :raw, id: "myUniqueId123") # => "9AE2311..."
|
235
267
|
#
|
236
268
|
# @param from [String] account id of an account in your wallet
|
237
269
|
# @param to (see Nanook::WalletAccount#pay)
|
@@ -239,57 +271,61 @@ class Nanook
|
|
239
271
|
# @param unit (see Nanook::Account#balance)
|
240
272
|
# @params id (see Nanook::WalletAccount#pay)
|
241
273
|
# @return (see Nanook::WalletAccount#pay)
|
274
|
+
# @raise [Nanook::Error] if unsuccessful
|
242
275
|
def pay(from:, to:, amount:, unit: Nanook.default_unit, id:)
|
243
276
|
wallet_required!
|
244
277
|
validate_wallet_contains_account!(from)
|
245
278
|
account(from).pay(to: to, amount: amount, unit: unit, id: id)
|
246
279
|
end
|
247
280
|
|
248
|
-
#
|
281
|
+
# Information about pending blocks (payments) that are waiting
|
249
282
|
# to be received by accounts in this wallet.
|
250
283
|
#
|
251
|
-
# See also the #receive method of this class for how to receive a pending payment.
|
284
|
+
# See also the {#receive} method of this class for how to receive a pending payment.
|
252
285
|
#
|
253
286
|
# @param limit [Integer] number of accounts with pending payments to return (default is 1000)
|
254
287
|
# @param detailed [Boolean]return a more complex Hash of pending block information (default is +false+)
|
255
288
|
# @param unit (see Nanook::Account#balance)
|
256
289
|
#
|
257
|
-
# ====
|
290
|
+
# ==== Examples:
|
258
291
|
#
|
259
292
|
# wallet.pending
|
260
293
|
#
|
261
|
-
#
|
294
|
+
# Example response:
|
295
|
+
#
|
262
296
|
# {
|
263
|
-
# :
|
297
|
+
# :nano_1111111111111111111111111111111111111111111111111117353trpda=>[
|
264
298
|
# "142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D",
|
265
299
|
# "718CC2121C3E641059BC1C2CFC45666C99E8AE922F7A807B7D07B62C995D79E2"
|
266
300
|
# ],
|
267
|
-
# :
|
301
|
+
# :nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3=>[
|
268
302
|
# "4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74"
|
269
303
|
# ]
|
270
304
|
# }
|
271
|
-
#
|
305
|
+
#
|
306
|
+
# Asking for more information:
|
272
307
|
#
|
273
308
|
# wallet.pending(detailed: true)
|
274
309
|
#
|
275
|
-
#
|
310
|
+
# Example response:
|
311
|
+
#
|
276
312
|
# {
|
277
|
-
# :
|
313
|
+
# :nano_1111111111111111111111111111111111111111111111111117353trpda=>[
|
278
314
|
# {
|
279
315
|
# :amount=>6.0,
|
280
|
-
# :source=>"
|
316
|
+
# :source=>"nano_3dcfozsmekr1tr9skf1oa5wbgmxt81qepfdnt7zicq5x3hk65fg4fqj58mbr",
|
281
317
|
# :block=>:"142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D"
|
282
318
|
# },
|
283
319
|
# {
|
284
320
|
# :amount=>12.0,
|
285
|
-
# :source=>"
|
321
|
+
# :source=>"nano_3dcfozsmekr1tr9skf1oa5wbgmxt81qepfdnt7zicq5x3hk65fg4fqj58mbr",
|
286
322
|
# :block=>:"242A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D"
|
287
323
|
# }
|
288
324
|
# ],
|
289
|
-
# :
|
325
|
+
# :nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3=>[
|
290
326
|
# {
|
291
327
|
# :amount=>106.370018,
|
292
|
-
# :source=>"
|
328
|
+
# :source=>"nano_13ezf4od79h1tgj9aiu4djzcmmguendtjfuhwfukhuucboua8cpoihmh8byo",
|
293
329
|
# :block=>:"4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74"
|
294
330
|
# }
|
295
331
|
# ]
|
@@ -332,14 +368,13 @@ class Nanook
|
|
332
368
|
# When called with no +block+ argument, the latest pending payment
|
333
369
|
# for the account will be received.
|
334
370
|
#
|
335
|
-
# Returns a <i>receive</i> block hash
|
336
|
-
#
|
337
|
-
# payments to receive.
|
371
|
+
# Returns a <i>receive</i> block hash id if a receive was successful,
|
372
|
+
# or +false+ if there were no pending payments to receive.
|
338
373
|
#
|
339
374
|
# You can receive a specific pending block if you know it by
|
340
375
|
# passing the block has in as an argument.
|
341
376
|
#
|
342
|
-
# ==== Examples
|
377
|
+
# ==== Examples:
|
343
378
|
#
|
344
379
|
# wallet.receive(into: "xrb...") # => "9AE2311..."
|
345
380
|
# wallet.receive("718CC21...", into: "xrb...") # => "9AE2311..."
|
@@ -354,7 +389,51 @@ class Nanook
|
|
354
389
|
account(into).receive(block)
|
355
390
|
end
|
356
391
|
|
357
|
-
#
|
392
|
+
# The default representative account id for the wallet. This is the
|
393
|
+
# representative that all new accounts created in this wallet will have.
|
394
|
+
#
|
395
|
+
# Changing the default representative for a wallet does not change
|
396
|
+
# the representatives for any accounts that have been created.
|
397
|
+
#
|
398
|
+
# ==== Example:
|
399
|
+
#
|
400
|
+
# wallet.default_representative # => "nano_3pc..."
|
401
|
+
#
|
402
|
+
# @return [String] Representative account of the account
|
403
|
+
def default_representative
|
404
|
+
rpc(:wallet_representative)[:representative]
|
405
|
+
end
|
406
|
+
alias_method :representative, :default_representative
|
407
|
+
|
408
|
+
# Sets the default representative for the wallet. A wallet's default
|
409
|
+
# representative is the representative all new accounts created in
|
410
|
+
# the wallet will have. Changing the default representative for a
|
411
|
+
# wallet does not change the representatives for existing accounts
|
412
|
+
# in the wallet.
|
413
|
+
#
|
414
|
+
# ==== Example:
|
415
|
+
#
|
416
|
+
# wallet.change_default_representative("nano_...") # => "nano_..."
|
417
|
+
#
|
418
|
+
# @param [String] representative the id of the representative account
|
419
|
+
# to set as this account's representative
|
420
|
+
# @return [String] the representative account id
|
421
|
+
# @raise [ArgumentError] if the representative account does not exist
|
422
|
+
# @raise [Nanook::Error] if setting the representative fails
|
423
|
+
def change_default_representative(representative)
|
424
|
+
unless Nanook::Account.new(@rpc, representative).exists?
|
425
|
+
raise ArgumentError.new("Representative account does not exist: #{representative}")
|
426
|
+
end
|
427
|
+
|
428
|
+
if rpc(:wallet_representative_set, representative: representative)[:set] == 1
|
429
|
+
representative
|
430
|
+
else
|
431
|
+
raise Nanook::Error.new("Setting the representative failed")
|
432
|
+
end
|
433
|
+
end
|
434
|
+
alias_method :change_representative, :change_default_representative
|
435
|
+
|
436
|
+
# Restores a previously created wallet by its seed.
|
358
437
|
# A new wallet will be created on your node (with a new wallet id)
|
359
438
|
# and will have its seed set to the given seed.
|
360
439
|
#
|
@@ -381,11 +460,73 @@ class Nanook
|
|
381
460
|
self
|
382
461
|
end
|
383
462
|
|
384
|
-
#
|
463
|
+
# Information about this wallet and all of its accounts.
|
464
|
+
#
|
465
|
+
# ==== Examples:
|
466
|
+
#
|
467
|
+
# wallet.info
|
468
|
+
#
|
469
|
+
# Example response:
|
385
470
|
#
|
386
|
-
#
|
471
|
+
# {
|
472
|
+
# id: "2C3C570EA8898443C0FD04A1C385A3E3A8C985AD792635FCDCEBB30ADF6A0570",
|
473
|
+
# accounts: [
|
474
|
+
# {
|
475
|
+
# id: "nano_11119gbh8hb4hj1duf7fdtfyf5s75okzxdgupgpgm1bj78ex3kgy7frt3s9n"
|
476
|
+
# frontier: "E71AF3E9DD86BBD8B4620EFA63E065B34D358CFC091ACB4E103B965F95783321",
|
477
|
+
# open_block: "643B77F1ECEFBDBE1CC909872964C1DBBE23A6149BD3CEF2B50B76044659B60F",
|
478
|
+
# representative_block: "643B77F1ECEFBDBE1CC909872964C1DBBE23A6149BD3CEF2B50B76044659B60F",
|
479
|
+
# balance: 1.45,
|
480
|
+
# modified_timestamp: 1511476234,
|
481
|
+
# block_count: 2
|
482
|
+
# },
|
483
|
+
# { ... }
|
484
|
+
# ]
|
485
|
+
# }
|
387
486
|
#
|
388
|
-
#
|
487
|
+
# @param unit (see #balance)
|
488
|
+
# @return [Hash{Symbol=>String|Array<Hash{Symbol=>String|Integer|Float}>}] information about the wallet.
|
489
|
+
# See {Nanook::Account#info} for details of what is returned for each account.
|
490
|
+
def info(unit: Nanook.default_unit)
|
491
|
+
unless Nanook::UNITS.include?(unit)
|
492
|
+
raise ArgumentError.new("Unsupported unit: #{unit}")
|
493
|
+
end
|
494
|
+
|
495
|
+
wallet_required!
|
496
|
+
accounts = rpc(:wallet_ledger)[:accounts].map do |account_id, payload|
|
497
|
+
payload[:id] = account_id
|
498
|
+
if unit == :nano
|
499
|
+
payload[:balance] = Nanook::Util.raw_to_NANO(payload[:balance])
|
500
|
+
end
|
501
|
+
payload
|
502
|
+
end
|
503
|
+
|
504
|
+
{
|
505
|
+
id: @wallet,
|
506
|
+
accounts: accounts
|
507
|
+
}.to_symbolized_hash
|
508
|
+
end
|
509
|
+
|
510
|
+
# Locks the wallet. A locked wallet cannot pocket pending transactions or make payments. See {#unlock}.
|
511
|
+
#
|
512
|
+
# ==== Example:
|
513
|
+
#
|
514
|
+
# wallet.lock #=> true
|
515
|
+
#
|
516
|
+
# @return [Boolean] indicates if the wallet was successfully locked
|
517
|
+
def lock
|
518
|
+
wallet_required!
|
519
|
+
response = rpc(:wallet_lock)
|
520
|
+
!response.empty? && response[:locked] == 1
|
521
|
+
end
|
522
|
+
|
523
|
+
# Returns +true+ if the wallet is locked.
|
524
|
+
#
|
525
|
+
# ==== Example:
|
526
|
+
#
|
527
|
+
# wallet.locked? #=> false
|
528
|
+
#
|
529
|
+
# @return [Boolean] indicates if the wallet is locked
|
389
530
|
def locked?
|
390
531
|
wallet_required!
|
391
532
|
response = rpc(:wallet_locked)
|
@@ -397,7 +538,8 @@ class Nanook
|
|
397
538
|
# ==== Example:
|
398
539
|
#
|
399
540
|
# wallet.unlock("new_pass") #=> true
|
400
|
-
#
|
541
|
+
#
|
542
|
+
# @return [Boolean] indicates if the unlocking action was successful
|
401
543
|
def unlock(password)
|
402
544
|
wallet_required!
|
403
545
|
rpc(:password_enter, password: password)[:valid] == 1
|