eth 0.5.6 → 0.5.8

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.
data/lib/eth/client.rb CHANGED
@@ -28,24 +28,31 @@ module Eth
28
28
  # The connected network's client coinbase.
29
29
  attr_accessor :default_account
30
30
 
31
- # The default transaction max priority fee per gas in Wei.
31
+ # The default transaction max priority fee per gas in Wei, defaults to {Tx::DEFAULT_PRIORITY_FEE}.
32
32
  attr_accessor :max_priority_fee_per_gas
33
33
 
34
- # The default transaction max fee per gas in Wei.
34
+ # The default transaction max fee per gas in Wei, defaults to {Tx::DEFAULT_GAS_PRICE}.
35
35
  attr_accessor :max_fee_per_gas
36
36
 
37
- # The default gas limit for the transaction.
37
+ # The default gas limit for the transaction, defaults to {Tx::DEFAULT_GAS_LIMIT}.
38
38
  attr_accessor :gas_limit
39
39
 
40
40
  # Creates a new RPC-Client, either by providing an HTTP/S host or
41
- # an IPC path.
41
+ # an IPC path. Supports basic authentication with username and password.
42
+ #
43
+ # **Note**, this sets the folling gas defaults: {Tx::DEFAULT_PRIORITY_FEE},
44
+ # {Tx::DEFAULT_GAS_PRICE}, and {Tx::DEFAULT_GAS_LIMIT}. Use
45
+ # {#max_priority_fee_per_gas}, {#max_fee_per_gas}, and {#gas_limit} to set
46
+ # custom values prior to submitting transactions.
42
47
  #
43
48
  # @param host [String] either an HTTP/S host or an IPC path.
44
49
  # @return [Eth::Client::Ipc] an IPC client.
50
+ # @return [Eth::Client::HttpAuth] an HTTP client with basic authentication.
45
51
  # @return [Eth::Client::Http] an HTTP client.
46
52
  # @raise [ArgumentError] in case it cannot determine the client type.
47
53
  def self.create(host)
48
54
  return Client::Ipc.new host if host.end_with? ".ipc"
55
+ return Client::HttpAuth.new host if Regexp.new(":.*@.*:", Regexp::IGNORECASE).match host
49
56
  return Client::Http.new host if host.start_with? "http"
50
57
  raise ArgumentError, "Unable to detect client type!"
51
58
  end
@@ -54,13 +61,16 @@ module Eth
54
61
  # use {Client.create} intead.
55
62
  def initialize(_)
56
63
  @id = 0
57
- @max_priority_fee_per_gas = 0
64
+ @max_priority_fee_per_gas = Tx::DEFAULT_PRIORITY_FEE
58
65
  @max_fee_per_gas = Tx::DEFAULT_GAS_PRICE
59
66
  @gas_limit = Tx::DEFAULT_GAS_LIMIT
60
67
  end
61
68
 
62
69
  # Gets the default account (coinbase) of the connected client.
63
70
  #
71
+ # **Note**, that many remote providers (e.g., Infura) do not provide
72
+ # any accounts.
73
+ #
64
74
  # @return [Eth::Address] the coinbase account address.
65
75
  def default_account
66
76
  @default_account ||= Address.new eth_coinbase["result"]
@@ -90,35 +100,41 @@ module Eth
90
100
  end
91
101
 
92
102
  # Simply transfer Ether to an account and waits for it to be mined.
93
- # Uses `eth_coinbase` and external signer if no sender key is
103
+ # Uses `eth_coinbase` and external signer if no sender key is
94
104
  # provided.
95
105
  #
96
- # @param destination [Eth::Address] the destination address.
97
- # @param amount [Integer] the transfer amount in Wei.
98
- # @param sender_key [Eth::Key] the sender private key.
99
- # @param legacy [Boolean] enables legacy transactions (pre-EIP-1559).
100
- # @return [String] the transaction hash.
101
- def transfer_and_wait(destination, amount, sender_key = nil, legacy = false)
102
- wait_for_tx(transfer(destination, amount, sender_key, legacy))
106
+ # See {#transfer} for params and overloads.
107
+ #
108
+ # @return [String] the transaction hash once it is mined.
109
+ def transfer_and_wait(destination, amount, **kwargs)
110
+ wait_for_tx(transfer(destination, amount, **kwargs))
103
111
  end
