scale.rb 0.2.2 → 0.2.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -37,7 +37,7 @@ module Scale
37
37
 
38
38
  if m[:events]
39
39
  m[:events].each_with_index do |event, index|
40
- event[:lookup] = "%02x%02x" % [call_module_index, index]
40
+ event[:lookup] = "%02x%02x" % [event_module_index, index]
41
41
  result.event_index[event[:lookup]] = [m, event]
42
42
  end
43
43
  event_module_index += 1
@@ -92,7 +92,7 @@ module Scale
92
92
  name: String.decode(scale_bytes).value,
93
93
  type: String.decode(scale_bytes).value, # convert
94
94
  value: Hex.decode(scale_bytes).value,
95
- docs: Scale::Types.type_of("Vec<String>").decode(scale_bytes).value.map(&:value)
95
+ documentation: Scale::Types.type_of("Vec<String>").decode(scale_bytes).value.map(&:value)
96
96
  }
97
97
  MetadataV6ModuleConstants.new result
98
98
  end
@@ -37,7 +37,7 @@ module Scale
37
37
 
38
38
  if m[:events]
39
39
  m[:events].each_with_index do |event, index|
40
- event[:lookup] = "%02x%02x" % [call_module_index, index]
40
+ event[:lookup] = "%02x%02x" % [event_module_index, index]
41
41
  result.event_index[event[:lookup]] = [m, event]
42
42
  end
43
43
  event_module_index += 1
@@ -106,14 +106,14 @@ module Scale
106
106
  storage_function_type = Scale::Types.type_of("Enum", %w[Plain Map DoubleMap]).decode(scale_bytes).value
107
107
  if storage_function_type == "Plain"
108
108
  result[:type] = {
109
- Plain: adjust(String.decode(scale_bytes).value)
109
+ Plain: String.decode(scale_bytes).value
110
110
  }
111
111
  elsif storage_function_type == "Map"
112
112
  result[:type] = {
113
113
  Map: {
114
114
  hasher: StorageHasher.decode(scale_bytes).value,
115
- key: adjust(String.decode(scale_bytes).value),
116
- value: adjust(String.decode(scale_bytes).value),
115
+ key: String.decode(scale_bytes).value,
116
+ value: String.decode(scale_bytes).value,
117
117
  linked: Bool.decode(scale_bytes).value
118
118
  }
119
119
  }
@@ -121,16 +121,16 @@ module Scale
121
121
  result[:type] = {
122
122
  DoubleMap: {
123
123
  hasher: StorageHasher.decode(scale_bytes).value,
124
- key1: adjust(String.decode(scale_bytes).value),
125
- key2: adjust(String.decode(scale_bytes).value),
126
- value: adjust(String.decode(scale_bytes).value),
124
+ key1: String.decode(scale_bytes).value,
125
+ key2: String.decode(scale_bytes).value,
126
+ value: String.decode(scale_bytes).value,
127
127
  key2Hasher: StorageHasher.decode(scale_bytes).value
128
128
  }
129
129
  }
130
130
  end
131
131
 
132
132
  result[:fallback] = Hex.decode(scale_bytes).value
133
- result[:docs] = Scale::Types.type_of("Vec<String>").decode(scale_bytes).value.map(&:value)
133
+ result[:documentation] = Scale::Types.type_of("Vec<String>").decode(scale_bytes).value.map(&:value)
134
134
 
135
135
  MetadataV7ModuleStorageEntry.new(result)
136
136
  end
@@ -143,7 +143,7 @@ module Scale
143
143
  name: String.decode(scale_bytes).value,
144
144
  type: String.decode(scale_bytes).value, # convert
145
145
  value: Hex.decode(scale_bytes).value,
146
- docs: Scale::Types.type_of("Vec<String>").decode(scale_bytes).value.map(&:value)
146
+ documentation: Scale::Types.type_of("Vec<String>").decode(scale_bytes).value.map(&:value)
147
147
  }
148
148
  MetadataV7ModuleConstants.new result
149
149
  end
@@ -37,7 +37,7 @@ module Scale
37
37
 
38
38
  if m[:events]
39
39
  m[:events].each_with_index do |event, index|
