eth 0.4.18 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/codeql.yml +6 -2
  3. data/.github/workflows/docs.yml +1 -1
  4. data/.github/workflows/spec.yml +52 -0
  5. data/.gitignore +24 -24
  6. data/.gitmodules +3 -3
  7. data/.yardopts +1 -0
  8. data/AUTHORS.txt +27 -0
  9. data/CHANGELOG.md +63 -13
  10. data/Gemfile +12 -4
  11. data/LICENSE.txt +202 -22
  12. data/README.md +231 -76
  13. data/bin/console +4 -4
  14. data/bin/setup +5 -4
  15. data/codecov.yml +6 -0
  16. data/eth.gemspec +23 -19
  17. data/lib/eth/abi/type.rb +178 -0
  18. data/lib/eth/abi.rb +396 -0
  19. data/lib/eth/address.rb +57 -10
  20. data/lib/eth/api.rb +223 -0
  21. data/lib/eth/chain.rb +151 -0
  22. data/lib/eth/client/http.rb +63 -0
  23. data/lib/eth/client/ipc.rb +50 -0
  24. data/lib/eth/client.rb +232 -0
  25. data/lib/eth/constant.rb +71 -0
  26. data/lib/eth/eip712.rb +184 -0
  27. data/lib/eth/key/decrypter.rb +121 -85
  28. data/lib/eth/key/encrypter.rb +180 -99
  29. data/lib/eth/key.rb +134 -45
  30. data/lib/eth/rlp/decoder.rb +114 -0
  31. data/lib/eth/rlp/encoder.rb +78 -0
  32. data/lib/eth/rlp/sedes/big_endian_int.rb +66 -0
  33. data/lib/eth/rlp/sedes/binary.rb +97 -0
  34. data/lib/eth/rlp/sedes/list.rb +84 -0
  35. data/lib/eth/rlp/sedes.rb +74 -0
  36. data/lib/eth/rlp.rb +63 -0
  37. data/lib/eth/signature.rb +163 -0
  38. data/lib/eth/solidity.rb +75 -0
  39. data/lib/eth/tx/eip1559.rb +337 -0
  40. data/lib/eth/tx/eip2930.rb +329 -0
  41. data/lib/eth/tx/legacy.rb +297 -0
  42. data/lib/eth/tx.rb +269 -146
  43. data/lib/eth/unit.rb +49 -0
  44. data/lib/eth/util.rb +235 -0
  45. data/lib/eth/version.rb +18 -1
  46. data/lib/eth.rb +34 -67
  47. metadata +47 -95
  48. data/.github/workflows/build.yml +0 -36
  49. data/lib/eth/gas.rb +0 -7
  50. data/lib/eth/open_ssl.rb +0 -395
  51. data/lib/eth/secp256k1.rb +0 -5
  52. data/lib/eth/sedes.rb +0 -39
  53. data/lib/eth/utils.rb +0 -126
