Merge pull request #121 from matiu/feature/ux13

Feature/ux13
This commit is contained in:
Manuel Aráoz 2014-04-21 13:18:16 -03:00
commit 5f66a179c9
9 changed files with 84 additions and 43 deletions

View File

@ -18,8 +18,10 @@
</figure> </figure>
<div class="text-right" ng-show="$root.wallet"> <div class="text-right" ng-show="$root.wallet">
<h5 ng-show="$root.wallet.id">Wallet ID: {{$root.wallet.id}}</h5> <h5 ng-show="$root.wallet.id">Wallet ID: {{$root.wallet.id}}</h5>
<p ng-show="totalBalance">{{totalBalance}} <i class="fi-bitcoin"></i></p> <p>
<p ng-show="!totalBalance">0 <i class="fi-bitcoin"></i></p> Balance: {{totalBalance || 0}} <i class="fi-bitcoin"></i><br>
Available to Spend:{{availableBalance || 0}} <i class="fi-bitcoin"></i>
</p>
</div> </div>
</div> </div>
@ -214,13 +216,13 @@
<script type="text/ng-template" id="addresses.html"> <script type="text/ng-template" id="addresses.html">
<div class="addresses" data-ng-controller="AddressesController"> <div class="addresses" data-ng-controller="AddressesController">
<div ng-show='$root.wallet.publicKeyRing.isComplete()'> <div ng-show='$root.wallet.publicKeyRing.isComplete()'>
<h3>Address</h3> <h3>Addresses (available to spend)</h3>
<div class="row"> <div class="row">
<div class="large-6 columns"> <div class="large-6 columns">
<a class="panel db" ng-repeat="addr in addrs" ng-click="selectAddr(addr)">{{addr}} <a class="panel db" ng-repeat="addr in addrs" ng-click="selectAddr(addr)">{{addr}}
<span ng-if="!isMain[addr]">(change)</span> <span ng-if="!isMain[addr]">(change)</span>
<span class="right">{{balanceByAddr[addr] || 0}} <i class="fi-bitcoin"></i></span></a> <span class="right">({{balanceByAddr[addr] || 0}} <i class="fi-bitcoin"></i>)</span></a>
</div> </div>
<div class="large-3 columns line-dashed-v text-center"> <div class="large-3 columns line-dashed-v text-center">

View File

