ether-fly 0.0.1 → 0.0.2
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 +49 -0
- data/bin/ether-fly +309 -20
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3df64de010310a17c6c11e09a1a2136cf3e84fca
|
4
|
+
data.tar.gz: 78f72289d962e0347d334982757718dbbae7fe05
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 22bb02684234b2b97e0b5ab24670e7ffe9bacd49501b3ce3ae2e7572dab5bc91242d607fe62790897e27b15ce6975792f8b99c8af44f7e2ae44ece8392fe0a7f
|
7
|
+
data.tar.gz: 3e00e49cce5219cd77c88e5a6385c0440b0c406f1715acd76dbe4971449f704f87525822020439f953a380d1cfa539241f871ba3102a9bfff0c6606be06e4d21
|
data/README.md
CHANGED
@@ -1,7 +1,11 @@
|
|
1
|
+
## Introduction
|
2
|
+
EtherFly is a Ethereum smart contract test framework in ruby.It provides two testing environments: testing in ruby EVM and testing in geth.You don't need to understand ruby grammar, just enjoy syntactic sugar.
|
3
|
+
|
1
4
|
## Install
|
2
5
|
```shell
|
3
6
|
bundle install ether-fly
|
4
7
|
```
|
8
|
+
|
5
9
|
## How to use
|
6
10
|
|
7
11
|
Help command:
|
@@ -21,3 +25,48 @@ Run tests
|
|
21
25
|
```
|
22
26
|
$ ether-fly t game
|
23
27
|
```
|
28
|
+
|
29
|
+
## Unit tests
|
30
|
+
You can wirte fast, simple tests.
|
31
|
+
```ruby
|
32
|
+
class TokenTest < Minitest::Test
|
33
|
+
include Ethereum
|
34
|
+
|
35
|
+
def setup
|
36
|
+
@state = Tester::State.new
|
37
|
+
@solidity_code = File.read('./contracts/Token.sol')
|
38
|
+
@c = @state.abi_contract @solidity_code, language: :solidity
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_issue_balance
|
42
|
+
assert_equal 0, @c.getBalance(Tester::Fixture.accounts[2])
|
43
|
+
@c.issue Tester::Fixture.accounts[2], 100
|
44
|
+
assert_equal 100, @c.getBalance(Tester::Fixture.accounts[2])
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_issue_exception
|
48
|
+
assert_raises(TransactionFailed) { @c.issue Tester::Fixture.accounts[3], 100, sender: Tester::Fixture.keys[4] }
|
49
|
+
assert_equal 0, @c.getBalance(Tester::Fixture.accounts[3])
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_token_transfer
|
53
|
+
@c.issue Tester::Fixture.accounts[2], 100
|
54
|
+
@c.transfer Tester::Fixture.accounts[3], 90, sender: Tester::Fixture.keys[2]
|
55
|
+
assert_equal 90, @c.getBalance(Tester::Fixture.accounts[3])
|
56
|
+
|
57
|
+
assert_raises(TransactionFailed) { @c.transfer Tester::Fixture.accounts[3], 90, sender: Tester::Fixture.keys[2] }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
```
|
62
|
+
More details:
|
63
|
+
https://github.com/seattlerb/minitest
|
64
|
+
|
65
|
+
## TODO
|
66
|
+
- Extract test file require and others
|
67
|
+
- Save migrate address
|
68
|
+
- Migrate ARGV
|
69
|
+
- Script for preload
|
70
|
+
- Easy way to load contract on chain
|
71
|
+
- Easy way to test on chain
|
72
|
+
- ES6
|
data/bin/ether-fly
CHANGED
@@ -1,13 +1,21 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'erb'
|
4
|
+
require 'json'
|
4
5
|
|
5
6
|
ARGV << "--help" if ARGV.empty?
|
6
7
|
|
7
8
|
aliases = {
|
9
|
+
"n" => "new",
|
8
10
|
"g" => "generate",
|
9
11
|
"t" => "test",
|
10
|
-
"
|
12
|
+
"i" => "init",
|
13
|
+
"ik" => "import_keys",
|
14
|
+
"b" => "build",
|
15
|
+
"m" => "migrate",
|
16
|
+
"s" => "server",
|
17
|
+
"c" => "console",
|
18
|
+
"gt" => "geth_test"
|
11
19
|
}
|
12
20
|
|
13
21
|
command = ARGV.shift
|
@@ -16,14 +24,21 @@ command = aliases[command] || command
|
|
16
24
|
HELP_MESSAGE = <<-EOF
|
17
25
|
Usage: eth-fly COMMAND [ARGS]
|
18
26
|
The most common eth-fly commands are:
|
19
|
-
|
20
|
-
|
21
|
-
new
|
22
|
-
|
27
|
+
new Create a new Smart Contract application. "eth-fly new my_app" creates a
|
28
|
+
new application called MyApp in "./my_app" (short-cut alias: "n")
|
29
|
+
generate Generate new Smart Contract and test file (short-cut alias: "g")
|
30
|
+
test Run tests (short-cut alias: "t")
|
31
|
+
init Init private geth chain (short-cut alias: "i")
|
32
|
+
import_keys Import keys to chain (short-cut alias: "ik")
|
33
|
+
build Build contract (short-cut alias: "b")
|
34
|
+
migrate Deploy contract on chain (short-cut alias: "m")
|
35
|
+
server Start chain (short-cut alias: "s")
|
36
|
+
console Open Chain console (short-cut alias: "c")
|
37
|
+
geth_test Test on chain (short-cut alias: "gt")
|
23
38
|
All commands can be run with -h (or --help) for more information.
|
24
39
|
EOF
|
25
40
|
|
26
|
-
COMMAND_WHITELIST = %w(generate
|
41
|
+
COMMAND_WHITELIST = %w(new generate test init import_keys build migrate server console geth_test)
|
27
42
|
|
28
43
|
CONTRACT_TEMPLATE = ERB.new <<-EOF
|
29
44
|
contract <%= name.capitalize %> {
|
@@ -50,24 +65,257 @@ GEMFILE_TEMPLATE = ERB.new <<-EOF
|
|
50
65
|
gem 'ether-fly', '>= 0.0.1'
|
51
66
|
EOF
|
52
67
|
|
53
|
-
|
54
|
-
|
68
|
+
GENESIS_TEMPLATE = <<-EOF
|
69
|
+
{
|
70
|
+
"nonce": "0x0000000000000042",
|
71
|
+
"difficulty": "0x020000",
|
72
|
+
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
73
|
+
"coinbase": "0x0000000000000000000000000000000000000000",
|
74
|
+
"timestamp": "0x00",
|
75
|
+
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
76
|
+
"extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
|
77
|
+
"gasLimit": "0x4c4b40"
|
78
|
+
}
|
79
|
+
EOF
|
55
80
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
81
|
+
KEYS_TEMPLATE = {
|
82
|
+
"3ae88fe370c39384fc16da2c9e768cf5d2495b48" => "095e53c9c20e23fd01eaad953c01da9e9d3ed9bebcfed8e5b2c2fce94037d963",
|
83
|
+
"81063419f13cab5ac090cd8329d8fff9feead4a0" => "5bc505a123a695176a9688ffe22798cfd40424c5b91c818e985574ea8ebda167",
|
84
|
+
"9da26fc2e1d6ad9fdd46138906b0104ae68a65d8" => "b6a03207128827eaae0d31d97a7a6243de31f2baf99eabd764e33389ecf436fc",
|
85
|
+
"bd2d69e3e68e1ab3944a865b3e566ca5c48740da" => "b35b8064c5c373629a05cc3ef39789ba4dacd404e6e864214ade934c198b636f",
|
86
|
+
"ca9f427df31a1f5862968fad1fe98c0a9ee068c4" => "9e35c48588711469e13c9a594f9f6d81491ce44ff1e8c5d968fcbd17168088a4"
|
87
|
+
}
|
88
|
+
|
89
|
+
SOLC_HELPER_TEMPLATE = %q{#!/usr/bin/env ruby
|
90
|
+
|
91
|
+
require 'json'
|
92
|
+
def library_code
|
93
|
+
'function create(abiDefinition) { return web3.eth.contract(abiDefinition);}/*function deploy(account, value, gas, contract, code, input) */function deploy() { var account = arguments[0]; var value = arguments[1]; var gas = arguments[2]; var contract = arguments[3]; var code = arguments[4]; var codeString = "contract.new(inputMarker,{from:\'accountMarker\', value: valueMarker, data: \'codeMarker\', gas: gasMarker}, function (e, contract) { if(!e) { if(!contract.address) { console.log(\"Contract transaction send: TransactionHash: \" + contract.transactionHash + \" waiting to be mined...\"); } else { console.log(\"Contract mined! Address: \" + contract.address); } } else { console.log(e) } })"; codeString = codeString.replace("accountMarker", account); codeString = codeString.replace("valueMarker", value); codeString = codeString.replace("codeMarker", code); codeString = codeString.replace("gasMarker", gas); input = "null"; if (arguments.length > 5) { if (arguments[5] != null) { var args = []; for (var i = 5;i < arguments.length; i++) { var val = arguments[i]; if (typeof(val) === \'string\') { val = "\"" + val + "\""; } args.push(val); } input = args.join(","); } } codeString = codeString.replace("inputMarker", input); console.log(input); var instance = eval(codeString); return instance;}function watcher(error, result) { if (!error) { console.log("Result"); console.log(JSON.stringify(result)); return; } console.log("Error" + error);}/*function call(account, gas, func, input) */function call() { var account = "eth.accounts["+arguments[0]+"]"; var gas = arguments[1]; var func = arguments[2]; input = "null"; if (arguments.length > 3) { if (arguments[3] != null) { var args = Array.prototype.slice.call(arguments, 3); input = args.join(","); } } codeString = "func.sendTransaction(inputMarker, gasMarker, {from:accountMarker}, watcher);"; codeString = codeString.replace("accountMarker",account); codeString = codeString.replace("gasMarker",gas); codeString = codeString.replace("inputMarker",input); eval(codeString);}function send(from_index, to, value, gas){ return eth.sendTransaction({from:eth.accounts[from_index], to:to, value:web3.toWei(value,\'ether\'), gas:gas});}function bal() { for (var i = 0; i < eth.accounts.length; i++) { account = eth.accounts[i]; balance = web3.fromWei(eth.getBalance(eth.accounts[i]), \'ether\'); console.log("Index : " + i); console.log("Account : "+ account); console.log("Balance : "+ balance); console.log("\n"); }}'
|
94
|
+
end
|
95
|
+
|
96
|
+
def compile_solidity(file)
|
97
|
+
json_string = `solc --add-std --optimize --combined-json abi,bin,userdoc,devdoc #{file}`
|
98
|
+
json_string = json_string.gsub("\\n","")
|
99
|
+
begin
|
100
|
+
json_object = JSON.parse(json_string)
|
101
|
+
throw if json_object.nil?
|
102
|
+
puts `solc --optimize --gas #{file}`
|
103
|
+
puts "\n\n"
|
104
|
+
puts "-------------------------------------"
|
105
|
+
json_object["contracts"]
|
106
|
+
rescue
|
107
|
+
puts "Failed to Compile."
|
108
|
+
abort
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def process_code(contracts)
|
113
|
+
contracts.keys.each.with_index do |key, i|
|
114
|
+
contracts[key]["bin"] = "0x" + contracts[key]["bin"]
|
115
|
+
contracts[key]["abi"] = JSON.parse(contracts[key]["abi"])
|
116
|
+
contracts[key]["devdoc"] = JSON.parse(contracts[key]["devdoc"])
|
117
|
+
contracts[key]["userdoc"] = JSON.parse(contracts[key]["userdoc"])
|
118
|
+
end
|
119
|
+
return contracts
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
def javascript_file_name(file_name)
|
124
|
+
file_name = file_name.split('/')[-1]
|
125
|
+
file_name.split('.')[0] + '_compiled.js'
|
126
|
+
end
|
127
|
+
|
128
|
+
def get_contract_to_deploy(compiled_object)
|
129
|
+
return compiled_object.keys[0] if compiled_object.keys.count == 1
|
130
|
+
puts "Which contract do you want to deploy?"
|
131
|
+
choice = 0
|
132
|
+
while choice <= 0 || choice > compiled_object.keys.count
|
133
|
+
compiled_object.keys.each.with_index do |key, i|
|
134
|
+
puts "#{(i+1)}. "+key
|
135
|
+
end
|
136
|
+
choice = $stdin.gets.to_i
|
60
137
|
end
|
138
|
+
return compiled_object.keys[choice - 1]
|
61
139
|
end
|
62
140
|
|
141
|
+
def get_input
|
142
|
+
puts "Enter Input: "
|
143
|
+
input = $stdin.gets
|
144
|
+
input.strip.chomp == "" ? "null" : input
|
145
|
+
end
|
146
|
+
|
147
|
+
def get_gas
|
148
|
+
gas = 0
|
149
|
+
while gas == 0
|
150
|
+
puts "Enter Gas: "
|
151
|
+
gas = $stdin.gets.to_i
|
152
|
+
end
|
153
|
+
gas
|
154
|
+
end
|
155
|
+
|
156
|
+
def get_value
|
157
|
+
gas = -1
|
158
|
+
while gas < 0
|
159
|
+
puts "Enter Value To Be Transferred: "
|
160
|
+
gas = $stdin.gets.to_i
|
161
|
+
end
|
162
|
+
gas
|
163
|
+
end
|
164
|
+
|
165
|
+
file_name = ARGV[0]
|
166
|
+
|
167
|
+
compiled_object = compile_solidity(file_name)
|
168
|
+
compiled_object = process_code(compiled_object)
|
169
|
+
javascript_file_name = javascript_file_name(file_name)
|
170
|
+
|
171
|
+
current_contract = get_contract_to_deploy(compiled_object)
|
172
|
+
|
173
|
+
compiled_variable_name = "#{current_contract}Compiled"
|
174
|
+
contract_variable_name = "#{current_contract}Contract"
|
175
|
+
contract_instance_variable_name = "#{current_contract}"
|
176
|
+
|
177
|
+
gas = get_gas
|
178
|
+
value = get_value
|
179
|
+
input = get_input
|
180
|
+
|
181
|
+
File.open(javascript_file_name, 'w') do |f|
|
182
|
+
f.write("#{library_code};\nvar #{compiled_variable_name} = #{compiled_object.to_json};")
|
183
|
+
f.write("#{contract_variable_name} = create(#{compiled_variable_name}.#{current_contract}.abi);")
|
184
|
+
f.write("#{contract_instance_variable_name} = deploy(eth.coinbase,#{value},#{gas},#{contract_variable_name},#{compiled_variable_name}.#{current_contract}.bin,#{input});")
|
185
|
+
f.write("console.log('Compiled Object : #{compiled_variable_name}');")
|
186
|
+
f.write("console.log('Contract : #{contract_variable_name}');")
|
187
|
+
f.write("console.log('Contract Instance : #{contract_instance_variable_name}');")
|
188
|
+
end
|
189
|
+
}
|
190
|
+
|
191
|
+
ATTACH_SH = <<-EOF
|
192
|
+
#!/bin/bash
|
193
|
+
|
194
|
+
geth=${GETH:-geth}
|
195
|
+
$geth attach ipc:data/geth.ipc
|
196
|
+
EOF
|
197
|
+
|
198
|
+
BUILD_SH = <<-EOF
|
199
|
+
#!/bin/bash
|
200
|
+
for sol in `find ./contracts -name '*.sol'`
|
201
|
+
do
|
202
|
+
filename="${sol}"
|
203
|
+
echo $filename
|
204
|
+
let len=${#filename}-16
|
205
|
+
# echo $len
|
206
|
+
jsfile="${filename:12:len}_compiled.js"
|
207
|
+
echo $jsfile
|
208
|
+
./bin/solc_helper.rb $sol $jsfile
|
209
|
+
mv $jsfile builds/
|
210
|
+
done
|
211
|
+
EOF
|
212
|
+
|
213
|
+
IMPORT_KEYS_SH = <<-EOF
|
214
|
+
#!/bin/sh
|
215
|
+
|
216
|
+
geth=${GETH:-geth}
|
217
|
+
echo "***** Using geth at: $geth"
|
218
|
+
|
219
|
+
echo "***** Import all pre-funded private keys"
|
220
|
+
|
221
|
+
for key in `find ./private_keys -name '*.key'`
|
222
|
+
do
|
223
|
+
./private_keys/import.sh $key $geth
|
224
|
+
done
|
225
|
+
|
226
|
+
echo "***** Done."
|
227
|
+
EOF
|
228
|
+
|
229
|
+
INIT_SH = <<-EOF
|
230
|
+
#! /bin/bash
|
231
|
+
geth --datadir `pwd`/data init genesis.json
|
232
|
+
EOF
|
233
|
+
|
234
|
+
PRIVATE_BLOCKCHAIN_SH = <<-EOF
|
235
|
+
#!/bin/bash
|
236
|
+
|
237
|
+
geth=${GETH:-geth}
|
238
|
+
|
239
|
+
$geth --datadir data --networkid 31415926 --rpc --rpccorsdomain "*" --nodiscover --unlock 3ae88fe370c39384fc16da2c9e768cf5d2495b48 --password <(echo -n 123456)
|
240
|
+
EOF
|
241
|
+
|
242
|
+
TEST_SH = <<-EOF
|
243
|
+
#!/bin/bash
|
244
|
+
|
245
|
+
geth=${GETH:-geth}
|
246
|
+
|
247
|
+
scripts=""
|
248
|
+
|
249
|
+
for file in `find ./builds -name '*compiled.js'`
|
250
|
+
do
|
251
|
+
scripts="${scripts};loadScript('$file')"
|
252
|
+
done
|
253
|
+
|
254
|
+
for file in `find ./test -name '*.js'`
|
255
|
+
do
|
256
|
+
scripts="${scripts};loadScript('$file');"
|
257
|
+
done
|
258
|
+
|
259
|
+
echo $scripts
|
260
|
+
$geth --datadir data --networkid 31415926 --rpc --rpccorsdomain "*" --nodiscover --unlock 3ae88fe370c39384fc16da2c9e768cf5d2495b48 --password <(echo -n 123456) --exec "$scripts" console 2>> ./logfile
|
261
|
+
EOF
|
262
|
+
|
263
|
+
IMPORT_SH = <<-EOF
|
264
|
+
#!/usr/bin/expect -f
|
265
|
+
|
266
|
+
set key [lindex $argv 0];
|
267
|
+
set geth [lindex $argv 1];
|
268
|
+
|
269
|
+
spawn $geth --datadir data account import $key
|
270
|
+
expect "Passphrase:"
|
271
|
+
send "123456\r"
|
272
|
+
expect "Repeat Passphrase:"
|
273
|
+
send "123456\r"
|
274
|
+
interact
|
275
|
+
EOF
|
276
|
+
|
277
|
+
RAKE_FILE = <<-EOF
|
278
|
+
require 'rake/testtask'
|
279
|
+
|
280
|
+
Rake::TestTask.new do |t|
|
281
|
+
t.libs += %w(lib test)
|
282
|
+
t.test_files = FileList['tests/**/*_test.rb']
|
283
|
+
t.verbose = true
|
284
|
+
end
|
285
|
+
|
286
|
+
task default: [:test]
|
287
|
+
EOF
|
288
|
+
|
63
289
|
def new
|
64
290
|
name = ARGV.shift
|
65
291
|
if name
|
66
292
|
puts "Creating project #{name}..."
|
67
|
-
system("mkdir #{name}")
|
293
|
+
system("mkdir #{name} && cd #{name} && mkdir private_keys && mkdir builds && mkdir contracts && mkdir bin && mkdir tests")
|
68
294
|
gemfile = GEMFILE_TEMPLATE.result(binding)
|
69
|
-
File.open("#{name}/Gemfile", "w+") {|f| f.write(gemfile) }
|
70
|
-
system("cd #{name} &&
|
295
|
+
File.open("#{name}/Gemfile", "w+") { |f| f.write(gemfile) }
|
296
|
+
system("cd #{name} && bundle install")
|
297
|
+
File.open("#{name}/genesis.json", "w+") { |f| f.write(GENESIS_TEMPLATE) }
|
298
|
+
|
299
|
+
KEYS_TEMPLATE.each do |k, v|
|
300
|
+
File.open("#{name}/private_keys/#{k}.key", "w+") { |f| f.write(v) }
|
301
|
+
end
|
302
|
+
File.open("#{name}/rakefile", "w+") { |f| f.write(RAKE_FILE) }
|
303
|
+
|
304
|
+
File.open("#{name}/bin/attach.sh", "w+", 0777) { |f| f.write(ATTACH_SH) }
|
305
|
+
|
306
|
+
File.open("#{name}/bin/build.sh", "w+", 0777) { |f| f.write(BUILD_SH) }
|
307
|
+
|
308
|
+
File.open("#{name}/bin/import_keys.sh", "w+", 0777) { |f| f.write(IMPORT_KEYS_SH) }
|
309
|
+
|
310
|
+
File.open("#{name}/bin/init.sh", "w+", 0777) { |f| f.write(INIT_SH) }
|
311
|
+
|
312
|
+
File.open("#{name}/bin/private_blockchain.sh", "w+", 0777) { |f| f.write(PRIVATE_BLOCKCHAIN_SH) }
|
313
|
+
|
314
|
+
File.open("#{name}/bin/test.sh", "w+", 0777) { |f| f.write(TEST_SH) }
|
315
|
+
|
316
|
+
File.open("#{name}/private_keys/import.sh", "w+", 0777) { |f| f.write(IMPORT_SH) }
|
317
|
+
|
318
|
+
File.open("#{name}/bin/solc_helper.rb", "w+", 0777) { |f| f.write(SOLC_HELPER_TEMPLATE) }
|
71
319
|
puts "You are flying..."
|
72
320
|
else
|
73
321
|
puts "Need project name"
|
@@ -79,10 +327,10 @@ def generate
|
|
79
327
|
if name
|
80
328
|
contract = CONTRACT_TEMPLATE.result(binding)
|
81
329
|
puts "Create #{name.capitalize}.sol contract file..."
|
82
|
-
File.open("contracts/#{name.capitalize}.sol", "w+") {|f| f.write(contract) }
|
330
|
+
File.open("contracts/#{name.capitalize}.sol", "w+") { |f| f.write(contract) }
|
83
331
|
test = TEST_TEMPLATE.result(binding)
|
84
332
|
puts "Create #{name}_test.rb test file..."
|
85
|
-
File.open("tests/#{name.capitalize}_test.rb", "w+") {|f| f.write(test) }
|
333
|
+
File.open("tests/#{name.capitalize}_test.rb", "w+") { |f| f.write(test) }
|
86
334
|
puts "You are flying..."
|
87
335
|
else
|
88
336
|
puts "Need contract name!"
|
@@ -91,9 +339,40 @@ end
|
|
91
339
|
|
92
340
|
def test
|
93
341
|
name = ARGV.shift
|
94
|
-
|
95
|
-
|
96
|
-
|
342
|
+
if name
|
343
|
+
puts "Test #{name.capitalize} contract..."
|
344
|
+
system("bundle exec ruby -Ilib:test tests/#{name}_test.rb")
|
345
|
+
else
|
346
|
+
puts "Test all contracts..."
|
347
|
+
system("bundle exec rake")
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
def init
|
352
|
+
system("./bin/init.sh")
|
353
|
+
end
|
354
|
+
|
355
|
+
def import_keys
|
356
|
+
system("./bin/import_keys.sh")
|
357
|
+
end
|
358
|
+
|
359
|
+
def build
|
360
|
+
system("./bin/build.sh")
|
361
|
+
end
|
362
|
+
|
363
|
+
def server
|
364
|
+
system("./bin/private_blockchain.sh")
|
365
|
+
end
|
366
|
+
|
367
|
+
def migrate
|
368
|
+
end
|
369
|
+
|
370
|
+
def console
|
371
|
+
system("./bin/attach.sh")
|
372
|
+
end
|
373
|
+
|
374
|
+
def geth_test
|
375
|
+
system("./bin/test.sh")
|
97
376
|
end
|
98
377
|
|
99
378
|
def help
|
@@ -113,4 +392,14 @@ def parse_command(command)
|
|
113
392
|
end
|
114
393
|
end
|
115
394
|
|
395
|
+
def run_command!(command)
|
396
|
+
command = parse_command(command)
|
397
|
+
|
398
|
+
if COMMAND_WHITELIST.include?(command)
|
399
|
+
send(command)
|
400
|
+
else
|
401
|
+
help
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
116
405
|
run_command!(command)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ether-fly
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Zhang YaNing
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-09-
|
11
|
+
date: 2016-09-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-ethereum
|
@@ -38,8 +38,9 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '5.8'
|
41
|
-
description: EtherFly is a Ethereum smart contract test framework in ruby.
|
42
|
-
|
41
|
+
description: 'EtherFly is a Ethereum smart contract test framework in ruby.It provides
|
42
|
+
two testing environments: testing in ruby EVM and testing in geth.You don''t need
|
43
|
+
to understand ruby grammar, just enjoy syntactic sugar.'
|
43
44
|
email:
|
44
45
|
- zhangyaning1985@gmail.com
|
45
46
|
executables:
|