etherlite 0.2.2 → 0.3.0

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
- 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