scale_rb 0.4.2 → 0.5.0
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/.devcontainer/devcontainer.json +21 -0
- data/Dockerfile +16 -0
- data/Gemfile +4 -4
- data/README.md +19 -7
- data/bin/console +0 -0
- data/bin/setup +0 -0
- data/examples/http_client_2.rb +0 -2
- data/exe/metadata +9 -11
- data/lib/address.rb +1 -1
- data/lib/custom_assign.rb +92 -0
- data/lib/scale_rb/call_helper.rb +42 -0
- data/lib/{client → scale_rb/client}/client_ext.rb +12 -13
- data/lib/{client → scale_rb/client}/http_client.rb +1 -1
- data/lib/{client → scale_rb/client}/ws_client.rb +11 -15
- data/lib/scale_rb/codec.rb +25 -0
- data/lib/scale_rb/codec_utils.rb +128 -0
- data/lib/scale_rb/decode.rb +164 -0
- data/lib/scale_rb/encode.rb +150 -0
- data/lib/{hasher.rb → scale_rb/hasher.rb} +10 -8
- data/lib/scale_rb/metadata/metadata.rb +114 -0
- data/lib/{metadata → scale_rb/metadata}/metadata_v10.rb +0 -17
- data/lib/{metadata → scale_rb/metadata}/metadata_v11.rb +0 -17
- data/lib/{metadata → scale_rb/metadata}/metadata_v12.rb +0 -17
- data/lib/{metadata → scale_rb/metadata}/metadata_v13.rb +0 -17
- data/lib/{metadata → scale_rb/metadata}/metadata_v14.rb +18 -18
- data/lib/{metadata → scale_rb/metadata}/metadata_v9.rb +0 -17
- data/lib/scale_rb/metadata/registry.rb +263 -0
- data/lib/scale_rb/metadata/type_exp.rb +286 -0
- data/lib/scale_rb/portable_registry.rb +133 -0
- data/lib/{storage_helper.rb → scale_rb/storage_helper.rb} +16 -4
- data/lib/scale_rb/types.rb +233 -0
- data/lib/scale_rb/utils.rb +125 -0
- data/lib/scale_rb/version.rb +1 -1
- data/lib/scale_rb.rb +20 -26
- data/lib/type_enforcer.rb +170 -0
- data/scale_rb.gemspec +3 -0
- metadata +57 -19
- data/lib/codec.rb +0 -450
- data/lib/metadata/metadata.rb +0 -137
- data/lib/monkey_patching.rb +0 -115
- data/lib/portable_codec.rb +0 -285
- data/lib/registry.rb +0 -13
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.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aki Wu
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-10-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: base58
|
@@ -108,6 +108,34 @@ dependencies:
|
|
108
108
|
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: dry-struct
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: dry-types
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
111
139
|
description: This gem includes a ruby implementation of SCALE Codec, a general Substrate
|
112
140
|
Http JSONRPC Client, and, a general Substrate Websocket JSON-RPC Client.
|
113
141
|
email:
|
@@ -117,11 +145,13 @@ executables:
|
|
117
145
|
extensions: []
|
118
146
|
extra_rdoc_files: []
|
119
147
|
files:
|
148
|
+
- ".devcontainer/devcontainer.json"
|
120
149
|
- ".gitignore"
|
121
150
|
- ".rspec"
|
122
151
|
- ".rubocop.yml"
|
123
152
|
- ".travis.yml"
|
124
153
|
- CODE_OF_CONDUCT.md
|
154
|
+
- Dockerfile
|
125
155
|
- Gemfile
|
126
156
|
- LICENSE.txt
|
127
157
|
- README.md
|
@@ -137,24 +167,32 @@ files:
|
|
137
167
|
- examples/ws_client_error_handling.rb
|
138
168
|
- exe/metadata
|
139
169
|
- lib/address.rb
|
140
|
-
- lib/
|
141
|
-
- lib/client/http_client.rb
|
142
|
-
- lib/client/ws_client.rb
|
143
|
-
- lib/codec.rb
|
144
|
-
- lib/hasher.rb
|
145
|
-
- lib/metadata/metadata.rb
|
146
|
-
- lib/metadata/metadata_v10.rb
|
147
|
-
- lib/metadata/metadata_v11.rb
|
148
|
-
- lib/metadata/metadata_v12.rb
|
149
|
-
- lib/metadata/metadata_v13.rb
|
150
|
-
- lib/metadata/metadata_v14.rb
|
151
|
-
- lib/metadata/metadata_v9.rb
|
152
|
-
- lib/monkey_patching.rb
|
153
|
-
- lib/portable_codec.rb
|
154
|
-
- lib/registry.rb
|
170
|
+
- lib/custom_assign.rb
|
155
171
|
- lib/scale_rb.rb
|
172
|
+
- lib/scale_rb/call_helper.rb
|
173
|
+
- lib/scale_rb/client/client_ext.rb
|
174
|
+
- lib/scale_rb/client/http_client.rb
|
175
|
+
- lib/scale_rb/client/ws_client.rb
|
176
|
+
- lib/scale_rb/codec.rb
|
177
|
+
- lib/scale_rb/codec_utils.rb
|
178
|
+
- lib/scale_rb/decode.rb
|
179
|
+
- lib/scale_rb/encode.rb
|
180
|
+
- lib/scale_rb/hasher.rb
|
181
|
+
- lib/scale_rb/metadata/metadata.rb
|
182
|
+
- lib/scale_rb/metadata/metadata_v10.rb
|
183
|
+
- lib/scale_rb/metadata/metadata_v11.rb
|
184
|
+
- lib/scale_rb/metadata/metadata_v12.rb
|
185
|
+
- lib/scale_rb/metadata/metadata_v13.rb
|
186
|
+
- lib/scale_rb/metadata/metadata_v14.rb
|
187
|
+
- lib/scale_rb/metadata/metadata_v9.rb
|
188
|
+
- lib/scale_rb/metadata/registry.rb
|
189
|
+
- lib/scale_rb/metadata/type_exp.rb
|
190
|
+
- lib/scale_rb/portable_registry.rb
|
191
|
+
- lib/scale_rb/storage_helper.rb
|
192
|
+
- lib/scale_rb/types.rb
|
193
|
+
- lib/scale_rb/utils.rb
|
156
194
|
- lib/scale_rb/version.rb
|
157
|
-
- lib/
|
195
|
+
- lib/type_enforcer.rb
|
158
196
|
- scale_rb.gemspec
|
159
197
|
- tea.yaml
|
160
198
|
homepage: https://github.com/wuminzhe/scale_rb
|
@@ -178,7 +216,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
178
216
|
- !ruby/object:Gem::Version
|
179
217
|
version: '0'
|
180
218
|
requirements: []
|
181
|
-
rubygems_version: 3.
|
219
|
+
rubygems_version: 3.5.16
|
182
220
|
signing_key:
|
183
221
|
specification_version: 4
|
184
222
|
summary: A Ruby SCALE Codec Library, and, Substrate RPC Client
|
data/lib/codec.rb
DELETED
@@ -1,450 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ScaleRb
|
4
|
-
class Error < StandardError; end
|
5
|
-
class NotImplemented < Error; end
|
6
|
-
class NilTypeError < Error; end
|
7
|
-
class TypeParseError < Error; end
|
8
|
-
class NotEnoughBytesError < Error; end
|
9
|
-
class InvalidBytesError < Error; end
|
10
|
-
class Unreachable < Error; end
|
11
|
-
class IndexOutOfRangeError < Error; end
|
12
|
-
class LengthNotEqualErr < Error; end
|
13
|
-
class InvalidValueError < Error; end
|
14
|
-
end
|
15
|
-
|
16
|
-
# TODO: set, bitvec
|
17
|
-
module ScaleRb
|
18
|
-
class << self
|
19
|
-
def type_def?(type)
|
20
|
-
type.instance_of?(String) && (
|
21
|
-
bytes?(type) ||
|
22
|
-
boolean?(type) ||
|
23
|
-
string?(type) ||
|
24
|
-
compact?(type) ||
|
25
|
-
int?(type) ||
|
26
|
-
uint?(type) ||
|
27
|
-
option?(type) ||
|
28
|
-
array?(type) ||
|
29
|
-
vec?(type) ||
|
30
|
-
tuple?(type)
|
31
|
-
) ||
|
32
|
-
type.instance_of?(Hash)
|
33
|
-
end
|
34
|
-
|
35
|
-
def bytes?(type)
|
36
|
-
type.downcase == 'bytes'
|
37
|
-
end
|
38
|
-
|
39
|
-
def boolean?(type)
|
40
|
-
type.downcase == 'bool' || type.downcase == 'boolean'
|
41
|
-
end
|
42
|
-
|
43
|
-
def string?(type)
|
44
|
-
type.downcase == 'str' || type.downcase == 'string' || type.downcase == 'text' || type.downcase == 'type'
|
45
|
-
end
|
46
|
-
|
47
|
-
def compact?(type)
|
48
|
-
type.downcase == 'compact' ||
|
49
|
-
(type[0..7].downcase == 'compact<' && type[-1] == '>')
|
50
|
-
end
|
51
|
-
|
52
|
-
def int?(type)
|
53
|
-
type[0].downcase == 'i' && type[1..] =~ /\A(8|16|32|64|128|256|512)\z/
|
54
|
-
end
|
55
|
-
|
56
|
-
def uint?(type)
|
57
|
-
type[0].downcase == 'u' && type[1..] =~ /\A(8|16|32|64|128|256|512)\z/
|
58
|
-
end
|
59
|
-
|
60
|
-
def option?(type)
|
61
|
-
type[0..6].downcase == 'option<' && type[-1] == '>'
|
62
|
-
end
|
63
|
-
|
64
|
-
def array?(type)
|
65
|
-
type[0] == '[' && type[-1] == ']'
|
66
|
-
end
|
67
|
-
|
68
|
-
def vec?(type)
|
69
|
-
type[0..3].downcase == 'vec<' && type[-1] == '>'
|
70
|
-
end
|
71
|
-
|
72
|
-
def tuple?(type)
|
73
|
-
type[0] == '(' && type[-1] == ')'
|
74
|
-
end
|
75
|
-
|
76
|
-
def struct?(type)
|
77
|
-
type.instance_of?(Hash)
|
78
|
-
end
|
79
|
-
|
80
|
-
def enum?(type)
|
81
|
-
type.instance_of?(Hash) && type.key?(:_enum)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
module ScaleRb
|
87
|
-
class << self
|
88
|
-
def parse_option(type)
|
89
|
-
type.scan(/\A[O|o]ption<(.+)>\z/).first.first
|
90
|
-
end
|
91
|
-
|
92
|
-
def parse_array(type)
|
93
|
-
scan_out = type.scan(/\A\[\s*(.+)\s*;\s*(\d+)\s*\]\z/)
|
94
|
-
raise ScaleRb::TypeParseError, type if scan_out.empty?
|
95
|
-
raise ScaleRb::TypeParseError, type if scan_out[0].length != 2
|
96
|
-
|
97
|
-
inner_type = scan_out[0][0]
|
98
|
-
length = scan_out[0][1].to_i
|
99
|
-
[inner_type, length]
|
100
|
-
end
|
101
|
-
|
102
|
-
def parse_vec(type)
|
103
|
-
type.scan(/\A[V|v]ec<(.+)>\z/).first.first
|
104
|
-
end
|
105
|
-
|
106
|
-
def parse_tuple(type)
|
107
|
-
type.scan(/\A\(\s*(.+)\s*\)\z/)[0][0].split(',').map(&:strip)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
# Helper functions
|
113
|
-
module ScaleRb
|
114
|
-
class << self
|
115
|
-
def _get_final_type_from_registry(registry, type)
|
116
|
-
raise "Wrong lookup type #{type.class}" if !type.instance_of?(String) && !type.instance_of?(Hash)
|
117
|
-
|
118
|
-
return if type.instance_of?(Hash)
|
119
|
-
|
120
|
-
mapped = registry._get(type) # mapped: String(name, type_def) | Hash(type_def: struct, enum) | nil
|
121
|
-
|
122
|
-
return if mapped.nil?
|
123
|
-
return mapped if type_def?(mapped)
|
124
|
-
|
125
|
-
_get_final_type_from_registry(registry, mapped)
|
126
|
-
end
|
127
|
-
|
128
|
-
def _decode_types(types, bytes, registry)
|
129
|
-
_decode_each(types, bytes) do |type, remaining_bytes|
|
130
|
-
decode(type, remaining_bytes, registry)
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
def _decode_each(types, bytes, &decode)
|
135
|
-
remaining_bytes = bytes
|
136
|
-
values = types.map do |type|
|
137
|
-
value, remaining_bytes = decode.call(type, remaining_bytes)
|
138
|
-
value
|
139
|
-
end
|
140
|
-
[values, remaining_bytes]
|
141
|
-
end
|
142
|
-
|
143
|
-
def _do_decode_compact(bytes)
|
144
|
-
case bytes[0] & 3
|
145
|
-
when 0
|
146
|
-
[bytes[0] >> 2, bytes[1..]]
|
147
|
-
when 1
|
148
|
-
[bytes[0..1]._flip._to_uint >> 2, bytes[2..]]
|
149
|
-
when 2
|
150
|
-
[bytes[0..3]._flip._to_uint >> 2, bytes[4..]]
|
151
|
-
when 3
|
152
|
-
length = 4 + (bytes[0] >> 2)
|
153
|
-
[bytes[1..length]._flip._to_uint, bytes[length + 1..]]
|
154
|
-
else
|
155
|
-
raise Unreachable, 'type: Compact'
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
def _encode_each(types, values, &encode)
|
160
|
-
_encode_each_without_merge(types, values, &encode).flatten
|
161
|
-
end
|
162
|
-
|
163
|
-
def _encode_each_without_merge(types, values, &encode)
|
164
|
-
raise LengthNotEqualErr, "types: #{types}, values: #{values.inspect}" if types.length != values.length
|
165
|
-
|
166
|
-
types.map.with_index do |type, i|
|
167
|
-
encode.call(type, values[i])
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
def _encode_types(types, values, registry = {})
|
172
|
-
_encode_each(types, values) do |type, value|
|
173
|
-
encode(type, value, registry)
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
def _encode_each_with_hashers(types, values, hashers, &encode)
|
178
|
-
if !hashers.nil? && hashers.length != types.length
|
179
|
-
raise ScaleRb::LengthNotEqualErr, "types length: #{types.length}, hashers length: #{hashers.length}"
|
180
|
-
end
|
181
|
-
|
182
|
-
bytes_array = ScaleRb._encode_each_without_merge(types, values, &encode)
|
183
|
-
bytes_array.each_with_index.reduce([]) do |memo, (bytes, i)|
|
184
|
-
memo + Hasher.apply_hasher(hashers[i], bytes)
|
185
|
-
end
|
186
|
-
end
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
module ScaleRb
|
191
|
-
# Decode
|
192
|
-
class << self
|
193
|
-
def decode(type, bytes, registry = {})
|
194
|
-
# logger.debug '--------------------------------------------------'
|
195
|
-
# debug 'decoding type', type
|
196
|
-
# debug 'bytes', bytes&.length
|
197
|
-
|
198
|
-
if type.instance_of?(String)
|
199
|
-
return decode_bytes(bytes) if bytes?(type) # Bytes
|
200
|
-
return decode_boolean(bytes) if boolean?(type) # Boolean
|
201
|
-
return decode_string(bytes) if string?(type) # String
|
202
|
-
return decode_int(type, bytes) if int?(type) # i8, i16...
|
203
|
-
return decode_uint(type, bytes) if uint?(type) # u8, u16...
|
204
|
-
return decode_compact(bytes) if compact?(type) # Compact<>
|
205
|
-
return decode_option(type, bytes, registry) if option?(type) # Option<>
|
206
|
-
return decode_array(type, bytes, registry) if array?(type) # [u8; 3]
|
207
|
-
return decode_vec(type, bytes, registry) if vec?(type) # Vec<u8>
|
208
|
-
return decode_tuple(type, bytes, registry) if tuple?(type) # (u8, u8)
|
209
|
-
|
210
|
-
# search the type from registry if not the types above
|
211
|
-
registry_type = _get_final_type_from_registry(registry, type)
|
212
|
-
return decode(registry_type, bytes, registry) if registry_type
|
213
|
-
elsif type.instance_of?(Hash)
|
214
|
-
return decode_enum(type, bytes, registry) if enum?(type)
|
215
|
-
return decode_struct(type, bytes, registry) if struct?(type)
|
216
|
-
end
|
217
|
-
|
218
|
-
raise NotImplemented, "type: #{type.inspect}"
|
219
|
-
end
|
220
|
-
|
221
|
-
def decode_bytes(bytes)
|
222
|
-
length, remaining_bytes = _do_decode_compact(bytes)
|
223
|
-
value = remaining_bytes[0...length]._to_hex
|
224
|
-
# debug 'length', length
|
225
|
-
# debug 'value', value
|
226
|
-
[
|
227
|
-
value,
|
228
|
-
remaining_bytes[length..]
|
229
|
-
]
|
230
|
-
end
|
231
|
-
|
232
|
-
def decode_boolean(bytes)
|
233
|
-
value =
|
234
|
-
if bytes[0] == 0x00
|
235
|
-
false
|
236
|
-
elsif bytes[0] == 0x01
|
237
|
-
true
|
238
|
-
else
|
239
|
-
raise InvalidBytesError, 'type: Boolean'
|
240
|
-
end
|
241
|
-
# debug 'value', value
|
242
|
-
[value, bytes[1..]]
|
243
|
-
end
|
244
|
-
|
245
|
-
def decode_string(bytes)
|
246
|
-
length, remaining_bytes = _do_decode_compact(bytes)
|
247
|
-
raise NotEnoughBytesError, 'type: String' if remaining_bytes.length < length
|
248
|
-
|
249
|
-
value = remaining_bytes[0...length]._to_utf8
|
250
|
-
# debug 'byte length', length
|
251
|
-
# debug 'value', value.inspect
|
252
|
-
[
|
253
|
-
value,
|
254
|
-
remaining_bytes[length..]
|
255
|
-
]
|
256
|
-
end
|
257
|
-
|
258
|
-
def decode_int(type, bytes)
|
259
|
-
bit_length = type[1..].to_i
|
260
|
-
byte_length = bit_length / 8
|
261
|
-
raise NotEnoughBytesError, "type: #{type}" if bytes.length < byte_length
|
262
|
-
|
263
|
-
value = bytes[0...byte_length]._flip._to_int(bit_length)
|
264
|
-
# debug 'value', value
|
265
|
-
[
|
266
|
-
value,
|
267
|
-
bytes[byte_length..]
|
268
|
-
]
|
269
|
-
end
|
270
|
-
|
271
|
-
def decode_uint(type_def, bytes)
|
272
|
-
bit_length = type_def[1..].to_i
|
273
|
-
byte_length = bit_length / 8
|
274
|
-
raise NotEnoughBytesError, "type: #{type_def}" if bytes.length < byte_length
|
275
|
-
|
276
|
-
value = bytes[0...byte_length]._flip._to_uint
|
277
|
-
# debug 'value', value
|
278
|
-
[
|
279
|
-
value,
|
280
|
-
bytes[byte_length..]
|
281
|
-
]
|
282
|
-
end
|
283
|
-
|
284
|
-
def decode_compact(bytes)
|
285
|
-
_do_decode_compact(bytes)
|
286
|
-
# debug 'value', result[0]
|
287
|
-
end
|
288
|
-
|
289
|
-
def decode_option(type_def, bytes, registry = {})
|
290
|
-
inner_type = parse_option(type_def)
|
291
|
-
|
292
|
-
return [nil, bytes[1..]] if bytes[0] == 0x00
|
293
|
-
return decode(inner_type, bytes[1..], registry) if bytes[0] == 0x01
|
294
|
-
|
295
|
-
raise InvalidBytesError, "type: #{type_def}"
|
296
|
-
end
|
297
|
-
|
298
|
-
def decode_array(type_def, bytes, registry = {})
|
299
|
-
inner_type, length = parse_array(type_def)
|
300
|
-
_decode_types([inner_type] * length, bytes, registry)
|
301
|
-
end
|
302
|
-
|
303
|
-
def decode_vec(type_def, bytes, registry = {})
|
304
|
-
inner_type = parse_vec(type_def)
|
305
|
-
length, remaining_bytes = _do_decode_compact(bytes)
|
306
|
-
# debug 'length', length
|
307
|
-
_decode_types([inner_type] * length, remaining_bytes, registry)
|
308
|
-
end
|
309
|
-
|
310
|
-
def decode_tuple(type_def, bytes, registry = {})
|
311
|
-
inner_types = parse_tuple(type_def)
|
312
|
-
_decode_types(inner_types, bytes, registry)
|
313
|
-
end
|
314
|
-
|
315
|
-
# TODO: custom index?
|
316
|
-
# {
|
317
|
-
# _enum: {
|
318
|
-
# name1: type1,
|
319
|
-
# name2: type2
|
320
|
-
# }
|
321
|
-
# }
|
322
|
-
# or
|
323
|
-
# {
|
324
|
-
# _enum: ['name1', 'name2']
|
325
|
-
# }
|
326
|
-
def decode_enum(type_def, bytes, registry = {})
|
327
|
-
index = bytes[0]
|
328
|
-
|
329
|
-
items = type_def[:_enum]
|
330
|
-
raise IndexOutOfRangeError, "type: #{type_def}" if index > items.length - 1
|
331
|
-
|
332
|
-
item = items.to_a[index] # 'name' or [:name, inner_type]
|
333
|
-
# debug 'value', item.inspect
|
334
|
-
return [item, bytes[1..]] if item.instance_of?(String)
|
335
|
-
|
336
|
-
value, remaining_bytes = decode(item[1], bytes[1..], registry)
|
337
|
-
[
|
338
|
-
{ item[0].to_sym => value },
|
339
|
-
remaining_bytes
|
340
|
-
]
|
341
|
-
end
|
342
|
-
|
343
|
-
def decode_struct(struct, bytes, registry = {})
|
344
|
-
values, remaining_bytes = _decode_types(struct.values, bytes, registry)
|
345
|
-
[
|
346
|
-
[struct.keys, values].transpose.to_h,
|
347
|
-
remaining_bytes
|
348
|
-
]
|
349
|
-
end
|
350
|
-
end
|
351
|
-
|
352
|
-
# Encode
|
353
|
-
class << self
|
354
|
-
def encode(type, value, registry = {})
|
355
|
-
# logger.debug '--------------------------------------------------'
|
356
|
-
# debug 'encoding type', type
|
357
|
-
# debug 'value', value
|
358
|
-
|
359
|
-
if type.instance_of?(String)
|
360
|
-
return encode_bytes(value) if bytes?(type)
|
361
|
-
return encode_boolean(value) if boolean?(type)
|
362
|
-
return encode_string(value) if string?(type)
|
363
|
-
return encode_compact(value) if compact?(type)
|
364
|
-
return encode_uint(type, value) if uint?(type)
|
365
|
-
return encode_option(type, value, registry) if option?(type)
|
366
|
-
return encode_array(type, value, registry) if array?(type)
|
367
|
-
return encode_vec(type, value, registry) if vec?(type)
|
368
|
-
return encode_tuple(type, value, registry) if tuple?(type)
|
369
|
-
|
370
|
-
registry_type = _get_final_type_from_registry(registry, type)
|
371
|
-
return encode(registry_type, value, registry) if registry_type
|
372
|
-
elsif type.instance_of?(Hash)
|
373
|
-
return encode_enum(type, value, registry) if enum?(type)
|
374
|
-
return encode_struct(type, value, registry) if struct?(type)
|
375
|
-
end
|
376
|
-
|
377
|
-
raise NotImplemented, "type: #{type}, value: #{value.inspect}"
|
378
|
-
end
|
379
|
-
|
380
|
-
def encode_bytes(value)
|
381
|
-
encode_compact(value.length) + value
|
382
|
-
end
|
383
|
-
|
384
|
-
def encode_boolean(value)
|
385
|
-
return [0x00] if value == false
|
386
|
-
return [0x01] if value == true
|
387
|
-
|
388
|
-
raise InvalidValueError, "type: Boolean, value: #{value.inspect}"
|
389
|
-
end
|
390
|
-
|
391
|
-
def encode_string(string)
|
392
|
-
body = string.unpack('C*')
|
393
|
-
prefix = encode_compact(body.length)
|
394
|
-
prefix + body
|
395
|
-
end
|
396
|
-
|
397
|
-
def encode_compact(value)
|
398
|
-
return [value << 2] if (value >= 0) && (value < 64)
|
399
|
-
return ((value << 2) + 1)._to_bytes._flip if value < 2**14
|
400
|
-
return ((value << 2) + 2)._to_bytes._flip if value < 2**30
|
401
|
-
|
402
|
-
bytes = value._to_bytes._flip
|
403
|
-
[(((bytes.length - 4) << 2) + 3)] + bytes
|
404
|
-
end
|
405
|
-
|
406
|
-
def encode_uint(type, value)
|
407
|
-
raise InvalidValueError, "type: #{type}, value: #{value.inspect}" unless value.instance_of?(Integer)
|
408
|
-
|
409
|
-
bit_length = type[1..].to_i
|
410
|
-
value._to_bytes(bit_length)._flip
|
411
|
-
end
|
412
|
-
|
413
|
-
def encode_option(type, value, registry = {})
|
414
|
-
return [0x00] if value.nil?
|
415
|
-
|
416
|
-
inner_type = type.scan(/\A[O|o]ption<(.+)>\z/).first.first
|
417
|
-
[0x01] + encode(inner_type, value, registry)
|
418
|
-
end
|
419
|
-
|
420
|
-
def encode_array(type, array, registry = {})
|
421
|
-
inner_type, length = parse_array(type)
|
422
|
-
raise LengthNotEqualErr, "type: #{type}, value: #{array.inspect}" if length != array.length
|
423
|
-
|
424
|
-
_encode_types([inner_type] * length, array, registry)
|
425
|
-
end
|
426
|
-
|
427
|
-
def encode_vec(type, array, registry = {})
|
428
|
-
inner_type = type.scan(/\A[V|v]ec<(.+)>\z/).first.first
|
429
|
-
length_bytes = encode_compact(array.length)
|
430
|
-
length_bytes + _encode_types([inner_type] * array.length, array, registry)
|
431
|
-
end
|
432
|
-
|
433
|
-
def encode_tuple(tuple_type, tuple, registry = {})
|
434
|
-
inner_types = tuple_type.scan(/\A\(\s*(.+)\s*\)\z/)[0][0].split(',').map(&:strip)
|
435
|
-
_encode_types(inner_types, tuple, registry)
|
436
|
-
end
|
437
|
-
|
438
|
-
def encode_enum(enum_type, enum, registry = {})
|
439
|
-
key = enum.keys.first
|
440
|
-
value = enum.values.first
|
441
|
-
value_type = enum_type[:_enum][key]
|
442
|
-
index = enum_type[:_enum].keys.index(key)
|
443
|
-
encode_uint('u8', index) + encode(value_type, value, registry)
|
444
|
-
end
|
445
|
-
|
446
|
-
def encode_struct(struct_type, struct, registry = {})
|
447
|
-
_encode_types(struct_type.values, struct.values, registry)
|
448
|
-
end
|
449
|
-
end
|
450
|
-
end
|
data/lib/metadata/metadata.rb
DELETED
@@ -1,137 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ScaleRb
|
4
|
-
module Metadata
|
5
|
-
class << self
|
6
|
-
def decode_metadata(bytes)
|
7
|
-
metadata, = ScaleRb.decode('MetadataTop', bytes, TYPES)
|
8
|
-
metadata
|
9
|
-
end
|
10
|
-
|
11
|
-
def build_registry(metadata)
|
12
|
-
raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless metadata._get(:metadata)._key?(:v14)
|
13
|
-
|
14
|
-
metadata_v14 = metadata._get(:metadata)._get(:v14)
|
15
|
-
MetadataV14.build_registry(metadata_v14)
|
16
|
-
end
|
17
|
-
|
18
|
-
def get_module(pallet_name, metadata)
|
19
|
-
version = metadata._get(:metadata).keys.first
|
20
|
-
raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless %w[v9 v10 v11 v12 v13
|
21
|
-
v14].include?(version.to_s)
|
22
|
-
|
23
|
-
Metadata.const_get("Metadata#{version.upcase}").get_module(pallet_name, metadata)
|
24
|
-
end
|
25
|
-
|
26
|
-
def get_module_by_index(pallet_index, metadata)
|
27
|
-
version = metadata._get(:metadata).keys.first
|
28
|
-
raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless %w[v9 v10 v11 v12 v13
|
29
|
-
v14].include?(version.to_s)
|
30
|
-
|
31
|
-
Metadata.const_get("Metadata#{version.upcase}").get_module_by_index(pallet_index, metadata)
|
32
|
-
end
|
33
|
-
|
34
|
-
def get_storage_item(pallet_name, item_name, metadata)
|
35
|
-
version = metadata._get(:metadata).keys.first
|
36
|
-
raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless %w[v9 v10 v11 v12 v13
|
37
|
-
v14].include?(version.to_s)
|
38
|
-
|
39
|
-
Metadata.const_get("Metadata#{version.upcase}").get_storage_item(pallet_name, item_name, metadata)
|
40
|
-
end
|
41
|
-
|
42
|
-
def get_calls_type(pallet_name, metadata)
|
43
|
-
version = metadata._get(:metadata).keys.first
|
44
|
-
raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless %w[v9 v10 v11 v12 v13
|
45
|
-
v14].include?(version.to_s)
|
46
|
-
|
47
|
-
Metadata.const_get("Metadata#{version.upcase}").get_calls_type(pallet_name, metadata)
|
48
|
-
end
|
49
|
-
|
50
|
-
def get_calls_type_id(pallet_name, metadata)
|
51
|
-
version = metadata._get(:metadata).keys.first
|
52
|
-
raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless %w[v9 v10 v11 v12 v13
|
53
|
-
v14].include?(version.to_s)
|
54
|
-
|
55
|
-
Metadata.const_get("Metadata#{version.upcase}").get_calls_type_id(pallet_name, metadata)
|
56
|
-
end
|
57
|
-
|
58
|
-
def get_call_type(pallet_name, call_name, metadata)
|
59
|
-
version = metadata._get(:metadata).keys.first
|
60
|
-
raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless %w[v9 v10 v11 v12 v13
|
61
|
-
v14].include?(version.to_s)
|
62
|
-
|
63
|
-
Metadata.const_get("Metadata#{version.upcase}").get_call_type(pallet_name, call_name, metadata)
|
64
|
-
end
|
65
|
-
|
66
|
-
# call examples:
|
67
|
-
# {:pallet_name=>"Deposit", :call_name=>"Claim", :call=>["claim", []]}
|
68
|
-
# {:pallet_name=>"Balances", :call_name=>"Transfer", :call=>[{:transfer=>{:dest=>[10, 18, 135, 151, 117, 120, 248, 136, 189, 193, 199, 98, 119, 129, 175, 28, 192, 0, 230, 171], :value=>11000000000000000000}}, []]}
|
69
|
-
def encode_call(call, metadata)
|
70
|
-
calls_type_id = get_calls_type_id(call[:pallet_name], metadata)
|
71
|
-
pallet_index = get_module(call[:pallet_name], metadata)._get(:index)
|
72
|
-
[pallet_index] + PortableCodec.encode(calls_type_id, call[:call].first, build_registry(metadata))
|
73
|
-
end
|
74
|
-
|
75
|
-
# callbytes's structure is: pallet_index + call_index + argsbytes
|
76
|
-
#
|
77
|
-
# callbytes examples:
|
78
|
-
# "0x0901"._to_bytes
|
79
|
-
# "0x05000a1287977578f888bdc1c7627781af1cc000e6ab1300004c31b8d9a798"._to_bytes
|
80
|
-
def decode_call(callbytes, metadata)
|
81
|
-
pallet_index = callbytes[0]
|
82
|
-
pallet = get_module_by_index(pallet_index, metadata)
|
83
|
-
|
84
|
-
pallet_name = pallet._get(:name)
|
85
|
-
|
86
|
-
# Remove the pallet_index
|
87
|
-
# The callbytes we used below should not contain the pallet index.
|
88
|
-
# This is because the pallet index is not part of the call type.
|
89
|
-
# Its structure is: call_index + call_args
|
90
|
-
callbytes_without_pallet_index = callbytes[1..]
|
91
|
-
calls_type_id = pallet._get(:calls)._get(:type)
|
92
|
-
decoded = PortableCodec.decode(
|
93
|
-
calls_type_id,
|
94
|
-
callbytes_without_pallet_index,
|
95
|
-
build_registry(metadata)
|
96
|
-
)
|
97
|
-
|
98
|
-
{
|
99
|
-
pallet_name: pallet_name,
|
100
|
-
call_name: decoded.first.is_a?(String) ? decoded.first._to_camel : decoded.first.keys.first.to_s._to_camel,
|
101
|
-
call: decoded
|
102
|
-
}
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
TYPES = {
|
107
|
-
'MetadataTop' => {
|
108
|
-
magicNumber: 'U32',
|
109
|
-
metadata: 'Metadata'
|
110
|
-
},
|
111
|
-
'Metadata' => {
|
112
|
-
_enum: {
|
113
|
-
v0: 'MetadataV0',
|
114
|
-
v1: 'MetadataV1',
|
115
|
-
v2: 'MetadataV2',
|
116
|
-
v3: 'MetadataV3',
|
117
|
-
v4: 'MetadataV4',
|
118
|
-
v5: 'MetadataV5',
|
119
|
-
v6: 'MetadataV6',
|
120
|
-
v7: 'MetadataV7',
|
121
|
-
v8: 'MetadataV8',
|
122
|
-
v9: 'MetadataV9',
|
123
|
-
v10: 'MetadataV10',
|
124
|
-
v11: 'MetadataV11',
|
125
|
-
v12: 'MetadataV12',
|
126
|
-
v13: 'MetadataV13',
|
127
|
-
v14: 'MetadataV14'
|
128
|
-
}
|
129
|
-
}
|
130
|
-
}.merge(MetadataV14::TYPES)
|
131
|
-
.merge(MetadataV13::TYPES)
|
132
|
-
.merge(MetadataV12::TYPES)
|
133
|
-
.merge(MetadataV11::TYPES)
|
134
|
-
.merge(MetadataV10::TYPES)
|
135
|
-
.merge(MetadataV9::TYPES)
|
136
|
-
end
|
137
|
-
end
|