addr tx orderer by TS. keep unconfirmed balance. fix times in txs

This commit is contained in:
Matias Alejo Garcia 2014-02-12 19:27:29 -03:00
parent d561c191e7
commit a35fcc776d
10 changed files with 105 additions and 28 deletions

View File

@ -43,5 +43,8 @@ module.exports.broadcastAddressTx = function(address, tx) {
};
module.exports.broadcastSyncInfo = function(historicSync) {
if (ios) ios.sockets.in('sync').emit('status', historicSync);
if (ios) {
ios.sockets.in('sync').emit('status', historicSync);
}
};

View File

@ -13,6 +13,9 @@ function spec() {
this.balanceSat = 0;
this.totalReceivedSat = 0;
this.totalSentSat = 0;
this.unconfirmedBalanceSat = 0;
this.txApperances = 0;
// TODO store only txids? +index? +all?
@ -51,12 +54,25 @@ function spec() {
},
enumerable: 1,
});
Object.defineProperty(this, 'unconfirmedBalance', {
get: function() {
return parseFloat(this.unconfirmedBalanceSat) / parseFloat(BitcoreUtil.COIN);
},
set: function(i) {
this.unconfirmedBalanceSat = i * BitcoreUtil.COIN;
},
enumerable: 1,
});
}
Address.prototype.update = function(next) {
var self = this;
if (!self.addrStr) return next();
var txs = [];
var db = new TransactionDb();
async.series([
function (cb) {
@ -64,27 +80,50 @@ function spec() {
if (err) return cb(err);
txOut.forEach(function(txItem){
var v = txItem.value_sat;
txs.push({txid: txItem.txid, ts: txItem.ts});
self.txApperances += 1;
if (txItem.spendTxId) {
txs.push({txid: txItem.spendTxId, ts: txItem.spendTs});
self.txApperances += 1;
}
if (txItem.isConfirmed) {
var v = txItem.value_sat;
self.totalReceivedSat += v;
self.transactions.push(txItem.txid);
if (! txItem.spendTxId || !txItem.spendIsConfirmed) {
if (! txItem.spendTxId ) {
//unspend
self.balanceSat += v;
}
else if(!txItem.spendIsConfirmed) {
// unspent
self.balanceSat += v;
self.txApperances +=1;
self.unconfirmedBalanceSat -= v;
}
else {
// spent
self.totalSentSat += v;
self.transactions.push(txItem.spendTxId);
self.txApperances +=2;
}
}
else {
self.unconfirmedBalanceSat += v;
}
});
return cb();
});
},
], function (err) {
// sort input and outputs togheter
txs.sort(
function compare(a,b) {
if (a.ts < b.ts) return 1;
if (a.ts > b.ts) return -1;
return 0;
});
self.transactions = txs.map(function(i) { return i.txid; } );
return next(err);
});
};

View File