40
- event[:lookup] = "%02x%02x" % [call_module_index, index]
40
+ event[:lookup] = "%02x%02x" % [event_module_index, index]
41
41
  result.event_index[event[:lookup]] = [m, event]
42
42
  end
43
43
  event_module_index += 1
@@ -88,7 +88,7 @@ module Scale
88
88
  def self.decode(scale_bytes)
89
89
  result = {
90
90
  name: String.decode(scale_bytes).value,
91
- docs: Scale::Types.type_of("Vec<String>").decode(scale_bytes).value.map(&:value)
91
+ documentation: Scale::Types.type_of("Vec<String>").decode(scale_bytes).value.map(&:value)
92
92
  }
93
93
 
94
94
  MetadataModuleError.new(result)
@@ -37,7 +37,7 @@ module Scale
37
37
 
38
38
  if m[:events]
39
39
  m[:events].each_with_index do |event, index|
40
- event[:lookup] = "%02x%02x" % [call_module_index, index]
40
+ event[:lookup] = "%02x%02x" % [event_module_index, index]
41
41
  result.event_index[event[:lookup]] = [m, event]
42
42
  end
43
43
  event_module_index += 1
@@ -29,89 +29,78 @@ module Scale
29
29
 
30
30
  class TypeRegistry
31
31
  include Singleton
32
- attr_accessor :types
32
+ attr_reader :spec_name, :types, :versioning, :custom_types
33
+ attr_accessor :spec_version
34
+ attr_accessor :metadata
33
35
 
34
- def load(spec_name = nil, spec_version = nil)
35
- @spec_name = spec_name
36
- @spec_version = spec_version
37
- @types = load_types(spec_name, spec_version.nil? ? nil : spec_version.to_i)
36
+ def load(spec_name: nil, custom_types: nil)
37
+ @spec_name = nil
38
+ @types = nil
39
+ @versioning = nil
40
+ @custom_types = nil
38
41
 
42
+ default_types, _, _ = load_chain_spec_types("default")
43
+
44
+ if spec_name.nil? || spec_name == "default"
45
+ @spec_name = "default"
46
+ @types = default_types
47
+ else
48
+ @spec_name = spec_name
49
+ spec_types, @versioning, @spec_version = load_chain_spec_types(spec_name)
50
+ @types = default_types.merge(spec_types)
51
+ end
52
+
53
+ self.custom_types = custom_types
39
54
  true
40
55
  end
41
56
 
42
57
  def get(type_name)
43
- type = @types[type_name]
44
- return Scale::Types.type_of(type_name) if type.nil?
45
- type
46
- end
58
+ raise "Types not loaded" if @types.nil?
47
59
 
48
- private
49
- def load_types(spec_name, spec_version)
50
- # hard coded types
51
- coded_types = Scale::Types
52
- .constants
53
- .select { |c| Scale::Types.const_get(c).is_a? Class }
54
- .map { |type_name| [type_name.to_s, type_name.to_s] }
55
- .to_h
56
- .transform_values {|type| Scale::Types.constantize(type) }
57
-
58
- return coded_types if spec_name.nil?
59
-
60
- # default spec types
61
- default_types = load_chain_spec_types("default", spec_version).transform_values do |type|
62
- Scale::Types.type_convert(type, coded_types)
63
- end
64
- default_types = coded_types.merge(default_types)
60
+ all_types = {}.merge(@types)
65
61
 
66
- # chain spec types
67
- if spec_name != "default"
68
- spec_types = load_chain_spec_types(spec_name, spec_version)
69
- spec_types.transform_values do |type|
70
- Scale::Types.type_convert(type, default_types)
62
+ if @spec_version && @versioning
63
+ @versioning.each do |item|
64
+ if @spec_version >= item["runtime_range"][0] && @spec_version <= (item["runtime_range"][1] || 1073741823)
65
+ all_types.merge!(item["types"])
66
+ end
71
67
  end
72
- default_types.merge(spec_types)
73
- else
74
- default_types
75
68
  end
69
+
70
+ all_types.merge!(@custom_types) if @custom_types
71
+
72
+ type = type_traverse(type_name, all_types)
73
+
74
+ Scale::Types.constantize(type)
76
75
  end
77
76
 
