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 +4 -4
- data/Gemfile.lock +3 -1
- data/README.md +0 -3
- data/exe/metadata +3 -3
- data/lib/address.rb +97 -0
- data/lib/metadata/metadata.rb +67 -0
- data/lib/metadata/metadata_v14.rb +19 -0
- data/lib/portable_codec.rb +14 -2
- data/lib/scale_rb/version.rb +1 -1
- data/lib/scale_rb.rb +2 -0
- data/scale_rb.gemspec +1 -0
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 241f9857282220d19480bed1cf2a1bcaeacd0948963a65455ee1c57b708ed4d6
|
4
|
+
data.tar.gz: 8ab8fad9f853c7f3d1d57bf9f283b2fbe16a6d17bb2f1221b84ff3a78feff34c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b712d5a8dc5a9c6c90580467f81939b843e876bc4bbf7f6b53bccbeb12a411e8104acffdfd3419ad70d760c4f375862c09de1b6964c5e4ecf8a92cdc4efdfdb2
|
7
|
+
data.tar.gz: 2b9cb6bb007b0dbff88839e3e811628241290de7383e1f85cfc68ba7a7936ea85d0a479d54035854d18e3cf79685aba1bf8f7f0d7b519ab4089cd75048f0262a
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
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
|
data/lib/metadata/metadata.rb
CHANGED
@@ -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 = {
|
data/lib/portable_codec.rb
CHANGED
@@ -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] *
|
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
|
-
|
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
|
data/lib/scale_rb/version.rb
CHANGED
data/lib/scale_rb.rb
CHANGED
data/scale_rb.gemspec
CHANGED
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.
|
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-
|
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
|