scale.rb 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f8538580b5cc0d84add3684e3af10bbbba86bc741abb66bc5d38594c7de17894
4
- data.tar.gz: a652f2dd8b436840f8b4e004fdf3fe81c699200fb68a11ea2ca52ae4a3e64062
3
+ metadata.gz: b6c01e31f2e50407197c68df2d81da349d5471d52ddcb1b17c1a30fcd5706eae
4
+ data.tar.gz: 5618f3aa22bcf94dc40a12bb15508cbe6dff74441879ffccdd8f2d6f626de992
5
5
  SHA512:
6
- metadata.gz: a5a71617b20e22dc876b71414c6bdf78cfdc23b94444f010d902eb382bb8f26d92e06de9eedca805aca9ba408035a981a106fa1d944081a3426864d6351b6b58
7
- data.tar.gz: 8a65c9e78531472b74f93eb48da5c0e54c7b05430342467afa03ead952643cc41901a4a8f6b908ba6e3e8721b9aa26e6e426d6664ffb8ab93390e7c0febfd74c
6
+ metadata.gz: c00a8b437a13ea3a795ac1dbdc4bbeda4442400cb0a8153ab0bc07e980f5c921091b54afffe28392646aa3fede9c7b8b96d1d74d1e4fb3a9e3cf5de0419c1bca
7
+ data.tar.gz: c449932d536db154cd4b6e3bbb9163bb6083494d69066e52b3e3fb856bdcc44944e9d102835f1c702c024667a32ae8c1baa0719fc1d6e0815fc90dbbbf92b956
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- scale.rb (0.2.4)
4
+ scale.rb (0.2.5)
5
5
  activesupport (>= 4.0.0)
6
6
  json (~> 2.3.0)
7
7
  substrate_common.rb (~> 0.1.8)
data/README.md CHANGED
@@ -79,10 +79,13 @@ examples in `exec/scale`
79
79
  rspec
80
80
  ```
81
81
 
82
- To run only low level format tests, call
82
+ To run single test file:
83
83
 
84
- ```
85
- rspec spec/low_level_spec.rb
84
+ ```bash
85
+ rspec spec/types_spec.rb
86
+ rspec spec/extrinsic_spec.rb
87
+ rspec spec/metadata_spec.rb
88
+ rspec spec/types_ffi_spec.rb
86
89
  ```
87
90
 
88
91
 
@@ -5,21 +5,8 @@ module Scale
5
5
  attr_accessor :version
6
6
  def self.decode(scale_bytes)
7
7
  bytes = scale_bytes.get_next_bytes(4)
8
- if bytes.bytes_to_utf8 == 'meta'
9
- metadata_version = Scale::Types.type_of('Enum', [
10
- 'MetadataV0',
11
- 'MetadataV1',
12
- 'MetadataV2',
13
- 'MetadataV3',
14
- 'MetadataV4',
15
- 'MetadataV5',
16
- 'MetadataV6',
17
- 'MetadataV7',
18
- 'MetadataV8',
19
- 'MetadataV9',
20
- 'MetadataV10',
21
- 'MetadataV11'
22
- ]).decode(scale_bytes).value
8
+ if bytes.bytes_to_utf8 == "meta"
9
+ metadata_version = Scale::Types.type_of("Enum", %w[MetadataV0 MetadataV1 MetadataV2 MetadataV3 MetadataV4 MetadataV5 MetadataV6 MetadataV7 MetadataV8 MetadataV9 MetadataV10 MetadataV11]).decode(scale_bytes).value
23
10
  metadata = Metadata.new "Scale::Types::#{metadata_version}".constantize.decode(scale_bytes)
24
11
  metadata.version = metadata_version[9..].to_i
25
12
  else
@@ -30,6 +17,24 @@ module Scale
30
17
  end
31
18
  metadata
32
19
  end
20
+
21
+ def get_module(module_name)
22
+ modules = self.value.value[:metadata][:modules]
23
+ modules.each do |m|
24
+ if m[:name].downcase == module_name.downcase
25
+ return m
26
+ end
27
+ end
28
+ end
29
+
30
+ def get_module_call(module_name, call_name)
31
+ the_module = get_module(module_name)
32
+ the_module[:calls].each do |call|
33
+ if call[:name].downcase == call_name.downcase
34
+ return call
35
+ end
36
+ end
37
+ end
33
38
  end
34
39
 
35
40
  class MetadataModule
@@ -45,19 +50,19 @@ module Scale
45
50
 
46
51
  has_storage = Bool.decode(scale_bytes).value
47
52
  if has_storage
48
- storages = Scale::Types.type_of('Vec<MetadataModuleStorage>').decode(scale_bytes).value
53
+ storages = Scale::Types.type_of("Vec<MetadataModuleStorage>").decode(scale_bytes).value
49
54
  result[:storage] = storages.map(&:value)
50
55
  end
51
56
 
52
57
  has_calls = Bool.decode(scale_bytes).value
53
58
  if has_calls
54
- calls = Scale::Types.type_of('Vec<MetadataModuleCall>').decode(scale_bytes).value
59
+ calls = Scale::Types.type_of("Vec<MetadataModuleCall>").decode(scale_bytes).value
55
60
  result[:calls] = calls.map(&:value)
