├── .bowerrc ├── .gitignore ├── Gruntfile.js ├── LICENSE ├── README.md ├── bower.json ├── config.js ├── console-testnet.sh ├── contracts └── greeting.sol ├── dist └── res │ └── eth.ico ├── index.js ├── mine-testnet.sh ├── nodemon.json ├── package.json ├── password-testnet ├── routes └── routes.js ├── schemas └── contracts.js ├── scripts ├── checkBalances.js ├── find and greet.js ├── greet and destroy.js └── greet and live.js ├── src ├── angular │ ├── appCore.js │ ├── controllers │ │ ├── contractsController.js │ │ ├── dbController.js │ │ ├── footerController.js │ │ ├── homeController.js │ │ ├── navBarController.js │ │ └── scriptsController.js │ ├── directives │ │ ├── footer.js │ │ └── navbar.js │ ├── routeProvider.js │ └── services │ │ └── appService.js └── css │ └── styles.css ├── test.js └── views ├── directives ├── footer.html └── navbar.html ├── error404.html ├── error500.html ├── index.html └── templates ├── contracts.html ├── db.html ├── home.html └── scripts.html /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "/dist/libs" 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | password-testnet 2 | node_modules 3 | dist/angular 4 | dist/css 5 | dist/libs 6 | logs/*.html -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = function(grunt,dirname) { 3 | 4 | grunt.loadNpmTasks('grunt-contrib-jshint'); 5 | grunt.loadNpmTasks('grunt-contrib-uglify'); 6 | grunt.loadNpmTasks('grunt-contrib-cssmin'); 7 | grunt.loadNpmTasks('grunt-contrib-watch'); 8 | grunt.loadNpmTasks('grunt-contrib-clean'); 9 | grunt.loadNpmTasks('grunt-contrib-copy'); 10 | grunt.loadNpmTasks('grunt-chmod'); 11 | grunt.loadNpmTasks('grunt-ng-annotate'); 12 | 13 | // Gruntfile.js 14 | 15 | grunt.initConfig({ 16 | 17 | // configure jshint to validate js files ----------------------------------- 18 | jshint: { 19 | options: { 20 | reporter: require('jshint-stylish') // use jshint-stylish to make our errors look and read good 21 | }, 22 | 23 | // when this task is run, lint the Gruntfile and all js files in src 24 | build: ['Gruntfile.js', 'src/angular/**/*.js'] 25 | }, 26 | 27 | // get the configuration info from package.json ---------------------------- 28 | // this way we can use things like name and version (pkg.name) 29 | pkg: grunt.file.readJSON('package.json'), 30 | 31 | // configure uglify to minify js files ------------------------------------- 32 | uglify: { 33 | options: { 34 | banner: '/*\n <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> \n*/\n' 35 | }, 36 | min: { 37 | files: [{ 38 | expand: true, 39 | cwd: 'src/angular/', 40 | src: '**/*.js', 41 | dest: 'dist/angular' 42 | },{ 43 | expand: true, 44 | cwd: 'src/', 45 | src: '**/*.js', 46 | dest: 'dist/' 47 | }] 48 | } 49 | }, 50 | 51 | ngAnnotate: { 52 | build: { 53 | files: [{ 54 | expand: true, 55 | src: 'src/angular/**/*.js' 56 | } 57 | ] 58 | } 59 | }, 60 | 61 | copy: { 62 | main: { 63 | files: [{ 64 | expand: true, 65 | cwd: 'src/angular/', 66 | src: ['**'], 67 | dest: 'dist/angular', 68 | options: { 69 | mode: '0777' 70 | } 71 | },{ 72 | expand: true, 73 | src: 'src/lenguages.js', 74 | dest: 'dist/', 75 | options: { 76 | mode: '0777' 77 | } 78 | }, { 79 | expand: true, 80 | cwd: 'src/css/', 81 | src: ['**'], 82 | dest: 'dist/css', 83 | options: { 84 | mode: '0777' 85 | } 86 | }], 87 | }, 88 | }, 89 | 90 | // configure uglify to minify css files ------------------------------------- 91 | cssmin: { 92 | options: { 93 | banner: '/*\n <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> \n*/\n' 94 | }, 95 | min: { 96 | files: [{ 97 | expand: true, 98 | cwd: 'src/css', 99 | src: '*.css', 100 | dest: 'dist/css' 101 | }] 102 | } 103 | }, 104 | 105 | watch: { 106 | css: { 107 | files: ['src/css/*.css'], 108 | tasks: ['cssmin'] 109 | }, 110 | js: { 111 | files: ['src/angular/**/*.js'], 112 | tasks: ['ngAnnotate','uglify'] 113 | }, 114 | dev: { 115 | files: ['src/angular/**/*.js','src/css/*.css'], 116 | tasks: ['copy',] 117 | }, 118 | options: { 119 | nospawn: true, 120 | } 121 | }, 122 | 123 | clean: { 124 | build: { 125 | src: ["dist/angular/*.js", "dist/css/*.css"] 126 | } 127 | }, 128 | 129 | chmod: { 130 | options: { 131 | mode: '755' 132 | }, 133 | target: { 134 | // Target-specific file/dir lists and/or options go here. 135 | src: ['dist/'] 136 | } 137 | } 138 | 139 | }); 140 | 141 | }; 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Augusto 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ethereumjs 2 | An app built using the MEAN stack to use and manage contracts and scripts on you own ethereum testnet. 3 | 4 | ## Install eth && geth 5 | 6 | Follow the instructions on this tutorial to intall eth and geth (I reccomend to install both of them): 7 | https://ethereum.org/cli 8 | 9 | ## Install solc 10 | 11 | Follow the instrucitons on the sol compiler install here: 12 | https://ethereum.org/greeter 13 | 14 | ## Create you testnet blockchain 15 | 16 | Create a new folder where you testnet will be located with a genesis.json file with this content: 17 | ``` 18 | { 19 | "nonce": "0xdeadbeefdeadbeef", 20 | "timestamp": "0x0", 21 | "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", 22 | "extraData": "0x0", 23 | "gasLimit": "0x8000000", 24 | "difficulty": "0x400", 25 | "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", 26 | "coinbase": "0x3333333333333333333333333333333333333333", 27 | "alloc": { 28 | } 29 | } 30 | ``` 31 | More info about the genesis creation here: http://adeduke.com/2015/08/how-to-create-a-private-ethereum-chain/ 32 | 33 | ## Create your new account && start mining 34 | 35 | Go to the app directory and edit the console-testnet.sh to match your testnet directory and run it. 36 | 37 | `geth --genesis [YOU TESTNET DIRECTORY]/genesis.json --datadir[YOU TESTNET DIRECTORY] --rpc --rpcaddr="0.0.0.0" --verbosity=2 --maxpeers=0 --rpccorsdomain="http://localhost:3000" console` 38 | 39 | Once you are in we need to create a new account and select our password: 40 | 41 | Run `personal.newAccount()` and put your new password. 42 | 43 | Create a file called password-testnet and put you passoword there. 44 | 45 | Now we have our account with teh password on a file we can start mining our testnet, change the directory on the mine-testnet.sh and run it. 46 | 47 | `geth --genesis [YOUR TESTNET DIRECTORY]/genesis.json --datadir [YOUR TESTNET DIRECTORY] --rpc --rpcaddr="0.0.0.0" --verbosity=5 --maxpeers=0 --rpccorsdomain="http://localhost:3000" --nodiscover --unlock=0 --password="password-testnet" --mine` 48 | 49 | Now that we are mining we can run our app. 50 | 51 | ## Set un Mongo DB 52 | 53 | If you want to store all your contracts on your local mongodb you will need: Mongo running locally, a db with a user created, set up the dbURI on config.js and run the app with the -store arg. Here are the steps: 54 | 55 | 1. Install mongo, more info here: https://docs.mongodb.org/manual/installation/ 56 | 2. Run your mongo console, if you type `mongo` it should work, if not use `mongo --host 127.0.0.1 --port 27017`. 57 | 3. Create a new db called ethereumjs with `use ethereumjs`. 58 | 4. Create a new user with `db.createUser( { user: "USERNAME", pwd: "PASSWORD", roles: [ "readWrite", "dbAdmin" ] } )`. 59 | 5. Add the dbURI to your config.js like `mongodb://USERNAME:PASSWORD@127.0.0.1:27017/ethereumjs` 60 | 61 | ## Run the app 62 | 63 | Once you are mining you can start another console and go to the app directory, if you are going to develop and make changes on the app run it using the -dev argument for better debug on the client files. 64 | 65 | `node index.js -dev` or `node index.js` 66 | 67 | For test: `npm test` 68 | 69 | You can also run it using nodemon for development `nodemon index.js -dev`, the nodemon.json its already attached. See more on http://nodemon.io/ 70 | 71 | ## TO DO 72 | 73 | - [x] Write tests. 74 | - [ ] Add more contracts. 75 | - [ ] Add more scripts. 76 | - [ ] Better documentation. 77 | 78 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "EthereumJS", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Augusto Lemble " 6 | ], 7 | "main": "node index.js", 8 | "license": "MIT", 9 | "homepage": "augustolemble.com", 10 | "private": true, 11 | "ignore": [ 12 | "**/.*", 13 | "node_modules", 14 | "bower_components", 15 | "/public/libs", 16 | "test", 17 | "tests" 18 | ], 19 | "dependencies": { 20 | "jquery": "~2.1.1", 21 | "angular": "latest", 22 | "angular-route": "latest", 23 | "angular-local-storage": "latest", 24 | "bootstrap": "latest", 25 | "font-awesome": "~4.3.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | logLevel : 'debug', // none, normal, debug, 3 | dbURI : 'mongodb://augusto:123456@127.0.0.1:27017/ethereumjs' //URI to use to connect to db 4 | }; -------------------------------------------------------------------------------- /console-testnet.sh: -------------------------------------------------------------------------------- 1 | geth --genesis ~/.eth-test/genesis.json --datadir ~/.eth-test --rpc --rpcaddr="0.0.0.0" --verbosity=2 --maxpeers=0 --rpccorsdomain="http://localhost:3000" console -------------------------------------------------------------------------------- /contracts/greeting.sol: -------------------------------------------------------------------------------- 1 | contract smart { 2 | /* Define variable owner of the type address*/ 3 | address owner; 4 | 5 | /* this function is executed at initialization and sets the owner of the contract */ 6 | function smart() { 7 | owner = msg.sender; 8 | } 9 | 10 | /* Function to recover the funds on the contract */ 11 | function destroy() { 12 | if (msg.sender == owner) suicide(owner); 13 | } 14 | } 15 | 16 | contract greeter is smart { 17 | /* define variable greeting of the type string */ 18 | string greeting; 19 | 20 | /* this runs when the contract is executed */ 21 | function greeter(string _greeting) public { 22 | greeting = _greeting; 23 | } 24 | 25 | /* main function */ 26 | function greet() constant returns (string) { 27 | return greeting; 28 | } 29 | } -------------------------------------------------------------------------------- /dist/res/eth.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustoL/ethereumjs/261870e3f05844417d366c3045b99cade504ad2c/dist/res/eth.ico -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | //Dependencies 2 | var express = require('express'); 3 | var mongoose = require('mongoose'); 4 | var favicon = require('serve-favicon'); 5 | var bodyParser = require('body-parser'); 6 | var async = require('async'); 7 | var cors = require('cors'); 8 | var grunt = require('grunt'); 9 | var Web3 = require("web3"); 10 | var fs = require("fs"); 11 | var web3 = new Web3(); 12 | 13 | //Configuration 14 | var config = new require('./config'); 15 | 16 | //Logger 17 | var logger = new require('just-a-logger')(config.logLevel, __dirname+'/logs'); 18 | 19 | //Get arguments 20 | var args = process.argv.slice(2); 21 | 22 | //Launch express 23 | var app = express(); 24 | process.env.PORT = 3000; 25 | 26 | //Connect 27 | logger.log(config.dbURI); 28 | mongoose.connect(config.dbURI); 29 | var db = mongoose.connection; 30 | db.on('error', console.error.bind(console, 'connection error:')); 31 | 32 | //Once connected do actions 33 | db.once('open', function callback () { 34 | logger.important('Connected to DB: '+config.dbURI); 35 | }); 36 | require('./schemas/contracts')(db); 37 | 38 | web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545')); 39 | console.log("Web3 "+web3.version.api+" started"); 40 | 41 | //Config Express 42 | app.set('port', 3000); 43 | app.set('views', __dirname + '/views'); 44 | app.engine('html', require('ejs').renderFile); 45 | app.set('view engine', 'html'); 46 | app.use(favicon(__dirname + '/dist/res/eth.ico')); 47 | app.use('/dist', express.static(__dirname + '/dist')); 48 | app.use(bodyParser.json({limit: '50mb'})); 49 | app.use(bodyParser.urlencoded({limit: '50mb', extended: true})); 50 | app.use(cors()); 51 | 52 | //Add routes 53 | require('./routes/routes')(logger, app, db, web3).addRoutes(); 54 | 55 | app.all('/internalError', function(req,res) { res.render('error500.html') }); 56 | 57 | //Start the server 58 | var server = app.listen(app.get('port'), function() { 59 | logger.important('Ethereum app started at port '+app.get('port')); 60 | }); 61 | 62 | if (args.indexOf('-dev') < 0){ 63 | grunt.tasks(['clean']); 64 | grunt.tasks(['ngAnnotate']); 65 | grunt.tasks(['uglify']); 66 | grunt.tasks(['cssmin']); 67 | grunt.tasks(['watch:js','watch:css']); 68 | } else { 69 | grunt.tasks(['clean']); 70 | grunt.tasks(['copy']); 71 | grunt.tasks(['chmod']); 72 | grunt.tasks(['watch:dev']); 73 | } 74 | 75 | process.on('SIGINT', function() { 76 | process.exit(); 77 | }); 78 | -------------------------------------------------------------------------------- /mine-testnet.sh: -------------------------------------------------------------------------------- 1 | geth --genesis ~/.eth-test/genesis.json --datadir ~/.eth-test --rpc --rpcaddr="0.0.0.0" --verbosity=5 --maxpeers=0 --rpccorsdomain="http://localhost:3000" --nodiscover --unlock=0 --password="password-testnet" --mine -------------------------------------------------------------------------------- /nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "verbose": true, 3 | "ignore": ["dist/*", "logs/*", "views/*"] 4 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "EthereumJS", 3 | "version": "0.0.2", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "mocha test -u tdd --timeout 0" 8 | }, 9 | "author": "Augusto Lemble (http://augustolemble.com)", 10 | "license": "MIT", 11 | "dependencies": { 12 | "async": "^1.5.0", 13 | "body-parser": "^1.13.3", 14 | "cookie-parser": "^1.3.5", 15 | "cors": "^2.7.1", 16 | "debug": "0.7.4", 17 | "ejs": "1.0.0", 18 | "express": "4.2.0", 19 | "grunt": "^0.4.5", 20 | "just-a-logger": "latest", 21 | "mongoose": "^4.4.1", 22 | "request": "2.40.0", 23 | "serve-favicon": "~2.2.0", 24 | "web3": "^0.15.1" 25 | }, 26 | "devDependencies": { 27 | "grunt": "~0.4.4", 28 | "grunt-chmod": "^1.1.1", 29 | "grunt-contrib-clean": "^0.7.0", 30 | "grunt-contrib-copy": "^0.8.2", 31 | "grunt-contrib-cssmin": "^0.14.0", 32 | "grunt-contrib-jshint": "latest", 33 | "grunt-contrib-less": "latest", 34 | "grunt-contrib-uglify": "latest", 35 | "grunt-contrib-watch": "^0.6.1", 36 | "grunt-ng-annotate": "^1.0.1", 37 | "jshint-stylish": "latest" 38 | }, 39 | "engines": { 40 | "node": "0.12.x" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /password-testnet: -------------------------------------------------------------------------------- 1 | augusto -------------------------------------------------------------------------------- /routes/routes.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var async = require('async'); 3 | 4 | module.exports = function(logger, app, db, web3){ 5 | 6 | var module = {}; 7 | 8 | module.addRoutes = function(){ 9 | 10 | //Index, templates and directives 11 | app.get('/', module.renderIndex); 12 | app.get('/contracts', module.renderIndex); 13 | app.get('/scripts', module.renderIndex); 14 | app.get('/db', module.renderIndex); 15 | app.get('/templates/:name', module.templates); 16 | app.get('/directives/:name', module.directives); 17 | 18 | app.get('/getContractsSrc', module.getContractsSrc); 19 | app.get('/getContracts', module.getContracts); 20 | app.get('/getScripts', module.getScripts); 21 | app.get('/getWeb3', module.getWeb3); 22 | app.get('/getContract',module.getContract); 23 | 24 | app.post('/runScript', module.runScript); 25 | app.post('/destroyContract', module.destroyContract); 26 | 27 | } 28 | 29 | module.renderIndex = function(req, res){ 30 | res.render('index.html'); 31 | }; 32 | 33 | module.templates = function(req, res){ 34 | res.render('templates/' + req.params.name); 35 | }; 36 | 37 | module.directives = function(req, res){ 38 | res.render('directives/' + req.params.name); 39 | }; 40 | 41 | module.getContractsSrc = function(req, res){ 42 | fs.readdir(__dirname+'/../contracts/', function (err, files) { 43 | var contractsSrc = []; 44 | if (files.length > 0){ 45 | async.forEachOf(files, function (value, key, callback) { 46 | fs.readFile(__dirname+'/../contracts/'+value, "utf8", function (err, data) { 47 | if (err) 48 | callback(err); 49 | try { 50 | contractsSrc.push({ 51 | name : value, 52 | code : data.toString('utf-8') 53 | }); 54 | callback(); 55 | } catch (e) { 56 | return callback(e); 57 | } 58 | }); 59 | }, function (err) { 60 | if (err) 61 | logger.error(err.message); 62 | res.json({ contractsSrc : contractsSrc }); 63 | }) 64 | } else { 65 | res.json({ contractsSrc : [] }); 66 | } 67 | }) 68 | }; 69 | 70 | module.getScripts = function(req, res){ 71 | fs.readdir(__dirname+'/../scripts/', function (err, files) { 72 | var scripts = []; 73 | if (files.length > 0){ 74 | async.forEachOf(files, function (value, key, callback) { 75 | fs.readFile(__dirname+'/../scripts/'+value, "utf8", function (err, data) { 76 | if (err) 77 | callback(err); 78 | try { 79 | scripts.push({ 80 | name : value, 81 | code : data.toString('utf-8') 82 | }); 83 | callback(); 84 | } catch (e) { 85 | return callback(e); 86 | } 87 | }); 88 | }, function (err) { 89 | if (err) 90 | logger.error(err.message); 91 | res.json({ scripts : scripts }); 92 | }) 93 | } else { 94 | res.json({ scripts : [] }); 95 | } 96 | }) 97 | }; 98 | 99 | module.getWeb3 = function(req, res){ 100 | res.json({ "version" : web3.version, "provider" : web3.currentProvider }); 101 | }; 102 | 103 | module.runScript = function(req, res){ 104 | try { 105 | console.log("Running script "+req.query.name+".."); 106 | fs.readFile(__dirname+'/../scripts/'+req.query.name, function (err, data) { 107 | if (err) 108 | throw err; 109 | var source = data.toString('utf-8'); 110 | require(__dirname+'/../scripts/'+req.query.name)(web3, db, function(err,address){ 111 | res.json({ success : true, code : source, address : address }); 112 | }); 113 | }); 114 | } catch(e){ 115 | res.json({ success : false, error : e.toString() }); 116 | } 117 | }; 118 | 119 | module.getContracts = function(req, res){ 120 | db.contracts.find().sort('-dateCompiled').exec(function(err, contracts){ 121 | if (err) 122 | res.json({ success : false, message : err.toString() }); 123 | else if (contracts) 124 | res.json({ success : true, contracts : contracts }); 125 | else 126 | res.json({ success : true, contracts : [] }); 127 | }); 128 | }; 129 | 130 | module.getContract = function(req, res){ 131 | db.findByAddress(req.query.address,function(err, contract){ 132 | if (err) 133 | res.json({ success : false, message : err.toString() }); 134 | else if (contract){ 135 | res.json({ success : true, code : web3.eth.contract(contract.ABI).at(contract.address) }); 136 | } else 137 | res.json({ success : true, code : "" }); 138 | }) 139 | }; 140 | 141 | module.destroyContract = function(req,res){ 142 | db.findByAddress(req.query.address,function(err, contract){ 143 | if (err) 144 | res.json({success : false, message : err.toString()}); 145 | else if (contract){ 146 | web3.eth.contract(contract.ABI).at(contract.address).destroy.sendTransaction({ from : web3.eth.accounts[0] }, function(err, address){ 147 | if (err) 148 | res.json({ success : false, message : err.toString() }) 149 | contract.destroy(function(err){ 150 | if (err) 151 | res.json({ success : false, message : err.toString() }); 152 | console.log("Contract on "+contract.address+" address destroyed."); 153 | res.json({ success : true }); 154 | }); 155 | }); 156 | } else 157 | res.json({ success : false, message : "There is no contract with the address "+req.query.address+" on DB." }); 158 | }) 159 | }; 160 | 161 | 162 | return module; 163 | 164 | } -------------------------------------------------------------------------------- /schemas/contracts.js: -------------------------------------------------------------------------------- 1 | var mongoose = require("mongoose"); 2 | 3 | module.exports = function(db) { 4 | 5 | var contract = new mongoose.Schema({ 6 | name : { type: String, default: ""}, 7 | source : { type: String, default: ""}, 8 | ABI : { type: [mongoose.Schema.Types.Mixed], default: []}, 9 | tx : { type: String, default: ""}, 10 | address : { type: String, default: ""}, 11 | dateCompiled : { type: Date, default: null}, 12 | dateDestroyed : { type: Date, default: null} 13 | }); 14 | 15 | contract.methods.fill = function(name, source, ABI, tx, callback){ 16 | this.name = name; 17 | this.source = source; 18 | this.ABI = ABI; 19 | this.tx = tx; 20 | this.dateCompiled = new Date(); 21 | this.save(function(err){ 22 | if (err) 23 | if (callback) 24 | callback(err); 25 | else 26 | throw err; 27 | else if (callback) 28 | callback(null, this); 29 | }); 30 | }; 31 | 32 | contract.methods.mined = function(address, callback){ 33 | this.address = address; 34 | this.save(function(err){ 35 | if (err) 36 | if (callback) 37 | callback(err); 38 | else 39 | throw err; 40 | else if (callback) 41 | callback(null, this); 42 | }); 43 | }; 44 | 45 | contract.methods.destroy = function(callback){ 46 | this.dateDestroyed = new Date(); 47 | this.save(function(err){ 48 | if (err) 49 | if (callback) 50 | callback(err); 51 | else 52 | throw err; 53 | else if (callback) 54 | callback(null, this); 55 | }); 56 | }; 57 | 58 | db.contracts = db.model('contracts', contract); 59 | 60 | db.findByTx = function(tx, callback){ 61 | db.contracts.findOne({tx : tx}).exec(function(err, contract){ 62 | if (err) 63 | callback(err); 64 | else if (contract) 65 | callback(null, contract); 66 | }) 67 | }; 68 | 69 | db.findByAddress = function(address, callback){ 70 | db.contracts.findOne({address : address}).exec(function(err, contract){ 71 | if (err) 72 | callback(err); 73 | else if (contract) 74 | callback(null, contract); 75 | }) 76 | }; 77 | 78 | db.newContract = function(name, source, ABI, tx, callback){ 79 | var newContract = new db.contracts(); 80 | newContract.fill(name, source, ABI, tx); 81 | newContract.save(function(err){ 82 | if (err) 83 | if (callback) 84 | callback(err); 85 | else 86 | throw err; 87 | else if (callback) 88 | callback(null,newContract); 89 | }); 90 | }; 91 | 92 | }; 93 | -------------------------------------------------------------------------------- /scripts/checkBalances.js: -------------------------------------------------------------------------------- 1 | module.exports = function(web3, db, finalCallback) { 2 | // Get the balance of all your eth accounts 3 | console.log('Your balances:'); 4 | var i =0; 5 | web3.eth.accounts.forEach( function(e){ 6 | console.log("web3.eth.accounts["+i+"]: " + e + " --> " + web3.fromWei(web3.eth.getBalance(e), "ether") + " ether"); 7 | i++; 8 | }); 9 | finalCallback(null); 10 | } -------------------------------------------------------------------------------- /scripts/find and greet.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var async = require('async'); 3 | 4 | module.exports = function(web3, db, finalCallback) { 5 | 6 | //The address of teh greeting contract that its living on the blockchain 7 | var address = '0xe202a6aed4575ed90a3abfb735bdb6e57f7b4461'; 8 | 9 | db.contracts.findOne({ 'address' : address }).exec(function(err, contract){ 10 | if (err) 11 | finalCallback(err); 12 | else if (contract){ 13 | console.log(web3.eth.contract(contract.ABI).at(contract.address).greet()); 14 | finalCallback(null); 15 | } else { 16 | console.log("There is no contract with the address "+address+" greeting on DB."); 17 | finalCallback("There is no contract with the address "+address+" greeting on DB."); 18 | } 19 | }) 20 | }; -------------------------------------------------------------------------------- /scripts/greet and destroy.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var async = require('async'); 3 | 4 | module.exports = function(web3, db, finalCallback) { 5 | var _greeting = "THANKS!, now im going to be destroyed :C "; 6 | 7 | fs.readFile(__dirname+'/../contracts/greeting.sol', function (err, data) { 8 | if (err) 9 | finalCallback(err); 10 | 11 | var contractSource = data.toString('utf-8'); 12 | var contractCompiled = web3.eth.compile.solidity(contractSource); 13 | 14 | web3.eth.contract(contractCompiled.greeter.info.abiDefinition).new(_greeting, { from : web3.eth.accounts[0], data : contractCompiled.greeter.code, gas : 300000 }, function(err, contract){ 15 | if(!err) { 16 | 17 | // NOTE: The callback will fire twice! 18 | // Once the contract has the transactionHash property set and once its deployed on an address. 19 | 20 | // First callback with the txHash 21 | if(!contract.address) { 22 | console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined..."); 23 | db.newContract('greeting', contractSource, contractCompiled.greeter.info.abiDefinition, contract.transactionHash); 24 | 25 | // Second callback with address, contract deployed ;) 26 | } else { 27 | console.log("Contract mined! Address: " + contract.address); 28 | async.waterfall([ 29 | //Find Contract on DB 30 | function(callback) { 31 | db.findByTx(contract.transactionHash, function(err, contractOnDB){ 32 | if (err) 33 | callback(err); 34 | callback(null, contractOnDB) 35 | }); 36 | }, 37 | //Save it as mined on DB 38 | function(contractOnDB, callback) { 39 | contractOnDB.mined(contract.address, function(err){ 40 | if (err) 41 | callback(err); 42 | callback(null, contractOnDB); 43 | }); 44 | }, 45 | //Show greet message and destroy on blockchain 46 | function(contractOnDB, callback) { 47 | console.log(contract.greet()); 48 | contract.destroy.sendTransaction({ from : web3.eth.accounts[0] }, function(err, address){ 49 | if (err) 50 | callback(err); 51 | callback(null, contractOnDB); 52 | }); 53 | }, 54 | //Save it as destroyed on DB 55 | function(contractOnDB, callback) { 56 | contractOnDB.destroy(function(err){ 57 | if (err) 58 | callback(err); 59 | callback(null); 60 | }); 61 | }, 62 | ], function (err) { 63 | if (err){ 64 | console.error(err.toString()); 65 | finalCallback(err); 66 | } 67 | console.log("Contract on "+contract.address+" address destroyed"); 68 | finalCallback(contract.address); 69 | }); 70 | } 71 | } else { 72 | console.error(err.toString()); 73 | finalCallback(err); 74 | } 75 | }); 76 | }); 77 | }; -------------------------------------------------------------------------------- /scripts/greet and live.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var async = require('async'); 3 | 4 | module.exports = function(web3, db, finalCallback) { 5 | var _greeting = "THANKS !, now im going to live forever and ever happy on the blockchain :D "; 6 | 7 | fs.readFile(__dirname+'/../contracts/greeting.sol', function (err, data) { 8 | if (err) 9 | finalCallback(err); 10 | 11 | var contractSource = data.toString('utf-8'); 12 | var contractCompiled = web3.eth.compile.solidity(contractSource); 13 | 14 | web3.eth.contract(contractCompiled.greeter.info.abiDefinition).new(_greeting, { from : web3.eth.accounts[0], data : contractCompiled.greeter.code, gas : 300000 }, function(err, contract){ 15 | if(!err) { 16 | 17 | // NOTE: The callback will fire twice! 18 | // Once the contract has the transactionHash property set and once its deployed on an address. 19 | 20 | // First callback with the txHash 21 | if(!contract.address) { 22 | console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined..."); 23 | db.newContract('greeting', contractSource, contractCompiled.greeter.info.abiDefinition, contract.transactionHash); 24 | 25 | // Second callback with address, contract deployed ;) 26 | } else { 27 | console.log("Contract mined! Address: " + contract.address); 28 | async.waterfall([ 29 | //Find Contract on DB 30 | function(callback) { 31 | db.findByTx(contract.transactionHash, function(err, contractOnDB){ 32 | if (err) 33 | callback(err); 34 | callback(null, contractOnDB) 35 | }); 36 | }, 37 | //Save it as mined on DB 38 | function(contractOnDB, callback) { 39 | contractOnDB.mined(contract.address, function(err){ 40 | if (err) 41 | callback(err); 42 | callback(null); 43 | }); 44 | } 45 | ], function (err) { 46 | if (err){ 47 | console.error(err.toString()); 48 | finalCallback(err); 49 | } 50 | console.log(contract.greet()); 51 | finalCallback(null, contract.address); 52 | }); 53 | } 54 | } else { 55 | console.error(err.toString()); 56 | finalCallback(err); 57 | } 58 | }); 59 | }); 60 | }; -------------------------------------------------------------------------------- /src/angular/appCore.js: -------------------------------------------------------------------------------- 1 | var app = angular.module('ethJS', ['ethJS.controllers', 'ethJS.directives', 'ethJS.services', 'ngRoute', 'LocalStorageModule']); 2 | 3 | //Controllers mudule 4 | angular.module('ethJS.controllers', []); 5 | //Services Module 6 | angular.module('ethJS.services', ['LocalStorageModule']); 7 | //Directives Module 8 | angular.module('ethJS.directives', []); 9 | 10 | //LocalStorage Configuraton 11 | app.config(["localStorageServiceProvider", function (localStorageServiceProvider) { 12 | localStorageServiceProvider 13 | .setPrefix('ethjs') 14 | .setStorageType('localStorage') 15 | .setNotify(true, true) 16 | }]); 17 | 18 | app.filter('to_trusted', ['$sce', function($sce){ 19 | return function(text) { 20 | return $sce.trustAsHtml(text); 21 | }; 22 | }]); -------------------------------------------------------------------------------- /src/angular/controllers/contractsController.js: -------------------------------------------------------------------------------- 1 | angular.module('ethJS.controllers').controller('contractsController', ['$scope', 'appService', '$location', function($scope, appService, $location){ 2 | console.log("contractsController init"); 3 | $scope.loading = true; 4 | $scope.contractsSrc = []; 5 | 6 | appService.getContractsSrc().then(function(promise){ 7 | $scope.contractsSrc = promise.data.contractsSrc; 8 | $scope.loading = false; 9 | }); 10 | 11 | }]); -------------------------------------------------------------------------------- /src/angular/controllers/dbController.js: -------------------------------------------------------------------------------- 1 | angular.module('ethJS.controllers').controller('dbController', ['$scope','appService', function($scope,appService){ 2 | console.log("dbController init"); 3 | $scope.contracts = []; 4 | $scope.loading = true; 5 | 6 | appService.getContracts().then(function(promise){ 7 | $scope.contracts = promise.data.contracts; 8 | console.log($scope.contracts); 9 | $scope.loading = false; 10 | }); 11 | 12 | $scope.destroyContract = function(address){ 13 | $scope.loading = true; 14 | appService.destroyContract(address).then(function(promise){ 15 | appService.getContracts().then(function(promise){ 16 | $scope.contracts = promise.data.contracts; 17 | console.log($scope.contracts); 18 | $scope.loading = false; 19 | }); 20 | }); 21 | }; 22 | 23 | $scope.openContract = function(contract){ 24 | contract.loading = true; 25 | appService.getContract(contract.address).then(function(promise){ 26 | console.log(promise.data); 27 | contract.code = promise.data.code; 28 | contract.loading = false; 29 | }); 30 | }; 31 | 32 | $scope.closeContract = function(contract){ 33 | contract.code = false;; 34 | }; 35 | 36 | }]); -------------------------------------------------------------------------------- /src/angular/controllers/footerController.js: -------------------------------------------------------------------------------- 1 | angular.module('ethJS.controllers').controller('footerController', ['$scope', function($scope){ 2 | console.log("footerController init"); 3 | }]); -------------------------------------------------------------------------------- /src/angular/controllers/homeController.js: -------------------------------------------------------------------------------- 1 | angular.module('ethJS.controllers').controller('homeController', ['$scope', 'appService', function($scope, appService){ 2 | console.log("homeController init"); 3 | $scope.appEvents = appService.history; 4 | $scope.web3Info = {}; 5 | $scope.loading = true; 6 | appService.getWeb3().then(function(promise){ 7 | $scope.web3Info = promise.data; 8 | $scope.loading = false; 9 | console.log($scope.web3Info); 10 | }) 11 | console.log($scope.appEvents); 12 | 13 | $scope.cleanHistory = function(){ 14 | appService.cleanHistory(); 15 | $scope.appEvents = []; 16 | } 17 | }]); -------------------------------------------------------------------------------- /src/angular/controllers/navBarController.js: -------------------------------------------------------------------------------- 1 | angular.module('ethJS.controllers').controller('navBarController', ['$scope', '$window', function($scope, $window){ 2 | console.log("navBarController init"); 3 | }]); -------------------------------------------------------------------------------- /src/angular/controllers/scriptsController.js: -------------------------------------------------------------------------------- 1 | angular.module('ethJS.controllers').controller('scriptsController', ['$scope', 'appService', function($scope, appService){ 2 | console.log("scriptsController init"); 3 | $scope.loading = true; 4 | $scope.scripts = []; 5 | 6 | appService.getScripts().then(function(promise){ 7 | $scope.scripts = promise.data.scripts; 8 | $scope.loading = false; 9 | }); 10 | 11 | $scope.runScript = function(scriptName){ 12 | appService.runScript(scriptName).then(function(promise){ 13 | if (promise.data.success){ 14 | $('#successAlert').show(); 15 | appService.addEvent({ 16 | success : promise.data.success, 17 | name : scriptName, 18 | code : promise.data.code, 19 | result : "Success", 20 | type : 'script', 21 | date : new Date() 22 | }); 23 | } else { 24 | $('#errorAlert').show(); 25 | appService.addEvent({ 26 | success : promise.data.success, 27 | name : scriptName, 28 | code : promise.data.code, 29 | result : "Error: "+pomise.data.error, 30 | type : 'script', 31 | date : new Date() 32 | }); 33 | } 34 | }); 35 | } 36 | }]); -------------------------------------------------------------------------------- /src/angular/directives/footer.js: -------------------------------------------------------------------------------- 1 | angular.module('ethJS.directives').directive('footer', function () { 2 | return { 3 | restrict: 'A', 4 | templateUrl: '/directives/footer.html', 5 | scope: true, 6 | transclude : false, 7 | controller: 'footerController as footerCtrl' 8 | }; 9 | }); -------------------------------------------------------------------------------- /src/angular/directives/navbar.js: -------------------------------------------------------------------------------- 1 | angular.module('ethJS.directives').directive('navbar', function () { 2 | return { 3 | restrict: 'E', 4 | templateUrl: '/directives/navbar.html', 5 | controller: 'navBarController' 6 | }; 7 | }); -------------------------------------------------------------------------------- /src/angular/routeProvider.js: -------------------------------------------------------------------------------- 1 | 2 | app.config(['$routeProvider', function ($routeProvider) { 3 | 4 | $routeProvider.when('/', { templateUrl: '/templates/home.html', controller : 'homeController' }); 5 | $routeProvider.when('/contracts', { templateUrl: '/templates/contracts.html', controller : 'contractsController' }); 6 | $routeProvider.when('/scripts', { templateUrl: '/templates/scripts.html', controller : 'scriptsController' }); 7 | $routeProvider.when('/db', { templateUrl: '/templates/db.html', controller : 'dbController' }); 8 | 9 | $routeProvider.otherwise({redirectTo: '/'}); 10 | 11 | }]).config(['$locationProvider', function($locationProvider) { 12 | $locationProvider.html5Mode(true); 13 | }]); 14 | -------------------------------------------------------------------------------- /src/angular/services/appService.js: -------------------------------------------------------------------------------- 1 | 2 | angular.module('ethJS.services').factory('appService', ['$http', 'localStorageService', function ($http, localStorageService) { 3 | 4 | var factory = {}; 5 | 6 | //Storage 7 | factory.addItem = function(key, value){ 8 | return localStorageService.set(key, value); 9 | } 10 | factory.getItem = function(key){ 11 | return localStorageService.get(key); 12 | } 13 | factory.removeItem = function(key){ 14 | localStorageService.remove(key); 15 | } 16 | factory.cleanHistory = function(){ 17 | localStorageService.clearAll(); 18 | } 19 | 20 | //History of events 21 | factory.history = factory.getItem("history") || []; 22 | 23 | factory.addEvent = function(event){ 24 | factory.history.push(event); 25 | factory.addItem("history", factory.history); 26 | } 27 | 28 | //Actions 29 | factory.getContractsSrc = function () { 30 | var promise = $http({ 31 | method: 'GET', 32 | url: '/getContractsSrc' 33 | }); 34 | return promise; 35 | } 36 | 37 | factory.getScripts = function () { 38 | var promise = $http({ 39 | method: 'GET', 40 | url: '/getScripts' 41 | }); 42 | return promise; 43 | } 44 | 45 | factory.getWeb3 = function () { 46 | var promise = $http({ 47 | method: 'GET', 48 | url: '/getWeb3' 49 | }); 50 | return promise; 51 | } 52 | 53 | factory.getContracts = function () { 54 | var promise = $http({ 55 | method: 'GET', 56 | url: '/getContracts' 57 | }); 58 | return promise; 59 | } 60 | 61 | factory.getABIContract = function (address) { 62 | var promise = $http({ 63 | method: 'GET', 64 | params: {address : address}, 65 | url: '/getABIContract' 66 | }); 67 | return promise; 68 | } 69 | 70 | factory.destroyContract = function (address) { 71 | var promise = $http({ 72 | method: 'POST', 73 | params: {address : address}, 74 | url: '/destroyContract' 75 | }); 76 | return promise; 77 | } 78 | 79 | factory.getContract = function (address) { 80 | var promise = $http({ 81 | method: 'GET', 82 | params: {address : address}, 83 | url: '/getContract' 84 | }); 85 | return promise; 86 | } 87 | 88 | factory.runScript = function(name){ 89 | var promise = $http({ 90 | method: 'POST', 91 | url: '/runScript', 92 | params: { name : name } 93 | }); 94 | return promise; 95 | } 96 | 97 | return factory; 98 | }]); -------------------------------------------------------------------------------- /src/css/styles.css: -------------------------------------------------------------------------------- 1 | html { 2 | position: relative; 3 | min-height: 100%; 4 | } 5 | 6 | body { 7 | font-family: myriad, sans-serif; 8 | font-size: 17px; 9 | background-color:gray; 10 | margin-bottom: 25px; 11 | } 12 | .fullHeight{ 13 | overflow: hidden; 14 | min-height:100%; 15 | height:auto; 16 | } 17 | 18 | a{ 19 | cursor:pointer; 20 | } 21 | 22 | .blog-nav{ 23 | padding-top: 3px; 24 | background-color: #F7FEFF; 25 | width: 100%; 26 | height: 50px; 27 | font-size: 28px; 28 | } 29 | .blog-nav a:hover{ 30 | text-decoration: none; 31 | } 32 | 33 | /* BOX */ 34 | .box { 35 | background-color: #F7FEFF; 36 | border-radius: 3px; 37 | box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12); 38 | padding: 15px; 39 | display: block; 40 | margin-top: 15px; 41 | margin-bottom: 15px; 42 | margin-right: 0px; 43 | margin-left: 0px; 44 | -webkit-transition:.6s cubic-bezier(0,1.5,.5,1); 45 | -moz-transition:.6s cubic-bezier(0,1.5,.5,1); 46 | -o-transition:.6s cubic-bezier(0,1.5,.5,1); 47 | transition:.6s cubic-bezier(0,1.5,.5,1); 48 | } 49 | 50 | .text-box{ 51 | resize : vertical; 52 | width: 100%; 53 | min-height: 500px; 54 | max-height: 1000px; 55 | } 56 | 57 | /* FOOTER */ 58 | footer{ 59 | position: absolute; 60 | width:100%; 61 | text-align: center; 62 | font-size: 14px; 63 | background-color: #F7FEFF; 64 | height: 25px; 65 | padding-top: 2px; 66 | bottom: 0; 67 | } 68 | @media (min-width: 0px) and (max-width: 768px) { 69 | footer{ 70 | position: absolute; 71 | width:100%; 72 | text-align: center; 73 | font-size: 14px; 74 | word-spacing: 10px; 75 | background-color: #F7FEFF; 76 | height: 25px; 77 | padding-top: 2px; 78 | bottom: 0; 79 | } 80 | } 81 | .spaceFooter{ 82 | cursor:pointer; 83 | } 84 | footer a{ 85 | text-decoration: none; 86 | margin-right: 10px; 87 | margin-left: 10px; 88 | } 89 | footer a:hover{ 90 | text-decoration: underline; 91 | } 92 | 93 | /* Useful Classes */ 94 | .no-margin{ 95 | margin:0px; 96 | } 97 | .no-padding{ 98 | padding:0px; 99 | } 100 | .margin-sides{ 101 | margin-right: 5px; 102 | margin-left: 5px; 103 | } 104 | .total-width{ 105 | width: 100%; 106 | } 107 | .margin-row{ 108 | margin-top : 5px; 109 | } 110 | .in-line{ 111 | display: inline-block; 112 | } 113 | .center{ 114 | text-align: center; 115 | } 116 | .absolute-position{ 117 | position: absolute; 118 | } 119 | .fixed-position{ 120 | position: fixed; 121 | } 122 | .to-the-back{ 123 | position:relative !important; 124 | z-index: 1000 !important; 125 | } 126 | .to-the-front{ 127 | position:relative !important; 128 | z-index: 9000 !important; 129 | } 130 | .cursor-pointer{ 131 | cursor: pointer; 132 | } 133 | 134 | /* ERROR */ 135 | .big-error{ 136 | font-size: 100px; 137 | } -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var mongoose = require('mongoose'); 3 | var favicon = require('serve-favicon'); 4 | var bodyParser = require('body-parser'); 5 | var cors = require('cors'); 6 | var Web3 = require("web3"); 7 | var fs = require("fs"); 8 | var web3 = new Web3(); 9 | var assert = require("assert"); 10 | var request = require("request"); 11 | 12 | describe('EthereumJS Test', function() { 13 | 14 | var config = new require('./config'); 15 | var logger = new require('just-a-logger')(config.logLevel, __dirname+'/logs'); 16 | var app = express(); 17 | var db = null; 18 | 19 | test('Configuration', function(done) { 20 | 21 | //Config Express 22 | app.set('port', 3000); 23 | app.set('views', __dirname + '/views'); 24 | app.engine('html', require('ejs').renderFile); 25 | app.set('view engine', 'html'); 26 | app.use(favicon(__dirname + '/dist/res/eth.ico')); 27 | app.use('/dist', express.static(__dirname + '/dist')); 28 | app.use(bodyParser.json({ limit: '50mb' })); 29 | app.use(bodyParser.urlencoded({ limit: '50mb', extended: true })); 30 | app.use(cors()); 31 | 32 | //Connect 33 | logger.log(config.dbURI); 34 | mongoose.connect(config.dbURI); 35 | db = mongoose.connection; 36 | db.on('error', console.error.bind(console, 'connection error:')); 37 | 38 | //Once connected do actions 39 | db.once('open', function callback () { 40 | logger.important('Connected to DB: '+config.dbURI); 41 | require('./schemas/contracts')(db); 42 | done(); 43 | }); 44 | 45 | }); 46 | 47 | test('Start web3 provider', function(done) { 48 | 49 | web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545')); 50 | console.log("Web3 "+web3.version.api+" started"); 51 | done(); 52 | 53 | }); 54 | 55 | test('Start server', function(done) { 56 | 57 | require('./routes/routes')(logger, app, db, web3).addRoutes(); 58 | app.all('/internalError', function(req, res) { res.render('error500.html') }); 59 | 60 | var server = app.listen(app.get('port'), function() { 61 | logger.important('Ethereum app started at port '+app.get('port')); 62 | done(); 63 | }); 64 | 65 | }); 66 | 67 | test('Execute script: checkBalances', function(done) { 68 | 69 | request.post({ url:'http://localhost:3000/runScript?name=checkBalances.js' }, function(err, httpResponse, body){ 70 | assert.equal(true, JSON.parse(body).success); 71 | done(); 72 | }); 73 | 74 | }); 75 | 76 | test('Execute script: greet and destroy', function(done) { 77 | 78 | request.post({ url:'http://localhost:3000/runScript?name=greet and destroy.js' }, function(err, httpResponse, body){ 79 | assert.equal(true, JSON.parse(body).success); 80 | done(); 81 | }); 82 | 83 | }); 84 | 85 | var contractAddress = ""; 86 | 87 | test('Execute script: greet and live && find and greet', function(done) { 88 | 89 | request.post({ url:'http://localhost:3000/runScript?name=greet and live.js' }, function(err, httpResponse, body){ 90 | contractAddress = JSON.parse(body).address; 91 | assert.equal(true, JSON.parse(body).success); 92 | done(); 93 | }); 94 | 95 | }); 96 | 97 | test('Execute script: find and greet', function(done) { 98 | request.post({url:'http://localhost:3000/runScript?name=find and greet.js&address='+contractAddress}, function(err, httpResponse, body){ 99 | assert.equal(true, JSON.parse(body).success); 100 | done(); 101 | }); 102 | }); 103 | 104 | test('Destroy living greeting contract', function(done) { 105 | 106 | request.post({url:'http://localhost:3000/destroyContract?address='+contractAddress}, function(err, httpResponse, body){ 107 | assert.equal(true, JSON.parse(body).success); 108 | done(); 109 | }); 110 | 111 | }); 112 | 113 | }); 114 | -------------------------------------------------------------------------------- /views/directives/footer.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /views/directives/navbar.html: -------------------------------------------------------------------------------- 1 | 9 | 10 | -------------------------------------------------------------------------------- /views/error404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Ethereum JS 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |
19 |
20 |
21 |
WHOOPS!
22 |

