nanook 2.1.0 → 2.5.1

Sign up to get free protection for your applications and to get access to all the features.
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