56
61
  end
57
62
 
58
63
  has_events = Bool.decode(scale_bytes).value
59
64
  if has_events
60
- events = Scale::Types.type_of('Vec<MetadataModuleEvent>').decode(scale_bytes).value
65
+ events = Scale::Types.type_of("Vec<MetadataModuleEvent>").decode(scale_bytes).value
61
66
  result[:events] = events.map(&:value)
62
67
  end
63
68
 
@@ -70,26 +75,26 @@ module Scale
70
75
  def self.decode(scale_bytes)
71
76
  result = {
72
77
  name: String.decode(scale_bytes).value,
73
- modifier: Scale::Types.type_of('Enum', %w[Optional Default]).decode(scale_bytes).value
78
+ modifier: Scale::Types.type_of("Enum", %w[Optional Default]).decode(scale_bytes).value
74
79
  }
75
80
 
76
81
  is_key_value = Bool.decode(scale_bytes).value
77
82
  result[:type] = if is_key_value
78
83
  {
79
84
  Map: {
80
- key: adjust(String.decode(scale_bytes).value),
81
- value: adjust(String.decode(scale_bytes).value),
85
+ key: rename(String.decode(scale_bytes).value),
86
+ value: rename(String.decode(scale_bytes).value),
82
87
  linked: Bool.decode(scale_bytes).value
83
88
  }
84
89
  }
85
90
  else
86
91
  {
87
- Plain: adjust(String.decode(scale_bytes).value)
92
+ Plain: rename(String.decode(scale_bytes).value)
88
93
  }
89
94
  end
90
95
 
91
96
  result[:fallback] = Hex.decode(scale_bytes).value
92
- result[:documentation] = Scale::Types.type_of('Vec<String>').decode(scale_bytes).value.map(&:value)
97
+ result[:documentation] = Scale::Types.type_of("Vec<String>").decode(scale_bytes).value.map(&:value)
93
98
 
94
99
  MetadataModuleStorage.new(result)
95
100
  end
@@ -100,8 +105,8 @@ module Scale
100
105
  def self.decode(scale_bytes)
101
106
  result = {}
102
107
  result[:name] = String.decode(scale_bytes).value
103
- result[:args] = Scale::Types.type_of('Vec<MetadataModuleCallArgument>').decode(scale_bytes).value.map(&:value)
104
- result[:documentation] = Scale::Types.type_of('Vec<String>').decode(scale_bytes).value.map(&:value)
108
+ result[:args] = Scale::Types.type_of("Vec<MetadataModuleCallArgument>").decode(scale_bytes).value.map(&:value)
109
+ result[:documentation] = Scale::Types.type_of("Vec<String>").decode(scale_bytes).value.map(&:value)
105
110
  MetadataModuleCall.new(result)
106
111
  end
107
112
  end
@@ -111,7 +116,7 @@ module Scale
111
116
  def self.decode(scale_bytes)
112
117
  result = {}
113
118
  result[:name] = String.decode(scale_bytes).value
114
- result[:type] = adjust(String.decode(scale_bytes).value)
119
+ result[:type] = rename(String.decode(scale_bytes).value)
115
120
 
116
121
  MetadataModuleCallArgument.new(result)
117
122
  end
@@ -122,8 +127,8 @@ module Scale
122
127
  def self.decode(scale_bytes)
123
128
  result = {}
124
129
  result[:name] = String.decode(scale_bytes).value
125
- result[:args] = Scale::Types.type_of('Vec<String>').decode(scale_bytes).value.map(&:value)
126
- result[:documentation] = Scale::Types.type_of('Vec<String>').decode(scale_bytes).value.map(&:value)
130
+ result[:args] = Scale::Types.type_of("Vec<String>").decode(scale_bytes).value.map(&:value)
131
+ result[:documentation] = Scale::Types.type_of("Vec<String>").decode(scale_bytes).value.map(&:value)
127
132
 
128
133
  MetadataModuleEvent.new(result)
129
134
  end
@@ -93,13 +93,13 @@ module Scale
93
93
  if is_key_value
94
94
  type = {
95
95
  MapType: {
96
- key: adjust(Bytes.decode(scale_bytes).value),
97
- value: adjust(Bytes.decode(scale_bytes).value)
96
+ key: rename(Bytes.decode(scale_bytes).value),
97
+ value: rename(Bytes.decode(scale_bytes).value)
98
98
  }
99
99
  }
100
100
  else
101
101
  type = {
102
- PlainType: adjust(Bytes.decode(scale_bytes).value)
102
+ PlainType: rename(Bytes.decode(scale_bytes).value)
103
103
  }
104
104
  end
105
105
 
@@ -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: adjust(String.decode(scale_bytes).value)
95
+ Plain: rename(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: adjust(String.decode(scale_bytes).value),
102
- value: adjust(String.decode(scale_bytes).value),
101
+ key: rename(String.decode(scale_bytes).value),
102
+ value: rename(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: adjust(String.decode(scale_bytes).value),
111
- key2: adjust(String.decode(scale_bytes).value),
112
- value: adjust(String.decode(scale_bytes).value),
110
+ key1: rename(String.decode(scale_bytes).value),
111
+ key2: rename(String.decode(scale_bytes).value),
112
+ value: rename(String.decode(scale_bytes).value),
113
113
  key2Hasher: StorageHasher.decode(scale_bytes).value
114
114
  }
115
115
  }
