nanook 0.7.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (202) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/CHANGELOG.md +26 -0
  4. data/Gemfile.lock +2 -2
  5. data/README.md +18 -7
  6. data/Rakefile +18 -0
  7. data/docs/0.7.0/apple-touch-icon.png +0 -0
  8. data/docs/0.7.0/classes/Nanook.html +572 -0
  9. data/docs/0.7.0/classes/Nanook/Account.html +909 -0
  10. data/docs/0.7.0/classes/Nanook/Block.html +717 -0
  11. data/docs/0.7.0/classes/Nanook/Error.html +84 -0
  12. data/docs/0.7.0/classes/Nanook/Key.html +253 -0
  13. data/docs/0.7.0/classes/Nanook/Node.html +657 -0
  14. data/docs/0.7.0/classes/Nanook/Rpc.html +247 -0
  15. data/docs/0.7.0/classes/Nanook/Util.html +197 -0
  16. data/docs/0.7.0/classes/Nanook/Wallet.html +986 -0
  17. data/docs/0.7.0/classes/Nanook/WalletAccount.html +446 -0
  18. data/docs/0.7.0/classes/Nanook/WorkPeer.html +294 -0
  19. data/docs/0.7.0/created.rid +14 -0
  20. data/docs/0.7.0/css/github.css +123 -0
  21. data/docs/0.7.0/css/main.css +374 -0
  22. data/docs/0.7.0/css/panel.css +360 -0
  23. data/docs/0.7.0/css/reset.css +48 -0
  24. data/docs/0.7.0/favicon.ico +0 -0
  25. data/docs/0.7.0/files/README_md.html +418 -0
  26. data/docs/0.7.0/files/lib/nanook/account_rb.html +89 -0
  27. data/docs/0.7.0/files/lib/nanook/block_rb.html +89 -0
  28. data/docs/0.7.0/files/lib/nanook/error_rb.html +89 -0
  29. data/docs/0.7.0/files/lib/nanook/key_rb.html +89 -0
  30. data/docs/0.7.0/files/lib/nanook/node_rb.html +89 -0
  31. data/docs/0.7.0/files/lib/nanook/rpc_rb.html +99 -0
  32. data/docs/0.7.0/files/lib/nanook/util_rb.html +89 -0
  33. data/docs/0.7.0/files/lib/nanook/version_rb.html +84 -0
  34. data/docs/0.7.0/files/lib/nanook/wallet_account_rb.html +89 -0
  35. data/docs/0.7.0/files/lib/nanook/wallet_rb.html +89 -0
  36. data/docs/0.7.0/files/lib/nanook/work_peer_rb.html +89 -0
  37. data/docs/0.7.0/files/lib/nanook_rb.html +94 -0
  38. data/docs/0.7.0/i/arrow-down.svg +8 -0
  39. data/docs/0.7.0/i/arrow-right.svg +8 -0
  40. data/docs/0.7.0/i/search.svg +12 -0
  41. data/docs/0.7.0/i/tree_bg.svg +8 -0
  42. data/docs/0.7.0/index.html +11 -0
  43. data/docs/0.7.0/js/highlight.pack.js +1 -0
  44. data/docs/0.7.0/js/jquery-1.3.2.min.js +19 -0
  45. data/docs/0.7.0/js/main.js +25 -0
  46. data/docs/0.7.0/js/navigation.js +142 -0
  47. data/docs/0.7.0/js/search_index.js +1 -0
  48. data/docs/0.7.0/js/searchdoc.js +465 -0
  49. data/docs/0.7.0/js/searcher.js +229 -0
  50. data/docs/0.7.0/panel/index.html +47 -0
  51. data/docs/0.7.0/panel/links.html +32 -0
  52. data/docs/0.7.0/panel/tree.js +1 -0
  53. data/docs/0.8.0/apple-touch-icon.png +0 -0
  54. data/docs/0.8.0/classes/Nanook.html +621 -0
  55. data/docs/0.8.0/classes/Nanook/Account.html +971 -0
  56. data/docs/0.8.0/classes/Nanook/Block.html +759 -0
  57. data/docs/0.8.0/classes/Nanook/Error.html +84 -0
  58. data/docs/0.8.0/classes/Nanook/Key.html +295 -0
  59. data/docs/0.8.0/classes/Nanook/Node.html +657 -0
  60. data/docs/0.8.0/classes/Nanook/Rpc.html +247 -0
  61. data/docs/0.8.0/classes/Nanook/Util.html +264 -0
  62. data/docs/0.8.0/classes/Nanook/Wallet.html +1056 -0
  63. data/docs/0.8.0/classes/Nanook/WalletAccount.html +582 -0
  64. data/docs/0.8.0/classes/Nanook/WorkPeer.html +294 -0
  65. data/docs/0.8.0/created.rid +14 -0
  66. data/docs/0.8.0/css/github.css +123 -0
  67. data/docs/0.8.0/css/main.css +374 -0
  68. data/docs/0.8.0/css/panel.css +360 -0
  69. data/docs/0.8.0/css/reset.css +48 -0
  70. data/docs/0.8.0/favicon.ico +0 -0
  71. data/docs/0.8.0/files/README_md.html +423 -0
  72. data/docs/0.8.0/files/lib/nanook/account_rb.html +89 -0
  73. data/docs/0.8.0/files/lib/nanook/block_rb.html +89 -0
  74. data/docs/0.8.0/files/lib/nanook/error_rb.html +89 -0
  75. data/docs/0.8.0/files/lib/nanook/key_rb.html +89 -0
  76. data/docs/0.8.0/files/lib/nanook/node_rb.html +89 -0
  77. data/docs/0.8.0/files/lib/nanook/rpc_rb.html +99 -0
  78. data/docs/0.8.0/files/lib/nanook/util_rb.html +97 -0
  79. data/docs/0.8.0/files/lib/nanook/version_rb.html +84 -0
  80. data/docs/0.8.0/files/lib/nanook/wallet_account_rb.html +89 -0
  81. data/docs/0.8.0/files/lib/nanook/wallet_rb.html +89 -0
  82. data/docs/0.8.0/files/lib/nanook/work_peer_rb.html +89 -0
  83. data/docs/0.8.0/files/lib/nanook_rb.html +94 -0
  84. data/docs/0.8.0/i/arrow-down.svg +8 -0
  85. data/docs/0.8.0/i/arrow-right.svg +8 -0
  86. data/docs/0.8.0/i/search.svg +12 -0
  87. data/docs/0.8.0/i/tree_bg.svg +8 -0
  88. data/docs/0.8.0/index.html +11 -0
  89. data/docs/0.8.0/js/highlight.pack.js +1 -0
  90. data/docs/0.8.0/js/jquery-1.3.2.min.js +19 -0
  91. data/docs/0.8.0/js/main.js +25 -0
  92. data/docs/0.8.0/js/navigation.js +142 -0
  93. data/docs/0.8.0/js/search_index.js +1 -0
  94. data/docs/0.8.0/js/searchdoc.js +465 -0
  95. data/docs/0.8.0/js/searcher.js +229 -0
  96. data/docs/0.8.0/panel/index.html +47 -0
  97. data/docs/0.8.0/panel/links.html +32 -0
  98. data/docs/0.8.0/panel/tree.js +1 -0
  99. data/docs/1.0.0/apple-touch-icon.png +0 -0
  100. data/docs/1.0.0/classes/Nanook.html +621 -0
  101. data/docs/1.0.0/classes/Nanook/Account.html +971 -0
  102. data/docs/1.0.0/classes/Nanook/Block.html +759 -0
  103. data/docs/1.0.0/classes/Nanook/Error.html +84 -0
  104. data/docs/1.0.0/classes/Nanook/Key.html +295 -0
  105. data/docs/1.0.0/classes/Nanook/Node.html +657 -0
  106. data/docs/1.0.0/classes/Nanook/Rpc.html +247 -0
  107. data/docs/1.0.0/classes/Nanook/Util.html +264 -0
  108. data/docs/1.0.0/classes/Nanook/Wallet.html +1056 -0
  109. data/docs/1.0.0/classes/Nanook/WalletAccount.html +582 -0
  110. data/docs/1.0.0/classes/Nanook/WorkPeer.html +294 -0
  111. data/docs/1.0.0/created.rid +14 -0
  112. data/docs/1.0.0/css/github.css +123 -0
  113. data/docs/1.0.0/css/main.css +374 -0
  114. data/docs/1.0.0/css/panel.css +360 -0
  115. data/docs/1.0.0/css/reset.css +48 -0
  116. data/docs/1.0.0/favicon.ico +0 -0
  117. data/docs/1.0.0/files/README_md.html +423 -0
  118. data/docs/1.0.0/files/lib/nanook/account_rb.html +89 -0
  119. data/docs/1.0.0/files/lib/nanook/block_rb.html +89 -0
  120. data/docs/1.0.0/files/lib/nanook/error_rb.html +89 -0
  121. data/docs/1.0.0/files/lib/nanook/key_rb.html +89 -0
  122. data/docs/1.0.0/files/lib/nanook/node_rb.html +89 -0
  123. data/docs/1.0.0/files/lib/nanook/rpc_rb.html +99 -0
  124. data/docs/1.0.0/files/lib/nanook/util_rb.html +97 -0
  125. data/docs/1.0.0/files/lib/nanook/version_rb.html +84 -0
  126. data/docs/1.0.0/files/lib/nanook/wallet_account_rb.html +89 -0
  127. data/docs/1.0.0/files/lib/nanook/wallet_rb.html +89 -0
  128. data/docs/1.0.0/files/lib/nanook/work_peer_rb.html +89 -0
  129. data/docs/1.0.0/files/lib/nanook_rb.html +94 -0
  130. data/docs/1.0.0/i/arrow-down.svg +8 -0
  131. data/docs/1.0.0/i/arrow-right.svg +8 -0
  132. data/docs/1.0.0/i/search.svg +12 -0
  133. data/docs/1.0.0/i/tree_bg.svg +8 -0
  134. data/docs/1.0.0/index.html +11 -0
  135. data/docs/1.0.0/js/highlight.pack.js +1 -0
  136. data/docs/1.0.0/js/jquery-1.3.2.min.js +19 -0
  137. data/docs/1.0.0/js/main.js +25 -0
  138. data/docs/1.0.0/js/navigation.js +142 -0
  139. data/docs/1.0.0/js/search_index.js +1 -0
  140. data/docs/1.0.0/js/searchdoc.js +465 -0
  141. data/docs/1.0.0/js/searcher.js +229 -0
  142. data/docs/1.0.0/panel/index.html +47 -0
  143. data/docs/1.0.0/panel/links.html +32 -0
  144. data/docs/1.0.0/panel/tree.js +1 -0
  145. data/docs/apple-touch-icon.png +0 -0
  146. data/docs/classes/Nanook.html +572 -0
  147. data/docs/classes/Nanook/Account.html +907 -0
  148. data/docs/classes/Nanook/Block.html +717 -0
  149. data/docs/classes/Nanook/Error.html +84 -0
  150. data/docs/classes/Nanook/Key.html +253 -0
  151. data/docs/classes/Nanook/Node.html +657 -0
  152. data/docs/classes/Nanook/Rpc.html +247 -0
  153. data/docs/classes/Nanook/Util.html +197 -0
  154. data/docs/classes/Nanook/Wallet.html +778 -0
  155. data/docs/classes/Nanook/WalletAccount.html +447 -0
  156. data/docs/classes/Nanook/WorkPeer.html +294 -0
  157. data/docs/created.rid +14 -0
  158. data/docs/css/github.css +123 -0
  159. data/docs/css/main.css +374 -0
  160. data/docs/css/panel.css +360 -0
  161. data/docs/css/reset.css +48 -0
  162. data/docs/favicon.ico +0 -0
  163. data/docs/files/README_md.html +408 -0
  164. data/docs/files/lib/nanook/account_rb.html +89 -0
  165. data/docs/files/lib/nanook/block_rb.html +89 -0
  166. data/docs/files/lib/nanook/error_rb.html +89 -0
  167. data/docs/files/lib/nanook/key_rb.html +89 -0
  168. data/docs/files/lib/nanook/node_rb.html +89 -0
  169. data/docs/files/lib/nanook/rpc_rb.html +99 -0
  170. data/docs/files/lib/nanook/util_rb.html +89 -0
  171. data/docs/files/lib/nanook/version_rb.html +84 -0
  172. data/docs/files/lib/nanook/wallet_account_rb.html +89 -0
  173. data/docs/files/lib/nanook/wallet_rb.html +89 -0
  174. data/docs/files/lib/nanook/work_peer_rb.html +89 -0
  175. data/docs/files/lib/nanook_rb.html +94 -0
  176. data/docs/i/arrow-down.svg +8 -0
  177. data/docs/i/arrow-right.svg +8 -0
  178. data/docs/i/search.svg +12 -0
  179. data/docs/i/tree_bg.svg +8 -0
  180. data/docs/index.html +11 -0
  181. data/docs/js/highlight.pack.js +1 -0
  182. data/docs/js/jquery-1.3.2.min.js +19 -0
  183. data/docs/js/main.js +25 -0
  184. data/docs/js/navigation.js +142 -0
  185. data/docs/js/search_index.js +1 -0
  186. data/docs/js/searchdoc.js +465 -0
  187. data/docs/js/searcher.js +229 -0
  188. data/docs/panel/index.html +47 -0
  189. data/docs/panel/links.html +32 -0
  190. data/docs/panel/tree.js +1 -0
  191. data/lib/nanook.rb +40 -4
  192. data/lib/nanook/account.rb +250 -8
  193. data/lib/nanook/block.rb +25 -2
  194. data/lib/nanook/key.rb +10 -2
  195. data/lib/nanook/node.rb +4 -0
  196. data/lib/nanook/rpc.rb +5 -1
  197. data/lib/nanook/util.rb +9 -1
  198. data/lib/nanook/version.rb +1 -1
  199. data/lib/nanook/wallet.rb +275 -14
  200. data/lib/nanook/wallet_account.rb +63 -11
  201. data/lib/nanook/work_peer.rb +4 -0
  202. metadata +188 -3
