scale_rb 0.1.4 → 0.1.6
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/.gitignore +1 -0
- data/Gemfile.lock +3 -3
- data/README.md +3 -0
- data/exe/metadata +3 -3
- data/lib/client/abstract_ws_client.rb +100 -0
- data/lib/{substrate/client.rb → client/http_client.rb} +52 -29
- data/lib/client/rpc_request_builder.rb +53 -0
- data/lib/metadata/metadata.rb +3 -3
- data/lib/metadata/metadata_v10.rb +1 -0
- data/lib/metadata/metadata_v11.rb +1 -0
- data/lib/metadata/metadata_v12.rb +1 -0
- data/lib/metadata/metadata_v13.rb +1 -0
- data/lib/metadata/metadata_v14.rb +1 -0
- data/lib/metadata/metadata_v9.rb +1 -0
- data/lib/monkey_patching.rb +2 -0
- data/lib/portable_codec.rb +53 -38
- data/lib/scale_rb/version.rb +1 -1
- data/lib/scale_rb.rb +3 -2
- data/lib/storage_helper.rb +52 -26
- data/scale_rb.gemspec +1 -1
- metadata +8 -7
- data/lib/substrate/rpc.rb +0 -70
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3c6c07616c5b65f7aee2b0504956231534d94cd3df9eba9320e4a22d2a38aed2
|
|
4
|
+
data.tar.gz: f2f3572c5d7ed389d5772c6245fb2e02eb75d57cf5ff28b78a8db82642d47402
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1709366a718feafae82a60b5a5aeb05e5e78fbc3160c151de66b2be25e62ad3f6031c50db0097cc1880c00ec263962f45b4cf3fcb6f4ccd0d13ab48ce9b84976
|
|
7
|
+
data.tar.gz: 231963a7fc17cc7d25ec5aded79120f11733e97d81edf58f4f2fc31edbb11865b435bd286b9817db744d98bad8751433eb68e809d567f9590d5ee70c5687b97d
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
scale_rb (0.1.
|
|
5
|
-
blake2b_rs (~> 0.1.
|
|
4
|
+
scale_rb (0.1.6)
|
|
5
|
+
blake2b_rs (~> 0.1.4)
|
|
6
6
|
xxhash
|
|
7
7
|
|
|
8
8
|
GEM
|
|
9
9
|
remote: https://rubygems.org/
|
|
10
10
|
specs:
|
|
11
|
-
blake2b_rs (0.1.
|
|
11
|
+
blake2b_rs (0.1.4)
|
|
12
12
|
ffi (~> 1.0)
|
|
13
13
|
thermite (~> 0)
|
|
14
14
|
diff-lcs (1.5.0)
|
data/README.md
CHANGED
data/exe/metadata
CHANGED
|
@@ -6,7 +6,7 @@ require 'json'
|
|
|
6
6
|
require 'optparse'
|
|
7
7
|
|
|
8
8
|
def print_metadata(url, at = nil)
|
|
9
|
-
puts JSON.pretty_generate(
|
|
9
|
+
puts JSON.pretty_generate(HttpClient.get_metadata(url, at))
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
# ./bin/metadata http://g2.dev.darwinia.network:2234 -b 0x23ebddd6519aaf1b7fc916c3709af13d7a4010943fb53038406581171000a58e
|
|
@@ -31,10 +31,10 @@ else
|
|
|
31
31
|
block_hash = @options[:block]
|
|
32
32
|
else
|
|
33
33
|
block_number = @options[:block].to_i
|
|
34
|
-
block_hash =
|
|
34
|
+
block_hash = HttpClient.chain_getBlockHash url, block_number
|
|
35
35
|
end
|
|
36
36
|
else
|
|
37
|
-
block_hash =
|
|
37
|
+
block_hash = HttpClient.chain_getBlockHash url
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
print_metadata url, block_hash
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class AbstractWsClient
|
|
4
|
+
extend RpcRequestBuilder
|
|
5
|
+
attr_accessor :metadata, :registry
|
|
6
|
+
|
|
7
|
+
def initialize
|
|
8
|
+
@id = 0
|
|
9
|
+
@metadata = nil
|
|
10
|
+
@registry = nil
|
|
11
|
+
@callbacks = {}
|
|
12
|
+
@subscription_callbacks = {}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def send_json_rpc(_body)
|
|
16
|
+
raise 'WsClient is a abstract base class for websocket client, please use its sub-class'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# changes: [
|
|
20
|
+
# [
|
|
21
|
+
# "0x26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7", # storage key
|
|
22
|
+
# "0x0400000000000000d887690900000000020000" # change
|
|
23
|
+
# ]
|
|
24
|
+
# ]
|
|
25
|
+
def process(resp)
|
|
26
|
+
# handle id
|
|
27
|
+
@callbacks[resp['id']]&.call(resp['id'], resp) if resp['id']
|
|
28
|
+
|
|
29
|
+
# handle storage subscription
|
|
30
|
+
return unless resp['params'] && resp['params']['subscription']
|
|
31
|
+
return unless @metadata && @registry
|
|
32
|
+
|
|
33
|
+
subscription = resp['params']['subscription']
|
|
34
|
+
changes = resp['params']['result']['changes']
|
|
35
|
+
block = resp['params']['result']['block']
|
|
36
|
+
p "block: #{block}"
|
|
37
|
+
|
|
38
|
+
return unless @subscription_callbacks[subscription]
|
|
39
|
+
|
|
40
|
+
pallet_name, item_name, subscription_callback = @subscription_callbacks[subscription]
|
|
41
|
+
storage_item = Metadata.get_storage_item(pallet_name, item_name, @metadata)
|
|
42
|
+
storages = decode_storages(changes.map(&:last), storage_item, registry)
|
|
43
|
+
subscription_callback.call(storages)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def get_metadata(callback = nil)
|
|
47
|
+
if callback.nil?
|
|
48
|
+
callback = lambda do |id, resp|
|
|
49
|
+
return unless resp['id'] && resp['result']
|
|
50
|
+
return if resp['id'] != id
|
|
51
|
+
|
|
52
|
+
metadata_hex = resp['result']
|
|
53
|
+
metadata = Metadata.decode_metadata(metadata_hex.strip.to_bytes)
|
|
54
|
+
return unless metadata
|
|
55
|
+
|
|
56
|
+
@metadata = metadata
|
|
57
|
+
@registry = Metadata.build_registry(@metadata)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
id = bind_id_to(callback)
|
|
62
|
+
body = state_getMetadata(id)
|
|
63
|
+
send_json_rpc(body)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def subscribe_storage(pallet_name, item_name, subscription_callback, key = nil, registry = nil)
|
|
67
|
+
callback = create_callback_for_subscribe_storage(pallet_name, item_name, subscription_callback)
|
|
68
|
+
id = bind_id_to(callback)
|
|
69
|
+
body = derived_state_subscribe_storage(id, pallet_name, item_name, key, registry)
|
|
70
|
+
send_json_rpc(body)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
def bind_id_to(callback)
|
|
76
|
+
@callbacks[@id] = callback
|
|
77
|
+
old = @id
|
|
78
|
+
@id += 1
|
|
79
|
+
old
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def decode_storages(datas, storage_item, registry)
|
|
83
|
+
datas.map do |data|
|
|
84
|
+
StorageHelper.decode_storage2(data, storage_item, registry)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def create_callback_for_subscribe_storage(pallet_name, item_name, subscription_callback)
|
|
89
|
+
lambda do |id, resp|
|
|
90
|
+
return unless resp['id'] && resp['result']
|
|
91
|
+
return if resp['id'] != id
|
|
92
|
+
|
|
93
|
+
@subscription_callbacks[resp['result']] = [
|
|
94
|
+
pallet_name,
|
|
95
|
+
item_name,
|
|
96
|
+
subscription_callback
|
|
97
|
+
]
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -1,15 +1,49 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
require 'uri'
|
|
4
|
+
require 'net/http'
|
|
5
|
+
require 'json'
|
|
6
|
+
|
|
7
|
+
module ScaleRb
|
|
8
|
+
module HttpClient
|
|
9
|
+
extend RpcRequestBuilder
|
|
10
|
+
|
|
5
11
|
class << self
|
|
12
|
+
def request(url, body)
|
|
13
|
+
uri = URI(url)
|
|
14
|
+
req = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json')
|
|
15
|
+
req.body = body
|
|
16
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
17
|
+
http.use_ssl = true if uri.instance_of? URI::HTTPS
|
|
18
|
+
res = http.request(req)
|
|
19
|
+
# puts res unless res.is_a?(Net::HTTPSuccess)
|
|
20
|
+
|
|
21
|
+
result = JSON.parse(res.body)
|
|
22
|
+
raise result['error'] if result['error']
|
|
23
|
+
|
|
24
|
+
result['result']
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def json_rpc_call(url, method, *params)
|
|
28
|
+
body = build_json_rpc_body(method, params, Time.now.to_i)
|
|
29
|
+
request(url, body)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def respond_to_missing?(*_args)
|
|
33
|
+
true
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def method_missing(method, *args)
|
|
37
|
+
json_rpc_call(args[0], method, *args[1..])
|
|
38
|
+
end
|
|
39
|
+
|
|
6
40
|
def get_metadata(url, at = nil)
|
|
7
|
-
hex =
|
|
41
|
+
hex = state_getMetadata(url, at)
|
|
8
42
|
Metadata.decode_metadata(hex.strip.to_bytes)
|
|
9
43
|
end
|
|
10
44
|
|
|
11
45
|
def query_storage_at(url, storage_keys, type_id, default, registry, at = nil)
|
|
12
|
-
result =
|
|
46
|
+
result = state_queryStorageAt(url, storage_keys, at)
|
|
13
47
|
result.map do |item|
|
|
14
48
|
item['changes'].map do |change|
|
|
15
49
|
storage_key = change[0]
|
|
@@ -21,7 +55,7 @@ module Substrate
|
|
|
21
55
|
end
|
|
22
56
|
|
|
23
57
|
def get_storage_keys_by_partial_key(url, partial_storage_key, start_key = nil, at = nil)
|
|
24
|
-
storage_keys =
|
|
58
|
+
storage_keys = state_getKeysPaged(url, partial_storage_key, 1000, start_key, at)
|
|
25
59
|
if storage_keys.length == 1000
|
|
26
60
|
storage_keys + get_storage_keys_by_partial_key(url, partial_storage_key, storage_keys.last, at)
|
|
27
61
|
else
|
|
@@ -43,14 +77,6 @@ module Substrate
|
|
|
43
77
|
end.flatten
|
|
44
78
|
end
|
|
45
79
|
|
|
46
|
-
# type_id: result type id
|
|
47
|
-
def get_storage(url, storage_key, type_id, default, registry, at = nil)
|
|
48
|
-
data = Substrate::RPC.state_getStorage(url, storage_key, at) || default
|
|
49
|
-
return nil if data.nil?
|
|
50
|
-
|
|
51
|
-
PortableCodec.decode(type_id, data.to_bytes, registry)[0]
|
|
52
|
-
end
|
|
53
|
-
|
|
54
80
|
# 1. Plain
|
|
55
81
|
# key: nil
|
|
56
82
|
# value: { type: 3, modifier: 'Default', callback: '' }
|
|
@@ -78,9 +104,10 @@ module Substrate
|
|
|
78
104
|
# },
|
|
79
105
|
# ..
|
|
80
106
|
#
|
|
81
|
-
|
|
107
|
+
# TODO: part of the key is provided, but not all
|
|
108
|
+
def get_storage(url, pallet_name, item_name, key, value, registry, at = nil)
|
|
82
109
|
# map, but no key's value provided. get all storages under the partial storage key
|
|
83
|
-
if
|
|
110
|
+
if key && (key[:value].nil? || key[:value].empty?)
|
|
84
111
|
partial_storage_key = StorageHelper.encode_storage_key(pallet_name, item_name).to_hex
|
|
85
112
|
get_storages_by_partial_key(
|
|
86
113
|
url,
|
|
@@ -91,24 +118,18 @@ module Substrate
|
|
|
91
118
|
at
|
|
92
119
|
)
|
|
93
120
|
else
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
url,
|
|
98
|
-
storage_key,
|
|
99
|
-
value[:type],
|
|
100
|
-
value[:modifier] == 'Default' ? value[:fallback] : nil,
|
|
101
|
-
registry,
|
|
102
|
-
at
|
|
103
|
-
)
|
|
121
|
+
storage_key = StorageHelper.encode_storage_key(pallet_name, item_name, key, registry).to_hex
|
|
122
|
+
data = state_getStorage(url, storage_key, at)
|
|
123
|
+
StorageHelper.decode_storage(data, value[:type], value[:modifier] == 'Optional', value[:fallback], registry)
|
|
104
124
|
end
|
|
105
125
|
end
|
|
106
126
|
|
|
107
|
-
def
|
|
108
|
-
raise '
|
|
127
|
+
def get_storage2(url, pallet_name, item_name, value_of_key, metadata, at = nil)
|
|
128
|
+
raise 'Metadata should not be nil' if metadata.nil?
|
|
109
129
|
|
|
110
130
|
registry = Metadata.build_registry(metadata)
|
|
111
131
|
item = Metadata.get_storage_item(pallet_name, item_name, metadata)
|
|
132
|
+
raise "No such storage item: `#{pallet_name}`.`#{item_name}`" if item.nil?
|
|
112
133
|
|
|
113
134
|
modifier = item._get(:modifier) # Default | Optional
|
|
114
135
|
fallback = item._get(:fallback)
|
|
@@ -116,6 +137,8 @@ module Substrate
|
|
|
116
137
|
|
|
117
138
|
plain = type._get(:plain)
|
|
118
139
|
map = type._get(:map)
|
|
140
|
+
# debug
|
|
141
|
+
|
|
119
142
|
key, value =
|
|
120
143
|
if plain
|
|
121
144
|
[
|
|
@@ -130,8 +153,8 @@ module Substrate
|
|
|
130
153
|
else
|
|
131
154
|
raise 'NoSuchStorageType'
|
|
132
155
|
end
|
|
133
|
-
|
|
156
|
+
get_storage(url, pallet_name, item_name, key, value, registry, at)
|
|
134
157
|
end
|
|
135
158
|
end
|
|
136
159
|
end
|
|
137
|
-
end
|
|
160
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
module RpcRequestBuilder
|
|
6
|
+
def build_json_rpc_body(method, params, id)
|
|
7
|
+
{
|
|
8
|
+
'id' => id,
|
|
9
|
+
'jsonrpc' => '2.0',
|
|
10
|
+
'method' => method,
|
|
11
|
+
'params' => params.reject(&:nil?)
|
|
12
|
+
}.to_json
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def respond_to_missing?(*_args)
|
|
16
|
+
true
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# example:
|
|
20
|
+
# state_getStorage(1, '0x363a..', 563_868)
|
|
21
|
+
#
|
|
22
|
+
# ==
|
|
23
|
+
#
|
|
24
|
+
# build_json_rpc_body('state_getStorage', ['0x363a..', 563_868], 1)
|
|
25
|
+
def method_missing(method, *args)
|
|
26
|
+
build_json_rpc_body(method, args[1..], args[0])
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
###################################
|
|
30
|
+
# derived functions
|
|
31
|
+
###################################
|
|
32
|
+
def derived_state_get_storage(rpc_id, pallet_name, item_name, key = nil, registry = nil)
|
|
33
|
+
storage_key = StorageHelper.encode_storage_key(pallet_name, item_name, key, registry).to_hex
|
|
34
|
+
state_getStorage(rpc_id, [storage_key])
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def derived_state_subscribe_storage(rpc_id, pallet_name, item_name, key = nil, registry = nil)
|
|
38
|
+
storage_key = StorageHelper.encode_storage_key(pallet_name, item_name, key, registry).to_hex
|
|
39
|
+
state_subscribeStorage(rpc_id, [storage_key])
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def derived_eth_call(rpc_id, to, data, at = nil)
|
|
43
|
+
eth_call(
|
|
44
|
+
rpc_id,
|
|
45
|
+
[
|
|
46
|
+
{
|
|
47
|
+
'from' => nil, 'to' => to, 'data' => data
|
|
48
|
+
},
|
|
49
|
+
at
|
|
50
|
+
]
|
|
51
|
+
)
|
|
52
|
+
end
|
|
53
|
+
end
|
data/lib/metadata/metadata.rb
CHANGED
|
@@ -15,10 +15,10 @@ module Metadata
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def get_storage_item(pallet_name, item_name, metadata)
|
|
18
|
-
|
|
18
|
+
version = metadata._get(:metadata).keys.first
|
|
19
|
+
raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless %w[v9 v10 v11 v12 v13 v14].include?(version.to_s)
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
MetadataV14.get_storage_item(pallet_name, item_name, metadata_v14)
|
|
21
|
+
Metadata.const_get("Metadata#{version.upcase}").get_storage_item(pallet_name, item_name, metadata)
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
|
|
@@ -11,6 +11,7 @@ module Metadata
|
|
|
11
11
|
|
|
12
12
|
def get_storage_item(module_name, item_name, metadata)
|
|
13
13
|
modula = get_module(module_name, metadata)
|
|
14
|
+
raise "Module `#{module_name}` not found" if modula.nil?
|
|
14
15
|
modula._get(:storage)._get(:items).find do |item|
|
|
15
16
|
item._get(:name) == item_name
|
|
16
17
|
end
|
|
@@ -11,6 +11,7 @@ module Metadata
|
|
|
11
11
|
|
|
12
12
|
def get_storage_item(module_name, item_name, metadata)
|
|
13
13
|
modula = get_module(module_name, metadata)
|
|
14
|
+
raise "Module `#{module_name}` not found" if modula.nil?
|
|
14
15
|
modula._get(:storage)._get(:items).find do |item|
|
|
15
16
|
item._get(:name) == item_name
|
|
16
17
|
end
|
|
@@ -11,6 +11,7 @@ module Metadata
|
|
|
11
11
|
|
|
12
12
|
def get_storage_item(module_name, item_name, metadata)
|
|
13
13
|
modula = get_module(module_name, metadata)
|
|
14
|
+
raise "Module `#{module_name}` not found" if modula.nil?
|
|
14
15
|
modula._get(:storage)._get(:items).find do |item|
|
|
15
16
|
item._get(:name) == item_name
|
|
16
17
|
end
|
|
@@ -11,6 +11,7 @@ module Metadata
|
|
|
11
11
|
|
|
12
12
|
def get_storage_item(module_name, item_name, metadata)
|
|
13
13
|
modula = get_module(module_name, metadata)
|
|
14
|
+
raise "Module `#{module_name}` not found" if modula.nil?
|
|
14
15
|
modula._get(:storage)._get(:items).find do |item|
|
|
15
16
|
item._get(:name) == item_name
|
|
16
17
|
end
|
|
@@ -16,6 +16,7 @@ module Metadata
|
|
|
16
16
|
|
|
17
17
|
def get_storage_item(pallet_name, item_name, metadata)
|
|
18
18
|
pallet = get_module(pallet_name, metadata)
|
|
19
|
+
raise "Pallet `#{pallet_name}` not found" if pallet.nil?
|
|
19
20
|
pallet._get(:storage)._get(:items).find do |item|
|
|
20
21
|
item._get(:name) == item_name
|
|
21
22
|
end
|
data/lib/metadata/metadata_v9.rb
CHANGED
|
@@ -11,6 +11,7 @@ module Metadata
|
|
|
11
11
|
|
|
12
12
|
def get_storage_item(module_name, item_name, metadata)
|
|
13
13
|
modula = get_module(module_name, metadata)
|
|
14
|
+
raise "Module `#{module_name}` not found" if modula.nil?
|
|
14
15
|
modula._get(:storage)._get(:items).find do |item|
|
|
15
16
|
item._get(:name) == item_name
|
|
16
17
|
end
|
data/lib/monkey_patching.rb
CHANGED
data/lib/portable_codec.rb
CHANGED
|
@@ -81,37 +81,41 @@ module PortableCodec
|
|
|
81
81
|
def decode_composite(composite_type, bytes, registry)
|
|
82
82
|
fields = composite_type._get(:fields)
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
84
|
+
# reduce composite level when composite only has one field without name
|
|
85
|
+
if fields.length == 1 && fields.first._get(:name).nil?
|
|
86
|
+
decode(fields.first._get(:type), bytes, registry)
|
|
87
|
+
else
|
|
88
|
+
type_name_list = fields.map { |f| f._get(:name) }
|
|
89
|
+
type_id_list = fields.map { |f| f._get(:type) }
|
|
90
|
+
|
|
91
|
+
type_value_list, remaining_bytes = _decode_types(type_id_list, bytes, registry)
|
|
92
|
+
[
|
|
93
|
+
if type_name_list.all?(&:nil?)
|
|
94
|
+
type_value_list
|
|
95
|
+
else
|
|
96
|
+
[type_name_list.map(&:to_sym), type_value_list].transpose.to_h
|
|
97
|
+
end,
|
|
98
|
+
remaining_bytes
|
|
99
|
+
]
|
|
100
|
+
end
|
|
96
101
|
end
|
|
97
102
|
|
|
98
103
|
def decode_variant(variant_type, bytes, registry)
|
|
99
104
|
variants = variant_type._get(:variants)
|
|
100
105
|
|
|
101
106
|
index = bytes[0]
|
|
102
|
-
|
|
103
|
-
raise VariantIndexOutOfRange,
|
|
104
|
-
"type: #{variant_type}, index: #{index}, bytes: #{bytes}"
|
|
105
|
-
end
|
|
107
|
+
item = variants.find { |v| v._get(:index) == index } # item is an composite
|
|
106
108
|
|
|
107
|
-
|
|
108
|
-
item_name = item_variant._get(:name)
|
|
109
|
-
item, remaining_bytes = decode_composite(item_variant, bytes[1..], registry)
|
|
109
|
+
raise VariantIndexOutOfRange, "type: #{variant_type}, index: #{index}, bytes: #{bytes}" if item.nil?
|
|
110
110
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
111
|
+
item_name = item._get(:name)
|
|
112
|
+
item_fields = item._get(:fields)
|
|
113
|
+
if item_fields.empty?
|
|
114
|
+
[item_name, bytes[1..]]
|
|
115
|
+
else
|
|
116
|
+
item_value, remaining_bytes = decode_composite(item, bytes[1..], registry)
|
|
117
|
+
[{ item_name.to_sym => item_value }, remaining_bytes]
|
|
118
|
+
end
|
|
115
119
|
end
|
|
116
120
|
|
|
117
121
|
def _decode_types(ids, bytes, registry = {})
|
|
@@ -130,6 +134,9 @@ module PortableCodec
|
|
|
130
134
|
raise TypeNotFound, "id: #{id}" if type.nil?
|
|
131
135
|
|
|
132
136
|
type_def = type._get(:def)
|
|
137
|
+
# debug
|
|
138
|
+
# p type_def
|
|
139
|
+
# p value
|
|
133
140
|
|
|
134
141
|
return encode_primitive(type_def, value) if type_def._key?(:primitive)
|
|
135
142
|
return encode_compact(value) if type_def._key?(:compact)
|
|
@@ -181,18 +188,26 @@ module PortableCodec
|
|
|
181
188
|
# or
|
|
182
189
|
# [value1, value2, ...]
|
|
183
190
|
def encode_composite(composite_type, value, registry)
|
|
184
|
-
values =
|
|
185
|
-
if value.instance_of?(Hash)
|
|
186
|
-
value.values
|
|
187
|
-
elsif value.instance_of?(Array)
|
|
188
|
-
value
|
|
189
|
-
else
|
|
190
|
-
raise CompositeInvalidValue, "value: #{value}, only hash and array"
|
|
191
|
-
end
|
|
192
|
-
|
|
193
191
|
fields = composite_type._get(:fields)
|
|
194
|
-
|
|
195
|
-
|
|
192
|
+
# reduce composite level when composite only has one field without name
|
|
193
|
+
if fields.length == 1 && fields.first._get(:name).nil?
|
|
194
|
+
# debug
|
|
195
|
+
# p fields.first._get(:type)
|
|
196
|
+
# p value
|
|
197
|
+
encode(fields.first._get(:type), value, registry)
|
|
198
|
+
else
|
|
199
|
+
values =
|
|
200
|
+
if value.instance_of?(Hash)
|
|
201
|
+
value.values
|
|
202
|
+
elsif value.instance_of?(Array)
|
|
203
|
+
value
|
|
204
|
+
else
|
|
205
|
+
raise CompositeInvalidValue, "value: #{value}, only hash and array"
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
type_id_list = fields.map { |f| f._get(:type) }
|
|
209
|
+
_encode_types(type_id_list, values, registry)
|
|
210
|
+
end
|
|
196
211
|
end
|
|
197
212
|
|
|
198
213
|
# value:
|
|
@@ -213,11 +228,11 @@ module PortableCodec
|
|
|
213
228
|
raise VariantInvalidValue, "type: #{variant_type}, value: #{value}"
|
|
214
229
|
end
|
|
215
230
|
|
|
216
|
-
|
|
217
|
-
raise VariantItemNotFound, "type: #{variant_type}, name: #{name}" if
|
|
218
|
-
raise VariantInvalidValue, "type: #{variant_type}, v: #{v}" if
|
|
231
|
+
item = variants.find { |var| var._get(:name) == name }
|
|
232
|
+
raise VariantItemNotFound, "type: #{variant_type}, name: #{name}" if item.nil?
|
|
233
|
+
raise VariantInvalidValue, "type: #{variant_type}, v: #{v}" if item._get(:fields).length != v.length
|
|
219
234
|
|
|
220
|
-
ScaleRb.encode_uint('u8',
|
|
235
|
+
ScaleRb.encode_uint('u8', item._get(:index)) + encode_composite(item, v, registry)
|
|
221
236
|
end
|
|
222
237
|
|
|
223
238
|
def _encode_types(ids, values, registry)
|
data/lib/scale_rb/version.rb
CHANGED
data/lib/scale_rb.rb
CHANGED
|
@@ -21,8 +21,9 @@ require 'hasher'
|
|
|
21
21
|
require 'storage_helper'
|
|
22
22
|
|
|
23
23
|
# client
|
|
24
|
-
require '
|
|
25
|
-
require '
|
|
24
|
+
require 'client/rpc_request_builder'
|
|
25
|
+
require 'client/http_client'
|
|
26
|
+
require 'client/abstract_ws_client'
|
|
26
27
|
|
|
27
28
|
# get registry from config
|
|
28
29
|
require 'registry'
|
data/lib/storage_helper.rb
CHANGED
|
@@ -2,37 +2,63 @@
|
|
|
2
2
|
|
|
3
3
|
module StorageHelper
|
|
4
4
|
class << self
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
# }
|
|
13
|
-
# registry: portable_types_registry
|
|
14
|
-
def encode_storage_key(pallet_name, method_name, params = nil, registry = nil)
|
|
15
|
-
pallet_method_key = Hasher.twox128(pallet_name) + Hasher.twox128(method_name)
|
|
5
|
+
# key: {
|
|
6
|
+
# value: ,
|
|
7
|
+
# type: ,
|
|
8
|
+
# hashers: []
|
|
9
|
+
# }
|
|
10
|
+
def encode_storage_key(pallet_name, item_name, key = nil, registry = nil)
|
|
11
|
+
storage_key = Hasher.twox128(pallet_name) + Hasher.twox128(item_name)
|
|
16
12
|
|
|
17
|
-
if
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
if key && registry
|
|
14
|
+
|
|
15
|
+
key_types, key_values =
|
|
16
|
+
if key[:hashers].length == 1
|
|
17
|
+
[
|
|
18
|
+
[key[:type]],
|
|
19
|
+
key[:value]
|
|
20
|
+
]
|
|
21
|
+
else
|
|
22
|
+
[
|
|
23
|
+
registry[key[:type]]._get(:def)._get(:tuple),
|
|
24
|
+
key[:value]
|
|
25
|
+
]
|
|
26
|
+
end
|
|
23
27
|
|
|
24
|
-
|
|
28
|
+
# debug
|
|
29
|
+
# p "encode_storage_key -----------------------"
|
|
30
|
+
# p key_types
|
|
31
|
+
# p key_values
|
|
32
|
+
# p "encode_storage_key -----------------------"
|
|
33
|
+
raise "Key's value doesn't match key's type, key's value: #{key_values.inspect}, but key's type: #{key_types.inspect}. Please check your key's value." if key_types.class != key_values.class || key_types.length != key_values.length
|
|
34
|
+
storage_key + PortableCodec._encode_types_with_hashers(key_types, key_values, registry, key[:hashers])
|
|
35
|
+
else
|
|
36
|
+
storage_key
|
|
25
37
|
end
|
|
26
38
|
end
|
|
27
39
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
40
|
+
# data: hex string
|
|
41
|
+
# type: portable type id
|
|
42
|
+
# optional: boolean
|
|
43
|
+
# fallback: hex string
|
|
44
|
+
# returns nil or data
|
|
45
|
+
def decode_storage(data, type, optional, fallback, registry)
|
|
46
|
+
data ||= (optional ? nil : fallback)
|
|
47
|
+
PortableCodec.decode(type, data.to_bytes, registry)[0] if data
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# storage_item: the storage item from metadata
|
|
51
|
+
def decode_storage2(data, storage_item, registry)
|
|
52
|
+
modifier = storage_item._get(:modifier) # Default | Optional
|
|
53
|
+
fallback = storage_item._get(:fallback)
|
|
54
|
+
type = storage_item._get(:type)._get(:plain) || storage_item._get(:type)._get(:map)._get(:value)
|
|
55
|
+
decode_storage(data, type, modifier == 'Optional', fallback, registry)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def decode_storage3(data, pallet_name, item_name, metadata)
|
|
59
|
+
registry = Metadata.build_registry(metadata)
|
|
60
|
+
storage_item = Metadata.get_storage_item(pallet_name, item_name, metadata)
|
|
61
|
+
decode_storage2(data, storage_item, registry)
|
|
36
62
|
end
|
|
37
63
|
end
|
|
38
64
|
end
|
data/scale_rb.gemspec
CHANGED
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.1.
|
|
4
|
+
version: 0.1.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Aki Wu
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2023-04-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: blake2b_rs
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 0.1.
|
|
19
|
+
version: 0.1.4
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 0.1.
|
|
26
|
+
version: 0.1.4
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: xxhash
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -59,6 +59,9 @@ files:
|
|
|
59
59
|
- bin/console
|
|
60
60
|
- bin/setup
|
|
61
61
|
- exe/metadata
|
|
62
|
+
- lib/client/abstract_ws_client.rb
|
|
63
|
+
- lib/client/http_client.rb
|
|
64
|
+
- lib/client/rpc_request_builder.rb
|
|
62
65
|
- lib/codec.rb
|
|
63
66
|
- lib/hasher.rb
|
|
64
67
|
- lib/metadata/metadata.rb
|
|
@@ -74,8 +77,6 @@ files:
|
|
|
74
77
|
- lib/scale_rb.rb
|
|
75
78
|
- lib/scale_rb/version.rb
|
|
76
79
|
- lib/storage_helper.rb
|
|
77
|
-
- lib/substrate/client.rb
|
|
78
|
-
- lib/substrate/rpc.rb
|
|
79
80
|
- scale_rb.gemspec
|
|
80
81
|
homepage: https://github.com/wuminzhe/scale_rb
|
|
81
82
|
licenses:
|
|
@@ -98,7 +99,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
98
99
|
- !ruby/object:Gem::Version
|
|
99
100
|
version: '0'
|
|
100
101
|
requirements: []
|
|
101
|
-
rubygems_version: 3.
|
|
102
|
+
rubygems_version: 3.3.7
|
|
102
103
|
signing_key:
|
|
103
104
|
specification_version: 4
|
|
104
105
|
summary: New Ruby SCALE Codec Library
|
data/lib/substrate/rpc.rb
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'uri'
|
|
4
|
-
require 'net/http'
|
|
5
|
-
require 'json'
|
|
6
|
-
|
|
7
|
-
module Substrate
|
|
8
|
-
module RPC
|
|
9
|
-
class << self
|
|
10
|
-
def json_rpc_call(method, params, url)
|
|
11
|
-
uri = URI(url)
|
|
12
|
-
req = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json')
|
|
13
|
-
req.body = {
|
|
14
|
-
'id' => 1,
|
|
15
|
-
'jsonrpc' => '2.0',
|
|
16
|
-
'method' => method,
|
|
17
|
-
'params' => params.reject(&:nil?)
|
|
18
|
-
}.to_json
|
|
19
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
|
20
|
-
http.use_ssl = true if uri.instance_of? URI::HTTPS
|
|
21
|
-
res = http.request(req)
|
|
22
|
-
# puts res unless res.is_a?(Net::HTTPSuccess)
|
|
23
|
-
|
|
24
|
-
result = JSON.parse(res.body)
|
|
25
|
-
raise result['error'] if result['error']
|
|
26
|
-
|
|
27
|
-
result['result']
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def chain_getBlockHash(url, block_number = nil)
|
|
31
|
-
json_rpc_call('chain_getBlockHash', [block_number], url)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def chain_getBlock(url, at = nil)
|
|
35
|
-
json_rpc_call('chain_getBlock', [at], url)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def state_getRuntimeVersion(url, at = nil)
|
|
39
|
-
json_rpc_call('state_getRuntimeVersion', [at], url)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def state_getMetadata(url, at = nil)
|
|
43
|
-
json_rpc_call('state_getMetadata', [at], url)
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def state_getStorage(url, key, at = nil)
|
|
47
|
-
json_rpc_call('state_getStorage', [key, at], url)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def state_queryStorageAt(url, keys, at = nil)
|
|
51
|
-
json_rpc_call('state_queryStorageAt', [keys, at], url)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def state_getKeysPaged(url, key, count, start_key = nil, at = nil)
|
|
55
|
-
json_rpc_call('state_getKeysPaged', [key, count, start_key, at], url)
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def eth_call(url, to, data, at_block_number = nil)
|
|
59
|
-
json_rpc_call('eth_call', [
|
|
60
|
-
{
|
|
61
|
-
'from' => nil,
|
|
62
|
-
'to' => to,
|
|
63
|
-
'data' => data
|
|
64
|
-
},
|
|
65
|
-
at_block_number
|
|
66
|
-
], url)
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
end
|