tezos_client 1.1.2 → 1.2.3

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: df136ec49d2d790db5cee86eb542be4c0a0ffbc08cd32da8b45ed24f3b30faac
4
- data.tar.gz: 245b8ca7495bd975cd20e41fcec00968ff436d80c2cbdfebdd47f95618323c67
3
+ metadata.gz: 1edfdfe5f7332ebbe4ecafd4baa3f03998e02204e33f854d9f394ba84cbf98c3
4
+ data.tar.gz: 7544eba6b1a6d602b24025a5c2831c1e803f53f92ae5f0925daa05a0b2ef3167
5
5
  SHA512:
6
- metadata.gz: 1ef0f079eb71e4fa9e2716130d7cbd06f33abd93a8dfdf14c9b388730fe0289b21d8d4b4424b2f246c8dfd3079af5b16e4438b3a22bab8ce0c564f8f5794e11f
7
- data.tar.gz: 90b9ef025edacccf89275c4f5ec6be72511f182705f6b224fb756f05259fdd940e480fc4b4368d674122858f0da2195c200a77585750a77c0ef3e0b7c2f02114
6
+ metadata.gz: 4a4e3ddacd06478d21821ce1e38ac5d731f2602d6cbca55e2440828de46c5933aaa8b77df00d3d989295ee325318ff53284725dc91d165ed32918cd2b3de9d8a
7
+ data.tar.gz: 980264f44b9761e4f7e716675a5775d1b2f3cbfd6de5d09024154c53000a1a95cc3c168efe259c1fd7b78d9a877d23a6c0fa4feea8a8bda942b753122cf73bc7
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- tezos_client (1.1.2)
4
+ tezos_client (1.2.3)
5
5
  active_interaction (~> 3.7)
6
6
  activesupport (~> 6.0.0)
7
7
  base58 (~> 0.2.3)
@@ -14,68 +14,68 @@ PATH
14
14
  GEM
15
15
  remote: https://rubygems.org/
16
16
  specs:
17
- actionpack (6.0.0)
18
- actionview (= 6.0.0)
19
- activesupport (= 6.0.0)
20
- rack (~> 2.0)
17
+ actionpack (6.0.3.2)
18
+ actionview (= 6.0.3.2)
19
+ activesupport (= 6.0.3.2)
20
+ rack (~> 2.0, >= 2.0.8)
21
21
  rack-test (>= 0.6.3)
22
22
  rails-dom-testing (~> 2.0)
23
23
  rails-html-sanitizer (~> 1.0, >= 1.2.0)
24
- actionview (6.0.0)
25
- activesupport (= 6.0.0)
24
+ actionview (6.0.3.2)
25
+ activesupport (= 6.0.3.2)
26
26
  builder (~> 3.1)
27
27
  erubi (~> 1.4)
28
28
  rails-dom-testing (~> 2.0)
29
29
  rails-html-sanitizer (~> 1.1, >= 1.2.0)
30
- active_interaction (3.7.1)
30
+ active_interaction (3.8.2)
31
31
  activemodel (>= 4, < 7)
32
- activemodel (6.0.0)
33
- activesupport (= 6.0.0)
34
- activesupport (6.0.0)
32
+ activemodel (6.0.3.2)
33
+ activesupport (= 6.0.3.2)
34
+ activesupport (6.0.3.2)
35
35
  concurrent-ruby (~> 1.0, >= 1.0.2)
36
36
  i18n (>= 0.7, < 2)
37
37
  minitest (~> 5.1)
38
38
  tzinfo (~> 1.1)
39
- zeitwerk (~> 2.1, >= 2.1.8)
39
+ zeitwerk (~> 2.2, >= 2.2.2)
40
40
  addressable (2.7.0)
41
41
  public_suffix (>= 2.0.2, < 5.0)
42
42
  ast (2.4.0)
43
43
  base58 (0.2.3)
44
44
  bip_mnemonic (0.0.4)
45
- builder (3.2.3)
45
+ builder (3.2.4)
46
46
  coderay (1.1.2)
47
- concurrent-ruby (1.1.5)
47
+ concurrent-ruby (1.1.6)
48
48
  crack (0.4.3)
49
49
  safe_yaml (~> 1.0.0)
50
- crass (1.0.5)
50
+ crass (1.0.6)
51
51
  diff-lcs (1.3)
52
52
  domain_name (0.5.20190701)