104
112
 
105
113
  # Simply transfer Ether to an account without any call data or
106
114
  # access lists attached. Uses `eth_coinbase` and external signer
107
115
  # if no sender key is provided.
108
116
  #
109
- # @param destination [Eth::Address] the destination address.
110
- # @param amount [Integer] the transfer amount in Wei.
111
- # @param sender_key [Eth::Key] the sender private key.
112
- # @param legacy [Boolean] enables legacy transactions (pre-EIP-1559).
113
- # @return [String] the transaction hash.
114
- def transfer(destination, amount, sender_key = nil, legacy = false)
117
+ # **Note**, that many remote providers (e.g., Infura) do not provide
118
+ # any accounts. Provide a `sender_key` if you experience issues.
119
+ #
120
+ # @overload transfer(destination, amount)
121
+ # @param destination [Eth::Address] the destination address.
122
+ # @param amount [Integer] the transfer amount in Wei.
123
+ # @overload transfer(destination, amount, **kwargs)
124
+ # @param destination [Eth::Address] the destination address.
125
+ # @param amount [Integer] the transfer amount in Wei.
126
+ # @param **sender_key [Eth::Key] the sender private key.
127
+ # @param **legacy [Boolean] enables legacy transactions (pre-EIP-1559).
128
+ # @param **nonce [Integer] optional specific nonce for transaction.
129
+ # @return [String] the local transaction hash.
130
+ def transfer(destination, amount, **kwargs)
115
131
  params = {
116
132
  value: amount,
117
133
  to: destination,
118
134
  gas_limit: gas_limit,
119
135
  chain_id: chain_id,
120
136
  }
121
- if legacy
137
+ if kwargs[:legacy]
122
138
  params.merge!({
123
139
  gas_price: max_fee_per_gas,
124
140
  })
@@ -128,22 +144,22 @@ module Eth
128
144
  max_gas_fee: max_fee_per_gas,
129
145
  })
130
146
  end
131
- unless sender_key.nil?
147
+ unless kwargs[:sender_key].nil?
132
148
 
133
149
  # use the provided key as sender and signer
134
150
  params.merge!({
135
- from: sender_key.address,
136
- nonce: get_nonce(sender_key.address),
151
+ from: kwargs[:sender_key].address,
152
+ nonce: kwargs[:nonce] || get_nonce(kwargs[:sender_key].address),
137
153
  })
138
154
  tx = Eth::Tx.new(params)
139
- tx.sign sender_key
155
+ tx.sign kwargs[:sender_key]
140
156
  return eth_send_raw_transaction(tx.hex)["result"]
141
157
  else
142
158
 
143
159
  # use the default account as sender and external signer
144
160
  params.merge!({
145
161
  from: default_account,
146
- nonce: get_nonce(default_account),
162
+ nonce: kwargs[:nonce] || get_nonce(default_account),
147
163
  })
148
164
  return eth_send_transaction(params)["result"]
149
165
  end
@@ -152,15 +168,9 @@ module Eth
152
168
  # Deploys a contract and waits for it to be mined. Uses
153
169
  # `eth_coinbase` or external signer if no sender key is provided.
154
170
  #
155
- # @overload deploy(contract)
156
- # @param contract [Eth::Contract] contracts to deploy.
157
- # @overload deploy(contract, *args, **kwargs)
158
- # @param contract [Eth::Contract] contracts to deploy.
159
- # *args Optional variable constructor parameter list
160
- # **sender_key [Eth::Key] the sender private key.
161
- # **legacy [Boolean] enables legacy transactions (pre-EIP-1559).
162
- # **gas_limit [Integer] optional gas limit override for deploying the contract.
163
- # @return [String] the contract address.
171
+ # See {#deploy} for params and overloads.
172
+ #
173
+ # @return [String] the contract address once it's mined.
164
174
  def deploy_and_wait(contract, *args, **kwargs)