@ -104,13 +104,14 @@ function spec() {
HistoricSync.prototype.showProgress = function() {
var self = this;
if ( ( self.syncedBlocks + self.skippedBlocks) % self.step !== 1) return;
if ( self.status ==='syncing' &&
( self.syncedBlocks + self.skippedBlocks) % self.step !== 1) return;
if (self.error) {
p('ERROR: ' + self.error);
}
else {
self.syncPercentage = parseFloat(100 * (self.syncedBlocks + self.skippedBlocks) / self.blockChainHeight).toFixed(3);
self.syncPercentage = parseFloat(100 * self.syncedBlocks / self.blockChainHeight).toFixed(3);
if (self.syncPercentage > 100) self.syncPercentage = 100;
p(util.format('status: [%d%%] skipped: %d ', self.syncPercentage, self.skippedBlocks));
@ -193,7 +194,6 @@ function spec() {
(blockEnd && blockEnd === blockHash)) {
self.status = 'finished';
p('DONE. Found block: ', blockHash);
self.showProgress();
return cb(err);
}
@ -266,7 +266,6 @@ function spec() {
var self = this;
self.showProgress();
self.getBlockFromFile(function(err, blockInfo) {
if (err) {
self.setError(util.format('ERROR: @%s: %s [count: syncedBlocks: %d]',
@ -406,12 +405,14 @@ function spec() {
});
});
}, function(err) {
self.showProgress();
return next(err);
});
}
else {
self.type = 'from RPC calls';
self.getPrevNextBlock(start, end, scanOpts, function(err) {
self.showProgress();
return next(err);
});
}

View File

@ -69,7 +69,7 @@ function spec(b) {
});
};
TransactionDb.prototype._addSpendInfo = function(r, txid, index) {
TransactionDb.prototype._addSpendInfo = function(r, txid, index, ts) {
if (r.spendTxId) {
if (!r.multipleSpendAttempts) {
r.multipleSpendAttempts = [{
@ -85,6 +85,7 @@ function spec(b) {
else {
r.spendTxId = txid;
r.spendIndex = parseInt(index);
r.spendTs = parseInt(ts);
}
};
@ -123,7 +124,7 @@ function spec(b) {
assert(typeof j !== 'undefined','Spent could not be stored: tx ' + txid +
'spend in TX:' + k[2] + ',' + k[3]+ ' j:' + j);
self._addSpendInfo(ret[j], k[4], k[5]);
self._addSpendInfo(ret[j], k[4], k[5], data.value);
})
.on('error', function (err) {
return cb(err);
@ -144,7 +145,7 @@ function spec(b) {
db.createReadStream({start: k, end: k + '~'})
.on('data', function (data) {
var k = data.key.split('-');
self._addSpendInfo(info.vout[k[3]], k[4], k[5]);
self._addSpendInfo(info.vout[k[3]], k[4], k[5], data.value);
})
.on('error', function (err) {
return cb(err);
@ -162,6 +163,7 @@ function spec(b) {
var valueIn = 0;
var incompleteInputs = 0;
var ts;
async.eachLimit(info.vin, CONCURRENCY, function(i, c_in) {
self.fromTxIdN(i.txid, i.vout, function(err, ret) {
@ -203,6 +205,8 @@ function spec(b) {
i.doubleSpendTxID = null;
}
info.firstSeenTs = i.spendTs;
valueIn += i.valueSat;
return c_in();
});
@ -264,7 +268,7 @@ function spec(b) {
db.createReadStream({start: k, end: k + '~'})
.on('data', function (data) {
var k = data.key.split('-');
self._addSpendInfo(ret, k[4], k[5]);
self._addSpendInfo(ret, k[4], k[5], data.value);
})
.on('error', function (error) {
return cb(error);
@ -336,7 +340,7 @@ function spec(b) {
db.createReadStream({start: k, end: k + '~'})
.on('data', function (data) {
var k = data.key.split('-');
self._addSpendInfo(o, k[4], k[5]);
self._addSpendInfo(o, k[4], k[5], data.value);
})
.on('error', function (err) {
return e_c(err);
@ -461,12 +465,20 @@ function spec(b) {
var addr = o.scriptPubKey.addresses[0];
var sat = Math.round(o.value * util.COIN);
db.batch()
.put( OUTS_PREFIX + tx.txid + '-' + o.n, addr + ':' + sat)
.put( ADDR_PREFIX + addr + '-' + ts + '-' + tx.txid +
'-' + o.n, sat)
.write(next_out);
// existed?
db.get(OUTS_PREFIX + tx.txid + '-' + o.n, function (err,val) {
if (!val) {
db.batch()
.put( OUTS_PREFIX + tx.txid + '-' + o.n, addr + ':' + sat)
.put( ADDR_PREFIX + addr + '-' + ts + '-' + tx.txid +
'-' + o.n, sat)
.write(next_out);
}
else {
return next_out();
}
});
}
else {
//console.log ('WARN in TX: %s could not parse OUTPUT %d', tx.txid, o.n);

View File

@ -48,7 +48,10 @@ ScopedSocket.prototype.emit = function(event, data, callback) {
angular.module('insight.socket').factory('getSocket',
function($rootScope) {
var socket = io.connect();
var socket = io.connect(null, {
'reconnect': true,
'reconnection delay': 500,
});
return function(scope) {
var scopedSocket = new ScopedSocket(socket, $rootScope);
scope.$on('$routeChangeStart', function() {

View File

@ -26,6 +26,11 @@
<td class="small">Final Balance</td>
<td class="address ellipsis text-right">{{$root.currency.getConvertion(address.balance)}}</td>
</tr>
<tr>
<td class="small">Unconfirmed Tx Balance</td>
<td class="address ellipsis text-right">{{$root.currency.getConvertion(address.unconfirmedBalance)}}</td>
</tr>
<tr>
<td class="small">No. Transactions</td>
<td class="address ellipsis text-right">{{address.txApperances}}</td>

View File

@ -24,7 +24,7 @@
<ul class="nav navbar-nav navbar-right">
<li>
<div class="status" data-ng-controller="StatusController">
<a href="#" data-ng-init="getSync()">
<div data-ng-init="getSync()" class="pull-left">
<span class="t text-danger" data-ng-show="sync.error" tooltip="{{sync.error}}" tooltip-placement="bottom">
<span class="glyphicon glyphicon-warning-sign"></span>
ERROR
@ -33,8 +33,9 @@
<span class="glyphicon glyphicon-refresh icon-rotate"></span>
{{sync.status}} {{sync.syncPercentage}}%
</span>
<span class="t text-default" tooltip="Historic sync finished" tooltip-placement="bottom" data-ng-show="sync.status==='finished'"> On sync</span>
</a> &middot;
<span class="t text-default" tooltip="Historic sync finished" tooltip-placement="bottom" data-ng-show="sync.status==='finished'"> On sync </span>
</div>
&nbsp; &middot;
<span data-ng-init="getStatus('Info')">
<strong>Conn</strong> {{info.connections}}
</span> &middot;

View File

@ -21,8 +21,15 @@
</tr>
<tr>
<td><strong>Received Time </strong></td>
<td class="text-muted text-right">{{tx.time * 1000|date:'medium'}}</td>
<td data-ng-show="tx.firstSeenTs" class="text-muted text-right">{{tx.firstSeenTs * 1000|date:'medium'}}</td>
<td data-ng-show="!tx.firstSeenTs" class="text-muted text-right">N/A</td>
</tr>
<tr>
<td><strong>Mined Time </strong></td>
<td data-ng-show="tx.time" class="text-muted text-right">{{tx.time * 1000|date:'medium'}}</td>
<td data-ng-show="!tx.time" class="text-muted text-right">N/A</td>
</tr>
</tbody>
</table>
<div data-ng-include src="'/views/includes/currency.html'"></div>

View File

@ -6,7 +6,13 @@
<a class="txid" href="/tx/{{tx.txid}}">{{tx.txid}}</a>
</div>
</div>
<div class="col-xs-12 col-md-6 text-right" data-ng-show="tx.time">
<div class="col-xs-12 col-md-6 text-right" data-ng-show="tx.firstSeenTs">
first seen at
<time>{{tx.firstSeenTs * 1000 | date:'medium'}}</time>
</div>
<div class="col-xs-12 col-md-6 text-right" data-ng-show="tx.time && !tx.firstSeenTs">
mined at
<time>{{tx.time * 1000 | date:'medium'}}</time>
</div>
</div>

View File

@ -43,7 +43,7 @@
},
{
"addr": "mzW2hdZN2um7WBvTDerdahKqRgj3md9C29",
"txApperances": 2041,
"txApperances": 6049,
"balance": 1199.74393853,
"totalReceived": 1199.74393853,
"totalSent": 0