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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 322a4404d64ad2d1d14328ec0440b6612aaf5867
4
- data.tar.gz: 820552a955aeb11ccb156333758c94eb73eddaae
3
+ metadata.gz: a374154be8bb1dac7fe3073b4ca7e92ace6b8991
4
+ data.tar.gz: 7b21a87aa5d0a754f6abe50ee3eabbdf82dd7c50
5
5
  SHA512:
6
- metadata.gz: b070b6eb2995dc8595a001e584e69fed37b855cbb03a88989fb5bd22fd4d85a57dea48e1d598c2cc990bab21b2162f94f06111acf9b767fa6d583d6d838e3f81
7
- data.tar.gz: 84958a99e16f93a6de3f870398dc085c504582cd590c60570c1701e2802c52e845b22edcd220938c694e31c62321df08a4527c9ff5370a34634e6764d157707b
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 as transact_<underscore_function_name>(params) (or transact_and_wait_<underscore_function_name>(params)) and call_<underscore_function_name>(params) e.g.:
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
+ [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](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.
@@ -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 = ["Digix"]
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 "digest-sha3"
35
+ spec.add_dependency "sha3-pure-ruby"
36
36
  end
@@ -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
+
@@ -71,41 +71,44 @@ module Ethereum
71
71
  end
72
72
 
73
73
  functions.each do |fun|
74
- if fun.constant
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)
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
- define_method "transact_and_wait_#{fun.name.underscore}".to_sym do |*args|
103
- function_name = "transact_#{fun.name.underscore}".to_sym
104
- tx = self.send(function_name, *args)
105
- tx.wait_for_miner
106
- return tx
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)
@@ -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 = 60.seconds)
34
+ def wait_for_deployment(timeout = 1500.seconds)
35
35
  start_time = Time.now
36
36
  while self.deployed? == false
37
- raise Timeout::Error if ((Time.now - start_time) > timeout)
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
@@ -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
@@ -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
 
@@ -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 = 60.seconds)
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)
@@ -1,3 +1,3 @@
1
1
  module Ethereum
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.8"
3
3
  end
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.2.0
4
+ version: 0.3.8
5
5
  platform: ruby
6
6
  authors:
7
- - Digix
7
+ - DigixGlobal Pte Ltd (https://dgx.io)
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-10-08 00:00:00.000000000 Z
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: digest-sha3
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