@@ -1,9 +1,24 @@
1
1
  class Nanook
2
+
3
+ # The <tt>Nanook::Block</tt> class contains methods to discover
4
+ # publicly-available information about blocks on the nano network.
5
+ #
6
+ # A block is represented by a unique hash
7
+ #
8
+ # Initialize this class through the convenient Nanook#block method:
9
+ #
10
+ # nanook = Nanook.new
11
+ # account = nanook.block("991CF19...")
12
+ #
13
+ # Or compose the longhand way like this:
14
+ #
15
+ # rpc_conn = Nanook::Rpc.new
16
+ # block = Nanook::Block.new(rpc_conn, "991CF19...")
2
17
  class Block
3
18
 
4
- def initialize(block, rpc)
5
- @block = block
19
+ def initialize(rpc, block)
6
20
  @rpc = rpc
21
+ @block = block
7
22
  block_required! # All methods expect a block
8
23
  end
9
24
 
@@ -28,6 +43,10 @@ class Nanook
28
43
  rpc(:history, :hash, count: limit)[:history]
29
44
  end
30
45
 
46
+ def id
47
+ @block
48
+ end
49
+
31
50
  def info(allow_unchecked: false)
32
51
  if allow_unchecked
33
52
  # TODO not actually sure what this response looks like when it's not an unchecked block, assuming its blank
