scale_rb 0.5.0 → 0.5.2

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.
@@ -10,8 +10,9 @@ module ScaleRb
10
10
  Primitive = Types::Strict::Symbol.enum(
11
11
  :I8, :U8, :I16, :U16, :I32, :U32, :I64, :U64, :I128, :U128, :I256, :U256, :Bool, :Str, :Char
12
12
  )
13
- Ti = Types::Strict::Integer.constrained(gteq: 0)
14
- U8 = Types::Strict::Integer.constrained(gteq: 0, lt: 256)
13
+ Ti = Types::Strict::Integer | Types::Strict::String
14
+ # U8 = Types::Strict::Integer.constrained(gteq: 0, lt: 256)
15
+ U8 = Types::Strict::Integer
15
16
  U8Array = Types::Strict::Array.of(U8)
16
17
  Hex = Types::Strict::String.constrained(format: /\A0x[0-9a-fA-F]+\z/)
17
18
 
@@ -23,9 +24,15 @@ module ScaleRb
23
24
  UnsignedInteger = Types::Strict::Integer.constrained(gteq: 0)
24
25
  TypedArray = ->(type) { Types::Array.of(type) }
25
26
 
27
+ class Param < Dry::Struct
28
+ attribute :name, Types::Strict::String
29
+ attribute? :type, Ti
30
+ end
31
+
26
32
  class Base < Dry::Struct
27
33
  attribute? :registry, Registry
28
34
  attribute? :path, Types::Strict::Array.of(Types::Strict::String)
35
+ attribute? :params, Types::Strict::Array.of(Param)
29
36
 
30
37
  def t(type_id)
31
38
  raise 'No registry' unless registry
@@ -1,3 +1,3 @@
1
1
  module ScaleRb
2
- VERSION = '0.5.0'
2
+ VERSION = '0.5.2'
3
3
  end
data/lib/scale_rb.rb CHANGED
@@ -21,16 +21,18 @@ require 'type_enforcer'
21
21
 
22
22
  require 'scale_rb/types'
23
23
  require 'scale_rb/portable_registry'
24
+ require 'scale_rb/old_registry'
24
25
  require 'scale_rb/codec'
25
26
 
26
27
  require 'scale_rb/metadata/metadata'
27
28
 
28
29
  require 'scale_rb/hasher'
29
30
  require 'scale_rb/storage_helper'
30
- require 'scale_rb/call_helper'
31
+ require 'scale_rb/extrinsic_helper'
31
32
 
32
33
  require 'address'
33
34
 
34
35
  # clients
36
+ require 'scale_rb/client/client_share'
35
37
  require 'scale_rb/client/http_client'
36
38
  require 'scale_rb/client/ws_client'
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.5.0
4
+ version: 0.5.2
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-10-13 00:00:00.000000000 Z
11
+ date: 2024-12-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base58
@@ -160,6 +160,7 @@ files:
160
160
  - bin/setup
161
161
  - examples/http_client_1.rb
162
162
  - examples/http_client_2.rb
163
+ - examples/http_client_3.rb
163
164
  - examples/ws_client_1.rb
164
165
  - examples/ws_client_2.rb
165
166
  - examples/ws_client_3.rb
@@ -170,13 +171,14 @@ files:
170
171
  - lib/custom_assign.rb
171
172
  - lib/scale_rb.rb
172
173
  - lib/scale_rb/call_helper.rb
173
- - lib/scale_rb/client/client_ext.rb
174
+ - lib/scale_rb/client/client_share.rb
174
175
  - lib/scale_rb/client/http_client.rb
175
176
  - lib/scale_rb/client/ws_client.rb
176
177
  - lib/scale_rb/codec.rb
177
178
  - lib/scale_rb/codec_utils.rb
178
179
  - lib/scale_rb/decode.rb
179
180
  - lib/scale_rb/encode.rb
181
+ - lib/scale_rb/extrinsic_helper.rb
180
182
  - lib/scale_rb/hasher.rb
181
183
  - lib/scale_rb/metadata/metadata.rb
182
184
  - lib/scale_rb/metadata/metadata_v10.rb
@@ -185,8 +187,7 @@ files:
185
187
  - lib/scale_rb/metadata/metadata_v13.rb
186
188
  - lib/scale_rb/metadata/metadata_v14.rb
187
189
  - 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/old_registry.rb
