scale_rb 0.4.1 → 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 -6
- data/bin/console +0 -0
- data/bin/setup +0 -0
- data/examples/http_client_1.rb +0 -2
- data/examples/http_client_2.rb +0 -2
- data/examples/ws_client_1.rb +0 -2
- data/examples/ws_client_3.rb +1 -3
- data/examples/ws_client_4.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 +3 -5
- data/lib/{client → scale_rb/client}/ws_client.rb +13 -20
- 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 +22 -30
- data/lib/type_enforcer.rb +170 -0
- data/scale_rb.gemspec +5 -0
- metadata +71 -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
@@ -0,0 +1,128 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ScaleRb
|
4
|
+
module CodecUtils
|
5
|
+
module InternalDecodeUtils
|
6
|
+
extend TypeEnforcer
|
7
|
+
include Types
|
8
|
+
|
9
|
+
__ :decode_uint,
|
10
|
+
{ type: String.constrained(format: /\A[Uu]\d+\z/), bytes: U8Array },
|
11
|
+
DecodeResult[UnsignedInteger]
|
12
|
+
def decode_uint(type, bytes)
|
13
|
+
bit_length = type[1..].to_i
|
14
|
+
byte_length = bit_length / 8
|
15
|
+
raise Codec::NotEnoughBytesError, "type: #{type}" if bytes.length < byte_length
|
16
|
+
|
17
|
+
value = Utils.u8a_to_uint(bytes[0...byte_length].reverse)
|
18
|
+
# debug 'value', value
|
19
|
+
[
|
20
|
+
value,
|
21
|
+
bytes[byte_length..]
|
22
|
+
]
|
23
|
+
end
|
24
|
+
|
25
|
+
__ :decode_int, { type: String.constrained(format: /\A[Ii]\d+\z/), bytes: U8Array }, DecodeResult[Integer]
|
26
|
+
def decode_int(type, bytes)
|
27
|
+
bit_length = type[1..].to_i
|
28
|
+
byte_length = bit_length / 8
|
29
|
+
raise Codec::NotEnoughBytesError, "type: #{type}" if bytes.length < byte_length
|
30
|
+
|
31
|
+
value = Utils.u8a_to_int(bytes[0...byte_length].reverse, bit_length)
|
32
|
+
# debug 'value', value
|
33
|
+
[
|
34
|
+
value,
|
35
|
+
bytes[byte_length..]
|
36
|
+
]
|
37
|
+
end
|
38
|
+
|
39
|
+
__ :decode_str, { bytes: U8Array }, DecodeResult[String]
|
40
|
+
def decode_str(bytes)
|
41
|
+
length, remaining_bytes = _do_decode_compact(bytes)
|
42
|
+
raise Codec::NotEnoughBytesError, 'type: String' if remaining_bytes.length < length
|
43
|
+
|
44
|
+
[Utils.u8a_to_utf8(remaining_bytes[0...length]), remaining_bytes[length..]]
|
45
|
+
end
|
46
|
+
|
47
|
+
__ :decode_boolean, { bytes: U8Array }, DecodeResult[Bool]
|
48
|
+
def decode_boolean(bytes)
|
49
|
+
value = case bytes[0]
|
50
|
+
when 0x00 then false
|
51
|
+
when 0x01 then true
|
52
|
+
else raise Codec::InvalidBytesError, 'type: Boolean'
|
53
|
+
end
|
54
|
+
[value, bytes[1..]]
|
55
|
+
end
|
56
|
+
|
57
|
+
# TODO: inner type decoding
|
58
|
+
__ :decode_compact, { bytes: U8Array }, DecodeResult[UnsignedInteger]
|
59
|
+
def decode_compact(bytes)
|
60
|
+
_do_decode_compact(bytes)
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def _do_decode_compact(bytes)
|
66
|
+
case bytes[0] & 3
|
67
|
+
when 0 then [bytes[0] >> 2, bytes[1..]]
|
68
|
+
when 1 then [Utils.u8a_to_uint(bytes[0..1].reverse) >> 2, bytes[2..]]
|
69
|
+
when 2 then [Utils.u8a_to_uint(bytes[0..3].reverse) >> 2, bytes[4..]]
|
70
|
+
when 3
|
71
|
+
length = 4 + (bytes[0] >> 2)
|
72
|
+
[Utils.u8a_to_uint(bytes[1..length].reverse), bytes[length + 1..]]
|
73
|
+
else
|
74
|
+
raise Codec::Unreachable, 'type: Compact'
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
module InternalEncodeUtils
|
80
|
+
extend TypeEnforcer
|
81
|
+
include Types
|
82
|
+
|
83
|
+
__ :encode_uint, { type: String.constrained(format: /\A[Uu]\d+\z/), value: Integer }, U8Array
|
84
|
+
def encode_uint(type, value)
|
85
|
+
raise InvalidValueError, "type: #{type}, value: #{value.inspect}" unless value.is_a?(::Integer)
|
86
|
+
|
87
|
+
bit_length = type[1..].to_i
|
88
|
+
Utils.int_to_u8a(value, bit_length).reverse
|
89
|
+
end
|
90
|
+
|
91
|
+
__ :encode_int, { type: String.constrained(format: /\A[Ii]\d+\z/), value: Integer }, U8Array
|
92
|
+
def encode_int(_type, _value)
|
93
|
+
raise NotImplemented, 'encode_int'
|
94
|
+
# raise InvalidValueError, "type: #{type}, value: #{value.inspect}" unless value.is_a?(Integer)
|
95
|
+
#
|
96
|
+
# bit_length = type[1..].to_i
|
97
|
+
# Utils.int_to_u8a(value, bit_length).reverse
|
98
|
+
end
|
99
|
+
|
100
|
+
__ :encode_str, { string: String }, U8Array
|
101
|
+
def encode_str(string)
|
102
|
+
body = string.unpack('C*')
|
103
|
+
encode_compact(body.length) + body
|
104
|
+
end
|
105
|
+
|
106
|
+
__ :encode_boolean, { value: Bool }, U8Array
|
107
|
+
def encode_boolean(value)
|
108
|
+
return [0x00] if value == false
|
109
|
+
return [0x01] if value == true
|
110
|
+
|
111
|
+
raise InvalidValueError, "type: Bool, value: #{value.inspect}"
|
112
|
+
end
|
113
|
+
|
114
|
+
__ :encode_compact, { value: Integer }, U8Array
|
115
|
+
def encode_compact(value)
|
116
|
+
return [value << 2] if value.between?(0, 63)
|
117
|
+
return Utils.int_to_u8a(((value << 2) + 1)).reverse if value < 2**14
|
118
|
+
return Utils.int_to_u8a(((value << 2) + 2)).reverse if value < 2**30
|
119
|
+
|
120
|
+
bytes = Utils.int_to_u8a(value).reverse
|
121
|
+
[(((bytes.length - 4) << 2) + 3)] + bytes
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
extend InternalDecodeUtils
|
126
|
+
extend InternalEncodeUtils
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'codec_utils'
|
4
|
+
|
5
|
+
# rubocop:disable all
|
6
|
+
module ScaleRb
|
7
|
+
module Decode
|
8
|
+
extend TypeEnforcer
|
9
|
+
include Types
|
10
|
+
|
11
|
+
__ :decode, { id: Ti, bytes: U8Array, registry: Registry }, DecodeResult[Any]
|
12
|
+
def decode(id, bytes, registry)
|
13
|
+
ScaleRb.logger.debug("Decoding #{id}, bytes: #{bytes.length} bytes")
|
14
|
+
type = registry[id]
|
15
|
+
raise Codec::TypeNotFound, "id: #{id}" if type.nil?
|
16
|
+
|
17
|
+
case type
|
18
|
+
when PrimitiveType then decode_primitive(type, bytes)
|
19
|
+
when CompactType then decode_compact(bytes)
|
20
|
+
when ArrayType then decode_array(type, bytes, registry)
|
21
|
+
when SequenceType then decode_sequence(type, bytes, registry)
|
22
|
+
when TupleType then decode_tuple(type, bytes, registry)
|
23
|
+
when StructType then decode_struct(type, bytes, registry)
|
24
|
+
when UnitType then [[], bytes]
|
25
|
+
when VariantType then decode_variant(type, bytes, registry)
|
26
|
+
else raise Codec::TypeNotImplemented, "id: #{id}, type: #{type}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
__ :decode_primitive, { type: PrimitiveType, bytes: U8Array }, DecodeResult[UnsignedInteger | Integer | String | Bool]
|
31
|
+
def decode_primitive(type, bytes)
|
32
|
+
primitive = type.primitive.to_s
|
33
|
+
ScaleRb.logger.debug("Decoding primitive: #{primitive}, bytes: #{bytes.length} bytes")
|
34
|
+
|
35
|
+
return CodecUtils.decode_uint(primitive, bytes) if primitive.start_with?('U')
|
36
|
+
return CodecUtils.decode_int(primitive, bytes) if primitive.start_with?('I')
|
37
|
+
return CodecUtils.decode_str(bytes) if primitive == 'Str'
|
38
|
+
return CodecUtils.decode_boolean(bytes) if primitive == 'Bool'
|
39
|
+
|
40
|
+
raise Codec::TypeNotImplemented, "decoding primitive: #{primitive}"
|
41
|
+
end
|
42
|
+
|
43
|
+
__ :decode_compact, { bytes: U8Array }, DecodeResult[UnsignedInteger]
|
44
|
+
def decode_compact(bytes)
|
45
|
+
ScaleRb.logger.debug("Decoding compact: bytes: #{bytes.length} bytes")
|
46
|
+
|
47
|
+
CodecUtils.decode_compact(bytes)
|
48
|
+
end
|
49
|
+
|
50
|
+
__ :decode_array, { type: ArrayType, bytes: U8Array, registry: Registry }, DecodeResult[TypedArray[Any]]
|
51
|
+
def decode_array(type, bytes, registry)
|
52
|
+
ScaleRb.logger.debug("Decoding array: #{type}, bytes: #{bytes.length} bytes")
|
53
|
+
|
54
|
+
len = type.len
|
55
|
+
inner_type_id = type.type
|
56
|
+
|
57
|
+
_decode_types([inner_type_id] * len, bytes, registry)
|
58
|
+
end
|
59
|
+
|
60
|
+
__ :decode_sequence, { sequence_type: SequenceType, bytes: U8Array, registry: Registry }, DecodeResult[TypedArray[Any]]
|
61
|
+
def decode_sequence(sequence_type, bytes, registry)
|
62
|
+
ScaleRb.logger.debug("Decoding sequence: #{sequence_type}, bytes: #{bytes.length} bytes")
|
63
|
+
|
64
|
+
len, remaining_bytes = decode_compact(bytes)
|
65
|
+
_decode_types([sequence_type.type] * len, remaining_bytes, registry)
|
66
|
+
end
|
67
|
+
|
68
|
+
__ :decode_tuple, { tuple_type: TupleType, bytes: U8Array, registry: Registry }, DecodeResult[TypedArray[Any] | Any]
|
69
|
+
def decode_tuple(tuple_type, bytes, registry)
|
70
|
+
ScaleRb.logger.debug("Decoding tuple: #{tuple_type}, bytes: #{bytes.length} bytes")
|
71
|
+
|
72
|
+
type_ids = tuple_type.tuple
|
73
|
+
|
74
|
+
# NOTE: If the tuple has only one element, decode that element directly.
|
75
|
+
# This is to make the structure of the decoded result clear.
|
76
|
+
if type_ids.length == 1
|
77
|
+
decode(type_ids.first, bytes, registry)
|
78
|
+
else
|
79
|
+
_decode_types(type_ids, bytes, registry)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
__ :decode_struct, { struct_type: StructType, bytes: U8Array, registry: Registry }, DecodeResult[HashMap[Symbol, Any]]
|
84
|
+
def decode_struct(struct_type, bytes, registry)
|
85
|
+
ScaleRb.logger.debug("Decoding struct: #{struct_type}, bytes: #{bytes.length} bytes")
|
86
|
+
|
87
|
+
fields = struct_type.fields
|
88
|
+
|
89
|
+
names = fields.map { |f| f.name.to_sym }
|
90
|
+
type_ids = fields.map(&:type)
|
91
|
+
|
92
|
+
values, remaining_bytes = _decode_types(type_ids, bytes, registry)
|
93
|
+
[
|
94
|
+
[names, values].transpose.to_h,
|
95
|
+
remaining_bytes
|
96
|
+
]
|
97
|
+
end
|
98
|
+
|
99
|
+
__ :decode_variant, { variant_type: VariantType, bytes: U8Array, registry: Registry }, DecodeResult[Nil | String | Integer | Symbol | HashMap[Symbol, Any]]
|
100
|
+
def decode_variant(variant_type, bytes, registry)
|
101
|
+
ScaleRb.logger.debug("Decoding variant: #{variant_type}, bytes: #{bytes.length} bytes")
|
102
|
+
|
103
|
+
# find the variant by the index
|
104
|
+
index = bytes[0].to_i
|
105
|
+
variant = variant_type.variants.find { |v| v.index == index }
|
106
|
+
raise Codec::VariantIndexOutOfRange, "type: #{variant_type}, index: #{index}, bytes: #{bytes}" if variant.nil?
|
107
|
+
|
108
|
+
# decode the variant
|
109
|
+
case variant
|
110
|
+
when SimpleVariant
|
111
|
+
if variant.name == :None
|
112
|
+
[nil, bytes[1..]]
|
113
|
+
else
|
114
|
+
[
|
115
|
+
variant.name,
|
116
|
+
bytes[1..]
|
117
|
+
]
|
118
|
+
end
|
119
|
+
when TupleVariant
|
120
|
+
value, remainning_bytes = decode_tuple(variant.tuple, bytes[1..], registry)
|
121
|
+
if variant.name == :Some
|
122
|
+
[value, remainning_bytes]
|
123
|
+
else
|
124
|
+
[
|
125
|
+
{ variant.name => value },
|
126
|
+
remainning_bytes
|
127
|
+
]
|
128
|
+
end
|
129
|
+
when StructVariant
|
130
|
+
value, remainning_bytes = decode_struct(variant.struct, bytes[1..], registry)
|
131
|
+
[
|
132
|
+
{ variant.name => value },
|
133
|
+
remainning_bytes
|
134
|
+
]
|
135
|
+
else raise 'Unreachable'
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
private
|
140
|
+
|
141
|
+
# @param type_id [Ti] Type identifier
|
142
|
+
# @param registry [Hash] Registry of types
|
143
|
+
# @return [Bool] True if the type is a U8, false otherwise
|
144
|
+
def _u8?(type_id, registry)
|
145
|
+
type = registry[type_id]
|
146
|
+
raise Codec::TypeNotFound, "id: #{type_id}" if type.nil?
|
147
|
+
|
148
|
+
type.is_a?(ScaleRb::PrimitiveType) && type.primitive == 'U8'
|
149
|
+
end
|
150
|
+
|
151
|
+
# @param type_ids [Array<Ti>] Array of type identifiers
|
152
|
+
# @param bytes [U8Array] Byte array to decode
|
153
|
+
# @param registry [Hash] Registry of types
|
154
|
+
# @return [Array<(Array<Any>, U8Array)>] Decoded values and remaining bytes
|
155
|
+
def _decode_types(type_ids, bytes, registry = {})
|
156
|
+
remaining_bytes = bytes
|
157
|
+
values = type_ids.map do |type_id|
|
158
|
+
value, remaining_bytes = decode(type_id, remaining_bytes, registry)
|
159
|
+
value
|
160
|
+
end
|
161
|
+
[values, remaining_bytes]
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable all
|
4
|
+
module ScaleRb
|
5
|
+
module Encode
|
6
|
+
extend TypeEnforcer
|
7
|
+
include Types
|
8
|
+
|
9
|
+
__ :encode, { id: Ti, value: Any, registry: Registry }, U8Array, level: 3
|
10
|
+
def encode(id, value, registry)
|
11
|
+
ScaleRb.logger.debug("Encoding #{id}, value: #{value}")
|
12
|
+
type = registry[id]
|
13
|
+
raise Codec::TypeNotFound, "id: #{id}" if type.nil?
|
14
|
+
|
15
|
+
case type # type: PortableType
|
16
|
+
when PrimitiveType then encode_primitive(type, value)
|
17
|
+
when CompactType then encode_compact(value)
|
18
|
+
when ArrayType then encode_array(type, value, registry)
|
19
|
+
when SequenceType then encode_sequence(type, value, registry)
|
20
|
+
when TupleType then encode_tuple(type, value, registry)
|
21
|
+
when StructType then encode_struct(type, value, registry)
|
22
|
+
when UnitType then []
|
23
|
+
when VariantType then encode_variant(type, value, registry)
|
24
|
+
else raise Codec::TypeNotImplemented, "encoding id: #{id}, type: #{type}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
__ :encode_primitive, { type: PrimitiveType, value: Any }, U8Array
|
29
|
+
def encode_primitive(type, value)
|
30
|
+
primitive = type.primitive.to_s
|
31
|
+
ScaleRb.logger.debug("Encoding primitive: #{primitive}, value: #{value}")
|
32
|
+
|
33
|
+
return ScaleRb::CodecUtils.encode_uint(primitive, value) if primitive.start_with?('U')
|
34
|
+
return ScaleRb::CodecUtils.encode_int(primitive, value) if primitive.start_with?('I')
|
35
|
+
return ScaleRb::CodecUtils.encode_string(value) if primitive == 'Str'
|
36
|
+
return ScaleRb::CodecUtils.encode_boolean(value) if primitive == 'Bool'
|
37
|
+
|
38
|
+
raise Codec::TypeNotImplemented, "encoding primitive: #{primitive}"
|
39
|
+
end
|
40
|
+
|
41
|
+
__ :encode_compact, { value: Ti }, U8Array
|
42
|
+
def encode_compact(value)
|
43
|
+
ScaleRb.logger.debug("Encoding compact: #{value}")
|
44
|
+
|
45
|
+
ScaleRb::CodecUtils.encode_compact(value)
|
46
|
+
end
|
47
|
+
|
48
|
+
__ :encode_array, { array_type: ArrayType, value: Array.of(Any), registry: Registry }, U8Array
|
49
|
+
def encode_array(array_type, value, registry)
|
50
|
+
ScaleRb.logger.debug("Encoding array: #{array_type}, value: #{value}")
|
51
|
+
|
52
|
+
len = array_type.len
|
53
|
+
inner_type_id = array_type.type
|
54
|
+
|
55
|
+
_encode_types([inner_type_id] * len, value, registry)
|
56
|
+
end
|
57
|
+
|
58
|
+
__ :encode_sequence, { sequence_type: SequenceType, value: Array.of(Any), registry: Registry }, U8Array
|
59
|
+
def encode_sequence(sequence_type, value, registry)
|
60
|
+
ScaleRb.logger.debug("Encoding sequence: #{sequence_type}, value: #{value}")
|
61
|
+
|
62
|
+
len = value.length
|
63
|
+
inner_type_id = sequence_type.type
|
64
|
+
|
65
|
+
encode_compact(len) + _encode_types([inner_type_id] * len, value, registry)
|
66
|
+
end
|
67
|
+
|
68
|
+
__ :encode_tuple, { tuple_type: TupleType, value: Array.of(Any) | Any, registry: Registry }, U8Array
|
69
|
+
def encode_tuple(tuple_type, value, registry)
|
70
|
+
ScaleRb.logger.debug("Encoding tuple: #{tuple_type}, value: #{value}")
|
71
|
+
|
72
|
+
type_ids = tuple_type.tuple
|
73
|
+
|
74
|
+
# For example: if the tuple type is (AccountId32), the value can be a AccountId32
|
75
|
+
# TODO: Check if this is correct
|
76
|
+
value = [value] if type_ids.length == 1
|
77
|
+
|
78
|
+
_encode_types(type_ids, value, registry)
|
79
|
+
end
|
80
|
+
|
81
|
+
__ :encode_struct, { struct_type: StructType, value: Hash.map(Symbol, Any), registry: Registry }, U8Array
|
82
|
+
def encode_struct(struct_type, value, registry)
|
83
|
+
ScaleRb.logger.debug("Encoding struct: #{struct_type}, value: #{value}")
|
84
|
+
|
85
|
+
fields = struct_type.fields
|
86
|
+
|
87
|
+
type_ids = fields.map(&:type)
|
88
|
+
_encode_types(type_ids, value.values, registry)
|
89
|
+
end
|
90
|
+
|
91
|
+
__ :encode_variant, { variant_type: VariantType, value: Nil | String | Integer | Symbol | HashMap[Symbol, Any], registry: Registry }, U8Array
|
92
|
+
def encode_variant(variant_type, value, registry)
|
93
|
+
ScaleRb.logger.debug("Encoding variant: #{variant_type}, value: #{value}")
|
94
|
+
|
95
|
+
if variant_type.option?
|
96
|
+
if value.nil?
|
97
|
+
name = :None
|
98
|
+
else
|
99
|
+
name = :Some
|
100
|
+
end
|
101
|
+
else
|
102
|
+
name = value.is_a?(::Symbol) ? value : value.keys.first
|
103
|
+
end
|
104
|
+
|
105
|
+
variant = variant_type.variants.find { |v| v.name == name }
|
106
|
+
raise Codec::VariantItemNotFound, "type: #{variant_type}, name: #{value}" if variant.nil?
|
107
|
+
|
108
|
+
case variant
|
109
|
+
when SimpleVariant
|
110
|
+
ScaleRb::CodecUtils.encode_uint('U8', variant.index)
|
111
|
+
when TupleVariant
|
112
|
+
# value example1: {:X2=>[{:Parachain=>12}, {:PalletInstance=>34}]}
|
113
|
+
# value.values.first: [[{:Parachain=>12}, {:PalletInstance=>34}]]
|
114
|
+
#
|
115
|
+
# value example2: {:Parachain=>12}
|
116
|
+
# value.values.first: 12
|
117
|
+
ScaleRb::CodecUtils.encode_uint('U8', variant.index) + encode_tuple(variant.tuple, value.values.first, registry)
|
118
|
+
when StructVariant
|
119
|
+
# value example: {
|
120
|
+
# :Transact=>{
|
121
|
+
# :origin_type=>:SovereignAccount,
|
122
|
+
# :require_weight_at_most=>5000000000,
|
123
|
+
# :call=>...
|
124
|
+
# }
|
125
|
+
# }
|
126
|
+
# value.values.first: {
|
127
|
+
# :origin_type=>:SovereignAccount,
|
128
|
+
# :require_weight_at_most=>5000000000,
|
129
|
+
# :call=>...
|
130
|
+
# }
|
131
|
+
ScaleRb::CodecUtils.encode_uint('U8', variant.index) + encode_struct(variant.struct, value.values.first, registry)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
private
|
136
|
+
|
137
|
+
# @param type_ids [Array<Ti>] Array of type identifiers
|
138
|
+
# @param values [Array<Any>] Array of values to encode
|
139
|
+
# @param registry [Registry] Registry of types
|
140
|
+
# @return [U8Array] Encoded bytes
|
141
|
+
def _encode_types(type_ids, values, registry)
|
142
|
+
raise Codec::LengthNotEqualErr, "type_ids: #{type_ids}, values: #{values.inspect}" if type_ids.length != values.length
|
143
|
+
|
144
|
+
type_ids.each_with_index.reduce([]) do |memo, (type_id, i)|
|
145
|
+
memo + encode(type_id, values[i], registry)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
end
|
@@ -8,10 +8,12 @@ module ScaleRb
|
|
8
8
|
class << self
|
9
9
|
# params:
|
10
10
|
# hasher: 'Identity' | 'Twox64Concat' | 'Blake2128Concat'
|
11
|
-
#
|
12
|
-
# return:
|
11
|
+
# bytes: u8a | hex string
|
12
|
+
# return: u8a
|
13
13
|
def apply_hasher(hasher, bytes)
|
14
|
-
|
14
|
+
bytes = Utils.hex_to_u8a(bytes) if bytes.is_a?(::String)
|
15
|
+
|
16
|
+
function_name = Utils.underscore(hasher.to_s.gsub('_', ''))
|
15
17
|
Hasher.send(function_name, bytes)
|
16
18
|
end
|
17
19
|
end
|
@@ -22,7 +24,7 @@ module ScaleRb
|
|
22
24
|
end
|
23
25
|
|
24
26
|
def twox64_concat(bytes)
|
25
|
-
data = bytes
|
27
|
+
data = Utils.u8a_to_utf8(bytes)
|
26
28
|
twox64(data) + bytes
|
27
29
|
end
|
28
30
|
|
@@ -32,24 +34,24 @@ module ScaleRb
|
|
32
34
|
|
33
35
|
def twox64(str)
|
34
36
|
result = XXhash.xxh64 str, 0
|
35
|
-
result.
|
37
|
+
Utils.hex_to_u8a(result.to_s(16)).reverse
|
36
38
|
end
|
37
39
|
|
38
40
|
def twox128(str)
|
39
41
|
bytes = []
|
40
42
|
2.times do |i|
|
41
43
|
result = XXhash.xxh64 str, i
|
42
|
-
bytes += result.
|
44
|
+
bytes += Utils.hex_to_u8a(result.to_s(16)).reverse
|
43
45
|
end
|
44
46
|
bytes
|
45
47
|
end
|
46
48
|
|
47
49
|
def blake2_128(bytes)
|
48
|
-
Blake2b.hex(bytes, 16)
|
50
|
+
Utils.hex_to_u8a(Blake2b.hex(bytes, 16))
|
49
51
|
end
|
50
52
|
|
51
53
|
def blake2_256(bytes)
|
52
|
-
Blake2b.hex(bytes, 32)
|
54
|
+
Utils.hex_to_u8a(Blake2b.hex(bytes, 32))
|
53
55
|
end
|
54
56
|
end
|
55
57
|
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './registry'
|
4
|
+
|
5
|
+
require_relative './metadata_v9'
|
6
|
+
require_relative './metadata_v10'
|
7
|
+
require_relative './metadata_v11'
|
8
|
+
require_relative './metadata_v12'
|
9
|
+
require_relative './metadata_v13'
|
10
|
+
require_relative './metadata_v14'
|
11
|
+
|
12
|
+
# NOTE: Only v14 and later are supported.
|
13
|
+
# https://github.com/paritytech/frame-metadata/blob/main/frame-metadata/src/lib.rs#L85
|
14
|
+
module ScaleRb
|
15
|
+
module Metadata
|
16
|
+
class << self
|
17
|
+
def decode_metadata(hex)
|
18
|
+
bytes = ScaleRb::Utils.hex_to_u8a(hex)
|
19
|
+
|
20
|
+
registry = ScaleRb::Metadata::Registry.new TYPES
|
21
|
+
ti = registry.use('MetadataPrefixed')
|
22
|
+
metadata, = ScaleRb::Codec.decode(ti, bytes, registry)
|
23
|
+
metadata
|
24
|
+
end
|
25
|
+
|
26
|
+
def build_registry(metadata_prefixed)
|
27
|
+
types = ScaleRb::Utils.get(metadata_prefixed, :metadata, :V14, :lookup, :types)
|
28
|
+
ScaleRb::PortableRegistry.new(types)
|
29
|
+
end
|
30
|
+
|
31
|
+
def get_module(pallet_name, metadata_prefixed)
|
32
|
+
metadata = Utils.get(metadata_prefixed, :metadata)
|
33
|
+
version = metadata.keys.first
|
34
|
+
raise NotImplementedError, version unless %i[V14].include?(version)
|
35
|
+
|
36
|
+
Metadata.const_get("Metadata#{version.upcase}").get_module(pallet_name, metadata_prefixed)
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_module_by_index(pallet_index, metadata_prefixed)
|
40
|
+
metadata = Utils.get(metadata_prefixed, :metadata)
|
41
|
+
version = metadata.keys.first.to_sym
|
42
|
+
raise NotImplementedError, version unless %i[V14].include?(version)
|
43
|
+
|
44
|
+
Metadata.const_get("Metadata#{version.upcase}").get_module_by_index(pallet_index, metadata_prefixed)
|
45
|
+
end
|
46
|
+
|
47
|
+
def get_storage_item(pallet_name, item_name, metadata_prefixed)
|
48
|
+
metadata = Utils.get(metadata_prefixed, :metadata)
|
49
|
+
version = metadata.keys.first.to_sym
|
50
|
+
raise NotImplementedError, version unless %i[V14].include?(version)
|
51
|
+
|
52
|
+
Metadata.const_get("Metadata#{version.upcase}").get_storage_item(pallet_name, item_name, metadata_prefixed)
|
53
|
+
end
|
54
|
+
|
55
|
+
def get_calls_type(pallet_name, metadata_prefixed)
|
56
|
+
metadata = Utils.get(metadata_prefixed, :metadata)
|
57
|
+
version = metadata.keys.first.to_sym
|
58
|
+
raise NotImplementedError, version unless %i[V14].include?(version)
|
59
|
+
|
60
|
+
Metadata.const_get("Metadata#{version.upcase}").get_calls_type(pallet_name, metadata_prefixed)
|
61
|
+
end
|
62
|
+
|
63
|
+
def get_calls_type_id(pallet_name, metadata_prefixed)
|
64
|
+
metadata = Utils.get(metadata_prefixed, :metadata)
|
65
|
+
version = metadata.keys.first.to_sym
|
66
|
+
raise NotImplementedError, version unless %i[V14].include?(version)
|
67
|
+
|
68
|
+
Metadata.const_get("Metadata#{version.upcase}").get_calls_type_id(pallet_name, metadata_prefixed)
|
69
|
+
end
|
70
|
+
|
71
|
+
def get_call_type(pallet_name, call_name, metadata_prefixed)
|
72
|
+
metadata = Utils.get(metadata_prefixed, :metadata)
|
73
|
+
version = metadata.keys.first.to_sym
|
74
|
+
raise NotImplementedError, version unless %i[V14].include?(version)
|
75
|
+
|
76
|
+
Metadata.const_get("Metadata#{version.upcase}").get_call_type(pallet_name, call_name, metadata_prefixed)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
TYPES = {
|
81
|
+
Type: 'Str',
|
82
|
+
Bytes: 'Vec<u8>',
|
83
|
+
MetadataPrefixed: {
|
84
|
+
magicNumber: 'U32',
|
85
|
+
metadata: 'Metadata'
|
86
|
+
},
|
87
|
+
Placeholder: 'Null',
|
88
|
+
Metadata: {
|
89
|
+
_enum: {
|
90
|
+
V0: 'Placeholder',
|
91
|
+
V1: 'Placeholder',
|
92
|
+
V2: 'Placeholder',
|
93
|
+
V3: 'Placeholder',
|
94
|
+
V4: 'Placeholder',
|
95
|
+
V5: 'Placeholder',
|
96
|
+
V6: 'Placeholder',
|
97
|
+
V7: 'Placeholder',
|
98
|
+
V8: 'Placeholder',
|
99
|
+
V9: 'MetadataV9',
|
100
|
+
V10: 'MetadataV10',
|
101
|
+
V11: 'MetadataV11',
|
102
|
+
V12: 'MetadataV12',
|
103
|
+
V13: 'MetadataV13',
|
104
|
+
V14: 'MetadataV14'
|
105
|
+
}
|
106
|
+
}
|
107
|
+
}.merge(MetadataV14::TYPES)
|
108
|
+
.merge(MetadataV13::TYPES)
|
109
|
+
.merge(MetadataV12::TYPES)
|
110
|
+
.merge(MetadataV11::TYPES)
|
111
|
+
.merge(MetadataV10::TYPES)
|
112
|
+
.merge(MetadataV9::TYPES)
|
113
|
+
end
|
114
|
+
end
|
@@ -3,23 +3,6 @@
|
|
3
3
|
module ScaleRb
|
4
4
|
module Metadata
|
5
5
|
module MetadataV10
|
6
|
-
class << self
|
7
|
-
def get_module(module_name, metadata)
|
8
|
-
metadata._get(:metadata)._get(:v10)._get(:modules).find do |m|
|
9
|
-
m._get(:name) == module_name
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def get_storage_item(module_name, item_name, metadata)
|
14
|
-
modula = get_module(module_name, metadata)
|
15
|
-
raise "Module `#{module_name}` not found" if modula.nil?
|
16
|
-
|
17
|
-
modula._get(:storage)._get(:items).find do |item|
|
18
|
-
item._get(:name) == item_name
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
6
|
TYPES = {
|
24
7
|
ErrorMetadataV10: 'ErrorMetadataV9',
|
25
8
|
EventMetadataV10: 'EventMetadataV9',
|
@@ -3,23 +3,6 @@
|
|
3
3
|
module ScaleRb
|
4
4
|
module Metadata
|
5
5
|
module MetadataV11
|
6
|
-
class << self
|
7
|
-
def get_module(module_name, metadata)
|
8
|
-
metadata._get(:metadata)._get(:v11)._get(:modules).find do |m|
|
9
|
-
m._get(:name) == module_name
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def get_storage_item(module_name, item_name, metadata)
|
14
|
-
modula = get_module(module_name, metadata)
|
15
|
-
raise "Module `#{module_name}` not found" if modula.nil?
|
16
|
-
|
17
|
-
modula._get(:storage)._get(:items).find do |item|
|
18
|
-
item._get(:name) == item_name
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
6
|
TYPES = {
|
24
7
|
ErrorMetadataV11: 'ErrorMetadataV10',
|
25
8
|
EventMetadataV11: 'EventMetadataV10',
|
@@ -3,23 +3,6 @@
|
|
3
3
|
module ScaleRb
|
4
4
|
module Metadata
|
5
5
|
module MetadataV12
|
6
|
-
class << self
|
7
|
-
def get_module(module_name, metadata)
|
8
|
-
metadata._get(:metadata)._get(:v12)._get(:modules).find do |m|
|
9
|
-
m._get(:name) == module_name
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def get_storage_item(module_name, item_name, metadata)
|
14
|
-
modula = get_module(module_name, metadata)
|
15
|
-
raise "Module `#{module_name}` not found" if modula.nil?
|
16
|
-
|
17
|
-
modula._get(:storage)._get(:items).find do |item|
|
18
|
-
item._get(:name) == item_name
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
6
|
TYPES = {
|
24
7
|
ErrorMetadataV12: 'ErrorMetadataV11',
|
25
8
|
EventMetadataV12: 'EventMetadataV11',
|