nanook 0.7.0 → 1.0.0

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.
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