Merge pull request #128 from matiu/feature/ux14

Feature/ux14
This commit is contained in:
Ryan X. Charles 2014-04-22 23:17:56 -03:00
commit c4d8efdfaa
8 changed files with 95 additions and 33 deletions

View file

@ -249,11 +249,13 @@
<div class="txheader"> <div class="txheader">
<div class="row"> <div class="row">
<div class="large-8 columns"> <div class="large-8 columns">
<tr ng-repeat="o in tx.outs"> <table style="width:100%">
<td class="text-right size-24">{{o.value}} <i class="fi-bitcoin"></i></td> <tr ng-repeat="out in tx.outs">
<td class="text-center size-48"> <i class="fi-arrow-right size-40"> </i> <td class="text-right size-24"> <i class="fi-bitcoin"></i> {{out.value}}</td>
<td class="text-left size-24">{{o.address}}</td> <td class="text-center size-48"> <i class="fi-arrow-right size-24"> </i></td>
<td class="text-left size-24">{{out.address}}</td>
</tr> </tr>
</table>
</div> </div>
<div class="large-4 columns text-right"> <div class="large-4 columns text-right">
<h6> created at {{tx.createdTs | date:'medium'}} </h6> <h6> created at {{tx.createdTs | date:'medium'}} </h6>
@ -266,7 +268,10 @@
<table style="width:100%"> <table style="width:100%">
<tbody> <tbody>
<tr> <tr>
<small class="right text-gray"> <strong> Proposal ID: </strong> {{tx.ntxid}} </small> <small class="right text-gray">
Fee: <strong> <i class="fi-bitcoin"></i> {{tx.fee}} </strong>
<strong> Proposal ID: </strong> {{tx.ntxid}}
</small>
</tr> </tr>
<tr ng-repeat="(peer, actions) in tx.peerActions"> <tr ng-repeat="(peer, actions) in tx.peerActions">
<td colspan="3"> <td colspan="3">

View file