@@ -75,6 +94,10 @@ class Nanook
75
94
  Nanook::Util.coerce_empty_string_to_type(response, Array)
76
95
  end
77
96
 
97
+ def inspect # :nodoc:
98
+ "#{self.class.name}(id: \"#{id}\", object_id: \"#{"0x00%x" % (object_id << 1)}\")"
99
+ end
100
+
78
101
  private
79
102
 
80
103
  # Some RPC calls expect the param that represents the block to be named
@@ -1,9 +1,9 @@
1
1
  class Nanook
2
2
  class Key
3
3
 
4
- def initialize(key=nil, rpc)
5
- @key = key
4
+ def initialize(rpc, key=nil)
6
5
  @rpc = rpc
6
+ @key = key
7
7
  end
8
8
 
9
9
  def generate(seed: nil, index: nil)
@@ -16,11 +16,19 @@ class Nanook
16
16
  end
17
17
  end
18
18
 
19
+ def id
20
+ @key
21
+ end
22
+
19
23
  def info
20
24
  key_required!
21
25
  rpc(:key_expand)
22
26
  end
23
27
 
28
+ def inspect # :nodoc:
29
+ "#{self.class.name}(id: \"#{id}\", object_id: \"#{"0x00%x" % (object_id << 1)}\")"
30
+ end
31
+
24
32
  private
