test working with values stored in satoshis

This commit is contained in:
Matias Alejo Garcia 2014-01-13 15:29:19 -03:00
parent 1324d8c183
commit 5a97c96d6e
8 changed files with 124 additions and 58 deletions

View File

@ -14,9 +14,9 @@ function spec() {
function Address(addrStr,cb) {
this.addrStr = addrStr;
this.balance = null;
this.totalReceived = null;
this.totalSent = null;
this.balanceSat = 0;
this.totalReceivedSat = 0;
this.totalSentSat = 0;
this.txApperances = 0;
// TODO store only txids? +index? +all?
@ -35,16 +35,16 @@ function spec() {
txItems.forEach(function(txItem){
console.log(txItem.txid + ' : ' + txItem.value_sat);
that.txApperances +=1;
// TESTING
that.balance += txItem.value + 0.1;
that.balanceSat += txItem.value_sat;
that.transactions.push(txItem.txid);
if (txItem.value > 0)
that.totalSent += txItem.value;
if (txItem.value_sat > 0)
that.totalSentSat += txItem.value_sat;
else
that.totalReceived += Math.abs(txItem.value);
that.totalReceivedSat += Math.abs(txItem.value_sat);
});
return cb();
})

View File

@ -58,19 +58,36 @@ TransactionSchema.statics.fromId = function(txid, cb) {
TransactionSchema.statics.fromIdWithInfo = function(txid, cb) {
var that = this;
// 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);
if (!tx) { return cb(new Error('TX not found')); }
if (!tx) {
return cb(new Error('TX not found'));
// No in mongo...but maybe in bitcoind... lets query it
/* var tx = new that();
tx.txid = txid;
tx.queryInfo(function(err, txInfo) {
if (!txInfo) return cb(new Error('TX not found'));
tx.save(function(err) {
console.log('asdadsads');
return cb(err,tx);
});
});
*/ }
tx.queryInfo(function(err) { return cb(err,tx); } );
});
};
TransactionSchema.statics.createFromArray = function(txs, next) {
var that = this;
if (!txs) return next();
@ -97,23 +114,23 @@ TransactionSchema.statics.explodeTransactionItems = function(txid, cb) {
if (err || !t) return cb(err);
var index=0;
t.info.vin.forEach(function(i){ i.n = index++});
async.each(t.info.vin, function(i, next_in) {
/*
* TODO Support multisigs???
*/
if (i.addr && i.value) {
//console.log("Creating IN %s %d", i.addr, i.valueSat);
TransactionItem.create({
txid : t.txid,
value : -1 * i.value,
value_sat : -1 * i.valueSat,
addr : i.addr,
index : index++,
index : i.n,
ts : t.info.time,
}, next_in);
}
else {
if ( !i.coinbase ) {
console.log ("TX: %s seems to be multisig IN. Skipping... ", t.txid);
console.log ("TX: %s,%d could not parse INPUT", t.txid, i.n);
}
return next_in();
}
@ -129,15 +146,17 @@ TransactionSchema.statics.explodeTransactionItems = function(txid, cb) {
&& o.scriptPubKey.addresses
&& o.scriptPubKey.addresses[0]
) {
//console.log("Creating OUT %s %d", o.scriptPubKey.addresses[0], o.valueSat);
TransactionItem.create({
txid : t.txid,
value : o.value,
value_sat : o.valueSat,
addr : o.scriptPubKey.addresses[0],
index : o.n,
ts : t.info.time,
}, next_out);
}
else {
console.log ("TX: %s,%d seems to be multisig OUT. Skipping... ", t.txid, o.n);
console.log ("TX: %s,%d could not parse OUTPUT. Skipping... ", t.txid, o.n);
return next_out();
}
},
@ -240,6 +259,7 @@ TransactionSchema.methods.queryInfo = function (next) {
if (i.value) {
that.info.vin[c].value = util.formatValue(i.value);
var n = util.valueToBigInt(i.value).toNumber();
that.info.vin[c].valueSat = n;
valueIn = valueIn.add( n );
var scriptSig = i.getScript();
@ -264,9 +284,13 @@ TransactionSchema.methods.queryInfo = function (next) {
});
}
var c = 0;
tx.outs.forEach( function(i) {
var n = util.valueToBigInt(i.v).toNumber();
valueOut = valueOut.add(n);
that.info.vout[c].valueSat = n;
c++;
});
that.info.valueOut = valueOut / util.COIN;

View File

@ -13,13 +13,15 @@ var TransactionItemSchema = new Schema({
type: String,
index: true,
},
// OJO: mongoose doesnt accept camelcase for field names
// <0 is Input >0 is Output
value: Number,
value_sat: Number,
ts: Number,
});
// Compound index
TransactionItemSchema.index({txid: 1, index: 1, value: 1}, {unique: true, dropDups: true});
TransactionItemSchema.index({txid: 1, index: 1, value_sat: 1}, {unique: true, dropDups: true});
TransactionItemSchema.statics.load = function(id, cb) {
@ -29,10 +31,24 @@ TransactionItemSchema.statics.load = function(id, cb) {
};
TransactionItemSchema.statics.fromAddr = function(addr, cb) {
TransactionItemSchema.statics.fromTxId = function(txid, cb) {
this.find({
addr: addr,
}).exec(cb);
txid: txid,
}).exec(function (err,items) {
// sort by 1) value sign 2) index
return cb(err,items.sort(function(a,b){
var sa= a.value_sat < 0 ? -1 : 1;
var sb= b.value_sat < 0 ? -1 : 1;
if (sa != sb) {
return sa-sb;
}
else {
return a.index - b.index;
}
}));
});
};
module.exports = mongoose.model('TransactionItem', TransactionItemSchema);

View File

@ -6,9 +6,9 @@ module.exports = {
name: "Mystery - Development"
},
bitcoind: {
user: 'mystery',
pass: 'real_mystery',
protocol: 'http',
protocol: process.env.BITCOIND_USER || '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',
},

View File

@ -8,9 +8,7 @@ var
config = require('../../config/config'),
Address = require('../../app/models/Address');
mongoose= require('mongoose'),
config = require('../../config/config');
var addrValid = JSON.parse(fs.readFileSync('test/model/addr.json'));
addrValid = JSON.parse(fs.readFileSync('test/model/addr.json'));
describe('Address update', function(){

View File

@ -1,15 +1,20 @@
[
{
"disabled":1,
"addr": "mjRmkmYzvZN3cA3aBKJgYJ65epn3WCG84H"
},
{
"disabled":1,
"addr": "mp3Rzxx9s1A21SY3sjJ3CQoa2Xjph7e5eS",
"balance": 0,
"totalReceived": 50,
"totalSent": 50.0
}
,
{
"addr": "mgqvRGJMwR9JU5VhJ3x9uX9MTkzTsmmDgQ",
"balance": 43.1
},
{
"addr": "mzW2hdZN2um7WBvTDerdahKqRgj3md9C29",
"balance": 910.39522682,

View File

@ -28,9 +28,6 @@ describe('Transaction', function(){
mongoose.connection.close();
done();
});
it('should pool tx\'s object from mongoose', function(done) {
var txid = '7e621eeb02874ab039a8566fd36f4591e65eca65313875221842c53de6907d6c';
Transaction.fromIdWithInfo(txid, function(err, tx) {
@ -80,23 +77,42 @@ describe('Transaction', function(){
done();
});
});
var txid22 = '666';
it('test unexisting TX ' + txid22, function(done) {
Transaction.fromIdWithInfo(txid22, function(err, tx) {
if (err && err.toString().match(/TX.not.found/)) {
return done();
}
else {
return done(err);
}
});
});
var txid2 = '64496d005faee77ac5a18866f50af6b8dd1f60107d6795df34c402747af98608';
it('create TX on the fly ' + txid2, function(done) {
TransactionItem.remove({txid: txid2}, function(err) {
Transaction.fromIdWithInfo(txid2, function(err, tx) {
if (err) return done(err);
assert.equal(tx.info.txid, txid2);
done();
});
});
});
var txid2 = '64496d005faee77ac5a18866f50af6b8dd1f60107d6795df34c402747af98608';
it('test a broken TX ' + txid2, function(done) {
Transaction.fromIdWithInfo(txid2, function(err, tx) {
if (err) done(err);
if (err) return done(err);
assert.equal(tx.info.txid, txid2);
assert.equal(tx.info.vin[0].addr, 'n1JagbRWBDi6VMvG7HfZmXX74dB9eiHJzU');
// TODO output -> multisig!
// https://www.biteasy.com/testnet/transactions/64496d005faee77ac5a18866f50af6b8dd1f60107d6795df34c402747af98608
done();
});
});
txItemsValid.forEach( function(v) {
if (v.disabled) return;
it('test a exploding TX ' + v.txid, function(done) {
// Remove first
@ -105,7 +121,8 @@ describe('Transaction', function(){
Transaction.explodeTransactionItems(v.txid, function(err, tx) {
if (err) done(err);
TransactionItem.find({txid: v.txid}).sort({ index:1 }).exec(function(err, readItems) {
TransactionItem
.fromTxId( v.txid, function(err, readItems) {
var unmatch={};
@ -113,20 +130,22 @@ describe('Transaction', function(){
unmatch[validItem.addr] =1;
});
v.items.forEach(function(validItem){
readItems.forEach(function(readItem){
if ( readItem.addr === validItem.addr &&
parseInt(readItem.index) == parseInt(validItem.index) &&
parseFloat(readItem.value) == parseFloat(validItem.value) )
delete unmatch[validItem.addr];
});
var readItem = readItems.shift();
assert.equal(readItem.addr,validItem.addr);
assert.equal(readItem.value_sat,validItem.value_sat);
assert.equal(readItem.index,validItem.index);
delete unmatch[validItem.addr];
});
var valid = util.inspect(v.items, { depth: null });
assert(!Object.keys(unmatch).length, '\n\tmatched:' + Object.keys(unmatch) + "\n\n" +valid + '\nvs.\n' + readItems);
assert(!Object.keys(unmatch).length,
'\n\tUnmatchs:' + Object.keys(unmatch) + "\n\n" +valid + '\nvs.\n' + readItems);
done();
});
});
});
});
});
});

View File

@ -1,20 +1,24 @@
[
{
"disabled": 1,
"txid": "75c5ffe6dc2eb0f6bd011a08c041ef115380ccd637d859b379506a0dca4c26fc"
},
{
"txid": "21798ddc9664ac0ef618f52b151dda82dafaf2e26d2bbef6cdaf55a6957ca237",
"items": [
{
"addr": "mwcFwXv2Yquy4vJA4nnNLAbHVjrPdC8Q1Z",
"value": -1.66224,
"value_sat": -166224000,
"index": 0
},
{
"addr": "mzjLe62faUqCSjkwQkwPAL5nYyR8K132fA",
"value": 1.34574,
"value_sat": 134574000,
"index": 0
},
{
"addr": "n28wb1cRGxPtfmsenYKFfsvnZ6kRapx3jF",
"value": 0.316,
"value_sat": 31600000,
"index": 1
}
]
@ -24,17 +28,17 @@
"items": [
{
"addr": "mzjLe62faUqCSjkwQkwPAL5nYyR8K132fA",
"value": -0.40790667,
"value_sat": -40790667,
"index": 0
},
{
"addr": "mhfQJUSissP6nLM5pz6DxHfctukrrLct2T",
"value": 0.193,
"value_sat": 19300000,
"index": 0
},
{
"addr": "mzcDhbL877ES3MGftWnc3EuTSXs3WXDDML",
"value": 0.21440667,
"value_sat": 21440667,
"index": 1
}
]
@ -44,22 +48,22 @@
"items": [
{
"addr": "mzeiUi4opeheWYveXqp8ebqHyVwYGA2s3x",
"value": -0.01225871,
"value_sat": -1225871,
"index": 0
},
{
"addr": "mtMLijHAbG8CsgBbQGajsqav9p9wKUYad5",
"value": -0.01201823,
"value_sat": -1201823,
"index": 1
},
{
"addr": "mhqyL1nDQDo1WLH9qH8sjRjx2WwrnmAaXE",
"value": 0.01327746,
"value_sat": 1327746,
"index": 0
},
{
"addr": "mkGrySSnxcqRbtPCisApj3zXCQVmUUWbf1",
"value": 0.01049948,
"value_sat": 1049948,
"index": 1
}
]