scale_rb 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 15825760ac8babb0cfa263f8cdaf72c8cdad02cc24c5c7816d1ff6febf6db8de
4
- data.tar.gz: a93953348decaf1fb7f220a9e0929e84e7ba4ee3ae7c53562c2064cea6a4d892
3
+ metadata.gz: cb19be98106d9f8331a9be9812f6252c23d6913cbd98cedcae34bf1a464e7b90
4
+ data.tar.gz: cff1e034d85f130ed7d149628647f020adb9ffc532d9646bceda054007d6bf14
5
5
  SHA512:
6
- metadata.gz: 6abb7a322f18aa546886081a03775824b02a988389572ab58c4ecbf58fa130c1391fb46d5ef8355e61752d0add3690085758f9b7a2e27ab4080ba57630eb5406
7
- data.tar.gz: '0377164249cb083560b6f8b5eb70f510413b4c620d7a51675da23d23cb4038c33e8e54040135b4a70ff9faeba0b1afba001408172e46cbc19f72c636e3a6a256'
6
+ metadata.gz: de658214901aa13071c6b8d0c1aa94c8db0b2cee3c6c1df3207eb0881399c12215ce6c05a7d89c7da115e279a60fbe4688710e5f3fba827d5bd729afb7275e59
7
+ data.tar.gz: 999f5311c1a66933281798c40bbb3b7956e528b3164c264f2a7694fa48c142683e49ff47a185c1e174501b2e8c3b083d2bd513d1e6c37cffff9002d9186908e4
@@ -0,0 +1,21 @@
1
+ // For format details, see https://aka.ms/devcontainer.json. For config options, see the
2
+ // README at: https://github.com/devcontainers/templates/tree/main/src/docker-existing-dockerfile
3
+ {
4
+ "name": "scale_rb",
5
+ "build": {
6
+ // Sets the run context to one level up instead of the .devcontainer folder.
7
+ "context": "..",
8
+ // Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename.
9
+ "dockerfile": "../Dockerfile"
10
+ }
11
+ // Features to add to the dev container. More info: https://containers.dev/features.
12
+ // "features": {},
13
+ // Use 'forwardPorts' to make a list of ports inside the container available locally.
14
+ // "forwardPorts": [],
15
+ // Uncomment the next line to run commands after the container is created.
16
+ // "postCreateCommand": "cat /etc/os-release",
17
+ // Configure tool-specific properties.
18
+ // "customizations": {},
19
+ // Uncomment to connect as an existing user other than the container default. More info: https://aka.ms/dev-containers-non-root.
20
+ // "remoteUser": "devcontainer"
21
+ }
data/Dockerfile ADDED
@@ -0,0 +1,16 @@
1
+ FROM ruby:3.1
2
+
3
+ # Dependencies
4
+ RUN apt-get update -qq && apt-get install -y build-essential
5
+ RUN curl https://sh.rustup.rs -sSf | bash -s -- -y
6
+ ENV PATH="/root/.cargo/bin:${PATH}"
7
+
8
+ # Set the working directory
9
+ WORKDIR /scale_rb
10
+ COPY . /scale_rb
11
+
12
+ # Intall gems
13
+ RUN bundle install
14
+
15
+ # default command is to run a shell
16
+ CMD ["bash"]
data/Gemfile CHANGED
@@ -1,8 +1,8 @@
1
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in scale_rb.gemspec
4
4
  gemspec
5
5
 
6
- gem "rake", "~> 12.0"
7
- gem "rspec", "~> 3.0"
8
- gem 'rubocop', group: 'development', require: false
6
+ gem 'rake', '~> 12.0'
7
+ gem 'rspec', '~> 3.0'
8
+ gem 'rubocop', group: 'development', require: false
data/README.md CHANGED
@@ -1,13 +1,11 @@
1
1
  # ScaleRb
2
2
 
3
- It is still under heavy development. Use the latest version.
4
-
5
3
  ## Installation
6
4
 
7
5
  Add this line to your application's Gemfile:
8
6
 