53
53
  unf (>= 0.0.5, < 1.0.0)
54
54
  erubi (1.9.0)
55
- ffi (1.12.2)
55
+ ffi (1.13.1)
56
56
  hashdiff (1.0.0)
57
57
  http-cookie (1.0.3)
58
58
  domain_name (~> 0.5)
59
59
  httparty (0.17.3)
60
60
  mime-types (~> 3.0)
61
61
  multi_xml (>= 0.5.2)
62
- i18n (1.7.0)
62
+ i18n (1.8.3)
63
63
  concurrent-ruby (~> 1.0)
64
64
  jaro_winkler (1.5.3)
65
- loofah (2.3.1)
65
+ loofah (2.6.0)
66
66
  crass (~> 1.0.2)
67
67
  nokogiri (>= 1.5.9)
68
68
  method_source (0.9.2)
69
69
  mime-types (3.3.1)
70
70
  mime-types-data (~> 3.2015)
71
- mime-types-data (3.2019.1009)
71
+ mime-types-data (3.2020.0512)
72
72
  mini_portile2 (2.4.0)
73
- minitest (5.13.0)
73
+ minitest (5.14.1)
74
74
  money-tree (0.10.0)
75
75
  ffi
76
76
  multi_xml (0.6.0)
77
77
  netrc (0.11.0)
78
- nokogiri (1.10.8)
78
+ nokogiri (1.10.9)
79
79
  mini_portile2 (~> 2.4.0)
80
80
  parallel (1.18.0)
81
81
  parser (2.6.5.0)
@@ -84,7 +84,7 @@ GEM
84
84
  coderay (~> 1.1.0)
85
85
  method_source (~> 0.9.0)
86
86
  public_suffix (4.0.1)
87
- rack (2.0.8)
87
+ rack (2.2.3)
88
88
  rack-test (1.1.0)
89
89
  rack (>= 1.0, < 3)
90
90
  rails-dom-testing (2.0.3)
@@ -92,14 +92,14 @@ GEM
92
92
  nokogiri (>= 1.6)
93
93
  rails-html-sanitizer (1.3.0)
94
94
  loofah (~> 2.3)
95
- railties (6.0.0)
96
- actionpack (= 6.0.0)
97
- activesupport (= 6.0.0)
95
+ railties (6.0.3.2)
96
+ actionpack (= 6.0.3.2)
97
+ activesupport (= 6.0.3.2)
98
98
  method_source
99
99
  rake (>= 0.8.7)
100
100
  thor (>= 0.20.3, < 2.0)
101
101
  rainbow (3.0.0)
102
- rake (10.5.0)
102
+ rake (13.0.1)
103
103
  rbnacl (5.0.0)
104
104
  ffi
105
105
  rest-client (2.0.2)
@@ -138,20 +138,20 @@ GEM
138
138
  rubocop-rails (~> 2.0)
139
139
  ruby-progressbar (1.10.1)
140
140
  safe_yaml (1.0.5)
141
- thor (0.20.3)
141
+ thor (1.0.1)
142
142
  thread_safe (0.3.6)
143
- tzinfo (1.2.5)
143
+ tzinfo (1.2.7)
144
144
  thread_safe (~> 0.1)
145
145
  unf (0.1.4)
146
146
  unf_ext
147
- unf_ext (0.0.7.6)
147
+ unf_ext (0.0.7.7)
148
148
  unicode-display_width (1.6.0)
149
149
  vcr (4.0.0)
150
150
  webmock (3.7.6)
151
151
  addressable (>= 2.3.6)
152
152
  crack (>= 0.3.2)
153
153
  hashdiff (>= 0.4.0, < 2.0.0)
154
- zeitwerk (2.2.1)
154
+ zeitwerk (2.3.0)
155
155
 
156
156
  PLATFORMS
157
157
  ruby
@@ -159,7 +159,7 @@ PLATFORMS
159
159
  DEPENDENCIES
160
160
  bundler (~> 1.16)
161
161
  pry
162
- rake (~> 10.0)
162
+ rake (~> 13.0)
163
163
  rspec (~> 3.0)
164
164
  rubocop-rails_config
165
165
  tezos_client!
@@ -36,6 +36,8 @@ require "tezos_client/smartpy_interface"
36
36
 
37
37
  require "tezos_client/tools/convert_to_hash"
