eth 0.5.1 → 0.5.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/spec.yml +3 -3
- data/AUTHORS.txt +10 -2
- data/CHANGELOG.md +29 -6
- data/README.md +94 -23
- data/codecov.yml +6 -0
- data/eth.gemspec +1 -1
- data/lib/eth/abi/event.rb +137 -0
- data/lib/eth/abi/type.rb +1 -1
- data/lib/eth/abi.rb +14 -2
- data/lib/eth/chain.rb +1 -1
- data/lib/eth/client/ipc.rb +3 -0
- data/lib/eth/client.rb +240 -1
- data/lib/eth/contract/event.rb +41 -0
- data/lib/eth/contract/function.rb +56 -0
- data/lib/eth/contract/function_input.rb +36 -0
- data/lib/eth/contract/function_output.rb +32 -0
- data/lib/eth/contract/initializer.rb +46 -0
- data/lib/eth/contract.rb +135 -0
- data/lib/eth/rlp/decoder.rb +7 -2
- data/lib/eth/rlp/sedes/binary.rb +2 -2
- data/lib/eth/solidity.rb +75 -0
- data/lib/eth/tx/eip1559.rb +1 -0
- data/lib/eth/tx/eip2930.rb +1 -0
- data/lib/eth/tx/legacy.rb +1 -0
- data/lib/eth/tx.rb +24 -29
- data/lib/eth/version.rb +1 -1
- data/lib/eth.rb +7 -0
- metadata +20 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: af4a4068c445fcbb0ec94375ffdf650894464bf62d69dd7a14af232452c3af3c
|
4
|
+
data.tar.gz: a962fe008b6ecb75bdc5a70c9363aa31f95d84f82359da53e7195544bbcb9db2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d909d4249f0f7a72cae28c0f4208e1aa8c8ba69779149a20ececf4a53cd6186b43062d7a9aa5921e3c3fee9f3e014df8e6dd01586c0651f714d9bca47a4953da
|
7
|
+
data.tar.gz: ad74d13143142ab3cf71cadfa79cbd1a7a9cf2628c0b5b6e279edd4385b20764b837e14b0f8f7f24d55884893a7b79b4c1323f89aca66adfa40eb6af8bd4db41
|
data/.github/workflows/spec.yml
CHANGED
@@ -19,7 +19,7 @@ jobs:
|
|
19
19
|
fail-fast: false
|
20
20
|
matrix:
|
21
21
|
os: [ubuntu-latest, macos-latest]
|
22
|
-
ruby: ['2.7', '3.
|
22
|
+
ruby: ['2.7', '3.1']
|
23
23
|
steps:
|
24
24
|
- uses: actions/checkout@v2
|
25
25
|
- uses: ruby/setup-ruby@v1
|
@@ -29,13 +29,13 @@ jobs:
|
|
29
29
|
- name: MacOs Dependencies
|
30
30
|
run: |
|
31
31
|
brew tap ethereum/ethereum
|
32
|
-
brew install --verbose pkg-config automake autogen ethereum
|
32
|
+
brew install --verbose pkg-config automake autogen ethereum solidity
|
33
33
|
if: startsWith(matrix.os, 'macOS')
|
34
34
|
- name: Ubuntu Dependencies
|
35
35
|
run: |
|
36
36
|
sudo add-apt-repository -y ppa:ethereum/ethereum
|
37
37
|
sudo apt-get update
|
38
|
-
sudo apt-get install ethereum
|
38
|
+
sudo apt-get install ethereum solc
|
39
39
|
if: startsWith(matrix.os, 'Ubuntu')
|
40
40
|
- name: Run Geth
|
41
41
|
run: |
|
data/AUTHORS.txt
CHANGED
@@ -2,6 +2,8 @@ The Ruby-Eth Contributors are:
|
|
2
2
|
* Steve Ellis @se3000
|
3
3
|
* Afri Schoedon @q9f
|
4
4
|
* John Omar @chainoperator
|
5
|
+
* Joshua Peek @josh
|
6
|
+
* Yuta Kurotaki @kurotaky
|
5
7
|
|
6
8
|
See also:
|
7
9
|
* https://github.com/q9f/eth.rb/graphs/contributors
|
@@ -10,12 +12,18 @@ The Ruby-Eth project was maintained 2016-2020 in Steve Ellis's (@se3000)
|
|
10
12
|
repository licensed under MIT conditions:
|
11
13
|
* https://github.com/se3000/ruby-eth
|
12
14
|
|
13
|
-
The latest
|
15
|
+
The latest Ruby-Eth gem is not only a rewrite of the aforementioned gem
|
16
|
+
but also a partial merge of the Ethereum.rb Ruby Ethereum library by
|
17
|
+
Marek Kirejczyk (@marekkirejczyk) and Yuta Kurotaki (@kurotaky) licensed
|
18
|
+
under MIT conditions:
|
19
|
+
* https://github.com/EthWorks/ethereum.rb
|
20
|
+
|
21
|
+
The latest version of the Ruby-Eth gem includes a revised version of the
|
14
22
|
ABI gem by Jan Xie (@janx) and Zhang Yaning (@u2) licensed under MIT
|
15
23
|
conditions:
|
16
24
|
* https://github.com/cryptape/ruby-ethereum-abi
|
17
25
|
|
18
|
-
The latest version of the Ruby-Eth gem contains a
|
26
|
+
The latest version of the Ruby-Eth gem contains a condensed version of the
|
19
27
|
RLP gem by Jan Xie (@janx) and Zhang Yaning (@u2) licensed under MIT
|
20
28
|
conditions:
|
21
29
|
* https://github.com/cryptape/ruby-rlp
|
data/CHANGELOG.md
CHANGED
@@ -1,20 +1,47 @@
|
|
1
1
|
# Change Log
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
|
4
|
+
## [0.5.3]
|
5
|
+
### Added
|
6
|
+
- Smart contract support ([#68](https://github.com/q9f/eth.rb/pull/68))
|
7
|
+
|
8
|
+
### Changed
|
9
|
+
- Eth/abi: decode event log ([#69](https://github.com/q9f/eth.rb/pull/69))
|
10
|
+
- Gem: bump version ([#70](https://github.com/q9f/eth.rb/pull/70))
|
11
|
+
- Eth/abi/event: batch log decoder ([#71](https://github.com/q9f/eth.rb/pull/71))
|
12
|
+
|
13
|
+
## [0.5.2]
|
14
|
+
### Added
|
15
|
+
- Eth/solidity: add solidity compiler bindings ([#66](https://github.com/q9f/eth.rb/pull/66))
|
16
|
+
|
17
|
+
### Changed
|
18
|
+
- Eth: remove duplicated code ([#62](https://github.com/q9f/eth.rb/pull/62))
|
19
|
+
- Ci: allow coverage to drop to 99% without failing ([#63](https://github.com/q9f/eth.rb/pull/63))
|
20
|
+
- Docs: update readme ([#64](https://github.com/q9f/eth.rb/pull/64))
|
21
|
+
- Docs: add wiki to readme ([#65](https://github.com/q9f/eth.rb/pull/65))
|
22
|
+
|
4
23
|
## [0.5.1]
|
24
|
+
### Added
|
25
|
+
- Add eth::rlp module ([#52](https://github.com/q9f/eth.rb/pull/52))
|
26
|
+
- Eth/client: implement http/ipc ([#37](https://github.com/q9f/eth.rb/pull/37))
|
27
|
+
|
5
28
|
### Changed
|
6
29
|
- Docs: update changelog ([#61](https://github.com/q9f/eth.rb/pull/61))
|
7
30
|
- Eth/chain: add sepolia chain id; docs ([#60](https://github.com/q9f/eth.rb/pull/60))
|
8
31
|
- Eth/rlp: cleanup ([#59](https://github.com/q9f/eth.rb/pull/59))
|
9
|
-
- Add eth::rlp module ([#52](https://github.com/q9f/eth.rb/pull/52))
|
10
32
|
- Eth/tx: properly serialize signatures ([#58](https://github.com/q9f/eth.rb/pull/58))
|
11
33
|
- Eth/client: fix legacy transfer ([#57](https://github.com/q9f/eth.rb/pull/57))
|
12
34
|
- Gem: relax openssl requirement ([#56](https://github.com/q9f/eth.rb/pull/56))
|
13
|
-
- Eth/client: implement http/ipc ([#37](https://github.com/q9f/eth.rb/pull/37))
|
14
35
|
- Docs: update changelog ([#53](https://github.com/q9f/eth.rb/pull/53))
|
15
36
|
- Spec: add upstream test fixtures for keystore ([#50](https://github.com/q9f/eth.rb/pull/50))
|
16
37
|
|
17
38
|
## [0.5.0]
|
39
|
+
### Added
|
40
|
+
- Eth/tx: create legacy, type-1, and type-2 transactions [#33](https://github.com/q9f/eth.rb/pull/33)
|
41
|
+
- Signature: implement eip 712 typed structured data signing [#27](https://github.com/q9f/eth.rb/pull/27)
|
42
|
+
- Lib: import ABI to eth/abi [#29](https://github.com/q9f/eth.rb/pull/29)
|
43
|
+
- Eth/chains: implement eip 155 for replay protection [#20](https://github.com/q9f/eth.rb/pull/20)
|
44
|
+
|
18
45
|
### Changed
|
19
46
|
- Docs: update readme with features [#49](https://github.com/q9f/eth.rb/pull/49)
|
20
47
|
- Eth/tx: add method to estimate intrinsic gas costs [#48](https://github.com/q9f/eth.rb/pull/48)
|
@@ -26,16 +53,12 @@ All notable changes to this project will be documented in this file.
|
|
26
53
|
- Lib: improve error handling [#39](https://github.com/q9f/eth.rb/pull/39)
|
27
54
|
- Docs: update readme for tx and keys [#40](https://github.com/q9f/eth.rb/pull/40)
|
28
55
|
- Implement encrypt/decrypt [#22](https://github.com/q9f/eth.rb/pull/22)
|
29
|
-
- Eth/tx: create legacy, type-1, and type-2 transactions [#33](https://github.com/q9f/eth.rb/pull/33)
|
30
56
|
- Gem: clean up some docs and scripts [#32](https://github.com/q9f/eth.rb/pull/32)
|
31
|
-
- Signature: implement eip 712 typed structured data signing [#27](https://github.com/q9f/eth.rb/pull/27)
|
32
|
-
- Lib: import ABI to eth/abi [#29](https://github.com/q9f/eth.rb/pull/29)
|
33
57
|
- Rename util and chain to singular [#26](https://github.com/q9f/eth.rb/pull/26)
|
34
58
|
- Docs: add some examples to readme [#25](https://github.com/q9f/eth.rb/pull/25)
|
35
59
|
- Key/signature: personal sign and verify [#24](https://github.com/q9f/eth.rb/pull/24)
|
36
60
|
- Ci: only run coverage on CI [#23](https://github.com/q9f/eth.rb/pull/23)
|
37
61
|
- Lib/signature: implement personal_recover (eip 191 [#21](https://github.com/q9f/eth.rb/pull/21)
|
38
|
-
- Eth/chains: implement eip 155 for replay protection [#20](https://github.com/q9f/eth.rb/pull/20)
|
39
62
|
- Eth/util: public_key_to_address should return an eth::address [#19](https://github.com/q9f/eth.rb/pull/19)
|
40
63
|
- Ci: add docs workflow [#18](https://github.com/q9f/eth.rb/pull/18)
|
41
64
|
- Address class implementation and tests [#13](https://github.com/q9f/eth.rb/pull/13)
|
data/README.md
CHANGED
@@ -1,16 +1,19 @@
|
|
1
|
-
#
|
1
|
+
# Ethereum for Ruby
|
2
2
|
|
3
3
|
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/q9f/eth.rb/Spec)](https://github.com/q9f/eth.rb/actions)
|
4
4
|
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/q9f/eth.rb)](https://github.com/q9f/eth.rb/releases)
|
5
5
|
[![Gem](https://img.shields.io/gem/v/eth)](https://rubygems.org/gems/eth)
|
6
6
|
[![Gem](https://img.shields.io/gem/dt/eth)](https://rubygems.org/gems/eth)
|
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)
|
7
8
|
[![codecov](https://codecov.io/gh/q9f/eth.rb/branch/main/graph/badge.svg?token=IK7USBPBZY)](https://codecov.io/gh/q9f/eth.rb)
|
8
9
|
[![Maintainability](https://api.codeclimate.com/v1/badges/469e6f66425198ad7614/maintainability)](https://codeclimate.com/github/q9f/eth.rb/maintainability)
|
9
|
-
[![
|
10
|
-
[![
|
11
|
-
[![
|
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)
|
12
15
|
|
13
|
-
A
|
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.
|
14
17
|
|
15
18
|
What you get:
|
16
19
|
- [x] Secp256k1 Key-Pairs and Encrypted Ethereum Key-Stores (JSON)
|
@@ -18,6 +21,7 @@ What you get:
|
|
18
21
|
- [x] EIP-155 Replay protection with Chain IDs (with presets)
|
19
22
|
- [x] EIP-191 Ethereum Signed Messages (with prefix and type)
|
20
23
|
- [x] EIP-712 Ethereum Signed Type Data
|
24
|
+
- [x] EIP-1271 Smart-Contract Authentification
|
21
25
|
- [x] EIP-1559 Ethereum Type-2 Transactions (with priority fee and max gas fee)
|
22
26
|
- [x] EIP-2028 Call-data intrinsic gas cost estimates (plus access lists)
|
23
27
|
- [x] EIP-2718 Ethereum Transaction Envelopes (and types)
|
@@ -25,11 +29,8 @@ What you get:
|
|
25
29
|
- [x] ABI-Encoder and Decoder (including type parser)
|
26
30
|
- [x] RLP-Encoder and Decoder (including sedes)
|
27
31
|
- [x] RPC-Client (IPC/HTTP) for Execution-Layer APIs
|
28
|
-
|
29
|
-
|
30
|
-
- [ ] Smart Contracts and Solidity Support
|
31
|
-
- [ ] EIP-1271 Smart-Contract Authentification
|
32
|
-
- [ ] HD-Wallets (BIP-32) and Mnemonics (BIP-39)
|
32
|
+
- [x] Solidity bindings (compile contracts from Ruby)
|
33
|
+
- [x] Full smart-contract support (deploy, transact, and call)
|
33
34
|
|
34
35
|
Contents:
|
35
36
|
- [1. Installation](#1-installation)
|
@@ -41,13 +42,14 @@ Contents:
|
|
41
42
|
- [2.5. Ethereum ABI Encoder and Decoder](#25-ethereum-abi-encoder-and-decoder)
|
42
43
|
- [2.6. Ethereum RLP Encoder and Decoder](#26-ethereum-rlp-encoder-and-decoder)
|
43
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)
|
44
47
|
- [3. Documentation](#3-documentation)
|
45
48
|
- [4. Testing](#4-testing)
|
46
49
|
- [5. Contributing](#5-contributing)
|
47
50
|
- [6. License and Credits](#6-license-and-credits)
|
48
51
|
|
49
52
|
## 1. Installation
|
50
|
-
|
51
53
|
Add this line to your application's Gemfile:
|
52
54
|
|
53
55
|
```ruby
|
@@ -61,9 +63,13 @@ gem install eth
|
|
61
63
|
```
|
62
64
|
|
63
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
|
69
|
+
[![Usage Wiki](https://img.shields.io/badge/usage-WIKI-blue)](https://github.com/q9f/eth.rb/wiki)
|
70
|
+
for full details.
|
64
71
|
|
65
72
|
### 2.1. Ethereum Keys and Addresses (EIP-55)
|
66
|
-
|
67
73
|
Generate a random Secp256k1 key-pair.
|
68
74
|
|
69
75
|
```ruby
|
@@ -95,7 +101,6 @@ address.checksummed # EIP 55
|
|
95
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.
|
96
102
|
|
97
103
|
### 2.2. Ethereum Signatures (EIP-191, EIP-712)
|
98
|
-
|
99
104
|
Manage keypairs to sign messages in EIP-191 (`personal_sign`) format or typed data in EIP-712 (`sign_typed_data`) format.
|
100
105
|
|
101
106
|
```ruby
|
@@ -127,7 +132,6 @@ Eth::Signature.verify "Hello World!", signature, address, Eth::Chain::GOERLI
|
|
127
132
|
See `/spec` or [Documentation](https://q9f.github.io/eth.rb/) for signing typed data as per EIP-712.
|
128
133
|
|
129
134
|
### 2.3. Ethereum Chains (EIP-155)
|
130
|
-
|
131
135
|
Manage Ethereum chain IDs for EIP-155 replay protection.
|
132
136
|
|
133
137
|
```ruby
|
@@ -142,7 +146,6 @@ chain_id = Eth::Chain.to_chain_id v
|
|
142
146
|
```
|
143
147
|
|
144
148
|
### 2.4. Ethereum Transactions (EIP-1559, EIP-2718, EIP-2930)
|
145
|
-
|
146
149
|
Create an EIP-1559-conform transaction:
|
147
150
|
|
148
151
|
```ruby
|
@@ -169,7 +172,6 @@ tx.hex
|
|
169
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.
|
170
173
|
|
171
174
|
### 2.5. Ethereum ABI Encoder and Decoder
|
172
|
-
|
173
175
|
Encode and decode Ethereum application binary interface data (ABI).
|
174
176
|
|
175
177
|
```ruby
|
@@ -180,7 +182,6 @@ Eth::Abi.decode(["string", "address"], "0000000000000000000000000000000000000000
|
|
180
182
|
```
|
181
183
|
|
182
184
|
### 2.6. Ethereum RLP Encoder and Decoder
|
183
|
-
|
184
185
|
Serialize and deserialize Ethereum recursive-length prefix data (RLP).
|
185
186
|
|
186
187
|
```ruby
|
@@ -198,7 +199,6 @@ Eth::Rlp.decode "c7c0c1c0c3c0c1c0"
|
|
198
199
|
```
|
199
200
|
|
200
201
|
### 2.7. Ethereum RPC-Client
|
201
|
-
|
202
202
|
Create an IPC- or HTTP-RPC-API client to seamlessly query the chain state, e.g., Infura over HTTPS with access token:
|
203
203
|
|
204
204
|
```ruby
|
@@ -229,8 +229,72 @@ cli.get_nonce cli.eth_coinbase["result"]
|
|
229
229
|
|
230
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
231
|
|
232
|
-
|
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
|
+
```
|
233
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
|
+
```
|
296
|
+
|
297
|
+
## 3. Documentation
|
234
298
|
The documentation can be found at: https://q9f.github.io/eth.rb
|
235
299
|
|
236
300
|
For any specific version, docs can be generated by `yard`:
|
@@ -244,8 +308,13 @@ yard doc
|
|
244
308
|
The goal is to have 100% API documentation available.
|
245
309
|
|
246
310
|
## 4. Testing
|
311
|
+
The test suite expects working local HTTP and IPC endpoints with a prefunded developer account, e.g.:
|
247
312
|
|
248
|
-
|
313
|
+
```shell
|
314
|
+
geth --dev --http --ipcpath /tmp/geth.ipc &
|
315
|
+
```
|
316
|
+
|
317
|
+
To run tests, simply use `rspec`. Note, that the Ethereum test fixtures are also required.
|
249
318
|
|
250
319
|
```shell
|
251
320
|
git submodule update --init --recursive
|
@@ -256,7 +325,6 @@ rspec
|
|
256
325
|
The goal is to have 100% specification coverage for all code inside this gem.
|
257
326
|
|
258
327
|
## 5. Contributing
|
259
|
-
|
260
328
|
Pull requests are welcome! To contribute, please consider the following:
|
261
329
|
* Code should be fully documented. Run `yard doc` and make sure it does not yield any warnings or undocumented sets.
|
262
330
|
* 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%.
|
@@ -269,8 +337,11 @@ The `eth` gem is licensed under the conditions of [Apache 2.0](./LICENSE.txt). P
|
|
269
337
|
This gem is a complete rewrite of the old `eth` gem by Steve Ellis.
|
270
338
|
* https://github.com/se3000/ruby-eth/ (MIT)
|
271
339
|
|
272
|
-
It
|
340
|
+
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)
|
342
|
+
|
343
|
+
This gem also includes a revised version of the ABI gem by Jan Xie and Zhang Yaning.
|
273
344
|
* https://github.com/cryptape/ruby-ethereum-abi (MIT)
|
274
345
|
|
275
|
-
It also contains a
|
346
|
+
It also contains a condensed version of the RLP gem by Jan Xie and Zhang Yaning.
|
276
347
|
* https://github.com/cryptape/ruby-rlp (MIT)
|
data/codecov.yml
ADDED
data/eth.gemspec
CHANGED
@@ -44,7 +44,7 @@ Gem::Specification.new do |spec|
|
|
44
44
|
spec.add_dependency "rbsecp256k1", "~> 5.1"
|
45
45
|
|
46
46
|
# openssl for encrypted key derivation
|
47
|
-
spec.add_dependency "openssl", "
|
47
|
+
spec.add_dependency "openssl", ">= 2.2", "< 4.0"
|
48
48
|
|
49
49
|
# scrypt for encrypted key derivation
|
50
50
|
spec.add_dependency "scrypt", "~> 3.0"
|
@@ -0,0 +1,137 @@
|
|
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
|
+
|
20
|
+
# Provides a Ruby implementation of the Ethereum Application Binary Interface (ABI).
|
21
|
+
module Abi
|
22
|
+
|
23
|
+
# Provides a module to decode transaction log events.
|
24
|
+
module Event
|
25
|
+
extend self
|
26
|
+
|
27
|
+
# Compute topic for ABI event interface.
|
28
|
+
#
|
29
|
+
# @param interface [Hash] ABI event interface.
|
30
|
+
# @return [String] a hex-string topic.
|
31
|
+
def compute_topic(interface)
|
32
|
+
sig = Abi.signature(interface)
|
33
|
+
Util.prefix_hex(Util.bin_to_hex(Util.keccak256(sig)))
|
34
|
+
end
|
35
|
+
|
36
|
+
# A decoded event log.
|
37
|
+
class LogDescription
|
38
|
+
# The event ABI interface used to decode the log.
|
39
|
+
attr_accessor :event_interface
|
40
|
+
|
41
|
+
# The the input argument of the event.
|
42
|
+
attr_accessor :args
|
43
|
+
|
44
|
+
# The named input argument of the event.
|
45
|
+
attr_accessor :kwargs
|
46
|
+
|
47
|
+
# The topic hash.
|
48
|
+
attr_accessor :topic
|
49
|
+
|
50
|
+
# Decodes event log argument values.
|
51
|
+
#
|
52
|
+
# @param event_interface [Hash] event ABI type.
|
53
|
+
# @param log [Hash] transaction receipt log
|
54
|
+
def initialize(event_interface, log)
|
55
|
+
@event_interface = event_interface
|
56
|
+
|
57
|
+
inputs = event_interface.fetch("inputs")
|
58
|
+
data = log.fetch("data")
|
59
|
+
topics = log.fetch("topics", [])
|
60
|
+
anonymous = event_interface.fetch("anonymous", false)
|
61
|
+
|
62
|
+
@topic = topics[0] if !anonymous
|
63
|
+
@args, @kwargs = Event.decode_log(inputs, data, topics, anonymous)
|
64
|
+
end
|
65
|
+
|
66
|
+
# The event name. (e.g. Transfer)
|
67
|
+
def name
|
68
|
+
@name ||= event_interface.fetch("name")
|
69
|
+
end
|
70
|
+
|
71
|
+
# The event signature. (e.g. Transfer(address,address,uint256))
|
72
|
+
def signature
|
73
|
+
@signature ||= Abi.signature(event_interface)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Decodes a stream of receipt logs with a set of ABI interfaces.
|
78
|
+
#
|
79
|
+
# @param interfaces [Array] event ABI types.
|
80
|
+
# @param logs [Array] transaction receipt logs
|
81
|
+
# @return [Hash] an enumerator of LogDescription objects.
|
82
|
+
def decode_logs(interfaces, logs)
|
83
|
+
Enumerator.new do |y|
|
84
|
+
topic_to_interfaces = Hash[interfaces.map { |i| [compute_topic(i), i] }]
|
85
|
+
|
86
|
+
logs.each do |log|
|
87
|
+
topic = log.fetch("topics", [])[0]
|
88
|
+
if topic && interface = topic_to_interfaces[topic]
|
89
|
+
y << [log, LogDescription.new(interface, log)]
|
90
|
+
else
|
91
|
+
y << [log, nil]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Decodes event log argument values.
|
98
|
+
#
|
99
|
+
# @param inputs [Array] event ABI types.
|
100
|
+
# @param data [String] ABI event data to be decoded.
|
101
|
+
# @param topics [Array] ABI event topics to be decoded.
|
102
|
+
# @param anonymous [Boolean] If event signature is excluded from topics.
|
103
|
+
# @return [[Array, Hash]] decoded positional arguments and decoded keyword arguments.
|
104
|
+
# @raise [DecodingError] if decoding fails for type.
|
105
|
+
def decode_log(inputs, data, topics, anonymous = false)
|
106
|
+
topic_inputs, data_inputs = inputs.partition { |i| i["indexed"] }
|
107
|
+
|
108
|
+
topic_types = topic_inputs.map { |i| i["type"] }
|
109
|
+
data_types = data_inputs.map { |i| i["type"] }
|
110
|
+
|
111
|
+
# If event is anonymous, all topics are arguments. Otherwise, the first
|
112
|
+
# topic will be the event signature.
|
113
|
+
if anonymous == false
|
114
|
+
topics = topics[1..-1]
|
115
|
+
end
|
116
|
+
|
117
|
+
decoded_topics = topics.map.with_index { |t, i| Abi.decode([topic_types[i]], t)[0] }
|
118
|
+
decoded_data = Abi.decode(data_types, data)
|
119
|
+
|
120
|
+
args = []
|
121
|
+
kwargs = {}
|
122
|
+
|
123
|
+
inputs.each_with_index do |input, index|
|
124
|
+
if input["indexed"]
|
125
|
+
value = decoded_topics[topic_inputs.index(input)]
|
126
|
+
else
|
127
|
+
value = decoded_data[data_inputs.index(input)]
|
128
|
+
end
|
129
|
+
args[index] = value
|
130
|
+
kwargs[input["name"].to_sym] = value
|
131
|
+
end
|
132
|
+
|
133
|
+
return args, kwargs
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
data/lib/eth/abi/type.rb
CHANGED
@@ -17,7 +17,7 @@
|
|
17
17
|
# Provides the {Eth} module.
|
18
18
|
module Eth
|
19
19
|
|
20
|
-
# Provides a Ruby implementation of the Ethereum
|
20
|
+
# Provides a Ruby implementation of the Ethereum Application Binary Interface (ABI).
|
21
21
|
module Abi
|
22
22
|
|
23
23
|
# Provides a class to handle and parse common ABI types.
|
data/lib/eth/abi.rb
CHANGED
@@ -16,12 +16,13 @@
|
|
16
16
|
|
17
17
|
require "konstructor"
|
18
18
|
|
19
|
+
require "eth/abi/event"
|
19
20
|
require "eth/abi/type"
|
20
21
|
|
21
22
|
# Provides the {Eth} module.
|
22
23
|
module Eth
|
23
24
|
|
24
|
-
# Provides a Ruby implementation of the Ethereum
|
25
|
+
# Provides a Ruby implementation of the Ethereum Application Binary Interface (ABI).
|
25
26
|
# ref: https://docs.soliditylang.org/en/develop/abi-spec.html
|
26
27
|
module Abi
|
27
28
|
extend self
|
@@ -43,7 +44,7 @@ module Eth
|
|
43
44
|
# @return [String] the encoded ABI data.
|
44
45
|
def encode(types, args)
|
45
46
|
|
46
|
-
#
|
47
|
+
# parse all types
|
47
48
|
parsed_types = types.map { |t| Type.parse(t) }
|
48
49
|
|
49
50
|
# prepare the "head"
|
@@ -290,6 +291,17 @@ module Eth
|
|
290
291
|
end
|
291
292
|
end
|
292
293
|
|
294
|
+
# Build event signature string from ABI interface.
|
295
|
+
#
|
296
|
+
# @param interface [Hash] ABI event interface.
|
297
|
+
# @return [String] interface signature string.
|
298
|
+
def signature(interface)
|
299
|
+
name = interface.fetch("name")
|
300
|
+
inputs = interface.fetch("inputs", [])
|
301
|
+
types = inputs.map { |i| i.fetch("type") }
|
302
|
+
"#{name}(#{types.join(",")})"
|
303
|
+
end
|
304
|
+
|
293
305
|
private
|
294
306
|
|
295
307
|
# Properly encodes unsigned integers.
|
data/lib/eth/chain.rb
CHANGED
@@ -136,7 +136,7 @@ module Eth
|
|
136
136
|
return v
|
137
137
|
end
|
138
138
|
|
139
|
-
#
|
139
|
+
# Converts a `v` value into a chain ID. This does not work for legacy signatures
|
140
140
|
# with `v < 36` that do not conform with EIP-155.
|
141
141
|
#
|
142
142
|
# @param v [Integer] the signature's `v` value.
|