api working WIP
This commit is contained in:
parent
5a97c96d6e
commit
868f22cf2b
|
@ -40,11 +40,11 @@ module.exports = function(grunt) {
|
||||||
livereload: true
|
livereload: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
test: {
|
|
||||||
// we monitor only app/models/* because we have test for models only now
|
// we monitor only app/models/* because we have test for models only now
|
||||||
files: ['test/**/*.js', 'test/*.js','app/models/*.js'],
|
// test: {
|
||||||
tasks: ['test'],
|
// files: ['test/**/*.js', 'test/*.js','app/models/*.js'],
|
||||||
}
|
// tasks: ['test'],
|
||||||
|
// }
|
||||||
},
|
},
|
||||||
jshint: {
|
jshint: {
|
||||||
all: {
|
all: {
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -14,10 +14,14 @@ var mongoose = require('mongoose'),
|
||||||
*/
|
*/
|
||||||
exports.block = function(req, res, next, hash) {
|
exports.block = function(req, res, next, hash) {
|
||||||
Block.fromHashWithInfo(hash, function(err, block) {
|
Block.fromHashWithInfo(hash, function(err, block) {
|
||||||
if (err) return next(err);
|
if (err && !block) {
|
||||||
if (!block) return next(new Error('Failed to load block ' + hash));
|
console.log(err);
|
||||||
|
res.status(404).send('Not found');
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
req.block = block.info;
|
req.block = block.info;
|
||||||
next();
|
return next();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,7 +30,9 @@ exports.block = function(req, res, next, hash) {
|
||||||
* Show block
|
* Show block
|
||||||
*/
|
*/
|
||||||
exports.show = function(req, res) {
|
exports.show = function(req, res) {
|
||||||
res.jsonp(req.block);
|
if (req.block) {
|
||||||
|
res.jsonp(req.block);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,16 +4,12 @@ require('classtool');
|
||||||
|
|
||||||
|
|
||||||
function spec() {
|
function spec() {
|
||||||
var util = require('util');
|
|
||||||
var RpcClient = require('bitcore/RpcClient').class();
|
|
||||||
var networks = require('bitcore/networks');
|
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
var Transaction = require('./Transaction');
|
|
||||||
var TransactionItem = require('./TransactionItem');
|
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) {
|
function Address(addrStr) {
|
||||||
this.addrStr = addrStr;
|
|
||||||
this.balanceSat = 0;
|
this.balanceSat = 0;
|
||||||
this.totalReceivedSat = 0;
|
this.totalReceivedSat = 0;
|
||||||
this.totalSentSat = 0;
|
this.totalSentSat = 0;
|
||||||
|
@ -21,38 +17,58 @@ function spec() {
|
||||||
|
|
||||||
// TODO store only txids? +index? +all?
|
// TODO store only txids? +index? +all?
|
||||||
this.transactions = [];
|
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) {
|
Address.prototype.update = function(next) {
|
||||||
|
|
||||||
|
if (! this.addrStr) {
|
||||||
|
return next(new Error('Invalid or undefined address string'));
|
||||||
|
}
|
||||||
|
|
||||||
var that = this;
|
var that = this;
|
||||||
async.series([
|
async.series([
|
||||||
// TODO TXout!
|
// TODO TXout!
|
||||||
//T
|
//T
|
||||||
function (cb) {
|
function (cb) {
|
||||||
TransactionItem.find({addr:that.addrStr}, function(err,txItems){
|
TransactionItem.find({addr:that.addrStr}, function(err,txItems){
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
|
|
||||||
txItems.forEach(function(txItem){
|
txItems.forEach(function(txItem){
|
||||||
|
|
||||||
console.log(txItem.txid + ' : ' + txItem.value_sat);
|
// console.log(txItem.txid + ' : ' + txItem.value_sat);
|
||||||
that.txApperances +=1;
|
that.txApperances +=1;
|
||||||
that.balanceSat += txItem.value_sat;
|
that.balanceSat += txItem.value_sat;
|
||||||
|
|
||||||
that.transactions.push(txItem.txid);
|
that.transactions.push(txItem.txid);
|
||||||
|
|
||||||
if (txItem.value_sat > 0)
|
if (txItem.value_sat > 0)
|
||||||
that.totalSentSat += txItem.value_sat;
|
that.totalSentSat += txItem.value_sat;
|
||||||
else
|
else
|
||||||
that.totalReceivedSat += Math.abs(txItem.value_sat);
|
that.totalReceivedSat += Math.abs(txItem.value_sat);
|
||||||
|
});
|
||||||
|
return cb();
|
||||||
});
|
});
|
||||||
return cb();
|
}
|
||||||
})
|
|
||||||
}
|
|
||||||
], function (err) {
|
], function (err) {
|
||||||
return next(err);
|
return next(err);
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
return Address;
|
return Address;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,32 +58,31 @@ TransactionSchema.statics.fromId = function(txid, cb) {
|
||||||
|
|
||||||
|
|
||||||
TransactionSchema.statics.fromIdWithInfo = function(txid, cb) {
|
TransactionSchema.statics.fromIdWithInfo = function(txid, cb) {
|
||||||
var that = this;
|
var That = this;
|
||||||
|
|
||||||
this.fromId(txid, function(err, tx) {
|
this.fromId(txid, function(err, tx) {
|
||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
|
|
||||||
if (!tx) {
|
if (!tx) {
|
||||||
|
|
||||||
return cb(new Error('TX not found'));
|
|
||||||
|
|
||||||
// No in mongo...but maybe in bitcoind... lets query it
|
// No in mongo...but maybe in bitcoind... lets query it
|
||||||
/* var tx = new that();
|
tx = new That();
|
||||||
|
|
||||||
tx.txid = txid;
|
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) {
|
tx.save(function(err) {
|
||||||
console.log('asdadsads');
|
return cb(err,tx);
|
||||||
return cb(err,tx);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
*/ }
|
}
|
||||||
|
else {
|
||||||
tx.queryInfo(function(err) { return cb(err,tx); } );
|
tx.queryInfo(function(err) {
|
||||||
|
return cb(err,tx);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -113,8 +112,10 @@ TransactionSchema.statics.explodeTransactionItems = function(txid, cb) {
|
||||||
this.fromIdWithInfo(txid, function(err, t) {
|
this.fromIdWithInfo(txid, function(err, t) {
|
||||||
if (err || !t) return cb(err);
|
if (err || !t) return cb(err);
|
||||||
|
|
||||||
var index=0;
|
var index = 0;
|
||||||
t.info.vin.forEach(function(i){ i.n = index++});
|
t.info.vin.forEach( function(i){
|
||||||
|
i.n = index++;
|
||||||
|
});
|
||||||
|
|
||||||
async.each(t.info.vin, function(i, next_in) {
|
async.each(t.info.vin, function(i, next_in) {
|
||||||
if (i.addr && i.value) {
|
if (i.addr && i.value) {
|
||||||
|
@ -130,9 +131,9 @@ TransactionSchema.statics.explodeTransactionItems = function(txid, cb) {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ( !i.coinbase ) {
|
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) {
|
function (err) {
|
||||||
|
@ -142,10 +143,7 @@ TransactionSchema.statics.explodeTransactionItems = function(txid, cb) {
|
||||||
/*
|
/*
|
||||||
* TODO Support multisigs
|
* TODO Support multisigs
|
||||||
*/
|
*/
|
||||||
if (o.value && o.scriptPubKey
|
if (o.value && o.scriptPubKey && o.scriptPubKey.addresses && o.scriptPubKey.addresses[0]) {
|
||||||
&& o.scriptPubKey.addresses
|
|
||||||
&& o.scriptPubKey.addresses[0]
|
|
||||||
) {
|
|
||||||
//console.log("Creating OUT %s %d", o.scriptPubKey.addresses[0], o.valueSat);
|
//console.log("Creating OUT %s %d", o.scriptPubKey.addresses[0], o.valueSat);
|
||||||
TransactionItem.create({
|
TransactionItem.create({
|
||||||
txid : t.txid,
|
txid : t.txid,
|
||||||
|
@ -156,8 +154,8 @@ TransactionSchema.statics.explodeTransactionItems = function(txid, cb) {
|
||||||
}, next_out);
|
}, next_out);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log ("TX: %s,%d could not parse OUTPUT. Skipping... ", t.txid, o.n);
|
console.log ('TX: %s,%d could not parse OUTPUT', t.txid, o.n);
|
||||||
return next_out();
|
return next_out();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
function (err) {
|
function (err) {
|
||||||
|
@ -206,7 +204,6 @@ TransactionSchema.methods.fillInputValues = function (tx, next) {
|
||||||
// This is used for pay-to-pubkey transaction in which
|
// This is used for pay-to-pubkey transaction in which
|
||||||
// the pubkey is not provided on the input
|
// the pubkey is not provided on the input
|
||||||
var scriptPubKey = j.getScript();
|
var scriptPubKey = j.getScript();
|
||||||
var txType = scriptPubKey.classify();
|
|
||||||
var hash = scriptPubKey.simpleOutHash();
|
var hash = scriptPubKey.simpleOutHash();
|
||||||
if (hash) {
|
if (hash) {
|
||||||
var addr = new Address(network.addressPubkey, hash);
|
var addr = new Address(network.addressPubkey, hash);
|
||||||
|
@ -273,18 +270,18 @@ TransactionSchema.methods.queryInfo = function (next) {
|
||||||
that.info.vin[c].addr = addrStr;
|
that.info.vin[c].addr = addrStr;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (i.addrFromOutput)
|
if (i.addrFromOutput)
|
||||||
that.info.vin[c].addr = i.addrFromOutput;
|
that.info.vin[c].addr = i.addrFromOutput;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
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++;
|
c++;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var c = 0;
|
c=0;
|
||||||
tx.outs.forEach( function(i) {
|
tx.outs.forEach( function(i) {
|
||||||
var n = util.valueToBigInt(i.v).toNumber();
|
var n = util.valueToBigInt(i.v).toNumber();
|
||||||
valueOut = valueOut.add(n);
|
valueOut = valueOut.add(n);
|
||||||
|
|
|
@ -41,7 +41,7 @@ TransactionItemSchema.statics.fromTxId = function(txid, cb) {
|
||||||
var sa= a.value_sat < 0 ? -1 : 1;
|
var sa= a.value_sat < 0 ? -1 : 1;
|
||||||
var sb= b.value_sat < 0 ? -1 : 1;
|
var sb= b.value_sat < 0 ? -1 : 1;
|
||||||
|
|
||||||
if (sa != sb) {
|
if (sa !== sb) {
|
||||||
return sa-sb;
|
return sa-sb;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -6,7 +6,7 @@ module.exports = {
|
||||||
name: "Mystery - Development"
|
name: "Mystery - Development"
|
||||||
},
|
},
|
||||||
bitcoind: {
|
bitcoind: {
|
||||||
protocol: process.env.BITCOIND_USER || 'http',
|
protocol: process.env.BITCOIND_PROTO || 'http',
|
||||||
user: process.env.BITCOIND_USER || 'mystery',
|
user: process.env.BITCOIND_USER || 'mystery',
|
||||||
pass: process.env.BITCOIND_PASS || 'real_mystery',
|
pass: process.env.BITCOIND_PASS || 'real_mystery',
|
||||||
host: process.env.BITCOIND_HOST || '127.0.0.1',
|
host: process.env.BITCOIND_HOST || '127.0.0.1',
|
||||||
|
|
|
@ -7,9 +7,9 @@ module.exports = {
|
||||||
},
|
},
|
||||||
port: '3301',
|
port: '3301',
|
||||||
bitcoind: {
|
bitcoind: {
|
||||||
user: 'mystery',
|
protocol: process.env.BITCOIND_PROTO || 'http',
|
||||||
pass: 'real_mystery',
|
user: process.env.BITCOIND_USER || 'mystery',
|
||||||
protocol: 'http',
|
pass: process.env.BITCOIND_PASS || 'real_mystery',
|
||||||
host: process.env.BITCOIND_HOST || '127.0.0.1',
|
host: process.env.BITCOIND_HOST || '127.0.0.1',
|
||||||
port: process.env.BITCOIND_PORT || '18332',
|
port: process.env.BITCOIND_PORT || '18332',
|
||||||
},
|
},
|
||||||
|
|
|
@ -19,4 +19,8 @@ module.exports = function(app) {
|
||||||
|
|
||||||
app.param('txid', transactions.transaction);
|
app.param('txid', transactions.transaction);
|
||||||
|
|
||||||
|
var addresses = require('../app/controllers/addresses');
|
||||||
|
app.get('/api/addr/:addr', addresses.show);
|
||||||
|
app.param('addr', addresses.address);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,7 +6,7 @@ var
|
||||||
assert = require('assert'),
|
assert = require('assert'),
|
||||||
fs = require('fs'),
|
fs = require('fs'),
|
||||||
config = require('../../config/config'),
|
config = require('../../config/config'),
|
||||||
Address = require('../../app/models/Address');
|
Address = require('../../app/models/Address').class();
|
||||||
mongoose= require('mongoose'),
|
mongoose= require('mongoose'),
|
||||||
addrValid = JSON.parse(fs.readFileSync('test/model/addr.json'));
|
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) {
|
it('should retrieve the correct info for:' + v.addr, function(done) {
|
||||||
this.timeout(5000);
|
this.timeout(5000);
|
||||||
|
|
||||||
var a = Address.new(v.addr);
|
var a = new Address(v.addr);
|
||||||
|
|
||||||
|
|
||||||
a.update(function(err) {
|
a.update(function(err) {
|
||||||
if (err) done(err);
|
if (err) done(err);
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"disabled":1,
|
|
||||||
"addr": "mjRmkmYzvZN3cA3aBKJgYJ65epn3WCG84H"
|
"addr": "mjRmkmYzvZN3cA3aBKJgYJ65epn3WCG84H"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"disabled":1,
|
|
||||||
"addr": "mp3Rzxx9s1A21SY3sjJ3CQoa2Xjph7e5eS",
|
"addr": "mp3Rzxx9s1A21SY3sjJ3CQoa2Xjph7e5eS",
|
||||||
"balance": 0,
|
"balance": 0,
|
||||||
"totalReceived": 50,
|
"totalReceived": 50,
|
||||||
|
@ -16,6 +14,7 @@
|
||||||
"balance": 43.1
|
"balance": 43.1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"disabled":1,
|
||||||
"addr": "mzW2hdZN2um7WBvTDerdahKqRgj3md9C29",
|
"addr": "mzW2hdZN2um7WBvTDerdahKqRgj3md9C29",
|
||||||
"balance": 910.39522682,
|
"balance": 910.39522682,
|
||||||
"totalReceived": 910.39522682,
|
"totalReceived": 910.39522682,
|
||||||
|
|
Loading…
Reference in New Issue