@ -10,8 +10,7 @@ angular.module('copay.addresses').controller('AddressesController',
var _updateBalance = function () { var _updateBalance = function () {
controllerUtils.setSocketHandlers(); controllerUtils.setSocketHandlers();
w.getBalance(true, function (balance, balanceByAddr, isMain) {
w.getBalance(function (balance, balanceByAddr, isMain) {
if (balanceByAddr && Object.keys(balanceByAddr).length) { if (balanceByAddr && Object.keys(balanceByAddr).length) {
$rootScope.balanceByAddr = balanceByAddr; $rootScope.balanceByAddr = balanceByAddr;
$scope.isMain = isMain; $scope.isMain = isMain;

View File

@ -27,11 +27,7 @@ angular.module('copay.header').controller('HeaderController',
$rootScope.$watch('wallet', function(wallet) { $rootScope.$watch('wallet', function(wallet) {
if (wallet) { if (wallet) {
controllerUtils.setSocketHandlers(); controllerUtils.setSocketHandlers();
$rootScope.wallet.getBalance(function(balance) { controllerUtils.updateBalance();
$rootScope.$apply(function() {
$rootScope.totalBalance = balance;
});
});
} }
}); });

View File

@ -4,9 +4,6 @@ var bitcore = require('bitcore');
angular.module('copay.transactions').controller('TransactionsController', angular.module('copay.transactions').controller('TransactionsController',
function($scope, $rootScope, $location) { function($scope, $rootScope, $location) {
$scope.title = 'Transactions'; $scope.title = 'Transactions';
$scope.oneAtATime = true;
var _updateTxs = function() { var _updateTxs = function() {
console.log('[transactions.js.10:_updateTxs:]'); //TODO console.log('[transactions.js.10:_updateTxs:]'); //TODO
var w =$rootScope.wallet; var w =$rootScope.wallet;
@ -32,6 +29,7 @@ console.log('[transactions.js.10:_updateTxs:]'); //TODO
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);
@ -69,4 +67,5 @@ console.log('[transactions.js.68:txid:] SENTTX CALLBACK',txid); //TODO
} }
}; };
_updateTxs();
}); });

View File

@ -213,7 +213,6 @@ PublicKeyRing.prototype.getAddresses = function(onlyMain) {
PublicKeyRing.prototype.getRedeemScriptMap = function () { PublicKeyRing.prototype.getRedeemScriptMap = function () {
var ret = {}; var ret = {};
console.log('[PublicKeyRing.js.216]', this.changeAddressIndex, this.addressIndex); //TODO
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'); ret[this.getAddress(i,true)] = this.getRedeemScript(i,true).getBuffer().toString('hex');

View File

@ -181,6 +181,16 @@ TxProposals.prototype.setSent = function(ntxid,txid) {
this.txps[ntxid].setSent(txid); this.txps[ntxid].setSent(txid);
}; };
TxProposals.prototype.getUsedUnspent = function() {
var ret = [];
for(var i in this.txps) {
var u = this.txps[i].builder.getSelectedUnspent();
for (var j in u){
ret.push(u[j].txid);
}
}
return ret;
};
TxProposals.prototype.merge = function(t) { TxProposals.prototype.merge = function(t) {
if (this.network.name !== t.network.name) if (this.network.name !== t.network.name)

View File

@ -400,7 +400,7 @@ Wallet.prototype.addressIsOwn = function(addrStr) {
return ret; return ret;
}; };
Wallet.prototype.getBalance = function(cb) { Wallet.prototype.getBalance = function(safe, cb) {
var balance = 0; var balance = 0;
var balanceByAddr = {}; var balanceByAddr = {};
var isMain = {}; var isMain = {};
@ -414,7 +414,8 @@ Wallet.prototype.getBalance = function(cb) {
balanceByAddr[a]=0; balanceByAddr[a]=0;
isMain[a]=1; isMain[a]=1;
}); });
this.getUnspent(function(utxos) { var f = safe ? this.getSafeUnspent.bind(this):this.getUnspent.bind(this);
f(function(utxos) {
for(var i=0;i<utxos.length; i++) { for(var i=0;i<utxos.length; i++) {
var u= utxos[i]; var u= utxos[i];
var amt = u.amount * COIN; var amt = u.amount * COIN;
@ -423,7 +424,7 @@ Wallet.prototype.getBalance = function(cb) {
} }
for(var a in balanceByAddr){ for(var a in balanceByAddr){
balanceByAddr[a] = balanceByAddr[a]/COIN; balanceByAddr[a] = balanceByAddr[a]/COIN;
}; }
return cb(balance / COIN, balanceByAddr, isMain); return cb(balance / COIN, balanceByAddr, isMain);
}); });
}; };
@ -434,8 +435,24 @@ Wallet.prototype.getUnspent = function(cb) {
}); });
}; };
Wallet.prototype.getSafeUnspent = function(cb) {
var self = this;
this.blockchain.getUnspent(this.getAddressesStr(), function(unspentList) {
var ret=[];
var uu = self.txProposals.getUsedUnspent();
for(var i in unspentList){
if (uu.indexOf(unspentList[i].txid) === -1)
ret.push(unspentList[i]);
}
return cb(ret);
});
};
Wallet.prototype.createTx = function(toAddress, amountSatStr, opts, cb) { Wallet.prototype.createTx = function(toAddress, amountSatStr, opts, cb) {
console.log('[Wallet.js.447:createTx:]'); //TODO
var self = this; var self = this;
if (typeof opts === 'function') { if (typeof opts === 'function') {
cb = opts; cb = opts;
@ -446,7 +463,8 @@ console.log('[Wallet.js.447:createTx:]'); //TODO
if (typeof opts.spendUnconfirmed === 'undefined') { if (typeof opts.spendUnconfirmed === 'undefined') {
opts.spendUnconfirmed = this.spendUnconfirmed; opts.spendUnconfirmed = this.spendUnconfirmed;
} }
self.getUnspent(function(unspentList) {
self.getSafeUnspent(function(unspentList) {
// TODO check enough funds, etc. // TODO check enough funds, etc.
self.createTxSync(toAddress, amountSatStr, unspentList, opts); self.createTxSync(toAddress, amountSatStr, unspentList, opts);
self.sendPublicKeyRing(); // Change Address self.sendPublicKeyRing(); // Change Address
@ -470,7 +488,6 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, utxos, opts) {
if (!opts.remainderOut) { if (!opts.remainderOut) {
opts.remainderOut ={ address: this.generateAddress(true).toString() }; opts.remainderOut ={ address: this.generateAddress(true).toString() };
} }
console.log('[Wallet.js.480:opts: CREATETXSYNC]',opts); //TODO
var b = new Builder(opts) var b = new Builder(opts)
.setUnspent(utxos) .setUnspent(utxos)

View File

@ -27,27 +27,33 @@ angular.module('copay.controllerUtils').factory('controllerUtils', function ($ro
}); });
w.on('created', function() { w.on('created', function() {
console.log('[controllerUtils.js.30:created:] RECV '); //TODO
$location.path('peer'); $location.path('peer');
$rootScope.wallet = w; $rootScope.wallet = w;
root.updateBalance();
$rootScope.wallet.getBalance(function(balance) {
$rootScope.totalBalance = balance;
});
}); });
w.on('refresh', function() { w.on('refresh', function() {
console.log('[controllerUtils.js] Refreshing'); //TODO console.log('[controllerUtils.js] Refreshing'); //TODO
$rootScope.$digest(); root.updateBalance();
}); });
w.on('openError', root.onErrorDigest); w.on('openError', root.onErrorDigest);
w.on('close', root.onErrorDigest); w.on('close', root.onErrorDigest);
console.log('[controllerUtils.js.45] CALLING NETSTART FROM setupUxHandlers'); //TODO
w.netStart(); w.netStart();
console.log('[controllerUtils.js.45] setupUxHandlers END'); //TODO
}; };
root.setSocketHandlers = function(cb) { root.updateBalance = function() {
var w = $rootScope.wallet;
w.getBalance(false,function(balance, balanceByAddr) {
$rootScope.totalBalance = balance;
$rootScope.balanceByAddr = balanceByAddr;
console.log('New balance:', balance);
w.getBalance(true,function(balance) {
$rootScope.availableBalance = balance;
$rootScope.$digest();
});
});
};
root.setSocketHandlers = function() {
Socket.removeAllListeners(); Socket.removeAllListeners();
var addrs = $rootScope.wallet.getAddressesStr(); var addrs = $rootScope.wallet.getAddressesStr();
@ -59,15 +65,7 @@ console.log('[controllerUtils.js.45] setupUxHandlers END'); //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);
$rootScope.wallet.getBalance(function(balance, balanceByAddr) { root.updateBalance();
$rootScope.$apply(function() {
$rootScope.totalBalance = balance;
$rootScope.balanceByAddr = balanceByAddr;
});
console.log('New balance:', balance);
if (typeof cb === 'function') return cb();
});
}); });
}); });
}; };

View File

@ -104,6 +104,30 @@ describe('TxProposals model', function() {
}; };
it('#getUsedUnspend', function () {
var priv = new PrivateKey(config);
var w = new TxProposals({
networkName: config.networkName,
});
var start = new Date().getTime();
var pkr=createPKR([priv]);
var ts = Date.now();
var isChange=0;
var index=0;
unspentTest[0].address = pkr.getAddress(index, isChange).toString();
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
w.add(createTx(
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
'123456789',
unspentTest,
{},
priv,
pkr
));
w.getUsedUnspent().length.should.equal(1);
w.getUsedUnspent()[0].should.equal(unspentTest[0].txid);
});
it('#merge with self', function () { it('#merge with self', function () {
var priv = new PrivateKey(config); var priv = new PrivateKey(config);
var w = new TxProposals({ var w = new TxProposals({
@ -472,8 +496,5 @@ 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);
}); });
}); });