165
175
  hash = wait_for_tx(deploy(contract, *args, **kwargs))
166
176
  addr = eth_get_transaction_receipt(hash)["result"]["contractAddress"]
@@ -170,14 +180,21 @@ module Eth
170
180
  # Deploys a contract. Uses `eth_coinbase` or external signer
171
181
  # if no sender key is provided.
172
182
  #
183
+ # **Note**, that many remote providers (e.g., Infura) do not provide
184
+ # any accounts. Provide a `sender_key` if you experience issues.
185
+ #
173
186
  # @overload deploy(contract)
174
187
  # @param contract [Eth::Contract] contracts to deploy.
188
+ # @overload deploy(contract, *args)
189
+ # @param contract [Eth::Contract] the contracts to deploy.
190
+ # @param *args (optional) variable constructor parameter list.
175
191
  # @overload deploy(contract, *args, **kwargs)
176
- # @param contract [Eth::Contract] contracts to deploy.
177
- # *args Optional variable constructor parameter list
178
- # **sender_key [Eth::Key] the sender private key.
179
- # **legacy [Boolean] enables legacy transactions (pre-EIP-1559).
180
- # **gas_limit [Integer] optional gas limit override for deploying the contract.
192
+ # @param contract [Eth::Contract] the contracts to deploy.
193
+ # @param *args (optional) variable constructor parameter list.
194
+ # @param **sender_key [Eth::Key] the sender private key.
195
+ # @param **legacy [Boolean] enables legacy transactions (pre-EIP-1559).
196
+ # @param **gas_limit [Integer] optional gas limit override for deploying the contract.
197
+ # @param **nonce [Integer] optional specific nonce for transaction.
181
198
  # @return [String] the transaction hash.
182
199
  # @raise [ArgumentError] in case the contract does not have any source.
183
200
  def deploy(contract, *args, **kwargs)
@@ -212,7 +229,7 @@ module Eth
212
229
  # Uses the provided key as sender and signer
213
230
  params.merge!({
214
231
  from: kwargs[:sender_key].address,
215
- nonce: get_nonce(kwargs[:sender_key].address),
232
+ nonce: kwargs[:nonce] || get_nonce(kwargs[:sender_key].address),
216
233
  })
217
234
  tx = Eth::Tx.new(params)
218
235
  tx.sign kwargs[:sender_key]
@@ -221,7 +238,7 @@ module Eth
221
238
  # Uses the default account as sender and external signer
222
239
  params.merge!({
223
240
  from: default_account,
224
- nonce: get_nonce(default_account),
241
+ nonce: kwargs[:nonce] || get_nonce(default_account),
225
242
  })
226
243
  return eth_send_transaction(params)["result"]
227
244
  end
@@ -230,24 +247,24 @@ module Eth
230
247
  # Calls a contract function without executing it
231
248
  # (non-transactional contract read).
232
249
  #
233
- # @overload call(contract, function_name)
234
- # @param contract [Eth::Contract] subject contract to call.
235
- # @param function_name [String] method name to be called.
236
- # @overload call(contract, function_name, value)
237
- # @param contract [Eth::Contract] subject contract to call.
238
- # @param function_name [String] method name to be called.
239
- # @param value [Integer|String] function arguments.
240
- # @overload call(contract, function_name, value, sender_key, legacy, gas_limit)
241
- # @param contract [Eth::Contract] subject contract to call.
242
- # @param function_name [String] method name to be called.
243
- # @param value [Integer|String] function arguments.
244
- # @param sender_key [Eth::Key] the sender private key.
245
- # @param legacy [Boolean] enables legacy transactions (pre-EIP-1559).
246
- # @param gas_limit [Integer] optional gas limit override for deploying the contract.
250
+ # @overload call(contract, function)
251
+ # @param contract [Eth::Contract] the subject contract to call.
252
+ # @param function [String] method name to be called.
253
+ # @overload call(contract, function, *args)
254
+ # @param contract [Eth::Contract] the subject contract to call.
255
+ # @param function [String] method name to be called.
256
+ # @param *args optional function arguments.
257
+ # @overload call(contract, function, *args, **kwargs)
258
+ # @param contract [Eth::Contract] the subject contract to call.
259
+ # @param function [String] method name to be called.
260
+ # @param *args optional function arguments.
261
+ # @param **sender_key [Eth::Key] the sender private key.
262
+ # @param **legacy [Boolean] enables legacy transactions (pre-EIP-1559).
263
+ # @param **gas_limit [Integer] optional gas limit override for deploying the contract.
247
264
  # @return [Object] returns the result of the call.
