eth 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/eth/api.rb ADDED
@@ -0,0 +1,223 @@
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
+ # Provides the {Eth} module.
16
+ module Eth
17
+
18
+ # Provides the `Eth::Api` module grouping known RPC commands.
19
+ module Api
20
+
21
+ # Implements the available RPC-APIs provided by Geth version 1.10.15.
22
+ COMMANDS = [
23
+ "admin_addPeer",
24
+ "admin_addTrustedPeer",
25
+ "admin_clearHistory",
26
+ "admin_datadir",
27
+ "admin_exportChain",
28
+ "admin_getDatadir",
29
+ "admin_getNodeInfo",
30
+ "admin_getPeers",
31
+ "admin_importChain",
32
+ "admin_nodeInfo",
33
+ "admin_peers",
34
+ "admin_removePeer",
35
+ "admin_removeTrustedPeer",
36
+ "admin_sleep",
37
+ "admin_sleepBlocks",
38
+ "admin_startHTTP",
39
+ "admin_startRPC",
40
+ "admin_startWS",
41
+ "admin_stopHTTP",
42
+ "admin_stopRPC",
43
+ "admin_stopWS",
44
+ "clique_discard",
45
+ "clique_getProposals",
46
+ "clique_getSigner",
47
+ "clique_getSigners",
48
+ "clique_getSignersAtHash",
49
+ "clique_getSnapshot",
50
+ "clique_getSnapshotAtHash",
51
+ "clique_proposals",
52
+ "clique_propose",
53
+ "clique_status",
54
+ "debug_accountRange",
55
+ "debug_backtraceAt",
56
+ "debug_blockProfile",
57
+ "debug_chaindbCompact",
58
+ "debug_chaindbProperty",
59
+ "debug_cpuProfile",
60
+ "debug_dumpBlock",
61
+ "debug_freeOSMemory",
62
+ "debug_freezeClient",
63
+ "debug_gcStats",
64
+ "debug_getAccessibleState",
65
+ "debug_getBadBlocks",
66
+ "debug_getBlockRlp",
67
+ "debug_getHeaderRlp",
68
+ "debug_getModifiedAccountsByHash",
69
+ "debug_getModifiedAccountsByNumber",
70
+ "debug_goTrace",
71
+ "debug_intermediateRoots",
72
+ "debug_memStats",
73
+ "debug_mutexProfile",
74
+ "debug_preimage",
75
+ "debug_printBlock",
76
+ "debug_seedHash",
77
+ "debug_setBlockProfileRate",
78
+ "debug_setGCPercent",
79
+ "debug_setHead",
80
+ "debug_setMutexProfileFraction",
81
+ "debug_stacks",
82
+ "debug_standardTraceBadBlockToFile",
83
+ "debug_standardTraceBlockToFile",
84
+ "debug_startCPUProfile",
85
+ "debug_startGoTrace",
86
+ "debug_stopCPUProfile",
87
+ "debug_stopGoTrace",
88
+ "debug_storageRangeAt",
89
+ "debug_testSignCliqueBlock",
90
+ "debug_traceBadBlock",
91
+ "debug_traceBlock",
92
+ "debug_traceBlockByHash",
93
+ "debug_traceBlockByNumber",
94
+ "debug_traceBlockFromFile",
95
+ "debug_traceCall",
96
+ "debug_traceTransaction",
97
+ "debug_verbosity",
98
+ "debug_vmodule",
99
+ "debug_writeBlockProfile",
100
+ "debug_writeMemProfile",
101
+ "debug_writeMutexProfile",
102
+ "eth_accounts",
103
+ "eth_blockNumber",
104
+ "eth_call",
105
+ "eth_chainId",
106
+ "eth_coinbase",
107
+ "eth_compile",
108
+ "eth_contract",
109
+ "eth_createAccessList",
110
+ "eth_defaultAccount",
111
+ "eth_defaultBlock",
112
+ "eth_estimateGas",
113
+ "eth_feeHistory",
114
+ "eth_fillTransaction",
115
+ "eth_filter",
116
+ "eth_gasPrice",
117
+ "eth_getAccounts",
118
+ "eth_getBalance",
119
+ "eth_getBlock",
120
+ "eth_getBlockByHash",
121
+ "eth_getBlockByNumber",
122
+ "eth_getBlockNumber",
123
+ "eth_getBlockTransactionCount",
124
+ "eth_getBlockTransactionCountByHash",
125
+ "eth_getBlockTransactionCountByNumber",
126
+ "eth_getBlockUncleCount",
127
+ "eth_getCode",
128
+ "eth_getCoinbase",
129
+ "eth_getCompilers",
130
+ "eth_getFilterChanges",
131
+ "eth_getFilterLogs",
132
+ "eth_getGasPrice",
133
+ "eth_getHashrate",
134
+ "eth_getHeaderByHash",
135
+ "eth_getHeaderByNumber",
136
+ "eth_getLogs",
137
+ "eth_getMaxPriorityFeePerGas",
138
+ "eth_getMining",
139
+ "eth_getPendingTransactions",
140
+ "eth_getProof",
141
+ "eth_getProtocolVersion",
142
+ "eth_getRawTransaction",
143
+ "eth_getRawTransactionFromBlock",
144
+ "eth_getStorageAt",
145
+ "eth_getSyncing",
146
+ "eth_getTransaction",
147
+ "eth_getTransactionByBlockHashAndIndex",
148
+ "eth_getTransactionByBlockNumberAndIndex",
149
+ "eth_getTransactionByHash",
150
+ "eth_getTransactionCount",
151
+ "eth_getTransactionFromBlock",
152
+ "eth_getTransactionReceipt",
153
+ "eth_getUncle",
154
+ "eth_getUncleCountByBlockHash",
155
+ "eth_getUncleCountByBlockNumber",
156
+ "eth_getWork",
157
+ "eth_hashrate",
158
+ "eth_iban",
159
+ "eth_icapNamereg",
160
+ "eth_isSyncing",
161
+ "eth_maxPriorityFeePerGas",
162
+ "eth_mining",
163
+ "eth_namereg",
164
+ "eth_newBlockFilter",
165
+ "eth_newFilter",
166
+ "eth_newPendingTransactionFilter",
167
+ "eth_pendingTransactions",
168
+ "eth_protocolVersion",
169
+ "eth_resend",
170
+ "eth_sendIBANTransaction",
171
+ "eth_sendRawTransaction",
172
+ "eth_sendTransaction",
173
+ "eth_sign",
174
+ "eth_signTransaction",
175
+ "eth_submitHashrate",
176
+ "eth_submitTransaction",
177
+ "eth_submitWork",
178
+ "eth_subscribe",
179
+ "eth_syncing",
180
+ "eth_uninstallFilter",
181
+ "eth_unsubscribe",
182
+ "les_addBalance",
183
+ "les_clientInfo",
184
+ "les_getCheckpoint",
185
+ "les_getCheckpointContractAddress",
186
+ "les_latestCheckpoint",
187
+ "les_priorityClientInfo",
188
+ "les_serverInfo",
189
+ "les_setClientParams",
190
+ "les_setDefaultParams",
191
+ "miner_getHashrate",
192
+ "miner_setEtherbase",
193
+ "miner_setExtra",
194
+ "miner_setGasLimit",
195
+ "miner_setGasPrice",
196
+ "miner_start",
197
+ "miner_stop",
198
+ "personal_deriveAccount",
199
+ "personal_ecRecover",
200
+ "personal_getListAccounts",
201
+ "personal_getListWallets",
202
+ "personal_importRawKey",
203
+ "personal_initializeWallet",
204
+ "personal_listAccounts",
205
+ "personal_listWallets",
206
+ "personal_lockAccount",
207
+ "personal_newAccount",
208
+ "personal_openWallet",
209
+ "personal_sendTransaction",
210
+ "personal_sign",
211
+ "personal_signTransaction",
212
+ "personal_unlockAccount",
213
+ "personal_unpair",
214
+ "txpool_content",
215
+ "txpool_contentFrom",
216
+ "txpool_getContent",
217
+ "txpool_getInspect",
218
+ "txpool_getStatus",
219
+ "txpool_inspect",
220
+ "txpool_status",
221
+ ]
222
+ end
223
+ end
data/lib/eth/chain.rb CHANGED
@@ -12,82 +12,85 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- # Provides the `Eth` module.
15
+ # Provides the {Eth} module.
16
16
  module Eth