25
33
 
26
34
  def rpc(action, params={})
@@ -25,6 +25,10 @@ class Nanook
25
25
  rpc(:frontier_count)[:count]
26
26
  end
27
27
 
28
+ def inspect # :nodoc:
29
+ "#{self.class.name}(object_id: \"#{"0x00%x" % (object_id << 1)}\")"
30
+ end
31
+
28
32
  def peers
29
33
  rpc(:peers)[:peers]
30
34
  end
@@ -36,6 +36,10 @@ class Nanook
36
36
  end
37
37
  end
38
38
 
39
+ def inspect # :nodoc:
40
+ "#{self.class.name}(host: #{@http.address}, timeout: #{@http.read_timeout} object_id: \"#{"0x00%x" % (object_id << 1)}\")"
41
+ end
42
+
39
43
  private
40
44
 
41
45
  # Convert Strings of primitives to primitives
@@ -56,7 +60,7 @@ class Nanook
56
60
  [k, v]
57
61
  end
58
62
 
59
- Hash[new_hash].to_symbolized_hash
63
+ Hash[new_hash.sort].to_symbolized_hash
60
64
  end
61
65
 
62
66
  def parse_value(v)
@@ -1,8 +1,16 @@
1
+ require 'bigdecimal'
2
+
1
3
  class Nanook
