scale_rb 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3aacfcd3c4509dd0ba01d6cc0af5f16037f9bf17f5226a5cf615c916968e5a31
4
- data.tar.gz: a8bc39ff0b80706cfd5614e906ea378ca7e08067aebe716095e3cf67710a54dc
3
+ metadata.gz: 97c7224f0e7d0a5f0d754206cee8d1d9cb5f1519c6c80e37b6c0b541aa0a4bcf
4
+ data.tar.gz: 51434a46e4f46a6c91bc0859575287076b0b1457e942ceff4ea66e74c0c89132
5
5
  SHA512:
6
- metadata.gz: 2c84c953639ff54df078a86c343aa315cbcd743e5a3ddc9ed72663139628dc4a059e04f74016cb434568504d7967144476e778c717e7a4d63f4f7fe979d45628
7
- data.tar.gz: 584fdaa093a917323b3a9b58331a242cf1fb9a9ea5965538b1521a56b5cf8758d10b9f1ed2b933973c137dba33d9cd0db14e8f0d468f4b7f0066f59f3a407834
6
+ metadata.gz: 6b0e80c6756b68f75d9f42e0d65f4c3205af0f63c3d57f51f5d3abf838057cb9dfc17d87b47f277aba5f95361bedf7618d4c31680a8c09ca57cde438c3be1020
7
+ data.tar.gz: 30351dad5922fffb55c37907225c19bbb1f771af842e231f18dd6ff1c43091876a70ed514536d3fbece2814528dc1b03d0c8a9a109cdb31e07bf1eed201ebf84
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- scale_rb (0.1.1)
4
+ scale_rb (0.1.2)
5
5
  blake2b_rs (~> 0.1.2)
6
6
  xxhash
7
7
 
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 bytes?(type)
6
- type.downcase == 'bytes'
7
- end
23
+ def boolean?(type)
24
+ type.downcase == 'bool' || type.downcase == 'boolean'
25
+ end
8
26
 
9
- def boolean?(type)
10
- type.downcase == 'bool' || type.downcase == 'boolean'
11
- end
27
+ def string?(type)
28
+ type.downcase == 'str' || type.downcase == 'string' || type.downcase == 'text'
29
+ end
12
30
 
13
- def string?(type)
14
- type.downcase == 'str' || type.downcase == 'string' || type.downcase == 'text'
15
- end
31
+ def compact?(type)
32
+ type.downcase == 'compact' ||
33
+ (type[0..7].downcase == 'compact<' && type[-1] == '>')
34
+ end
16
35
 
17
- def compact?(type)
18
- type.downcase == 'compact' ||
19
- (type[0..7].downcase == 'compact<' && type[-1] == '>')
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 int?(type)
23
- type[0].downcase == 'i' && type[1..] =~ /\A(8|16|32|64|128|256|512)\z/
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 uint?(type)
27
- type[0].downcase == 'u' && type[1..] =~ /\A(8|16|32|64|128|256|512)\z/
28
- end
44
+ def option?(type)
45
+ type[0..6].downcase == 'option<' && type[-1] == '>'
46
+ end
29
47
 
30
- # def bitvec?(type)
31
- # end
48
+ def array?(type)
49
+ type[0] == '[' && type[-1] == ']'
50
+ end
32
51
 
33
- def option?(type)
34
- type[0..6].downcase == 'option<' && type[-1] == '>'
35
- end
52
+ def vec?(type)
53
+ type[0..3].downcase == 'vec<' && type[-1] == '>'
54
+ end
36
55
 
37
- def array?(type)
38
- type[0] == '[' && type[-1] == ']'
39
- end
56
+ def tuple?(type)
57
+ type[0] == '(' && type[-1] == ')'
58
+ end
40
59
 
41
- def vec?(type)
42
- type[0..3].downcase == 'vec<' && type[-1] == '>'
43
- end
60
+ def struct?(type)
61
+ type.instance_of?(Hash)
62
+ end
44
63
 
45
- def tuple?(type)
46
- type[0] == '(' && type[-1] == ')'
64
+ def enum?(type)
65
+ type.instance_of?(Hash) && type.key?(:_enum)
66
+ end
67
+ end
47
68
  end
48
69
 