17
17
 
18
- # Encapsulates `Chain` IDs and utilities for EIP-155 compatibility.
19
- # ref: https://eips.ethereum.org/EIPS/eip-155
18
+ # Encapsulates {Eth::Chain} IDs and utilities for EIP-155 compatibility.
19
+ # Ref: https://eips.ethereum.org/EIPS/eip-155
20
20
  module Chain
21
21
  extend self
22
22
 
23
23
  # Provides a special replay protection error if EIP-155 is violated.
24
24
  class ReplayProtectionError < StandardError; end
25
25
 
26
- # Chain ID for Ethereum mainnet
26
+ # Chain ID for Ethereum mainnet.
27
27
  ETHEREUM = 1.freeze
28
28
 
29
- # Chain ID for Expanse mainnet
29
+ # Chain ID for Expanse mainnet.
30
30
  EXPANSE = 2.freeze
31
31
 
32
- # Chain ID for Optimistic Ethereum mainnet
32
+ # Chain ID for Optimistic Ethereum mainnet.
33
33
  OPTIMISM = 10.freeze
34
34
 
35
- # Chain ID for Ethereum Classic mainnet
35
+ # Chain ID for Ethereum Classic mainnet.
36
36
  CLASSIC = 61.freeze
37
37
 
38
- # Chain ID for POA Network mainnet
38
+ # Chain ID for POA Network mainnet.
39
39
  POA_NET = 99.freeze
