ethereum 0.2.0 → 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +55 -3
- data/ethereum.gemspec +2 -2
- data/lib/ethereum.rb +3 -0
- data/lib/ethereum/client.rb +18 -0
- data/lib/ethereum/contract.rb +35 -32
- data/lib/ethereum/deployment.rb +2 -2
- data/lib/ethereum/formatter.rb +2 -2
- data/lib/ethereum/http_client.rb +40 -0
- data/lib/ethereum/ipc_client.rb +1 -12
- data/lib/ethereum/transaction.rb +5 -3
- data/lib/ethereum/version.rb +1 -1
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a374154be8bb1dac7fe3073b4ca7e92ace6b8991
|
4
|
+
data.tar.gz: 7b21a87aa5d0a754f6abe50ee3eabbdf82dd7c50
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 51e40edef7d4ede819c2ab3e7b3dbce2bc69488ba5b807db0dbcc1b57055611893b5e6c2fb6b782341d67ea22a2216c9287896fa826317faf7c646d8709709ae
|
7
|
+
data.tar.gz: 8982b0e349cacf5dc63ff700f73afbc2797da4bf070294c039da744851536ce9c034920b3bd5cff2147ff22f18678f23fbce6a7a022dda50ed06e05673f9311a
|
data/README.md
CHANGED
@@ -4,12 +4,21 @@ A simple library for Ethereum.
|
|
4
4
|
|
5
5
|
## Features
|
6
6
|
|
7
|
+
* Pure Ruby implementation
|
7
8
|
* IPC Client with batch calls support
|
9
|
+
* HTTP Client with batch calls support
|
8
10
|
* Compile and deploy Solidity contracts
|
9
11
|
* Expose deployed contracts as Ruby classes
|
10
12
|
* Test solidity contracts with a Ruby testing framework of your choice
|
11
13
|
* Call and wait for the result of Solidity function calls.
|
12
14
|
|
15
|
+
## Ruby Compatibility
|
16
|
+
|
17
|
+
* Ruby 2.x
|
18
|
+
* Ruby 1.9.x
|
19
|
+
* JRuby
|
20
|
+
* Rubinius
|
21
|
+
|
13
22
|
## Requirements
|
14
23
|
|
15
24
|
We currently support UNIX/Linux environments and Windows IPC support on the roadmap.
|
@@ -53,22 +62,65 @@ simple_name_registry_instance.deploy_and_wait
|
|
53
62
|
|
54
63
|
### Transacting and Calling Solidity Functions
|
55
64
|
|
56
|
-
Solidity functions are exposed
|
65
|
+
Solidity functions are exposed using the following conventions:
|
66
|
+
|
67
|
+
```
|
68
|
+
transact_[function_name](params)
|
69
|
+
transact_and_wait_[function_name](params)
|
70
|
+
call_[function_name](params)
|
71
|
+
```
|
72
|
+
|
73
|
+
**Example Contract in Solidity**
|
74
|
+
```
|
75
|
+
contract SimpleNameRegistry {
|
76
|
+
|
77
|
+
mapping (address => bool) public myMapping;
|
78
|
+
|
79
|
+
function register(address _a, bytes32 _b) {
|
80
|
+
}
|
81
|
+
|
82
|
+
function getSomeValue(address _x) public constant returns(bool b, address b) {
|
83
|
+
}
|
84
|
+
|
85
|
+
}
|
86
|
+
```
|
57
87
|
|
58
88
|
```ruby
|
59
89
|
simple_name_registry_instance.transact_and_wait_register("0x5b6cb65d40b0e27fab87a2180abcab22174a2d45", "minter.contract.dgx")
|
60
90
|
simple_name_registry_instance.transact_register("0x385acafdb80b71ae001f1dbd0d65e62ec2fff055", "anthony@eufemio.dgx")
|
91
|
+
simple_name_registry_instance.call_get_some_value("0x385acafdb80b71ae001f1dbd0d65e62ec2fff055")
|
92
|
+
simple_name_registry_instance.call_my_mapping("0x385acafdb80b71ae001f1dbd0d65e62ec2fff055")
|
93
|
+
```
|
94
|
+
|
95
|
+
### Run contracts using a different address
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
simple_name_registry_instance.as("0x0c0d99d3608a2d1d38bb1b28025e970d3910b1e1")
|
99
|
+
```
|
100
|
+
|
101
|
+
### Point contract instance to a previously deployed contract
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
simple_name_registry_instance.at("0x734533083b5fc0cd14b7cb8c8eb6ed0c9bd184d3")
|
61
105
|
```
|
62
106
|
|
63
107
|
## Roadmap
|
64
108
|
|
65
|
-
* Add JSON RPC Client support
|
66
109
|
* Add Windows IPC Client (named pipes)
|
110
|
+
* Add support for creating and sending of raw transactions
|
111
|
+
* Offline account creation
|
67
112
|
* Solidity constant function output should be properly formatted according to the ouput data type
|
68
|
-
* Unit testing and contract testing examples
|
113
|
+
* Unit testing and contract testing examples. Use [web3.js](https://github.com/ethereum/web3.js) tests as a baseline.
|
114
|
+
* ContractTransaction class
|
69
115
|
* Add more examples
|
70
116
|
* API documentation
|
71
117
|
|
118
|
+
## Support
|
119
|
+
|
120
|
+
Please join our Gitter chat room or open a new issue in this repository
|
121
|
+
|
122
|
+
[](https://gitter.im/DigixGlobal/ethereum-ruby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
123
|
+
|
72
124
|
## Development
|
73
125
|
|
74
126
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/ethereum.gemspec
CHANGED
@@ -6,7 +6,7 @@ require 'ethereum/version'
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "ethereum"
|
8
8
|
spec.version = Ethereum::VERSION
|
9
|
-
spec.authors = ["
|
9
|
+
spec.authors = ["DigixGlobal Pte Ltd (https://dgx.io)"]
|
10
10
|
spec.email = ["ace@dgx.io"]
|
11
11
|
|
12
12
|
spec.summary = %q{Ethereum libraries for Ruby}
|
@@ -32,5 +32,5 @@ Gem::Specification.new do |spec|
|
|
32
32
|
spec.add_development_dependency "rspec"
|
33
33
|
spec.add_development_dependency "pry"
|
34
34
|
spec.add_dependency "activesupport"
|
35
|
-
spec.add_dependency "
|
35
|
+
spec.add_dependency "sha3-pure-ruby"
|
36
36
|
end
|
data/lib/ethereum.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
require "ethereum/version"
|
2
2
|
require 'active_support'
|
3
3
|
require 'active_support/core_ext'
|
4
|
+
require 'sha3-pure-ruby'
|
4
5
|
|
5
6
|
module Ethereum
|
7
|
+
require 'ethereum/client'
|
6
8
|
require 'ethereum/ipc_client'
|
9
|
+
require 'ethereum/http_client'
|
7
10
|
require 'ethereum/initializer'
|
8
11
|
require 'ethereum/contract'
|
9
12
|
require 'ethereum/function'
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Ethereum
|
2
|
+
class Client
|
3
|
+
|
4
|
+
RPC_COMMANDS = %w(eth_accounts eth_blockNumber eth_getBalance eth_protocolVersion eth_coinbase eth_mining eth_gasPrice eth_getStorage eth_storageAt eth_getStorageAt eth_getTransactionCount eth_getBlockTransactionCountByHash eth_getBlockTransactionCountByNumber eth_getUncleCountByBlockHash eth_getUncleCountByBlockNumber eth_getData eth_getCode eth_sign eth_sendRawTransaction eth_sendTransaction eth_transact eth_estimateGas eth_call eth_flush eth_getBlockByHash eth_getBlockByNumber eth_getTransactionByHash eth_getTransactionByBlockNumberAndIndex eth_getTransactionByBlockHashAndIndex eth_getUncleByBlockHashAndIndex eth_getUncleByBlockNumberAndIndex eth_getCompilers eth_compileSolidity eth_newFilter eth_newBlockFilter eth_newPendingTransactionFilter eth_uninstallFilter eth_getFilterChanges eth_getFilterLogs eth_getLogs eth_hashrate eth_getWork eth_submitWork eth_resend eth_pendingTransactions eth_getTransactionReceipt)
|
5
|
+
|
6
|
+
def get_id
|
7
|
+
@id = @id + 1
|
8
|
+
return @id
|
9
|
+
end
|
10
|
+
|
11
|
+
def clear_batch
|
12
|
+
@batch = []
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
data/lib/ethereum/contract.rb
CHANGED
@@ -71,41 +71,44 @@ module Ethereum
|
|
71
71
|
end
|
72
72
|
|
73
73
|
functions.each do |fun|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
end
|
86
|
-
return {result: connection.call({to: self.address, from: self.sender, data: payload.join()})["result"].gsub(/^0x/,'').scan(/.{64}/)}
|
87
|
-
end
|
88
|
-
else
|
89
|
-
define_method "transact_#{fun.name.underscore}".to_sym do |*args|
|
90
|
-
formatter = Ethereum::Formatter.new
|
91
|
-
arg_types = fun.inputs.collect(&:type)
|
92
|
-
connection = self.connection
|
93
|
-
return {result: :error, message: "missing parameters for #{fun.function_string}" } if arg_types.length != args.length
|
94
|
-
payload = []
|
95
|
-
payload << fun.signature
|
96
|
-
arg_types.zip(args).each do |arg|
|
97
|
-
payload << formatter.to_payload(arg)
|
98
|
-
end
|
99
|
-
txid = connection.send_transaction({to: self.address, from: self.sender, data: payload.join(), gas: self.gas, gasPrice: self.gas_price})["result"]
|
100
|
-
return Ethereum::Transaction.new(txid, self.connection)
|
74
|
+
|
75
|
+
define_method "call_#{fun.name.underscore}".to_sym do |*args|
|
76
|
+
formatter = Ethereum::Formatter.new
|
77
|
+
arg_types = fun.inputs.collect(&:type)
|
78
|
+
#out_types = fun.outputs.collect(&:type)
|
79
|
+
connection = self.connection
|
80
|
+
return {result: :error, message: "missing parameters for #{fun.function_string}" } if arg_types.length != args.length
|
81
|
+
payload = []
|
82
|
+
payload << fun.signature
|
83
|
+
arg_types.zip(args).each do |arg|
|
84
|
+
payload << formatter.to_payload(arg)
|
101
85
|
end
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
86
|
+
raw_result = connection.call({to: self.address, from: self.sender, data: payload.join()})["result"]
|
87
|
+
formatted_result = raw_result.gsub(/^0x/,'').scan(/.{64}/)
|
88
|
+
return {data: payload.join(), raw: raw_result, formatted: formatted_result}
|
89
|
+
end
|
90
|
+
|
91
|
+
define_method "transact_#{fun.name.underscore}".to_sym do |*args|
|
92
|
+
formatter = Ethereum::Formatter.new
|
93
|
+
arg_types = fun.inputs.collect(&:type)
|
94
|
+
connection = self.connection
|
95
|
+
return {result: :error, message: "missing parameters for #{fun.function_string}" } if arg_types.length != args.length
|
96
|
+
payload = []
|
97
|
+
payload << fun.signature
|
98
|
+
arg_types.zip(args).each do |arg|
|
99
|
+
payload << formatter.to_payload(arg)
|
107
100
|
end
|
101
|
+
txid = connection.send_transaction({to: self.address, from: self.sender, data: payload.join(), gas: self.gas, gasPrice: self.gas_price})["result"]
|
102
|
+
return Ethereum::Transaction.new(txid, self.connection, payload.join(), args)
|
108
103
|
end
|
104
|
+
|
105
|
+
define_method "transact_and_wait_#{fun.name.underscore}".to_sym do |*args|
|
106
|
+
function_name = "transact_#{fun.name.underscore}".to_sym
|
107
|
+
tx = self.send(function_name, *args)
|
108
|
+
tx.wait_for_miner
|
109
|
+
return tx
|
110
|
+
end
|
111
|
+
|
109
112
|
end
|
110
113
|
end
|
111
114
|
Object.const_set(class_name, class_methods)
|
data/lib/ethereum/deployment.rb
CHANGED
@@ -31,10 +31,10 @@ module Ethereum
|
|
31
31
|
@valid_deployment = @connection.get_code(@contract_address)["result"] != "0x"
|
32
32
|
end
|
33
33
|
|
34
|
-
def wait_for_deployment(timeout =
|
34
|
+
def wait_for_deployment(timeout = 1500.seconds)
|
35
35
|
start_time = Time.now
|
36
36
|
while self.deployed? == false
|
37
|
-
raise
|
37
|
+
raise "Transaction #{@id} timed out." if ((Time.now - start_time) > timeout)
|
38
38
|
sleep 5
|
39
39
|
return true if self.deployed?
|
40
40
|
end
|
data/lib/ethereum/formatter.rb
CHANGED
@@ -54,11 +54,11 @@ module Ethereum
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def uint_to_payload(uint)
|
57
|
-
self.to_twos_complement(uint)
|
57
|
+
self.to_twos_complement(uint).rjust(64, '0')
|
58
58
|
end
|
59
59
|
|
60
60
|
def int_to_payload(int)
|
61
|
-
self.to_twos_complement(uint)
|
61
|
+
self.to_twos_complement(uint).rjust(64, '0')
|
62
62
|
end
|
63
63
|
|
64
64
|
def bytes_to_payload(bytes)
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'pry'
|
2
|
+
module Ethereum
|
3
|
+
class HttpClient < Client
|
4
|
+
attr_accessor :command, :id, :host, :port, :batch, :converted_transactions, :uri
|
5
|
+
|
6
|
+
def initialize(host, port)
|
7
|
+
@host = host
|
8
|
+
@port = port
|
9
|
+
@id = 1
|
10
|
+
@uri = URI("http://#{@host}:#{@port}")
|
11
|
+
@batch = []
|
12
|
+
end
|
13
|
+
|
14
|
+
RPC_COMMANDS.each do |rpc_command|
|
15
|
+
method_name = "#{rpc_command.split("_")[1].underscore}"
|
16
|
+
define_method method_name do |*args|
|
17
|
+
command = rpc_command
|
18
|
+
payload = {jsonrpc: "2.0", method: command, params: args, id: get_id}
|
19
|
+
http = Net::HTTP.new(@host, @port)
|
20
|
+
header = {'Content-Type' => 'application/json'}
|
21
|
+
request = Net::HTTP::Post.new(uri, header)
|
22
|
+
request.body = payload.to_json
|
23
|
+
response = http.request(request)
|
24
|
+
return JSON.parse(response.body)
|
25
|
+
end
|
26
|
+
|
27
|
+
define_method "#{method_name}_batch" do |*args|
|
28
|
+
command = rpc_command
|
29
|
+
payload = {jsonrpc: "2.0", method: command, params: args, id: get_id}
|
30
|
+
@batch << payload.to_json
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def send_batch
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
data/lib/ethereum/ipc_client.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'socket'
|
2
2
|
module Ethereum
|
3
|
-
class IpcClient
|
3
|
+
class IpcClient < Client
|
4
4
|
attr_accessor :command, :id, :ipcpath, :batch, :converted_transactions
|
5
5
|
|
6
6
|
def initialize(ipcpath = "#{ENV['HOME']}/.ethereum/geth.ipc")
|
@@ -9,13 +9,6 @@ module Ethereum
|
|
9
9
|
@batch = []
|
10
10
|
end
|
11
11
|
|
12
|
-
def get_id
|
13
|
-
@id = @id + 1
|
14
|
-
return @id
|
15
|
-
end
|
16
|
-
|
17
|
-
RPC_COMMANDS = %w(eth_accounts eth_blockNumber eth_getBalance eth_protocolVersion eth_coinbase eth_mining eth_gasPrice eth_getStorage eth_storageAt eth_getStorageAt eth_getTransactionCount eth_getBlockTransactionCountByHash eth_getBlockTransactionCountByNumber eth_getUncleCountByBlockHash eth_getUncleCountByBlockNumber eth_getData eth_getCode eth_sign eth_sendRawTransaction eth_sendTransaction eth_transact eth_estimateGas eth_call eth_flush eth_getBlockByHash eth_getBlockByNumber eth_getTransactionByHash eth_getTransactionByBlockNumberAndIndex eth_getTransactionByBlockHashAndIndex eth_getUncleByBlockHashAndIndex eth_getUncleByBlockNumberAndIndex eth_getCompilers eth_compileSolidity eth_newFilter eth_newBlockFilter eth_newPendingTransactionFilter eth_uninstallFilter eth_getFilterChanges eth_getFilterLogs eth_getLogs eth_hashrate eth_getWork eth_submitWork eth_resend eth_pendingTransactions eth_getTransactionReceipt)
|
18
|
-
|
19
12
|
RPC_COMMANDS.each do |rpc_command|
|
20
13
|
method_name = "#{rpc_command.split("_")[1].underscore}"
|
21
14
|
define_method method_name do |*args|
|
@@ -52,10 +45,6 @@ module Ethereum
|
|
52
45
|
return collection
|
53
46
|
end
|
54
47
|
|
55
|
-
def clear_batch
|
56
|
-
@batch = []
|
57
|
-
end
|
58
|
-
|
59
48
|
end
|
60
49
|
end
|
61
50
|
|
data/lib/ethereum/transaction.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
module Ethereum
|
2
2
|
|
3
3
|
class Transaction
|
4
|
-
attr_accessor :id, :mined, :connection
|
4
|
+
attr_accessor :id, :mined, :connection, :input, :input_parameters
|
5
5
|
|
6
|
-
def initialize(id, connection)
|
6
|
+
def initialize(id, connection, data, input_parameters = [])
|
7
7
|
@mined = false
|
8
8
|
@connection = connection
|
9
9
|
@id = id
|
10
|
+
@input = data
|
11
|
+
@input_parameters = input_parameters
|
10
12
|
end
|
11
13
|
|
12
14
|
def mined?
|
@@ -14,7 +16,7 @@ module Ethereum
|
|
14
16
|
@mined = @connection.get_transaction_by_hash(@id)["result"]["blockNumber"].present?
|
15
17
|
end
|
16
18
|
|
17
|
-
def wait_for_miner(timeout =
|
19
|
+
def wait_for_miner(timeout = 1500.seconds)
|
18
20
|
start_time = Time.now
|
19
21
|
while self.mined? == false
|
20
22
|
raise Timeout::Error if ((Time.now - start_time) > timeout)
|
data/lib/ethereum/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ethereum
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- DigixGlobal Pte Ltd (https://dgx.io)
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-10-
|
11
|
+
date: 2015-10-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -81,7 +81,7 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: sha3-pure-ruby
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - ">="
|
@@ -116,12 +116,14 @@ files:
|
|
116
116
|
- bin/setup
|
117
117
|
- ethereum.gemspec
|
118
118
|
- lib/ethereum.rb
|
119
|
+
- lib/ethereum/client.rb
|
119
120
|
- lib/ethereum/contract.rb
|
120
121
|
- lib/ethereum/deployment.rb
|
121
122
|
- lib/ethereum/formatter.rb
|
122
123
|
- lib/ethereum/function.rb
|
123
124
|
- lib/ethereum/function_input.rb
|
124
125
|
- lib/ethereum/function_output.rb
|
126
|
+
- lib/ethereum/http_client.rb
|
125
127
|
- lib/ethereum/initializer.rb
|
126
128
|
- lib/ethereum/ipc_client.rb
|
127
129
|
- lib/ethereum/transaction.rb
|