scale_rb 0.3.2 → 0.3.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 +1 -0
- data/README.md +3 -1
- data/examples/http_client_2.rb +8 -2
- data/examples/ws_client_1.rb +3 -3
- data/examples/ws_client_2.rb +8 -3
- data/examples/ws_client_3.rb +4 -3
- data/examples/ws_client_error_handling.rb +9 -0
- data/lib/client/client_ext.rb +1 -1
- data/lib/client/http_client.rb +6 -5
- data/lib/client/ws_client.rb +75 -97
- data/lib/scale_rb/version.rb +1 -1
- metadata +3 -3
- data/Gemfile.lock +0 -97
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 946dbb730e56172125e2524d66c41650fb08a3b799576000b5254467080ec771
|
4
|
+
data.tar.gz: cae0b7ce708380ceeefa2bdd412abc30adbc5de5153b68bec12625497cf89e03
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3d9b11df5acc3538b9fd7af4aabd1db74f9fb0f08ab7bc2620299d2145beee2805eeee12b1948e33a9198b0141b4b6c57187bb99f984743dbfb1c7e62e9b0ca7
|
7
|
+
data.tar.gz: df6d923402362b259384fe585a83ee490dc3e5bc5154d41b886a74ee1ab19d3e1fa0e92c0a3f8c2b5ffb976f12138418728b0c046ac23470bb1954b12a65a048
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
data/examples/http_client_2.rb
CHANGED
@@ -3,7 +3,13 @@ require 'scale_rb'
|
|
3
3
|
ScaleRb.logger.level = Logger::DEBUG
|
4
4
|
|
5
5
|
client = ScaleRb::HttpClient.new('https://polkadot-rpc.dwellir.com')
|
6
|
-
block_number =
|
6
|
+
block_number = 21711742
|
7
7
|
block_hash = client.chain_getBlockHash(block_number)
|
8
|
-
|
8
|
+
metadata = client.get_metadata(block_hash)
|
9
|
+
|
10
|
+
storage_query = ScaleRb::WsClient::StorageQuery.new(
|
11
|
+
pallet_name: 'System',
|
12
|
+
storage_name: 'Events',
|
13
|
+
)
|
14
|
+
storage = client.get_storage(block_hash, storage_query, metadata)
|
9
15
|
puts "block #{block_number}(#{block_hash}) has #{storage.length} events"
|
data/examples/ws_client_1.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'scale_rb'
|
2
2
|
|
3
|
-
|
3
|
+
ScaleRb.logger.level = Logger::DEBUG
|
4
4
|
|
5
5
|
ScaleRb::WsClient.start('wss://polkadot-rpc.dwellir.com') do |client|
|
6
6
|
block_hash = client.chain_getBlockHash(21585684)
|
7
7
|
runtime_version = client.state_getRuntimeVersion(block_hash)
|
8
|
-
puts runtime_version[
|
9
|
-
puts runtime_version[
|
8
|
+
puts runtime_version[:specName]
|
9
|
+
puts runtime_version[:specVersion]
|
10
10
|
end
|
data/examples/ws_client_2.rb
CHANGED
@@ -1,9 +1,14 @@
|
|
1
1
|
require 'scale_rb'
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
# You can have multiple subscriptions at the same time
|
5
4
|
ScaleRb::WsClient.start('wss://polkadot-rpc.dwellir.com') do |client|
|
6
5
|
client.chain_subscribeNewHead do |head|
|
7
|
-
puts "Received new head at height: #{head[
|
6
|
+
puts "Received new head at height: #{head[:number].to_i(16)}"
|
7
|
+
end
|
8
|
+
|
9
|
+
client.state_subscribeStorage do |storage|
|
10
|
+
block_hash = storage[:block]
|
11
|
+
changes = storage[:changes]
|
12
|
+
puts "Received #{changes.size} storage changes at block: #{block_hash}"
|
8
13
|
end
|
9
14
|
end
|
data/examples/ws_client_3.rb
CHANGED
@@ -2,19 +2,20 @@ require 'scale_rb'
|
|
2
2
|
|
3
3
|
# ScaleRb.logger.level = Logger::DEBUG
|
4
4
|
|
5
|
+
# Unsubscribe after receiving 4 new heads
|
5
6
|
ScaleRb::WsClient.start('wss://polkadot-rpc.dwellir.com') do |client|
|
6
7
|
count = 0
|
7
8
|
|
8
9
|
subscription_id = client.chain_subscribeNewHead do |head|
|
9
|
-
count
|
10
|
+
count += 1
|
10
11
|
|
11
12
|
if count < 5
|
12
|
-
block_number = head[
|
13
|
+
block_number = head[:number].to_i(16)
|
13
14
|
block_hash = client.chain_getBlockHash(block_number)
|
14
15
|
puts "Received new head at height: #{block_number}, block hash: #{block_hash}"
|
15
16
|
else
|
16
17
|
unsub_result = client.chain_unsubscribeNewHead(subscription_id)
|
17
|
-
puts "
|
18
|
+
puts "Unsubscribe result: #{unsub_result}"
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
data/lib/client/client_ext.rb
CHANGED
@@ -42,7 +42,7 @@ module ScaleRb
|
|
42
42
|
def query_storage_at(block_hash, storage_keys, type_id, default, registry)
|
43
43
|
result = state_queryStorageAt(storage_keys, block_hash)
|
44
44
|
result.map do |item|
|
45
|
-
item[
|
45
|
+
item[:changes].map do |change|
|
46
46
|
storage_key = change[0]
|
47
47
|
data = change[1] || default
|
48
48
|
storage = data.nil? ? nil : PortableCodec.decode(type_id, data._to_bytes, registry)[0]
|
data/lib/client/http_client.rb
CHANGED
@@ -17,7 +17,7 @@ module ScaleRb
|
|
17
17
|
raise 'url format is not correct' unless url.match?(url_regex)
|
18
18
|
|
19
19
|
@uri = URI.parse(url)
|
20
|
-
@supported_methods = request('rpc_methods', [])[
|
20
|
+
@supported_methods = request('rpc_methods', [])[:methods]
|
21
21
|
end
|
22
22
|
|
23
23
|
def request(method, params = [])
|
@@ -37,11 +37,12 @@ module ScaleRb
|
|
37
37
|
response = http.request(request)
|
38
38
|
raise response unless response.is_a?(Net::HTTPOK)
|
39
39
|
|
40
|
-
|
40
|
+
# parse response, make key symbol
|
41
|
+
body = JSON.parse(response.body, symbolize_names: true)
|
41
42
|
ScaleRb.logger.debug "Response: #{body}"
|
42
|
-
raise body[
|
43
|
+
raise body[:error] if body[:error]
|
43
44
|
|
44
|
-
body[
|
45
|
+
body[:result]
|
45
46
|
end
|
46
47
|
|
47
48
|
def respond_to_missing?(*_args)
|
@@ -54,4 +55,4 @@ module ScaleRb
|
|
54
55
|
request(method.to_s, args)
|
55
56
|
end
|
56
57
|
end
|
57
|
-
end
|
58
|
+
end
|
data/lib/client/ws_client.rb
CHANGED
@@ -1,58 +1,55 @@
|
|
1
1
|
require 'async'
|
2
2
|
require 'async/websocket/client'
|
3
3
|
require 'async/http/endpoint'
|
4
|
-
require 'async/queue'
|
5
|
-
require 'json'
|
6
4
|
|
7
5
|
require_relative 'client_ext'
|
8
6
|
|
9
7
|
module ScaleRb
|
10
8
|
class WsClient
|
11
|
-
def self.start(url)
|
12
|
-
Async do |task|
|
13
|
-
endpoint = Async::HTTP::Endpoint.parse(url, alpn_protocols: Async::HTTP::Protocol::HTTP11.names)
|
14
|
-
client = WsClient.new
|
15
9
|
|
16
|
-
|
10
|
+
class << self
|
11
|
+
# @param [string] url
|
12
|
+
def start(url)
|
13
|
+
Sync do
|
14
|
+
endpoint = Async::HTTP::Endpoint.parse(url, alpn_protocols: Async::HTTP::Protocol::HTTP11.names)
|
15
|
+
|
17
16
|
Async::WebSocket::Client.connect(endpoint) do |connection|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
client = WsClient.new(connection)
|
18
|
+
|
19
|
+
# `recv_task` does not raise errors (subclass of StandardError), so it will not be stopped by any errors.
|
20
|
+
recv_task = Async do
|
21
|
+
while (message = client.read_message)
|
22
|
+
data = parse_message(message)
|
23
|
+
next if data.nil?
|
24
|
+
|
25
|
+
ScaleRb.logger.debug "Received response: #{data}"
|
26
|
+
Async do
|
27
|
+
client.handle_response(data)
|
28
|
+
end
|
22
29
|
end
|
23
30
|
end
|
24
31
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
Async do
|
31
|
-
client.handle_response(data)
|
32
|
-
rescue => e
|
33
|
-
ScaleRb.logger.error "#{e.class}: #{e.message}"
|
34
|
-
ScaleRb.logger.error e.backtrace.join("\n")
|
35
|
-
task.stop
|
36
|
-
end
|
37
|
-
end
|
38
|
-
rescue => e
|
39
|
-
ScaleRb.logger.error "#{e.class}: #{e.message}"
|
40
|
-
ScaleRb.logger.error e.backtrace.join("\n")
|
32
|
+
client.supported_methods = client.rpc_methods()[:methods]
|
33
|
+
yield client
|
34
|
+
|
35
|
+
recv_task.wait
|
41
36
|
ensure
|
42
|
-
|
37
|
+
recv_task&.stop
|
43
38
|
end
|
44
39
|
end
|
45
40
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def parse_message(message)
|
46
|
+
message.parse
|
47
|
+
rescue StandardError => e
|
48
|
+
ScaleRb.logger.error "Error while parsing message: #{e.inspect}, message: #{message}"
|
49
|
+
nil
|
54
50
|
end
|
55
51
|
end
|
52
|
+
|
56
53
|
end
|
57
54
|
end
|
58
55
|
|
@@ -61,8 +58,8 @@ module ScaleRb
|
|
61
58
|
include ClientExt
|
62
59
|
attr_accessor :supported_methods
|
63
60
|
|
64
|
-
def initialize
|
65
|
-
@
|
61
|
+
def initialize(connection)
|
62
|
+
@connection = connection
|
66
63
|
@response_handler = ResponseHandler.new
|
67
64
|
@subscription_handler = SubscriptionHandler.new
|
68
65
|
@request_id = 1
|
@@ -84,10 +81,10 @@ module ScaleRb
|
|
84
81
|
if method.include?('unsubscribe')
|
85
82
|
unsubscribe(method, args[0])
|
86
83
|
elsif method.include?('subscribe')
|
87
|
-
raise
|
84
|
+
raise 'A subscribe method needs a block' unless block_given?
|
88
85
|
|
89
86
|
subscribe(method, args) do |notification|
|
90
|
-
yield notification[
|
87
|
+
yield notification[:params][:result]
|
91
88
|
end
|
92
89
|
else
|
93
90
|
request(method, args)
|
@@ -111,17 +108,27 @@ module ScaleRb
|
|
111
108
|
end
|
112
109
|
end
|
113
110
|
|
114
|
-
def next_request
|
115
|
-
@queue.dequeue
|
116
|
-
end
|
117
|
-
|
118
111
|
def handle_response(response)
|
119
|
-
if response.key?(
|
112
|
+
if response.key?(:id)
|
120
113
|
@response_handler.handle(response)
|
121
|
-
elsif response.key?(
|
114
|
+
elsif response.key?(:method)
|
122
115
|
@subscription_handler.handle(response)
|
123
116
|
else
|
124
|
-
|
117
|
+
ScaleRb.logger.info "Received an unknown response: #{response}"
|
118
|
+
end
|
119
|
+
rescue StandardError => e
|
120
|
+
ScaleRb.logger.error "Error while handling response: #{e.inspect}"
|
121
|
+
ScaleRb.logger.debug e.backtrace.join("\n")
|
122
|
+
end
|
123
|
+
|
124
|
+
def read_message
|
125
|
+
loop do
|
126
|
+
return @connection.read
|
127
|
+
rescue StandardError => e
|
128
|
+
ScaleRb.logger.error "Error while read message from connection: #{e.inspect}"
|
129
|
+
ScaleRb.logger.debug e.backtrace.join("\n")
|
130
|
+
sleep 1
|
131
|
+
retry
|
125
132
|
end
|
126
133
|
end
|
127
134
|
|
@@ -131,88 +138,59 @@ module ScaleRb
|
|
131
138
|
response_future = Async::Notification.new
|
132
139
|
|
133
140
|
@response_handler.register(@request_id, proc { |response|
|
134
|
-
|
135
|
-
response_future.signal(response['result'])
|
141
|
+
response_future.signal(response[:result])
|
136
142
|
})
|
137
143
|
|
138
|
-
request =
|
139
|
-
|
144
|
+
request = { jsonrpc: '2.0', id: @request_id, method: method, params: params }
|
145
|
+
ScaleRb.logger.debug "Sending request: #{request}"
|
146
|
+
@connection.write(request.to_json)
|
140
147
|
|
141
148
|
@request_id += 1
|
142
|
-
|
143
149
|
response_future.wait
|
144
150
|
end
|
145
151
|
end
|
146
152
|
|
147
|
-
class JsonRpcRequest
|
148
|
-
attr_reader :id, :method, :params
|
149
|
-
|
150
|
-
def initialize(id, method, params = {})
|
151
|
-
@id = id
|
152
|
-
@method = method
|
153
|
-
@params = params
|
154
|
-
end
|
155
|
-
|
156
|
-
def to_json(*_args)
|
157
|
-
{ jsonrpc: '2.0', id: @id, method: @method, params: @params }.to_json
|
158
|
-
end
|
159
|
-
|
160
|
-
# def to_s
|
161
|
-
# to_json
|
162
|
-
# end
|
163
|
-
end
|
164
|
-
|
165
153
|
class ResponseHandler
|
166
154
|
def initialize
|
167
|
-
@
|
155
|
+
@callbacks = {}
|
168
156
|
end
|
169
157
|
|
170
|
-
#
|
171
|
-
def register(id,
|
172
|
-
@
|
158
|
+
# callback: a proc with response data as param
|
159
|
+
def register(id, callback)
|
160
|
+
@callbacks[id] = callback
|
173
161
|
end
|
174
162
|
|
175
163
|
def handle(response)
|
176
|
-
id = response[
|
177
|
-
if @
|
178
|
-
|
179
|
-
|
180
|
-
@
|
164
|
+
id = response[:id]
|
165
|
+
if @callbacks.key?(id)
|
166
|
+
callback = @callbacks[id]
|
167
|
+
callback.call(response)
|
168
|
+
@callbacks.delete(id)
|
181
169
|
else
|
182
|
-
ScaleRb.logger.
|
170
|
+
ScaleRb.logger.info "Received a message with unknown id: #{response}"
|
183
171
|
end
|
184
172
|
end
|
185
173
|
end
|
186
174
|
|
187
175
|
class SubscriptionHandler
|
188
176
|
def initialize
|
189
|
-
@
|
177
|
+
@callbacks = {}
|
190
178
|
end
|
191
179
|
|
192
|
-
def subscribe(subscription_id,
|
193
|
-
@
|
180
|
+
def subscribe(subscription_id, callback)
|
181
|
+
@callbacks[subscription_id] = callback
|
194
182
|
end
|
195
183
|
|
196
184
|
def unsubscribe(subscription_id)
|
197
|
-
@
|
185
|
+
@callbacks.delete(subscription_id)
|
198
186
|
end
|
199
187
|
|
200
188
|
def handle(notification)
|
201
|
-
subscription_id = notification.dig(
|
189
|
+
subscription_id = notification.dig(:params, :subscription)
|
202
190
|
return if subscription_id.nil?
|
203
191
|
|
204
|
-
if @
|
205
|
-
@
|
206
|
-
else
|
207
|
-
# the subscription_id may be not registered.
|
208
|
-
# in client.subscribe function,
|
209
|
-
# ...
|
210
|
-
# subscription_id = request(method, params)
|
211
|
-
# @subscription_handler.subscribe(subscription_id, block)
|
212
|
-
# ...
|
213
|
-
# the request(method, params) may be slow, so the subscription_id may be not registered when the first notification comes.
|
214
|
-
sleep 0.01
|
215
|
-
handle(notification)
|
192
|
+
if @callbacks.key?(subscription_id)
|
193
|
+
@callbacks[subscription_id].call(notification)
|
216
194
|
end
|
217
195
|
end
|
218
196
|
end
|
data/lib/scale_rb/version.rb
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.3.
|
4
|
+
version: 0.3.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: 2024-
|
11
|
+
date: 2024-08-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: base58
|
@@ -109,7 +109,6 @@ files:
|
|
109
109
|
- ".travis.yml"
|
110
110
|
- CODE_OF_CONDUCT.md
|
111
111
|
- Gemfile
|
112
|
-
- Gemfile.lock
|
113
112
|
- LICENSE.txt
|
114
113
|
- README.md
|
115
114
|
- Rakefile
|
@@ -121,6 +120,7 @@ files:
|
|
121
120
|
- examples/ws_client_2.rb
|
122
121
|
- examples/ws_client_3.rb
|
123
122
|
- examples/ws_client_4.rb
|
123
|
+
- examples/ws_client_error_handling.rb
|
124
124
|
- exe/metadata
|
125
125
|
- lib/address.rb
|
126
126
|
- lib/client/client_ext.rb
|
data/Gemfile.lock
DELETED
@@ -1,97 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
scale_rb (0.3.2)
|
5
|
-
async
|
6
|
-
async-http (~> 0.69.0)
|
7
|
-
async-websocket (~> 0.26.2)
|
8
|
-
base58
|
9
|
-
blake2b_rs (~> 0.1.4)
|
10
|
-
xxhash
|
11
|
-
|
12
|
-
GEM
|
13
|
-
remote: https://rubygems.org/
|
14
|
-
specs:
|
15
|
-
async (2.14.2)
|
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)
|
34
|
-
base58 (0.2.3)
|
35
|
-
blake2b_rs (0.1.4)
|
36
|
-
ffi (~> 1.0)
|
37
|
-
thermite (~> 0)
|
38
|
-
console (1.27.0)
|
39
|
-
fiber-annotation
|
40
|
-
fiber-local (~> 1.1)
|
41
|
-
json
|
42
|
-
diff-lcs (1.5.0)
|
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.13.0)
|
49
|
-
io-event (1.6.5)
|
50
|
-
io-stream (0.4.0)
|
51
|
-
json (2.7.2)
|
52
|
-
minitar (0.9)
|
53
|
-
protocol-hpack (1.4.3)
|
54
|
-
protocol-http (0.28.1)
|
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)
|
66
|
-
rake (12.3.3)
|
67
|
-
rspec (3.11.0)
|
68
|
-
rspec-core (~> 3.11.0)
|
69
|
-
rspec-expectations (~> 3.11.0)
|
70
|
-
rspec-mocks (~> 3.11.0)
|
71
|
-
rspec-core (3.11.0)
|
72
|
-
rspec-support (~> 3.11.0)
|
73
|
-
rspec-expectations (3.11.0)
|
74
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
75
|
-
rspec-support (~> 3.11.0)
|
76
|
-
rspec-mocks (3.11.1)
|
77
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
78
|
-
rspec-support (~> 3.11.0)
|
79
|
-
rspec-support (3.11.0)
|
80
|
-
thermite (0.13.0)
|
81
|
-
minitar (~> 0.5)
|
82
|
-
rake (>= 10)
|
83
|
-
tomlrb (~> 1.2)
|
84
|
-
tomlrb (1.3.0)
|
85
|
-
traces (0.11.1)
|
86
|
-
xxhash (0.5.0)
|
87
|
-
|
88
|
-
PLATFORMS
|
89
|
-
ruby
|
90
|
-
|
91
|
-
DEPENDENCIES
|
92
|
-
rake (~> 12.0)
|
93
|
-
rspec (~> 3.0)
|
94
|
-
scale_rb!
|
95
|
-
|
96
|
-
BUNDLED WITH
|
97
|
-
2.1.4
|