etherlite 0.2.2 → 0.3.0

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
- SHA1:
3
- metadata.gz: ca6ccaaf22a1079aa68d7d157900b271bed5e1db
4
- data.tar.gz: 1d208e7063d99de949f7b80a3eefdffb799ee840
2
+ SHA256:
3
+ metadata.gz: fe14df0fc898d4e298d57704e8a7f2acf0cb3dcace02b94903b8f295f94e971c
4
+ data.tar.gz: 87c4bc2dca3fb92d8a1eca54080cbfa50107defe48d0007cc5e6c3910bdfaa4e
5
5
  SHA512:
6
- metadata.gz: 18451599c309267ee0fe65da4d04ff653ada9673ed9a21381bd27c7d5aa1333cdaed95a1d7d21d3e911d743490cf7f7728fb5fd7d4e6ccbc03ea02ff08578609
7
- data.tar.gz: a6bf702b4f531e738651060de080ae097e67328783164c6509117fb49c3c76727e9b8c1784eec283f34c5586b3cde2d88cb24643d00ae32feb31bebfbce66313
6
+ metadata.gz: c1e16e2460b1e67948efd91921b1e03e6805c114fdba9a375c4b83695baa6d01ca80b46fc3530be5ac923c641d47190cc7fc466cdf6daef793f55cb54993be0a
7
+ data.tar.gz: 76cb54b21dd785777fcd474f0bbf85e374b9a6aad8bd64d1ddfed73f195c51a736b339045b09056be8da32c34e7d272abcf7393b4bc1bd187efe2fb2186adc57
@@ -24,11 +24,11 @@ Gem::Specification.new do |spec|
24
24
  spec.add_dependency "eth", "~> 0.4.4"
25
25
  spec.add_dependency "activesupport"
26
26
 
27
- spec.add_development_dependency "bundler", "~> 1.12"
27
+ spec.add_development_dependency "bundler", "~> 2.1.4"
28
28
  spec.add_development_dependency "rake", "~> 10.0"
29
29
  spec.add_development_dependency "rspec", "~> 3.0"
30
30
  spec.add_development_dependency "guard", "~> 2.14"
31
31
  spec.add_development_dependency "guard-rspec", "~> 4.7"
32
- spec.add_development_dependency "webmock", "~> 3.0.1"
32
+ spec.add_development_dependency "webmock", "~> 3.7.5"
33
33
  spec.add_development_dependency "pry"
34
34
  end
@@ -32,6 +32,7 @@ require "etherlite/contract/function_input"
32
32
 
33
33
  require "etherlite/errors"
34
34
  require "etherlite/configuration"
35
+ require "etherlite/event_provider"
35
36
  require "etherlite/abi"
36
37
  require "etherlite/utils"
37
38
  require "etherlite/connection"
@@ -9,7 +9,11 @@ module Etherlite
9
9
  end
10
10
 
11
11
  def send_transaction(_options = {})