248
- def call(contract, function_name, *args, **kwargs)
249
- func = contract.functions.select { |func| func.name == function_name }[0]
250
- raise ArgumentError, "function_name does not exist!" if func.nil?
265
+ def call(contract, function, *args, **kwargs)
266
+ func = contract.functions.select { |func| func.name == function }[0]
267
+ raise ArgumentError, "this function does not exist!" if func.nil?
251
268
  output = call_raw(contract, func, *args, **kwargs)
252
269
  if output&.length == 1
253
270
  return output[0]
@@ -259,31 +276,36 @@ module Eth
259
276
  # Executes a contract function with a transaction (transactional
260
277
  # contract read/write).
261
278
  #
262
- # @overload transact(contract, function_name)
263
- # @param contract [Eth::Contract] subject contract to call.
264
- # @param function_name [String] method name to be called.
265
- # @overload transact(contract, function_name, value)
266
- # @param contract [Eth::Contract] subject contract to call.
267
- # @param function_name [String] method name to be called.
268
- # @param value [Integer|String] function arguments.
269
- # @overload transact(contract, function_name, value, sender_key, legacy, address, gas_limit)
270
- # @param contract [Eth::Contract] subject contract to call.
271
- # @param function_name [String] method name to be called.
272
- # @param value [Integer|String] function arguments.
273
- # @param sender_key [Eth::Key] the sender private key.
274
- # @param legacy [Boolean] enables legacy transactions (pre-EIP-1559).
275
- # @param address [String] contract address.
276
- # @param gas_limit [Integer] optional gas limit override for deploying the contract.
277
- # @return [Object] returns the result of the call.
278
- def transact(contract, function_name, *args, **kwargs)
279
+ # **Note**, that many remote providers (e.g., Infura) do not provide
280
+ # any accounts. Provide a `sender_key` if you experience issues.
281
+ #
282
+ # @overload transact(contract, function)
283
+ # @param contract [Eth::Contract] the subject contract to write to.
284
+ # @param function [String] method name to be executed.
285
+ # @overload transact(contract, function, *args)
286
+ # @param contract [Eth::Contract] the subject contract to write to.
287
+ # @param function [String] method name to be executed.
288
+ # @param *args optional function arguments.
289
+ # @overload transact(contract, function, *args, **kwargs)
290
+ # @param contract [Eth::Contract] the subject contract to write to.
291
+ # @param function_name [String] method name to be executed.
292
+ # @param *args optional function arguments.
293
+ # @param **sender_key [Eth::Key] the sender private key.
294
+ # @param **legacy [Boolean] enables legacy transactions (pre-EIP-1559).
295
+ # @param **address [Eth::Address] contract address.
296
+ # @param **gas_limit [Integer] optional gas limit override for deploying the contract.
297
+ # @param **nonce [Integer] optional specific nonce for transaction.
298
+ # @param **tx_value [Integer] optional transaction value field filling.
299
+ # @return [Object] returns the result of the transaction.
300
+ def transact(contract, function, *args, **kwargs)
279
301
  gas_limit = if kwargs[:gas_limit]
280
302
  kwargs[:gas_limit]
281
303
  else
282
304
  Tx.estimate_intrinsic_gas(contract.bin) + Tx::CREATE_GAS