@ -5,8 +5,9 @@ angular.module('copay.transactions').controller('TransactionsController',
function($scope, $rootScope, $location) { function($scope, $rootScope, $location) {
$scope.title = 'Transactions'; $scope.title = 'Transactions';
var _updateTxs = function() { var _updateTxs = function() {
console.log('[transactions.js.10:_updateTxs:]'); //TODO
var w =$rootScope.wallet; var w =$rootScope.wallet;
if (!w) return;
var inT = w.getTxProposals(); var inT = w.getTxProposals();
var txs = []; var txs = [];
@ -25,11 +26,10 @@ console.log('[transactions.js.10:_updateTxs:]'); //TODO
}); });
// extra fields // extra fields
i.outs = outs; i.outs = outs;
i.fee = i.feeSat/bitcore.util.COIN; i.fee = i.builder.feeSat/bitcore.util.COIN;
i.missingSignatures = tx.countInputMissingSignatures(0); i.missingSignatures = tx.countInputMissingSignatures(0);
txs.push(i); txs.push(i);
}); });
console.log('[transactions.js.35:txs:]',txs); //TODO
$scope.txs = txs; $scope.txs = txs;
w.removeListener('txProposalsUpdated',_updateTxs) w.removeListener('txProposalsUpdated',_updateTxs)
w.once('txProposalsUpdated',_updateTxs); w.once('txProposalsUpdated',_updateTxs);
@ -38,7 +38,7 @@ console.log('[transactions.js.35:txs:]',txs); //TODO
$scope.send = function (ntxid) { $scope.send = function (ntxid) {
var w = $rootScope.wallet; var w = $rootScope.wallet;
w.sendTx(ntxid, function(txid) { w.sendTx(ntxid, function(txid) {
console.log('[transactions.js.68:txid:] SENTTX CALLBACK',txid); //TODO console.log('[transactions.js.68:txid:] SENTTX CALLBACK',txid); //TODO
$rootScope.flashMessage = txid $rootScope.flashMessage = txid
? {type:'success', message: 'Transactions SENT! txid:' + txid} ? {type:'success', message: 'Transactions SENT! txid:' + txid}
: {type:'error', message: 'There was an error sending the Transaction'} : {type:'error', message: 'There was an error sending the Transaction'}
@ -51,17 +51,20 @@ console.log('[transactions.js.68:txid:] SENTTX CALLBACK',txid); //TODO
$scope.sign = function (ntxid) { $scope.sign = function (ntxid) {
var w = $rootScope.wallet; var w = $rootScope.wallet;
var ret = w.sign(ntxid); var ret = w.sign(ntxid);
_updateTxs();
if (!ret) {
$rootScope.flashMessage = {type:'error', message: 'There was an error signing the Transaction'};
_updateTxs();
$rootScope.$digest();
return;
}
var p = w.getTxProposal(ntxid); var p = w.getTxProposal(ntxid);
if (p.txp.builder.isFullySigned()) { if (p.txp.builder.isFullySigned()) {
$scope.send(ntxid); $scope.send(ntxid);
_updateTxs();
$rootScope.$digest();
} }
else { else {
$rootScope.flashMessage = ret
? {type:'success', message: 'Transactions signed'}
: {type:'error', message: 'There was an error signing the Transaction'}
;
_updateTxs(); _updateTxs();
$rootScope.$digest(); $rootScope.$digest();
} }

View file

@ -71,7 +71,6 @@ PrivateKey.prototype.get = function(index,isChange) {
PrivateKey.prototype.getAll = function(addressIndex, changeAddressIndex) { PrivateKey.prototype.getAll = function(addressIndex, changeAddressIndex) {
var ret = []; var ret = [];
for(var i=0;i<addressIndex; i++) { for(var i=0;i<addressIndex; i++) {
ret.push(this.get(i,false)); ret.push(this.get(i,false));
} }

View file

@ -142,7 +142,7 @@ PublicKeyRing.prototype.getPubKeys = function (index, isChange) {
var bip32 = this.copayersBIP32[i].derive(path); var bip32 = this.copayersBIP32[i].derive(path);
pubKeys[i] = bip32.eckey.public; pubKeys[i] = bip32.eckey.public;
} }
this.publicKeysCache[path] = pubKeys.map(function(pk){return pk.toString('hex')}); this.publicKeysCache[path] = pubKeys.map(function(pk){return pk.toString('hex');});
} else { } else {
pubKeys = pubKeys.map(function(s){return new Buffer(s,'hex')}); pubKeys = pubKeys.map(function(s){return new Buffer(s,'hex')});
} }
@ -158,6 +158,7 @@ PublicKeyRing.prototype._checkIndexRange = function (index, isChange) {
} }
}; };
// TODO this could be cached
PublicKeyRing.prototype.getRedeemScript = function (index, isChange) { PublicKeyRing.prototype.getRedeemScript = function (index, isChange) {
this._checkIndexRange(index, isChange); this._checkIndexRange(index, isChange);
@ -166,13 +167,21 @@ PublicKeyRing.prototype.getRedeemScript = function (index, isChange) {
return script; return script;
}; };
// TODO this could be cached
PublicKeyRing.prototype.getAddress = function (index, isChange) { PublicKeyRing.prototype.getAddress = function (index, isChange) {
this._checkIndexRange(index, isChange); this._checkIndexRange(index, isChange);
var script = this.getRedeemScript(index,isChange); var script = this.getRedeemScript(index,isChange);
return Address.fromScript(script, this.network.name); return Address.fromScript(script, this.network.name);
}; };
// TODO this could be cached
PublicKeyRing.prototype._addScriptMap = function (map, index, isChange) {
this._checkIndexRange(index, isChange);
var script = this.getRedeemScript(index,isChange);
map[Address.fromScript(script, this.network.name).toString()] = script.getBuffer().toString('hex');
};
// TODO this could be cached
PublicKeyRing.prototype.getScriptPubKeyHex = function (index, isChange) { PublicKeyRing.prototype.getScriptPubKeyHex = function (index, isChange) {
this._checkIndexRange(index, isChange); this._checkIndexRange(index, isChange);
var addr = this.getAddress(index,isChange); var addr = this.getAddress(index,isChange);
@ -180,7 +189,6 @@ PublicKeyRing.prototype.getScriptPubKeyHex = function (index, isChange) {
}; };
//generate a new address, update index. //generate a new address, update index.
PublicKeyRing.prototype.generateAddress = function(isChange) { PublicKeyRing.prototype.generateAddress = function(isChange) {
@ -215,11 +223,10 @@ PublicKeyRing.prototype.getRedeemScriptMap = function () {
var ret = {}; var ret = {};
for (var i=0; i<this.changeAddressIndex; i++) { for (var i=0; i<this.changeAddressIndex; i++) {
ret[this.getAddress(i,true)] = this.getRedeemScript(i,true).getBuffer().toString('hex'); this._addScriptMap(ret,i,true);
} }
for (var i=0; i<this.addressIndex; i++) { for (var i=0; i<this.addressIndex; i++) {
ret[this.getAddress(i)] = this.getRedeemScript(i).getBuffer().toString('hex'); this._addScriptMap(ret,i,false);
} }
return ret; return ret;
}; };

View file

@ -269,7 +269,6 @@ Wallet.prototype.sendPublicKeyRing = function(recipients) {
Wallet.prototype.generateAddress = function(isChange) { Wallet.prototype.generateAddress = function(isChange) {
var addr = this.publicKeyRing.generateAddress(isChange); var addr = this.publicKeyRing.generateAddress(isChange);
console.log('[Wallet.js.281:addr:]',addr, this.publicKeyRing.toObj(), this.getAddresses()); //TODO
this.sendPublicKeyRing(); this.sendPublicKeyRing();
this.store(true); this.store(true);
return addr; return addr;
@ -318,7 +317,6 @@ Wallet.prototype.sign = function(ntxid) {
var pkr = self.publicKeyRing; var pkr = self.publicKeyRing;
var keys = self.privateKey.getAll(pkr.addressIndex, pkr.changeAddressIndex); var keys = self.privateKey.getAll(pkr.addressIndex, pkr.changeAddressIndex);
console.log('[Wallet.js.329:keys:]',keys); //TODO
var b = txp.builder; var b = txp.builder;
var before = b.signaturesAdded; var before = b.signaturesAdded;
@ -465,11 +463,11 @@ Wallet.prototype.createTx = function(toAddress, amountSatStr, opts, cb) {
} }
self.getSafeUnspent(function(unspentList) { self.getSafeUnspent(function(unspentList) {
// TODO check enough funds, etc. if (self.createTxSync(toAddress, amountSatStr, unspentList, opts)) {
self.createTxSync(toAddress, amountSatStr, unspentList, opts); self.sendPublicKeyRing(); // Change Address
self.sendPublicKeyRing(); // Change Address self.sendTxProposals();
self.sendTxProposals(); self.store();
self.store(); }
return cb(); return cb();
}); });
}; };
@ -497,10 +495,8 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, utxos, opts) {
var signRet; var signRet;
if (priv) { if (priv) {
console.log('[Wallet.js.486] aLL Priv', priv.getAll(pkr.addressIndex, pkr.changeAddressIndex)); //TODO
b.sign( priv.getAll(pkr.addressIndex, pkr.changeAddressIndex) ); b.sign( priv.getAll(pkr.addressIndex, pkr.changeAddressIndex) );
} }
console.log('[Wallet.js.494]', b, b.build().serialize().toString('hex')); //TODO
var me = {}; var me = {};
var myId = this.getMyPeerId(); var myId = this.getMyPeerId();
var now = Date.now(); var now = Date.now();

View file

@ -261,7 +261,6 @@ console.log('[WebRTC.js.255] WARN: NO CONNECTION TO:', peerId); //TODO
Network.prototype.send = function(peerIds, data, cb) { Network.prototype.send = function(peerIds, data, cb) {
var self=this; var self=this;
console.log('[WebRTC.js.242] SENDING ', data.type); //TODO
if (!peerIds) { if (!peerIds) {
peerIds = this.connectedPeers; peerIds = this.connectedPeers;
data.isBroadcast = 1; data.isBroadcast = 1;

View file

@ -61,7 +61,7 @@ angular.module('copay.controllerUtils').factory('controllerUtils', function ($ro
console.log('### SUBSCRIBE TO', addrs[i]); console.log('### SUBSCRIBE TO', addrs[i]);
Socket.emit('subscribe', addrs[i]); Socket.emit('subscribe', addrs[i]);
} }
console.log('[controllerUtils.js.64]'); //TODO
addrs.forEach(function(addr) { addrs.forEach(function(addr) {
Socket.on(addr, function(txid) { Socket.on(addr, function(txid) {
console.log('Received!', txid); console.log('Received!', txid);

View file

@ -59,9 +59,61 @@ var createPKR = function (bip32s) {
return w; return w;
}; };
var vopts = {
verifyP2SH: true,
dontVerifyStrictEnc: true
};
describe('TxProposals model', function() { describe('TxProposals model', function() {
it('verify TXs', function (done) {
var priv = new PrivateKey(config);
var priv2 = new PrivateKey(config);
var priv3 = new PrivateKey(config);
var ts = Date.now();
var isChange=0;
var index=0;
var pkr = createPKR([priv, priv2, priv3]);
var opts = {remainderOut: { address: pkr.generateAddress(true).toString() }};
var w = new TxProposals({
networkName: config.networkName,
});
unspentTest[0].address = pkr.getAddress(index, isChange).toString();
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
w.add(createTx(
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
'123456789',
unspentTest,
opts,
priv,
pkr
));
var k = Object.keys(w.txps)[0];
var b = w.txps[k].builder;
var tx = b.build();
tx.isComplete().should.equal(false);
b.sign( priv2.getAll(pkr.addressIndex, pkr.changeAddressIndex) );
b.sign( priv3.getAll(pkr.addressIndex, pkr.changeAddressIndex) );
tx = b.build();
tx.isComplete().should.equal(true);
var s = new Script(new Buffer(unspentTest[0].scriptPubKey,'hex'));
tx.verifyInput(0,s, {
verifyP2SH: true,
dontVerifyStrictEnc: true
}, function(err, results){
should.not.exist(err);
results.should.equal(true);
done();
});
});
it('should create an instance', function () { it('should create an instance', function () {
var w = new TxProposals({ var w = new TxProposals({
networkName: config.networkName networkName: config.networkName
@ -496,5 +548,6 @@ var _dumpChunks = function (scriptSig, label) {
w2.merge(w); w2.merge(w);
Object.keys(w2.txps).length.should.equal(1); Object.keys(w2.txps).length.should.equal(1);
}); });
}); });