diff --git a/Gruntfile.js b/Gruntfile.js index a386491..715c647 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -40,11 +40,11 @@ module.exports = function(grunt) { 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'], - } +// test: { +// files: ['test/**/*.js', 'test/*.js','app/models/*.js'], +// tasks: ['test'], +// } }, jshint: { all: { diff --git a/app/controllers/addresses.js b/app/controllers/addresses.js new file mode 100644 index 0000000..e13000c --- /dev/null +++ b/app/controllers/addresses.js @@ -0,0 +1,37 @@ +'use strict'; + +/** + * Module dependencies. + */ + +var Address = require('../models/Address'); + + +/** + * Find block by hash ... + */ +exports.address = function(req, res, next, addr) { + var a = Address.new(addr); + + a.update(function(err) { + if (err && !a.totalReceivedSat) { + console.log(err); + res.status(404).send('Invalid address'); + return next(); + } + + req.address = a; + return next(); + }); +}; + + +/** + * Show block + */ +exports.show = function(req, res) { + if (req.address) { + res.jsonp(req.address); + } +}; + diff --git a/app/controllers/blocks.js b/app/controllers/blocks.js index 5381ec0..21f82d0 100644 --- a/app/controllers/blocks.js +++ b/app/controllers/blocks.js @@ -14,10 +14,14 @@ var mongoose = require('mongoose'), */ exports.block = function(req, res, next, hash) { Block.fromHashWithInfo(hash, function(err, block) { - if (err) return next(err); - if (!block) return next(new Error('Failed to load block ' + hash)); + if (err && !block) { + console.log(err); + res.status(404).send('Not found'); + return next(); + } + req.block = block.info; - next(); + return next(); }); }; @@ -26,7 +30,9 @@ exports.block = function(req, res, next, hash) { * Show block */ exports.show = function(req, res) { - res.jsonp(req.block); + if (req.block) { + res.jsonp(req.block); + } }; /** diff --git a/app/models/Address.js b/app/models/Address.js index ef8f319..0541488 100644 --- a/app/models/Address.js +++ b/app/models/Address.js @@ -4,16 +4,12 @@ require('classtool'); function spec() { - var util = require('util'); - var RpcClient = require('bitcore/RpcClient').class(); - var networks = require('bitcore/networks'); var async = require('async'); - var Transaction = require('./Transaction'); var TransactionItem = require('./TransactionItem'); - var config = require('../../config/config'); + var BitcoreAddress = require('bitcore/Address').class(); + var BitcoreUtil = require('bitcore/util/util'); - function Address(addrStr,cb) { - this.addrStr = addrStr; + function Address(addrStr) { this.balanceSat = 0; this.totalReceivedSat = 0; this.totalSentSat = 0; @@ -21,38 +17,58 @@ function spec() { // TODO store only txids? +index? +all? this.transactions = []; + + var a = new BitcoreAddress(addrStr); + try { + a.validate(); + this.addrStr = addrStr; + } catch(e){ + } } + + Address.prototype.__defineGetter__('balance', function(){ + +console.log('#################### '+this.balanceSat); + + + return this.balanceSat / BitcoreUtil.COIN; + }); + Address.prototype.update = function(next) { + if (! this.addrStr) { + return next(new Error('Invalid or undefined address string')); + } + var that = this; async.series([ // TODO TXout! //T function (cb) { - TransactionItem.find({addr:that.addrStr}, function(err,txItems){ - if (err) return cb(err); + TransactionItem.find({addr:that.addrStr}, function(err,txItems){ + if (err) return cb(err); - txItems.forEach(function(txItem){ + txItems.forEach(function(txItem){ -console.log(txItem.txid + ' : ' + txItem.value_sat); - that.txApperances +=1; - that.balanceSat += txItem.value_sat; + // console.log(txItem.txid + ' : ' + txItem.value_sat); + that.txApperances +=1; + that.balanceSat += txItem.value_sat; - that.transactions.push(txItem.txid); + that.transactions.push(txItem.txid); - if (txItem.value_sat > 0) - that.totalSentSat += txItem.value_sat; - else - that.totalReceivedSat += Math.abs(txItem.value_sat); + if (txItem.value_sat > 0) + that.totalSentSat += txItem.value_sat; + else + that.totalReceivedSat += Math.abs(txItem.value_sat); + }); + return cb(); }); - return cb(); - }) - } + } ], function (err) { return next(err); }); - } + }; return Address; } diff --git a/app/models/Transaction.js b/app/models/Transaction.js index 7858b35..29b0499 100644 --- a/app/models/Transaction.js +++ b/app/models/Transaction.js @@ -58,32 +58,31 @@ TransactionSchema.statics.fromId = function(txid, cb) { TransactionSchema.statics.fromIdWithInfo = function(txid, cb) { - var that = this; + var That = this; this.fromId(txid, function(err, tx) { if (err) return cb(err); - if (!tx) { - - return cb(new Error('TX not found')); - + if (!tx) { // No in mongo...but maybe in bitcoind... lets query it -/* var tx = new that(); + tx = new That(); tx.txid = txid; - - tx.queryInfo(function(err, txInfo) { + tx.queryInfo(function(err, txInfo) { - if (!txInfo) return cb(new Error('TX not found')); + if (!txInfo) + return cb(new Error('TX not found1')); - tx.save(function(err) { -console.log('asdadsads'); - return cb(err,tx); + tx.save(function(err) { + return cb(err,tx); }); }); -*/ } - - tx.queryInfo(function(err) { return cb(err,tx); } ); + } + else { + tx.queryInfo(function(err) { + return cb(err,tx); + }); + } }); }; @@ -113,8 +112,10 @@ TransactionSchema.statics.explodeTransactionItems = function(txid, cb) { this.fromIdWithInfo(txid, function(err, t) { if (err || !t) return cb(err); - var index=0; - t.info.vin.forEach(function(i){ i.n = index++}); + var index = 0; + t.info.vin.forEach( function(i){ + i.n = index++; + }); async.each(t.info.vin, function(i, next_in) { if (i.addr && i.value) { @@ -130,9 +131,9 @@ TransactionSchema.statics.explodeTransactionItems = function(txid, cb) { } else { if ( !i.coinbase ) { - console.log ("TX: %s,%d could not parse INPUT", t.txid, i.n); + console.log ('TX: %s,%d could not parse INPUT', t.txid, i.n); } - return next_in(); + return next_in(); } }, function (err) { @@ -142,10 +143,7 @@ TransactionSchema.statics.explodeTransactionItems = function(txid, cb) { /* * TODO Support multisigs */ - if (o.value && o.scriptPubKey - && o.scriptPubKey.addresses - && o.scriptPubKey.addresses[0] - ) { + if (o.value && o.scriptPubKey && o.scriptPubKey.addresses && o.scriptPubKey.addresses[0]) { //console.log("Creating OUT %s %d", o.scriptPubKey.addresses[0], o.valueSat); TransactionItem.create({ txid : t.txid, @@ -156,8 +154,8 @@ TransactionSchema.statics.explodeTransactionItems = function(txid, cb) { }, next_out); } else { - console.log ("TX: %s,%d could not parse OUTPUT. Skipping... ", t.txid, o.n); - return next_out(); + console.log ('TX: %s,%d could not parse OUTPUT', t.txid, o.n); + return next_out(); } }, function (err) { @@ -206,7 +204,6 @@ TransactionSchema.methods.fillInputValues = function (tx, next) { // This is used for pay-to-pubkey transaction in which // the pubkey is not provided on the input var scriptPubKey = j.getScript(); - var txType = scriptPubKey.classify(); var hash = scriptPubKey.simpleOutHash(); if (hash) { var addr = new Address(network.addressPubkey, hash); @@ -273,18 +270,18 @@ TransactionSchema.methods.queryInfo = function (next) { that.info.vin[c].addr = addrStr; } else { - if (i.addrFromOutput) + if (i.addrFromOutput) that.info.vin[c].addr = i.addrFromOutput; } } else { - console.log("TX could not be parsed: %s,%d",txInfo.result.txid, c); + console.log('TX could not be parsed: %s,%d' ,txInfo.result.txid, c); } c++; }); } - var c = 0; + c=0; tx.outs.forEach( function(i) { var n = util.valueToBigInt(i.v).toNumber(); valueOut = valueOut.add(n); diff --git a/app/models/TransactionItem.js b/app/models/TransactionItem.js index bb7c4b9..5a04f84 100644 --- a/app/models/TransactionItem.js +++ b/app/models/TransactionItem.js @@ -41,7 +41,7 @@ TransactionItemSchema.statics.fromTxId = function(txid, cb) { var sa= a.value_sat < 0 ? -1 : 1; var sb= b.value_sat < 0 ? -1 : 1; - if (sa != sb) { + if (sa !== sb) { return sa-sb; } else { diff --git a/config/env/development.js b/config/env/development.js index 479553e..3439a60 100755 --- a/config/env/development.js +++ b/config/env/development.js @@ -6,7 +6,7 @@ module.exports = { name: "Mystery - Development" }, bitcoind: { - protocol: process.env.BITCOIND_USER || 'http', + protocol: process.env.BITCOIND_PROTO || 'http', user: process.env.BITCOIND_USER || 'mystery', pass: process.env.BITCOIND_PASS || 'real_mystery', host: process.env.BITCOIND_HOST || '127.0.0.1', diff --git a/config/env/test.js b/config/env/test.js index f668acf..dd7a70e 100755 --- a/config/env/test.js +++ b/config/env/test.js @@ -7,9 +7,9 @@ module.exports = { }, port: '3301', bitcoind: { - user: 'mystery', - pass: 'real_mystery', - protocol: 'http', + protocol: process.env.BITCOIND_PROTO || 'http', + user: process.env.BITCOIND_USER || 'mystery', + pass: process.env.BITCOIND_PASS || 'real_mystery', host: process.env.BITCOIND_HOST || '127.0.0.1', port: process.env.BITCOIND_PORT || '18332', }, diff --git a/config/routes.js b/config/routes.js index 83c7eb3..45bc4ad 100644 --- a/config/routes.js +++ b/config/routes.js @@ -19,4 +19,8 @@ module.exports = function(app) { app.param('txid', transactions.transaction); + var addresses = require('../app/controllers/addresses'); + app.get('/api/addr/:addr', addresses.show); + app.param('addr', addresses.address); + }; diff --git a/test/model/addr.js b/test/model/addr.js index b999200..2a59f61 100644 --- a/test/model/addr.js +++ b/test/model/addr.js @@ -6,7 +6,7 @@ var assert = require('assert'), fs = require('fs'), config = require('../../config/config'), - Address = require('../../app/models/Address'); + Address = require('../../app/models/Address').class(); mongoose= require('mongoose'), addrValid = JSON.parse(fs.readFileSync('test/model/addr.json')); @@ -30,8 +30,7 @@ describe('Address update', function(){ it('should retrieve the correct info for:' + v.addr, function(done) { this.timeout(5000); - var a = Address.new(v.addr); - + var a = new Address(v.addr); a.update(function(err) { if (err) done(err); diff --git a/test/model/addr.json b/test/model/addr.json index 716a62b..22f4255 100644 --- a/test/model/addr.json +++ b/test/model/addr.json @@ -1,10 +1,8 @@ [ { -"disabled":1, "addr": "mjRmkmYzvZN3cA3aBKJgYJ65epn3WCG84H" }, { -"disabled":1, "addr": "mp3Rzxx9s1A21SY3sjJ3CQoa2Xjph7e5eS", "balance": 0, "totalReceived": 50, @@ -16,6 +14,7 @@ "balance": 43.1 }, { +"disabled":1, "addr": "mzW2hdZN2um7WBvTDerdahKqRgj3md9C29", "balance": 910.39522682, "totalReceived": 910.39522682,