38
38
  require "tezos_client/tools/find_big_maps_in_storage"
39
+ require "tezos_client/tools/hash_to_micheline"
40
+ require "tezos_client/tools/annots_to_type"
39
41
 
40
42
  class TezosClient
41
43
  using CurrencyUtils
@@ -22,6 +22,9 @@ class TezosClient
22
22
  :pending_operations,
23
23
  :pack_data,
24
24
  :big_map_value,
25
- :list_big_map_by_contract
25
+ :contract_big_maps,
26
+ :block_operations,
27
+ :contract_storage_type,
28
+ :entrypoint
26
29
  end
27
30
  end
@@ -165,6 +165,22 @@ class TezosClient
165
165
  end
166
166
  end
167
167
 
168
+ # payload must be bytes
169
+ def check_signature(public_key:, signature:, payload:)
170
+ verify_key = RbNaCl::VerifyKey.new(decode_tz(public_key).to_bin)
171
+
172
+ bin_sig = decode_tz(signature).to_bin
173
+ payload_hash = RbNaCl::Hash::Blake2b.digest(ignore_0x(payload).to_bin, digest_size: 32)
174
+
175
+ verify_key.verify(bin_sig, payload_hash)
176
+ rescue RbNaCl::BadSignatureError
177
+ false
178
+ end
179
+
180
+ def check_signature!(public_key:, signature:, payload:)
181
+ check_signature(public_key: public_key, signature: signature, payload: payload) || raise(BadSignatureError)
182
+ end
183
+
168
184
  def operation_id(signed_operation_hex)
169
185
  hash = RbNaCl::Hash::Blake2b.digest(
170
186
  signed_operation_hex.to_bin,
@@ -220,5 +236,9 @@ class TezosClient
220
236
  RbNaCl::SigningKey.generate
221
237
  end
222
238
  end
239
+
240
+ def ignore_0x(payload)
241
+ payload.starts_with?("0x") ? payload[2..-1] : payload
242
+ end
223
243
  end
224
244
  end
@@ -23,6 +23,9 @@ class TezosClient
23
23
  class SmartPyError < SysCallError
24
24
  end
25
25
 
26
+ class BadSignatureError < StandardError
27
+ end
28
+
26
29
  class InvalidActivation < RpcRequestFailure
27
30
  attr_reader :pkh
28
31
 
@@ -184,7 +184,8 @@ class TezosClient
184
184
  operations: rpc_operation_args,
185
185
  signature: base_58_signature,
186
186
  protocol: protocol,
187
- branch: branch)
187
+ branch: branch
188
+ )
188
189
 
189
190
  ensure_applied!(rpc_responses)
190
191
 
@@ -201,37 +202,40 @@ class TezosClient
201
202
  end
202
203
 
203
204
  private
204
- def ensure_applied!(rpc_responses)
205
- metadatas = rpc_responses.map { |response| response[:metadata] }
206
- operation_results = metadatas.map { |metadata| metadata[:operation_result] }
207
205
 
208
- failed = operation_results.detect do |operation_result|
209
- operation_result != nil && operation_result[:status] != "applied"
210
- end
206
+ def ensure_applied!(rpc_responses)
207
+ metadatas = rpc_responses.map { |response| response[:metadata] }
208
+ operation_results = metadatas.map { |metadata| metadata[:operation_result] }
209
+ internal_operations = metadatas.map { |metadata| metadata[:internal_operation_results] }.flatten.compact
210
+ operation_results.concat(internal_operations.map { |internal_operation| internal_operation[:result] })
211
211
 
212
- return metadatas if failed.nil?
212
+ failed = operation_results.detect do |operation_result|
213
+ operation_result != nil && operation_result[:status] != "applied"
214
+ end
213
215
 
214
- failed_operation_result = operation_results.detect do |operation_result|
215
- operation_result[:status] == "failed"
216
- end
216
+ return metadatas if failed.nil?
217
217
 
218
- failed!("failed", failed_operation_result[:errors], operation_results)
218
+ failed_operation_result = operation_results.detect do |operation_result|
219
+ operation_result[:status] == "failed"
219
220
  end
220
221
 
221
- def exception_klass(errors)
222
- error = errors[0]
223
- case error[:id]
224
- when TezBalanceTooLow::FIRST_ERROR_REGEXP
225
- TezBalanceTooLow
226
- when ScriptRuntimeError::FIRST_ERROR_REGEXP
227
- ScriptRuntimeError
228
- else
229
- OperationFailure
230
- end
231
- end
222
+ failed!("failed", failed_operation_result[:errors], operation_results)
223
+ end
232
224
 
