scale_rb 0.1.4 → 0.1.5
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} +47 -27
- data/lib/client/rpc_request_builder.rb +53 -0
- data/lib/metadata/metadata.rb +3 -3
- data/lib/monkey_patching.rb +2 -0
- data/lib/portable_codec.rb +47 -38
- data/lib/scale_rb/version.rb +1 -1
- data/lib/scale_rb.rb +3 -2
- data/lib/storage_helper.rb +45 -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: f83289d7a27bca72fe9e21e43f2b06ff29e191e47b9e1397cb96ea1adf6ee6c0
|
4
|
+
data.tar.gz: a1e77aaffcbc32aa795cb9cd57303f71a3fc1477c42e2540034d9060dc88a415
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 26a88e5148bd175700d992542ea490dfd97b298b24dd8a6955fa24e276c12a8018b914c9c2f321b59cce4d8be24ceda7674814a83495a6079bebef43f8407d7a
|
7
|
+
data.tar.gz: 74e818ab1e4d56caac4b78de0e15545b53e86361a5557fa72eae7e8310dec0b09a101590551e5b6d5b218d41c690e6eaea6221a84a93a14c904620724390aaf0
|
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.5)
|
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,7 +104,7 @@ module Substrate
|
|
78
104
|
# },
|
79
105
|
# ..
|
80
106
|
#
|
81
|
-
def
|
107
|
+
def get_storage(url, pallet_name, item_name, key, value, registry, at = nil)
|
82
108
|
# map, but no key's value provided. get all storages under the partial storage key
|
83
109
|
if !key.nil? && key[:value].nil?
|
84
110
|
partial_storage_key = StorageHelper.encode_storage_key(pallet_name, item_name).to_hex
|
@@ -91,20 +117,13 @@ module Substrate
|
|
91
117
|
at
|
92
118
|
)
|
93
119
|
else
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
url,
|
98
|
-
storage_key,
|
99
|
-
value[:type],
|
100
|
-
value[:modifier] == 'Default' ? value[:fallback] : nil,
|
101
|
-
registry,
|
102
|
-
at
|
103
|
-
)
|
120
|
+
storage_key = StorageHelper.encode_storage_key(pallet_name, item_name, key, registry).to_hex
|
121
|
+
data = state_getStorage(url, storage_key, at)
|
122
|
+
StorageHelper.decode_storage(data, value[:type], value[:modifier] == 'Optional', value[:fallback], registry)
|
104
123
|
end
|
105
124
|
end
|
106
125
|
|
107
|
-
def
|
126
|
+
def get_storage2(url, pallet_name, item_name, value_of_key, metadata, at = nil)
|
108
127
|
raise 'metadata should not be nil' if metadata.nil?
|
109
128
|
|
110
129
|
registry = Metadata.build_registry(metadata)
|
@@ -116,6 +135,7 @@ module Substrate
|
|
116
135
|
|
117
136
|
plain = type._get(:plain)
|
118
137
|
map = type._get(:map)
|
138
|
+
|
119
139
|
key, value =
|
120
140
|
if plain
|
121
141
|
[
|
@@ -130,8 +150,8 @@ module Substrate
|
|
130
150
|
else
|
131
151
|
raise 'NoSuchStorageType'
|
132
152
|
end
|
133
|
-
|
153
|
+
get_storage(url, pallet_name, item_name, key, value, registry, at)
|
134
154
|
end
|
135
155
|
end
|
136
156
|
end
|
137
|
-
end
|
157
|
+
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
|
|
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 = {})
|
@@ -181,18 +185,23 @@ module PortableCodec
|
|
181
185
|
# or
|
182
186
|
# [value1, value2, ...]
|
183
187
|
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
188
|
fields = composite_type._get(:fields)
|
194
|
-
|
195
|
-
|
189
|
+
# reduce composite level when composite only has one field without name
|
190
|
+
if fields.length == 1 && fields.first._get(:name).nil?
|
191
|
+
encode(fields.first._get(:type), value, registry)
|
192
|
+
else
|
193
|
+
values =
|
194
|
+
if value.instance_of?(Hash)
|
195
|
+
value.values
|
196
|
+
elsif value.instance_of?(Array)
|
197
|
+
value
|
198
|
+
else
|
199
|
+
raise CompositeInvalidValue, "value: #{value}, only hash and array"
|
200
|
+
end
|
201
|
+
|
202
|
+
type_id_list = fields.map { |f| f._get(:type) }
|
203
|
+
_encode_types(type_id_list, values, registry)
|
204
|
+
end
|
196
205
|
end
|
197
206
|
|
198
207
|
# value:
|
@@ -213,11 +222,11 @@ module PortableCodec
|
|
213
222
|
raise VariantInvalidValue, "type: #{variant_type}, value: #{value}"
|
214
223
|
end
|
215
224
|
|
216
|
-
|
217
|
-
raise VariantItemNotFound, "type: #{variant_type}, name: #{name}" if
|
218
|
-
raise VariantInvalidValue, "type: #{variant_type}, v: #{v}" if
|
225
|
+
item = variants.find { |var| var._get(:name) == name }
|
226
|
+
raise VariantItemNotFound, "type: #{variant_type}, name: #{name}" if item.nil?
|
227
|
+
raise VariantInvalidValue, "type: #{variant_type}, v: #{v}" if item._get(:fields).length != v.length
|
219
228
|
|
220
|
-
ScaleRb.encode_uint('u8',
|
229
|
+
ScaleRb.encode_uint('u8', item._get(:index)) + encode_composite(item, v, registry)
|
221
230
|
end
|
222
231
|
|
223
232
|
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,56 @@
|
|
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
|
+
types, 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
|
+
storage_key + PortableCodec._encode_types_with_hashers(types, values, registry, key[:hashers])
|
29
|
+
else
|
30
|
+
storage_key
|
25
31
|
end
|
26
32
|
end
|
27
33
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
34
|
+
# data: hex string
|
35
|
+
# type: portable type id
|
36
|
+
# optional: boolean
|
37
|
+
# fallback: hex string
|
38
|
+
def decode_storage(data, type, optional, fallback, registry)
|
39
|
+
data ||= (optional ? nil : fallback)
|
40
|
+
PortableCodec.decode(type, data.to_bytes, registry)[0]
|
41
|
+
end
|
42
|
+
|
43
|
+
# storage_item: the storage item from metadata
|
44
|
+
def decode_storage2(data, storage_item, registry)
|
45
|
+
modifier = storage_item._get(:modifier) # Default | Optional
|
46
|
+
fallback = storage_item._get(:fallback)
|
47
|
+
type = storage_item._get(:type)._get(:plain) || storage_item._get(:type)._get(:map)._get(:value)
|
48
|
+
decode_storage(data, type, modifier == 'Optional', fallback, registry)
|
49
|
+
end
|
50
|
+
|
51
|
+
def decode_storage3(data, pallet_name, item_name, metadata)
|
52
|
+
registry = Metadata.build_registry(metadata)
|
53
|
+
storage_item = Metadata.get_storage_item(pallet_name, item_name, metadata)
|
54
|
+
decode_storage2(data, storage_item, registry)
|
36
55
|
end
|
37
56
|
end
|
38
57
|
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.5
|
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-03-30 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
|