78
- def load_chain_spec_types(spec_name, spec_version)
79
- file = File.join File.expand_path("../..", __FILE__), "lib", "type_registry", "#{spec_name}.json"
80
- json_string = File.open(file).read
81
- json = JSON.parse(json_string)
77
+ def custom_types=(custom_types)
78
+ @custom_types = custom_types.stringify_keys if (not custom_types.nil?) && custom_types.class.name == "Hash"
79
+ end
82
80
 
83
- types = {}
84
- runtime_id = json["runtime_id"]
85
- versioning = json["versioning"] || []
81
+ private
86
82
 
87
- if runtime_id.nil? || (spec_version && spec_version >= runtime_id)
88
- types = json["types"]
89
- end
83
+ def load_chain_spec_types(spec_name)
84
+ file = File.join File.expand_path("../..", __FILE__), "lib", "type_registry", "#{spec_name}.json"
85
+ json_string = File.open(file).read
86
+ json = JSON.parse(json_string)
90
87
 
91
- if spec_version
92
- versioning.each do |item|
93
- if spec_version >= item["runtime_range"][0] && spec_version <= (item["runtime_range"][1] || 1073741823)
94
- types.merge!(item["types"])
95
- end
96
- end
88
+ runtime_id = json["runtime_id"]
89
+
90
+ [json["types"], json["versioning"], runtime_id]
97
91
  end
98
92
 
99
- types.transform_values! do |type|
100
- if type.class != ::String
101
- Scale::Types.constantize(type)
93
+ def type_traverse(type, types)
94
+ if types.has_key?(type) && types[type] != type
95
+ type_traverse(types[type], types)
102
96
  else
103
- t = Scale::Types.type_convert(type, types)
104
- if t.class == ::String
105
- Scale::Types.constantize(t)
97
+ if type.class == ::String
98
+ rename(type)
106
99
  else
107
- t
100
+ type
108
101
  end
109
102
  end
110
103
  end
111
-
112
- types
113
- end
114
-
115
104
  end
116
105
 
117
106
  # TODO: == implement
@@ -227,7 +216,6 @@ module Scale
227
216
  end
228
217
 
229
218
  def self.get(type_name)
230
- type_name = adjust(type_name)
231
219
  TypeRegistry.instance.get(type_name)
232
220
  end
233
221
 
@@ -247,19 +235,6 @@ module Scale
247
235
  end
248
236
  end
249
237
 
250
- def self.type_convert(type, types)
251
- return type if type.class != ::String
252
-
253
- if type =~ /\[u\d+; \d+\]/
254
- byte_length = type.scan(/\[u\d+; (\d+)\]/).first.first
255
- "VecU8Length#{byte_length}"
256
- elsif types.has_key?(type) && types[type] != type
257
- type_convert(types[type], types)
258
- else
259
- adjust(type)
260
- end
261
- end
262
-
263
238
  def self.type_of(type_string, values = nil)
264
239
  if type_string.end_with?(">")
265
240
  type_strs = type_string.scan(/^([^<]*)<(.+)>$/).first
@@ -274,7 +249,7 @@ module Scale
274
249
  name = "#{type_str}_Of_#{inner_type_str.camelize}_#{klass.object_id}"
275
250
  Scale::Types.const_set fix(name), klass
276
251
  else
277
- raise "#{type_str} not support inner type"
252
+ raise "#{type_str} not support inner type: #{type_string}"
278
253
  end
279
254
  elsif type_string.start_with?("(") && type_string.end_with?(")") # tuple
280
255
  # TODO: add nested tuple support
@@ -345,13 +320,14 @@ def fix(name)
345
320
  .gsub(":", "։")
346
321
  end
347
322
 
348
- def adjust(type)
323
+ def rename(type)
349
324
  type = type.gsub("T::", "")
350
325
  .gsub("<T>", "")
351
326
  .gsub("<T as Trait>::", "")
352
327
  .delete("\n")
353
328
  .gsub("EventRecord<Event, Hash>", "EventRecord")
354
329
  .gsub(/(u)(\d+)/, 'U\2')
330
+ return "Bool" if type == "bool"
355
331
  return "Null" if type == "()"
356
332
  return "String" if type == "Vec<u8>"
357
333
  return "Compact" if type == "Compact<u32>" || type == "Compact<U32>"
