scale.rb 0.2.14 → 0.2.19
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Cargo.lock +2007 -11
- data/Cargo.toml +9 -2
- data/Dockerfile +4 -1
- data/Gemfile.lock +45 -46
- data/README.md +28 -1
- data/exe/scale +39 -70
- data/lib/address.rb +3 -0
- data/lib/common.rb +163 -0
- data/lib/helper.rb +128 -0
- data/lib/metadata/metadata.rb +15 -1
- data/lib/scale.rb +105 -33
- data/lib/scale/base.rb +52 -13
- data/lib/scale/block.rb +17 -27
- data/lib/scale/types.rb +71 -4
- data/lib/scale/version.rb +1 -1
- data/lib/substrate_client.rb +170 -0
- data/lib/type_registry/{crab-28.json → crab.json} +474 -126
- data/lib/type_registry/darwinia.json +701 -136
- data/lib/type_registry/default.json +2 -2
- data/lib/type_registry/pangolin.json +332 -0
- data/scale.gemspec +7 -5
- data/scripts/block_events.rb +2 -3
- data/src/lib.rs +42 -1
- data/src/storage_key.rs +41 -0
- metadata +52 -26
- data/.DS_Store +0 -0
- data/lib/type_registry/darwinia-8.json +0 -662
- data/lib/type_registry/edgeware.json +0 -124
- data/lib/type_registry/joystream.json +0 -49
- data/lib/type_registry/kulupu.json +0 -15
- data/lib/type_registry/plasm.json +0 -89
- data/lib/type_registry/robonomics.json +0 -39
- data/lib/type_registry/westend.json +0 -63
data/lib/scale/block.rb
CHANGED
@@ -5,12 +5,12 @@ module Scale
|
|
5
5
|
include SingleValue
|
6
6
|
# attr_accessor :address, :signature, :nonce, :era, :extrinsic_hash, :call_index, :params_raw, :params
|
7
7
|
|
8
|
-
def self.generate_hash(
|
9
|
-
|
8
|
+
def self.generate_hash(bytes)
|
9
|
+
Crypto.blake2_256 bytes
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.decode(scale_bytes)
|
13
|
-
metadata = Scale::TypeRegistry.instance.metadata
|
13
|
+
metadata = Scale::TypeRegistry.instance.metadata.value
|
14
14
|
result = {}
|
15
15
|
|
16
16
|
extrinsic_length = Compact.decode(scale_bytes).value
|
@@ -24,9 +24,6 @@ module Scale
|
|
24
24
|
if contains_transaction
|
25
25
|
address = Scale::Types.get("Address").decode(scale_bytes)
|
26
26
|
result[:address] = address.value
|
27
|
-
result[:account_length] = address.account_length
|
28
|
-
result[:account_id] = address.account_id
|
29
|
-
result[:account_index] = address.account_index
|
30
27
|
result[:signature] = Scale::Types.get("Signature").decode(scale_bytes).value
|
31
28
|
result[:nonce] = Scale::Types.get("Compact").decode(scale_bytes).value
|
32
29
|
result[:era] = Scale::Types.get("Era").decode(scale_bytes).value
|
@@ -39,9 +36,6 @@ module Scale
|
|
39
36
|
if contains_transaction
|
40
37
|
address = Scale::Types.get("Address").decode(scale_bytes)
|
41
38
|
result[:address] = address.value
|
42
|
-
result[:account_length] = address.account_length
|
43
|
-
result[:account_id] = address.account_id
|
44
|
-
result[:account_index] = address.account_index
|
45
39
|
result[:signature] = Scale::Types.get("Signature").decode(scale_bytes).value
|
46
40
|
result[:era] = Scale::Types.get("Era").decode(scale_bytes).value
|
47
41
|
result[:nonce] = Scale::Types.get("Compact").decode(scale_bytes).value
|
@@ -55,9 +49,6 @@ module Scale
|
|
55
49
|
if contains_transaction
|
56
50
|
address = Scale::Types.get("Address").decode(scale_bytes)
|
57
51
|
result[:address] = address.value
|
58
|
-
result[:account_length] = address.account_length
|
59
|
-
result[:account_id] = address.account_id
|
60
|
-
result[:account_index] = address.account_index
|
61
52
|
result[:signature] = Scale::Types.get("Signature").decode(scale_bytes).value
|
62
53
|
result[:era] = Scale::Types.get("Era").decode(scale_bytes).value
|
63
54
|
result[:nonce] = Scale::Types.get("Compact").decode(scale_bytes).value
|
@@ -69,13 +60,8 @@ module Scale
|
|
69
60
|
elsif version_info == "0x04" || version_info == "0x84"
|
70
61
|
|
71
62
|
if contains_transaction
|
72
|
-
address = Scale::Types.get("Address").decode(scale_bytes)
|
73
|
-
result[:
|
74
|
-
result[:account_length] = address.account_length
|
75
|
-
result[:account_id] = address.account_id
|
76
|
-
result[:account_index] = address.account_index
|
77
|
-
result[:signature_version] = Scale::Types.get("U8").decode(scale_bytes).value
|
78
|
-
result[:signature] = Scale::Types.get("Signature").decode(scale_bytes).value
|
63
|
+
result[:address] = Scale::Types.get("Address").decode(scale_bytes).value
|
64
|
+
result[:signature] = Scale::Types.get("MultiSignature").decode(scale_bytes).value
|
79
65
|
result[:era] = Scale::Types.get("Era").decode(scale_bytes).value
|
80
66
|
result[:nonce] = Scale::Types.get("Compact").decode(scale_bytes).value
|
81
67
|
result[:tip] = Scale::Types.get("Compact").decode(scale_bytes).value
|
@@ -146,7 +132,7 @@ module Scale
|
|
146
132
|
include SingleValue
|
147
133
|
|
148
134
|
def self.decode(scale_bytes)
|
149
|
-
metadata = Scale::TypeRegistry.instance.metadata
|
135
|
+
metadata = Scale::TypeRegistry.instance.metadata.value
|
150
136
|
|
151
137
|
result = {}
|
152
138
|
phase = scale_bytes.get_next_bytes(1).first
|
@@ -155,9 +141,13 @@ module Scale
|
|
155
141
|
result[:extrinsic_idx] = U32.decode(scale_bytes).value
|
156
142
|
end
|
157
143
|
|
158
|
-
|
159
|
-
event = metadata.event_index[
|
160
|
-
|
144
|
+
index = scale_bytes.get_next_bytes(2).bytes_to_hex[2..]
|
145
|
+
event = metadata.event_index[index][1]
|
146
|
+
the_module = metadata.event_index[index][0]
|
147
|
+
|
148
|
+
result[:event_index] = index
|
149
|
+
result[:event_metadata] = event
|
150
|
+
result[:module_metadata] = the_module
|
161
151
|
|
162
152
|
result[:params] = []
|
163
153
|
event[:args].each do |arg_type|
|
@@ -175,18 +165,18 @@ module Scale
|
|
175
165
|
end
|
176
166
|
end
|
177
167
|
|
178
|
-
# log
|
179
|
-
class Other < Bytes; end
|
180
|
-
|
181
168
|
class AuthoritiesChange
|
182
169
|
include Vec
|
183
170
|
inner_type "AccountId"
|
184
171
|
end
|
185
172
|
|
186
|
-
class
|
173
|
+
class GenericConsensusEngineId < VecU8Length4; end
|
187
174
|
|
188
175
|
class ChangesTrieRoot < Bytes; end
|
189
176
|
|
177
|
+
# log
|
178
|
+
class Other < Bytes; end
|
179
|
+
|
190
180
|
class SealV0
|
191
181
|
include Struct
|
192
182
|
items(
|
data/lib/scale/types.rb
CHANGED
@@ -6,10 +6,13 @@ module Scale
|
|
6
6
|
BYTES_LENGTH = 1
|
7
7
|
|
8
8
|
def self.decode(scale_bytes)
|
9
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
9
10
|
bytes = scale_bytes.get_next_bytes(self::BYTES_LENGTH)
|
10
11
|
if bytes == [0]
|
12
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
11
13
|
Bool.new(false)
|
12
14
|
elsif bytes == [1]
|
15
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
13
16
|
Bool.new(true)
|
14
17
|
else
|
15
18
|
raise "Bad data"
|
@@ -80,6 +83,7 @@ module Scale
|
|
80
83
|
include SingleValue
|
81
84
|
|
82
85
|
def self.decode(scale_bytes)
|
86
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
83
87
|
first_byte = scale_bytes.get_next_bytes(1)[0]
|
84
88
|
first_byte_in_bin = first_byte.to_s(2).rjust(8, "0")
|
85
89
|
|
@@ -113,6 +117,7 @@ module Scale
|
|
113
117
|
.to_i(16)
|
114
118
|
end
|
115
119
|
|
120
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
116
121
|
Compact.new(value)
|
117
122
|
end
|
118
123
|
|
@@ -141,6 +146,7 @@ module Scale
|
|
141
146
|
include SingleValue
|
142
147
|
|
143
148
|
def self.decode(scale_bytes)
|
149
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
144
150
|
length = Scale::Types::Compact.decode(scale_bytes).value
|
145
151
|
bytes = scale_bytes.get_next_bytes(length)
|
146
152
|
|
@@ -148,8 +154,10 @@ module Scale
|
|
148
154
|
# => "Café"
|
149
155
|
str = bytes.pack("C*").force_encoding("utf-8")
|
150
156
|
if str.valid_encoding?
|
157
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
151
158
|
Bytes.new str
|
152
159
|
else
|
160
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
153
161
|
Bytes.new bytes.bytes_to_hex
|
154
162
|
end
|
155
163
|
end
|
@@ -171,8 +179,10 @@ module Scale
|
|
171
179
|
include SingleValue
|
172
180
|
|
173
181
|
def self.decode(scale_bytes)
|
182
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
174
183
|
length = Scale::Types::Compact.decode(scale_bytes).value
|
175
184
|
hex_string = scale_bytes.get_next_bytes(length).bytes_to_hex
|
185
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
176
186
|
Hex.new(hex_string)
|
177
187
|
end
|
178
188
|
end
|
@@ -180,8 +190,10 @@ module Scale
|
|
180
190
|
class String
|
181
191
|
include SingleValue
|
182
192
|
def self.decode(scale_bytes)
|
193
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
183
194
|
length = Scale::Types::Compact.decode(scale_bytes).value
|
184
195
|
bytes = scale_bytes.get_next_bytes(length)
|
196
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
185
197
|
String.new bytes.pack("C*").force_encoding("utf-8")
|
186
198
|
end
|
187
199
|
end
|
@@ -189,7 +201,9 @@ module Scale
|
|
189
201
|
class H160
|
190
202
|
include SingleValue
|
191
203
|
def self.decode(scale_bytes)
|
204
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
192
205
|
bytes = scale_bytes.get_next_bytes(20)
|
206
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
193
207
|
H160.new(bytes.bytes_to_hex)
|
194
208
|
end
|
195
209
|
|
@@ -202,7 +216,9 @@ module Scale
|
|
202
216
|
class H256
|
203
217
|
include SingleValue
|
204
218
|
def self.decode(scale_bytes)
|
219
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
205
220
|
bytes = scale_bytes.get_next_bytes(32)
|
221
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
206
222
|
H256.new(bytes.bytes_to_hex)
|
207
223
|
end
|
208
224
|
|
@@ -215,7 +231,9 @@ module Scale
|
|
215
231
|
class H512
|
216
232
|
include SingleValue
|
217
233
|
def self.decode(scale_bytes)
|
234
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
218
235
|
bytes = scale_bytes.get_next_bytes(64)
|
236
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
219
237
|
H512.new(bytes.bytes_to_hex)
|
220
238
|
end
|
221
239
|
|
@@ -234,12 +252,14 @@ module Scale
|
|
234
252
|
# the <address> is 32 byte account id or 1, 2, 4, 8 byte account index
|
235
253
|
# scale_bytes: account length byte + <address>'s bytes
|
236
254
|
def self.decode(scale_bytes)
|
255
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
237
256
|
account_length = scale_bytes.get_next_bytes(1).first
|
238
257
|
|
239
258
|
if account_length == 0xff # 32 bytes address(Public key)
|
240
259
|
account_id = scale_bytes.get_next_bytes(32).bytes_to_hex
|
241
260
|
account_length = [account_length].bytes_to_hex
|
242
261
|
|
262
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
243
263
|
Address.new({
|
244
264
|
account_id: account_id,
|
245
265
|
account_length: account_length
|
@@ -258,6 +278,7 @@ module Scale
|
|
258
278
|
# TODO: add account_idx
|
259
279
|
account_length = [account_length].bytes_to_hex
|
260
280
|
|
281
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
261
282
|
Address.new({
|
262
283
|
account_index: account_index,
|
263
284
|
account_length: account_length
|
@@ -280,10 +301,14 @@ module Scale
|
|
280
301
|
|
281
302
|
class AccountIdAddress < GenericAddress
|
282
303
|
def self.decode(scale_bytes)
|
283
|
-
|
304
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
305
|
+
result = AccountIdAddress.new({
|
284
306
|
account_id: AccountId.decode(scale_bytes).value,
|
285
307
|
account_length: "0xff"
|
286
308
|
})
|
309
|
+
|
310
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
311
|
+
result
|
287
312
|
end
|
288
313
|
|
289
314
|
def encode
|
@@ -304,12 +329,15 @@ module Scale
|
|
304
329
|
class Era
|
305
330
|
include SingleValue
|
306
331
|
def self.decode(scale_bytes)
|
332
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
307
333
|
byte = scale_bytes.get_next_bytes(1).bytes_to_hex
|
308
|
-
if byte == "0x00"
|
334
|
+
result = if byte == "0x00"
|
309
335
|
Era.new byte
|
310
336
|
else
|
311
337
|
Era.new byte + scale_bytes.get_next_bytes(1).bytes_to_hex()[2..]
|
312
338
|
end
|
339
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
340
|
+
result
|
313
341
|
end
|
314
342
|
end
|
315
343
|
|
@@ -320,12 +348,14 @@ module Scale
|
|
320
348
|
class CompactMoment
|
321
349
|
include SingleValue
|
322
350
|
def self.decode(scale_bytes)
|
351
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
323
352
|
value = Compact.decode(scale_bytes).value
|
324
353
|
if value > 10000000000
|
325
354
|
value /= 1000
|
326
355
|
end
|
327
356
|
|
328
|
-
|
357
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
358
|
+
CompactMoment.new Time.at(value).strftime("%F %T")
|
329
359
|
end
|
330
360
|
end
|
331
361
|
|
@@ -570,34 +600,52 @@ module Scale
|
|
570
600
|
|
571
601
|
class VecU8Length2
|
572
602
|
include VecU8FixedLength
|
603
|
+
BYTE_LENGTH = 2
|
573
604
|
end
|
574
605
|
|
575
606
|
class VecU8Length3
|
576
607
|
include VecU8FixedLength
|
608
|
+
BYTE_LENGTH = 3
|
577
609
|
end
|
578
610
|
|
579
611
|
class VecU8Length4
|
580
612
|
include VecU8FixedLength
|
613
|
+
BYTE_LENGTH = 4
|
581
614
|
end
|
582
615
|
|
583
616
|
class VecU8Length8
|
584
617
|
include VecU8FixedLength
|
618
|
+
BYTE_LENGTH = 8
|
585
619
|
end
|
586
620
|
|
587
621
|
class VecU8Length16
|
588
622
|
include VecU8FixedLength
|
623
|
+
BYTE_LENGTH = 16
|
589
624
|
end
|
590
625
|
|
591
626
|
class VecU8Length20
|
592
627
|
include VecU8FixedLength
|
628
|
+
BYTE_LENGTH = 20
|
593
629
|
end
|
594
630
|
|
595
631
|
class VecU8Length32
|
596
632
|
include VecU8FixedLength
|
633
|
+
BYTE_LENGTH = 32
|
597
634
|
end
|
598
635
|
|
599
636
|
class VecU8Length64
|
600
637
|
include VecU8FixedLength
|
638
|
+
BYTE_LENGTH = 64
|
639
|
+
end
|
640
|
+
|
641
|
+
class VecU8Length128
|
642
|
+
include VecU8FixedLength
|
643
|
+
BYTE_LENGTH = 128
|
644
|
+
end
|
645
|
+
|
646
|
+
class VecU8Length256
|
647
|
+
include VecU8FixedLength
|
648
|
+
BYTE_LENGTH = 256
|
601
649
|
end
|
602
650
|
|
603
651
|
class BalanceLock
|
@@ -614,7 +662,9 @@ module Scale
|
|
614
662
|
include SingleValue
|
615
663
|
|
616
664
|
def self.decode(scale_bytes)
|
665
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
617
666
|
bytes = scale_bytes.get_next_bytes(20)
|
667
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
618
668
|
EthereumAddress.new(bytes.bytes_to_hex)
|
619
669
|
end
|
620
670
|
|
@@ -631,8 +681,10 @@ module Scale
|
|
631
681
|
include SingleValue
|
632
682
|
|
633
683
|
def self.decode(scale_bytes)
|
684
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
634
685
|
bytes = scale_bytes.get_next_bytes(65)
|
635
686
|
EcdsaSignature.new(bytes.bytes_to_hex)
|
687
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
636
688
|
end
|
637
689
|
|
638
690
|
def encode
|
@@ -740,7 +792,11 @@ module Scale
|
|
740
792
|
class VoteOutcome
|
741
793
|
include SingleValue
|
742
794
|
def self.decode(scale_bytes)
|
743
|
-
|
795
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
796
|
+
result = new(scale_bytes.get_next_bytes(32))
|
797
|
+
|
798
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
799
|
+
result
|
744
800
|
end
|
745
801
|
end
|
746
802
|
|
@@ -781,6 +837,7 @@ module Scale
|
|
781
837
|
include SingleValue
|
782
838
|
|
783
839
|
def self.decode(scale_bytes, metadata, chain_spec)
|
840
|
+
puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
784
841
|
call_index = scale_bytes.get_next_bytes(2).bytes_to_hex[2..]
|
785
842
|
call_module, call = metadata.value.call_index[call_index]
|
786
843
|
|
@@ -789,6 +846,7 @@ module Scale
|
|
789
846
|
{name: arg[:name], type: arg[:type], value: arg_obj.encode, value_raw: arg_obj.value}
|
790
847
|
end
|
791
848
|
|
849
|
+
puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
|
792
850
|
self.new({
|
793
851
|
call_index: call_index,
|
794
852
|
call_function: call[:name],
|
@@ -826,6 +884,15 @@ module Scale
|
|
826
884
|
end
|
827
885
|
end
|
828
886
|
|
887
|
+
class GenericBlock
|
888
|
+
include SingleValue
|
889
|
+
|
890
|
+
def self.decode(scale_bytes)
|
891
|
+
end
|
892
|
+
|
893
|
+
def encode
|
894
|
+
end
|
895
|
+
end
|
829
896
|
|
830
897
|
end
|
831
898
|
end
|
data/lib/scale/version.rb
CHANGED
@@ -0,0 +1,170 @@
|
|
1
|
+
require "faye/websocket"
|
2
|
+
require "eventmachine"
|
3
|
+
|
4
|
+
def ws_request(url, payload)
|
5
|
+
result = nil
|
6
|
+
|
7
|
+
EM.run do
|
8
|
+
ws = Faye::WebSocket::Client.new(url)
|
9
|
+
|
10
|
+
ws.on :open do |event|
|
11
|
+
ws.send(payload.to_json)
|
12
|
+
end
|
13
|
+
|
14
|
+
ws.on :message do |event|
|
15
|
+
if event.data.include?("jsonrpc")
|
16
|
+
result = JSON.parse event.data
|
17
|
+
ws.close(3001, "data received")
|
18
|
+
EM.stop
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
ws.on :close do |event|
|
23
|
+
ws = nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
result
|
28
|
+
end
|
29
|
+
|
30
|
+
class SubstrateClient
|
31
|
+
class WebsocketError < StandardError; end
|
32
|
+
class RpcError < StandardError; end
|
33
|
+
class RpcTimeout < StandardError; end
|
34
|
+
|
35
|
+
attr_reader :metadata
|
36
|
+
attr_reader :spec_name, :spec_version
|
37
|
+
|
38
|
+
def initialize(url)
|
39
|
+
@url = url
|
40
|
+
@request_id = 1
|
41
|
+
@metadata_cache = {}
|
42
|
+
end
|
43
|
+
|
44
|
+
def request(method, params)
|
45
|
+
payload = {
|
46
|
+
"jsonrpc" => "2.0",
|
47
|
+
"method" => method,
|
48
|
+
"params" => params,
|
49
|
+
"id" => @request_id
|
50
|
+
}
|
51
|
+
|
52
|
+
data = ws_request(@url, payload)
|
53
|
+
if data["error"]
|
54
|
+
raise RpcError, data["error"]
|
55
|
+
else
|
56
|
+
data["result"]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def init_types_and_metadata(block_hash=nil)
|
61
|
+
runtime_version = self.state_getRuntimeVersion(block_hash)
|
62
|
+
spec_name = runtime_version["specName"].downcase
|
63
|
+
spec_version = runtime_version["specVersion"]
|
64
|
+
|
65
|
+
registry = Scale::TypeRegistry.instance
|
66
|
+
|
67
|
+
# load types
|
68
|
+
if registry.types == nil
|
69
|
+
registry.load(spec_name: spec_name)
|
70
|
+
end
|
71
|
+
registry.spec_version = spec_version
|
72
|
+
|
73
|
+
# set current metadata
|
74
|
+
metadata = @metadata_cache[spec_version]
|
75
|
+
if metadata.nil?
|
76
|
+
hex = self.state_getMetadata(block_hash)
|
77
|
+
metadata = Scale::Types::Metadata.decode(Scale::Bytes.new(hex))
|
78
|
+
@metadata_cache[spec_version] = metadata
|
79
|
+
end
|
80
|
+
|
81
|
+
@metadata = metadata
|
82
|
+
registry.metadata = metadata
|
83
|
+
|
84
|
+
true
|
85
|
+
end
|
86
|
+
|
87
|
+
def get_metadata_from_cache(spec_version)
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
def invoke(method, *params)
|
92
|
+
request(method, params)
|
93
|
+
end
|
94
|
+
|
95
|
+
# ################################################
|
96
|
+
# origin rpc methods
|
97
|
+
# ################################################
|
98
|
+
def method_missing(method, *args)
|
99
|
+
invoke method, *args
|
100
|
+
end
|
101
|
+
|
102
|
+
# ################################################
|
103
|
+
# custom methods based on origin rpc methods
|
104
|
+
# ################################################
|
105
|
+
def methods
|
106
|
+
invoke("rpc_methods")["methods"]
|
107
|
+
end
|
108
|
+
|
109
|
+
def get_block_number(block_hash)
|
110
|
+
header = self.chain_getHeader(block_hash)
|
111
|
+
header["number"].to_i(16)
|
112
|
+
end
|
113
|
+
|
114
|
+
def get_metadata(block_hash=nil)
|
115
|
+
self.init_types_and_metadata(block_hash)
|
116
|
+
@metadata
|
117
|
+
end
|
118
|
+
|
119
|
+
def get_block(block_hash=nil)
|
120
|
+
self.init_types_and_metadata(block_hash)
|
121
|
+
block = self.chain_getBlock(block_hash)
|
122
|
+
SubstrateClient::Helper.decode_block(block)
|
123
|
+
rescue => ex
|
124
|
+
puts ex.message
|
125
|
+
puts ex.backtrace.join("\n\t")
|
126
|
+
end
|
127
|
+
|
128
|
+
def get_block_events(block_hash=nil)
|
129
|
+
self.init_types_and_metadata(block_hash)
|
130
|
+
|
131
|
+
storage_key = "0x26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7"
|
132
|
+
events_data = state_getStorage storage_key, block_hash
|
133
|
+
|
134
|
+
scale_bytes = Scale::Bytes.new(events_data)
|
135
|
+
decoded = Scale::Types.get("Vec<EventRecord>").decode(scale_bytes).to_human
|
136
|
+
[events_data, decoded]
|
137
|
+
end
|
138
|
+
|
139
|
+
# Plain: client.get_storage("Sudo", "Key")
|
140
|
+
# Plain: client.get_storage("Balances", "TotalIssuance")
|
141
|
+
# Map: client.get_storage("System", "Account", ["0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"])
|
142
|
+
# DoubleMap: client.get_storage("ImOnline", "AuthoredBlocks", [2818, "0x749ddc93a65dfec3af27cc7478212cb7d4b0c0357fef35a0163966ab5333b757"])
|
143
|
+
def get_storage(module_name, storage_name, params = nil, block_hash = nil)
|
144
|
+
self.init_types_and_metadata(block_hash)
|
145
|
+
|
146
|
+
storage_key, return_type = SubstrateClient::Helper.generate_storage_key_from_metadata(@metadata, module_name, storage_name, params)
|
147
|
+
data = self.state_getStorage(storage_key, block_hash)
|
148
|
+
return unless data
|
149
|
+
|
150
|
+
bytes = Scale::Bytes.new(data)
|
151
|
+
type = Scale::Types.get(return_type)
|
152
|
+
type.decode(bytes)
|
153
|
+
end
|
154
|
+
|
155
|
+
def generate_storage_key(module_name, storage_name, params = nil, block_hash = nil)
|
156
|
+
self.init_types_and_metadata(block_hash)
|
157
|
+
SubstrateClient::Helper.generate_storage_key_from_metadata(@metadata, module_name, storage_name, params)
|
158
|
+
end
|
159
|
+
|
160
|
+
# compose_call "Balances", "Transfer", { dest: "0x586cb27c291c813ce74e86a60dad270609abf2fc8bee107e44a80ac00225c409", value: 1_000_000_000_000 }
|
161
|
+
def compose_call(module_name, call_name, params, block_hash=nil)
|
162
|
+
self.init_types_and_metadata(block_hash)
|
163
|
+
SubstrateClient::Helper.compose_call_from_metadata(@metadata, module_name, call_name, params)
|
164
|
+
end
|
165
|
+
|
166
|
+
def generate_storage_hash_from_data(storage_hex_data)
|
167
|
+
"0x" + Crypto.blake2_256(Scale::Bytes.new(storage_hex_data).bytes)
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|