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
data/lib/monkey_patching.rb
DELETED
@@ -1,115 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# https://www.rubyguides.com/2017/01/read-binary-data/
|
4
|
-
class String
|
5
|
-
def _to_bytes
|
6
|
-
data = start_with?('0x') ? self[2..] : self
|
7
|
-
raise 'Not valid hex string' if data =~ /[^\da-f]+/i
|
8
|
-
|
9
|
-
data = "0#{data}" if data.length.odd?
|
10
|
-
data.scan(/../).map(&:hex)
|
11
|
-
end
|
12
|
-
|
13
|
-
def _to_camel
|
14
|
-
split('_').collect(&:capitalize).join
|
15
|
-
end
|
16
|
-
|
17
|
-
def _underscore
|
18
|
-
gsub(/::/, '/')
|
19
|
-
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
20
|
-
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
21
|
-
.tr('-', '_')
|
22
|
-
.downcase
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
class Integer
|
27
|
-
def _to_bytes(bit_length = nil)
|
28
|
-
return to_s(16)._to_bytes unless bit_length
|
29
|
-
|
30
|
-
hex = to_s(16).rjust(bit_length / 4, '0')
|
31
|
-
hex._to_bytes
|
32
|
-
end
|
33
|
-
|
34
|
-
# unsigned to signed
|
35
|
-
def _to_signed(bit_length)
|
36
|
-
unsigned_mid = 2**(bit_length - 1)
|
37
|
-
unsigned_ceiling = 2**bit_length
|
38
|
-
self >= unsigned_mid ? self - unsigned_ceiling : self
|
39
|
-
end
|
40
|
-
|
41
|
-
# signed to unsigned
|
42
|
-
def _to_unsigned(bit_length)
|
43
|
-
unsigned_mid = 2**(bit_length - 1)
|
44
|
-
unsigned_ceiling = 2**bit_length
|
45
|
-
raise 'out of scope' if self >= unsigned_mid || self <= -unsigned_mid
|
46
|
-
|
47
|
-
negative? ? unsigned_ceiling + self : self
|
48
|
-
end
|
49
|
-
|
50
|
-
# unix timestamp to utc
|
51
|
-
def _to_utc
|
52
|
-
Time.at(self).utc.asctime
|
53
|
-
end
|
54
|
-
|
55
|
-
# utc to unix timestamp
|
56
|
-
def _from_utc(utc_asctime)
|
57
|
-
Time.parse(utc_asctime)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
class Array
|
62
|
-
def _to_hex
|
63
|
-
raise 'Not a byte array' unless _byte_array?
|
64
|
-
|
65
|
-
reduce('0x') { |hex, byte| hex + byte.to_s(16).rjust(2, '0') }
|
66
|
-
end
|
67
|
-
|
68
|
-
def _to_bin
|
69
|
-
raise 'Not a byte array' unless _byte_array?
|
70
|
-
|
71
|
-
reduce('0b') { |bin, byte| bin + byte.to_s(2).rjust(8, '0') }
|
72
|
-
end
|
73
|
-
|
74
|
-
def _to_utf8
|
75
|
-
raise 'Not a byte array' unless _byte_array?
|
76
|
-
|
77
|
-
pack('C*').force_encoding('utf-8')
|
78
|
-
end
|
79
|
-
|
80
|
-
def _to_uint
|
81
|
-
_to_hex.to_i(16)
|
82
|
-
end
|
83
|
-
|
84
|
-
def _to_int(bit_length)
|
85
|
-
_to_uint._to_signed(bit_length)
|
86
|
-
end
|
87
|
-
|
88
|
-
def _flip
|
89
|
-
reverse
|
90
|
-
end
|
91
|
-
|
92
|
-
def _byte_array?
|
93
|
-
all? { |e| e >= 0 and e <= 255 }
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
class Hash
|
98
|
-
def _key?(key)
|
99
|
-
if key.instance_of?(String)
|
100
|
-
key?(key) || key?(key.to_sym)
|
101
|
-
else
|
102
|
-
key?(key) || key?(key.to_s)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
def _get(key)
|
107
|
-
if key.instance_of?(String)
|
108
|
-
self[key] || self[key.to_sym]
|
109
|
-
elsif key.instance_of?(Symbol)
|
110
|
-
self[key] || self[key.to_s]
|
111
|
-
else
|
112
|
-
self[key]
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
data/lib/portable_codec.rb
DELETED
@@ -1,285 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ScaleRb
|
4
|
-
module PortableCodec
|
5
|
-
class Error < StandardError; end
|
6
|
-
class TypeNotFound < Error; end
|
7
|
-
class TypeNotImplemented < Error; end
|
8
|
-
class CompositeInvalidValue < Error; end
|
9
|
-
class ArrayLengthNotEqual < Error; end
|
10
|
-
class VariantItemNotFound < Error; end
|
11
|
-
class VariantIndexOutOfRange < Error; end
|
12
|
-
class VariantInvalidValue < Error; end
|
13
|
-
|
14
|
-
class << self
|
15
|
-
def u256(value)
|
16
|
-
bytes = ScaleRb.encode('u256', value)
|
17
|
-
bytes.each_slice(8).map do |slice|
|
18
|
-
ScaleRb.decode('u64', slice).first
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
class << self
|
24
|
-
# registry:
|
25
|
-
# {
|
26
|
-
# 0 => {
|
27
|
-
# path: [...],
|
28
|
-
# params: [...],
|
29
|
-
# def: {
|
30
|
-
# primitive: 'u8' | array: {} | ...
|
31
|
-
# }
|
32
|
-
# },
|
33
|
-
# 1 => {
|
34
|
-
# ...
|
35
|
-
# }
|
36
|
-
# }
|
37
|
-
def decode(id, bytes, registry)
|
38
|
-
type = registry[id]
|
39
|
-
raise TypeNotFound, "id: #{id}" if type.nil?
|
40
|
-
|
41
|
-
_path = type._get(:path)
|
42
|
-
_params = type._get(:params)
|
43
|
-
type_def = type._get(:def)
|
44
|
-
|
45
|
-
return decode_primitive(type_def, bytes) if type_def._key?(:primitive)
|
46
|
-
return decode_compact(bytes) if type_def._key?(:compact)
|
47
|
-
return decode_array(type_def._get(:array), bytes, registry) if type_def._key?(:array)
|
48
|
-
return decode_sequence(type_def._get(:sequence), bytes, registry) if type_def._key?(:sequence)
|
49
|
-
return decode_tuple(type_def._get(:tuple), bytes, registry) if type_def._key?(:tuple)
|
50
|
-
return decode_composite(type_def._get(:composite), bytes, registry) if type_def._key?(:composite)
|
51
|
-
return decode_variant(type_def._get(:variant), bytes, registry) if type_def._key?(:variant)
|
52
|
-
|
53
|
-
raise TypeNotImplemented, "id: #{id}"
|
54
|
-
end
|
55
|
-
|
56
|
-
# Uint, Str, Bool
|
57
|
-
# Int, Bytes ?
|
58
|
-
def decode_primitive(type_def, bytes)
|
59
|
-
primitive = type_def._get(:primitive)
|
60
|
-
return ScaleRb.decode_uint(primitive, bytes) if ScaleRb.uint?(primitive)
|
61
|
-
return ScaleRb.decode_string(bytes) if ScaleRb.string?(primitive)
|
62
|
-
|
63
|
-
ScaleRb.decode_boolean(bytes) if ScaleRb.boolean?(primitive)
|
64
|
-
# return ScaleRb.decode_int(primitive, bytes) if int?(primitive)
|
65
|
-
# return ScaleRb.decode_bytes(bytes) if bytes?(primitive)
|
66
|
-
end
|
67
|
-
|
68
|
-
def decode_compact(bytes)
|
69
|
-
ScaleRb.decode_compact(bytes)
|
70
|
-
end
|
71
|
-
|
72
|
-
def decode_array(array_type, bytes, registry)
|
73
|
-
len = array_type._get(:len)
|
74
|
-
inner_type_id = array_type._get(:type)
|
75
|
-
|
76
|
-
# check if the type of inner_type_id is a u8
|
77
|
-
if _u8?(inner_type_id, registry)
|
78
|
-
[
|
79
|
-
bytes[0...len]._to_hex,
|
80
|
-
bytes[len..]
|
81
|
-
]
|
82
|
-
else
|
83
|
-
_decode_types([inner_type_id] * len, bytes, registry)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def _u8?(type_id, registry)
|
88
|
-
type = registry[type_id]
|
89
|
-
raise TypeNotFound, "id: #{type_id}" if type.nil?
|
90
|
-
|
91
|
-
type._get(:def)._get(:primitive)&.downcase == 'u8'
|
92
|
-
end
|
93
|
-
|
94
|
-
def decode_sequence(sequence_type, bytes, registry)
|
95
|
-
len, remaining_bytes = decode_compact(bytes)
|
96
|
-
inner_type_id = sequence_type._get(:type)
|
97
|
-
_decode_types([inner_type_id] * len, remaining_bytes, registry)
|
98
|
-
end
|
99
|
-
|
100
|
-
def decode_tuple(tuple_type, bytes, registry)
|
101
|
-
_decode_types(tuple_type, bytes, registry)
|
102
|
-
end
|
103
|
-
|
104
|
-
# {
|
105
|
-
# name: value,
|
106
|
-
# ...
|
107
|
-
# }
|
108
|
-
def decode_composite(composite_type, bytes, registry)
|
109
|
-
fields = composite_type._get(:fields)
|
110
|
-
|
111
|
-
# reduce composite level when composite only has one field without name
|
112
|
-
if fields.length == 1 && fields.first._get(:name).nil?
|
113
|
-
decode(fields.first._get(:type), bytes, registry)
|
114
|
-
else
|
115
|
-
type_name_list = fields.map { |f| f._get(:name) }
|
116
|
-
type_id_list = fields.map { |f| f._get(:type) }
|
117
|
-
|
118
|
-
type_value_list, remaining_bytes = _decode_types(type_id_list, bytes, registry)
|
119
|
-
[
|
120
|
-
if type_name_list.all?(&:nil?)
|
121
|
-
type_value_list
|
122
|
-
else
|
123
|
-
[type_name_list.map(&:to_sym), type_value_list].transpose.to_h
|
124
|
-
end,
|
125
|
-
remaining_bytes
|
126
|
-
]
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
def decode_variant(variant_type, bytes, registry)
|
131
|
-
variants = variant_type._get(:variants)
|
132
|
-
|
133
|
-
index = bytes[0].to_i # TODO: check
|
134
|
-
item = variants.find { |v| v._get(:index) == index } # item is an composite
|
135
|
-
|
136
|
-
raise VariantIndexOutOfRange, "type: #{variant_type}, index: #{index}, bytes: #{bytes}" if item.nil?
|
137
|
-
|
138
|
-
item_name = item._get(:name)
|
139
|
-
item_fields = item._get(:fields)
|
140
|
-
if item_fields.empty?
|
141
|
-
[item_name, bytes[1..]]
|
142
|
-
else
|
143
|
-
item_value, remaining_bytes = decode_composite(item, bytes[1..], registry)
|
144
|
-
[{ item_name.to_sym => item_value }, remaining_bytes]
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
def _decode_types(ids, bytes, registry = {})
|
149
|
-
ScaleRb._decode_each(ids, bytes) do |id, remaining_bytes|
|
150
|
-
decode(id, remaining_bytes, registry)
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
def encode_with_hasher(value, type_id, registry, hasher)
|
155
|
-
value_bytes = encode(type_id, value, registry)
|
156
|
-
Hasher.apply_hasher(hasher, value_bytes)
|
157
|
-
end
|
158
|
-
|
159
|
-
def encode(id, value, registry)
|
160
|
-
type = registry[id]
|
161
|
-
raise TypeNotFound, "id: #{id}" if type.nil?
|
162
|
-
|
163
|
-
type_def = type._get(:def)
|
164
|
-
# debug
|
165
|
-
# p type_def
|
166
|
-
# p value
|
167
|
-
|
168
|
-
return encode_primitive(type_def, value) if type_def._key?(:primitive)
|
169
|
-
return encode_compact(value) if type_def._key?(:compact)
|
170
|
-
return encode_array(type_def._get(:array), value, registry) if type_def._key?(:array)
|
171
|
-
return encode_sequence(type_def._get(:sequence), value, registry) if type_def._key?(:sequence)
|
172
|
-
return encode_tuple(type_def._get(:tuple), value, registry) if type_def._key?(:tuple)
|
173
|
-
return encode_composite(type_def._get(:composite), value, registry) if type_def._key?(:composite)
|
174
|
-
return encode_variant(type_def._get(:variant), value, registry) if type_def._key?(:variant)
|
175
|
-
|
176
|
-
raise TypeNotImplemented, "id: #{id}"
|
177
|
-
end
|
178
|
-
|
179
|
-
def encode_primitive(type_def, value)
|
180
|
-
primitive = type_def._get(:primitive)
|
181
|
-
return ScaleRb.encode_uint(primitive, value) if ScaleRb.uint?(primitive)
|
182
|
-
return ScaleRb.encode_string(value) if ScaleRb.string?(primitive)
|
183
|
-
|
184
|
-
ScaleRb.encode_boolean(value) if ScaleRb.boolean?(primitive)
|
185
|
-
end
|
186
|
-
|
187
|
-
def encode_compact(value)
|
188
|
-
ScaleRb.encode_compact(value)
|
189
|
-
end
|
190
|
-
|
191
|
-
def encode_array(array_type, value, registry)
|
192
|
-
length = array_type._get(:len)
|
193
|
-
inner_type_id = array_type._get(:type)
|
194
|
-
raise ArrayLengthNotEqual, "type: #{array_type}, value: #{value.inspect}" if length != value.length
|
195
|
-
|
196
|
-
_encode_types([inner_type_id] * length, value, registry)
|
197
|
-
end
|
198
|
-
|
199
|
-
def encode_sequence(sequence_type, value, registry)
|
200
|
-
inner_type_id = sequence_type._get(:type)
|
201
|
-
length_bytes = encode_compact(value.length)
|
202
|
-
length_bytes + _encode_types([inner_type_id] * value.length, value, registry)
|
203
|
-
end
|
204
|
-
|
205
|
-
# tuple_type: [type_id1, type_id2, ...]
|
206
|
-
def encode_tuple(tuple_type, value, registry)
|
207
|
-
_encode_types(tuple_type, value, registry)
|
208
|
-
end
|
209
|
-
|
210
|
-
# value:
|
211
|
-
# {
|
212
|
-
# name1: value1,
|
213
|
-
# name2: value2,
|
214
|
-
# ...
|
215
|
-
# }
|
216
|
-
# or
|
217
|
-
# [value1, value2, ...]
|
218
|
-
def encode_composite(composite_type, value, registry)
|
219
|
-
fields = composite_type._get(:fields)
|
220
|
-
# reduce composite level when composite only has one field without name
|
221
|
-
if fields.length == 1 && fields.first._get(:name).nil?
|
222
|
-
# debug
|
223
|
-
# p fields.first._get(:type)
|
224
|
-
# p value
|
225
|
-
encode(fields.first._get(:type), value, registry)
|
226
|
-
else
|
227
|
-
values =
|
228
|
-
if value.instance_of?(Hash)
|
229
|
-
value.values
|
230
|
-
elsif value.instance_of?(Array)
|
231
|
-
value
|
232
|
-
else
|
233
|
-
raise CompositeInvalidValue, "value: #{value}, only hash and array"
|
234
|
-
end
|
235
|
-
|
236
|
-
type_id_list = fields.map { |f| f._get(:type) }
|
237
|
-
_encode_types(type_id_list, values, registry)
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
# value:
|
242
|
-
# {
|
243
|
-
# name: v(Hash)
|
244
|
-
# }
|
245
|
-
# or
|
246
|
-
# the_value(String)
|
247
|
-
def encode_variant(variant_type, value, registry)
|
248
|
-
variants = variant_type._get(:variants)
|
249
|
-
|
250
|
-
name, v = # v: item inner value
|
251
|
-
if value.instance_of?(Hash)
|
252
|
-
[value.keys.first.to_s, value.values.first]
|
253
|
-
elsif value.instance_of?(String)
|
254
|
-
[value, {}]
|
255
|
-
else
|
256
|
-
raise VariantInvalidValue, "type: #{variant_type}, value: #{value}"
|
257
|
-
end
|
258
|
-
|
259
|
-
item = variants.find { |var| var._get(:name) == name }
|
260
|
-
raise VariantItemNotFound, "type: #{variant_type}, name: #{name}" if item.nil?
|
261
|
-
|
262
|
-
# if the variant item has more than one field, the value must be a hash with the same length.
|
263
|
-
# if the variant item has only one field, that means the field is a type id point to a composite. TODO: check the type's fields length
|
264
|
-
if item._get(:fields).length > 1 && item._get(:fields).length != v.length
|
265
|
-
raise VariantFieldsLengthNotMatch,
|
266
|
-
"type: #{variant_type}, \nvalue: #{v}"
|
267
|
-
end
|
268
|
-
|
269
|
-
ScaleRb.encode_uint('u8', item._get(:index)) + encode_composite(item, v, registry)
|
270
|
-
end
|
271
|
-
|
272
|
-
def _encode_types(ids, values, registry)
|
273
|
-
ScaleRb._encode_each(ids, values) do |id, value|
|
274
|
-
encode(id, value, registry)
|
275
|
-
end
|
276
|
-
end
|
277
|
-
|
278
|
-
def _encode_types_with_hashers(ids, values, registry, hashers)
|
279
|
-
ScaleRb._encode_each_with_hashers(ids, values, hashers) do |id, value|
|
280
|
-
encode(id, value, registry)
|
281
|
-
end
|
282
|
-
end
|
283
|
-
end
|
284
|
-
end
|
285
|
-
end
|
data/lib/registry.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ScaleRb
|
4
|
-
# A `registry` is a ruby Hash object, key is the type name, value is the type definition or mapped type name.
|
5
|
-
# A `config` contains the complete versioned type definition for a network.
|
6
|
-
# https://github.com/polkadot-js/api/blob/master/packages/types-known/src/spec/polkadot.ts
|
7
|
-
def self.build_registry_from_config(config, spec_version)
|
8
|
-
version = config[:versioned].find do |item|
|
9
|
-
item[:minmax].include?(spec_version)
|
10
|
-
end
|
11
|
-
config[:shared_types].merge(version.nil? ? {} : version[:types])
|
12
|
-
end
|
13
|
-
end
|