2
4
  class Util
3
5
 
6
+ STEP = BigDecimal.new("10")**BigDecimal.new("30")
7
+
4
8
  def self.NANO_to_raw(nano)
5
- nano * (10**30)
9
+ (BigDecimal.new(nano.to_s) * STEP).to_i
10
+ end
11
+
12
+ def self.raw_to_NANO(raw)
13
+ raw.to_f / STEP
6
14
  end
7
15
 
8
16
  def self.coerce_empty_string_to_type(response, type)
@@ -1,3 +1,3 @@
1
1
  class Nanook
2
- VERSION = "0.7.0"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -1,82 +1,332 @@
1
1
  class Nanook
2
+
3
+ # The <tt>Nanook::Wallet</tt> class lets you manage your nano wallets,
4
+ # as well as some account-specific things like making and receiving payments.
5
+ #
6
+ # Your wallets each have a seed, which is a 32-byte uppercase hex
7
+ # string that looks like this:
8
+ #
9
+ # 000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F
10
+ #
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.
17
+ #
18
+ # === Initializing
19
+ #
20
+ # Initialize this class through the convenient Nanook#wallet method:
21
+ #
22
+ # nanook = Nanook.new
23
+ # wallet = nanook.wallet(wallet_seed)
24
+ #
25
+ # Or compose the longhand way like this:
26
+ #
27
+ # rpc_conn = Nanook::Rpc.new
28
+ # wallet = Nanook::Wallet.new(rpc_conn, wallet_seed)
2
29
  class Wallet
3
30
 
4
- def initialize(wallet, rpc)
5
- @wallet = wallet
31
+ def initialize(rpc, wallet)
6
32
  @rpc = rpc
