scale.rb 0.2.19 → 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.
data/lib/scale/types.rb CHANGED
@@ -2,7 +2,7 @@ module Scale
2
2
  module Types
3
3
 
4
4
  class Bool
5
- include SingleValue
5
+ include Base
6
6
  BYTES_LENGTH = 1
7
7
 
8
8
  def self.decode(scale_bytes)
@@ -10,10 +10,10 @@ module Scale
10
10
  bytes = scale_bytes.get_next_bytes(self::BYTES_LENGTH)
11
11
  if bytes == [0]
12
12
  puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
13
- Bool.new(false)
13
+ new(false)
14
14
  elsif bytes == [1]
15
15
  puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
16
- Bool.new(true)
16
+ new(true)
17
17
  else
18
18
  raise "Bad data"
19
19
  end
@@ -24,6 +24,35 @@ module Scale
24
24
  end
25
25
  end
26
26
 
27
+ class OptionBool
28
+ include Base
29
+ def self.decode(scale_bytes)
30
+ byte = scale_bytes.get_next_bytes(1)[0]
31
+ value = if byte == 0x00
32
+ nil
33
+ elsif byte == 0x01
34
+ true
35
+ elsif byte == 0x02
36
+ false
37
+ else
38
+ raise BadDataError.new("Bad scale data for OptionBool #{byte.to_s(16)}")
39
+ end
40
+ new(value)
41
+ end
42
+
43
+ def encode
44
+ if value.nil?
45
+ "00"
46
+ elsif value === true
47
+ "01"
48
+ elsif value === false
49
+ "02"
50
+ else
51
+ raise WrongValueError.new("OptionBool can not have value other than `nil`, `true`, `false`")
52
+ end
53
+ end
54
+ end
55
+
27
56
  class U8
28
57
  include FixedWidthUInt
29
58
  BYTE_LENGTH = 1
@@ -54,6 +83,11 @@ module Scale
54
83
  BYTE_LENGTH = 32
55
84
  end
56
85
 
86
+ class U512
87
+ include FixedWidthUInt
88
+ BYTE_LENGTH = 64
89
+ end
90
+
57
91
  class I8
58
92
  include FixedWidthInt
59
93
  BYTE_LENGTH = 1
@@ -80,7 +114,7 @@ module Scale
80
114
  end
81
115
 
82
116
  class Compact
83
- include SingleValue
117
+ include Base
84
118
 
85
119
  def self.decode(scale_bytes)
86
120
  puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
@@ -118,7 +152,7 @@ module Scale
118
152
  end
119
153
 
120
154
  puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
121
- Compact.new(value)
155
+ new(value)
122
156
  end
123
157
 
124
158
  def encode
@@ -143,7 +177,7 @@ module Scale
143
177
  end
144
178
 
145
179
  class Bytes
146
- include SingleValue
180
+ include Base
147
181
 
148
182
  def self.decode(scale_bytes)
149
183
  puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
@@ -155,10 +189,10 @@ module Scale
155
189
  str = bytes.pack("C*").force_encoding("utf-8")
156
190
  if str.valid_encoding?
157
191
  puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
158
- Bytes.new str
192
+ new str
159
193
  else
160
194
  puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
161
- Bytes.new bytes.bytes_to_hex
195
+ new bytes.bytes_to_hex
162
196
  end
163
197
  end
164
198
 
@@ -176,35 +210,40 @@ module Scale
176
210
  end
177
211
 
178
212
  class Hex
179
- include SingleValue
213
+ include Base
180
214
 
181
215
  def self.decode(scale_bytes)
182
216
  puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
183
217
  length = Scale::Types::Compact.decode(scale_bytes).value
184
218
  hex_string = scale_bytes.get_next_bytes(length).bytes_to_hex
185
219
  puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
186
- Hex.new(hex_string)
220
+ new(hex_string)
221
+ end
222
+
223
+ def encode
224
+ length = Compact.new((value.length - 2)/2).encode
225
+ "#{length}#{value[2..]}"
187
226
  end
188
227
  end
189
228
 
190
229
  class String
191
- include SingleValue
230
+ include Base
192
231
  def self.decode(scale_bytes)
193
232
  puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
194
233
  length = Scale::Types::Compact.decode(scale_bytes).value
195
234
  bytes = scale_bytes.get_next_bytes(length)
196
235
  puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
197
- String.new bytes.pack("C*").force_encoding("utf-8")
236
+ new bytes.pack("C*").force_encoding("utf-8")
198
237
  end
199
238
  end
200
239
 
201
240
  class H160
202
- include SingleValue
241
+ include Base
203
242
  def self.decode(scale_bytes)
204
243
  puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
205
244
  bytes = scale_bytes.get_next_bytes(20)
206
245
  puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
207
- H160.new(bytes.bytes_to_hex)
246
+ new(bytes.bytes_to_hex)
208
247
  end
209
248
 
210
249
  def encode
@@ -214,12 +253,12 @@ module Scale
214
253
  end
215
254
 
216
255
  class H256