data/README.md CHANGED
@@ -1,151 +1,306 @@
1
- # Eth for Ruby
2
- [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/se3000/ruby-eth/Build)](https://github.com/se3000/ruby-eth/actions)
3
- [![GitHub release (latest by date)](https://img.shields.io/github/v/release/se3000/ruby-eth)](https://github.com/se3000/ruby-eth/releases)
1
+ # Ethereum for Ruby
2
+
3
+ [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/q9f/eth.rb/Spec)](https://github.com/q9f/eth.rb/actions)
4
+ [![GitHub release (latest by date)](https://img.shields.io/github/v/release/q9f/eth.rb)](https://github.com/q9f/eth.rb/releases)
4
5
  [![Gem](https://img.shields.io/gem/v/eth)](https://rubygems.org/gems/eth)
5
6
  [![Gem](https://img.shields.io/gem/dt/eth)](https://rubygems.org/gems/eth)
6
- [![GitHub top language](https://img.shields.io/github/languages/top/se3000/ruby-eth?color=red)](https://github.com/se3000/ruby-eth/pulse)
7
- [![GitHub](https://img.shields.io/github/license/se3000/ruby-eth)](LICENSE)
8
-
9
- A simple library to build and sign Ethereum transactions. Allows separation of key and node management. Sign transactions and handle keys anywhere you can run ruby, broadcast transactions through any node.
10
-
11
- ## Installation
12
-
7
+ [![Visitors](https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2Fq9f%2Feth.rb&count_bg=%2379C83D&title_bg=%23555555&icon=rubygems.svg&icon_color=%23FF0000&title=visitors&edge_flat=false)](https://hits.seeyoufarm.com)
8
+ [![codecov](https://codecov.io/gh/q9f/eth.rb/branch/main/graph/badge.svg?token=IK7USBPBZY)](https://codecov.io/gh/q9f/eth.rb)
9
+ [![Maintainability](https://api.codeclimate.com/v1/badges/469e6f66425198ad7614/maintainability)](https://codeclimate.com/github/q9f/eth.rb/maintainability)
10
+ [![Top Language](https://img.shields.io/github/languages/top/q9f/eth.rb?color=red)](https://github.com/q9f/eth.rb/pulse)
11
+ [![Yard Doc API](https://img.shields.io/badge/documentation-API-blue)](https://q9f.github.io/eth.rb)
12
+ [![Usage Wiki](https://img.shields.io/badge/usage-WIKI-blue)](https://github.com/q9f/eth.rb/wiki)
13
+ [![Open-Source License](https://img.shields.io/github/license/q9f/eth.rb)](LICENSE)
14
+ [![Contributions Welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/q9f/eth.rb/issues)
15
+
16
+ A straightforward library to build, sign, and broadcast Ethereum transactions. It allows the separation of key and node management. Sign transactions and handle keys anywhere you can run Ruby and broadcast transactions through any local or remote node. Sign messages and recover signatures for authentication.
17
+
18
+ What you get:
19
+ - [x] Secp256k1 Key-Pairs and Encrypted Ethereum Key-Stores (JSON)
20
+ - [x] EIP-55 Checksummed Ethereum Addresses
21
+ - [x] EIP-155 Replay protection with Chain IDs (with presets)
22
+ - [x] EIP-191 Ethereum Signed Messages (with prefix and type)
23
+ - [x] EIP-712 Ethereum Signed Type Data
24
+ - [x] EIP-1559 Ethereum Type-2 Transactions (with priority fee and max gas fee)
25
+ - [x] EIP-2028 Call-data intrinsic gas cost estimates (plus access lists)
26
+ - [x] EIP-2718 Ethereum Transaction Envelopes (and types)
27
+ - [x] EIP-2930 Ethereum Type-1 Transactions (with access lists)
28
+ - [x] ABI-Encoder and Decoder (including type parser)
29
+ - [x] RLP-Encoder and Decoder (including sedes)
30
+ - [x] RPC-Client (IPC/HTTP) for Execution-Layer APIs
31
+ - [x] Solidity bindings (compile contracts from Ruby)
32
+
33
+ Soon (TM):
34
+ - [ ] Smart Contract Support
35
+ - [ ] EIP-1271 Smart-Contract Authentification
36
+ - [ ] HD-Wallets (BIP-32) and Mnemonics (BIP-39)
37
+
38
+ Contents:
39
+ - [1. Installation](#1-installation)
40
+ - [2. Usage](#2-usage)
41
+ - [2.1. Ethereum Keys and Addresses (EIP-55)](#21-ethereum-keys-and-addresses-eip-55)
42
+ - [2.2. Ethereum Signatures (EIP-191, EIP-712)](#22-ethereum-signatures-eip-191-eip-712)
43
+ - [2.3. Ethereum Chains (EIP-155)](#23-ethereum-chains-eip-155)
44
+ - [2.4. Ethereum Transactions (EIP-1559, EIP-2718, EIP-2930)](#24-ethereum-transactions-eip-1559-eip-2718-eip-2930)
45
+ - [2.5. Ethereum ABI Encoder and Decoder](#25-ethereum-abi-encoder-and-decoder)
46
+ - [2.6. Ethereum RLP Encoder and Decoder](#26-ethereum-rlp-encoder-and-decoder)
47
+ - [2.7. Ethereum RPC-Client](#27-ethereum-rpc-client)
48
+ - [2.8 Solidity Compiler Bindings](#28-solidity-compiler-bindings)
49
+ - [3. Documentation](#3-documentation)
50
+ - [4. Testing](#4-testing)
51
+ - [5. Contributing](#5-contributing)
52
+ - [6. License and Credits](#6-license-and-credits)
53
+
54
+ ## 1. Installation
13
55
  Add this line to your application's Gemfile:
14
56
 
15
57
  ```ruby
16
- gem 'eth'
58
+ gem "eth"
17
59
  ```
18
60
 
19
- And then execute:
20
-
21
- $ bundle install
22
-
23
61
  Or install it yourself as:
24
62
 
25
- $ gem install eth
26
-
27
- ## Usage
63
+ ```shell
64
+ gem install eth
65
+ ```
28
66
 
29
- ### Keys
67
+ ## 2. Usage
68
+ Check out
69
+ [![Yard Doc API](https://img.shields.io/badge/documentation-API-blue)](https://q9f.github.io/eth.rb)
70
+ and
71
+ [![Usage Wiki](https://img.shields.io/badge/usage-WIKI-blue)](https://github.com/q9f/eth.rb/wiki)
72
+ for full details.
30
73
 
31
- Create a new public/private key and get its address:
74
+ ### 2.1. Ethereum Keys and Addresses (EIP-55)
75
+ Generate a random Secp256k1 key-pair.
32
76
 
33
77
  ```ruby
34
78
  key = Eth::Key.new
35
- key.private_hex
36
- key.public_hex
37
- key.address # EIP55 checksummed address
79
+ # => #<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>>
38
80
  ```
39
81
 
40
- Import an existing key:
82
+ Create an password-encrypted Ethereum key-store.
41
83
 
42
84
  ```ruby
43
- old_key = Eth::Key.new priv: private_key
85
+ my_key = Eth::Key.new priv: "30137644b564785d01420f8043f043d74dcca64008e57c59f8ce713a0005a54b"
86
+ key_store = Eth::Key::Encrypter.perform my_key, "secret-password-1337"
87
+ # => "{\"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}"
88
+ restored_key = Eth::Key::Decrypter.perform key_store, "secret-password-1337"
89
+ # => "30137644b564785d01420f8043f043d74dcca64008e57c59f8ce713a0005a54b"
44
90
  ```
45
91
 
46
- Or decrypt an [encrypted key](https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition):
92
+ Manage Ethereum address objects adhering to EIP-55 checksum format.
47
93
 
48
94
  ```ruby
49
- decrypted_key = Eth::Key.decrypt File.read('./some/path.json'), 'p455w0rD'
95
+ address = Eth::Address.new "0xd496b23d61f88a8c7758fca7560dcfac7b3b01f9"
96
+ # => #<Eth::Address:0x00005574a6bd4fc8 @address="0xd496b23d61f88a8c7758fca7560dcfac7b3b01f9">
97
+ address.valid?
98
+ # => true
99
+ address.checksummed # EIP 55
100
+ # => "0xD496b23D61F88A8C7758fca7560dCFac7b3b01F9"
50
101
  ```
51
102
 
52
- You can also encrypt your keys for use with other ethereum libraries:
103
+ 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.
104
+
105
+ ### 2.2. Ethereum Signatures (EIP-191, EIP-712)
106
+ Manage keypairs to sign messages in EIP-191 (`personal_sign`) format or typed data in EIP-712 (`sign_typed_data`) format.
53
107
 
54
108
  ```ruby
55
- encrypted_key_info = Eth::Key.encrypt key, 'p455w0rD'
109
+ key = Eth::Key.new priv: "268be6f4a68c40f6862b7ac9aed8f701dc25a95ddb9a44d8b1f520b75f440a9a"
110
+ # => #<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>>
111
+ key.public_hex
112
+ # => "04b45200621c013a5fbab999ac33b0c836328a04afa0255ffbe6ea0f6fd97e187b02199886d942a9f50f7e279a2bc74c93b2afcbd7255489939f9b36a5eae5e281"
113
+ key.address.to_s
114
+ # => "0xD496b23D61F88A8C7758fca7560dCFac7b3b01F9"
115
+ key.personal_sign "Hello World!"
116
+ # => "ac6a59417d8688c8144f01a662384fa691636b48a071d4b7c13902bb87ca472b0bce1d7a758f39a5759ed5e937ce61f50dd1b83158371f8d0faeb9b7d81c194225"
56
117
  ```
57
118
 
58
- ### Transactions
59
-
60
- Build a transaction from scratch:
119
+ Recover and verify personal signatures respecting EIPs 155, 191, and 712.
61
120
 
62
121
  ```ruby
63
- tx = Eth::Tx.new({
64
- data: hex_data,
65
- gas_limit: 21_000,
66
- gas_price: 3_141_592,
67
- nonce: 1,
68
- to: key2.address,
69
- value: 1_000_000_000_000,
70
- })
122
+ address = Eth::Address.new "0xd496b23d61f88a8c7758fca7560dcfac7b3b01f9"
123
+ # => #<Eth::Address:0x00005574a6bd4fc8 @address="0xd496b23d61f88a8c7758fca7560dcfac7b3b01f9">
124
+ signature = "ac6a59417d8688c8144f01a662384fa691636b48a071d4b7c13902bb87ca472b0bce1d7a758f39a5759ed5e937ce61f50dd1b83158371f8d0faeb9b7d81c19422d"
125
+ # => "ac6a59417d8688c8144f01a662384fa691636b48a071d4b7c13902bb87ca472b0bce1d7a758f39a5759ed5e937ce61f50dd1b83158371f8d0faeb9b7d81c19422d"
126
+ recovered_key = Eth::Signature.personal_recover "Hello World!", signature, Eth::Chain::GOERLI
127
+ # => "04b45200621c013a5fbab999ac33b0c836328a04afa0255ffbe6ea0f6fd97e187b02199886d942a9f50f7e279a2bc74c93b2afcbd7255489939f9b36a5eae5e281"
128
+ Eth::Util.public_key_to_address(recovered_key).to_s
129
+ # => "0xD496b23D61F88A8C7758fca7560dCFac7b3b01F9"
130
+ Eth::Signature.verify "Hello World!", signature, address, Eth::Chain::GOERLI
131
+ # => true
71
132
  ```
72
133
 
73
- Or decode an encoded raw transaction:
134
+ See `/spec` or [Documentation](https://q9f.github.io/eth.rb/) for signing typed data as per EIP-712.
135
+
136
+ ### 2.3. Ethereum Chains (EIP-155)
137
+ Manage Ethereum chain IDs for EIP-155 replay protection.
74
138
 
75
139
  ```ruby
76
- tx = Eth::Tx.decode hex
140
+ chain_id = Eth::Chain::OPTIMISM
141
+ # => 10
142
+ v = Eth::Chain.to_v 0, Eth::Chain::OPTIMISM
143
+ # => 55
144
+ recovery_id = Eth::Chain.to_recovery_id v, Eth::Chain::OPTIMISM
145
+ # => 0
146
+ chain_id = Eth::Chain.to_chain_id v
147
+ # => 10
77
148
  ```
78
149
 
79
- Then sign the transaction:
150
+ ### 2.4. Ethereum Transactions (EIP-1559, EIP-2718, EIP-2930)
151
+ Create an EIP-1559-conform transaction:
80
152
 
81
153
  ```ruby
82
- tx.sign key
154
+ payload = {
155
+ chain_id: Eth::Chain::GOERLI,
156
+ nonce: 5,
157
+ priority_fee: 3 * Eth::Unit::GWEI,
158
+ max_gas_fee: 69 * Eth::Unit::GWEI,
159
+ gas_limit: 230_420,
160
+ to: "0xCaA29806044A08E533963b2e573C1230A2cd9a2d",
161
+ value: 0.069423 * Eth::Unit::ETHER,
162
+ }
163
+ # => {:chain_id=>5, :nonce=>5, :priority_fee=>0.3e10, :max_gas_fee=>0.69e11, :gas_limit=>230420, :to=>"0xCaA29806044A08E533963b2e573C1230A2cd9a2d", :value=>0.69423e17}
164
+ tx = Eth::Tx.new payload
165
+ # => #<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>
166
+ my_key = Eth::Key.new priv: "30137644b564785d01420f8043f043d74dcca64008e57c59f8ce713a0005a54b"
167
+ # => #<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>>
168
+ tx.sign my_key
169
+ # => "cba302c0ebf8d0205a78ae97f560419b407e32e2426f416abc95a9bfc9dac09c"
170
+ tx.hex
171
+ # => "02f873050584b2d05e00851010b872008303841494caa29806044a08e533963b2e573c1230a2cd9a2d87f6a3d9c63df00080c080a03aa187d10b138d3e0155729adb961cd89e10f988ba2d19d6869770b9e5a23d10a04d40864600136ae214916043c7d63b849c98db757e95c86983a036982816e1af"
83
172
  ```
84
173
 
85
- Get the raw transaction with `tx.hex`, and broadcast it through any Ethereum node. Or, just get the TXID with `tx.hash`.
174
+ 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.
86
175
 
87
- ### Utils
88
-
89
- Validate an [EIP55](https://github.com/ethereum/EIPs/issues/55) checksummed address:
176
+ ### 2.5. Ethereum ABI Encoder and Decoder
177
+ Encode and decode Ethereum application binary interface data (ABI).
90
178
 
91
179
  ```ruby
92
- Eth::Utils.valid_address? address
180
+ Eth::Util.bin_to_hex Eth::Abi.encode(["string", "address"], ["Hello, Bob!", "0xd496b23d61f88a8c7758fca7560dcfac7b3b01f9"])
181
+ # => "0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000d496b23d61f88a8c7758fca7560dcfac7b3b01f9000000000000000000000000000000000000000000000000000000000000000b48656c6c6f2c20426f6221000000000000000000000000000000000000000000"
182
+ Eth::Abi.decode(["string", "address"], "0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000d496b23d61f88a8c7758fca7560dcfac7b3b01f9000000000000000000000000000000000000000000000000000000000000000b48656c6c6f2c20426f6221000000000000000000000000000000000000000000")
183
+ # => ["Hello, Bob!", "0xd496b23d61f88a8c7758fca7560dcfac7b3b01f9"]
93
184
  ```
94
185
 
95
- Or add a checksum to an existing address:
186
+ ### 2.6. Ethereum RLP Encoder and Decoder
187
+ Serialize and deserialize Ethereum recursive-length prefix data (RLP).
96
188
 
97
189
  ```ruby
98
- Eth::Utils.format_address "0x4bc787699093f11316e819b5692be04a712c4e69" # => "0x4bc787699093f11316e819B5692be04A712C4E69"
190
+ Eth::Util.bin_to_hex Eth::Rlp.encode ["Hello, Bob!", "0xd496b23d61f88a8c7758fca7560dcfac7b3b01f9"]
191
+ # => "f78b48656c6c6f2c20426f6221aa307864343936623233643631663838613863373735386663613735363064636661633762336230316639"
192
+ Eth::Rlp.decode "f78b48656c6c6f2c20426f6221aa307864343936623233643631663838613863373735386663613735363064636661633762336230316639"
193
+ # => ["Hello, Bob!", "0xd496b23d61f88a8c7758fca7560dcfac7b3b01f9"]
99
194
  ```
100
195
 
101
- ### Personal Signatures
196
+ Or ;-)
197
+
198
+ ```ruby
199
+ Eth::Rlp.decode "c7c0c1c0c3c0c1c0"
200
+ # => [[], [[]], [[], [[]]]]
201
+ ```
102
202
 
103
- You can recover public keys and generate web3/metamask-compatible signatures:
203
+ ### 2.7. Ethereum RPC-Client
204
+ Create an IPC- or HTTP-RPC-API client to seamlessly query the chain state, e.g., Infura over HTTPS with access token:
104
205
 
105
206
  ```ruby
106
- # Generate signature
107
- key.personal_sign('hello world')
207
+ infura = Eth::Client.create "https://mainnet.infura.io/v3/#{access_token}"
208
+ # => #<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>>
209
+ deposit_contract = Eth::Address.new "0x00000000219ab540356cBB839Cbe05303d7705Fa"
210
+ # => #<Eth::Address:0x000055d43f381738 @address="0x00000000219ab540356cBB839Cbe05303d7705Fa">
211
+ infura.get_balance deposit_contract
212
+ # => 9087314000069000000000069
213
+ ```
214
+
215
+ Or set up a local development environment with `geth --dev`:
108
216
 
109
- # Recover signature
110
- message = 'test'
111
- signature = '0x3eb24bd327df8c2b614c3f652ec86efe13aa721daf203820241c44861a26d37f2bffc6e03e68fc4c3d8d967054c9cb230ed34339b12ef89d512b42ae5bf8c2ae1c'
112
- Eth::Key.personal_recover(message, signature) # => 043e5b33f0080491e21f9f5f7566de59a08faabf53edbc3c32aaacc438552b25fdde531f8d1053ced090e9879cbf2b0d1c054e4b25941dab9254d2070f39418afc
217
+ ```ruby
218
+ cli = Eth::Client.create "/tmp/geth.ipc"
219
+ # => #<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">
220
+ cli.eth_coinbase
221
+ # => {"jsonrpc"=>"2.0", "id"=>1, "result"=>"0x6868074fb21c48dfad0c448fbabd99383a6598e4"}
222
+ tx = cli.transfer_and_wait(Eth::Key.new.address, 1337 * Eth::Unit::ETHER)
223
+ # => "0x141c6dff40df34fe4fce5a65588d2161dab3e0e977fb8049ff7d79bc901034f7"
224
+ cli.eth_get_transaction_by_hash tx
225
+ # => {"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"}}
226
+ cli.get_balance "0x311c61e5dc6123ad016bb7fd687d283c327bcd5f"
227
+ # => 1337000000000000000000
228
+ cli.get_nonce cli.eth_coinbase["result"]
229
+ # => 1
113
230
  ```
114
231
 
115
- ### Configure
232
+ Check out `Eth::Api` for a list of supported RPC-APIs or consult the [Documentation](https://q9f.github.io/eth.rb/) for more details.
116
233
 
117
- In order to prevent replay attacks, you must specify which Ethereum chain your transactions are created for. See [EIP 155](https://github.com/ethereum/EIPs/issues/155) for more detail.
234
+ ### 2.8 Solidity Compiler Bindings
235
+ Link a system-level Solidity compiler (`solc`) to your Ruby library and compile contracts.
118
236
 
119
237
  ```ruby
120
- Eth.configure do |config|
121
- config.chain_id = 1 # nil by default, meaning valid on any chain
122
- end
238
+ solc = Eth::Solidity.new
239
+ # => #<Eth::Solidity:0x000055f05040c6d0 @compiler="/usr/bin/solc">
240
+ contract = solc.compile "spec/fixtures/contracts/greeter.sol"
241
+ # => {"Greeter"=>
242
+ # {"abi"=>
243
+ # [{"inputs"=>[{"internalType"=>"string", "name"=>"message", "type"=>"string"}], "stateMutability"=>"nonpayable", "type"=>"constructor"},
244
+ # {"inputs"=>[], "name"=>"greet", "outputs"=>[{"internalType"=>"string", "name"=>"", "type"=>"string"}], "stateMutability"=>"view", "type"=>"function"},
245
+ # {"inputs"=>[], "name"=>"kill", "outputs"=>[], "stateMutability"=>"nonpayable", "type"=>"function"}],
246
+ # "bin"=>
247
+ # "6080604052348015...6c634300080c0033"},
248
+ # "Mortal"=>
249
+ # {"abi"=>[{"inputs"=>[], "stateMutability"=>"nonpayable", "type"=>"constructor"}, {"inputs"=>[], "name"=>"kill", "outputs"=>[], "stateMutability"=>"nonpayable", "type"=>"function"}],
250
+ # "bin"=>
251
+ # "6080604052348015...6c634300080c0033"}}
123
252
  ```
124
253
 
125
- ## Contributing
254
+ 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.
126
255
 
127
- Bug reports and pull requests are welcome on GitHub at https://github.com/se3000/ruby-eth. Tests are encouraged.
256
+ ## 3. Documentation
257
+ The documentation can be found at: https://q9f.github.io/eth.rb
128
258
 
129
- ### Tests
259
+ For any specific version, docs can be generated by `yard`:
130
260
 
131
- First install the [Ethereum common tests](https://github.com/ethereum/tests):
261
+ ```shell
262
+ gem install bundler rdoc yard
263
+ git checkout v0.5.0
264
+ yard doc
265
+ ```
266
+
267
+ The goal is to have 100% API documentation available.
268
+
269
+ ## 4. Testing
270
+ The test suite expects working local HTTP and IPC endpoints with a prefunded developer account, e.g.:
132
271
 
133
272
  ```shell
134
- git submodule update --init
273
+ geth --dev --http --ipcpath /tmp/geth.ipc &
135
274
  ```
136
275
 
137
- Then run the associated tests:
276
+ To run tests, simply use `rspec`. Note, that the Ethereum test fixtures are also required.
138
277
 
139
278
  ```shell
279
+ git submodule update --init --recursive
280
+ bundle install
140
281
  rspec
141
282
  ```
142
283
 
143
- ## License
284
+ The goal is to have 100% specification coverage for all code inside this gem.
285
+
286
+ ## 5. Contributing
287
+ Pull requests are welcome! To contribute, please consider the following:
288
+ * Code should be fully documented. Run `yard doc` and make sure it does not yield any warnings or undocumented sets.
289
+ * 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%.
290
+ * 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.
291
+ * Submit pull requests, questions, or issues to Github: https://github.com/q9f/eth.rb
292
+
293
+ ## 6. License and Credits
294
+ The `eth` gem is licensed under the conditions of [Apache 2.0](./LICENSE.txt). Please see [AUTHORS](./AUTHORS.txt) for contributors and copyright notices.
295
+
296
+ This gem is a complete rewrite of the old `eth` gem by Steve Ellis.
297
+ * https://github.com/se3000/ruby-eth/ (MIT)
144
298
 
145
- The gem is available as open-source software under the terms of the [MIT License](http://opensource.org/licenses/MIT).
299
+ 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.
300
+ * https://github.com/EthWorks/ethereum.rb (MIT)
146
301
 
147
- ## TODO
302
+ This gem also includes a revised version of the ABI gem by Jan Xie and Zhang Yaning.
303
+ * https://github.com/cryptape/ruby-ethereum-abi (MIT)
148
304
 
149
- * Better test suite.
150
- * Expose API for HD keys.
151
- * Support signing with [libsecp256k1](https://github.com/bitcoin-core/secp256k1).
305
+ It also contains a condensed version of the RLP gem by Jan Xie and Zhang Yaning.
306
+ * https://github.com/cryptape/ruby-rlp (MIT)
data/bin/console CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "eth"
3
+ # use the local version of the code instead of a globally installed gem
4
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
5
5
 
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
6
+ require "eth"
7
+ include Eth
8
8
 
9
9
  require "pry"
10
10
  Pry.start
data/bin/setup CHANGED
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
2
 
6
3
  bundle install
4
+ git submodule update --init --recursive
5
+ rufo .
6
+ yard doc
7
+ rspec
7
8
 
8
- # Do any other automated setup that you need to do here
9
+ echo "Tests fail? Run \`geth --dev --http --ipcpath /tmp/geth.ipc\` in background and try again."
data/codecov.yml ADDED
@@ -0,0 +1,6 @@
1
+ coverage:
2
+ status:
3
+ project:
4
+ default:
5
+ target: 99%
6
+ threshold: 1%
data/eth.gemspec CHANGED
@@ -12,16 +12,17 @@ Gem::Specification.new do |spec|
12
12
  spec.authors = ["Steve Ellis", "Afri Schoedon"]
13
13
  spec.email = ["email@steveell.is", "ruby@q9f.cc"]
14
14
 
15
- spec.summary = %q{Simple API to sign Ethereum transactions.}
16
- spec.description = %q{Library to build, parse, and sign Ethereum transactions.}
17
- spec.homepage = "https://github.com/se3000/ruby-eth"
18
- spec.license = "MIT"
15
+ spec.summary = %q{Ruby Ethereum library.}
16
+ spec.description = %q{Library to handle Ethereum accounts, messages, and transactions.}
17
+ spec.homepage = "https://github.com/q9f/eth.rb"
18
+ spec.license = "Apache-2.0"
19
19
 
20
20
  spec.metadata = {
21
- "homepage_uri" => "https://github.com/se3000/ruby-eth",
22
- "source_code_uri" => "https://github.com/se3000/ruby-eth",
23
- "github_repo" => "https://github.com/se3000/ruby-eth",
24
- "bug_tracker_uri" => "https://github.com/se3000/ruby-eth/issues",
21
+ "bug_tracker_uri" => "https://github.com/q9f/eth.rb/issues",
22
+ "changelog_uri" => "https://github.com/q9f/eth.rb/blob/main/CHANGELOG.md",
23
+ "documentation_uri" => "https://q9f.github.io/eth.rb/",
24
+ "github_repo" => "https://github.com/q9f/eth.rb",
25
+ "source_code_uri" => "https://github.com/q9f/eth.rb",
25
26
  }.freeze
26
27
 
27
28
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
@@ -30,18 +31,21 @@ Gem::Specification.new do |spec|
30
31
  spec.require_paths = ["lib"]
31
32
  spec.test_files = spec.files.grep %r{^(test|spec|features)/}
32
33
 
33
- spec.add_dependency "keccak", "~> 1.3"
34
- spec.add_dependency "ffi", "~> 1.15"
35
- spec.add_dependency "money-tree", "~> 0.11"
36
- spec.add_dependency "openssl", "~> 3.0"
37
- spec.add_dependency "rlp", "~> 0.7"
38
- spec.add_dependency "scrypt", "~> 3.0"
39
-
40
34
  spec.platform = Gem::Platform::RUBY
41
35
  spec.required_ruby_version = ">= 2.6", "< 4.0"
42
36
 
43
- spec.add_development_dependency "bundler", "~> 2.2"
44
- spec.add_development_dependency "pry", "~> 0.14"
45
- spec.add_development_dependency "rake", "~> 13.0"
46
- spec.add_development_dependency "rspec", "~> 3.10"
37
+ # keccak for hashing everything in ethereum
38
+ spec.add_dependency "keccak", "~> 1.3"
39
+
40
+ # konstructor gem for overloading constructors
41
+ spec.add_dependency "konstructor", "~> 1.0"
42
+
43
+ # rbsecp256k1 for key-pairs and signatures
44
+ spec.add_dependency "rbsecp256k1", "~> 5.1"
45
+
46
+ # openssl for encrypted key derivation
47
+ spec.add_dependency "openssl", "~> 2.2"
48
+
49
+ # scrypt for encrypted key derivation
50
+ spec.add_dependency "scrypt", "~> 3.0"
47
51
  end