233
- def failed!(status, errors, metadata)
234
- raise exception_klass(errors).new(metadata: metadata, errors: errors, status: status)
225
+ def exception_klass(errors)
226
+ error = errors[0]
227
+ case error[:id]
228
+ when TezBalanceTooLow::FIRST_ERROR_REGEXP
229
+ TezBalanceTooLow
230
+ when ScriptRuntimeError::FIRST_ERROR_REGEXP
231
+ ScriptRuntimeError
232
+ else
233
+ OperationFailure
235
234
  end
235
+ end
236
+
237
+ def failed!(status, errors, metadata)
238
+ raise exception_klass(errors).new(metadata: metadata, errors: errors, status: status)
239
+ end
236
240
  end
237
- end
241
+ end
@@ -28,20 +28,28 @@ class TezosClient
28
28
  get "#{contract_link(contract_id)}/manager_key"
29
29
  end
30
30
 
31
+ def contract_storage_type(contract_id)
32
+ contract = contract_detail(contract_id)
33
+ contract[:script][:code].find { |elem| elem[:prim] == "storage" }[:args].first
34
+ end
35
+
31
36
  def contract_storage(contract_id)
32
37
  get "#{contract_link(contract_id)}/storage"
33
38
  end
34
39
 
40
+ def entrypoint(contract_id, entrypoint)
41
+ get("#{contract_link(contract_id)}/entrypoints/#{entrypoint}")
42
+ end
43
+
35
44
  def big_map_value(big_map_id:, key:, key_type:)
36
45
  expr_key = encode_script_expr(data: key, type: key_type)
37
46
 
38
47
  get "/chains/main/blocks/head/context/big_maps/#{big_map_id}/#{expr_key}"
39
48
  end
40
49
 
41
- def list_big_map_by_contract(contract_address:)
50
+ def contract_big_maps(contract_address)
42
51
  contract_storage = contract_storage(contract_address)
43
- contract = contract_detail(contract_address)
44
- storage_type = contract[:script][:code].find { |elem| elem[:prim] == "storage" }[:args].first
52
+ storage_type = contract_storage_type(contract_address)
45
53
 
