scale.rb 0.2.3 → 0.2.8
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 +10 -10
- 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 +7 -7
- data/lib/metadata/metadata_v12.rb +87 -0
- data/lib/metadata/metadata_v4.rb +6 -6
- data/lib/metadata/metadata_v5.rb +6 -6
- data/lib/metadata/metadata_v6.rb +1 -1
- data/lib/metadata/metadata_v7.rb +8 -8
- data/lib/metadata/metadata_v8.rb +1 -1
- data/lib/scale.rb +78 -77
- data/lib/scale/base.rb +55 -20
- data/lib/scale/block.rb +102 -19
- data/lib/scale/types.rb +25 -1
- data/lib/scale/version.rb +1 -1
- 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/scale.gemspec +1 -1
- data/scripts/block_events.rb +34 -0
- data/scripts/example.rb +4 -0
- metadata +9 -4
data/lib/metadata/metadata_v5.rb
CHANGED
@@ -92,14 +92,14 @@ module Scale
|
|
92
92
|
storage_function_type = Scale::Types.type_of("Enum", %w[Plain Map DoubleMap]).decode(scale_bytes).value
|
93
93
|
if storage_function_type == "Plain"
|
94
94
|
result[:type] = {
|
95
|
-
Plain:
|
95
|
+
Plain: String.decode(scale_bytes).value
|
96
96
|
}
|
97
97
|
elsif storage_function_type == "Map"
|
98
98
|
result[:type] = {
|
99
99
|
Map: {
|
100
100
|
hasher: StorageHasher.decode(scale_bytes).value,
|
101
|
-
key:
|
102
|
-
value:
|
101
|
+
key: String.decode(scale_bytes).value,
|
102
|
+
value: String.decode(scale_bytes).value,
|
103
103
|
linked: Bool.decode(scale_bytes).value
|
104
104
|
}
|
105
105
|
}
|
@@ -107,9 +107,9 @@ module Scale
|
|
107
107
|
result[:type] = {
|
108
108
|
DoubleMap: {
|
109
109
|
hasher: StorageHasher.decode(scale_bytes).value,
|
110
|
-
key1:
|
111
|
-
key2:
|
112
|
-
value:
|
110
|
+
key1: String.decode(scale_bytes).value,
|
111
|
+
key2: String.decode(scale_bytes).value,
|
112
|
+
value: String.decode(scale_bytes).value,
|
113
113
|
key2Hasher: StorageHasher.decode(scale_bytes).value
|
114
114
|
}
|
115
115
|
}
|
data/lib/metadata/metadata_v6.rb
CHANGED
@@ -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
|
-
|
95
|
+
documentation: Scale::Types.type_of("Vec<String>").decode(scale_bytes).value.map(&:value)
|
96
96
|
}
|
97
97
|
MetadataV6ModuleConstants.new result
|
98
98
|
end
|
data/lib/metadata/metadata_v7.rb
CHANGED
@@ -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
@@ -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/scale.rb
CHANGED
@@ -23,95 +23,85 @@ require "metadata/metadata_v8"
|
|
23
23
|
require "metadata/metadata_v9"
|
24
24
|
require "metadata/metadata_v10"
|
25
25
|
require "metadata/metadata_v11"
|
26
|
+
require "metadata/metadata_v12"
|
26
27
|
|
27
28
|
module Scale
|
28
29
|
class Error < StandardError; end
|
29
30
|
|
30
31
|
class TypeRegistry
|
31
32
|
include Singleton
|
32
|
-
|
33
|
+
attr_reader :spec_name, :types, :versioning, :custom_types
|
34
|
+
attr_accessor :spec_version
|
35
|
+
attr_accessor :metadata
|
33
36
|
|
34
|
-
def load(spec_name
|
35
|
-
@spec_name =
|
36
|
-
@
|
37
|
-
@
|
37
|
+
def load(spec_name: nil, custom_types: nil)
|
38
|
+
@spec_name = nil
|
39
|
+
@types = nil
|
40
|
+
@versioning = nil
|
41
|
+
@custom_types = nil
|
38
42
|
|
43
|
+
default_types, _, _ = load_chain_spec_types("default")
|
44
|
+
|
45
|
+
if spec_name.nil? || spec_name == "default"
|
46
|
+
@spec_name = "default"
|
47
|
+
@types = default_types
|
48
|
+
else
|
49
|
+
@spec_name = spec_name
|
50
|
+
spec_types, @versioning, @spec_version = load_chain_spec_types(spec_name)
|
51
|
+
@types = default_types.merge(spec_types)
|
52
|
+
end
|
53
|
+
|
54
|
+
self.custom_types = custom_types
|
39
55
|
true
|
40
56
|
end
|
41
57
|
|
42
58
|
def get(type_name)
|
43
|
-
|
44
|
-
return Scale::Types.type_of(type_name) if type.nil?
|
45
|
-
type
|
46
|
-
end
|
59
|
+
raise "Types not loaded" if @types.nil?
|
47
60
|
|
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)
|
61
|
+
all_types = {}.merge(@types)
|
65
62
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
63
|
+
if @spec_version && @versioning
|
64
|
+
@versioning.each do |item|
|
65
|
+
if @spec_version >= item["runtime_range"][0] && @spec_version <= (item["runtime_range"][1] || 1073741823)
|
66
|
+
all_types.merge!(item["types"])
|
67
|
+
end
|
71
68
|
end
|
72
|
-
default_types.merge(spec_types)
|
73
|
-
else
|
74
|
-
default_types
|
75
69
|
end
|
70
|
+
|
71
|
+
all_types.merge!(@custom_types) if @custom_types
|
72
|
+
|
73
|
+
type = type_traverse(type_name, all_types)
|
74
|
+
|
75
|
+
Scale::Types.constantize(type)
|
76
76
|
end
|
77
77
|
|
78
|
-
def
|
79
|
-
|
80
|
-
|
81
|
-
json = JSON.parse(json_string)
|
78
|
+
def custom_types=(custom_types)
|
79
|
+
@custom_types = custom_types.stringify_keys if (not custom_types.nil?) && custom_types.class.name == "Hash"
|
80
|
+
end
|
82
81
|
|
83
|
-
|
84
|
-
runtime_id = json["runtime_id"]
|
85
|
-
versioning = json["versioning"] || []
|
82
|
+
private
|
86
83
|
|
87
|
-
|
88
|
-
|
89
|
-
|
84
|
+
def load_chain_spec_types(spec_name)
|
85
|
+
file = File.join File.expand_path("../..", __FILE__), "lib", "type_registry", "#{spec_name}.json"
|
86
|
+
json_string = File.open(file).read
|
87
|
+
json = JSON.parse(json_string)
|
90
88
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
types.merge!(item["types"])
|
95
|
-
end
|
96
|
-
end
|
89
|
+
runtime_id = json["runtime_id"]
|
90
|
+
|
91
|
+
[json["types"], json["versioning"], runtime_id]
|
97
92
|
end
|
98
93
|
|
99
|
-
|
100
|
-
if type
|
101
|
-
|
94
|
+
def type_traverse(type, types)
|
95
|
+
if types.has_key?(type) && types[type] != type
|
96
|
+
type_traverse(types[type], types)
|
102
97
|
else
|
103
|
-
|
104
|
-
|
105
|
-
Scale::Types.constantize(t)
|
98
|
+
if type.class == ::String
|
99
|
+
rename(type)
|
106
100
|
else
|
107
|
-
|
101
|
+
type
|
108
102
|
end
|
109
103
|
end
|
110
104
|
end
|
111
|
-
|
112
|
-
types
|
113
|
-
end
|
114
|
-
|
115
105
|
end
|
116
106
|
|
117
107
|
# TODO: == implement
|
@@ -227,7 +217,6 @@ module Scale
|
|
227
217
|
end
|
228
218
|
|
229
219
|
def self.get(type_name)
|
230
|
-
type_name = adjust(type_name)
|
231
220
|
TypeRegistry.instance.get(type_name)
|
232
221
|
end
|
233
222
|
|
@@ -247,19 +236,6 @@ module Scale
|
|
247
236
|
end
|
248
237
|
end
|
249
238
|
|
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
239
|
def self.type_of(type_string, values = nil)
|
264
240
|
if type_string.end_with?(">")
|
265
241
|
type_strs = type_string.scan(/^([^<]*)<(.+)>$/).first
|
@@ -274,7 +250,7 @@ module Scale
|
|
274
250
|
name = "#{type_str}_Of_#{inner_type_str.camelize}_#{klass.object_id}"
|
275
251
|
Scale::Types.const_set fix(name), klass
|
276
252
|
else
|
277
|
-
raise "#{type_str} not support inner type"
|
253
|
+
raise "#{type_str} not support inner type: #{type_string}"
|
278
254
|
end
|
279
255
|
elsif type_string.start_with?("(") && type_string.end_with?(")") # tuple
|
280
256
|
# TODO: add nested tuple support
|
@@ -345,13 +321,14 @@ def fix(name)
|
|
345
321
|
.gsub(":", "։")
|
346
322
|
end
|
347
323
|
|
348
|
-
def
|
324
|
+
def rename(type)
|
349
325
|
type = type.gsub("T::", "")
|
350
326
|
.gsub("<T>", "")
|
351
327
|
.gsub("<T as Trait>::", "")
|
352
328
|
.delete("\n")
|
353
329
|
.gsub("EventRecord<Event, Hash>", "EventRecord")
|
354
330
|
.gsub(/(u)(\d+)/, 'U\2')
|
331
|
+
return "Bool" if type == "bool"
|
355
332
|
return "Null" if type == "()"
|
356
333
|
return "String" if type == "Vec<u8>"
|
357
334
|
return "Compact" if type == "Compact<u32>" || type == "Compact<U32>"
|
@@ -360,9 +337,17 @@ def adjust(type)
|
|
360
337
|
return "Compact" if type == "<Balance as HasCompact>::Type"
|
361
338
|
return "Compact" if type == "<BlockNumber as HasCompact>::Type"
|
362
339
|
return "Compact" if type == "Compact<Balance>"
|
340
|
+
return "Compact" if type == "Compact<BlockNumber>"
|
363
341
|
return "CompactMoment" if type == "<Moment as HasCompact>::Type"
|
342
|
+
return "CompactMoment" if type == "Compact<Moment>"
|
364
343
|
return "InherentOfflineReport" if type == "<InherentOfflineReport as InherentOfflineReport>::Inherent"
|
365
344
|
return "AccountData" if type == "AccountData<Balance>"
|
345
|
+
|
346
|
+
if type =~ /\[U\d+; \d+\]/
|
347
|
+
byte_length = type.scan(/\[U\d+; (\d+)\]/).first.first
|
348
|
+
return "VecU8Length#{byte_length}"
|
349
|
+
end
|
350
|
+
|
366
351
|
type
|
367
352
|
end
|
368
353
|
|
@@ -395,3 +380,19 @@ class Integer
|
|
395
380
|
self
|
396
381
|
end
|
397
382
|
end
|
383
|
+
|
384
|
+
class ::Hash
|
385
|
+
# via https://stackoverflow.com/a/25835016/2257038
|
386
|
+
def stringify_keys
|
387
|
+
h = self.map do |k,v|
|
388
|
+
v_str = if v.instance_of? Hash
|
389
|
+
v.stringify_keys
|
390
|
+
else
|
391
|
+
v
|
392
|
+
end
|
393
|
+
|
394
|
+
[k.to_s, v_str]
|
395
|
+
end
|
396
|
+
Hash[h]
|
397
|
+
end
|
398
|
+
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
|
|