283
305
  end
284
- fun = contract.functions.select { |func| func.name == function_name }[0]
306
+ fun = contract.functions.select { |func| func.name == function }[0]
285
307
  params = {
286
- value: 0,
308
+ value: kwargs[:tx_value] || 0,
287
309
  gas_limit: gas_limit,
288
310
  chain_id: chain_id,
289
311
  to: kwargs[:address] || contract.address,
@@ -303,7 +325,7 @@ module Eth
303
325
  # use the provided key as sender and signer
304
326
  params.merge!({
305
327
  from: kwargs[:sender_key].address,
306
- nonce: get_nonce(kwargs[:sender_key].address),
328
+ nonce: kwargs[:nonce] || get_nonce(kwargs[:sender_key].address),
307
329
  })
308
330
  tx = Eth::Tx.new(params)
309
331
  tx.sign kwargs[:sender_key]
@@ -312,7 +334,7 @@ module Eth
312
334
  # use the default account as sender and external signer
313
335
  params.merge!({
314
336
  from: default_account,
315
- nonce: get_nonce(default_account),
337
+ nonce: kwargs[:nonce] || get_nonce(default_account),
316
338
  })
317
339
  return eth_send_transaction(params)["result"]
318
340
  end
@@ -321,23 +343,11 @@ module Eth
321
343
  # Executes a contract function with a transaction and waits for it
322
344
  # to be mined (transactional contract read/write).
323
345
  #
324
- # @overload transact_and_wait(contract, function_name)
325
- # @param contract [Eth::Contract] subject contract to call.
326
- # @param function_name [String] method name to be called.
327
- # @overload transact_and_wait(contract, function_name, value)
328
- # @param contract [Eth::Contract] subject contract to call.
329
- # @param function_name [String] method name to be called.
330
- # @param value [Integer|String] function arguments.
331
- # @overload transact_and_wait(contract, function_name, value, sender_key, legacy, address)
332
- # @param contract [Eth::Contract] subject contract to call.
333
- # @param function_name [String] method name to be called.
334
- # @param value [Integer|String] function arguments.
335
- # @param sender_key [Eth::Key] the sender private key.
336
- # @param legacy [Boolean] enables legacy transactions (pre-EIP-1559).
337
- # @param address [String] contract address.
338
- # @return [Object] returns the result of the call.
339
- def transact_and_wait(contract, function_name, *args, **kwargs)
340
- wait_for_tx(transact(contract, function_name, *args, **kwargs))
346
+ # See {#transact} for params and overloads.
347
+ #
348
+ # @return [Object] returns the result of the transaction.
349
+ def transact_and_wait(contract, function, *args, **kwargs)
350
+ wait_for_tx(transact(contract, function, *args, **kwargs))
341
351
  end
342
352
 
343
353
  # Provides an interface to call `isValidSignature` as per EIP-1271 on a given
@@ -393,7 +403,7 @@ module Eth
393
403
  end
394
404
 
395
405
  # Metafunction to provide all known RPC commands defined in
396
- # Eth::Api as snake_case methods to the Eth::Client classes.
406
+ # {Eth::Api} as snake_case methods to the {Eth::Client} classes.
397
407
  Api::COMMANDS.each do |cmd|
398
408
  method_name = cmd.gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase
399
409
  define_method method_name do |*args|
@@ -404,39 +414,14 @@ module Eth
404
414
  private
405
415
 
406
416
  # Non-transactional function call called from call().
417
+ # @see https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_call
407
418
  def call_raw(contract, func, *args, **kwargs)
408
- gas_limit = if kwargs[:gas_limit]
409
- kwargs[:gas_limit]
410
- else
411
- Tx.estimate_intrinsic_gas(contract.bin) + Tx::CREATE_GAS
412
- end
413
419
  params = {
414
- gas_limit: gas_limit,
415
- chain_id: chain_id,
416
420
  data: call_payload(func, args),
417
- }
418
- if kwargs[:address] || contract.address
419
- params.merge!({ to: kwargs[:address] || contract.address })
420
- end
421
- if kwargs[:legacy]
422
- params.merge!({
423
- gas_price: max_fee_per_gas,
424
- })
425
- else
426
- params.merge!({
427
- priority_fee: max_priority_fee_per_gas,
428
- max_gas_fee: max_fee_per_gas,
429
- })
430
- end
431
- unless kwargs[:sender_key].nil?
432
- # Uses the provided key as sender and signer
433
- params.merge!({
434
- from: kwargs[:sender_key].address,
435
- nonce: get_nonce(kwargs[:sender_key].address),
436
- })
437
- tx = Eth::Tx.new(params)
438
- tx.sign kwargs[:sender_key]
439
- end
421
+ to: kwargs[:address] || contract.address,
422
+ from: kwargs[:from],
423
+ }.compact
424
+
440
425
  raw_result = eth_call(params)["result"]