@@ -360,9 +336,17 @@ def adjust(type)
360
336
  return "Compact" if type == "<Balance as HasCompact>::Type"
361
337
  return "Compact" if type == "<BlockNumber as HasCompact>::Type"
362
338
  return "Compact" if type == "Compact<Balance>"
339
+ return "Compact" if type == "Compact<BlockNumber>"
363
340
  return "CompactMoment" if type == "<Moment as HasCompact>::Type"
341
+ return "CompactMoment" if type == "Compact<Moment>"
364
342
  return "InherentOfflineReport" if type == "<InherentOfflineReport as InherentOfflineReport>::Inherent"
365
343
  return "AccountData" if type == "AccountData<Balance>"
344
+
345
+ if type =~ /\[U\d+; \d+\]/
346
+ byte_length = type.scan(/\[U\d+; (\d+)\]/).first.first
347
+ return "VecU8Length#{byte_length}"
348
+ end
349
+
366
350
  type
367
351
  end
368
352
 
@@ -395,3 +379,19 @@ class Integer
395
379
  self
396
380
  end
397
381
  end
382
+
383
+ class ::Hash
384
+ # via https://stackoverflow.com/a/25835016/2257038
385
+ def stringify_keys
386
+ h = self.map do |k,v|
387
+ v_str = if v.instance_of? Hash
388
+ v.stringify_keys
389
+ else
390
+ v
391
+ end
392
+
393
+ [k.to_s, v_str]
394
+ end
395
+ Hash[h]
396
+ end
397
+ end
@@ -11,6 +11,28 @@ module Scale
11
11
  def ==(other)
12
12
  value == other.value
13
13
  end
14
+
15
+ def to_human
16
+ if @value.class == ::Hash
17
+ @value.transform_values do |v|
18
+ if v.class.included_modules.include?(SingleValue)
19
+ v.to_human
20
+ else
21
+ v
22
+ end
23
+ end
24
+ elsif @value.class == ::Array
25
+ @value.map do |v|
26
+ if v.class.included_modules.include?(SingleValue)
27
+ v.to_human
28
+ else
29
+ v
30
+ end
31
+ end
32
+ else
33
+ @value
34
+ end
35
+ end
14
36
  end
15
37
 
16
38
  # value: one of nil, false, true, scale object
@@ -67,9 +89,8 @@ module Scale
67
89
 
68
90
  module ClassMethods
69
91
  def decode(scale_bytes)
70
- bit_length = to_s[15..].to_i
71
- byte_length = bit_length / 8
72
- bytes = scale_bytes.get_next_bytes byte_length
92
+ bytes = scale_bytes.get_next_bytes self::BYTE_LENGTH
93
+ bit_length = bytes.length.to_i * 8
73
94
  value = bytes.reverse.bytes_to_hex.to_i(16).to_signed(bit_length)
74
95
  new(value)
75
96
  end
@@ -83,7 +104,7 @@ module Scale
83
104
  if value.class != ::Integer
84
105
  raise "#{self.class}'s value must be integer"
85
106
  end
86
- bit_length = self.class.name[15..].to_i
107
+ bit_length = self.class::BYTE_LENGTH * 8
87
108
  hex = value.to_unsigned(bit_length).to_s(16).hex_to_bytes.reverse.bytes_to_hex
88
109
  hex[2..]
89
110
  end
@@ -111,19 +132,20 @@ module Scale
111
132
  if value.class != ::Integer
112
133
  raise "#{self.class}'s value must be integer"
113
134
  end
114
- bytes = value.to_s(16).rjust(self.class::BYTE_LENGTH * 2, "0").scan(/.{2}/).reverse.map {|hex| hex.to_i(16) }
135
+ byte_length = self.class::BYTE_LENGTH
136
+ bytes = value.to_s(16).rjust(byte_length * 2, "0").scan(/.{2}/).reverse.map {|hex| hex.to_i(16) }
115
137
  bytes.bytes_to_hex[2..]
116
138
  end
117
139
  end
118
140
 
119
-
120
141
  module Struct
121
142
  include SingleValue
122
143
  # new(1.to_u32, U32(69))
123
144
  module ClassMethods
124
145
  def decode(scale_bytes)
125
146
  item_values = self::ITEM_TYPE_STRS.map do |item_type_str|
