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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/devcontainer.json +21 -0
  3. data/Dockerfile +16 -0
  4. data/Gemfile +4 -4
  5. data/README.md +19 -6
  6. data/bin/console +0 -0
  7. data/bin/setup +0 -0
  8. data/examples/http_client_1.rb +0 -2
  9. data/examples/http_client_2.rb +0 -2
  10. data/examples/ws_client_1.rb +0 -2
  11. data/examples/ws_client_3.rb +1 -3
  12. data/examples/ws_client_4.rb +0 -2
  13. data/exe/metadata +9 -11
  14. data/lib/address.rb +1 -1
  15. data/lib/custom_assign.rb +92 -0
  16. data/lib/scale_rb/call_helper.rb +42 -0
  17. data/lib/{client → scale_rb/client}/client_ext.rb +12 -13
  18. data/lib/{client → scale_rb/client}/http_client.rb +3 -5
  19. data/lib/{client → scale_rb/client}/ws_client.rb +13 -20
  20. data/lib/scale_rb/codec.rb +25 -0
  21. data/lib/scale_rb/codec_utils.rb +128 -0
  22. data/lib/scale_rb/decode.rb +164 -0
  23. data/lib/scale_rb/encode.rb +150 -0
  24. data/lib/{hasher.rb → scale_rb/hasher.rb} +10 -8
  25. data/lib/scale_rb/metadata/metadata.rb +114 -0
  26. data/lib/{metadata → scale_rb/metadata}/metadata_v10.rb +0 -17
  27. data/lib/{metadata → scale_rb/metadata}/metadata_v11.rb +0 -17
  28. data/lib/{metadata → scale_rb/metadata}/metadata_v12.rb +0 -17
  29. data/lib/{metadata → scale_rb/metadata}/metadata_v13.rb +0 -17
  30. data/lib/{metadata → scale_rb/metadata}/metadata_v14.rb +18 -18
  31. data/lib/{metadata → scale_rb/metadata}/metadata_v9.rb +0 -17
  32. data/lib/scale_rb/metadata/registry.rb +263 -0
  33. data/lib/scale_rb/metadata/type_exp.rb +286 -0
  34. data/lib/scale_rb/portable_registry.rb +133 -0
  35. data/lib/{storage_helper.rb → scale_rb/storage_helper.rb} +16 -4
  36. data/lib/scale_rb/types.rb +233 -0
  37. data/lib/scale_rb/utils.rb +125 -0
  38. data/lib/scale_rb/version.rb +1 -1
  39. data/lib/scale_rb.rb +22 -30
  40. data/lib/type_enforcer.rb +170 -0
  41. data/scale_rb.gemspec +5 -0
  42. metadata +71 -19
  43. data/lib/codec.rb +0 -450
  44. data/lib/metadata/metadata.rb +0 -137
  45. data/lib/monkey_patching.rb +0 -115
  46. data/lib/portable_codec.rb +0 -285
  47. 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
- # bytes: u8 array
12
- # return: u8 array
11
+ # bytes: u8a | hex string
12
+ # return: u8a
13
13
  def apply_hasher(hasher, bytes)
14
- function_name = hasher.gsub('_', '')._underscore
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._to_utf8
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._to_bytes.reverse
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._to_bytes.reverse
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)._to_bytes
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)._to_bytes
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',