etheruby 0.1.0 → 0.9.1

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
  SHA1:
3
- metadata.gz: 62e7a1ef2415572fb35e1617898576247fabeccb
4
- data.tar.gz: 9f6747ff369f23fe11f3a67c0b815b6a53bbfd72
3
+ metadata.gz: dfed46cee6fdea612e7c4c0c08b0cd634d8746a4
4
+ data.tar.gz: 77c90af3d066a14055b39297c5092705dd22b3e0
5
5
  SHA512:
6
- metadata.gz: b5deae709916778cfd2e39217f22edb24929da0a57054cd5020a0882e8bf222d3b1928d90140a21ce99f9aaeb0eb103f4172031f1d9b857f05aee62ea39e9648
7
- data.tar.gz: f725746f91570b71d37d89b62c241945688603fedaf17f0fb56db178511eb73206edd72d9d45fba75b88ebdb16458765e242166222d81765b7c03649e99b9051
6
+ metadata.gz: 72a01c07b209b5124207a196adb86d9d5207cf9a461265a62822ff74bd55caa6aed3f67ab53b6c33ebe67822bad5beca3ba684db8dbb44141c2aef53856a2ec8
7
+ data.tar.gz: b2960aeab3cb037b99b139aecbef3f350fbc06b8add6ec0ed5aac8c5e3d713d2863ad54dd7d3fc5de81f02162ee549828e25797a5e74756857b9d55aa5109dce
data/lib/etheruby.rb CHANGED
@@ -1,76 +1,4 @@
1
1
  require 'logger'
2
-
3
2
  require_relative 'etheruby/client'
4
- require_relative 'etheruby/contract_method_dsl'
5
- require_relative 'etheruby/arguments_generator'
6
- require_relative 'etheruby/response_parser'
7
-
8
- module Etheruby
9
- class NoContractMethodError < StandardError; end
10
-
11
- def contract
12
- Class.new do
13
- def self.inherited(subclass)
14
- @@c_methods = {}
15
- @@logger = ::Logger.new(STDOUT)
16
- @@logger.level = if ENV.has_key? 'ETHERUBY_DEBUG'
17
- ::Logger::DEBUG
18
- else
19
- ::Logger::WARN
20
- end
21
- @@logger.progname = "Etheruby Contract '#{subclass.name}'"
22
- end
23
-
24
- def self.at_address(address)
25
- @@address = address
26
- end
27
-
28
- def self.method(name, &blk)
29
- cmd = ContractMethodDSL.new(name)
30
- cmd.instance_exec &blk if blk
31
- @@c_methods[name] = cmd.validate!
32
- @@logger.debug("Registred method #{name}")
33
- end
34
-
35
- def self.method_missing(sym, *args)
36
- raise NoContractMethodError.new (
37
- "The method #{sym} does not exist in the #{self.class.to_s} contract."
38
- ) unless @@c_methods.include? sym
39
- execute_contract_method(@@c_methods[sym], args)
40
- end
41
-
42
- def self.execute_contract_method(method_info, args)
43
- arguments = ArgumentsGenerator.new(method_info[:params], args).to_s
44
- data = "#{method_info[:signature]}#{arguments}"
45
- composed_body = { to: self.address, data: data }
46
- [ :gas, :gasPrice, :value, :from ].each { |kw|
47
- composed_body[kw] = method_info[kw] if method_info.has_key? kw
48
- }
49
- @@logger.debug("Calling #{method_info[:name]} with parameters #{composed_body.inspect}")
50
- response = call_api composed_body
51
- if response.has_key? 'error'
52
- @@logger.error("Failed contract execution #{response['error']['message']}")
53
- else
54
- @@logger.debug("Response from API for #{method_info[:name]} : #{response.inspect}")
55
- end
56
- if method_info.has_key? :returns
57
- ResponseParser.new(method_info[:returns], response['result']).parse
58
- else
59
- response['result']
60
- end
61
- end
62
-
63
- def self.call_api(composed_body)
64
- Client.eth.call composed_body, "latest"
65
- end
66
-
67
- def self.address
68
- "0x#{@@address.to_s(16)}"
69
- end
70
- end
71
- end
72
-
73
- module_function :contract
74
-
75
- Contract = Etheruby::contract
76
- end
3
+ require_relative 'etheruby/contract'
4
+ require_relative 'etheruby/railtie' if defined?(Rails)
@@ -18,21 +18,35 @@ module Etheruby
18
18
 
19
19
  def to_s
20
20
  raise ArgumentsCountError.new("Bad number of arguments") unless args.count == params.count
21
- head = ''
21
+ head = []
22
22
  tail = ''
23
- current_tail_position = (params.count*32)
23
+ current_tail_position = 0
24
24
  (0..params.count-1).each do |i|
25
25
  param, arg = params[i], args[i]
26
26
  if Etheruby.is_static_type? param
27
- head += Etheruby.treat_variable(param, arg, :encode).to_s
27
+ head << {final: Etheruby.treat_variable(param, arg, :encode).to_s}
28
28
  else
