scale.rb 0.1.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.
@@ -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