@@ -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: adjust(String.decode(scale_bytes).value)
95
+ Plain: rename(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: adjust(String.decode(scale_bytes).value),
102
- value: adjust(String.decode(scale_bytes).value),
101
+ key: rename(String.decode(scale_bytes).value),
102
+ value: rename(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: adjust(String.decode(scale_bytes).value),
111
- key2: adjust(String.decode(scale_bytes).value),
112
- value: adjust(String.decode(scale_bytes).value),
110
+ key1: rename(String.decode(scale_bytes).value),
111
+ key2: rename(String.decode(scale_bytes).value),
112
+ value: rename(String.decode(scale_bytes).value),
113
113
  key2Hasher: StorageHasher.decode(scale_bytes).value
114
114
  }
115
115
  }
@@ -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: rename(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: rename(String.decode(scale_bytes).value),
116
+ value: rename(String.decode(scale_bytes).value),
117
117
  linked: Bool.decode(scale_bytes).value
118
118
  }
119
119
  }
@@ -121,9 +121,9 @@ 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: rename(String.decode(scale_bytes).value),
125
+ key2: rename(String.decode(scale_bytes).value),
126
+ value: rename(String.decode(scale_bytes).value),
127
127
  key2Hasher: StorageHasher.decode(scale_bytes).value
128
128
  }
129
129
  }
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
- 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
 
data/lib/scale/block.rb CHANGED
@@ -9,7 +9,8 @@ module Scale
9
9
  Blake2b.hex data, Blake2b::Key.none, 32
10
10
  end
11
11
 
12
- def self.decode(scale_bytes, metadata)
12
+ def self.decode(scale_bytes)
13
+ metadata = Scale::TypeRegistry.instance.metadata
13
14
  result = {}
14
15
 
15
16
  extrinsic_length = Compact.decode(scale_bytes).value
@@ -83,11 +84,11 @@ module Scale
83
84
  result[:call_index] = scale_bytes.get_next_bytes(2).bytes_to_hex[2..]
84
85
 
85
86
  else
86
- raise "Extrinsics version #{version_info} is not implemented"
87
+ raise "Extrinsic version #{version_info} is not implemented"
87
88
  end
88
89
 
89
90
  if result[:call_index]
90
- call_module, call = metadata.value.call_index[result[:call_index]]
91
+ call_module, call = metadata.call_index[result[:call_index]]
91
92
 
92
93
  result[:call_function] = call[:name].downcase
93
94
  result[:call_module] = call_module[:name].downcase
@@ -97,7 +98,7 @@ module Scale
97
98
  result[:params] = call[:args].map do |arg|
98
99
  type = Scale::Types.get(arg[:type])
99
100
  arg_obj = type.decode(scale_bytes)
100
- {name: arg[:name], type: type.name, value: arg_obj.value, value_raw: "0x#{arg_obj.encode}" }
101
+ {name: arg[:name], type: arg[:type], scale_type: type, value: arg_obj.value }
101
102
  end
102
103
  end
103
104
 
@@ -107,24 +108,24 @@ module Scale
107
108
  Extrinsic.new result
108
109
  end
109
110
 
110
- def encode(metadata)
111
- puts metadata.value.value["modules"]
111
+ def encode
112
112
  result = "04" + self.value[:call_index]
113
113
 
114
- result = result +
115
- self.value[:params].map do |param|
116
- param[:type].constantize.new(param[:value]).encode
117
- end.join
114
+ result += self.value[:params].map do |param|
115
+ Scale::Types.get(param[:type]).new(param[:value]).encode
116
+ end.join
118
117
 
119
- result = "0x" + Compact.new(result.length / 2).encode + result
120
- return result
118
+ "0x" + Compact.new(result.length / 2).encode + result
119
+ end
120
+
121
+ def to_human
122
+ @value
121
123
  end
122
124
  end
123
125
 
124
126
  class EventRecord
125
127
  include SingleValue
126
128
 
127
- # 0x0c000000000000001027000001010000010000000400be07e2c28688db5368445c33d32b3c7bcad15dab1ec802ba8cccc1c22b86574f6992da89ff412eaf9bafac4024
128
129
  def self.decode(scale_bytes)
129
130
  metadata = Scale::TypeRegistry.instance.metadata
130
131
 
@@ -137,22 +138,72 @@ module Scale
137
138
 
138
139
  type = scale_bytes.get_next_bytes(2).bytes_to_hex[2..]
139
140
  event = metadata.event_index[type][1]
140
- mod = metadata.event_index[type][0]
141
+ # mod = metadata.event_index[type][0]
141
142
 
142
143
  result[:params] = []
143
144
  event[:args].each do |arg_type|
144
- value = Scale::Types.get(arg_type).decode(scale_bytes).value
145
+ value = Scale::Types.get(arg_type).decode(scale_bytes).to_human
145
146
  result[:params] << {
147
+ name: event[:name],
146
148
  type: arg_type,
147
149
  value: value
148
150
  }
