scale.rb 0.2.1 → 0.2.6

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.
@@ -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)
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