126
- Scale::Types.get(item_type_str).decode(scale_bytes)
147
+ type = Scale::TypeRegistry.instance.get(item_type_str)
148
+ type.decode(scale_bytes)
127
149
  end
128
150
 
129
151
  value = {}
@@ -197,7 +219,7 @@ module Scale
197
219
  module ClassMethods
198
220
  def decode(scale_bytes)
199
221
  index = scale_bytes.get_next_bytes(1)[0]
200
- if const_defined? "ITEM_NAMES"
222
+ if const_defined? "ITEM_TYPE_STRS"
201
223
  item_type_str = self::ITEM_TYPE_STRS[index]
202
224
  raise "There is no such member with index #{index} for enum #{self}" if item_type_str.nil?
203
225
  value = Scale::Types.get(item_type_str).decode(scale_bytes)
@@ -208,16 +230,20 @@ module Scale
208
230
  end
209
231
 
210
232
  def items(items)
211
- attr_names = []
212
- attr_type_strs = []
233
+ if items.class == ::Hash
234
+ attr_names = []
235
+ attr_type_strs = []
213
236
 
214
- items.each_pair do |attr_name, attr_type_str|
215
- attr_names << attr_name
216
- attr_type_strs << attr_type_str
217
- end
237
+ items.each_pair do |attr_name, attr_type_str|
238
+ attr_names << attr_name
239
+ attr_type_strs << attr_type_str
240
+ end
218
241
 
219
- const_set(:ITEM_NAMES, attr_names)
220
- const_set(:ITEM_TYPE_STRS, attr_type_strs)
242
+ const_set(:ITEM_NAMES, attr_names)
243
+ const_set(:ITEM_TYPE_STRS, attr_type_strs)
244
+ elsif items.class == ::Array
245
+ const_set(:ITEM_TYPE_STRS, items)
246
+ end
221
247
  end
222
248
 
223
249
  def values(*values)
@@ -238,6 +264,14 @@ module Scale
238
264
  self.class::VALUES.index(value).to_s(16).rjust(2, "0")
239
265
  end
240
266
  end
267
+
268
+ def to_human
269
+ if self.class.const_defined? "ITEM_TYPE_STRS"
270
+ @value.to_human
271
+ else
272
+ @value
273
+ end
274
+ end
241
275
  end
242
276
 
243
277
  module Vec
@@ -248,7 +282,8 @@ module Scale
248
282
  number = Scale::Types::Compact.decode(scale_bytes).value
249
283
  items = []
250
284
  number.times do
251
- item = Scale::Types.get(self::INNER_TYPE_STR).decode(scale_bytes)
285
+ type = Scale::Types.get(self::INNER_TYPE_STR)
286
+ item = type.decode(scale_bytes)
252
287
  items << item
253
288
  end
254
289
  raw ? items : new(items)
@@ -278,7 +313,7 @@ module Scale
278
313
 
279
314
  module ClassMethods
280
315
  def decode(scale_bytes)
281
- value = "Scale::Types::U#{self::BYTES_LENGTH * 8}".constantize.decode(scale_bytes).value
316
+ value = "Scale::Types::U#{self::BYTE_LENGTH * 8}".constantize.decode(scale_bytes).value
282
317
  return new [] unless value || value <= 0
283
318
 
284
319
  result = self::ITEMS.select { |_, mask| value & mask > 0 }.keys
@@ -295,7 +330,7 @@ module Scale
295
330
  def items(items, bytes_length = 1)
296
331
  raise "byte length is wrong: #{bytes_length}" unless [1, 2, 4, 8, 16].include?(bytes_length)
297
332
  const_set(:ITEMS, items)
298
- const_set(:BYTES_LENGTH, bytes_length)
333
+ const_set(:BYTE_LENGTH, bytes_length)
299
334
  end
300
335
  end
301
336
 
@@ -305,7 +340,7 @@ module Scale
305
340
 
306
341
  def encode
307
342
  value = self.class::ITEMS.select { |key, _| self.value.include?(key) }.values.sum
308
- "Scale::Types::U#{self.class::BYTES_LENGTH * 8}".constantize.new(value).encode
343
+ "Scale::Types::U#{self.class::BYTE_LENGTH * 8}".constantize.new(value).encode
309
344
  end
310
345
  end
311
346