scale.rb 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,561 @@
1
+ module Scale
2
+ module Types
3
+
4
+ class Bool
5
+ include SingleValue
6
+ BYTES_LENGTH = 1
7
+
8
+ def self.decode(scale_bytes)
9
+ bytes = scale_bytes.get_next_bytes(self::BYTES_LENGTH)
10
+ if bytes == [0]
11
+ Bool.new(false)
12
+ elsif bytes == [1]
13
+ Bool.new(true)
14
+ else
15
+ raise "Bad data"
16
+ end
17
+ end
18
+
19
+ def encode
20
+ self.value === true ? "01" : "00"
21
+ end
22
+ end
23
+
24
+ class U8
25
+ include FixedWidthUInt
26
+ BYTES_LENGTH = 1
27
+ end
28
+
29
+ class U16
30
+ include FixedWidthUInt
31
+ BYTES_LENGTH = 2
32
+ end
33
+
34
+ class U32
35
+ include FixedWidthUInt
36
+ BYTES_LENGTH = 4
37
+ end
38
+
39
+ class U64
40
+ include FixedWidthUInt
41
+ BYTES_LENGTH = 8
42
+ end
43
+
44
+ class U128
45
+ include FixedWidthUInt
46
+ BYTES_LENGTH = 16
47
+ end
48
+
49
+ class Compact
50
+ include SingleValue
51
+
52
+ def self.decode(scale_bytes)
53
+ first_byte = scale_bytes.get_next_bytes(1)[0]
54
+ first_byte_in_bin = first_byte.to_s(2).rjust(8, '0')
55
+
56
+ mode = first_byte_in_bin[6..7]
57
+ value =
58
+ if mode == '00'
59
+ first_byte >> 2
60
+ elsif mode == '01'
61
+ second_byte = scale_bytes.get_next_bytes(1)[0]
62
+ [first_byte, second_byte]
63
+ .reverse
64
+ .map { |b| b.to_s(16).rjust(2, '0') }
65
+ .join
66
+ .to_i(16) >> 2
67
+ elsif mode == '10'
68
+ remaining_bytes = scale_bytes.get_next_bytes(3)
69
+ ([first_byte] + remaining_bytes)
70
+ .reverse
71
+ .map { |b| b.to_s(16).rjust(2, '0') }
72
+ .join
73
+ .to_i(16) >> 2
74
+ # or like this:
75
+ # ['02093d00'].pack('H*').unpack('l').first / 4
76
+ elsif mode == '11'
77
+ remaining_length = 4 + (first_byte >> 2)
78
+ remaining_bytes = scale_bytes.get_next_bytes(remaining_length)
79
+ remaining_bytes
80
+ .reverse
81
+ .map { |b| b.to_s(16).rjust(2, '0') }
82
+ .join
83
+ .to_i(16)
84
+ end
85
+
86
+ Compact.new(value)
87
+ end
88
+
89
+ def encode
90
+ if self.value >= 0 and self.value <= 63
91
+ (value << 2).to_s(16).rjust(2, '0')
92
+ elsif self.value > 63 and self.value <= (2**14 - 1)
93
+ ((value << 2) + 1).to_s(16).rjust(4, '0').scan(/.{2}/).reverse.join
94
+ elsif self.value > (2**14 - 1) and self.value <= (2**30 - 1)
95
+ ((value << 2) + 2).to_s(16).rjust(8, '0').scan(/.{2}/).reverse.join
96
+ elsif self.value > (2**30 - 1)
97
+ value_in_hex = self.value.to_s(16)
98
+ length = if value_in_hex.length % 2 == 1
99
+ value_in_hex.length + 1
100
+ else
101
+ value_in_hex.length
102
+ end
103
+
104
+ hex = value_in_hex.rjust(length, '0').scan(/.{2}/).reverse.join
105
+ (((length/2 - 4) << 2) + 3).to_s(16).rjust(2, '0') + hex
106
+ end
107
+ end
108
+ end
109
+
110
+ class Bytes
111
+ include SingleValue
112
+
113
+ def self.decode(scale_bytes)
114
+ length = Scale::Types::Compact.decode(scale_bytes).value
115
+ bytes = scale_bytes.get_next_bytes(length)
116
+
117
+ # [67, 97, 102, 195, 169].pack('C*').force_encoding('utf-8')
118
+ # => "Café"
119
+ str = bytes.pack("C*").force_encoding("utf-8")
120
+ if str.valid_encoding?
121
+ Bytes.new str
122
+ else
123
+ Bytes.new bytes.bytes_to_hex
124
+ end
125
+ end
126
+
127
+ def encode
128
+ if self.value.start_with?("0x")
129
+ length = Compact.new((self.value.length - 2)/2).encode
130
+ "#{length}#{self.value[2..]}"
131
+ else
132
+ bytes = self.value.unpack("C*")
133
+ hex_string = bytes.bytes_to_hex[2..]
134
+ length = Compact.new(bytes.length).encode
135
+ "#{length}#{hex_string}"
136
+ end
137
+ end
138
+ end
139
+
140
+ class Hex
141
+ include SingleValue
142
+
143
+ def self.decode(scale_bytes)
144
+ length = Scale::Types::Compact.decode(scale_bytes).value
145
+ hex_string = scale_bytes.get_next_bytes(length).bytes_to_hex
146
+ Hex.new(hex_string)
147
+ end
148
+ end
149
+
150
+ class String
151
+ include SingleValue
152
+ def self.decode(scale_bytes)
153
+ length = Scale::Types::Compact.decode(scale_bytes).value
154
+ bytes = scale_bytes.get_next_bytes(length)
155
+ String.new bytes.pack("C*").force_encoding("utf-8")
156
+ end
157
+ end
158
+
159
+ class H160
160
+ include SingleValue
161
+ def self.decode(scale_bytes)
162
+ bytes = scale_bytes.get_next_bytes(20)
163
+ H160.new(bytes.bytes_to_hex)
164
+ end
165
+
166
+ def encode
167
+ raise "Format error" if not self.value.start_with?("0x") || self.value.length != 42
168
+ ScaleBytes.new self.value
169
+ end
170
+ end
171
+
172
+ class H256
173
+ include SingleValue
174
+ def self.decode(scale_bytes)
175
+ bytes = scale_bytes.get_next_bytes(32)
176
+ H256.new(bytes.bytes_to_hex)
177
+ end
178
+
179
+ def encode
180
+ raise "Format error" if not self.value.start_with?("0x") || self.value.length != 66
181
+ ScaleBytes.new self.value
182
+ end
183
+ end
184
+
185
+ class H512
186
+ include SingleValue
187
+ def self.decode(scale_bytes)
188
+ bytes = scale_bytes.get_next_bytes(64)
189
+ H512.new(bytes.bytes_to_hex)
190
+ end
191
+
192
+ def encode
193
+ raise "Format error" if not self.value.start_with?("0x") || self.value.length != 130
194
+ ScaleBytes.new self.value
195
+ end
196
+ end
197
+
198
+ class Address
199
+ include SingleValue
200
+ def self.decode(scale_bytes)
201
+ prefix = scale_bytes.get_next_bytes(1).first
202
+ if prefix == 0xff
203
+ value = scale_bytes.get_next_bytes(32).bytes_to_hex
204
+ elsif prefix == 0xfc
205
+ value = scale_bytes.get_next_bytes(2).bytes_to_hex
206
+ elsif prefix == 0xfd
207
+ value = scale_bytes.get_next_bytes(4).bytes_to_hex
208
+ elsif prefix == 0xfe
209
+ value = scale_bytes.get_next_bytes(8).bytes_to_hex
210
+ else
211
+ value = [prefix].bytes_to_hex
212
+ end
213
+
214
+ Address.new(value)
215
+ end
216
+
217
+ def encode(ss58=false, addr_type=42)
218
+ if self.value.start_with?("0x")
219
+ if ss58 === true
220
+ ::Address.encode(self.value, addr_type)
221
+ else
222
+ prefix = if self.value.length == 66
223
+ "ff"
224
+ elsif self.value.length == 6
225
+ "fc"
226
+ elsif self.value.length == 10
227
+ "fd"
228
+ elsif self.value.length == 18
229
+ "fe"
230
+ else
231
+ ""
232
+ end
233
+ "#{prefix}#{self.value[2..]}"
234
+ end
235
+ else
236
+ raise "Format error"
237
+ end
238
+ end
239
+ end
240
+
241
+ class AccountId < H256; end
242
+
243
+ class Balance < U128; end
244
+
245
+ class BalanceOf < Balance; end
246
+
247
+ class BlockNumber < U32; end
248
+
249
+ class AccountIndex < U32; end
250
+
251
+ class Era
252
+ include SingleValue
253
+ def self.decode(scale_bytes)
254
+ byte = scale_bytes.get_next_bytes(1).bytes_to_hex
255
+ if byte == "0x00"
256
+ Era.new byte
257
+ else
258
+ Era.new byte + scale_bytes.get_next_bytes(1).bytes_to_hex()[2..]
259
+ end
260
+ end
261
+ end
262
+
263
+ class EraIndex < U32; end
264
+
265
+ class Moment < U64; end
266
+
267
+ class CompactMoment
268
+ include SingleValue
269
+ def self.decode(scale_bytes)
270
+ value = Compact.decode(scale_bytes).value
271
+ if value > 10000000000
272
+ value = value / 1000
273
+ end
274
+
275
+ CompactMoment.new Time.at(seconds_since_epoch_integer).to_datetime
276
+ end
277
+ end
278
+
279
+ class ProposalPreimage
280
+ include Struct
281
+ items(
282
+ proposal: "Hex",
283
+ registredBy: "AccountId",
284
+ deposit: "BalanceOf",
285
+ blockNumber: "BlockNumber"
286
+ )
287
+ end
288
+
289
+ class RewardDestination
290
+ include Enum
291
+ values "Staked", "Stash", "Controller"
292
+ end
293
+
294
+ class WithdrawReasons
295
+ include Set
296
+ values(
297
+ {
298
+ "TransactionPayment" => 1,
299
+ "Transfer" => 2,
300
+ "Reserve" => 4,
301
+ "Fee" => 8,
302
+ "Tip" => 16
303
+ }, 1
304
+ )
305
+ end
306
+
307
+ class ReferendumIndex < U32; end
308
+
309
+ class PropIndex < U32; end
310
+
311
+ class Vote < U32; end
312
+
313
+ class SessionKey < H256; end
314
+
315
+ class SessionIndex < U32; end
316
+
317
+ class ParaId < U32; end
318
+
319
+ class KeyValue
320
+ include Struct
321
+ items key: "Vec<U8>", value: "Vec<U8>"
322
+ end
323
+
324
+ class NewAccountOutcome < Compact; end
325
+
326
+ class StakingLedger
327
+ include Struct
328
+ items(
329
+ stash: "AccountId",
330
+ total: "Compact",
331
+ active: "Compact",
332
+ unlocking: "Vec<UnlockChunk>"
333
+ )
334
+ end
335
+
336
+ class UnlockChunk
337
+ include Struct
338
+ items(
339
+ value: "Compact",
340
+ era: "Compact"
341
+ )
342
+ end
343
+
344
+ class Exposure
345
+ include Struct
346
+ items(
347
+ total: "Compact",
348
+ own: "Compact",
349
+ others: "Vec<IndividualExposure>"
350
+ )
351
+ end
352
+
353
+ class IndividualExposure
354
+ include Struct
355
+ items(
356
+ who: "AccountId",
357
+ value: "Compact"
358
+ )
359
+ end
360
+
361
+ class BabeAuthorityWeight < U64; end
362
+
363
+ class Points < U32; end
364
+
365
+ class EraPoints
366
+ include Struct
367
+ items(
368
+ total: "Points",
369
+ individual: "Vec<Points>"
370
+ )
371
+ end
372
+
373
+ class VoteThreshold
374
+ include Enum
375
+ values 'SuperMajorityApprove', 'SuperMajorityAgainst', 'SimpleMajority'
376
+ end
377
+
378
+ class Null
379
+ include SingleValue
380
+ def self.decode(scale_bytes)
381
+ Null.new nil
382
+ end
383
+
384
+ def encode
385
+ ""
386
+ end
387
+ end
388
+
389
+ class InherentOfflineReport < Null; end
390
+
391
+ class LockPeriods < U8; end
392
+
393
+ class Hash < H256; end
394
+
395
+ class VoteIndex < U32; end
396
+
397
+ class ProposalIndex < U32; end
398
+
399
+ class Permill < U32; end
400
+
401
+ class Perbill < U32; end
402
+
403
+ class ApprovalFlag < U32; end
404
+
405
+ class SetIndex < U32; end
406
+
407
+ class AuthorityId < AccountId; end
408
+
409
+ class ValidatorId < AccountId; end
410
+
411
+ class AuthorityWeight < U64; end
412
+
413
+ class StoredPendingChange
414
+ include Struct
415
+ items(
416
+ scheduled_at: "U32",
417
+ forced: "U32"
418
+ )
419
+ end
420
+
421
+ class ReportIdOf < Hash; end
422
+
423
+ class StorageHasher
424
+ include Enum
425
+ values 'Blake2_128', 'Blake2_256', 'Blake2_128Concat', 'Twox128', 'Twox256', 'Twox64Concat'
426
+ end
427
+
428
+ class VoterInfo
429
+ include Struct
430
+ items(
431
+ last_active: "VoteIndex",
432
+ last_win: "VoteIndex",
433
+ pot: "Balance",
434
+ stake: "Balance"
435
+ )
436
+ end
437
+
438
+ class Gas < U64; end
439
+
440
+ class CodeHash < Hash; end
441
+
442
+ class PrefabWasmModule
443
+ include Struct
444
+ items(
445
+ scheduleVersion: "Compact",
446
+ initial: "Compact",
447
+ maximum: "Compact",
448
+ _reserved: "Option<Null>",
449
+ code: "Bytes"
450
+ )
451
+ end
452
+
453
+ class OpaqueNetworkState
454
+ include Struct
455
+ items(
456
+ peerId: "OpaquePeerId",
457
+ externalAddresses: "Vec<OpaqueMultiaddr>"
458
+ )
459
+ end
460
+
461
+ class OpaquePeerId < Bytes; end
462
+
463
+ class OpaqueMultiaddr < Bytes; end
464
+
465
+ class SessionKeysSubstrate
466
+ include Struct
467
+ items(
468
+ grandpa: "AccountId",
469
+ babe: "AccountId",
470
+ im_online: "AccountId"
471
+ )
472
+ end
473
+
474
+ class LegacyKeys
475
+ include Struct
476
+ items(
477
+ grandpa: "AccountId",
478
+ babe: "AccountId"
479
+ )
480
+ end
481
+
482
+ class EdgewareKeys
483
+ include Struct
484
+ items(
485
+ grandpa: "AccountId"
486
+ )
487
+ end
488
+
489
+ class QueuedKeys
490
+ include Struct
491
+ items(
492
+ validator: "ValidatorId",
493
+ keys: "Keys"
494
+ )
495
+ end
496
+
497
+ class LegacyQueuedKeys
498
+ include Struct
499
+ items(
500
+ validator: "ValidatorId",
501
+ keys: "LegacyKeys"
502
+ )
503
+ end
504
+
505
+ class EdgewareQueuedKeys
506
+ include Struct
507
+ items(
508
+ validator: "ValidatorId",
509
+ keys: "EdgewareKeys"
510
+ )
511
+ end
512
+
513
+ class VecQueuedKeys
514
+ include Vec
515
+ inner_type "QueuedKeys"
516
+ end
517
+
518
+ class VecU8Length2
519
+ include VecU8FixedLength
520
+ end
521
+
522
+ class VecU8Length3
523
+ include VecU8FixedLength
524
+ end
525
+
526
+ class VecU8Length4
527
+ include VecU8FixedLength
528
+ end
529
+
530
+ class VecU8Length8
531
+ include VecU8FixedLength
532
+ end
533
+
534
+ class VecU8Length16
535
+ include VecU8FixedLength
536
+ end
537
+
538
+ class VecU8Length20
539
+ include VecU8FixedLength
540
+ end
541
+
542
+ class VecU8Length32
543
+ include VecU8FixedLength
544
+ end
545
+
546
+ class VecU8Length64
547
+ include VecU8FixedLength
548
+ end
549
+
550
+ class BalanceLock
551
+ include Struct
552
+ items(
553
+ id: "VecU8Length8",
554
+ amount: "Balance",
555
+ until: "U32",
556
+ reasons: "WithdrawReasons"
557
+ )
558
+ end
559
+
560
+ end
561
+ end
@@ -0,0 +1,3 @@
1
+ module Scale
2
+ VERSION = "0.1.0"
3
+ end