46
54
  TezosClient::Tools::FindBigMapsInStorage.run!(
47
55
  storage: contract_storage,
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TezosClient::Tools::AnnotsToType < ActiveInteraction::Base
4
+ # example of typed_annots :
5
+ # {
6
+ # spending_ref: "string",
7
+ # remainder_amount: "nat",
8
+ # expires_at: "timestamp"
9
+ # }
10
+ hash :typed_annots, strip: false
11
+
12
+ validate :validate_types
13
+
14
+ def execute
15
+ return { "prim" => typed_annots.values.first } if typed_annots.size == 1
16
+
17
+ { "prim" => "pair", "args" => generate_type_args(ordered_annots) }
18
+ end
19
+
20
+ private
21
+ def generate_type_args(annots)
22
+ annot = annots.pop
23
+ annot_type = typed_annots[annot]
24
+
25
+ unless annots.size == 1
26
+ return [{ "prim" => "pair", "args" => generate_type_args(annots) },
27
+ { "prim" => annot_type, "annots" => ["%#{annot}"] }]
28
+ end
29
+
30
+ generated_args = [{ "prim" => annot_type, "annots" => ["%#{annot}"] }]
31
+ annot = annots.pop
32
+ annot_type = typed_annots[annot]
33
+ generated_args.unshift({ "prim" => annot_type, "annots" => ["%#{annot}"] })
34
+
35
+ generated_args
36
+ end
37
+
38
+ def ordered_annots
39
+ @ordered_annots ||= typed_annots.keys.sort
40
+ end
41
+
42
+ def validate_types
43
+ allowed_types = TezosClient::Tools::HashToMicheline::TYPES_MAPPING.keys
44
+ return if typed_annots.values.map(&:to_sym).all? { |type| type.in? allowed_types }
45
+
46
+ errors.add(:base, "The allowed types are: #{allowed_types.join(', ')}")
47
+ end
48
+ end
@@ -1,99 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class TezosClient::Tools::ConvertToHash < ActiveInteraction::Base
4
- interface :data
5
- interface :type
3
+ require_relative "convert_to_hash/base"
6
4
 
7
- def execute
8
- decorated_value
9
- end
10
-
11
- private
12
- def value
13
- case type[:prim]
14
- when "pair"
15
- pair_type
16
- when "list"
17
- list_type
18
- when "int"
19
- int_type
20
- when "nat"
21
- int_type
22
- when "key"
23
- key_type
24
- when "timestamp"
25
- timestamp_type
26
- when "string"
27
- string_type
28
- when "address"
29
- address_type
30
- else
31
- raise "type '#{type[:prim]}' not implemented"
32
- end
33
- end
34
-
35
- def pair_type
36
- raise "Not a 'Pair' type" unless data[:prim] == "Pair"
37
- raise "Difference detected between data and type \nDATA: #{data} \nTYPE:#{type} " unless data[:args].size == type[:args].size
38
-
39
- (data[:args]).zip(type[:args]).map do |data_n, type_n|
40
- compose(
41
- TezosClient::Tools::ConvertToHash,
42
- data: data_n,
43
- type: type_n
44
- )
45
- end.reduce({}, &:merge)
46
- end
5
+ Dir[File.join(__dir__, "convert_to_hash", "*.rb")].each { |file| require file }
47
6
 
48
- def list_type
49
- convert_list_element(data: data, element_type: type[:args].first)
50
- end
7
+ class TezosClient
8
+ module Tools
9
+ class ConvertToHash < ActiveInteraction::Base
10
+ interface :data
11
+ interface :type
51
12
 
52
- def convert_list_element(data:, element_type:)
53
- data.map do |elem|
54
- compose(
55
- TezosClient::Tools::ConvertToHash,
56
- data: elem,
57
- type: element_type
58
- )
13
+ def execute
14
+ TezosClient::Tools::ConvertToHash::Base.new(data: data, type: type).value
15
+ end
59
16
  end
60
17
  end
61
-
62
- def int_type
63
- data[:int].to_i
64
- end
65
-
66
- def key_type
67
- data[:bytes] || data[:string]
68
- end
69
-
70
- def timestamp_type
71
- Time.zone.at(data[:int].to_i)
72
- end
73
-
74
- def string_type
75
- data[:string]
76
- end
77
-
78
- def address_type
79
- data[:bytes] || data[:string]
80
- end
81
-
82
- def decorated_value
83
- anonymous? ? value : { var_name => value }
84
- end
85
-
86
- def anonymous?
87
- !(type.key?(:annots) && type[:annots].any?)
88
- end
89
-
90
- def var_name_annot
91
- type[:annots].first
92
- end
93
-
94
- def var_name
95
- return nil if anonymous?
96
-
97
- "#{var_name_annot[1..-1]}".to_sym
98
- end
99
18
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TezosClient
4
+ module Tools
5
+ class ConvertToHash < ActiveInteraction::Base
6
+ class Address < Base
7
+ include TezosClient::Crypto
8
+
9
+ def decode
10
+ if data.key?(:bytes)
11
+ if data[:bytes].start_with?("0000")
12
+ encode_tz(:tz1, data[:bytes][4..-1])
13
+ elsif data[:bytes].start_with?("0001")
14
+ encode_tz(:tz2, data[:bytes][4..-1])
15
+ elsif data[:bytes].start_with?("0002")
16
+ encode_tz(:tz3, data[:bytes][4..-1])
17
+ elsif data[:bytes].start_with?("01")
18
+ encode_tz(:KT, data[:bytes][2..-3])
19
+ else
20
+ data[:bytes]
21
+ end
22
+ else
23
+ data[:string]
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TezosClient
4
+ module Tools
5
+ class ConvertToHash < ActiveInteraction::Base
6
+ class Base
7
+ def initialize(data:, type:)
8
+ @data = data
9
+ @type = type
10
+ end
11
+
12
+ attr_accessor :data, :type
13
+
14
+ def value
15
+ anonymous? ? decode : { var_name => decode }
16
+ end
17
+
18
+ protected
19
+ def decode
20
+ klass.new(
21
+ data: data,
22
+ type: type
23
+ ).decode
24
+
25
+ rescue NameError => e
26
+ raise NotImplementedError, "type '#{type[:prim]}' not implemented"
27
+ end
28
+
29
+ def anonymous?
30
+ !(type.key?(:annots) && type[:annots].any?)
31
+ end
32
+
33
+ def var_name_annot
34
+ type[:annots].first
35
+ end
36
+
37
+ def var_name
38
+ return nil if anonymous?
39
+
40
+ "#{var_name_annot[1..-1]}".to_sym
41
+ end
42
+
43
+ private
44
+ def klass
45
+ "TezosClient::Tools::ConvertToHash::#{type[:prim].camelize}".constantize
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TezosClient
4
+ class BigMap < Struct.new(:name, :id, :value_type, :key_type); end
5
+
6
+ module Tools
7
+ class ConvertToHash < ActiveInteraction::Base
8
+ class BigMap < Base
9
+ def decode
10
+ ::TezosClient::BigMap.new(
11
+ var_name,
12
+ data[:int],
13
+ type[:args].second,
14
+ type[:args].first
15
+ )
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TezosClient
4
+ module Tools
5
+ class ConvertToHash < ActiveInteraction::Base
6
+ class Bytes < Base
7
+ def decode
8
+ data[:bytes] || data[:string]
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TezosClient
4
+ module Tools
5
+ class ConvertToHash < ActiveInteraction::Base
6
+ class Int < Base
7
+ def decode
8
+ data[:int].to_i
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TezosClient
4
+ module Tools
5
+ class ConvertToHash < ActiveInteraction::Base
6
+ class Key < Base
7
+ include TezosClient::Crypto
8
+
9
+ def decode
10
+ if data.key?(:bytes)
11
+ if data[:bytes].start_with?("00")
12
+ encode_tz(:edpk, data[:bytes][2..-1])
13
+ elsif data[:bytes].start_with?("01")
14
+ encode_tz(:sppk, data[:bytes][2..-1])
15
+ elsif data[:bytes].start_with?("02")
16
+ encode_tz(:p2pk, data[:bytes][2..-1])
17
+ else
18
+ data[:bytes]
19
+ end
20
+ else
21
+ data[:string]
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TezosClient
4
+ module Tools
5
+ class ConvertToHash < ActiveInteraction::Base
6
+ class List < Base
7
+ def decode
8
+ data.map do |elem|
9
+ TezosClient::Tools::ConvertToHash::Base.new(
10
+ data: elem,
11
+ type: elem_type
12
+ ).value
13
+ end
14
+ end
15
+
16
+ def elem_type
17
+ type[:args].first
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TezosClient
4
+ module Tools
5
+ class ConvertToHash < ActiveInteraction::Base
6
+ class Map < Base
7
+ def decode
8
+ new_map = {}
9
+
10
+ data.each do |elem|
11
+ raise "Not a 'Map' type" unless elem[:prim] == "Elt"
12
+
13
+ key = TezosClient::Tools::ConvertToHash::Base.new(
14
+ data: elem[:args].first,
15
+ type: type[:args].first
16
+ ).value
17
+
18
+ value = TezosClient::Tools::ConvertToHash::Base.new(
19
+ data: elem[:args].second,
20
+ type: type[:args].second
21
+ ).value
22
+
23
+ new_map[key] = value
24
+ end
25
+
26
+ new_map
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TezosClient
4
+ module Tools
5
+ class ConvertToHash < ActiveInteraction::Base
6
+ class Nat < Base
7
+ def decode
8
+ data[:int].to_i
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TezosClient
4
+ module Tools
5
+ class ConvertToHash < ActiveInteraction::Base
6
+ class Pair < Base
7
+ def decode
8
+ raise "Not a 'Pair' type" unless data[:prim] == "Pair"
9
+ raise "Difference detected between data and type \nDATA: #{data} \nTYPE:#{type} " unless data[:args].size == type[:args].size
10
+
11
+ (data[:args]).zip(type[:args]).map do |data_n, type_n|
12
+ TezosClient::Tools::ConvertToHash::Base.new(
13
+ data: data_n,
14
+ type: type_n
15
+ ).value
16
+ end.reduce({}, &:merge)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TezosClient
4
+ module Tools
5
+ class ConvertToHash < ActiveInteraction::Base
6
+ class Signature < Base
7
+ include TezosClient::Crypto
8
+
9
+ def decode
10
+ if data.key?(:bytes)
11
+ encode_tz(:edsig, data[:bytes])
12
+ else
13
+ data[:string]
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TezosClient
4
+ module Tools
5
+ class ConvertToHash < ActiveInteraction::Base
6
+ class String < Base
7
+ def decode
8
+ data[:string]
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TezosClient
4
+ module Tools
5
+ class ConvertToHash < ActiveInteraction::Base
6
+ class Timestamp < Base
7
+ def decode
8
+ if data.key? :int
9
+ Time.zone.at(data[:int].to_i)
10
+ elsif data.key? :string
11
+ Time.zone.parse(data[:string])
12
+ else
13
+ raise "Can not convert timestamp: #{data}"
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -7,50 +7,19 @@ class TezosClient::Tools::FindBigMapsInStorage < ActiveInteraction::Base
7
7
  strip: false
8
8
 
9
9
  def execute
10
- case storage_type[:prim]
11
- when "pair"
12
- pair_type(data: storage, type: storage_type)
13
- when "list"
14
- list_type(data: storage, type: storage_type)
15
- when "big_map"
16
- big_map_type(data: storage, type: storage_type)
17
- end
18
- end
19
-
20
- def pair_type(data:, type:)
21
- raise "Not a 'Pair' type" unless data[:prim] == "Pair"
22
- raise "Difference detected between data and type \nDATA: #{data} \nTYPE:#{type} " unless data[:args].size == type[:args].size
23
-
24
- (0 .. data[:args].size - 1).map do |iter|
25
- compose(
26
- TezosClient::Tools::FindBigMapsInStorage,
27
- storage: data[:args][iter],
28
- storage_type: type[:args][iter]
29
- )
30
- end.compact.flatten
10
+ hash_storage
11
+ .map(&:last)
12
+ .select { |value| value.is_a? TezosClient::BigMap }
13
+ .map(&:to_h)
14
+ .map(&:with_indifferent_access)
31
15
  end
32
16
 
33
- def list_type(data:, type:)
34
- element_type = type[:args].first
35
- data.map do |elem|
17
+ private
18
+ def hash_storage
36
19
  compose(
37
20
  TezosClient::Tools::ConvertToHash,
38
- data: elem,
39
- type: element_type
21
+ data: storage,
22
+ type: storage_type
40
23
  )
41
24
  end
42
- end
43
-
44
- def big_map_type(data:, type:)
45
- {
46
- name: var_name(type),
47
- id: data[:int],
48
- value_type: type[:args].second,
49
- key_type: type[:args].first
50
- }.with_indifferent_access
51
- end
52
-
53
- def var_name(type)
54
- "#{type[:annots].first[1..-1]}".to_sym
55
- end
56
25
  end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ class TezosClient::Tools::HashToMicheline < ActiveInteraction::Base
4
+ # TODO: handle Arrays and Maps
5
+ TYPES_MAPPING = {
6
+ int: :int,
7
+ nat: :int,
8
+ string: :string,
9
+ signature: :string,
10
+ bytes: :bytes,
11
+ timestamp: :int,
12
+ key: :string,
13
+ address: :string
14
+ }.freeze
15
+
16
+ string :contract_address, default: nil
17
+ string :entrypoint, default: nil
18
+ # example of params:
19
+ # {
20
+ # spending_ref: "toto",
21
+ # expires_at: Time.now
22
+ # }
23
+ hash :params, strip: false
24
+ hash :storage_type, strip: false, default: {}
25
+ interface :blockchain_client, methods: [:entrypoint], default: -> { TezosClient.new }
26
+
27
+ # if storage_type is not received, it is fetched from the blockchain using
28
+ # contract_address and entrypoint (that are mandatory in this case)
29
+ validate :storage_type_or_contract_address_presence
30
+
31
+ def execute
32
+ return hash_type_to_hash_data(_storage_type.fetch(:prim), params.values.first) if params.size == 1
33
+
34
+ { prim: "Pair", args: generate_micheline(_storage_type[:args]) }
35
+ end
36
+
37
+ private
38
+ def generate_micheline(remaining_storage_type)
39
+ remaining_storage_type.each_with_object([]) do |h, acc|
40
+ next acc << { prim: "Pair", args: generate_micheline(h[:args]) } if h[:prim] == "pair"
41
+
42
+ annot = h[:annots].first.slice(1..-1).to_sym # remove '%'
43
+ acc << hash_type_to_hash_data(h[:prim], params.fetch(annot))
44
+ end
45
+ end
46
+
47
+ def convert_type(michelson_type)
48
+ TYPES_MAPPING.fetch(michelson_type.to_sym)
49
+ end
50
+
51
+ def hash_type_to_hash_data(michelson_type, value)
52
+ type = convert_type(michelson_type)
53
+
54
+ converted_value = case michelson_type.to_sym
55
+ when :nat, :int
56
+ value.to_s
57
+ when :timestamp
58
+ errors.add(:base, "timestamp input must be an instance of Time") unless value.is_a? Time
59
+
60
+ value.to_i.to_s
61
+ else
62
+ value
63
+ end
64
+
65
+ { type => converted_value }
66
+ end
67
+
68
+ def _storage_type
69
+ (storage_type.presence || blockchain_client.entrypoint(contract_address, entrypoint)).deep_symbolize_keys
70
+ end
71
+
72
+ def storage_type_or_contract_address_presence
73
+ return if storage_type.present? ^ (contract_address.present? && entrypoint.present?)
74
+
75
+ errors.add(:base,
76
+ "You should provide the contract_address and the entrypoint only if storage_type is not provided")
77
+ end
78
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class TezosClient
4
- VERSION = "1.1.2"
4
+ VERSION = "1.2.3"
5
5
  end
@@ -34,7 +34,7 @@ Gem::Specification.new do |spec|
34
34
  spec.require_paths = ["lib"]
35
35
 
36
36
  spec.add_development_dependency "bundler", "~> 1.16"
37
- spec.add_development_dependency "rake", "~> 10.0"
37
+ spec.add_development_dependency "rake", "~> 13.0"
38
38
  spec.add_development_dependency "rspec", "~> 3.0"
39
39
  spec.add_development_dependency "rubocop-rails_config"
40
40
  spec.add_development_dependency "webmock"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tezos_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pierre Michard
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-02-27 00:00:00.000000000 Z
11
+ date: 2020-07-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: '13.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '13.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -274,8 +274,23 @@ files:
274
274
  - lib/tezos_client/smartpy_inteface/smartpy_wrapper.rb
275
275
  - lib/tezos_client/smartpy_interface.rb
276
276
  - lib/tezos_client/string_utils.rb
277
+ - lib/tezos_client/tools/annots_to_type.rb
277
278
  - lib/tezos_client/tools/convert_to_hash.rb
279
+ - lib/tezos_client/tools/convert_to_hash/address.rb
280
+ - lib/tezos_client/tools/convert_to_hash/base.rb
281
+ - lib/tezos_client/tools/convert_to_hash/big_map.rb
282
+ - lib/tezos_client/tools/convert_to_hash/bytes.rb
283
+ - lib/tezos_client/tools/convert_to_hash/int.rb
284
+ - lib/tezos_client/tools/convert_to_hash/key.rb
285
+ - lib/tezos_client/tools/convert_to_hash/list.rb
286
+ - lib/tezos_client/tools/convert_to_hash/map.rb
287
+ - lib/tezos_client/tools/convert_to_hash/nat.rb
288
+ - lib/tezos_client/tools/convert_to_hash/pair.rb
289
+ - lib/tezos_client/tools/convert_to_hash/signature.rb
290
+ - lib/tezos_client/tools/convert_to_hash/string.rb
291
+ - lib/tezos_client/tools/convert_to_hash/timestamp.rb
278
292
  - lib/tezos_client/tools/find_big_maps_in_storage.rb
293
+ - lib/tezos_client/tools/hash_to_micheline.rb
279
294
  - lib/tezos_client/tools/system_call.rb
280
295
  - lib/tezos_client/tools/temporary_file.rb
281
296
  - lib/tezos_client/version.rb
@@ -286,7 +301,7 @@ licenses:
286
301
  - MIT
287
302
  metadata:
288
303
  allowed_push_host: https://rubygems.org
289
- post_install_message:
304
+ post_install_message:
290
305
  rdoc_options: []
291
306
  require_paths:
292
307
  - lib
@@ -301,9 +316,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
301
316
  - !ruby/object:Gem::Version
302
317
  version: '0'
303
318
  requirements: []
304
- rubyforge_project:
305
- rubygems_version: 2.7.6
306
- signing_key:
319
+ rubygems_version: 3.0.4
320
+ signing_key:
307
321
  specification_version: 4
308
322
  summary: Wrapper to the tezos client.
309
323
  test_files: []