33
+ @wallet = wallet
7
34
  end
8
35
 
36
+ # A convenient method that returns an account in your wallet, allowing
37
+ # you to perform all the actions in Nanook::WalletAccount on it.
38
+ #
39
+ # wallet.account("xrb_...") #=> Nanook::WalletAccount instance
40
+ #
41
+ # See Nanook::WalletAccount.
42
+ #
43
+ # Will throw an ArgumentError if the wallet does not contain the account.
44
+ #
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.
52
+ #
53
+ # ==== Examples
54
+ #
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
9
57
  def account(account=nil)
10
- Nanook::WalletAccount.new(@wallet, account, @rpc)
58
+ Nanook::WalletAccount.new(@rpc, @wallet, account)
11
59
  end
12
60
 
61
+ # Returns an Array with Strings of all account ids in the wallet.
62
+ #
63
+ # ==== Example response
64
+ #
65
+ # [
66
+ # "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000",
67
+ # "xrb_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx"
68
+ # ]
13
69
  def accounts
14
70
  wallet_required!
15
71
  response = rpc(:account_list)[:accounts]
16
72
  Nanook::Util.coerce_empty_string_to_type(response, Array)
17
73
  end
18
74
 
19
- def balance(account_break_down: false)
75
+ # Returns a Hash containing the balance of all accounts in the
76
+ # wallet, optionally breaking the balances down by account.
77
+ #
78
+ # ==== Arguments
79
+ #
80
+ # [+account_break_down:+] Boolean (default is +false+). When +true+
81
+ # the response will contain balances per
82
+ # account.
83
+ # [+unit:+] Symbol (default is +:nano+) Represents the unit that
84
+ # the balances will be returned in.
85
+ # Must be either +:nano+ or +:raw+. (Note: this method
86
+ # interprets +:nano+ as NANO, which is technically Mnano
87
+ # See {What are Nano's Units}[https://nano.org/en/faq#what-are-nano-units-])
88
+ #
89
+ # ==== Examples
90
+ # wallet.balance
91
+ #
92
+ # Example response:
93
+ #
94
+ # {
95
+ # "balance"=>5,
96
+ # "pending"=>0.001
97
+ # }
98
+ #
99
+ # Asking for the balances to be returned in raw instead of NANO.
100
+ #
101
+ # wallet.balance(unit: :raw)
102
+ #
103
+ # Example response:
104
+ #
105
+ # {
106
+ # "balance"=>5000000000000000000000000000000,
107
+ # "pending"=>1000000000000000000000000000
108
+ # }
109
+ #
110
+ # Asking for totals to be broken down by account:
111
+ #
112
+ # wallet.balance(account_break_down: true)
113
+ #
114
+ # Example response:
115
+ #
116
+ {
117
+ "xrb_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000"=>{
118
+ "balance"=>2500000000000000,
119
+ "pending"=>10000000000000
120
+ },
121
+ "xrb_1e5aqegc1jb7qe964u4adzmcezyo6o146zb8hm6dft8tkp79za3sxwjym5rx"=>{
122
+ "balance"=>2500000000000000,
123
+ "pending"=>0
124
+ },
125
+ }
126
+ def balance(account_break_down: false, unit: Nanook::WalletAccount::DEFAULT_UNIT)
20
127
  wallet_required!
128
+
129
+ unless Nanook::WalletAccount::UNITS.include?(unit)
130
+ raise ArgumentError.new("Unsupported unit: #{unit}")
131
+ end
132
+
21
133
  if account_break_down
22
- rpc(:wallet_balances)[:balances]
23
- else
24
- rpc(:wallet_balance_total)
134
+ return Nanook::Util.coerce_empty_string_to_type(rpc(:wallet_balances)[:balances], Hash).tap do |r|
135
+ if unit == :nano
136
+ r.each do |account, balances|
137
+ r[account][:balance] = Nanook::Util.raw_to_NANO(r[account][:balance])
138
+ r[account][:pending] = Nanook::Util.raw_to_NANO(r[account][:balapendingnce])
139
+ end
140
+ end
141
+ end
142
+ end
143
+
144
+ rpc(:wallet_balance_total).tap do |r|
145
+ if unit == :nano
146
+ r[:balance] = Nanook::Util.raw_to_NANO(r[:balance])
147
+ r[:pending] = Nanook::Util.raw_to_NANO(r[:pending])
148
+ end
25
149
  end