441
426
  types = func.outputs.map { |i| i.type }
442
427
  return nil if raw_result == "0x"
@@ -447,7 +432,7 @@ module Eth
447
432
  def call_payload(fun, args)
448
433
  types = fun.inputs.map { |i| i.type }
449
434
  encoded_str = Util.bin_to_hex(Eth::Abi.encode(types, args))
450
- "0x" + fun.signature + (encoded_str.empty? ? "0" * 64 : encoded_str)
435
+ Util.prefix_hex(fun.signature + (encoded_str.empty? ? "0" * 64 : encoded_str))
451
436
  end
452
437
 
453
438
  # Encodes constructor params
@@ -496,4 +481,5 @@ end
496
481
 
497
482
  # Load the client/* libraries
498
483
  require "eth/client/http"
484
+ require "eth/client/http_auth"
499
485
  require "eth/client/ipc"
@@ -32,7 +32,7 @@ module Eth
32
32
 
33
33
  # Returns complete types with subtypes, e.g., `uint256`.
34
34
  def type
35
- @type.base_type + @type.sub_type
35
+ @type.base_type + @type.sub_type + @type.dimensions.map { |dimension| "[#{dimension > 0 ? dimension : ""}]" }.join("")
36
36
  end
37
37
  end
38
38
  end
@@ -31,7 +31,7 @@ module Eth
31
31
 
32
32
  # Returns complete types with subtypes, e.g., `uint256`.
33
33
  def type
34
- @type.base_type + @type.sub_type
34
+ @type.base_type + @type.sub_type + @type.dimensions.map { |dimension| "[#{dimension > 0 ? dimension : ""}]" }.join("")
35
35
  end
36
36
  end
37
37
  end
