scale_rb 0.1.6 → 0.1.8

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.
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