scale_rb 0.2.2 → 0.3.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/.gitignore +1 -0
- data/.rspec +0 -0
- data/.rubocop.yml +0 -0
- data/.travis.yml +0 -0
- data/CODE_OF_CONDUCT.md +0 -0
- data/Gemfile +0 -0
- data/Gemfile.lock +50 -2
- data/LICENSE.txt +0 -0
- data/README.md +7 -4
- data/Rakefile +0 -0
- data/examples/http_client_1.rb +9 -0
- data/examples/http_client_2.rb +9 -0
- data/examples/ws_client_1.rb +14 -0
- data/examples/ws_client_2.rb +9 -0
- data/examples/ws_client_3.rb +21 -0
- data/examples/ws_client_4.rb +13 -0
- data/lib/address.rb +0 -0
- data/lib/client/client_ext.rb +214 -0
- data/lib/client/http_client.rb +37 -77
- data/lib/client/ws_client.rb +202 -0
- data/lib/codec.rb +0 -0
- data/lib/hasher.rb +0 -0
- data/lib/metadata/metadata.rb +0 -0
- data/lib/metadata/metadata_v10.rb +0 -0
- data/lib/metadata/metadata_v11.rb +0 -0
- data/lib/metadata/metadata_v12.rb +0 -0
- data/lib/metadata/metadata_v13.rb +0 -0
- data/lib/metadata/metadata_v14.rb +0 -0
- data/lib/metadata/metadata_v9.rb +0 -0
- data/lib/monkey_patching.rb +0 -0
- data/lib/portable_codec.rb +0 -0
- data/lib/registry.rb +0 -0
- data/lib/scale_rb/version.rb +1 -1
- data/lib/scale_rb.rb +4 -4
- data/lib/storage_helper.rb +0 -0
- data/scale_rb.gemspec +7 -3
- data/tea.yaml +6 -0
- metadata +61 -13
- data/lib/client/abstract_ws_client.rb +0 -104
- data/lib/client/http_client_metadata.rb +0 -78
- data/lib/client/http_client_storage.rb +0 -180
- data/lib/client/rpc_request_builder.rb +0 -55
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 79d55aeb610c1a4a11410703445983aa6b02cbf8ee21653a38d425b06c41e3dc
|
4
|
+
data.tar.gz: 8e7832aa2495fed7226797bd21bc23db257754c8d5160cba57f7830879fe592f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 879a524038c25c42b98724a95c9db2658ba41a952386fa4132eb56ceff4d3403aa3fc519c4add1d29fc1ad6e413bdb5f1bc8ab4585a836327bc233dc7750ab43
|
7
|
+
data.tar.gz: 4529731208f640854a9b9b3676ffdd3727b9344833ab026cd593f5d10e17ea0428bd651bc01aa774cb80fd68350249ba68be4b99eea54db6fe597b6f3732723a
|
data/.gitignore
CHANGED
data/.rspec
CHANGED
File without changes
|
data/.rubocop.yml
CHANGED
File without changes
|
data/.travis.yml
CHANGED
File without changes
|
data/CODE_OF_CONDUCT.md
CHANGED
File without changes
|
data/Gemfile
CHANGED
File without changes
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
scale_rb (0.
|
4
|
+
scale_rb (0.3.0)
|
5
|
+
async
|
6
|
+
async-http (~> 0.69.0)
|
7
|
+
async-websocket (~> 0.26.2)
|
5
8
|
base58
|
6
9
|
blake2b_rs (~> 0.1.4)
|
7
10
|
xxhash
|
@@ -9,13 +12,57 @@ PATH
|
|
9
12
|
GEM
|
10
13
|
remote: https://rubygems.org/
|
11
14
|
specs:
|
15
|
+
async (2.14.0)
|
16
|
+
console (~> 1.25, >= 1.25.2)
|
17
|
+
fiber-annotation
|
18
|
+
io-event (~> 1.6, >= 1.6.5)
|
19
|
+
async-http (0.69.0)
|
20
|
+
async (>= 2.10.2)
|
21
|
+
async-pool (~> 0.7)
|
22
|
+
io-endpoint (~> 0.11)
|
23
|
+
io-stream (~> 0.4)
|
24
|
+
protocol-http (~> 0.26)
|
25
|
+
protocol-http1 (~> 0.19)
|
26
|
+
protocol-http2 (~> 0.18)
|
27
|
+
traces (>= 0.10)
|
28
|
+
async-pool (0.7.0)
|
29
|
+
async (>= 1.25)
|
30
|
+
async-websocket (0.26.2)
|
31
|
+
async-http (~> 0.54)
|
32
|
+
protocol-rack (~> 0.5)
|
33
|
+
protocol-websocket (~> 0.14)
|
12
34
|
base58 (0.2.3)
|
13
35
|
blake2b_rs (0.1.4)
|
14
36
|
ffi (~> 1.0)
|
15
37
|
thermite (~> 0)
|
38
|
+
console (1.25.2)
|
39
|
+
fiber-annotation
|
40
|
+
fiber-local (~> 1.1)
|
41
|
+
json
|
16
42
|
diff-lcs (1.5.0)
|
17
|
-
ffi (1.
|
43
|
+
ffi (1.17.0)
|
44
|
+
fiber-annotation (0.2.0)
|
45
|
+
fiber-local (1.1.0)
|
46
|
+
fiber-storage
|
47
|
+
fiber-storage (0.1.2)
|
48
|
+
io-endpoint (0.11.0)
|
49
|
+
io-event (1.6.5)
|
50
|
+
io-stream (0.4.0)
|
51
|
+
json (2.7.2)
|
18
52
|
minitar (0.9)
|
53
|
+
protocol-hpack (1.4.3)
|
54
|
+
protocol-http (0.27.0)
|
55
|
+
protocol-http1 (0.19.1)
|
56
|
+
protocol-http (~> 0.22)
|
57
|
+
protocol-http2 (0.18.0)
|
58
|
+
protocol-hpack (~> 1.4)
|
59
|
+
protocol-http (~> 0.18)
|
60
|
+
protocol-rack (0.6.0)
|
61
|
+
protocol-http (~> 0.23)
|
62
|
+
rack (>= 1.0)
|
63
|
+
protocol-websocket (0.15.0)
|
64
|
+
protocol-http (~> 0.2)
|
65
|
+
rack (3.1.7)
|
19
66
|
rake (12.3.3)
|
20
67
|
rspec (3.11.0)
|
21
68
|
rspec-core (~> 3.11.0)
|
@@ -35,6 +82,7 @@ GEM
|
|
35
82
|
rake (>= 10)
|
36
83
|
tomlrb (~> 1.2)
|
37
84
|
tomlrb (1.3.0)
|
85
|
+
traces (0.11.1)
|
38
86
|
xxhash (0.5.0)
|
39
87
|
|
40
88
|
PLATFORMS
|
data/LICENSE.txt
CHANGED
File without changes
|
data/README.md
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# ScaleRb
|
2
2
|
|
3
|
-
*WARNING: UNDER DEVELOPMENT*
|
4
|
-
|
5
3
|
## Installation
|
6
4
|
|
7
5
|
Add this line to your application's Gemfile:
|
@@ -18,9 +16,14 @@ Or install it yourself as:
|
|
18
16
|
|
19
17
|
$ gem install scale_rb
|
20
18
|
|
21
|
-
##
|
19
|
+
## Run examples
|
22
20
|
|
23
|
-
|
21
|
+
```bash
|
22
|
+
git clone https://github.com/wuminzhe/scale_rb.git
|
23
|
+
cd scale_rb
|
24
|
+
bundle install
|
25
|
+
bundle exec ruby examples/http_client_1.rb
|
26
|
+
```
|
24
27
|
|
25
28
|
## Development
|
26
29
|
|
data/Rakefile
CHANGED
File without changes
|
@@ -0,0 +1,9 @@
|
|
1
|
+
|
2
|
+
require 'scale_rb'
|
3
|
+
|
4
|
+
ScaleRb.logger.level = Logger::DEBUG
|
5
|
+
|
6
|
+
client = ScaleRb::HttpClient.new('https://polkadot-rpc.dwellir.com')
|
7
|
+
block_hash = client.chain_getBlockHash(21585684)
|
8
|
+
runtime_version = client.state_getRuntimeVersion(block_hash)
|
9
|
+
puts runtime_version
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'scale_rb'
|
2
|
+
|
3
|
+
ScaleRb.logger.level = Logger::DEBUG
|
4
|
+
|
5
|
+
client = ScaleRb::HttpClient.new('https://polkadot-rpc.dwellir.com')
|
6
|
+
block_number = 21585684
|
7
|
+
block_hash = client.chain_getBlockHash(block_number)
|
8
|
+
storage = client.get_storage(block_hash, 'System', 'Events')
|
9
|
+
puts "block #{block_number}(#{block_hash}) has #{storage.length} events"
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'scale_rb'
|
2
|
+
|
3
|
+
ScaleRb.logger.level = Logger::DEBUG
|
4
|
+
|
5
|
+
# the commented code below is the same as the code above
|
6
|
+
ScaleRb::WsClient.start('wss://polkadot-rpc.dwellir.com') do |client|
|
7
|
+
block_hash = client.chain_getBlockHash(21585684)
|
8
|
+
# block_hash = client.request('chain_getBlockHash', [21585684])
|
9
|
+
|
10
|
+
runtime_version = client.state_getRuntimeVersion(block_hash)
|
11
|
+
# runtime_version = client.request('state_getRuntimeVersion', [block_hash])
|
12
|
+
|
13
|
+
puts runtime_version
|
14
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'scale_rb'
|
2
|
+
|
3
|
+
ScaleRb.logger.level = Logger::DEBUG
|
4
|
+
|
5
|
+
ScaleRb::WsClient.start('wss://polkadot-rpc.dwellir.com') do |client|
|
6
|
+
count = 0
|
7
|
+
|
8
|
+
subscription_id = client.chain_subscribeNewHead do |head|
|
9
|
+
count = count + 1
|
10
|
+
|
11
|
+
if count < 5
|
12
|
+
block_number = head['number'].to_i(16)
|
13
|
+
block_hash = client.chain_getBlockHash(block_number)
|
14
|
+
puts "Received new head at height: #{block_number}, block hash: #{block_hash}"
|
15
|
+
else
|
16
|
+
client.chain_unsubscribeNewHead(subscription_id)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
puts "Subscribed to new heads with subscription id: #{subscription_id}"
|
21
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'scale_rb'
|
2
|
+
|
3
|
+
# ScaleRb.logger.level = Logger::DEBUG
|
4
|
+
|
5
|
+
ScaleRb::WsClient.start('wss://polkadot-rpc.dwellir.com') do |client|
|
6
|
+
client.chain_subscribeFinalizedHeads do |head|
|
7
|
+
block_number = head['number'].to_i(16)
|
8
|
+
block_hash = client.chain_getBlockHash(block_number)
|
9
|
+
|
10
|
+
storage = client.get_storage(block_hash, 'System', 'Events')
|
11
|
+
puts "block #{block_number}(#{block_hash}) has #{storage.length} events"
|
12
|
+
end
|
13
|
+
end
|
data/lib/address.rb
CHANGED
File without changes
|
@@ -0,0 +1,214 @@
|
|
1
|
+
module ScaleRb
|
2
|
+
module ClientExt
|
3
|
+
def get_metadata(block_hash)
|
4
|
+
dir = ENV['SCALE_RB_METADATA_DIR'] || File.join(Dir.pwd, 'metadata')
|
5
|
+
|
6
|
+
get_metadata_by_block_hash(dir, block_hash)
|
7
|
+
end
|
8
|
+
|
9
|
+
# get storage at block_hash
|
10
|
+
def get_storage(block_hash, pallet_name, storage_name, key_part1: nil, key_part2: nil)
|
11
|
+
metadata = get_metadata(block_hash)
|
12
|
+
|
13
|
+
# storeage item
|
14
|
+
pallet_name = to_pascal pallet_name
|
15
|
+
storage_name = to_pascal storage_name
|
16
|
+
|
17
|
+
# storage param
|
18
|
+
key = [key_part1, key_part2].compact
|
19
|
+
ScaleRb.logger.debug "#{pallet_name}.#{storage_name}(#{key.join(', ')})"
|
20
|
+
key = key.map { |part_of_key| c(part_of_key) }
|
21
|
+
ScaleRb.logger.debug "converted key: #{key}"
|
22
|
+
|
23
|
+
get_storage2(
|
24
|
+
block_hash, # at
|
25
|
+
pallet_name,
|
26
|
+
storage_name,
|
27
|
+
key,
|
28
|
+
metadata
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def get_metadata_by_block_hash(cache_dir, block_hash)
|
35
|
+
# Get metadata from cache if it exists
|
36
|
+
runtime_version = state_getRuntimeVersion(block_hash)
|
37
|
+
spec_name = runtime_version['specName']
|
38
|
+
spec_version = runtime_version['specVersion']
|
39
|
+
metadata = cached_metadata(spec_name, spec_version, cache_dir)
|
40
|
+
return metadata if metadata
|
41
|
+
|
42
|
+
# Get metadata from node
|
43
|
+
metadata_hex = state_getMetadata(block_hash)
|
44
|
+
metadata = ScaleRb::Metadata.decode_metadata(metadata_hex.strip._to_bytes)
|
45
|
+
|
46
|
+
# cache it
|
47
|
+
save_metadata_to_file(spec_name, spec_version, metadata, cache_dir)
|
48
|
+
|
49
|
+
return metadata
|
50
|
+
end
|
51
|
+
|
52
|
+
def cached_metadata(spec_name, spec_version, dir)
|
53
|
+
file_path = File.join(dir, "#{spec_name}-#{spec_version}.json")
|
54
|
+
return unless File.exist?(file_path)
|
55
|
+
|
56
|
+
JSON.parse(File.read(file_path))
|
57
|
+
end
|
58
|
+
|
59
|
+
def save_metadata_to_file(spec_name, spec_version, metadata, dir)
|
60
|
+
FileUtils.mkdir_p(dir)
|
61
|
+
|
62
|
+
File.open(File.join(dir, "#{spec_name}-#{spec_version}.json"), 'w') do |f|
|
63
|
+
f.write(JSON.pretty_generate(metadata))
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
####
|
68
|
+
|
69
|
+
def query_storage_at(block_hash, storage_keys, type_id, default, registry)
|
70
|
+
result = state_queryStorageAt(storage_keys, block_hash)
|
71
|
+
result.map do |item|
|
72
|
+
item['changes'].map do |change|
|
73
|
+
storage_key = change[0]
|
74
|
+
data = change[1] || default
|
75
|
+
storage = data.nil? ? nil : PortableCodec.decode(type_id, data._to_bytes, registry)[0]
|
76
|
+
{ storage_key: storage_key, storage: storage }
|
77
|
+
end
|
78
|
+
end.flatten
|
79
|
+
end
|
80
|
+
|
81
|
+
def get_storage_keys_by_partial_key(block_hash, partial_storage_key, start_key = nil)
|
82
|
+
storage_keys = state_getKeysPaged(partial_storage_key, 1000, start_key, block_hash)
|
83
|
+
if storage_keys.length == 1000
|
84
|
+
storage_keys + get_storage_keys_by_partial_key(block_hash, partial_storage_key, storage_keys.last)
|
85
|
+
else
|
86
|
+
storage_keys
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def get_storages_by_partial_key(block_hash, partial_storage_key, type_id_of_value, default, registry)
|
91
|
+
storage_keys = get_storage_keys_by_partial_key(block_hash, partial_storage_key, partial_storage_key)
|
92
|
+
storage_keys.each_slice(250).map do |slice|
|
93
|
+
query_storage_at(
|
94
|
+
slice,
|
95
|
+
type_id_of_value,
|
96
|
+
default,
|
97
|
+
registry,
|
98
|
+
block_hash
|
99
|
+
)
|
100
|
+
end.flatten
|
101
|
+
end
|
102
|
+
|
103
|
+
# 1. Plain
|
104
|
+
# key: nil
|
105
|
+
# value: { type: 3, modifier: 'Default', callback: '' }
|
106
|
+
#
|
107
|
+
# 2. Map
|
108
|
+
# key: { value: value, type: 0, hashers: ['Blake2128Concat'] }
|
109
|
+
# value: { type: 3, modifier: 'Default', callback: '' }
|
110
|
+
#
|
111
|
+
# 3. Map, but key.value is nil
|
112
|
+
# key: { value: nil, type: 0, hashers: ['Blake2128Concat'] }
|
113
|
+
# value: { type: 3, modifier: 'Default', callback: '' }
|
114
|
+
#
|
115
|
+
# example:
|
116
|
+
# 'System',
|
117
|
+
# 'Account',
|
118
|
+
# key = {
|
119
|
+
# value: [['0x724d50824542b56f422588421643c4a162b90b5416ef063f2266a1eae6651641'._to_bytes]], # [AccountId]
|
120
|
+
# type: 0,
|
121
|
+
# hashers: ['Blake2128Concat']
|
122
|
+
# },
|
123
|
+
# value = {
|
124
|
+
# type: 3,
|
125
|
+
# modifier: 'Default',
|
126
|
+
# callback: '0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
127
|
+
# },
|
128
|
+
# ..
|
129
|
+
#
|
130
|
+
# TODO: part of the key is provided, but not all
|
131
|
+
def get_storage1(block_hash, pallet_name, item_name, key, value, registry)
|
132
|
+
if key
|
133
|
+
if key[:value].nil? || key[:value].empty?
|
134
|
+
# map, but no key's value provided. get all storages under the partial storage key
|
135
|
+
partial_storage_key = StorageHelper.encode_storage_key(pallet_name, item_name)._to_hex
|
136
|
+
get_storages_by_partial_key(
|
137
|
+
block_hash,
|
138
|
+
partial_storage_key,
|
139
|
+
value[:type],
|
140
|
+
value[:modifier] == 'Default' ? value[:fallback] : nil,
|
141
|
+
registry
|
142
|
+
)
|
143
|
+
elsif key[:value].length != key[:hashers].length
|
144
|
+
# map with multi parts, but not have all values
|
145
|
+
partial_storage_key = StorageHelper.encode_storage_key(pallet_name, item_name, key, registry)._to_hex
|
146
|
+
get_storages_by_partial_key(
|
147
|
+
block_hash,
|
148
|
+
partial_storage_key,
|
149
|
+
value[:type],
|
150
|
+
value[:modifier] == 'Default' ? value[:fallback] : nil,
|
151
|
+
registry
|
152
|
+
)
|
153
|
+
end
|
154
|
+
else
|
155
|
+
storage_key = StorageHelper.encode_storage_key(pallet_name, item_name, key, registry)._to_hex
|
156
|
+
data = state_getStorage(storage_key, block_hash)
|
157
|
+
StorageHelper.decode_storage(data, value[:type], value[:modifier] == 'Optional', value[:fallback], registry)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def get_storage2(block_hash, pallet_name, item_name, value_of_key, metadata)
|
162
|
+
raise 'Metadata should not be nil' if metadata.nil?
|
163
|
+
|
164
|
+
registry = Metadata.build_registry(metadata)
|
165
|
+
item = Metadata.get_storage_item(
|
166
|
+
pallet_name, item_name, metadata
|
167
|
+
)
|
168
|
+
raise "No such storage item: `#{pallet_name}`.`#{item_name}`" if item.nil?
|
169
|
+
|
170
|
+
modifier = item._get(:modifier) # Default | Optional
|
171
|
+
fallback = item._get(:fallback)
|
172
|
+
type = item._get(:type)
|
173
|
+
|
174
|
+
plain = type._get(:plain)
|
175
|
+
map = type._get(:map)
|
176
|
+
# debug
|
177
|
+
|
178
|
+
key, value =
|
179
|
+
if plain
|
180
|
+
[
|
181
|
+
nil,
|
182
|
+
{ type: plain,
|
183
|
+
modifier: modifier, fallback: fallback }
|
184
|
+
]
|
185
|
+
elsif map
|
186
|
+
[
|
187
|
+
{ value: value_of_key,
|
188
|
+
type: map._get(:key), hashers: map._get(:hashers) },
|
189
|
+
{ type: map._get(:value),
|
190
|
+
modifier: modifier, fallback: fallback }
|
191
|
+
]
|
192
|
+
else
|
193
|
+
raise 'NoSuchStorageType'
|
194
|
+
end
|
195
|
+
get_storage1(block_hash, pallet_name, item_name, key, value, registry)
|
196
|
+
end
|
197
|
+
|
198
|
+
def to_pascal(str)
|
199
|
+
str.split('_').collect(&:capitalize).join
|
200
|
+
end
|
201
|
+
|
202
|
+
# convert key to byte array
|
203
|
+
def c(key)
|
204
|
+
if key.start_with?('0x')
|
205
|
+
key._to_bytes
|
206
|
+
elsif key.to_i.to_s == key # check if key is a number
|
207
|
+
key.to_i
|
208
|
+
else
|
209
|
+
key
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|
214
|
+
end
|
data/lib/client/http_client.rb
CHANGED
@@ -3,95 +3,55 @@
|
|
3
3
|
require 'uri'
|
4
4
|
require 'net/http'
|
5
5
|
require 'json'
|
6
|
-
require_relative './rpc_request_builder'
|
7
|
-
require_relative './http_client_metadata'
|
8
|
-
require_relative './http_client_storage'
|
9
6
|
|
10
|
-
|
7
|
+
require_relative 'client_ext'
|
8
|
+
|
11
9
|
module ScaleRb
|
12
|
-
|
13
|
-
|
10
|
+
class HttpClient
|
11
|
+
include ClientExt
|
12
|
+
attr_accessor :supported_methods
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
uri = URI(url)
|
20
|
-
req = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json')
|
21
|
-
req.body = body
|
22
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
23
|
-
http.use_ssl = true if uri.instance_of? URI::HTTPS
|
24
|
-
res = http.request(req)
|
14
|
+
def initialize(url)
|
15
|
+
# check if the url is started with http or https
|
16
|
+
url_regex = %r{^https?://}
|
17
|
+
raise 'url format is not correct' unless url.match?(url_regex)
|
25
18
|
|
26
|
-
|
19
|
+
@uri = URI.parse(url)
|
20
|
+
@supported_methods = request('rpc_methods', [])['methods']
|
21
|
+
end
|
27
22
|
|
28
|
-
|
29
|
-
|
30
|
-
|
23
|
+
def request(method, params = [])
|
24
|
+
# don't check for rpc_methods, because there is no @supported_methods when initializing
|
25
|
+
if method != 'rpc_methods' && !@supported_methods.include?(method)
|
26
|
+
raise "Method `#{method}` is not supported. It should be in [#{@supported_methods.join(', ')}]."
|
27
|
+
end
|
31
28
|
|
32
|
-
|
33
|
-
|
34
|
-
raise e unless tries < 5
|
29
|
+
http = Net::HTTP.new(@uri.host, @uri.port)
|
30
|
+
http.use_ssl = @uri.scheme == 'https'
|
35
31
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
request(url, body, tries + 1)
|
40
|
-
end
|
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}"
|
41
35
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
end
|
36
|
+
# https://docs.ruby-lang.org/en/master/Net/HTTPResponse.html
|
37
|
+
response = http.request(request)
|
38
|
+
raise response unless response.is_a?(Net::HTTPOK)
|
46
39
|
|
47
|
-
|
48
|
-
|
49
|
-
|
40
|
+
body = JSON.parse(response.body)
|
41
|
+
ScaleRb.logger.debug "Response: #{body}"
|
42
|
+
raise body['error'] if body['error']
|
50
43
|
|
51
|
-
|
52
|
-
|
53
|
-
# check if the first argument is a url
|
54
|
-
url_regex = %r{^https?://}
|
55
|
-
raise 'url format is not correct' unless args[0].match?(url_regex)
|
44
|
+
body['result']
|
45
|
+
end
|
56
46
|
|
57
|
-
|
58
|
-
|
47
|
+
def respond_to_missing?(*_args)
|
48
|
+
true
|
49
|
+
end
|
59
50
|
|
60
|
-
|
61
|
-
|
51
|
+
def method_missing(method, *args)
|
52
|
+
ScaleRb.logger.debug "#{method}(#{args.join(', ')})"
|
62
53
|
|
63
|
-
|
64
|
-
result = json_rpc_call(url, 'rpc_methods', [])
|
65
|
-
result['methods']
|
66
|
-
end
|
54
|
+
request(method.to_s, args)
|
67
55
|
end
|
68
56
|
end
|
69
|
-
end
|
70
|
-
|
71
|
-
# https://polkadot.js.org/docs/substrate/rpc/
|
72
|
-
#
|
73
|
-
# Examples:
|
74
|
-
# # Get all supported rpc methods
|
75
|
-
# ScaleRb::HttpClient.rpc_methods("https://rpc.darwinia.network")
|
76
|
-
#
|
77
|
-
# # eth_blockNumber
|
78
|
-
# ScaleRb::HttpClient.eth_blockNumber("https://rpc.darwinia.network")
|
79
|
-
#
|
80
|
-
# # system_name
|
81
|
-
# ScaleRb::HttpClient.system_name("https://rpc.darwinia.network")
|
82
|
-
#
|
83
|
-
# # chain_getHead
|
84
|
-
# ScaleRb::HttpClient.chain_getHead("https://rpc.darwinia.network")
|
85
|
-
#
|
86
|
-
# # state_getMetadata of darwinia block #1582
|
87
|
-
# ScaleRb::HttpClient.state_getMetadata(
|
88
|
-
# "https://rpc.darwinia.network",
|
89
|
-
# "0xb5a4f16d0feba7531e75315432b4d31a5b918987e026437890a2cbf5b8d9956d"
|
90
|
-
# )
|
91
|
-
#
|
92
|
-
# # eth_getBalance of address 0x0000000000000000000000000000000000000000 at block #1582
|
93
|
-
# ScaleRb::HttpClient.eth_getBalance(
|
94
|
-
# "https://rpc.darwinia.network",
|
95
|
-
# "0x0000000000000000000000000000000000000000",
|
96
|
-
# 1582
|
97
|
-
# )
|
57
|
+
end
|