40
40
 
41
- # Chain ID for xDAI mainnet
41
+ # Chain ID for Gnosis mainnet.
42
42
  XDAI = 100.freeze
43
43
 
44
- # Chain ID for Arbitrum mainnet
44
+ # Chain ID for Arbitrum mainnet.
45
45
  ARBITRUM = 42161.freeze
46
46
 
47
- # Chain ID for Morden (Ethereum) testnet
47
+ # Chain ID for Morden (Ethereum) testnet.
48
48
  MORDEN = 2.freeze
49
49
 
50
- # Chain ID for Ropsten testnet
50
+ # Chain ID for Ropsten testnet.
51
51
  ROPSTEN = 3.freeze
52
52
 
53
- # Chain ID for Rinkeby testnet
53
+ # Chain ID for Rinkeby testnet.
54
54
  RINKEBY = 4.freeze
55
55
 
56
- # Chain ID for Goerli testnet
56
+ # Chain ID for Goerli testnet.
57
57
  GOERLI = 5.freeze
58
58
 
59
- # Chain ID for Kotti testnet
59
+ # Chain ID for Kotti testnet.
60
60
  KOTTI = 6.freeze
61
61
 
62
- # Chain ID for Kovan testnet
62
+ # Chain ID for Kovan testnet.
63
63
  KOVAN = 42.freeze
64
64
 
65
- # Chain ID for Morden (Classic) testnet
65
+ # Chain ID for Morden (Classic) testnet.
66
66
  MORDEN_CLASSIC = 62.freeze
67
67
 
68
- # Chain ID for Mordor testnet
68
+ # Chain ID for Mordor testnet.
69
69
  MORDOR = 63.freeze
70
70
 
71
- # Chain ID for Optimistik Kovan testnet
71
+ # Chain ID for Optimistik Kovan testnet.
72
72
  KOVAN_OPTIMISM = 69.freeze
73
73
 
74
- # Chain ID for Arbitrum xDAI testnet
74
+ # Chain ID for Arbitrum xDAI testnet.
75
75
  XDAI_ARBITRUM = 200.freeze
76
76
 
77
- # Chain ID for Optimistic Goerli testnet
77
+ # Chain ID for Optimistic Goerli testnet.
78
78
  GOERLI_OPTIMISM = 420.freeze
79
79
 
80
- # Chain ID for Arbitrum Rinkeby testnet
80
+ # Chain ID for Arbitrum Rinkeby testnet.
81
81
  RINKEBY_ARBITRUM = 421611.freeze
82
82
 
