fix conflicts

This commit is contained in:
Matias Alejo Garcia 2014-06-24 13:02:25 -03:00
commit f1257d054c
49 changed files with 1015 additions and 755 deletions

View file

@ -19,7 +19,7 @@ var log = function() {
// From the bundle
var copay = require('copay');
var copayApp = window.copayApp = angular.module('copayApp',[
var copayApp = window.copayApp = angular.module('copayApp', [
'ngRoute',
'angularMoment',
'mm.foundation',
@ -34,4 +34,3 @@ angular.module('copayApp.filters', []);
angular.module('copayApp.services', []);
angular.module('copayApp.controllers', []);
angular.module('copayApp.directives', []);

View file

@ -2,35 +2,34 @@
angular.module('copayApp.controllers').controller('FooterController', function($rootScope, $sce, $scope, $http) {
if (config.themes && Array.isArray(config.themes) && config.themes[0]) {
$scope.themes = config.themes;
}
else {
$scope.themes = ['default'];
if (config.themes && Array.isArray(config.themes) && config.themes[0]) {
$scope.themes = config.themes;
} else {
$scope.themes = ['default'];
}
$scope.theme = 'css/tpl-' + $scope.themes[0] + '.css';
$scope.change_theme = function(name) {
$scope.theme = 'css/tpl-' + name + '.css';
};
$scope.version = copay.version;
$scope.getVideoURL = function(copayer) {
if (config.disableVideo) return;
var vi = $rootScope.videoInfo[copayer]
if (!vi) return;
if ($rootScope.wallet.getOnlinePeerIDs().indexOf(copayer) === -1) {
// peer disconnected, remove his video
delete $rootScope.videoInfo[copayer]
return;
}
$scope.theme = 'css/tpl-' + $scope.themes[0] + '.css';
$scope.change_theme = function(name) {
$scope.theme = 'css/tpl-' + name + '.css';
};
$scope.version = copay.version;
$scope.getVideoURL = function(copayer) {
if (config.disableVideo) return;
var vi = $rootScope.videoInfo[copayer]
if (!vi) return;
if ($rootScope.wallet.getOnlinePeerIDs().indexOf(copayer) === -1) {
// peer disconnected, remove his video
delete $rootScope.videoInfo[copayer]
return;
}
var encoded = vi.url;
var url = decodeURI(encoded);
var trusted = $sce.trustAsResourceUrl(url);
return trusted;
};
});
var encoded = vi.url;
var url = decodeURI(encoded);
var trusted = $sce.trustAsResourceUrl(url);
return trusted;
};
});

View file

@ -2,8 +2,7 @@
angular.module('copayApp.controllers').controller('HeaderController',
function($scope, $rootScope, $location, notification, $http, controllerUtils) {
$scope.menu = [
{
$scope.menu = [{
'title': 'Addresses',
'icon': 'fi-address-book',
'link': '#/addresses'
@ -21,15 +20,27 @@ angular.module('copayApp.controllers').controller('HeaderController',
'link': '#/backup'
}];
$http.get('https://api.github.com/repos/bitpay/copay/tags').success(function(data){
var toInt = function (s) { return parseInt(s); };
$scope.getNumber = function(num) {
return new Array(num);
}
$http.get('https://api.github.com/repos/bitpay/copay/tags').success(function(data) {
var toInt = function(s) {
return parseInt(s);
};
var latestVersion = data[0].name.replace('v', '').split('.').map(toInt);
var currentVersion = copay.version.split('.').map(toInt);
if (currentVersion[0] < latestVersion[0]){
$scope.updateVersion = {class: 'error', version:data[0].name};
if (currentVersion[0] < latestVersion[0]) {
$scope.updateVersion = {
class: 'error',
version: data[0].name
};
} else if (currentVersion[0] == latestVersion[0] && currentVersion[1] < latestVersion[1]) {
$scope.updateVersion = {class: 'info', version:data[0].name};
}
$scope.updateVersion = {
class: 'info',
version: data[0].name
};
}
});
$rootScope.unitName = config.unitName;
@ -55,7 +66,7 @@ angular.module('copayApp.controllers').controller('HeaderController',
$rootScope.$watch('receivedFund', function(receivedFund) {
if (receivedFund) {
var currentAddr;
for(var i=0;i<$rootScope.addrInfos.length;i++) {
for (var i = 0; i < $rootScope.addrInfos.length; i++) {
var addrinfo = $rootScope.addrInfos[i];
if (addrinfo.address.toString() == receivedFund[1] && !addrinfo.isChange) {
currentAddr = addrinfo.address.toString();
@ -79,12 +90,12 @@ angular.module('copayApp.controllers').controller('HeaderController',
$scope.isActive = function(item) {
if (item.link && item.link.replace('#','') == $location.path()) {
if (item.link && item.link.replace('#', '') == $location.path()) {
return true;
}
return false;
};
$scope.signout = function() {
logout();
$scope.clearFlashMessage();
@ -93,7 +104,7 @@ angular.module('copayApp.controllers').controller('HeaderController',
$scope.refresh = function() {
var w = $rootScope.wallet;
w.connectToAll();
if ($rootScope.addrInfos.length > 0 ) {
if ($rootScope.addrInfos.length > 0) {
controllerUtils.updateBalance(function() {
$rootScope.$digest();
});

View file

@ -5,11 +5,14 @@ angular.module('copayApp.controllers').controller('ImportController',
$scope.title = 'Import a backup';
var reader = new FileReader();
var _importBackup = function(encryptedObj) {
Passphrase.getBase64Async($scope.password, function(passphrase){
Passphrase.getBase64Async($scope.password, function(passphrase) {
walletFactory.import(encryptedObj, passphrase, function(err, w) {
if (err) {
$scope.loading = false;
$rootScope.$flashMessage = { message: err.errMsg || 'Wrong password', type: 'error'};
$rootScope.$flashMessage = {
message: err.errMsg || 'Wrong password',
type: 'error'
};
$rootScope.$digest();
return;
}
@ -43,7 +46,10 @@ angular.module('copayApp.controllers').controller('ImportController',
$scope.import = function(form) {
if (form.$invalid) {
$scope.loading = false;
$rootScope.$flashMessage = { message: 'There is an error in the form. Please, try again', type: 'error'};
$rootScope.$flashMessage = {
message: 'There is an error in the form. Please, try again',
type: 'error'
};
return;
}
@ -53,7 +59,10 @@ angular.module('copayApp.controllers').controller('ImportController',
if (!backupFile && !backupText) {
$scope.loading = false;
$rootScope.$flashMessage = { message: 'Please, select your backup file or paste the text', type: 'error'};
$rootScope.$flashMessage = {
message: 'Please, select your backup file or paste the text',
type: 'error'
};
$scope.loading = false;
return;
}
@ -62,8 +71,7 @@ angular.module('copayApp.controllers').controller('ImportController',
if (backupFile) {
reader.readAsBinaryString(backupFile);
}
else {
} else {
_importBackup(backupText);
}
};

View file

@ -33,7 +33,7 @@ angular.module('copayApp.controllers').controller('SendController',
$scope.submitForm = function(form) {
if (form.$invalid) {
$rootScope.$flashMessage = {
message: 'You can not send a proposal transaction. Please, try again',
message: 'Unable to send a transaction proposal. Please, try again',
type: 'error'
};
return;
@ -207,7 +207,7 @@ angular.module('copayApp.controllers').controller('SendController',
templateUrl: 'addressBookModal.html',
windowClass: 'tiny',
controller: function($scope, $modalInstance) {
$scope.submitAddressBook = function(form) {
if (form.$invalid) {
$rootScope.$flashMessage = {
@ -254,4 +254,8 @@ angular.module('copayApp.controllers').controller('SendController',
});
};
$scope.topAmount = function() {
var maxSat = ($rootScope.availableBalance * config.unitToSatoshi).toFixed(0) - bitcore.TransactionBuilder.FEE_PER_1000B_SAT;
$scope.amount = maxSat / config.unitToSatoshi;
};
});

View file

@ -51,7 +51,7 @@ angular.module('copayApp.controllers').controller('SetupController',
var updateRCSelect = function(n) {
$scope.requiredCopayers = (valid_pairs[[parseInt(n / 2 + 1), n]] > 0 || config.networkName === 'testnet') ?
parseInt(n / 2 + 1) : 1;
parseInt(n / 2 + 1) : 1;
$scope.RCValues = [];
for (var m = 1; m <= n; m++) {
if (valid_pairs[[m, n]] > 0 || config.networkName === 'testnet') {

View file

@ -125,7 +125,7 @@ angular.module('copayApp.directives')
.directive('contact', function() {
return {
restrict: 'E',
link:function(scope, element, attrs) {
link: function(scope, element, attrs) {
if (!scope.wallet) return;
var address = attrs.address;
@ -137,7 +137,7 @@ angular.module('copayApp.directives')
element.append(address);
}
}
};
};
})
.directive('highlightOnChange', function() {
return {

View file

@ -1,11 +1,13 @@
'use strict';
angular.module('copayApp.filters', [])
.filter('amTimeAgo', ['amMoment', function(amMoment) {
return function(input) {
return amMoment.preprocessDate(input).fromNow();
};
}])
.filter('amTimeAgo', ['amMoment',
function(amMoment) {
return function(input) {
return amMoment.preprocessDate(input).fromNow();
};
}
])
.filter('paged', function() {
return function(elements) {
if (elements) {
@ -17,41 +19,15 @@ angular.module('copayApp.filters', [])
})
.filter('limitAddress', function() {
return function(elements, showAll) {
var addrs = [];
if (elements.length > 0) {
if (showAll) {
return elements;
}
if (elements.length == 1) {
return elements;
}
else {
for (var i=0;i<elements.length;i++) {
if (!elements[i].isChange && (!elements[i].balance || elements[i].balance == 0)) {
addrs.push(elements[i]);
break;
}
}
for (var i=0;i<elements.length;i++) {
if (elements[i].balance && elements[i].balance > 0) {
addrs.push(elements[i]);
}
}
return addrs;
}
if (elements.length <= 1 || showAll) {
return elements;
}
// Show last 3 non-change addresses plus those with balance
var addrs = elements.filter(function(e, i) {
return (!e.isChange && i < 3) || (e.balance && e.balance > 0);
});
return addrs;
};
})
.filter('withoutFunds', function() {
return function(elements) {
var len = 0;
for (var i=0;i<elements.length;i++) {
if (!elements[i].balance || elements[i].balance == 0) {
len++;
}
}
return len;
};
})
;
});

View file

@ -168,15 +168,29 @@ Insight.prototype.checkActivity = function(addresses, cb) {
if (!addresses) throw new Error('address must be set');
this.getTransactions(addresses, function onResult(txs) {
var flatArray = function (xss) { return xss.reduce(function(r, xs) { return r.concat(xs); }, []); };
var getInputs = function (t) { return t.vin.map(function (vin) { return vin.addr }); };
var getOutputs = function (t) { return flatArray(
t.vout.map(function (vout) { return vout.scriptPubKey.addresses; })
);};
var flatArray = function(xss) {
return xss.reduce(function(r, xs) {
return r.concat(xs);
}, []);
};
var getInputs = function(t) {
return t.vin.map(function(vin) {
return vin.addr
});
};
var getOutputs = function(t) {
return flatArray(
t.vout.map(function(vout) {
return vout.scriptPubKey.addresses;
})
);
};
var activityMap = new Array(addresses.length);
var activeAddress = flatArray(txs.map(function(t) { return getInputs(t).concat(getOutputs(t)); }));
activeAddress.forEach(function (addr) {
var activeAddress = flatArray(txs.map(function(t) {
return getInputs(t).concat(getOutputs(t));
}));
activeAddress.forEach(function(addr) {
var index = addresses.indexOf(addr);
if (index != -1) activityMap[index] = true;
});

View file

@ -1,17 +1,17 @@
'use strict';
var imports = require('soop').imports();
var bitcore = require('bitcore');
var HK = bitcore.HierarchicalKey;
var WalletKey = bitcore.WalletKey;
var networks = bitcore.networks;
var util = bitcore.util;
var Structure = require('./Structure');
var imports = require('soop').imports();
var bitcore = require('bitcore');
var HK = bitcore.HierarchicalKey;
var WalletKey = bitcore.WalletKey;
var networks = bitcore.networks;
var util = bitcore.util;
var Structure = require('./Structure');
function PrivateKey(opts) {
opts = opts || {};
this.network = opts.networkName === 'testnet' ?
this.network = opts.networkName === 'testnet' ?
networks.testnet : networks.livenet;
var init = opts.extendedPrivateKeyString || this.network.name;
this.bip = opts.HK || new HK(init);
@ -81,15 +81,19 @@ PrivateKey.prototype.getForPaths = function(paths) {
PrivateKey.prototype.getForPath = function(path) {
var pk = this.privateKeyCache[path];
if (!pk) {
var derivedHK = this._getHK(path);
var derivedHK = this._getHK(path);
pk = this.privateKeyCache[path] = derivedHK.eckey.private.toString('hex');
}
var wk = new WalletKey({network: this.network});
wk.fromObj({priv: pk});
var wk = new WalletKey({
network: this.network
});
wk.fromObj({
priv: pk
});
return wk;
};
PrivateKey.prototype.get = function(index,isChange) {
PrivateKey.prototype.get = function(index, isChange) {
var path = Structure.FullBranch(index, isChange);
return this.getForPath(path);
};
@ -99,11 +103,11 @@ PrivateKey.prototype.getAll = function(receiveIndex, changeIndex) {
throw new Error('Invalid parameters');
var ret = [];
for(var i=0;i<receiveIndex; i++) {
ret.push(this.get(i,false));
for (var i = 0; i < receiveIndex; i++) {
ret.push(this.get(i, false));
}
for(var i=0; i<changeIndex; i++) {
ret.push(this.get(i,true));
for (var i = 0; i < changeIndex; i++) {
ret.push(this.get(i, true));
}
return ret;
};

View file

@ -77,7 +77,7 @@ TxProposal.prototype.mergeMetadata = function(v1, author) {
Object.keys(v1.seenBy).forEach(function(k) {
if (!v0.seenBy[k]) {
if (k != author) throw new Error('Non authoritative seenBy change by '+author);
if (k != author) throw new Error('Non authoritative seenBy change by ' + author);
v0.seenBy[k] = v1.seenBy[k];
events.push({
type: 'seen',
@ -89,7 +89,7 @@ TxProposal.prototype.mergeMetadata = function(v1, author) {
Object.keys(v1.signedBy).forEach(function(k) {
if (!v0.signedBy[k]) {
if (k != author) throw new Error('Non authoritative signedBy change by '+author);
if (k != author) throw new Error('Non authoritative signedBy change by ' + author);
v0.signedBy[k] = v1.signedBy[k];
events.push({
type: 'signed',
@ -101,7 +101,7 @@ TxProposal.prototype.mergeMetadata = function(v1, author) {
Object.keys(v1.rejectedBy).forEach(function(k) {
if (!v0.rejectedBy[k]) {
if (k != author) throw new Error('Non authoritative rejectedBy change by '+author);
if (k != author) throw new Error('Non authoritative rejectedBy change by ' + author);
v0.rejectedBy[k] = v1.rejectedBy[k];
events.push({
type: 'rejected',

View file

@ -44,7 +44,7 @@ function Wallet(opts) {
this.token = opts.token;
this.tokenTime = opts.tokenTime;
}
this.verbose = opts.verbose;
this.publicKeyRing.walletId = this.id;
this.txProposals.walletId = this.id;
@ -142,12 +142,11 @@ Wallet.prototype._handleAddressBook = function(senderId, data, isInbound) {
this.log('RECV ADDRESSBOOK:', data);
var rcv = data.addressBook;
var hasChange;
for(var key in rcv) {
for (var key in rcv) {
if (!this.addressBook[key]) {
this.addressBook[key] = rcv[key];
hasChange = true;
}
else {
} else {
if (rcv[key].createdTs > this.addressBook[key].createdTs) {
this.addressBook[key] = rcv[key];
hasChange = true;
@ -395,7 +394,7 @@ Wallet.prototype.sendAllTxProposals = function(recipients) {
Wallet.prototype.sendTxProposal = function(ntxid, recipients) {
preconditions.checkArgument(ntxid);
preconditions.checkState(this.txProposals.txps[ntxid]);
this.log('### SENDING txProposal '+ntxid+' TO:', recipients || 'All', this.txProposals);
this.log('### SENDING txProposal ' + ntxid + ' TO:', recipients || 'All', this.txProposals);
this.network.send(recipients, {
type: 'txProposal',
txProposal: this.txProposals.txps[ntxid].toObj(),
@ -771,7 +770,7 @@ Wallet.prototype.updateIndexes = function(callback) {
Wallet.prototype.deriveAddresses = function(index, amout, isChange) {
var ret = new Array(amout);
for(var i = 0; i < amout; i++) {
for (var i = 0; i < amout; i++) {
ret[i] = this.publicKeyRing.getAddress(index + i, isChange).toString();
}
return ret;
@ -791,7 +790,7 @@ Wallet.prototype.indexDiscovery = function(start, change, gap, cb) {
// Optimize window to minimize the derivations.
var scanWindow = (lastActive == -1) ? gap : gap - (scanIndex - lastActive) + 1;
var addresses = self.deriveAddresses(scanIndex, scanWindow, change);
self.blockchain.checkActivity(addresses, function(err, actives){
self.blockchain.checkActivity(addresses, function(err, actives) {
if (err) throw err;
// Check for new activities in the newlly scanned addresses
@ -804,7 +803,9 @@ Wallet.prototype.indexDiscovery = function(start, change, gap, cb) {
next();
});
},
function _while() { return hasActivity; },
function _while() {
return hasActivity;
},
function _finnaly(err) {
if (err) return cb(err);
cb(null, lastActive);

View file

@ -1,10 +1,10 @@
'use strict';
var imports = require('soop').imports();
var EventEmitter= imports.EventEmitter || require('events').EventEmitter;
var bitcore = require('bitcore');
var util = bitcore.util;
var extend = require('util')._extend;
var imports = require('soop').imports();
var EventEmitter = imports.EventEmitter || require('events').EventEmitter;
var bitcore = require('bitcore');
var util = bitcore.util;
var extend = require('util')._extend;
/*
* Emits
* 'connect'
@ -19,17 +19,17 @@ var extend = require('util')._extend;
*/
function Network(opts) {
var self = this;
opts = opts || {};
this.apiKey = opts.apiKey || 'lwjd5qra8257b9';
this.debug = opts.debug || 3;
this.maxPeers = opts.maxPeers || 10;
var self = this;
opts = opts || {};
this.apiKey = opts.apiKey || 'lwjd5qra8257b9';
this.debug = opts.debug || 3;
this.maxPeers = opts.maxPeers || 10;
this.reconnectAttempts = opts.reconnectAttempts || 3;
this.sjclParams = opts.sjclParams || {
salt: 'f28bfb49ef70573c',
iter:500,
mode:'ccm',
ts:parseInt(64),
this.sjclParams = opts.sjclParams || {
salt: 'f28bfb49ef70573c',
iter: 500,
mode: 'ccm',
ts: parseInt(64),
};
this.opts = {};
['config', 'port', 'host', 'path', 'debug', 'key', 'secure'].forEach(function(k) {
@ -47,11 +47,11 @@ Network.prototype.cleanUp = function() {
this.privkey = null; //TODO: hide privkey in a closure
this.copayerId = null;
this.signingKey = null;
this.allowedCopayerIds=null;
this.isInboundPeerAuth=[];
this.copayerForPeer={};
this.connections={};
this.criticalErr='';
this.allowedCopayerIds = null;
this.isInboundPeerAuth = [];
this.copayerForPeer = {};
this.connections = {};
this.criticalErr = '';
if (this.peer) {
this.peer.disconnect();
this.peer.destroy();
@ -62,7 +62,7 @@ Network.prototype.cleanUp = function() {
this.tries = 0;
};
Network.parent=EventEmitter;
Network.parent = EventEmitter;
// Array helpers
Network._arrayDiff = function(a, b) {
@ -99,9 +99,9 @@ Network._arrayRemove = function(el, array) {
};
Network.prototype.connectedCopayers = function() {
var ret =[];
for(var i in this.connectedPeers){
var copayerId =this.copayerForPeer[this.connectedPeers[i]];
var ret = [];
for (var i in this.connectedPeers) {
var copayerId = this.copayerForPeer[this.connectedPeers[i]];
if (copayerId) ret.push(copayerId);
}
return ret;
@ -126,7 +126,7 @@ Network.prototype._onClose = function(peerID) {
Network.prototype.connectToCopayers = function(copayerIds) {
var self = this;
var arrayDiff= Network._arrayDiff(copayerIds, self.connectedCopayers());
var arrayDiff = Network._arrayDiff(copayerIds, self.connectedCopayers());
arrayDiff.forEach(function(copayerId) {
if (self.allowedCopayerIds && !self.allowedCopayerIds[copayerId]) {
@ -146,7 +146,7 @@ Network.prototype._sendHello = function(copayerId) {
Network.prototype._addConnectedCopayer = function(copayerId, isInbound) {
var peerId = this.peerFromCopayer(copayerId);
this._addCopayerMap(peerId,copayerId);
this._addCopayerMap(peerId, copayerId);
Network._arrayPushOnce(peerId, this.connectedPeers);
this.emit('connect', copayerId);
};
@ -158,15 +158,15 @@ Network.prototype._onData = function(enchex, isInbound, peerId) {
var privkey = this.privkey;
try {
try {
var data = this._decrypt(privkey, encbuf);
payload= JSON.parse(data);
payload = JSON.parse(data);
} catch (e) {
this._deletePeer(peerId);
return;
}
if(isInbound && payload.type === 'hello') {
if (isInbound && payload.type === 'hello') {
var payloadStr = JSON.stringify(payload);
if (this.allowedCopayerIds && !this.allowedCopayerIds[payload.copayerId]) {
@ -179,13 +179,13 @@ Network.prototype._onData = function(enchex, isInbound, peerId) {
return;
}
if ( !this.copayerForPeer[peerId] || (isInbound && !this.isInboundPeerAuth[peerId]) ) {
if (!this.copayerForPeer[peerId] || (isInbound && !this.isInboundPeerAuth[peerId])) {
this._deletePeer(peerId);
return;
}
var self=this;
switch(payload.type) {
var self = this;
switch (payload.type) {
case 'disconnect':
this._onClose(peerId);
break;
@ -206,21 +206,21 @@ Network.prototype._setupConnectionHandlers = function(dataConn, toCopayerId) {
var isInbound = toCopayerId ? false : true;
dataConn.on('open', function() {
if (!Network._inArray(dataConn.peer, self.connectedPeers) &&
!self.connections[dataConn.peer]) {
if (!Network._inArray(dataConn.peer, self.connectedPeers) &&
!self.connections[dataConn.peer]) {
self.connections[dataConn.peer] = dataConn;
// The connecting peer send hello
if(toCopayerId) {
if (toCopayerId) {
self.emit('connected');
self._sendHello(toCopayerId);
self._sendHello(toCopayerId);
self._addConnectedCopayer(toCopayerId);
}
}
});
dataConn.on('data', function(data) {
dataConn.on('data', function(data) {
self._onData(data, isInbound, dataConn.peer);
});
@ -244,14 +244,14 @@ Network.prototype._setupPeerHandlers = function(openCallback) {
p.on('open', function() {
self.connectedPeers = [self.peerId];
self.copayerForPeer[self.peerId]= self.copayerId;
self.copayerForPeer[self.peerId] = self.copayerId;
return openCallback();
});
p.on('error', function(err) {
console.log('RECV ERROR: ', err); //TODO
if (!err.message.match(/Could\snot\sconnect\sto peer/) ) {
self.criticalError=err.message;
if (!err.message.match(/Could\snot\sconnect\sto peer/)) {
self.criticalError = err.message;
}
});
@ -270,11 +270,9 @@ Network.prototype._setupPeerHandlers = function(openCallback) {
Network.prototype._addCopayerMap = function(peerId, copayerId) {
if (!this.copayerForPeer[peerId]) {
if(Object.keys(this.copayerForPeer).length < this.maxPeers) {
this.copayerForPeer[peerId]=copayerId;
}
else {
}
if (Object.keys(this.copayerForPeer).length < this.maxPeers) {
this.copayerForPeer[peerId] = copayerId;
} else {}
}
};
@ -288,16 +286,16 @@ Network.prototype.setCopayerId = function(copayerId) {
throw new Error('network already started: can not change peerId')
}
this.copayerId = copayerId;
this.copayerIdBuf = new Buffer(copayerId,'hex');
this.copayerIdBuf = new Buffer(copayerId, 'hex');
this.peerId = this.peerFromCopayer(this.copayerId);
this._addCopayerMap(this.peerId,copayerId);
this._addCopayerMap(this.peerId, copayerId);
};
// TODO cache this.
Network.prototype.peerFromCopayer = function(hex) {
var SIN = bitcore.SIN;
return new SIN(new Buffer(hex,'hex')).toString();
return new SIN(new Buffer(hex, 'hex')).toString();
};
Network.prototype.start = function(opts, openCallback) {
@ -317,7 +315,7 @@ Network.prototype.start = function(opts, openCallback) {
this.setCopayerId(opts.copayerId);
var self = this;
var setupPeer = function () {
var setupPeer = function() {
if (self.connectedPeers.length > 0) return; // Already connected!
if (self.peer) {
self.peer.destroy();
@ -333,7 +331,7 @@ Network.prototype.start = function(opts, openCallback) {
return;
}
if (self.criticalError && self.criticalError.match(/taken/)) {
self.criticalError=' Looks like you are already connected to this wallet please close all other Copay Wallets '
self.criticalError = ' Looks like you are already connected to this wallet please close all other Copay Wallets '
}
self.emit('serverError', self.criticalError);
self.cleanUp();
@ -376,7 +374,7 @@ Network.prototype._sendToOne = function(copayerId, payload, sig, cb) {
Network.prototype.send = function(copayerIds, payload, cb) {
if (!payload) return cb();
var self=this;
var self = this;
if (!copayerIds) {
copayerIds = this.connectedCopayers();
payload.isBroadcast = 1;
@ -394,7 +392,7 @@ Network.prototype.send = function(copayerIds, payload, cb) {
copayerIds.forEach(function(copayerId) {
var copayerIdBuf = new Buffer(copayerId, 'hex');
var encPayload = self._encrypt(copayerIdBuf, payloadBuf);
self._sendToOne(copayerId, encPayload, sig, function () {
self._sendToOne(copayerId, encPayload, sig, function() {
if (++i === l && typeof cb === 'function') cb();
});
});
@ -417,16 +415,18 @@ Network.prototype.connectTo = function(copayerId) {
};
Network.prototype.lockIncommingConnections = function(allowedCopayerIdsArray) {
this.allowedCopayerIds={};
for(var i in allowedCopayerIdsArray) {
this.allowedCopayerIds[ allowedCopayerIdsArray[i] ] = true;
this.allowedCopayerIds = {};
for (var i in allowedCopayerIdsArray) {
this.allowedCopayerIds[allowedCopayerIdsArray[i]] = true;
}
};
Network.prototype.disconnect = function(cb, forced) {
var self = this;
self.closing = 1;
self.send(null, { type: 'disconnect' }, function(){
self.send(null, {
type: 'disconnect'
}, function() {
self.cleanUp();
if (typeof cb === 'function') cb();
});

View file

@ -111,7 +111,7 @@ Storage.prototype.get = function(walletId, k) {
// set value for key
Storage.prototype.set = function(walletId, k, v, callback) {
this.setGlobal(this._key(walletId,k), v, callback);
this.setGlobal(this._key(walletId, k), v, callback);
};
// remove value for key
@ -143,6 +143,6 @@ Storage.prototype.getEncryptedObj = function(walletId) {
Storage.prototype.clearAll = function(callback) {
this.data = {};
this.save(callback);
};
};
module.exports = require('soop')(Storage);

View file

@ -2,8 +2,7 @@
var imports = require('soop').imports();
function Storage() {
}
function Storage() {}
Storage.prototype._read = function(k) {
var ret;
@ -13,7 +12,7 @@ Storage.prototype._read = function(k) {
return ret;
};
Storage.prototype._write = function(k,v) {
Storage.prototype._write = function(k, v) {
localStorage.setItem(k, JSON.stringify(v));
};
@ -27,7 +26,7 @@ Storage.prototype._getWalletKeys = function(walletId) {
if (walletId = split[0])
keys.push(split[2]);
}
}
}
return keys;
};
@ -38,8 +37,8 @@ Storage.prototype.getGlobal = function(k) {
};
// set value for key
Storage.prototype.setGlobal = function(k,v) {
this._write(k,v);
Storage.prototype.setGlobal = function(k, v) {
this._write(k, v);
};
// remove value for key
@ -54,44 +53,44 @@ Storage.prototype._key = function(walletId, k) {
};
// get value by key
Storage.prototype.get = function(walletId, k) {
return this.getGlobal(this._key(walletId,k));
return this.getGlobal(this._key(walletId, k));
};
// set value for key
Storage.prototype.set = function(walletId, k,v) {
this.setGlobal(this._key(walletId,k), v);
Storage.prototype.set = function(walletId, k, v) {
this.setGlobal(this._key(walletId, k), v);
};
// remove value for key
Storage.prototype.remove = function(walletId, k) {
this.removeGlobal(this._key(walletId,k));
this.removeGlobal(this._key(walletId, k));
};
Storage.prototype.setName = function(walletId, name) {
this.setGlobal('nameFor::'+walletId, name);
this.setGlobal('nameFor::' + walletId, name);
};
Storage.prototype.getName = function(walletId) {
return this.getGlobal('nameFor::'+walletId);
return this.getGlobal('nameFor::' + walletId);
};
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 key = localStorage.key(i);
var split = key.split('::');
if (split.length == 2) {
var walletId = split[0];
if (walletId === 'nameFor') continue;
if (typeof uniq[walletId] === 'undefined' ) {
if (typeof uniq[walletId] === 'undefined') {
walletIds.push(walletId);
uniq[walletId] = 1;
}
}
}
}
}
return walletIds;
};
@ -100,9 +99,9 @@ Storage.prototype.getWallets = function() {
var uniq = {};
var ids = this.getWalletIds();
for (var i in ids){
for (var i in ids) {
wallets.push({
id:ids[i],
id: ids[i],
name: this.getName(ids[i]),
});
}
@ -120,6 +119,6 @@ Storage.prototype.setFromObj = function(walletId, obj) {
// remove all values
Storage.prototype.clearAll = function() {
localStorage.clear();
};
};
module.exports = require('soop')(Storage);

View file

@ -60,15 +60,14 @@ angular
.config(function($locationProvider) {
$locationProvider
.html5Mode(false);
//.hashPrefix('!');
//.hashPrefix('!');
})
.run(function($rootScope, $location) {
$rootScope.$on('$routeChangeStart', function(event, next, current) {
if (!util.supports.data) {
$location.path('unsupported');
}
else {
} else {
if ((!$rootScope.wallet || !$rootScope.wallet.id) && next.validate) {
$location.path('signin');
}

View file

@ -6,7 +6,7 @@ var BackupService = function(notification) {
};
BackupService.prototype.getName = function(wallet) {
return (wallet.name ? (wallet.name+'-') : '') + wallet.id;
return (wallet.name ? (wallet.name + '-') : '') + wallet.id;
};
BackupService.prototype.download = function(wallet) {

View file

@ -3,19 +3,19 @@
// Detect mobile devices
var isMobile = {
Android: function() {
return !! navigator.userAgent.match(/Android/i);
return !!navigator.userAgent.match(/Android/i);
},
BlackBerry: function() {
return !! navigator.userAgent.match(/BlackBerry/i);
return !!navigator.userAgent.match(/BlackBerry/i);
},
iOS: function() {
return !! navigator.userAgent.match(/iPhone|iPad|iPod/i);
return !!navigator.userAgent.match(/iPhone|iPad|iPod/i);
},
Opera: function() {
return !! navigator.userAgent.match(/Opera Mini/i);
return !!navigator.userAgent.match(/Opera Mini/i);
},
Windows: function() {
return !! navigator.userAgent.match(/IEMobile/i);
return !!navigator.userAgent.match(/IEMobile/i);
},
any: function() {
return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows());

View file

@ -1,40 +1,61 @@
'use strict';
angular.module('copayApp.services').
factory('notification', ['$timeout',function($timeout){
factory('notification', ['$timeout',
function($timeout) {
var notifications = JSON.parse(localStorage.getItem('notifications')) || [],
queue = [];
queue = [];
var settings = {
info: { duration: 5000, enabled: true },
funds: { duration: 5000, enabled: true },
warning: { duration: 5000, enabled: true },
error: { duration: 1e10, enabled: true },
success: { duration: 5000, enabled: true },
progress: { duration: 0, enabled: true },
custom: { duration: 35000, enabled: true },
info: {
duration: 5000,
enabled: true
},
funds: {
duration: 5000,
enabled: true
},
warning: {
duration: 5000,
enabled: true
},
error: {
duration: 1e10,
enabled: true
},
success: {
duration: 5000,
enabled: true
},
progress: {
duration: 0,
enabled: true
},
custom: {
duration: 35000,
enabled: true
},
details: true,
localStorage: false,
html5Mode: false,
html5DefaultIcon: 'img/favicon.ico'
};
function html5Notify(icon, title, content, ondisplay, onclose){
if(window.webkitNotifications.checkPermission() === 0){
if(!icon){
function html5Notify(icon, title, content, ondisplay, onclose) {
if (window.webkitNotifications.checkPermission() === 0) {
if (!icon) {
icon = 'img/favicon.ico';
}
var noti = window.webkitNotifications.createNotification(icon, title, content);
if(typeof ondisplay === 'function'){
if (typeof ondisplay === 'function') {
noti.ondisplay = ondisplay;
}
if(typeof onclose === 'function'){
if (typeof onclose === 'function') {
noti.onclose = onclose;
}
noti.show();
}
else {
} else {
settings.html5Mode = false;
}
}
@ -44,53 +65,50 @@ angular.module('copayApp.services').
/* ========== SETTINGS RELATED METHODS =============*/
disableHtml5Mode: function(){
disableHtml5Mode: function() {
settings.html5Mode = false;
},
disableType: function(notificationType){
disableType: function(notificationType) {
settings[notificationType].enabled = false;
},
enableHtml5Mode: function(){
enableHtml5Mode: function() {
// settings.html5Mode = true;
settings.html5Mode = this.requestHtml5ModePermissions();
},
enableType: function(notificationType){
enableType: function(notificationType) {
settings[notificationType].enabled = true;
},
getSettings: function(){
getSettings: function() {
return settings;
},
toggleType: function(notificationType){
toggleType: function(notificationType) {
settings[notificationType].enabled = !settings[notificationType].enabled;
},
toggleHtml5Mode: function(){
toggleHtml5Mode: function() {
settings.html5Mode = !settings.html5Mode;
},
requestHtml5ModePermissions: function(){
if (window.webkitNotifications){
requestHtml5ModePermissions: function() {
if (window.webkitNotifications) {
if (window.webkitNotifications.checkPermission() === 0) {
return true;
}
else{
window.webkitNotifications.requestPermission(function(){
if(window.webkitNotifications.checkPermission() === 0){
} else {
window.webkitNotifications.requestPermission(function() {
if (window.webkitNotifications.checkPermission() === 0) {
settings.html5Mode = true;
}
else{
} else {
settings.html5Mode = false;
}
});
return false;
}
}
else{
} else {
return false;
}
},
@ -98,38 +116,38 @@ angular.module('copayApp.services').
/* ============ QUERYING RELATED METHODS ============*/
getAll: function(){
getAll: function() {
// Returns all notifications that are currently stored
return notifications;
},
getQueue: function(){
getQueue: function() {
return queue;
},
/* ============== NOTIFICATION METHODS ==============*/
info: function(title, content, userData){
info: function(title, content, userData) {
return this.awesomeNotify('info', 'info', title, content, userData);
},
funds: function(title, content, userData){
funds: function(title, content, userData) {
return this.awesomeNotify('funds', 'bitcoin', title, content, userData);
},
error: function(title, content, userData){
error: function(title, content, userData) {
return this.awesomeNotify('error', 'x', title, content, userData);
},
success: function(title, content, userData){
success: function(title, content, userData) {
return this.awesomeNotify('success', 'check', title, content, userData);
},
warning: function(title, content, userData){
warning: function(title, content, userData) {
return this.awesomeNotify('warning', 'alert', title, content, userData);
},
awesomeNotify: function(type, icon, title, content, userData){
awesomeNotify: function(type, icon, title, content, userData) {
/**
* Supposed to wrap the makeNotification method for drawing icons using font-awesome
* rather than an image.
@ -143,13 +161,13 @@ angular.module('copayApp.services').
return this.makeNotification(type, false, icon, title, content, userData);
},
notify: function(image, title, content, userData){
notify: function(image, title, content, userData) {
// Wraps the makeNotification method for displaying notifications with images
// rather than icons
return this.makeNotification('custom', image, true, title, content, userData);
},
makeNotification: function(type, image, icon, title, content, userData){
makeNotification: function(type, image, icon, title, content, userData) {
var notification = {
'type': type,
'image': image,
@ -161,16 +179,15 @@ angular.module('copayApp.services').
};
notifications.push(notification);
if(settings.html5Mode){
html5Notify(image, title, content, function(){
if (settings.html5Mode) {
html5Notify(image, title, content, function() {
// inner on display function
}, function(){
}, function() {
// inner on close function
});
}
else{
} else {
queue.push(notification);
$timeout(function removeFromQueueTimeout(){
$timeout(function removeFromQueueTimeout() {
queue.splice(queue.indexOf(notification), 1);
}, settings[type].duration);
@ -183,80 +200,77 @@ angular.module('copayApp.services').
/* ============ PERSISTENCE METHODS ============ */
save: function(){
save: function() {
// Save all the notifications into localStorage
if(settings.localStorage){
if (settings.localStorage) {
localStorage.setItem('notifications', JSON.stringify(notifications));
}
},
restore: function(){
restore: function() {
// Load all notifications from localStorage
},
clear: function(){
clear: function() {
notifications = [];
this.save();
}
};
}]).
directive('notifications', function(notification, $compile){
/**
*
* It should also parse the arguments passed to it that specify
* its position on the screen like "bottom right" and apply those
* positions as a class to the container element
*
* Finally, the directive should have its own controller for
* handling all of the notifications from the notification service
*/
var html =
'<div class="dr-notification-wrapper" ng-repeat="noti in queue">' +
'<div class="dr-notification-close-btn" ng-click="removeNotification(noti)">' +
'<i class="fi-x"></i>' +
'</div>' +
'<div class="dr-notification">' +
'<div class="dr-notification-image dr-notification-type-{{noti.type}}" ng-switch on="noti.image">' +
'<i class="fi-{{noti.icon}}" ng-switch-when="false"></i>' +
'<img ng-src="{{noti.image}}" ng-switch-default />' +
'</div>' +
'<div class="dr-notification-content">' +
'<h3 class="dr-notification-title">{{noti.title}}</h3>' +
'<p class="dr-notification-text">{{noti.content}}</p>' +
'</div>' +
'</div>' +
'</div>';
}
]).
directive('notifications', function(notification, $compile) {
/**
*
* It should also parse the arguments passed to it that specify
* its position on the screen like "bottom right" and apply those
* positions as a class to the container element
*
* Finally, the directive should have its own controller for
* handling all of the notifications from the notification service
*/
var html =
'<div class="dr-notification-wrapper" ng-repeat="noti in queue">' +
'<div class="dr-notification-close-btn" ng-click="removeNotification(noti)">' +
'<i class="fi-x"></i>' +
'</div>' +
'<div class="dr-notification">' +
'<div class="dr-notification-image dr-notification-type-{{noti.type}}" ng-switch on="noti.image">' +
'<i class="fi-{{noti.icon}}" ng-switch-when="false"></i>' +
'<img ng-src="{{noti.image}}" ng-switch-default />' +
'</div>' +
'<div class="dr-notification-content">' +
'<h3 class="dr-notification-title">{{noti.title}}</h3>' +
'<p class="dr-notification-text">{{noti.content}}</p>' +
'</div>' +
'</div>' +
'</div>';
function link(scope, element, attrs){
var position = attrs.notifications;
position = position.split(' ');
element.addClass('dr-notification-container');
for(var i = 0; i < position.length ; i++){
element.addClass(position[i]);
}
function link(scope, element, attrs) {
var position = attrs.notifications;
position = position.split(' ');
element.addClass('dr-notification-container');
for (var i = 0; i < position.length; i++) {
element.addClass(position[i]);
}
}
return {
restrict: 'A',
scope: {},
template: html,
link: link,
controller: ['$scope', function NotificationsCtrl( $scope ){
return {
restrict: 'A',
scope: {},
template: html,
link: link,
controller: ['$scope',
function NotificationsCtrl($scope) {
$scope.queue = notification.getQueue();
$scope.removeNotification = function(noti){
$scope.removeNotification = function(noti) {
$scope.queue.splice($scope.queue.indexOf(noti), 1);
};
}
]
};
});
};
});

View file

@ -1,4 +1,3 @@
'use strict';
angular.module('copayApp.services').value('walletFactory', new copay.WalletFactory(config, copay.version));

View file

@ -1,23 +1,24 @@
/*
** copay-shell integration
*/
** copay-shell integration
*/
(function() {
/*
** This is a monkey patch for when Copay is running from
** within Copay-Shell (atom-shell). Since the renderer (the frontend)
** receives context from Node.js, we get a `module.exports` contruct
** available to us. Because of this, some libs (specifically Moment.js)
** attempt to assume their CommonJS form and bind to this. This causes
** there to be no references in the window to these libs, so let's trick
** the renderer into thinking that we are _not_ in a CommonJS environment.
*/
if (typeof module !== 'undefined') module = { exports: null };
** This is a monkey patch for when Copay is running from
** within Copay-Shell (atom-shell). Since the renderer (the frontend)
** receives context from Node.js, we get a `module.exports` contruct
** available to us. Because of this, some libs (specifically Moment.js)
** attempt to assume their CommonJS form and bind to this. This causes
** there to be no references in the window to these libs, so let's trick
** the renderer into thinking that we are _not_ in a CommonJS environment.
*/
if (typeof module !== 'undefined') module = {
exports: null
};
// are we running in copay shell?
if (window.process && process.type === 'renderer') {
window.cshell = initCopayShellBindings();
}
else {
} else {
return;
}
@ -35,12 +36,14 @@
function initCopayShellBindings() {
var ipc = require('ipc');
var ipc = require('ipc');
var clipb = require('clipboard');
// atom shell forces to implement the clipboard on our own - thanks obama.
Mousetrap.stopCallback = function() { return false };
Mousetrap.stopCallback = function() {
return false
};
Mousetrap.bind('ctrl+c', function(e) {
clipb.writeText(window.getSelection().toString());