Merge pull request #75 from cmgustavo/feature/socket-io-support

Feature/socket io support
This commit is contained in:
Matias Alejo Garcia 2014-04-17 13:37:58 -03:00
commit ff37bea6fb
15 changed files with 3507 additions and 39 deletions

3
.gitignore vendored
View File

@ -45,6 +45,7 @@ public/css/main.css
README.html README.html
lib lib/*
!lib/socket.io.js
js/copayBundle.js js/copayBundle.js

View File

@ -18,7 +18,8 @@
</figure> </figure>
<div class="text-right" ng-show="$root.wallet"> <div class="text-right" ng-show="$root.wallet">
<h5>Company Funds</h5> <h5>Company Funds</h5>
<p>4.324 BTC</p> <p ng-show="totalBalance">{{totalBalance}} BTC</p>
<p ng-show="!totalBalance">0 BTC</p>
</div> </div>
</div> </div>
@ -181,7 +182,7 @@
</div> </div>
<div class="large-3 columns line-dashed-v text-center"> <div class="large-3 columns line-dashed-v text-center">
<qrcode size="160" data="{{selectedAddr}}"></qrcode> <qrcode size="160" data="{{selectedAddr}}"></qrcode>
<p class="m10t"> <strong> 2.5432 BTC </strong> </p> <p class="m10t" ng-repeat="addr in addrs" ng-if="selectedAddr==addr"> <strong> {{addrBalance[addr]}} BTC </strong> </p>
</div> </div>
<div class="large-1 columns"> </div> <div class="large-1 columns"> </div>
<div class="large-2 columns"> <div class="large-2 columns">
@ -326,14 +327,15 @@
<script src="lib/peerjs/peer.js"></script> <script src="lib/peerjs/peer.js"></script>
<script src="lib/bitcore.js"></script> <script src="lib/bitcore.js"></script>
<script src="lib/crypto-js/rollups/aes.js"></script> <script src="lib/crypto-js/rollups/aes.js"></script>
<script src="lib/socket.io.js"></script>
<script src="js/copayBundle.js"></script> <script src="js/copayBundle.js"></script>
<script src="js/app.js"></script> <script src="js/app.js"></script>
<script src="js/config.js"></script> <script src="js/config.js"></script>
<script src="js/routes.js"></script> <script src="js/routes.js"></script>
<script src="js/directives.js"></script> <script src="js/directives.js"></script>
<script src="js/filters.js"></script> <script src="js/filters.js"></script>
<script src="js/services/socket.js"></script>
<script src="js/services/walletFactory.js"></script> <script src="js/services/walletFactory.js"></script>
<script src="js/services/controllerUtils.js"></script> <script src="js/services/controllerUtils.js"></script>

View File

@ -11,6 +11,7 @@ angular.module('copay',[
'copay.backup', 'copay.backup',
'copay.walletFactory', 'copay.walletFactory',
'copay.signin', 'copay.signin',
'copay.socket',
'copay.controllerUtils', 'copay.controllerUtils',
'copay.setup', 'copay.setup',
'copay.peer' 'copay.peer'
@ -26,4 +27,5 @@ angular.module('copay.controllerUtils', []);
angular.module('copay.signin', []); angular.module('copay.signin', []);
angular.module('copay.setup', []); angular.module('copay.setup', []);
angular.module('copay.peer', []); angular.module('copay.peer', []);
angular.module('copay.socket', []);

View File

@ -18,10 +18,12 @@ var config = {
verbose: 1, verbose: 1,
}, },
blockchain: { blockchain: {
host: 'test.insight.is', host: 'localhost',
port: 80 port: 3001
// host: 'localhost', },
// port: 3001 socket: {
host: 'localhost',
port: 3001
}, },
verbose: 1, verbose: 1,
}; };

View File

@ -1,13 +1,15 @@
'use strict'; 'use strict';
angular.module('copay.backup').controller('BackupController', angular.module('copay.backup').controller('BackupController',
function($scope, $rootScope, $location) { function($scope, $rootScope, $location, Socket, controllerUtils) {
if (!$rootScope.wallet || !$rootScope.wallet.id) {
if (!$rootScope.wallet.id) {
$location.path('signin'); $location.path('signin');
} }
else {
var socket = Socket($scope);
socket.on('connect', controllerUtils.handleTransactionByAddress($scope));
}
$scope.title = 'Backup'; $scope.title = 'Backup';
}); });

View File

@ -24,7 +24,7 @@ angular.module('copay.header').controller('HeaderController',
'link': '#/backup' 'link': '#/backup'
}]; }];
if (!$rootScope.peerId) { if (!$rootScope.wallet || !$rootScope.wallet.id) {
$location.path('signin'); $location.path('signin');
} }
@ -40,6 +40,7 @@ angular.module('copay.header').controller('HeaderController',
if (w) { if (w) {
w.disconnect(); w.disconnect();
delete $rootScope['wallet']; delete $rootScope['wallet'];
$rootScope.totalBalance = 0;
$location.path('signin'); $location.path('signin');
} }
}; };
@ -47,4 +48,5 @@ angular.module('copay.header').controller('HeaderController',
$scope.clearFlashMessage = function() { $scope.clearFlashMessage = function() {
$rootScope.flashMessage = {}; $rootScope.flashMessage = {};
}; };
}); });

View File

@ -1,7 +1,7 @@
'use strict'; 'use strict';
angular.module('copay.home').controller('HomeController', angular.module('copay.home').controller('HomeController',
function($scope, $rootScope, $location) { function($scope, $rootScope, $location, Socket, controllerUtils) {
$scope.title = 'Home'; $scope.title = 'Home';
$scope.oneAtATime = true; $scope.oneAtATime = true;
@ -24,6 +24,9 @@ angular.module('copay.home').controller('HomeController',
$scope.selectedAddr = $scope.addrs[0]; $scope.selectedAddr = $scope.addrs[0];
_getBalance(); _getBalance();
var socket = Socket($scope);
socket.on('connect', controllerUtils.handleTransactionByAddress($scope));
} }
$scope.newAddr = function() { $scope.newAddr = function() {
@ -31,6 +34,8 @@ angular.module('copay.home').controller('HomeController',
$scope.addrs.push(a); $scope.addrs.push(a);
_getBalance(); _getBalance();
var socket = Socket($scope);
socket.on('connect', controllerUtils.handleTransactionByAddress($scope));
}; };
$scope.selectAddr = function(addr) { $scope.selectAddr = function(addr) {

View File

@ -1,10 +1,18 @@
'use strict'; 'use strict';
angular.module('copay.peer').controller('PeerController', angular.module('copay.peer').controller('PeerController',
function($scope, $rootScope, $location, $routeParams) { function($scope, $rootScope, $location, $routeParams, Socket, controllerUtils) {
$scope.init = function() { $scope.init = function() {
//Network.connect($rootScope.masterId); //Network.connect($rootScope.masterId);
}; };
if (!$rootScope.wallet || !$rootScope.wallet.id) {
$location.path('signin');
}
else {
var socket = Socket($scope);
socket.on('connect', controllerUtils.handleTransactionByAddress($scope));
}
}); });

View File

@ -1,13 +1,17 @@
'use strict'; 'use strict';
angular.module('copay.send').controller('SendController', angular.module('copay.send').controller('SendController',
function($scope, $rootScope, $location) { function($scope, $rootScope, $location, Socket, controllerUtils) {
$scope.title = 'Send'; $scope.title = 'Send';
if (!$rootScope.wallet.id) { if (!$rootScope.wallet || !$rootScope.wallet.id) {
$location.path('signin'); $location.path('signin');
} }
else {
var socket = Socket($scope);
socket.on('connect', controllerUtils.handleTransactionByAddress($scope));
}
$scope.sendTest = function() { $scope.sendTest = function() {
var w = $rootScope.wallet; var w = $rootScope.wallet;

View File

@ -1,15 +1,15 @@
'use strict'; 'use strict';
angular.module('copay.transactions').controller('TransactionsController', angular.module('copay.transactions').controller('TransactionsController',
function($scope, $rootScope, $location) { function($scope, $rootScope, $location, Socket, controllerUtils) {
$scope.title = 'Transactions'; $scope.title = 'Transactions';
$scope.oneAtATime = true; $scope.oneAtATime = true;
if (!$rootScope.wallet.id) { if (!$rootScope.wallet || !$rootScope.wallet.id) {
$location.path('signin'); $location.path('signin');
} }
else {
$scope.txsinput = [ $scope.txsinput = [
{ {
fromAddr: "n3zUqNR7Bbbc4zJhPVj1vG2Lx66K3Xhzvb", fromAddr: "n3zUqNR7Bbbc4zJhPVj1vG2Lx66K3Xhzvb",
@ -25,6 +25,10 @@ angular.module('copay.transactions').controller('TransactionsController',
$scope.txsoutput = $rootScope.wallet.getTxProposals(); $scope.txsoutput = $rootScope.wallet.getTxProposals();
var socket = Socket($scope);
socket.on('connect', controllerUtils.handleTransactionByAddress($scope));
}
$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);

View File

@ -34,7 +34,9 @@ Insight.prototype.getBalance = function(unspent) {
for(var i=0;i<unspent.length; i++) { for(var i=0;i<unspent.length; i++) {
balance = balance + unspent[i].amount; balance = balance + unspent[i].amount;
} }
if (balance) {
balance = balance.toFixed(4);
}
return balance; return balance;
}; };

View File

@ -277,7 +277,18 @@ Wallet.prototype.getAddressesStr = function() {
return ret; return ret;
}; };
Wallet.prototype.getBalance = function(cb) {
var balance = 0;
this.blockchain.listUnspent(this.getAddressesStr(), function(unspent) {
for(var i=0;i<unspent.length; i++) {
balance = balance + unspent[i].amount;
}
if (balance) {
balance = balance.toFixed(4);
}
return cb(balance);
});
};
Wallet.prototype.listUnspent = function(cb) { Wallet.prototype.listUnspent = function(cb) {
this.blockchain.listUnspent(this.getAddressesStr(), cb); this.blockchain.listUnspent(this.getAddressesStr(), cb);

View File

@ -1,16 +1,20 @@
'use strict'; 'use strict';
angular.module('copay.controllerUtils').factory('controllerUtils', function ($rootScope, $location) { angular.module('copay.controllerUtils').factory('controllerUtils', function ($rootScope, $location, Socket) {
var root = {}; var root = {};
root.setupUxHandlers = function(w) { root.setupUxHandlers = function(w) {
w.on('created', function() { w.on('created', function() {
$location.path('peer'); $location.path('peer');
$rootScope.wallet = w; $rootScope.wallet = w;
// Initial getBalance
$rootScope.wallet.getBalance(function(balance) {
$rootScope.totalBalance = balance;
$rootScope.$digest(); $rootScope.$digest();
}); });
});
w.on('refresh', function() { w.on('refresh', function() {
console.log('[controllerUtils.js] RECEIVED REFRESH'); //TODO console.log('[controllerUtils.js] RECEIVED REFRESH'); //TODO
$rootScope.$digest();
}); });
w.on('openError', function(){ w.on('openError', function(){
@ -20,6 +24,26 @@ angular.module('copay.controllerUtils').factory('controllerUtils', function ($ro
}); });
}; };
root.handleTransactionByAddress = function(scope) {
var socket = Socket(scope);
var addrs = $rootScope.wallet.getAddressesStr();
socket.emit('subscribe', 'inv');
for(var i=0;i<addrs.length;i++) {
socket.emit('subscribe', addrs[i]);
}
addrs.forEach(function(addr) {
socket.on(addr, function(txid) {
console.log('Received!', txid);
$rootScope.wallet.getBalance(function(balance) {
scope.$apply(function() {
$rootScope.totalBalance = balance;
});
console.log('New balance:', balance);
});
});
});
};
return root; return root;
}); });

72
js/services/socket.js Normal file
View File

@ -0,0 +1,72 @@
'use strict';
var ScopedSocket = function(socket, $rootScope) {
this.socket = socket;
this.$rootScope = $rootScope;
this.listeners = [];
};
ScopedSocket.prototype.removeAllListeners = function(opts) {
if (!opts) opts = {};
for (var i = 0; i < this.listeners.length; i++) {
var details = this.listeners[i];
if (opts.skipConnect && details.event === 'connect') {
continue;
}
this.socket.removeListener(details.event, details.fn);
}
this.listeners = [];
};
ScopedSocket.prototype.on = function(event, callback) {
var socket = this.socket;
var $rootScope = this.$rootScope;
var wrapped_callback = function() {
var args = arguments;
$rootScope.$apply(function() {
callback.apply(socket, args);
});
};
socket.on(event, wrapped_callback);
this.listeners.push({
event: event,
fn: wrapped_callback
});
};
ScopedSocket.prototype.emit = function(event, data, callback) {
var socket = this.socket;
var $rootScope = this.$rootScope;
socket.emit(event, data, function() {
var args = arguments;
$rootScope.$apply(function() {
if (callback) {
callback.apply(socket, args);
}
});
});
};
angular.module('copay.socket').factory('Socket',
function($rootScope) {
var server = 'http://' + config.socket.host + ':' + config.socket.port;
var socket = io.connect(server, {
'reconnect': true,
'reconnection delay': 500,
});
return function(scope) {
var scopedSocket = new ScopedSocket(socket, $rootScope);
scope.$on('$destroy', function() {
scopedSocket.removeAllListeners();
});
socket.on('connect', function() {
scopedSocket.removeAllListeners({
skipConnect: true
});
});
return scopedSocket;
};
});

3327
lib/socket.io.js Normal file

File diff suppressed because it is too large Load Diff