190
191
  - lib/scale_rb/portable_registry.rb
191
192
  - lib/scale_rb/storage_helper.rb
192
193
  - lib/scale_rb/types.rb
@@ -216,7 +217,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
216
217
  - !ruby/object:Gem::Version
217
218
  version: '0'
218
219
  requirements: []
219
- rubygems_version: 3.5.16
220
+ rubygems_version: 3.5.21
220
221
  signing_key:
221
222
  specification_version: 4
222
223
  summary: A Ruby SCALE Codec Library, and, Substrate RPC Client
@@ -1,263 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative './type_exp'
4
- require_relative '../types'
5
-
6
- # rubocop:disable all
7
- module ScaleRb
8
- module Metadata
9
- class Registry
10
- include Types
11
-
12
- # Map name to index of type in `types` array
13
- # % lookup :: String -> Integer
14
- attr_reader :lookup
15
-
16
- # % keys :: Integer -> String
17
- attr_reader :keys
18
-
19
- # % types :: Array<PortableType>
20
- attr_reader :types
21
-
22
- attr_reader :old_types
23
-
24
- # % initialize :: Hash<Symbol, Any> -> void
25
- def initialize(old_types)
26
- @old_types = old_types
27
- @lookup = {}
28
- @keys = {}
29
- @types = []
30
-
31
- build()
32
- end
33
-
34
- def build()
35
- @old_types.keys.each do |name|
36
- use(name.to_s)
37
- end
38
- end
39
-
40
- def [](index)
41
- @types[index]
42
- end
43
-
44
- def inspect
45
- "registry(#{@types.length} types)"
46
- end
47
-
48
- def to_s
49
- @types.map.with_index do |type, index|
50
- "#{@keys[index]} => #{type.to_s}"
51
- end.join("\n")
52
- end
53
-
54
- # % use :: String -> Integer
55
- def use(old_type_exp)
56
- raise "Empty old_type_exp: #{old_type_exp}" if old_type_exp.nil? || old_type_exp.strip == ''
57
-
58
- ast_type = TypeExp.parse(old_type_exp)
59
- raise "No AST type for #{old_type_exp}" if ast_type.nil?
60
-
61
- key = ast_type.to_s
62
- ti = lookup[key]
63
- return ti if ti
64
-
65
- ti = @types.length
66
- @types[ti] = "Placeholder"
67
- @lookup[key] = ti
68
- @keys[ti] = key
69
- @types[ti] = build_portable_type(ast_type)
70
- ti
71
- end
72
-
73
- # % build_portable_type :: NamedType | ArrayType | TupleType -> PortableType
74
- # __ :build_portable_type, { ast_type: TypedArray[TypeExp::ArrayType | TypeExp::TupleType | TypeExp::NamedType] } => PortableType
75
- def build_portable_type(ast_type)
76
- case ast_type
77
- when TypeExp::ArrayType
78
- ArrayType.new(use(ast_type.item), ast_type.len, registry: self)
79
- when TypeExp::TupleType
80
- TupleType.new(ast_type.params.map { |param| use(param) })
81
- when TypeExp::NamedType
82
- build_portable_type_from_named_type(ast_type)
83
- else
84
- raise "Unknown type: #{ast_type.class}"
85
- end
86
- end
87
-
88
- # % build_portable_type_from_named_type :: NamedType -> PortableType
89
- def build_portable_type_from_named_type(named_type)
90
- name = named_type.name
91
- params = named_type.params
92
-
93
- definition = @old_types[name.to_sym]
94
- return build_from_definition(name, definition) if definition
95
-
96
- primitive = as_primitive(name)
97
- return primitive if primitive
98
-
99
- case name
100
- when 'Vec'
101
- item_index = use(params[0].to_s)
102
- SequenceType.new(type: item_index, registry: self)
103
- when 'Option'
104
- item_index = use(params[0].to_s)
105
- VariantType.option(item_index, self)
106
- when 'Result'
107
- ok_index = use(params[0].to_s)
108
- err_index = use(params[1].to_s)
109
- VariantType.result(ok_index, err_index, self)
110
- when 'Compact'
111
- # item_index = use(params[0].to_s)
112
- # CompactType.new(type: item_index, registry: self)
113
- CompactType.new
114
- when 'Null'
115
- UnitType.new
116
- else
117
- raise "Unknown type: #{name}"
118
- end
119
- end
120
-
121
- # % as_primitive :: String -> PrimitiveType | nil
122
- def as_primitive(name)
123
- case name.downcase
124
- when /^i\d+$/
125
- PrimitiveType.new(primitive: "I#{name[1..]}".to_sym)
126
- when /^u\d+$/
127
- PrimitiveType.new(primitive: "U#{name[1..]}".to_sym)
128
- when /^bool$/
129
- PrimitiveType.new(primitive: :Bool)
130
- when /^str$/, /^text$/
131
- PrimitiveType.new(primitive: :Str)
132
- else
133
- nil
134
- end
135
- end
136
-
137
- # % build_from_definition :: String -> OldTypeDefinition -> PortableType | TypeAlias
138
- #
139
- # type OldTypeDefinition = String | OldEnumDefinition | OldStructDefinition
140
- # type OldEnumDefinition = {
141
- # _enum: String[] | Hash<Symbol, Any>,
142
- # }
143
- # type OldStructDefinition = {
144
- # _struct: Hash<Symbol, Any>
145
- # }
146
- def build_from_definition(name, definition) # rubocop:disable Metrics/MethodLength
147
- case definition
148
- when String
149
- # TypeAlias.new(name, use(definition))
150
- alias_type_id = use(definition)
151
- # p "alias_type_id: #{alias_type_id}"
152
- types[alias_type_id]
153
- when Hash
154
- if definition[:_enum]
155
- _build_portable_type_from_enum_definition(definition)
156
- elsif definition[:_set]
157
- raise 'Sets are not supported'
158
- else
159
- _build_portable_type_from_struct_definition(definition)
160
- end
161
- end
162
- end
163
-
164
- private
165
-
166
- def _indexed_enum?(definition)
167
- definition[:_enum].is_a?(::Hash) && definition[:_enum].values.all? { |value| value.is_a?(::Integer) }
168
- end
169
-
170
- # % _build_portable_type_from_enum_definition :: Hash<Symbol, Any> -> VariantType
171
- def _build_portable_type_from_enum_definition(definition)
172
- variants =
173
- if definition[:_enum].is_a?(::Array)
174
- # Simple array enum:
175
- # {
176
- # _enum: ['A', 'B', 'C']
177
- # }
178
- definition[:_enum].map.with_index do |variant_name, index|
179
- SimpleVariant.new(name: variant_name.to_sym, index:)
180
- end
181
- elsif definition[:_enum].is_a?(::Hash)
182
- if _indexed_enum?(definition)
183
- # Indexed enum:
184
- # {
185
- # _enum: {
186
- # Variant1: 0,
187
- # Variant2: 1,
188
- # Variant3: 2
189
- # }
190
- # }
191
- definition[:_enum].map do |variant_name, index|
192
- SimpleVariant.new(name: variant_name, index:)
193
- end
194
- else
195
- # Mixed enum:
196
- # {
197
- # _enum: {
198
- # A: 'u32',
199
- # B: {a: 'u32', b: 'u32'},
200
- # C: null,
201
- # D: ['u32', 'u32']
202
- # }
203
- # }
204
- definition[:_enum].map.with_index do |(variant_name, variant_def), index|
205
- case variant_def
206
- when ::String
207
- TupleVariant.new(
208
- name: variant_name,
209
- index:,
210
- tuple: TupleType.new(
211
- tuple: [use(variant_def)],
212
- registry: self
213
- ),
214
- )
215
- when ::Array
216
- TupleVariant.new(
217
- name: variant_name,
218
- index:,
219
- tuple: TupleType.new(
220
- tuple: variant_def.map { |field_type| use(field_type) },
221
- registry: self
222
- )
223
- )
224
- when ::Hash
225
- StructVariant.new(
226
- name: variant_name,
227
- index:,
228
- struct: StructType.new(
229
- fields: variant_def.map do |field_name, field_type|
230
- Field.new(name: field_name.to_s, type: use(field_type))
231
- end,
232
- registry: self
233
- )
234
- )
235
- else
236
- raise "Unknown variant type for #{variant_name}: #{variant_def.class}"
237
- end
238
- end
239
- end
240
- end
241
- VariantType.new(variants:, registry: self)
242
- end
243
-
244
- # % _build_portable_type_from_struct_definition :: Hash<Symbol, Any> -> StructType
245
- def _build_portable_type_from_struct_definition(definition)
246
- fields = definition.map do |field_name, field_type|
247
- Field.new(name: field_name.to_s, type: use(field_type))
248
- end
249
- StructType.new(fields:, registry: self)
250
- end
251
- end
252
- end
253
- end
254
-
255
- # require_relative '../../metadata/metadata'
256
-
257
- # begin
258
- # registry = ScaleRb::Metadata::Registry.new ScaleRb::Metadata::TYPES
259
- # puts registry
260
- # rescue StandardError => e
261
- # puts e.message
262
- # puts e.backtrace.join("\n")
263
- # end
@@ -1,286 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ScaleRb
4
- module Metadata
5
- module TypeExp
6
- class Tokenizer
7
- attr_reader :tokens, :index
8
-
9
- # % tokenize :: String -> [String]
10
- def initialize(type_exp)
11
- @tokens = tokenize(type_exp)
12
- @index = 0
13
- end
14
-
15
- # % next_token :: -> String
16
- def next_token
17
- token = @tokens[@index]
18
- @index += 1
19
- token
20
- end
21
-
22
- # % peek_token :: -> String
23
- def peek_token
24
- @tokens[@index]
25
- end
26
-
27
- # % eof? :: -> Bool
28
- def eof?
29
- @index >= @tokens.length
30
- end
31
-
32
- private
33
-
34
- def tokenize(type_exp)
35
- tokens = []
36
- current_token = ''
37
-
38
- type_exp.each_char do |char|
39
- case char
40
- when /[a-zA-Z0-9_]/
41
- current_token += char
42
- when ':', '<', '>', '(', ')', '[', ']', ',', ';', '&', "'"
43
- tokens << current_token unless current_token.empty?
44
- if char == ':' && tokens.last == ':'
45
- tokens[-1] = '::'
46
- else
47
- tokens << char
48
- end
49
- current_token = ''
50
- when /\s/
51
- tokens << current_token unless current_token.empty?
52
- current_token = ''
53
- else
54
- raise abort
55
- end
56
- end
57
-
58
- tokens << current_token unless current_token.empty?
59
- tokens
60
- end
61
- end
62
-
63
- class NamedType
64
- attr_reader :name, :params
65
-
66
- def initialize(name, params)
67
- @name = name
68
- @params = params
69
- end
70
-
71
- def to_s
72
- params.empty? ? name : "#{name}<#{params.map(&:to_s).join(', ')}>"
73
- end
74
- end
75
-
76
- class ArrayType
77
- attr_reader :item, :len
78
-
79
- def initialize(item, len)
80
- @item = item
81
- @len = len
82
- end
83
-
84
- def to_s
85
- "[#{item}; #{len}]"
86
- end
87
- end
88
-
89
- class TupleType
90
- attr_reader :params
91
-
92
- def initialize(params)
93
- @params = params
94
- end
95
-
96
- def to_s
97
- "(#{params.map(&:to_s).join(', ')})"
98
- end
99
- end
100
-
101
- # % print :: NamedType | ArrayType | TupleType -> String
102
- def self.print(type)
103
- type.to_s
104
- end
105
-
106
- # % parse :: String -> NamedType | ArrayType | TupleType
107
- def self.parse(type_exp)
108
- TypeExpParser.new(type_exp).parse
109
- end
110
-
111
- class TypeExpParser
112
- def initialize(type_exp)
113
- @type_exp = type_exp
114
- @tokenizer = Tokenizer.new(type_exp)
115
- @current_token = @tokenizer.next_token
116
- end
117
-
118
- def parse
119
- build_type
120
- end
121
-
122
- private
123
-
124
- # Consume and return the current token, or nil if it doesn't equal the expected token.
125
- def expect(token)
126
- return unless @current_token == token
127
-
128
- current_token = @current_token
129
- @current_token = @tokenizer.next_token
130
- current_token
131
- end
132
-
133
- def expect!(token)
134
- expect(token) || raise("Expected #{token}, got #{@current_token}")
135
- end
136
-
137
- # Consume and return the current token if it matches the expected regex pattern.
138
- def expect_regex(pattern)
139
- return unless pattern.match?(@current_token)
140
-
141
- current_token = @current_token
142
- @current_token = @tokenizer.next_token
143
- current_token
144
- end
145
-
146
- def expect_regex!(pattern)
147
- expect_regex(pattern) || raise("Expected current token matching #{pattern.inspect}, got #{@current_token}")
148
- end
149
-
150
- # Consume and return a natural number (integer) if the current token matches.
151
- def expect_nat
152
- expect_regex(/^\d+$/)&.to_i
153
- end
154
-
155
- def expect_nat!
156
- expect_nat || raise("Expected natural number, got #{@current_token}")
157
- end
158
-
159
- def expect_name
160
- expect_regex(/^[a-zA-Z]\w*$/)
161
- end
162
-
163
- def expect_name!
164
- expect_name || raise("Expected name, got #{@current_token}")
165
- end
166
-
167
- def list(sep, &block)
168
- result = []
169
- item = block.call
170
- return result if item.nil?
171
-
172
- result << item
173
- while expect(sep)
174
- item = block.call
175
- break if item.nil? # (A, B,)
176
-
177
- result << item
178
- end
179
- result
180
- end
181
-
182
- def build_tuple_type
183
- return nil unless expect('(')
184
-
185
- params = list(',') { build_type }
186
- expect!(')')
187
-
188
- TupleType.new(params)
189
- end
190
-
191
- # [u8; 16; H128]
192
- # [u8; 16]
193
- def build_array_type
194
- return nil unless expect('[')
195
-
196
- item = build_type
197
- raise "Expected array item, got #{@current_token}" if item.nil?
198
-
199
- expect!(';')
200
- len = expect_nat!
201
-
202
- # [u8; 16; H128]
203
- if expect(';')
204
- expect_name! # Just consume the name
205
- end
206
-
207
- expect!(']')
208
- ArrayType.new(item, len)
209
- end
210
-
211
- def build_named_type
212
- name = nil
213
- trait = nil
214
- item = nil
215
-
216
- if expect('<')
217
- # Handle trait syntax: <T::Trait as OtherTrait>::Type
218
- # name trait item
219
- # '<T::InherentOfflineReport as InherentOfflineReport>::Inherent' -> 'InherentOfflineReport'
220
- # '<T::Balance as HasCompact>' -> 'Compact<Balance>'
221
- # '<T as Trait<I>>::Proposal' -> 'Proposal'
222
- name = build_named_type.name
223
- expect!('as')
224
- trait = build_named_type.name
225
- expect!('>')
226
- else
227
- name = expect_name
228
- return if name.nil?
229
- end
230
-
231
- # Consume the :: and get the next name
232
- item = expect_name while expect('::')
233
-
234
- # Handle special cases
235
- # From subsquid's code. But where are these coming from?
236
- if name == 'InherentOfflineReport' && name == trait && item == 'Inherent'
237
- # Do nothing
238
- elsif name == 'exec' && item == 'StorageKey'
239
- name = 'ContractStorageKey'
240
- elsif name == 'Lookup' && item == 'Source'
241
- name = 'LookupSource'
242
- elsif name == 'Lookup' && item == 'Target'
243
- name = 'LookupTarget'
244
- elsif item
245
- # '<T::Balance as HasCompact>::Item' will raise error
246
- raise "Expected item, got #{item}" if trait == 'HasCompact'
247
-
248
- name = item
249
- elsif trait == 'HasCompact' # '<T::Balance as HasCompact>'
250
- return NamedType.new('Compact', [NamedType.new(name, [])])
251
- end
252
-
253
- NamedType.new(name, type_parameters)
254
- end
255
-
256
- def type_parameters
257
- if expect('<')
258
- params = list(',') { expect_nat || build_type }
259
- expect!('>')
260
- else
261
- params = []
262
- end
263
-
264
- params
265
- end
266
-
267
- # &[u8]
268
- # &'static [u8]
269
- def build_pointer_bytes
270
- return nil unless expect('&') # &
271
-
272
- expect("'") && expect!('static')
273
- expect!('[')
274
- expect!('u8')
275
- expect!(']')
276
- NamedType.new('Vec', [NamedType.new('u8', [])])
277
- end
278
-
279
- # % build_type :: TupleType | ArrayType | NamedType
280
- def build_type
281
- build_tuple_type || build_array_type || build_named_type || build_pointer_bytes
282
- end
283
- end
284
- end
285
- end
286
- end