12
- nonce_manager.with_next_nonce_for(normalized_address) do |nonce|
12
+ nonce_options = {
13
+ replace: _options.fetch(:replace, false)
14
+ }
15
+
16
+ nonce_manager.with_next_nonce_for(normalized_address, nonce_options) do |nonce|
13
17
  tx = Eth::Tx.new(
14
18
  value: _options.fetch(:value, 0),
15
19
  data: _options.fetch(:data, ''),
@@ -12,8 +12,21 @@ module Etherlite
12
12
  connection.eth_gas_price
13
13
  end
14
14
 
15
- def get_transaction(_hash)
16
- load_transaction(_hash).refresh
15
+ def get_transaction(*_args)
16
+ load_transaction(*_args).refresh
17
+ end
18
+
19
+ def get_logs(events: nil, address: nil, from_block: :earliest, to_block: :latest)
20
+ params = {
21
+ fromBlock: Etherlite::Utils.encode_block_param(from_block),
22
+ toBlock: Etherlite::Utils.encode_block_param(to_block)
23
+ }
24
+
25
+ params[:topics] = [Array(events).map(&:topic)] unless events.nil?
26
+ params[:address] = Etherlite::Utils.encode_address_param(address) unless address.nil?
27
+
28
+ logs = connection.ipc_call(:eth_getLogs, params)
29
+ ::Etherlite::EventProvider.parse_raw_logs(connection, logs)
17
30
  end
18
31
 
19
32
  def load_transaction(_hash)
@@ -9,6 +9,10 @@ module Etherlite
9
9
  Etherlite::Utils.hex_to_uint ipc_call(:eth_gasPrice)
10
10
  end
11
11
 
12
+ def eth_get_transaction_by_hash(_tx_hash)
13
+ ipc_call(:eth_getTransactionByHash, _tx_hash)
14
+ end
15
+
12
16
  def eth_get_transaction_receipt(_tx_hash)
13
17
  ipc_call(:eth_getTransactionReceipt, _tx_hash)
14
18
  end
@@ -3,7 +3,7 @@ module Etherlite::Abi
3
3
  def perform
4
4
  klass = Class.new(Etherlite::Contract::Base)
5
5
 
6
- define_class_getter klass, 'unlinked_binary', unlinked_binary
6
+ define_class_getter klass, 'unlinked_bytecode', unlinked_bytecode
7
7
 
8
8
  abi_definitions.each do |definition|
9
9
  case definition['type']
@@ -18,12 +18,13 @@ module Etherlite::Abi
18
18
 
19
19
  klass.functions.freeze
20
20
  klass.events.freeze
21
+ ::Etherlite::EventProvider.register_contract_events klass
21
22
  klass
22
23
  end
23
24
 
24
25
  private
25
26
 
26
- def unlinked_binary
27
+ def unlinked_bytecode
27
28
  @artifact['unlinked_binary'] || @artifact['bytecode'] || ''
28
29
  end
29
30
 
@@ -10,7 +10,7 @@ module Etherlite::Contract
10
10
  @events ||= []
11
11
  end
12
12
 
13
- def self.unlinked_binary
13
+ def self.unlinked_bytecode
14
14
  '0x0'
15
15
  end
16
16
 
@@ -18,13 +18,13 @@ module Etherlite::Contract
18
18
  nil
19
19
  end
20
20
 
21
- def self.binary
22
- @binary ||= begin
23
- if /__[^_]+_+/ === unlinked_binary
21
+ def self.bytecode
22
+ @bytecode ||= begin
23
+ if /__[^_]+_+/.match? unlinked_bytecode
24
24
  raise UnlinkedContractError, 'compiled contract contains unresolved library references'
25
25
  end
26
26
 
27
- unlinked_binary
27
+ unlinked_bytecode
28
28
  end
29
29
  end
30
30
 
@@ -32,7 +32,7 @@ module Etherlite::Contract
32
32
  options = _args.last.is_a?(Hash) ? _args.pop : {}
33
33
  as = options[:as] || options[:client].try(:default_account) || Etherlite.default_account
34
34
 
35
- tx_data = binary
35
+ tx_data = options.fetch(:bytecode, bytecode)
36
36
  tx_data += constructor.encode(_args) unless constructor.nil?
37
37
 
38
38
  as.send_transaction({ data: tx_data }.merge(options))
@@ -64,24 +64,14 @@ module Etherlite::Contract
64
64
  toBlock: Etherlite::Utils.encode_block_param(to_block)
65
65
  }
66
66
 
67
- params[:topics] = [events.map { |e| event_topic e }] unless events.nil?
68
-
69
- event_map = Hash[(events || self.class.events).map { |e| [event_topic(e), e] }]
67
+ params[:topics] = [events.map(&:topic)] unless events.nil?
70
68
 
71
69
  logs = @connection.ipc_call(:eth_getLogs, params)
72
- logs.map do |log|
73
- event = event_map[log["topics"].first]
74
- # TODO: support anonymous events!
75
- event.decode(@connection, log) unless event.nil?
76
- end
70
+ ::Etherlite::EventProvider.parse_raw_logs(@connection, logs)
77
71
  end
