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 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