nanook 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +36 -1
- data/README.md +20 -9
- data/lib/nanook.rb +4 -4
- data/lib/nanook/account.rb +169 -111
- data/lib/nanook/error.rb +1 -0
- data/lib/nanook/node.rb +131 -4
- data/lib/nanook/rpc.rb +23 -2
- data/lib/nanook/util.rb +19 -0
- data/lib/nanook/version.rb +1 -1
- data/lib/nanook/wallet.rb +111 -75
- data/lib/nanook/wallet_account.rb +44 -40
- metadata +2 -2
data/lib/nanook/error.rb
CHANGED
data/lib/nanook/node.rb
CHANGED
@@ -1,31 +1,96 @@
|
|
1
1
|
class Nanook
|
2
|
+
|
3
|
+
# The <tt>Nanook::Node</tt> class contains methods to manage your nano
|
4
|
+
# node and query its data of the nano network.
|
5
|
+
#
|
6
|
+
# Your node is constantly syncing data with other nodes on the network. When
|
7
|
+
# your node first starts up after being built, its database will be empty
|
8
|
+
# and it will begin synchronizing and downloading data of the nano ledger
|
9
|
+
# to its local database. The ledger is the central record of all accounts
|
10
|
+
# and transactions. Some of the methods in this class query your node's
|
11
|
+
# database formed from the nano ledger, and so the responses are determined
|
12
|
+
# by the completeness of your node's database.
|
13
|
+
#
|
14
|
+
# You can determine how synchronized your node is with the nano ledger
|
15
|
+
# with the {#sync_progress} method.
|
16
|
+
#
|
17
|
+
# === Initializing
|
18
|
+
#
|
19
|
+
# Initialize this class through the convenient {Nanook#node} method:
|
20
|
+
#
|
21
|
+
# node = Nanook.new.node
|
22
|
+
#
|
23
|
+
# Or compose the longhand way like this:
|
24
|
+
#
|
25
|
+
# rpc_conn = Nanook::Rpc.new
|
26
|
+
# node = Nanook::Node.new(rpc_conn)
|
2
27
|
class Node
|
3
28
|
|
4
29
|
def initialize(rpc)
|
5
30
|
@rpc = rpc
|
6
31
|
end
|
7
32
|
|
33
|
+
# The number of accounts in the nano ledger--essentially all
|
34
|
+
# accounts with _open_ blocks. An _open_ block
|
35
|
+
# is the type of block written to the nano ledger when an account
|
36
|
+
# receives its first payment (see {Nanook::WalletAccount#receive}). All accounts
|
37
|
+
# that respond +true+ to {Nanook::Account#exists?} have open blocks in the ledger.
|
38
|
+
#
|
39
|
+
# @return [Integer] number of accounts with _open_ blocks.
|
8
40
|
def account_count
|
9
41
|
rpc(:frontier_count)[:count]
|
10
42
|
end
|
11
43
|
alias_method :frontier_count, :account_count
|
12
44
|
|
45
|
+
# The count of all blocks downloaded to the node, and
|
46
|
+
# blocks still to be synchronized by the node.
|
47
|
+
#
|
48
|
+
# ==== Example:
|
49
|
+
#
|
50
|
+
#
|
51
|
+
#
|
52
|
+
# @return [Hash{Symbol=>Integer}] number of blocks and unchecked
|
53
|
+
# synchronizing blocks
|
13
54
|
def block_count
|
14
55
|
rpc(:block_count)
|
15
56
|
end
|
16
57
|
|
17
|
-
|
58
|
+
# The count of all known blocks by their type.
|
59
|
+
#
|
60
|
+
# ==== Example:
|
61
|
+
#
|
62
|
+
# node.block_count_by_type
|
63
|
+
#
|
64
|
+
# Example response:
|
65
|
+
#
|
66
|
+
# {
|
67
|
+
# send: 1000,
|
68
|
+
# receive: 900,
|
69
|
+
# open: 900,
|
70
|
+
# change: 50
|
71
|
+
# }
|
72
|
+
#
|
73
|
+
# @return [Hash{Symbol=>Integer}] number of blocks by type
|
74
|
+
def block_count_by_type
|
18
75
|
rpc(:block_count_type)
|
19
76
|
end
|
77
|
+
alias_method :block_count_type, :block_count_by_type
|
20
78
|
|
79
|
+
# Initialize bootstrap to a specific IP address and port.
|
80
|
+
#
|
81
|
+
# @return [Boolean] indicating if the action was successful
|
21
82
|
def bootstrap(address:, port:)
|
22
83
|
rpc(:bootstrap, address: address, port: port).has_key?(:success)
|
23
84
|
end
|
24
85
|
|
86
|
+
# Initialize multi-connection bootstrap to random peers
|
87
|
+
#
|
88
|
+
# @return [Boolean] indicating if the action was successful
|
25
89
|
def bootstrap_any
|
26
90
|
rpc(:bootstrap_any).has_key?(:success)
|
27
91
|
end
|
28
92
|
|
93
|
+
# @return [String]
|
29
94
|
def inspect
|
30
95
|
"#{self.class.name}(object_id: \"#{"0x00%x" % (object_id << 1)}\")"
|
31
96
|
end
|
@@ -34,14 +99,60 @@ class Nanook
|
|
34
99
|
rpc(:peers)[:peers]
|
35
100
|
end
|
36
101
|
|
37
|
-
|
38
|
-
|
102
|
+
# All representatives and their voting weight.
|
103
|
+
#
|
104
|
+
# ==== Example:
|
105
|
+
#
|
106
|
+
# node.representatives
|
107
|
+
#
|
108
|
+
# Example response:
|
109
|
+
#
|
110
|
+
# {
|
111
|
+
# xrb_1111111111111111111111111111111111111111111111111117353trpda: 3822372327060170000000000000000000000,
|
112
|
+
# xrb_1111111111111111111111111111111111111111111111111awsq94gtecn: 30999999999999999999999999000000,
|
113
|
+
# xrb_114nk4rwjctu6n6tr6g6ps61g1w3hdpjxfas4xj1tq6i8jyomc5d858xr1xi: 0
|
114
|
+
# }
|
115
|
+
#
|
116
|
+
# @return [Hash{Symbol=>Integer}] known representatives and their voting weight
|
117
|
+
def representatives(unit: Nanook.default_unit)
|
118
|
+
unless Nanook::UNITS.include?(unit)
|
119
|
+
raise ArgumentError.new("Unsupported unit: #{unit}")
|
120
|
+
end
|
121
|
+
|
122
|
+
response = rpc(:representatives)[:representatives]
|
123
|
+
return response if unit == :raw
|
124
|
+
|
125
|
+
r = response.map do |account_id, balance|
|
126
|
+
balance = Nanook::Util.raw_to_NANO(balance)
|
127
|
+
|
128
|
+
[account_id, balance]
|
129
|
+
end
|
130
|
+
|
131
|
+
Hash[r].to_symbolized_hash
|
132
|
+
end
|
133
|
+
|
134
|
+
# All online representatives that have voted recently. Note, due to the
|
135
|
+
# design of the nano RPC, this method cannot return the voting weight
|
136
|
+
# of the representatives.
|
137
|
+
#
|
138
|
+
# ==== Example:
|
139
|
+
#
|
140
|
+
# node.representatives_online # => ["xrb_111...", "xrb_222"]
|
141
|
+
#
|
142
|
+
# @return [Array<String>] array of representative account ids
|
143
|
+
def representatives_online
|
144
|
+
response = rpc(:representatives_online)[:representatives].keys.map(&:to_s)
|
39
145
|
end
|
40
146
|
|
147
|
+
# Safely shuts down the node.
|
148
|
+
#
|
149
|
+
# @return [Boolean] indicating if action was successful
|
41
150
|
def stop
|
42
151
|
rpc(:stop).has_key?(:success)
|
43
152
|
end
|
44
153
|
|
154
|
+
# @param limit [Integer] number of synchronizing blocks to return
|
155
|
+
# @return [Hash{Symbol=>String}] information about the synchronizing blocks for this node
|
45
156
|
def synchronizing_blocks(limit: 1000)
|
46
157
|
response = rpc(:unchecked, count: limit)[:blocks]
|
47
158
|
response = response.map do |block, info|
|
@@ -49,7 +160,16 @@ class Nanook
|
|
49
160
|
end
|
50
161
|
Hash[response.sort].to_symbolized_hash
|
51
162
|
end
|
52
|
-
|
163
|
+
alias_method :unchecked, :synchronizing_blocks
|
164
|
+
|
165
|
+
# The percentage completeness of the synchronization process for
|
166
|
+
# your node as it downloads the nano ledger. Note, it's normal for
|
167
|
+
# your progress to not ever reach 100. The closer to 100, the more
|
168
|
+
# complete your node's data is, and so the query methods in this class
|
169
|
+
# become more reliable.
|
170
|
+
#
|
171
|
+
# @return [Float] the percentage completeness of the synchronization
|
172
|
+
# process for your node
|
53
173
|
def sync_progress
|
54
174
|
response = rpc(:block_count)
|
55
175
|
|
@@ -60,13 +180,20 @@ class Nanook
|
|
60
180
|
count.to_f * 100 / total.to_f
|
61
181
|
end
|
62
182
|
|
183
|
+
# This method is deprecated and will be removed in 3.0, as a node never
|
184
|
+
# reaches 100% synchronization.
|
185
|
+
#
|
186
|
+
# @return [Boolean] signalling if this node ever reaches 100% synchronized
|
63
187
|
def synced?
|
188
|
+
warn "[DEPRECATION] `synced?` is deprecated and will be removed in 3.0"
|
64
189
|
rpc(:block_count)[:unchecked] == 0
|
65
190
|
end
|
66
191
|
|
192
|
+
# @return [Hash{Symbol=>Integer|String}] version information for this node
|
67
193
|
def version
|
68
194
|
rpc(:version)
|
69
195
|
end
|
196
|
+
alias_method :info, :version
|
70
197
|
|
71
198
|
private
|
72
199
|
|
data/lib/nanook/rpc.rb
CHANGED
@@ -2,10 +2,23 @@ require 'json'
|
|
2
2
|
require 'symbolized'
|
3
3
|
|
4
4
|
class Nanook
|
5
|
+
|
6
|
+
# The <tt>Nanook::Rpc</tt> class is responsible for maintaining the
|
7
|
+
# connection to the RPC server, calling the RPC and parsing its response
|
8
|
+
# into Ruby primitives.
|
9
|
+
#
|
10
|
+
# Internally, the {Nanook} class creates an instance of this class, and
|
11
|
+
# it's generally more convenient to interact with the RPC through an
|
12
|
+
# instance of {Nanook#rpc} instead of by instantiating this class directly:
|
13
|
+
#
|
14
|
+
# nanook = Nanook.new
|
15
|
+
# nanook.rpc(:accounts_create, wallet: wallet_id, count: 2)
|
5
16
|
class Rpc
|
6
17
|
|
18
|
+
# Default RPC server and port to connect to
|
7
19
|
DEFAULT_URI = "http://localhost:7076"
|
8
|
-
|
20
|
+
# Default request timeout in seconds
|
21
|
+
DEFAULT_TIMEOUT = 60
|
9
22
|
|
10
23
|
def initialize(uri=DEFAULT_URI, timeout:DEFAULT_TIMEOUT)
|
11
24
|
@rpc_server = URI(uri)
|
@@ -20,6 +33,12 @@ class Nanook
|
|
20
33
|
@request.content_type = "application/json"
|
21
34
|
end
|
22
35
|
|
36
|
+
# Calls the RPC server and returns the response.
|
37
|
+
#
|
38
|
+
# @param action [Symbol] the "action" of the RPC to call. The RPC always
|
39
|
+
# expects an "action" param to identify what RPC action is being called.
|
40
|
+
# @param params [Hash] all other params to pass to the RPC
|
41
|
+
# @return [Hash] the response from the RPC
|
23
42
|
def call(action, params={})
|
24
43
|
# Stringify param values
|
25
44
|
params = Hash[params.map {|k, v| [k, v.to_s] }]
|
@@ -36,13 +55,14 @@ class Nanook
|
|
36
55
|
end
|
37
56
|
end
|
38
57
|
|
58
|
+
# @return [String]
|
39
59
|
def inspect
|
40
60
|
"#{self.class.name}(host: \"#{@rpc_server}\", timeout: #{@http.read_timeout} object_id: \"#{"0x00%x" % (object_id << 1)}\")"
|
41
61
|
end
|
42
62
|
|
43
63
|
private
|
44
64
|
|
45
|
-
#
|
65
|
+
# Recursively parses the RPC response, sending values to #parse_value
|
46
66
|
def process_hash(h)
|
47
67
|
new_hash = h.map do |k,v|
|
48
68
|
v = if v.is_a?(Array)
|
@@ -63,6 +83,7 @@ class Nanook
|
|
63
83
|
Hash[new_hash.sort].to_symbolized_hash
|
64
84
|
end
|
65
85
|
|
86
|
+
# Converts Strings to primitives
|
66
87
|
def parse_value(v)
|
67
88
|
return v.to_i if v.match(/^\d+\Z/)
|
68
89
|
return true if v == "true"
|
data/lib/nanook/util.rb
CHANGED
@@ -1,18 +1,37 @@
|
|
1
1
|
require 'bigdecimal'
|
2
2
|
|
3
3
|
class Nanook
|
4
|
+
|
5
|
+
# Set of class utility methods.
|
4
6
|
class Util
|
5
7
|
|
8
|
+
# Constant used to convert back and forth between raw and NANO.
|
6
9
|
STEP = BigDecimal.new("10")**BigDecimal.new("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
16
|
(BigDecimal.new(nano.to_s) * STEP).to_i
|
10
17
|
end
|
11
18
|
|
19
|
+
# Converts an amount of raw to an amount of NANO.
|
20
|
+
#
|
21
|
+
# @param raw [Integer] amount in raw
|
22
|
+
# @return [Float|Integer] amount in NANO
|
12
23
|
def self.raw_to_NANO(raw)
|
13
24
|
(raw.to_f / STEP).to_f
|
14
25
|
end
|
15
26
|
|
27
|
+
# Converts an empty String value into an empty version of another type.
|
28
|
+
#
|
29
|
+
# The RPC often returns an empty String (<tt>""</tt>) as a value, when a
|
30
|
+
# +nil+, or empty Array (<tt>[]</tt>), or empty Hash (<tt>{}</tt>) would be better.
|
31
|
+
# If the response might be
|
32
|
+
#
|
33
|
+
# @param response the value returned from the RPC server
|
34
|
+
# @param type the type to return an empty of
|
16
35
|
def self.coerce_empty_string_to_type(response, type)
|
17
36
|
if response == "" || response.nil?
|
18
37
|
return type.new
|
data/lib/nanook/version.rb
CHANGED
data/lib/nanook/wallet.rb
CHANGED
@@ -3,21 +3,42 @@ class Nanook
|
|
3
3
|
# The <tt>Nanook::Wallet</tt> class lets you manage your nano wallets,
|
4
4
|
# as well as some account-specific things like making and receiving payments.
|
5
5
|
#
|
6
|
-
#
|
7
|
-
#
|
6
|
+
# === Wallet seeds vs ids
|
7
|
+
#
|
8
|
+
# Your wallets each have an id as well as a seed. Both are 32-byte uppercase hex
|
9
|
+
# strings that look like this:
|
8
10
|
#
|
9
11
|
# 000D1BAEC8EC208142C99059B393051BAC8380F9B5A2E6B2489A277D81789F3F
|
10
12
|
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
# your
|
13
|
+
# This class uses wallet _ids_ to identify your wallet. A wallet id only
|
14
|
+
# exists locally on the nano node that it was created on. The person
|
15
|
+
# who knows this id can only perform all read and write actions against
|
16
|
+
# the wallet and all accounts inside the wallet from the same nano node
|
17
|
+
# that it was created on. This makes wallet ids fairly safe to use as a
|
18
|
+
# person needs to know your wallet id as well as have access to run
|
19
|
+
# RPC commands against your nano node to be able to control your accounts.
|
20
|
+
#
|
21
|
+
# A _seed_ on the otherhand 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://github.com/nanocurrency/raiblocks/wiki/Command-line-interface
|
37
|
+
# --wallet_decrypt_unsafe CLI command}.
|
17
38
|
#
|
18
39
|
# === Initializing
|
19
40
|
#
|
20
|
-
# Initialize this class through the convenient Nanook#wallet method:
|
41
|
+
# Initialize this class through the convenient {Nanook#wallet} method:
|
21
42
|
#
|
22
43
|
# nanook = Nanook.new
|
23
44
|
# wallet = nanook.wallet(wallet_id)
|
@@ -33,31 +54,37 @@ class Nanook
|
|
33
54
|
@wallet = wallet
|
34
55
|
end
|
35
56
|
|
36
|
-
#
|
37
|
-
#
|
57
|
+
# Returns the given account in the wallet as a {Nanook::WalletAccount} instance
|
58
|
+
# to let you start working with it.
|
38
59
|
#
|
39
|
-
#
|
60
|
+
# Call with no +account+ argument if you wish to create a new account
|
61
|
+
# in the wallet, like this:
|
40
62
|
#
|
41
|
-
#
|
63
|
+
# wallet.account.create # => Nanook::WalletAccount
|
42
64
|
#
|
43
|
-
#
|
65
|
+
# See {Nanook::WalletAccount} for all the methods you can call on the
|
66
|
+
# account object returned.
|
44
67
|
#
|
45
|
-
# ====
|
46
|
-
# [+account+] Optional String of an account (starting with
|
47
|
-
# <tt>"xrb..."</tt>) to start working with. Must be an
|
48
|
-
# account within the wallet. When
|
49
|
-
# no account is given, the instance returned only allows you to call
|
50
|
-
# +create+ on it, to create a new account. Otherwise, you
|
51
|
-
# must pass an account string for all other methods.
|
68
|
+
# ==== Examples:
|
52
69
|
#
|
53
|
-
#
|
70
|
+
# wallet.account("xrb_...") # => Nanook::WalletAccount
|
71
|
+
# wallet.account.create # => Nanook::WalletAccount
|
54
72
|
#
|
55
|
-
#
|
56
|
-
#
|
73
|
+
# @param [String] account optional String of an account (starting with
|
74
|
+
# <tt>"xrb..."</tt>) to start working with. Must be an account within
|
75
|
+
# the wallet. When no account is given, the instance returned only
|
76
|
+
# allows you to call +create+ on it, to create a new account.
|
77
|
+
# @raise [ArgumentError] if the wallet does no contain the account
|
78
|
+
# @return [Nanook::WalletAccount]
|
57
79
|
def account(account=nil)
|
58
80
|
Nanook::WalletAccount.new(@rpc, @wallet, account)
|
59
81
|
end
|
60
82
|
|
83
|
+
# Array of {Nanook::WalletAccount} instances of accounts in the wallet.
|
84
|
+
#
|
85
|
+
# See {Nanook::WalletAccount} for all the methods you can call on the
|
86
|
+
# account objects returned.
|
87
|
+
#
|
61
88
|
# ==== Example:
|
62
89
|
#
|
63
90
|
# wallet.accounts # => [Nanook::WalletAccount, Nanook::WalletAccount...]
|
@@ -71,21 +98,9 @@ class Nanook
|
|
71
98
|
end
|
72
99
|
end
|
73
100
|
|
74
|
-
#
|
75
|
-
# wallet, optionally breaking the balances down by account.
|
76
|
-
#
|
77
|
-
# ==== Arguments
|
101
|
+
# Balance of all accounts in the wallet, optionally breaking the balances down by account.
|
78
102
|
#
|
79
|
-
#
|
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
|
103
|
+
# ==== Examples:
|
89
104
|
# wallet.balance
|
90
105
|
#
|
91
106
|
# Example response:
|
@@ -122,6 +137,12 @@ class Nanook
|
|
122
137
|
# "pending"=>0
|
123
138
|
# },
|
124
139
|
# }
|
140
|
+
#
|
141
|
+
# @param [Boolean] account_break_down (default is +false+). When +true+
|
142
|
+
# the response will contain balances per account.
|
143
|
+
# @param unit (see Nanook::Account#balance)
|
144
|
+
#
|
145
|
+
# @return [Hash{Symbol=>Integer|Float|Hash}]
|
125
146
|
def balance(account_break_down: false, unit: Nanook.default_unit)
|
126
147
|
wallet_required!
|
127
148
|
|
@@ -150,6 +171,10 @@ class Nanook
|
|
150
171
|
|
151
172
|
# Changes a wallet's seed.
|
152
173
|
#
|
174
|
+
# ==== Example:
|
175
|
+
#
|
176
|
+
# wallet.change_seed("000D1BA...") # => true
|
177
|
+
#
|
153
178
|
# @param seed [String] the seed to change to.
|
154
179
|
# @return [Boolean] indicating whether the change was successful.
|
155
180
|
def change_seed(seed)
|
@@ -162,6 +187,10 @@ class Nanook
|
|
162
187
|
# The wallet will be created only on this node. It's important that
|
163
188
|
# if you intend to add funds to accounts in this wallet that you
|
164
189
|
# backup the wallet *seed* in order to restore the wallet in future.
|
190
|
+
# The nano command line interface (CLI) is the only method for
|
191
|
+
# backing up a wallet's seed. See the
|
192
|
+
# {https://github.com/nanocurrency/raiblocks/wiki/Command-line-interface
|
193
|
+
# --wallet_decrypt_unsafe CLI command}.
|
165
194
|
#
|
166
195
|
# ==== Example:
|
167
196
|
# Nanook.new.wallet.create # => Nanook::Wallet
|
@@ -172,11 +201,13 @@ class Nanook
|
|
172
201
|
self
|
173
202
|
end
|
174
203
|
|
175
|
-
#
|
176
|
-
#
|
204
|
+
# Destroys the wallet.
|
205
|
+
#
|
206
|
+
# ==== Example:
|
207
|
+
#
|
208
|
+
# wallet.destroy # => true
|
177
209
|
#
|
178
|
-
#
|
179
|
-
# true
|
210
|
+
# @return [Boolean] indicating success of the action
|
180
211
|
def destroy
|
181
212
|
wallet_required!
|
182
213
|
rpc(:wallet_destroy)
|
@@ -185,80 +216,81 @@ class Nanook
|
|
185
216
|
|
186
217
|
# Generates a String containing a JSON representation of your wallet.
|
187
218
|
#
|
188
|
-
# ==== Example
|
219
|
+
# ==== Example:
|
189
220
|
#
|
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"
|
221
|
+
# 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
222
|
def export
|
192
223
|
wallet_required!
|
193
224
|
rpc(:wallet_export)[:json]
|
194
225
|
end
|
195
226
|
|
196
|
-
#
|
197
|
-
#
|
198
|
-
# ==== Arguments
|
227
|
+
# Will return +true+ if the account exists in the wallet.
|
199
228
|
#
|
200
|
-
#
|
229
|
+
# ==== Example:
|
230
|
+
# wallet.contains?("xrb_...") # => true
|
201
231
|
#
|
202
|
-
#
|
203
|
-
#
|
232
|
+
# @param account [String] id (will start with <tt>"xrb_..."</tt>)
|
233
|
+
# @return [Boolean] indicating if the wallet contains the given account
|
204
234
|
def contains?(account)
|
205
235
|
wallet_required!
|
206
236
|
response = rpc(:wallet_contains, account: account)
|
207
237
|
!response.empty? && response[:exists] == 1
|
208
238
|
end
|
209
239
|
|
210
|
-
# @return [String]
|
240
|
+
# @return [String] the wallet id
|
211
241
|
def id
|
212
242
|
@wallet
|
213
243
|
end
|
214
|
-
alias_method :seed, :id
|
215
244
|
|
216
245
|
# @return [String]
|
217
246
|
def inspect
|
218
247
|
"#{self.class.name}(id: \"#{id}\", object_id: \"#{"0x00%x" % (object_id << 1)}\")"
|
219
248
|
end
|
220
249
|
|
221
|
-
#
|
222
|
-
# on the nano network.
|
223
|
-
# if successful, or a {Nanook::Error} if unsuccessful.
|
250
|
+
# Makes a payment from an account in your wallet to another account
|
251
|
+
# on the nano network.
|
224
252
|
#
|
225
|
-
# Note, there may be a delay in receiving a response due to Proof of
|
253
|
+
# Note, there may be a delay in receiving a response due to Proof of
|
254
|
+
# Work being done. From the {Nano RPC}[https://github.com/nanocurrency/raiblocks/wiki/RPC-protocol#account-create]:
|
226
255
|
#
|
227
|
-
# <i>Proof of Work is precomputed for one transaction in the
|
256
|
+
# <i>Proof of Work is precomputed for one transaction in the
|
257
|
+
# background. If it has been a while since your last transaction it
|
258
|
+
# will send instantly, the next one will need to wait for Proof of
|
259
|
+
# Work to be generated.</i>
|
228
260
|
#
|
229
|
-
# ==== Examples
|
261
|
+
# ==== Examples:
|
230
262
|
#
|
231
263
|
# wallet.pay(from: "xrb_...", to: "xrb_...", amount: 1.1, id: "myUniqueId123") # => "9AE2311..."
|
232
264
|
# wallet.pay(from: "xrb_...", to: "xrb_...", amount: 54000000000000, unit: :raw, id: "myUniqueId123") # => "9AE2311..."
|
233
265
|
#
|
234
|
-
# ==== Arguments
|
235
|
-
#
|
236
266
|
# @param from [String] account id of an account in your wallet
|
237
267
|
# @param to (see Nanook::WalletAccount#pay)
|
238
268
|
# @param amount (see Nanook::WalletAccount#pay)
|
239
269
|
# @param unit (see Nanook::Account#balance)
|
240
270
|
# @params id (see Nanook::WalletAccount#pay)
|
241
271
|
# @return (see Nanook::WalletAccount#pay)
|
272
|
+
# @raise [Nanook::Error] if unsuccessful
|
242
273
|
def pay(from:, to:, amount:, unit: Nanook.default_unit, id:)
|
243
274
|
wallet_required!
|
244
275
|
validate_wallet_contains_account!(from)
|
245
276
|
account(from).pay(to: to, amount: amount, unit: unit, id: id)
|
246
277
|
end
|
247
278
|
|
248
|
-
#
|
279
|
+
# Information about pending blocks (payments) that are waiting
|
249
280
|
# to be received by accounts in this wallet.
|
250
281
|
#
|
251
|
-
# See also the #receive method of this class for how to receive a pending payment.
|
282
|
+
# See also the {#receive} method of this class for how to receive a pending payment.
|
252
283
|
#
|
253
284
|
# @param limit [Integer] number of accounts with pending payments to return (default is 1000)
|
254
285
|
# @param detailed [Boolean]return a more complex Hash of pending block information (default is +false+)
|
255
286
|
# @param unit (see Nanook::Account#balance)
|
256
287
|
#
|
257
|
-
# ====
|
288
|
+
# ==== Examples:
|
258
289
|
#
|
259
290
|
# wallet.pending
|
260
291
|
#
|
261
|
-
#
|
292
|
+
# Example response:
|
293
|
+
#
|
262
294
|
# {
|
263
295
|
# :xrb_1111111111111111111111111111111111111111111111111117353trpda=>[
|
264
296
|
# "142A538F36833D1CC78B94E11C766F75818F8B940771335C6C1B8AB880C5BB1D",
|
@@ -268,11 +300,13 @@ class Nanook
|
|
268
300
|
# "4C1FEEF0BEA7F50BE35489A1233FE002B212DEA554B55B1B470D78BD8F210C74"
|
269
301
|
# ]
|
270
302
|
# }
|
271
|
-
#
|
303
|
+
#
|
304
|
+
# Asking for more information:
|
272
305
|
#
|
273
306
|
# wallet.pending(detailed: true)
|
274
307
|
#
|
275
|
-
#
|
308
|
+
# Example response:
|
309
|
+
#
|
276
310
|
# {
|
277
311
|
# :xrb_1111111111111111111111111111111111111111111111111117353trpda=>[
|
278
312
|
# {
|
@@ -332,14 +366,13 @@ class Nanook
|
|
332
366
|
# When called with no +block+ argument, the latest pending payment
|
333
367
|
# for the account will be received.
|
334
368
|
#
|
335
|
-
# Returns a <i>receive</i> block hash
|
336
|
-
#
|
337
|
-
# payments to receive.
|
369
|
+
# Returns a <i>receive</i> block hash id if a receive was successful,
|
370
|
+
# or +false+ if there were no pending payments to receive.
|
338
371
|
#
|
339
372
|
# You can receive a specific pending block if you know it by
|
340
373
|
# passing the block has in as an argument.
|
341
374
|
#
|
342
|
-
# ==== Examples
|
375
|
+
# ==== Examples:
|
343
376
|
#
|
344
377
|
# wallet.receive(into: "xrb...") # => "9AE2311..."
|
345
378
|
# wallet.receive("718CC21...", into: "xrb...") # => "9AE2311..."
|
@@ -354,7 +387,7 @@ class Nanook
|
|
354
387
|
account(into).receive(block)
|
355
388
|
end
|
356
389
|
|
357
|
-
#
|
390
|
+
# Restores a previously created wallet by its seed.
|
358
391
|
# A new wallet will be created on your node (with a new wallet id)
|
359
392
|
# and will have its seed set to the given seed.
|
360
393
|
#
|
@@ -381,11 +414,13 @@ class Nanook
|
|
381
414
|
self
|
382
415
|
end
|
383
416
|
|
384
|
-
# Returns
|
417
|
+
# Returns +true+ if the wallet is locked.
|
385
418
|
#
|
386
|
-
# ==== Example
|
419
|
+
# ==== Example:
|
387
420
|
#
|
388
|
-
#
|
421
|
+
# wallet.locked? #=> false
|
422
|
+
#
|
423
|
+
# @return [Boolean] indicates if the wallet is locked
|
389
424
|
def locked?
|
390
425
|
wallet_required!
|
391
426
|
response = rpc(:wallet_locked)
|
@@ -397,7 +432,8 @@ class Nanook
|
|
397
432
|
# ==== Example:
|
398
433
|
#
|
399
434
|
# wallet.unlock("new_pass") #=> true
|
400
|
-
#
|
435
|
+
#
|
436
|
+
# @return [Boolean] indicates if the unlocking action was successful
|
401
437
|
def unlock(password)
|
402
438
|
wallet_required!
|
403
439
|
rpc(:password_enter, password: password)[:valid] == 1
|