scale_rb 0.1.11 → 0.1.14

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: b9af24645257f5dc7c2028047ba01ef9a3d1fe4282581717cb62334a6f96f153
4
- data.tar.gz: 8d79a47702d593158680d4fe2f5a887962fd87bc19e51e2d57b4ea6ca2ec0a9b
3
+ metadata.gz: 82a0911194368a4fcefec7a414694346f087c0ded749d3865f6732f27c8afef0
4
+ data.tar.gz: 14b34a748f835c527726ebd42440cced5ed8b5c0d954cb15c41e288ce3e5aff6
5
5
  SHA512:
6
- metadata.gz: b573f530576618d07382f3b995cc5413a564e4bf95149882cc83b6cb0d885e2adee2f903b5db0c8a14fd5b6964683b6851f6105e0c53c6bcb98e625c2991a639
7
- data.tar.gz: efa796fe20f73749749bfd06de0f08c1d836268ddb99963775003f282eff60e15accd4d62556eaa1d01b0821447bdcb4bd8956e5445401ca562da2df1fc547f8
6
+ metadata.gz: 805efca604cc93794b5c1d4ee3dd1785d74d6a049b55f0ecc0503c85869c2759a37380b6735b8ecf874b6b33b31492f7b203870b7b414758740545821f98db19
7
+ data.tar.gz: d5f577ec96adf7a51ef7044b0d5f8bc874e3a12daf66e3cc743677a6a095ddda909267b941dd15a06646dc941caeabe810fd960140c1c94261d173796ee40b9d
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- scale_rb (0.1.11)
4
+ scale_rb (0.1.14)
5
5
  base58
6
6
  blake2b_rs (~> 0.1.4)
7
7
  xxhash
@@ -14,7 +14,7 @@ GEM
14
14
  ffi (~> 1.0)
15
15
  thermite (~> 0)
16
16
  diff-lcs (1.5.0)
17
- ffi (1.15.5)
17
+ ffi (1.16.3)
18
18
  minitar (0.9)
19
19
  rake (12.3.3)
20
20
  rspec (3.11.0)
data/lib/address.rb CHANGED
@@ -14,7 +14,7 @@ class Address
14
14
  # Darwinia Live
15
15
  18,
16
16
  # Dothereum (SS58, AccountId)
17
- 20, 21,
17
+ 20, 21,
18
18
  # Generic Substrate wildcard (SS58, AccountId)
19
19
  42, 43,
20
20
 
@@ -30,54 +30,62 @@ class Address
30
30
  ]
31
31
 
32
32
  class << self
33
-
34
33
  def array_to_hex_string(arr)
35
34
  body = arr.map { |i| i.to_s(16).rjust(2, '0') }.join
36
35
  "0x#{body}"
37
36
  end
38
37
 
39
- def decode(address, addr_type = 42, ignore_checksum = true)
38
+ def decode(address, addr_type = 42, _ignore_checksum = true)
40
39
  decoded = Base58.base58_to_binary(address, :bitcoin)
41
40
  is_pubkey = decoded.size == 35
42
41
 
43
- size = decoded.size - ( is_pubkey ? 2 : 1 )
42
+ size = decoded.size - (is_pubkey ? 2 : 1)
43
+
44
+ prefix = decoded[0, 1].unpack1('C*')
44
45
 
45
- prefix = decoded[0, 1].unpack("C*").first
46
+ raise 'Invalid address type' unless TYPES.include?(addr_type)
46
47
 
47
- raise "Invalid address type" unless TYPES.include?(addr_type)
48
-
49
48
  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
49
+ is_valid_checksum =
50
+ if is_pubkey
51
+ decoded[-2].unpack1('C*') == hash_bytes[0] && decoded[-1].unpack1('C*') == hash_bytes[1]
52
+ else
53
+ decoded[-1].unpack1('C*') == hash_bytes[0]
54
+ end
55
55
 
56
56
  # raise "Invalid decoded address checksum" unless is_valid_checksum && ignore_checksum
57
57
 
58
- decoded[1...size].unpack("H*").first
58
+ decoded[1...size].unpack1('H*')
59
59
  end
60
60
 
61
-
62
61
  def encode(pubkey, addr_type = 42)
63
62
  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)
63
+ key = [pubkey].pack('H*')
64
+
65
+ pubkey_bytes = key.bytes
66
+
67
+ checksum_length = case pubkey_bytes.length
68
+ when 32, 33
69
+ 2
70
+ when 1, 2, 4, 8
71
+ 1
72
+ else
73
+ raise 'Invalid pubkey length'
74
+ end
75
+
76
+ ss58_format_bytes = if addr_type < 64
77
+ [addr_type].pack('C*')
78
+ else
79
+ [
80
+ ((ss58_format & 0b0000_0000_1111_1100) >> 2) | 0b0100_0000,
81
+ (ss58_format >> 8) | ((ss58_format & 0b0000_0000_0000_0011) << 6)
82
+ ].pack('C*')
83
+ end
84
+
85
+ input_bytes = ss58_format_bytes.bytes + pubkey_bytes
86
+ checksum = Blake2b.hex(SS58_PREFIX.bytes + input_bytes, 64).to_bytes
87
+
88
+ Base58.binary_to_base58((input_bytes + checksum[0...checksum_length]).pack('C*'), :bitcoin)
81
89
  end