149
151
  end
150
152
 
151
- result[:topics] = Scale::Types.get('Vec<Hash>').decode(scale_bytes).value.map(&:value)
153
+ result[:topics] = Scale::Types.get("Vec<Hash>").decode(scale_bytes).value.map(&:value)
152
154
 
153
155
  EventRecord.new(result)
154
156
  end
155
157
  end
156
158
 
159
+ # log
160
+ class Other < Bytes; end
161
+
162
+ class AuthoritiesChange
163
+ include Vec
164
+ inner_type "AccountId"
165
+ end
166
+
167
+ class ConsensusEngineId < VecU8Length4; end
168
+
169
+ class ChangesTrieRoot < Bytes; end
170
+
171
+ class SealV0
172
+ include Struct
173
+ items(
174
+ slot: "U64",
175
+ signature: "Signature"
176
+ )
177
+ end
178
+
179
+ class Consensus
180
+ include Struct
181
+ items(
182
+ engine: "ConsensusEngineId",
183
+ data: "Hex"
184
+ )
185
+ end
186
+
187
+ class Seal
188
+ include Struct
189
+ items(
190
+ engine: "ConsensusEngineId",
191
+ data: "Hex"
192
+ )
193
+ end
194
+
195
+ class PreRuntime
196
+ include Struct
197
+ items(
198
+ engine: "ConsensusEngineId",
199
+ data: "Hex"
200
+ )
201
+ end
202
+
203
+ class LogDigest
204
+ include Enum
205
+ items %w[Other AuthoritiesChange ChangesTrieRoot SealV0 Consensus Seal PreRuntime]
206
+ end
207
+
157
208
  end
158
209
  end
data/lib/scale/types.rb CHANGED
@@ -46,24 +46,34 @@ module Scale
46
46
  BYTE_LENGTH = 16
47
47
  end
48
48
 
49
+ class U256
50
+ include FixedWidthUInt
51
+ BYTE_LENGTH = 32
52
+ end
53
+
49
54
  class I8
50
55
  include FixedWidthInt
56
+ BYTE_LENGTH = 1
51
57
  end
52
58
 
53
59
  class I16
54
60
  include FixedWidthInt
61
+ BYTE_LENGTH = 2
55
62
  end
56
63
 
57
64
  class I32
58
65
  include FixedWidthInt
66
+ BYTE_LENGTH = 4
59
67
  end
60
68
 
61
69
  class I64
62
70
  include FixedWidthInt
71
+ BYTE_LENGTH = 8
63
72
  end
64
73
 
65
74
  class I128
66
75
  include FixedWidthInt
76
+ BYTE_LENGTH = 16
67
77
  end
68
78
 
69
79
  class Compact
@@ -303,7 +313,7 @@ module Scale
303
313
  value /= 1000
304
314
  end
305
315
 
306
- CompactMoment.new Time.at(seconds_since_epoch_integer).to_datetime
316
+ CompactMoment.new Time.at(value).to_datetime.strftime("%F %T")
307
317
  end
308
318
  end
309
319
 
@@ -791,5 +801,19 @@ module Scale
791
801
  )
792
802
  end
793
803
 
804
+ class VecH512Length2
805
+ include SingleValue
806
+
807
+ def self.decode(scale_bytes)
808
+ end
809
+
810
+ def encode
811
+ "0x" + self.value.map do |item|
812
+ item[2..]
813
+ end.join
814
+ end
815
+ end
816
+
817
+
794
818
  end
795
819
  end
data/lib/scale/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Scale
2
- VERSION = "0.2.4".freeze
2
+ VERSION = "0.2.5".freeze
3
3
  end
data/lib/scale.rb CHANGED
@@ -29,89 +29,65 @@ module Scale
29
29
 
30
30
  class TypeRegistry
31
31
  include Singleton
32
- attr_accessor :types, :metadata
32
+ attr_accessor :types, :versioning
33
+ attr_accessor :spec_version, :metadata
34
+ attr_accessor :custom_types
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
+ default_types, _ = load_chain_spec_types("default")
38
38
 
39
+ if spec_name.nil? || spec_name == "default"
40
+ @types = default_types
41
+ else
42
+ spec_types, @versioning = load_chain_spec_types(spec_name)
43
+ @types = default_types.merge(spec_types)
44
+ end
45
+
46
+ @custom_types = custom_types.stringify_keys if custom_types.nil? && custom_types.class.name == "Hash"
39
47
  true
40
48
  end
41
49
 
42
50
  def get(type_name)
43
- type = @types[type_name]
44
- return Scale::Types.type_of(type_name) if type.nil?
45
- type
46
- end
51
+ raise "Types not loaded" if @types.nil?
47
52
 
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)
53
+ all_types = {}.merge(@types)
65
54
 
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)
55
+ if @spec_version && @versioning
56
+ @versioning.each do |item|
57
+ if @spec_version >= item["runtime_range"][0] && @spec_version <= (item["runtime_range"][1] || 1073741823)
58
+ all_types.merge!(item["types"])
59
+ end
71
60
  end
