test working with values stored in satoshis
This commit is contained in:
parent
1324d8c183
commit
5a97c96d6e
|
@ -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();
|
||||
})
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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',
|
||||
},
|
||||
|
|
|
@ -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(){
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) )
|
||||
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();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue