scale_rb 0.1.6 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3c6c07616c5b65f7aee2b0504956231534d94cd3df9eba9320e4a22d2a38aed2
4
- data.tar.gz: f2f3572c5d7ed389d5772c6245fb2e02eb75d57cf5ff28b78a8db82642d47402
3
+ metadata.gz: 241f9857282220d19480bed1cf2a1bcaeacd0948963a65455ee1c57b708ed4d6
4
+ data.tar.gz: 8ab8fad9f853c7f3d1d57bf9f283b2fbe16a6d17bb2f1221b84ff3a78feff34c
5
5
  SHA512:
6
- metadata.gz: 1709366a718feafae82a60b5a5aeb05e5e78fbc3160c151de66b2be25e62ad3f6031c50db0097cc1880c00ec263962f45b4cf3fcb6f4ccd0d13ab48ce9b84976
7
- data.tar.gz: 231963a7fc17cc7d25ec5aded79120f11733e97d81edf58f4f2fc31edbb11865b435bd286b9817db744d98bad8751433eb68e809d567f9590d5ee70c5687b97d
6
+ metadata.gz: b712d5a8dc5a9c6c90580467f81939b843e876bc4bbf7f6b53bccbeb12a411e8104acffdfd3419ad70d760c4f375862c09de1b6964c5e4ecf8a92cdc4efdfdb2
7
+ data.tar.gz: 2b9cb6bb007b0dbff88839e3e811628241290de7383e1f85cfc68ba7a7936ea85d0a479d54035854d18e3cf79685aba1bf8f7f0d7b519ab4089cd75048f0262a
data/Gemfile.lock CHANGED
@@ -1,13 +1,15 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- scale_rb (0.1.6)
4
+ scale_rb (0.1.8)
5
+ base58
5
6
  blake2b_rs (~> 0.1.4)
6
7
  xxhash
7
8
 
8
9
  GEM
9
10
  remote: https://rubygems.org/
10
11
  specs:
12
+ base58 (0.2.3)
11
13
  blake2b_rs (0.1.4)
12
14
  ffi (~> 1.0)
13
15
  thermite (~> 0)
data/README.md CHANGED
@@ -2,9 +2,6 @@
2
2
 
3
3
  *WARNING: UNDER DEVELOPMENT*
4
4
 
5
- * Only support metadata v14.
6
- * Http & WebSocket client helper. No Client in this repo.
7
-
8
5
  ## Installation
9
6
 
10
7
  Add this line to your application's Gemfile:
data/exe/metadata CHANGED
@@ -6,7 +6,7 @@ require 'json'
6
6
  require 'optparse'
7
7
 
8
8
  def print_metadata(url, at = nil)
9
- puts JSON.pretty_generate(HttpClient.get_metadata(url, at))
9
+ puts JSON.pretty_generate(ScaleRb::HttpClient.get_metadata(url, at))
10
10
  end
11
11
 
12
12
  # ./bin/metadata http://g2.dev.darwinia.network:2234 -b 0x23ebddd6519aaf1b7fc916c3709af13d7a4010943fb53038406581171000a58e
@@ -31,10 +31,10 @@ else
31
31
  block_hash = @options[:block]
32
32
  else
33
33
  block_number = @options[:block].to_i
34
- block_hash = HttpClient.chain_getBlockHash url, block_number
34
+ block_hash = ScaleRb::HttpClient.chain_getBlockHash url, block_number
35
35
  end
36
36
  else
37
- block_hash = HttpClient.chain_getBlockHash url
37
+ block_hash = ScaleRb::HttpClient.chain_getBlockHash url
38
38
  end
39
39
 
40
40
  print_metadata url, block_hash
data/lib/address.rb ADDED
@@ -0,0 +1,97 @@
1
+ require 'base58'
2
+
3
+ # Warning: Just for test
4
+ class Address
5
+ SS58_PREFIX = 'SS58PRE'
6
+
7
+ TYPES = [
8
+ # Polkadot Live (SS58, AccountId)
9
+ 0, 1,
10
+ # Polkadot Canary (SS58, AccountId)
11
+ 2, 3,
12
+ # Kulupu (SS58, Reserved)
13
+ 16, 17,
14
+ # Darwinia Live
15
+ 18,
16
+ # Dothereum (SS58, AccountId)
17
+ 20, 21,
18
+ # Generic Substrate wildcard (SS58, AccountId)
19
+ 42, 43,
20
+
21
+ # Schnorr/Ristretto 25519 ("S/R 25519") key
22
+ 48,
23
+ # Edwards Ed25519 key
24
+ 49,
25
+ # ECDSA SECP256k1 key
26
+ 50,
27
+
28
+ # Reserved for future address format extensions.
29
+ *64..255
30
+ ]
31
+
32
+ class << self
33
+
34
+ def array_to_hex_string(arr)
35
+ body = arr.map { |i| i.to_s(16).rjust(2, '0') }.join
36
+ "0x#{body}"
37
+ end
38
+
39
+ def decode(address, addr_type = 42, ignore_checksum = true)
40
+ decoded = Base58.base58_to_binary(address, :bitcoin)
41
+ is_pubkey = decoded.size == 35
42
+
43
+ size = decoded.size - ( is_pubkey ? 2 : 1 )
44
+
45
+ prefix = decoded[0, 1].unpack("C*").first
46
+
47
+ raise "Invalid address type" unless TYPES.include?(addr_type)
48
+
49
+ hash_bytes = make_hash(decoded[0, size])
50
+ if is_pubkey
51
+ is_valid_checksum = decoded[-2].unpack("C*").first == hash_bytes[0] && decoded[-1].unpack("C*").first == hash_bytes[1]
52
+ else
53
+ is_valid_checksum = decoded[-1].unpack("C*").first == hash_bytes[0]
54
+ end
55
+
56
+ # raise "Invalid decoded address checksum" unless is_valid_checksum && ignore_checksum
57
+
58
+ decoded[1...size].unpack("H*").first
59
+ end
60
+
61
+
62
+ def encode(pubkey, addr_type = 42)
63
+ pubkey = pubkey[2..-1] if pubkey =~ /^0x/i
64
+ key = [pubkey].pack("H*")
65
+
66
+ u8_array = key.bytes
67
+
68
+ u8_array.unshift(addr_type)
69
+
70
+ bytes = make_hash(u8_array.pack("C*"))
71
+
72
+ checksum = bytes[0, key.size == 32 ? 2 : 1]
73
+
74
+ u8_array.push(*checksum)
75
+
76
+ u8_array = u8_array.map { |i| if i.is_a?(String) then i.to_i(16) else i end }
77
+ # u8_array = [42, 202, 122, 179, 154, 86, 153, 242, 157, 207, 38, 115, 170, 163, 73, 75, 72, 81, 26, 186, 224, 220, 60, 101, 15, 243, 152, 246, 95, 229, 225, 18, 56, 0x7e]
78
+ input = u8_array.pack("C*")
79
+
80
+ Base58.binary_to_base58(input, :bitcoin)
81
+ end
82
+
83
+ def make_hash(body)
84
+ Blake2b.hex("#{SS58_PREFIX}#{body}".bytes, 64)
85
+ end
86
+
87
+ def is_ss58_address?(address)
88
+ begin
89
+ decode(address)
90
+ rescue
91
+ return false
92
+ end
93
+ return true
94
+ end
95
+
96
+ end
97
+ end
@@ -14,12 +14,79 @@ module Metadata
14
14
  MetadataV14.build_registry(metadata_v14)
15
15
  end
16
16
 
17
+ def get_module(pallet_name, metadata)
18
+ version = metadata._get(:metadata).keys.first
19
+ raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless %w[v9 v10 v11 v12 v13 v14].include?(version.to_s)
20
+
21
+ Metadata.const_get("Metadata#{version.upcase}").get_module(pallet_name, metadata)
22
+ end
23
+
24
+ def get_module_by_index(pallet_index, metadata)
25
+ version = metadata._get(:metadata).keys.first
26
+ raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless %w[v9 v10 v11 v12 v13 v14].include?(version.to_s)
27
+
28
+ Metadata.const_get("Metadata#{version.upcase}").get_module_by_index(pallet_index, metadata)
29
+ end
30
+
17
31
  def get_storage_item(pallet_name, item_name, metadata)