29
- head += Etheruby::Encoders::Uint.new(current_tail_position).encode
29
+ head << {pointer: current_tail_position}
30
30
  content = Etheruby.treat_variable(param, arg, :encode).to_s
31
31
  current_tail_position += content.length/2
32
32
  tail += content
33
33
  end
34
34
  end
35
- return head + tail
35
+ head_size = head.map { |x|
36
+ if x.has_key?(:pointer)
37
+ 32
38
+ else
39
+ x[:final].length/2
40
+ end
41
+ }.inject(0){|sum,x| sum + x }
42
+ final_head = head.map { |x|
43
+ if x.has_key?(:pointer)
44
+ Etheruby::Encoders::Uint.new(head_size + x[:pointer]).encode
45
+ else
46
+ x[:final]
47
+ end
48
+ }.join
49
+ return final_head + tail
36
50
  end
37
51
 
38
52
  end
@@ -0,0 +1,74 @@
1
+ require_relative 'client'
2
+ require_relative 'contract_method_dsl'
3
+ require_relative 'arguments_generator'
4
+ require_relative 'response_parser'
5
+
6
+ module Etheruby
7
+ class NoContractMethodError < StandardError; end
8
+
9
+ def contract
10
+ Class.new do
11
+ def self.inherited(subclass)
12
+ @@c_methods = {}
13
+ @@logger = ::Logger.new(STDOUT)
14
+ @@logger.level = if ENV.has_key? 'ETHERUBY_DEBUG'
15
+ ::Logger::DEBUG
16
+ else
17
+ ::Logger::WARN
18
+ end
19
+ @@logger.progname = "Etheruby Contract '#{subclass.name}'"
20
+ end
21
+
22
+ def self.at_address(address)
23
+ @@address = address
24
+ end
25
+
26
+ def self.method(name, &blk)
27
+ cmd = ContractMethodDSL.new(name)
28
+ cmd.instance_exec &blk if blk
29
+ @@c_methods[name] = cmd.validate!
30
+ @@logger.debug("Registred method #{name}")
31
+ end
32
+
33
+ def self.method_missing(sym, *args)
34
+ raise NoContractMethodError.new (
35
+ "The method #{sym} does not exist in the #{self.class.to_s} contract."
36
+ ) unless @@c_methods.include? sym
37
+ execute_contract_method(@@c_methods[sym], args)
38
+ end
39
+
40
+ def self.execute_contract_method(method_info, args)
41
+ arguments = ArgumentsGenerator.new(method_info[:params], args).to_s
42
+ data = "#{method_info[:signature]}#{arguments}"
43
+ composed_body = { to: self.address, data: data }
44
+ [ :gas, :gasPrice, :value, :from ].each { |kw|
45
+ composed_body[kw] = method_info[kw] if method_info.has_key? kw
46
+ }
47
+ @@logger.debug("Calling #{method_info[:name]} with parameters #{composed_body.inspect}")
48
+ response = call_api composed_body
49
+ if response.has_key? 'error'
50
+ @@logger.error("Failed contract execution #{response['error']['message']}")
51
+ else
52
+ @@logger.debug("Response from API for #{method_info[:name]} : #{response.inspect}")
53
+ end
54
+ if method_info.has_key? :returns
55
+ ResponseParser.new(method_info[:returns], response['result']).parse
56
+ else
57
+ response['result']
58
+ end
59
+ end
60
+
61
+ def self.call_api(composed_body)
62
+ Client.eth.call composed_body, "latest"
63
+ end
64
+
65
+ def self.address
66
+ "0x#{@@address.to_s(16)}"
67
+ end
68
+ end
69
+ end
70
+
71
+ module_function :contract
72
+
73
+ Contract = Etheruby::contract
74
+ end
@@ -9,7 +9,7 @@ module Etheruby::Encoders
9
9
  end
10
10
 
11
11
  def decode
12
- Uint.new(data).decode[0] == 1
12
+ return Uint.new(data).decode[0] == 1, 32
13
13
  end
14
14
  end
15
15
 
@@ -0,0 +1,26 @@
1
+ require_relative 'base'
2
+ require_relative 'address'
3
+
4
+ module Etheruby::Encoders
5
+
6
+ class Function < Base
7
+
8
+ def encode
9
+ (data[:address].to_s(16) + data[:selector].to_s(16)).ljust(64, '0')
10
+ end
11
+
12
+ def decode
13
+ address, selector = data[0..39], data[40..47]
14
+ return {
15
+ address: Address.new(address).decode[0],
16
+ selector: "0x#{selector}"
17
+ }, 32
18
+ end
19
+
20
+ def to_s
21
+ encode
22
+ end
23
+
24
+ end
25
+
26
+ end
@@ -0,0 +1,9 @@
1
+ module Etheruby
2
+
3
+ class Railtie < Rails::Railtie
4
+ initializer "etheruby.configure" do |app|
5
+ Etheruby::Client.uri = app.config.etheruby_uri if app.config.respond_to? :etheruby_uri
6
+ end
7
+ end
8
+
9
+ end
@@ -1,4 +1,6 @@
1
1
  require_relative 'type_matchers'
