From 848b4856589b4384dc8a9c2ccbb9ef55911624db Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 8 Jan 2014 16:46:56 -0300 Subject: [PATCH 01/25] simple test for block thin model --- test/model/block.js | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/test/model/block.js b/test/model/block.js index 88af38e6..f164be20 100644 --- a/test/model/block.js +++ b/test/model/block.js @@ -11,31 +11,30 @@ var config = require('../../config/config'), Block = require('../../app/models/Block'); -mongoose.connect(config.db); -var db = mongoose.connection; +mongoose.connection.on('error', function(err) { console.log(err); }); describe('getInfo', function(){ - var block_hash = TESTING_BLOCK; + before(function(done) { + mongoose.connect(config.db); + done(); + }); + after(function(done) { + mongoose.connection.close(); + done(); + }); - db.on('error', console.error.bind(console, 'connection error:')); - - db.once('open', function (){ - - - var block2 = Block.fromHashWithInfo(block_hash, function(err, b2) { - if (err) done(err); - - console.log("Block obj:"); - console.log(b2); - console.log("Block.info:"); - console.log(b2.info); - db.close(); - done(); - }); + it('should pool block\'s info from bitcoind', function(done) { + var block2 = Block.fromHashWithInfo(TESTING_BLOCK, function(err, b2) { + if (err) done(err); + assert.equal(b2.hash, TESTING_BLOCK); + assert.equal(b2.info.hash, TESTING_BLOCK); + assert.equal(b2.info.chainwork, '00000000000000000000000000000000000000000000000000446af21d50acd3'); + done(); + }); }); }); From 5509e941ba561f49bf3d8abe86c3b649dfa4f6b0 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 8 Jan 2014 17:04:45 -0300 Subject: [PATCH 02/25] mocha test for transaction --- app/models/Transaction.js | 13 ++++++----- test/mocha.opts | 1 + test/model/block.js | 15 +++++++++---- test/model/transaction.js | 46 +++++++++++++++++++++++++++++++++++++++ test/test.js | 9 -------- 5 files changed, 66 insertions(+), 18 deletions(-) create mode 100644 test/model/transaction.js delete mode 100644 test/test.js diff --git a/app/models/Transaction.js b/app/models/Transaction.js index 5d2a6ee7..fb8cd869 100644 --- a/app/models/Transaction.js +++ b/app/models/Transaction.js @@ -5,7 +5,10 @@ */ var mongoose = require('mongoose'), Schema = mongoose.Schema, - async = require('async'); + async = require('async'), + RpcClient = require('bitcore/RpcClient').class(), + config = require('../../config/config'); + /** */ @@ -31,14 +34,14 @@ TransactionSchema.statics.load = function(id, cb) { }; -TransactionSchema.statics.fromID = function(txid, cb) { +TransactionSchema.statics.fromId = function(txid, cb) { this.findOne({ txid: txid, }).exec(cb); }; -TransactionSchema.statics.fromIDWithInfo = function(txid, cb) { - this.fromHash(hash, function(err, tx) { +TransactionSchema.statics.fromIdWithInfo = function(txid, cb) { + this.fromId(txid, function(err, tx) { if (err) return cb(err); tx.getInfo(function(err) { return cb(err,tx); } ); @@ -82,7 +85,7 @@ TransactionSchema.methods.getInfo = function (next) { var that = this; var rpc = new RpcClient(config.bitcoind); - rpc.getRawTransaction(this.txid, function(err, txInfo) { + rpc.getRawTransaction(this.txid, 1, function(err, txInfo) { if (err) return next(err); that.info = txInfo.result; diff --git a/test/mocha.opts b/test/mocha.opts index 74590dc4..a9caeb4a 100644 --- a/test/mocha.opts +++ b/test/mocha.opts @@ -1,4 +1,5 @@ --require should -R spec --ui bdd +--recursive diff --git a/test/model/block.js b/test/model/block.js index f164be20..6a2b5f08 100644 --- a/test/model/block.js +++ b/test/model/block.js @@ -14,7 +14,7 @@ var mongoose.connection.on('error', function(err) { console.log(err); }); -describe('getInfo', function(){ +describe('Block getInfo', function(){ before(function(done) { mongoose.connect(config.db); @@ -26,15 +26,22 @@ describe('getInfo', function(){ done(); }); - it('should pool block\'s info from bitcoind', function(done) { + it('should poll block\'s info from mongoose', function(done) { var block2 = Block.fromHashWithInfo(TESTING_BLOCK, function(err, b2) { if (err) done(err); assert.equal(b2.hash, TESTING_BLOCK); - assert.equal(b2.info.hash, TESTING_BLOCK); - assert.equal(b2.info.chainwork, '00000000000000000000000000000000000000000000000000446af21d50acd3'); done(); }); }); + + it('should poll block\'s info from bitcoind', function(done) { + var block2 = Block.fromHashWithInfo(TESTING_BLOCK, function(err, b2) { + if (err) done(err); + assert.equal(b2.info.hash, TESTING_BLOCK); + assert.equal(b2.info.chainwork, '00000000000000000000000000000000000000000000000000446af21d50acd3'); + done(); + }); + }); }); diff --git a/test/model/transaction.js b/test/model/transaction.js new file mode 100644 index 00000000..bef066f1 --- /dev/null +++ b/test/model/transaction.js @@ -0,0 +1,46 @@ +#!/usr/bin/env node + +process.env.NODE_ENV = process.env.NODE_ENV || 'development'; + + +var TESTING_TX = '9f4648538a8fd773029139f7e67cee51586bced78d7ff0388d10cb71096f2289'; + +var + mongoose= require('mongoose'), + assert = require('assert'), + config = require('../../config/config'), + Transaction = require('../../app/models/Transaction'); + + +mongoose.connection.on('error', function(err) { console.log(err); }); + +describe('Transaction getInfo', function(){ + + before(function(done) { + mongoose.connect(config.db); + done(); + }); + + after(function(done) { + mongoose.connection.close(); + done(); + }); + + it('should pool tx\'s object from mongoose', function(done) { + Transaction.fromIdWithInfo(TESTING_TX, function(err, tx) { + if (err) done(err); + assert.equal(tx.txid, TESTING_TX); + done(); + }); + }); + + it('should pool tx\'s info from bitcoind', function(done) { + Transaction.fromIdWithInfo(TESTING_TX, function(err, tx) { + if (err) done(err); + assert.equal(tx.info.txid, TESTING_TX); + assert.equal(tx.info.blockhash, '000000007af2a08af7ce4934167dc2afd7a2e6bfd31472332db02a6f38cb7b4d'); + done(); + }); + }); +}); + diff --git a/test/test.js b/test/test.js deleted file mode 100644 index bab25b64..00000000 --- a/test/test.js +++ /dev/null @@ -1,9 +0,0 @@ -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 451b24d4a8b391bc3a5456e991227ee355337c0c Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 8 Jan 2014 17:15:46 -0300 Subject: [PATCH 03/25] fix API using the new thin object model --- app/controllers/blocks.js | 4 ++-- app/controllers/transactions.js | 4 ++-- app/models/Block.js | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/app/controllers/blocks.js b/app/controllers/blocks.js index d9c9f89c..3a38d8dd 100644 --- a/app/controllers/blocks.js +++ b/app/controllers/blocks.js @@ -13,10 +13,10 @@ var mongoose = require('mongoose'), * Find block by hash ... */ exports.block = function(req, res, next, hash) { - Block.fromHash(hash, function(err, block) { + Block.fromHashWithInfo(hash, function(err, block) { if (err) return next(err); if (!block) return next(new Error('Failed to load block ' + hash)); - req.block = block; + req.block = block.info; next(); }); }; diff --git a/app/controllers/transactions.js b/app/controllers/transactions.js index 8bf4635c..6a4cffd3 100644 --- a/app/controllers/transactions.js +++ b/app/controllers/transactions.js @@ -15,10 +15,10 @@ var Transaction = require('../models/Transaction'); * Find block by hash ... */ exports.transaction = function(req, res, next, txid) { - Transaction.fromID(txid, function(err, tx) { + Transaction.fromIdWithInfo(txid, function(err, tx) { if (err) return next(err); if (!tx) return next(new Error('Failed to load TX ' + txid)); - req.transaction = tx; + req.transaction = tx.info; next(); }); }; diff --git a/app/models/Block.js b/app/models/Block.js index 8705978c..4353797c 100644 --- a/app/models/Block.js +++ b/app/models/Block.js @@ -5,7 +5,6 @@ */ var mongoose = require('mongoose'), Schema = mongoose.Schema, - async = require('async'), RpcClient = require('bitcore/RpcClient').class(), config = require('../../config/config') ; From 6de5bf3566271b30b7334516b2891901b9e28100 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 8 Jan 2014 17:45:37 -0300 Subject: [PATCH 04/25] add time to block for sorting --- app/models/Block.js | 1 + lib/Sync.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/Block.js b/app/models/Block.js index 4353797c..a226c34a 100644 --- a/app/models/Block.js +++ b/app/models/Block.js @@ -22,6 +22,7 @@ var BlockSchema = new Schema({ index: true, unique: true, }, + time: Number, }); diff --git a/lib/Sync.js b/lib/Sync.js index 8254cd8c..6fb58cd6 100644 --- a/lib/Sync.js +++ b/lib/Sync.js @@ -71,7 +71,7 @@ function spec(b) { return this.getNextBlock(genesisHash, cb); - Block.findOne({}, {}, { sort: { 'confirmations' : 1 } }, function(err, block) { + Block.findOne({}, {}, { sort: { 'time' : -1 } }, function(err, block) { if (err) return cb(err); var nextHash = From 100b901581f40fd44e23bdebee729285a894434c Mon Sep 17 00:00:00 2001 From: Mario Colque Date: Thu, 9 Jan 2014 14:53:28 -0300 Subject: [PATCH 05/25] reusing the blocklist template. Parsing new model --- public/js/config.js | 2 +- public/js/controllers/blocks.js | 8 +------- public/views/blocks/list.html | 21 ++++++++++++++------- public/views/blocks/list_date.html | 10 ---------- 4 files changed, 16 insertions(+), 25 deletions(-) delete mode 100644 public/views/blocks/list_date.html diff --git a/public/js/config.js b/public/js/config.js index 35fe3836..1b06b84f 100755 --- a/public/js/config.js +++ b/public/js/config.js @@ -14,7 +14,7 @@ angular.module('mystery').config(['$routeProvider', templateUrl: 'views/blocks/list.html' }). when('/blocks-date/:blockDate', { - templateUrl: 'views/blocks/list_date.html' + templateUrl: 'views/blocks/list.html' }). otherwise({ redirectTo: '/' diff --git a/public/js/controllers/blocks.js b/public/js/controllers/blocks.js index 98e88010..002aea0e 100644 --- a/public/js/controllers/blocks.js +++ b/public/js/controllers/blocks.js @@ -3,13 +3,7 @@ angular.module('mystery.blocks').controller('BlocksController', ['$scope', '$routeParams', '$location', 'Global', 'Block', 'Blocks', function ($scope, $routeParams, $location, Global, Block, Blocks) { $scope.global = Global; - $scope.list_blocks = function() { - Blocks.query(function(blocks) { - $scope.blocks = blocks; - }); - }; - - $scope.list_blocks_date = function() { + $scope.list = function() { Blocks.query({ blockDate: $routeParams.blockDate }, function(blocks) { diff --git a/public/views/blocks/list.html b/public/views/blocks/list.html index f258705a..656793fe 100644 --- a/public/views/blocks/list.html +++ b/public/views/blocks/list.html @@ -1,10 +1,17 @@ -
+
-
    -
  • - {{block.hash}} {{block.time}} -
  • -
-
\ No newline at end of file + + + + + + + + + + + +
HashSolved at
{{block.hash}}{{block.time}}
+
diff --git a/public/views/blocks/list_date.html b/public/views/blocks/list_date.html deleted file mode 100644 index 349857cf..00000000 --- a/public/views/blocks/list_date.html +++ /dev/null @@ -1,10 +0,0 @@ -
- -
    -
  • - {{block.hash}} {{block.time}} -
  • -
-
From d0874c48cf975e727cf667de8d4817c3a2a22013 Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Thu, 9 Jan 2014 15:13:26 -0300 Subject: [PATCH 06/25] front-end with angularjs: blockpage and transaction page. Basic information. --- app/views/includes/foot.jade | 4 +- config/routes.js | 2 +- public/js/app.js | 3 +- public/js/config.js | 3 ++ public/js/controllers/transactions.js | 14 +++++ public/js/services/transactions.js | 8 +++ public/views/block.html | 74 ++++++++++++++++++++++----- public/views/index.html | 12 ++--- public/views/transaction.html | 32 ++++++++++++ 9 files changed, 128 insertions(+), 24 deletions(-) create mode 100644 public/js/controllers/transactions.js create mode 100644 public/js/services/transactions.js create mode 100644 public/views/transaction.html diff --git a/app/views/includes/foot.jade b/app/views/includes/foot.jade index edca962e..ad487576 100755 --- a/app/views/includes/foot.jade +++ b/app/views/includes/foot.jade @@ -1,7 +1,7 @@ #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') @@ -23,6 +23,7 @@ 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/transactions.js') 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') @@ -31,4 +32,5 @@ script(type='text/javascript', src='/js/services/index.js') 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/controllers/transactions.js') script(type='text/javascript', src='/js/init.js') diff --git a/config/routes.js b/config/routes.js index ab4c9b18..fd522bda 100644 --- a/config/routes.js +++ b/config/routes.js @@ -14,7 +14,7 @@ module.exports = function(app) { app.get('/last_blocks', blocks.last_blocks); var transactions = require('../app/controllers/transactions'); - app.get('/tx/:txid', transactions.show); + app.get('/api/tx/:txid', transactions.show); app.param('txid', transactions.transaction); diff --git a/public/js/app.js b/public/js/app.js index 2b6bc682..ca50d772 100755 --- a/public/js/app.js +++ b/public/js/app.js @@ -1,7 +1,8 @@ 'use strict'; -angular.module('mystery', ['ngCookies', 'ngResource', 'ngRoute', 'ui.bootstrap', 'ui.route', 'mystery.system', 'mystery.index', 'mystery.blocks']); +angular.module('mystery', ['ngCookies', 'ngResource', 'ngRoute', 'ui.bootstrap', 'ui.route', 'mystery.system', 'mystery.index', 'mystery.blocks', 'mystery.transactions']); angular.module('mystery.system', []); angular.module('mystery.index', []); angular.module('mystery.blocks', []); +angular.module('mystery.transactions', []); diff --git a/public/js/config.js b/public/js/config.js index 35fe3836..eaefc256 100755 --- a/public/js/config.js +++ b/public/js/config.js @@ -7,6 +7,9 @@ angular.module('mystery').config(['$routeProvider', when('/block/:blockHash', { templateUrl: 'views/block.html' }). + when('/tx/:txId', { + templateUrl: 'views/transaction.html' + }). when('/', { templateUrl: 'views/index.html' }). diff --git a/public/js/controllers/transactions.js b/public/js/controllers/transactions.js new file mode 100644 index 00000000..53aaf925 --- /dev/null +++ b/public/js/controllers/transactions.js @@ -0,0 +1,14 @@ +'use strict'; + +angular.module('mystery.transactions').controller('transactionsController', ['$scope', '$routeParams', '$location', 'Global', 'Transaction', function ($scope, $routeParams, $location, Global, Transaction) { + $scope.global = Global; + + $scope.findOne = function() { + Transaction.get({ + txId: $routeParams.txId + }, function(tx) { + $scope.tx = tx; + }); + }; +}]); + diff --git a/public/js/services/transactions.js b/public/js/services/transactions.js new file mode 100644 index 00000000..9edfacaf --- /dev/null +++ b/public/js/services/transactions.js @@ -0,0 +1,8 @@ +'use strict'; + +angular.module('mystery.transactions').factory('Transaction', ['$resource', function($resource) { + return $resource('/api/tx/:txId', { + txId: '@txId' + }); +}]); + diff --git a/public/views/block.html b/public/views/block.html index 686a6ade..1c89df8e 100644 --- a/public/views/block.html +++ b/public/views/block.html @@ -1,23 +1,73 @@
+ +

Summary

+
+
Number Of Transactions
+
--
+
Output Total
+
--
+
Estimated Transaction Volume
+
--
+
Transaction Fees
+
--
+
Height
+
{{block.height}}
+
Timestamp
+
{{block.time}}
+
Received Time
+
{{block.time}}
+
Relayed By
+
--
+
Difficulty
+
{{block.difficulty}}
+
Bits
+
{{block.bits}}
+
Size
+
{{block.size}}
+
Version
+
{{block.version}}
+
Nonce
+
{{block.nonce}}
+
+ +

Hashes

- - - - - + + - - - - - + + + + + + + + + + + + + +
HeightAgeTransactionsConfirmationsSize (kB)Hashes 
{{block.height}}{{block.time | date:'short'}}{{block.tx.length }}{{block.confirmations}}{{block.size / 1024}}Hash{{block.hash}}
Previous Block{{block.previousblockhash}}
Next Block(s){{block.nextblockhash}}
Merkle Root{{block.merkleroot}}
-
\ No newline at end of file + +

Transactions

+ + + + + + + + + +
Hash
{{tx}}
+ diff --git a/public/views/index.html b/public/views/index.html index 953dc31b..97d4c36a 100644 --- a/public/views/index.html +++ b/public/views/index.html @@ -4,19 +4,13 @@ - - - - - + + - + - - -
HeightAgeTransactionsConfirmationsSize (kB)HashTime
{{block.height}}{{block.hash}} {{block.time | date:'short'}}{{block.tx.length }}{{block.confirmations}}{{block.size / 1024}}
diff --git a/public/views/transaction.html b/public/views/transaction.html new file mode 100644 index 00000000..b5c519bd --- /dev/null +++ b/public/views/transaction.html @@ -0,0 +1,32 @@ +
+ +
    +
  • {{tx.txid}}
  • +
  • VIN +
      +
    • coinbase: {{vin.coinbase}}
    • +
    • sequence: {{vin.sequence}}
    • +
    • txid: {{vin.txid}}
    • +
    • vout: {{vin.vout}}
    • +
    +
  • +
  • VOUT +
      +
    • value: {{vout.value}}
    • +
    • n: {{vout.n}}
    • +
    • addresses: {{vin.scriptPubKey}} +
        +
      • address: {{addr}}
      • +
      +
    • +
    +
  • +
  • Blockhash: {{tx.blockhash}}
  • +
  • Confirmations: {{tx.confirmations}}
  • +
  • Time {{tx.time}}
  • +
  • Bloctime {{tx.blocktime}}
  • +
+
+ From aa771bf4dd6bdfdc69d49d1911437ca0f278566f Mon Sep 17 00:00:00 2001 From: Mario Colque Date: Thu, 9 Jan 2014 15:15:30 -0300 Subject: [PATCH 07/25] blocks controller improved to find blocks by date --- app/controllers/blocks.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/app/controllers/blocks.js b/app/controllers/blocks.js index 3a38d8dd..8939f21c 100644 --- a/app/controllers/blocks.js +++ b/app/controllers/blocks.js @@ -51,7 +51,13 @@ exports.list = function(req, res) { var findParam = {}; if (req.query.blockDate) { - findParam = {}; + var gte = Math.round((new Date(req.query.blockDate)).getTime() / 1000); + var lte = gte + 86400; + + findParam = { time: { + '$gte': gte, + '$lte': lte + }}; } Block @@ -67,3 +73,14 @@ exports.list = function(req, res) { } }); }; + + +1296688602 + + + +1296615600 + +1296615600000 + + From aab6121dd00994cf8688822be0a786adf7d00f1a Mon Sep 17 00:00:00 2001 From: Mario Colque Date: Thu, 9 Jan 2014 15:21:51 -0300 Subject: [PATCH 08/25] unnecessary number removed --- app/controllers/blocks.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/app/controllers/blocks.js b/app/controllers/blocks.js index 8939f21c..53759402 100644 --- a/app/controllers/blocks.js +++ b/app/controllers/blocks.js @@ -75,12 +75,3 @@ exports.list = function(req, res) { }; -1296688602 - - - -1296615600 - -1296615600000 - - From 0bf989425ad3109ef770571e96f4ac989c745acd Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Thu, 9 Jan 2014 11:44:52 -0300 Subject: [PATCH 09/25] bitcoind diff --- etc/bitcoind/bitcoin.conf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/etc/bitcoind/bitcoin.conf b/etc/bitcoind/bitcoin.conf index 062c09e0..879bedec 100644 --- a/etc/bitcoind/bitcoin.conf +++ b/etc/bitcoind/bitcoin.conf @@ -6,7 +6,8 @@ testnet=3 txindex=1 # Allow connections outsite localhost? -# rpcallowip=192.168.0.* +rpcallowip=192.168.1.* +rpcallowip='192.168.1.*' From 35d5be894fb39e8b43d41a773410c80205d33844 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Thu, 9 Jan 2014 17:30:29 -0300 Subject: [PATCH 10/25] more information added to TX API: values and IN addresses. Test updated --- app/controllers/transactions.js | 13 +++- app/models/Block.js | 1 + app/models/Transaction.js | 108 +++++++++++++++++++++++++++++--- config/env/development.js | 3 +- config/routes.js | 3 + package.json | 1 + test/model/block.js | 8 ++- test/model/transaction.js | 9 ++- 8 files changed, 127 insertions(+), 19 deletions(-) diff --git a/app/controllers/transactions.js b/app/controllers/transactions.js index 6a4cffd3..caa66f13 100644 --- a/app/controllers/transactions.js +++ b/app/controllers/transactions.js @@ -16,7 +16,12 @@ var Transaction = require('../models/Transaction'); */ exports.transaction = function(req, res, next, txid) { Transaction.fromIdWithInfo(txid, function(err, tx) { - if (err) return next(err); + if (err) { + console.log(err); + res.status(404).send('Not found'); + return next(); + } + if (!tx) return next(new Error('Failed to load TX ' + txid)); req.transaction = tx.info; next(); @@ -25,9 +30,11 @@ exports.transaction = function(req, res, next, txid) { /** - * Show block */ exports.show = function(req, res) { - res.jsonp(req.transaction); + + if (req.transaction) { + res.jsonp(req.transaction); + } }; diff --git a/app/models/Block.js b/app/models/Block.js index a226c34a..7374943a 100644 --- a/app/models/Block.js +++ b/app/models/Block.js @@ -57,6 +57,7 @@ BlockSchema.statics.fromHash = function(hash, cb) { BlockSchema.statics.fromHashWithInfo = function(hash, cb) { this.fromHash(hash, function(err, block) { if (err) return cb(err); + if (!block) { return cb(new Error('Block not found')); } block.getInfo(function(err) { return cb(err,block); } ); }); diff --git a/app/models/Transaction.js b/app/models/Transaction.js index fb8cd869..8d26c70f 100644 --- a/app/models/Transaction.js +++ b/app/models/Transaction.js @@ -3,10 +3,15 @@ /** * Module dependencies. */ -var mongoose = require('mongoose'), - Schema = mongoose.Schema, - async = require('async'), +var mongoose = require('mongoose'), + Schema = mongoose.Schema, + async = require('async'), RpcClient = require('bitcore/RpcClient').class(), + Transaction = require('bitcore/Transaction').class(), + Address = require('bitcore/Address').class(), + networks = require('bitcore/networks'), + util = require('bitcore/util/util'), + bignum = require('BigNum'), config = require('../../config/config'); @@ -41,10 +46,15 @@ TransactionSchema.statics.fromId = function(txid, cb) { }; TransactionSchema.statics.fromIdWithInfo = function(txid, cb) { + + // TODO Should we go to mongoDB first? Now, no extra information is stored at mongo. + this.fromId(txid, function(err, tx) { if (err) return cb(err); - tx.getInfo(function(err) { return cb(err,tx); } ); + if (!tx) { return cb(new Error('TX not found')); } + + tx.queryInfo(function(err) { return cb(err,tx); } ); }); }; @@ -79,18 +89,98 @@ TransactionSchema.statics.createFromArray = function(txs, next) { }; +TransactionSchema.methods.fillInputValues = function (tx, next) { -TransactionSchema.methods.getInfo = function (next) { + if (! this.rpc) this.rpc = new RpcClient(config.bitcoind); var that = this; - var rpc = new RpcClient(config.bitcoind); + async.each(tx.ins, function(i, cb) { - rpc.getRawTransaction(this.txid, 1, function(err, txInfo) { + var outHash = i.getOutpointHash(); + var outIndex = i.getOutpointIndex(); + var outHashBase64 = outHash.reverse().toString('hex'); + + var c=0; + that.rpc.getRawTransaction(outHashBase64, function(err, txdata) { + var txin = new Transaction(); + var b = new Buffer(txdata.result,'hex'); + txin.parse(b); + + txin.outs.forEach( function(j) { + // console.log( c + ': ' + util.formatValue(j.v) ); + if (c === outIndex) { + i.value = j.v; + } + c++; + }); + return cb(); + }); + }, + function(err) { + return next(err); + } + ); +}; + +TransactionSchema.methods.queryInfo = function (next) { + + var that = this; + var network = ( config.network === 'testnet') ? networks.testnet : networks.livenet ; + this.rpc = new RpcClient(config.bitcoind); + + + this.rpc.getRawTransaction(this.txid, 1, function(err, txInfo) { if (err) return next(err); + that.info = txInfo.result; - //console.log("THAT", that); - return next(null, that.info); + // Transaction parsing + var b = new Buffer(txInfo.result.hex,'hex'); + var tx = new Transaction(); + tx.parse(b); + + that.fillInputValues(tx, function(err) { + + // Copy TX relevant values to .info + + var c = 0; + + + var valueIn = bignum(0); + var valueOut = bignum(0); + tx.ins.forEach(function(i) { + + that.info.vin[c].value = util.formatValue(i.value); + + var n = util.valueToBigInt(i.value).toNumber(); + valueIn = valueIn.add( n ); + + + var scriptSig = i.getScript(); + var pubKey = scriptSig.simpleInPubKey(); + var pubKeyHash = util.sha256ripe160(pubKey); + var addr = new Address(network.addressPubkey, pubKeyHash); + var addrStr = addr.toString(); + + that.info.vin[c].addr = addrStr; + + c++; + }); + + + tx.outs.forEach( function(i) { + var n = util.valueToBigInt(i.v).toNumber(); + valueOut = valueOut.add(n); + }); + + that.info.valueIn = valueIn / util.COIN; + that.info.valueOut = valueOut / util.COIN; + that.info.feeds = (valueIn - valueOut) / util.COIN; + + that.info.size = b.length; + + return next(err, that.info); + }); }); }; diff --git a/config/env/development.js b/config/env/development.js index 6836a43c..e51b30f5 100755 --- a/config/env/development.js +++ b/config/env/development.js @@ -11,5 +11,6 @@ module.exports = { protocol: 'http', host: process.env.BITCOIND_HOST || '127.0.0.1', port: process.env.BITCOIND_PORT || '8332', - } + }, + network: 'testnet', } diff --git a/config/routes.js b/config/routes.js index fd522bda..f24ac7d0 100644 --- a/config/routes.js +++ b/config/routes.js @@ -9,8 +9,11 @@ module.exports = function(app) { //Block routes var blocks = require('../app/controllers/blocks'); app.get('/api/blocks', blocks.list); + + app.get('/api/block/:blockHash', blocks.show); app.param('blockHash', blocks.block); + app.get('/last_blocks', blocks.last_blocks); var transactions = require('../app/controllers/transactions'); diff --git a/package.json b/package.json index 1dd908e4..33f323dc 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "async": "*", "classtool": "*", "commander": "*", + "bignum": "*", "express": "~3.4.7", "jade": "~1.0.2", "mongoose": "~3.8.3", diff --git a/test/model/block.js b/test/model/block.js index 6a2b5f08..7fa2a302 100644 --- a/test/model/block.js +++ b/test/model/block.js @@ -3,7 +3,7 @@ process.env.NODE_ENV = process.env.NODE_ENV || 'development'; -var TESTING_BLOCK = '0000000000b6288775bbd326bedf324ca8717a15191da58391535408205aada4'; +var TESTING_BLOCK = '000000000185678d3d7ecc9962c96418174431f93fe20bf216d5565272423f74'; var mongoose= require('mongoose'), @@ -14,7 +14,7 @@ var mongoose.connection.on('error', function(err) { console.log(err); }); -describe('Block getInfo', function(){ +describe('Block fromHashWithInfo', function(){ before(function(done) { mongoose.connect(config.db); @@ -27,7 +27,9 @@ describe('Block getInfo', function(){ }); it('should poll block\'s info from mongoose', function(done) { +console.log('asdasd'); var block2 = Block.fromHashWithInfo(TESTING_BLOCK, function(err, b2) { +console.log('333'); if (err) done(err); assert.equal(b2.hash, TESTING_BLOCK); @@ -39,7 +41,7 @@ describe('Block getInfo', function(){ var block2 = Block.fromHashWithInfo(TESTING_BLOCK, function(err, b2) { if (err) done(err); assert.equal(b2.info.hash, TESTING_BLOCK); - assert.equal(b2.info.chainwork, '00000000000000000000000000000000000000000000000000446af21d50acd3'); + assert.equal(b2.info.chainwork, '000000000000000000000000000000000000000000000000001b6dc969ffe847'); done(); }); }); diff --git a/test/model/transaction.js b/test/model/transaction.js index bef066f1..fe3aef0c 100644 --- a/test/model/transaction.js +++ b/test/model/transaction.js @@ -3,7 +3,7 @@ process.env.NODE_ENV = process.env.NODE_ENV || 'development'; -var TESTING_TX = '9f4648538a8fd773029139f7e67cee51586bced78d7ff0388d10cb71096f2289'; +var TESTING_TX = '21798ddc9664ac0ef618f52b151dda82dafaf2e26d2bbef6cdaf55a6957ca237'; var mongoose= require('mongoose'), @@ -14,7 +14,7 @@ var mongoose.connection.on('error', function(err) { console.log(err); }); -describe('Transaction getInfo', function(){ +describe('Transaction fromIdWithInfo', function(){ before(function(done) { mongoose.connect(config.db); @@ -38,7 +38,10 @@ describe('Transaction getInfo', function(){ Transaction.fromIdWithInfo(TESTING_TX, function(err, tx) { if (err) done(err); assert.equal(tx.info.txid, TESTING_TX); - assert.equal(tx.info.blockhash, '000000007af2a08af7ce4934167dc2afd7a2e6bfd31472332db02a6f38cb7b4d'); + assert.equal(tx.info.blockhash, '000000000185678d3d7ecc9962c96418174431f93fe20bf216d5565272423f74'); + assert.equal(tx.info.valueOut, 1.66174); + assert.equal(tx.info.feeds, 0.0005 ); + assert.equal(tx.info.size, 226 ); done(); }); }); From 50485ce18ecfc1e23495d2b8d7955352d128a5e2 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Thu, 9 Jan 2014 18:18:47 -0300 Subject: [PATCH 11/25] fix coinbase TXs in inputs --- app/models/Transaction.js | 44 ++++++++++++++++++++++++++------------- test/model/transaction.js | 22 +++++++++++++++----- 2 files changed, 46 insertions(+), 20 deletions(-) diff --git a/app/models/Transaction.js b/app/models/Transaction.js index 8d26c70f..58a07072 100644 --- a/app/models/Transaction.js +++ b/app/models/Transaction.js @@ -91,6 +91,8 @@ TransactionSchema.statics.createFromArray = function(txs, next) { TransactionSchema.methods.fillInputValues = function (tx, next) { + if (tx.isCoinBase()) return next(); + if (! this.rpc) this.rpc = new RpcClient(config.bitcoind); var that = this; @@ -103,9 +105,17 @@ TransactionSchema.methods.fillInputValues = function (tx, next) { var c=0; that.rpc.getRawTransaction(outHashBase64, function(err, txdata) { var txin = new Transaction(); + + if (err || ! txdata.result) return cb( new Error('Input TX '+outHashBase64+' not found')); + var b = new Buffer(txdata.result,'hex'); txin.parse(b); + + if ( txin.isCoinBase() ) { + return cb(); + } + txin.outs.forEach( function(j) { // console.log( c + ': ' + util.formatValue(j.v) ); if (c === outIndex) { @@ -148,24 +158,28 @@ TransactionSchema.methods.queryInfo = function (next) { var valueIn = bignum(0); var valueOut = bignum(0); - tx.ins.forEach(function(i) { - that.info.vin[c].value = util.formatValue(i.value); + if ( tx.isCoinBase() ) { + that.info.isCoinBase = true; + } + else { + tx.ins.forEach(function(i) { - var n = util.valueToBigInt(i.value).toNumber(); - valueIn = valueIn.add( n ); + that.info.vin[c].value = util.formatValue(i.value); + var n = util.valueToBigInt(i.value).toNumber(); + valueIn = valueIn.add( n ); + var scriptSig = i.getScript(); + var pubKey = scriptSig.simpleInPubKey(); + var pubKeyHash = util.sha256ripe160(pubKey); + var addr = new Address(network.addressPubkey, pubKeyHash); + var addrStr = addr.toString(); - var scriptSig = i.getScript(); - var pubKey = scriptSig.simpleInPubKey(); - var pubKeyHash = util.sha256ripe160(pubKey); - var addr = new Address(network.addressPubkey, pubKeyHash); - var addrStr = addr.toString(); + that.info.vin[c].addr = addrStr; - that.info.vin[c].addr = addrStr; - - c++; - }); + c++; + }); + } tx.outs.forEach( function(i) { @@ -173,8 +187,8 @@ TransactionSchema.methods.queryInfo = function (next) { valueOut = valueOut.add(n); }); - that.info.valueIn = valueIn / util.COIN; - that.info.valueOut = valueOut / util.COIN; + that.info.valueIn = valueIn / util.COIN; + that.info.valueOut = valueOut / util.COIN; that.info.feeds = (valueIn - valueOut) / util.COIN; that.info.size = b.length; diff --git a/test/model/transaction.js b/test/model/transaction.js index fe3aef0c..ee9f16cf 100644 --- a/test/model/transaction.js +++ b/test/model/transaction.js @@ -3,7 +3,6 @@ process.env.NODE_ENV = process.env.NODE_ENV || 'development'; -var TESTING_TX = '21798ddc9664ac0ef618f52b151dda82dafaf2e26d2bbef6cdaf55a6957ca237'; var mongoose= require('mongoose'), @@ -27,17 +26,19 @@ describe('Transaction fromIdWithInfo', function(){ }); it('should pool tx\'s object from mongoose', function(done) { - Transaction.fromIdWithInfo(TESTING_TX, function(err, tx) { + var test_txid = '21798ddc9664ac0ef618f52b151dda82dafaf2e26d2bbef6cdaf55a6957ca237'; + Transaction.fromIdWithInfo(test_txid, function(err, tx) { if (err) done(err); - assert.equal(tx.txid, TESTING_TX); + assert.equal(tx.txid, test_txid); done(); }); }); it('should pool tx\'s info from bitcoind', function(done) { - Transaction.fromIdWithInfo(TESTING_TX, function(err, tx) { + var test_txid = '21798ddc9664ac0ef618f52b151dda82dafaf2e26d2bbef6cdaf55a6957ca237'; + Transaction.fromIdWithInfo(test_txid, function(err, tx) { if (err) done(err); - assert.equal(tx.info.txid, TESTING_TX); + assert.equal(tx.info.txid, test_txid); assert.equal(tx.info.blockhash, '000000000185678d3d7ecc9962c96418174431f93fe20bf216d5565272423f74'); assert.equal(tx.info.valueOut, 1.66174); assert.equal(tx.info.feeds, 0.0005 ); @@ -45,5 +46,16 @@ describe('Transaction fromIdWithInfo', function(){ done(); }); }); + + it('test a coinbase TX', function(done) { + var test_txid2 = '2a104bab1782e9b6445583296d4a0ecc8af304e4769ceb64b890e8219c562399'; + Transaction.fromIdWithInfo(test_txid2, function(err, tx) { + if (err) done(err); + assert(tx.info.isCoinBase); + assert.equal(tx.info.txid, test_txid2); + done(); + }); + }); + }); From 4de5c5dd0071c5c91ae479dc8dcefc40e8413154 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Thu, 9 Jan 2014 18:35:14 -0300 Subject: [PATCH 12/25] omit feeds + valueIn in coinbase TXs --- app/models/Transaction.js | 7 +++++-- test/model/transaction.js | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/models/Transaction.js b/app/models/Transaction.js index 58a07072..e48bd1ba 100644 --- a/app/models/Transaction.js +++ b/app/models/Transaction.js @@ -187,9 +187,12 @@ TransactionSchema.methods.queryInfo = function (next) { valueOut = valueOut.add(n); }); - that.info.valueIn = valueIn / util.COIN; that.info.valueOut = valueOut / util.COIN; - that.info.feeds = (valueIn - valueOut) / util.COIN; + + if ( !tx.isCoinBase() ) { + that.info.valueIn = valueIn / util.COIN; + that.info.feeds = (valueIn - valueOut) / util.COIN; + } that.info.size = b.length; diff --git a/test/model/transaction.js b/test/model/transaction.js index ee9f16cf..7c51ec71 100644 --- a/test/model/transaction.js +++ b/test/model/transaction.js @@ -30,6 +30,7 @@ describe('Transaction fromIdWithInfo', function(){ Transaction.fromIdWithInfo(test_txid, function(err, tx) { if (err) done(err); assert.equal(tx.txid, test_txid); + assert(!tx.info.isCoinBase); done(); }); }); @@ -43,6 +44,7 @@ describe('Transaction fromIdWithInfo', function(){ assert.equal(tx.info.valueOut, 1.66174); assert.equal(tx.info.feeds, 0.0005 ); assert.equal(tx.info.size, 226 ); + assert(!tx.info.isCoinBase); done(); }); }); @@ -53,6 +55,7 @@ describe('Transaction fromIdWithInfo', function(){ if (err) done(err); assert(tx.info.isCoinBase); assert.equal(tx.info.txid, test_txid2); + assert(!tx.info.feeds); done(); }); }); From 279a357f0eebe250bdbc8e4aefd96a9de475b652 Mon Sep 17 00:00:00 2001 From: Mario Colque Date: Thu, 9 Jan 2014 18:36:20 -0300 Subject: [PATCH 13/25] Added pagination by date to blocklist page --- app/controllers/blocks.js | 44 ++++++++++++++++++++++++--------- public/js/controllers/blocks.js | 7 +++--- public/views/blocks/list.html | 11 ++++++++- 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/app/controllers/blocks.js b/app/controllers/blocks.js index 53759402..5dfa632f 100644 --- a/app/controllers/blocks.js +++ b/app/controllers/blocks.js @@ -48,28 +48,50 @@ exports.last_blocks = function(req, res) { * List of blocks by date */ exports.list = function(req, res) { - var findParam = {}; + //helper to convert timestamps to yyyy-mm-dd format + var formatTimestamp = function (date) { + var yyyy = date.getUTCFullYear().toString(); + var mm = (date.getUTCMonth() + 1).toString(); // getMonth() is zero-based + var dd = date.getUTCDate().toString(); + return yyyy + '-' + (mm[1] ? mm : '0' + mm[0]) + '-' + (dd[1] ? dd : '0' + dd[0]); //padding + }; + + var dateStr; if (req.query.blockDate) { - var gte = Math.round((new Date(req.query.blockDate)).getTime() / 1000); - var lte = gte + 86400; - - findParam = { time: { - '$gte': gte, - '$lte': lte - }}; + dateStr = req.query.blockDate; + } else { + dateStr = formatTimestamp(new Date()); } + var gte = Math.round((new Date(dateStr)).getTime() / 1000); + + //pagination + var lte = gte + 86400; + var prev = formatTimestamp(new Date((gte - 86400) * 1000)); + var next = formatTimestamp(new Date(lte * 1000)); + Block - .find(findParam) - .limit(5) + .find({ + time: { + '$gte': gte, + '$lte': lte + } + }) .exec(function(err, blocks) { if (err) { res.render('error', { status: 500 }); } else { - res.jsonp(blocks); + res.jsonp({ + blocks: blocks, + pagination: { + next: next, + prev: prev, + current: dateStr + } + }); } }); }; diff --git a/public/js/controllers/blocks.js b/public/js/controllers/blocks.js index 002aea0e..7bb5c80b 100644 --- a/public/js/controllers/blocks.js +++ b/public/js/controllers/blocks.js @@ -4,10 +4,11 @@ angular.module('mystery.blocks').controller('BlocksController', ['$scope', '$rou $scope.global = Global; $scope.list = function() { - Blocks.query({ + Blocks.get({ blockDate: $routeParams.blockDate - }, function(blocks) { - $scope.blocks = blocks; + }, function(res) { + $scope.blocks = res.blocks; + $scope.pagination = res.pagination; }); }; diff --git a/public/views/blocks/list.html b/public/views/blocks/list.html index 656793fe..042810ef 100644 --- a/public/views/blocks/list.html +++ b/public/views/blocks/list.html @@ -1,6 +1,15 @@
From c41446b1318801816428550232d6950da3e975e8 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Thu, 9 Jan 2014 19:49:48 -0300 Subject: [PATCH 14/25] Enhacements in gruntfile --- Gruntfile.js | 29 ++++++++++++++++++----------- app/models/Transaction.js | 1 - config/env/test.js | 15 +++++++++++---- test/model/block.js | 4 ++-- 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index ab534a16..bd6d921e 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,6 +1,16 @@ 'use strict'; 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'); + // Project Configuration grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), @@ -29,6 +39,11 @@ module.exports = function(grunt) { options: { livereload: true } + }, + test: { + // we monitor only app/models/* because we have test for models only now + files: ['test/**/*.js', 'test/*.js','app/models/*.js'], + tasks: ['test'], } }, jshint: { @@ -43,7 +58,7 @@ module.exports = function(grunt) { options: { reporter: 'spec', }, - src: ['test/*.js'] + src: ['test/**/*.js'], }, nodemon: { @@ -51,9 +66,9 @@ module.exports = function(grunt) { options: { file: 'server.js', args: [], - ignoredFiles: ['public/**'], + ignoredFiles: ['public/**', 'test/**'], watchedExtensions: ['js'], - nodeArgs: ['--debug'], + // nodeArgs: ['--debug'], delayTime: 1, env: { PORT: 3000 @@ -75,14 +90,6 @@ 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'); - //Making grunt default to force in order not to break the project. grunt.option('force', true); diff --git a/app/models/Transaction.js b/app/models/Transaction.js index e48bd1ba..e80ab5be 100644 --- a/app/models/Transaction.js +++ b/app/models/Transaction.js @@ -181,7 +181,6 @@ TransactionSchema.methods.queryInfo = function (next) { }); } - tx.outs.forEach( function(i) { var n = util.valueToBigInt(i.v).toNumber(); valueOut = valueOut.add(n); diff --git a/config/env/test.js b/config/env/test.js index dabf6021..902efe9d 100755 --- a/config/env/test.js +++ b/config/env/test.js @@ -1,9 +1,16 @@ 'use strict'; module.exports = { - db: "mongodb://localhost/mystery-test", - port: 3001, + db: "mongodb://localhost/mystery-dev", app: { name: "Mystery - Test" - } -} \ No newline at end of file + }, + bitcoind: { + user: 'mystery', + pass: 'real_mystery', + protocol: 'http', + host: process.env.BITCOIND_HOST || '127.0.0.1', + port: process.env.BITCOIND_PORT || '8332', + }, + network: 'testnet', +} diff --git a/test/model/block.js b/test/model/block.js index 7fa2a302..1f4a798d 100644 --- a/test/model/block.js +++ b/test/model/block.js @@ -26,10 +26,9 @@ describe('Block fromHashWithInfo', function(){ done(); }); + it('should poll block\'s info from mongoose', function(done) { -console.log('asdasd'); var block2 = Block.fromHashWithInfo(TESTING_BLOCK, function(err, b2) { -console.log('333'); if (err) done(err); assert.equal(b2.hash, TESTING_BLOCK); @@ -37,6 +36,7 @@ console.log('333'); }); }); + it('should poll block\'s info from bitcoind', function(done) { var block2 = Block.fromHashWithInfo(TESTING_BLOCK, function(err, b2) { if (err) done(err); From 507de91fe50e5101345f821cb314532c9e028dd2 Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Fri, 10 Jan 2014 01:55:47 -0300 Subject: [PATCH 15/25] Transaction Page: look and feel. Parser and show data from API --- public/views/transaction.html | 121 ++++++++++++++++++++++++++-------- 1 file changed, 95 insertions(+), 26 deletions(-) diff --git a/public/views/transaction.html b/public/views/transaction.html index b5c519bd..e37226e8 100644 --- a/public/views/transaction.html +++ b/public/views/transaction.html @@ -1,32 +1,101 @@
-
    -
  • {{tx.txid}}
  • -
  • VIN -
      -
    • coinbase: {{vin.coinbase}}
    • -
    • sequence: {{vin.sequence}}
    • -
    • txid: {{vin.txid}}
    • -
    • vout: {{vin.vout}}
    • -
    -
  • -
  • VOUT -
      -
    • value: {{vout.value}}
    • -
    • n: {{vout.n}}
    • -
    • addresses: {{vin.scriptPubKey}} -
        -
      • address: {{addr}}
      • + +
+ + + + + + + + + + + + + + + + + + + +
Input Output
+ +
+ No Inputs (Newly Generated isCoinBasens) +
+
  +
+ - - - -
  • Blockhash: {{tx.blockhash}}
  • -
  • Confirmations: {{tx.confirmations}}
  • -
  • Time {{tx.time}}
  • -
  • Bloctime {{tx.blocktime}}
  • - +
    +
    + + +
    + +
    +
    +
    +
    +

    Summary

    +
    +
    + + + + + + + + + + + + + + + +
    Size{{tx.size}} (bytes)
    Received Time{{tx.time * 1000|date:'medium'}}
    Reward From BlockNeed height to show (it links to block page)
    +
    +
    +
    +
    +
    +
    +

    Inputs and Outputs

    +
    +
    + + + + + + + + + + + + + + + +
    Total Input{{tx.valueIn}} BTC
    Total Output{{tx.valueOut}} BTC
    Fees{{tx.feeds}} BTC
    +
    +
    +
    +
    From 145a7208a0d913ff96cbfb0f8838a1e48b9185b6 Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Fri, 10 Jan 2014 02:14:56 -0300 Subject: [PATCH 16/25] completed readme.md for api prerequisites --- README.md | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index ca751e31..9127bf9d 100644 --- a/README.md +++ b/README.md @@ -45,26 +45,34 @@ $ npm install -g bower http://localhost:3000 - - - - -## 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 - -check utils/sync.js --help for options. - - ## API A REST API is provided at /api. The entry points are: +### Prerequisites + Get bitcore from github repository: + + $ git clone https://github.com/bitpay/bitcore.git + + $ cd bitcore + + $ npm install + + Then create a symbolic link from this to your mystery repository. We need to + use bitcore from github, not with npm for now: + + $ cd mystery/node_modules + + $ rm -R bitcore + + $ ln -s /bitcore + + Run sync from mystery repository (to save blocks in MongoDB): + + $ utils/sync.js + + Check utils/sync.js --help for options. + ### Blocks ``` /api/block/[:hash] From e10e5fa2c0673fbcbcd716b9b44687d2e8a06059 Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Fri, 10 Jan 2014 02:22:06 -0300 Subject: [PATCH 17/25] fix link back to blockpage --- public/views/transaction.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/views/transaction.html b/public/views/transaction.html index e37226e8..c047b443 100644 --- a/public/views/transaction.html +++ b/public/views/transaction.html @@ -64,7 +64,7 @@ Reward From Block - Need height to show (it links to block page) + Need height to show (it links to block page) From 63dfe42ce8a18ffcc40d94c9725cdc0e7e3f24e1 Mon Sep 17 00:00:00 2001 From: Mario Colque Date: Fri, 10 Jan 2014 09:36:09 -0300 Subject: [PATCH 18/25] date style fixed --- public/views/blocks/list.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/views/blocks/list.html b/public/views/blocks/list.html index 042810ef..d8315692 100644 --- a/public/views/blocks/list.html +++ b/public/views/blocks/list.html @@ -19,7 +19,7 @@ {{block.hash}} - {{block.time}} + {{block.time * 1000 | date:'medium'}} From f2917c51ca66711dc2943d8c3457defbd55ccd03 Mon Sep 17 00:00:00 2001 From: Mario Colque Date: Fri, 10 Jan 2014 09:37:18 -0300 Subject: [PATCH 19/25] added new route for address page --- public/js/config.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/public/js/config.js b/public/js/config.js index 905cd7f8..c1761605 100755 --- a/public/js/config.js +++ b/public/js/config.js @@ -19,6 +19,9 @@ angular.module('mystery').config(['$routeProvider', when('/blocks-date/:blockDate', { templateUrl: 'views/blocks/list.html' }). + when('/address/:address', { + templateUrl: 'views/address.html' + }). otherwise({ redirectTo: '/' }); From 9db404c7f2c21042526c99ecdbec8fdbcb181168 Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Fri, 10 Jan 2014 10:03:48 -0300 Subject: [PATCH 20/25] Prepared BlockPage (look&feel) for getting info by API --- public/css/common.css | 7 +- public/views/block.html | 161 +++++++++++++++++++++++++--------------- 2 files changed, 107 insertions(+), 61 deletions(-) diff --git a/public/css/common.css b/public/css/common.css index 7ca093ad..396601a7 100644 --- a/public/css/common.css +++ b/public/css/common.css @@ -40,6 +40,11 @@ body { padding-right: 15px; } -code { +.code { font-size: 80%; } + +.address { + font-size: 10px; +} + diff --git a/public/views/block.html b/public/views/block.html index 1c89df8e..61534fca 100644 --- a/public/views/block.html +++ b/public/views/block.html @@ -2,72 +2,113 @@ - -

    Summary

    -
    -
    Number Of Transactions
    -
    --
    -
    Output Total
    -
    --
    -
    Estimated Transaction Volume
    -
    --
    -
    Transaction Fees
    -
    --
    -
    Height
    -
    {{block.height}}
    -
    Timestamp
    -
    {{block.time}}
    -
    Received Time
    -
    {{block.time}}
    -
    Relayed By
    -
    --
    -
    Difficulty
    -
    {{block.difficulty}}
    -
    Bits
    -
    {{block.bits}}
    -
    Size
    -
    {{block.size}}
    -
    Version
    -
    {{block.version}}
    -
    Nonce
    -
    {{block.nonce}}
    -
    - -

    Hashes

    - - - - - - - - - - - - - - - - - - - - - - - -
    Hashes 
    Hash{{block.hash}}
    Previous Block{{block.previousblockhash}}
    Next Block(s){{block.nextblockhash}}
    Merkle Root{{block.merkleroot}}
    - + +
    +
    +
    +
    +

    Summary

    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Number Of Transactions--
    Output Total--
    Estimated Transaction Volume--
    Transaction Fees--
    Height{{block.height}}
    Timestamp{{block.time * 1000 | date:'medium'}}
    Received Time-- +
    Relayed By--
    Difficulty{{block.difficulty}}
    Bits{{block.bits}}
    Size{{block.size}}
    Version{{block.version}}
    Nonce{{block.nonce}}
    +
    +
    +
    +
    +
    +
    +

    Hashes

    +
    +
    + + + + + + + + + + + + + + + + + + + +
    Hash{{block.hash}}
    Previous Block{{block.previousblockhash}}
    Next Block{{block.nextblockhash}}
    Merkle Root{{block.merkleroot}}
    +
    +
    +
    +
    +

    Transactions

    - - - + + +
    Hash
    {{tx}}
    {{tx}}
    From 8d8a1c256b8977cf86ee25e07f1141f8d73c1e85 Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Fri, 10 Jan 2014 10:25:16 -0300 Subject: [PATCH 21/25] fix text in block and transaction page --- public/views/block.html | 2 +- public/views/transaction.html | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/public/views/block.html b/public/views/block.html index 61534fca..98d76ac9 100644 --- a/public/views/block.html +++ b/public/views/block.html @@ -100,7 +100,7 @@ -

    Transactions

    +

    Transactions Transactions contained within this block

    diff --git a/public/views/transaction.html b/public/views/transaction.html index c047b443..5c55a50f 100644 --- a/public/views/transaction.html +++ b/public/views/transaction.html @@ -1,12 +1,15 @@
    +
    + {{tx.txid}} +
    +
    Hash
    From 67857abcc7fc79c7a0302b08c5fa5896b9b78c1b Mon Sep 17 00:00:00 2001 From: Gustavo Cortez Date: Fri, 10 Jan 2014 10:46:09 -0300 Subject: [PATCH 22/25] Cleaning homepage for now. It does not get any values from API, only shows a link to blocks list. --- app/controllers/blocks.js | 15 --------------- config/routes.js | 2 -- public/js/controllers/index.js | 6 +----- public/js/services/index.js | 2 +- public/views/index.html | 19 +++++-------------- 5 files changed, 7 insertions(+), 37 deletions(-) diff --git a/app/controllers/blocks.js b/app/controllers/blocks.js index 5dfa632f..5381ec04 100644 --- a/app/controllers/blocks.js +++ b/app/controllers/blocks.js @@ -29,21 +29,6 @@ exports.show = function(req, res) { res.jsonp(req.block); }; -/** - * List of blocks at HomePage - */ -exports.last_blocks = function(req, res) { - Block.find().sort({time:-1}).limit(7).exec(function(err, blocks) { - if (err) { - res.render('error', { - status: 500 - }); - } else { - res.jsonp(blocks); - } - }); -}; - /** * List of blocks by date */ diff --git a/config/routes.js b/config/routes.js index f24ac7d0..83c7eb3c 100644 --- a/config/routes.js +++ b/config/routes.js @@ -14,8 +14,6 @@ module.exports = function(app) { app.get('/api/block/:blockHash', blocks.show); app.param('blockHash', blocks.block); - app.get('/last_blocks', blocks.last_blocks); - var transactions = require('../app/controllers/transactions'); app.get('/api/tx/:txid', transactions.show); diff --git a/public/js/controllers/index.js b/public/js/controllers/index.js index bec0f0ad..60435269 100755 --- a/public/js/controllers/index.js +++ b/public/js/controllers/index.js @@ -2,9 +2,5 @@ angular.module('mystery.system').controller('IndexController', ['$scope', 'Global', 'Index', function ($scope, Global, Index) { $scope.global = Global; - $scope.last_blocks = function() { - Index.query(function(blocks) { - $scope.blocks = blocks; - }); - }; + $scope.index = Index; }]); diff --git a/public/js/services/index.js b/public/js/services/index.js index f961642e..08cb3ffa 100644 --- a/public/js/services/index.js +++ b/public/js/services/index.js @@ -1,5 +1,5 @@ 'use strict'; angular.module('mystery.index').factory('Index', ['$resource', function($resource) { - return $resource('/last_blocks'); + return $resource; }]); diff --git a/public/views/index.html b/public/views/index.html index 97d4c36a..469172a2 100644 --- a/public/views/index.html +++ b/public/views/index.html @@ -1,17 +1,8 @@
    -
    - - - - - - - - - - -
    HashTime
    {{block.hash}}{{block.time | date:'short'}}
    + From a774a711b34ef419cb5fc8c7c8fff2a0b6e3f8d9 Mon Sep 17 00:00:00 2001 From: Mario Colque Date: Fri, 10 Jan 2014 11:36:16 -0300 Subject: [PATCH 23/25] added angular-qrcode --- app/views/includes/foot.jade | 3 +++ bower.json | 5 +++-- public/js/app.js | 3 ++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/views/includes/foot.jade b/app/views/includes/foot.jade index ad487576..2b10e086 100755 --- a/app/views/includes/foot.jade +++ b/app/views/includes/foot.jade @@ -10,6 +10,8 @@ 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') +script(type='text/javascript', src='/lib/qrcode-generator/js/qrcode.js') +script(type='text/javascript', src='/lib/angular-qrcode/qrcode.js') //Angular UI script(type='text/javascript', src='/lib/angular-bootstrap/ui-bootstrap.js') @@ -33,4 +35,5 @@ 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/controllers/transactions.js') +script(type='text/javascript', src='/js/controllers/address.js') script(type='text/javascript', src='/js/init.js') diff --git a/bower.json b/bower.json index 46be4c59..60f6edbd 100644 --- a/bower.json +++ b/bower.json @@ -9,6 +9,7 @@ "angular-route": "latest", "bootstrap": "3.0.3", "angular-bootstrap": "0.9.0", - "angular-ui-utils": "0.1.0" + "angular-ui-utils": "0.1.0", + "angular-qrcode": "latest" } -} \ No newline at end of file +} diff --git a/public/js/app.js b/public/js/app.js index ca50d772..cfc1f8cf 100755 --- a/public/js/app.js +++ b/public/js/app.js @@ -1,8 +1,9 @@ 'use strict'; -angular.module('mystery', ['ngCookies', 'ngResource', 'ngRoute', 'ui.bootstrap', 'ui.route', 'mystery.system', 'mystery.index', 'mystery.blocks', 'mystery.transactions']); +angular.module('mystery', ['ngCookies', 'ngResource', 'ngRoute', 'ui.bootstrap', 'ui.route', 'mystery.system', 'mystery.index', 'mystery.blocks', 'mystery.transactions', 'monospaced.qrcode', 'mystery.address']); angular.module('mystery.system', []); angular.module('mystery.index', []); angular.module('mystery.blocks', []); angular.module('mystery.transactions', []); +angular.module('mystery.address', []); From 6d44c9b53ae6b88005c62beedca6ae1a8bea5f7c Mon Sep 17 00:00:00 2001 From: Mario Colque Date: Fri, 10 Jan 2014 11:36:43 -0300 Subject: [PATCH 24/25] added new template and controller for address page --- public/js/controllers/address.js | 20 +++++++++++ public/views/address.html | 60 ++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 public/js/controllers/address.js create mode 100644 public/views/address.html diff --git a/public/js/controllers/address.js b/public/js/controllers/address.js new file mode 100644 index 00000000..e921d983 --- /dev/null +++ b/public/js/controllers/address.js @@ -0,0 +1,20 @@ +'use strict'; + +angular.module('mystery.address').controller('AddressController', ['$scope', function ($scope) { + + //example data + $scope.address = '1JmTTDcksW7A6GN7JnxuXkMAXsVN9zmgm1'; + $scope.hash160 = '77ad7d08aaa9cf489ea4e468eaeb892b85f71e27'; + $scope.transactions = [ + { + hash: '49a1d01759690476dbeec4a8efd969c09c6d4269ea2d88f4d9d4f098f021413c', + time: 1234123445, + amount: 0.3 + }, + { + hash: 'cce948b422a4d485900fb82e64458720eb89f545af3f07ddf7d18660f9f881e9', + time: 1234123445, + amount: 0.1 + } + ]; +}]); diff --git a/public/views/address.html b/public/views/address.html new file mode 100644 index 00000000..45a01495 --- /dev/null +++ b/public/views/address.html @@ -0,0 +1,60 @@ +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + +
    Address{{address}}
    Hash160{{hash160}}
    Total Output1 BTC
    Total Input0.2 BTC
    Current balance10.2 BTC
    +
    +
    + +
    +
    +

    + Transactions + transactions this address relates to +

    + + + + + + + + + + + + + + + + +
    Transaction HashDatetimeTransacted amount
    {{transaction.hash}}{{transaction.time | date:'medium'}}{{transaction.amount}} BTC
    +
    +
    From 2bf3fd8a1308973bf8a6aec3ebd2ff3a4cc88f89 Mon Sep 17 00:00:00 2001 From: Mario Colque Date: Fri, 10 Jan 2014 11:38:51 -0300 Subject: [PATCH 25/25] BigNum module name fixed --- app/models/Transaction.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/models/Transaction.js b/app/models/Transaction.js index e80ab5be..64007892 100644 --- a/app/models/Transaction.js +++ b/app/models/Transaction.js @@ -11,9 +11,9 @@ var mongoose = require('mongoose'), Address = require('bitcore/Address').class(), networks = require('bitcore/networks'), util = require('bitcore/util/util'), - bignum = require('BigNum'), + bignum = require('bignum'), config = require('../../config/config'); - + /** */ @@ -48,7 +48,7 @@ TransactionSchema.statics.fromId = function(txid, cb) { TransactionSchema.statics.fromIdWithInfo = function(txid, cb) { // TODO Should we go to mongoDB first? Now, no extra information is stored at mongo. - + this.fromId(txid, function(err, tx) { if (err) return cb(err);