From 77db6a3d255ad2baa457e76272063e04a7ce927c Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 6 Jan 2014 12:22:39 -0300 Subject: [PATCH 01/50] package.json added --- package.json | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 package.json diff --git a/package.json b/package.json new file mode 100644 index 0000000..477fe83 --- /dev/null +++ b/package.json @@ -0,0 +1,33 @@ +{ + "name": "mystery", + "version": "0.0.1", + "private": true, + "dependencies": { + }, + "author": { + "name": "Ryan X Charles", + "email": "ryan@bitpay.com" + }, + "repository": "git://github.com/bitpay/mystery.git", + "contributors": [{ + "name": "Matias Alejo Garcia", + "email": "ematiu@gmail.com" + }], + "bugs": { + "url": "https://github.com/bitpay/mystery/issues" + }, + "homepage": "https://github.com/bitpay/mystery", + "license": "MIT", + "keywords": [ + "mystery", + "secret", + "enigma", + "riddle", + "mystification", + "puzzle", + "conundrum" + ], + "engines": { + "node": "*" + } +} From 0d84b855edf82e377e88d9e365643352aaca095a Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Mon, 6 Jan 2014 12:28:10 -0300 Subject: [PATCH 02/50] git ignore for node --- .gitignore | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9ad72e0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +lib-cov +*.seed +*.log +*.csv +*.dat +*.out +*.pid +*.gz +*.swp + +pids +logs +results + +npm-debug.log +node_modules + +.DS_Store + From da455b49645503746e07d7210a3a7aba43556f11 Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Mon, 6 Jan 2014 13:33:58 -0300 Subject: [PATCH 03/50] added mongo dependency. basic skel --- app/controllers/index.js | 5 +++ app/views/404.jade | 13 +++++++ app/views/500.jade | 12 ++++++ app/views/includes/foot.jade | 0 app/views/includes/head.jade | 12 ++++++ app/views/index.jade | 4 ++ app/views/layouts/default.jade | 8 ++++ config/config.js | 9 +++++ config/env/all.js | 10 +++++ config/env/development.js | 8 ++++ config/env/production.js | 8 ++++ config/env/test.js | 9 +++++ config/express.js | 69 ++++++++++++++++++++++++++++++++++ config/routes.js | 9 +++++ package.json | 8 +++- server.js | 55 +++++++++++++++++++++++++++ 16 files changed, 238 insertions(+), 1 deletion(-) create mode 100644 app/controllers/index.js create mode 100755 app/views/404.jade create mode 100755 app/views/500.jade create mode 100755 app/views/includes/foot.jade create mode 100755 app/views/includes/head.jade create mode 100755 app/views/index.jade create mode 100755 app/views/layouts/default.jade create mode 100644 config/config.js create mode 100755 config/env/all.js create mode 100755 config/env/development.js create mode 100755 config/env/production.js create mode 100755 config/env/test.js create mode 100644 config/express.js create mode 100644 config/routes.js create mode 100644 server.js diff --git a/app/controllers/index.js b/app/controllers/index.js new file mode 100644 index 0000000..1e34bd9 --- /dev/null +++ b/app/controllers/index.js @@ -0,0 +1,5 @@ +'use strict'; + +exports.render = function(req, res) { + res.render('index'); +}; diff --git a/app/views/404.jade b/app/views/404.jade new file mode 100755 index 0000000..2f0d9e8 --- /dev/null +++ b/app/views/404.jade @@ -0,0 +1,13 @@ +extends layouts/default + +block main + h1 Oops something went wrong + br + span 404 + +block content + #error-message-box + #error-stack-trace + pre + code!= error + diff --git a/app/views/500.jade b/app/views/500.jade new file mode 100755 index 0000000..491b000 --- /dev/null +++ b/app/views/500.jade @@ -0,0 +1,12 @@ +extends layouts/default + +block main + h1 Oops something went wrong + br + span 500 + +block content + #error-message-box + #error-stack-trace + pre + code!= error diff --git a/app/views/includes/foot.jade b/app/views/includes/foot.jade new file mode 100755 index 0000000..e69de29 diff --git a/app/views/includes/head.jade b/app/views/includes/head.jade new file mode 100755 index 0000000..08e4f44 --- /dev/null +++ b/app/views/includes/head.jade @@ -0,0 +1,12 @@ +head + meta(charset='utf-8') + meta(http-equiv='X-UA-Compatible', content='IE=edge,chrome=1') + meta(name='viewport', content='width=device-width,initial-scale=1') + + title BitPay + meta(http-equiv='Content-type', content='text/html;charset=UTF-8') + meta(name="keywords", content="node.js, express, mongoose, mongodb, angularjs") + meta(name="description", content="Mystery") + + link(href='/img/icons/favicon.ico', rel='shortcut icon', type='image/x-icon') + diff --git a/app/views/index.jade b/app/views/index.jade new file mode 100755 index 0000000..874b042 --- /dev/null +++ b/app/views/index.jade @@ -0,0 +1,4 @@ +extends layouts/default + +block content + h1 Hello BitPay! diff --git a/app/views/layouts/default.jade b/app/views/layouts/default.jade new file mode 100755 index 0000000..3c47dc2 --- /dev/null +++ b/app/views/layouts/default.jade @@ -0,0 +1,8 @@ +doctype html +html(lang='en', xmlns='http://www.w3.org/1999/xhtml') + include ../includes/head + body + section.content + section.container + block content + include ../includes/foot diff --git a/config/config.js b/config/config.js new file mode 100644 index 0000000..b4b4230 --- /dev/null +++ b/config/config.js @@ -0,0 +1,9 @@ +'use strict'; + +var _ = require('lodash'); + +// Load app configuration + +module.exports = _.extend( + require(__dirname + '/../config/env/all.js'), + require(__dirname + '/../config/env/' + process.env.NODE_ENV + '.js') || {}); diff --git a/config/env/all.js b/config/env/all.js new file mode 100755 index 0000000..22d15f7 --- /dev/null +++ b/config/env/all.js @@ -0,0 +1,10 @@ +'use strict'; + +var path = require('path'), +rootPath = path.normalize(__dirname + '/../..'); + +module.exports = { + root: rootPath, + port: process.env.PORT || 3000, + db: process.env.MONGOHQ_URL +} diff --git a/config/env/development.js b/config/env/development.js new file mode 100755 index 0000000..b0a4665 --- /dev/null +++ b/config/env/development.js @@ -0,0 +1,8 @@ +'use strict'; + +module.exports = { + db: "mongodb://localhost/mystery-dev", + app: { + name: "Mystery - Development" + } +} \ No newline at end of file diff --git a/config/env/production.js b/config/env/production.js new file mode 100755 index 0000000..9bc30bc --- /dev/null +++ b/config/env/production.js @@ -0,0 +1,8 @@ +'use strict'; + +module.exports = { + db: "mongodb://localhost/mystery", + app: { + name: "Mystery - Production" + } +} \ No newline at end of file diff --git a/config/env/test.js b/config/env/test.js new file mode 100755 index 0000000..7b30a47 --- /dev/null +++ b/config/env/test.js @@ -0,0 +1,9 @@ +'use strict'; + +module.exports = { + db: "mongodb://localhost/mystery-test", + port: 3001, + app: { + name: "Mystery - Test" + } +} \ No newline at end of file diff --git a/config/express.js b/config/express.js new file mode 100644 index 0000000..08343fe --- /dev/null +++ b/config/express.js @@ -0,0 +1,69 @@ +'use strict'; + +/** + * Module dependencies. + */ +var express = require('express'), + config = require('./config'); + +module.exports = function(app, passport, db) { + app.set('showStackError', true); + + //Prettify HTML + app.locals.pretty = true; + + //Should be placed before express.static + app.use(express.compress({ + filter: function(req, res) { + return (/json|text|javascript|css/).test(res.getHeader('Content-Type')); + }, + level: 9 + })); + + //Set views path, template engine and default layout + app.set('views', config.root + '/app/views'); + app.set('view engine', 'jade'); + + //Enable jsonp + app.enable("jsonp callback"); + + app.configure(function() { + //cookieParser should be above session + app.use(express.cookieParser()); + + // request body parsing middleware should be above methodOverride + app.use(express.urlencoded()); + app.use(express.json()); + app.use(express.methodOverride()); + + //routes should be at the last + app.use(app.router); + + //Setting the fav icon and static folder + app.use(express.favicon()); + app.use(express.static(config.root + '/public')); + + //Assume "not found" in the error msgs is a 404. this is somewhat silly, but valid, you can do whatever you like, set properties, use instanceof etc. + app.use(function(err, req, res, next) { + //Treat as 404 + if (~err.message.indexOf('not found')) return next(); + + //Log it + console.error(err.stack); + + //Error page + res.status(500).render('500', { + error: err.stack + }); + }); + + //Assume 404 since no middleware responded + app.use(function(req, res, next) { + res.status(404).render('404', { + url: req.originalUrl, + error: 'Not found' + }); + }); + + }); +}; \ No newline at end of file diff --git a/config/routes.js b/config/routes.js new file mode 100644 index 0000000..9fbf748 --- /dev/null +++ b/config/routes.js @@ -0,0 +1,9 @@ +'use strict'; + +module.exports = function(app) { + + //Home route + var index = require('../app/controllers/index'); + app.get('/', index.render); + +}; diff --git a/package.json b/package.json index 477fe83..68b8253 100644 --- a/package.json +++ b/package.json @@ -29,5 +29,11 @@ ], "engines": { "node": "*" - } + }, + "dependencies": { + "express": "~3.4.7", + "jade": "~1.0.2", + "mongoose": "~3.8.3", + "lodash": "~2.4.1" + } } diff --git a/server.js b/server.js new file mode 100644 index 0000000..68bb10f --- /dev/null +++ b/server.js @@ -0,0 +1,55 @@ +'use strict'; + +/** + * Module dependencies. + */ +var express = require('express'), + fs = require('fs'); + +/** + * Main application entry file. + */ + +//Load configurations +//Set the node enviornment variable if not set before +process.env.NODE_ENV = process.env.NODE_ENV || 'development'; + +//Initializing system variables +var config = require('./config/config'), + mongoose = require('mongoose'); + +//Bootstrap db connection +var db = mongoose.connect(config.db); + +//Bootstrap models +var models_path = __dirname + '/app/models'; +var walk = function(path) { + fs.readdirSync(path).forEach(function(file) { + var newPath = path + '/' + file; + var stat = fs.statSync(newPath); + if (stat.isFile()) { + if (/(.*)\.(js$|coffee$)/.test(file)) { + require(newPath); + } + } else if (stat.isDirectory()) { + walk(newPath); + } + }); +}; +walk(models_path); + +var app = express(); + +//express settings +require('./config/express')(app, db); + +//Bootstrap routes +require('./config/routes')(app); + +//Start the app by listening on +var port = process.env.PORT || config.port; +app.listen(port); +console.log('Express app started on port ' + port); + +//expose app +exports = module.exports = app; From 79e6cdfffdeb4f7ff9973e9eea14116400a6693a Mon Sep 17 00:00:00 2001 From: Mario Colque Date: Mon, 6 Jan 2014 14:21:52 -0300 Subject: [PATCH 04/50] dependencies removed --- package.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/package.json b/package.json index 68b8253..d44870a 100644 --- a/package.json +++ b/package.json @@ -2,8 +2,6 @@ "name": "mystery", "version": "0.0.1", "private": true, - "dependencies": { - }, "author": { "name": "Ryan X Charles", "email": "ryan@bitpay.com" From e33ee06cc615eba11abc403549ec4ad2fee7b770 Mon Sep 17 00:00:00 2001 From: Mario Colque Date: Mon, 6 Jan 2014 14:37:32 -0300 Subject: [PATCH 05/50] using two spaces for tabs --- app/controllers/index.js | 2 +- config/config.js | 4 +- config/env/all.js | 6 +-- config/env/development.js | 8 ++-- config/env/production.js | 8 ++-- config/env/test.js | 10 ++-- config/express.js | 96 +++++++++++++++++++-------------------- config/routes.js | 6 +-- server.js | 28 ++++++------ 9 files changed, 84 insertions(+), 84 deletions(-) diff --git a/app/controllers/index.js b/app/controllers/index.js index 1e34bd9..f71d55c 100644 --- a/app/controllers/index.js +++ b/app/controllers/index.js @@ -1,5 +1,5 @@ 'use strict'; exports.render = function(req, res) { - res.render('index'); + res.render('index'); }; diff --git a/config/config.js b/config/config.js index b4b4230..2f0e7c9 100644 --- a/config/config.js +++ b/config/config.js @@ -5,5 +5,5 @@ var _ = require('lodash'); // Load app configuration module.exports = _.extend( - require(__dirname + '/../config/env/all.js'), - require(__dirname + '/../config/env/' + process.env.NODE_ENV + '.js') || {}); + require(__dirname + '/../config/env/all.js'), + require(__dirname + '/../config/env/' + process.env.NODE_ENV + '.js') || {}); diff --git a/config/env/all.js b/config/env/all.js index 22d15f7..7f53a56 100755 --- a/config/env/all.js +++ b/config/env/all.js @@ -4,7 +4,7 @@ var path = require('path'), rootPath = path.normalize(__dirname + '/../..'); module.exports = { - root: rootPath, - port: process.env.PORT || 3000, - db: process.env.MONGOHQ_URL + root: rootPath, + port: process.env.PORT || 3000, + db: process.env.MONGOHQ_URL } diff --git a/config/env/development.js b/config/env/development.js index b0a4665..0ef298c 100755 --- a/config/env/development.js +++ b/config/env/development.js @@ -1,8 +1,8 @@ 'use strict'; module.exports = { - db: "mongodb://localhost/mystery-dev", - app: { - name: "Mystery - Development" - } + db: "mongodb://localhost/mystery-dev", + app: { + name: "Mystery - Development" + } } \ No newline at end of file diff --git a/config/env/production.js b/config/env/production.js index 9bc30bc..5d2c3b4 100755 --- a/config/env/production.js +++ b/config/env/production.js @@ -1,8 +1,8 @@ 'use strict'; module.exports = { - db: "mongodb://localhost/mystery", - app: { - name: "Mystery - Production" - } + db: "mongodb://localhost/mystery", + app: { + name: "Mystery - Production" + } } \ No newline at end of file diff --git a/config/env/test.js b/config/env/test.js index 7b30a47..dabf602 100755 --- a/config/env/test.js +++ b/config/env/test.js @@ -1,9 +1,9 @@ 'use strict'; module.exports = { - db: "mongodb://localhost/mystery-test", - port: 3001, - app: { - name: "Mystery - Test" - } + db: "mongodb://localhost/mystery-test", + port: 3001, + app: { + name: "Mystery - Test" + } } \ No newline at end of file diff --git a/config/express.js b/config/express.js index 08343fe..1abe190 100644 --- a/config/express.js +++ b/config/express.js @@ -4,66 +4,66 @@ * Module dependencies. */ var express = require('express'), - config = require('./config'); + config = require('./config'); module.exports = function(app, passport, db) { - app.set('showStackError', true); + app.set('showStackError', true); - //Prettify HTML - app.locals.pretty = true; + //Prettify HTML + app.locals.pretty = true; - //Should be placed before express.static - app.use(express.compress({ - filter: function(req, res) { - return (/json|text|javascript|css/).test(res.getHeader('Content-Type')); - }, - level: 9 - })); + //Should be placed before express.static + app.use(express.compress({ + filter: function(req, res) { + return (/json|text|javascript|css/).test(res.getHeader('Content-Type')); + }, + level: 9 + })); - //Set views path, template engine and default layout - app.set('views', config.root + '/app/views'); - app.set('view engine', 'jade'); + //Set views path, template engine and default layout + app.set('views', config.root + '/app/views'); + app.set('view engine', 'jade'); - //Enable jsonp - app.enable("jsonp callback"); + //Enable jsonp + app.enable("jsonp callback"); - app.configure(function() { - //cookieParser should be above session - app.use(express.cookieParser()); + app.configure(function() { + //cookieParser should be above session + app.use(express.cookieParser()); - // request body parsing middleware should be above methodOverride - app.use(express.urlencoded()); - app.use(express.json()); - app.use(express.methodOverride()); + // request body parsing middleware should be above methodOverride + app.use(express.urlencoded()); + app.use(express.json()); + app.use(express.methodOverride()); - //routes should be at the last - app.use(app.router); - - //Setting the fav icon and static folder - app.use(express.favicon()); - app.use(express.static(config.root + '/public')); + //routes should be at the last + app.use(app.router); - //Assume "not found" in the error msgs is a 404. this is somewhat silly, but valid, you can do whatever you like, set properties, use instanceof etc. - app.use(function(err, req, res, next) { - //Treat as 404 - if (~err.message.indexOf('not found')) return next(); + //Setting the fav icon and static folder + app.use(express.favicon()); + app.use(express.static(config.root + '/public')); - //Log it - console.error(err.stack); + //Assume "not found" in the error msgs is a 404. this is somewhat silly, but valid, you can do whatever you like, set properties, use instanceof etc. + app.use(function(err, req, res, next) { + //Treat as 404 + if (~err.message.indexOf('not found')) return next(); - //Error page - res.status(500).render('500', { - error: err.stack - }); - }); - - //Assume 404 since no middleware responded - app.use(function(req, res, next) { - res.status(404).render('404', { - url: req.originalUrl, - error: 'Not found' - }); - }); + //Log it + console.error(err.stack); + //Error page + res.status(500).render('500', { + error: err.stack + }); }); + + //Assume 404 since no middleware responded + app.use(function(req, res, next) { + res.status(404).render('404', { + url: req.originalUrl, + error: 'Not found' + }); + }); + + }); }; \ No newline at end of file diff --git a/config/routes.js b/config/routes.js index 9fbf748..af9c691 100644 --- a/config/routes.js +++ b/config/routes.js @@ -2,8 +2,8 @@ module.exports = function(app) { - //Home route - var index = require('../app/controllers/index'); - app.get('/', index.render); + //Home route + var index = require('../app/controllers/index'); + app.get('/', index.render); }; diff --git a/server.js b/server.js index 68bb10f..de2a349 100644 --- a/server.js +++ b/server.js @@ -4,7 +4,7 @@ * Module dependencies. */ var express = require('express'), - fs = require('fs'); + fs = require('fs'); /** * Main application entry file. @@ -14,9 +14,9 @@ var express = require('express'), //Set the node enviornment variable if not set before process.env.NODE_ENV = process.env.NODE_ENV || 'development'; -//Initializing system variables +//Initializing system variables var config = require('./config/config'), - mongoose = require('mongoose'); + mongoose = require('mongoose'); //Bootstrap db connection var db = mongoose.connect(config.db); @@ -24,17 +24,17 @@ var db = mongoose.connect(config.db); //Bootstrap models var models_path = __dirname + '/app/models'; var walk = function(path) { - fs.readdirSync(path).forEach(function(file) { - var newPath = path + '/' + file; - var stat = fs.statSync(newPath); - if (stat.isFile()) { - if (/(.*)\.(js$|coffee$)/.test(file)) { - require(newPath); - } - } else if (stat.isDirectory()) { - walk(newPath); - } - }); + fs.readdirSync(path).forEach(function(file) { + var newPath = path + '/' + file; + var stat = fs.statSync(newPath); + if (stat.isFile()) { + if (/(.*)\.(js$|coffee$)/.test(file)) { + require(newPath); + } + } else if (stat.isDirectory()) { + walk(newPath); + } + }); }; walk(models_path); From 91ea1d23bc065a1236be37b212f73024c7f8317e Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 6 Jan 2014 15:00:28 -0300 Subject: [PATCH 06/50] index page --- app/views/includes/head.jade | 2 +- app/views/index.jade | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/app/views/includes/head.jade b/app/views/includes/head.jade index 08e4f44..f286985 100755 --- a/app/views/includes/head.jade +++ b/app/views/includes/head.jade @@ -3,7 +3,7 @@ head meta(http-equiv='X-UA-Compatible', content='IE=edge,chrome=1') meta(name='viewport', content='width=device-width,initial-scale=1') - title BitPay + title Mystery meta(http-equiv='Content-type', content='text/html;charset=UTF-8') meta(name="keywords", content="node.js, express, mongoose, mongodb, angularjs") meta(name="description", content="Mystery") diff --git a/app/views/index.jade b/app/views/index.jade index 874b042..02348b3 100755 --- a/app/views/index.jade +++ b/app/views/index.jade @@ -1,4 +1,24 @@ extends layouts/default block content - h1 Hello BitPay! + h1 mystery + p ˈmɪst(ə)ri/' + | noun + audio(src="https://ssl.gstatic.com/dictionary/static/sounds/de/0/mystery.mp3",preload="auto",data-dobid="aud",id="aud") + button(onclick="document.getElementById('aud').play()") Play + + ol + li + strong something that is difficult or impossible to understand or explain. + p "the mysteries of outer space" + | synonyms: puzzle, enigma, conundrum, riddle, secret, unsolved problem, problem, question, question mark, closed book; secrecy or obscurity. + p "much of her past is shrouded in mystery" + | synonyms: secrecy, darkness, obscurity, ambiguity, ambiguousness, uncertainty, impenetrability, vagueness, nebulousness; More + li + strong a person or thing whose identity or nature is puzzling or unknown. + p "‘He's a bit of a mystery,’ said Nina" + li + strong a novel, play, or film dealing with a puzzling crime, especially a murder. + p "the 1920s murder mystery, The Ghost Train" + | synonyms: thriller, detective story/novel, murder story; More + From af8ce3e4941fc671b7928936ad7bf203a569d6d8 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 6 Jan 2014 15:51:44 -0300 Subject: [PATCH 07/50] bitcoind configuration sample --- etc/bitcoind/bitcoin.conf | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 etc/bitcoind/bitcoin.conf diff --git a/etc/bitcoind/bitcoin.conf b/etc/bitcoind/bitcoin.conf new file mode 100644 index 0000000..50bac19 --- /dev/null +++ b/etc/bitcoind/bitcoin.conf @@ -0,0 +1,12 @@ +rpcuser=mystery +rpcpassword=real_mystery +server=1 +rpcallowip=127.0.0.1 +rpcport=8332 +testnet=1 +txindex=1 + + + + + From 6bf3b4f0537c328aac188024af99f1df2db7fe66 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 6 Jan 2014 15:55:45 -0300 Subject: [PATCH 08/50] markdown updated --- README.md | 8 ++++++++ config/routes.js | 3 +++ 2 files changed, 11 insertions(+) diff --git a/README.md b/README.md index 17e46ba..96ff245 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,10 @@ mystery ======= + + +## bitcoind configuration + + There is a bitcoind configuration sample at: +``` + etc/mystery/bitcoin.conf +```: diff --git a/config/routes.js b/config/routes.js index af9c691..182a216 100644 --- a/config/routes.js +++ b/config/routes.js @@ -6,4 +6,7 @@ module.exports = function(app) { var index = require('../app/controllers/index'); app.get('/', index.render); + //TX routes + // + }; From 5a6979a91124afb322ba758d897636ebaa96341c Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 6 Jan 2014 16:06:56 -0300 Subject: [PATCH 09/50] bitcore dependency added --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index d44870a..e364609 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "express": "~3.4.7", "jade": "~1.0.2", "mongoose": "~3.8.3", - "lodash": "~2.4.1" + "lodash": "~2.4.1", + "bitcore": "*" } } From 0341f8f691d79b025adead4489e90ddb03cdb644 Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Mon, 6 Jan 2014 16:12:14 -0300 Subject: [PATCH 10/50] bootstrap ready! --- .bowerrc | 3 ++ .gitignore | 1 + app/views/includes/foot.jade | 6 +++ app/views/includes/head.jade | 5 ++- app/views/includes/navbar.jade | 17 ++++++++ app/views/index.jade | 3 +- app/views/layouts/default.jade | 3 +- bower.json | 7 ++++ package.json | 74 ++++++++++++++++++---------------- public/css/common.css | 45 +++++++++++++++++++++ public/img/.gitignore | 0 11 files changed, 126 insertions(+), 38 deletions(-) create mode 100644 .bowerrc create mode 100644 app/views/includes/navbar.jade create mode 100644 bower.json create mode 100644 public/css/common.css create mode 100755 public/img/.gitignore diff --git a/.bowerrc b/.bowerrc new file mode 100644 index 0000000..47ad667 --- /dev/null +++ b/.bowerrc @@ -0,0 +1,3 @@ +{ + "directory": "public/lib" +} diff --git a/.gitignore b/.gitignore index 9ad72e0..bb726e2 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,5 @@ npm-debug.log node_modules .DS_Store +public/lib/* diff --git a/app/views/includes/foot.jade b/app/views/includes/foot.jade index e69de29..b2a61b6 100755 --- a/app/views/includes/foot.jade +++ b/app/views/includes/foot.jade @@ -0,0 +1,6 @@ +#footer + .container + p.text-muted Place sticky footer content here. + +script(type='text/javascript', src='/lib/jquery/jquery.min.js') +script(type='text/javascript', src='/lib/bootstrap/dist/js/bootstrap.min.js') diff --git a/app/views/includes/head.jade b/app/views/includes/head.jade index 08e4f44..939021f 100755 --- a/app/views/includes/head.jade +++ b/app/views/includes/head.jade @@ -1,7 +1,7 @@ head meta(charset='utf-8') meta(http-equiv='X-UA-Compatible', content='IE=edge,chrome=1') - meta(name='viewport', content='width=device-width,initial-scale=1') + meta(name='viewport', content='width=device-width,initial-scale=1.0') title BitPay meta(http-equiv='Content-type', content='text/html;charset=UTF-8') @@ -10,3 +10,6 @@ head link(href='/img/icons/favicon.ico', rel='shortcut icon', type='image/x-icon') + link(rel='stylesheet', href='/lib/bootstrap/dist/css/bootstrap.min.css') + link(rel='stylesheet', href='/css/common.css') + \ No newline at end of file diff --git a/app/views/includes/navbar.jade b/app/views/includes/navbar.jade new file mode 100644 index 0000000..eabfbb9 --- /dev/null +++ b/app/views/includes/navbar.jade @@ -0,0 +1,17 @@ +.navbar.navbar-default.navbar-fixed-top(role='navigation') + .container + .navbar-header + button.navbar-toggle(type='button', data-toggle='collapse', data-target='.navbar-collapse') + span.sr-only Toggle navigation + span.icon-bar + span.icon-bar + span.icon-bar + a.navbar-brand(href='#') Mystery + .collapse.navbar-collapse + ul.nav.navbar-nav + li.active + a(href='#') Home + li + a(href='#about') About + li + a(href='#contact') Contact diff --git a/app/views/index.jade b/app/views/index.jade index 874b042..53ad530 100755 --- a/app/views/index.jade +++ b/app/views/index.jade @@ -1,4 +1,5 @@ extends layouts/default block content - h1 Hello BitPay! + .page-header + h1 Hello BitPay! diff --git a/app/views/layouts/default.jade b/app/views/layouts/default.jade index 3c47dc2..186b81c 100755 --- a/app/views/layouts/default.jade +++ b/app/views/layouts/default.jade @@ -2,7 +2,8 @@ doctype html html(lang='en', xmlns='http://www.w3.org/1999/xhtml') include ../includes/head body - section.content + #wrap + include ../includes/navbar section.container block content include ../includes/foot diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..62688af --- /dev/null +++ b/bower.json @@ -0,0 +1,7 @@ +{ + "name": "Mystery", + "version": "0.0.1", + "dependencies": { + "bootstrap": "3.0.3" + } +} \ No newline at end of file diff --git a/package.json b/package.json index d44870a..6a3cbc6 100644 --- a/package.json +++ b/package.json @@ -1,37 +1,41 @@ { - "name": "mystery", - "version": "0.0.1", - "private": true, - "author": { - "name": "Ryan X Charles", - "email": "ryan@bitpay.com" - }, - "repository": "git://github.com/bitpay/mystery.git", - "contributors": [{ - "name": "Matias Alejo Garcia", - "email": "ematiu@gmail.com" - }], - "bugs": { - "url": "https://github.com/bitpay/mystery/issues" - }, - "homepage": "https://github.com/bitpay/mystery", - "license": "MIT", - "keywords": [ - "mystery", - "secret", - "enigma", - "riddle", - "mystification", - "puzzle", - "conundrum" - ], - "engines": { - "node": "*" - }, - "dependencies": { - "express": "~3.4.7", - "jade": "~1.0.2", - "mongoose": "~3.8.3", - "lodash": "~2.4.1" - } + "name": "mystery", + "version": "0.0.1", + "private": true, + "author": { + "name": "Ryan X Charles", + "email": "ryan@bitpay.com" + }, + "repository": "git://github.com/bitpay/mystery.git", + "contributors": [{ + "name": "Matias Alejo Garcia", + "email": "ematiu@gmail.com" + }], + "bugs": { + "url": "https://github.com/bitpay/mystery/issues" + }, + "homepage": "https://github.com/bitpay/mystery", + "license": "MIT", + "keywords": [ + "mystery", + "secret", + "enigma", + "riddle", + "mystification", + "puzzle", + "conundrum" + ], + "engines": { + "node": "*" + }, + "scripts": { + "postinstall": "node node_modules/bower/bin/bower install" + }, + "dependencies": { + "express": "~3.4.7", + "jade": "~1.0.2", + "mongoose": "~3.8.3", + "lodash": "~2.4.1", + "bower": "~1.2.8" + } } diff --git a/public/css/common.css b/public/css/common.css new file mode 100644 index 0000000..7ca093a --- /dev/null +++ b/public/css/common.css @@ -0,0 +1,45 @@ +/* Sticky footer styles +-------------------------------------------------- */ + +html, +body { + height: 100%; + /* The html and body elements cannot have any padding or margin. */ +} + +/* Wrapper for page content to push down footer */ +#wrap { + min-height: 100%; + height: auto; + /* Negative indent footer by its height */ + margin: 0 auto -60px; + /* Pad bottom by footer height */ + padding: 0 0 60px; +} + +/* Set the fixed height of the footer here */ +#footer { + height: 60px; + background-color: #f5f5f5; +} + + +/* Custom page CSS +-------------------------------------------------- */ +/* Not required for template or sticky footer method. */ + +#wrap > .container { + padding: 60px 15px 0; +} +.container .text-muted { + margin: 20px 0; +} + +#footer > .container { + padding-left: 15px; + padding-right: 15px; +} + +code { + font-size: 80%; +} diff --git a/public/img/.gitignore b/public/img/.gitignore new file mode 100755 index 0000000..e69de29 From 6f0a6d8b069a02784bc242397495ba0cf1ffc8af Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 6 Jan 2014 17:19:14 -0300 Subject: [PATCH 11/50] sample CLi to get a block using the RPC interfase + Bitcore --- README.md | 2 +- etc/bitcoind/bitcoin.conf | 5 +++-- util/get_block.js | 27 +++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) create mode 100755 util/get_block.js diff --git a/README.md b/README.md index 96ff245..69bc9c9 100644 --- a/README.md +++ b/README.md @@ -7,4 +7,4 @@ mystery There is a bitcoind configuration sample at: ``` etc/mystery/bitcoin.conf -```: +``` diff --git a/etc/bitcoind/bitcoin.conf b/etc/bitcoind/bitcoin.conf index 50bac19..062c09e 100644 --- a/etc/bitcoind/bitcoin.conf +++ b/etc/bitcoind/bitcoin.conf @@ -1,11 +1,12 @@ rpcuser=mystery rpcpassword=real_mystery server=1 -rpcallowip=127.0.0.1 rpcport=8332 -testnet=1 +testnet=3 txindex=1 +# Allow connections outsite localhost? +# rpcallowip=192.168.0.* diff --git a/util/get_block.js b/util/get_block.js new file mode 100755 index 0000000..27880d8 --- /dev/null +++ b/util/get_block.js @@ -0,0 +1,27 @@ +#!/usr/bin/env node + + + +var RpcClient = require('../node_modules/bitcore/RpcClient').class(); + + +var block_hash = process.argv[2] || '0000000000b6288775bbd326bedf324ca8717a15191da58391535408205aada4'; + +var rpc = new RpcClient({ + user: 'mystery', + pass: 'real_mystery', + protocol: 'http', +}); + +var block = rpc.getBlock(block_hash, function(err, block) { + + console.log("Err:"); + console.log(err); + + + console.log("Block info:"); + console.log(block); +}); + + + From 3216cadac9084cd0f7ee892550153ff4d10fc320 Mon Sep 17 00:00:00 2001 From: Mario Colque Date: Mon, 6 Jan 2014 17:32:22 -0300 Subject: [PATCH 12/50] added .nodemonignore to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index bb726e2..e322bd9 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ results npm-debug.log node_modules +.nodemonignore .DS_Store public/lib/* From fab9d62df6e8add327946ad461ea5f787d3aa319 Mon Sep 17 00:00:00 2001 From: Mario Colque Date: Mon, 6 Jan 2014 17:32:58 -0300 Subject: [PATCH 13/50] added .editorconfig --- .editorconfig | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c2cdfb8 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,21 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# editorconfig.org + +root = true + + +[*] + +# Change these settings to your own preference +indent_style = space +indent_size = 2 + +# We recommend you to keep these unchanged +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false From f73586d49fc3f3744ce97f5ee0f95d5175b9f664 Mon Sep 17 00:00:00 2001 From: Mario Colque Date: Mon, 6 Jan 2014 17:33:44 -0300 Subject: [PATCH 14/50] Added Grunt and jsint --- .jshintrc | 40 +++++++++++++++++++++++++ Gruntfile.js | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 .jshintrc create mode 100644 Gruntfile.js diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..66eeef6 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,40 @@ +{ + "node": true, // Enable globals available when code is running inside of the NodeJS runtime environment. + "browser": true, // Standard browser globals e.g. `window`, `document`. + "esnext": true, // Allow ES.next specific features such as `const` and `let`. + "bitwise": false, // Prohibit bitwise operators (&, |, ^, etc.). + "camelcase": false, // Permit only camelcase for `var` and `object indexes`. + "curly": false, // Require {} for every new block or scope. + "eqeqeq": true, // Require triple equals i.e. `===`. + "immed": true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );` + "latedef": true, // Prohibit variable use before definition. + "newcap": true, // Require capitalization of all constructor functions e.g. `new F()`. + "noarg": true, // Prohibit use of `arguments.caller` and `arguments.callee`. + "quotmark": "single", // Define quotes to string values. + "regexp": true, // Prohibit `.` and `[^...]` in regular expressions. + "undef": true, // Require all non-global variables be declared before they are used. + "unused": true, // Warn unused variables. + "strict": true, // Require `use strict` pragma in every file. + "trailing": true, // Prohibit trailing whitespaces. + "smarttabs": false, // Suppresses warnings about mixed tabs and spaces + "globals": { // Globals variables. + "angular": true + }, + "predef": [ // Extra globals. + "define", + "require", + "exports", + "module", + "describe", + "before", + "beforeEach", + "after", + "afterEach", + "it", + "inject", + "expect" + ], + "indent": 4, // Specify indentation spacing + "devel": true, // Allow development statements e.g. `console.log();`. + "noempty": true // Prohibit use of empty blocks. +} \ No newline at end of file diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 0000000..9a93a60 --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,83 @@ +'use strict'; + +module.exports = function(grunt) { + // Project Configuration + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + watch: { + jade: { + files: ['app/views/**'], + options: { + livereload: true, + }, + }, + js: { + files: ['Gruntfile.js', 'server.js', 'app/**/*.js', 'public/js/**'], + tasks: ['jshint'], + options: { + livereload: true, + }, + }, + html: { + files: ['public/views/**'], + options: { + livereload: true, + }, + }, + css: { + files: ['public/css/**'], + options: { + livereload: true + } + } + }, + jshint: { + all: { + src: ['Gruntfile.js', 'server.js', 'app/**/*.js', 'public/js/**'], + options: { + jshintrc: true + } + } + }, + nodemon: { + dev: { + options: { + file: 'server.js', + args: [], + ignoredFiles: ['public/**'], + watchedExtensions: ['js'], + nodeArgs: ['--debug'], + delayTime: 1, + env: { + PORT: 3000 + }, + cwd: __dirname + } + } + }, + concurrent: { + tasks: ['nodemon', 'watch'], + options: { + logConcurrentOutput: true + } + }, + env: { + test: { + NODE_ENV: 'test' + } + } + }); + + //Load NPM tasks + grunt.loadNpmTasks('grunt-contrib-watch'); + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-nodemon'); + grunt.loadNpmTasks('grunt-concurrent'); + grunt.loadNpmTasks('grunt-env'); + + //Making grunt default to force in order not to break the project. + grunt.option('force', true); + + //Default task(s). + grunt.registerTask('default', ['jshint', 'concurrent']); +}; From cbc7a6773a6118a004abbb2d8e37b46f1191e59c Mon Sep 17 00:00:00 2001 From: Mario Colque Date: Mon, 6 Jan 2014 17:34:17 -0300 Subject: [PATCH 15/50] package.json updated --- package.json | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index be95e6e..b17b04a 100644 --- a/package.json +++ b/package.json @@ -7,10 +7,12 @@ "email": "ryan@bitpay.com" }, "repository": "git://github.com/bitpay/mystery.git", - "contributors": [{ - "name": "Matias Alejo Garcia", - "email": "ematiu@gmail.com" - }], + "contributors": [ + { + "name": "Matias Alejo Garcia", + "email": "ematiu@gmail.com" + } + ], "bugs": { "url": "https://github.com/bitpay/mystery/issues" }, @@ -29,6 +31,7 @@ "node": "*" }, "scripts": { + "start": "node node_modules/grunt-cli/bin/grunt", "postinstall": "node node_modules/bower/bin/bower install" }, "dependencies": { @@ -37,6 +40,19 @@ "mongoose": "~3.8.3", "lodash": "~2.4.1", "bower": "~1.2.8", - "bitcore": "*" + "bitcore": "*", + "grunt": "~0.4.2", + "grunt-cli": "~0.1.11", + "grunt-env": "~0.4.1", + "grunt-contrib-jshint": "~0.8.0", + "grunt-contrib-watch": "~0.5.3", + "grunt-concurrent": "~0.4.2", + "grunt-nodemon": "~0.1.2" + }, + "devDependencies": { + "grunt-contrib-watch": "~0.5.3", + "grunt-contrib-jshint": "~0.8.0", + "grunt-nodemon": "~0.1.2", + "grunt-concurrent": "~0.4.2" } } From cf1deca94ff8ae5f2165662fdb717e05cd9df404 Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Mon, 6 Jan 2014 17:34:25 -0300 Subject: [PATCH 16/50] angular js supported! --- app/views/includes/foot.jade | 29 ++++++++++++++++++++-- app/views/includes/navbar.jade | 18 +------------- app/views/index.jade | 43 +++++++++++++++++---------------- app/views/layouts/default.jade | 3 +-- bower.json | 9 ++++++- public/js/app.js | 5 ++++ public/js/config.js | 21 ++++++++++++++++ public/js/controllers/header.js | 15 ++++++++++++ public/js/controllers/index.js | 5 ++++ public/js/directives.js | 1 + public/js/filters.js | 1 + public/js/init.js | 9 +++++++ public/js/services/global.js | 14 +++++++++++ public/views/header.html | 18 ++++++++++++++ public/views/index.html | 5 ++++ 15 files changed, 153 insertions(+), 43 deletions(-) create mode 100755 public/js/app.js create mode 100755 public/js/config.js create mode 100755 public/js/controllers/header.js create mode 100755 public/js/controllers/index.js create mode 100755 public/js/directives.js create mode 100755 public/js/filters.js create mode 100755 public/js/init.js create mode 100755 public/js/services/global.js create mode 100755 public/views/header.html create mode 100644 public/views/index.html diff --git a/app/views/includes/foot.jade b/app/views/includes/foot.jade index b2a61b6..f7cc3e6 100755 --- a/app/views/includes/foot.jade +++ b/app/views/includes/foot.jade @@ -2,5 +2,30 @@ .container p.text-muted Place sticky footer content here. -script(type='text/javascript', src='/lib/jquery/jquery.min.js') -script(type='text/javascript', src='/lib/bootstrap/dist/js/bootstrap.min.js') +//script(type='text/javascript', src='/lib/jquery/jquery.min.js') +//script(type='text/javascript', src='/lib/bootstrap/dist/js/bootstrap.min.js') + +//AngularJS +script(type='text/javascript', src='/lib/angular/angular.js') +script(type='text/javascript', src='/lib/angular-cookies/angular-cookies.js') +script(type='text/javascript', src='/lib/angular-resource/angular-resource.js') +script(type='text/javascript', src='/lib/angular-route/angular-route.js') + +//Angular UI +script(type='text/javascript', src='/lib/angular-bootstrap/ui-bootstrap.js') +script(type='text/javascript', src='/lib/angular-bootstrap/ui-bootstrap-tpls.js') +script(type='text/javascript', src='/lib/angular-ui-utils/ui-utils.js') + +//Application Init +script(type='text/javascript', src='/js/app.js') +script(type='text/javascript', src='/js/config.js') +script(type='text/javascript', src='/js/directives.js') +script(type='text/javascript', src='/js/filters.js') + +//Application Services +script(type='text/javascript', src='/js/services/global.js') + +//Application Controllers +script(type='text/javascript', src='/js/controllers/index.js') +script(type='text/javascript', src='/js/controllers/header.js') +script(type='text/javascript', src='/js/init.js') diff --git a/app/views/includes/navbar.jade b/app/views/includes/navbar.jade index eabfbb9..a1b2b1c 100644 --- a/app/views/includes/navbar.jade +++ b/app/views/includes/navbar.jade @@ -1,17 +1 @@ -.navbar.navbar-default.navbar-fixed-top(role='navigation') - .container - .navbar-header - button.navbar-toggle(type='button', data-toggle='collapse', data-target='.navbar-collapse') - span.sr-only Toggle navigation - span.icon-bar - span.icon-bar - span.icon-bar - a.navbar-brand(href='#') Mystery - .collapse.navbar-collapse - ul.nav.navbar-nav - li.active - a(href='#') Home - li - a(href='#about') About - li - a(href='#contact') Contact +.navbar.navbar-default.navbar-fixed-top(data-ng-include="'views/header.html'", role='navigation') diff --git a/app/views/index.jade b/app/views/index.jade index cd0eb69..7f33718 100755 --- a/app/views/index.jade +++ b/app/views/index.jade @@ -1,24 +1,25 @@ extends layouts/default block content - .page-header - h1 Hello BitPay! - p ˈmɪst(ə)ri/' - | noun - audio(src="https://ssl.gstatic.com/dictionary/static/sounds/de/0/mystery.mp3",preload="auto",data-dobid="aud",id="aud") - button(onclick="document.getElementById('aud').play()") Play - - ol - li - strong something that is difficult or impossible to understand or explain. - p "the mysteries of outer space" - | synonyms: puzzle, enigma, conundrum, riddle, secret, unsolved problem, problem, question, question mark, closed book; secrecy or obscurity. - p "much of her past is shrouded in mystery" - | synonyms: secrecy, darkness, obscurity, ambiguity, ambiguousness, uncertainty, impenetrability, vagueness, nebulousness; More - li - strong a person or thing whose identity or nature is puzzling or unknown. - p "‘He's a bit of a mystery,’ said Nina" - li - strong a novel, play, or film dealing with a puzzling crime, especially a murder. - p "the 1920s murder mystery, The Ghost Train" - | synonyms: thriller, detective story/novel, murder story; More + section.container(data-ng-view) + + section.container + p ˈmɪst(ə)ri/' + | noun + audio(src="https://ssl.gstatic.com/dictionary/static/sounds/de/0/mystery.mp3",preload="auto",data-dobid="aud",id="aud") + button(onclick="document.getElementById('aud').play()") Play + + ol + li + strong something that is difficult or impossible to understand or explain. + p "the mysteries of outer space" + | synonyms: puzzle, enigma, conundrum, riddle, secret, unsolved problem, problem, question, question mark, closed book; secrecy or obscurity. + p "much of her past is shrouded in mystery" + | synonyms: secrecy, darkness, obscurity, ambiguity, ambiguousness, uncertainty, impenetrability, vagueness, nebulousness; More + li + strong a person or thing whose identity or nature is puzzling or unknown. + p "‘He's a bit of a mystery,’ said Nina" + li + strong a novel, play, or film dealing with a puzzling crime, especially a murder. + p "the 1920s murder mystery, The Ghost Train" + | synonyms: thriller, detective story/novel, murder story; More diff --git a/app/views/layouts/default.jade b/app/views/layouts/default.jade index 186b81c..64e2713 100755 --- a/app/views/layouts/default.jade +++ b/app/views/layouts/default.jade @@ -4,6 +4,5 @@ html(lang='en', xmlns='http://www.w3.org/1999/xhtml') body #wrap include ../includes/navbar - section.container - block content + block content include ../includes/foot diff --git a/bower.json b/bower.json index 62688af..46be4c5 100644 --- a/bower.json +++ b/bower.json @@ -2,6 +2,13 @@ "name": "Mystery", "version": "0.0.1", "dependencies": { - "bootstrap": "3.0.3" + "angular": "latest", + "angular-resource": "latest", + "angular-cookies": "latest", + "angular-mocks": "latest", + "angular-route": "latest", + "bootstrap": "3.0.3", + "angular-bootstrap": "0.9.0", + "angular-ui-utils": "0.1.0" } } \ No newline at end of file diff --git a/public/js/app.js b/public/js/app.js new file mode 100755 index 0000000..77b64cb --- /dev/null +++ b/public/js/app.js @@ -0,0 +1,5 @@ +'use strict'; + +angular.module('mystery', ['ngCookies', 'ngResource', 'ngRoute', 'ui.bootstrap', 'ui.route', 'mystery.system']); + +angular.module('mystery.system', []); \ No newline at end of file diff --git a/public/js/config.js b/public/js/config.js new file mode 100755 index 0000000..b86700b --- /dev/null +++ b/public/js/config.js @@ -0,0 +1,21 @@ +'use strict'; + +//Setting up route +angular.module('mystery').config(['$routeProvider', + function($routeProvider) { + $routeProvider. + when('/', { + templateUrl: 'views/index.html' + }). + otherwise({ + redirectTo: '/' + }); + } +]); + +//Setting HTML5 Location Mode +angular.module('mystery').config(['$locationProvider', + function($locationProvider) { + $locationProvider.hashPrefix('!'); + } +]); \ No newline at end of file diff --git a/public/js/controllers/header.js b/public/js/controllers/header.js new file mode 100755 index 0000000..512cb00 --- /dev/null +++ b/public/js/controllers/header.js @@ -0,0 +1,15 @@ +'use strict'; + +angular.module('mystery.system').controller('HeaderController', ['$scope', 'Global', function ($scope, Global) { + $scope.global = Global; + + $scope.menu = [{ + 'title': 'Articles', + 'link': 'articles' + }, { + 'title': 'Create New Article', + 'link': 'articles/create' + }]; + + $scope.isCollapsed = false; +}]); \ No newline at end of file diff --git a/public/js/controllers/index.js b/public/js/controllers/index.js new file mode 100755 index 0000000..503829c --- /dev/null +++ b/public/js/controllers/index.js @@ -0,0 +1,5 @@ +'use strict'; + +angular.module('mystery.system').controller('IndexController', ['$scope', 'Global', function ($scope, Global) { + $scope.global = Global; +}]); \ No newline at end of file diff --git a/public/js/directives.js b/public/js/directives.js new file mode 100755 index 0000000..a726efc --- /dev/null +++ b/public/js/directives.js @@ -0,0 +1 @@ +'use strict'; \ No newline at end of file diff --git a/public/js/filters.js b/public/js/filters.js new file mode 100755 index 0000000..a726efc --- /dev/null +++ b/public/js/filters.js @@ -0,0 +1 @@ +'use strict'; \ No newline at end of file diff --git a/public/js/init.js b/public/js/init.js new file mode 100755 index 0000000..d7c9428 --- /dev/null +++ b/public/js/init.js @@ -0,0 +1,9 @@ +'use strict'; + +angular.element(document).ready(function() { + //Fixing facebook bug with redirect + if (window.location.hash === '#_=_') window.location.hash = '#!'; + + //Then init the app + angular.bootstrap(document, ['mystery']); +}); \ No newline at end of file diff --git a/public/js/services/global.js b/public/js/services/global.js new file mode 100755 index 0000000..8dc532e --- /dev/null +++ b/public/js/services/global.js @@ -0,0 +1,14 @@ +'use strict'; + +//Global service for global variables +angular.module('mystery.system').factory('Global', [ + function() { + var _this = this; + _this._data = { + user: window.user, + authenticated: !! window.user + }; + + return _this._data; + } +]); diff --git a/public/views/header.html b/public/views/header.html new file mode 100755 index 0000000..70189e7 --- /dev/null +++ b/public/views/header.html @@ -0,0 +1,18 @@ +
+ + +
diff --git a/public/views/index.html b/public/views/index.html new file mode 100644 index 0000000..b92fe02 --- /dev/null +++ b/public/views/index.html @@ -0,0 +1,5 @@ +
+ +
From 86e11424d8735d19ccb228cf86c6c3983c2450d7 Mon Sep 17 00:00:00 2001 From: Mario Colque Date: Mon, 6 Jan 2014 17:54:32 -0300 Subject: [PATCH 17/50] removed spaces --- .jshintrc | 4 +- Gruntfile.js | 144 ++++++++++++++++---------------- public/js/config.js | 26 +++--- public/js/controllers/header.js | 22 ++--- public/js/init.js | 10 +-- public/js/services/global.js | 16 ++-- 6 files changed, 111 insertions(+), 111 deletions(-) diff --git a/.jshintrc b/.jshintrc index 66eeef6..bd532c2 100644 --- a/.jshintrc +++ b/.jshintrc @@ -34,7 +34,7 @@ "inject", "expect" ], - "indent": 4, // Specify indentation spacing + "indent": 2, // Specify indentation spacing "devel": true, // Allow development statements e.g. `console.log();`. "noempty": true // Prohibit use of empty blocks. -} \ No newline at end of file +} diff --git a/Gruntfile.js b/Gruntfile.js index 9a93a60..6d397b7 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,83 +1,83 @@ 'use strict'; module.exports = function(grunt) { - // Project Configuration - grunt.initConfig({ - pkg: grunt.file.readJSON('package.json'), - watch: { - jade: { - files: ['app/views/**'], - options: { - livereload: true, - }, - }, - js: { - files: ['Gruntfile.js', 'server.js', 'app/**/*.js', 'public/js/**'], - tasks: ['jshint'], - options: { - livereload: true, - }, - }, - html: { - files: ['public/views/**'], - options: { - livereload: true, - }, - }, - css: { - files: ['public/css/**'], - options: { - livereload: true - } - } + // Project Configuration + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + watch: { + jade: { + files: ['app/views/**'], + options: { + livereload: true, }, - jshint: { - all: { - src: ['Gruntfile.js', 'server.js', 'app/**/*.js', 'public/js/**'], - options: { - jshintrc: true - } - } + }, + js: { + files: ['Gruntfile.js', 'server.js', 'app/**/*.js', 'public/js/**'], + tasks: ['jshint'], + options: { + livereload: true, }, - nodemon: { - dev: { - options: { - file: 'server.js', - args: [], - ignoredFiles: ['public/**'], - watchedExtensions: ['js'], - nodeArgs: ['--debug'], - delayTime: 1, - env: { - PORT: 3000 - }, - cwd: __dirname - } - } + }, + html: { + files: ['public/views/**'], + options: { + livereload: true, }, - concurrent: { - tasks: ['nodemon', 'watch'], - options: { - logConcurrentOutput: true - } - }, - env: { - test: { - NODE_ENV: 'test' - } + }, + css: { + files: ['public/css/**'], + options: { + livereload: true } - }); + } + }, + jshint: { + all: { + src: ['Gruntfile.js', 'server.js', 'app/**/*.js', 'public/js/**'], + options: { + jshintrc: true + } + } + }, + nodemon: { + dev: { + options: { + file: 'server.js', + args: [], + ignoredFiles: ['public/**'], + watchedExtensions: ['js'], + nodeArgs: ['--debug'], + delayTime: 1, + env: { + PORT: 3000 + }, + cwd: __dirname + } + } + }, + concurrent: { + tasks: ['nodemon', 'watch'], + options: { + logConcurrentOutput: true + } + }, + env: { + test: { + NODE_ENV: 'test' + } + } + }); - //Load NPM tasks - grunt.loadNpmTasks('grunt-contrib-watch'); - grunt.loadNpmTasks('grunt-contrib-jshint'); - grunt.loadNpmTasks('grunt-nodemon'); - grunt.loadNpmTasks('grunt-concurrent'); - grunt.loadNpmTasks('grunt-env'); + //Load NPM tasks + grunt.loadNpmTasks('grunt-contrib-watch'); + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-nodemon'); + grunt.loadNpmTasks('grunt-concurrent'); + grunt.loadNpmTasks('grunt-env'); - //Making grunt default to force in order not to break the project. - grunt.option('force', true); + //Making grunt default to force in order not to break the project. + grunt.option('force', true); - //Default task(s). - grunt.registerTask('default', ['jshint', 'concurrent']); + //Default task(s). + grunt.registerTask('default', ['jshint', 'concurrent']); }; diff --git a/public/js/config.js b/public/js/config.js index b86700b..fe68006 100755 --- a/public/js/config.js +++ b/public/js/config.js @@ -2,20 +2,20 @@ //Setting up route angular.module('mystery').config(['$routeProvider', - function($routeProvider) { - $routeProvider. - when('/', { - templateUrl: 'views/index.html' - }). - otherwise({ - redirectTo: '/' - }); - } + function($routeProvider) { + $routeProvider. + when('/', { + templateUrl: 'views/index.html' + }). + otherwise({ + redirectTo: '/' + }); + } ]); //Setting HTML5 Location Mode angular.module('mystery').config(['$locationProvider', - function($locationProvider) { - $locationProvider.hashPrefix('!'); - } -]); \ No newline at end of file + function($locationProvider) { + $locationProvider.hashPrefix('!'); + } +]); diff --git a/public/js/controllers/header.js b/public/js/controllers/header.js index 512cb00..039a5ac 100755 --- a/public/js/controllers/header.js +++ b/public/js/controllers/header.js @@ -1,15 +1,15 @@ 'use strict'; angular.module('mystery.system').controller('HeaderController', ['$scope', 'Global', function ($scope, Global) { - $scope.global = Global; + $scope.global = Global; - $scope.menu = [{ - 'title': 'Articles', - 'link': 'articles' - }, { - 'title': 'Create New Article', - 'link': 'articles/create' - }]; - - $scope.isCollapsed = false; -}]); \ No newline at end of file + $scope.menu = [{ + 'title': 'Articles', + 'link': 'articles' + }, { + 'title': 'Create New Article', + 'link': 'articles/create' + }]; + + $scope.isCollapsed = false; +}]); diff --git a/public/js/init.js b/public/js/init.js index d7c9428..b226e6f 100755 --- a/public/js/init.js +++ b/public/js/init.js @@ -1,9 +1,9 @@ 'use strict'; angular.element(document).ready(function() { - //Fixing facebook bug with redirect - if (window.location.hash === '#_=_') window.location.hash = '#!'; + //Fixing facebook bug with redirect + if (window.location.hash === '#_=_') window.location.hash = '#!'; - //Then init the app - angular.bootstrap(document, ['mystery']); -}); \ No newline at end of file + //Then init the app + angular.bootstrap(document, ['mystery']); +}); diff --git a/public/js/services/global.js b/public/js/services/global.js index 8dc532e..7900652 100755 --- a/public/js/services/global.js +++ b/public/js/services/global.js @@ -2,13 +2,13 @@ //Global service for global variables angular.module('mystery.system').factory('Global', [ - function() { - var _this = this; - _this._data = { - user: window.user, - authenticated: !! window.user - }; + function() { + var _this = this; + _this._data = { + user: window.user, + authenticated: !! window.user + }; - return _this._data; - } + return _this._data; + } ]); From be497058fc87598b66e2aabd4bccea4adedb4aae Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Mon, 6 Jan 2014 18:01:23 -0300 Subject: [PATCH 18/50] little fix in tab spaces --- public/js/controllers/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/js/controllers/index.js b/public/js/controllers/index.js index 503829c..4cb2b6f 100755 --- a/public/js/controllers/index.js +++ b/public/js/controllers/index.js @@ -1,5 +1,5 @@ 'use strict'; angular.module('mystery.system').controller('IndexController', ['$scope', 'Global', function ($scope, Global) { - $scope.global = Global; + $scope.global = Global; }]); \ No newline at end of file From 075f86ba43fd8fbdf4c0ccba291b674f8d9158a4 Mon Sep 17 00:00:00 2001 From: Mario Colque Date: Mon, 6 Jan 2014 18:16:28 -0300 Subject: [PATCH 19/50] added installation steps --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 69bc9c9..35ff00c 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,13 @@ mystery ======= +## Install + +- sudo npm -g i grunt-cli +- npm i +- grunt + + ## bitcoind configuration There is a bitcoind configuration sample at: From ade4053e010bbe6cd2395422cc6ffd8f61d9c55d Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Mon, 6 Jan 2014 18:38:30 -0300 Subject: [PATCH 20/50] mocha support! --- Gruntfile.js | 11 +++++++++++ package.json | 12 +++++++----- test/test.js | 9 +++++++++ 3 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 test/test.js diff --git a/Gruntfile.js b/Gruntfile.js index 6d397b7..743d984 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -61,6 +61,13 @@ module.exports = function(grunt) { logConcurrentOutput: true } }, + mochaTest: { + options: { + reporter: 'spec', + require: 'server.js' + }, + src: ['test/*.js'] + }, env: { test: { NODE_ENV: 'test' @@ -71,6 +78,7 @@ module.exports = function(grunt) { //Load NPM tasks grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-mocha-test'); grunt.loadNpmTasks('grunt-nodemon'); grunt.loadNpmTasks('grunt-concurrent'); grunt.loadNpmTasks('grunt-env'); @@ -80,4 +88,7 @@ module.exports = function(grunt) { //Default task(s). grunt.registerTask('default', ['jshint', 'concurrent']); + + //Test task. + grunt.registerTask('test', ['env:test', 'mochaTest']); }; diff --git a/package.json b/package.json index b17b04a..b407613 100644 --- a/package.json +++ b/package.json @@ -47,12 +47,14 @@ "grunt-contrib-jshint": "~0.8.0", "grunt-contrib-watch": "~0.5.3", "grunt-concurrent": "~0.4.2", - "grunt-nodemon": "~0.1.2" + "grunt-nodemon": "~0.1.2", + "grunt-mocha-test": "~0.8.1" }, "devDependencies": { - "grunt-contrib-watch": "~0.5.3", - "grunt-contrib-jshint": "~0.8.0", - "grunt-nodemon": "~0.1.2", - "grunt-concurrent": "~0.4.2" + "grunt-contrib-watch": "latest", + "grunt-contrib-jshint": "latest", + "grunt-nodemon": "latest", + "grunt-concurrent": "latest", + "grunt-mocha-test": "latest" } } diff --git a/test/test.js b/test/test.js new file mode 100644 index 0000000..bab25b6 --- /dev/null +++ b/test/test.js @@ -0,0 +1,9 @@ +var assert = require("assert") +describe('Array', function(){ + describe('#indexOf()', function(){ + it('should return -1 when the value is not present', function(){ + assert.equal(-1, [1,2,3].indexOf(5)); + assert.equal(-1, [1,2,3].indexOf(0)); + }) + }) +}) From 1c96756743206fa0301dccab1b51f28708dad6aa Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 6 Jan 2014 19:02:33 -0300 Subject: [PATCH 21/50] getblock working! --- config/env/development.js | 7 ++++++- config/routes.js | 6 ++++-- package.json | 1 + util/get_block.js | 12 +++++------- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/config/env/development.js b/config/env/development.js index 0ef298c..2ddf0dc 100755 --- a/config/env/development.js +++ b/config/env/development.js @@ -4,5 +4,10 @@ module.exports = { db: "mongodb://localhost/mystery-dev", app: { name: "Mystery - Development" + }, + bitcoind: { + user: 'mystery', + pass: 'real_mystery', + protocol: 'http', } -} \ No newline at end of file +} diff --git a/config/routes.js b/config/routes.js index 182a216..1f75a0e 100644 --- a/config/routes.js +++ b/config/routes.js @@ -6,7 +6,9 @@ module.exports = function(app) { var index = require('../app/controllers/index'); app.get('/', index.render); - //TX routes - // + //Block routes + var blocks = require('model/app/controllers/blocks'); + app.get('/block/:block_hash', blocks.show); + }; diff --git a/package.json b/package.json index be95e6e..0188d4d 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "postinstall": "node node_modules/bower/bin/bower install" }, "dependencies": { + "classtool": "*", "express": "~3.4.7", "jade": "~1.0.2", "mongoose": "~3.8.3", diff --git a/util/get_block.js b/util/get_block.js index 27880d8..783d7cf 100755 --- a/util/get_block.js +++ b/util/get_block.js @@ -1,17 +1,15 @@ #!/usr/bin/env node - - +process.env.NODE_ENV = process.env.NODE_ENV || 'development'; var RpcClient = require('../node_modules/bitcore/RpcClient').class(); +var config = require('../config/config'); + var block_hash = process.argv[2] || '0000000000b6288775bbd326bedf324ca8717a15191da58391535408205aada4'; -var rpc = new RpcClient({ - user: 'mystery', - pass: 'real_mystery', - protocol: 'http', -}); + +var rpc = new RpcClient(config.bitcoind); var block = rpc.getBlock(block_hash, function(err, block) { From 6c4e476555d853ce1ea5b652f55685a576257573 Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Mon, 6 Jan 2014 19:36:47 -0300 Subject: [PATCH 22/50] mocha testing --- package.json | 6 ++++-- test/mocha.opts | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 test/mocha.opts diff --git a/package.json b/package.json index b407613..110c3e0 100644 --- a/package.json +++ b/package.json @@ -48,13 +48,15 @@ "grunt-contrib-watch": "~0.5.3", "grunt-concurrent": "~0.4.2", "grunt-nodemon": "~0.1.2", - "grunt-mocha-test": "~0.8.1" + "grunt-mocha-test": "~0.8.1", + "should": "~2.1.1" }, "devDependencies": { "grunt-contrib-watch": "latest", "grunt-contrib-jshint": "latest", "grunt-nodemon": "latest", "grunt-concurrent": "latest", - "grunt-mocha-test": "latest" + "grunt-mocha-test": "latest", + "should": "latest" } } diff --git a/test/mocha.opts b/test/mocha.opts new file mode 100644 index 0000000..74590dc --- /dev/null +++ b/test/mocha.opts @@ -0,0 +1,4 @@ +--require should +-R spec +--ui bdd + From e79e81fe4b4cb164959aa3f68728be4e5fc766d0 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Mon, 6 Jan 2014 23:50:29 -0300 Subject: [PATCH 23/50] block syncing working! --- app/models/Block.js | 68 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 3 +- util/sync.js | 64 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 app/models/Block.js create mode 100755 util/sync.js diff --git a/app/models/Block.js b/app/models/Block.js new file mode 100644 index 0000000..9440426 --- /dev/null +++ b/app/models/Block.js @@ -0,0 +1,68 @@ +'use strict'; + +/** + * Module dependencies. + */ +var mongoose = require('mongoose'), + Schema = mongoose.Schema; + + +/** + * Block Schema + */ +var BlockSchema = new Schema({ + hash: { + type: String, + index: true, + unique: true, + }, + size: Number, + confirmations: Number, + version: Number, + merkleroot: String, + tx: [ String ], + time: Date, + nonce: Number, + bits: String, + difficulty: Number, + chainwork: String, + previousblockhash: { + type: String, + index: true, + unique: true, + }, + nextblockhash: { + type: String, + index: true, + unique: true, + }, +}); + +/** + * Validations + */ + +/* +BlockSchema.path('title').validate(function(title) { + return title.length; +},'Title cannot be blank'); +*/ + +/** + * Statics + */ + +BlockSchema.statics.load = function(id, cb) { + this.findOne({ + _id: id + }).exec(cb); +}; + + +BlockSchema.statics.fromHash = function(hash, cb) { + this.findOne({ + hash: hash, + }).exec(cb); +}; + +module.exports = mongoose.model('Block', BlockSchema); diff --git a/package.json b/package.json index 0188d4d..b235128 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "mongoose": "~3.8.3", "lodash": "~2.4.1", "bower": "~1.2.8", - "bitcore": "*" + "bitcore": "*", + "buffertools": "*" } } diff --git a/util/sync.js b/util/sync.js new file mode 100755 index 0000000..9fe5a5b --- /dev/null +++ b/util/sync.js @@ -0,0 +1,64 @@ +#!/usr/bin/env node + +process.env.NODE_ENV = process.env.NODE_ENV || 'development'; +require('buffertools').extend(); + +var RpcClient = require('../node_modules/bitcore/RpcClient').class(); +var networks = require('../node_modules/bitcore/networks'); + +var Block = require('../app/models/Block'); +var config = require('../config/config'); +var mongoose = require('mongoose'); + +var networkName = process.argv[2] || 'testnet'; +var genesisBlockHash = networks.testnet.genesisBlock.hash.reverse().toString('hex'); + + +function syncBlocks(blockHash) { + + rpc.getBlock(blockHash, function(err, blockInfo) { + if (err) { + console.log(err); + throw(err); + } + + if ( ! ( blockInfo.result.height % 1000) ) + console.log("Height:" + blockInfo.result.height); + + Block.create( blockInfo.result, function(err, inBlock) { + + if (err && err.toString().match(/E11000/)) { +// console.log("\twas there. Skipping"); + return syncBlocks(blockInfo.result.nextblockhash); + } + + if (err) throw(err); + + if (inBlock.nextblockhash && ! inBlock.nextblockhash.match(/^0+$/) ) { + syncBlocks(inBlock.nextblockhash) + } + else { + mongoose.connection.close(); + } + + }); + }); + +} + + +mongoose.connect(config.db); + +var db = mongoose.connection; +var rpc = new RpcClient(config.bitcoind); + + +db.on('error', console.error.bind(console, 'connection error:')); +db.once('open', function callback () { + + syncBlocks(genesisBlockHash); + +}); + + + From b1a439e688c67dce8e7fd79a3e1e6745eb57f830 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 7 Jan 2014 09:11:01 -0300 Subject: [PATCH 24/50] add percentage status to sync --- util/sync.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/util/sync.js b/util/sync.js index 2cb5d5e..78991de 100755 --- a/util/sync.js +++ b/util/sync.js @@ -3,6 +3,7 @@ process.env.NODE_ENV = process.env.NODE_ENV || 'development'; require('buffertools').extend(); +var util = require('util'); var RpcClient = require('../node_modules/bitcore/RpcClient').class(); var networks = require('../node_modules/bitcore/networks'); @@ -26,8 +27,11 @@ function getNextBlock(blockHash,cb) { return cb(err); } - if ( ! ( blockInfo.result.height % 1000) ) - console.log("Height:" + blockInfo.result.height); + if ( ! ( blockInfo.result.height % 1000) ) { + var h = blockInfo.result.height, + d = blockInfo.result.confirmations; + console.log( util.format("Height: %d/%d [%d%%]", h, d, 100*h/(h+d))); + } Block.create( blockInfo.result, function(err, inBlock) { From f9e33647091d245f8581b99c6c4f451e28079efe Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Tue, 7 Jan 2014 09:43:04 -0300 Subject: [PATCH 25/50] better readme --- README.md | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 91 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 35ff00c..0bf63f1 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,101 @@ -mystery -======= +# Mystery + +Project description. + +## Prerequisites +* Node.js - Download and Install [Node.js](http://www.nodejs.org/download/). You can also follow [this gist](https://gist.github.com/isaacs/579814) for a quick and easy way to install Node.js and npm +* MongoDB - Download and Install [MongoDB](http://www.mongodb.org/downloads) - Make sure it's running on the default port (27017). + +### Tools Prerequisites +* NPM - Node.js package manager, should be installed when you install node.js. +* Grunt - Download and Install [Grunt](http://gruntjs.com). +* Bower - Web package manager, installing [Bower](http://bower.io/) is simple when you have npm: + +``` +$ npm install -g bower +``` + +## Additional Packages +* Express - Defined as npm module in the [package.json](package.json) file. +* Mongoose - Defined as npm module in the [package.json](package.json) file. +* AngularJS - Defined as bower module in the [bower.json](bower.json) file. +* Twitter Bootstrap - Defined as bower module in the [bower.json](bower.json) file. +* UI Bootstrap - Defined as bower module in the [bower.json](bower.json) file. + +## Quick Install + The quickest way to get started with MEAN is to clone the project and utilize it like this: + + Grunt Command Line Interface: + + $ sudo npm -g install grunt-cli + + Install dependencies: + + $ npm install + + We use [Grunt](https://github.com/gruntjs/grunt-cli) to start the server: + + $ grunt + + When not using grunt you can use (for example in production): + + $ node server + + Then open a browser and go to: + + http://localhost:3000 -## Install +## Troubleshooting +If you did not get all library during grunt command, please use the follow command: -- sudo npm -g i grunt-cli -- npm i -- grunt + $ bower install +## Configuration +All configuration is specified in the [config](config/) folder, particularly the [config.js](config/config.js) file and the [env](config/env/) files. Here you will need to specify your application name and database name. -## bitcoind configuration +### bitcoind There is a bitcoind configuration sample at: ``` etc/mystery/bitcoin.conf ``` + +### Environmental Settings + +There are three environments provided by default, __development__, __test__, and __production__. Each of these environments has the following configuration options: +* __db__ - This is the name of the MongoDB database to use, and is set by default to __mystery-dev__ for the development environment. +* __app.name__ - This is the name of your app or website, and can be different for each environment. You can tell which environment you are running by looking at the TITLE attribute that your app generates. + +To run with a different environment, just specify NODE_ENV as you call grunt: + + $ NODE_ENV=test grunt + +If you are using node instead of grunt, it is very similar: + + $ NODE_ENV=test node server + +## Github +[Mystery](https://github.com/bitpay/mystery) + +## License +(The MIT License) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. From 9feb87ddf2f3a3aeb15a70706f608535c60e1a8b Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 7 Jan 2014 09:48:31 -0300 Subject: [PATCH 26/50] API for blocks v0.1 working! --- app/controllers/blocks.js | 33 +++++++++++++++++++++++++++++++++ app/models/Block.js | 20 ++++++++++---------- config/routes.js | 7 +++++-- util/sync.js | 6 +++--- 4 files changed, 51 insertions(+), 15 deletions(-) create mode 100644 app/controllers/blocks.js diff --git a/app/controllers/blocks.js b/app/controllers/blocks.js new file mode 100644 index 0000000..fdef665 --- /dev/null +++ b/app/controllers/blocks.js @@ -0,0 +1,33 @@ +'use strict'; + + +var Block = require('../models/Block'); +//, _ = require('lodash'); + + + +/** + * Module dependencies. + */ + + +/** + * Find block by hash ... + */ +exports.block = function(req, res, next, hash) { + Block.fromHash(hash, function(err, block) { + if (err) return next(err); + if (!block) return next(new Error('Failed to load block ' + hash)); + req.block = block; + next(); + }); +}; + + +/** + * Show block + */ +exports.show = function(req, res) { + res.jsonp(req.block); +}; + diff --git a/app/models/Block.js b/app/models/Block.js index 9440426..53272b5 100644 --- a/app/models/Block.js +++ b/app/models/Block.js @@ -11,8 +11,8 @@ var mongoose = require('mongoose'), * Block Schema */ var BlockSchema = new Schema({ - hash: { - type: String, + hash: { + type: String, index: true, unique: true, }, @@ -27,12 +27,12 @@ var BlockSchema = new Schema({ difficulty: Number, chainwork: String, previousblockhash: { - type: String, + type: String, index: true, unique: true, }, nextblockhash: { - type: String, + type: String, index: true, unique: true, }, @@ -53,16 +53,16 @@ BlockSchema.path('title').validate(function(title) { */ BlockSchema.statics.load = function(id, cb) { - this.findOne({ - _id: id - }).exec(cb); + this.findOne({ + _id: id + }).exec(cb); }; BlockSchema.statics.fromHash = function(hash, cb) { - this.findOne({ - hash: hash, - }).exec(cb); + this.findOne({ + hash: hash, + }).exec(cb); }; module.exports = mongoose.model('Block', BlockSchema); diff --git a/config/routes.js b/config/routes.js index 1f75a0e..7150af0 100644 --- a/config/routes.js +++ b/config/routes.js @@ -8,7 +8,10 @@ module.exports = function(app) { //Block routes - var blocks = require('model/app/controllers/blocks'); - app.get('/block/:block_hash', blocks.show); + var blocks = require('../app/controllers/blocks'); + app.get('/block/:blockHash', blocks.show); + + + app.param('blockHash', blocks.block); }; diff --git a/util/sync.js b/util/sync.js index 78991de..9aff445 100755 --- a/util/sync.js +++ b/util/sync.js @@ -40,7 +40,7 @@ function getNextBlock(blockHash,cb) { return cb(err); } - return getNextBlock(blockInfo.result.nextblockhash); + return getNextBlock(blockInfo.result.nextblockhash, cb); }); }); @@ -49,7 +49,7 @@ function getNextBlock(blockHash,cb) { function syncBlocks(network, cb) { - Block.findOne({}, {}, { sort: { 'height' : -1 } }, function(err, block) { + Block.findOne({}, {}, { sort: { 'confirmations' : 1 } }, function(err, block) { if (err) { return cb(err); } @@ -63,7 +63,7 @@ function syncBlocks(network, cb) { ; - console.log('Starting at hash' + nextHash); + console.log('Starting at hash: ' + nextHash); getNextBlock(nextHash, cb); }); } From cb57249d0835417c334670ce7f931c902c9efd26 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 7 Jan 2014 09:50:56 -0300 Subject: [PATCH 27/50] readme.md updated for API --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index 0bf63f1..1486373 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,19 @@ $ npm install -g bower http://localhost:3000 + + +## API + +### Blocks +``` + /block/[:hash] + /block/00000000a967199a2fad0877433c93df785a8d8ce062e5f9b451cd1397bdbf62 +``` + + + + ## Troubleshooting If you did not get all library during grunt command, please use the follow command: From 54969b2f58dc2e87ea88557e9d30d34db2dcc507 Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Tue, 7 Jan 2014 10:18:45 -0300 Subject: [PATCH 28/50] added previous step for run sync blocks in documentation. --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 1486373..d63e259 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,15 @@ $ npm install -g bower ## API + +## Prerequisites + Get bitcore from github repository: + $ git clone https://github.com/bitpay/bitcore.git + $ cd bitcore + $ npm install + + Run sync from mystery repository: + $ utils/sync.js ### Blocks ``` From c375d718abc9674417484345732016cf3cf6bfe6 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 7 Jan 2014 10:43:50 -0300 Subject: [PATCH 29/50] development config --- config/env/development.js | 1 + 1 file changed, 1 insertion(+) diff --git a/config/env/development.js b/config/env/development.js index 2ddf0dc..969bd38 100755 --- a/config/env/development.js +++ b/config/env/development.js @@ -9,5 +9,6 @@ module.exports = { user: 'mystery', pass: 'real_mystery', protocol: 'http', + host: process.env.BITCOIND_HOST || '127.0.0.1', } } From 89657e971e535418387e3532979d33d1e22a687d Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 7 Jan 2014 10:56:53 -0300 Subject: [PATCH 30/50] BITCOIND_HOST and BITCOIND_PORT env variabled --- README.md | 5 ++++- config/env/development.js | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d63e259..eb30b46 100644 --- a/README.md +++ b/README.md @@ -78,11 +78,14 @@ All configuration is specified in the [config](config/) folder, particularly the ### bitcoind - There is a bitcoind configuration sample at: +There is a bitcoind configuration sample at: ``` etc/mystery/bitcoin.conf ``` +If you want to use a external bitcoind server set BITCOIND_HOST / BITCOIND_PORT enviroment variables. Make sure that bitcoind is configured to accept incomming connections using 'rpcallowip' decribed in https://en.bitcoin.it/wiki/Running_Bitcoin. + + ### Environmental Settings There are three environments provided by default, __development__, __test__, and __production__. Each of these environments has the following configuration options: diff --git a/config/env/development.js b/config/env/development.js index 969bd38..6836a43 100755 --- a/config/env/development.js +++ b/config/env/development.js @@ -10,5 +10,6 @@ module.exports = { pass: 'real_mystery', protocol: 'http', host: process.env.BITCOIND_HOST || '127.0.0.1', + port: process.env.BITCOIND_PORT || '8332', } } From 8a1aa6b8fd9213094209ae52a2f3bacbf794c3f0 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 7 Jan 2014 14:12:44 -0300 Subject: [PATCH 31/50] reindex option for sync --- package.json | 1 + util/sync.js | 69 +++++++++++++++++++++++++++++++--------------------- 2 files changed, 42 insertions(+), 28 deletions(-) diff --git a/package.json b/package.json index 0fc2f26..51a566e 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ }, "dependencies": { "classtool": "*", + "commander": "*", "express": "~3.4.7", "jade": "~1.0.2", "mongoose": "~3.8.3", diff --git a/util/sync.js b/util/sync.js index 9aff445..f1be0a8 100755 --- a/util/sync.js +++ b/util/sync.js @@ -1,8 +1,11 @@ #!/usr/bin/env node process.env.NODE_ENV = process.env.NODE_ENV || 'development'; + require('buffertools').extend(); +var SYNC_VERSION = '0.1'; +var program = require('commander'); var util = require('util'); var RpcClient = require('../node_modules/bitcore/RpcClient').class(); var networks = require('../node_modules/bitcore/networks'); @@ -11,10 +14,37 @@ var Block = require('../app/models/Block'); var config = require('../config/config'); var mongoose = require('mongoose'); -var networkName = process.argv[2] || 'testnet'; +program + .version(SYNC_VERSION) + .option('-N --network [livenet]', 'Set bitcoin network [livenet]', 'livenet') + .option('-R --reindex', 'Force reindexing', '0') + .parse(process.argv); + +var networkName = program.network; var network = networkName == 'testnet' ? networks.testnet : networks.livenet; + +mongoose.connect(config.db); +var db = mongoose.connection; +var rpc = new RpcClient(config.bitcoind); + + +db.on('error', console.error.bind(console, 'connection error:')); + +db.once('open', function callback () { + + syncBlocks(network, program.reindex, function(err) { + if (err) { + console.log(err); + } + mongoose.connection.close(); + }); +}); + + + + function getNextBlock(blockHash,cb) { if ( !blockHash ) { @@ -47,43 +77,26 @@ function getNextBlock(blockHash,cb) { } -function syncBlocks(network, cb) { +function syncBlocks(network, reindex, cb) { + + var genesisHash = network.genesisBlock.hash.reverse().toString('hex'); + + if (reindex) + return getNextBlock(genesisHash, cb); + Block.findOne({}, {}, { sort: { 'confirmations' : 1 } }, function(err, block) { - if (err) { - return cb(err); - } - - + if (err) return cb(err); var nextHash = block && block.hash ? block.hash - : network.genesisBlock.hash.reverse().toString('hex') + : genesisHash ; console.log('Starting at hash: ' + nextHash); - getNextBlock(nextHash, cb); + return getNextBlock(nextHash, cb); }); } - -mongoose.connect(config.db); - -var db = mongoose.connection; -var rpc = new RpcClient(config.bitcoind); - - -db.on('error', console.error.bind(console, 'connection error:')); -db.once('open', function callback () { - syncBlocks(network, function(err) { - if (err) { - console.log(err); - } - mongoose.connection.close(); - }); -}); - - - From d8093fe681c63831bff92ebe088746bc4fb019a2 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 7 Jan 2014 15:21:59 -0300 Subject: [PATCH 32/50] move sync to a class for testing --- Sync.js | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 Sync.js diff --git a/Sync.js b/Sync.js new file mode 100644 index 0000000..df30060 --- /dev/null +++ b/Sync.js @@ -0,0 +1,99 @@ +require('classtool'); + +function spec(b) { + var mongoose = require('mongoose'); + var util = require('util'); + + var RpcClient = require('bitcore/RpcClient').class(); + var networks = require('bitcore/networks'); + + var config = require('./config/config'); + var Block = require('./app/models/Block'); + + function Sync(config) { + this.network = config.networkName == 'testnet' ? networks.testnet : networks.livenet; + } + + Sync.prototype.getNextBlock = function (blockHash,cb) { + var that = this; + + if ( !blockHash ) { + return cb(); + } + + this.rpc.getBlock(blockHash, function(err, blockInfo) { + if (err) { + return cb(err); + } + + if ( ! ( blockInfo.result.height % 1000) ) { + var h = blockInfo.result.height, + d = blockInfo.result.confirmations; + console.log( util.format("Height: %d/%d [%d%%]", h, d, 100*h/(h+d))); + } + + Block.create( blockInfo.result, function(err, inBlock) { + + // E11000 => already exists + if (err && ! err.toString().match(/E11000/)) { + return cb(err); + } + + return that.getNextBlock(blockInfo.result.nextblockhash, cb); + + }); + }); + } + + Sync.prototype.syncBlocks = function (reindex, cb) { + + var that = this; + var genesisHash = this.network.genesisBlock.hash.reverse().toString('hex'); + + if (reindex) + return this.getNextBlock(genesisHash, cb); + + + Block.findOne({}, {}, { sort: { 'confirmations' : 1 } }, function(err, block) { + if (err) return cb(err); + + var nextHash = + block && block.hash + ? block.hash + : genesisHash + ; + + + console.log('Starting at hash: ' + nextHash); + return that.getNextBlock(nextHash, cb); + }); + } + + + Sync.prototype.start = function (reindex, cb) { + + + mongoose.connect(config.db); + var db = mongoose.connection; + this.rpc = new RpcClient(config.bitcoind); + var that = this; + + + db.on('error', console.error.bind(console, 'connection error:')); + + db.once('open', function callback () { + + that.syncBlocks(reindex, function(err) { + if (err) { + return cb(err); + + } + mongoose.connection.close(); + return cb(); + }); + }); + } + return Sync; +}; +module.defineClass(spec); + From 34cff77e4219011f7cb775e9cad56077f734efb2 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 7 Jan 2014 16:49:42 -0300 Subject: [PATCH 33/50] transaction exploding from blocks --- Gruntfile.js | 16 +++---- Sync.js | 45 ++++++++++++++---- app/models/Block.js | 33 ++++++++++++- app/models/Transaction.js | 41 ++++++++++++++++ package.json | 1 + util/sync.js | 99 +++++++-------------------------------- 6 files changed, 133 insertions(+), 102 deletions(-) create mode 100644 app/models/Transaction.js diff --git a/Gruntfile.js b/Gruntfile.js index 743d984..ab534a1 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -39,6 +39,13 @@ module.exports = function(grunt) { } } }, + mochaTest: { + options: { + reporter: 'spec', + }, + src: ['test/*.js'] + }, + nodemon: { dev: { options: { @@ -61,13 +68,6 @@ module.exports = function(grunt) { logConcurrentOutput: true } }, - mochaTest: { - options: { - reporter: 'spec', - require: 'server.js' - }, - src: ['test/*.js'] - }, env: { test: { NODE_ENV: 'test' @@ -87,7 +87,7 @@ module.exports = function(grunt) { grunt.option('force', true); //Default task(s). - grunt.registerTask('default', ['jshint', 'concurrent']); + grunt.registerTask('default', ['jshint','concurrent']); //Test task. grunt.registerTask('test', ['env:test', 'mochaTest']); diff --git a/Sync.js b/Sync.js index df30060..7269c8f 100644 --- a/Sync.js +++ b/Sync.js @@ -6,9 +6,11 @@ function spec(b) { var RpcClient = require('bitcore/RpcClient').class(); var networks = require('bitcore/networks'); + var async = require('async'); var config = require('./config/config'); var Block = require('./app/models/Block'); + var Transaction=require('./app/models/Transaction'); function Sync(config) { this.network = config.networkName == 'testnet' ? networks.testnet : networks.livenet; @@ -39,8 +41,13 @@ function spec(b) { return cb(err); } - return that.getNextBlock(blockInfo.result.nextblockhash, cb); - + if (inBlock) { + inBlock.explodeTransactions(function (err) { + return that.getNextBlock(blockInfo.result.nextblockhash, cb); + }); + } + else + return that.getNextBlock(blockInfo.result.nextblockhash, cb); }); }); } @@ -70,7 +77,7 @@ function spec(b) { } - Sync.prototype.start = function (reindex, cb) { + Sync.prototype.start = function (opts, next) { mongoose.connect(config.db); @@ -81,15 +88,35 @@ function spec(b) { db.on('error', console.error.bind(console, 'connection error:')); - db.once('open', function callback () { + db.once('open', function (){ - that.syncBlocks(reindex, function(err) { - if (err) { - return cb(err); + async.series([ + function(cb){ + if (opts.destroy) { + console.log("Deleting Blocks..."); + Block.remove().exec(cb); + } + }, + function(cb){ + if (opts.destroy) { + console.log("Deleting TXs..."); + Transaction.remove().exec(cb); + } + }, + function(cb) { + that.syncBlocks(opts.reindex, function(err) { + if (err) { + return cb(err); + } + db.close(); + return cb(); + }); } - mongoose.connection.close(); - return cb(); + ], + function(err) { + if (err) return next(er); + return next(); }); }); } diff --git a/app/models/Block.js b/app/models/Block.js index 53272b5..511cd7c 100644 --- a/app/models/Block.js +++ b/app/models/Block.js @@ -3,9 +3,11 @@ /** * Module dependencies. */ -var mongoose = require('mongoose'), - Schema = mongoose.Schema; +var mongoose = require('mongoose'), + Schema = mongoose.Schema; +var async = require('async'); +var Transaction = require('./Transaction'); /** * Block Schema @@ -38,6 +40,32 @@ var BlockSchema = new Schema({ }, }); +BlockSchema.methods.explodeTransactions = function(next) { + + // console.log('exploding %s', this.hash, typeof this.tx); + + async.forEach( this.tx, + function(tx, callback) { + // console.log('procesing TX %s', tx); + Transaction.create({ hash: tx }, function(err) { + if (err && ! err.toString().match(/E11000/)) { + return callback(); + } + if (err) { + + return callback(err); + } + return callback(); + + }); + }, + function(err) { + if (err) return next(err); + return next(); + } + ); +}; + /** * Validations */ @@ -65,4 +93,5 @@ BlockSchema.statics.fromHash = function(hash, cb) { }).exec(cb); }; + module.exports = mongoose.model('Block', BlockSchema); diff --git a/app/models/Transaction.js b/app/models/Transaction.js new file mode 100644 index 0000000..ba8678e --- /dev/null +++ b/app/models/Transaction.js @@ -0,0 +1,41 @@ +'use strict'; + +/** + * Module dependencies. + */ +var mongoose = require('mongoose'), + Schema = mongoose.Schema; + + +/** + */ +var TransactionSchema = new Schema({ + hash: { + type: String, + index: true, + unique: true, + }, + parsed: { + type: Boolean, + default: false, + }, +}); + +/** + * Statics + */ + +TransactionSchema.statics.load = function(id, cb) { + this.findOne({ + _id: id + }).exec(cb); +}; + + +TransactionSchema.statics.fromHash = function(hash, cb) { + this.findOne({ + hash: hash, + }).exec(cb); +}; + +module.exports = mongoose.model('Transaction', TransactionSchema); diff --git a/package.json b/package.json index 51a566e..1dd908e 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "postinstall": "node node_modules/bower/bin/bower install" }, "dependencies": { + "async": "*", "classtool": "*", "commander": "*", "express": "~3.4.7", diff --git a/util/sync.js b/util/sync.js index f1be0a8..9a2bbbf 100755 --- a/util/sync.js +++ b/util/sync.js @@ -6,97 +6,30 @@ require('buffertools').extend(); var SYNC_VERSION = '0.1'; var program = require('commander'); -var util = require('util'); -var RpcClient = require('../node_modules/bitcore/RpcClient').class(); -var networks = require('../node_modules/bitcore/networks'); - -var Block = require('../app/models/Block'); -var config = require('../config/config'); -var mongoose = require('mongoose'); +var Sync = require('../Sync').class(); program .version(SYNC_VERSION) - .option('-N --network [livenet]', 'Set bitcoin network [livenet]', 'livenet') + .option('-N --network [livenet]', 'Set bitcoin network [testnet]', 'testnet') .option('-R --reindex', 'Force reindexing', '0') + .option('-D --destroy', 'Remove current DB', '0') .parse(process.argv); -var networkName = program.network; -var network = networkName == 'testnet' ? networks.testnet : networks.livenet; +var sync = new Sync({ networkName: program.network }); +if (program.remove) { +} -mongoose.connect(config.db); -var db = mongoose.connection; -var rpc = new RpcClient(config.bitcoind); - - -db.on('error', console.error.bind(console, 'connection error:')); - -db.once('open', function callback () { - - syncBlocks(network, program.reindex, function(err) { - if (err) { - console.log(err); - } - mongoose.connection.close(); - }); +sync.start({ + reindex: program.reindex, + destroy: program.destroy, +}, function(err){ + if (err) { + console.log(err); + } + else { + console.log('Done!'); + } }); - - - -function getNextBlock(blockHash,cb) { - - if ( !blockHash ) { - console.log("done"); - return cb(); - } - - rpc.getBlock(blockHash, function(err, blockInfo) { - if (err) { - return cb(err); - } - - if ( ! ( blockInfo.result.height % 1000) ) { - var h = blockInfo.result.height, - d = blockInfo.result.confirmations; - console.log( util.format("Height: %d/%d [%d%%]", h, d, 100*h/(h+d))); - } - - Block.create( blockInfo.result, function(err, inBlock) { - - // E11000 => already exists - if (err && ! err.toString().match(/E11000/)) { - return cb(err); - } - - return getNextBlock(blockInfo.result.nextblockhash, cb); - - }); - }); - -} - -function syncBlocks(network, reindex, cb) { - - var genesisHash = network.genesisBlock.hash.reverse().toString('hex'); - - if (reindex) - return getNextBlock(genesisHash, cb); - - - Block.findOne({}, {}, { sort: { 'confirmations' : 1 } }, function(err, block) { - if (err) return cb(err); - - var nextHash = - block && block.hash - ? block.hash - : genesisHash - ; - - - console.log('Starting at hash: ' + nextHash); - return getNextBlock(nextHash, cb); - }); -} - From 52f0120f3978a5e237004a4f197407804a8b683b Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Tue, 7 Jan 2014 18:12:37 -0300 Subject: [PATCH 34/50] get block in angular from node! --- app/controllers/blocks.js | 10 ++++------ app/controllers/index.js | 22 ++++++++++++++++++++++ app/models/Block.js | 2 +- app/views/includes/foot.jade | 1 + app/views/index.jade | 21 --------------------- config/routes.js | 2 +- public/js/app.js | 5 +++-- public/js/controllers/index.js | 9 +++++++-- public/js/services/index.js | 5 +++++ public/views/index.html | 7 ++++++- 10 files changed, 50 insertions(+), 34 deletions(-) create mode 100644 public/js/services/index.js diff --git a/app/controllers/blocks.js b/app/controllers/blocks.js index fdef665..39b508e 100644 --- a/app/controllers/blocks.js +++ b/app/controllers/blocks.js @@ -1,15 +1,13 @@ 'use strict'; - -var Block = require('../models/Block'); -//, _ = require('lodash'); - - - /** * Module dependencies. */ +var mongoose = require('mongoose'), + Block = mongoose.model('Block'); +//, _ = require('lodash'); + /** * Find block by hash ... diff --git a/app/controllers/index.js b/app/controllers/index.js index f71d55c..423b411 100644 --- a/app/controllers/index.js +++ b/app/controllers/index.js @@ -1,5 +1,27 @@ 'use strict'; +/** + * Module dependencies. + */ + +var mongoose = require('mongoose'), + Block = mongoose.model('Block'); + exports.render = function(req, res) { res.render('index'); }; + +/** + * List of blocks at HomePage + */ +exports.all = function(req, res) { + Block.find().limit(7).exec(function(err, blocks) { + if (err) { + res.render('error', { + status: 500 + }); + } else { + res.jsonp(blocks); + } + }); +}; diff --git a/app/models/Block.js b/app/models/Block.js index 53272b5..de89280 100644 --- a/app/models/Block.js +++ b/app/models/Block.js @@ -65,4 +65,4 @@ BlockSchema.statics.fromHash = function(hash, cb) { }).exec(cb); }; -module.exports = mongoose.model('Block', BlockSchema); +mongoose.model('Block', BlockSchema); diff --git a/app/views/includes/foot.jade b/app/views/includes/foot.jade index f7cc3e6..e4c8706 100755 --- a/app/views/includes/foot.jade +++ b/app/views/includes/foot.jade @@ -24,6 +24,7 @@ script(type='text/javascript', src='/js/filters.js') //Application Services script(type='text/javascript', src='/js/services/global.js') +script(type='text/javascript', src='/js/services/index.js') //Application Controllers script(type='text/javascript', src='/js/controllers/index.js') diff --git a/app/views/index.jade b/app/views/index.jade index 7f33718..a74f173 100755 --- a/app/views/index.jade +++ b/app/views/index.jade @@ -2,24 +2,3 @@ extends layouts/default block content section.container(data-ng-view) - - section.container - p ˈmɪst(ə)ri/' - | noun - audio(src="https://ssl.gstatic.com/dictionary/static/sounds/de/0/mystery.mp3",preload="auto",data-dobid="aud",id="aud") - button(onclick="document.getElementById('aud').play()") Play - - ol - li - strong something that is difficult or impossible to understand or explain. - p "the mysteries of outer space" - | synonyms: puzzle, enigma, conundrum, riddle, secret, unsolved problem, problem, question, question mark, closed book; secrecy or obscurity. - p "much of her past is shrouded in mystery" - | synonyms: secrecy, darkness, obscurity, ambiguity, ambiguousness, uncertainty, impenetrability, vagueness, nebulousness; More - li - strong a person or thing whose identity or nature is puzzling or unknown. - p "‘He's a bit of a mystery,’ said Nina" - li - strong a novel, play, or film dealing with a puzzling crime, especially a murder. - p "the 1920s murder mystery, The Ghost Train" - | synonyms: thriller, detective story/novel, murder story; More diff --git a/config/routes.js b/config/routes.js index 7150af0..3da0264 100644 --- a/config/routes.js +++ b/config/routes.js @@ -5,12 +5,12 @@ module.exports = function(app) { //Home route var index = require('../app/controllers/index'); app.get('/', index.render); + app.get('/last_blocks', index.all); //Block routes var blocks = require('../app/controllers/blocks'); app.get('/block/:blockHash', blocks.show); - app.param('blockHash', blocks.block); diff --git a/public/js/app.js b/public/js/app.js index 77b64cb..afb98d4 100755 --- a/public/js/app.js +++ b/public/js/app.js @@ -1,5 +1,6 @@ 'use strict'; -angular.module('mystery', ['ngCookies', 'ngResource', 'ngRoute', 'ui.bootstrap', 'ui.route', 'mystery.system']); +angular.module('mystery', ['ngCookies', 'ngResource', 'ngRoute', 'ui.bootstrap', 'ui.route', 'mystery.system', 'mystery.index']); -angular.module('mystery.system', []); \ No newline at end of file +angular.module('mystery.system', []); +angular.module('mystery.index', []); diff --git a/public/js/controllers/index.js b/public/js/controllers/index.js index 4cb2b6f..bec0f0a 100755 --- a/public/js/controllers/index.js +++ b/public/js/controllers/index.js @@ -1,5 +1,10 @@ 'use strict'; -angular.module('mystery.system').controller('IndexController', ['$scope', 'Global', function ($scope, Global) { +angular.module('mystery.system').controller('IndexController', ['$scope', 'Global', 'Index', function ($scope, Global, Index) { $scope.global = Global; -}]); \ No newline at end of file + $scope.last_blocks = function() { + Index.query(function(blocks) { + $scope.blocks = blocks; + }); + }; +}]); diff --git a/public/js/services/index.js b/public/js/services/index.js new file mode 100644 index 0000000..f961642 --- /dev/null +++ b/public/js/services/index.js @@ -0,0 +1,5 @@ +'use strict'; + +angular.module('mystery.index').factory('Index', ['$resource', function($resource) { + return $resource('/last_blocks'); +}]); diff --git a/public/views/index.html b/public/views/index.html index b92fe02..d84010f 100644 --- a/public/views/index.html +++ b/public/views/index.html @@ -1,5 +1,10 @@ -
+
+
    +
  • + {{block.hash}} +
  • +
