scale_rb 0.1.1 → 0.1.2
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/Gemfile.lock +1 -1
- data/exe/metadata +3 -3
- data/lib/codec.rb +201 -157
- data/lib/portable_codec.rb +13 -29
- data/lib/scale_rb/version.rb +1 -1
- data/lib/scale_rb.rb +2 -2
- data/lib/storage_helper.rb +1 -1
- data/lib/substrate/client.rb +137 -0
- data/lib/substrate/rpc.rb +70 -0
- metadata +4 -4
- data/lib/client/client.rb +0 -78
- data/lib/client/rpc.rb +0 -60
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 97c7224f0e7d0a5f0d754206cee8d1d9cb5f1519c6c80e37b6c0b541aa0a4bcf
|
4
|
+
data.tar.gz: 51434a46e4f46a6c91bc0859575287076b0b1457e942ceff4ea66e74c0c89132
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b0e80c6756b68f75d9f42e0d65f4c3205af0f63c3d57f51f5d3abf838057cb9dfc17d87b47f277aba5f95361bedf7618d4c31680a8c09ca57cde438c3be1020
|
7
|
+
data.tar.gz: 30351dad5922fffb55c37907225c19bbb1f771af842e231f18dd6ff1c43091876a70ed514536d3fbece2814528dc1b03d0c8a9a109cdb31e07bf1eed201ebf84
|
data/Gemfile.lock
CHANGED
data/exe/metadata
CHANGED
@@ -6,7 +6,7 @@ require 'json'
|
|
6
6
|
require 'optparse'
|
7
7
|
|
8
8
|
def print_metadata(url, at = nil)
|
9
|
-
puts JSON.pretty_generate(Client.get_metadata(url, at))
|
9
|
+
puts JSON.pretty_generate(Substrate::Client.get_metadata(url, at))
|
10
10
|
end
|
11
11
|
|
12
12
|
# ./bin/metadata http://g2.dev.darwinia.network:2234 -b 0x23ebddd6519aaf1b7fc916c3709af13d7a4010943fb53038406581171000a58e
|
@@ -31,10 +31,10 @@ else
|
|
31
31
|
block_hash = @options[:block]
|
32
32
|
else
|
33
33
|
block_number = @options[:block].to_i
|
34
|
-
block_hash = RPC.chain_getBlockHash url, block_number
|
34
|
+
block_hash = Substrate::RPC.chain_getBlockHash url, block_number
|
35
35
|
end
|
36
36
|
else
|
37
|
-
block_hash = RPC.chain_getBlockHash url
|
37
|
+
block_hash = Substrate::RPC.chain_getBlockHash url
|
38
38
|
end
|
39
39
|
|
40
40
|
print_metadata url, block_hash
|
data/lib/codec.rb
CHANGED
@@ -1,81 +1,176 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module ScaleRb
|
4
|
+
class Error < StandardError; end
|
5
|
+
class NotImplemented < Error; end
|
6
|
+
class NilTypeError < Error; end
|
7
|
+
class TypeParseError < Error; end
|
8
|
+
class NotEnoughBytesError < Error; end
|
9
|
+
class InvalidBytesError < Error; end
|
10
|
+
class Unreachable < Error; end
|
11
|
+
class IndexOutOfRangeError < Error; end
|
12
|
+
class LengthNotEqualErr < Error; end
|
13
|
+
class InvalidValueError < Error; end
|
14
|
+
end
|
15
|
+
|
3
16
|
# TODO: set, bitvec
|
17
|
+
module ScaleRb
|
18
|
+
class << self
|
19
|
+
def bytes?(type)
|
20
|
+
type.downcase == 'bytes'
|
21
|
+
end
|
4
22
|
|
5
|
-
def
|
6
|
-
|
7
|
-
end
|
23
|
+
def boolean?(type)
|
24
|
+
type.downcase == 'bool' || type.downcase == 'boolean'
|
25
|
+
end
|
8
26
|
|
9
|
-
def
|
10
|
-
|
11
|
-
end
|
27
|
+
def string?(type)
|
28
|
+
type.downcase == 'str' || type.downcase == 'string' || type.downcase == 'text'
|
29
|
+
end
|
12
30
|
|
13
|
-
def
|
14
|
-
|
15
|
-
|
31
|
+
def compact?(type)
|
32
|
+
type.downcase == 'compact' ||
|
33
|
+
(type[0..7].downcase == 'compact<' && type[-1] == '>')
|
34
|
+
end
|
16
35
|
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
end
|
36
|
+
def int?(type)
|
37
|
+
type[0].downcase == 'i' && type[1..] =~ /\A(8|16|32|64|128|256|512)\z/
|
38
|
+
end
|
21
39
|
|
22
|
-
def
|
23
|
-
|
24
|
-
end
|
40
|
+
def uint?(type)
|
41
|
+
type[0].downcase == 'u' && type[1..] =~ /\A(8|16|32|64|128|256|512)\z/
|
42
|
+
end
|
25
43
|
|
26
|
-
def
|
27
|
-
|
28
|
-
end
|
44
|
+
def option?(type)
|
45
|
+
type[0..6].downcase == 'option<' && type[-1] == '>'
|
46
|
+
end
|
29
47
|
|
30
|
-
|
31
|
-
|
48
|
+
def array?(type)
|
49
|
+
type[0] == '[' && type[-1] == ']'
|
50
|
+
end
|
32
51
|
|
33
|
-
def
|
34
|
-
|
35
|
-
end
|
52
|
+
def vec?(type)
|
53
|
+
type[0..3].downcase == 'vec<' && type[-1] == '>'
|
54
|
+
end
|
36
55
|
|
37
|
-
def
|
38
|
-
|
39
|
-
end
|
56
|
+
def tuple?(type)
|
57
|
+
type[0] == '(' && type[-1] == ')'
|
58
|
+
end
|
40
59
|
|
41
|
-
def
|
42
|
-
|
43
|
-
end
|
60
|
+
def struct?(type)
|
61
|
+
type.instance_of?(Hash)
|
62
|
+
end
|
44
63
|
|
45
|
-
def
|
46
|
-
|
64
|
+
def enum?(type)
|
65
|
+
type.instance_of?(Hash) && type.key?(:_enum)
|
66
|
+
end
|
67
|
+
end
|
47
68
|
end
|
48
69
|
|
49
|
-
|
50
|
-
|
51
|
-
|
70
|
+
module ScaleRb
|
71
|
+
class << self
|
72
|
+
def parse_option(type)
|
73
|
+
type.scan(/\A[O|o]ption<(.+)>\z/).first.first
|
74
|
+
end
|
52
75
|
|
53
|
-
def
|
54
|
-
|
55
|
-
|
76
|
+
def parse_array(type)
|
77
|
+
scan_out = type.scan(/\A\[\s*(.+)\s*;\s*(\d+)\s*\]\z/)
|
78
|
+
raise ScaleRb::TypeParseError, type if scan_out.empty?
|
79
|
+
raise ScaleRb::TypeParseError, type if scan_out[0].length != 2
|
56
80
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
81
|
+
inner_type = scan_out[0][0]
|
82
|
+
length = scan_out[0][1].to_i
|
83
|
+
[inner_type, length]
|
84
|
+
end
|
85
|
+
|
86
|
+
def parse_vec(type)
|
87
|
+
type.scan(/\A[V|v]ec<(.+)>\z/).first.first
|
88
|
+
end
|
61
89
|
|
62
|
-
|
63
|
-
|
64
|
-
|
90
|
+
def parse_tuple(type)
|
91
|
+
type.scan(/\A\(\s*(.+)\s*\)\z/)[0][0].split(',').map(&:strip)
|
92
|
+
end
|
93
|
+
end
|
65
94
|
end
|
66
95
|
|
96
|
+
# Helper functions
|
67
97
|
module ScaleRb
|
68
|
-
class
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
98
|
+
class << self
|
99
|
+
def _get_final_type_from_registry(registry, type)
|
100
|
+
mapped_type = registry[type]
|
101
|
+
if mapped_type.nil?
|
102
|
+
nil
|
103
|
+
elsif registry[mapped_type].nil?
|
104
|
+
mapped_type
|
105
|
+
else
|
106
|
+
_get_final_type_from_registry(registry, mapped_type)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def _decode_types(types, bytes, registry)
|
111
|
+
_decode_each(types, bytes) do |type, remaining_bytes|
|
112
|
+
decode(type, remaining_bytes, registry)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def _decode_each(types, bytes, &decode)
|
117
|
+
remaining_bytes = bytes
|
118
|
+
values = types.map do |type|
|
119
|
+
value, remaining_bytes = decode.call(type, remaining_bytes)
|
120
|
+
value
|
121
|
+
end
|
122
|
+
[values, remaining_bytes]
|
123
|
+
end
|
124
|
+
|
125
|
+
def _do_decode_compact(bytes)
|
126
|
+
case bytes[0] & 3
|
127
|
+
when 0
|
128
|
+
[bytes[0] >> 2, bytes[1..]]
|
129
|
+
when 1
|
130
|
+
[bytes[0..1].flip.to_uint >> 2, bytes[2..]]
|
131
|
+
when 2
|
132
|
+
[bytes[0..3].flip.to_uint >> 2, bytes[4..]]
|
133
|
+
when 3
|
134
|
+
length = 4 + (bytes[0] >> 2)
|
135
|
+
[bytes[1..length].flip.to_uint, bytes[length + 1..]]
|
136
|
+
else
|
137
|
+
raise Unreachable, 'type: Compact'
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def _encode_each(types, values, &encode)
|
142
|
+
_encode_each_without_merge(types, values, &encode).flatten
|
143
|
+
end
|
144
|
+
|
145
|
+
def _encode_each_without_merge(types, values, &encode)
|
146
|
+
raise LengthNotEqualErr, "types: #{types}, values: #{values.inspect}" if types.length != values.length
|
147
|
+
|
148
|
+
types.map.with_index do |type, i|
|
149
|
+
encode.call(type, values[i])
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def _encode_types(types, values, registry = {})
|
154
|
+
_encode_each(types, values) do |type, value|
|
155
|
+
encode(type, value, registry)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def _encode_each_with_hashers(types, values, hashers, &encode)
|
160
|
+
if !hashers.nil? && hashers.length != types.length
|
161
|
+
raise ScaleRb::LengthNotEqualErr, "types length: #{types.length}, hashers length: #{hashers.length}"
|
162
|
+
end
|
78
163
|
|
164
|
+
bytes_array = ScaleRb._encode_each_without_merge(types, values, &encode)
|
165
|
+
bytes_array.each_with_index.reduce([]) do |memo, (bytes, i)|
|
166
|
+
memo + Hasher.apply_hasher(hashers[i], bytes)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
module ScaleRb
|
173
|
+
# Decode
|
79
174
|
class << self
|
80
175
|
def decode(type, bytes, registry = {})
|
81
176
|
logger.debug '--------------------------------------------------'
|
@@ -95,7 +190,7 @@ module ScaleRb
|
|
95
190
|
return decode_tuple(type, bytes, registry) if tuple?(type) # (u8, u8)
|
96
191
|
|
97
192
|
# search the type from registry if not the types above
|
98
|
-
registry_type =
|
193
|
+
registry_type = _get_final_type_from_registry(registry, type)
|
99
194
|
return decode(registry_type, bytes, registry) if registry_type
|
100
195
|
elsif type.instance_of?(Hash)
|
101
196
|
return decode_enum(type, bytes, registry) if enum?(type)
|
@@ -106,7 +201,7 @@ module ScaleRb
|
|
106
201
|
end
|
107
202
|
|
108
203
|
def decode_bytes(bytes)
|
109
|
-
length, remaining_bytes =
|
204
|
+
length, remaining_bytes = _do_decode_compact(bytes)
|
110
205
|
value = remaining_bytes[0...length].to_hex
|
111
206
|
debug 'length', length
|
112
207
|
debug 'value', value
|
@@ -130,7 +225,7 @@ module ScaleRb
|
|
130
225
|
end
|
131
226
|
|
132
227
|
def decode_string(bytes)
|
133
|
-
length, remaining_bytes =
|
228
|
+
length, remaining_bytes = _do_decode_compact(bytes)
|
134
229
|
raise NotEnoughBytesError, 'type: String' if remaining_bytes.length < length
|
135
230
|
|
136
231
|
value = remaining_bytes[0...length].to_utf8
|
@@ -155,10 +250,10 @@ module ScaleRb
|
|
155
250
|
]
|
156
251
|
end
|
157
252
|
|
158
|
-
def decode_uint(
|
159
|
-
bit_length =
|
253
|
+
def decode_uint(type_def, bytes)
|
254
|
+
bit_length = type_def[1..].to_i
|
160
255
|
byte_length = bit_length / 8
|
161
|
-
raise NotEnoughBytesError, "type: #{
|
256
|
+
raise NotEnoughBytesError, "type: #{type_def}" if bytes.length < byte_length
|
162
257
|
|
163
258
|
value = bytes[0...byte_length].flip.to_uint
|
164
259
|
debug 'value', value
|
@@ -169,60 +264,63 @@ module ScaleRb
|
|
169
264
|
end
|
170
265
|
|
171
266
|
def decode_compact(bytes)
|
172
|
-
result =
|
267
|
+
result = _do_decode_compact(bytes)
|
173
268
|
debug 'value', result[0]
|
174
269
|
result
|
175
270
|
end
|
176
271
|
|
177
|
-
def decode_option(
|
178
|
-
inner_type =
|
272
|
+
def decode_option(type_def, bytes, registry = {})
|
273
|
+
inner_type = parse_option(type_def)
|
179
274
|
|
180
275
|
return [nil, bytes[1..]] if bytes[0] == 0x00
|
181
276
|
return decode(inner_type, bytes[1..], registry) if bytes[0] == 0x01
|
182
277
|
|
183
|
-
raise InvalidBytesError, "type: #{
|
278
|
+
raise InvalidBytesError, "type: #{type_def}"
|
184
279
|
end
|
185
280
|
|
186
|
-
def decode_array(
|
187
|
-
inner_type, length =
|
281
|
+
def decode_array(type_def, bytes, registry = {})
|
282
|
+
inner_type, length = parse_array(type_def)
|
188
283
|
_decode_types([inner_type] * length, bytes, registry)
|
189
284
|
end
|
190
285
|
|
191
|
-
def decode_vec(
|
192
|
-
inner_type =
|
193
|
-
length, remaining_bytes =
|
286
|
+
def decode_vec(type_def, bytes, registry = {})
|
287
|
+
inner_type = parse_vec(type_def)
|
288
|
+
length, remaining_bytes = _do_decode_compact(bytes)
|
194
289
|
debug 'length', length
|
195
290
|
_decode_types([inner_type] * length, remaining_bytes, registry)
|
196
291
|
end
|
197
292
|
|
198
|
-
def decode_tuple(
|
199
|
-
inner_types =
|
293
|
+
def decode_tuple(type_def, bytes, registry = {})
|
294
|
+
inner_types = parse_tuple(type_def)
|
200
295
|
_decode_types(inner_types, bytes, registry)
|
201
296
|
end
|
202
297
|
|
203
|
-
# TODO:
|
204
|
-
|
298
|
+
# TODO: custom index?
|
299
|
+
# {
|
300
|
+
# _enum: {
|
301
|
+
# name1: type1,
|
302
|
+
# name2: type2
|
303
|
+
# }
|
304
|
+
# }
|
305
|
+
# or
|
306
|
+
# {
|
307
|
+
# _enum: ['name1', 'name2']
|
308
|
+
# }
|
309
|
+
def decode_enum(type_def, bytes, registry = {})
|
205
310
|
index = bytes[0]
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
value = enum_type[:_enum][index]
|
220
|
-
debug 'value', value.inspect
|
221
|
-
[
|
222
|
-
value,
|
223
|
-
remaining_bytes
|
224
|
-
]
|
225
|
-
end
|
311
|
+
|
312
|
+
items = type_def[:_enum]
|
313
|
+
raise IndexOutOfRangeError, "type: #{type_def}" if index > items.length - 1
|
314
|
+
|
315
|
+
item = items.to_a[index] # 'name' or [:name, inner_type]
|
316
|
+
debug 'value', item.inspect
|
317
|
+
return [item, remaining_bytes] if item.instance_of?(String)
|
318
|
+
|
319
|
+
value, remaining_bytes = decode(item[1], bytes[1..], registry)
|
320
|
+
[
|
321
|
+
{ item[0].to_sym => value },
|
322
|
+
remaining_bytes
|
323
|
+
]
|
226
324
|
end
|
227
325
|
|
228
326
|
def decode_struct(struct, bytes, registry = {})
|
@@ -234,56 +332,13 @@ module ScaleRb
|
|
234
332
|
end
|
235
333
|
end
|
236
334
|
|
237
|
-
|
238
|
-
mapped_type = registry[type]
|
239
|
-
if mapped_type.nil?
|
240
|
-
nil
|
241
|
-
elsif registry[mapped_type].nil?
|
242
|
-
mapped_type
|
243
|
-
else
|
244
|
-
get_final_type_from_registry(registry, mapped_type)
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
def self._decode_types(type_list, bytes, registry = {})
|
249
|
-
if type_list.empty?
|
250
|
-
[[], bytes]
|
251
|
-
else
|
252
|
-
value, remaining_bytes = decode(type_list.first, bytes, registry)
|
253
|
-
value_list, remaining_bytes = _decode_types(type_list[1..], remaining_bytes, registry)
|
254
|
-
[[value] + value_list, remaining_bytes]
|
255
|
-
end
|
256
|
-
end
|
257
|
-
|
258
|
-
def self.do_decode_compact(bytes)
|
259
|
-
case bytes[0] & 3
|
260
|
-
when 0
|
261
|
-
[bytes[0] >> 2, bytes[1..]]
|
262
|
-
when 1
|
263
|
-
[bytes[0..1].flip.to_uint >> 2, bytes[2..]]
|
264
|
-
when 2
|
265
|
-
[bytes[0..3].flip.to_uint >> 2, bytes[4..]]
|
266
|
-
when 3
|
267
|
-
length = 4 + (bytes[0] >> 2)
|
268
|
-
[bytes[1..length].flip.to_uint, bytes[length + 1..]]
|
269
|
-
else
|
270
|
-
raise Unreachable, 'type: Compact'
|
271
|
-
end
|
272
|
-
end
|
273
|
-
|
335
|
+
# Encode
|
274
336
|
class << self
|
275
337
|
def encode(type, value, registry = {})
|
276
|
-
logger.debug '
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
bytes = do_encode(type, value, registry)
|
281
|
-
|
282
|
-
logger.debug " encoded: #{bytes}"
|
283
|
-
bytes
|
284
|
-
end
|
338
|
+
logger.debug '--------------------------------------------------'
|
339
|
+
debug 'encoding type', type
|
340
|
+
debug 'value', value
|
285
341
|
|
286
|
-
def do_encode(type, value, registry = {})
|
287
342
|
if type.instance_of?(String)
|
288
343
|
return encode_bytes(value) if bytes?(type)
|
289
344
|
return encode_boolean(value) if boolean?(type)
|
@@ -295,8 +350,8 @@ module ScaleRb
|
|
295
350
|
return encode_vec(type, value, registry) if vec?(type)
|
296
351
|
return encode_tuple(type, value, registry) if tuple?(type)
|
297
352
|
|
298
|
-
registry_type =
|
299
|
-
return
|
353
|
+
registry_type = _get_final_type_from_registry(registry, type)
|
354
|
+
return encode(registry_type, value, registry) if registry_type
|
300
355
|
elsif type.instance_of?(Hash)
|
301
356
|
return encode_enum(type, value, registry) if enum?(type)
|
302
357
|
return encode_struct(type, value, registry) if struct?(type)
|
@@ -340,11 +395,11 @@ module ScaleRb
|
|
340
395
|
return [0x00] if value.nil?
|
341
396
|
|
342
397
|
inner_type = type.scan(/\A[O|o]ption<(.+)>\z/).first.first
|
343
|
-
[0x01] +
|
398
|
+
[0x01] + encode(inner_type, value, registry)
|
344
399
|
end
|
345
400
|
|
346
401
|
def encode_array(type, array, registry = {})
|
347
|
-
inner_type, length =
|
402
|
+
inner_type, length = parse_array(type)
|
348
403
|
raise LengthNotEqualErr, "type: #{type}, value: #{array.inspect}" if length != array.length
|
349
404
|
|
350
405
|
_encode_types([inner_type] * length, array, registry)
|
@@ -366,22 +421,11 @@ module ScaleRb
|
|
366
421
|
value = enum.values.first
|
367
422
|
value_type = enum_type[:_enum][key]
|
368
423
|
index = enum_type[:_enum].keys.index(key)
|
369
|
-
encode_uint('u8', index) +
|
424
|
+
encode_uint('u8', index) + encode(value_type, value, registry)
|
370
425
|
end
|
371
426
|
|
372
427
|
def encode_struct(struct_type, struct, registry = {})
|
373
428
|
_encode_types(struct_type.values, struct.values, registry)
|
374
429
|
end
|
375
|
-
|
376
|
-
def _encode_types(type_list, value_list, registry = {})
|
377
|
-
raise LengthNotEqualErr, "type: #{type_list}, value: #{value_list.inspect}" if type_list.length != value_list.length
|
378
|
-
|
379
|
-
if type_list.empty?
|
380
|
-
[]
|
381
|
-
else
|
382
|
-
bytes = do_encode(type_list.first, value_list.first, registry)
|
383
|
-
bytes + _encode_types(type_list[1..], value_list[1..], registry)
|
384
|
-
end
|
385
|
-
end
|
386
430
|
end
|
387
431
|
end
|
data/lib/portable_codec.rb
CHANGED
@@ -47,9 +47,9 @@ module PortableCodec
|
|
47
47
|
# Int, Bytes ?
|
48
48
|
def decode_primitive(type_def, bytes)
|
49
49
|
primitive = type_def._get(:primitive)
|
50
|
-
return ScaleRb.decode_uint(primitive, bytes) if uint?(primitive)
|
51
|
-
return ScaleRb.decode_string(bytes) if string?(primitive)
|
52
|
-
return ScaleRb.decode_boolean(bytes) if boolean?(primitive)
|
50
|
+
return ScaleRb.decode_uint(primitive, bytes) if ScaleRb.uint?(primitive)
|
51
|
+
return ScaleRb.decode_string(bytes) if ScaleRb.string?(primitive)
|
52
|
+
return ScaleRb.decode_boolean(bytes) if ScaleRb.boolean?(primitive)
|
53
53
|
# return ScaleRb.decode_int(primitive, bytes) if int?(primitive)
|
54
54
|
# return ScaleRb.decode_bytes(bytes) if bytes?(primitive)
|
55
55
|
end
|
@@ -115,12 +115,8 @@ module PortableCodec
|
|
115
115
|
end
|
116
116
|
|
117
117
|
def _decode_types(ids, bytes, registry = {})
|
118
|
-
|
119
|
-
|
120
|
-
else
|
121
|
-
value, remaining_bytes = decode(ids.first, bytes, registry)
|
122
|
-
value_list, remaining_bytes = _decode_types(ids[1..], remaining_bytes, registry)
|
123
|
-
[[value] + value_list, remaining_bytes]
|
118
|
+
ScaleRb._decode_each(ids, bytes) do |id, remaining_bytes|
|
119
|
+
decode(id, remaining_bytes, registry)
|
124
120
|
end
|
125
121
|
end
|
126
122
|
|
@@ -148,9 +144,9 @@ module PortableCodec
|
|
148
144
|
|
149
145
|
def encode_primitive(type_def, value)
|
150
146
|
primitive = type_def._get(:primitive)
|
151
|
-
return ScaleRb.encode_uint(primitive, value) if uint?(primitive)
|
152
|
-
return ScaleRb.encode_string(value) if string?(primitive)
|
153
|
-
return ScaleRb.encode_boolean(value) if boolean?(primitive)
|
147
|
+
return ScaleRb.encode_uint(primitive, value) if ScaleRb.uint?(primitive)
|
148
|
+
return ScaleRb.encode_string(value) if ScaleRb.string?(primitive)
|
149
|
+
return ScaleRb.encode_boolean(value) if ScaleRb.boolean?(primitive)
|
154
150
|
end
|
155
151
|
|
156
152
|
def encode_compact(value)
|
@@ -225,26 +221,14 @@ module PortableCodec
|
|
225
221
|
end
|
226
222
|
|
227
223
|
def _encode_types(ids, values, registry)
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
def _encode_types_with_hashers(values, type_ids, registry, hashers)
|
232
|
-
if !hashers.nil? && hashers.length != type_ids.length
|
233
|
-
raise ScaleRb::LengthNotEqualErr, "type_ids length: #{type_ids.length}, hashers length: #{hashers.length}"
|
234
|
-
end
|
235
|
-
|
236
|
-
bytes_array = _encode_types_without_merge(type_ids, values, registry)
|
237
|
-
bytes_array.each_with_index.reduce([]) do |memo, (bytes, i)|
|
238
|
-
memo + Hasher.apply_hasher(hashers[i], bytes)
|
224
|
+
ScaleRb._encode_each(ids, values) do |id, value|
|
225
|
+
encode(id, value, registry)
|
239
226
|
end
|
240
227
|
end
|
241
228
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
ids.map.with_index do |type_id, i|
|
247
|
-
encode(type_id, values[i], registry)
|
229
|
+
def _encode_types_with_hashers(ids, values, registry, hashers)
|
230
|
+
ScaleRb._encode_each_with_hashers(ids, values, hashers) do |id, value|
|
231
|
+
encode(id, value, registry)
|
248
232
|
end
|
249
233
|
end
|
250
234
|
end
|
data/lib/scale_rb/version.rb
CHANGED
data/lib/scale_rb.rb
CHANGED
data/lib/storage_helper.rb
CHANGED
@@ -21,7 +21,7 @@ module StorageHelper
|
|
21
21
|
type_ids = params[:type_ids]
|
22
22
|
hashers = params[:hashers]
|
23
23
|
|
24
|
-
pallet_method_key + PortableCodec._encode_types_with_hashers(
|
24
|
+
pallet_method_key + PortableCodec._encode_types_with_hashers(type_ids, values, registry, hashers)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Substrate
|
4
|
+
module Client
|
5
|
+
class << self
|
6
|
+
def get_metadata(url, at = nil)
|
7
|
+
hex = Substrate::RPC.state_getMetadata(url, at)
|
8
|
+
Metadata.decode_metadata(hex.strip.to_bytes)
|
9
|
+
end
|
10
|
+
|
11
|
+
def query_storage_at(url, storage_keys, type_id, default, registry, at = nil)
|
12
|
+
result = Substrate::RPC.state_queryStorageAt(url, storage_keys, at)
|
13
|
+
result.map do |item|
|
14
|
+
item['changes'].map do |change|
|
15
|
+
storage_key = change[0]
|
16
|
+
data = change[1] || default
|
17
|
+
storage = data.nil? ? nil : PortableCodec.decode(type_id, data.to_bytes, registry)[0]
|
18
|
+
{ storage_key: storage_key, storage: storage }
|
19
|
+
end
|
20
|
+
end.flatten
|
21
|
+
end
|
22
|
+
|
23
|
+
def get_storage_keys_by_partial_key(url, partial_storage_key, start_key = nil, at = nil)
|
24
|
+
storage_keys = Substrate::RPC.state_getKeysPaged(url, partial_storage_key, 1000, start_key, at)
|
25
|
+
if storage_keys.length == 1000
|
26
|
+
storage_keys + get_storage_keys_by_partial_key(url, partial_storage_key, storage_keys.last, at)
|
27
|
+
else
|
28
|
+
storage_keys
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def get_storages_by_partial_key(url, partial_storage_key, type_id_of_value, default, registry, at = nil)
|
33
|
+
storage_keys = get_storage_keys_by_partial_key(url, partial_storage_key, partial_storage_key, at)
|
34
|
+
storage_keys.each_slice(250).map do |slice|
|
35
|
+
query_storage_at(
|
36
|
+
url,
|
37
|
+
slice,
|
38
|
+
type_id_of_value,
|
39
|
+
default,
|
40
|
+
registry,
|
41
|
+
at
|
42
|
+
)
|
43
|
+
end.flatten
|
44
|
+
end
|
45
|
+
|
46
|
+
# type_id: result type id
|
47
|
+
def get_storage(url, storage_key, type_id, default, registry, at = nil)
|
48
|
+
data = Substrate::RPC.state_getStorage(url, storage_key, at) || default
|
49
|
+
return nil if data.nil?
|
50
|
+
|
51
|
+
PortableCodec.decode(type_id, data.to_bytes, registry)[0]
|
52
|
+
end
|
53
|
+
|
54
|
+
# 1. Plain
|
55
|
+
# key: nil
|
56
|
+
# value: { type: 3, modifier: 'Default', callback: '' }
|
57
|
+
#
|
58
|
+
# 2. Map
|
59
|
+
# key: { value: value, type: 0, hashers: ['Blake2128Concat'] }
|
60
|
+
# value: { type: 3, modifier: 'Default', callback: '' }
|
61
|
+
#
|
62
|
+
# 3. Map, but key.value is nil
|
63
|
+
# key: { value: nil, type: 0, hashers: ['Blake2128Concat'] }
|
64
|
+
# value: { type: 3, modifier: 'Default', callback: '' }
|
65
|
+
#
|
66
|
+
# example:
|
67
|
+
# 'System',
|
68
|
+
# 'Account',
|
69
|
+
# key = {
|
70
|
+
# value: [['0x724d50824542b56f422588421643c4a162b90b5416ef063f2266a1eae6651641'.to_bytes]], # [AccountId]
|
71
|
+
# type: 0,
|
72
|
+
# hashers: ['Blake2128Concat']
|
73
|
+
# },
|
74
|
+
# value = {
|
75
|
+
# type: 3,
|
76
|
+
# modifier: 'Default',
|
77
|
+
# callback: '0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
78
|
+
# },
|
79
|
+
# ..
|
80
|
+
#
|
81
|
+
def get_storage2(url, pallet_name, item_name, key, value, registry, at = nil)
|
82
|
+
# map, but no key's value provided. get all storages under the partial storage key
|
83
|
+
if !key.nil? && key[:value].nil?
|
84
|
+
partial_storage_key = StorageHelper.encode_storage_key(pallet_name, item_name).to_hex
|
85
|
+
get_storages_by_partial_key(
|
86
|
+
url,
|
87
|
+
partial_storage_key,
|
88
|
+
value[:type],
|
89
|
+
value[:modifier] == 'Default' ? value[:fallback] : nil,
|
90
|
+
registry,
|
91
|
+
at
|
92
|
+
)
|
93
|
+
else
|
94
|
+
params = (StorageHelper.build_params(key[:value], key[:type], key[:hashers], registry) unless key.nil?)
|
95
|
+
storage_key = StorageHelper.encode_storage_key(pallet_name, item_name, params, registry).to_hex
|
96
|
+
get_storage(
|
97
|
+
url,
|
98
|
+
storage_key,
|
99
|
+
value[:type],
|
100
|
+
value[:modifier] == 'Default' ? value[:fallback] : nil,
|
101
|
+
registry,
|
102
|
+
at
|
103
|
+
)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def get_storage3(url, pallet_name, item_name, value_of_key, metadata, at = nil)
|
108
|
+
raise 'metadata should not be nil' if metadata.nil?
|
109
|
+
|
110
|
+
registry = Metadata.build_registry(metadata)
|
111
|
+
item = Metadata.get_storage_item(pallet_name, item_name, metadata)
|
112
|
+
|
113
|
+
modifier = item._get(:modifier) # Default | Optional
|
114
|
+
fallback = item._get(:fallback)
|
115
|
+
type = item._get(:type)
|
116
|
+
|
117
|
+
plain = type._get(:plain)
|
118
|
+
map = type._get(:map)
|
119
|
+
key, value =
|
120
|
+
if plain
|
121
|
+
[
|
122
|
+
nil,
|
123
|
+
{ type: plain, modifier: modifier, fallback: fallback }
|
124
|
+
]
|
125
|
+
elsif map
|
126
|
+
[
|
127
|
+
{ value: value_of_key, type: map._get(:key), hashers: map._get(:hashers) },
|
128
|
+
{ type: map._get(:value), modifier: modifier, fallback: fallback }
|
129
|
+
]
|
130
|
+
else
|
131
|
+
raise 'NoSuchStorageType'
|
132
|
+
end
|
133
|
+
get_storage2(url, pallet_name, item_name, key, value, registry, at)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'uri'
|
4
|
+
require 'net/http'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
module Substrate
|
8
|
+
module RPC
|
9
|
+
class << self
|
10
|
+
def json_rpc_call(method, params, url)
|
11
|
+
uri = URI(url)
|
12
|
+
req = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json')
|
13
|
+
req.body = {
|
14
|
+
'id' => 1,
|
15
|
+
'jsonrpc' => '2.0',
|
16
|
+
'method' => method,
|
17
|
+
'params' => params.reject(&:nil?)
|
18
|
+
}.to_json
|
19
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
20
|
+
http.use_ssl = true if uri.instance_of? URI::HTTPS
|
21
|
+
res = http.request(req)
|
22
|
+
# puts res unless res.is_a?(Net::HTTPSuccess)
|
23
|
+
|
24
|
+
result = JSON.parse(res.body)
|
25
|
+
raise result['error'] if result['error']
|
26
|
+
|
27
|
+
result['result']
|
28
|
+
end
|
29
|
+
|
30
|
+
def chain_getBlockHash(url, block_number = nil)
|
31
|
+
json_rpc_call('chain_getBlockHash', [block_number], url)
|
32
|
+
end
|
33
|
+
|
34
|
+
def chain_getBlock(url, at = nil)
|
35
|
+
json_rpc_call('chain_getBlock', [at], url)
|
36
|
+
end
|
37
|
+
|
38
|
+
def state_getRuntimeVersion(url, at = nil)
|
39
|
+
json_rpc_call('state_getRuntimeVersion', [at], url)
|
40
|
+
end
|
41
|
+
|
42
|
+
def state_getMetadata(url, at = nil)
|
43
|
+
json_rpc_call('state_getMetadata', [at], url)
|
44
|
+
end
|
45
|
+
|
46
|
+
def state_getStorage(url, key, at = nil)
|
47
|
+
json_rpc_call('state_getStorage', [key, at], url)
|
48
|
+
end
|
49
|
+
|
50
|
+
def state_queryStorageAt(url, keys, at = nil)
|
51
|
+
json_rpc_call('state_queryStorageAt', [keys, at], url)
|
52
|
+
end
|
53
|
+
|
54
|
+
def state_getKeysPaged(url, key, count, start_key = nil, at = nil)
|
55
|
+
json_rpc_call('state_getKeysPaged', [key, count, start_key, at], url)
|
56
|
+
end
|
57
|
+
|
58
|
+
def eth_call(url, to, data, at_block_number = nil)
|
59
|
+
json_rpc_call('eth_call', [
|
60
|
+
{
|
61
|
+
'from' => nil,
|
62
|
+
'to' => to,
|
63
|
+
'data' => data
|
64
|
+
},
|
65
|
+
at_block_number
|
66
|
+
], url)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scale_rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aki Wu
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-10-
|
11
|
+
date: 2022-10-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: blake2b_rs
|
@@ -59,8 +59,6 @@ files:
|
|
59
59
|
- bin/console
|
60
60
|
- bin/setup
|
61
61
|
- exe/metadata
|
62
|
-
- lib/client/client.rb
|
63
|
-
- lib/client/rpc.rb
|
64
62
|
- lib/codec.rb
|
65
63
|
- lib/hasher.rb
|
66
64
|
- lib/metadata.rb
|
@@ -71,6 +69,8 @@ files:
|
|
71
69
|
- lib/scale_rb.rb
|
72
70
|
- lib/scale_rb/version.rb
|
73
71
|
- lib/storage_helper.rb
|
72
|
+
- lib/substrate/client.rb
|
73
|
+
- lib/substrate/rpc.rb
|
74
74
|
- scale_rb.gemspec
|
75
75
|
homepage: https://github.com/wuminzhe/scale_rb
|
76
76
|
licenses:
|
data/lib/client/client.rb
DELETED
@@ -1,78 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Client
|
4
|
-
class << self
|
5
|
-
def get_metadata(url, at = nil)
|
6
|
-
hex = RPC.state_getMetadata(url, at)
|
7
|
-
Metadata.decode_metadata(hex.strip.to_bytes)
|
8
|
-
end
|
9
|
-
|
10
|
-
# type_id: result type id
|
11
|
-
def get_storage(url, storage_key, type_id, default, registry, at = nil)
|
12
|
-
data = RPC.state_getStorage(url, storage_key, at) || default
|
13
|
-
return nil if data.nil?
|
14
|
-
|
15
|
-
PortableCodec.decode(type_id, data.to_bytes, registry)[0]
|
16
|
-
end
|
17
|
-
|
18
|
-
# key: { value: .., type: 0, hashers: ['Blake2128Concat'] } | nil
|
19
|
-
# value: { type: 3, modifier: 'Default', callback: '' }
|
20
|
-
#
|
21
|
-
# example:
|
22
|
-
# 'System',
|
23
|
-
# 'Account',
|
24
|
-
# key = {
|
25
|
-
# value: [['0x724d50824542b56f422588421643c4a162b90b5416ef063f2266a1eae6651641'.to_bytes]], # [AccountId]
|
26
|
-
# type: 0,
|
27
|
-
# hashers: ['Blake2128Concat']
|
28
|
-
# },
|
29
|
-
# value = {
|
30
|
-
# type: 3,
|
31
|
-
# modifier: 'Default',
|
32
|
-
# callback: '0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
33
|
-
# },
|
34
|
-
# ..
|
35
|
-
def get_storage2(url, pallet_name, item_name, key, value, registry, at = nil)
|
36
|
-
params = (StorageHelper.build_params(key[:value], key[:type], key[:hashers], registry) if key)
|
37
|
-
|
38
|
-
storage_key = StorageHelper.encode_storage_key(pallet_name, item_name, params, registry).to_hex
|
39
|
-
get_storage(
|
40
|
-
url,
|
41
|
-
storage_key,
|
42
|
-
value[:type],
|
43
|
-
value[:modifier] == 'Default' ? value[:fallback] : nil,
|
44
|
-
registry,
|
45
|
-
at
|
46
|
-
)
|
47
|
-
end
|
48
|
-
|
49
|
-
def get_storage3(url, pallet_name, item_name, key_value, metadata, at = nil)
|
50
|
-
raise 'metadata should not be nil' if metadata.nil?
|
51
|
-
|
52
|
-
registry = Metadata.build_registry(metadata)
|
53
|
-
item = Metadata.get_storage_item(pallet_name, item_name, metadata)
|
54
|
-
|
55
|
-
modifier = item._get(:modifier) # Default | Optional
|
56
|
-
fallback = item._get(:fallback)
|
57
|
-
type = item._get(:type)
|
58
|
-
|
59
|
-
plain = type._get(:plain)
|
60
|
-
map = type._get(:map)
|
61
|
-
key, value =
|
62
|
-
if plain
|
63
|
-
[
|
64
|
-
nil,
|
65
|
-
{ type: plain, modifier: modifier, fallback: fallback }
|
66
|
-
]
|
67
|
-
elsif map
|
68
|
-
[
|
69
|
-
{ value: key_value, type: map._get(:key), hashers: map._get(:hashers) },
|
70
|
-
{ type: map._get(:value), modifier: modifier, fallback: fallback }
|
71
|
-
]
|
72
|
-
else
|
73
|
-
raise 'NoSuchStorageType'
|
74
|
-
end
|
75
|
-
get_storage2(url, pallet_name, item_name, key, value, registry, at)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
data/lib/client/rpc.rb
DELETED
@@ -1,60 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'uri'
|
4
|
-
require 'net/http'
|
5
|
-
require 'json'
|
6
|
-
|
7
|
-
module RPC
|
8
|
-
class << self
|
9
|
-
def json_rpc_call(method, params, url)
|
10
|
-
uri = URI(url)
|
11
|
-
req = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json')
|
12
|
-
req.body = {
|
13
|
-
'id' => 1,
|
14
|
-
'jsonrpc' => '2.0',
|
15
|
-
'method' => method,
|
16
|
-
'params' => params.all?(nil) ? [] : params
|
17
|
-
}.to_json
|
18
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
19
|
-
http.use_ssl = true if uri.instance_of? URI::HTTPS
|
20
|
-
res = http.request(req)
|
21
|
-
# puts res unless res.is_a?(Net::HTTPSuccess)
|
22
|
-
|
23
|
-
result = JSON.parse(res.body)
|
24
|
-
raise result['error'] if result['error']
|
25
|
-
|
26
|
-
result['result']
|
27
|
-
end
|
28
|
-
|
29
|
-
def chain_getBlockHash(url, block_number = nil)
|
30
|
-
json_rpc_call('chain_getBlockHash', [block_number], url)
|
31
|
-
end
|
32
|
-
|
33
|
-
def chain_getBlock(url, at = nil)
|
34
|
-
json_rpc_call('chain_getBlock', [at], url)
|
35
|
-
end
|
36
|
-
|
37
|
-
def state_getRuntimeVersion(url, at = nil)
|
38
|
-
json_rpc_call('state_getRuntimeVersion', [at], url)
|
39
|
-
end
|
40
|
-
|
41
|
-
def state_getMetadata(url, at = nil)
|
42
|
-
json_rpc_call('state_getMetadata', [at], url)
|
43
|
-
end
|
44
|
-
|
45
|
-
def state_getStorage(url, key, at = nil)
|
46
|
-
json_rpc_call('state_getStorage', [key, at], url)
|
47
|
-
end
|
48
|
-
|
49
|
-
def eth_call(url, to, data, at_block_number = nil)
|
50
|
-
json_rpc_call('eth_call', [
|
51
|
-
{
|
52
|
-
'from' => nil,
|
53
|
-
'to' => to,
|
54
|
-
'data' => data
|
55
|
-
},
|
56
|
-
at_block_number
|
57
|
-
], url)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|