217
- include SingleValue
256
+ include Base
218
257
  def self.decode(scale_bytes)
219
258
  puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
220
259
  bytes = scale_bytes.get_next_bytes(32)
221
260
  puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
222
- H256.new(bytes.bytes_to_hex)
261
+ new(bytes.bytes_to_hex)
223
262
  end
224
263
 
225
264
  def encode
@@ -229,12 +268,12 @@ module Scale
229
268
  end
230
269
 
231
270
  class H512
232
- include SingleValue
271
+ include Base
233
272
  def self.decode(scale_bytes)
234
273
  puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
235
274
  bytes = scale_bytes.get_next_bytes(64)
236
275
  puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
237
- H512.new(bytes.bytes_to_hex)
276
+ new(bytes.bytes_to_hex)
238
277
  end
239
278
 
240
279
  def encode
@@ -244,7 +283,7 @@ module Scale
244
283
  end
245
284
 
246
285
  class GenericAddress
247
- include SingleValue
286
+ include Base
248
287
 
249
288
  # https://github.com/paritytech/substrate/wiki/External-Address-Format-(SS58)
250
289
  # base58encode ( concat ( <address-type>, <address>, <checksum> ) )
@@ -260,7 +299,7 @@ module Scale
260
299
  account_length = [account_length].bytes_to_hex
261
300
 
262
301
  puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