78
72
 
79
73
  private
80
74
 
81
75
  attr_reader :default_account, :normalized_address
82
-
83
- def event_topic(_event)
84
- '0x' + Etherlite::Utils.sha3(_event.signature)
85
- end
86
76
  end
87
77
  end
@@ -17,19 +17,25 @@ module Etherlite::Contract
17
17
  end
18
18
  end
19
19
 
20
+ def self.topic
21
+ '0x' + Etherlite::Utils.sha3(signature)
22
+ end
23
+
20
24
  def self.decode(_connection, _json)
21
25
  new(
22
26
  _json['blockNumber'].nil? ? nil : Etherlite::Utils.hex_to_uint(_json['blockNumber']),
23
27
  _json['transactionHash'],
28
+ Etherlite::Address.new(_connection, Etherlite::Utils.normalize_address(_json['address'])),
24
29
  DecodeLogInputs.for(connection: _connection, inputs: inputs, json: _json)
25
30
  )
26
31
  end
27
32
 
28
- attr_reader :block_number, :tx_hash, :attributes
33
+ attr_reader :block_number, :tx_hash, :address, :attributes
29
34
 
30
- def initialize(_block_number, _tx_hash, _attributes)
35
+ def initialize(_block_number, _tx_hash, _address, _attributes)
31
36
  @block_number = _block_number
32
37
  @tx_hash = _tx_hash
38
+ @address = _address
33
39
  @attributes = _attributes
34
40
  end
35
41
  end
@@ -0,0 +1,29 @@
1
+ module Etherlite
2
+ module EventProvider
3
+ extend self
4
+
5
+ def register_contract_events(_contract_class)
6
+ _contract_class.events.each { |e| register_event e }
7
+ end
8
+
9
+ def register_event(_event)
10
+ event_by_topic[_event.topic] = _event
11
+ end
12
+
13
+ def parse_raw_log(_connection, _raw_log)
14
+ event = event_by_topic[_raw_log["topics"].first]
15
+ return nil if event.nil?
16
+ event.decode(_connection, _raw_log)
17
+ end
18
+
19
+ def parse_raw_logs(_connection, _raw_logs)
20
+ _raw_logs.map { |e| parse_raw_log(_connection, e) }.reject &:nil?
21
+ end
22
+
23
+ private
24
+
25
+ def event_by_topic
26
+ @event_by_topic ||= {}
27
+ end
28
+ end
29
+ end
@@ -17,9 +17,10 @@ module Etherlite
17
17
  last_nonce
18
18
  end
19
19
 
20
- def with_next_nonce_for(_normalized_address)
20
+ def with_next_nonce_for(_normalized_address, replace: false)
21
21
  @@nonce_mutex.synchronize do
22
- next_nonce = last_nonce_for(_normalized_address) + 1
22
+ next_nonce = last_nonce_for(_normalized_address)
23
+ next_nonce += 1 if next_nonce.negative? || !replace # if first tx, don't replace
23
24
 
24
25
  begin
25
26
  result = yield next_nonce
@@ -1,52 +1,92 @@
1
1
  module Etherlite
2
2
  class Transaction
3
- attr_reader :tx_hash, :receipt
3
+ attr_reader :tx_hash
4
4
 
5
5
  def initialize(_connection, _tx_hash)
6
6
  @connection = _connection
7
7
  @tx_hash = _tx_hash
8
- @receipt = {}
8
+ @loaded = false
9
9
  end
10
10
 
11
11
  def refresh
12
- @receipt = @connection.eth_get_transaction_receipt(@tx_hash) || {}
12
+ @original = @connection.eth_get_transaction_by_hash(@tx_hash)
13
+ @loaded = true
13
14
  self
14
15
  end
15
16
 
17
+ def original
18
+ refresh unless @loaded
19
+ @original
20
+ end
21
+
16
22
  def removed?
