scale_rb 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
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.1
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-14 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,269 +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 [](identifier)
41
- if identifier.is_a?(::Integer)
42
- @types[identifier]
43
- elsif identifier.is_a?(::String)
44
- @types[use(identifier)]
45
- else
46
- raise "Unknown identifier type: #{identifier.class}"
47
- end
48
- end
49
-
50
- def inspect
51
- "registry(#{@types.length} types)"
52
- end
53
-
54
- def to_s
55
- @types.map.with_index do |type, index|
56
- "#{@keys[index]} => #{type.to_s}"
57
- end.join("\n")
58
- end
59
-
60
- # % use :: String -> Integer
61
- def use(old_type_exp)
62
- raise "Empty old_type_exp: #{old_type_exp}" if old_type_exp.nil? || old_type_exp.strip == ''
63
-
64
- ast_type = TypeExp.parse(old_type_exp)
65
- raise "No AST type for #{old_type_exp}" if ast_type.nil?
66
-
67
- key = ast_type.to_s
68
- ti = lookup[key]
69
- return ti if ti
70
-
71
- ti = @types.length
72
- @types[ti] = "Placeholder"
73
- @lookup[key] = ti
74
- @keys[ti] = key
75
- @types[ti] = build_portable_type(ast_type)
76
- ti
77
- end
78
-
79
- # % build_portable_type :: NamedType | ArrayType | TupleType -> PortableType
80
- # __ :build_portable_type, { ast_type: TypedArray[TypeExp::ArrayType | TypeExp::TupleType | TypeExp::NamedType] } => PortableType
81
- def build_portable_type(ast_type)
82
- case ast_type
83
- when TypeExp::ArrayType
84
- ArrayType.new(use(ast_type.item), ast_type.len, registry: self)
85
- when TypeExp::TupleType
86
- TupleType.new(ast_type.params.map { |param| use(param) })
87
- when TypeExp::NamedType
88
- build_portable_type_from_named_type(ast_type)
89
- else
90
- raise "Unknown type: #{ast_type.class}"
91
- end
92
- end
93
-
94
- # % build_portable_type_from_named_type :: NamedType -> PortableType
95
- def build_portable_type_from_named_type(named_type)
96
- name = named_type.name
97
- params = named_type.params
98
-
99
- definition = @old_types[name.to_sym]
100
- return build_from_definition(name, definition) if definition
101
-
102
- primitive = as_primitive(name)
103
- return primitive if primitive
104
-
105
- case name
106
- when 'Vec'
107
- item_index = use(params[0].to_s)
108
- SequenceType.new(type: item_index, registry: self)
109
- when 'Option'
110
- item_index = use(params[0].to_s)
111
- VariantType.option(item_index, self)
112
- when 'Result'
113
- ok_index = use(params[0].to_s)
114
- err_index = use(params[1].to_s)
115
- VariantType.result(ok_index, err_index, self)
116
- when 'Compact'
117
- # item_index = use(params[0].to_s)
118
- # CompactType.new(type: item_index, registry: self)
119
- CompactType.new
120
- when 'Null'
121
- UnitType.new
122
- else
123
- raise "Unknown type: #{name}"
124
- end
125
- end
126
-
127
- # % as_primitive :: String -> PrimitiveType | nil
128
- def as_primitive(name)
129
- case name.downcase
130
- when /^i\d+$/
131
- PrimitiveType.new(primitive: "I#{name[1..]}".to_sym)
132
- when /^u\d+$/
133
- PrimitiveType.new(primitive: "U#{name[1..]}".to_sym)
134
- when /^bool$/
135
- PrimitiveType.new(primitive: :Bool)
136
- when /^str$/, /^text$/
137
- PrimitiveType.new(primitive: :Str)
138
- else
139
- nil
140
- end
141
- end
142
-
143
- # % build_from_definition :: String -> OldTypeDefinition -> PortableType | TypeAlias
144
- #
145
- # type OldTypeDefinition = String | OldEnumDefinition | OldStructDefinition
146
- # type OldEnumDefinition = {
147
- # _enum: String[] | Hash<Symbol, Any>,
148
- # }
149
- # type OldStructDefinition = {
150
- # _struct: Hash<Symbol, Any>
151
- # }
152
- def build_from_definition(name, definition) # rubocop:disable Metrics/MethodLength
153
- case definition
154
- when String
155
- # TypeAlias.new(name, use(definition))
156
- alias_type_id = use(definition)
157
- # p "alias_type_id: #{alias_type_id}"
158
- types[alias_type_id]
159
- when Hash
160
- if definition[:_enum]
161
- _build_portable_type_from_enum_definition(definition)
162
- elsif definition[:_set]
163
- raise 'Sets are not supported'
164
- else
165
- _build_portable_type_from_struct_definition(definition)
166
- end
167
- end
168
- end
169
-
170
- private
171
-
172
- def _indexed_enum?(definition)
173
- definition[:_enum].is_a?(::Hash) && definition[:_enum].values.all? { |value| value.is_a?(::Integer) }
174
- end
175
-
176
- # % _build_portable_type_from_enum_definition :: Hash<Symbol, Any> -> VariantType
177
- def _build_portable_type_from_enum_definition(definition)
178
- variants =
179
- if definition[:_enum].is_a?(::Array)
180
- # Simple array enum:
181
- # {
182
- # _enum: ['A', 'B', 'C']
183
- # }
184
- definition[:_enum].map.with_index do |variant_name, index|
185
- SimpleVariant.new(name: variant_name.to_sym, index:)
186
- end
187
- elsif definition[:_enum].is_a?(::Hash)
188
- if _indexed_enum?(definition)
189
- # Indexed enum:
190
- # {
191
- # _enum: {
192
- # Variant1: 0,
193
- # Variant2: 1,
194
- # Variant3: 2
195
- # }
196
- # }
197
- definition[:_enum].map do |variant_name, index|
198
- SimpleVariant.new(name: variant_name, index:)
199
- end
200
- else
201
- # Mixed enum:
202
- # {
203
- # _enum: {
204
- # A: 'u32',
205
- # B: {a: 'u32', b: 'u32'},
206
- # C: null,
207
- # D: ['u32', 'u32']
208
- # }
209
- # }
210
- definition[:_enum].map.with_index do |(variant_name, variant_def), index|
211
- case variant_def
212
- when ::String
213
- TupleVariant.new(
214
- name: variant_name,
215
- index:,
216
- tuple: TupleType.new(
217
- tuple: [use(variant_def)],
218
- registry: self
219
- ),
220
- )
221
- when ::Array
222
- TupleVariant.new(
223
- name: variant_name,
224
- index:,
225
- tuple: TupleType.new(
226
- tuple: variant_def.map { |field_type| use(field_type) },
227
- registry: self
228
- )
229
- )
230
- when ::Hash
231
- StructVariant.new(
232
- name: variant_name,
233
- index:,
234
- struct: StructType.new(
235
- fields: variant_def.map do |field_name, field_type|
236
- Field.new(name: field_name.to_s, type: use(field_type))
237
- end,
238
- registry: self
239
- )
240
- )
241
- else
242
- raise "Unknown variant type for #{variant_name}: #{variant_def.class}"
243
- end
244
- end
245
- end
246
- end
247
- VariantType.new(variants:, registry: self)
248
- end
249
-
250
- # % _build_portable_type_from_struct_definition :: Hash<Symbol, Any> -> StructType
251
- def _build_portable_type_from_struct_definition(definition)
252
- fields = definition.map do |field_name, field_type|
253
- Field.new(name: field_name.to_s, type: use(field_type))
254
- end
255
- StructType.new(fields:, registry: self)
256
- end
257
- end
258
- end
259
- end
260
-
261
- # require_relative '../../metadata/metadata'
262
-
263
- # begin
264
- # registry = ScaleRb::Metadata::Registry.new ScaleRb::Metadata::TYPES
265
- # puts registry
266
- # rescue StandardError => e
267
- # puts e.message
268
- # puts e.backtrace.join("\n")
269
- # 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