26
150
  end
27
151
 
152
+ # Creates a new wallet.
153
+ #
154
+ # Nanook.new.wallet.create
155
+ #
156
+ # ==== Very important
157
+ #
158
+ # <b>Please read this.</b> The response of this method is a wallet seed. A seed is
159
+ # a 32-byte uppercase hex string. You can think of this string as your
160
+ # API key to the nano network. The person who knows it can do all read and write
161
+ # actions against the wallet and all accounts inside the wallet from
162
+ # anywhere on the nano network, not just on the node you created the
163
+ # wallet on.
164
+ #
165
+ # If you intend for your wallet to contain funds, then make sure that
166
+ # you consider the seed that is returned as the key to your funds
167
+ # and store it somewhere secret and safe. Only transmit
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.
171
+ #
172
+ # ==== Example response:
173
+ #
174
+ # "CC2C9846A44DB6F0363F647D12B957794AD937F59498D4E35C172C81E2888650"
28
175
  def create
29
176
  rpc(:wallet_create)[:wallet]
30
177
  end
31
178
 
179
+ # Destroy the wallet. Returns a boolean indicating whether the action
180
+ # was successful or not.
181
+ #
182
+ # ==== Example Response
183
+ # true
32
184
  def destroy
33
185
  wallet_required!
34
186
  rpc(:wallet_destroy)
35
187
  true
36
188
  end
37
189
 
190
+ # Generates a String containing a JSON representation of your wallet.
191
+ #
192
+ # ==== Example response
193
+ #
194
+ # "{\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"
38
195
  def export
39
196
  wallet_required!
40
197
  rpc(:wallet_export)[:json]
41
198
  end
42
199
 
200
+ # Returns boolean indicating if the wallet contains an account.
201
+ #
202
+ # ==== Arguments
203
+ #
204
+ # [+account+] String account id (will start with <tt>"xrb_..."</tt>)
205
+ #
206
+ # ==== Example response
207
+ # true
43
208
  def contains?(account)
44
209
  wallet_required!
45
210
  response = rpc(:wallet_contains, account: account)
46
211
  !response.empty? && response[:exists] == 1
47
212
  end
48
213
 
49
- def pay(from:, to:, amount:, id:)
214
+ def id
215
+ @wallet
216
+ end
217
+
218
+ def inspect # :nodoc:
219
+ "#{self.class.name}(id: \"#{id}\", object_id: \"#{"0x00%x" % (object_id << 1)}\")"
220
+ end
221
+
222
+ # Make a payment from an account in your wallet to another account
223
+ # on the nano network. Returns a <i>send</i> block hash if successful,
224
+ # or an error String if unsuccessful.
225
+ #
226
+ # ==== Arguments
227
+ #
228
+ # [+from:+] String account id of an account in your wallet
229
+ # [+to:+] String account id of the recipient of your payment
230
+ # [+amount:+] Can be either an Integer or Float.
231
+ # [+unit:+] Symbol (default is +:nano+). Represents the unit that +amount+ is in.
232
+ # Must be either +:nano+ or +:raw+. (Note: this method
233
+ # interprets +:nano+ as NANO, which is technically Mnano
234
+ # See {What are Nano's Units}[https://nano.org/en/faq#what-are-nano-units-])
235
+ # [+id:+] String. Must be unique per payment. It serves an important
236
+ # purpose; it allows you to make the same call multiple
237
+ # times with the same +id+ and be reassured that you will
238
+ # only ever send that nano payment once.
239
+ #
240
+ # 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]:
241
+ #
242
+ # <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>
243
+ #
244
+ # ==== Examples
245
+ #
246
+ # wallet.pay(from: "xrb_...", to: "xrb_...", amount: 1.1, id: "myUniqueId123")
247
+ # wallet.pay(from: "xrb_...", to: "xrb_...", amount: 54000000000000, unit: :raw, id: "myUniqueId123")
248
+ #
249
+ # ==== Example responses
250
+ # "718CC2121C3E641059BC1C2CFC45666C99E8AE922F7A807B7D07B62C995D79E2"
251
+ #
252
+ # Or:
253
+ #
254
+ # "Account not found"
255
+ def pay(from:, to:, amount:, unit: Nanook::WalletAccount::DEFAULT_UNIT, id:)
50
256
  wallet_required!