9
7
  ```ruby
10
- gem 'scale_rb', '~> 0.4.0'
8
+ gem "scale_rb"
11
9
  ```
12
10
 
13
11
  And then execute:
@@ -29,15 +27,30 @@ bundle exec ruby examples/http_client_1.rb
29
27
 
30
28
  ## Development
31
29
 
32
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+ ### Run devcontainer
31
+
32
+ Open the project in vscode, then in the command palette, type `Reopen in Container` to open the project in a devcontainer.
33
+
34
+ ![image](https://github.com/user-attachments/assets/39af785c-5570-46df-9e6e-bf816e7f7b68)
35
+
33
36
 
34
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
37
+ After the devcontainer is opened, you can run the following commands:
38
+
39
+ 1. Tests:
40
+
41
+ ```bash
42
+ bundle exec rspec
43
+ ```
44
+
45
+ 2. Examples:
46
+ ```bash
47
+ bundle exec ruby examples/http_client_1.rb
48
+ ```
35
49
 
36
50
  ## Contributing
37
51
 
38
52
  Bug reports and pull requests are welcome on GitHub at https://github.com/wuminzhe/scale_rb. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/wuminzhe/scale_rb/blob/master/CODE_OF_CONDUCT.md).
39
53
 
40
-
41
54
  ## License
42
55
 
43
56
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/bin/console CHANGED
File without changes
data/bin/setup CHANGED
File without changes
@@ -1,8 +1,6 @@
1
1
 
2
2
  require 'scale_rb'
3
3
 
4
- ScaleRb.logger.level = Logger::DEBUG
5
-
6
4
  client = ScaleRb::HttpClient.new('https://polkadot-rpc.dwellir.com')
7
5
  block_hash = client.chain_getBlockHash(21585684)
8
6
  runtime_version = client.state_getRuntimeVersion(block_hash)
@@ -14,7 +14,5 @@ def fetch_some_storages(client, block_number)
14
14
  puts "Time taken: #{end_time - start_time} seconds"
15
15
  end
16
16
 
17
- ScaleRb.logger.level = Logger::DEBUG
18
-
19
17
  client = ScaleRb::HttpClient.new('https://polkadot-rpc.dwellir.com')
20
18
  fetch_some_storages(client, 21711742)
@@ -1,7 +1,5 @@
1
1
  require 'scale_rb'
2
2
 
3
- ScaleRb.logger.level = Logger::DEBUG
4
-
5
3
  ScaleRb::WsClient.start('wss://polkadot-rpc.dwellir.com') do |client|
6
4
  block_hash = client.chain_getBlockHash(21585684)
7
5
  runtime_version = client.state_getRuntimeVersion(block_hash)
@@ -1,7 +1,5 @@
1
1
  require 'scale_rb'
2
2
 
3
- # ScaleRb.logger.level = Logger::DEBUG
4
-
5
3
  # Unsubscribe after receiving 4 new heads
6
4
  ScaleRb::WsClient.start('wss://polkadot-rpc.dwellir.com') do |client|
7
5
  count = 0
@@ -15,7 +13,7 @@ ScaleRb::WsClient.start('wss://polkadot-rpc.dwellir.com') do |client|
15
13
  puts "Received new head at height: #{block_number}, block hash: #{block_hash}"
16
14
  else
17
15
  unsub_result = client.chain_unsubscribeNewHead(subscription_id)
18
- puts "Unsubscribe result: #{unsub_result}"
16
+ puts "Unsubscribe #{subscription_id} #{unsub_result === true ? 'succeeded' : 'failed'}"
19
17
  end
20
18
  end
21
19
 
@@ -14,8 +14,6 @@ def fetch_some_storages(client, block_number)
14
14
  puts "Time taken: #{end_time - start_time} seconds"
15
15
  end
16
16
 
17
- ScaleRb.logger.level = Logger::DEBUG
18
-
19
17
  ScaleRb::WsClient.start('wss://polkadot-rpc.dwellir.com') do |client|
20
18
  fetch_some_storages(client, 21711742)
21
19
  end
data/exe/metadata CHANGED
@@ -5,13 +5,9 @@ require 'scale_rb'
5
5
  require 'json'
6
6
  require 'optparse'
7
7
 
8
- def print_metadata(url, at = nil)
9
- puts JSON.pretty_generate(ScaleRb::HttpClient.get_metadata(url, at))
10
- end
11
-
12
- # ./bin/metadata http://g2.dev.darwinia.network:2234 -b 0x23ebddd6519aaf1b7fc916c3709af13d7a4010943fb53038406581171000a58e
13
- # ./bin/metadata https://rpc.darwinia.network -b 10511703
14
- # ./bin/metadata https://pangoro-rpc.darwinia.network
8
+ # ./exe/metadata https://polkadot-rpc.dwellir.com -b 0xfc2d86c5a2cc92b7770dcc14e74116912c9f848000b5f4ceca6fe1475588692c
9
+ # ./exe/metadata https://polkadot-rpc.dwellir.com -b 22931689
10
+ # ./exe/metadata https://polkadot-rpc.dwellir.com
15
11
  @options = {}
16
12
  parser = OptionParser.new do |opts|
17
13
  opts.banner = 'Usage: metadata [url] [options]'
@@ -26,16 +22,18 @@ else
26
22
  parser.parse!
27
23
  url = ARGV[0]
28
24
 
25
+ client = ScaleRb::HttpClient.new(url)
26
+
27
+ block_hash = nil
29
28
  if @options[:block]
30
29
  if @options[:block].length == 66
31
30
  block_hash = @options[:block]
32
31
  else
33
32
  block_number = @options[:block].to_i
34
- block_hash = ScaleRb::HttpClient.chain_getBlockHash url, block_number
33
+ block_hash = client.chain_getBlockHash(block_number)
35
34
  end
36
- else
37
- block_hash = ScaleRb::HttpClient.chain_getBlockHash url
38
35
  end
39
36
 
40
- print_metadata url, block_hash
37
+ metadata = client.get_metadata(block_hash)
38
+ puts JSON.pretty_generate(metadata)
41
39
  end
data/lib/address.rb CHANGED
@@ -79,7 +79,7 @@ module ScaleRb
79
79
  end
80
80
 
81
81
  input_bytes = ss58_format_bytes.bytes + pubkey_bytes
82
- checksum = Blake2b.hex(SS58_PREFIX.bytes + input_bytes, 64)._to_bytes
82
+ checksum = Utils.hex_to_u8a(Blake2b.hex(SS58_PREFIX.bytes + input_bytes, 64))
83
83
 
84
84
  Base58.binary_to_base58((input_bytes + checksum[0...checksum_length]).pack('C*'), :bitcoin)
85
85
  end
@@ -0,0 +1,92 @@
1
+ def custom_assign(positional_params, keyword_params, args, kwargs = {}, defaults = {})
2
+ assigned = {}
3
+
4
+ # Handle positional arguments (with optional defaults)
5
+ raise ArgumentError, 'Too many positional arguments' if args.length > positional_params.length
6
+
7
+ positional_params.each_with_index do |param, index|
8
+ if args[index]
9
+ assigned[param] = args[index] # Assign from args if available
10
+ elsif args.length == positional_params.length
11
+ assigned[param] = nil
12
+ elsif defaults.key?(param)
13
+ assigned[param] = defaults[param] # Assign default if no argument is provided
14
+ else
15
+ raise ArgumentError, "Missing required positional argument: #{param}"
16
+ end
17
+ end
18
+
19
+ # Handle keyword arguments (with optional defaults)
20
+ kwargs.each_key do |key|
21
+ raise ArgumentError, "Unknown keyword argument: #{key}" unless keyword_params.include?(key)
22
+ end
23
+
24
+ keyword_params.each do |key|
25
+ if kwargs.key?(key)
26
+ assigned[key] = kwargs[key] # Assign from kwargs if available
27
+ elsif defaults.key?(key)
28
+ assigned[key] = defaults[key] # Assign default if not provided
29
+ else
30
+ raise ArgumentError, "Missing required keyword argument: #{key}"
31
+ end
32
+ end
33
+
34
+ # assert_equal(positional_params.length + keyword_params.length, assigned.length)
35
+ assigned
36
+ end
37
+
38
+ def get_method_params(method)
39
+ params = method.parameters
40
+
41
+ positional_params = []
42
+ keyword_params = []
43
+
44
+ params.each do |type, name|
45
+ case type
46
+ when :req, :opt # Required, optional positional arguments
47
+ positional_params << name
48
+ when :key, :keyreq # Keyword arguments
49
+ keyword_params << name
50
+ end
51
+ end
52
+
53
+ [positional_params, keyword_params]
54
+ end
55
+
56
+ def assert_equal(expected, actual)
57
+ raise "Expected #{expected}, but got #{actual}" unless expected === actual
58
+ end
59
+
60
+ def build_assigned_params(method, defaults, args, kwargs)
61
+ positional_params, keyword_params = get_method_params(method)
62
+ custom_assign(positional_params, keyword_params, args, kwargs, defaults)
63
+ end
64
+
65
+ # def my_method(a, b = 2, c:, d: 4); end
66
+
67
+ # defaults = { b: 2, d: 4 }
68
+
69
+ # # my_method(5, c: 3)
70
+ # p build_assigned_params(:my_method, defaults, 5, c: 3)
71
+ # # => {:a=>5, :b=>2, :c=>3, :d=>4}
72
+
73
+ # # my_method(5, 6, c: 3)
74
+ # p build_assigned_params(:my_method, defaults, 5, 6, c: 3)
75
+ # # => {:a=>5, :b=>6, :c=>3, :d=>4}
76
+
77
+ # # my_method(5, 6, c: 3, d: 10)
78
+ # p build_assigned_params(:my_method, defaults, 5, 6, c: 3, d: 10)
79
+ # # => {:a=>5, :b=>6, :c=>3, :d=>10}
80
+
81
+ # # my_method(5, 6, c: 3, d: 10, e: 11)
82
+ # begin
83
+ # build_assigned_params(:my_method, defaults, 5, 6, c: 3, d: 10, e: 11)
84
+ # rescue ArgumentError => e
85
+ # puts e.message # => "Unknown keyword argument: e"
86
+ # end
87
+
88
+ # begin
89
+ # build_assigned_params(:my_method, defaults, 5, 6, 7, c: 3, d: 10)
90
+ # rescue ArgumentError => e
91
+ # puts e.message # => "Too many positional arguments"
92
+ # end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ScaleRb
4
+ module CallHelper
5
+ # callbytes's structure is: pallet_index + call_index + argsbytes
6
+ #
7
+ # callbytes examples:
8
+ # "0x0901"._to_bytes
9
+ # "0x05000a1287977578f888bdc1c7627781af1cc000e6ab1300004c31b8d9a798"._to_bytes
10
+ def self.decode_call(callbytes, metadata)
11
+ pallet_index = callbytes[0]
12
+ pallet = Metadata.get_module_by_index(pallet_index, metadata)
13
+
14
+ # Remove the pallet_index
15
+ # The callbytes we used below should not contain the pallet index.
16
+ # This is because the pallet index is not part of the call type.
17
+ # Its structure is: call_index + call_args
18
+ callbytes_without_pallet_index = callbytes[1..]
19
+ calls_type_id = pallet._get(:calls, :type)
20
+ decoded = Codec.decode(
21
+ calls_type_id,
22
+ callbytes_without_pallet_index,
23
+ Metadata.build_registry(metadata)
24
+ )&.first
25
+
26
+ {
27
+ pallet_name: pallet._get(:name),
28
+ call_name: decoded.is_a?(::Hash) ? decoded.keys.first.to_s : decoded.to_s,
29
+ call: decoded
30
+ }
31
+ end
32
+
33
+ # call examples:
34
+ # {:pallet_name=>"Deposit", :call_name=>"claim", :call=>:claim]}
35
+ # {:pallet_name=>"Balances", :call_name=>"transfer", :call=>{:transfer=>{:dest=>[10, 18, 135, 151, 117, 120, 248, 136, 189, 193, 199, 98, 119, 129, 175, 28, 192, 0, 230, 171], :value=>11000000000000000000}}]}
36
+ def self.encode_call(call, metadata)
37
+ calls_type_id = Metadata.get_calls_type_id(call[:pallet_name], metadata)
38
+ pallet_index = Metadata.get_module(call[:pallet_name], metadata)._get(:index)
39
+ [pallet_index] + Codec.encode(calls_type_id, call[:call], Metadata.build_registry(metadata))
40
+ end
41
+ end
42
+ end
@@ -1,12 +1,11 @@
1
1
  module ScaleRb
2
-
3
2
  # This module is used to add extra methods to both the ScaleRb::WsClient ScaleRb::HttpClient
4
3
  module ClientExt
5
4
  # get decoded metadata at block_hash
6
5
  def get_metadata(block_hash = nil)
7
6
  block_hash ||= chain_getHead
8
7
  metadata_hex = state_getMetadata(block_hash)
9
- ScaleRb::Metadata.decode_metadata(metadata_hex.strip._to_bytes)
8
+ Metadata.decode_metadata(metadata_hex)
10
9
  end
11
10
 
12
11
  # Get decoded storage at block_hash
@@ -39,8 +38,8 @@ module ScaleRb
39
38
  item[:changes].map do |change|
40
39
  storage_key = change[0]
41
40
  data = change[1] || default
42
- storage = data.nil? ? nil : PortableCodec.decode(type_id, data._to_bytes, registry)[0]
43
- { storage_key: storage_key, storage: storage }
41
+ storage = data.nil? ? nil : Codec.decode(type_id, Utils.hex_to_u8a(data), registry)[0]
42
+ { storage_key:, storage: }
44
43
  end
45
44
  end.flatten
46
45
  end
@@ -83,7 +82,7 @@ module ScaleRb
83
82
  # 'System',
84
83
  # 'Account',
85
84
  # key = {
86
- # value: [['0x724d50824542b56f422588421643c4a162b90b5416ef063f2266a1eae6651641'._to_bytes]], # [AccountId]
85
+ # value: [[Utils.hex_to_u8a('0x724d50824542b56f422588421643c4a162b90b5416ef063f2266a1eae6651641')]], # [AccountId]
87
86
  # type: 0,
88
87
  # hashers: ['Blake2128Concat']
89
88
  # },
@@ -101,7 +100,7 @@ module ScaleRb
101
100
  if key
102
101
  if key[:value].nil? || key[:value].empty?
103
102
  # map, but no key's value provided. get all storages under the partial storage key
104
- partial_storage_key = StorageHelper.encode_storage_key(pallet_name, item_name)._to_hex
103
+ partial_storage_key = Utils.u8a_to_hex(StorageHelper.encode_storage_key(pallet_name, item_name))
105
104
  get_storages_by_partial_key(
106
105
  block_hash,
107
106
  partial_storage_key,
@@ -111,7 +110,8 @@ module ScaleRb
111
110
  )
112
111
  elsif key[:value].length != key[:hashers].length
113
112
  # map with multi parts, but not have all values
114
- partial_storage_key = StorageHelper.encode_storage_key(pallet_name, item_name, key, registry)._to_hex
113
+ partial_storage_key = Utils.u8a_to_hex(StorageHelper.encode_storage_key(pallet_name, item_name, key,
114
+ registry))
115
115
  get_storages_by_partial_key(
116
116
  block_hash,
117
117
  partial_storage_key,
@@ -120,12 +120,12 @@ module ScaleRb
120
120
  registry
121
121
  )
122
122
  else
123
- storage_key = StorageHelper.encode_storage_key(pallet_name, item_name, key, registry)._to_hex
123
+ storage_key = Utils.u8a_to_hex(StorageHelper.encode_storage_key(pallet_name, item_name, key, registry))
124
124
  data = state_getStorage(storage_key, block_hash)
125
125
  StorageHelper.decode_storage(data, value[:type], value[:modifier] == 'Optional', value[:fallback], registry)
126
126
  end
127
127
  else
128
- storage_key = StorageHelper.encode_storage_key(pallet_name, item_name)._to_hex
128
+ storage_key = Utils.u8a_to_hex(StorageHelper.encode_storage_key(pallet_name, item_name))
129
129
  data = state_getStorage(storage_key, block_hash)
130
130
  StorageHelper.decode_storage(data, value[:type], value[:modifier] == 'Optional', value[:fallback], registry)
131
131
  end
@@ -152,12 +152,12 @@ module ScaleRb
152
152
  if plain
153
153
  [
154
154
  nil,
155
- { type: plain, modifier: modifier, fallback: fallback }
155
+ { type: plain, modifier:, fallback: }
156
156
  ]
157
157
  elsif map
158
158
  [
159
159
  { value: params, type: map._get(:key), hashers: map._get(:hashers) },
160
- { type: map._get(:value), modifier: modifier, fallback: fallback }
160
+ { type: map._get(:value), modifier:, fallback: }
161
161
  ]
162
162
  else
163
163
  raise 'NoSuchStorageType'
@@ -175,11 +175,10 @@ module ScaleRb
175
175
  if key.is_a?(Integer)
176
176
  key.to_i
177
177
  elsif key.is_a?(String) && key.start_with?('0x')
178
- key._to_bytes
178
+ Utils.hex_to_u8a(key)
179
179
  else
180
180
  key
181
181
  end
182
182
  end
183
-
184
183
  end
185
184
  end
@@ -30,8 +30,8 @@ module ScaleRb
30
30
  http.use_ssl = @uri.scheme == 'https'
31
31
 
32
32
  request = Net::HTTP::Post.new(@uri, 'Content-Type' => 'application/json')
33
- request.body = { jsonrpc: '2.0', method: method, params: params, id: Time.now.to_i }.to_json
34
- ScaleRb.logger.debug "Request: #{request.body}"
33
+ request.body = { jsonrpc: '2.0', method:, params:, id: Time.now.to_i }.to_json
34
+ ScaleRb.logger.debug "—→ #{request.body}"
35
35
 
36
36
  # https://docs.ruby-lang.org/en/master/Net/HTTPResponse.html
37
37
  response = http.request(request)
@@ -39,7 +39,7 @@ module ScaleRb
39
39
 
40
40
  # parse response, make key symbol
41
41
  body = JSON.parse(response.body, symbolize_names: true)
42
- ScaleRb.logger.debug "Response: #{body}"
42
+ ScaleRb.logger.debug "←— #{body}"
43
43
  raise body[:error] if body[:error]
44
44
 
45
45
  body[:result]
@@ -50,8 +50,6 @@ module ScaleRb
50
50
  end
51
51
 
52
52
  def method_missing(method, *args)
53
- # ScaleRb.logger.debug "#{method}(#{args.join(', ')})"
54
-
55
53
  request(method.to_s, args)
56
54
  end
57
55
  end
@@ -6,7 +6,6 @@ require_relative 'client_ext'
6
6
 
7
7
  module ScaleRb
8
8
  class WsClient
9
-
10
9
  class << self
11
10
  # @param [string] url
12
11
  def start(url)
@@ -22,14 +21,14 @@ module ScaleRb
22
21
  data = parse_message(message)
23
22
  next if data.nil?
24
23
 
25
- ScaleRb.logger.debug "Response: #{data}"
24
+ ScaleRb.logger.debug "←— #{data}"
26
25
  Async do
27
26
  client.handle_response(data)
28
27
  end
29
28
  end
30
29
  end
31
30
 
32
- client.supported_methods = client.rpc_methods()[:methods]
31
+ client.supported_methods = client.rpc_methods[:methods]
33
32
  yield client
34
33
 
35
34
  recv_task.wait
@@ -37,7 +36,6 @@ module ScaleRb
37
36
  recv_task&.stop
38
37
  end
39
38
  end
40
-
41
39
  end
42
40
 
43
41
  private
@@ -45,11 +43,10 @@ module ScaleRb
45
43
  def parse_message(message)
46
44
  message.parse
47
45
  rescue StandardError => e
48
- ScaleRb.logger.error "Error while parsing message: #{e.inspect}, message: #{message}"
46
+ Console::Event::Failure.for(e).emit(self, 'Parse message failed!')
49
47
  nil
50
48
  end
51
49
  end
52
-
53
50
  end
54
51
  end
55
52
 
@@ -71,7 +68,6 @@ module ScaleRb
71
68
 
72
69
  def method_missing(method, *args)
73
70
  method = method.to_s
74
- # ScaleRb.logger.debug "#{method}(#{args.join(', ')})"
75
71
 
76
72
  # why not check 'rpc_methods', because there is no @supported_methods when initializing
77
73
  if method != 'rpc_methods' && !@supported_methods.include?(method)
@@ -103,9 +99,9 @@ module ScaleRb
103
99
  def unsubscribe(method, subscription_id)
104
100
  return unless method.include?('unsubscribe')
105
101
 
106
- if @subscription_handler.unsubscribe(subscription_id)
107
- request(method, [subscription_id])
108
- end
102
+ return unless @subscription_handler.unsubscribe(subscription_id)
103
+
104
+ request(method, [subscription_id])
109
105
  end
110
106
 
111
107
  def handle_response(response)
@@ -117,16 +113,14 @@ module ScaleRb
117
113
  ScaleRb.logger.info "Received an unknown response: #{response}"
118
114
  end
119
115
  rescue StandardError => e
120
- ScaleRb.logger.error "Error while handling response: #{e.inspect}"
121
- ScaleRb.logger.debug e.backtrace.join("\n")
116
+ Console::Event::Failure.for(e).emit(self, 'Handle response failed!')
122
117
  end
123
118
 
124
119
  def read_message
125
120
  loop do
126
121
  return @connection.read
127
122
  rescue StandardError => e
128
- ScaleRb.logger.error "Error while read message from connection: #{e.inspect}"
129
- ScaleRb.logger.debug e.backtrace.join("\n")
123
+ Console::Event::Failure.for(e).emit(self, 'Read message from connection failed!')
130
124
  sleep 1
131
125
  retry
132
126
  end
@@ -141,8 +135,8 @@ module ScaleRb
141
135
  response_future.resolve(response[:result])
142
136
  })