@@ -0,0 +1,77 @@
1
+ # Copyright (c) 2016-2022 The Ruby-Eth Contributors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # -*- encoding : ascii-8bit -*-
16
+
17
+ # Provides the {Eth} module.
18
+ module Eth
19
+ # Provides ENS specific functionality
20
+ # ref: https://ens.domains
21
+ module Ens
22
+
23
+ # Utility class for resolving ENS names to Ethereum addresses
24
+ class Resolver
25
+
26
+ # The default address for ENS, which applies to most chains
27
+ DEFAULT_ADDRESS = "0x00000000000c2e074ec69a0dfb2997ba6c7d2e1e".freeze
28
+
29
+ # Create an instance of the ENS Resolver
30
+ #
31
+ # @param client [Eth::Client] The client instance
32
+ # @param address [String] The address of the ENS contract
33
+ def initialize(client, address = DEFAULT_ADDRESS)
34
+ @client = client
35
+ @contract = Eth::Contract.from_abi(
36
+ name: "ENS",
37
+ address: address,
38
+ abi: JSON.parse(File.read(File.join(File.dirname(__FILE__), "../../../abis/ens.json"))),
39
+ )
40
+ end
41
+
42
+ # Resolve an ENS name to an address
43
+ #
44
+ # @param ens_name [String] The ENS name, eg: fancy.eth
45
+ # @return [String] The owner address of the name, as a hex string
46
+ def resolve(ens_name)
47
+ @client.call(@contract, "owner", namehash(ens_name))
48
+ end
49
+
50
+ # Generate node for the given domain name
51
+ # See: https://docs.ens.domains/contract-api-reference/name-processing
52
+ #
53
+ # @param ens_name [String] The ENS name, eg: fancy.eth
54
+ # @return [String] The node as a hex string
55
+ def namehash(ens_name)
56
+ node = ("0" * 64)
57
+ name = normalize(ens_name)
58
+ name.split(".").reverse.each do |label|
59
+ hash = Digest::Keccak.new(256).hexdigest(label)
60
+ node = Digest::Keccak.new(256).hexdigest([node + hash].pack("H*"))
61
+ end
62
+ "0x#{node}"
63
+ end
64
+
65
+ # Normalize a string as specified by http://unicode.org/reports/tr46/
66
+ #
67
+ # @param input [String] The input string
68
+ # @return [String] The normalized output string
69
+ def normalize(input)
70
+ # TODO: This is fairly complicated, and there doesn't seem to be a ruby
71
+ # library which can handle it perfectly.
72
+ # https://www.unicode.org/reports/tr46/tr46-27.html
73
+ input.downcase
74
+ end
75
+ end
76
+ end
77
+ end
data/lib/eth/signature.rb CHANGED
@@ -70,7 +70,10 @@ module Eth
70
70
  context = Secp256k1::Context.new
71
71
  r, s, v = dissect signature
72
72
  v = v.to_i(16)
73
- raise SignatureError, "Invalid signature v byte #{v} for chain ID #{chain_id}!" if v < chain_id
73
+ if !Chain.is_ledger? v and !Chain.is_legacy? v
74
+ min_v = 2 * chain_id + 35
75
+ raise SignatureError, "Invalid signature v byte #{v} for chain ID #{chain_id}!" if v < min_v
76
+ end
74
77
  recovery_id = Chain.to_recovery_id v, chain_id
75
78
  signature_rs = Util.hex_to_bin "#{r}#{s}"
76
79
  recoverable_signature = context.recoverable_signature_from_compact signature_rs, recovery_id
@@ -188,7 +188,7 @@ module Eth
188
188
 
189
189
  # recover sender address
190
190
  v = Chain.to_v recovery_id, chain_id
191
- public_key = Signature.recover(unsigned_hash, "#{r}#{s}#{v.to_s(16)}", chain_id)
191
+ public_key = Signature.recover(unsigned_hash, "#{r.rjust(64, "0")}#{s.rjust(64, "0")}#{v.to_s(16)}", chain_id)
192
192
  address = Util.public_key_to_address(public_key).to_s
193
193
  @sender = Tx.sanitize_address address
194
194
  end
@@ -183,7 +183,7 @@ module Eth
183
183
 
184
184
  # recover sender address
185
185
  v = Chain.to_v recovery_id, chain_id
186
- public_key = Signature.recover(unsigned_hash, "#{r}#{s}#{v.to_s(16)}", chain_id)
186
+ public_key = Signature.recover(unsigned_hash, "#{r.rjust(64, "0")}#{s.rjust(64, "0")}#{v.to_s(16)}", chain_id)
187
187
  address = Util.public_key_to_address(public_key).to_s
188
188
  @sender = Tx.sanitize_address address
189
189
  end
data/lib/eth/tx/legacy.rb CHANGED
@@ -156,7 +156,7 @@ module Eth
156
156
  unless chain_id.nil?
157
157
 
158
158
  # recover sender address
159
- public_key = Signature.recover(unsigned_hash, "#{r}#{s}#{v}", chain_id)
159
+ public_key = Signature.recover(unsigned_hash, "#{r.rjust(64, "0")}#{s.rjust(64, "0")}#{v}", chain_id)
160
160
  address = Util.public_key_to_address(public_key).to_s
161
161
  @sender = Tx.sanitize_address address
162
162
  else
