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.
- checksums.yaml +4 -4
- data/.devcontainer/devcontainer.json +21 -0
- data/Dockerfile +16 -0
- data/Gemfile +4 -4
- data/README.md +19 -6
- data/bin/console +0 -0
- data/bin/setup +0 -0
- data/examples/http_client_1.rb +0 -2
- data/examples/http_client_2.rb +0 -2
- data/examples/ws_client_1.rb +0 -2
- data/examples/ws_client_3.rb +1 -3
- data/examples/ws_client_4.rb +0 -2
- data/exe/metadata +9 -11
- data/lib/address.rb +1 -1
- data/lib/custom_assign.rb +92 -0
- data/lib/scale_rb/call_helper.rb +42 -0
- data/lib/{client → scale_rb/client}/client_ext.rb +12 -13
- data/lib/{client → scale_rb/client}/http_client.rb +3 -5
- data/lib/{client → scale_rb/client}/ws_client.rb +13 -20
- data/lib/scale_rb/codec.rb +25 -0
- data/lib/scale_rb/codec_utils.rb +128 -0
- data/lib/scale_rb/decode.rb +164 -0
- data/lib/scale_rb/encode.rb +150 -0
- data/lib/{hasher.rb → scale_rb/hasher.rb} +10 -8
- data/lib/scale_rb/metadata/metadata.rb +114 -0
- data/lib/{metadata → scale_rb/metadata}/metadata_v10.rb +0 -17
- data/lib/{metadata → scale_rb/metadata}/metadata_v11.rb +0 -17
- data/lib/{metadata → scale_rb/metadata}/metadata_v12.rb +0 -17
- data/lib/{metadata → scale_rb/metadata}/metadata_v13.rb +0 -17
- data/lib/{metadata → scale_rb/metadata}/metadata_v14.rb +18 -18
- data/lib/{metadata → scale_rb/metadata}/metadata_v9.rb +0 -17
- data/lib/scale_rb/metadata/registry.rb +263 -0
- data/lib/scale_rb/metadata/type_exp.rb +286 -0
- data/lib/scale_rb/portable_registry.rb +133 -0
- data/lib/{storage_helper.rb → scale_rb/storage_helper.rb} +16 -4
- data/lib/scale_rb/types.rb +233 -0
- data/lib/scale_rb/utils.rb +125 -0
- data/lib/scale_rb/version.rb +1 -1
- data/lib/scale_rb.rb +22 -30
- data/lib/type_enforcer.rb +170 -0
- data/scale_rb.gemspec +5 -0
- metadata +71 -19
- data/lib/codec.rb +0 -450
- data/lib/metadata/metadata.rb +0 -137
- data/lib/monkey_patching.rb +0 -115
- data/lib/portable_codec.rb +0 -285
- data/lib/registry.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cb19be98106d9f8331a9be9812f6252c23d6913cbd98cedcae34bf1a464e7b90
|
4
|
+
data.tar.gz: cff1e034d85f130ed7d149628647f020adb9ffc532d9646bceda054007d6bf14
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
7
|
-
gem
|
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
|
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
|
-
|
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
|
+

|
35
|
+
|
33
36
|
|
34
|
-
|
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
|
data/examples/http_client_1.rb
CHANGED
data/examples/http_client_2.rb
CHANGED
@@ -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)
|
data/examples/ws_client_1.rb
CHANGED
data/examples/ws_client_3.rb
CHANGED
@@ -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
|
16
|
+
puts "Unsubscribe #{subscription_id} #{unsub_result === true ? 'succeeded' : 'failed'}"
|
19
17
|
end
|
20
18
|
end
|
21
19
|
|
data/examples/ws_client_4.rb
CHANGED
@@ -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
|
-
|
9
|
-
|
10
|
-
|
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 =
|
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
|
-
|
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)
|
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
|
-
|
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 :
|
43
|
-
{ storage_key
|
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'
|
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)
|
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,
|
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)
|
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)
|
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
|
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
|
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
|
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
|
34
|
-
ScaleRb.logger.debug "
|
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 "
|
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 "
|
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
|
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
|
-
|
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
|
-
|
107
|
-
|
108
|
-
|
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
|
-
|
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
|
-
|
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
|
145
|
-
ScaleRb.logger.debug "
|
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
|
-
|
193
|
-
|
194
|
-
|
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
|