mirror of https://github.com/BTCPrivate/copay.git
Merge pull request #816 from yemel/feature/bipNNN-refactor
Feature/bip nnn refactor
This commit is contained in:
commit
f497d76405
|
@ -396,7 +396,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="large-9 medium-12 columns" ng-if="addresses[0]">
|
<div class="large-9 medium-12 columns" ng-if="addresses[0]">
|
||||||
<div class="large-8 medium-8 columns" ng-init="showAll=0">
|
<div class="large-8 medium-8 columns" ng-init="showAll=0">
|
||||||
<a class="panel radius db" ng-repeat="addr in addresses | limitAddress:showAll"
|
<a class="panel radius db" ng-repeat="addr in addresses|removeEmpty|limitAddress:showAll"
|
||||||
ng-click="selectAddress(addr)"
|
ng-click="selectAddress(addr)"
|
||||||
ng-class="{selected : addr.address == selectedAddr.address}">
|
ng-class="{selected : addr.address == selectedAddr.address}">
|
||||||
|
|
||||||
|
@ -418,7 +418,7 @@
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a class="secondary radius" ng-click="showAll=!showAll" ng-show="addresses.length != (addresses|limitAddress).length">
|
<a class="secondary radius" ng-click="showAll=!showAll" ng-show="(addresses|removeEmpty).length != (addresses|removeEmpty|limitAddress).length">
|
||||||
<span ng-if="!showAll">Show all</span>
|
<span ng-if="!showAll">Show all</span>
|
||||||
<span ng-if="showAll">Show less</span>
|
<span ng-if="showAll">Show less</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -33,7 +33,8 @@ angular.module('copayApp.controllers').controller('AddressesController',
|
||||||
$scope.addresses.push({
|
$scope.addresses.push({
|
||||||
'address': addrinfo.addressStr,
|
'address': addrinfo.addressStr,
|
||||||
'balance': $rootScope.balanceByAddr ? $rootScope.balanceByAddr[addrinfo.addressStr] : 0,
|
'balance': $rootScope.balanceByAddr ? $rootScope.balanceByAddr[addrinfo.addressStr] : 0,
|
||||||
'isChange': addrinfo.isChange
|
'isChange': addrinfo.isChange,
|
||||||
|
'owned': addrinfo.owned
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
$scope.selectedAddr = $scope.addresses[0];
|
$scope.selectedAddr = $scope.addresses[0];
|
||||||
|
|
|
@ -17,6 +17,14 @@ angular.module('copayApp.filters', [])
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
.filter('removeEmpty', function() {
|
||||||
|
return function(elements) {
|
||||||
|
// Hide empty addresses from other copayers
|
||||||
|
return elements.filter(function(e) {
|
||||||
|
return e.owned || e.balance > 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
.filter('limitAddress', function() {
|
.filter('limitAddress', function() {
|
||||||
return function(elements, showAll) {
|
return function(elements, showAll) {
|
||||||
if (elements.length <= 1 || showAll) {
|
if (elements.length <= 1 || showAll) {
|
||||||
|
|
|
@ -1,29 +1,56 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
var imports = require('soop').imports();
|
var imports = require('soop').imports();
|
||||||
|
var preconditions = require('preconditions').singleton();
|
||||||
|
var Structure = require('./Structure');
|
||||||
|
|
||||||
function AddressIndex(opts) {
|
function AddressIndex(opts) {
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
this.walletId = opts.walletId;
|
this.cosigner = opts.cosigner
|
||||||
|
|
||||||
this.changeIndex = opts.changeIndex || 0;
|
this.changeIndex = opts.changeIndex || 0;
|
||||||
this.receiveIndex = opts.receiveIndex || 0;
|
this.receiveIndex = opts.receiveIndex || 0;
|
||||||
|
|
||||||
|
if (typeof this.cosigner === 'undefined') {
|
||||||
|
this.cosigner = Structure.SHARED_INDEX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AddressIndex.init = function(totalCopayers) {
|
||||||
|
preconditions.shouldBeNumber(totalCopayers);
|
||||||
|
var indexes = [new AddressIndex()];
|
||||||
|
for (var i = 0 ; i < totalCopayers ; i++) {
|
||||||
|
indexes.push(new AddressIndex({cosigner: i}));
|
||||||
|
}
|
||||||
|
return indexes;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddressIndex.fromList = function(indexes) {
|
||||||
|
return indexes.map(function(i) { return AddressIndex.fromObj(i); });
|
||||||
}
|
}
|
||||||
|
|
||||||
AddressIndex.fromObj = function(data) {
|
AddressIndex.fromObj = function(data) {
|
||||||
if (data instanceof AddressIndex) {
|
if (data instanceof AddressIndex) {
|
||||||
throw new Error('bad data format: Did you use .toObj()?');
|
throw new Error('bad data format: Did you use .toObj()?');
|
||||||
}
|
}
|
||||||
var ret = new AddressIndex(data);
|
return new AddressIndex(data);
|
||||||
return ret;
|
};
|
||||||
|
|
||||||
|
AddressIndex.serialize = function(indexes) {
|
||||||
|
return indexes.map(function(i) { return i.toObj(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
AddressIndex.update = function(shared, totalCopayers) {
|
||||||
|
var indexes = this.init(totalCopayers);
|
||||||
|
indexes[0].changeIndex = shared.changeIndex;
|
||||||
|
indexes[0].receiveIndex = shared.receiveIndex;
|
||||||
|
return this.serialize(indexes);
|
||||||
};
|
};
|
||||||
|
|
||||||
AddressIndex.prototype.toObj = function() {
|
AddressIndex.prototype.toObj = function() {
|
||||||
return {
|
return {
|
||||||
walletId: this.walletId,
|
cosigner: this.cosigner,
|
||||||
changeIndex: this.changeIndex,
|
changeIndex: this.changeIndex,
|
||||||
receiveIndex: this.receiveIndex,
|
receiveIndex: this.receiveIndex
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -34,10 +61,10 @@ AddressIndex.prototype.checkRange = function(index, isChange) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
AddressIndex.prototype.getChangeIndex = function() {
|
AddressIndex.prototype.getChangeIndex = function() {
|
||||||
return this.changeIndex;
|
return this.changeIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
AddressIndex.prototype.getReceiveIndex = function() {
|
AddressIndex.prototype.getReceiveIndex = function() {
|
||||||
return this.receiveIndex;
|
return this.receiveIndex;
|
||||||
};
|
};
|
||||||
|
@ -51,6 +78,9 @@ AddressIndex.prototype.increment = function(isChange) {
|
||||||
};
|
};
|
||||||
|
|
||||||
AddressIndex.prototype.merge = function(inAddressIndex) {
|
AddressIndex.prototype.merge = function(inAddressIndex) {
|
||||||
|
preconditions.shouldBeObject(inAddressIndex)
|
||||||
|
.checkArgument(this.cosigner == inAddressIndex.cosigner);
|
||||||
|
|
||||||
var hasChanged = false;
|
var hasChanged = false;
|
||||||
|
|
||||||
// Indexes
|
// Indexes
|
||||||
|
|
|
@ -16,6 +16,7 @@ function PrivateKey(opts) {
|
||||||
var init = opts.extendedPrivateKeyString || this.network.name;
|
var init = opts.extendedPrivateKeyString || this.network.name;
|
||||||
this.bip = opts.HK || new HK(init);
|
this.bip = opts.HK || new HK(init);
|
||||||
this.privateKeyCache = opts.privateKeyCache || {};
|
this.privateKeyCache = opts.privateKeyCache || {};
|
||||||
|
this.publicHex = this.deriveBIP45Branch().eckey.public.toString('hex');
|
||||||
};
|
};
|
||||||
|
|
||||||
PrivateKey.prototype.getId = function() {
|
PrivateKey.prototype.getId = function() {
|
||||||
|
@ -101,21 +102,21 @@ PrivateKey.prototype.getForPath = function(path) {
|
||||||
return wk;
|
return wk;
|
||||||
};
|
};
|
||||||
|
|
||||||
PrivateKey.prototype.get = function(index, isChange) {
|
PrivateKey.prototype.get = function(index, isChange, cosigner) {
|
||||||
var path = Structure.FullBranch(index, isChange);
|
var path = Structure.FullBranch(index, isChange, cosigner);
|
||||||
return this.getForPath(path);
|
return this.getForPath(path);
|
||||||
};
|
};
|
||||||
|
|
||||||
PrivateKey.prototype.getAll = function(receiveIndex, changeIndex) {
|
PrivateKey.prototype.getAll = function(receiveIndex, changeIndex, cosigner) {
|
||||||
if (typeof receiveIndex === 'undefined' || typeof changeIndex === 'undefined')
|
if (typeof receiveIndex === 'undefined' || typeof changeIndex === 'undefined')
|
||||||
throw new Error('Invalid parameters');
|
throw new Error('Invalid parameters');
|
||||||
|
|
||||||
var ret = [];
|
var ret = [];
|
||||||
for (var i = 0; i < receiveIndex; i++) {
|
for (var i = 0; i < receiveIndex; i++) {
|
||||||
ret.push(this.get(i, false));
|
ret.push(this.get(i, false, cosigner));
|
||||||
}
|
}
|
||||||
for (var i = 0; i < changeIndex; i++) {
|
for (var i = 0; i < changeIndex; i++) {
|
||||||
ret.push(this.get(i, true));
|
ret.push(this.get(i, true, cosigner));
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,7 +24,8 @@ function PublicKeyRing(opts) {
|
||||||
|
|
||||||
this.copayersHK = opts.copayersHK || [];
|
this.copayersHK = opts.copayersHK || [];
|
||||||
|
|
||||||
this.indexes = AddressIndex.fromObj(opts.indexes) || new AddressIndex(opts);
|
this.indexes = opts.indexes ? AddressIndex.fromList(opts.indexes)
|
||||||
|
: AddressIndex.init(this.totalCopayers);
|
||||||
|
|
||||||
this.publicKeysCache = opts.publicKeysCache || {};
|
this.publicKeysCache = opts.publicKeysCache || {};
|
||||||
this.nicknameFor = opts.nicknameFor || {};
|
this.nicknameFor = opts.nicknameFor || {};
|
||||||
|
@ -36,6 +37,12 @@ PublicKeyRing.fromObj = function(data) {
|
||||||
if (data instanceof PublicKeyRing) {
|
if (data instanceof PublicKeyRing) {
|
||||||
throw new Error('bad data format: Did you use .toObj()?');
|
throw new Error('bad data format: Did you use .toObj()?');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Support old indexes schema
|
||||||
|
if (!Array.isArray(data.indexes)) {
|
||||||
|
data.indexes = AddressIndex.update(data.indexes, data.totalCopayers);
|
||||||
|
}
|
||||||
|
|
||||||
var ret = new PublicKeyRing(data);
|
var ret = new PublicKeyRing(data);
|
||||||
|
|
||||||
for (var k in data.copayersExtPubKeys) {
|
for (var k in data.copayersExtPubKeys) {
|
||||||
|
@ -51,7 +58,7 @@ PublicKeyRing.prototype.toObj = function() {
|
||||||
networkName: this.network.name,
|
networkName: this.network.name,
|
||||||
requiredCopayers: this.requiredCopayers,
|
requiredCopayers: this.requiredCopayers,
|
||||||
totalCopayers: this.totalCopayers,
|
totalCopayers: this.totalCopayers,
|
||||||
indexes: this.indexes.toObj(),
|
indexes: AddressIndex.serialize(this.indexes),
|
||||||
|
|
||||||
copayersExtPubKeys: this.copayersHK.map(function(b) {
|
copayersExtPubKeys: this.copayersHK.map(function(b) {
|
||||||
return b.extendedPublicKeyString();
|
return b.extendedPublicKeyString();
|
||||||
|
@ -136,10 +143,10 @@ PublicKeyRing.prototype.addCopayer = function(newEpk, nickname) {
|
||||||
return newEpk;
|
return newEpk;
|
||||||
};
|
};
|
||||||
|
|
||||||
PublicKeyRing.prototype.getPubKeys = function(index, isChange) {
|
PublicKeyRing.prototype.getPubKeys = function(index, isChange, cosigner) {
|
||||||
this._checkKeys();
|
this._checkKeys();
|
||||||
|
|
||||||
var path = Structure.Branch(index, isChange);
|
var path = Structure.Branch(index, isChange, cosigner);
|
||||||
var pubKeys = this.publicKeysCache[path];
|
var pubKeys = this.publicKeysCache[path];
|
||||||
if (!pubKeys) {
|
if (!pubKeys) {
|
||||||
pubKeys = [];
|
pubKeys = [];
|
||||||
|
@ -162,20 +169,29 @@ PublicKeyRing.prototype.getPubKeys = function(index, isChange) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO this could be cached
|
// TODO this could be cached
|
||||||
PublicKeyRing.prototype.getRedeemScript = function(index, isChange) {
|
PublicKeyRing.prototype.getRedeemScript = function(index, isChange, cosigner) {
|
||||||
var pubKeys = this.getPubKeys(index, isChange);
|
var pubKeys = this.getPubKeys(index, isChange, cosigner);
|
||||||
var script = Script.createMultisig(this.requiredCopayers, pubKeys);
|
var script = Script.createMultisig(this.requiredCopayers, pubKeys);
|
||||||
return script;
|
return script;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO this could be cached
|
// TODO this could be cached
|
||||||
PublicKeyRing.prototype.getAddress = function(index, isChange) {
|
PublicKeyRing.prototype.getAddress = function(index, isChange, id) {
|
||||||
var script = this.getRedeemScript(index, isChange);
|
var cosigner = this.getCosigner(id);
|
||||||
|
var script = this.getRedeemScript(index, isChange, cosigner);
|
||||||
var address = Address.fromScript(script, this.network.name);
|
var address = Address.fromScript(script, this.network.name);
|
||||||
this.addressToPath[address.toString()] = Structure.FullBranch(index, isChange);
|
this.addressToPath[address.toString()] = Structure.FullBranch(index, isChange, cosigner);
|
||||||
return address;
|
return address;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Overloaded to receive a PubkeyString or a consigner index
|
||||||
|
PublicKeyRing.prototype.getIndex = function(id) {
|
||||||
|
var cosigner = this.getCosigner(id);
|
||||||
|
var index = this.indexes.filter(function(i) { return i.cosigner == cosigner });
|
||||||
|
if (index.length != 1) throw new Error('no index for cosigner');
|
||||||
|
return index[0];
|
||||||
|
};
|
||||||
|
|
||||||
PublicKeyRing.prototype.pathForAddress = function(address) {
|
PublicKeyRing.prototype.pathForAddress = function(address) {
|
||||||
var path = this.addressToPath[address];
|
var path = this.addressToPath[address];
|
||||||
if (!path) throw new Error('Couldn\'t find path for address ' + address);
|
if (!path) throw new Error('Couldn\'t find path for address ' + address);
|
||||||
|
@ -183,17 +199,19 @@ PublicKeyRing.prototype.pathForAddress = function(address) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO this could be cached
|
// TODO this could be cached
|
||||||
PublicKeyRing.prototype.getScriptPubKeyHex = function(index, isChange) {
|
PublicKeyRing.prototype.getScriptPubKeyHex = function(index, isChange, pubkey) {
|
||||||
var addr = this.getAddress(index, isChange);
|
var cosigner = this.getCosigner(pubkey);
|
||||||
|
var addr = this.getAddress(index, isChange, cosigner);
|
||||||
return Script.createP2SH(addr.payload()).getBuffer().toString('hex');
|
return Script.createP2SH(addr.payload()).getBuffer().toString('hex');
|
||||||
};
|
};
|
||||||
|
|
||||||
//generate a new address, update index.
|
//generate a new address, update index.
|
||||||
PublicKeyRing.prototype.generateAddress = function(isChange) {
|
PublicKeyRing.prototype.generateAddress = function(isChange, pubkey) {
|
||||||
isChange = !!isChange;
|
isChange = !!isChange;
|
||||||
var index = isChange ? this.indexes.getChangeIndex() : this.indexes.getReceiveIndex();
|
var addrIndex = this.getIndex(pubkey);
|
||||||
var ret = this.getAddress(index, isChange);
|
var index = isChange ? addrIndex.getChangeIndex() : addrIndex.getReceiveIndex();
|
||||||
this.indexes.increment(isChange);
|
var ret = this.getAddress(index, isChange, addrIndex.cosigner);
|
||||||
|
addrIndex.increment(isChange);
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -203,28 +221,58 @@ PublicKeyRing.prototype.getAddresses = function(opts) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
PublicKeyRing.prototype.getAddressesInfo = function(opts) {
|
PublicKeyRing.prototype.getCosigner = function(pubKey) {
|
||||||
|
if (typeof pubKey == 'undefined') return Structure.SHARED_INDEX;
|
||||||
|
if (typeof pubKey == 'number') return pubKey;
|
||||||
|
|
||||||
|
var sorted = this.copayersHK.map(function(h, i){
|
||||||
|
return h.eckey.public.toString('hex');
|
||||||
|
}).sort(function(h1, h2){ return h1.localeCompare(h2); });
|
||||||
|
|
||||||
|
var index = sorted.indexOf(pubKey);
|
||||||
|
if (index == -1) throw new Error('no public key in ring');
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PublicKeyRing.prototype.getAddressesInfo = function(opts, pubkey) {
|
||||||
|
var ret = [];
|
||||||
|
var self = this;
|
||||||
|
var cosigner = pubkey && this.getCosigner(pubkey);
|
||||||
|
this.indexes.forEach(function(index) {
|
||||||
|
ret = ret.concat(self.getAddressesInfoForIndex(index, opts, cosigner));
|
||||||
|
});
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
PublicKeyRing.prototype.getAddressesInfoForIndex = function(index, opts, cosigner) {
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
|
|
||||||
|
var isOwned = index.cosigner == Structure.SHARED_INDEX
|
||||||
|
|| index.cosigner == cosigner;
|
||||||
|
|
||||||
var ret = [];
|
var ret = [];
|
||||||
if (!opts.excludeChange) {
|
if (!opts.excludeChange) {
|
||||||
for (var i = 0; i < this.indexes.getChangeIndex(); i++) {
|
for (var i = 0; i < index.changeIndex; i++) {
|
||||||
var a = this.getAddress(i, true);
|
var a = this.getAddress(i, true, index.cosigner);
|
||||||
ret.unshift({
|
ret.unshift({
|
||||||
address: this.getAddress(i, true),
|
address: a,
|
||||||
addressStr: a.toString(),
|
addressStr: a.toString(),
|
||||||
isChange: true
|
isChange: true,
|
||||||
|
owned: isOwned
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!opts.excludeMain) {
|
if (!opts.excludeMain) {
|
||||||
for (var i = 0; i < this.indexes.getReceiveIndex(); i++) {
|
for (var i = 0; i < index.receiveIndex; i++) {
|
||||||
var a = this.getAddress(i, false);
|
var a = this.getAddress(i, false, index.cosigner);
|
||||||
ret.unshift({
|
ret.unshift({
|
||||||
address: a,
|
address: a,
|
||||||
addressStr: a.toString(),
|
addressStr: a.toString(),
|
||||||
isChange: false
|
isChange: false,
|
||||||
|
owned: isOwned
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -235,7 +283,7 @@ PublicKeyRing.prototype.getAddressesInfo = function(opts) {
|
||||||
// TODO this could be cached
|
// TODO this could be cached
|
||||||
PublicKeyRing.prototype._addScriptMap = function(map, path) {
|
PublicKeyRing.prototype._addScriptMap = function(map, path) {
|
||||||
var p = Structure.indicesForPath(path);
|
var p = Structure.indicesForPath(path);
|
||||||
var script = this.getRedeemScript(p.index, p.isChange);
|
var script = this.getRedeemScript(p.index, p.isChange, p.cosigner);
|
||||||
map[Address.fromScript(script, this.network.name).toString()] = script.getBuffer().toString('hex');
|
map[Address.fromScript(script, this.network.name).toString()] = script.getBuffer().toString('hex');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -303,17 +351,25 @@ PublicKeyRing.prototype._mergePubkeys = function(inPKR) {
|
||||||
};
|
};
|
||||||
|
|
||||||
PublicKeyRing.prototype.merge = function(inPKR, ignoreId) {
|
PublicKeyRing.prototype.merge = function(inPKR, ignoreId) {
|
||||||
var hasChanged = false;
|
|
||||||
|
|
||||||
this._checkInPKR(inPKR, ignoreId);
|
this._checkInPKR(inPKR, ignoreId);
|
||||||
|
|
||||||
if (this.indexes.merge(inPKR.indexes))
|
var hasChanged = false;
|
||||||
hasChanged = true;
|
hasChanged |= this.mergeIndexes(inPKR.indexes);
|
||||||
|
hasChanged |= this._mergePubkeys(inPKR);
|
||||||
|
|
||||||
if (this._mergePubkeys(inPKR))
|
return !!hasChanged;
|
||||||
hasChanged = true;
|
|
||||||
|
|
||||||
return hasChanged;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PublicKeyRing.prototype.mergeIndexes = function(indexes) {
|
||||||
|
var self = this;
|
||||||
|
var hasChanged = false;
|
||||||
|
|
||||||
|
indexes.forEach(function(theirs) {
|
||||||
|
var mine = self.getIndex(theirs.cosigner);
|
||||||
|
hasChanged |= mine.merge(theirs);
|
||||||
|
});
|
||||||
|
|
||||||
|
return !!hasChanged
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = require('soop')(PublicKeyRing);
|
module.exports = require('soop')(PublicKeyRing);
|
||||||
|
|
|
@ -40,6 +40,7 @@ Structure.indicesForPath = function(path) {
|
||||||
return {
|
return {
|
||||||
isChange: s[3] === '1',
|
isChange: s[3] === '1',
|
||||||
index: parseInt(s[4]),
|
index: parseInt(s[4]),
|
||||||
|
cosigner: parseInt(s[2])
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@ function Wallet(opts) {
|
||||||
this.registeredPeerIds = [];
|
this.registeredPeerIds = [];
|
||||||
this.addressBook = opts.addressBook || {};
|
this.addressBook = opts.addressBook || {};
|
||||||
this.backupOffered = opts.backupOffered || false;
|
this.backupOffered = opts.backupOffered || false;
|
||||||
|
this.publicKey = this.privateKey.publicHex;
|
||||||
}
|
}
|
||||||
|
|
||||||
Wallet.parent = EventEmitter;
|
Wallet.parent = EventEmitter;
|
||||||
|
@ -82,8 +83,8 @@ Wallet.prototype.connectToAll = function() {
|
||||||
|
|
||||||
Wallet.prototype._handleIndexes = function(senderId, data, isInbound) {
|
Wallet.prototype._handleIndexes = function(senderId, data, isInbound) {
|
||||||
this.log('RECV INDEXES:', data);
|
this.log('RECV INDEXES:', data);
|
||||||
var inIndexes = AddressIndex.fromObj(data.indexes);
|
var inIndexes = AddressIndex.fromList(data.indexes);
|
||||||
var hasChanged = this.publicKeyRing.indexes.merge(inIndexes);
|
var hasChanged = this.publicKeyRing.mergeIndexes(inIndexes);
|
||||||
if (hasChanged) {
|
if (hasChanged) {
|
||||||
this.emit('publicKeyRingUpdated');
|
this.emit('publicKeyRingUpdated');
|
||||||
this.store();
|
this.store();
|
||||||
|
@ -440,11 +441,12 @@ Wallet.prototype.sendPublicKeyRing = function(recipients) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
Wallet.prototype.sendIndexes = function(recipients) {
|
Wallet.prototype.sendIndexes = function(recipients) {
|
||||||
this.log('### INDEXES TO:', recipients || 'All', this.publicKeyRing.indexes.toObj());
|
var indexes = AddressIndex.serialize(this.publicKeyRing.indexes);
|
||||||
|
this.log('### INDEXES TO:', recipients || 'All', indexes);
|
||||||
|
|
||||||
this.network.send(recipients, {
|
this.network.send(recipients, {
|
||||||
type: 'indexes',
|
type: 'indexes',
|
||||||
indexes: this.publicKeyRing.indexes.toObj(),
|
indexes: indexes,
|
||||||
walletId: this.id,
|
walletId: this.id,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -463,7 +465,7 @@ Wallet.prototype.getName = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype._doGenerateAddress = function(isChange) {
|
Wallet.prototype._doGenerateAddress = function(isChange) {
|
||||||
return this.publicKeyRing.generateAddress(isChange);
|
return this.publicKeyRing.generateAddress(isChange, this.publicKey);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -517,7 +519,6 @@ Wallet.prototype.sign = function(ntxid, cb) {
|
||||||
if (cb) cb(false);
|
if (cb) cb(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
var pkr = self.publicKeyRing;
|
|
||||||
var keys = self.privateKey.getForPaths(txp.inputChainPaths);
|
var keys = self.privateKey.getForPaths(txp.inputChainPaths);
|
||||||
|
|
||||||
var b = txp.builder;
|
var b = txp.builder;
|
||||||
|
@ -589,7 +590,7 @@ Wallet.prototype.getAddressesStr = function(opts) {
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.getAddressesInfo = function(opts) {
|
Wallet.prototype.getAddressesInfo = function(opts) {
|
||||||
return this.publicKeyRing.getAddressesInfo(opts);
|
return this.publicKeyRing.getAddressesInfo(opts, this.publicKey);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.addressIsOwn = function(addrStr, opts) {
|
Wallet.prototype.addressIsOwn = function(addrStr, opts) {
|
||||||
|
@ -755,31 +756,44 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, comment, utxos
|
||||||
|
|
||||||
Wallet.prototype.updateIndexes = function(callback) {
|
Wallet.prototype.updateIndexes = function(callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var start = self.publicKeyRing.indexes.changeIndex;
|
|
||||||
self.log('Updating indexes...');
|
self.log('Updating indexes...');
|
||||||
self.indexDiscovery(start, true, 20, function(err, changeIndex) {
|
|
||||||
if (err) return callback(err);
|
|
||||||
if (changeIndex != -1)
|
|
||||||
self.publicKeyRing.indexes.changeIndex = changeIndex + 1;
|
|
||||||
|
|
||||||
start = self.publicKeyRing.indexes.receiveIndex;
|
var tasks = this.publicKeyRing.indexes.map(function(index) {
|
||||||
self.indexDiscovery(start, false, 20, function(err, receiveIndex) {
|
return function(callback) {
|
||||||
if (err) return callback(err);
|
self.updateIndex(index, callback);
|
||||||
if (receiveIndex != -1)
|
};
|
||||||
self.publicKeyRing.indexes.receiveIndex = receiveIndex + 1;
|
});
|
||||||
|
|
||||||
|
async.parallel(tasks, function(err) {
|
||||||
|
if (err) callback(err);
|
||||||
self.log('Indexes updated');
|
self.log('Indexes updated');
|
||||||
self.emit('publicKeyRingUpdated');
|
self.emit('publicKeyRingUpdated');
|
||||||
self.store();
|
self.store();
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Wallet.prototype.updateIndex = function(index, callback) {
|
||||||
|
var self = this;
|
||||||
|
var SCANN_WINDOW = 20;
|
||||||
|
self.indexDiscovery(index.changeIndex, true, index.cosigner, SCANN_WINDOW, function(err, changeIndex) {
|
||||||
|
if (err) return callback(err);
|
||||||
|
if (changeIndex != -1)
|
||||||
|
index.changeIndex = changeIndex + 1;
|
||||||
|
|
||||||
|
self.indexDiscovery(index.receiveIndex, false, index.cosigner, SCANN_WINDOW, function(err, receiveIndex) {
|
||||||
|
if (err) return callback(err);
|
||||||
|
if (receiveIndex != -1)
|
||||||
|
index.receiveIndex = receiveIndex + 1;
|
||||||
|
callback();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Wallet.prototype.deriveAddresses = function(index, amout, isChange) {
|
Wallet.prototype.deriveAddresses = function(index, amout, isChange, cosigner) {
|
||||||
var ret = new Array(amout);
|
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();
|
ret[i] = this.publicKeyRing.getAddress(index + i, isChange, cosigner).toString();
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -787,7 +801,7 @@ Wallet.prototype.deriveAddresses = function(index, amout, isChange) {
|
||||||
// This function scans the publicKeyRing branch starting at index @start and reports the index with last activity,
|
// This function scans the publicKeyRing branch starting at index @start and reports the index with last activity,
|
||||||
// using a scan window of @gap. The argument @change defines the branch to scan: internal or external.
|
// using a scan window of @gap. The argument @change defines the branch to scan: internal or external.
|
||||||
// Returns -1 if no activity is found in range.
|
// Returns -1 if no activity is found in range.
|
||||||
Wallet.prototype.indexDiscovery = function(start, change, gap, cb) {
|
Wallet.prototype.indexDiscovery = function(start, change, cosigner, gap, cb) {
|
||||||
var scanIndex = start;
|
var scanIndex = start;
|
||||||
var lastActive = -1;
|
var lastActive = -1;
|
||||||
var hasActivity = false;
|
var hasActivity = false;
|
||||||
|
@ -797,7 +811,7 @@ Wallet.prototype.indexDiscovery = function(start, change, gap, cb) {
|
||||||
function _do(next) {
|
function _do(next) {
|
||||||
// Optimize window to minimize the derivations.
|
// Optimize window to minimize the derivations.
|
||||||
var scanWindow = (lastActive == -1) ? gap : gap - (scanIndex - lastActive) + 1;
|
var scanWindow = (lastActive == -1) ? gap : gap - (scanIndex - lastActive) + 1;
|
||||||
var addresses = self.deriveAddresses(scanIndex, scanWindow, change);
|
var addresses = self.deriveAddresses(scanIndex, scanWindow, change, cosigner);
|
||||||
self.blockchain.checkActivity(addresses, function(err, actives) {
|
self.blockchain.checkActivity(addresses, function(err, actives) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "copay",
|
"name": "copay",
|
||||||
"version": "0.2.1",
|
"version": "0.3.1",
|
||||||
"description": "A multisignature wallet",
|
"description": "A multisignature wallet",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
@ -12,6 +12,7 @@ try {
|
||||||
}
|
}
|
||||||
var PublicKeyRing = copay.PublicKeyRing;
|
var PublicKeyRing = copay.PublicKeyRing;
|
||||||
var AddressIndex = copay.AddressIndex;
|
var AddressIndex = copay.AddressIndex;
|
||||||
|
var Structure = copay.Structure;
|
||||||
|
|
||||||
|
|
||||||
var config = {
|
var config = {
|
||||||
|
@ -22,7 +23,7 @@ var createAI = function() {
|
||||||
var i = new AddressIndex();
|
var i = new AddressIndex();
|
||||||
should.exist(i);
|
should.exist(i);
|
||||||
|
|
||||||
i.walletId = '1234567';
|
i.cosigner = 1;
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
};
|
};
|
||||||
|
@ -34,7 +35,31 @@ describe('AddressIndex model', function() {
|
||||||
should.exist(i);
|
should.exist(i);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('show be able to tostore and read', function() {
|
it('should init indexes', function() {
|
||||||
|
var is = AddressIndex.init(2);
|
||||||
|
should.exist(is);
|
||||||
|
is.length.should.equal(3);
|
||||||
|
|
||||||
|
var cosigners = is.map(function(i) { return i.cosigner; });
|
||||||
|
cosigners.indexOf(Structure.SHARED_INDEX).should.not.equal(-1);
|
||||||
|
cosigners.indexOf(0).should.not.equal(-1);
|
||||||
|
cosigners.indexOf(1).should.not.equal(-1);
|
||||||
|
cosigners.indexOf(2).should.equal(-1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should serialize to object list and back', function() {
|
||||||
|
var is = AddressIndex.init(3);
|
||||||
|
should.exist(is);
|
||||||
|
is.length.should.equal(4);
|
||||||
|
|
||||||
|
var list = AddressIndex.serialize(is);
|
||||||
|
list.length.should.equal(4);
|
||||||
|
|
||||||
|
var is2 = AddressIndex.fromList(list);
|
||||||
|
is2.length.should.equal(4);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('show be able to store and read', function() {
|
||||||
var i = createAI();
|
var i = createAI();
|
||||||
var changeN = 2;
|
var changeN = 2;
|
||||||
var addressN = 2;
|
var addressN = 2;
|
||||||
|
@ -49,7 +74,7 @@ describe('AddressIndex model', function() {
|
||||||
should.exist(data);
|
should.exist(data);
|
||||||
|
|
||||||
var i2 = AddressIndex.fromObj(data);
|
var i2 = AddressIndex.fromObj(data);
|
||||||
i2.walletId.should.equal(i.walletId);
|
i2.cosigner.should.equal(i.cosigner);
|
||||||
|
|
||||||
i2.getChangeIndex().should.equal(changeN);
|
i2.getChangeIndex().should.equal(changeN);
|
||||||
i2.getReceiveIndex().should.equal(addressN);
|
i2.getReceiveIndex().should.equal(addressN);
|
||||||
|
@ -74,7 +99,7 @@ describe('AddressIndex model', function() {
|
||||||
for (var i = 0; i < 7; i++)
|
for (var i = 0; i < 7; i++)
|
||||||
j.increment(false);
|
j.increment(false);
|
||||||
var j2 = new AddressIndex({
|
var j2 = new AddressIndex({
|
||||||
walletId: j.walletId,
|
cosigner: j.cosigner,
|
||||||
});
|
});
|
||||||
j2.merge(j).should.equal(true);
|
j2.merge(j).should.equal(true);
|
||||||
j2.changeIndex.should.equal(15);
|
j2.changeIndex.should.equal(15);
|
||||||
|
@ -83,4 +108,12 @@ describe('AddressIndex model', function() {
|
||||||
j2.merge(j).should.equal(false);
|
j2.merge(j).should.equal(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('#merge should fail with different cosigner index', function() {
|
||||||
|
var j1 = new AddressIndex({ walletId: '1234', cosigner: 2 });
|
||||||
|
var j2 = new AddressIndex({ walletId: '1234', cosigner: 3 });
|
||||||
|
|
||||||
|
var merge = function() { j2.merge(j1); };
|
||||||
|
merge.should.throw(Error);
|
||||||
|
})
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,6 +5,9 @@ var should = chai.should();
|
||||||
var bitcore = bitcore || require('bitcore');
|
var bitcore = bitcore || require('bitcore');
|
||||||
var Address = bitcore.Address;
|
var Address = bitcore.Address;
|
||||||
var buffertools = bitcore.buffertools;
|
var buffertools = bitcore.buffertools;
|
||||||
|
|
||||||
|
var Structure = require('../js/models/core/Structure');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var copay = require('copay'); //browser
|
var copay = require('copay'); //browser
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -33,7 +36,8 @@ var createW = function(networkName) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
w: w,
|
w: w,
|
||||||
copayers: copayers
|
copayers: copayers,
|
||||||
|
pub: w.copayersHK[0].eckey.public.toString('hex')
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -85,7 +89,7 @@ describe('PublicKeyRing model', function() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('show be able to tostore and read', function() {
|
it('should be able to to store and read', function() {
|
||||||
var k = createW();
|
var k = createW();
|
||||||
var w = k.w;
|
var w = k.w;
|
||||||
var copayers = k.copayers;
|
var copayers = k.copayers;
|
||||||
|
@ -93,10 +97,10 @@ describe('PublicKeyRing model', function() {
|
||||||
var addressN = 2;
|
var addressN = 2;
|
||||||
var start = new Date().getTime();
|
var start = new Date().getTime();
|
||||||
for (var i = 0; i < changeN; i++) {
|
for (var i = 0; i < changeN; i++) {
|
||||||
w.generateAddress(true);
|
w.generateAddress(true, k.pub);
|
||||||
}
|
}
|
||||||
for (var i = 0; i < addressN; i++) {
|
for (var i = 0; i < addressN; i++) {
|
||||||
w.generateAddress(false);
|
w.generateAddress(false, k.pub);
|
||||||
}
|
}
|
||||||
|
|
||||||
var data = w.toObj();
|
var data = w.toObj();
|
||||||
|
@ -112,8 +116,8 @@ describe('PublicKeyRing model', function() {
|
||||||
}).should.throw();
|
}).should.throw();
|
||||||
}
|
}
|
||||||
|
|
||||||
w2.indexes.getChangeIndex().should.equal(changeN);
|
w2.getIndex(k.pub).getChangeIndex().should.equal(changeN);
|
||||||
w2.indexes.getReceiveIndex().should.equal(addressN);
|
w2.getIndex(k.pub).getReceiveIndex().should.equal(addressN);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -123,7 +127,7 @@ describe('PublicKeyRing model', function() {
|
||||||
|
|
||||||
[true, false].forEach(function(isChange){
|
[true, false].forEach(function(isChange){
|
||||||
for (var i = 0; i < 2; i++) {
|
for (var i = 0; i < 2; i++) {
|
||||||
var a = w.generateAddress(isChange);
|
var a = w.generateAddress(isChange, k.pub);
|
||||||
a.isValid().should.equal(true);
|
a.isValid().should.equal(true);
|
||||||
a.isScript().should.equal(true);
|
a.isScript().should.equal(true);
|
||||||
a.network().name.should.equal('livenet');
|
a.network().name.should.equal('livenet');
|
||||||
|
@ -145,7 +149,7 @@ describe('PublicKeyRing model', function() {
|
||||||
|
|
||||||
[true, false].forEach(function(isChange){
|
[true, false].forEach(function(isChange){
|
||||||
for (var i = 0; i < 2; i++) {
|
for (var i = 0; i < 2; i++) {
|
||||||
w.generateAddress(isChange);
|
w.generateAddress(isChange, k.pub);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -164,12 +168,12 @@ describe('PublicKeyRing model', function() {
|
||||||
var w = k.w;
|
var w = k.w;
|
||||||
|
|
||||||
for (var i = 0; i < 3; i++)
|
for (var i = 0; i < 3; i++)
|
||||||
w.generateAddress(true);
|
w.generateAddress(true, k.pub);
|
||||||
for (var i = 0; i < 2; i++)
|
for (var i = 0; i < 2; i++)
|
||||||
w.generateAddress(false);
|
w.generateAddress(false, k.pub);
|
||||||
|
|
||||||
w.indexes.getChangeIndex().should.equal(3);
|
w.getIndex(k.pub).getChangeIndex().should.equal(3);
|
||||||
w.indexes.getReceiveIndex().should.equal(2);
|
w.getIndex(k.pub).getReceiveIndex().should.equal(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('#merge index tests', function() {
|
it('#merge index tests', function() {
|
||||||
|
@ -177,9 +181,9 @@ describe('PublicKeyRing model', function() {
|
||||||
var w = k.w;
|
var w = k.w;
|
||||||
|
|
||||||
for (var i = 0; i < 2; i++)
|
for (var i = 0; i < 2; i++)
|
||||||
w.generateAddress(true);
|
w.generateAddress(true, k.pub);
|
||||||
for (var i = 0; i < 3; i++)
|
for (var i = 0; i < 3; i++)
|
||||||
w.generateAddress(false);
|
w.generateAddress(false, k.pub);
|
||||||
|
|
||||||
var w2 = new PublicKeyRing({
|
var w2 = new PublicKeyRing({
|
||||||
networkName: 'livenet',
|
networkName: 'livenet',
|
||||||
|
@ -188,8 +192,8 @@ describe('PublicKeyRing model', function() {
|
||||||
w2.merge(w).should.equal(true);
|
w2.merge(w).should.equal(true);
|
||||||
w2.requiredCopayers.should.equal(3);
|
w2.requiredCopayers.should.equal(3);
|
||||||
w2.totalCopayers.should.equal(5);
|
w2.totalCopayers.should.equal(5);
|
||||||
w2.indexes.getChangeIndex().should.equal(2);
|
w2.getIndex(k.pub).getChangeIndex().should.equal(2);
|
||||||
w2.indexes.getReceiveIndex().should.equal(3);
|
w2.getIndex(k.pub).getReceiveIndex().should.equal(3);
|
||||||
|
|
||||||
//
|
//
|
||||||
w2.merge(w).should.equal(false);
|
w2.merge(w).should.equal(false);
|
||||||
|
@ -380,15 +384,36 @@ describe('PublicKeyRing model', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('#getIndex should return the right one', function() {
|
||||||
|
var config = {
|
||||||
|
networkName: 'livenet',
|
||||||
|
};
|
||||||
|
var p = new PublicKeyRing(config);
|
||||||
|
var i = p.getIndex(Structure.SHARED_INDEX);
|
||||||
|
should.exist(i);
|
||||||
|
i.cosigner.should.equal(Structure.SHARED_INDEX);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('#getIndex should throw error', function() {
|
||||||
|
var config = {
|
||||||
|
networkName: 'livenet',
|
||||||
|
};
|
||||||
|
var p = new PublicKeyRing(config);
|
||||||
|
|
||||||
|
(function badCosigner() {
|
||||||
|
return p.getIndex(54);
|
||||||
|
}).should.throw();
|
||||||
|
});
|
||||||
|
|
||||||
it('#getRedeemScriptMap check tests', function() {
|
it('#getRedeemScriptMap check tests', function() {
|
||||||
var k = createW();
|
var k = createW();
|
||||||
var w = k.w;
|
var w = k.w;
|
||||||
var amount = 2;
|
var amount = 2;
|
||||||
|
|
||||||
for (var i = 0; i < amount; i++)
|
for (var i = 0; i < amount; i++)
|
||||||
w.generateAddress(true);
|
w.generateAddress(true, k.pub);
|
||||||
for (var i = 0; i < amount; i++)
|
for (var i = 0; i < amount; i++)
|
||||||
w.generateAddress(false);
|
w.generateAddress(false, k.pub);
|
||||||
|
|
||||||
var m = w.getRedeemScriptMap([
|
var m = w.getRedeemScriptMap([
|
||||||
'm/45\'/2147483647/1/0',
|
'm/45\'/2147483647/1/0',
|
||||||
|
|
|
@ -51,12 +51,15 @@ var createPKR = function(bip32s) {
|
||||||
w.addCopayer();
|
w.addCopayer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.generateAddress(false);
|
|
||||||
w.generateAddress(false);
|
var pubkey = bip32s[0].publicHex;
|
||||||
w.generateAddress(false);
|
|
||||||
w.generateAddress(true);
|
w.generateAddress(false, pubkey);
|
||||||
w.generateAddress(true);
|
w.generateAddress(false, pubkey);
|
||||||
w.generateAddress(true);
|
w.generateAddress(false, pubkey);
|
||||||
|
w.generateAddress(true, pubkey);
|
||||||
|
w.generateAddress(true, pubkey);
|
||||||
|
w.generateAddress(true, pubkey);
|
||||||
|
|
||||||
return w;
|
return w;
|
||||||
};
|
};
|
||||||
|
@ -77,19 +80,22 @@ describe('TxProposals model', function() {
|
||||||
var priv = new PrivateKey(config);
|
var priv = new PrivateKey(config);
|
||||||
var priv2 = new PrivateKey(config);
|
var priv2 = new PrivateKey(config);
|
||||||
var priv3 = new PrivateKey(config);
|
var priv3 = new PrivateKey(config);
|
||||||
|
var pub = priv.publicHex;
|
||||||
|
|
||||||
var ts = Date.now();
|
var ts = Date.now();
|
||||||
var pkr = createPKR([priv, priv2, priv3]);
|
var pkr = createPKR([priv, priv2, priv3]);
|
||||||
var opts = {
|
var opts = {
|
||||||
remainderOut: {
|
remainderOut: {
|
||||||
address: pkr.generateAddress(true).toString()
|
address: pkr.generateAddress(true, pub).toString()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var w = new TxProposals({
|
var w = new TxProposals({
|
||||||
networkName: config.networkName,
|
networkName: config.networkName,
|
||||||
});
|
});
|
||||||
unspentTest[0].address = pkr.getAddress(index, isChange).toString();
|
|
||||||
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
|
unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString();
|
||||||
|
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub);
|
||||||
w.add(createTx(
|
w.add(createTx(
|
||||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||||
'123456789',
|
'123456789',
|
||||||
|
@ -102,8 +108,10 @@ describe('TxProposals model', function() {
|
||||||
var b = w.txps[ntxid].builder;
|
var b = w.txps[ntxid].builder;
|
||||||
var tx = b.build();
|
var tx = b.build();
|
||||||
tx.isComplete().should.equal(false);
|
tx.isComplete().should.equal(false);
|
||||||
b.sign(priv2.getAll(pkr.indexes.getReceiveIndex(), pkr.indexes.getChangeIndex()));
|
|
||||||
b.sign(priv3.getAll(pkr.indexes.getReceiveIndex(), pkr.indexes.getChangeIndex()));
|
var ringIndex = pkr.getIndex(pub);
|
||||||
|
b.sign(priv2.getAll(ringIndex.getReceiveIndex(), ringIndex.getChangeIndex(), ringIndex.cosigner));
|
||||||
|
b.sign(priv3.getAll(ringIndex.getReceiveIndex(), ringIndex.getChangeIndex(), ringIndex.cosigner));
|
||||||
tx = b.build();
|
tx = b.build();
|
||||||
tx.isComplete().should.equal(true);
|
tx.isComplete().should.equal(true);
|
||||||
|
|
||||||
|
@ -132,6 +140,7 @@ describe('TxProposals model', function() {
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
|
|
||||||
var amountSat = bitcore.Bignum(amountSatStr);
|
var amountSat = bitcore.Bignum(amountSatStr);
|
||||||
|
var pub = priv.publicHex;
|
||||||
|
|
||||||
if (!pkr.isComplete()) {
|
if (!pkr.isComplete()) {
|
||||||
throw new Error('publicKeyRing is not complete');
|
throw new Error('publicKeyRing is not complete');
|
||||||
|
@ -139,7 +148,7 @@ describe('TxProposals model', function() {
|
||||||
|
|
||||||
if (!opts.remainderOut) {
|
if (!opts.remainderOut) {
|
||||||
opts.remainderOut = {
|
opts.remainderOut = {
|
||||||
address: pkr.generateAddress(true).toString()
|
address: pkr.generateAddress(true, pub).toString()
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -181,14 +190,16 @@ describe('TxProposals model', function() {
|
||||||
|
|
||||||
it('#getUsedUnspend', function() {
|
it('#getUsedUnspend', function() {
|
||||||
var priv = new PrivateKey(config);
|
var priv = new PrivateKey(config);
|
||||||
|
var pub = priv.publicHex;
|
||||||
|
|
||||||
var w = new TxProposals({
|
var w = new TxProposals({
|
||||||
networkName: config.networkName,
|
networkName: config.networkName,
|
||||||
});
|
});
|
||||||
var start = new Date().getTime();
|
var start = new Date().getTime();
|
||||||
var pkr = createPKR([priv]);
|
var pkr = createPKR([priv]);
|
||||||
var ts = Date.now();
|
var ts = Date.now();
|
||||||
unspentTest[0].address = pkr.getAddress(index, isChange).toString();
|
unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString();
|
||||||
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
|
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub);
|
||||||
w.add(createTx(
|
w.add(createTx(
|
||||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||||
'123456789',
|
'123456789',
|
||||||
|
@ -204,6 +215,8 @@ describe('TxProposals model', function() {
|
||||||
|
|
||||||
it('#merge with self', function() {
|
it('#merge with self', function() {
|
||||||
var priv = new PrivateKey(config);
|
var priv = new PrivateKey(config);
|
||||||
|
var pub = priv.publicHex;
|
||||||
|
|
||||||
var w = new TxProposals({
|
var w = new TxProposals({
|
||||||
networkName: config.networkName,
|
networkName: config.networkName,
|
||||||
});
|
});
|
||||||
|
@ -211,8 +224,8 @@ describe('TxProposals model', function() {
|
||||||
var pkr = createPKR([priv]);
|
var pkr = createPKR([priv]);
|
||||||
var ts = Date.now();
|
var ts = Date.now();
|
||||||
|
|
||||||
unspentTest[0].address = pkr.getAddress(index, isChange).toString();
|
unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString();
|
||||||
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
|
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub);
|
||||||
w.add(createTx(
|
w.add(createTx(
|
||||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||||
'123456789',
|
'123456789',
|
||||||
|
@ -246,11 +259,13 @@ describe('TxProposals model', function() {
|
||||||
it('#merge, merge signatures case 1', function() {
|
it('#merge, merge signatures case 1', function() {
|
||||||
var priv2 = new PrivateKey(config);
|
var priv2 = new PrivateKey(config);
|
||||||
var priv = new PrivateKey(config);
|
var priv = new PrivateKey(config);
|
||||||
|
var pub = priv.publicHex;
|
||||||
|
|
||||||
var ts = Date.now();
|
var ts = Date.now();
|
||||||
var pkr = createPKR([priv]);
|
var pkr = createPKR([priv]);
|
||||||
var opts = {
|
var opts = {
|
||||||
remainderOut: {
|
remainderOut: {
|
||||||
address: pkr.generateAddress(true).toString()
|
address: pkr.generateAddress(true, pub).toString()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -258,8 +273,8 @@ describe('TxProposals model', function() {
|
||||||
var w = new TxProposals({
|
var w = new TxProposals({
|
||||||
networkName: config.networkName,
|
networkName: config.networkName,
|
||||||
});
|
});
|
||||||
unspentTest[0].address = pkr.getAddress(index, isChange).toString();
|
unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString();
|
||||||
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
|
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub);
|
||||||
w.add(createTx(
|
w.add(createTx(
|
||||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||||
'123456789',
|
'123456789',
|
||||||
|
@ -282,8 +297,8 @@ describe('TxProposals model', function() {
|
||||||
networkName: config.networkName,
|
networkName: config.networkName,
|
||||||
publicKeyRing: w.publicKeyRing,
|
publicKeyRing: w.publicKeyRing,
|
||||||
});
|
});
|
||||||
unspentTest[0].address = pkr.getAddress(index, isChange).toString();
|
unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString();
|
||||||
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
|
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub);
|
||||||
w2.add(createTx(
|
w2.add(createTx(
|
||||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||||
'123456789',
|
'123456789',
|
||||||
|
@ -346,6 +361,7 @@ describe('TxProposals model', function() {
|
||||||
var priv = PrivateKey.fromObj(o1);
|
var priv = PrivateKey.fromObj(o1);
|
||||||
var priv2 = PrivateKey.fromObj(o2);
|
var priv2 = PrivateKey.fromObj(o2);
|
||||||
var priv3 = PrivateKey.fromObj(o3);
|
var priv3 = PrivateKey.fromObj(o3);
|
||||||
|
var pub = priv.publicHex;
|
||||||
|
|
||||||
var ts = Date.now();
|
var ts = Date.now();
|
||||||
var pkr = createPKR([priv, priv2]);
|
var pkr = createPKR([priv, priv2]);
|
||||||
|
@ -354,9 +370,9 @@ describe('TxProposals model', function() {
|
||||||
address: '2MxK2m7cPtEwjZBB8Ksq7ppjkgJyFPJGemr'
|
address: '2MxK2m7cPtEwjZBB8Ksq7ppjkgJyFPJGemr'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var addressToSign = pkr.generateAddress(false);
|
var addressToSign = pkr.generateAddress(false, pub);
|
||||||
unspentTest[0].address = addressToSign.toString();
|
unspentTest[0].address = addressToSign.toString();
|
||||||
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
|
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub);
|
||||||
var tx, txb;
|
var tx, txb;
|
||||||
|
|
||||||
var w = new TxProposals({
|
var w = new TxProposals({
|
||||||
|
@ -459,19 +475,22 @@ describe('TxProposals model', function() {
|
||||||
var priv = new PrivateKey(config);
|
var priv = new PrivateKey(config);
|
||||||
var priv2 = new PrivateKey(config);
|
var priv2 = new PrivateKey(config);
|
||||||
var priv3 = new PrivateKey(config);
|
var priv3 = new PrivateKey(config);
|
||||||
|
var pub = priv.publicHex;
|
||||||
|
|
||||||
|
|
||||||
var ts = Date.now();
|
var ts = Date.now();
|
||||||
var pkr = createPKR([priv, priv2, priv3]);
|
var pkr = createPKR([priv, priv2, priv3]);
|
||||||
var opts = {
|
var opts = {
|
||||||
remainderOut: {
|
remainderOut: {
|
||||||
address: pkr.generateAddress(true).toString()
|
address: pkr.generateAddress(true, pub).toString()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var w = new TxProposals({
|
var w = new TxProposals({
|
||||||
networkName: config.networkName,
|
networkName: config.networkName,
|
||||||
});
|
});
|
||||||
unspentTest[0].address = pkr.getAddress(index, isChange).toString();
|
unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString();
|
||||||
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
|
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub);
|
||||||
w.add(createTx(
|
w.add(createTx(
|
||||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||||
'123456789',
|
'123456789',
|
||||||
|
@ -491,8 +510,8 @@ describe('TxProposals model', function() {
|
||||||
var w2 = new TxProposals({
|
var w2 = new TxProposals({
|
||||||
networkName: config.networkName,
|
networkName: config.networkName,
|
||||||
});
|
});
|
||||||
unspentTest[0].address = pkr.getAddress(index, isChange).toString();
|
unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString();
|
||||||
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
|
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub);
|
||||||
w2.add(createTx(
|
w2.add(createTx(
|
||||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||||
'123456789',
|
'123456789',
|
||||||
|
@ -511,8 +530,8 @@ describe('TxProposals model', function() {
|
||||||
var w3 = new TxProposals({
|
var w3 = new TxProposals({
|
||||||
networkName: config.networkName,
|
networkName: config.networkName,
|
||||||
});
|
});
|
||||||
unspentTest[0].address = pkr.getAddress(index, isChange).toString();
|
unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString();
|
||||||
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
|
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub);
|
||||||
w3.add(createTx(
|
w3.add(createTx(
|
||||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||||
'123456789',
|
'123456789',
|
||||||
|
@ -558,6 +577,8 @@ describe('TxProposals model', function() {
|
||||||
it('#toObj #fromObj roundtrip', function() {
|
it('#toObj #fromObj roundtrip', function() {
|
||||||
|
|
||||||
var priv = new PrivateKey(config);
|
var priv = new PrivateKey(config);
|
||||||
|
var pub = priv.publicHex;
|
||||||
|
|
||||||
var pkr = createPKR([priv]);
|
var pkr = createPKR([priv]);
|
||||||
var w = new TxProposals({
|
var w = new TxProposals({
|
||||||
walletId: 'qwerty',
|
walletId: 'qwerty',
|
||||||
|
@ -565,8 +586,8 @@ describe('TxProposals model', function() {
|
||||||
});
|
});
|
||||||
var ts = Date.now();
|
var ts = Date.now();
|
||||||
|
|
||||||
unspentTest[0].address = pkr.getAddress(index, isChange).toString();
|
unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString();
|
||||||
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange);
|
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub);
|
||||||
w.add(createTx(
|
w.add(createTx(
|
||||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||||
'123456789',
|
'123456789',
|
||||||
|
|
|
@ -9,6 +9,7 @@ try {
|
||||||
var copay = require('../copay'); //node
|
var copay = require('../copay'); //node
|
||||||
}
|
}
|
||||||
var Wallet = require('../js/models/core/Wallet');
|
var Wallet = require('../js/models/core/Wallet');
|
||||||
|
var Structure = copay.Structure;
|
||||||
var Storage = require('./mocks/FakeStorage');
|
var Storage = require('./mocks/FakeStorage');
|
||||||
var Network = require('./mocks/FakeNetwork');
|
var Network = require('./mocks/FakeNetwork');
|
||||||
var Blockchain = require('./mocks/FakeBlockchain');
|
var Blockchain = require('./mocks/FakeBlockchain');
|
||||||
|
@ -122,7 +123,7 @@ describe('Wallet model', function() {
|
||||||
var opts = {};
|
var opts = {};
|
||||||
var w = cachedCreateW();
|
var w = cachedCreateW();
|
||||||
addCopayers(w);
|
addCopayers(w);
|
||||||
w.publicKeyRing.generateAddress(false);
|
w.publicKeyRing.generateAddress(false, w.publicKey);
|
||||||
w.publicKeyRing.isComplete().should.equal(true);
|
w.publicKeyRing.isComplete().should.equal(true);
|
||||||
w.generateAddress(true).isValid().should.equal(true);
|
w.generateAddress(true).isValid().should.equal(true);
|
||||||
w.generateAddress(true, function(addr) {
|
w.generateAddress(true, function(addr) {
|
||||||
|
@ -194,8 +195,8 @@ describe('Wallet model', function() {
|
||||||
|
|
||||||
var w = cachedCreateW2();
|
var w = cachedCreateW2();
|
||||||
|
|
||||||
unspentTest[0].address = w.publicKeyRing.getAddress(1, true).toString();
|
unspentTest[0].address = w.publicKeyRing.getAddress(1, true, w.publicKey).toString();
|
||||||
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true);
|
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true, w.publicKey);
|
||||||
|
|
||||||
var ntxid = w.createTxSync(
|
var ntxid = w.createTxSync(
|
||||||
'mgGJEugdPnvhmRuFdbdQcFfoFLc1XXeB79',
|
'mgGJEugdPnvhmRuFdbdQcFfoFLc1XXeB79',
|
||||||
|
@ -219,8 +220,8 @@ describe('Wallet model', function() {
|
||||||
var w = cachedCreateW2();
|
var w = cachedCreateW2();
|
||||||
var comment = 'This is a comment';
|
var comment = 'This is a comment';
|
||||||
|
|
||||||
unspentTest[0].address = w.publicKeyRing.getAddress(1, true).toString();
|
unspentTest[0].address = w.publicKeyRing.getAddress(1, true, w.publicKey).toString();
|
||||||
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true);
|
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true, w.publicKey);
|
||||||
|
|
||||||
var ntxid = w.createTxSync(
|
var ntxid = w.createTxSync(
|
||||||
'mgGJEugdPnvhmRuFdbdQcFfoFLc1XXeB79',
|
'mgGJEugdPnvhmRuFdbdQcFfoFLc1XXeB79',
|
||||||
|
@ -241,8 +242,8 @@ describe('Wallet model', function() {
|
||||||
var w = cachedCreateW2();
|
var w = cachedCreateW2();
|
||||||
var comment = 'Lorem ipsum dolor sit amet, suas euismod vis te, velit deleniti vix an. Pri ex suscipit similique, inermis per';
|
var comment = 'Lorem ipsum dolor sit amet, suas euismod vis te, velit deleniti vix an. Pri ex suscipit similique, inermis per';
|
||||||
|
|
||||||
unspentTest[0].address = w.publicKeyRing.getAddress(1, true).toString();
|
unspentTest[0].address = w.publicKeyRing.getAddress(1, true, w.publicKey).toString();
|
||||||
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true);
|
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true, w.publicKey);
|
||||||
|
|
||||||
var badCreate = function() {
|
var badCreate = function() {
|
||||||
w.createTxSync(
|
w.createTxSync(
|
||||||
|
@ -277,8 +278,8 @@ describe('Wallet model', function() {
|
||||||
var ts = Date.now();
|
var ts = Date.now();
|
||||||
for (var isChange = false; !isChange; isChange = true) {
|
for (var isChange = false; !isChange; isChange = true) {
|
||||||
for (var index = 0; index < 3; index++) {
|
for (var index = 0; index < 3; index++) {
|
||||||
unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange).toString();
|
unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange, w.publicKey).toString();
|
||||||
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange);
|
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange, w.publicKey);
|
||||||
w.createTxSync(
|
w.createTxSync(
|
||||||
'mgGJEugdPnvhmRuFdbdQcFfoFLc1XXeB79',
|
'mgGJEugdPnvhmRuFdbdQcFfoFLc1XXeB79',
|
||||||
'123456789',
|
'123456789',
|
||||||
|
@ -359,13 +360,15 @@ describe('Wallet model', function() {
|
||||||
it('handle network indexes correctly', function() {
|
it('handle network indexes correctly', function() {
|
||||||
var w = createW();
|
var w = createW();
|
||||||
var aiObj = {
|
var aiObj = {
|
||||||
walletId: w.id,
|
indexes: [{
|
||||||
|
cosigner: 0,
|
||||||
changeIndex: 3,
|
changeIndex: 3,
|
||||||
receiveIndex: 2
|
receiveIndex: 2
|
||||||
|
}]
|
||||||
};
|
};
|
||||||
w._handleIndexes('senderID', aiObj, true);
|
w._handleIndexes('senderID', aiObj, true);
|
||||||
w.publicKeyRing.indexes.getReceiveIndex(2);
|
w.publicKeyRing.getIndex(0).getReceiveIndex(2);
|
||||||
w.publicKeyRing.indexes.getChangeIndex(3);
|
w.publicKeyRing.getIndex(0).getChangeIndex(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handle network pubKeyRings correctly', function() {
|
it('handle network pubKeyRings correctly', function() {
|
||||||
|
@ -381,19 +384,19 @@ describe('Wallet model', function() {
|
||||||
networkName: w.networkName,
|
networkName: w.networkName,
|
||||||
requiredCopayers: w.requiredCopayers,
|
requiredCopayers: w.requiredCopayers,
|
||||||
totalCopayers: w.totalCopayers,
|
totalCopayers: w.totalCopayers,
|
||||||
indexes: {
|
indexes: [{
|
||||||
walletId: undefined,
|
cosigner: 0,
|
||||||
changeIndex: 2,
|
changeIndex: 2,
|
||||||
receiveIndex: 3
|
receiveIndex: 3
|
||||||
},
|
}],
|
||||||
copayersExtPubKeys: cepk,
|
copayersExtPubKeys: cepk,
|
||||||
nicknameFor: {},
|
nicknameFor: {},
|
||||||
};
|
};
|
||||||
w._handlePublicKeyRing('senderID', {
|
w._handlePublicKeyRing('senderID', {
|
||||||
publicKeyRing: pkrObj
|
publicKeyRing: pkrObj
|
||||||
}, true);
|
}, true);
|
||||||
w.publicKeyRing.indexes.getReceiveIndex(2);
|
w.publicKeyRing.getIndex(0).getReceiveIndex(2);
|
||||||
w.publicKeyRing.indexes.getChangeIndex(3);
|
w.publicKeyRing.getIndex(0).getChangeIndex(3);
|
||||||
for (var i = 0; i < w.requiredCopayers; i++) {
|
for (var i = 0; i < w.requiredCopayers; i++) {
|
||||||
w.publicKeyRing.toObj().copayersExtPubKeys[i].should.equal(cepk[i]);
|
w.publicKeyRing.toObj().copayersExtPubKeys[i].should.equal(cepk[i]);
|
||||||
}
|
}
|
||||||
|
@ -685,8 +688,8 @@ describe('Wallet model', function() {
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
w = cachedCreateW2();
|
w = cachedCreateW2();
|
||||||
ADDRESSES_CHANGE = w.deriveAddresses(0, 20, true);
|
ADDRESSES_CHANGE = w.deriveAddresses(0, 20, true, 0);
|
||||||
ADDRESSES_RECEIVE = w.deriveAddresses(0, 20, false);
|
ADDRESSES_RECEIVE = w.deriveAddresses(0, 20, false, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
var mockFakeActivity = function(f) {
|
var mockFakeActivity = function(f) {
|
||||||
|
@ -705,7 +708,7 @@ describe('Wallet model', function() {
|
||||||
mockFakeActivity(function(index) {
|
mockFakeActivity(function(index) {
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
w.indexDiscovery(0, false, 5, function(e, lastActive) {
|
w.indexDiscovery(0, false, 0, 5, function(e, lastActive) {
|
||||||
lastActive.should.equal(-1);
|
lastActive.should.equal(-1);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -715,7 +718,7 @@ describe('Wallet model', function() {
|
||||||
mockFakeActivity(function(index) {
|
mockFakeActivity(function(index) {
|
||||||
return index <= 7;
|
return index <= 7;
|
||||||
});
|
});
|
||||||
w.indexDiscovery(0, false, 5, function(e, lastActive) {
|
w.indexDiscovery(0, false, 0, 5, function(e, lastActive) {
|
||||||
lastActive.should.equal(7);
|
lastActive.should.equal(7);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -725,7 +728,7 @@ describe('Wallet model', function() {
|
||||||
mockFakeActivity(function(index) {
|
mockFakeActivity(function(index) {
|
||||||
return index <= 10 || index == 17;
|
return index <= 10 || index == 17;
|
||||||
});
|
});
|
||||||
w.indexDiscovery(0, false, 5, function(e, lastActive) {
|
w.indexDiscovery(0, false, 0, 5, function(e, lastActive) {
|
||||||
lastActive.should.equal(10);
|
lastActive.should.equal(10);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -735,7 +738,7 @@ describe('Wallet model', function() {
|
||||||
mockFakeActivity(function(index) {
|
mockFakeActivity(function(index) {
|
||||||
return index <= 14 && index % 2 == 0;
|
return index <= 14 && index % 2 == 0;
|
||||||
});
|
});
|
||||||
w.indexDiscovery(0, false, 5, function(e, lastActive) {
|
w.indexDiscovery(0, false, 0, 5, function(e, lastActive) {
|
||||||
lastActive.should.equal(14);
|
lastActive.should.equal(14);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -747,8 +750,11 @@ describe('Wallet model', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
w.updateIndexes(function(err) {
|
w.updateIndexes(function(err) {
|
||||||
w.publicKeyRing.indexes.receiveIndex.should.equal(15);
|
w.publicKeyRing.getIndex(0).receiveIndex.should.equal(15);
|
||||||
w.publicKeyRing.indexes.changeIndex.should.equal(15);
|
w.publicKeyRing.getIndex(0).changeIndex.should.equal(15);
|
||||||
|
|
||||||
|
w.publicKeyRing.getIndex(1).receiveIndex.should.equal(0);
|
||||||
|
w.publicKeyRing.getIndex(1).changeIndex.should.equal(0);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -768,8 +774,8 @@ describe('Wallet model', function() {
|
||||||
|
|
||||||
it('#deriveAddresses', function(done) {
|
it('#deriveAddresses', function(done) {
|
||||||
var w = cachedCreateW2();
|
var w = cachedCreateW2();
|
||||||
var addresses1 = w.deriveAddresses(0, 5, false);
|
var addresses1 = w.deriveAddresses(0, 5, false, 0);
|
||||||
var addresses2 = w.deriveAddresses(4, 5, false);
|
var addresses2 = w.deriveAddresses(4, 5, false, 0);
|
||||||
|
|
||||||
addresses1.length.should.equal(5);
|
addresses1.length.should.equal(5);
|
||||||
addresses2.length.should.equal(5);
|
addresses2.length.should.equal(5);
|
||||||
|
|
|
@ -10,7 +10,7 @@ var FakeBlockchain = require('./mocks/FakeBlockchain');
|
||||||
var FakeStorage = require('./mocks/FakeStorage');
|
var FakeStorage = require('./mocks/FakeStorage');
|
||||||
var WalletFactory = require('../js/models/core/WalletFactory');
|
var WalletFactory = require('../js/models/core/WalletFactory');
|
||||||
|
|
||||||
var o = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5"},"publicKeyRing":{"walletId":"dbfe10c3fae71cea","networkName":"testnet","requiredCopayers":3,"totalCopayers":5,"indexes":{"changeIndex":0,"receiveIndex":0},"copayersExtPubKeys":["tpubD6NzVbkrYhZ4YGK8ZhZ8WVeBXNAAoTYjjpw9twCPiNGrGQYFktP3iVQkKmZNiFnUcAFMJRxJVJF6Nq9MDv2kiRceExJaHFbxUCGUiRhmy97","tpubD6NzVbkrYhZ4YKGDJkzWdQsQV3AcFemaQKiwNhV4RL8FHnBFvinidGdQtP8RKj3h34E65RkdtxjrggZYqsEwJ8RhhN2zz9VrjLnrnwbXYNc","tpubD6NzVbkrYhZ4YkDiewjb32Pp3Sz9WK2jpp37KnL7RCrHAyPpnLfgdfRnTdpn6DTWmPS7niywfgWiT42aJb1J6CjWVNmkgsMCxuw7j9DaGKB","tpubD6NzVbkrYhZ4XEtUAz4UUTWbprewbLTaMhR8NUvSJUEAh4Sidxr6rRPFdqqVRR73btKf13wUjds2i8vVCNo8sbKrAnyoTr3o5Y6QSbboQjk","tpubD6NzVbkrYhZ4Yj9AAt6xUVuGPVd8jXCrEE6V2wp7U3PFh8jYYvVad31b4VUXEYXzSnkco4fktu8r4icBsB2t3pCR3WnhVLedY2hxGcPFLKD"],"nicknameFor":{},"publicKeysCache":{"m/0/1/0":["0314368b8efa07e8c7dad30498d0a7e3aa575db1fef833347c6d381c1a33a17b17","02cfd95f89ab46bd3bd86954dd9f83dbab0cd2e4466dee587e8e4d8d733fc0d748","02568969eb6212fe946450be6c5b3353fc754a40b2cdc4aed501a8976fec371da8","0360f870a088ae0ef1c37035a9b6a462ca8dcdd5da275f4e2dcd19f44b81d3e7e4","0300ad8f1bded838b02e127bb25961fbcee718db2df81f680f889692acdcbdd73d"],"m/0/1/1":["024f97a9adb2fa9306c4e3d9244f5e5355c7e2c6b3dd4122ba804e17dc9729df5d","0214834a5adcbc4ad0f3bbbc1c280b8ac480387fcc9a1fd988c1526ed496d923c4","024e72338bd5e976375d076bd71a9649e9141b4cbfc9e16cb7109b354b3e913a05","0322045ea35c3118aa7ab9f2c9f182b0120956b0aa65cc72b9d093f145327a4b17","030dc2450c72df366c1960739c577a2efd4451070bd78effcb6f71d1bcd7dfc7a8"],"m/0/1/2":["0247de59deb66783b8f9b0c326234a9569d00866c2a73f599e77a4d0cab5cbce8f","0376e49f0ac3647404034aae0dc8dd927c34a634ef24ea36f56a272f75fce9539b","032fbaa2593bd1eea4a46e7ac15f15802cdd1eb65a7d5bc4364ddd9d52f0838234","03a81f2a7e1f7191aa0b0c6e0a4ccefc71edd3564e86014972fe338045f68d5a5a","02eb8a012ea9a709392502cacda6ef5115d6d2319ab470d546d9068ab941621a99"],"m/0/0/0":["036dcbd378b4352120d6b720b6294dd2d0dd02801fcf010bb69dadbec1f3999279","022089eedb85dc45d1efa418e1ea226588deedebc1d85acca15ff72783e33636c0","0388aa5fd432b74c56427396f350d236c3ca8f7b2f62da513ce4c2e6ff04a67e9c","02fc4caa7449db7483d2e1fccdacac6fa2f736278c758af9966402589b5632f13e","02e4a15b885d8b2d586f82fa85d16179644e60a154674bde0ec3004810b1bdab99"],"m/0/0/1":["039afa26b2f341c76c7b3c3d0672438f35ac6ebb67b1ddfefac9cd79b7b24418c1","021acaaf500d431ebc396f50630767b01c91ce98ae48e968775ceaad932b7e3b8e","022a947259c4a9f76d5e95c0849df31d01233df41d0d75d631b89317a48d8cddce","03d38d9f94217da780303d9a8987c86d737ef39683febc0cd6632cddbfa62186fd","0394d2581b307fe2af19721888d922aab58ab198ef88cedf9506177e30d807811e"],"m/0/0/2":["037825ffce15d34f9bd6c02bcda7701826706471a4d6ab5004eb965f98811c2098","023768dd6d3c71b7df5733ccda5b2d8b454d5b4c4179d91a6fda74db8b869a2406","021a79e91f003f308764d43039e9b5d56bc8f33ca2f4d30ec6cc5a37c0d09dc273","02437f1e388b273936319f79a5d22958ef5ebff9c8cd7b6f6f72518445b1e30867","0373b0881cb4fd02baa62589023fdfe9739c6148cf104d907549f2528eb80146f5"]}},"txProposals":{"txps":[],"walletId":"dbfe10c3fae71cea","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPeoHLg3tY75z4xLeEe8MqAXLNcRA6J6UTRvHV8VZTXznt9eoTmSk1fwSrwZtMhY3XkNsceJ14h6sCXHSWinRqMSSbY8tfhHi","networkName":"testnet","privateKeyCache":{}},"addressBook":{},"backupOffered":false}';
|
var o = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5"},"publicKeyRing":{"walletId":"dbfe10c3fae71cea","networkName":"testnet","requiredCopayers":3,"totalCopayers":5,"indexes":[{"cosigner":2,"changeIndex":0,"receiveIndex":0}],"copayersExtPubKeys":["tpubD6NzVbkrYhZ4YGK8ZhZ8WVeBXNAAoTYjjpw9twCPiNGrGQYFktP3iVQkKmZNiFnUcAFMJRxJVJF6Nq9MDv2kiRceExJaHFbxUCGUiRhmy97","tpubD6NzVbkrYhZ4YKGDJkzWdQsQV3AcFemaQKiwNhV4RL8FHnBFvinidGdQtP8RKj3h34E65RkdtxjrggZYqsEwJ8RhhN2zz9VrjLnrnwbXYNc","tpubD6NzVbkrYhZ4YkDiewjb32Pp3Sz9WK2jpp37KnL7RCrHAyPpnLfgdfRnTdpn6DTWmPS7niywfgWiT42aJb1J6CjWVNmkgsMCxuw7j9DaGKB","tpubD6NzVbkrYhZ4XEtUAz4UUTWbprewbLTaMhR8NUvSJUEAh4Sidxr6rRPFdqqVRR73btKf13wUjds2i8vVCNo8sbKrAnyoTr3o5Y6QSbboQjk","tpubD6NzVbkrYhZ4Yj9AAt6xUVuGPVd8jXCrEE6V2wp7U3PFh8jYYvVad31b4VUXEYXzSnkco4fktu8r4icBsB2t3pCR3WnhVLedY2hxGcPFLKD"],"nicknameFor":{},"publicKeysCache":{"m/0/1/0":["0314368b8efa07e8c7dad30498d0a7e3aa575db1fef833347c6d381c1a33a17b17","02cfd95f89ab46bd3bd86954dd9f83dbab0cd2e4466dee587e8e4d8d733fc0d748","02568969eb6212fe946450be6c5b3353fc754a40b2cdc4aed501a8976fec371da8","0360f870a088ae0ef1c37035a9b6a462ca8dcdd5da275f4e2dcd19f44b81d3e7e4","0300ad8f1bded838b02e127bb25961fbcee718db2df81f680f889692acdcbdd73d"],"m/0/1/1":["024f97a9adb2fa9306c4e3d9244f5e5355c7e2c6b3dd4122ba804e17dc9729df5d","0214834a5adcbc4ad0f3bbbc1c280b8ac480387fcc9a1fd988c1526ed496d923c4","024e72338bd5e976375d076bd71a9649e9141b4cbfc9e16cb7109b354b3e913a05","0322045ea35c3118aa7ab9f2c9f182b0120956b0aa65cc72b9d093f145327a4b17","030dc2450c72df366c1960739c577a2efd4451070bd78effcb6f71d1bcd7dfc7a8"],"m/0/1/2":["0247de59deb66783b8f9b0c326234a9569d00866c2a73f599e77a4d0cab5cbce8f","0376e49f0ac3647404034aae0dc8dd927c34a634ef24ea36f56a272f75fce9539b","032fbaa2593bd1eea4a46e7ac15f15802cdd1eb65a7d5bc4364ddd9d52f0838234","03a81f2a7e1f7191aa0b0c6e0a4ccefc71edd3564e86014972fe338045f68d5a5a","02eb8a012ea9a709392502cacda6ef5115d6d2319ab470d546d9068ab941621a99"],"m/0/0/0":["036dcbd378b4352120d6b720b6294dd2d0dd02801fcf010bb69dadbec1f3999279","022089eedb85dc45d1efa418e1ea226588deedebc1d85acca15ff72783e33636c0","0388aa5fd432b74c56427396f350d236c3ca8f7b2f62da513ce4c2e6ff04a67e9c","02fc4caa7449db7483d2e1fccdacac6fa2f736278c758af9966402589b5632f13e","02e4a15b885d8b2d586f82fa85d16179644e60a154674bde0ec3004810b1bdab99"],"m/0/0/1":["039afa26b2f341c76c7b3c3d0672438f35ac6ebb67b1ddfefac9cd79b7b24418c1","021acaaf500d431ebc396f50630767b01c91ce98ae48e968775ceaad932b7e3b8e","022a947259c4a9f76d5e95c0849df31d01233df41d0d75d631b89317a48d8cddce","03d38d9f94217da780303d9a8987c86d737ef39683febc0cd6632cddbfa62186fd","0394d2581b307fe2af19721888d922aab58ab198ef88cedf9506177e30d807811e"],"m/0/0/2":["037825ffce15d34f9bd6c02bcda7701826706471a4d6ab5004eb965f98811c2098","023768dd6d3c71b7df5733ccda5b2d8b454d5b4c4179d91a6fda74db8b869a2406","021a79e91f003f308764d43039e9b5d56bc8f33ca2f4d30ec6cc5a37c0d09dc273","02437f1e388b273936319f79a5d22958ef5ebff9c8cd7b6f6f72518445b1e30867","0373b0881cb4fd02baa62589023fdfe9739c6148cf104d907549f2528eb80146f5"]}},"txProposals":{"txps":[],"walletId":"dbfe10c3fae71cea","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPeoHLg3tY75z4xLeEe8MqAXLNcRA6J6UTRvHV8VZTXznt9eoTmSk1fwSrwZtMhY3XkNsceJ14h6sCXHSWinRqMSSbY8tfhHi","networkName":"testnet","privateKeyCache":{}},"addressBook":{},"backupOffered":false}';
|
||||||
|
|
||||||
describe('WalletFactory model', function() {
|
describe('WalletFactory model', function() {
|
||||||
var config = {
|
var config = {
|
||||||
|
@ -82,7 +82,6 @@ describe('WalletFactory model', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('#fromObj #toObj round trip', function() {
|
it('#fromObj #toObj round trip', function() {
|
||||||
|
|
||||||
var wf = new WalletFactory(config, '0.0.5');
|
var wf = new WalletFactory(config, '0.0.5');
|
||||||
var w = wf.fromObj(JSON.parse(o));
|
var w = wf.fromObj(JSON.parse(o));
|
||||||
|
|
||||||
|
@ -95,6 +94,22 @@ describe('WalletFactory model', function() {
|
||||||
JSON.stringify(w.toObj()).should.equal(o);
|
JSON.stringify(w.toObj()).should.equal(o);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('support old index schema: #fromObj #toObj round trip', function() {
|
||||||
|
var o = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5"},"publicKeyRing":{"walletId":"dbfe10c3fae71cea","networkName":"testnet","requiredCopayers":3,"totalCopayers":5,"indexes":{"changeIndex":0,"receiveIndex":0},"copayersExtPubKeys":["tpubD6NzVbkrYhZ4YGK8ZhZ8WVeBXNAAoTYjjpw9twCPiNGrGQYFktP3iVQkKmZNiFnUcAFMJRxJVJF6Nq9MDv2kiRceExJaHFbxUCGUiRhmy97","tpubD6NzVbkrYhZ4YKGDJkzWdQsQV3AcFemaQKiwNhV4RL8FHnBFvinidGdQtP8RKj3h34E65RkdtxjrggZYqsEwJ8RhhN2zz9VrjLnrnwbXYNc","tpubD6NzVbkrYhZ4YkDiewjb32Pp3Sz9WK2jpp37KnL7RCrHAyPpnLfgdfRnTdpn6DTWmPS7niywfgWiT42aJb1J6CjWVNmkgsMCxuw7j9DaGKB","tpubD6NzVbkrYhZ4XEtUAz4UUTWbprewbLTaMhR8NUvSJUEAh4Sidxr6rRPFdqqVRR73btKf13wUjds2i8vVCNo8sbKrAnyoTr3o5Y6QSbboQjk","tpubD6NzVbkrYhZ4Yj9AAt6xUVuGPVd8jXCrEE6V2wp7U3PFh8jYYvVad31b4VUXEYXzSnkco4fktu8r4icBsB2t3pCR3WnhVLedY2hxGcPFLKD"],"nicknameFor":{},"publicKeysCache":{"m/0/1/0":["0314368b8efa07e8c7dad30498d0a7e3aa575db1fef833347c6d381c1a33a17b17","02cfd95f89ab46bd3bd86954dd9f83dbab0cd2e4466dee587e8e4d8d733fc0d748","02568969eb6212fe946450be6c5b3353fc754a40b2cdc4aed501a8976fec371da8","0360f870a088ae0ef1c37035a9b6a462ca8dcdd5da275f4e2dcd19f44b81d3e7e4","0300ad8f1bded838b02e127bb25961fbcee718db2df81f680f889692acdcbdd73d"],"m/0/1/1":["024f97a9adb2fa9306c4e3d9244f5e5355c7e2c6b3dd4122ba804e17dc9729df5d","0214834a5adcbc4ad0f3bbbc1c280b8ac480387fcc9a1fd988c1526ed496d923c4","024e72338bd5e976375d076bd71a9649e9141b4cbfc9e16cb7109b354b3e913a05","0322045ea35c3118aa7ab9f2c9f182b0120956b0aa65cc72b9d093f145327a4b17","030dc2450c72df366c1960739c577a2efd4451070bd78effcb6f71d1bcd7dfc7a8"],"m/0/1/2":["0247de59deb66783b8f9b0c326234a9569d00866c2a73f599e77a4d0cab5cbce8f","0376e49f0ac3647404034aae0dc8dd927c34a634ef24ea36f56a272f75fce9539b","032fbaa2593bd1eea4a46e7ac15f15802cdd1eb65a7d5bc4364ddd9d52f0838234","03a81f2a7e1f7191aa0b0c6e0a4ccefc71edd3564e86014972fe338045f68d5a5a","02eb8a012ea9a709392502cacda6ef5115d6d2319ab470d546d9068ab941621a99"],"m/0/0/0":["036dcbd378b4352120d6b720b6294dd2d0dd02801fcf010bb69dadbec1f3999279","022089eedb85dc45d1efa418e1ea226588deedebc1d85acca15ff72783e33636c0","0388aa5fd432b74c56427396f350d236c3ca8f7b2f62da513ce4c2e6ff04a67e9c","02fc4caa7449db7483d2e1fccdacac6fa2f736278c758af9966402589b5632f13e","02e4a15b885d8b2d586f82fa85d16179644e60a154674bde0ec3004810b1bdab99"],"m/0/0/1":["039afa26b2f341c76c7b3c3d0672438f35ac6ebb67b1ddfefac9cd79b7b24418c1","021acaaf500d431ebc396f50630767b01c91ce98ae48e968775ceaad932b7e3b8e","022a947259c4a9f76d5e95c0849df31d01233df41d0d75d631b89317a48d8cddce","03d38d9f94217da780303d9a8987c86d737ef39683febc0cd6632cddbfa62186fd","0394d2581b307fe2af19721888d922aab58ab198ef88cedf9506177e30d807811e"],"m/0/0/2":["037825ffce15d34f9bd6c02bcda7701826706471a4d6ab5004eb965f98811c2098","023768dd6d3c71b7df5733ccda5b2d8b454d5b4c4179d91a6fda74db8b869a2406","021a79e91f003f308764d43039e9b5d56bc8f33ca2f4d30ec6cc5a37c0d09dc273","02437f1e388b273936319f79a5d22958ef5ebff9c8cd7b6f6f72518445b1e30867","0373b0881cb4fd02baa62589023fdfe9739c6148cf104d907549f2528eb80146f5"]}},"txProposals":{"txps":[],"walletId":"dbfe10c3fae71cea","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPeoHLg3tY75z4xLeEe8MqAXLNcRA6J6UTRvHV8VZTXznt9eoTmSk1fwSrwZtMhY3XkNsceJ14h6sCXHSWinRqMSSbY8tfhHi","networkName":"testnet","privateKeyCache":{}},"addressBook":{},"backupOffered":false}';
|
||||||
|
var o2 = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5"},"publicKeyRing":{"walletId":"dbfe10c3fae71cea","networkName":"testnet","requiredCopayers":3,"totalCopayers":5,"indexes":[{"cosigner":2147483647,"changeIndex":0,"receiveIndex":0},{"cosigner":0,"changeIndex":0,"receiveIndex":0},{"cosigner":1,"changeIndex":0,"receiveIndex":0},{"cosigner":2,"changeIndex":0,"receiveIndex":0},{"cosigner":3,"changeIndex":0,"receiveIndex":0},{"cosigner":4,"changeIndex":0,"receiveIndex":0}],"copayersExtPubKeys":["tpubD6NzVbkrYhZ4YGK8ZhZ8WVeBXNAAoTYjjpw9twCPiNGrGQYFktP3iVQkKmZNiFnUcAFMJRxJVJF6Nq9MDv2kiRceExJaHFbxUCGUiRhmy97","tpubD6NzVbkrYhZ4YKGDJkzWdQsQV3AcFemaQKiwNhV4RL8FHnBFvinidGdQtP8RKj3h34E65RkdtxjrggZYqsEwJ8RhhN2zz9VrjLnrnwbXYNc","tpubD6NzVbkrYhZ4YkDiewjb32Pp3Sz9WK2jpp37KnL7RCrHAyPpnLfgdfRnTdpn6DTWmPS7niywfgWiT42aJb1J6CjWVNmkgsMCxuw7j9DaGKB","tpubD6NzVbkrYhZ4XEtUAz4UUTWbprewbLTaMhR8NUvSJUEAh4Sidxr6rRPFdqqVRR73btKf13wUjds2i8vVCNo8sbKrAnyoTr3o5Y6QSbboQjk","tpubD6NzVbkrYhZ4Yj9AAt6xUVuGPVd8jXCrEE6V2wp7U3PFh8jYYvVad31b4VUXEYXzSnkco4fktu8r4icBsB2t3pCR3WnhVLedY2hxGcPFLKD"],"nicknameFor":{},"publicKeysCache":{"m/0/1/0":["0314368b8efa07e8c7dad30498d0a7e3aa575db1fef833347c6d381c1a33a17b17","02cfd95f89ab46bd3bd86954dd9f83dbab0cd2e4466dee587e8e4d8d733fc0d748","02568969eb6212fe946450be6c5b3353fc754a40b2cdc4aed501a8976fec371da8","0360f870a088ae0ef1c37035a9b6a462ca8dcdd5da275f4e2dcd19f44b81d3e7e4","0300ad8f1bded838b02e127bb25961fbcee718db2df81f680f889692acdcbdd73d"],"m/0/1/1":["024f97a9adb2fa9306c4e3d9244f5e5355c7e2c6b3dd4122ba804e17dc9729df5d","0214834a5adcbc4ad0f3bbbc1c280b8ac480387fcc9a1fd988c1526ed496d923c4","024e72338bd5e976375d076bd71a9649e9141b4cbfc9e16cb7109b354b3e913a05","0322045ea35c3118aa7ab9f2c9f182b0120956b0aa65cc72b9d093f145327a4b17","030dc2450c72df366c1960739c577a2efd4451070bd78effcb6f71d1bcd7dfc7a8"],"m/0/1/2":["0247de59deb66783b8f9b0c326234a9569d00866c2a73f599e77a4d0cab5cbce8f","0376e49f0ac3647404034aae0dc8dd927c34a634ef24ea36f56a272f75fce9539b","032fbaa2593bd1eea4a46e7ac15f15802cdd1eb65a7d5bc4364ddd9d52f0838234","03a81f2a7e1f7191aa0b0c6e0a4ccefc71edd3564e86014972fe338045f68d5a5a","02eb8a012ea9a709392502cacda6ef5115d6d2319ab470d546d9068ab941621a99"],"m/0/0/0":["036dcbd378b4352120d6b720b6294dd2d0dd02801fcf010bb69dadbec1f3999279","022089eedb85dc45d1efa418e1ea226588deedebc1d85acca15ff72783e33636c0","0388aa5fd432b74c56427396f350d236c3ca8f7b2f62da513ce4c2e6ff04a67e9c","02fc4caa7449db7483d2e1fccdacac6fa2f736278c758af9966402589b5632f13e","02e4a15b885d8b2d586f82fa85d16179644e60a154674bde0ec3004810b1bdab99"],"m/0/0/1":["039afa26b2f341c76c7b3c3d0672438f35ac6ebb67b1ddfefac9cd79b7b24418c1","021acaaf500d431ebc396f50630767b01c91ce98ae48e968775ceaad932b7e3b8e","022a947259c4a9f76d5e95c0849df31d01233df41d0d75d631b89317a48d8cddce","03d38d9f94217da780303d9a8987c86d737ef39683febc0cd6632cddbfa62186fd","0394d2581b307fe2af19721888d922aab58ab198ef88cedf9506177e30d807811e"],"m/0/0/2":["037825ffce15d34f9bd6c02bcda7701826706471a4d6ab5004eb965f98811c2098","023768dd6d3c71b7df5733ccda5b2d8b454d5b4c4179d91a6fda74db8b869a2406","021a79e91f003f308764d43039e9b5d56bc8f33ca2f4d30ec6cc5a37c0d09dc273","02437f1e388b273936319f79a5d22958ef5ebff9c8cd7b6f6f72518445b1e30867","0373b0881cb4fd02baa62589023fdfe9739c6148cf104d907549f2528eb80146f5"]}},"txProposals":{"txps":[],"walletId":"dbfe10c3fae71cea","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPeoHLg3tY75z4xLeEe8MqAXLNcRA6J6UTRvHV8VZTXznt9eoTmSk1fwSrwZtMhY3XkNsceJ14h6sCXHSWinRqMSSbY8tfhHi","networkName":"testnet","privateKeyCache":{}},"addressBook":{},"backupOffered":false}';
|
||||||
|
|
||||||
|
var wf = new WalletFactory(config, '0.0.5');
|
||||||
|
var w = wf.fromObj(JSON.parse(o));
|
||||||
|
|
||||||
|
should.exist(w);
|
||||||
|
w.id.should.equal("dbfe10c3fae71cea");
|
||||||
|
should.exist(w.publicKeyRing.getCopayerId);
|
||||||
|
should.exist(w.txProposals.toObj);
|
||||||
|
should.exist(w.privateKey.toObj);
|
||||||
|
|
||||||
|
JSON.stringify(w.toObj()).should.equal(o2);
|
||||||
|
});
|
||||||
|
|
||||||
it('should create wallet from encrypted object', function() {
|
it('should create wallet from encrypted object', function() {
|
||||||
var wf = new WalletFactory(config, '0.0.1');
|
var wf = new WalletFactory(config, '0.0.1');
|
||||||
var walletObj = JSON.parse(o);
|
var walletObj = JSON.parse(o);
|
||||||
|
|
|
@ -69,6 +69,35 @@ describe('Unit: Testing Filters', function() {
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('removeEmpty addresses', function() {
|
||||||
|
it('should work with empty lists', inject(function($filter) {
|
||||||
|
var removeEmpty = $filter('removeEmpty');
|
||||||
|
expect(removeEmpty([]).length).to.equal(0);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should filter empty addresses from other copayers', inject(function($filter) {
|
||||||
|
var removeEmpty = $filter('removeEmpty');
|
||||||
|
var addresses = [{
|
||||||
|
owned: true,
|
||||||
|
balance: 0
|
||||||
|
}, {
|
||||||
|
owned: false,
|
||||||
|
balance: 0
|
||||||
|
}, {
|
||||||
|
owned: true,
|
||||||
|
balance: 0
|
||||||
|
}, {
|
||||||
|
owned: false,
|
||||||
|
balance: 0
|
||||||
|
}];
|
||||||
|
expect(removeEmpty(addresses).length).to.equal(2);
|
||||||
|
addresses[1].owned = true;
|
||||||
|
expect(removeEmpty(addresses).length).to.equal(3);
|
||||||
|
addresses[3].balance = 10;
|
||||||
|
expect(removeEmpty(addresses).length).to.equal(4);
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
describe('noFractionNumber bits', function() {
|
describe('noFractionNumber bits', function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
config.unitToSatoshi = 100;
|
config.unitToSatoshi = 100;
|
||||||
|
|
Loading…
Reference in New Issue