18
32
  version = metadata._get(:metadata).keys.first
19
33
  raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless %w[v9 v10 v11 v12 v13 v14].include?(version.to_s)
20
34
 
21
35
  Metadata.const_get("Metadata#{version.upcase}").get_storage_item(pallet_name, item_name, metadata)
22
36
  end
37
+
38
+ def get_calls_type(pallet_name, metadata)
39
+ version = metadata._get(:metadata).keys.first
40
+ raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless %w[v9 v10 v11 v12 v13 v14].include?(version.to_s)
41
+
42
+ Metadata.const_get("Metadata#{version.upcase}").get_calls_type(pallet_name, metadata)
43
+ end
44
+
45
+ def get_calls_type_id(pallet_name, metadata)
46
+ version = metadata._get(:metadata).keys.first
47
+ raise ScaleRb::NotImplemented, metadata._get(:metadata).keys.first unless %w[v9 v10 v11 v12 v13 v14].include?(version.to_s)
48
+
49
+ Metadata.const_get("Metadata#{version.upcase}").get_calls_type_id(pallet_name, metadata)
50
+ end
51
+
52
+ # call examples:
53
+ # {:pallet_name=>"Deposit", :call_name=>"Claim", :call=>["claim", []]}
54
+ # {:pallet_name=>"Balances", :call_name=>"Transfer", :call=>[{:transfer=>{:dest=>[10, 18, 135, 151, 117, 120, 248, 136, 189, 193, 199, 98, 119, 129, 175, 28, 192, 0, 230, 171], :value=>11000000000000000000}}, []]}
55
+ def encode_call(call, metadata)
56
+ calls_type_id = get_calls_type_id(call[:pallet_name], metadata)
57
+ pallet_index = get_module(call[:pallet_name], metadata)._get(:index)
58
+ [pallet_index] + PortableCodec.encode(calls_type_id, call[:call].first, build_registry(metadata))
59
+ end
60
+
61
+ # callbytes's structure is: pallet_index + call_index + argsbytes
62
+ #
63
+ # callbytes examples:
64
+ # "0x0901".to_bytes
65
+ # "0x05000a1287977578f888bdc1c7627781af1cc000e6ab1300004c31b8d9a798".to_bytes
66
+ def decode_call(callbytes, metadata)
67
+ pallet_index = callbytes[0]
68
+ pallet = get_module_by_index(pallet_index, metadata)
69
+
70
+ pallet_name = pallet._get(:name)
71
+
72
+ # Remove the pallet_index
73
+ # The callbytes we used below should not contain the pallet index.
74
+ # This is because the pallet index is not part of the call type.
75
+ # Its structure is: call_index + call_args
76
+ callbytes_without_pallet_index = callbytes[1..]
77
+ calls_type_id = pallet._get(:calls)._get(:type)
78
+ decoded = PortableCodec.decode(
79
+ calls_type_id,
80
+ callbytes_without_pallet_index,
81
+ build_registry(metadata)
82
+ )
83
+
84
+ {
85
+ pallet_name: pallet_name,
86
+ call_name: decoded.first.is_a?(String) ? decoded.first.to_camel : decoded.first.keys.first.to_s.to_camel,
87
+ call: decoded
88
+ }
89
+ end
23
90
  end
24
91
 
