beowulf-ruby-testnet 0.0.1
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 +7 -0
- data/.gitignore +58 -0
- data/Gemfile +3 -0
- data/LICENSE +21 -0
- data/README.md +204 -0
- data/Rakefile +52 -0
- data/beowulf.gemspec +43 -0
- data/lib/beowulf.rb +35 -0
- data/lib/beowulf/account_history_api.rb +15 -0
- data/lib/beowulf/api.rb +845 -0
- data/lib/beowulf/base_error.rb +21 -0
- data/lib/beowulf/block_api.rb +14 -0
- data/lib/beowulf/broadcast_operations.json +74 -0
- data/lib/beowulf/chain_config.rb +15 -0
- data/lib/beowulf/condenser_api.rb +48 -0
- data/lib/beowulf/database_api.rb +5 -0
- data/lib/beowulf/error_parser.rb +228 -0
- data/lib/beowulf/logger.rb +20 -0
- data/lib/beowulf/methods.json +129 -0
- data/lib/beowulf/network_broadcast_api.rb +7 -0
- data/lib/beowulf/operation.rb +99 -0
- data/lib/beowulf/operation_ids.rb +33 -0
- data/lib/beowulf/operation_types.rb +31 -0
- data/lib/beowulf/transaction.rb +320 -0
- data/lib/beowulf/type/amount.rb +23 -0
- data/lib/beowulf/type/array.rb +17 -0
- data/lib/beowulf/type/authority.rb +48 -0
- data/lib/beowulf/type/authority_update.rb +50 -0
- data/lib/beowulf/type/future.rb +16 -0
- data/lib/beowulf/type/hash.rb +17 -0
- data/lib/beowulf/type/permission.rb +17 -0
- data/lib/beowulf/type/point_in_time.rb +17 -0
- data/lib/beowulf/type/public_key.rb +18 -0
- data/lib/beowulf/type/serializer.rb +12 -0
- data/lib/beowulf/type/u_int16.rb +17 -0
- data/lib/beowulf/type/u_int32.rb +17 -0
- data/lib/beowulf/utils.rb +221 -0
- data/lib/beowulf/version.rb +4 -0
- data/lib/beowulf/wallet.rb +212 -0
- metadata +463 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
module Beowulf
|
2
|
+
module Type
|
3
|
+
class Amount < Serializer
|
4
|
+
attr_reader :amount, :precision, :asset
|
5
|
+
|
6
|
+
def initialize(value)
|
7
|
+
super(:amount, value)
|
8
|
+
@amount, @asset = value.strip.split(' ')
|
9
|
+
@precision = 5
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_bytes
|
13
|
+
asset = @asset.ljust(9, "\x00")
|
14
|
+
amount = (@amount.to_f * 10 ** @precision).round
|
15
|
+
[amount].pack('q') + [@precision].pack('L') + asset
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
"#{@amount} #{@asset}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Beowulf
|
4
|
+
module Type
|
5
|
+
class Authority
|
6
|
+
include Utils
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
# puts 'Authority.initialize.options', options.to_json
|
10
|
+
@weight_threshold = options[:weight_threshold] || 1
|
11
|
+
@account_auths = options[:account_auths] || []
|
12
|
+
@key_auths = options[:key_auths] || []
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_bytes
|
16
|
+
wt = @weight_threshold.to_i + 0
|
17
|
+
bytes = [wt].pack("I")
|
18
|
+
#uint8_t
|
19
|
+
bytes << pakC(@account_auths.length)
|
20
|
+
if @account_auths.length > 0
|
21
|
+
@account_auths.each do |account|
|
22
|
+
bytes << pakStr(account[0])
|
23
|
+
bytes << pakS(account[1])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
#uint8_t
|
27
|
+
bytes << pakC(@key_auths.length)
|
28
|
+
if @key_auths.length > 0
|
29
|
+
@key_auths.each do |key|
|
30
|
+
bytes << pakPubKey(key[0])
|
31
|
+
bytes << pakS(key[1])
|
32
|
+
end
|
33
|
+
end
|
34
|
+
bytes
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_json(options)
|
38
|
+
JSON.dump ({
|
39
|
+
:weight_threshold => @weight_threshold,
|
40
|
+
:account_auths => @account_auths,
|
41
|
+
:key_auths => @key_auths
|
42
|
+
})
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Beowulf
|
4
|
+
module Type
|
5
|
+
class AuthorityUpdate
|
6
|
+
include Utils
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
# puts 'AuthorityUpdate.initialize.options', options.to_json
|
10
|
+
@weight_threshold = options[:weight_threshold] || 1
|
11
|
+
@account_auths = options[:account_auths] || []
|
12
|
+
@key_auths = options[:key_auths] || []
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_bytes
|
16
|
+
bytes = unhexlify("01")
|
17
|
+
wt = @weight_threshold.to_i + 0
|
18
|
+
bytes << [wt].pack("I")
|
19
|
+
#uint8_t
|
20
|
+
bytes << pakC(@account_auths.length)
|
21
|
+
if @account_auths.length > 0
|
22
|
+
@account_auths.each do |account|
|
23
|
+
bytes << pakStr(account[0])
|
24
|
+
bytes << pakS(account[1])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
#uint8_t
|
28
|
+
bytes << pakC(@key_auths.length)
|
29
|
+
if @key_auths.length > 0
|
30
|
+
@key_auths.each do |key|
|
31
|
+
bytes << pakPubKey(key[0])
|
32
|
+
bytes << pakS(key[1])
|
33
|
+
end
|
34
|
+
end
|
35
|
+
bytes
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_json(options)
|
39
|
+
JSON.dump ({
|
40
|
+
:weight_threshold => @weight_threshold,
|
41
|
+
:account_auths => @account_auths,
|
42
|
+
:key_auths => @key_auths
|
43
|
+
})
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Beowulf
|
2
|
+
module Type
|
3
|
+
class PublicKey < Serializer
|
4
|
+
def initialize(value)
|
5
|
+
super(:public_key, value)
|
6
|
+
raise NotImplementedError, 'stub'
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_bytes
|
10
|
+
pakPubKey(@value)
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
@value
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,221 @@
|
|
1
|
+
require 'base58'
|
2
|
+
|
3
|
+
module Beowulf
|
4
|
+
module Utils
|
5
|
+
def extract_signatures(options)
|
6
|
+
return [] unless defined? options[:params].map
|
7
|
+
|
8
|
+
params = options[:params]
|
9
|
+
|
10
|
+
signatures = params.map do |param|
|
11
|
+
next unless defined? param.map
|
12
|
+
|
13
|
+
param.map do |tx|
|
14
|
+
tx[:signatures] rescue nil
|
15
|
+
end
|
16
|
+
end.flatten.compact
|
17
|
+
|
18
|
+
expirations = params.map do |param|
|
19
|
+
next unless defined? param.map
|
20
|
+
|
21
|
+
param.map do |tx|
|
22
|
+
Time.parse(tx[:expiration] + 'Z') rescue nil
|
23
|
+
end
|
24
|
+
end.flatten.compact
|
25
|
+
|
26
|
+
[signatures, expirations.min]
|
27
|
+
end
|
28
|
+
|
29
|
+
def send_log(level, obj, prefix = nil)
|
30
|
+
log_message = case obj
|
31
|
+
when String
|
32
|
+
log_message = if !!prefix
|
33
|
+
"#{prefix} :: #{obj}"
|
34
|
+
else
|
35
|
+
obj
|
36
|
+
end
|
37
|
+
|
38
|
+
if !!@logger
|
39
|
+
@logger.send level, log_message
|
40
|
+
else
|
41
|
+
puts "#{level}: #{log_message}"
|
42
|
+
end
|
43
|
+
else
|
44
|
+
if defined? @logger.ap
|
45
|
+
if !!prefix
|
46
|
+
@logger.ap log_level: level, prefix => obj
|
47
|
+
else
|
48
|
+
@logger.ap obj, level
|
49
|
+
end
|
50
|
+
else
|
51
|
+
if !!prefix
|
52
|
+
@logger.send level, ({prefix => obj}).inspect
|
53
|
+
else
|
54
|
+
@logger.send level, obj.inspect
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
nil
|
60
|
+
end
|
61
|
+
|
62
|
+
def error(obj, prefix = nil)
|
63
|
+
send_log(:error, obj, prefix)
|
64
|
+
end
|
65
|
+
|
66
|
+
def warning(obj, prefix = nil, log_debug_node = false)
|
67
|
+
debug("Current node: #{@url}", prefix) if !!log_debug_node && @url
|
68
|
+
|
69
|
+
send_log(:warn, obj, prefix)
|
70
|
+
end
|
71
|
+
|
72
|
+
def debug(obj, prefix = nil)
|
73
|
+
if %w(DEBUG TRACE).include? ENV['LOG']
|
74
|
+
send_log(:debug, obj, prefix)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def hexlify(s)
|
79
|
+
a = []
|
80
|
+
if s.respond_to? :each_byte
|
81
|
+
s.each_byte { |b| a << sprintf('%02X', b) }
|
82
|
+
else
|
83
|
+
s.each { |b| a << sprintf('%02X', b) }
|
84
|
+
end
|
85
|
+
a.join.downcase
|
86
|
+
end
|
87
|
+
|
88
|
+
def unhexlify(s)
|
89
|
+
s.split.pack('H*')
|
90
|
+
end
|
91
|
+
|
92
|
+
def varint(n)
|
93
|
+
data = []
|
94
|
+
while n >= 0x80
|
95
|
+
data += [(n & 0x7f) | 0x80]
|
96
|
+
|
97
|
+
n >>= 7
|
98
|
+
end
|
99
|
+
|
100
|
+
data += [n]
|
101
|
+
|
102
|
+
data.pack('C*')
|
103
|
+
end
|
104
|
+
|
105
|
+
def pakStr(s)
|
106
|
+
s = s.dup.force_encoding('BINARY')
|
107
|
+
bytes = []
|
108
|
+
bytes << varint(s.size)
|
109
|
+
bytes << s
|
110
|
+
|
111
|
+
bytes.join
|
112
|
+
end
|
113
|
+
|
114
|
+
def pakArr(a)
|
115
|
+
varint(a.size) + a.map do |v|
|
116
|
+
case v
|
117
|
+
when Symbol then pakStr(v.to_s)
|
118
|
+
when String then pakStr(v)
|
119
|
+
when Integer then paks(v)
|
120
|
+
when TrueClass then pakC(1)
|
121
|
+
when FalseClass then pakC(0)
|
122
|
+
when ::Array then pakArr(v)
|
123
|
+
when ::Hash then pakHash(v)
|
124
|
+
when NilClass then next
|
125
|
+
else
|
126
|
+
raise OperationError, "Unsupported type: #{v.class}"
|
127
|
+
end
|
128
|
+
end.join
|
129
|
+
end
|
130
|
+
|
131
|
+
def pakHash(h)
|
132
|
+
varint(h.size) + h.map do |k, v|
|
133
|
+
pakStr(k.to_s) + case v
|
134
|
+
when Symbol then pakStr(v.to_s)
|
135
|
+
when String then pakStr(v)
|
136
|
+
when Integer then paks(v)
|
137
|
+
when TrueClass then pakC(1)
|
138
|
+
when FalseClass then pakC(0)
|
139
|
+
when ::Array then pakArr(v)
|
140
|
+
when ::Hash then pakHash(v)
|
141
|
+
when NilClass then next
|
142
|
+
else
|
143
|
+
raise OperationError, "Unsupported type: #{v.class}"
|
144
|
+
end
|
145
|
+
end.join
|
146
|
+
end
|
147
|
+
|
148
|
+
#uint8_t
|
149
|
+
def pakC(i)
|
150
|
+
[i].pack('C')
|
151
|
+
end
|
152
|
+
|
153
|
+
#int8_t
|
154
|
+
def pakc(i)
|
155
|
+
[i].pack('c')
|
156
|
+
end
|
157
|
+
|
158
|
+
#int16_t
|
159
|
+
def paks(i)
|
160
|
+
[i].pack('s')
|
161
|
+
end
|
162
|
+
|
163
|
+
#uint16_t
|
164
|
+
def pakS(i)
|
165
|
+
[i].pack('S')
|
166
|
+
end
|
167
|
+
|
168
|
+
#uint32_t
|
169
|
+
def pakI(i)
|
170
|
+
[i].pack('I')
|
171
|
+
end
|
172
|
+
|
173
|
+
#int64_t
|
174
|
+
def pakL!(i)
|
175
|
+
[i].pack('L!')
|
176
|
+
end
|
177
|
+
|
178
|
+
#uint64_t
|
179
|
+
def pakQ(i)
|
180
|
+
[i].pack('Q')
|
181
|
+
end
|
182
|
+
|
183
|
+
#int64_t
|
184
|
+
def pakq(i)
|
185
|
+
[i].pack('q')
|
186
|
+
end
|
187
|
+
|
188
|
+
def pakPubKey(s)
|
189
|
+
# Get substring past index three through end of string.
|
190
|
+
pkn1 = s[3..-1]
|
191
|
+
# puts 'pkn1', pkn1
|
192
|
+
|
193
|
+
#b58.length=37
|
194
|
+
b58 = Base58.base58_to_binary(pkn1, :bitcoin)
|
195
|
+
# puts 'b58.length', b58.length
|
196
|
+
# puts 'b58', hexlify(b58)
|
197
|
+
|
198
|
+
# Get checksum 4-bytes end.
|
199
|
+
lb58 = b58.length-4
|
200
|
+
chs = b58[lb58..-1]
|
201
|
+
|
202
|
+
# Get raw PublicKey = b58 cut 4-bytes checksum.
|
203
|
+
# pkn2.length=33
|
204
|
+
hb58 = lb58-1
|
205
|
+
pkn2 = b58[0..hb58]
|
206
|
+
|
207
|
+
# Validate PublicKey again.
|
208
|
+
checksum = OpenSSL::Digest::RIPEMD160.digest(pkn2)
|
209
|
+
# take 4 bytes.
|
210
|
+
nchs = checksum[0..3]
|
211
|
+
achs = hexlify(chs)
|
212
|
+
bnchs = hexlify(nchs)
|
213
|
+
if !(achs.eql? bnchs)
|
214
|
+
puts achs, bnchs
|
215
|
+
puts 'Public key is incorrect'
|
216
|
+
end
|
217
|
+
pkn2
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
221
|
+
end
|