mirror of
https://github.com/embarklabs/embark.git
synced 2025-01-11 14:24:24 +00:00
Merge branch 'develop'
This commit is contained in:
commit
87a8fc7eab
@ -23,7 +23,7 @@ module.exports = (grunt) ->
|
|||||||
src: ['test/**/*.js']
|
src: ['test/**/*.js']
|
||||||
|
|
||||||
grunt.loadTasks "tasks"
|
grunt.loadTasks "tasks"
|
||||||
require('matchdep').filterAll('grunt-*').forEach(grunt.loadNpmTasks)
|
require('matchdep').filterAll(['grunt-*','!grunt-cli']).forEach(grunt.loadNpmTasks)
|
||||||
|
|
||||||
grunt.registerTask 'default', ['clean']
|
grunt.registerTask 'default', ['clean']
|
||||||
grunt.registerTask 'build', ['clean', 'coffee']
|
grunt.registerTask 'build', ['clean', 'coffee']
|
||||||
|
83
README.md
83
README.md
@ -7,15 +7,17 @@ Embark is a framework that allows you to easily develop and deploy DApps.
|
|||||||
|
|
||||||
With Embark you can:
|
With Embark you can:
|
||||||
* Automatically deploy contracts and make them available in your JS code. Embark watches for changes, and if you update a contract, Embark will automatically redeploy the contracts (if needed) and the dapp.
|
* Automatically deploy contracts and make them available in your JS code. Embark watches for changes, and if you update a contract, Embark will automatically redeploy the contracts (if needed) and the dapp.
|
||||||
|
* Use any build pipeline or tool you wish, including grunt and meteor.
|
||||||
* Do Test Driven Development with Contracts using Javascript.
|
* Do Test Driven Development with Contracts using Javascript.
|
||||||
* Easily deploy to & use decentralized systems such as IPFS.
|
* Easily deploy to & use decentralized systems such as IPFS.
|
||||||
|
* Keep track of deployed contracts, deploy only when truly needed.
|
||||||
* Quickly create advanced DApps using multiple contracts.
|
* Quickly create advanced DApps using multiple contracts.
|
||||||
|
|
||||||
See the [Wiki](https://github.com/iurimatias/embark-framework/wiki) for more details.
|
See the [Wiki](https://github.com/iurimatias/embark-framework/wiki) for more details.
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
======
|
======
|
||||||
Requirements: geth (1.0.0), solc (0.9.23), node (0.12.2) and npm
|
Requirements: geth (1.0.0), solc (0.1.0) or serpent (develop), node (0.12.2) and npm
|
||||||
|
|
||||||
For specs: pyethereum, ethertdd.py
|
For specs: pyethereum, ethertdd.py
|
||||||
|
|
||||||
@ -49,6 +51,8 @@ This will automatically deploy the contracts, update their JS bindings and deplo
|
|||||||
|
|
||||||
Note that if you update your code it will automatically be re-deployed, contracts included. There is no need to restart embark, refreshing the page on the browser will do.
|
Note that if you update your code it will automatically be re-deployed, contracts included. There is no need to restart embark, refreshing the page on the browser will do.
|
||||||
|
|
||||||
|
note: for a demo using meteor do ```embark meteor_demo``` followed by ```embark deploy``` then ```meteor```
|
||||||
|
|
||||||
Creating a new DApp
|
Creating a new DApp
|
||||||
======
|
======
|
||||||
|
|
||||||
@ -62,7 +66,7 @@ DApp Structure
|
|||||||
|
|
||||||
```Bash
|
```Bash
|
||||||
app/
|
app/
|
||||||
|___ contracts/ #solidity contracts
|
|___ contracts/ #solidity or serpent contracts
|
||||||
|___ html/
|
|___ html/
|
||||||
|___ css/
|
|___ css/
|
||||||
|___ js/
|
|___ js/
|
||||||
@ -74,7 +78,7 @@ DApp Structure
|
|||||||
|___ contracts/ #contracts tests
|
|___ contracts/ #contracts tests
|
||||||
```
|
```
|
||||||
|
|
||||||
Solidity files in the contracts directory will automatically be deployed with embark run. Changes in any files will automatically be reflected in app, changes to contracts will result in a redeployment and update of their JS Bindings
|
Solidity/Serpent files in the contracts directory will automatically be deployed with embark run. Changes in any files will automatically be reflected in app, changes to contracts will result in a redeployment and update of their JS Bindings
|
||||||
|
|
||||||
Using Contracts
|
Using Contracts
|
||||||
======
|
======
|
||||||
@ -145,6 +149,7 @@ You can now deploy many instances of the same contract. e.g
|
|||||||
# config/contracts.yml
|
# config/contracts.yml
|
||||||
development:
|
development:
|
||||||
Currency:
|
Currency:
|
||||||
|
deploy: false
|
||||||
args:
|
args:
|
||||||
- 100
|
- 100
|
||||||
Usd:
|
Usd:
|
||||||
@ -171,16 +176,44 @@ Contracts addresses can be defined, If an address is defined the contract wouldn
|
|||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can also define contract interfaces (Stubs) and actions to do on deployment
|
||||||
|
|
||||||
|
```Yaml
|
||||||
|
development:
|
||||||
|
DataSource:
|
||||||
|
args:
|
||||||
|
MyDataSource:
|
||||||
|
args:
|
||||||
|
instanceOf: DataSource
|
||||||
|
Manager:
|
||||||
|
stubs:
|
||||||
|
- DataSource
|
||||||
|
args:
|
||||||
|
- $MyDataSource
|
||||||
|
onDeploy:
|
||||||
|
- Manager.updateStorage($MyDataSource)
|
||||||
|
- MyDataSource.set(5)
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
Tests
|
Tests
|
||||||
======
|
======
|
||||||
|
|
||||||
You can run specs with ```embark spec```, it will run any files ending *_spec.js under ```spec/```.
|
You can run specs with ```embark spec```, it will run any files ending *_spec.js under ```spec/```.
|
||||||
|
|
||||||
Embark includes a testing lib to fastly run & test your contracts in a EVM.
|
Embark includes a testing lib to fastly run & test your contracts in a EVM.
|
||||||
|
|
||||||
```Javascript
|
```Javascript
|
||||||
# spec/contracts/simple_storage_spec.js
|
# spec/contracts/simple_storage_spec.js
|
||||||
EmbarkSpec = require('embark-framework').Tests;
|
Embark = require('embark-framework');
|
||||||
|
Embark.init();
|
||||||
|
Embark.blockchainConfig.loadConfigFile('config/blockchain.yml');
|
||||||
|
Embark.contractsConfig.loadConfigFile('config/contracts.yml');
|
||||||
|
|
||||||
|
var files = ['app/contracts/simpleStorage.sol'];
|
||||||
|
Embark.contractsConfig.init(files, 'development');
|
||||||
|
|
||||||
|
var EmbarkSpec = Embark.tests(files);
|
||||||
|
|
||||||
describe("SimpleStorage", function() {
|
describe("SimpleStorage", function() {
|
||||||
beforeAll(function() {
|
beforeAll(function() {
|
||||||
@ -222,6 +255,7 @@ The environment is a specific blockchain configuration that can be managed at co
|
|||||||
rpc_port: 8101
|
rpc_port: 8101
|
||||||
rpc_whitelist: "*"
|
rpc_whitelist: "*"
|
||||||
datadir: default
|
datadir: default
|
||||||
|
chains: chains_staging.json
|
||||||
network_id: 0
|
network_id: 0
|
||||||
console: true
|
console: true
|
||||||
account:
|
account:
|
||||||
@ -231,7 +265,6 @@ The environment is a specific blockchain configuration that can be managed at co
|
|||||||
|
|
||||||
See [Configuration](https://github.com/iurimatias/embark-framework/wiki/Configuration).
|
See [Configuration](https://github.com/iurimatias/embark-framework/wiki/Configuration).
|
||||||
|
|
||||||
|
|
||||||
Deploying only contracts
|
Deploying only contracts
|
||||||
======
|
======
|
||||||
Although embark run will automatically deploy contracts, you can choose to only deploy the contracts to a specific environment
|
Although embark run will automatically deploy contracts, you can choose to only deploy the contracts to a specific environment
|
||||||
@ -242,6 +275,26 @@ $ embark deploy privatenet
|
|||||||
|
|
||||||
embark deploy will deploy all contracts at app/contracts and return the resulting addresses
|
embark deploy will deploy all contracts at app/contracts and return the resulting addresses
|
||||||
|
|
||||||
|
Structuring Application
|
||||||
|
======
|
||||||
|
|
||||||
|
Embark is quite flexible and you can configure you're own directory structure using ```embark.yml```
|
||||||
|
|
||||||
|
```Yaml
|
||||||
|
# embark.yml
|
||||||
|
type: "manual" #other options: meteor, grunt
|
||||||
|
contracts: ["app/contracts/**/*.sol", "app/contracts/**/*.se"] # contracts files
|
||||||
|
output: "src/embark.js" # resulting javascript interface
|
||||||
|
blockchainConfig: "config/blockchain.yml" # blockchain config
|
||||||
|
contractsConfig: "config/contracts.yml" # contracts config
|
||||||
|
```
|
||||||
|
|
||||||
|
Deploying to IPFS
|
||||||
|
======
|
||||||
|
|
||||||
|
To deploy a dapp to IPFS, all you need to do is run a local IPFS node and then run ```embark ipfs```.
|
||||||
|
If you want to deploy to the live net then after configuring you account on ```config/blockchain.yml``` on the ```production``` environment then you can deploy to that chain by specifying the environment ```embark ipfs production```.
|
||||||
|
|
||||||
LiveReload Plugin
|
LiveReload Plugin
|
||||||
======
|
======
|
||||||
|
|
||||||
@ -255,5 +308,19 @@ Because embark is internally using grunt tasks, debugging is not straightforward
|
|||||||
- normally you would write something like `node-debug -p 7000 embark -- deploy`
|
- normally you would write something like `node-debug -p 7000 embark -- deploy`
|
||||||
- This gives you nothing with embark. If you look at `deploy` command in [`./bin/embark`](https://github.com/iurimatias/embark-framework/blob/develop/bin/embark#L32-L35) you will notice that it internally runs grunt task `grunt deploy_contracts:[env]`
|
- This gives you nothing with embark. If you look at `deploy` command in [`./bin/embark`](https://github.com/iurimatias/embark-framework/blob/develop/bin/embark#L32-L35) you will notice that it internally runs grunt task `grunt deploy_contracts:[env]`
|
||||||
- with this knowledge we can prepare proper command to start debugging
|
- with this knowledge we can prepare proper command to start debugging
|
||||||
- `node-debug -p 7000 grunt -- deploy_contracts:development`
|
- ```node-debug -p 7000 grunt -- deploy_contracts:development```
|
||||||
- [here](https://github.com/iurimatias/embark-framework/blob/develop/tasks/tasks.coffee) is list of all debuggable grunt tasks
|
|
||||||
|
|
||||||
|
[here](https://github.com/iurimatias/embark-framework/blob/develop/tasks/tasks.coffee) is list of all debuggable grunt tasks
|
||||||
|
|
||||||
|
EACCESS Error
|
||||||
|
======
|
||||||
|
If you get EACCES (access denied) errors, don't use sudo, try this:
|
||||||
|
|
||||||
|
```Bash
|
||||||
|
$ mkdir ~/npm-global
|
||||||
|
$ npm config set prefix ~/npm-global
|
||||||
|
$ echo 'export PATH="$PATH:$HOME/npm-global/bin"' >>~/.bashrc
|
||||||
|
$ source ~/.bashrc
|
||||||
|
$ npm install -g embark-framework grunt-cli
|
||||||
|
```
|
||||||
|
25
bin/embark
Normal file → Executable file
25
bin/embark
Normal file → Executable file
@ -6,7 +6,7 @@ var wrench = require('wrench');
|
|||||||
var grunt = require('grunt');
|
var grunt = require('grunt');
|
||||||
require('shelljs/global');
|
require('shelljs/global');
|
||||||
var readYaml = require('read-yaml');
|
var readYaml = require('read-yaml');
|
||||||
var Embark = require('embark-framework');
|
var Embark = require('..');
|
||||||
|
|
||||||
var run = function(cmd) {
|
var run = function(cmd) {
|
||||||
if (exec(cmd).code != 0) {
|
if (exec(cmd).code != 0) {
|
||||||
@ -17,22 +17,19 @@ var run = function(cmd) {
|
|||||||
var deploy = function(env, embarkConfig) {
|
var deploy = function(env, embarkConfig) {
|
||||||
var contractFiles = grunt.file.expand(embarkConfig.contracts);
|
var contractFiles = grunt.file.expand(embarkConfig.contracts);
|
||||||
var destFile = embarkConfig.output;
|
var destFile = embarkConfig.output;
|
||||||
var chainFile = embarkConfig.chains;
|
|
||||||
|
|
||||||
Embark.init();
|
Embark.init();
|
||||||
Embark.blockchainConfig.loadConfigFile(embarkConfig.blockchainConfig);
|
Embark.blockchainConfig.loadConfigFile(embarkConfig.blockchainConfig);
|
||||||
Embark.contractsConfig.loadConfigFile(embarkConfig.contractsConfig);
|
Embark.contractsConfig.loadConfigFile(embarkConfig.contractsConfig);
|
||||||
|
|
||||||
if (chainFile === undefined) {
|
var chainFile = Embark.blockchainConfig.blockchainConfig[env].chains || embarkConfig.chains || './chains.json';
|
||||||
chainFile = './chains.json';
|
|
||||||
}
|
|
||||||
|
|
||||||
abi = Embark.deployContracts(env, contractFiles, destFile, chainFile);
|
abi = Embark.deployContracts(env, contractFiles, destFile, chainFile);
|
||||||
grunt.file.write(destFile, abi);
|
grunt.file.write(destFile, abi);
|
||||||
}
|
}
|
||||||
|
|
||||||
program
|
program
|
||||||
.version('0.8.4')
|
.version('0.9.1')
|
||||||
|
|
||||||
program.command('new [name]').description('New application').action(function(name) {
|
program.command('new [name]').description('New application').action(function(name) {
|
||||||
if (name === undefined) {
|
if (name === undefined) {
|
||||||
@ -132,13 +129,24 @@ program.command('blockchain [env]').description('run blockchain').action(functio
|
|||||||
Embark.blockchainConfig.loadConfigFile(embarkConfig.blockchainConfig)
|
Embark.blockchainConfig.loadConfigFile(embarkConfig.blockchainConfig)
|
||||||
Embark.contractsConfig.loadConfigFile(embarkConfig.contractsConfig)
|
Embark.contractsConfig.loadConfigFile(embarkConfig.contractsConfig)
|
||||||
|
|
||||||
//TODO: better with --exec, but need to fix console bug first
|
Embark.copyMinerJavascriptToTemp();
|
||||||
wrench.copyDirSyncRecursive(__dirname + "/../js", "/tmp/js", {forceDelete: true});
|
|
||||||
|
|
||||||
Embark.startBlockchain(env, true);
|
Embark.startBlockchain(env, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
program.command('geth <env> [args...]').description('run geth with specified arguments').action(function(env_, args_) {
|
||||||
|
var env = env_ || 'development';
|
||||||
|
var embarkConfig = readYaml.sync("./embark.yml");
|
||||||
|
var args = args_.join(' ');
|
||||||
|
|
||||||
|
Embark.init()
|
||||||
|
Embark.blockchainConfig.loadConfigFile(embarkConfig.blockchainConfig)
|
||||||
|
Embark.contractsConfig.loadConfigFile(embarkConfig.contractsConfig)
|
||||||
|
|
||||||
|
Embark.geth(env, args);
|
||||||
|
});
|
||||||
|
|
||||||
program.command('demo').description('create a working dapp with a SimpleStorage contract').action(function() {
|
program.command('demo').description('create a working dapp with a SimpleStorage contract').action(function() {
|
||||||
var boilerPath = path.join(__dirname + '/../boilerplate');
|
var boilerPath = path.join(__dirname + '/../boilerplate');
|
||||||
var demoPath = path.join(__dirname + '/../demo');
|
var demoPath = path.join(__dirname + '/../demo');
|
||||||
@ -169,4 +177,3 @@ if (!process.argv.slice(2).length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
exit();
|
exit();
|
||||||
|
|
||||||
|
2
boilerplate/.gitignore
vendored
Normal file
2
boilerplate/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
node_modules/
|
||||||
|
chains/development.json
|
@ -33,6 +33,7 @@ module.exports = (grunt) ->
|
|||||||
contracts:
|
contracts:
|
||||||
src: [
|
src: [
|
||||||
"app/contracts/**/*.sol"
|
"app/contracts/**/*.sol"
|
||||||
|
"app/contracts/**/*.se"
|
||||||
]
|
]
|
||||||
|
|
||||||
coffee:
|
coffee:
|
||||||
|
@ -5,6 +5,7 @@ development:
|
|||||||
minerthreads: 1
|
minerthreads: 1
|
||||||
genesis_block: config/genesis/dev_genesis.json
|
genesis_block: config/genesis/dev_genesis.json
|
||||||
datadir: /tmp/embark
|
datadir: /tmp/embark
|
||||||
|
chains: config/chains/development.json
|
||||||
mine_when_needed: true
|
mine_when_needed: true
|
||||||
max_peers: 0
|
max_peers: 0
|
||||||
gas_limit: 500000
|
gas_limit: 500000
|
||||||
|
1
boilerplate/config/chains/development.json
Normal file
1
boilerplate/config/chains/development.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
@ -1,10 +1,11 @@
|
|||||||
{
|
{
|
||||||
"nonce": "0x0000000000000042",
|
"nonce": "0x0000000000000042",
|
||||||
"difficulty": "0x40000",
|
"difficulty": "0x0",
|
||||||
"alloc": {
|
"alloc": {
|
||||||
|
"0x3333333333333333333333333333333333333333": {"balance": "15000000000000000000"}
|
||||||
},
|
},
|
||||||
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"coinbase": "0x0000000000000000000000000000000000000000",
|
"coinbase": "0x3333333333333333333333333333333333333333",
|
||||||
"timestamp": "0x00",
|
"timestamp": "0x00",
|
||||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"extraData": "0x",
|
"extraData": "0x",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
type: "grunt" #other options: meteor, manual
|
type: "grunt" #other options: meteor, manual
|
||||||
#contracts: ["app/contracts/**/*.sol"]
|
#contracts: ["app/contracts/**/*.sol", "app/contracts/**/*.se"]
|
||||||
#output: "src/embark.js"
|
#output: "src/embark.js"
|
||||||
#blockchainConfig: "config/blockchain.yml"
|
#blockchainConfig: "config/blockchain.yml"
|
||||||
#contractsConfig: "config/contracts.yml"
|
#contractsConfig: "config/contracts.yml"
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"homepage": "",
|
"homepage": "",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"embark-framework": "^0.8.4",
|
"embark-framework": "^0.9.1",
|
||||||
"grunt-embark": "^0.3.0",
|
"grunt-embark": "^0.4.1",
|
||||||
"grunt-contrib-clean": "^0.6.0",
|
"grunt-contrib-clean": "^0.6.0",
|
||||||
"grunt-contrib-coffee": "^0.13.0",
|
"grunt-contrib-coffee": "^0.13.0",
|
||||||
"grunt-contrib-concat": "^0.5.1",
|
"grunt-contrib-concat": "^0.5.1",
|
||||||
|
@ -5,6 +5,7 @@ development:
|
|||||||
minerthreads: 1
|
minerthreads: 1
|
||||||
genesis_block: config/genesis/dev_genesis.json
|
genesis_block: config/genesis/dev_genesis.json
|
||||||
datadir: /tmp/embark
|
datadir: /tmp/embark
|
||||||
|
chains: config/chains/development.json
|
||||||
mine_when_needed: true
|
mine_when_needed: true
|
||||||
gas_limit: 500000
|
gas_limit: 500000
|
||||||
gas_price: 10000000000000
|
gas_price: 10000000000000
|
||||||
|
1
demo/config/chains/development.json
Normal file
1
demo/config/chains/development.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
@ -1,5 +1,5 @@
|
|||||||
type: "meteor"
|
type: "meteor"
|
||||||
contracts: ["contracts/**/*.sol"]
|
contracts: ["contracts/**/*.sol", "contracts/**/*.se"]
|
||||||
output: "client/embark.js"
|
output: "client/embark.js"
|
||||||
blockchainConfig: "config/blockchain.yml"
|
blockchainConfig: "config/blockchain.yml"
|
||||||
contractsConfig: "config/contracts.yml"
|
contractsConfig: "config/contracts.yml"
|
||||||
|
148
js/mine.js
148
js/mine.js
@ -1,16 +1,75 @@
|
|||||||
var miner_var;
|
// Adapted from Iuri Matias' Embark framework
|
||||||
|
// https://github.com/iurimatias/embark-framework
|
||||||
|
// Modified by ryepdx to mine at regular intervals.
|
||||||
|
(function() {
|
||||||
|
var main = function () {
|
||||||
|
/* TODO: Find a way to load mining config from YML.
|
||||||
|
|
||||||
if (admin.miner === undefined) {
|
if (!loadScript("config.js")) {
|
||||||
miner_var = miner;
|
console.log("== config.js not found");
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
miner_var = admin.miner;
|
|
||||||
}
|
|
||||||
|
|
||||||
miner_var.setEtherbase(web3.eth.accounts[0]);
|
if (typeof(config) === "undefined") {
|
||||||
|
config = {};
|
||||||
|
console.log("== config is undefined, proceeding with defaults");
|
||||||
|
}
|
||||||
|
|
||||||
|
In the meantime, just set an empty config object.
|
||||||
|
*/
|
||||||
|
config = {}
|
||||||
|
|
||||||
|
defaults = {
|
||||||
|
interval_ms: 15000,
|
||||||
|
initial_ether: 15000000000000000000,
|
||||||
|
mine_pending_txns: true,
|
||||||
|
mine_periodically: false,
|
||||||
|
mine_normally: false,
|
||||||
|
threads: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
for (key in defaults) {
|
||||||
|
if (config[key] === undefined) {
|
||||||
|
config[key] = defaults[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var miner_obj = (admin.miner === undefined) ? miner : admin.miner;
|
||||||
|
|
||||||
|
if (config.mine_normally) {
|
||||||
|
miner_obj.start(config.threads);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
miner_obj.stop();
|
||||||
|
|
||||||
|
fundAccount(config, miner_obj, function () {
|
||||||
|
if (config.mine_periodically) start_periodic_mining(config, miner_obj);
|
||||||
|
if (config.mine_pending_txns) start_transaction_mining(config, miner_obj);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var fundAccount = function (config, miner_obj, cb) {
|
||||||
|
var accountFunded = function () {
|
||||||
|
return (eth.getBalance(eth.coinbase) >= config.initial_ether);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountFunded()) {
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("== Funding account");
|
||||||
|
miner_obj.start();
|
||||||
|
|
||||||
|
var blockWatcher = web3.eth.filter("latest").watch(function () {
|
||||||
|
if (accountFunded()) {
|
||||||
|
console.log("== Account funded");
|
||||||
|
|
||||||
|
blockWatcher.stopWatching();
|
||||||
|
miner_obj.stop();
|
||||||
|
cb();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
setInterval(function() {
|
|
||||||
var minimalAmount = (web3.eth.getBalance(web3.eth.coinbase) >= 15000000000000000000);
|
|
||||||
var pendingTransactions = function() {
|
var pendingTransactions = function() {
|
||||||
if (web3.eth.pendingTransactions === undefined || web3.eth.pendingTransactions === null) {
|
if (web3.eth.pendingTransactions === undefined || web3.eth.pendingTransactions === null) {
|
||||||
return txpool.status.pending || txpool.status.queued;
|
return txpool.status.pending || txpool.status.queued;
|
||||||
@ -21,19 +80,60 @@ setInterval(function() {
|
|||||||
else {
|
else {
|
||||||
return web3.eth.pendingTransactions.length > 0 || web3.eth.getBlock('pending').transactions.length > 0;
|
return web3.eth.pendingTransactions.length > 0 || web3.eth.getBlock('pending').transactions.length > 0;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
if(!web3.eth.mining && (!minimalAmount || pendingTransactions())) {
|
var start_periodic_mining = function (config, miner_obj) {
|
||||||
if (!minimalAmount) { console.log("=== minimal ether amount not reached yet") }
|
var last_mined_ms = Date.now();
|
||||||
if (pendingTransactions()) { console.log("=== there are pending transactions") }
|
var timeout_set = false;
|
||||||
console.log("=== start mining");
|
|
||||||
miner_var.start();
|
|
||||||
}
|
|
||||||
else if (web3.eth.mining && minimalAmount && !pendingTransactions()) {
|
|
||||||
if (minimalAmount) { console.log("=== minimal ether amount reached") }
|
|
||||||
if (!pendingTransactions()) { console.log("=== no pending transactions") }
|
|
||||||
console.log("=== stop mining");
|
|
||||||
miner_var.stop();
|
|
||||||
}
|
|
||||||
}, 1000)
|
|
||||||
|
|
||||||
|
miner_obj.start(config.threads);
|
||||||
|
web3.eth.filter("latest").watch(function () {
|
||||||
|
if ((config.mine_pending_txns && pendingTransactions()) || timeout_set) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
timeout_set = true;
|
||||||
|
|
||||||
|
var now = Date.now();
|
||||||
|
var ms_since_block = now - last_mined_ms;
|
||||||
|
last_mined_ms = now;
|
||||||
|
|
||||||
|
var next_block_in_ms;
|
||||||
|
|
||||||
|
if (ms_since_block > config.interval_ms) {
|
||||||
|
next_block_in_ms = 0;
|
||||||
|
} else {
|
||||||
|
next_block_in_ms = (config.interval_ms - ms_since_block);
|
||||||
|
}
|
||||||
|
|
||||||
|
miner_obj.stop();
|
||||||
|
console.log("== Looking for next block in " + next_block_in_ms + "ms");
|
||||||
|
|
||||||
|
setTimeout(function () {
|
||||||
|
console.log("== Looking for next block");
|
||||||
|
timeout_set = false;
|
||||||
|
miner_obj.start(config.threads);
|
||||||
|
}, next_block_in_ms);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var start_transaction_mining = function (config, miner_obj) {
|
||||||
|
web3.eth.filter("pending").watch(function () {
|
||||||
|
if (miner_obj.hashrate > 0) return;
|
||||||
|
|
||||||
|
console.log("== Pending transactions! Looking for next block...");
|
||||||
|
miner_obj.start(config.threads);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (config.mine_periodically) return;
|
||||||
|
|
||||||
|
web3.eth.filter("latest").watch(function () {
|
||||||
|
if (!pendingTransactions()) {
|
||||||
|
console.log("== No transactions left. Stopping miner...");
|
||||||
|
miner_obj.stop();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
main();
|
||||||
|
})();
|
||||||
|
@ -9,6 +9,7 @@ Blockchain.prototype.generate_basic_command = function() {
|
|||||||
var address = config.account.address;
|
var address = config.account.address;
|
||||||
|
|
||||||
var cmd = "geth ";
|
var cmd = "geth ";
|
||||||
|
var rpc_api = ['eth', 'web3'];
|
||||||
|
|
||||||
if (config.datadir !== "default") {
|
if (config.datadir !== "default") {
|
||||||
cmd += "--datadir=\"" + config.datadir + "\" ";
|
cmd += "--datadir=\"" + config.datadir + "\" ";
|
||||||
@ -31,6 +32,13 @@ Blockchain.prototype.generate_basic_command = function() {
|
|||||||
cmd += "--genesis=\"" + config.genesisBlock + "\" ";
|
cmd += "--genesis=\"" + config.genesisBlock + "\" ";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.whisper) {
|
||||||
|
cmd += "--shh ";
|
||||||
|
rpc_api.push('shh')
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd += '--rpcapi "' + rpc_api.join(',') + '" ';
|
||||||
|
|
||||||
//TODO: this should be configurable
|
//TODO: this should be configurable
|
||||||
cmd += "--maxpeers " + config.maxPeers + " ";
|
cmd += "--maxpeers " + config.maxPeers + " ";
|
||||||
|
|
||||||
@ -49,6 +57,10 @@ Blockchain.prototype.init_command = function() {
|
|||||||
return this.generate_basic_command() + "account new ";
|
return this.generate_basic_command() + "account new ";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Blockchain.prototype.geth_command = function(geth_args) {
|
||||||
|
return this.generate_basic_command() + geth_args;
|
||||||
|
}
|
||||||
|
|
||||||
Blockchain.prototype.run_command = function(address, use_tmp) {
|
Blockchain.prototype.run_command = function(address, use_tmp) {
|
||||||
var cmd = this.generate_basic_command();
|
var cmd = this.generate_basic_command();
|
||||||
var config = this.config;
|
var config = this.config;
|
||||||
@ -108,4 +120,15 @@ Blockchain.prototype.startChain = function(use_tmp) {
|
|||||||
exec(this.run_command(address, use_tmp));
|
exec(this.run_command(address, use_tmp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Blockchain.prototype.execGeth = function(args) {
|
||||||
|
var cmd = this.geth_command(args);
|
||||||
|
console.log("executing: " + cmd);
|
||||||
|
exec(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
Blockchain.prototype.getStartChainCommand = function(use_tmp) {
|
||||||
|
var address = this.get_address();
|
||||||
|
return this.run_command(address, use_tmp);
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = Blockchain
|
module.exports = Blockchain
|
||||||
|
@ -6,6 +6,7 @@ ChainManager = function() {
|
|||||||
this.chainManagerConfig = {};
|
this.chainManagerConfig = {};
|
||||||
this.currentChain = {};
|
this.currentChain = {};
|
||||||
this.file = "";
|
this.file = "";
|
||||||
|
this.web3 = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChainManager.prototype.loadConfigFile = function(filename) {
|
ChainManager.prototype.loadConfigFile = function(filename) {
|
||||||
@ -34,6 +35,7 @@ ChainManager.prototype.init = function(env, config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.currentChain = this.chainManagerConfig[chainId];
|
this.currentChain = this.chainManagerConfig[chainId];
|
||||||
|
this.web3 = web3;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChainManager.prototype.addContract = function(contractName, code, args, address) {
|
ChainManager.prototype.addContract = function(contractName, code, args, address) {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
var shelljs = require('shelljs');
|
||||||
|
var shelljs_global = require('shelljs/global');
|
||||||
var web3 = require('web3');
|
var web3 = require('web3');
|
||||||
|
|
||||||
Compiler = function(blockchainConfig) {
|
Compiler = function(blockchainConfig) {
|
||||||
@ -18,8 +20,85 @@ Compiler.prototype.init = function(env) {
|
|||||||
console.log("address is : " + primaryAddress);
|
console.log("address is : " + primaryAddress);
|
||||||
};
|
};
|
||||||
|
|
||||||
Compiler.prototype.compile = function(source) {
|
Compiler.prototype.compile_solidity = function(contractFile) {
|
||||||
return web3.eth.compile.solidity(source);
|
var cmd, result, output, json, compiled_object;
|
||||||
|
|
||||||
|
cmd = "solc --input-file " + contractFile + " --combined-json binary,json-abi";
|
||||||
|
|
||||||
|
result = exec(cmd, {silent: true});
|
||||||
|
output = result.output;
|
||||||
|
|
||||||
|
if (result.code === 1) {
|
||||||
|
throw new Error(result.output);
|
||||||
|
}
|
||||||
|
|
||||||
|
json = JSON.parse(output).contracts;
|
||||||
|
compiled_object = {}
|
||||||
|
|
||||||
|
for (var className in json) {
|
||||||
|
var contract = json[className];
|
||||||
|
|
||||||
|
compiled_object[className] = {};
|
||||||
|
compiled_object[className].code = contract.binary;
|
||||||
|
compiled_object[className].info = {};
|
||||||
|
compiled_object[className].info.abiDefinition = JSON.parse(contract["json-abi"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return compiled_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
Compiler.prototype.compile_serpent = function(contractFile) {
|
||||||
|
var cmd, result, output, json, compiled_object;
|
||||||
|
|
||||||
|
cmd = "serpent compile " + contractFile;
|
||||||
|
|
||||||
|
result = exec(cmd, {silent: true});
|
||||||
|
code = result.output;
|
||||||
|
|
||||||
|
if (result.code === 1) {
|
||||||
|
throw new Error(result.output);
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = "serpent mk_full_signature " + contractFile;
|
||||||
|
result = exec(cmd, {silent: true});
|
||||||
|
|
||||||
|
if (result.code === 1) {
|
||||||
|
throw new Error(result.output);
|
||||||
|
}
|
||||||
|
|
||||||
|
json = JSON.parse(result.output.trim());
|
||||||
|
className = contractFile.split('.')[0].split("/").pop();
|
||||||
|
|
||||||
|
for (var i=0; i < json.length; i++) {
|
||||||
|
var elem = json[i];
|
||||||
|
|
||||||
|
if (elem.outputs.length > 0) {
|
||||||
|
elem.constant = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compiled_object = {}
|
||||||
|
compiled_object[className] = {};
|
||||||
|
compiled_object[className].code = code.trim();
|
||||||
|
compiled_object[className].info = {};
|
||||||
|
compiled_object[className].info.abiDefinition = json;
|
||||||
|
|
||||||
|
return compiled_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Compiler.prototype.compile = function(contractFile) {
|
||||||
|
var extension = contractFile.split('.')[1];
|
||||||
|
|
||||||
|
if (extension === 'sol') {
|
||||||
|
return this.compile_solidity(contractFile);
|
||||||
|
}
|
||||||
|
else if (extension === 'se') {
|
||||||
|
return this.compile_serpent(contractFile);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Error("extension not known");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = Compiler;
|
module.exports = Compiler;
|
||||||
|
@ -40,11 +40,13 @@ BlockchainConfig.prototype.config = function(env) {
|
|||||||
minerthreads: config.minerthreads,
|
minerthreads: config.minerthreads,
|
||||||
genesisBlock: config.genesis_block,
|
genesisBlock: config.genesis_block,
|
||||||
datadir: config.datadir,
|
datadir: config.datadir,
|
||||||
|
chains: config.chains,
|
||||||
networkId: networkId,
|
networkId: networkId,
|
||||||
maxPeers: 4,
|
maxPeers: 4,
|
||||||
port: config.port || "30303",
|
port: config.port || "30303",
|
||||||
console_toggle: config.console || false,
|
console_toggle: config.console || false,
|
||||||
mine_when_needed: config.mine_when_needed || false,
|
mine_when_needed: config.mine_when_needed || false,
|
||||||
|
whisper: config.whisper || false,
|
||||||
account: config.account
|
account: config.account
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,9 +79,8 @@ ContractsConfig.prototype.compileContracts = function(env) {
|
|||||||
// compile files
|
// compile files
|
||||||
for (j = 0; j < this.contractFiles.length; j++) {
|
for (j = 0; j < this.contractFiles.length; j++) {
|
||||||
contractFile = this.contractFiles[j];
|
contractFile = this.contractFiles[j];
|
||||||
source = fs.readFileSync(contractFile).toString()
|
|
||||||
|
|
||||||
compiled_contracts = this.compiler.compile(source);
|
compiled_contracts = this.compiler.compile(contractFile);
|
||||||
for (var className in compiled_contracts) {
|
for (var className in compiled_contracts) {
|
||||||
var contract = compiled_contracts[className];
|
var contract = compiled_contracts[className];
|
||||||
|
|
||||||
@ -133,6 +132,11 @@ ContractsConfig.prototype.compileContracts = function(env) {
|
|||||||
contract.types.push('static');
|
contract.types.push('static');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
contract.deploy = contractConfig.deploy;
|
||||||
|
if (contractConfig.deploy === undefined) {
|
||||||
|
contract.deploy = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.all_contracts.indexOf(className) < 0) {
|
if (this.all_contracts.indexOf(className) < 0) {
|
||||||
this.all_contracts.push(className);
|
this.all_contracts.push(className);
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,11 @@ Deploy.prototype.deploy_contracts = function(env) {
|
|||||||
className = all_contracts[k];
|
className = all_contracts[k];
|
||||||
contract = this.contractDB[className];
|
contract = this.contractDB[className];
|
||||||
|
|
||||||
|
if (contract.deploy === false) {
|
||||||
|
console.log("skipping " + className);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var realArgs = [];
|
var realArgs = [];
|
||||||
for (var l = 0; l < contract.args.length; l++) {
|
for (var l = 0; l < contract.args.length; l++) {
|
||||||
arg = contract.args[l];
|
arg = contract.args[l];
|
||||||
@ -77,7 +82,7 @@ Deploy.prototype.deploy_contracts = function(env) {
|
|||||||
else {
|
else {
|
||||||
var chainContract = this.chainManager.getContract(className, contract.compiled.code, realArgs);
|
var chainContract = this.chainManager.getContract(className, contract.compiled.code, realArgs);
|
||||||
|
|
||||||
if (chainContract != undefined) {
|
if (chainContract != undefined && web3.eth.getCode(chainContract.address) !== "0x") {
|
||||||
console.log("contract " + className + " is unchanged and already deployed at " + chainContract.address);
|
console.log("contract " + className + " is unchanged and already deployed at " + chainContract.address);
|
||||||
this.deployedContracts[className] = chainContract.address;
|
this.deployedContracts[className] = chainContract.address;
|
||||||
this.execute_cmds(contract.onDeploy);
|
this.execute_cmds(contract.onDeploy);
|
||||||
@ -110,13 +115,12 @@ Deploy.prototype.deploy_contracts = function(env) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log("deployed " + className + " at " + contractAddress);
|
console.log("deployed " + className + " at " + contractAddress);
|
||||||
|
this.chainManager.addContract(className, contract.compiled.code, realArgs, contractAddress);
|
||||||
|
this.chainManager.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.deployedContracts[className] = contractAddress;
|
this.deployedContracts[className] = contractAddress;
|
||||||
this.chainManager.addContract(className, contract.compiled.code, realArgs, contractAddress);
|
|
||||||
this.chainManager.save();
|
|
||||||
|
|
||||||
console.log("deployed " + className + " at " + contractAddress);
|
|
||||||
this.execute_cmds(contract.onDeploy);
|
this.execute_cmds(contract.onDeploy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -125,7 +129,7 @@ Deploy.prototype.deploy_contracts = function(env) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Deploy.prototype.execute_cmds = function(cmds) {
|
Deploy.prototype.execute_cmds = function(cmds) {
|
||||||
if (cmds.length === 0) return;
|
if (cmds == undefined || cmds.length === 0) return;
|
||||||
|
|
||||||
eval(this.generate_abi_file());
|
eval(this.generate_abi_file());
|
||||||
for (var i = 0; i < cmds.length; i++) {
|
for (var i = 0; i < cmds.length; i++) {
|
||||||
|
16
lib/index.js
16
lib/index.js
@ -35,6 +35,16 @@ Embark = {
|
|||||||
chain.startChain(use_tmp);
|
chain.startChain(use_tmp);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
copyMinerJavascriptToTemp: function(){
|
||||||
|
//TODO: better with --exec, but need to fix console bug first
|
||||||
|
wrench.copyDirSyncRecursive(__dirname + "/../js", "/tmp/js", {forceDelete: true});
|
||||||
|
},
|
||||||
|
|
||||||
|
getStartBlockchainCommand: function(env, use_tmp) {
|
||||||
|
var chain = new Blockchain(this.blockchainConfig.config(env));
|
||||||
|
return chain.getStartChainCommand(use_tmp);
|
||||||
|
},
|
||||||
|
|
||||||
deployContracts: function(env, contractFiles, destFile, chainFile) {
|
deployContracts: function(env, contractFiles, destFile, chainFile) {
|
||||||
this.contractsConfig.init(contractFiles, env);
|
this.contractsConfig.init(contractFiles, env);
|
||||||
|
|
||||||
@ -44,8 +54,12 @@ Embark = {
|
|||||||
return deploy.generate_abi_file(destFile);
|
return deploy.generate_abi_file(destFile);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
geth: function(env, args) {
|
||||||
|
var chain = new Blockchain(this.blockchainConfig.config(env));
|
||||||
|
chain.execGeth(args);
|
||||||
|
},
|
||||||
|
|
||||||
release: Release
|
release: Release
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Embark;
|
module.exports = Embark;
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "embark-framework",
|
"name": "embark-framework",
|
||||||
"version": "0.8.4",
|
"version": "0.9.1",
|
||||||
"description": "",
|
"description": "",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
@ -10,7 +10,7 @@ describe('embark.blockchain', function() {
|
|||||||
var blockchain = new Blockchain(blockchainConfig);
|
var blockchain = new Blockchain(blockchainConfig);
|
||||||
|
|
||||||
it('should return correct cmd', function() {
|
it('should return correct cmd', function() {
|
||||||
assert.strictEqual(blockchain.generate_basic_command(), "geth --datadir=\"/tmp/embark\" --logfile=\"/tmp/embark.log\" --port 30303 --rpc --rpcport 8101 --networkid "+blockchainConfig.networkId+" --rpccorsdomain \"*\" --minerthreads \"1\" --mine --genesis=\"config/genesis.json\" --maxpeers 4 --password config/password ");
|
assert.strictEqual(blockchain.generate_basic_command(), "geth --datadir=\"/tmp/embark\" --logfile=\"/tmp/embark.log\" --port 30303 --rpc --rpcport 8101 --rpcaddr localhost --networkid "+blockchainConfig.networkId+" --rpccorsdomain \"*\" --minerthreads \"1\" --mine --genesis=\"config/genesis.json\" --rpcapi \"eth,web3\" --maxpeers 4 --password config/password ");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
69
test/compiler.js
Normal file
69
test/compiler.js
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
var Compiler = require('../lib/compiler.js');
|
||||||
|
var assert = require('assert');
|
||||||
|
|
||||||
|
describe('embark.compiler', function() {
|
||||||
|
|
||||||
|
describe('compile a file', function() {
|
||||||
|
var files = [
|
||||||
|
'test/support/contracts/simple_storage.sol'
|
||||||
|
];
|
||||||
|
|
||||||
|
it("should build a correct compiled object", function() {
|
||||||
|
var compiler = new Compiler();
|
||||||
|
|
||||||
|
var compiledFile = compiler.compile(files[0]);
|
||||||
|
|
||||||
|
assert.equal(compiledFile.SimpleStorage.code, '606060405260405160208060f78339016040526060805190602001505b806000600050819055505b5060c28060356000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900480632a1afcd914604b57806360fe47b114606a5780636d4ce63c14607b576049565b005b605460045060b9565b6040518082815260200191505060405180910390f35b6079600480359060200150609a565b005b608460045060a8565b6040518082815260200191505060405180910390f35b806000600050819055505b50565b6000600060005054905060b6565b90565b6000600050548156');
|
||||||
|
|
||||||
|
assert.equal(JSON.stringify(compiledFile.SimpleStorage.info.abiDefinition), '[{"constant":true,"inputs":[],"name":"storedData","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"type":"function"},{"inputs":[{"name":"initialValue","type":"uint256"}],"type":"constructor"}]');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('compile a file with an error', function() {
|
||||||
|
var files = [
|
||||||
|
'test/support/contracts/error.sol'
|
||||||
|
];
|
||||||
|
|
||||||
|
it("throw an error", function() {
|
||||||
|
var compiler = new Compiler();
|
||||||
|
|
||||||
|
assert.throws(function() { compiler.compile(files[0]) }, Error);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('compile a serpent file', function() {
|
||||||
|
var files = [
|
||||||
|
'test/support/contracts/cash.se'
|
||||||
|
];
|
||||||
|
|
||||||
|
it("should build a correct compiled object", function() {
|
||||||
|
var compiler = new Compiler();
|
||||||
|
|
||||||
|
var compiledFile = compiler.compile(files[0]);
|
||||||
|
|
||||||
|
assert.equal(compiledFile.cash.code, '6000603f536a0186a000000000000000006040604059905901600090526000815232816020015280905020556103658061003a60003961039f56600061047f537c010000000000000000000000000000000000000000000000000000000060003504638357984f81141561005f57600435604052604060405990590160009052600081526040518160200152809050205460605260206060f35b63693200ce8114156101465760043560a05260243560c0523260e0526040604059905901600090526000815260e051816020015280905020546101005260c051610100511215156101385760c0516040604059905901600090526000815260e05181602001528090502054036040604059905901600090526000815260e0518160200152809050205560c0516040604059905901600090526000815260a05181602001528090502054016040604059905901600090526000815260a0518160200152809050205560c0516101c05260206101c0f3610145565b60006101e05260206101e0f35b5b6380b97fc081141561024c5760043560a05260243560c05260443561020052326102005114151561017e576000610220526020610220f35b6040604059905901600090526000815261020051816020015280905020546101005260c0516101005112151561023e5760c0516040604059905901600090526000815261020051816020015280905020540360406040599059016000905260008152610200518160200152809050205560c0516040604059905901600090526000815260a05181602001528090502054016040604059905901600090526000815260a0518160200152809050205560c0516102e05260206102e0f361024b565b6000610300526020610300f35b5b634c764abc8114156102b4576004356103205260243561034052610340516040604059905901600090526000815261032051816020015280905020540360406040599059016000905260008152610320518160200152809050205560016103a05260206103a0f35b63a92c9b8381141561031c57600435610320526024356103405261034051604060405990590160009052600081526103205181602001528090502054016040604059905901600090526000815261032051816020015280905020556001610400526020610400f35b631d62e92281141561036357600435604052602435610420526104205160406040599059016000905260008152604051816020015280905020556001610460526020610460f35b505b6000f3');
|
||||||
|
|
||||||
|
assert.equal(JSON.stringify(compiledFile.cash.info.abiDefinition), '[{\"name\":\"addCash(int256,int256)\",\"type\":\"function\",\"inputs\":[{\"name\":\"ID\",\"type\":\"int256\"},{\"name\":\"amount\",\"type\":\"int256\"}],\"outputs\":[{\"name\":\"out\",\"type\":\"int256\"}],\"constant\":true},{\"name\":\"balance(int256)\",\"type\":\"function\",\"inputs\":[{\"name\":\"address\",\"type\":\"int256\"}],\"outputs\":[{\"name\":\"out\",\"type\":\"int256\"}],\"constant\":true},{\"name\":\"send(int256,int256)\",\"type\":\"function\",\"inputs\":[{\"name\":\"recver\",\"type\":\"int256\"},{\"name\":\"value\",\"type\":\"int256\"}],\"outputs\":[{\"name\":\"out\",\"type\":\"int256\"}],\"constant\":true},{\"name\":\"sendFrom(int256,int256,int256)\",\"type\":\"function\",\"inputs\":[{\"name\":\"recver\",\"type\":\"int256\"},{\"name\":\"value\",\"type\":\"int256\"},{\"name\":\"from\",\"type\":\"int256\"}],\"outputs\":[{\"name\":\"out\",\"type\":\"int256\"}],\"constant\":true},{\"name\":\"setCash(int256,int256)\",\"type\":\"function\",\"inputs\":[{\"name\":\"address\",\"type\":\"int256\"},{\"name\":\"balance\",\"type\":\"int256\"}],\"outputs\":[{\"name\":\"out\",\"type\":\"int256\"}],\"constant\":true},{\"name\":\"subtractCash(int256,int256)\",\"type\":\"function\",\"inputs\":[{\"name\":\"ID\",\"type\":\"int256\"},{\"name\":\"amount\",\"type\":\"int256\"}],\"outputs\":[{\"name\":\"out\",\"type\":\"int256\"}],\"constant\":true}]');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('compile a file with an error', function() {
|
||||||
|
var files = [
|
||||||
|
'test/support/contracts/error.sol'
|
||||||
|
];
|
||||||
|
|
||||||
|
it("throw an error", function() {
|
||||||
|
var compiler = new Compiler();
|
||||||
|
|
||||||
|
assert.throws(function() { compiler.compile(files[0]) }, Error);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -43,6 +43,7 @@ describe('embark.config.blockchain', function() {
|
|||||||
minerthreads: 1,
|
minerthreads: 1,
|
||||||
genesis_block: 'config/genesis.json',
|
genesis_block: 'config/genesis.json',
|
||||||
datadir: '/tmp/embark',
|
datadir: '/tmp/embark',
|
||||||
|
chains: 'chains_development.json',
|
||||||
mine_when_needed: true,
|
mine_when_needed: true,
|
||||||
gas_limit: 123,
|
gas_limit: 123,
|
||||||
gas_price: 100,
|
gas_price: 100,
|
||||||
@ -63,9 +64,11 @@ describe('embark.config.blockchain', function() {
|
|||||||
gasLimit: 123,
|
gasLimit: 123,
|
||||||
gasPrice: 100,
|
gasPrice: 100,
|
||||||
rpcWhitelist: "*",
|
rpcWhitelist: "*",
|
||||||
|
whisper: false,
|
||||||
minerthreads: 1,
|
minerthreads: 1,
|
||||||
genesisBlock: 'config/genesis.json',
|
genesisBlock: 'config/genesis.json',
|
||||||
datadir: '/tmp/embark',
|
datadir: '/tmp/embark',
|
||||||
|
chains: 'chains_development.json',
|
||||||
networkId: 0,
|
networkId: 0,
|
||||||
maxPeers: 4,
|
maxPeers: 4,
|
||||||
port: "30303",
|
port: "30303",
|
||||||
@ -87,12 +90,13 @@ describe('embark.config.blockchain', function() {
|
|||||||
network_id: 0,
|
network_id: 0,
|
||||||
minerthreads: 1,
|
minerthreads: 1,
|
||||||
datadir: '/tmp/embark',
|
datadir: '/tmp/embark',
|
||||||
|
chains: undefined,
|
||||||
mine_when_needed: true,
|
mine_when_needed: true,
|
||||||
console: false,
|
console: false,
|
||||||
account: {
|
account: {
|
||||||
init: true,
|
init: true,
|
||||||
password: 'config/password'
|
password: 'config/password'
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
staging: {}
|
staging: {}
|
||||||
};
|
};
|
||||||
@ -105,9 +109,11 @@ describe('embark.config.blockchain', function() {
|
|||||||
gasLimit: 500000,
|
gasLimit: 500000,
|
||||||
gasPrice: 10000000000000,
|
gasPrice: 10000000000000,
|
||||||
rpcWhitelist: "*",
|
rpcWhitelist: "*",
|
||||||
|
whisper: false,
|
||||||
minerthreads: 1,
|
minerthreads: 1,
|
||||||
genesisBlock: undefined,
|
genesisBlock: undefined,
|
||||||
datadir: '/tmp/embark',
|
datadir: '/tmp/embark',
|
||||||
|
chains: undefined,
|
||||||
networkId: 0,
|
networkId: 0,
|
||||||
maxPeers: 4,
|
maxPeers: 4,
|
||||||
port: "30303",
|
port: "30303",
|
||||||
|
@ -110,12 +110,13 @@ describe('embark.deploy', function() {
|
|||||||
deploy.deploy_contracts("development");
|
deploy.deploy_contracts("development");
|
||||||
|
|
||||||
it("should deploy contracts", function() {
|
it("should deploy contracts", function() {
|
||||||
var all_contracts = ['SimpleStorage', 'BarStorage', 'FooStorage'];
|
var all_contracts = ['BarStorage', 'FooStorage'];
|
||||||
for(var i=0; i < all_contracts.length; i++) {
|
for(var i=0; i < all_contracts.length; i++) {
|
||||||
var className = all_contracts[i];
|
var className = all_contracts[i];
|
||||||
|
|
||||||
assert.equal(deploy.deployedContracts.hasOwnProperty(className), true);
|
assert.equal(deploy.deployedContracts.hasOwnProperty(className), true);
|
||||||
}
|
}
|
||||||
|
assert.notEqual(deploy.deployedContracts.hasOwnProperty('SimpleStorage'), true);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
75
test/support/contracts/cash.se
Normal file
75
test/support/contracts/cash.se
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# This software (Augur) allows buying && selling event outcomes in ethereum
|
||||||
|
# Copyright (C) 2015 Forecast Foundation
|
||||||
|
# This program is free software; you can redistribute it &&/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it &&/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
# Any questions please contact joey@augur.net
|
||||||
|
|
||||||
|
data cashcoinBalances[]
|
||||||
|
|
||||||
|
def init():
|
||||||
|
# test initial funds
|
||||||
|
self.cashcoinBalances[tx.origin] = 100000*2^64
|
||||||
|
|
||||||
|
# @return: cash balance of address
|
||||||
|
def balance(address):
|
||||||
|
return(self.cashcoinBalances[address])
|
||||||
|
|
||||||
|
# should send values as fixed point in UI (1 is 2^64, 4 is 4*2^64, .5 is 2^63, etc.)
|
||||||
|
# so cashcoin fees could just go to root branch, or we could not have fees besides
|
||||||
|
# gas fee to do a send transaction
|
||||||
|
# @return: value sent, 0 if fails
|
||||||
|
def send(recver, value):
|
||||||
|
sender = tx.origin
|
||||||
|
senderBalance = self.cashcoinBalances[sender]
|
||||||
|
if(senderBalance >= value):
|
||||||
|
self.cashcoinBalances[sender] -= value
|
||||||
|
self.cashcoinBalances[recver] += value
|
||||||
|
return(value)
|
||||||
|
else:
|
||||||
|
return(0)
|
||||||
|
|
||||||
|
# @return value of cash sent; fail is 0
|
||||||
|
def sendFrom(recver, value, from):
|
||||||
|
if(from!=tx.origin):
|
||||||
|
return(0)
|
||||||
|
senderBalance = self.cashcoinBalances[from]
|
||||||
|
if(senderBalance >= value):
|
||||||
|
self.cashcoinBalances[from] -= value
|
||||||
|
self.cashcoinBalances[recver] += value
|
||||||
|
return(value)
|
||||||
|
else:
|
||||||
|
return(0)
|
||||||
|
|
||||||
|
# make sure only coming from specific contracts
|
||||||
|
def subtractCash(ID, amount):
|
||||||
|
#if(!self.whitelist.check(msg.sender)):
|
||||||
|
# return(-1)
|
||||||
|
self.cashcoinBalances[ID] -= amount
|
||||||
|
return(1)
|
||||||
|
|
||||||
|
def addCash(ID, amount):
|
||||||
|
#if(!self.whitelist.check(msg.sender)):
|
||||||
|
# return(-1)
|
||||||
|
self.cashcoinBalances[ID] += amount
|
||||||
|
return(1)
|
||||||
|
|
||||||
|
def setCash(address, balance):
|
||||||
|
#if !self.whitelist.check(msg.sender):
|
||||||
|
# return(-1)
|
||||||
|
self.cashcoinBalances[address] = balance
|
||||||
|
return(1)
|
14
test/support/contracts/error.sol
Normal file
14
test/support/contracts/error.sol
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
contract SimpleStorage {
|
||||||
|
uint public storedData;
|
||||||
|
|
||||||
|
function SimpleStorage(uint initialValue) {
|
||||||
|
storedData2 = initialValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
function set(uint x) {
|
||||||
|
storedData = x;
|
||||||
|
}
|
||||||
|
function get() constant returns (uint retVal) {
|
||||||
|
return storedData;
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
development:
|
development:
|
||||||
SimpleStorage:
|
SimpleStorage:
|
||||||
|
deploy: false
|
||||||
args:
|
args:
|
||||||
- 100
|
- 100
|
||||||
BarStorage:
|
BarStorage:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user