nanook 2.2.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +145 -3
- data/README.md +157 -90
- data/bin/console +4 -3
- data/lib/nanook.rb +77 -21
- data/lib/nanook/account.rb +236 -168
- data/lib/nanook/block.rb +363 -119
- data/lib/nanook/errors.rb +10 -0
- data/lib/nanook/node.rb +229 -66
- data/lib/nanook/private_key.rb +115 -0
- data/lib/nanook/public_key.rb +55 -0
- data/lib/nanook/rpc.rb +104 -44
- data/lib/nanook/util.rb +68 -19
- data/lib/nanook/version.rb +3 -1
- data/lib/nanook/wallet.rb +413 -120
- data/lib/nanook/wallet_account.rb +154 -91
- data/lib/nanook/work_peer.rb +14 -7
- metadata +29 -28
- data/lib/nanook/error.rb +0 -5
- data/lib/nanook/key.rb +0 -46
data/bin/console
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
|
-
require
|
4
|
-
require
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'nanook'
|
5
6
|
|
6
7
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
8
|
# with your gem easier. You can also use a different console, if you like.
|
8
9
|
|
9
|
-
require
|
10
|
+
require 'pry'
|
10
11
|
Pry.start
|
data/lib/nanook.rb
CHANGED
@@ -1,12 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'net/http'
|
2
4
|
require 'uri'
|
3
5
|
require 'forwardable'
|
4
6
|
|
5
|
-
Dir[File.dirname(__FILE__)
|
7
|
+
Dir["#{File.dirname(__FILE__)}/nanook/*.rb"].sort.each { |file| require file }
|
8
|
+
|
9
|
+
require_relative 'nanook/util'
|
6
10
|
|
7
11
|
# ==== Initializing
|
8
12
|
#
|
9
|
-
# Connect to the default RPC host at http://
|
13
|
+
# Connect to the default RPC host at http://[::1]:7076 and with a timeout of 60 seconds:
|
10
14
|
#
|
11
15
|
# nanook = Nanook.new
|
12
16
|
#
|
@@ -19,8 +23,9 @@ Dir[File.dirname(__FILE__) + '/nanook/*.rb'].each { |file| require file }
|
|
19
23
|
# Nanook.new(timeout: 600)
|
20
24
|
# Nanook.new("http://ip6-localhost.com:7076", timeout: 600)
|
21
25
|
class Nanook
|
26
|
+
include Util
|
22
27
|
|
23
|
-
UNITS = [
|
28
|
+
UNITS = %i[raw nano].freeze
|
24
29
|
DEFAULT_UNIT = :nano
|
25
30
|
|
26
31
|
# @return [Nanook::Rpc]
|
@@ -32,38 +37,39 @@ class Nanook
|
|
32
37
|
def self.default_unit
|
33
38
|
return DEFAULT_UNIT unless defined?(UNIT)
|
34
39
|
|
35
|
-
unless UNITS.include?(UNIT.to_sym)
|
36
|
-
raise Nanook::Error.new("UNIT #{UNIT} must be one of #{UNITS}")
|
37
|
-
end
|
38
|
-
|
39
40
|
UNIT.to_sym
|
40
41
|
end
|
41
42
|
|
42
43
|
# Returns a new instance of {Nanook}.
|
43
44
|
#
|
44
45
|
# ==== Examples:
|
45
|
-
# Connecting to http://
|
46
|
+
# Connecting to http://[::1]:7076 with the default timeout of 60s:
|
47
|
+
#
|
46
48
|
# Nanook.new
|
49
|
+
#
|
47
50
|
# Setting a custom timeout:
|
51
|
+
#
|
48
52
|
# Nanook.new(timeout: 10)
|
53
|
+
#
|
49
54
|
# Connecting to a custom RPC host and setting a timeout:
|
50
|
-
#
|
55
|
+
#
|
56
|
+
# Nanook.new("http://ip6-localhost:7076", timeout: 10)
|
51
57
|
#
|
52
58
|
# @param uri [String] default is {Nanook::Rpc::DEFAULT_URI}. The RPC host to connect to
|
53
59
|
# @param timeout [Integer] default is {Nanook::Rpc::DEFAULT_TIMEOUT}. Connection timeout in number of seconds
|
54
|
-
def initialize(uri=Nanook::Rpc::DEFAULT_URI, timeout:Nanook::Rpc::DEFAULT_TIMEOUT)
|
60
|
+
def initialize(uri = Nanook::Rpc::DEFAULT_URI, timeout: Nanook::Rpc::DEFAULT_TIMEOUT)
|
55
61
|
@rpc = Nanook::Rpc.new(uri, timeout: timeout)
|
56
62
|
end
|
57
63
|
|
58
64
|
# Returns a new instance of {Nanook::Account}.
|
59
65
|
#
|
60
66
|
# ==== Example:
|
61
|
-
# account = Nanook.new.account("
|
67
|
+
# account = Nanook.new.account("nano_3e3j5tkog48pnny9dmfzj1r16pg8t1e76dz5tmac6iq689wyjfpi00000000")
|
62
68
|
#
|
63
69
|
# @param account [String] the id of the account you want to work with
|
64
70
|
# @return [Nanook::Account]
|
65
71
|
def account(account)
|
66
|
-
|
72
|
+
as_account(account)
|
67
73
|
end
|
68
74
|
|
69
75
|
# Returns a new instance of {Nanook::Block}.
|
@@ -74,23 +80,35 @@ class Nanook
|
|
74
80
|
# @param block [String] the id/hash of the block you want to work with
|
75
81
|
# @return [Nanook::Block]
|
76
82
|
def block(block)
|
77
|
-
|
83
|
+
as_block(block)
|
78
84
|
end
|
79
85
|
|
80
86
|
# @return [String]
|
81
|
-
def
|
82
|
-
"#{self.class.name}(rpc: #{@rpc
|
87
|
+
def to_s
|
88
|
+
"#{self.class.name}(rpc: #{@rpc})"
|
83
89
|
end
|
90
|
+
alias inspect to_s
|
84
91
|
|
85
|
-
# Returns a new instance of {Nanook::
|
92
|
+
# Returns a new instance of {Nanook::PrivateKey}.
|
86
93
|
#
|
87
94
|
# ==== Example:
|
88
|
-
# key = Nanook.new.
|
95
|
+
# key = Nanook.new.private_key("3068BB1CA04525BB0E416C485FE6A67FD52540227D267CC8B6E8DA958A7FA039")
|
89
96
|
#
|
90
97
|
# @param key [String] a private key
|
91
|
-
# @return [Nanook::
|
92
|
-
def
|
93
|
-
|
98
|
+
# @return [Nanook::PrivateKey]
|
99
|
+
def private_key(key = nil)
|
100
|
+
as_private_key(key)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Returns a new instance of {Nanook::PublicKey}.
|
104
|
+
#
|
105
|
+
# ==== Example:
|
106
|
+
# key = Nanook.new.public_key("3068BB1CA04525BB0E416C485FE6A67FD52540227D267CC8B6E8DA958A7FA039")
|
107
|
+
#
|
108
|
+
# @param key [String] a public key
|
109
|
+
# @return [Nanook::PublicKey]
|
110
|
+
def public_key(key)
|
111
|
+
as_public_key(key)
|
94
112
|
end
|
95
113
|
|
96
114
|
# Returns a new instance of {Nanook::Node}.
|
@@ -110,7 +128,7 @@ class Nanook
|
|
110
128
|
#
|
111
129
|
# @param wallet [String] the id of the wallet you want to work with
|
112
130
|
# @return [Nanook::Wallet]
|
113
|
-
def wallet(wallet=nil)
|
131
|
+
def wallet(wallet = nil)
|
114
132
|
Nanook::Wallet.new(@rpc, wallet)
|
115
133
|
end
|
116
134
|
|
@@ -124,4 +142,42 @@ class Nanook
|
|
124
142
|
Nanook::WorkPeer.new(@rpc)
|
125
143
|
end
|
126
144
|
|
145
|
+
# Return summarized metrics received from other nodes of the whole network.
|
146
|
+
#
|
147
|
+
# ==== Example:
|
148
|
+
# Nanook.new.network_telemetry
|
149
|
+
#
|
150
|
+
# ==== Example response:
|
151
|
+
# {
|
152
|
+
# block_count: 5777903,
|
153
|
+
# cemented_count: 688819,
|
154
|
+
# unchecked_count: 443468,
|
155
|
+
# account_count: 620750,
|
156
|
+
# bandwidth_cap: 1572864,
|
157
|
+
# peer_count: 32,
|
158
|
+
# protocol_version: 18,
|
159
|
+
# uptime: 556896,
|
160
|
+
# genesis_block: Nanook::Block,
|
161
|
+
# major_version: 21,
|
162
|
+
# minor_version: 0,
|
163
|
+
# patch_version: 0,
|
164
|
+
# pre_release_version: 0,
|
165
|
+
# maker: 0,
|
166
|
+
# timestamp: Time,
|
167
|
+
# active_difficulty: "ffffffcdbf40aa45"
|
168
|
+
# }
|
169
|
+
#
|
170
|
+
# @return [Nanook::WorkPeer]
|
171
|
+
def network_telemetry
|
172
|
+
response = call_rpc(:telemetry, _coerce: Hash)
|
173
|
+
response[:genesis_block] = as_block(response[:genesis_block]) if response[:genesis_block]
|
174
|
+
response[:timestamp] = as_time(response[:timestamp]) if response[:timestamp]
|
175
|
+
response
|
176
|
+
end
|
177
|
+
|
178
|
+
private
|
179
|
+
|
180
|
+
def call_rpc(action, params = {})
|
181
|
+
@rpc.call(action, params)
|
182
|
+
end
|
127
183
|
end
|
data/lib/nanook/account.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'util'
|
2
4
|
|
5
|
+
class Nanook
|
3
6
|
# The <tt>Nanook::Account</tt> class contains methods to discover
|
4
7
|
# publicly-available information about accounts on the nano network.
|
5
8
|
#
|
@@ -8,17 +11,45 @@ class Nanook
|
|
8
11
|
# Initialize this class through the convenient {Nanook#account} method:
|
9
12
|
#
|
10
13
|
# nanook = Nanook.new
|
11
|
-
# account = nanook.account("
|
14
|
+
# account = nanook.account("nano_...")
|
12
15
|
#
|
13
16
|
# Or compose the longhand way like this:
|
14
17
|
#
|
15
18
|
# rpc_conn = Nanook::Rpc.new
|
16
|
-
# account = Nanook::Account.new(rpc_conn, "
|
19
|
+
# account = Nanook::Account.new(rpc_conn, "nano_...")
|
17
20
|
class Account
|
21
|
+
include Nanook::Util
|
18
22
|
|
19
23
|
def initialize(rpc, account)
|
20
24
|
@rpc = rpc
|
21
|
-
@account = account
|
25
|
+
@account = account.to_s
|
26
|
+
end
|
27
|
+
|
28
|
+
# The id of the account.
|
29
|
+
#
|
30
|
+
# ==== Example:
|
31
|
+
#
|
32
|
+
# account.id # => "nano_16u..."
|
33
|
+
#
|
34
|
+
# @return [String] the id of the account
|
35
|
+
def id
|
36
|
+
@account
|
37
|
+
end
|
38
|
+
|
39
|
+
# @param other [Nanook::Account] account to compare
|
40
|
+
# @return [Boolean] true if accounts are equal
|
41
|
+
def ==(other)
|
42
|
+
other.class == self.class &&
|
43
|
+
other.id == id
|
44
|
+
end
|
45
|
+
alias eql? ==
|
46
|
+
|
47
|
+
# The hash value is used along with #eql? by the Hash class to determine if two objects
|
48
|
+
# reference the same hash key.
|
49
|
+
#
|
50
|
+
# @return [Integer]
|
51
|
+
def hash
|
52
|
+
id.hash
|
22
53
|
end
|
23
54
|
|
24
55
|
# Information about this accounts that have set this account as their representative.
|
@@ -30,28 +61,36 @@ class Nanook
|
|
30
61
|
# Example response:
|
31
62
|
#
|
32
63
|
# {
|
33
|
-
#
|
34
|
-
#
|
64
|
+
# Nanook::Account=>50.0,
|
65
|
+
# Nanook::Account=>961.64
|
35
66
|
# }
|
36
67
|
#
|
37
68
|
# @param unit (see #balance)
|
38
|
-
# @return [Hash{
|
69
|
+
# @return [Hash{Nanook::Account=>Integer|Float}] {Nanook::Account} accounts which delegate to this account, and their account balance
|
70
|
+
# @raise [Nanook::NanoUnitError] if `unit` is invalid
|
39
71
|
def delegators(unit: Nanook.default_unit)
|
40
|
-
|
41
|
-
raise ArgumentError.new("Unsupported unit: #{unit}")
|
42
|
-
end
|
43
|
-
|
44
|
-
response = rpc(:delegators)[:delegators]
|
72
|
+
validate_unit!(unit)
|
45
73
|
|
46
|
-
|
74
|
+
response = rpc(:delegators, _access: :delegators, _coerce: Hash)
|
47
75
|
|
48
76
|
r = response.map do |account_id, balance|
|
49
|
-
balance =
|
77
|
+
balance = raw_to_NANO(balance) if unit == :nano
|
50
78
|
|
51
|
-
[account_id, balance]
|
79
|
+
[as_account(account_id), balance]
|
52
80
|
end
|
53
81
|
|
54
|
-
Hash[r]
|
82
|
+
Hash[r]
|
83
|
+
end
|
84
|
+
|
85
|
+
# Number of accounts that have set this account as their representative.
|
86
|
+
#
|
87
|
+
# === Example:
|
88
|
+
#
|
89
|
+
# account.delegators_count # => 2
|
90
|
+
#
|
91
|
+
# @return [Integer]
|
92
|
+
def delegators_count
|
93
|
+
rpc(:delegators_count, _access: :count)
|
55
94
|
end
|
56
95
|
|
57
96
|
# Returns true if the account has an <i>open</i> block.
|
@@ -73,13 +112,21 @@ class Nanook
|
|
73
112
|
#
|
74
113
|
# @return [Boolean] Indicates if this account has an open block
|
75
114
|
def exists?
|
76
|
-
|
115
|
+
begin
|
116
|
+
response = rpc(:account_info)
|
117
|
+
rescue Nanook::Error
|
118
|
+
return false
|
119
|
+
end
|
120
|
+
|
77
121
|
!response.empty? && !response[:open_block].nil?
|
78
122
|
end
|
79
|
-
|
123
|
+
alias open? exists?
|
80
124
|
|
81
125
|
# An account's history of send and receive payments.
|
82
126
|
#
|
127
|
+
# This call may return results that include unconfirmed blocks, so it should not be used in
|
128
|
+
# any processes or integrations requiring only details from blocks confirmed by the network.
|
129
|
+
#
|
83
130
|
# ==== Example:
|
84
131
|
#
|
85
132
|
# account.history
|
@@ -89,73 +136,90 @@ class Nanook
|
|
89
136
|
# [
|
90
137
|
# {
|
91
138
|
# type: "send",
|
92
|
-
# account:
|
139
|
+
# account: Nanook::Account,
|
93
140
|
# amount: 2,
|
94
|
-
#
|
141
|
+
# block: Nanook::Block
|
95
142
|
# }
|
96
143
|
# ]
|
97
144
|
#
|
98
|
-
# @param limit [Integer] maximum number of history items to return
|
145
|
+
# @param limit [Integer] maximum number of history items to return. Defaults to 1000
|
146
|
+
# @param sort [Symbol] default +:asc+. When set to +:desc+ the history will be returned oldest to newest.
|
99
147
|
# @param unit (see #balance)
|
100
|
-
# @return [Array<Hash{Symbol=>String}>] the history of send and receive payments for this account
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
end
|
148
|
+
# @return [Array<Hash{Symbol=>String|Float|Integer|Nanook::Account|NanookBlock}>] the history of send and receive payments for this account
|
149
|
+
# @raise [Nanook::NanoUnitError] if `unit` is invalid
|
150
|
+
def history(limit: 1000, unit: Nanook.default_unit, sort: :asc)
|
151
|
+
validate_unit!(unit)
|
105
152
|
|
106
|
-
response = rpc(:account_history, count: limit)
|
153
|
+
response = rpc(:account_history, count: limit, reverse: (sort == :desc), _access: :history, _coerce: Array)
|
107
154
|
|
108
|
-
|
109
|
-
|
110
|
-
|
155
|
+
response.map do |history|
|
156
|
+
history[:amount] = raw_to_NANO(history[:amount]) if unit == :nano
|
157
|
+
history[:account] = as_account(history[:account])
|
158
|
+
history[:block] = as_block(history.delete(:hash)) # Rename the key from `hash` to `block`
|
111
159
|
|
112
|
-
response.map! do |history|
|
113
|
-
history[:amount] = Nanook::Util.raw_to_NANO(history[:amount])
|
114
160
|
history
|
115
161
|
end
|
116
162
|
end
|
117
163
|
|
118
|
-
#
|
119
|
-
#
|
164
|
+
# Return blocks for the account.
|
165
|
+
#
|
166
|
+
# @param limit [Integer] maximum number of history items to return. Defaults to 1000
|
167
|
+
# @param sort [Symbol] default +:asc+. When set to +:desc+ the blocks will be returned oldest to newest.
|
168
|
+
# @return [Array<Nanook::Block>]
|
169
|
+
def blocks(limit: 1000, sort: :asc)
|
170
|
+
history(limit: limit, sort: sort).map { |i| i[:block] }
|
171
|
+
end
|
172
|
+
|
173
|
+
# Returns the open block for the account if it exists on the node.
|
174
|
+
#
|
175
|
+
# @return [Nanook::Block]
|
176
|
+
def open_block
|
177
|
+
blocks(limit: 1, sort: :desc).first
|
178
|
+
end
|
179
|
+
|
180
|
+
# The last modified time of the account in UTC. For many accounts on the node
|
181
|
+
# this will be the timestamp of when the node bootstrapped.
|
120
182
|
#
|
121
183
|
# ==== Example:
|
122
184
|
#
|
123
185
|
# account.last_modified_at # => Time
|
124
186
|
#
|
125
|
-
# @return [Time] last modified time of the account in
|
126
|
-
# your nano node (usually UTC).
|
187
|
+
# @return [Time] last modified time of the account in UTC. Can be nil
|
127
188
|
def last_modified_at
|
128
|
-
|
129
|
-
Time.at(response[:modified_timestamp])
|
189
|
+
as_time(rpc(:account_info, _access: :modified_timestamp))
|
130
190
|
end
|
131
191
|
|
132
192
|
# The public key of the account.
|
133
193
|
#
|
134
194
|
# ==== Example:
|
135
195
|
#
|
136
|
-
# account.public_key # =>
|
196
|
+
# account.public_key # => Nanook::PublicKey
|
137
197
|
#
|
138
|
-
# @return [
|
198
|
+
# @return [Nanook::PublicKey] public key of the account
|
139
199
|
def public_key
|
140
|
-
rpc(:account_key
|
200
|
+
as_public_key(rpc(:account_key, _access: :key))
|
141
201
|
end
|
142
202
|
|
143
|
-
# The representative
|
144
|
-
# Representatives are accounts which cast votes in the case of a
|
145
|
-
# fork in the network.
|
203
|
+
# The representative for the account.
|
146
204
|
#
|
147
205
|
# ==== Example:
|
148
206
|
#
|
149
|
-
# account.representative # =>
|
207
|
+
# account.representative # => Nanook::Account
|
150
208
|
#
|
151
|
-
# @return [
|
209
|
+
# @return [Nanook::Account] Representative of the account. Can be nil.
|
152
210
|
def representative
|
153
|
-
rpc(:account_representative
|
211
|
+
representative = rpc(:account_representative, _access: :representative)
|
212
|
+
as_account(representative) if representative
|
154
213
|
end
|
155
214
|
|
156
215
|
# The account's balance, including pending (unreceived payments).
|
157
216
|
# To receive a pending amount see {WalletAccount#receive}.
|
158
217
|
#
|
218
|
+
# This call returns information that may be based on unconfirmed blocks.
|
219
|
+
# These details should not be relied on for any process or integration that
|
220
|
+
# requires confirmed blocks. The pending balance is calculated from
|
221
|
+
# potentially unconfirmed blocks.
|
222
|
+
#
|
159
223
|
# ==== Examples:
|
160
224
|
#
|
161
225
|
# account.balance
|
@@ -183,37 +247,23 @@ class Nanook
|
|
183
247
|
# Represents the unit that the balances will be returned in.
|
184
248
|
# Note: this method interprets
|
185
249
|
# +:nano+ as NANO, which is technically Mnano.
|
186
|
-
# See {https://nano.org/
|
187
|
-
#
|
188
|
-
# @raise ArgumentError if an invalid +unit+ was given.
|
250
|
+
# See {https://docs.nano.org/protocol-design/distribution-and-units/#unit-dividers What are Nano's Units}
|
251
|
+
# @raise [Nanook::NanoUnitError] if `unit` is invalid
|
189
252
|
# @return [Hash{Symbol=>Integer|Float}]
|
190
253
|
def balance(unit: Nanook.default_unit)
|
191
|
-
|
192
|
-
raise ArgumentError.new("Unsupported unit: #{unit}")
|
193
|
-
end
|
254
|
+
validate_unit!(unit)
|
194
255
|
|
195
256
|
rpc(:account_balance).tap do |r|
|
196
257
|
if unit == :nano
|
197
|
-
r[:balance] =
|
198
|
-
r[:pending] =
|
258
|
+
r[:balance] = raw_to_NANO(r[:balance])
|
259
|
+
r[:pending] = raw_to_NANO(r[:pending])
|
199
260
|
end
|
200
261
|
end
|
201
262
|
end
|
202
263
|
|
203
264
|
# @return [Integer] number of blocks for this account
|
204
265
|
def block_count
|
205
|
-
rpc(:account_block_count
|
206
|
-
end
|
207
|
-
|
208
|
-
# The id of the account.
|
209
|
-
#
|
210
|
-
# ==== Example:
|
211
|
-
#
|
212
|
-
# account.id # => "xrb_16u..."
|
213
|
-
#
|
214
|
-
# @return [String] the id of the account
|
215
|
-
def id
|
216
|
-
@account
|
266
|
+
rpc(:account_block_count, _access: :block_count)
|
217
267
|
end
|
218
268
|
|
219
269
|
# Information about the account.
|
@@ -225,7 +275,7 @@ class Nanook
|
|
225
275
|
# Example response:
|
226
276
|
#
|
227
277
|
# {
|
228
|
-
# id: "
|
278
|
+
# id: "nano_16u1uufyoig8777y6r8iqjtrw8sg8maqrm36zzcm95jmbd9i9aj5i8abr8u5",
|
229
279
|
# balance: 11.439597000000001,
|
230
280
|
# block_count: 4,
|
231
281
|
# frontier: "2C3C570EA8898443C0FD04A1C385A3E3A8C985AD792635FCDCEBB30ADF6A0570",
|
@@ -241,69 +291,62 @@ class Nanook
|
|
241
291
|
# Example response:
|
242
292
|
#
|
243
293
|
# {
|
244
|
-
# id: "
|
294
|
+
# id: "nano_16u1uufyoig8777y6r8iqjtrw8sg8maqrm36zzcm95jmbd9i9aj5i8abr8u5",
|
245
295
|
# balance: 11.439597000000001,
|
246
296
|
# block_count: 4,
|
247
|
-
# frontier:
|
248
|
-
#
|
249
|
-
# open_block:
|
250
|
-
# pending: 0,
|
251
|
-
#
|
252
|
-
#
|
253
|
-
#
|
254
|
-
# weight: 0
|
297
|
+
# frontier: Nanook::Block,
|
298
|
+
# last_modified_at: Time,
|
299
|
+
# open_block: Nanook::Block,
|
300
|
+
# pending: 1.0,
|
301
|
+
# representative: Nanook::Account,
|
302
|
+
# representative_block: Nanook::Block,
|
303
|
+
# weight: 0.1
|
255
304
|
# }
|
256
305
|
#
|
257
|
-
# @param detailed [Boolean] (default is false). When +true+, four
|
258
|
-
# additional calls are made to the RPC to return more information
|
259
306
|
# @param unit (see #balance)
|
260
|
-
# @return [Hash{Symbol=>String|Integer|Float}] information about the account containing:
|
307
|
+
# @return [Hash{Symbol=>String|Integer|Float|Nanook::Account|Nanook::Block|Time}] information about the account containing:
|
261
308
|
# [+id+] The account id
|
262
|
-
# [+frontier+] The latest
|
263
|
-
# [+
|
264
|
-
# [+
|
265
|
-
# [+
|
266
|
-
# [+
|
309
|
+
# [+frontier+] The latest {Nanook::Block}
|
310
|
+
# [+confirmation_height+] Confirmation height
|
311
|
+
# [+confirmation_height_frontier+] The {Nanook::Block} of the confirmation height
|
312
|
+
# [+pending+] Pending balance in either NANO or raw (depending on the <tt>unit:</tt> argument)
|
313
|
+
# [+open_block+] The first {Nanook::Block} in every account's blockchain. When this block was published the account was officially open
|
314
|
+
# [+representative_block+] The {Nanook::Block} that named the representative for the account
|
315
|
+
# [+balance+] Balance in either NANO or raw (depending on the <tt>unit:</tt> argument)
|
316
|
+
# [+last_modified_at+] Time of when the account was last modified in UTC
|
317
|
+
# [+representative+] Representative {Nanook::Account}
|
267
318
|
# [+block_count+] Number of blocks in the account's blockchain
|
268
|
-
#
|
269
|
-
# When <tt>detailed: true</tt> is passed as an argument, this method
|
270
|
-
# makes four additional calls to the RPC to return more information
|
271
|
-
# about an account:
|
272
|
-
#
|
273
319
|
# [+weight+] See {#weight}
|
274
|
-
#
|
275
|
-
#
|
276
|
-
|
277
|
-
|
278
|
-
unless Nanook::UNITS.include?(unit)
|
279
|
-
raise ArgumentError.new("Unsupported unit: #{unit}")
|
280
|
-
end
|
320
|
+
#
|
321
|
+
# @raise [Nanook::NanoUnitError] if `unit` is invalid
|
322
|
+
def info(unit: Nanook.default_unit)
|
323
|
+
validate_unit!(unit)
|
281
324
|
|
282
|
-
response = rpc(:account_info)
|
325
|
+
response = rpc(:account_info, representative: true, weight: true, pending: true)
|
283
326
|
response.merge!(id: @account)
|
327
|
+
response[:frontier] = as_block(response[:frontier]) if response[:frontier]
|
328
|
+
response[:open_block] = as_block(response[:open_block]) if response[:open_block]
|
329
|
+
response[:representative_block] = as_block(response[:representative_block]) if response[:representative_block]
|
330
|
+
response[:representative] = as_account(response[:representative]) if response[:representative]
|
331
|
+
response[:confirmation_height_frontier] = as_block(response[:confirmation_height_frontier]) if response[:confirmation_height_frontier]
|
332
|
+
response[:last_modified_at] = as_time(response.delete(:modified_timestamp))
|
284
333
|
|
285
334
|
if unit == :nano
|
286
|
-
response
|
335
|
+
response.merge!(
|
336
|
+
balance: raw_to_NANO(response[:balance]),
|
337
|
+
pending: raw_to_NANO(response[:pending]),
|
338
|
+
weight: raw_to_NANO(response[:weight])
|
339
|
+
)
|
287
340
|
end
|
288
341
|
|
289
|
-
|
290
|
-
return response unless detailed
|
291
|
-
|
292
|
-
# Otherwise make additional calls
|
293
|
-
response.merge!({
|
294
|
-
weight: weight,
|
295
|
-
pending: balance(unit: unit)[:pending],
|
296
|
-
representative: representative,
|
297
|
-
public_key: public_key
|
298
|
-
})
|
299
|
-
|
300
|
-
# Sort this new hash by keys
|
301
|
-
Hash[response.sort].to_symbolized_hash
|
342
|
+
response
|
302
343
|
end
|
303
344
|
|
304
|
-
|
305
|
-
|
345
|
+
# @return [String]
|
346
|
+
def to_s
|
347
|
+
"#{self.class.name}(id: \"#{short_id}\")"
|
306
348
|
end
|
349
|
+
alias inspect to_s
|
307
350
|
|
308
351
|
# Information about the given account as well as other
|
309
352
|
# accounts up the ledger. The number of accounts returned is determined
|
@@ -316,43 +359,56 @@ class Nanook
|
|
316
359
|
# Example response:
|
317
360
|
#
|
318
361
|
# {
|
319
|
-
#
|
320
|
-
# :frontier=>
|
321
|
-
# :open_block=>
|
322
|
-
# :representative_block=>
|
323
|
-
# :
|
324
|
-
# :
|
325
|
-
# :
|
362
|
+
# Nanook::Account => {
|
363
|
+
# :frontier => Nanook::Block,
|
364
|
+
# :open_block => Nanook::Block,
|
365
|
+
# :representative_block => Nanook::Block,
|
366
|
+
# :representative => Nanook::Account,
|
367
|
+
# :balance => 1143.7,
|
368
|
+
# :last_modified_at => Time,
|
369
|
+
# :block_count => 4
|
370
|
+
# :weight => 5
|
371
|
+
# :pending => 2.0
|
326
372
|
# },
|
327
|
-
#
|
373
|
+
# Nanook::Account => { ... }
|
328
374
|
# }
|
329
375
|
#
|
330
|
-
# @param [Integer]
|
331
|
-
# @param [Time]
|
376
|
+
# @param limit [Integer] number of accounts to return in the ledger (default is 1000)
|
377
|
+
# @param modified_since [Time] optional. Return only accounts modified in the local database after this time (default is from the unix epoch)
|
332
378
|
# @param unit (see #balance)
|
333
|
-
# @
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
params = {
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
379
|
+
# @param sort [Symbol] default +:asc+. When set to +:desc+ the ledger will be returned oldest to newest.
|
380
|
+
# @return [Hash{Nanook::Account=>String|Integer}]
|
381
|
+
# @raise [Nanook::NanoUnitError] if `unit` is invalid
|
382
|
+
def ledger(limit: 1000, modified_since: 0, unit: Nanook.default_unit, sort: :asc)
|
383
|
+
validate_unit!(unit)
|
384
|
+
|
385
|
+
params = {
|
386
|
+
count: limit,
|
387
|
+
sorting: (sort == :desc),
|
388
|
+
modified_since: modified_since.to_i,
|
389
|
+
_access: :accounts,
|
390
|
+
_coerce: Hash
|
391
|
+
}
|
392
|
+
|
393
|
+
response = rpc(:ledger, params)
|
394
|
+
|
395
|
+
r = response.map do |account_id, ledger|
|
396
|
+
if unit == :nano
|
397
|
+
ledger[:balance] = raw_to_NANO(ledger[:balance])
|
398
|
+
ledger[:pending] = raw_to_NANO(ledger[:pending])
|
399
|
+
ledger[:weight] = raw_to_NANO(ledger[:weight])
|
400
|
+
end
|
348
401
|
|
349
|
-
|
350
|
-
|
402
|
+
ledger[:last_modified_at] = as_time(ledger.delete(:modified_timestamp))
|
403
|
+
ledger[:representative] = as_account(ledger[:representative]) if ledger[:representative]
|
404
|
+
ledger[:representative_block] = as_block(ledger[:representative_block]) if ledger[:representative_block]
|
405
|
+
ledger[:open_block] = as_block(ledger[:open_block]) if ledger[:open_block]
|
406
|
+
ledger[:frontier] = as_block(ledger[:frontier]) if ledger[:frontier]
|
351
407
|
|
352
|
-
[account_id,
|
408
|
+
[as_account(account_id), ledger]
|
353
409
|
end
|
354
410
|
|
355
|
-
Hash[r]
|
411
|
+
Hash[r]
|
356
412
|
end
|
357
413
|
|
358
414
|
# Information about pending blocks (payments) that are
|
@@ -368,7 +424,7 @@ class Nanook
|
|
368
424
|
#
|
369
425
|
# ==== Examples:
|
370
426
|
#
|
371
|
-
# account.pending # => [
|
427
|
+
# account.pending # => [Nanook::Block, ..."]
|
372
428
|
#
|
373
429
|
# Asking for more detail to be returned:
|
374
430
|
#
|
@@ -378,9 +434,9 @@ class Nanook
|
|
378
434
|
#
|
379
435
|
# [
|
380
436
|
# {
|
381
|
-
# block:
|
437
|
+
# block: Nanook::Block,
|
382
438
|
# amount: 6,
|
383
|
-
# source:
|
439
|
+
# source: Nanook::Account
|
384
440
|
# },
|
385
441
|
# { ... }
|
386
442
|
# ]
|
@@ -389,28 +445,34 @@ class Nanook
|
|
389
445
|
# @param detailed [Boolean]return a more complex Hash of pending block information (default is +false+)
|
390
446
|
# @param unit (see #balance)
|
391
447
|
#
|
392
|
-
# @return [Array<
|
393
|
-
# @return [Array<Hash{Symbol=>
|
448
|
+
# @return [Array<Nanook::Block>]
|
449
|
+
# @return [Array<Hash{Symbol=>Nanook::Block|Nanook::Account|Integer}>]
|
450
|
+
# @raise [Nanook::NanoUnitError] if `unit` is invalid
|
394
451
|
def pending(limit: 1000, detailed: false, unit: Nanook.default_unit)
|
395
|
-
|
396
|
-
raise ArgumentError.new("Unsupported unit: #{unit}")
|
397
|
-
end
|
452
|
+
validate_unit!(unit)
|
398
453
|
|
399
|
-
params = {
|
454
|
+
params = {
|
455
|
+
count: limit,
|
456
|
+
_access: :blocks,
|
457
|
+
_coerce: (detailed ? Hash : Array)
|
458
|
+
}
|
400
459
|
params[:source] = true if detailed
|
401
460
|
|
402
|
-
response = rpc(:pending, params)
|
403
|
-
response = Nanook::Util.coerce_empty_string_to_type(response, (detailed ? Hash : Array))
|
461
|
+
response = rpc(:pending, params)
|
404
462
|
|
405
|
-
|
463
|
+
unless detailed
|
464
|
+
return response.map do |block|
|
465
|
+
as_block(block)
|
466
|
+
end
|
467
|
+
end
|
406
468
|
|
407
469
|
response.map do |key, val|
|
408
|
-
p = val.merge(
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
end
|
470
|
+
p = val.merge(
|
471
|
+
block: as_block(key.to_s),
|
472
|
+
source: as_account(val[:source])
|
473
|
+
)
|
413
474
|
|
475
|
+
p[:amount] = raw_to_NANO(p[:amount]) if unit == :nano
|
414
476
|
p
|
415
477
|
end
|
416
478
|
end
|
@@ -419,23 +481,29 @@ class Nanook
|
|
419
481
|
#
|
420
482
|
# Weight is determined by the account's balance, and represents
|
421
483
|
# the voting weight that account has on the network. Only accounts
|
422
|
-
# with greater than
|
484
|
+
# with greater than 0.1% of the online voting weight and are on a node
|
485
|
+
# configured to vote can vote.
|
423
486
|
#
|
424
487
|
# ==== Example:
|
425
488
|
#
|
426
489
|
# account.weight # => 0
|
427
490
|
#
|
428
|
-
# @return [Integer] the account's weight
|
429
|
-
|
430
|
-
|
491
|
+
# @return [Integer|Float] the account's weight
|
492
|
+
# @raise [Nanook::NanoUnitError] if `unit` is invalid
|
493
|
+
def weight(unit: Nanook.default_unit)
|
494
|
+
validate_unit!(unit)
|
495
|
+
|
496
|
+
weight = rpc(:account_weight, _access: :weight)
|
497
|
+
|
498
|
+
return weight unless unit == :nano
|
499
|
+
|
500
|
+
raw_to_NANO(weight)
|
431
501
|
end
|
432
502
|
|
433
503
|
private
|
434
504
|
|
435
|
-
def rpc(action, params={})
|
436
|
-
|
437
|
-
@rpc.call(action, p.merge(params))
|
505
|
+
def rpc(action, params = {})
|
506
|
+
@rpc.call(action, { account: @account }.merge(params))
|
438
507
|
end
|
439
|
-
|
440
508
|
end
|
441
509
|
end
|