263
- Address.new({
302
+ new({
264
303
  account_id: account_id,
265
304
  account_length: account_length
266
305
  })
@@ -279,7 +318,7 @@ module Scale
279
318
  account_length = [account_length].bytes_to_hex
280
319
 
281
320
  puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
282
- Address.new({
321
+ new({
283
322
  account_index: account_index,
284
323
  account_length: account_length
285
324
  })
@@ -302,7 +341,7 @@ module Scale
302
341
  class AccountIdAddress < GenericAddress
303
342
  def self.decode(scale_bytes)
304
343
  puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
305
- result = AccountIdAddress.new({
344
+ result = new({
306
345
  account_id: AccountId.decode(scale_bytes).value,
307
346
  account_length: "0xff"
308
347
  })
@@ -316,6 +355,17 @@ module Scale
316
355
  end
317
356
  end
318
357
 
358
+ class GenericMultiAddress
359
+ include Enum
360
+ items(
361
+ Id: "AccountId",
362
+ Index: "Compact",
363
+ Raw: "Hex",
364
+ Address32: "H256",
365
+ Address20: "H160"
366
+ )
367
+ end
368
+
319
369
  class AccountId < H256; end
320
370
 
321
371
  class Balance < U128; end
@@ -327,14 +377,14 @@ module Scale
327
377
  class AccountIndex < U32; end
328
378
 
329
379
  class Era
330
- include SingleValue
380
+ include Base
331
381
  def self.decode(scale_bytes)
332
382
  puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
333
383
  byte = scale_bytes.get_next_bytes(1).bytes_to_hex
334
384
  result = if byte == "0x00"
335
- Era.new byte
385
+ new byte
336
386
  else
337
- Era.new byte + scale_bytes.get_next_bytes(1).bytes_to_hex()[2..]
387
+ new byte + scale_bytes.get_next_bytes(1).bytes_to_hex()[2..]
338
388
  end
339
389
  puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
340
390
  result
@@ -346,7 +396,7 @@ module Scale
346
396
  class Moment < U64; end
347
397
 
348
398
  class CompactMoment
349
- include SingleValue
399
+ include Base
350
400
  def self.decode(scale_bytes)
351
401
  puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
352
402
  value = Compact.decode(scale_bytes).value
@@ -355,7 +405,7 @@ module Scale
355
405
  end
356
406
 
357
407
  puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
358
- CompactMoment.new Time.at(value).strftime("%F %T")
408
+ new Time.at(value).strftime("%F %T")
359
409
  end
360
410
  end
361
411
 
@@ -459,9 +509,9 @@ module Scale
459
509
  end
460
510
 
461
511
  class Null
462
- include SingleValue
512
+ include Base
463
513
  def self.decode(scale_bytes)
464
- Null.new nil
514
+ new nil
465
515
  end
466
516
 
467
517
  def encode
@@ -652,20 +702,20 @@ module Scale
652
702
  include Struct
653
703
  items(
654
704
  id: "VecU8Length8",
655
- amount: "Balance",
705
+ amount: "Scale::Types::Balance",
656
706
  until: "U32",
657
- reasons: "WithdrawReasons"
707
+ reasons: "Scale::Types::WithdrawReasons"
658
708
  )
659
709
  end
660
710
 
661
711
  class EthereumAddress
662
- include SingleValue
712
+ include Base
663
713
 
664
714
  def self.decode(scale_bytes)
665
715
  puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
666
716
  bytes = scale_bytes.get_next_bytes(20)
667
717
  puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
668
- EthereumAddress.new(bytes.bytes_to_hex)
718
+ new(bytes.bytes_to_hex)
669
719
  end
670
720
 
671
721
  def encode
@@ -678,12 +728,12 @@ module Scale
678
728
  end
679
729
 
680
730
  class EcdsaSignature
681
- include SingleValue
731
+ include Base
682
732
 
683
733
  def self.decode(scale_bytes)
684
734
  puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
685
735
  bytes = scale_bytes.get_next_bytes(65)
686
- EcdsaSignature.new(bytes.bytes_to_hex)
736
+ new(bytes.bytes_to_hex)
687
737
  puts " END " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
688
738
  end
689
739
 
@@ -790,7 +840,7 @@ module Scale
790
840
  end
791
841
 
792
842
  class VoteOutcome
793
- include SingleValue
843
+ include Base
794
844
  def self.decode(scale_bytes)
795
845
  puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
796
846
  result = new(scale_bytes.get_next_bytes(32))
@@ -834,7 +884,7 @@ module Scale
834
884
  end
835
885
 
836
886
  class BoxProposal
837
- include SingleValue
887
+ include Base
838
888
 
839
889
  def self.decode(scale_bytes, metadata, chain_spec)
840
890
  puts "BEGIN " + self::TYPE_NAME + ": #{scale_bytes}" if Scale::Types.debug == true
@@ -872,7 +922,7 @@ module Scale
872
922
  end
873
923
 
874
924
  class VecH512Length2
875
- include SingleValue
925
+ include Base
876
926
 
877
927
  def self.decode(scale_bytes)
878
928
  end
@@ -885,7 +935,7 @@ module Scale
885
935
  end
886
936
 
887
937
  class GenericBlock
888
- include SingleValue
938
+ include Base
889
939
 
890
940
  def self.decode(scale_bytes)
891
941
  end
data/lib/scale/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Scale
2
- VERSION = "0.2.19".freeze
2
+ VERSION = "0.3.0".freeze
3
3
  end
@@ -0,0 +1,63 @@
1
+ module Scale
2
+ class Bytes
3
+ attr_reader :data, :bytes
4
+ attr_reader :offset
5
+
6
+ def initialize(data)
7
+ if (data.class == Array) && data.is_byte_array?
8
+ @bytes = data
9
+ elsif (data.class == String) && data.start_with?("0x") && (data.length % 2 == 0)
10
+ arr = data[2..].scan(/../).map(&:hex)
11
+ @bytes = arr
12
+ else
13
+ raise "Provided data is not valid"
14
+ end
15
+
16
+ @data = data
17
+ @offset = 0
18
+ end
19
+
20
+ def reset_offset
21
+ @offset = 0
22
+ end
23
+
24
+ def get_next_bytes(length)
25
+ result = @bytes[@offset...@offset + length]
26
+ if result.length < length
27
+ str = @data[(2 + @offset * 2)..]
28
+ str = str.length > 40 ? (str[0...40]).to_s + "..." : str
29
+ raise "No enough data: #{str}, expect length: #{length}, but #{result.length}"
30
+ end
31
+ @offset += length
32
+ result
33
+ rescue RangeError => ex
34
+ puts "length: #{length}"
35
+ puts ex.message
36
+ puts ex.backtrace
37
+ end
38
+
39
+ def get_remaining_bytes
40
+ @bytes[offset..]
41
+ end
42
+
43
+ def to_hex_string
44
+ @bytes.bytes_to_hex
45
+ end
46
+
47
+ def to_bin_string
48
+ @bytes.bytes_to_bin
49
+ end
50
+
51
+ def to_ascii
52
+ @bytes[0...offset].pack("C*") + "<================================>" + @bytes[offset..].pack("C*")
53
+ end
54
+
55
+ def ==(other)
56
+ bytes == other.bytes && offset == other.offset
57
+ end
58
+
59
+ def to_s
60
+ green(@bytes[0...offset].bytes_to_hex) + yellow(@bytes[offset..].bytes_to_hex[2..])
61
+ end
62
+ end
63
+ end
@@ -39,6 +39,7 @@ class SubstrateClient
39
39
  @url = url
40
40
  @request_id = 1
41
41
  @metadata_cache = {}
42
+ init_types_and_metadata
42
43
  end
43
44
 
44
45
  def request(method, params)
@@ -136,16 +137,18 @@ class SubstrateClient
136
137
  [events_data, decoded]
137
138
  end
138
139
 
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
140
  def get_storage(module_name, storage_name, params = nil, block_hash = nil)
144
141
  self.init_types_and_metadata(block_hash)
145
142
 
146
- storage_key, return_type = SubstrateClient::Helper.generate_storage_key_from_metadata(@metadata, module_name, storage_name, params)
143
+ storage_key, return_type, storage_item = SubstrateClient::Helper.generate_storage_key_from_metadata(@metadata, module_name, storage_name, params)
144
+
147
145
  data = self.state_getStorage(storage_key, block_hash)
148
- return unless data
146
+
147
+ if data.nil?
148
+ return if storage_item[:modifier] == "Optional"
149
+
150
+ data = storage_item[:fallback]
151
+ end
149
152
 
150
153
  bytes = Scale::Bytes.new(data)
151
154
  type = Scale::Types.get(return_type)