72
- default_types.merge(spec_types)
73
- else
74
- default_types
75
61
  end
62
+
63
+ all_types.merge!(@custom_types) if @custom_types
64
+
65
+ type = type_traverse(type_name, all_types)
66
+
67
+ Scale::Types.constantize(type)
76
68
  end
77
69
 
78
- def load_chain_spec_types(spec_name, spec_version)
70
+ def load_chain_spec_types(spec_name)
79
71
  file = File.join File.expand_path("../..", __FILE__), "lib", "type_registry", "#{spec_name}.json"
80
72
  json_string = File.open(file).read
81
73
  json = JSON.parse(json_string)
82
74
 
83
- types = {}
84
75
  runtime_id = json["runtime_id"]
85
- versioning = json["versioning"] || []
86
-
87
- if runtime_id.nil? || (spec_version && spec_version >= runtime_id)
88
- types = json["types"]
89
- end
90
76
 
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
97
- end
77
+ [json["types"], json["versioning"]]
78
+ end
98
79
 
99
- types.transform_values! do |type|
100
- if type.class != ::String
101
- Scale::Types.constantize(type)
80
+ def type_traverse(type, types)
81
+ if types.has_key?(type)
82
+ type_traverse(types[type], types)
83
+ else
84
+ if type.class == ::String
85
+ rename(type)
102
86
  else
103
- t = Scale::Types.type_convert(type, types)
104
- if t.class == ::String
105
- Scale::Types.constantize(t)
106
- else
107
- t
108
- end
87
+ type
109
88
  end
110
89
  end
111
-
112
- types
113
90
  end
114
-
115
91
  end
116
92
 
117
93
  # TODO: == implement
@@ -227,7 +203,6 @@ module Scale
227
203
  end
228
204
 
229
205
  def self.get(type_name)
230
- type_name = adjust(type_name)
231
206
  TypeRegistry.instance.get(type_name)
232
207
  end
233
208
 
@@ -247,19 +222,6 @@ module Scale
247
222
  end
248
223
  end
249
224
 
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
225
  def self.type_of(type_string, values = nil)
264
226
  if type_string.end_with?(">")
265
227
  type_strs = type_string.scan(/^([^<]*)<(.+)>$/).first
@@ -274,7 +236,7 @@ module Scale
274
236
  name = "#{type_str}_Of_#{inner_type_str.camelize}_#{klass.object_id}"
275
237
  Scale::Types.const_set fix(name), klass
276
238
  else
277
- raise "#{type_str} not support inner type"
239
+ raise "#{type_str} not support inner type: #{type_string}"
278
240
  end
279
241
  elsif type_string.start_with?("(") && type_string.end_with?(")") # tuple
280
242
  # TODO: add nested tuple support
@@ -345,13 +307,14 @@ def fix(name)
345
307
  .gsub(":", "։")
346
308
  end
347
309
 
348
- def adjust(type)
310
+ def rename(type)
349
311
  type = type.gsub("T::", "")
350
312
  .gsub("<T>", "")
351
313
  .gsub("<T as Trait>::", "")
352
314
  .delete("\n")
353
315
  .gsub("EventRecord<Event, Hash>", "EventRecord")
354
316
  .gsub(/(u)(\d+)/, 'U\2')
317
+ return "Bool" if type == "bool"
355
318
  return "Null" if type == "()"
356
319
  return "String" if type == "Vec<u8>"
357
320
  return "Compact" if type == "Compact<u32>" || type == "Compact<U32>"
@@ -361,8 +324,15 @@ def adjust(type)
361
324
  return "Compact" if type == "<BlockNumber as HasCompact>::Type"
362
325
  return "Compact" if type == "Compact<Balance>"
363
326
  return "CompactMoment" if type == "<Moment as HasCompact>::Type"
327
+ return "CompactMoment" if type == "Compact<Moment>"
364
328
  return "InherentOfflineReport" if type == "<InherentOfflineReport as InherentOfflineReport>::Inherent"
365
329
  return "AccountData" if type == "AccountData<Balance>"
330
+
331
+ if type =~ /\[U\d+; \d+\]/
332
+ byte_length = type.scan(/\[U\d+; (\d+)\]/).first.first
333
+ return "VecU8Length#{byte_length}"
334
+ end
335
+
366
336
  type
367
337
  end
368
338
 
@@ -395,3 +365,19 @@ class Integer
395
365
  self
396
366
  end
397
367
  end
368
+
369
+ class ::Hash
370
+ # via https://stackoverflow.com/a/25835016/2257038
371
+ def stringify_keys
372
+ h = self.map do |k,v|
373
+ v_str = if v.instance_of? Hash
374
+ v.stringify_keys
375
+ else
376
+ v
377
+ end
378
+
379
+ [k.to_s, v_str]
380
+ end
381
+ Hash[h]
382
+ end
383
+ end
@@ -107,6 +107,13 @@
107
107
  ["ktoner", "TokenBalance"],
108
108
  ["lottery", "TokenBalance"]
109
109
  ]