From 12d75a0091ed01f97719349d2f00940900f4ba93 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Tue, 7 Jan 2014 20:40:05 -0300 Subject: [PATCH 35/50] prototype p2p app that communicates with bitcoind --- .gitignore | 1 + HeaderDB.js | 213 +++++++++++++++++++++++++++++++++++++++++++++++++ p2p.js | 223 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 437 insertions(+) create mode 100644 HeaderDB.js create mode 100755 p2p.js diff --git a/.gitignore b/.gitignore index 0021b27..daa3529 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ node_modules *.swp *~ .project +peerdb.json npm-debug.log node_modules diff --git a/HeaderDB.js b/HeaderDB.js new file mode 100644 index 0000000..a751cd4 --- /dev/null +++ b/HeaderDB.js @@ -0,0 +1,213 @@ +require('classtool'); + +function ClassSpec(b) { + var assert = require('assert'); + var fs = require('fs'); + var Block = require('bitcore/Block').class(); + var Deserialize = require('bitcore/Deserialize'); + var Parser = require('bitcore/util/BinaryParser').class(); + var coinUtil = require('bitcore/util/util'); + + function HeaderDB(b) { + this.network = b.network; + this.fd = null; + this.blocks = {}; + this.byHeight = []; + this.bestBlock = null; + this.cached_size = 0; + } + + HeaderDB.prototype.size = function() { + this.cached_size = Object.keys(this.blocks).length; + return this.cached_size; + }; + + HeaderDB.prototype.locator = function(block) { + if (!block) + block = this.bestBlock; + + var step = 1; + var start = 0; + var loc = []; + // see https://en.bitcoin.it/wiki/Protocol_specification#getblocks + for (var i = block.height; i > 0; i -= step, ++start) { + if (start >= 10) + step *= 2; + loc.push(this.byHeight[i]); + } + assert.equal(this.byHeight[0].toString(), + this.network.genesisBlock.hash.toString()); + loc.push(this.byHeight[0]); + console.log("Requesting more headers. Current height: " + block.height ); + return loc; + }; + + HeaderDB.prototype.add = function(block) { + var hash = block.calcHash(); + block.hash = hash; + var curWork = Deserialize.intFromCompact(block.bits); + + if (hash in this.blocks) { + var old = this.blocks[hash]; + throw new Error("duplicate block (was at height " + old.height + ")"); + } + + var bestChain = false; + + var reorg = { + oldBest: null, + conn: 0, + disconn: 0, + }; + + if (this.cached_size == 0) { + if (this.network.genesisBlock.hash.toString() != + hash.toString()) + throw new Error("Invalid genesis block"); + + block.height = 0; + block.work = curWork; + bestChain = true; + this.cached_size++; + } else { + var prevBlock = this.blocks[block.prev_hash]; + if (!prevBlock) + throw new Error("orphan block; prev not found"); + + block.height = prevBlock.height + 1; + block.work = prevBlock.work + curWork; + this.cached_size++; + + if (block.work > this.bestBlock.work) + bestChain = true; + } + + + // add to by-hash index + this.blocks[hash] = block; + + if (bestChain) { + var oldBest = this.bestBlock; + var newBest = block; + + reorg.oldBest = oldBest; + + // likely case: new best chain has greater height + if (!oldBest) { + while (newBest) { + newBest = this.blocks[newBest.prev_hash]; + reorg.conn++; + } + } else { + while (newBest && + (newBest.height > oldBest.height)) { + newBest = this.blocks[newBest.prev_hash]; + reorg.conn++; + } + } + + // unlikely: old best chain has greater height + while (oldBest && newBest && + (oldBest.height > newBest.height)) { + oldBest = this.blocks[oldBest.prev_hash]; + reorg.disconn++; + } + + // height matches, but still walking parallel + while (oldBest && newBest && (oldBest != newBest)) { + newBest = this.blocks[newBest.prev_hash]; + reorg.conn++; + + oldBest = this.blocks[oldBest.prev_hash]; + reorg.disconn++; + } + + var shuf = (reorg.conn > reorg.disconn) ? + reorg.conn : reorg.disconn; + + // reorg analyzed, updated best-chain pointer + this.bestBlock = block; + + // update by-height index + var ptr = block; + var updated = []; + for (var idx = block.height; + idx > (block.height - shuf); idx--) { + if (idx < 0) + break; + var update = [ idx, ptr ]; + updated.push(update); + ptr = this.blocks[ptr.prev_hash]; + } + + updated.reverse(); + + for (var i = 0; i < updated.length; i++) { + var update = updated[i]; + var idx = update[0]; + var ptr = update[1]; + + if (idx < this.byHeight.length) + this.byHeight[idx] = ptr.hash; + else + this.byHeight.push(ptr.hash); + } + } + return reorg; + }; + + HeaderDB.prototype.addBuf = function(buf) { + var block = new Block(); + var parser = new Parser(buf); + block.parse(parser, true); + this.add(block); + + }; + + + HeaderDB.prototype.readFile = function(filename) { + var fd = fs.openSync(filename, 'r'); + var stats = fs.fstatSync(fd); + if (stats.size % 80 != 0) + throw new Error("Corrupted header db"); + + while (1) { + var buf = new Buffer(80); + var bread = fs.readSync(fd, buf, 0, 80, null); + if (bread < 80) + break; + + this.addBuf(buf); + + if ( ! ( this.cached_size % 1000 )) { + console.log("\tblock..." + this.cached_size ) ; + } + } + + fs.closeSync(fd); + }; + + HeaderDB.prototype.writeFile = function(filename) { + var block = this.bestBlock; + var data = []; + while (block) { + var s = block.getHeader(); + data.push(s); + block = this.blocks[block.prev_hash]; + } + + data.reverse(); + + var fd = fs.openSync(filename, 'w'); + + data.forEach(function(datum) { + fs.writeSync(fd, datum, 0, 80, null); + }); + + fs.closeSync(fd); + }; + + return HeaderDB; +}; +module.defineClass(ClassSpec); + diff --git a/p2p.js b/p2p.js new file mode 100755 index 0000000..9014d63 --- /dev/null +++ b/p2p.js @@ -0,0 +1,223 @@ +var fs = require('fs'); +var HeaderDB = require('./HeaderDB').class(); +var Block = require('bitcore/Block').class(); +var CoinConst = require('bitcore/const'); +var coinUtil = require('bitcore/util/util'); +var networks = require('bitcore/networks'); +var Parser = require('bitcore/util/BinaryParser').class(); + +var peerdb_fn = 'peerdb.json'; + +var peerdb = undefined; +var hdrdb = undefined; +var network = networks.testnet; +var config = { + network : network.name +}; +var PeerManager = require('bitcore/PeerManager').createClass({ + config : config +}); +var Peer = require('bitcore/Peer').class(); + +var syncState = 'init'; + +function peerdb_load() { + try { + peerdb = JSON.parse(fs.readFileSync(peerdb_fn)); + } catch (d) { + console.warn('Unable to read peer db', peerdb_fn, 'creating new one.'); + peerdb = [ { + ipv4 : '127.0.0.1', + port : 18333 + }, ]; + + fs.writeFileSync(peerdb_fn, JSON.stringify(peerdb)); + } +} + +function hdrdb_load() +{ + hdrdb = new HeaderDB({network: network}); +} + +function get_more_headers(info) { + var conn = info.conn; + var loc = hdrdb.locator(); + if (loc.length == 0) { + return; + } + conn.sendGetHeaders(loc, coinUtil.NULL_HASH); +} + +function add_header(info, block) { + var hashStr = coinUtil.formatHashFull(block.calcHash()); + + try { + hdrdb.add(block); + } catch (e) { + return; + } +} + +function handle_headers(info) { + console.log("handle headers"); + var conn = info.conn; + var headers = info.message.headers; + + headers.forEach(function(hdr) { + add_header(info, hdr); + }); + + // We persist the header DB after each batch + //hdrdb.writeFile(hdrdb_fn); + + // Only one request per batch of headers we receive. + get_more_headers(info); +} + +function handle_block(info) { + console.log("handle block") + var block = info.message.block; + add_header(info, block); + + if (syncState === 'init') { + syncState = 'headers'; + get_more_headers(info); + } +} + +function handle_verack(info) { + var inv = { + type : CoinConst.MSG.BLOCK, + hash : network.genesisBlock.hash, + }; + var invs = [ inv ]; + console.log('p2psync: Asking for the genesis block'); + + // Asks for the genesis block + info.conn.sendGetData(invs); +} + +function handle_connected(data) { + var peerman = data.pm; + var peers_n = peerman.peers.length; + console.log('p2psync: Connected to ' + peers_n + ' peer' + + (peers_n != 1 ? 's' : '')); +} + +function p2psync() { + var peerman = new PeerManager(); + + peerdb.forEach(function(datum) { + var peer = new Peer(datum.ipv4, datum.port); + peerman.addPeer(peer); + }); + + peerman.on('connection', function(conn) { + conn.on('verack', handle_verack); + conn.on('block', handle_block); + conn.on('headers', handle_headers); + }); + peerman.on('connect', handle_connected); + + peerman.start(); +} + +function filesync_block_buf(blkdir, fn, buf) { + var parser = new Parser(buf); + var block = new Block(); + block.parse(parser, true); + + var hashStr = coinUtil.formatHashFull(block.calcHash()); + + try { + hdrdb.add(block); + } catch (e) { + var height = hdrdb.size(); + console.log('HeaderDB failed adding block #' + height + ', ' + hashStr); + console.log(' Reason: ' + e); + return; + } + + var height = hdrdb.size() - 1; + if ((height % 1000) == 0) + console.log('HeaderDB added block #' + height + ', ' + hashStr); +} + +function filesync_open_cb(err, fd, blkdir, fn) { + if (err) + throw err; + + var hdrbuf = new Buffer(4 * 2); + while (1) { + // read 2x 32-bit header + var bread = fs.readSync(fd, hdrbuf, 0, 4 * 2, null); + if (bread < (4 * 2)) { + console.log('Short read/EOF, ending scan of ' + fn); + break; + } + + // check magic matches + var magic = hdrbuf.slice(0, 4); + if (magic.toString() != network.magic.toString()) { + console.log('Invalid network magic, ending scan of ' + fn); + break; + } + + // block size + var blkSize = hdrbuf.readUInt32LE(4); + if (blkSize > (1 * 1024 * 1024)) + throw new Error('Invalid block size ' + blkSize); + + // read raw block data + var blkBuf = new Buffer(blkSize); + bread = fs.readSync(fd, blkBuf, 0, blkSize, null); + if (bread != blkSize) + throw new Error('Failed to read block'); + + // process block + filesync_block_buf(blkdir, fn, blkBuf); + } + + fs.closeSync(fd); + + hdrdb.writeFile(hdrdb_fn); + console.log('Wrote header db'); +} + +function filesync_block_file(blkdir, fn) { + console.log('Scanning ' + fn + ' for block data.'); + + var pathname = blkdir + '/' + fn; + fs.open(pathname, 'r', function(err, fd) { + filesync_open_cb(err, fd, blkdir, fn); + }); +} + +function cmd_filesync_rd(err, files, blkdir) { + if (err) + throw err; + + files = files.sort(); + + var scanned = 0; + files.forEach(function(fn) { + var re = /^blk\d+\.dat$/; + if (fn.match(re)) { + filesync_block_file(blkdir, fn); + scanned++; + } + }); + + console.log('Scanned ' + scanned + ' of ' + files.length + ' files in ' + + blkdir); +} + +function main() { + peerdb_load(); + hdrdb_load(); + + p2psync(); +} + +main(); From 36bad3920f655b26a93740f904f8b7eaf7c2c991 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Tue, 7 Jan 2014 20:41:06 -0300 Subject: [PATCH 36/50] removing unnecesary code --- p2p.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/p2p.js b/p2p.js index 9014d63..f7474a9 100755 --- a/p2p.js +++ b/p2p.js @@ -43,9 +43,6 @@ function hdrdb_load() function get_more_headers(info) { var conn = info.conn; var loc = hdrdb.locator(); - if (loc.length == 0) { - return; - } conn.sendGetHeaders(loc, coinUtil.NULL_HASH); } From 1063af6f90293c4bbc774633cdf941f6e17a34fd Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 7 Jan 2014 21:03:48 -0300 Subject: [PATCH 37/50] fix bug in drop DBs + Transation with many fields in mongo --- Sync.js | 6 ++++-- app/models/Block.js | 4 ++-- app/models/Transaction.js | 31 +++++++++++++++++++++++++------ 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/Sync.js b/Sync.js index 7269c8f..287f8f8 100644 --- a/Sync.js +++ b/Sync.js @@ -94,14 +94,16 @@ function spec(b) { function(cb){ if (opts.destroy) { console.log("Deleting Blocks..."); - Block.remove().exec(cb); + return Block.remove().exec(cb); } + return cb(); }, function(cb){ if (opts.destroy) { console.log("Deleting TXs..."); - Transaction.remove().exec(cb); + return Transaction.remove().exec(cb); } + return cb(); }, function(cb) { that.syncBlocks(opts.reindex, function(err) { diff --git a/app/models/Block.js b/app/models/Block.js index 511cd7c..3ce94ef 100644 --- a/app/models/Block.js +++ b/app/models/Block.js @@ -44,10 +44,10 @@ BlockSchema.methods.explodeTransactions = function(next) { // console.log('exploding %s', this.hash, typeof this.tx); - async.forEach( this.tx, + async.forEach( this.tx, function(tx, callback) { // console.log('procesing TX %s', tx); - Transaction.create({ hash: tx }, function(err) { + Transaction.create({ txid: tx }, function(err) { if (err && ! err.toString().match(/E11000/)) { return callback(); } diff --git a/app/models/Transaction.js b/app/models/Transaction.js index ba8678e..fcd1240 100644 --- a/app/models/Transaction.js +++ b/app/models/Transaction.js @@ -10,15 +10,25 @@ var mongoose = require('mongoose'), /** */ var TransactionSchema = new Schema({ - hash: { + txid: { type: String, index: true, unique: true, }, - parsed: { - type: Boolean, - default: false, + version: Number, + locktime: Number, + vin: { + type: Array, + default: [], }, + vout: { + type: Array, + default: [], + }, + blockhash: String, + confirmations: Number, + time: Number, + blocktime: Number, }); /** @@ -32,10 +42,19 @@ TransactionSchema.statics.load = function(id, cb) { }; -TransactionSchema.statics.fromHash = function(hash, cb) { +TransactionSchema.statics.fromID = function(txid, cb) { this.findOne({ - hash: hash, + txid: txid, }).exec(cb); }; +/* + * virtual + */ + +// ugly? new object every call? +TransactionSchema.virtual('date').get(function () { + return new Date(this.time); +}); + module.exports = mongoose.model('Transaction', TransactionSchema); From ca28ed62b4fe153af7897268cb8505ccdf530470 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 8 Jan 2014 01:37:29 -0300 Subject: [PATCH 38/50] transaction syncing working! --- Sync.js | 115 ++++++++++++++++++++++++++++++++++---- app/models/Transaction.js | 6 +- util/sync.js | 9 ++- 3 files changed, 112 insertions(+), 18 deletions(-) diff --git a/Sync.js b/Sync.js index 287f8f8..788dbdd 100644 --- a/Sync.js +++ b/Sync.js @@ -24,9 +24,7 @@ function spec(b) { } this.rpc.getBlock(blockHash, function(err, blockInfo) { - if (err) { - return cb(err); - } + if (err) return cb(err); if ( ! ( blockInfo.result.height % 1000) ) { var h = blockInfo.result.height, @@ -57,6 +55,7 @@ function spec(b) { var that = this; var genesisHash = this.network.genesisBlock.hash.reverse().toString('hex'); + console.log("Syncing Blocks..."); if (reindex) return this.getNextBlock(genesisHash, cb); @@ -71,12 +70,76 @@ function spec(b) { ; - console.log('Starting at hash: ' + nextHash); + console.log('\tStarting at hash: ' + nextHash); return that.getNextBlock(nextHash, cb); }); } + var progress_bar = function(string, current, total) { + console.log( util.format("\t%s %d/%d [%d%%]", + string, current, total, parseInt(100 * current/total)) + ); + } + + Sync.prototype.syncTXs = function (reindex, cb) { + + var that = this; + + console.log("Syncing TXs..."); + if (reindex) { + // TODO? + } + + + Transaction.find({blockHash: null}, function(err, txs) { + if (err) return cb(err); + + var read = 0; + var pull = 0; + var write = 0; + var total = txs.length; + console.log("\tneed to pull %d txs", total); + + if (!total) return cb(); + + async.each(txs, + function(tx, next){ + if (! tx.txid) { + console.log("NO TXID skipping...", tx); + return next(); + } + + if ( ! ( read++ % 1000) ) + progress_bar('read', read, total); + + + that.rpc.getRawTransaction(tx.txid, 1, function(err, txInfo) { + + if ( ! ( pull++ % 1000) ) + progress_bar('\tpull', pull, total); + + if (!err && txInfo) { + Transaction.update({txid: tx.txid}, txInfo.result, function(err) { + if (err) return next(err); + + if ( ! ( write++ % 1000) ) + progress_bar('\t\twrite', write, total); + + return next(); + }); + } + else return next(); + }); + }, + function(err){ + if (err) return cb(err); + return cb(err); + } + ); + }); + } + Sync.prototype.start = function (opts, next) { @@ -106,18 +169,46 @@ function spec(b) { return cb(); }, function(cb) { - that.syncBlocks(opts.reindex, function(err) { - if (err) { - return cb(err); - } - db.close(); + if (! opts.skip_blocks) { + that.syncBlocks(opts.reindex, function(err) { + if (err) { + return cb(err); + + } + console.log("\tBlocks done."); + + return cb(); + }); + } + else { return cb(); - }); - } + } + }, + function(cb) { + if (! opts.skip_txs) { + that.syncTXs(opts.reindex, function(err) { + if (err) { + return cb(err); + + } + return cb(); + }); + } + else { + return cb(); + } + }, + function(cb) { + db.close(); + return cb(); + }, ], function(err) { - if (err) return next(er); + if (err) { + db.close(); + return next(err); + } return next(); }); }); diff --git a/app/models/Transaction.js b/app/models/Transaction.js index fcd1240..566a480 100644 --- a/app/models/Transaction.js +++ b/app/models/Transaction.js @@ -25,7 +25,11 @@ var TransactionSchema = new Schema({ type: Array, default: [], }, - blockhash: String, + blockhash: { + type: String, + index: true, + default: null, + }, confirmations: Number, time: Number, blocktime: Number, diff --git a/util/sync.js b/util/sync.js index 9a2bbbf..22d1a53 100755 --- a/util/sync.js +++ b/util/sync.js @@ -13,6 +13,8 @@ program .option('-N --network [livenet]', 'Set bitcoin network [testnet]', 'testnet') .option('-R --reindex', 'Force reindexing', '0') .option('-D --destroy', 'Remove current DB', '0') + .option('--skip_blocks', 'Sync blocks') + .option('--skip_txs', 'Sync transactions') .parse(process.argv); var sync = new Sync({ networkName: program.network }); @@ -21,12 +23,9 @@ if (program.remove) { } -sync.start({ - reindex: program.reindex, - destroy: program.destroy, -}, function(err){ +sync.start( program, function(err){ if (err) { - console.log(err); + console.log("CRITICAL ERROR: ", err); } else { console.log('Done!'); From dac973c65fc5a7ca405b6617e5cf4295f456132e Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 8 Jan 2014 01:40:57 -0300 Subject: [PATCH 39/50] tx syncing v2 --- Sync.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Sync.js b/Sync.js index 788dbdd..ae7d23e 100644 --- a/Sync.js +++ b/Sync.js @@ -16,6 +16,12 @@ function spec(b) { this.network = config.networkName == 'testnet' ? networks.testnet : networks.livenet; } + var progress_bar = function(string, current, total) { + console.log( util.format("\t%s %d/%d [%d%%]", + string, current, total, parseInt(100 * current/total)) + ); + } + Sync.prototype.getNextBlock = function (blockHash,cb) { var that = this; @@ -29,7 +35,7 @@ function spec(b) { if ( ! ( blockInfo.result.height % 1000) ) { var h = blockInfo.result.height, d = blockInfo.result.confirmations; - console.log( util.format("Height: %d/%d [%d%%]", h, d, 100*h/(h+d))); + progress_bar('height', h, h + d); } Block.create( blockInfo.result, function(err, inBlock) { @@ -76,12 +82,6 @@ function spec(b) { } - var progress_bar = function(string, current, total) { - console.log( util.format("\t%s %d/%d [%d%%]", - string, current, total, parseInt(100 * current/total)) - ); - } - Sync.prototype.syncTXs = function (reindex, cb) { var that = this; @@ -92,7 +92,7 @@ function spec(b) { } - Transaction.find({blockHash: null}, function(err, txs) { + Transaction.find({blockhash: null}, function(err, txs) { if (err) return cb(err); var read = 0; From 7002363841e431b1389d7ffe0a0ecc9c6f2e0dc2 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 8 Jan 2014 01:47:20 -0300 Subject: [PATCH 40/50] TX API working + sync --- app/controllers/transactions.js | 33 +++++++++++++++++++++++++++++++++ config/routes.js | 8 +++++--- 2 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 app/controllers/transactions.js diff --git a/app/controllers/transactions.js b/app/controllers/transactions.js new file mode 100644 index 0000000..8bf4635 --- /dev/null +++ b/app/controllers/transactions.js @@ -0,0 +1,33 @@ +'use strict'; + + +var Transaction = require('../models/Transaction'); +//, _ = require('lodash'); + + + +/** + * Module dependencies. + */ + + +/** + * Find block by hash ... + */ +exports.transaction = function(req, res, next, txid) { + Transaction.fromID(txid, function(err, tx) { + if (err) return next(err); + if (!tx) return next(new Error('Failed to load TX ' + txid)); + req.transaction = tx; + next(); + }); +}; + + +/** + * Show block + */ +exports.show = function(req, res) { + res.jsonp(req.transaction); +}; + diff --git a/config/routes.js b/config/routes.js index 7150af0..507378f 100644 --- a/config/routes.js +++ b/config/routes.js @@ -7,11 +7,13 @@ module.exports = function(app) { app.get('/', index.render); //Block routes - var blocks = require('../app/controllers/blocks'); app.get('/block/:blockHash', blocks.show); - - app.param('blockHash', blocks.block); + + var transactions = require('../app/controllers/transactions'); + app.get('/tx/:txid', transactions.show); + + app.param('txid', transactions.transaction); }; From 06207b6c17392ddc071ea003654c4ec0ab222c6f Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 8 Jan 2014 02:00:37 -0300 Subject: [PATCH 41/50] readme updated --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index eb30b46..c986815 100644 --- a/README.md +++ b/README.md @@ -58,12 +58,21 @@ $ npm install -g bower Run sync from mystery repository: $ utils/sync.js + +check utils/sync.js --help for options. + ### Blocks ``` /block/[:hash] /block/00000000a967199a2fad0877433c93df785a8d8ce062e5f9b451cd1397bdbf62 ``` +### Transactions +``` + /tx/[:txid] + /tx/525de308971eabd941b139f46c7198b5af9479325c2395db7f2fb5ae8562556c +``` + From c2bbdb294192160f060c6b97f42429bfe605b028 Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Wed, 8 Jan 2014 09:17:41 -0300 Subject: [PATCH 42/50] For blocks info, we always use controller blocks. Index controller only render homepage --- app/controllers/blocks.js | 15 +++++++++++++++ app/controllers/index.js | 22 ---------------------- config/routes.js | 2 +- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/app/controllers/blocks.js b/app/controllers/blocks.js index 39b508e..f08016a 100644 --- a/app/controllers/blocks.js +++ b/app/controllers/blocks.js @@ -29,3 +29,18 @@ exports.show = function(req, res) { res.jsonp(req.block); }; +/** + * List of blocks at HomePage + */ +exports.last_blocks = function(req, res) { + Block.find().limit(7).exec(function(err, blocks) { + if (err) { + res.render('error', { + status: 500 + }); + } else { + res.jsonp(blocks); + } + }); +}; + diff --git a/app/controllers/index.js b/app/controllers/index.js index 423b411..f71d55c 100644 --- a/app/controllers/index.js +++ b/app/controllers/index.js @@ -1,27 +1,5 @@ 'use strict'; -/** - * Module dependencies. - */ - -var mongoose = require('mongoose'), - Block = mongoose.model('Block'); - exports.render = function(req, res) { res.render('index'); }; - -/** - * List of blocks at HomePage - */ -exports.all = function(req, res) { - Block.find().limit(7).exec(function(err, blocks) { - if (err) { - res.render('error', { - status: 500 - }); - } else { - res.jsonp(blocks); - } - }); -}; diff --git a/config/routes.js b/config/routes.js index 03378b6..4b37ad7 100644 --- a/config/routes.js +++ b/config/routes.js @@ -5,12 +5,12 @@ module.exports = function(app) { //Home route var index = require('../app/controllers/index'); app.get('/', index.render); - app.get('/last_blocks', index.all); //Block routes var blocks = require('../app/controllers/blocks'); app.get('/block/:blockHash', blocks.show); app.param('blockHash', blocks.block); + app.get('/last_blocks', blocks.last_blocks); var transactions = require('../app/controllers/transactions'); app.get('/tx/:txid', transactions.show); From 513d8d88c95faa6a34fea3d54b2de4a786c14bf8 Mon Sep 17 00:00:00 2001 From: Mario Colque Date: Wed, 8 Jan 2014 09:28:24 -0300 Subject: [PATCH 43/50] added new route /blocks --- config/routes.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/config/routes.js b/config/routes.js index 4b37ad7..26154c6 100644 --- a/config/routes.js +++ b/config/routes.js @@ -8,13 +8,14 @@ module.exports = function(app) { //Block routes var blocks = require('../app/controllers/blocks'); + app.get('/blocks', blocks.list); app.get('/block/:blockHash', blocks.show); app.param('blockHash', blocks.block); app.get('/last_blocks', blocks.last_blocks); var transactions = require('../app/controllers/transactions'); app.get('/tx/:txid', transactions.show); - + app.param('txid', transactions.transaction); - + }; From 1ec2984bab77a4247b91fee1ff6baa667d76e850 Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Wed, 8 Jan 2014 09:32:38 -0300 Subject: [PATCH 44/50] Frontend: Blocks controller for angularjs --- app/views/includes/foot.jade | 2 ++ public/js/app.js | 3 ++- public/js/controllers/blocks.js | 8 ++++++++ public/js/services/blocks.js | 5 +++++ 4 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 public/js/controllers/blocks.js create mode 100644 public/js/services/blocks.js diff --git a/app/views/includes/foot.jade b/app/views/includes/foot.jade index e4c8706..edca962 100755 --- a/app/views/includes/foot.jade +++ b/app/views/includes/foot.jade @@ -23,10 +23,12 @@ script(type='text/javascript', src='/js/directives.js') script(type='text/javascript', src='/js/filters.js') //Application Services +script(type='text/javascript', src='/js/services/blocks.js') script(type='text/javascript', src='/js/services/global.js') script(type='text/javascript', src='/js/services/index.js') //Application Controllers script(type='text/javascript', src='/js/controllers/index.js') script(type='text/javascript', src='/js/controllers/header.js') +script(type='text/javascript', src='/js/controllers/blocks.js') script(type='text/javascript', src='/js/init.js') diff --git a/public/js/app.js b/public/js/app.js index afb98d4..2b6bc68 100755 --- a/public/js/app.js +++ b/public/js/app.js @@ -1,6 +1,7 @@ 'use strict'; -angular.module('mystery', ['ngCookies', 'ngResource', 'ngRoute', 'ui.bootstrap', 'ui.route', 'mystery.system', 'mystery.index']); +angular.module('mystery', ['ngCookies', 'ngResource', 'ngRoute', 'ui.bootstrap', 'ui.route', 'mystery.system', 'mystery.index', 'mystery.blocks']); angular.module('mystery.system', []); angular.module('mystery.index', []); +angular.module('mystery.blocks', []); diff --git a/public/js/controllers/blocks.js b/public/js/controllers/blocks.js new file mode 100644 index 0000000..032b593 --- /dev/null +++ b/public/js/controllers/blocks.js @@ -0,0 +1,8 @@ +'use strict'; + +angular.module('mystery.blocks').controller('BlocksController', ['$scope', '$routeParams', '$location', 'Global', 'Blocks', function ($scope, $routeParams, $location, Global, Blocks) { + $scope.global = Global; + + // for avoid warning. please remove when you use Blocks + $scope.blocks = Blocks; +}]); diff --git a/public/js/services/blocks.js b/public/js/services/blocks.js new file mode 100644 index 0000000..e60ded2 --- /dev/null +++ b/public/js/services/blocks.js @@ -0,0 +1,5 @@ +'use strict'; + +angular.module('mystery.blocks').factory('Blocks', ['$resource', function($resource) { + return $resource; +}]); From 6aa680ef08689f7d8ba81aebf6b42f6cde92af8b Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 8 Jan 2014 09:47:12 -0300 Subject: [PATCH 45/50] adds heights to block --- app/models/Block.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/Block.js b/app/models/Block.js index 3ce94ef..db88ed4 100644 --- a/app/models/Block.js +++ b/app/models/Block.js @@ -19,6 +19,7 @@ var BlockSchema = new Schema({ unique: true, }, size: Number, + height: Number, confirmations: Number, version: Number, merkleroot: String, From 92054210a806b6efd996b58d2e21996a6f1e0867 Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Wed, 8 Jan 2014 11:05:19 -0300 Subject: [PATCH 46/50] block page draft --- app/controllers/blocks.js | 2 +- app/models/Block.js | 2 +- public/js/config.js | 3 +++ public/js/controllers/blocks.js | 8 ++++++++ public/js/controllers/header.js | 7 ++----- public/js/services/blocks.js | 4 +++- public/views/block.html | 23 +++++++++++++++++++++++ public/views/header.html | 8 ++++---- public/views/index.html | 23 ++++++++++++++++++----- 9 files changed, 63 insertions(+), 17 deletions(-) create mode 100644 public/views/block.html diff --git a/app/controllers/blocks.js b/app/controllers/blocks.js index f08016a..0407c75 100644 --- a/app/controllers/blocks.js +++ b/app/controllers/blocks.js @@ -33,7 +33,7 @@ exports.show = function(req, res) { * List of blocks at HomePage */ exports.last_blocks = function(req, res) { - Block.find().limit(7).exec(function(err, blocks) { + Block.find().sort({time:-1}).limit(7).exec(function(err, blocks) { if (err) { res.render('error', { status: 500 diff --git a/app/models/Block.js b/app/models/Block.js index af173dc..ee68b94 100644 --- a/app/models/Block.js +++ b/app/models/Block.js @@ -94,4 +94,4 @@ BlockSchema.statics.fromHash = function(hash, cb) { }).exec(cb); }; -mongoose.model('Block', BlockSchema); +module.exports = mongoose.model('Block', BlockSchema); diff --git a/public/js/config.js b/public/js/config.js index fe68006..1e36afd 100755 --- a/public/js/config.js +++ b/public/js/config.js @@ -4,6 +4,9 @@ angular.module('mystery').config(['$routeProvider', function($routeProvider) { $routeProvider. + when('/block/:blockHash', { + templateUrl: 'views/block.html' + }). when('/', { templateUrl: 'views/index.html' }). diff --git a/public/js/controllers/blocks.js b/public/js/controllers/blocks.js index 032b593..13b6bfd 100644 --- a/public/js/controllers/blocks.js +++ b/public/js/controllers/blocks.js @@ -3,6 +3,14 @@ angular.module('mystery.blocks').controller('BlocksController', ['$scope', '$routeParams', '$location', 'Global', 'Blocks', function ($scope, $routeParams, $location, Global, Blocks) { $scope.global = Global; + $scope.findOne = function() { + Blocks.get({ + blockHash: $routeParams.blockHash + }, function(block) { + $scope.block = block; + }); + }; + // for avoid warning. please remove when you use Blocks $scope.blocks = Blocks; }]); diff --git a/public/js/controllers/header.js b/public/js/controllers/header.js index 039a5ac..8dddc14 100755 --- a/public/js/controllers/header.js +++ b/public/js/controllers/header.js @@ -4,11 +4,8 @@ angular.module('mystery.system').controller('HeaderController', ['$scope', 'Glob $scope.global = Global; $scope.menu = [{ - 'title': 'Articles', - 'link': 'articles' - }, { - 'title': 'Create New Article', - 'link': 'articles/create' + 'title': 'Blocks', + 'link': 'blocks' }]; $scope.isCollapsed = false; diff --git a/public/js/services/blocks.js b/public/js/services/blocks.js index e60ded2..fe5cf40 100644 --- a/public/js/services/blocks.js +++ b/public/js/services/blocks.js @@ -1,5 +1,7 @@ 'use strict'; angular.module('mystery.blocks').factory('Blocks', ['$resource', function($resource) { - return $resource; + return $resource('block/:blockHash', { + blockHash: '@blockHash' + }); }]); diff --git a/public/views/block.html b/public/views/block.html new file mode 100644 index 0000000..686a6ad --- /dev/null +++ b/public/views/block.html @@ -0,0 +1,23 @@ +
+ + + + + + + + + + + + + + + + + + +
HeightAgeTransactionsConfirmationsSize (kB)
{{block.height}}{{block.time | date:'short'}}{{block.tx.length }}{{block.confirmations}}{{block.size / 1024}}
+
\ No newline at end of file diff --git a/public/views/header.html b/public/views/header.html index 70189e7..fb034ed 100755 --- a/public/views/header.html +++ b/public/views/header.html @@ -6,13 +6,13 @@ - Mystery + Mystery diff --git a/public/views/index.html b/public/views/index.html index d84010f..953dc31 100644 --- a/public/views/index.html +++ b/public/views/index.html @@ -2,9 +2,22 @@ -
    -
  • - {{block.hash}} -
  • -
+ + + + + + + + + + + + + + + + + +
HeightAgeTransactionsConfirmationsSize (kB)
{{block.height}}{{block.time | date:'short'}}{{block.tx.length }}{{block.confirmations}}{{block.size / 1024}}
From ac261d42c6f7b8821f88bc74e8193bc937cf31c7 Mon Sep 17 00:00:00 2001 From: Mario Colque Date: Wed, 8 Jan 2014 11:55:06 -0300 Subject: [PATCH 47/50] Added new Angular views for block list --- public/views/blocks/list.html | 10 ++++++++++ public/views/blocks/list_date.html | 10 ++++++++++ 2 files changed, 20 insertions(+) create mode 100644 public/views/blocks/list.html create mode 100644 public/views/blocks/list_date.html diff --git a/public/views/blocks/list.html b/public/views/blocks/list.html new file mode 100644 index 0000000..f258705 --- /dev/null +++ b/public/views/blocks/list.html @@ -0,0 +1,10 @@ +
+ +
    +
  • + {{block.hash}} {{block.time}} +
  • +
+
\ No newline at end of file diff --git a/public/views/blocks/list_date.html b/public/views/blocks/list_date.html new file mode 100644 index 0000000..349857c --- /dev/null +++ b/public/views/blocks/list_date.html @@ -0,0 +1,10 @@ +
+ +
    +
  • + {{block.hash}} {{block.time}} +
  • +
+
From f6d870bb5e55c246fe1d646167ffc877fcbe9fbb Mon Sep 17 00:00:00 2001 From: Mario Colque Date: Wed, 8 Jan 2014 11:55:24 -0300 Subject: [PATCH 48/50] added new route --- config/routes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/routes.js b/config/routes.js index 26154c6..5a3e80f 100644 --- a/config/routes.js +++ b/config/routes.js @@ -8,7 +8,7 @@ module.exports = function(app) { //Block routes var blocks = require('../app/controllers/blocks'); - app.get('/blocks', blocks.list); + app.get('/api/blocks', blocks.list); app.get('/block/:blockHash', blocks.show); app.param('blockHash', blocks.block); app.get('/last_blocks', blocks.last_blocks); From c967df577eecc109e1736d9545e3248dd8322a5b Mon Sep 17 00:00:00 2001 From: Mario Colque Date: Wed, 8 Jan 2014 11:56:36 -0300 Subject: [PATCH 49/50] added new blocklist page --- app/controllers/blocks.js | 25 ++++++++++++++++++++++++- public/js/config.js | 6 ++++++ public/js/controllers/blocks.js | 16 +++++++++++++++- public/js/services/blocks.js | 2 +- 4 files changed, 46 insertions(+), 3 deletions(-) diff --git a/app/controllers/blocks.js b/app/controllers/blocks.js index f08016a..2904efd 100644 --- a/app/controllers/blocks.js +++ b/app/controllers/blocks.js @@ -23,7 +23,7 @@ exports.block = function(req, res, next, hash) { /** - * Show block + * Show block */ exports.show = function(req, res) { res.jsonp(req.block); @@ -44,3 +44,26 @@ exports.last_blocks = function(req, res) { }); }; +/** + * List of blocks by date + */ +exports.list = function(req, res) { + var findParam = {}; + + if (req.query.blockDate) { + findParam = {}; + } + + Block + .find(findParam) + .limit(5) + .exec(function(err, blocks) { + if (err) { + res.render('error', { + status: 500 + }); + } else { + res.jsonp(blocks); + } + }); +}; diff --git a/public/js/config.js b/public/js/config.js index fe68006..c4b7d3e 100755 --- a/public/js/config.js +++ b/public/js/config.js @@ -7,6 +7,12 @@ angular.module('mystery').config(['$routeProvider', when('/', { templateUrl: 'views/index.html' }). + when('/blocks', { + templateUrl: 'views/blocks/list.html' + }). + when('/blocks-date/:blockDate', { + templateUrl: 'views/blocks/list_date.html' + }). otherwise({ redirectTo: '/' }); diff --git a/public/js/controllers/blocks.js b/public/js/controllers/blocks.js index 032b593..2b708cb 100644 --- a/public/js/controllers/blocks.js +++ b/public/js/controllers/blocks.js @@ -2,7 +2,21 @@ angular.module('mystery.blocks').controller('BlocksController', ['$scope', '$routeParams', '$location', 'Global', 'Blocks', function ($scope, $routeParams, $location, Global, Blocks) { $scope.global = Global; - + + $scope.list_blocks = function() { + Blocks.query(function(blocks) { + $scope.blocks = blocks; + }); + }; + + $scope.list_blocks_date = function() { + Blocks.query({ + blockDate: $routeParams.blockDate + }, function(blocks) { + $scope.blocks = blocks; + }); + }; + // for avoid warning. please remove when you use Blocks $scope.blocks = Blocks; }]); diff --git a/public/js/services/blocks.js b/public/js/services/blocks.js index e60ded2..6c827a6 100644 --- a/public/js/services/blocks.js +++ b/public/js/services/blocks.js @@ -1,5 +1,5 @@ 'use strict'; angular.module('mystery.blocks').factory('Blocks', ['$resource', function($resource) { - return $resource; + return $resource('/api/blocks'); }]); From 19636a5ffb1cc6e6dbd3447f7ada6f611f251950 Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Wed, 8 Jan 2014 13:13:50 -0300 Subject: [PATCH 50/50] fix url for block info --- config/routes.js | 2 +- public/js/services/blocks.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/routes.js b/config/routes.js index 5a3e80f..ab4c9b1 100644 --- a/config/routes.js +++ b/config/routes.js @@ -9,7 +9,7 @@ module.exports = function(app) { //Block routes var blocks = require('../app/controllers/blocks'); app.get('/api/blocks', blocks.list); - app.get('/block/:blockHash', blocks.show); + app.get('/api/block/:blockHash', blocks.show); app.param('blockHash', blocks.block); app.get('/last_blocks', blocks.last_blocks); diff --git a/public/js/services/blocks.js b/public/js/services/blocks.js index 69185f1..7747ff3 100644 --- a/public/js/services/blocks.js +++ b/public/js/services/blocks.js @@ -1,7 +1,7 @@ 'use strict'; angular.module('mystery.blocks').factory('Block', ['$resource', function($resource) { - return $resource('block/:blockHash', { + return $resource('/api/block/:blockHash', { blockHash: '@blockHash' }); }]);