51
- account(from).pay(to: to, amount: amount, id: id)
257
+ validate_wallet_contains_account!(from)
258
+ account(from).pay(to: to, amount: amount, unit: unit, id: id)
52
259
  end
53
260
 
261
+ # Receives a pending payment into an account in the wallet.
262
+ #
263
+ # When called with no +block+ argument, the latest pending payment
264
+ # for the account will be received.
265
+ #
266
+ # Returns a <i>receive</i> block hash if a receive was successful,
267
+ # or +false+ if there were no pending payments to receive.
268
+ #
269
+ # You can also receive a specific pending block if you know it by
270
+ # passing the block has in as an argument.
271
+ #
272
+ # ==== Arguments
273
+ #
274
+ # [+block+] Optional block hash of pending payment. If not provided,
275
+ # the latest pending payment will be received
276
+ # [+into:+] String account id of account in your wallet to receive the
277
+ # payment into
278
+ #
279
+ # ==== Examples
280
+ #
281
+ # wallet.receive(into: "xrb...")
282
+ # wallet.receive("718CC21...", into: "xrb...")
283
+ #
284
+ # ==== Example responses
285
+ #
286
+ # "718CC2121C3E641059BC1C2CFC45666C99E8AE922F7A807B7D07B62C995D79E2"
287
+ #
288
+ # Or:
289
+ #
290
+ # false
54
291
  def receive(block=nil, into:)
55
292
  wallet_required!
293
+ validate_wallet_contains_account!(into)
56
294
  account(into).receive(block)
57
295
  end
58
296
 
297
+ # Returns a boolean to indicate if the wallet is locked.
298
+ #
299
+ # ==== Example response
300
+ #
301
+ # true
59
302
  def locked?
60
303
  wallet_required!
61
304
  response = rpc(:wallet_locked)
62
305
  !response.empty? && response[:locked] != 0
63
306
  end
64
307
 
308
+ # Unlocks a previously locked wallet. Returns a boolean to indicate
309
+ # if the action was successful.
310
+ #
311
+ # ==== Example response
312
+ #
313
+ # true
65
314
  def unlock(password)
66
315
  wallet_required!
67
316
  rpc(:password_enter, password: password)[:valid] == 1
68
317
  end
69
318
 
319
+ # Changes the password for a wallet. Returns a boolean to indicate
320
+ # if the action was successful.
321
+ #
322
+ # ==== Example response
323
+ #
324
+ # true
70
325
  def change_password(password)
71
326
  wallet_required!
72
327
  rpc(:password_change, password: password)[:changed] == 1
73
328
  end
74
329
 
75
- def all
76
- wallet_required!
77
- rpc(:account_list)[:accounts]
78
- end
79
-
80
330
  private
81
331
 
82
332
  def rpc(action, params={})
@@ -90,5 +340,16 @@ class Nanook
90
340
  end
91
341
  end
92
342
 
343
+ def validate_wallet_contains_account!(account)
344
+ @known_valid_accounts ||= []
345
+ return if @known_valid_accounts.include?(account)
346
+
347
+ if contains?(account)
348
+ @known_valid_accounts << account
349
+ else
350
+ raise ArgumentError.new("Account does not exist in wallet. Account: #{account}, wallet: #{@wallet}")
351
+ end
352
+ end
353
+
93
354
  end
94
355
  end