83
- # Chain ID for the geth private network preset
83
+ # Chain ID for Sepolia testnet.
84
+ SEPOLIA = 11155111.freeze
85
+
86
+ # Chain ID for the geth private network preset.
84
87
  PRIVATE_GETH = 1337.freeze
85
88
 
86
89
  # Indicates wether the given `v` indicates a legacy chain value
87
90
  # without EIP-155 replay protection.
88
91
  #
89
- # @param v [Integer] the signature's `v` value
90
- # @return [Boolean] true if legacy value
92
+ # @param v [Integer] the signature's `v` value.
93
+ # @return [Boolean] true if legacy value.
91
94
  def is_legacy?(v)
92
95
  [27, 28].include? v
93
96
  end
@@ -95,7 +98,7 @@ module Eth
95
98
  # Convert a given `v` value to an ECDSA recovery id for the given
96
99
  # EIP-155 chain ID.
97
100
  #
98
- # @param v [Integer] the signature's `v` value
101
+ # @param v [Integer] the signature's `v` value.
99
102
  # @param chain_id [Integer] the chain id the signature was generated on.
100
103
  # @return [Integer] the recovery id corresponding to `v`.
101
104
  # @raise [ReplayProtectionError] if the given `v` is invalid.
@@ -134,10 +137,10 @@ module Eth
134
137
  end
135
138
 
136
139
  # Converst a `v` value into a chain ID. This does not work for legacy signatures
137
- # with v < 36 that do not conform with EIP-155.
140
+ # with `v < 36` that do not conform with EIP-155.
138
141
  #
139
142
  # @param v [Integer] the signature's `v` value.
140
- # @return [Integer] the chain id as per EIP-155 or nil if there is no replay protection.
143
+ # @return [Integer] the chain id as per EIP-155 or `nil` if there is no replay protection.
141
144
  def to_chain_id(v)
142
145
  return nil if v < 36
143
146
  chain_id = (v - 35) / 2