49
- def struct?(type)
50
- type.instance_of?(Hash)
51
- end
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 enum?(type)
54
- type.instance_of?(Hash) && type.key?(:_enum)
55
- end
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
- def parse_fixed_array(type)
58
- scan_out = type.scan(/\A\[\s*(.+)\s*;\s*(\d+)\s*\]\z/)
59
- raise ScaleRb::TypeParseError, type if scan_out.empty?
60
- raise ScaleRb::TypeParseError, type if scan_out[0].length != 2
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
- inner_type = scan_out[0][0]
63
- length = scan_out[0][1].to_i
64
- [inner_type, length]
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 Error < StandardError; end
69
- class NotImplemented < Error; end
70
- class NilTypeError < Error; end
71
- class TypeParseError < Error; end
72
- class NotEnoughBytesError < Error; end
73
- class InvalidBytesError < Error; end
74
- class Unreachable < Error; end
75
- class IndexOutOfRangeError < Error; end
76
- class LengthNotEqualErr < Error; end
77
- class InvalidValueError < Error; end
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 = get_final_type_from_registry(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 = do_decode_compact(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 = do_decode_compact(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(type, bytes)
159
- bit_length = type[1..].to_i
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: #{type}" if bytes.length < byte_length
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 = do_decode_compact(bytes)
267
+ result = _do_decode_compact(bytes)
173
268
  debug 'value', result[0]
174
269
  result
175
270
  end
176
271
 
177
- def decode_option(type, bytes, registry = {})
178
- inner_type = type.scan(/\A[O|o]ption<(.+)>\z/).first.first
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: #{type}"
278
+ raise InvalidBytesError, "type: #{type_def}"
184
279
  end
185
280
 
186
- def decode_array(type, bytes, registry = {})
187
- inner_type, length = parse_fixed_array(type)
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(type, bytes, registry = {})
192
- inner_type = type.scan(/\A[V|v]ec<(.+)>\z/).first.first
193
- length, remaining_bytes = do_decode_compact(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(tuple_type, bytes, registry = {})
199
- inner_types = tuple_type.scan(/\A\(\s*(.+)\s*\)\z/)[0][0].split(',').map(&:strip)
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: custrom index
204
- def decode_enum(enum_type, bytes, registry = {})
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
- raise IndexOutOfRangeError, "type: #{enum_type}" if index > enum_type[:_enum].length - 1
207
-
208
- remaining_bytes = bytes[1..]
209
- if enum_type[:_enum].instance_of?(Hash)
210
- key = enum_type[:_enum].keys[index]
211
- type = enum_type[:_enum].values[index]
212
-
213
- value, remaining_bytes = decode(type, remaining_bytes, registry)
214
- [
215
- { key => value },
216
- remaining_bytes
217
- ]
218
- elsif enum_type[:_enum].instance_of?(Array)
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
- def self.get_final_type_from_registry(registry, type)
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
- logger.debug " type: #{type}"
278
- logger.debug " value: #{value}"
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 = get_final_type_from_registry(registry, type)
299
- return do_encode(registry_type, value, registry) if registry_type
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] + do_encode(inner_type, value, registry)
398
+ [0x01] + encode(inner_type, value, registry)
344
399
  end
345
400
 
346
401
  def encode_array(type, array, registry = {})
347
- inner_type, length = parse_fixed_array(type)
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) + do_encode(value_type, value, registry)
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
@@ -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
- if ids.empty?
119
- [[], bytes]
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
- _encode_types_without_merge(ids, values, registry).flatten
229
- end
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
- # return: [value1_bytes, value2_bytes, ...]
243
- def _encode_types_without_merge(ids, values, registry)
244
- raise ScaleRb::LengthNotEqualErr, "types: #{ids}, values: #{values.inspect}" if ids.length != values.length
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
@@ -1,3 +1,3 @@
1
1
  module ScaleRb
2
- VERSION = '0.1.1'
2
+ VERSION = '0.1.2'
3
3
  end
data/lib/scale_rb.rb CHANGED
@@ -16,8 +16,8 @@ require 'hasher'
16
16
  require 'storage_helper'
17
17
 
18
18
  # client
19
- require 'client/rpc'
20
- require 'client/client'
19
+ require 'substrate/rpc'
20
+ require 'substrate/client'
21
21
 
22
22
  # get registry from config
23
23
  require 'registry'
@@ -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(values, type_ids, registry, 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.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-04 00:00:00.000000000 Z
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