eth 0.5.6 → 0.5.7

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
2
  SHA256:
3
- metadata.gz: aabc7ea4a3cd8e94e91e5e9d3bfb0600960079c72e9f99de61d721cae0a73feb
4
- data.tar.gz: 04e28c96e36958ca58cd49e1e6182a17bf5bc56cab28bd0052f8881899250294
3
+ metadata.gz: 86b3022f82e96aed2d1aad682ad106f3f5efe9488e03ed048e0c5862d30c3284
4
+ data.tar.gz: 40cb5224db9e074360586aca07f6421edc47668fa0f5d81728fa7574f0c2a978
5
5
  SHA512:
6
- metadata.gz: 9e7413915597355913492ea5dc22167507ab4d75b3de8783b8c87fb0849e036316f33264053fd166ada749a08215d599197eb4b94d8c954c898aec80bb91f3d7
7
- data.tar.gz: c8b0a8c288ffe282edbda04d73dff58baa66e9f50dba1998c2450b775ed27201b988048dcfd3b902ac81d19b6dfe9e73d60d86b0c300df7e0cddc301b14ec13c
6
+ metadata.gz: cf5872ec79f0c708a5c05060514b9179279db310b1c0c0682679cd90bcd0998f9ef1a7f8787c298380a252462c5ea33fdc3d44c0bdb5e3c57991515514077b85
7
+ data.tar.gz: 4a7adde0050a724270f5779a2fe4fca596202a930ee7e1af1e4493878a21e7102ee75a2d5ce91ac455b016c9c396d6771396e5c890f5dcef7ea220b0eadd2d58
@@ -20,7 +20,7 @@ jobs:
20
20
  gem install yard
21
21
  yard doc
22
22
  - name: Deploy GH Pages
23
- uses: JamesIves/github-pages-deploy-action@v4.3.3
23
+ uses: JamesIves/github-pages-deploy-action@v4.4.0
24
24
  with:
25
25
  branch: gh-pages
26
26
  folder: doc/