25
92
  TYPES = {
@@ -14,6 +14,12 @@ module Metadata
14
14
  end
15
15
  end
16
16
 
17
+ def get_module_by_index(pallet_index, metadata)
18
+ metadata._get(:metadata)._get(:v14)._get(:pallets).find do |p|
19
+ p._get(:index) == pallet_index
20
+ end
21
+ end
22
+
17
23
  def get_storage_item(pallet_name, item_name, metadata)
18
24
  pallet = get_module(pallet_name, metadata)
19
25
  raise "Pallet `#{pallet_name}` not found" if pallet.nil?
@@ -21,6 +27,19 @@ module Metadata
21
27
  item._get(:name) == item_name
22
28
  end
23
29
  end
30
+
31
+ def get_calls_type(pallet_name, metadata)
32
+ type_id = get_calls_type_id(pallet_name, metadata)
33
+ metadata._get(:metadata)._get(:v14)._get(:lookup)._get(:types).find do |type|
34
+ type._get(:id) == type_id
35
+ end
36
+ end
37
+
38
+ def get_calls_type_id(pallet_name, metadata)
39
+ pallet = get_module(pallet_name, metadata)
40
+ raise "Pallet `#{pallet_name}` not found" if pallet.nil?
41
+ pallet._get(:calls)._get(:type)
42
+ end
24
43
  end
25
44
 
26
45
  TYPES = {
@@ -10,6 +10,15 @@ module PortableCodec
10
10
  class VariantIndexOutOfRange < Error; end
11
11
  class VariantInvalidValue < Error; end
12
12
 
13
+ class << self
14
+ def u256(value)
15
+ bytes = ScaleRb.encode('u256', value)
16
+ bytes.each_slice(8).map do |slice|
17
+ ScaleRb.decode('u64', slice).first
18
+ end
19
+ end
20
+ end
21
+
13
22
  class << self
14
23
  # registry:
15
24
  # {
@@ -171,7 +180,7 @@ module PortableCodec
171
180
  def encode_sequence(sequence_type, value, registry)
172
181
  inner_type_id = sequence_type._get(:type)
173
182
  length_bytes = encode_compact(value.length)
174
- length_bytes + _encode_types([inner_type_id] * array.length, value, registry)
183
+ length_bytes + _encode_types([inner_type_id] * value.length, value, registry)
175
184
  end
176
185
 
177
186
  # tuple_type: [type_id1, type_id2, ...]
@@ -230,7 +239,10 @@ module PortableCodec
230
239
 
231
240
  item = variants.find { |var| var._get(:name) == name }
232
241
  raise VariantItemNotFound, "type: #{variant_type}, name: #{name}" if item.nil?
233
- raise VariantInvalidValue, "type: #{variant_type}, v: #{v}" if item._get(:fields).length != v.length
242
+
243
+ # if the variant item has more than one field, the value must be a hash with the same length.
244
+ # if the variant item has only one field, that means the field is a type id point to a composite. TODO: check the type's fields length
245
+ raise VariantFieldsLengthNotMatch, "type: #{variant_type}, \nvalue: #{v}" if item._get(:fields).length > 1 && item._get(:fields).length != v.length
234
246
 
235
247
  ScaleRb.encode_uint('u8', item._get(:index)) + encode_composite(item, v, registry)
236
248
  end
@@ -1,3 +1,3 @@
1
1
  module ScaleRb
2
- VERSION = '0.1.6'
2
+ VERSION = '0.1.8'
3
3
  end
data/lib/scale_rb.rb CHANGED
@@ -28,6 +28,8 @@ require 'client/abstract_ws_client'
28
28
  # get registry from config
29
29
  require 'registry'
30
30
 
31
+ require 'address'
32
+
31
33
  module ScaleRb
32
34
  class << self
33
35
  attr_writer :logger
data/scale_rb.gemspec CHANGED
@@ -28,4 +28,5 @@ Gem::Specification.new do |spec|
28
28
  # for hashers
29
29
  spec.add_dependency 'blake2b_rs', '~> 0.1.4'
30
30
  spec.add_dependency 'xxhash'
31
+ spec.add_dependency "base58"
31
32
  end
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.1.6
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aki Wu
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-04-01 00:00:00.000000000 Z
11
+ date: 2023-04-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: blake2b_rs
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: base58
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  description: Ruby implementation of the parity SCALE data format
42
56
  email:
43
57
  - wuminzhe@gmail.com
@@ -59,6 +73,7 @@ files:
59
73
  - bin/console
60
74
  - bin/setup
61
75
  - exe/metadata
76
+ - lib/address.rb
62
77
  - lib/client/abstract_ws_client.rb
63
78
  - lib/client/http_client.rb
64
79
  - lib/client/rpc_request_builder.rb