data/lib/eth/tx.rb CHANGED
@@ -39,8 +39,11 @@ module Eth
39
39
  # The minimum transaction gas limit required for a value transfer.
40
40
  DEFAULT_GAS_LIMIT = 21_000.freeze
41
41
 
42
- # The "default" transaction gas price of 20 GWei. Do not use.
43
- DEFAULT_GAS_PRICE = (20 * Unit::GWEI).freeze
42
+ # The "default" transaction priority fee of 1.01 GWei. Do not use.
43
+ DEFAULT_PRIORITY_FEE = (1.01 * Unit::GWEI).freeze
44
+
45
+ # The "default" transaction gas price of 42.69 GWei. Do not use.
46
+ DEFAULT_GAS_PRICE = (42.69 * Unit::GWEI).freeze
44
47
 
45
48
  # The calldata gas cost of a non-zero byte as per EIP-2028.
46
49
  COST_NON_ZERO_BYTE = 16.freeze
@@ -55,7 +58,7 @@ module Eth
55
58
  COST_ADDRESS = 2_400.freeze
56
59
 
57
60
  # The maximum transaction gas limit is bound by the block gas limit.
58
- BLOCK_GAS_LIMIT = 25_000_000.freeze
61
+ BLOCK_GAS_LIMIT = 30_000_000.freeze
59
62
 
60
63
  # The legacy transaction type is 0.
61
64
  TYPE_LEGACY = 0x00.freeze
data/lib/eth/version.rb CHANGED
@@ -16,5 +16,5 @@
16
16
  module Eth
17
17
 
18
18
  # Defines the version of the {Eth} module.
19
- VERSION = "0.5.6".freeze
19
+ VERSION = "0.5.8".freeze
20
20
  end
data/lib/eth.rb CHANGED
@@ -32,4 +32,5 @@ require "eth/solidity"
32
32
  require "eth/tx"
33
33
  require "eth/unit"
34
34
  require "eth/util"
35
+ require "eth/ens/resolver"
35
36
  require "eth/version"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eth
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.6
4
+ version: 0.5.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Ellis
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2022-07-01 00:00:00.000000000 Z
12
+ date: 2022-11-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: keccak
@@ -109,6 +109,7 @@ files:
109
109
  - LICENSE.txt
110
110
  - README.md
111
111
  - Rakefile
112
+ - abis/ens.json
112
113
  - bin/console
113
114
  - bin/setup
114
115
  - codecov.yml
@@ -122,6 +123,7 @@ files:
122
123
  - lib/eth/chain.rb
123
124
  - lib/eth/client.rb
124
125
  - lib/eth/client/http.rb
126
+ - lib/eth/client/http_auth.rb
125
127
  - lib/eth/client/ipc.rb
126
128
  - lib/eth/constant.rb
127
129
  - lib/eth/contract.rb
@@ -131,6 +133,7 @@ files:
131
133
  - lib/eth/contract/function_output.rb
132
134
  - lib/eth/contract/initializer.rb
133
135
  - lib/eth/eip712.rb
136
+ - lib/eth/ens/resolver.rb
134
137
  - lib/eth/key.rb
135
138
  - lib/eth/key/decrypter.rb
136
139
  - lib/eth/key/encrypter.rb
@@ -163,11 +166,12 @@ post_install_message:
163
166
  rdoc_options: []
164
167
  require_paths:
165
168
  - lib
169
+ - abis
166
170
  required_ruby_version: !ruby/object:Gem::Requirement
167
171
  requirements:
168
172
  - - ">="
169
173
  - !ruby/object:Gem::Version
170
- version: '2.6'
174
+ version: '2.7'
171
175
  - - "<"
172
176
  - !ruby/object:Gem::Version
173
177
  version: '4.0'
@@ -177,7 +181,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
177
181
  - !ruby/object:Gem::Version
178
182
  version: '0'
179
183
  requirements: []
180
- rubygems_version: 3.3.15
184
+ rubygems_version: 3.3.25
181
185
  signing_key:
182
186
  specification_version: 4
183
187
  summary: Ruby Ethereum library.