17
- @receipt.nil?
23
+ original.nil?
18
24
  end
19
25
 
20
- def succeeded?
21
- status == 1
26
+ def mined?
27
+ original.present? && !original['blockNumber'].nil?
22
28
  end
23
29
 
24
- def status
25
- return nil if removed?
26
- status = @receipt['status']
27
- status.is_a?(String) ? Utils.hex_to_uint(status) : status
30
+ def gas
31
+ original && Utils.hex_to_uint(original['gas'])
28
32
  end
29
33
 
30
- def mined?
31
- !removed? && @receipt.key?('blockNumber')
34
+ def gas_price
35
+ original && Utils.hex_to_uint(original['gasPrice'])
36
+ end
37
+
38
+ def value
39
+ original && Utils.hex_to_uint(original['value'])
40
+ end
41
+
42
+ def block_number
43
+ return nil unless mined?
44
+
45
+ Utils.hex_to_uint(original['blockNumber'])
32
46
  end
33
47
 
34
48
  def confirmations
35
49
  return 0 unless mined?
36
50
 
37
- @connection.eth_block_number - block_number
51
+ (@connection.eth_block_number - block_number) + 1
52
+ end
53
+
54
+ # receipt attributes
55
+
56
+ def receipt
57
+ return nil unless mined?
58
+
59
+ @receipt ||= @connection.eth_get_transaction_receipt(@tx_hash)
60
+ end
61
+
62
+ def status
63
+ return nil if receipt.nil?
64
+
65
+ receipt['status'].is_a?(String) ? Utils.hex_to_uint(receipt['status']) : receipt['status']
66
+ end
67
+
68
+ def succeeded?
69
+ status == 1
70
+ end
71
+
72
+ def failed?
73
+ status == 0
38
74
  end
39
75
 
40
76
  def gas_used
41
- Utils.hex_to_uint @receipt['gasUsed']
77
+ receipt && Utils.hex_to_uint(receipt['gasUsed'])
42
78
  end
43
79
 
44
- def block_number
45
- Utils.hex_to_uint @receipt['blockNumber']
80
+ def logs
81
+ receipt && (receipt['logs'] || [])
82
+ end
83
+
84
+ def events
85
+ receipt && ::Etherlite::EventProvider.parse_raw_logs(@connection, logs)
46
86
  end
47
87
 
48
88
  def contract_address
49
- @receipt['contractAddress']
89
+ receipt && receipt['contractAddress']
50
90
  end
51
91
 
52
92
  def wait_for_block(timeout: 120)
@@ -1,3 +1,3 @@
1
1
  module Etherlite
2
- VERSION = "0.2.2"
2
+ VERSION = "0.3.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: etherlite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ignacio Baixas
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-02-19 00:00:00.000000000 Z
11
+ date: 2020-08-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: digest-sha3
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '1.12'
75
+ version: 2.1.4
76
76
  type: :development
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: '1.12'
82
+ version: 2.1.4
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rake
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -142,14 +142,14 @@ dependencies:
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: 3.0.1
145
+ version: 3.7.5
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: 3.0.1
152
+ version: 3.7.5
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: pry
155
155
  requirement: !ruby/object:Gem::Requirement
@@ -208,6 +208,7 @@ files:
208
208
  - lib/etherlite/contract/function.rb
209
209
  - lib/etherlite/contract/function_input.rb
210
210
  - lib/etherlite/errors.rb
211
+ - lib/etherlite/event_provider.rb
211
212
  - lib/etherlite/nonce_manager.rb
212
213
  - lib/etherlite/railtie.rb
213
214
  - lib/etherlite/railties/configuration_extensions.rb
@@ -247,8 +248,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
247
248
  - !ruby/object:Gem::Version
248
249
  version: '0'
249
250
  requirements: []
250
- rubyforge_project:
251
- rubygems_version: 2.6.4
251
+ rubygems_version: 3.0.3
252
252
  signing_key:
253
253
  specification_version: 4
254
254
  summary: Ethereum integration for ruby on rails