fix conflicts

This commit is contained in:
Mario Colque 2014-04-17 18:05:26 -03:00
commit 2c0b733025
24 changed files with 3745 additions and 193 deletions

View file

@ -11,6 +11,8 @@ angular.module('copay',[
'copay.backup',
'copay.walletFactory',
'copay.signin',
'copay.socket',
'copay.controllerUtils',
'copay.setup',
'copay.peer'
]);
@ -21,7 +23,9 @@ angular.module('copay.transactions', []);
angular.module('copay.send', []);
angular.module('copay.backup', []);
angular.module('copay.walletFactory', []);
angular.module('copay.controllerUtils', []);
angular.module('copay.signin', []);
angular.module('copay.setup', []);
angular.module('copay.peer', []);
angular.module('copay.socket', []);

View file

@ -3,7 +3,12 @@
var config = {
networkName: 'testnet',
network: {
apiKey: 'lwjd5qra8257b9',
key: 'lwjd5qra8257b9',
// This is for running local peerJs with params: ./peerjs -p 10009 -k 'sdfjhwefh'
// key: 'sdfjhwefh',
// host: 'localhost',
// port: 10009,
// path: '/',
maxPeers: 3,
debug: 3,
},
@ -18,10 +23,12 @@ var config = {
verbose: 1,
},
blockchain: {
host: 'test.insight.is',
port: 80
// host: 'localhost',
// port: 3001
host: 'localhost',
port: 3001
},
socket: {
host: 'localhost',
port: 3001
},
verbose: 1,
};

View file

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

View file

