nanook 2.1.0 → 2.2.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.
- 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
|