82
90
 
83
91
  def make_hash(body)
@@ -87,11 +95,11 @@ class Address
87
95
  def is_ss58_address?(address)
88
96
  begin
89
97
  decode(address)
90
- rescue
98
+ rescue StandardError
91
99
  return false
92
100
  end
93
- return true
101
+ true
94
102
  end
95
-
96
103
  end
97
- end
104
+ end
105
+
@@ -3,6 +3,7 @@
3
3
  require 'uri'
4
4
  require 'net/http'
5
5
  require 'json'
6
+ require_relative './http_client_metadata'
6
7
 
7
8
  # TODO: method_name = cmd.gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase
8
9
  module ScaleRb
@@ -129,17 +130,30 @@ module ScaleRb
129
130
  #
130
131
  # TODO: part of the key is provided, but not all
131
132
  def get_storage(url, pallet_name, item_name, key, value, registry, at = nil)
132
- # map, but no key's value provided. get all storages under the partial storage key
133
- if key && (key[:value].nil? || key[:value].empty?)
134
- partial_storage_key = StorageHelper.encode_storage_key(pallet_name, item_name).to_hex
135
- get_storages_by_partial_key(
136
- url,
137
- partial_storage_key,
138
- value[:type],
139
- value[:modifier] == 'Default' ? value[:fallback] : nil,
140
- registry,
141
- at
142
- )
133
+ if key
134
+ if key[:value].nil? || key[:value].empty?
135
+ # map, but no key's value provided. get all storages under the partial storage key
136
+ partial_storage_key = StorageHelper.encode_storage_key(pallet_name, item_name).to_hex
137
+ get_storages_by_partial_key(
138
+ url,
139
+ partial_storage_key,
140
+ value[:type],
141
+ value[:modifier] == 'Default' ? value[:fallback] : nil,
142
+ registry,
143
+ at
144
+ )
145
+ elsif key[:value].length != key[:hashers].length
146
+ # map with multi part, but only provide part value
147
+ partial_storage_key = StorageHelper.encode_storage_key(pallet_name, item_name, key, registry).to_hex
148
+ get_storages_by_partial_key(
149
+ url,
150
+ partial_storage_key,
151
+ value[:type],
152
+ value[:modifier] == 'Default' ? value[:fallback] : nil,
153
+ registry,
154
+ at
155
+ )
156
+ end
143
157
  else
144
158
  storage_key = StorageHelper.encode_storage_key(pallet_name, item_name, key, registry).to_hex
145
159
  data = state_getStorage(url, storage_key, at)
@@ -178,6 +192,44 @@ module ScaleRb
178
192
  end
179
193
  get_storage(url, pallet_name, item_name, key, value, registry, at)
180
194
  end
195
+
196
+ # get_storage3 is a more ruby style function
197
+ #
198
+ # pallet_name and storage_name is pascal style like 'darwinia_staking'
199
+ def get_storage3(url, metadata, pallet_name, storage_name, key_part1: nil, key_part2: nil, at: nil)
200
+ pallet_name = to_pascal pallet_name
201
+ storage_name = to_pascal storage_name
202
+ ScaleRb.logger.debug "#{pallet_name}.#{storage_name}(#{[key_part1, key_part2].compact.join(', ')})"
203
+
204
+ key = [key_part1, key_part2].compact.map { |part_of_key| c(part_of_key) }
205
+ ScaleRb.logger.debug "converted key: #{key}"
206
+
207
+ get_storage2(
208
+ url,
209
+ pallet_name,
210
+ storage_name,
211
+ key,
212
+ metadata,
213
+ at
214
+ )
215
+ end
216
+
217
+ private
218
+
219
+ def to_pascal(str)
220
+ str.split('_').collect(&:capitalize).join
221
+ end
222
+
223
+ # convert key to byte array
224
+ def c(key)
225
+ if key.start_with?('0x')
226
+ key.to_bytes
227
+ elsif key.to_i.to_s == key # check if key is a number
228
+ key.to_i
229
+ else
230
+ key
231
+ end
232
+ end
181
233
  end
182
234
  end
183
235
  end