143
137
 
144
- request = { jsonrpc: '2.0', id: @request_id, method: method, params: params }
145
- ScaleRb.logger.debug "Request: #{request}"
138
+ request = { jsonrpc: '2.0', id: @request_id, method:, params: }
139
+ ScaleRb.logger.debug "—→ #{request}"
146
140
  @connection.write(request.to_json)
147
141
 
148
142
  @request_id += 1
@@ -189,10 +183,9 @@ module ScaleRb
189
183
  subscription_id = notification.dig(:params, :subscription)
190
184
  return if subscription_id.nil?
191
185
 
192
- if @callbacks.key?(subscription_id)
193
- @callbacks[subscription_id].call(notification)
194
- end
186
+ return unless @callbacks.key?(subscription_id)
187
+
188
+ @callbacks[subscription_id].call(notification)
195
189
  end
196
190
  end
197
-
198
191
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'decode'
4
+ require_relative 'encode'
5
+
6
+ module ScaleRb
7
+ module Codec
8
+ class Error < StandardError; end
9
+ class TypeNotFound < Error; end
10
+ class TypeNotImplemented < Error; end
11
+ class CompositeInvalidValue < Error; end
12
+ class ArrayLengthNotEqual < Error; end
13
+ class VariantItemNotFound < Error; end
14
+ class VariantIndexOutOfRange < Error; end
15
+ class VariantInvalidValue < Error; end
16
+ class VariantFieldsLengthNotMatch < Error; end
17
+ class LengthNotEqualErr < Error; end
18
+ class NotEnoughBytesError < Error; end
19
+ class Unreachable < Error; end
20
+ class InvalidBytesError < Error; end
21
+
22
+ extend Decode
23
+ extend Encode
24
+ end
25
+ end