nanook 2.2.0 → 3.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.
- 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
|