@@ -0,0 +1,63 @@
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.
21
+ class Client::Http < 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
+ # Constructor for the HTTP Client. Should not be used; use
36
+ # {Client.create} intead.
37
+ #
38
+ # @param host [String] an URI pointing to an HTTP RPC-API.
39
+ def initialize(host)
40
+ super
41
+ uri = URI.parse(host)
42
+ raise ArgumentError, "Unable to parse the HTTP-URI!" unless ["http", "https"].include? uri.scheme
43
+ @host = uri.host
44
+ @port = uri.port
45
+ @ssl = uri.scheme == "https"
46
+ @uri = URI("#{uri.scheme}://#{@host}:#{@port}#{uri.path}")
47
+ end
48
+
49
+ # Sends an RPC request to the connected HTTP client.
50
+ #
51
+ # @param payload [Hash] the RPC request parameters.
52
+ # @return [String] a JSON-encoded response.
53
+ def send(payload)
54
+ http = Net::HTTP.new(@host, @port)
55
+ http.use_ssl = @ssl
56
+ header = { "Content-Type" => "application/json" }
57
+ request = Net::HTTP::Post.new(@uri, header)
58
+ request.body = payload
59
+ response = http.request(request)
60
+ response.body
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,47 @@
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 "socket"
16
+
17
+ # Provides the {Eth} module.
18
+ module Eth
19
+
20
+ # Provides an IPC-RPC client.
21
+ class Client::Ipc < Client
22
+
23
+ # The path of the IPC socket.
24
+ attr_accessor :path
25
+
26
+ # Constructor for the IPC Client. Should not be used; use
27
+ # {Client.create} intead.
28
+ #
29
+ # @param path [String] an URI pointing to an IPC RPC-API.
30
+ def initialize(path)
31
+ super
32
+ @path = path
33
+ end
34
+
35
+ # Sends an RPC request to the connected IPC socket.
36
+ #
37
+ # @param payload [Hash] the RPC request parameters.
38
+ # @return [String] a JSON-encoded response.
39
+ def send(payload)
40
+ socket = UNIXSocket.new(@path)
41
+ socket.puts(payload)
42
+ read = socket.recvmsg(nil)[0]
43
+ socket.close
44
+ return read
45
+ end
46
+ end
47
+ end
data/lib/eth/client.rb ADDED
@@ -0,0 +1,232 @@
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
+ # Provides the {Eth} module.
16
+ module Eth
17
+
18
+ # Provides the {Eth::Client} super-class to connect to Ethereum
19
+ # network's RPC-API endpoints (IPC or HTTP).
20
+ class Client
21
+
22
+ # The client's RPC-request ID starting at 0.
23
+ attr_reader :id
24
+
25
+ # The connected network's chain ID.
26
+ attr_reader :chain_id
27
+
28
+ # The connected network's client coinbase.
29
+ attr_accessor :default_account
30
+
31
+ # The default transaction max priority fee per gas in Wei.
32
+ attr_accessor :max_priority_fee_per_gas
33
+
34
+ # The default transaction max fee per gas in Wei.
35
+ attr_accessor :max_fee_per_gas
36
+
37
+ # The default gas limit for the transaction.
38
+ attr_accessor :gas_limit
39
+
40
+ # Creates a new RPC-Client, either by providing an HTTP/S host or
41
+ # an IPC path.
42
+ #
43
+ # @param host [String] either an HTTP/S host or an IPC path.
44
+ # @return [Eth::Client::Ipc] an IPC client.
45
+ # @return [Eth::Client::Http] an HTTP client.
46
+ # @raise [ArgumentError] in case it cannot determine the client type.
47
+ def self.create(host)
48
+ return Client::Ipc.new host if host.end_with? ".ipc"
49
+ return Client::Http.new host if host.start_with? "http"
50
+ raise ArgumentError, "Unable to detect client type!"
51
+ end
52
+
53
+ # Constructor for the {Eth::Client} super-class. Should not be used;
54
+ # use {Client.create} intead.
55
+ def initialize(_)
56
+ @id = 0
57
+ @max_priority_fee_per_gas = 0
58
+ @max_fee_per_gas = Tx::DEFAULT_GAS_PRICE
59
+ @gas_limit = Tx::DEFAULT_GAS_LIMIT
60
+ end
61
+
62
+ # Gets the default account (coinbase) of the connected client.
63
+ #
64
+ # @return [Eth::Address] the coinbase account address.
65
+ def default_account
66
+ @default_account ||= Address.new eth_coinbase["result"]
67
+ end
68
+
69
+ # Gets the chain ID of the connected network.
70
+ #
71
+ # @return [Integer] the chain ID.
72
+ def chain_id
73
+ @chain_id ||= eth_chain_id["result"].to_i 16
74
+ end
75
+
76
+ # Gets the balance for an address.
77
+ #
78
+ # @param address [Eth::Address] the address to get the balance for.
79
+ # @return [Integer] the balance in Wei.
80
+ def get_balance(address)
81
+ eth_get_balance(address)["result"].to_i 16
82
+ end
83
+
84
+ # Gets the next nonce for an address used to draft new transactions.
85
+ #
86
+ # @param address [Eth::Address] the address to get the nonce for.
87
+ # @return [Integer] the next nonce to be used.
88
+ def get_nonce(address)
89
+ eth_get_transaction_count(address, "pending")["result"].to_i 16
90
+ end
91
+
92
+ # 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
94
+ # provided.
95
+ #
96
+ # @param destination [Eth::Address] the destination address.
97
+ # @param amount [Integer] the transfer amount in Wei.
98
+ # @param sender_key [Eth::Key] the sender private key.
99
+ # @param legacy [Boolean] enables legacy transactions (pre-EIP-1559).
100
+ # @return [String] the transaction hash.
101
+ def transfer_and_wait(destination, amount, sender_key = nil, legacy = false)
102
+ wait_for_tx(transfer(destination, amount, sender_key, legacy))
103
+ end
104
+
105
+ # Simply transfer Ether to an account without any call data or
106
+ # access lists attached. Uses `eth_coinbase` and external signer
107
+ # if no sender key is provided.
108
+ #
109
+ # @param destination [Eth::Address] the destination address.
110
+ # @param amount [Integer] the transfer amount in Wei.
111
+ # @param sender_key [Eth::Key] the sender private key.
112
+ # @param legacy [Boolean] enables legacy transactions (pre-EIP-1559).
113
+ # @return [String] the transaction hash.
114
+ def transfer(destination, amount, sender_key = nil, legacy = false)
115
+ params = {
116
+ value: amount,
117
+ to: destination,
118
+ gas_limit: gas_limit,
119
+ chain_id: chain_id,
120
+ }
121
+ if legacy
122
+ params.merge!({
123
+ gas_price: max_fee_per_gas,
124
+ })
125
+ else
126
+ params.merge!({
127
+ priority_fee: max_priority_fee_per_gas,
128
+ max_gas_fee: max_fee_per_gas,
129
+ })
130
+ end
131
+ unless sender_key.nil?
132
+
133
+ # use the provided key as sender and signer
134
+ params.merge!({
135
+ from: sender_key.address,
136
+ nonce: get_nonce(sender_key.address),
137
+ })
138
+ tx = Eth::Tx.new(params)
139
+ tx.sign sender_key
140
+ return eth_send_raw_transaction(tx.hex)["result"]
141
+ else
142
+
143
+ # use the default account as sender and external signer
144
+ params.merge!({
145
+ from: default_account,
146
+ nonce: get_nonce(default_account),
147
+ })
148
+ return eth_send_transaction(params)["result"]
149
+ end
150
+ end
151
+
152
+ # Gives control over resetting the RPC request ID back to zero.
153
+ # Usually not needed.
154
+ #
155
+ # @return [Integer] 0
156
+ def reset_id
157
+ @id = 0
158
+ end
159
+
160
+ # Checkes wether a transaction is mined or not.
161
+ #
162
+ # @param hash [String] the transaction hash.
163
+ # @return [Boolean] true if included in a block.
164
+ def is_mined_tx?(hash)
165
+ mined_tx = eth_get_transaction_by_hash hash
166
+ !mined_tx.nil? && !mined_tx["result"].nil? && !mined_tx["result"]["blockNumber"].nil?
167
+ end
168
+
169
+ # Waits for an transaction to be mined by the connected chain.
170
+ #
171
+ # @param hash [String] the transaction hash.
172
+ # @return [String] the transactin hash once the transaction is mined.
173
+ # @raise [Timeout::Error] if it's not mined within 5 minutes.
174
+ def wait_for_tx(hash)
175
+ start_time = Time.now
176
+ timeout = 300
177
+ retry_rate = 0.1
178
+ loop do
179
+ raise Timeout::Error if ((Time.now - start_time) > timeout)
180
+ return hash if is_mined_tx? hash
181
+ sleep retry_rate
182
+ end
183
+ end
184
+
185
+ # Metafunction to provide all known RPC commands defined in
186
+ # Eth::Api as snake_case methods to the Eth::Client classes.
187
+ Api::COMMANDS.each do |cmd|
188
+ method_name = cmd.gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase
189
+ define_method method_name do |*args|
190
+ send_command cmd, args
191
+ end
192
+ end
193
+
194
+ private
195
+
196
+ # Prepares parameters and sends the command to the client.
197
+ def send_command(command, args)
198
+ args << "latest" if ["eth_getBalance", "eth_call"].include? command
199
+ payload = {
200
+ jsonrpc: "2.0",
201
+ method: command,
202
+ params: marshal(args),
203
+ id: next_id,
204
+ }
205
+ output = JSON.parse(send(payload.to_json))
206
+ raise IOError, output["error"]["message"] unless output["error"].nil?
207
+ return output
208
+ end
209
+
210
+ # Increments the request id.
211
+ def next_id
212
+ @id += 1
213
+ end
214
+
215
+ # Recursively marshals all request parameters.
216
+ def marshal(params)
217
+ if params.is_a? Array
218
+ return params.map! { |param| marshal(param) }
219
+ elsif params.is_a? Hash
220
+ return params.transform_values! { |param| marshal(param) }
221
+ elsif params.is_a? Numeric
222
+ return Util.prefix_hex "#{params.to_i.to_s(16)}"
223
+ elsif params.is_a? Address
224
+ return params.to_s
225
+ elsif Util.is_hex? params
226
+ return Util.prefix_hex params
227
+ else
228
+ return params
229
+ end
230
+ end
231
+ end
232
+ end