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.
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
- DEFAULT_TIMEOUT = 500 # seconds
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
- # Convert Strings of primitives to primitives
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
- STEP = BigDecimal.new("10")**BigDecimal.new("30")
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.new(nano.to_s) * STEP).to_i
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
@@ -1,3 +1,3 @@
1
1
  class Nanook
2
- VERSION = "2.1.0"
2
+ VERSION = "2.5.1"
3
3
  end
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
- # Your wallets each have a seed, which is a 32-byte uppercase hex
7
- # string that looks like this:
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
- # You can think of this string as your API key to the nano network.
12
- # The person who knows it can do all read and write actions against
13
- # the wallet and all accounts inside the wallet from anywhere on the
14
- # nano network, not just on the node you created the wallet on.
15
- # <b>Make sure this key is always secret and safe</b>. Do not commit
16
- # your seed into source control.
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
- # A convenient method that returns an account in your wallet, allowing
37
- # you to perform all the actions in Nanook::WalletAccount on it.
56
+ # Returns the given account in the wallet as a {Nanook::WalletAccount} instance
57
+ # to let you start working with it.
38
58
  #
39
- # wallet.account("xrb_...") #=> Nanook::WalletAccount instance
59
+ # Call with no +account+ argument if you wish to create a new account
60
+ # in the wallet, like this:
40
61
  #
41
- # See Nanook::WalletAccount.
62
+ # wallet.account.create # => Nanook::WalletAccount
42
63
  #
43
- # Will throw an ArgumentError if the wallet does not contain the account.
64
+ # See {Nanook::WalletAccount} for all the methods you can call on the
65
+ # account object returned.
44
66
  #
45
- # ==== Arguments
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
- # ==== Examples
69
+ # wallet.account("nano_...") # => Nanook::WalletAccount
70
+ # wallet.account.create # => Nanook::WalletAccount
54
71
  #
55
- # wallet.account.create # Creates an account in the wallet and returns a Nanook::WalletAccount
56
- # wallet.account(account_id) # Returns a Nanook::WalletAccount for the account
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
- # Returns a Hash containing the balance of all accounts in the
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
- # ==== Arguments
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
- # "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000"=>{
130
+ # "nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000"=>{
117
131
  # "balance"=>2.5,
118
132
  # "pending"=>1
119
133
  # },
120
- # "xrb_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx"=>{
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
- # Destroy the wallet. Returns a boolean indicating whether the action
176
- # was successful or not.
206
+ # Destroys the wallet.
207
+ #
208
+ # ==== Example:
209
+ #
210
+ # wallet.destroy # => true
177
211
  #
178
- # ==== Example Response
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 response
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
- # Returns boolean indicating if the wallet contains an account.
229
+ # Will return +true+ if the account exists in the wallet.
197
230
  #
198
- # ==== Arguments
199
- #
200
- # [+account+] String account id (will start with <tt>"xrb_..."</tt>)
231
+ # ==== Example:
232
+ # wallet.contains?("nano_...") # => true
201
233
  #
202
- # ==== Example response
203
- # true
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
- # Make a payment from an account in your wallet to another account
222
- # on the nano network. Returns a <i>send</i> block id
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
- # <i>Proof of Work is precomputed for one transaction in the background. If it has been a while since your last transaction it will send instantly, the next one will need to wait for Proof of Work to be generated.</i>
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
- # ==== Examples
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
- # wallet.pay(from: "xrb_...", to: "xrb_...", amount: 1.1, id: "myUniqueId123") # => "9AE2311..."
232
- # wallet.pay(from: "xrb_...", to: "xrb_...", amount: 54000000000000, unit: :raw, id: "myUniqueId123") # => "9AE2311..."
263
+ # ==== Examples:
233
264
  #
234
- # ==== Arguments
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
- # Returns information about pending blocks (payments) that are waiting
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
- # ==== Example 1:
290
+ # ==== Examples:
258
291
  #
259
292
  # wallet.pending
260
293
  #
261
- # ==== Example 1 response:
294
+ # Example response:
295
+ #
262
296
  # {
263
- # :xrb_1111111111111111111111111111111111111111111111111117353trpda=>[
297
+ # :nano_1111111111111111111111111111111111111111111111111117353trpda=>[
264
298
  # "142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D",
265
299
  # "718CC2121C3E641059BC1C2CFC45666C99E8AE922F7A807B7D07B62C995D79E2"
266
300
  # ],
267
- # :xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3=>[
301
+ # :nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3=>[
268
302
  # "4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74"
269
303
  # ]
270
304
  # }
271
- # ==== Example 2:
305
+ #
306
+ # Asking for more information:
272
307
  #
273
308
  # wallet.pending(detailed: true)
274
309
  #
275
- # ==== Example 2 response:
310
+ # Example response:
311
+ #
276
312
  # {
277
- # :xrb_1111111111111111111111111111111111111111111111111117353trpda=>[
313
+ # :nano_1111111111111111111111111111111111111111111111111117353trpda=>[
278
314
  # {
279
315
  # :amount=>6.0,
280
- # :source=>"xrb_3dcfozsmekr1tr9skf1oa5wbgmxt81qepfdnt7zicq5x3hk65fg4fqj58mbr",
316
+ # :source=>"nano_3dcfozsmekr1tr9skf1oa5wbgmxt81qepfdnt7zicq5x3hk65fg4fqj58mbr",
281
317
  # :block=>:"142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D"
282
318
  # },
283
319
  # {
284
320
  # :amount=>12.0,
285
- # :source=>"xrb_3dcfozsmekr1tr9skf1oa5wbgmxt81qepfdnt7zicq5x3hk65fg4fqj58mbr",
321
+ # :source=>"nano_3dcfozsmekr1tr9skf1oa5wbgmxt81qepfdnt7zicq5x3hk65fg4fqj58mbr",
286
322
  # :block=>:"242A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D"
287
323
  # }
288
324
  # ],
289
- # :xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3=>[
325
+ # :nano_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3=>[
290
326
  # {
291
327
  # :amount=>106.370018,
292
- # :source=>"xrb_13ezf4od79h1tgj9aiu4djzcmmguendtjfuhwfukhuucboua8cpoihmh8byo",
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
- # if a receive was successful, or +false+ if there were no pending
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
- # Restore a previously created wallet by its seed.
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
- # Returns a boolean to indicate if the wallet is locked.
463
+ # Information about this wallet and all of its accounts.
464
+ #
465
+ # ==== Examples:
466
+ #
467
+ # wallet.info
468
+ #
469
+ # Example response:
385
470
  #
386
- # ==== Example response
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
- # true
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
- # @return [Boolean] indicates if the action was successful
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