2
+ require_relative 'treat_variable'
3
+ require_relative 'encoders/int'
2
4
 
3
5
  module Etheruby
4
6
 
@@ -13,11 +15,32 @@ module Etheruby
13
15
 
14
16
  def parse
15
17
  if returns.count == 1
16
- Etheruby::treat_variable(returns[0], response, :decode)
18
+ v, s = Etheruby::treat_variable(returns[0], response, :decode)
19
+ v = v.decode if v.is_a? Etheruby::Encoders::DynamicArray or v.is_a? Etheruby::Encoders::StaticArray
20
+ v
17
21
  else
18
- returns.each do |type|
19
-
22
+ real_response = @response
23
+ values = []
24
+ i = 0
25
+ loop do
26
+ return_type = returns[i]
27
+ if Etheruby::is_static_type?(return_type)
28
+ v, s = Etheruby::treat_variable(return_type, real_response, :decode)
29
+ else
30
+ value_position, s = Etheruby::Encoders::Uint.new(real_response).decode
31
+ v, take_size = Etheruby::treat_variable(
32
+ return_type,
33
+ @response[(value_position*2)..response.length],
34
+ :decode
35
+ )
36
+ end
37
+ v = v.decode if v.is_a? Etheruby::Encoders::DynamicArray or v.is_a? Etheruby::Encoders::StaticArray
38
+ values << v
39
+ break if values.count == returns.count
40
+ real_response = real_response[s*2..real_response.length]
41
+ i += 1
20
42
  end
43
+ values
21
44
  end
22
45
  end
23
46
 
@@ -19,11 +19,9 @@ module Etheruby
19
19
 
20
20
  def treat_variable(param, arg, direction)
21
21
  if match = TypeMatchers.is_sized_type(param)
22
- # Parameter is a sized type, e.g. uint256, byte32 ...
23
22
  klass = Etheruby::Encoders.const_get(match[1].capitalize)
24
- return case klass
25
- when Encoders::Bytes
26
- Byte.new(match[2].to_i, arg)
23
+ if match[1] == 'bytes'
24
+ Encoders::Byte.new(match[2].to_i, arg)
27
25
  else
28
26
  klass.new(arg)
29
27
  end.send(direction)
@@ -42,7 +40,7 @@ module Etheruby
42
40
  Etheruby::Encoders::DynamicArray.new(match[1], arg).send(direction)
43
41
 
44
42
  else
45
- # Parameter is a single-word type : string, bytes, address etc...
43
+ # Parameter is a single-word type : string, bytes, address, function etc...
46
44
  Etheruby::Encoders.const_get(param.capitalize).new(arg).send(direction)
47
45
 
48
46
  end
metadata CHANGED
@@ -1,57 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: etheruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jérémy SEBAN
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-17 00:00:00.000000000 Z
11
+ date: 2017-01-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: digest-sha3
14
+ name: simplecov
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.1'
19
+ version: '0.12'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.1'
26
+ version: '0.12'
27
27
  - !ruby/object:Gem::Dependency
28
- name: simplecov
28
+ name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.12'
33
+ version: '12.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: '0.12'
40
+ version: '12.0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rake
42
+ name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '12.0'
47
+ version: '3.5'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '12.0'
54
+ version: '3.5'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: multi_json
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -67,19 +67,19 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '1.12'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rspec
70
+ name: digest-sha3
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '3.5'
75
+ version: '1.1'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '3.5'
82
+ version: '1.1'
83
83
  description: Etheruby is a library including a client for the JSON-RPC API and a Object-Contract
84
84
  Mapper to interact with smart-contracts.
85
85
  email: jeremy@seban.eu
@@ -90,6 +90,7 @@ files:
90
90
  - lib/etheruby.rb
91
91
  - lib/etheruby/arguments_generator.rb
92
92
  - lib/etheruby/client.rb
93
+ - lib/etheruby/contract.rb
93
94
  - lib/etheruby/contract_method_dsl.rb
94
95
  - lib/etheruby/encoders/address.rb
95
96
  - lib/etheruby/encoders/arrays.rb
@@ -97,8 +98,10 @@ files:
97
98
  - lib/etheruby/encoders/bool.rb
98
99
  - lib/etheruby/encoders/bytes.rb
99
100
  - lib/etheruby/encoders/fixed.rb
101
+ - lib/etheruby/encoders/function.rb
100
102
  - lib/etheruby/encoders/int.rb
101
103
  - lib/etheruby/encoders/string.rb
104
+ - lib/etheruby/railtie.rb
102
105
  - lib/etheruby/response_parser.rb
103
106
  - lib/etheruby/treat_variable.rb
104
107
  - lib/etheruby/type_matchers.rb
@@ -125,5 +128,5 @@ rubyforge_project:
125
128
  rubygems_version: 2.4.5
126
129
  signing_key:
127
130
  specification_version: 4
128
- summary: 'Etheruby : Ethereum smart-contract classy-describer for Ruby.'
131
+ summary: 'Etheruby : The Ethereum Object-Contract Mapper (OCM) for Ruby.'
129
132
  test_files: []