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 +5 -5
- data/etherlite.gemspec +2 -2
- data/lib/etherlite.rb +1 -0
- data/lib/etherlite/account/private_key.rb +5 -1
- data/lib/etherlite/api/node.rb +15 -2
- data/lib/etherlite/api/rpc.rb +4 -0
- data/lib/etherlite/commands/abi/load_contract.rb +3 -2
- data/lib/etherlite/contract/base.rb +8 -18
- data/lib/etherlite/contract/event_base.rb +8 -2
- data/lib/etherlite/event_provider.rb +29 -0
- data/lib/etherlite/nonce_manager.rb +3 -2
- data/lib/etherlite/transaction.rb +57 -17
- data/lib/etherlite/version.rb +1 -1
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fe14df0fc898d4e298d57704e8a7f2acf0cb3dcace02b94903b8f295f94e971c
|
4
|
+
data.tar.gz: 87c4bc2dca3fb92d8a1eca54080cbfa50107defe48d0007cc5e6c3910bdfaa4e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c1e16e2460b1e67948efd91921b1e03e6805c114fdba9a375c4b83695baa6d01ca80b46fc3530be5ac923c641d47190cc7fc466cdf6daef793f55cb54993be0a
|
7
|
+
data.tar.gz: 76cb54b21dd785777fcd474f0bbf85e374b9a6aad8bd64d1ddfed73f195c51a736b339045b09056be8da32c34e7d272abcf7393b4bc1bd187efe2fb2186adc57
|
data/etherlite.gemspec
CHANGED
@@ -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.
|
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.
|
32
|
+
spec.add_development_dependency "webmock", "~> 3.7.5"
|
33
33
|
spec.add_development_dependency "pry"
|
34
34
|
end
|
data/lib/etherlite.rb
CHANGED
@@ -9,7 +9,11 @@ module Etherlite
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def send_transaction(_options = {})
|
12
|
-
|
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, ''),
|
data/lib/etherlite/api/node.rb
CHANGED
@@ -12,8 +12,21 @@ module Etherlite
|
|
12
12
|
connection.eth_gas_price
|
13
13
|
end
|
14
14
|
|
15
|
-
def get_transaction(
|
16
|
-
load_transaction(
|
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)
|
data/lib/etherlite/api/rpc.rb
CHANGED
@@ -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, '
|
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
|
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.
|
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.
|
22
|
-
@
|
23
|
-
if /__[^_]+_
|
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
|
-
|
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 =
|
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
|
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
|
-
|
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)
|
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
|
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
|
-
@
|
8
|
+
@loaded = false
|
9
9
|
end
|
10
10
|
|
11
11
|
def refresh
|
12
|
-
@
|
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
|
-
|
23
|
+
original.nil?
|
18
24
|
end
|
19
25
|
|
20
|
-
def
|
21
|
-
|
26
|
+
def mined?
|
27
|
+
original.present? && !original['blockNumber'].nil?
|
22
28
|
end
|
23
29
|
|
24
|
-
def
|
25
|
-
|
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
|
31
|
-
|
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
|
77
|
+
receipt && Utils.hex_to_uint(receipt['gasUsed'])
|
42
78
|
end
|
43
79
|
|
44
|
-
def
|
45
|
-
|
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
|
-
|
89
|
+
receipt && receipt['contractAddress']
|
50
90
|
end
|
51
91
|
|
52
92
|
def wait_for_block(timeout: 120)
|
data/lib/etherlite/version.rb
CHANGED
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.
|
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:
|
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:
|
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:
|
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.
|
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.
|
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
|
-
|
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
|