Error 404: URL Not found.

23 |
24 |
25 |
26 | 27 | -------------------------------------------------------------------------------- /views/error500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Ethereum JS 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |
19 |
20 |
21 |
WHOOPS!
22 |

Error 500: Internal Error.

23 |
24 |
25 |
26 | 27 | -------------------------------------------------------------------------------- /views/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Ethereum JS 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |
37 |
38 | 39 | -------------------------------------------------------------------------------- /views/templates/contracts.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 |
7 |

{{contract.name}}

8 |
{{contract.code}}
9 |
10 |
11 |
12 |
13 |
14 | -------------------------------------------------------------------------------- /views/templates/db.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 |

7 |
8 |
9 |
10 |
11 |

Contracts

12 |
13 |

{{contract.name}} 14 | - {{contract.address}} 15 | 16 | 17 | 18 |

19 |

20 |
21 |
Date compiled: {{ contract.dateCompiled | date:'short'}}
22 |
Date destroyed: {{ contract.dateDestroyed | date:'short'}}
23 | Source code:
{{contract.source}}
24 | Code on blockchain:
{{contract.code | json:4 }}
25 |
26 |
27 |
28 |
29 | -------------------------------------------------------------------------------- /views/templates/home.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 |

7 |
8 |
9 |
10 |
11 |

Web3 Info

12 |

Web3:{{web3Info.version}}

13 |

Provider:{{web3Info.provider}}

14 |
15 |
16 |

Session Events

17 |
18 |
19 |
20 |

Compilation of contract: {{ event.name }} {{ event.date | date:'short'}}

21 |
22 | Code 23 |
24 | 							{{ event.code }}
25 | 						
26 |
27 |
28 | Result: 29 |
30 | 							{{ event.result | json:4 }}
31 | 						
32 |
33 | 							{{ event.result }}
34 | 						
35 |
36 |
37 |
38 |

Execution of script: {{ event.name }} {{ event.date | date:'short'}}

39 |
40 | Code: 41 |
42 | 							{{ event.code }}
43 | 						
44 |
45 |
46 | Result: 47 |
48 | 							{{ event.result }}
49 | 						
50 |
51 |
52 |
53 |
54 | 55 |
56 |
57 | -------------------------------------------------------------------------------- /views/templates/scripts.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 |
7 |

{{script.name}}

8 |
{{script.code}}
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------