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.
- checksums.yaml +4 -4
- data/.DS_Store +0 -0
- data/.dockerignore +11 -0
- data/Dockerfile +9 -6
- data/Gemfile.lock +7 -7
- data/README.md +8 -5
- data/lib/metadata/metadata.rb +33 -28
- data/lib/metadata/metadata_v0.rb +3 -3
- data/lib/metadata/metadata_v1.rb +8 -8
- data/lib/metadata/metadata_v10.rb +1 -1
- data/lib/metadata/metadata_v11.rb +1 -1
- data/lib/metadata/metadata_v2.rb +1 -1
- data/lib/metadata/metadata_v3.rb +1 -1
- data/lib/metadata/metadata_v4.rb +7 -7
- data/lib/metadata/metadata_v5.rb +7 -7
- data/lib/metadata/metadata_v6.rb +2 -2
- data/lib/metadata/metadata_v7.rb +9 -9
- data/lib/metadata/metadata_v8.rb +2 -2
- data/lib/metadata/metadata_v9.rb +1 -1
- data/lib/scale.rb +77 -77
- data/lib/scale/base.rb +55 -20
- data/lib/scale/block.rb +120 -7
- data/lib/scale/types.rb +25 -1
- data/lib/scale/version.rb +1 -1
- data/lib/type_registry/certifybook-chain.json +10 -0
- data/lib/type_registry/darwinia.json +7 -0
- data/lib/type_registry/default.json +3713 -290
- data/lib/type_registry/kulupu.json +11 -2
- data/lib/type_registry/kusama.json +160 -18
- data/lib/type_registry/polkadot.json +85 -0
- data/lib/type_registry/westend.json +48 -3
- data/scripts/block_events.rb +34 -0
- data/scripts/example.rb +4 -0
- metadata +7 -2
data/lib/metadata/metadata_v7.rb
CHANGED
@@ -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" % [
|
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:
|
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:
|
116
|
-
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:
|
125
|
-
key2:
|
126
|
-
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[:
|
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
|
-
|
146
|
+
documentation: Scale::Types.type_of("Vec<String>").decode(scale_bytes).value.map(&:value)
|
147
147
|
}
|
148
148
|
MetadataV7ModuleConstants.new result
|
149
149
|
end
|
data/lib/metadata/metadata_v8.rb
CHANGED
@@ -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" % [
|
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
|
-
|
91
|
+
documentation: Scale::Types.type_of("Vec<String>").decode(scale_bytes).value.map(&:value)
|
92
92
|
}
|
93
93
|
|
94
94
|
MetadataModuleError.new(result)
|
data/lib/metadata/metadata_v9.rb
CHANGED
@@ -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" % [
|
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
|
data/lib/scale.rb
CHANGED
@@ -29,89 +29,78 @@ module Scale
|
|
29
29
|
|
30
30
|
class TypeRegistry
|
31
31
|
include Singleton
|
32
|
-
|
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
|
35
|
-
@spec_name =
|
36
|
-
@
|
37
|
-
@
|
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
|
-
|
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
|
-
|
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
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
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
|
79
|
-
|
80
|
-
|
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
|
-
|
84
|
-
runtime_id = json["runtime_id"]
|
85
|
-
versioning = json["versioning"] || []
|
81
|
+
private
|
86
82
|
|
87
|
-
|
88
|
-
|
89
|
-
|
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
|
-
|
92
|
-
|
93
|
-
|
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
|
-
|
100
|
-
if type
|
101
|
-
|
93
|
+
def type_traverse(type, types)
|
94
|
+
if types.has_key?(type)
|
95
|
+
type_traverse(types[type], types)
|
102
96
|
else
|
103
|
-
|
104
|
-
|
105
|
-
Scale::Types.constantize(t)
|
97
|
+
if type.class == ::String
|
98
|
+
rename(type)
|
106
99
|
else
|
107
|
-
|
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
|
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
|
data/lib/scale/base.rb
CHANGED
@@ -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
|
-
|
71
|
-
|
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
|
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
|
-
|
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::
|
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? "
|
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
|
-
|
212
|
-
|
233
|
+
if items.class == ::Hash
|
234
|
+
attr_names = []
|
235
|
+
attr_type_strs = []
|
213
236
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
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
|
-
|
220
|
-
|
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
|
-
|
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::
|
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(:
|
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::
|
343
|
+
"Scale::Types::U#{self.class::BYTE_LENGTH * 8}".constantize.new(value).encode
|
309
344
|
end
|
310
345
|
end
|
311
346
|
|