data/CHANGELOG.md CHANGED
@@ -1,6 +1,36 @@
1
1
  # Change Log
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## [0.5.6]
5
+ ### Added
6
+ - Eth/client: Add gas limit override option for contract deployments ([#128](https://github.com/q9f/eth.rb/pull/128))
7
+ - Eth/abi: support dynamic array encoding ([#122](https://github.com/q9f/eth.rb/pull/122))
8
+
9
+ ### Changed
10
+ - Eth/client: Include contract constructor args when estimating intrinsic gas ([#111](https://github.com/q9f/eth.rb/pull/111))
11
+ - Eth/abi: allow parsing numerics from string inputs ([#112](https://github.com/q9f/eth.rb/pull/112))
12
+ - Eth/signature: fix prefix_message for multibyte characters ([#120](https://github.com/q9f/eth.rb/pull/120))
13
+ - Eth/abi: raise error if numeric comes as string ([#114](https://github.com/q9f/eth.rb/pull/114))
14
+ - Gem: bump version to 0.5.6 ([#130](https://github.com/q9f/eth.rb/pull/130))
15
+
16
+ ## [0.5.5]
17
+ ### Added
18
+ - Eth/contract: Add missing def_delegator for constructor_inputs ([#96](https://github.com/q9f/eth.rb/pull/96))
19
+ - Eth/client: Enable passing in constructor params to deploy ([#106](https://github.com/q9f/eth.rb/pull/106))
20
+ - Eth/chain: add matic/mumbai ([#107](https://github.com/q9f/eth.rb/pull/107))
21
+
22
+ ### Changed
23
+ - Gem: bump version to 0.5.5 ([#89](https://github.com/q9f/eth.rb/pull/89))
24
+ - Docs: update changelog for 0.5.4 ([#90](https://github.com/q9f/eth.rb/pull/90))
25
+ - Ci: add weekly dependency checks ([#91](https://github.com/q9f/eth.rb/pull/91))
26
+ - Build(deps): bump github/codeql-action from 1 to 2 ([#92](https://github.com/q9f/eth.rb/pull/92))
27
+ - Build(deps): bump actions/checkout from 2 to 3 ([#93](https://github.com/q9f/eth.rb/pull/93))
28
+ - Build(deps): bump JamesIves/github-pages-deploy-action from 4.1.7 to 4.3.3 ([#94](https://github.com/q9f/eth.rb/pull/94))
29
+ - Eth/abi: fix handling of hex values for byte strings ([#100](https://github.com/q9f/eth.rb/pull/100))
30
+ - Eth/abi: add a testcase for handling hex and bin strings ([#101](https://github.com/q9f/eth.rb/pull/101))
31
+ - Eth/abi: Fix Eth::Abi::DecodingError in call method ([#105](https://github.com/q9f/eth.rb/pull/105))
32
+ - Eth: some docs and cleanups ([#108](https://github.com/q9f/eth.rb/pull/108))
33
+
4
34
  ## [0.5.4]
5
35
  ### Added
6
36
  - Eth/client: method for eip-1271 ([#80](https://github.com/q9f/eth.rb/pull/80))
data/README.md CHANGED
@@ -1,3 +1,9 @@
1
+ <!--
2
+ # @markup markdown
3
+ # @title Ethereum for Ruby
4
+ # @author Afri Schoedon
5
+ -->
6
+
1
7
  # Ethereum for Ruby
2
8
 
3
9
  [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/q9f/eth.rb/Spec)](https://github.com/q9f/eth.rb/actions)
@@ -30,26 +36,9 @@ What you get:
30
36
  - [x] RLP-Encoder and Decoder (including sedes)
31
37
  - [x] RPC-Client (IPC/HTTP) for Execution-Layer APIs
32
38
  - [x] Solidity bindings (compile contracts from Ruby)
33
- - [x] Full smart-contract support (deploy, transact, and call)
34
-
35
- Contents:
36
- - [1. Installation](#1-installation)
37
- - [2. Usage](#2-usage)
38
- - [2.1. Ethereum Keys and Addresses (EIP-55)](#21-ethereum-keys-and-addresses-eip-55)
39
- - [2.2. Ethereum Signatures (EIP-191, EIP-712)](#22-ethereum-signatures-eip-191-eip-712)
40
- - [2.3. Ethereum Chains (EIP-155)](#23-ethereum-chains-eip-155)
41
- - [2.4. Ethereum Transactions (EIP-1559, EIP-2718, EIP-2930)](#24-ethereum-transactions-eip-1559-eip-2718-eip-2930)
42
- - [2.5. Ethereum ABI Encoder and Decoder](#25-ethereum-abi-encoder-and-decoder)
43
- - [2.6. Ethereum RLP Encoder and Decoder](#26-ethereum-rlp-encoder-and-decoder)
44
- - [2.7. Ethereum RPC-Client](#27-ethereum-rpc-client)
45
- - [2.8. Solidity Compiler Bindings](#28-solidity-compiler-bindings)
46
- - [2.9. Interact with Smart Contract](#29-interact-with-smart-contract)
47
- - [3. Documentation](#3-documentation)
48
- - [4. Testing](#4-testing)
49
- - [5. Contributing](#5-contributing)
50
- - [6. License and Credits](#6-license-and-credits)
39
+ - [x] ~~Full~~ Some smart-contract support (deploy, transact, and call)
51
40
 
52
- ## 1. Installation
41
+ ## Installation
53
42
  Add this line to your application's Gemfile:
54
43
 
55
44
  ```ruby
@@ -62,252 +51,27 @@ Or install it yourself as:
62
51
  gem install eth
63
52
  ```
64
53
 
65
- ## 2. Usage
66
- Check out
67
- [![Yard Doc API](https://img.shields.io/badge/documentation-API-blue)](https://q9f.github.io/eth.rb)
68
- and
54
+ ## Usage
55
+ Check out the
56
+ [![Yard API Docs](https://img.shields.io/badge/documentation-API-blue)](https://q9f.github.io/eth.rb)
57
+ and the
69
58
  [![Usage Wiki](https://img.shields.io/badge/usage-WIKI-blue)](https://github.com/q9f/eth.rb/wiki)
70
- for full details.
71
-
72
- ### 2.1. Ethereum Keys and Addresses (EIP-55)
73
- Generate a random Secp256k1 key-pair.
74
-
75
- ```ruby
76
- key = Eth::Key.new
77
- # => #<Eth::Key:0x00005574a6ba80b8 @private_key=#<Secp256k1::PrivateKey:0x00005574a6b9a0a8 @data=")&\x86P\xB5\x16\xD9]\xFA;\x1F\xF6\xD9\xCF\xE3Vj/\xE2\x81\xC0\x9D\xE9\x05o!q\x82G\x9A\x10Q">, @public_key=#<Secp256k1::PublicKey:0x00005574a6b9bf98>>
78
- ```
79
-
80
- Create an password-encrypted Ethereum key-store.
81
-
82
- ```ruby
83
- my_key = Eth::Key.new priv: "30137644b564785d01420f8043f043d74dcca64008e57c59f8ce713a0005a54b"
84
- key_store = Eth::Key::Encrypter.perform my_key, "secret-password-1337"
85
- # => "{\"crypto\":{\"cipher\":\"aes-128-ctr\",\"cipherparams\":{\"iv\":\"7e5c0fe1e27f4ea61b0f4427dd63555f\"},\"ciphertext\":\"6353653bba494cdae6bcd510febc980cdc6f7b23cfbdf950d7a909a69625c8fd\",\"kdf\":\"pbkdf2\",\"kdfparams\":{\"c\":262144,\"dklen\":32,\"prf\":\"hmac-sha256\",\"salt\":\"cce96286f3c32267fc91f756365307fe6a4c83b6b2a73c69535f721fa407736c\"},\"mac\":\"3361ffd2b158a1d7bca5a5fd86a251ba3e9d80b602c867a2e0f47023a0e17a57\"},\"id\":\"642ee9fc-72e4-4d0a-902f-247c0b59bfda\",\"version\":3}"
86
- restored_key = Eth::Key::Decrypter.perform key_store, "secret-password-1337"
87
- # => "30137644b564785d01420f8043f043d74dcca64008e57c59f8ce713a0005a54b"
88
- ```
89
-
90
- Manage Ethereum address objects adhering to EIP-55 checksum format.
91
-
92
- ```ruby
93
- address = Eth::Address.new "0xd496b23d61f88a8c7758fca7560dcfac7b3b01f9"
94
- # => #<Eth::Address:0x00005574a6bd4fc8 @address="0xd496b23d61f88a8c7758fca7560dcfac7b3b01f9">
95
- address.valid?
96
- # => true
97
- address.checksummed # EIP 55
98
- # => "0xD496b23D61F88A8C7758fca7560dCFac7b3b01F9"
99
- ```
100
-
101
- See `/spec` or [Documentation](https://q9f.github.io/eth.rb/) for more details about key-pairs, encrypting/decrypting key-stores with a secret, and checksummed addresses.
102
-
103
- ### 2.2. Ethereum Signatures (EIP-191, EIP-712)
104
- Manage keypairs to sign messages in EIP-191 (`personal_sign`) format or typed data in EIP-712 (`sign_typed_data`) format.
105
-
106
- ```ruby
107
- key = Eth::Key.new priv: "268be6f4a68c40f6862b7ac9aed8f701dc25a95ddb9a44d8b1f520b75f440a9a"
108
- # => #<Eth::Key:0x00005574a699adc0 @private_key=#<Secp256k1::PrivateKey:0x00005574a6998200 @data="&\x8B\xE6\xF4\xA6\x8C@\xF6\x86+z\xC9\xAE\xD8\xF7\x01\xDC%\xA9]\xDB\x9AD\xD8\xB1\xF5 \xB7_D\n\x9A">, @public_key=#<Secp256k1::PublicKey:0x00005574a6998160>>
109
- key.public_hex
110
- # => "04b45200621c013a5fbab999ac33b0c836328a04afa0255ffbe6ea0f6fd97e187b02199886d942a9f50f7e279a2bc74c93b2afcbd7255489939f9b36a5eae5e281"
111
- key.address.to_s
112
- # => "0xD496b23D61F88A8C7758fca7560dCFac7b3b01F9"
113
- key.personal_sign "Hello World!"
114
- # => "ac6a59417d8688c8144f01a662384fa691636b48a071d4b7c13902bb87ca472b0bce1d7a758f39a5759ed5e937ce61f50dd1b83158371f8d0faeb9b7d81c194225"
115
- ```
116
-
117
- Recover and verify personal signatures respecting EIPs 155, 191, and 712.
118
-
119
- ```ruby
120
- address = Eth::Address.new "0xd496b23d61f88a8c7758fca7560dcfac7b3b01f9"
121
- # => #<Eth::Address:0x00005574a6bd4fc8 @address="0xd496b23d61f88a8c7758fca7560dcfac7b3b01f9">
122
- signature = "ac6a59417d8688c8144f01a662384fa691636b48a071d4b7c13902bb87ca472b0bce1d7a758f39a5759ed5e937ce61f50dd1b83158371f8d0faeb9b7d81c19422d"
123
- # => "ac6a59417d8688c8144f01a662384fa691636b48a071d4b7c13902bb87ca472b0bce1d7a758f39a5759ed5e937ce61f50dd1b83158371f8d0faeb9b7d81c19422d"
124
- recovered_key = Eth::Signature.personal_recover "Hello World!", signature, Eth::Chain::GOERLI
125
- # => "04b45200621c013a5fbab999ac33b0c836328a04afa0255ffbe6ea0f6fd97e187b02199886d942a9f50f7e279a2bc74c93b2afcbd7255489939f9b36a5eae5e281"
126
- Eth::Util.public_key_to_address(recovered_key).to_s
127
- # => "0xD496b23D61F88A8C7758fca7560dCFac7b3b01F9"
128
- Eth::Signature.verify "Hello World!", signature, address, Eth::Chain::GOERLI
129
- # => true
130
- ```
131
-
132
- See `/spec` or [Documentation](https://q9f.github.io/eth.rb/) for signing typed data as per EIP-712.
133
-
134
- ### 2.3. Ethereum Chains (EIP-155)
135
- Manage Ethereum chain IDs for EIP-155 replay protection.
136
-
137
- ```ruby
138
- chain_id = Eth::Chain::OPTIMISM
139
- # => 10
140
- v = Eth::Chain.to_v 0, Eth::Chain::OPTIMISM
141
- # => 55
142
- recovery_id = Eth::Chain.to_recovery_id v, Eth::Chain::OPTIMISM
143
- # => 0
144
- chain_id = Eth::Chain.to_chain_id v
145
- # => 10
146
- ```
147
-
148
- ### 2.4. Ethereum Transactions (EIP-1559, EIP-2718, EIP-2930)
149
- Create an EIP-1559-conform transaction:
150
-
151
- ```ruby
152
- payload = {
153
- chain_id: Eth::Chain::GOERLI,
154
- nonce: 5,
155
- priority_fee: 3 * Eth::Unit::GWEI,
156
- max_gas_fee: 69 * Eth::Unit::GWEI,
157
- gas_limit: 230_420,
158
- to: "0xCaA29806044A08E533963b2e573C1230A2cd9a2d",
159
- value: 0.069423 * Eth::Unit::ETHER,
160
- }
161
- # => {:chain_id=>5, :nonce=>5, :priority_fee=>0.3e10, :max_gas_fee=>0.69e11, :gas_limit=>230420, :to=>"0xCaA29806044A08E533963b2e573C1230A2cd9a2d", :value=>0.69423e17}
162
- tx = Eth::Tx.new payload
163
- # => #<Eth::Tx::Eip1559:0x0000557e35fc5a68 @access_list=[], @amount=69423000000000000, @chain_id=5, @destination="CaA29806044A08E533963b2e573C1230A2cd9a2d", @gas_limit=230420, @max_fee_per_gas=69000000000, @max_priority_fee_per_gas=3000000000, @payload="", @sender="", @signature_r=0, @signature_s=0, @signature_y_parity=nil, @signer_nonce=5, @type=2>
164
- my_key = Eth::Key.new priv: "30137644b564785d01420f8043f043d74dcca64008e57c59f8ce713a0005a54b"
165
- # => #<Eth::Key:0x0000557e36243178 @private_key=#<Secp256k1::PrivateKey:0x0000557e36242d40 @data="0\x13vD\xB5dx]\x01B\x0F\x80C\xF0C\xD7M\xCC\xA6@\b\xE5|Y\xF8\xCEq:\x00\x05\xA5K">, @public_key=#<Secp256k1::PublicKey:0x0000557e36242cf0>>
166
- tx.sign my_key
167
- # => "cba302c0ebf8d0205a78ae97f560419b407e32e2426f416abc95a9bfc9dac09c"
168
- tx.hex
169
- # => "02f873050584b2d05e00851010b872008303841494caa29806044a08e533963b2e573c1230a2cd9a2d87f6a3d9c63df00080c080a03aa187d10b138d3e0155729adb961cd89e10f988ba2d19d6869770b9e5a23d10a04d40864600136ae214916043c7d63b849c98db757e95c86983a036982816e1af"
170
- ```
171
-
172
- This gem also supports access lists and ABI-encoded data payloads. See `/spec` or [Documentation](https://q9f.github.io/eth.rb/) for more details about the various supported transaction types (legacy, type-1, type-2), payload parameters, and how to estimate intrinsic gas costs.
173
-
174
- ### 2.5. Ethereum ABI Encoder and Decoder
175
- Encode and decode Ethereum application binary interface data (ABI).
176
-
177
- ```ruby
178
- Eth::Util.bin_to_hex Eth::Abi.encode(["string", "address"], ["Hello, Bob!", "0xd496b23d61f88a8c7758fca7560dcfac7b3b01f9"])
179
- # => "0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000d496b23d61f88a8c7758fca7560dcfac7b3b01f9000000000000000000000000000000000000000000000000000000000000000b48656c6c6f2c20426f6221000000000000000000000000000000000000000000"
180
- Eth::Abi.decode(["string", "address"], "0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000d496b23d61f88a8c7758fca7560dcfac7b3b01f9000000000000000000000000000000000000000000000000000000000000000b48656c6c6f2c20426f6221000000000000000000000000000000000000000000")
181
- # => ["Hello, Bob!", "0xd496b23d61f88a8c7758fca7560dcfac7b3b01f9"]
182
- ```
183
-
184
- ### 2.6. Ethereum RLP Encoder and Decoder
185
- Serialize and deserialize Ethereum recursive-length prefix data (RLP).
186
-
187
- ```ruby
188
- Eth::Util.bin_to_hex Eth::Rlp.encode ["Hello, Bob!", "0xd496b23d61f88a8c7758fca7560dcfac7b3b01f9"]
189
- # => "f78b48656c6c6f2c20426f6221aa307864343936623233643631663838613863373735386663613735363064636661633762336230316639"
190
- Eth::Rlp.decode "f78b48656c6c6f2c20426f6221aa307864343936623233643631663838613863373735386663613735363064636661633762336230316639"
191
- # => ["Hello, Bob!", "0xd496b23d61f88a8c7758fca7560dcfac7b3b01f9"]
192
- ```
193
-
194
- Or ;-)
195
-
196
- ```ruby
197
- Eth::Rlp.decode "c7c0c1c0c3c0c1c0"
198
- # => [[], [[]], [[], [[]]]]
199
- ```
200
-
201
- ### 2.7. Ethereum RPC-Client
202
- Create an IPC- or HTTP-RPC-API client to seamlessly query the chain state, e.g., Infura over HTTPS with access token:
203
-
204
- ```ruby
205
- infura = Eth::Client.create "https://mainnet.infura.io/v3/#{access_token}"
206
- # => #<Eth::Client::Http:0x000055d43f3ca460 @gas_limit=21000, @host="mainnet.infura.io", @id=0, @max_fee_per_gas=0.2e11, @max_priority_fee_per_gas=0, @port=443, @ssl=true, @uri=#<URI::HTTPS https://mainnet.infura.io/v3/31b...d93>>
207
- deposit_contract = Eth::Address.new "0x00000000219ab540356cBB839Cbe05303d7705Fa"
208
- # => #<Eth::Address:0x000055d43f381738 @address="0x00000000219ab540356cBB839Cbe05303d7705Fa">
209
- infura.get_balance deposit_contract
210
- # => 9087314000069000000000069
211
- ```
212
-
213
- Or set up a local development environment with `geth --dev`:
214
-
215
- ```ruby
216
- cli = Eth::Client.create "/tmp/geth.ipc"
217
- # => #<Eth::Client::Ipc:0x000055d43f51c390 @gas_limit=21000, @id=0, @max_fee_per_gas=0.2e11, @max_priority_fee_per_gas=0, @path="/tmp/geth.ipc">
218
- cli.eth_coinbase
219
- # => {"jsonrpc"=>"2.0", "id"=>1, "result"=>"0x6868074fb21c48dfad0c448fbabd99383a6598e4"}
220
- tx = cli.transfer_and_wait(Eth::Key.new.address, 1337 * Eth::Unit::ETHER)
221
- # => "0x141c6dff40df34fe4fce5a65588d2161dab3e0e977fb8049ff7d79bc901034f7"
222
- cli.eth_get_transaction_by_hash tx
223
- # => {"jsonrpc"=>"2.0", "id"=>8, "result"=> {"blockHash"=>"0x47e742038c75851348dbda87b15fde044d54c442c371f43bea881a44d5589de3", "blockNumber"=>"0x1", "from"=>"0x6868074fb21c48dfad0c448fbabd99383a6598e4", "gas"=>"0x5208", "gasPrice"=>"0x342770c1", "maxFeePerGas"=>"0x77359401", "maxPriorityFeePerGas"=>"0x1", "hash"=>"0x141c6dff40df34fe4fce5a65588d2161dab3e0e977fb8049ff7d79bc901034f7", "input"=>"0x", "nonce"=>"0x0", "to"=>"0x311c61e5dc6123ad016bb7fd687d283c327bcd5f", "transactionIndex"=>"0x0", "value"=>"0x487a9a304539440000", "type"=>"0x2", "accessList"=>[], "chainId"=>"0x539", "v"=>"0x0", "r"=>"0xb42477d69eae65a3a3d91d9cb173e4a45a403fb0a15fa729dbfdc9d13211d7b5", "s"=>"0x4a2f98fc2b61c2d7c907520bc8c6ebe42ea6fe1cb6824f95e4b30e9464395100"}}
224
- cli.get_balance "0x311c61e5dc6123ad016bb7fd687d283c327bcd5f"
225
- # => 1337000000000000000000
226
- cli.get_nonce cli.eth_coinbase["result"]
227
- # => 1
228
- ```
229
-
230
- Check out `Eth::Api` for a list of supported RPC-APIs or consult the [Documentation](https://q9f.github.io/eth.rb/) for more details.
231
-
232
- ### 2.8. Solidity Compiler Bindings
233
- Link a system-level Solidity compiler (`solc`) to your Ruby library and compile contracts.
234
-
235
- ```ruby
236
- solc = Eth::Solidity.new
237
- # => #<Eth::Solidity:0x000055f05040c6d0 @compiler="/usr/bin/solc">
238
- contract = solc.compile "spec/fixtures/contracts/greeter.sol"
239
- # => {"Greeter"=>
240
- # {"abi"=>
241
- # [{"inputs"=>[{"internalType"=>"string", "name"=>"message", "type"=>"string"}], "stateMutability"=>"nonpayable", "type"=>"constructor"},
242
- # {"inputs"=>[], "name"=>"greet", "outputs"=>[{"internalType"=>"string", "name"=>"", "type"=>"string"}], "stateMutability"=>"view", "type"=>"function"},
243
- # {"inputs"=>[], "name"=>"kill", "outputs"=>[], "stateMutability"=>"nonpayable", "type"=>"function"}],
244
- # "bin"=>
245
- # "6080604052348015...6c634300080c0033"},
246
- # "Mortal"=>
247
- # {"abi"=>[{"inputs"=>[], "stateMutability"=>"nonpayable", "type"=>"constructor"}, {"inputs"=>[], "name"=>"kill", "outputs"=>[], "stateMutability"=>"nonpayable", "type"=>"function"}],
248
- # "bin"=>
249
- # "6080604052348015...6c634300080c0033"}}
250
- ```
251
-
252
- The `contract["Greeter"]["bin"]` could be directly used to deploy the contract as `Eth::Tx` payload. Check out the [Documentation](https://q9f.github.io/eth.rb/) for more details.
253
-
254
- ### 2.9. Interact with Smart Contract
255
-
256
- Create, compile, and deploy smart contracts.
257
-
258
- ```ruby
259
- contract = Eth::Contract.from_file(file: 'spec/fixtures/contracts/dummy.sol')
260
- # => #<Eth::Contract::Dummy:0x00007fbeee936598>
261
- cli = Eth::Client.create "/tmp/geth.ipc"
262
- # => #<Eth::Client::Ipc:0x00007fbeee946128 @gas_limit=21000, @id=0, @max_fee_per_gas=0.2e11, @max_priority_fee_per_gas=0, @path="/tmp/geth.ipc">
263
- address = cli.deploy_and_wait(contract)
264
- # => "0x2f2faa160420cee087ded96bad52475147136bd8"
265
- ```
266
-
267
- Transact with or call the deployed contract.
268
-
269
- ```ruby
270
- cli.transact_and_wait(contract, "set", 1234)
271
- # => "0x49ca4c0a5729da19a1d2574de9a444a9cd3219bdad81745b54f9cf3bb83b6a06"
272
- cli.call(contract, "get")
273
- # => 1234
274
- ```
275
-
276
- Or call an existing contract, e.g., the ENS registry:
277
-
278
- ```ruby
279
- ens_registry_abi = '[{"inputs":[{"internalType":"contract ENS","name":"_old","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"label","type":"bytes32"},{"indexed":false,"internalType":"address","name":"owner","type":"address"}],"name":"NewOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"address","name":"resolver","type":"address"}],"name":"NewResolver","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"ttl","type":"uint64"}],"name":"NewTTL","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"address","name":"owner","type":"address"}],"name":"Transfer","type":"event"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"old","outputs":[{"internalType":"contract ENS","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"recordExists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"owner","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"resolver","type":"address"},{"internalType":"uint64","name":"ttl","type":"uint64"}],"name":"setRecord","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"resolver","type":"address"}],"name":"setResolver","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"label","type":"bytes32"},{"internalType":"address","name":"owner","type":"address"}],"name":"setSubnodeOwner","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"label","type":"bytes32"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"resolver","type":"address"},{"internalType":"uint64","name":"ttl","type":"uint64"}],"name":"setSubnodeRecord","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint64","name":"ttl","type":"uint64"}],"name":"setTTL","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"ttl","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"}]'
280
- ens_registry_address = "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e"
281
- ens_registry_name = "ENSRegistryWithFallback"
282
- ens_registry = Eth::Contract.from_abi(name: ens_registry_name, address: ens_registry_address, abi: ens_registry_abi)
283
- # => #<Eth::Contract::ENSRegistryWithFallback:0x000055bece570980>
284
- ens_registry.address
285
- # => "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e"
286
- cli.call(ens_registry, "old")
287
- # => "0x112234455c3a32fd11230c42e7bccd4a84e02010"
288
- ```
289
-
290
- The gem also comes with an EIP-1271 smart-contract authentification interface.
291
-
292
- ```ruby
293
- cli.is_valid_signature contract, hash, signature
294
- # => true
295
- ```
59
+ for all the details and example snippets.
296
60
 
297
- ## 3. Documentation
61
+ ## Documentation
298
62
  The documentation can be found at: https://q9f.github.io/eth.rb
299
63
 
300
64
  For any specific version, docs can be generated by `yard`:
301
65
 
302
66
  ```shell
303
67
  gem install bundler rdoc yard
304
- git checkout v0.5.0
68
+ git checkout $VERSION
305
69
  yard doc
306
70
  ```
307
71
 
308
72
  The goal is to have 100% API documentation available.
309
73
 
310
- ## 4. Testing
74
+ ## Testing
311
75
  The test suite expects working local HTTP and IPC endpoints with a prefunded developer account, e.g.:
312
76
 
313
77
  ```shell
@@ -324,24 +88,24 @@ rspec
324
88
 
325
89
  The goal is to have 100% specification coverage for all code inside this gem.
326
90
 
327
- ## 5. Contributing
91
+ ## Contributing
328
92
  Pull requests are welcome! To contribute, please consider the following:
329
93
  * Code should be fully documented. Run `yard doc` and make sure it does not yield any warnings or undocumented sets.
330
94
  * Code should be fully covered by tests. Run `rspec` to make sure all tests pass. The CI has an integration that will assis you to identify uncovered lines of code and get coverage up to 100%.
331
95
  * Code should be formatted properly. Try to eliminate the most common issues such as trailing white-spaces or duplicate new-lines. Usage of the `rufo` gem is recommended.
332
- * Submit pull requests, questions, or issues to Github: https://github.com/q9f/eth.rb
96
+ * Submit pull requests, questions, or issues to Github: <https://github.com/q9f/eth.rb>
333
97
 
334
- ## 6. License and Credits
98
+ ## License and Credits
335
99
  The `eth` gem is licensed under the conditions of [Apache 2.0](./LICENSE.txt). Please see [AUTHORS](./AUTHORS.txt) for contributors and copyright notices.
336
100
 
337
101
  This gem is a complete rewrite of the old `eth` gem by Steve Ellis.
338
- * https://github.com/se3000/ruby-eth/ (MIT)
102
+ * <https://github.com/se3000/ruby-eth> (MIT)
339
103
 
340
104
  It is not only a rewrite of the `eth` gem but also a partial merge of the `ethereum` gem by Marek Kirejczyk and Yuta Kurotaki.
341
- * https://github.com/EthWorks/ethereum.rb (MIT)
105
+ * <https://github.com/EthWorks/ethereum.rb> (MIT)
342
106
 
343
107
  This gem also includes a revised version of the ABI gem by Jan Xie and Zhang Yaning.
344
- * https://github.com/cryptape/ruby-ethereum-abi (MIT)
108
+ * <https://github.com/cryptape/ruby-ethereum-abi> (MIT)
345
109
 
346
110
  It also contains a condensed version of the RLP gem by Jan Xie and Zhang Yaning.
347
- * https://github.com/cryptape/ruby-rlp (MIT)
111
+ * <https://github.com/cryptape/ruby-rlp> (MIT)
data/lib/eth/chain.rb CHANGED
@@ -92,6 +92,15 @@ module Eth
92
92
  # Chain ID for the geth private network preset.
93
93
  PRIVATE_GETH = 1337.freeze
94
94
 
95
+ # Indicates wether the given `v` indicates a legacy chain value
96
+ # used by ledger wallets without EIP-155 replay protection.
97
+ #
98
+ # @param v [Integer] the signature's `v` value.
99
+ # @return [Boolean] true if ledger's legacy value.
100
+ def is_ledger?(v)
101
+ [0, 1].include? v
102
+ end
103
+
95
104
  # Indicates wether the given `v` indicates a legacy chain value
96
105
  # without EIP-155 replay protection.
97
106
  #
@@ -0,0 +1,73 @@
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
+ require "net/http"
16
+
17
+ # Provides the {Eth} module.
18
+ module Eth
19
+
20
+ # Provides an HTTP/S-RPC client with basic authentication.
21
+ class Client::HttpAuth < Client
22
+
23
+ # The host of the HTTP endpoint.
24
+ attr_reader :host
25
+
26
+ # The port of the HTTP endpoint.
27
+ attr_reader :port
28
+
29
+ # The full URI of the HTTP endpoint, including path.
30
+ attr_reader :uri
31
+
32
+ # Attribute indicator for SSL.
33
+ attr_reader :ssl
34
+
35
+ # Attribute for user.
36
+ attr_reader :user
37
+
38
+ # Constructor for the HTTP Client. Should not be used; use
39
+ # {Client.create} intead.
40
+ #
41
+ # @param host [String] an URI pointing to an HTTP RPC-API.
42
+ def initialize(host)
43
+ super
44
+ uri = URI.parse(host)
45
+ raise ArgumentError, "Unable to parse the HTTP-URI!" unless ["http", "https"].include? uri.scheme
46
+ @host = uri.host
47
+ @port = uri.port
48
+ @ssl = uri.scheme == "https"
49
+ @user = uri.user
50
+ @password = uri.password
51
+ @uri = URI("#{uri.scheme}://#{uri.user}:#{uri.password}@#{@host}:#{@port}#{uri.path}")
52
+ end
53
+
54
+ # Sends an RPC request to the connected HTTP client.
55
+ #
56
+ # @param payload [Hash] the RPC request parameters.
57
+ # @return [String] a JSON-encoded response.
58
+ def send(payload)
59
+ http = Net::HTTP.new(@host, @port)
60
+ http.use_ssl = @ssl
61
+ header = { "Content-Type" => "application/json" }
62
+ request = Net::HTTP::Post.new(@uri, header)
63
+ request.body = payload
64
+ response = http.request(request)
65
+ response.body
66
+ end
67
+ end
68
+
69
+ private
70
+
71
+ # Attribute for password.
72
+ attr_reader :password
73
+ end
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,14 +100,12 @@ 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.
106
+ # See {#transfer} for params and overloads.
107
+ #
108
+ # @return [String] the transaction hash once it is mined.
101
109
  def transfer_and_wait(destination, amount, sender_key = nil, legacy = false)
102
110
  wait_for_tx(transfer(destination, amount, sender_key, legacy))
103
111
  end
@@ -106,11 +114,14 @@ module Eth
106
114
  # access lists attached. Uses `eth_coinbase` and external signer
107
115
  # if no sender key is provided.
108
116
  #
117
+ # **Note**, that many remote providers (e.g., Infura) do not provide
118
+ # any accounts. Provide a `sender_key` if you experience issues.
119
+ #
109
120
  # @param destination [Eth::Address] the destination address.
110
121
  # @param amount [Integer] the transfer amount in Wei.
111
122
  # @param sender_key [Eth::Key] the sender private key.
112
123
  # @param legacy [Boolean] enables legacy transactions (pre-EIP-1559).
113
- # @return [String] the transaction hash.
124
+ # @return [String] the local transaction hash.
114
125
  def transfer(destination, amount, sender_key = nil, legacy = false)
115
126
  params = {
116
127
  value: amount,
@@ -152,15 +163,9 @@ module Eth
152
163
  # Deploys a contract and waits for it to be mined. Uses
153
164
  # `eth_coinbase` or external signer if no sender key is provided.
154
165
  #
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.
166
+ # See {#deploy} for params and overloads.
167
+ #
168
+ # @return [String] the contract address once it's mined.
164
169
  def deploy_and_wait(contract, *args, **kwargs)
165
170
  hash = wait_for_tx(deploy(contract, *args, **kwargs))
166
171
  addr = eth_get_transaction_receipt(hash)["result"]["contractAddress"]
@@ -170,14 +175,20 @@ module Eth
170
175
  # Deploys a contract. Uses `eth_coinbase` or external signer
171
176
  # if no sender key is provided.
172
177
  #
178
+ # **Note**, that many remote providers (e.g., Infura) do not provide
179
+ # any accounts. Provide a `sender_key` if you experience issues.
180
+ #
173
181
  # @overload deploy(contract)
174
182
  # @param contract [Eth::Contract] contracts to deploy.
183
+ # @overload deploy(contract, *args)
184
+ # @param contract [Eth::Contract] the contracts to deploy.
185
+ # @param *args (optional) variable constructor parameter list.
175
186
  # @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.
187
+ # @param contract [Eth::Contract] the contracts to deploy.
188
+ # @param *args (optional) variable constructor parameter list.
189
+ # @param **sender_key [Eth::Key] the sender private key.
190
+ # @param **legacy [Boolean] enables legacy transactions (pre-EIP-1559).
191
+ # @param **gas_limit [Integer] optional gas limit override for deploying the contract.
181
192
  # @return [String] the transaction hash.
182
193
  # @raise [ArgumentError] in case the contract does not have any source.
183
194
  def deploy(contract, *args, **kwargs)
@@ -230,24 +241,24 @@ module Eth
230
241
  # Calls a contract function without executing it
231
242
  # (non-transactional contract read).
232
243
  #
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.
244
+ # @overload call(contract, function)
245
+ # @param contract [Eth::Contract] the subject contract to call.
246
+ # @param function [String] method name to be called.
247
+ # @overload call(contract, function, *args)
248
+ # @param contract [Eth::Contract] the subject contract to call.
249
+ # @param function [String] method name to be called.
250
+ # @param *args optional function arguments.
251
+ # @overload call(contract, function, *args, **kwargs)
252
+ # @param contract [Eth::Contract] the subject contract to call.
253
+ # @param function [String] method name to be called.
254
+ # @param *args optional function arguments.
255
+ # @param **sender_key [Eth::Key] the sender private key.
256
+ # @param **legacy [Boolean] enables legacy transactions (pre-EIP-1559).
257
+ # @param **gas_limit [Integer] optional gas limit override for deploying the contract.
247
258
  # @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?
259
+ def call(contract, function, *args, **kwargs)
260
+ func = contract.functions.select { |func| func.name == function }[0]
261
+ raise ArgumentError, "this function does not exist!" if func.nil?
251
262
  output = call_raw(contract, func, *args, **kwargs)
252
263
  if output&.length == 1
253
264
  return output[0]
@@ -259,29 +270,32 @@ module Eth
259
270
  # Executes a contract function with a transaction (transactional
260
271
  # contract read/write).
261
272
  #
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)
273
+ # **Note**, that many remote providers (e.g., Infura) do not provide
274
+ # any accounts. Provide a `sender_key` if you experience issues.
275
+ #
276
+ # @overload transact(contract, function)
277
+ # @param contract [Eth::Contract] the subject contract to write to.
278
+ # @param function [String] method name to be executed.
279
+ # @overload transact(contract, function, *args)
280
+ # @param contract [Eth::Contract] the subject contract to write to.
281
+ # @param function [String] method name to be executed.
282
+ # @param *args optional function arguments.
283
+ # @overload transact(contract, function, *args, **kwargs)
284
+ # @param contract [Eth::Contract] the subject contract to write to.
285
+ # @param function_name [String] method name to be executed.
286
+ # @param *args optional function arguments.
287
+ # @param **sender_key [Eth::Key] the sender private key.
288
+ # @param **legacy [Boolean] enables legacy transactions (pre-EIP-1559).
289
+ # @param **address [Eth::Address] contract address.
290
+ # @param **gas_limit [Integer] optional gas limit override for deploying the contract.
291
+ # @return [Object] returns the result of the transaction.
292
+ def transact(contract, function, *args, **kwargs)
279
293
  gas_limit = if kwargs[:gas_limit]
280
294
  kwargs[:gas_limit]
281
295
  else
282
296
  Tx.estimate_intrinsic_gas(contract.bin) + Tx::CREATE_GAS
283
297
  end
284
- fun = contract.functions.select { |func| func.name == function_name }[0]
298
+ fun = contract.functions.select { |func| func.name == function }[0]
285
299
  params = {
286
300
  value: 0,
287
301
  gas_limit: gas_limit,
@@ -321,23 +335,11 @@ module Eth
321
335
  # Executes a contract function with a transaction and waits for it
322
336
  # to be mined (transactional contract read/write).
323
337
  #
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))
338
+ # See {#transact} for params and overloads.
339
+ #
340
+ # @return [Object] returns the result of the transaction.
341
+ def transact_and_wait(contract, function, *args, **kwargs)
342
+ wait_for_tx(transact(contract, function, *args, **kwargs))
341
343
  end
342
344
 
343
345
  # Provides an interface to call `isValidSignature` as per EIP-1271 on a given
@@ -393,7 +395,7 @@ module Eth
393
395
  end
394
396
 
395
397
  # Metafunction to provide all known RPC commands defined in
396
- # Eth::Api as snake_case methods to the Eth::Client classes.
398
+ # {Eth::Api} as snake_case methods to the {Eth::Client} classes.
397
399
  Api::COMMANDS.each do |cmd|
398
400
  method_name = cmd.gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase
399
401
  define_method method_name do |*args|
@@ -447,7 +449,7 @@ module Eth
447
449
  def call_payload(fun, args)
448
450
  types = fun.inputs.map { |i| i.type }
449
451
  encoded_str = Util.bin_to_hex(Eth::Abi.encode(types, args))
450
- "0x" + fun.signature + (encoded_str.empty? ? "0" * 64 : encoded_str)
452
+ Util.prefix_hex(fun.signature + (encoded_str.empty? ? "0" * 64 : encoded_str))
451
453
  end
452
454
 
453
455
  # Encodes constructor params
@@ -496,4 +498,5 @@ end
496
498
 
497
499
  # Load the client/* libraries
498
500
  require "eth/client/http"
501
+ require "eth/client/http_auth"
499
502
  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
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.7".freeze
20
20
  end
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.7
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-10-31 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: keccak
@@ -122,6 +122,7 @@ files:
122
122
  - lib/eth/chain.rb
123
123
  - lib/eth/client.rb
124
124
  - lib/eth/client/http.rb
125
+ - lib/eth/client/http_auth.rb
125
126
  - lib/eth/client/ipc.rb
126
127
  - lib/eth/constant.rb
127
128
  - lib/eth/contract.rb
@@ -177,7 +178,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
177
178
  - !ruby/object:Gem::Version
178
179
  version: '0'
179
180
  requirements: []
180
- rubygems_version: 3.3.15
181
+ rubygems_version: 3.3.23
181
182
  signing_key:
182
183
  specification_version: 4
183
184
  summary: Ruby Ethereum library.