@@ -0,0 +1,76 @@
1
+ require 'json'
2
+ require 'fileutils'
3
+
4
+ module ScaleRb
5
+ module HttpClient
6
+ class << self
7
+ # cached version of get_metadata
8
+ # get metadata from cache first
9
+ def get_metadata_cached(url, at: nil, dir: File.join(Dir.pwd, 'metadata'))
10
+ # if at
11
+ # require_block_hash_correct(url, at)
12
+ # else
13
+ # at = ScaleRb::HttpClient.chain_getFinalizedHead(url)
14
+ # end
15
+ at = ScaleRb::HttpClient.chain_getFinalizedHead(url) if at.nil?
16
+ spec_name, spec_version = get_spec(url, at)
17
+
18
+ # get metadata from cache first
19
+ metadata = metadata_cached(
20
+ spec_name: spec_name,
21
+ spec_version: spec_version,
22
+ dir: dir
23
+ )
24
+ return metadata if metadata
25
+
26
+ # get metadata from rpc
27
+ metadata = ScaleRb::HttpClient.get_metadata(url, at)
28
+
29
+ # cache it
30
+ puts "caching metadata `#{spec_name}_#{spec_version}.json`"
31
+ save_metadata_to_file(
32
+ spec_name: spec_name,
33
+ spec_version: spec_version,
34
+ metadata: metadata,
35
+ dir: dir
36
+ )
37
+
38
+ metadata
39
+ end
40
+
41
+ private
42
+
43
+ def get_spec(url, at)
44
+ runtime_version = ScaleRb::HttpClient.state_getRuntimeVersion(url, at)
45
+ spec_name = runtime_version['specName']
46
+ spec_version = runtime_version['specVersion']
47
+ [spec_name, spec_version]
48
+ end
49
+
50
+ def metadata_cached(spec_name:, spec_version:, dir:)
51
+ raise 'spec_version is required' unless spec_version
52
+ raise 'spec_name is required' unless spec_name
53
+
54
+ file_path = File.join(dir, "#{spec_name}_#{spec_version}.json")
55
+ return unless File.exist?(file_path)
56
+
57
+ puts "found metadata `#{spec_name}_#{spec_version}.json` in cache"
58
+ JSON.parse(File.read(file_path))
59
+ end
60
+
61
+ def save_metadata_to_file(spec_name:, spec_version:, metadata:, dir:)
62
+ FileUtils.mkdir_p(dir)
63
+
64
+ File.open(File.join(dir, "#{spec_name}_#{spec_version}.json"), 'w') do |f|
65
+ f.write(JSON.pretty_generate(metadata))
66
+ end
67
+ end
68
+
69
+ def require_block_hash_correct(url, block_hash)
70
+ return unless ScaleRb::HttpClient.chain_getHeader(url, block_hash).nil?
71
+
72
+ raise 'Unable to retrieve header and parent from supplied hash'
73
+ end
74
+ end
75
+ end
76
+ end
@@ -1,3 +1,3 @@
1
1
  module ScaleRb
2
- VERSION = '0.1.11'
2
+ VERSION = '0.1.14'
3
3
  end
@@ -12,26 +12,26 @@ module StorageHelper
12
12
 
13
13
  if key && registry
14
14
 
15
- key_types, key_values =
15
+ key_types, key_values, key_hashers =
16
16
  if key[:hashers].length == 1
17
17
  [
18
18
  [key[:type]],
19
- key[:value]
19
+ key[:value],
20
+ key[:hashers]
20
21
  ]
21
22
  else
22
23
  [
23
- registry[key[:type]]._get(:def)._get(:tuple),
24
- key[:value]
24
+ registry[key[:type]]._get(:def)._get(:tuple).first(key[:value].length),
25
+ key[:value],
26
+ key[:hashers].first(key[:value].length)
25
27
  ]
26
28
  end
27
29
 
28
- # debug
29
- # p "encode_storage_key -----------------------"
30
- # p key_types
31
- # p key_values
32
- # p "encode_storage_key -----------------------"
33
- raise "Key's value doesn't match key's type, key's value: #{key_values.inspect}, but key's type: #{key_types.inspect}. Please check your key's value." if key_types.class != key_values.class || key_types.length != key_values.length
34
- storage_key + PortableCodec._encode_types_with_hashers(key_types, key_values, registry, key[:hashers])
30
+ if key_types.class != key_values.class || key_types.length != key_values.length
31
+ raise "Key's value doesn't match key's type, key's value: #{key_values.inspect}, but key's type: #{key_types.inspect}. Please check your key's value."
32
+ end
33
+
34
+ storage_key + PortableCodec._encode_types_with_hashers(key_types, key_values, registry, key_hashers)
35
35
  else
36
36
  storage_key
37
37
  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.11
4
+ version: 0.1.14
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-08-21 00:00:00.000000000 Z
11
+ date: 2023-10-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: blake2b_rs
@@ -76,6 +76,7 @@ files:
76
76
  - lib/address.rb
77
77
  - lib/client/abstract_ws_client.rb
78
78
  - lib/client/http_client.rb
79
+ - lib/client/http_client_metadata.rb
79
80
  - lib/client/rpc_request_builder.rb
80
81
  - lib/codec.rb
81
82
  - lib/hasher.rb