commit
0bac775982
21 changed files with 166 additions and 49 deletions
18
2fa
Normal file
18
2fa
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
|
||||
- 2-2
|
||||
1 desktop
|
||||
1 mobile
|
||||
|
||||
- each device creates its own key
|
||||
- both devices are expected to be logged using the same profile (email / password)
|
||||
- if using local storage -> all is OK.
|
||||
- keys will be safe an will never leave the device
|
||||
|
||||
- if using insight
|
||||
both 'copayers' need to have a new and different password for accessing the wallet.
|
||||
|
||||
|
||||
|
||||
|
||||
-
|
||||
12
TODO
Normal file
12
TODO
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
- homeWallet address...e sta ok?
|
||||
- receive controller .. owned
|
||||
--
|
||||
// pkr.cache = opts.cache;
|
||||
|
||||
(en send.js)
|
||||
// $rootScope.pendingTxCount = res.pendingForUs;
|
||||
|
||||
-- probar payment intent
|
||||
|
||||
// TODO refrescar en 'add'
|
||||
1
commm
Normal file
1
commm
Normal file
|
|
@ -0,0 +1 @@
|
|||
7b6bcfbbbb6bf82f8843305f563d2a2491f310fe
|
||||
|
|
@ -62,7 +62,8 @@ angular.module('copayApp.controllers').controller('CreateController',
|
|||
$scope.error = 'Could not create wallet: ' + err;
|
||||
}
|
||||
}
|
||||
$rootScope.$digest()
|
||||
|
||||
$rootScope.$digest();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
'use strict';
|
||||
angular.module('copayApp.controllers').controller('CreateWalletController', function($scope, $rootScope) {
|
||||
|
||||
$rootScope.title = 'Create Wallet';
|
||||
});
|
||||
|
|
@ -25,7 +25,7 @@ angular.module('copayApp.controllers').controller('HomeController', function($sc
|
|||
$scope.$on("$destroy", function(){
|
||||
var iden = $rootScope.iden;
|
||||
if (iden) {
|
||||
iden.removeListener('newWallets', $scope.done );
|
||||
iden.removeListener('newWallet', $scope.done );
|
||||
iden.removeListener('noWallets', $scope.done );
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,13 +1,16 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('HomeWalletController',
|
||||
function($scope, $rootScope) {
|
||||
angular.module('copayApp.controllers').controller('HomeWalletController', function($scope, $rootScope) {
|
||||
$scope.init = function() {
|
||||
|
||||
$rootScope.title = 'Home';
|
||||
$scope.addr = _.last($rootScope.wallet.getReceiveAddresses());
|
||||
|
||||
// This is necesarry, since wallet can change in homeWallet, without running init() again.
|
||||
$rootScope.$watch('wallet', function() {
|
||||
$scope.addr = _.last($rootScope.wallet.getReceiveAddresses());
|
||||
if ($rootScope.wallet && $rootScope.wallet.isComplete()) {
|
||||
$scope.addr = _.last($rootScope.wallet.getReceiveAddresses());
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -81,6 +81,8 @@ angular.module('copayApp.controllers').controller('ImportController',
|
|||
if (err) {
|
||||
$scope.loading = false;
|
||||
$scope.error = 'Could not read wallet. Please check your password';
|
||||
$rootScope.$digest();
|
||||
return;
|
||||
}
|
||||
copay.Compatibility.deleteOldWallet(backupOldWallet);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('JoinController',
|
||||
function($scope, $rootScope, $timeout, isMobile, notification) {
|
||||
function($scope, $rootScope, $timeout, isMobile, notification, identityService) {
|
||||
$rootScope.fromSetup = false;
|
||||
$scope.loading = false;
|
||||
$scope.isMobile = isMobile.any();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
'use strict';
|
||||
angular.module('copayApp.controllers').controller('ProfileController', function($scope, $rootScope, $location, $modal, $filter, backupService, identityService) {
|
||||
angular.module('copayApp.controllers').controller('ProfileController', function($scope, $rootScope, $location, $modal, $filter, $timeout, backupService, identityService) {
|
||||
$scope.username = $rootScope.iden.getName();
|
||||
$scope.isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
|
||||
|
||||
|
|
@ -26,11 +26,13 @@ angular.module('copayApp.controllers').controller('ProfileController', function(
|
|||
});
|
||||
};
|
||||
|
||||
|
||||
$scope.init = function() {
|
||||
if ($rootScope.quotaPerItem) {
|
||||
$scope.perItem = $filter('noFractionNumber')($rootScope.quotaPerItem / 1000, 1);
|
||||
$scope.nrWallets = parseInt($rootScope.quotaItems) - 1;
|
||||
}
|
||||
// no need to add event handlers here. Wallet deletion is handle by callback.
|
||||
};
|
||||
|
||||
$scope.setWallets = function() {
|
||||
|
|
@ -46,8 +48,10 @@ angular.module('copayApp.controllers').controller('ProfileController', function(
|
|||
w.usage = $filter('noFractionNumber')(bits / max * 100, 0);
|
||||
}
|
||||
});
|
||||
|
||||
$scope.wallets = wallets;
|
||||
$timeout(function(){
|
||||
$scope.$digest();
|
||||
})
|
||||
};
|
||||
|
||||
$scope.downloadWalletBackup = function(w) {
|
||||
|
|
|
|||
|
|
@ -63,7 +63,19 @@ angular.module('copayApp.controllers').controller('SidebarController', function(
|
|||
$scope.walletSelection = false;
|
||||
$scope.setWallets();
|
||||
});
|
||||
iden.on('deleteWallet', function() {
|
||||
iden.on('walletDeleted', function(wid) {
|
||||
if (wid == $rootScope.wallet.id) {
|
||||
copay.logger.debug('Deleted focused wallet:', wid);
|
||||
|
||||
// new focus
|
||||
var newWid = $rootScope.iden.getLastFocusedWalletId();
|
||||
if (newWid && $rootScope.iden.getWalletById(newWid)) {
|
||||
identityService.setFocusedWallet(newWid);
|
||||
} else {
|
||||
copay.logger.debug('No wallets');
|
||||
identityService.noFocusedWallet(newWid);
|
||||
}
|
||||
}
|
||||
$scope.walletSelection = false;
|
||||
$scope.setWallets();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -151,6 +151,7 @@ Identity.prototype.readAndBindWallet = function(walletId, cb) {
|
|||
var self = this;
|
||||
self.retrieveWalletFromStorage(walletId, {}, function(error, wallet) {
|
||||
if (!error) {
|
||||
self.wallets[wallet.getId()] = wallet;
|
||||
self.bindWallet(wallet);
|
||||
}
|
||||
return cb(error);
|
||||
|
|
@ -386,6 +387,8 @@ Identity.prototype.importWalletFromObj = function(obj, opts, cb) {
|
|||
log.debug('Updating Indexes for wallet:' + w.getName());
|
||||
w.updateIndexes(function(err) {
|
||||
log.debug('Adding wallet to profile:' + w.getName());
|
||||
self.wallets[w.getId()] = w;
|
||||
self.updateFocusedTimestamp(w.getId());
|
||||
self.bindWallet(w);
|
||||
self.storeWallet(w, cb);
|
||||
});
|
||||
|
|
@ -471,8 +474,9 @@ Identity.importFromFullJson = function(str, password, opts, cb) {
|
|||
* @emits newWallet (walletId)
|
||||
*/
|
||||
Identity.prototype.bindWallet = function(w) {
|
||||
preconditions.checkArgument(w && this.wallets[w.getId()]);
|
||||
|
||||
var self = this;
|
||||
self.wallets[w.getId()] = w;
|
||||
log.debug('Binding wallet:' + w.getName());
|
||||
|
||||
w.on('txProposalsUpdated', function() {
|
||||
|
|
@ -569,11 +573,10 @@ Identity.prototype.createWallet = function(opts, cb) {
|
|||
opts.version = opts.version || this.version;
|
||||
|
||||
var self = this;
|
||||
|
||||
|
||||
var w = new walletClass(opts);
|
||||
self.bindWallet(w);
|
||||
self.wallets[w.getId()] = w;
|
||||
self.updateFocusedTimestamp(w.getId());
|
||||
self.bindWallet(w);
|
||||
self.storeWallet(w, function(err) {
|
||||
if (err) return cb(err);
|
||||
|
||||
|
|
@ -641,7 +644,7 @@ Identity.prototype.deleteWallet = function(walletId, cb) {
|
|||
|
||||
this.storage.removeItem(Wallet.getStorageKey(walletId), function(err) {
|
||||
if (err) return cb(err);
|
||||
self.emitAndKeepAlive('deletedWallet', walletId);
|
||||
self.emitAndKeepAlive('walletDeleted', walletId);
|
||||
self.store(null, cb);
|
||||
return cb();
|
||||
});
|
||||
|
|
@ -664,15 +667,16 @@ Identity.prototype.decodeSecret = function(secret) {
|
|||
* @return {string} walletId
|
||||
*/
|
||||
Identity.prototype.getLastFocusedWalletId = function() {
|
||||
var max = _.max(this.focusedTimestamp);
|
||||
var aId = _.findKey(this.wallets) || this.walletIds[0];
|
||||
if (this.walletIds.length == 0) return undefined;
|
||||
|
||||
var max = _.max(this.focusedTimestamps);
|
||||
|
||||
if (!max)
|
||||
return aId;
|
||||
return this.walletIds[0];
|
||||
|
||||
return _.findKey(this.focusedTimestamps, function(ts) {
|
||||
return ts == max;
|
||||
}) || aId;
|
||||
}) || this.walletIds[0];
|
||||
};
|
||||
|
||||
Identity.prototype.updateFocusedTimestamp = function(wid) {
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ Wallet.TX_SIGNED_AND_BROADCASTED = 'txSignedAndBroadcasted';
|
|||
|
||||
Wallet.prototype.emitAndKeepAlive = function(args) {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
log.debug('Wallet:'+ this.getName() + ' Emitting:', args);
|
||||
log.debug('Wallet:' + this.getName() + ' Emitting:', args);
|
||||
this.keepAlive();
|
||||
this.emit.apply(this, arguments);
|
||||
};
|
||||
|
|
@ -331,14 +331,16 @@ Wallet.prototype._onPublicKeyRing = function(senderId, data) {
|
|||
return;
|
||||
}
|
||||
if (hasChanged) {
|
||||
|
||||
if (wasIncomplete) {
|
||||
this.sendPublicKeyRing();
|
||||
}
|
||||
if (this.publicKeyRing.isComplete()) {
|
||||
this._lockIncomming();
|
||||
this.emitAndKeepAlive('ready');
|
||||
} else {
|
||||
this.emitAndKeepAlive('publicKeyRingUpdated');
|
||||
}
|
||||
|
||||
this.emitAndKeepAlive('publicKeyRingUpdated');
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -891,7 +893,7 @@ Wallet.prototype._setupBlockchainHandlers = function() {
|
|||
self.blockchain.on('tx', function(tx) {
|
||||
log.debug('Wallet:' + self.id + ' blockchain tx event');
|
||||
var addresses = self.getAddresses();
|
||||
if (_.indexOf(addresses,tx.address)>=0) {
|
||||
if (_.indexOf(addresses, tx.address) >= 0) {
|
||||
self.emitAndKeepAlive('tx', tx.address, self.addressIsChange(tx.address));
|
||||
}
|
||||
});
|
||||
|
|
@ -932,7 +934,7 @@ Wallet.prototype.netStart = function() {
|
|||
|
||||
|
||||
self._setupBlockchainHandlers();
|
||||
self.netStarted= true;
|
||||
self.netStarted = true;
|
||||
|
||||
if (!this.isShared()) {
|
||||
self.emitAndKeepAlive('ready');
|
||||
|
|
@ -956,7 +958,7 @@ Wallet.prototype.netStart = function() {
|
|||
}
|
||||
log.debug('Wallet:' + self.id + ' Starting network.');
|
||||
this.network.start(startOpts, function() {
|
||||
self.emitAndKeepAlive('ready');
|
||||
self.emitAndKeepAlive(self.isComplete() ? 'ready' : 'waitingCopayers');
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -1399,7 +1401,8 @@ Wallet.prototype.getPendingTxProposalsCount = function() {
|
|||
var txps = this.txProposals.txps;
|
||||
var maxRejectCount = this.maxRejectCount();
|
||||
var myId = this.getMyCopayerId();
|
||||
var pending =0, pendingForUs = 0;
|
||||
var pending = 0,
|
||||
pendingForUs = 0;
|
||||
|
||||
_.each(txps, function(inTxp, ntxid) {
|
||||
if (!inTxp.isPending(maxRejectCount))
|
||||
|
|
@ -1407,7 +1410,7 @@ Wallet.prototype.getPendingTxProposalsCount = function() {
|
|||
|
||||
pending++;
|
||||
|
||||
if (!inTxp.signedBy[myId] && !inTxp.rejectedBy[myId] )
|
||||
if (!inTxp.signedBy[myId] && !inTxp.rejectedBy[myId])
|
||||
pendingForUs++
|
||||
});
|
||||
|
||||
|
|
@ -1845,9 +1848,8 @@ Wallet.prototype._getPayProRefundOutputs = function(txp) {
|
|||
var opts = JSON.parse(txp.builder.vanilla.opts);
|
||||
if (!opts.remainderOut) {
|
||||
log.warn('no remainder set. Not setting refund in PayPro');
|
||||
return;
|
||||
return;
|
||||
}
|
||||
console.log('[Wallet.js.1842:builder:]',txp.builder.vanilla.opts); //TODO
|
||||
var addrStr = opts.remainderOut.address;
|
||||
var addr = new bitcore.Address(addrStr);
|
||||
var script = bitcore.Script.createP2SH(addr.payload()).getBuffer();
|
||||
|
|
@ -2032,7 +2034,7 @@ Wallet.prototype.addressIsOwn = function(addrStr) {
|
|||
/**
|
||||
* @desc Returns true if a given address is a change address (remainder)
|
||||
* @param addrStr
|
||||
* @return {boolean}
|
||||
* @return {boolean}
|
||||
*/
|
||||
Wallet.prototype.addressIsChange = function(addrStr) {
|
||||
return this.publicKeyRing.addressIsChange(addrStr);
|
||||
|
|
@ -2129,7 +2131,7 @@ Wallet.prototype.getUnspent = function(cb) {
|
|||
var addresses = this.getAddresses();
|
||||
|
||||
|
||||
log.debug('Wallet ' + this.getName() + ': Getting unspents from ' + addresses.length + ' addresses');
|
||||
log.debug('Wallet ' + this.getName() + ': Getting unspents from ' + addresses.length + ' addresses');
|
||||
this.blockchain.getUnspent(addresses, function(err, unspentList) {
|
||||
|
||||
if (err) {
|
||||
|
|
|
|||
|
|
@ -126,6 +126,13 @@ angular.module('copayApp.services')
|
|||
$location.path('/send');
|
||||
};
|
||||
|
||||
root.noFocusedWallet = function() {
|
||||
$rootScope.wallet = null;
|
||||
$timeout(function() {
|
||||
$rootScope.$digest();
|
||||
})
|
||||
};
|
||||
|
||||
root.setFocusedWallet = function(w, dontUpdateIt) {
|
||||
if (!_.isObject(w))
|
||||
w = $rootScope.iden.getWalletById(w);
|
||||
|
|
@ -157,6 +164,11 @@ angular.module('copayApp.services')
|
|||
notification.error('Error', $filter('translate')('Received corrupt message from ') + peerId);
|
||||
}
|
||||
});
|
||||
|
||||
w.on('publicKeyRingUpdated', function() {
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
w.on('ready', function() {
|
||||
var isFocused = root.isFocused(wid);
|
||||
copay.logger.debug('Wallet:' + w.getName() + ' is ready. Focused:', isFocused);
|
||||
|
|
@ -280,13 +292,8 @@ angular.module('copayApp.services')
|
|||
$rootScope.$digest()
|
||||
});
|
||||
|
||||
iden.on('deletedWallet', function(wid) {
|
||||
notification.info('Wallet deleted', $filter('translate')('This wallet was deleted'));
|
||||
if ($rootScope.wallet.id === wid) {
|
||||
$rootScope.wallet = null;
|
||||
var lastFocused = iden.getLastFocusedWalletId();
|
||||
root.setFocusedWallet(lastFocused);
|
||||
}
|
||||
iden.on('walletDeleted', function(wid) {
|
||||
// do nothing. this is handled 'on sync' on controller.
|
||||
});
|
||||
|
||||
iden.on('closed', function() {
|
||||
|
|
@ -307,7 +314,7 @@ angular.module('copayApp.services')
|
|||
};
|
||||
|
||||
root.importWallet = function(encryptedObj, pass, opts, cb) {
|
||||
copay.Compatibility.importEncryptedWallet($rootScope.iden, encryptedObj, pass, opts);
|
||||
copay.Compatibility.importEncryptedWallet($rootScope.iden, encryptedObj, pass, opts, cb);
|
||||
};
|
||||
|
||||
root.joinWallet = function(opts, cb) {
|
||||
|
|
|
|||
37
meeting
Normal file
37
meeting
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
|
||||
- We have an historical opportunity
|
||||
|
||||
- To create the software EVERYONE in the WORLD will use for their finance
|
||||
- To enhance everyone's life by creating an awesome software
|
||||
- To colaborate with Bitcoin adoption, by creating a simple and intuite wallet
|
||||
-
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- be obsessive about the UX
|
||||
- fucking use Copay
|
||||
- subscribe and read bitcore dev
|
||||
|
||||
|
||||
|
||||
- Company funds
|
||||
- Startups
|
||||
- Middle size companies
|
||||
|
||||
- Friends funds
|
||||
- Own funds
|
||||
- 1-1 for every day usage
|
||||
- easy and FAST mobile access
|
||||
- QR reading
|
||||
- PayPro
|
||||
|
||||
- 2-4 for long term holding
|
||||
- swipe without need of insight or copay.io
|
||||
- paper walleting
|
||||
-
|
||||
|
||||
NOT:
|
||||
|
||||
|
||||
19
test-users
Normal file
19
test-users
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
|
||||
wallet addr: 2N7YdozHPSyDomeov9sU6kL3RdGkZPUaV2v
|
||||
|
||||
|
||||
ematiu+1@gmail.com password: 123
|
||||
extPubKey: tprv8ZgxMBicQKsPdWNCTqR5zbCTTCLgc4saAQE32LqLWMHmSzFncTdZegFS7CyA8FKQX9kX7FPAJ1scvtkgumYRJ4iAc4pNekm3LzPtikR3C2L
|
||||
|
||||
ematiu+2@gmail.com password:2
|
||||
extPubKey: tprv8ZgxMBicQKsPem5BuuDT6xY9etUC2RohpUoyzoa1MEkkZyAHhszaHPZTmgDheN31hSP1r6bRwpj2JC66r1CPpftwaRrhz9Wz3e9yRVScw9Y
|
||||
|
||||
|
||||
ematiu+3@gmail.com password:3
|
||||
extPubKey: tprv8ZgxMBicQKsPeQixUQZw1zm2LY6uJqT6oJMStMQHsHkMQDFXwxdomkkFCvMWZbQri3B8mzapiMvREXP85HFKmoUND48yfLEq7AuNCaj41Dw
|
||||
|
||||
|
||||
util/swipeWallet.js n2kMqQ8Si9GndzQ6FrJxcwHMKacK2rCEpK 2 tprv8ZgxMBicQKsPdWNCTqR5zbCTTCLgc4saAQE32LqLWMHmSzFncTdZegFS7CyA8FKQX9kX7FPAJ1scvtkgumYRJ4iAc4pNekm3LzPtikR3C2L tprv8ZgxMBicQKsPem5BuuDT6xY9etUC2RohpUoyzoa1MEkkZyAHhszaHPZTmgDheN31hSP1r6bRwpj2JC66r1CPpftwaRrhz9Wz3e9yRVScw9Y tprv8ZgxMBicQKsPeQixUQZw1zm2LY6uJqT6oJMStMQHsHkMQDFXwxdomkkFCvMWZbQri3B8mzapiMvREXP85HFKmoUND48yfLEq7AuNCaj41Dw
|
||||
|
||||
my addr: n2kMqQ8Si9GndzQ6FrJxcwHMKacK2rCEpK
|
||||
|
||||
|
|
@ -16,7 +16,7 @@ describe('http utils', function() {
|
|||
send: function() {
|
||||
var self = this;
|
||||
setTimeout(function() {
|
||||
self.response = 'test';
|
||||
self.response = [1,2,3,4];
|
||||
self.error ? self.onerror() : self.onload();
|
||||
}, 10);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ describe('log utils', function() {
|
|||
log.warn('hola');
|
||||
|
||||
var arg = console.warn.getCall(0).args[0];
|
||||
arg.should.contain('util.log.js');
|
||||
//arg.should.contain('util.log.js'); /* Firefox does not include the stack track */
|
||||
arg.should.contain('hola');
|
||||
console.warn.restore();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -116,7 +116,6 @@ var createBundle = function(opts) {
|
|||
|
||||
// The following 2 lines fix karma tests
|
||||
b.require('sjcl');
|
||||
|
||||
if (opts.debug) {
|
||||
//include dev dependencies
|
||||
b.require('sinon');
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<div class="home-wallet" ng-controller="HomeWalletController">
|
||||
<div class="home-wallet" ng-controller="HomeWalletController" ng-init="init()">
|
||||
<div class="row hide-for-large-up">
|
||||
<div class="medium-12 small-12 columns">
|
||||
<h1 translate>Home</h1>
|
||||
|
|
|
|||
1
w
Normal file
1
w
Normal file
|
|
@ -0,0 +1 @@
|
|||
xprv9s21ZrQH143K3DYCbPDJdFhNDCzChAdsFwz2HFwgtcEufYffAvhZXcJ3XwxjepPJp3FBSHYFnPsxtAzDbSruoRW3rVThyqc2iFKSFw7zhE6
|
||||
Loading…
Add table
Add a link
Reference in a new issue