110
+ },
111
+ "DoubleNodeWithMerkleProof": {
112
+ "type": "struct",
113
+ "type_mapping": [
114
+ ["dag_nodes", "VecH512Length2"],
115
+ ["proof", "Vec<H128>"]
116
+ ]
110
117
  }
111
118
  }
112
119
  }
@@ -35,13 +35,6 @@
35
35
  ["balance", "Balance"]
36
36
  ]
37
37
  },
38
- "ReferendumInfo<BlockNumber, Hash, Balance>": {
39
- "type": "enum",
40
- "type_mapping": [
41
- ["Ongoing", "ReferendumStatus"],
42
- ["Finished", "ReferendumInfoFinished"]
43
- ]
44
- },
45
38
  "ReferendumInfoFinished": {
46
39
  "type": "struct",
47
40
  "type_mapping": [
@@ -67,6 +60,13 @@
67
60
  ["tally", "Tally"]
68
61
  ]
69
62
  },
63
+ "ReferendumInfo": {
64
+ "type": "enum",
65
+ "type_mapping": [
66
+ ["Ongoing", "ReferendumStatus"],
67
+ ["Finished", "ReferendumInfoFinished"]
68
+ ]
69
+ },
70
70
  "VotingDirectVote": {
71
71
  "type": "struct",
72
72
  "type_mapping": [
@@ -247,7 +247,8 @@
247
247
  "type": "enum",
248
248
  "value_list": [
249
249
  "Normal",
250
- "Operational"
250
+ "Operational",
251
+ "Mandatory"
251
252
  ]
252
253
  },
253
254
  "DispatchInfo": {
@@ -338,6 +339,7 @@
338
339
  "MomentOf": "Moment",
339
340
  "MoreAttestations": "Null",
340
341
  "Multiplier": "u64",
342
+ "CallHash": "H256",
341
343
  "Timepoint": {
342
344
  "type": "struct",
343
345
  "type_mapping": [
@@ -364,7 +366,7 @@
364
366
  "PhantomData": "Null",
365
367
  "sp_std::marker::PhantomData<(AccountId, Event)>": "PhantomData",
366
368
  "Reporter": "AccountId",
367
- "OffenceDetails<AccountId, IdentificationTuple>": {
369
+ "OffenceDetails": {
368
370
  "type": "struct",
369
371
  "type_mapping": [
370
372
  ["offender", "Offender"],
@@ -543,17 +545,6 @@
543
545
  ]
544
546
  },
545
547
  "WinningData": "Vec<WinningDataEntry>",
546
- "WithdrawReasons": {
547
- "type": "set",
548
- "value_type": "u64",
549
- "value_list": {
550
- "TransactionPayment": 1,
551
- "Transfer": 2,
552
- "Reserve": 4,
553
- "Fee": 8,
554
- "Tip": 16
555
- }
556
- },
557
548
  "Index": "U32",
558
549
  "Kind": "[u8; 16]",
559
550
  "Nominations": {
@@ -583,7 +574,8 @@
583
574
  ["blockNumber", "BlockNumber"],
584
575
  ["networkState", "OpaqueNetworkState"],
585
576
  ["sessionIndex", "SessionIndex"],
586
- ["authorityIndex", "AuthIndex"]
577
+ ["authorityIndex", "AuthIndex"],
578
+ ["validatorsLen", "u32"]
587
579
  ]
588
580
  },
589
581
  "RewardDestination": {
@@ -837,6 +829,164 @@
837
829
  ["perBlock", "Balance"],
838
830
  ["startingBlock", "BlockNumber"]
839
831
  ]
832
+ },
833
+ "NominatorIndex": "u32",
834
+ "ValidatorIndex": "u16",
835
+ "PerU16": "u16",
836
+ "OffchainAccuracy": "PerU16",
837
+ "CompactScore": {
838
+ "type": "struct",
839
+ "type_mapping": [
840
+ ["validatorIndex", "ValidatorIndex"],
841
+ ["offchainAccuracy", "OffchainAccuracy"]
842
+ ]
843
+ },
844
+ "CompactAssignments": {
845
+ "type": "struct",
846
+ "type_mapping": [
847
+ ["votes1", "Vec<(NominatorIndex, ValidatorIndex)>"],
848
+ ["votes2", "Vec<(NominatorIndex, [CompactScore; 1], ValidatorIndex)>"],
849
+ ["votes3", "Vec<(NominatorIndex, [CompactScore; 2], ValidatorIndex)>"],
850
+ ["votes4", "Vec<(NominatorIndex, [CompactScore; 3], ValidatorIndex)>"],
851
+ ["votes5", "Vec<(NominatorIndex, [CompactScore; 4], ValidatorIndex)>"],
852
+ ["votes6", "Vec<(NominatorIndex, [CompactScore; 5], ValidatorIndex)>"],
853
+ ["votes7", "Vec<(NominatorIndex, [CompactScore; 6], ValidatorIndex)>"],
854
+ ["votes8", "Vec<(NominatorIndex, [CompactScore; 7], ValidatorIndex)>"],
855
+ ["votes9", "Vec<(NominatorIndex, [CompactScore; 8], ValidatorIndex)>"],
856
+ ["votes10", "Vec<(NominatorIndex, [CompactScore; 9], ValidatorIndex)>"],
857
+ ["votes11", "Vec<(NominatorIndex, [CompactScore; 10], ValidatorIndex)>"],
858
+ ["votes12", "Vec<(NominatorIndex, [CompactScore; 11], ValidatorIndex)>"],
859
+ ["votes13", "Vec<(NominatorIndex, [CompactScore; 12], ValidatorIndex)>"],
860
+ ["votes14", "Vec<(NominatorIndex, [CompactScore; 13], ValidatorIndex)>"],
861
+ ["votes15", "Vec<(NominatorIndex, [CompactScore; 14], ValidatorIndex)>"],
862
+ ["votes16", "Vec<(NominatorIndex, [CompactScore; 15], ValidatorIndex)>"]
863
+ ]
864
+ },
865
+ "DeferredOffenceOf": {
866
+ "type": "struct",
867
+ "type_mapping": [
868
+ ["offences", "Vec<OffenceDetails>"],
869
+ ["perc", "Vec<Perbill>"],
870
+ ["session", "SessionIndex"]
871
+ ]
872
+ },
873
+ "Statement": {
874
+ "type": "enum",
875
+ "type_mapping": [
876
+ ["Never", "Null"],
877
+ ["Candidate", "Hash"],
878
+ ["Valid", "Hash"],
879
+ ["Invalid", "Hash"]
880
+ ]
881
+ },
882
+ "ValidatorSignature": "Signature",
883
+ "DoubleVoteReportStatement": {
884
+ "type": "struct",
885
+ "type_mapping": [
886
+ ["statement", "Statement"],
887
+ ["signature", "ValidatorSignature"]
888
+ ]
889
+ },
890
+ "DoubleVoteReportProof": {
891
+ "type": "struct",
892
+ "type_mapping": [
893
+ ["session", "SessionIndex"],
894
+ ["trieNodes", "Vec<Bytes>"]
895
+ ]
896
+ },
897
+ "SigningContext": {
898
+ "type": "struct",
899
+ "type_mapping": [
900
+ ["sessionIndex", "SessionIndex"],
901
+ ["parentHash", "Hash"]
902
+ ]
903
+ },
904
+ "DoubleVoteReport": {
905
+ "type": "struct",
906
+ "type_mapping": [
907
+ ["identity", "ValidatorId"],
908
+ ["first", "DoubleVoteReportStatement"],
909
+ ["second", "DoubleVoteReportStatement"],
910
+ ["proof", "DoubleVoteReportProof"],
911
+ ["signingContext", "SigningContext"]
912
+ ]
913
+ },
914
+ "ElectionCompute": {
915
+ "type": "enum",
916
+ "value_list": [
917
+ "OnChain",
918
+ "Signed",
919
+ "Authority"
920
+ ]
921
+ },
922
+ "ElectionResult": {
923
+ "type": "struct",
924
+ "type_mapping": [
925
+ ["compute", "ElectionCompute"],
926
+ ["slotStake", "Balance"],
927
+ ["electedStashes", "Vec<AccountId>"],
928
+ ["exposures", "Vec<(AccountId, Exposure)>"]
929
+ ]
930
+ },
931
+ "ElectionStatus": {
932
+ "type": "enum",
933
+ "type_mapping": [
934
+ ["Close", "Null"],
935
+ ["Open", "BlockNumber"]
936
+ ]
937
+ },
938
+ "Phase": {
939
+ "type": "enum",
940
+ "type_mapping": [
941
+ ["ApplyExtrinsic", "u32"],
942
+ ["Finalization", "Null"],
943
+ ["Initialization", "Null"]
944
+ ]
945
+ },
946
+ "PhragmenScore": "[u128; 3]",
947
+ "PreimageStatusAvailable": {
948
+ "type": "struct",
949
+ "type_mapping": [
950
+ ["data", "Bytes"],
951
+ ["provider", "AccountId"],
952
+ ["deposit", "Balance"],
953
+ ["since", "BlockNumber"],
954
+ ["expiry", "Option<BlockNumber>"]
955
+ ]
956
+ },
957
+ "PreimageStatus": {
958
+ "type": "enum",
959
+ "type_mapping": [
960
+ ["Missing", "BlockNumber"],
961
+ ["Available", "PreimageStatusAvailable"]
962
+ ]
963
+ },
964
+ "Randomness": "Hash",
965
+ "MaybeRandomness": "Option<Randomness>",
966
+ "schnorrkel::Randomness": "Hash",
967
+ "schnorrkel::RawVRFOutput": "[u8; 32]",
968
+ "TaskAddress": {
969
+ "type": "struct",
970
+ "type_mapping": [
971
+ ["blockNumber", "BlockNumber"],
972
+ ["index", "u32"]
973
+ ]
974
+ },
975
+ "ValidationCode": "Bytes",
976
+ "ParaPastCodeMeta": {
977
+ "type": "struct",
978
+ "type_mapping": [
979
+ ["upgrade_times", "Vec<BlockNumber>"],
980
+ ["last_pruned", "Option<BlockNumber>"]
981
+ ]
982
+ },
983
+ "ModuleId": "LockIdentifier",
984
+ "RuntimeDbWeight": {
985
+ "type": "struct",
986
+ "type_mapping": [
987
+ ["read", "Weight"],
988
+ ["write", "Weight"]
989
+ ]
840
990
  }
841
991
  }
842
992
  }
@@ -1,6 +1,6 @@
1
1
  {
2
- "runtime_id": 2,
2
+ "runtime_id": 3,
3
3
  "types": {
4
- "Weight": "u16"
4
+ "Weight": "u64"
5
5
  }
6
6
  }
@@ -1,9 +1,10 @@
1
1
  {
2
- "runtime_id": 1054,
2
+ "runtime_id": 1062,
3
3
  "types": {
4
4
  "Address": "AccountIdAddress",
5
5
  "BlockNumber": "U32",
6
6
  "LeasePeriod": "BlockNumber",
7
+ "Weight": "u64",
7
8
  "SessionKeysPolkadot": {
8
9
  "type": "struct",
9
10
  "type_mapping": [
@@ -180,7 +181,47 @@
180
181
  ]
181
182
  }
182
183
  }
184
+ },
185
+ {
186
+ "runtime_range": [1019, 1056],
187
+ "types": {
188
+ "Weight": "u32"
189
+ }
190
+ },
191
+ {
192
+ "runtime_range": [1057, null],
193
+ "types": {
194
+ "Weight": "u64"
195
+ }
196
+ },
197
+ {
198
+ "runtime_range": [1019, 1058],
199
+ "types": {
200
+ "Heartbeat": {
201
+ "type": "struct",
202
+ "type_mapping": [
203
+ ["blockNumber", "BlockNumber"],
204
+ ["networkState", "OpaqueNetworkState"],
205
+ ["sessionIndex", "SessionIndex"],
206
+ ["authorityIndex", "AuthIndex"]
207
+ ]
208
+ }
209
+ }
210
+ },
211
+ {
212
+ "runtime_range": [1062, null],
213
+ "types": {
214
+ "Heartbeat": {
215
+ "type": "struct",
216
+ "type_mapping": [
217
+ ["blockNumber", "BlockNumber"],
218
+ ["networkState", "OpaqueNetworkState"],
219
+ ["sessionIndex", "SessionIndex"],
220
+ ["authorityIndex", "AuthIndex"],
221
+ ["validatorsLen", "u32"]
222
+ ]
223
+ }
224
+ }
183
225
  }
184
-
185
226
  ]