@ -1,7 +1,7 @@
'use strict';
angular.module('copay.header').controller('HeaderController',
function($scope, $rootScope, $location, walletFactory) {
function($scope, $rootScope, $location, walletFactory, controllerUtils) {
$scope.menu = [{
'title': 'Home',
'icon': 'fi-home',
@ -24,7 +24,7 @@ angular.module('copay.header').controller('HeaderController',
'link': '#/backup'
}];
if (!$rootScope.peerId) {
if (!$rootScope.wallet || !$rootScope.wallet.id) {
$location.path('signin');
}
@ -39,12 +39,12 @@ angular.module('copay.header').controller('HeaderController',
var w = $rootScope.wallet;
if (w) {
w.disconnect();
delete $rootScope['wallet'];
$location.path('signin');
controllerUtils.logout();
}
};
$scope.clearFlashMessage = function() {
$rootScope.flashMessage = {};
};
});

View file

@ -1,16 +1,15 @@
'use strict';
angular.module('copay.home').controller('HomeController',
function($scope, $rootScope, $location) {
function($scope, $rootScope, $location, Socket, controllerUtils) {
$scope.title = 'Home';
$scope.oneAtATime = true;
$scope.addrBalance = {};
var _getBalance = function() {
$scope.addrs.forEach(function(addr) {
$rootScope.wallet.blockchain.listUnspent([addr], function(unspent) {
var balance = $rootScope.wallet.blockchain.getBalance(unspent);
$rootScope.wallet.getBalance([addr], function(balance) {
$scope.addrBalance[addr] = balance;
$scope.$digest();
});
@ -24,13 +23,17 @@ angular.module('copay.home').controller('HomeController',
$scope.selectedAddr = $scope.addrs[0];
_getBalance();
var socket = Socket($scope);
socket.on('connect', controllerUtils.handleTransactionByAddress($scope));
}
$scope.newAddr = function() {
var a = $rootScope.wallet.generateAddress().toString();
$scope.addrs.push(a);
_getBalance();
var socket = Socket($scope);
socket.on('connect', controllerUtils.handleTransactionByAddress($scope));
};
$scope.selectAddr = function(addr) {

View file

@ -1,10 +1,18 @@
'use strict';
angular.module('copay.peer').controller('PeerController',
function($scope, $rootScope, $location, $routeParams) {
function($scope, $rootScope, $location, $routeParams, Socket, controllerUtils) {
$scope.init = function() {
//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';
angular.module('copay.send').controller('SendController',
function($scope, $rootScope, $location) {
function($scope, $rootScope, $location, Socket, controllerUtils) {
$scope.title = 'Send';
if (!$rootScope.wallet.id) {
if (!$rootScope.wallet || !$rootScope.wallet.id) {
$location.path('signin');
}
else {
var socket = Socket($scope);
socket.on('connect', controllerUtils.handleTransactionByAddress($scope));
}
$scope.sendTest = function() {
var w = $rootScope.wallet;

View file

@ -1,7 +1,7 @@
'use strict';
angular.module('copay.setup').controller('SetupController',
function($scope, $rootScope, $location, walletFactory) {
function($scope, $rootScope, $location, walletFactory, controllerUtils) {
$scope.loading = false;
@ -32,16 +32,7 @@ angular.module('copay.setup').controller('SetupController',
totalCopayers: totalCopayers
};
var w = walletFactory.create(opts);
w.on('created', function(){
$location.path('peer');
$rootScope.wallet = w;
$rootScope.$digest();
});
w.on('openError', function(){
$scope.loading = false;
$rootScope.flashMessage = {type:'error', message: 'Wallet not found'};
$location.path('signin');
});
controllerUtils.setupUxHandlers(w);
w.netStart();
};

View file

@ -1,36 +1,17 @@
'use strict';
angular.module('copay.signin').controller('SigninController',
function($scope, $rootScope, $location, walletFactory) {
function($scope, $rootScope, $location, walletFactory, controllerUtils) {
// var peerData = Storage.get($rootScope.walletId, 'peerData');
// $rootScope.peerId = peerData ? peerData.peerId : null;
$scope.loading = false;
$scope.selectedWalletId = false;
$scope.walletIds = walletFactory.getWalletIds();
$scope.listWalletIds = function() {
return walletFactory.getWalletIds();
};
var _setupUxHandlers = function(w) {
w.on('created', function() {
$location.path('peer');
$rootScope.wallet = w;
$rootScope.$digest();
});
w.on('refresh', function() {
console.log('[signin.js.23] RECEIVED REFRESH'); //TODO
$rootScope.$digest();
});
w.on('openError', function(){
$scope.loading = false;
$rootScope.flashMessage = {type:'error', message: 'Wallet not found'};
$location.path('signin');
});
};
$scope.selectedWalletId = $scope.walletIds.length ? $scope.walletIds[0]:null;
$scope.create = function() {
$location.path('setup');
@ -40,16 +21,18 @@ console.log('[signin.js.23] RECEIVED REFRESH'); //TODO
$scope.loading = true;
var w = walletFactory.open(walletId);
_setupUxHandlers(w);
controllerUtils.setupUxHandlers(w);
w.netStart();
};
$scope.join = function(cid) {
console.log('[signin.js.42:join:]'); //TODO
$scope.loading = true;
walletFactory.network.on('openError', function() {
controllerUtils.onError($scope);
$rootScope.$digest();
});
walletFactory.connectTo(cid, function(w) {
console.log('[signin.js.50]'); //TODO
_setupUxHandlers(w);
controllerUtils.setupUxHandlers(w);
w.netStart();
});
};

View file

@ -1,29 +1,33 @@
'use strict';
angular.module('copay.transactions').controller('TransactionsController',
function($scope, $rootScope, $location) {
function($scope, $rootScope, $location, Socket, controllerUtils) {
$scope.title = 'Transactions';
$scope.oneAtATime = true;
if (!$rootScope.wallet.id) {
if (!$rootScope.wallet || !$rootScope.wallet.id) {
$location.path('signin');
}
else {
$scope.txsinput = [
{
fromAddr: "n3zUqNR7Bbbc4zJhPVj1vG2Lx66K3Xhzvb",
toAddr: "msvv2mDfE298s7boXwALq4Dqv77K3TWRZ1",
amount: 23.9982
},
{
fromAddr: "my9wnLwwUrwpNfEgSrWY62ymEGf1edKf4J",
toAddr: "monCusNiDuptf68rtr58hEjKpJt6cW6zwS",
amount: 2.22
}
];
$scope.txsinput = [
{
fromAddr: "n3zUqNR7Bbbc4zJhPVj1vG2Lx66K3Xhzvb",
toAddr: "msvv2mDfE298s7boXwALq4Dqv77K3TWRZ1",
amount: 23.9982
},
{
fromAddr: "my9wnLwwUrwpNfEgSrWY62ymEGf1edKf4J",
toAddr: "monCusNiDuptf68rtr58hEjKpJt6cW6zwS",
amount: 2.22
$scope.txsoutput = $rootScope.wallet.getTxProposals();
var socket = Socket($scope);
socket.on('connect', controllerUtils.handleTransactionByAddress($scope));
}
];
$scope.txsoutput = $rootScope.wallet.getTxProposals();
$scope.sign = function (ntxid) {
var w = $rootScope.wallet;

View file

@ -29,15 +29,6 @@ function _asyncForEach(array, fn, callback) {
}
};
Insight.prototype.getBalance = function(unspent) {
var balance = 0;
for(var i=0;i<unspent.length; i++) {
balance = balance + unspent[i].amount;
}
return balance;
};
Insight.prototype.listUnspent = function(addresses, cb) {
var self = this;

View file

@ -166,10 +166,7 @@ PublicKeyRing.prototype.getAddress = function (index, isChange) {
this._checkIndexRange(index, isChange);
var script = this.getRedeemScript(index,isChange);
var hash = coinUtil.sha256ripe160(script.getBuffer());
var version = this.network.P2SHVersion;
var addr = new Address(version, hash);
return addr;
return Address.fromScript(script, this.network.name);
};
PublicKeyRing.prototype.getScriptPubKeyHex = function (index, isChange) {
@ -185,10 +182,11 @@ PublicKeyRing.prototype.generateAddress = function(isChange) {
var ret =
this.getAddress(isChange ? this.changeAddressIndex : this.addressIndex, isChange);
if (isChange)
if (isChange) {
this.changeAddressIndex++;
else
} else {
this.addressIndex++;
}
return ret;

View file

@ -96,11 +96,12 @@ Wallet.prototype._handleTxProposals = function(senderId, data, isInbound) {
Wallet.prototype._handleData = function(senderId, data, isInbound) {
if (this.id !== data.walletId)
throw new Error('wrong message received: Bad wallet ID');
if (this.id !== data.walletId) {
this.emit('badMessage',senderId);
this.log('badMessage FROM:', senderId); //TODO
return;
}
this.log('[Wallet.js.98]' , data.type); //TODO
switch(data.type) {
case 'publicKeyRing':
this._handlePublicKeyRing(senderId, data, isInbound);
@ -108,18 +109,17 @@ Wallet.prototype._handleData = function(senderId, data, isInbound) {
case 'txProposals':
this._handleTxProposals(senderId, data, isInbound);
break;
case 'abort':
this.emit('abort');
break;
}
};
Wallet.prototype._handleNetworkChange = function(newPeer) {
if (!newPeer) return;
this.log('#### Setting new PEER:', newPeer);
this.sendWalletId(newPeer);
this.sendPublicKeyRing(newPeer);
this.sendTxProposals(newPeer);
if (newPeer) {
this.log('#### Setting new PEER:', newPeer);
this.sendWalletId(newPeer);
this.sendPublicKeyRing(newPeer);
this.sendTxProposals(newPeer);
}
this.emit('refresh');
};
Wallet.prototype._optsToObj = function () {
@ -136,10 +136,17 @@ Wallet.prototype._optsToObj = function () {
Wallet.prototype.netStart = function() {
var self = this;
var net = this.network;
net.removeAllListeners();
net.on('networkChange', self._handleNetworkChange.bind(self) );
net.on('data', self._handleData.bind(self) );
net.on('open', function() {}); // TODO
net.on('close', function() {}); // TODO
net.on('openError', function() {
this.log('[Wallet.js.132:openError:] GOT openError'); //TODO
self.emit('openError');
});
net.on('close', function() {
self.emit('close');
});
net.start(function(peerId) {
self.emit('created');
});
@ -211,6 +218,7 @@ Wallet.prototype.sendPublicKeyRing = function(recipients) {
this.emit('publicKeyRingUpdated', this.publicKeyRing);
};
Wallet.prototype.generateAddress = function() {
var addr = this.publicKeyRing.generateAddress();
this.store();
@ -303,10 +311,34 @@ Wallet.prototype.getAddressesStr = function() {
return ret;
};
Wallet.prototype.getTotalBalance = function(cb) {
this.getBalance(this.getAddressesStr(), function(balance) {
return cb(balance);
});
};
Wallet.prototype.getBalance = function(addrs, cb) {
var balance = 0;
this.listUnspent(addrs, function(utxos) {
for(var i=0;i<utxos.length; i++) {
balance = balance + utxos[i].amount;
}
if (balance) {
if (balance === parseInt(balance)) {
balance = balance;
}
else {
balance = balance.toFixed(8);
}
}
return cb(balance);
});
};
Wallet.prototype.listUnspent = function(cb) {
this.blockchain.listUnspent(this.getAddressesStr(), cb);
Wallet.prototype.listUnspent = function(addrs, cb) {
this.blockchain.listUnspent(addrs, function(utxos) {
return cb(utxos);
});
};
@ -326,7 +358,7 @@ Wallet.prototype.createTx = function(toAddress, amountSatStr, opts, cb) {
opts.remainderOut={ address: this.publicKeyRing.generateAddress(true).toString()};
}
self.listUnspent(function(utxos) {
self.listUnspent(self.getAddressesStr(), function(utxos) {
// TODO check enough funds, etc.
self.createTxSync(toAddress, amountSatStr, utxos, opts);
self.store();

View file

@ -148,12 +148,14 @@ WalletFactory.prototype.openRemote = function(peedId) {
opts.storage = this.storage;
opts.network = this.network;
opts.blockchain = this.blockchain;
opts.spendUnconfirmed = opts.spendUnconfirmed || this.walletDefaults.spendUnconfirmed;
opts.spendUnconfirmed = typeof opts.spendUnconfirmed === undefined
?this.walletDefaults.spendUnconfirmed : opts.spendUnconfirmed;
opts.requiredCopayers = requiredCopayers;
opts.totalCopayers = totalCopayers;
var w = new Wallet(opts);
w.store();
this.addWalletId(w.id);
return w;
};

View file

@ -16,11 +16,18 @@ var EventEmitter= imports.EventEmitter || require('events').EventEmitter;
*/
function Network(opts) {
var self = this;
opts = opts || {};
this.peerId = opts.peerId;
this.apiKey = opts.apiKey || 'lwjd5qra8257b9';
this.debug = opts.debug || 3;
this.maxPeers = opts.maxPeers || 5;
this.opts = { key: opts.key };
// For using your own peerJs server
['port', 'host', 'path', 'debug'].forEach(function(k) {
if (opts[k]) self.opts[k]=opts[k];
});
this.connectedPeers = [];
}
@ -61,14 +68,9 @@ Network._arrayRemove = function(el, array) {
return array;
};
// DEBUG
Network.prototype._showConnectedPeers = function() {
// console.log("### CONNECTED PEERS", this.connectedPeers);
};
Network.prototype._onClose = function(peerId) {
this.connectedPeers = Network._arrayRemove(peerId, this.connectedPeers);
this._notify();
this._notifyNetworkChange();
};
Network.prototype._connectToPeers = function(peerIds) {
@ -97,7 +99,7 @@ Network.prototype._onData = function(data, isInbound) {
switch(obj.data.type) {
case 'peerList':
this._connectToPeers(obj.data.peers);
this._notify();
this._notifyNetworkChange();
break;
case 'disconnect':
this._onClose(obj.sender);
@ -133,6 +135,13 @@ Network.prototype._addPeer = function(peerId, isInbound) {
}
};
Network.prototype._checkAnyPeer = function() {
if (!this.connectedPeers.length) {
console.log('EMIT openError: no more peers, not even you!');
this.emit('openError');
}
}
Network.prototype._setupConnectionHandlers = function(dataConn, isInbound) {
var self=this;
@ -144,7 +153,7 @@ Network.prototype._setupConnectionHandlers = function(dataConn, isInbound) {
dataConn.peer, isInbound);
self._addPeer(dataConn.peer, isInbound);
self._notify( isInbound ? dataConn.peer : null);
self._notifyNetworkChange( isInbound ? dataConn.peer : null);
this.emit('open');
}
});
@ -155,19 +164,19 @@ Network.prototype._setupConnectionHandlers = function(dataConn, isInbound) {
dataConn.on('error', function(e) {
console.log('### DATA ERROR',e ); //TODO
self.emit('dataError');
});
dataConn.on('close', function() {
if (self.closing) return;
self.closing=1;
console.log('### CLOSE RECV FROM:', dataConn.peer);
self._onClose(dataConn.peer);
this.emit('close');
self._checkAnyPeer();
});
};
Network.prototype._notify = function(newPeer) {
this._showConnectedPeers();
Network.prototype._notifyNetworkChange = function(newPeer) {
console.log('[WebRTC.js.164:_notifyNetworkChange:]', newPeer); //TODO
this.emit('networkChange', newPeer);
};
@ -178,7 +187,7 @@ Network.prototype._setupPeerHandlers = function(openCallback) {
p.on('open', function(peerId) {
self.peerId = peerId;
self.connectedPeers = [peerId];
self._notify();
self._notifyNetworkChange();
return openCallback(peerId);
});
@ -187,7 +196,7 @@ Network.prototype._setupPeerHandlers = function(openCallback) {
self.peer.disconnect();
self.peer.destroy();
self.peer = null;
this.emit('abort');
self._checkAnyPeer();
});
p.on('connection', function(dataConn) {
@ -210,11 +219,7 @@ Network.prototype.start = function(openCallback) {
// Start PeerJS Peer
if (this.peer) return openCallback(); // This is for connectTo-> peer is started before
this.peer = new Peer(this.peerId, {
key: this.apiKey, // TODO: we need our own PeerServer KEY (http://peerjs.com/peerserver)
debug: this.debug,
});
this.peer = new Peer(this.peerId, this.opts);
this._setupPeerHandlers(openCallback);
};
@ -239,6 +244,7 @@ Network.prototype._sendToOne = function(peerId, data, cb) {
Network.prototype.send = function(peerIds, data, cb) {
var self=this;
console.log('[WebRTC.js.242] SENDING ', data.type); //TODO
if (!peerIds) {
peerIds = this.connectedPeers;
data.isBroadcast = 1;
@ -248,6 +254,7 @@ Network.prototype.send = function(peerIds, data, cb) {
var l = peerIds.length;
var i = 0;
peerIds.forEach(function(peerId) {
console.log('[WebRTC.js.258:peerId:]',peerId); //TODO
self._sendToOne(peerId, data, function () {
if (++i === l && typeof cb === 'function') cb();
});
@ -263,7 +270,6 @@ Network.prototype.connectTo = function(peerId) {
console.log('### STARTING TO CONNECT TO:' + peerId );
var dataConn = this.peer.connect(peerId, {
// label: 'wallet',
serialization: 'none',
reliable: true,
metadata: { message: 'hi copayer!' }
@ -276,7 +282,6 @@ Network.prototype.connectTo = function(peerId) {
Network.prototype.disconnect = function(cb) {
var self = this;
self.closing = 1;
this.send(null, { type: 'disconnect' }, function() {
self.connectedPeers = [];
self.peerId = null;

View file

@ -54,13 +54,17 @@ Storage.prototype.remove = function(walletId, k) {
Storage.prototype.getWalletIds = function() {
var walletIds = [];
var uniq = {};
for (var i = 0; i < localStorage.length; i++) {
var key = localStorage.key(i);
var split = key.split('::');
if (split.length == 2) {
var walletId = split[0];
walletIds.push(walletId);
if (typeof uniq[walletId] === 'undefined' ) {
walletIds.push(walletId);
uniq[walletId] = 1;
}
}
}

View file

@ -0,0 +1,71 @@
'use strict';
angular.module('copay.controllerUtils').factory('controllerUtils', function ($rootScope, $location, Socket) {
var root = {};
root.logout = function(scope) {
delete $rootScope['wallet'];
$rootScope.totalBalance = 0;
$location.path('signin');
};
root.onError = function(scope) {
if (scope) scope.loading = false;
$rootScope.flashMessage = {type:'error', message: 'Could not connect to peer'};
root.logout();
}
root.onErrorDigest = function(scope) {
root.onError(scope);
$rootScope.$digest();
}
root.setupUxHandlers = function(w) {
w.on('badMessage', function(peerId) {
$rootScope.flashMessage = {type:'error', message: 'Received wrong message from peer id:' + peerId};
});
w.on('created', function() {
$location.path('peer');
$rootScope.wallet = w;
// Initial getBalance
$rootScope.wallet.getTotalBalance(function(balance) {
$rootScope.totalBalance = balance;
$rootScope.$digest();
});
});
w.on('refresh', function() {
console.log('[controllerUtils.js] Refreshing'); //TODO
$rootScope.$digest();
});
w.on('openError', root.onErrorDigest);
w.on('close', root.onErrorDigest);
};
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.getTotalBalance(function(balance) {
scope.$apply(function() {
$rootScope.totalBalance = balance;
});
console.log('New balance:', balance);
});
});
});
};
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;
};
});