scale_rb 0.5.1 → 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.
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