186
227
  }
@@ -1,6 +1,7 @@
1
1
  {
2
- "runtime_id": 1000,
2
+ "runtime_id": 1006,
3
3
  "types": {
4
+ "Address": "AccountIdAddress",
4
5
  "BlockNumber": "U32",
5
6
  "LeasePeriod": "BlockNumber",
6
7
  "SessionKeysPolkadot": {
@@ -0,0 +1,34 @@
1
+ require "scale"
2
+
3
+
4
+ client = SubstrateClient.new("ws://127.0.0.1:9944/")
5
+ client.init
6
+ metadata = client.get_metadata nil
7
+
8
+ the_module = metadata.get_module("CertificateModule")
9
+ puts ""
10
+ puts "CertificateModule calls:"
11
+ puts "---------------------------------------"
12
+ puts the_module[:calls]
13
+
14
+ the_call = metadata.get_module_call("CertificateModule", "create_entity")
15
+ puts ""
16
+ puts "create_entity call:"
17
+ puts "---------------------------------------"
18
+ puts the_call
19
+
20
+
21
+ puts ""
22
+ puts "CertificateModule storages:"
23
+ puts "---------------------------------------"
24
+ puts the_module[:storage][:items]
25
+
26
+ # Scale::TypeRegistry.instance.metadata = metadata.value
27
+ # puts metadata.value.event_index["0400"][1]
28
+ # puts metadata.value.event_index["0401"][1]
29
+ # puts metadata.value.event_index["0402"][1]
30
+ # hex_events = "0x0c000000000000001027000001010000010000000400be07e2c28688db5368445c33d32b3c7bcad15dab1ec802ba8cccc1c22b86574f6992da89ff412eaf9bafac4024ca23eea8c988a437fc96a1c6445148a8ebb4d2000001000000000010270000000100"
31
+ # scale_bytes = Scale::Bytes.new(hex_events)
32
+ # Scale::Types.get("Vec<EventRecord>").decode(scale_bytes).value.each do |er|
33
+ # puts er.value
34
+ # end
@@ -0,0 +1,4 @@
1
+ require "scale"
2
+
3
+ client = SubstrateClient.new("wss://kusama-rpc.polkadot.io/")
4
+ client.init
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.2.4
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wu Minzhe
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-04-15 00:00:00.000000000 Z
11
+ date: 2020-05-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: substrate_common.rb
@@ -189,6 +189,8 @@ files:
189
189
  - lib/type_registry/test.json
190
190
  - lib/type_registry/westend.json
191
191
  - scale.gemspec
192
+ - scripts/block_events.rb
193
+ - scripts/example.rb
192
194
  - src/lib.rs
193
195
  homepage: https://github.com/itering/scale.rb
194
196
  licenses: