mirror of https://github.com/BTCPrivate/copay.git
add different toObj/fromObj fn for networking
This commit is contained in:
parent
c8917fccd6
commit
966818c53a
|
@ -99,14 +99,6 @@ PublicKeyRing.prototype._checkKeys = function() {
|
|||
throw new Error('dont have required keys yet');
|
||||
};
|
||||
|
||||
PublicKeyRing.prototype._newExtendedPublicKey = function() {
|
||||
return new PrivateKey({
|
||||
networkName: this.network.name
|
||||
})
|
||||
.deriveBIP45Branch()
|
||||
.extendedPublicKeyString();
|
||||
};
|
||||
|
||||
PublicKeyRing.prototype._updateBip = function(index) {
|
||||
var hk = this.copayersHK[index].derive(HDPath.IdBranch);
|
||||
this.copayerIds[index] = hk.eckey.public.toString('hex');
|
||||
|
@ -125,6 +117,8 @@ PublicKeyRing.prototype.nicknameForCopayer = function(copayerId) {
|
|||
};
|
||||
|
||||
PublicKeyRing.prototype.addCopayer = function(newEpk, nickname) {
|
||||
preconditions.checkArgument(newEpk);
|
||||
|
||||
if (this.isComplete())
|
||||
throw new Error('PKR already has all required key:' + this.totalCopayers);
|
||||
|
||||
|
@ -133,10 +127,6 @@ PublicKeyRing.prototype.addCopayer = function(newEpk, nickname) {
|
|||
throw new Error('PKR already has that key');
|
||||
});
|
||||
|
||||
if (!newEpk) {
|
||||
newEpk = this._newExtendedPublicKey();
|
||||
}
|
||||
|
||||
var i = this.copayersHK.length;
|
||||
var bip = new HK(newEpk);
|
||||
this.copayersHK.push(bip);
|
||||
|
@ -307,6 +297,30 @@ PublicKeyRing.prototype.forPaths = function(paths) {
|
|||
};
|
||||
|
||||
|
||||
PublicKeyRing.prototype.copayersForPubkeys = function(pubkeys, paths) {
|
||||
|
||||
var inKeyMap = {}, ret = [];
|
||||
for(var i in pubkeys ){
|
||||
inKeyMap[pubkeys[i]] = 1;
|
||||
};
|
||||
|
||||
var keys = this.getForPaths(paths);
|
||||
for(var i in keys ){
|
||||
for(var copayerIndex in keys[i] ){
|
||||
var kHex = keys[i][copayerIndex].toString('hex');
|
||||
if (inKeyMap[kHex]) {
|
||||
ret.push(this.copayerIds[copayerIndex]);
|
||||
delete inKeyMap[kHex];
|
||||
}
|
||||
}
|
||||
}
|
||||
for(var i in inKeyMap)
|
||||
throw new Error('Pubkey not identified')
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
|
||||
// TODO this could be cached
|
||||
PublicKeyRing.prototype._addScriptMap = function(map, path) {
|
||||
var p = HDPath.indexesForPath(path);
|
||||
|
|
|
@ -10,6 +10,9 @@ var Key = bitcore.Key;
|
|||
var buffertools = bitcore.buffertools;
|
||||
var preconditions = require('preconditions').instance();
|
||||
|
||||
var VERSION = 1;
|
||||
var CORE_FIELDS = ['builderObj','inputChainPaths', 'version'];
|
||||
|
||||
|
||||
function TxProposal(opts) {
|
||||
preconditions.checkArgument(opts);
|
||||
|
@ -17,22 +20,26 @@ function TxProposal(opts) {
|
|||
preconditions.checkArgument(opts.creator,'no creator');
|
||||
preconditions.checkArgument(opts.createdTs,'no createdTs');
|
||||
preconditions.checkArgument(opts.builder,'no builder');
|
||||
preconditions.checkArgument(opts.inputChainPaths,'no inputChainPaths');
|
||||
|
||||
|
||||
this.creator = opts.creator;
|
||||
this.createdTs = opts.createdTs;
|
||||
this.builder = opts.builder;
|
||||
this.inputChainPaths = opts.inputChainPaths;
|
||||
|
||||
this.version = opts.version;
|
||||
this.builder = opts.builder;
|
||||
this.createdTs = opts.createdTs;
|
||||
this.createdTs = opts.createdTs;
|
||||
this._inputSignatures = [];
|
||||
this.seenBy = opts.seenBy || {};
|
||||
|
||||
// CopayerIds
|
||||
this.creator = opts.creator;
|
||||
this.signedBy = opts.signedBy || {};
|
||||
this.seenBy = opts.seenBy || {};
|
||||
this.rejectedBy = opts.rejectedBy || {};
|
||||
this.sentTs = opts.sentTs || null;
|
||||
this.sentTxid = opts.sentTxid || null;
|
||||
this.comment = opts.comment || null;
|
||||
this.readonly = opts.readonly || null;
|
||||
// this._updateSignedBy();
|
||||
|
||||
this.sync();
|
||||
}
|
||||
|
||||
TxProposal.prototype.getId = function() {
|
||||
|
@ -47,11 +54,24 @@ TxProposal.prototype.toObj = function() {
|
|||
};
|
||||
|
||||
|
||||
TxProposal.prototype.setSent = function(sentTxid) {
|
||||
this.sentTxid = sentTxid;
|
||||
this.sentTs = Date.now();
|
||||
TxProposal.prototype.toObjForNetwork = function() {
|
||||
var o = this.toObj;
|
||||
|
||||
var newOutput = {};
|
||||
CORE_FIELDS.forEach(function(k){
|
||||
newOutput[k] = o[k];
|
||||
});
|
||||
return newOutput;
|
||||
};
|
||||
|
||||
TxProposal.prototype.sync = function() {
|
||||
this._check();
|
||||
this._updateSignedBy();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
// fromObj => from a trusted source
|
||||
TxProposal.fromObj = function(o, forceOpts) {
|
||||
preconditions.checkArgument(o.builderObj);
|
||||
delete o['builder'];
|
||||
|
@ -64,17 +84,24 @@ TxProposal.fromObj = function(o, forceOpts) {
|
|||
o.builder = TransactionBuilder.fromObj(o.builderObj);
|
||||
} catch (e) {
|
||||
|
||||
// backwards (V0) compatatibility fix.
|
||||
if (!o.version) {
|
||||
o.builder = new BuilderMockV0(o.builderObj);
|
||||
o.readonly = 1;
|
||||
};
|
||||
}
|
||||
return new TxProposal(o);
|
||||
};
|
||||
|
||||
var t = new TxProposal(o);
|
||||
t._check();
|
||||
t._updateSignedBy();
|
||||
TxProposal.fromObjUntrusted = function(o, forceOpts, senderId) {
|
||||
var newInput = {};
|
||||
CORE_FIELDS.forEach(function(k){
|
||||
newInput[k] = o[k];
|
||||
});
|
||||
if (newInput.version !== VERSION)
|
||||
throw new Error('Peer using different version');
|
||||
|
||||
return t;
|
||||
return TxProposal.fromObj(newInput, forceOpts, senderId);
|
||||
};
|
||||
|
||||
|
||||
|
@ -144,7 +171,8 @@ TxProposal.prototype._updateSignedBy = function() {
|
|||
if (signatureIndexes.length !== signatureCount)
|
||||
throw new Error('Invalid signature');
|
||||
this._inputSignatures[i] = signatureIndexes.map(function(i) {
|
||||
return info.keys[i].toString('hex');
|
||||
var r = info.keys[i].toString('hex');
|
||||
return r;
|
||||
});
|
||||
};
|
||||
};
|
||||
|
@ -184,6 +212,21 @@ TxProposal.prototype.mergeBuilder = function(incoming) {
|
|||
};
|
||||
|
||||
|
||||
TxProposal.prototype.setSeen = function(copayerId) {
|
||||
if (!this.seenBy[copayerId])
|
||||
this.seenBy[copayerId] = Date.now();
|
||||
};
|
||||
|
||||
TxProposal.prototype.setRejected = function(copayerId) {
|
||||
if (!this.rejectedBy[copayerId] && !this.signedBy)
|
||||
this.rejectedBy[copayerId] = Date.now();
|
||||
};
|
||||
|
||||
TxProposal.prototype.setSent = function(sentTxid) {
|
||||
this.sentTxid = sentTxid;
|
||||
this.sentTs = Date.now();
|
||||
};
|
||||
|
||||
/* OTDO
|
||||
events.push({
|
||||
type: 'seen',
|
||||
|
@ -213,12 +256,11 @@ TxProposal.prototype._allSignatures = function() {
|
|||
return ret;
|
||||
};
|
||||
|
||||
// merge will not merge any metadata.
|
||||
TxProposal.prototype.merge = function(incoming) {
|
||||
var ret = {};
|
||||
var newSignatures = [];
|
||||
|
||||
incoming._check();
|
||||
incoming._updateSignedBy();
|
||||
incoming.sync();
|
||||
|
||||
var prevInputSignatures = this._allSignatures();
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ function TxProposals(opts) {
|
|||
this.txps = {};
|
||||
}
|
||||
|
||||
// fromObj => from a trusted source
|
||||
TxProposals.fromObj = function(o, forceOpts) {
|
||||
var ret = new TxProposals({
|
||||
networkName: o.networkName,
|
||||
|
@ -60,8 +61,6 @@ TxProposals.prototype.merge = function(inTxp, allowedPubKeys) {
|
|||
|
||||
var ntxid = inTxp.getId();
|
||||
var ret = {};
|
||||
ret.events = [];
|
||||
ret.events.hasChanged = false;
|
||||
|
||||
if (myTxps[ntxid]) {
|
||||
var v0 = myTxps[ntxid];
|
||||
|
@ -70,12 +69,7 @@ TxProposals.prototype.merge = function(inTxp, allowedPubKeys) {
|
|||
}
|
||||
else {
|
||||
this.txps[ntxid] = inTxp;
|
||||
ret.hasChanged = true;
|
||||
ret.events.push({
|
||||
type: 'new',
|
||||
cid: inTxp.creator,
|
||||
tx: ntxid
|
||||
});
|
||||
ret.new = 1;
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
@ -88,22 +82,14 @@ TxProposals.prototype.mergeFromObj = function(txProposalObj, allowedPubKeys, opt
|
|||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// Add a LOCALLY CREATED (trusted) tx proposal
|
||||
TxProposals.prototype.add = function(data) {
|
||||
var txp = new TxProposal(data);
|
||||
TxProposals.prototype.add = function(txp) {
|
||||
txp.sync();
|
||||
var ntxid = txp.getId();
|
||||
this.txps[ntxid] = txp;
|
||||
return ntxid;
|
||||
};
|
||||
|
||||
TxProposals.prototype.setSent = function(ntxid, txid) {
|
||||
//sent TxProposals are local an not broadcasted.
|
||||
this.txps[ntxid].setSent(txid);
|
||||
};
|
||||
|
||||
|
||||
TxProposals.prototype.getTxProposal = function(ntxid, copayers) {
|
||||
var txp = this.txps[ntxid];
|
||||
var i = JSON.parse(JSON.stringify(txp));
|
||||
|
|
|
@ -17,6 +17,7 @@ var Address = bitcore.Address;
|
|||
|
||||
var HDParams = require('./HDParams');
|
||||
var PublicKeyRing = require('./PublicKeyRing');
|
||||
var TxProposal = require('./TxProposal');
|
||||
var TxProposals = require('./TxProposals');
|
||||
var PrivateKey = require('./PrivateKey');
|
||||
var copayConfig = require('../../../config');
|
||||
|
@ -129,11 +130,39 @@ Wallet.prototype._handlePublicKeyRing = function(senderId, data, isInbound) {
|
|||
};
|
||||
|
||||
|
||||
Wallet.prototype._processProposalEvents = function(mergeInfo) {
|
||||
var ev = [];
|
||||
if (mergeInfo.new) {
|
||||
ev = {
|
||||
type: 'new',
|
||||
cid: senderId
|
||||
}
|
||||
} else {
|
||||
for (var i in mergeInfo.newCopayers) {
|
||||
var copayerId = mergeInfo.newCopayers[i];
|
||||
ev.push({
|
||||
type: 'signed',
|
||||
cid: copayerId
|
||||
});
|
||||
}
|
||||
}
|
||||
if (ev)
|
||||
this.emit('txProposalEvent',ev);
|
||||
};
|
||||
|
||||
|
||||
Wallet.prototype._handleTxProposal = function(senderId, data) {
|
||||
this.log('RECV TXPROPOSAL: ', data);
|
||||
var mergeInfo;
|
||||
var mergeInfo, ntxid;
|
||||
|
||||
try {
|
||||
mergeInfo = this.txProposals.mergeFromObj(data.txProposal, senderId, Wallet.builderOpts);
|
||||
mergeInfo.newCopayers=[];
|
||||
for (var i in mergeInfo.newSignatures) {
|
||||
var k = mergeInfo.newSignatures[i];
|
||||
mergeInfo.newCopayers.push(this.getCopayerIdFromPubKey(k));
|
||||
};
|
||||
ntxid = mergeInfo.inTxp.getId();
|
||||
} catch (e) {
|
||||
var corruptEvent = {
|
||||
type: 'corrupt',
|
||||
|
@ -143,21 +172,36 @@ Wallet.prototype._handleTxProposal = function(senderId, data) {
|
|||
this.emit('txProposalEvent', corruptEvent);
|
||||
return;
|
||||
}
|
||||
this.sendSeen(ntxid);
|
||||
|
||||
var added = this.addSeenToTxProposals();
|
||||
if (added) {
|
||||
this.log('### BROADCASTING txProposals with my seenBy updated.');
|
||||
this.sendTxProposal(mergeInfo.inTxp.getId());
|
||||
}
|
||||
if (mergeInfo.hasChanged)
|
||||
this.sendTxProposal(ntxid);
|
||||
|
||||
this.emit('txProposalsUpdated');
|
||||
this.store();
|
||||
|
||||
for (var i = 0; i < mergeInfo.events.length; i++) {
|
||||
this.emit('txProposalEvent', mergeInfo.events[i]);
|
||||
}
|
||||
this._processProposalEvents(senderId, mergeInfo);
|
||||
};
|
||||
|
||||
|
||||
Wallet.prototype._handleReject = function(senderId, data, isInbound) {
|
||||
this.log('RECV REJECT:', data);
|
||||
// TODO check that has not signed.
|
||||
//
|
||||
this.txProposals.txps[data.ntxid].setRejected(senderId);
|
||||
this.emit('txProposalsUpdated');
|
||||
this.store();
|
||||
|
||||
};
|
||||
|
||||
Wallet.prototype._handleSeen = function(senderId, data, isInbound) {
|
||||
this.log('RECV SEEN:', data);
|
||||
this.txProposals.txps[data.ntxid].setSeen(senderId);
|
||||
this.emit('txProposalsUpdated');
|
||||
this.store();
|
||||
};
|
||||
|
||||
|
||||
|
||||
Wallet.prototype._handleAddressBook = function(senderId, data, isInbound) {
|
||||
this.log('RECV ADDRESSBOOK:', data);
|
||||
var rcv = data.addressBook;
|
||||
|
@ -199,6 +243,10 @@ Wallet.prototype._handleData = function(senderId, data, isInbound) {
|
|||
case 'publicKeyRing':
|
||||
this._handlePublicKeyRing(senderId, data, isInbound);
|
||||
break;
|
||||
case 'reject':
|
||||
this._handleReject(senderId, data, isInbound);
|
||||
case 'seen':
|
||||
this._handleReject(senderId, data, isInbound);
|
||||
case 'txProposal':
|
||||
this._handleTxProposal(senderId, data, isInbound);
|
||||
break;
|
||||
|
@ -381,6 +429,7 @@ Wallet.prototype.toObj = function() {
|
|||
return walletObj;
|
||||
};
|
||||
|
||||
// fromObj => from a trusted source
|
||||
Wallet.fromObj = function(o, storage, network, blockchain) {
|
||||
var opts = JSON.parse(JSON.stringify(o.opts));
|
||||
opts.addressBook = o.addressBook;
|
||||
|
@ -424,6 +473,26 @@ Wallet.prototype.sendTxProposal = function(ntxid, recipients) {
|
|||
});
|
||||
};
|
||||
|
||||
Wallet.prototype.sendSeen = function(ntxid) {
|
||||
preconditions.checkArgument(ntxid);
|
||||
this.log('### SENDING seen: ' + ntxid + ' TO: All');
|
||||
this.send(null, {
|
||||
type: 'seen',
|
||||
ntxid: ntxid,
|
||||
walletId: this.id,
|
||||
});
|
||||
};
|
||||
|
||||
Wallet.prototype.sendReject = function(ntxid) {
|
||||
preconditions.checkArgument(ntxid);
|
||||
this.log('### SENDING reject: ' + ntxid + ' TO: All');
|
||||
this.send(null, {
|
||||
type: 'reject',
|
||||
ntxid: ntxid,
|
||||
walletId: this.id,
|
||||
});
|
||||
};
|
||||
|
||||
Wallet.prototype.sendWalletReady = function(recipients) {
|
||||
this.log('### SENDING WalletReady TO:', recipients);
|
||||
|
||||
|
@ -521,7 +590,7 @@ Wallet.prototype.reject = function(ntxid) {
|
|||
}
|
||||
|
||||
txp.rejectedBy[myId] = Date.now();
|
||||
this.sendTxProposal(ntxid);
|
||||
this.sendReject(ntxid);
|
||||
this.store();
|
||||
this.emit('txProposalsUpdated');
|
||||
};
|
||||
|
@ -534,10 +603,10 @@ Wallet.prototype.sign = function(ntxid, cb) {
|
|||
setTimeout(function() {
|
||||
var myId = self.getMyCopayerId();
|
||||
var txp = self.txProposals.txps[ntxid];
|
||||
if (!txp || txp.rejectedBy[myId] || txp.signedBy[myId]) {
|
||||
if (cb) cb(false);
|
||||
}
|
||||
|
||||
// if (!txp || txp.rejectedBy[myId] || txp.signedBy[myId]) {
|
||||
// if (cb) cb(false);
|
||||
// }
|
||||
//
|
||||
var keys = self.privateKey.getForPaths(txp.inputChainPaths);
|
||||
|
||||
var b = txp.builder;
|
||||
|
@ -574,7 +643,7 @@ Wallet.prototype.sendTx = function(ntxid, cb) {
|
|||
this.blockchain.sendRawTransaction(txHex, function(txid) {
|
||||
self.log('BITCOIND txid:', txid);
|
||||
if (txid) {
|
||||
self.txProposals.setSent(ntxid, txid);
|
||||
self.txProposals.txps[ntxid].setSent(txid);
|
||||
self.sendTxProposal(ntxid);
|
||||
self.store();
|
||||
}
|
||||
|
@ -582,20 +651,20 @@ Wallet.prototype.sendTx = function(ntxid, cb) {
|
|||
});
|
||||
};
|
||||
|
||||
Wallet.prototype.addSeenToTxProposals = function() {
|
||||
var ret = false;
|
||||
var myId = this.getMyCopayerId();
|
||||
|
||||
for (var k in this.txProposals.txps) {
|
||||
var txp = this.txProposals.txps[k];
|
||||
if (!txp.seenBy[myId]) {
|
||||
|
||||
txp.seenBy[myId] = Date.now();
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
// Wallet.prototype.addSeenToTxProposals = function() {
|
||||
// var ret = false;
|
||||
// var myId = this.getMyCopayerId();
|
||||
//
|
||||
// for (var k in this.txProposals.txps) {
|
||||
// var txp = this.txProposals.txps[k];
|
||||
// if (!txp.seenBy[myId]) {
|
||||
//
|
||||
// txp.seenBy[myId] = Date.now();
|
||||
// ret = true;
|
||||
// }
|
||||
// }
|
||||
// return ret;
|
||||
// };
|
||||
|
||||
// TODO: remove this method and use getAddressesInfo everywhere
|
||||
Wallet.prototype.getAddresses = function(opts) {
|
||||
|
@ -718,6 +787,7 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, comment, utxos
|
|||
|
||||
preconditions.checkArgument(new Address(toAddress).network().name === this.getNetworkName());
|
||||
preconditions.checkState(pkr.isComplete());
|
||||
preconditions.checkState(priv);
|
||||
if (comment) preconditions.checkArgument(comment.length <= 100);
|
||||
|
||||
if (!opts.remainderOut) {
|
||||
|
@ -744,22 +814,23 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, comment, utxos
|
|||
|
||||
b = b.setHashToScriptMap(pkr.getRedeemScriptMap(inputChainPaths));
|
||||
|
||||
if (priv) {
|
||||
var keys = priv.getForPaths(inputChainPaths);
|
||||
var signed = b.sign(keys);
|
||||
}
|
||||
var keys = priv.getForPaths(inputChainPaths);
|
||||
var signed = b.sign(keys);
|
||||
var myId = this.getMyCopayerId();
|
||||
var now = Date.now();
|
||||
|
||||
var me = {};
|
||||
|
||||
var tx = b.build();
|
||||
if (priv && tx.countInputSignatures(0)) me[myId] = now;
|
||||
if (!tx.countInputSignatures(0))
|
||||
throw new Error ('Could not sign generated tx');
|
||||
|
||||
var me = {};
|
||||
me[myId] = now;
|
||||
|
||||
var meSeen = {};
|
||||
if (priv) meSeen[myId] = now;
|
||||
|
||||
var data = {
|
||||
var ntxid = this.txProposals.add(new TxProposal({
|
||||
inputChainPaths: inputChainPaths,
|
||||
signedBy: me,
|
||||
seenBy: meSeen,
|
||||
|
@ -767,9 +838,7 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, comment, utxos
|
|||
createdTs: now,
|
||||
builder: b,
|
||||
comment: comment
|
||||
};
|
||||
|
||||
var ntxid = this.txProposals.add(data);
|
||||
}));
|
||||
return ntxid;
|
||||
};
|
||||
|
||||
|
|
|
@ -182,8 +182,6 @@ describe('TxProposal', function() {
|
|||
});
|
||||
it('#_updateSignedBy', function() {
|
||||
var txp = dummyProposal;
|
||||
txp._inputSignatures.should.deep.equal([]);
|
||||
txp._updateSignedBy();
|
||||
txp._inputSignatures.should.deep.equal([[ '03197599f6e209cefef07da2fddc6fe47715a70162c531ffff8e611cef23dfb70d', '03a94351fecc4328bb683bf93a1aa67378374904eac5980c7966723a51897c56e3' ]]);
|
||||
});
|
||||
describe('#_check', function() {
|
||||
|
|
|
@ -10,7 +10,7 @@ try {
|
|||
}
|
||||
var copayConfig = require('../config');
|
||||
var Wallet = require('../js/models/core/Wallet');
|
||||
var Structure = copay.Structure;
|
||||
var PrivateKey = copay.PrivateKey;
|
||||
var Storage = require('./mocks/FakeStorage');
|
||||
var Network = require('./mocks/FakeNetwork');
|
||||
var Blockchain = require('./mocks/FakeBlockchain');
|
||||
|
@ -19,22 +19,30 @@ var TransactionBuilder = bitcore.TransactionBuilder;
|
|||
var Transaction = bitcore.Transaction;
|
||||
var Address = bitcore.Address;
|
||||
|
||||
var config = {
|
||||
requiredCopayers: 3,
|
||||
totalCopayers: 5,
|
||||
spendUnconfirmed: true,
|
||||
reconnectDelay: 100,
|
||||
networkName: 'testnet',
|
||||
};
|
||||
|
||||
var getNewEpk = function() {
|
||||
return new PrivateKey({
|
||||
networkName: config.networkName,
|
||||
})
|
||||
.deriveBIP45Branch()
|
||||
.extendedPublicKeyString();
|
||||
}
|
||||
|
||||
var addCopayers = function(w) {
|
||||
for (var i = 0; i < 4; i++) {
|
||||
w.publicKeyRing.addCopayer();
|
||||
w.publicKeyRing.addCopayer(getNewEpk());
|
||||
}
|
||||
};
|
||||
|
||||
describe('Wallet model', function() {
|
||||
|
||||
var config = {
|
||||
requiredCopayers: 3,
|
||||
totalCopayers: 5,
|
||||
spendUnconfirmed: true,
|
||||
reconnectDelay: 100,
|
||||
networkName: 'testnet',
|
||||
};
|
||||
|
||||
it('should fail to create an instance', function() {
|
||||
(function() {
|
||||
new Wallet(config)
|
||||
|
@ -47,12 +55,11 @@ describe('Wallet model', function() {
|
|||
});
|
||||
|
||||
|
||||
var createW = function(netKey, N, conf) {
|
||||
var createW = function(N, conf) {
|
||||
|
||||
var c = JSON.parse(JSON.stringify(conf || config));
|
||||
if (!N) N = c.totalCopayers;
|
||||
|
||||
if (netKey) c.netKey = netKey;
|
||||
var mainPrivateKey = new copay.PrivateKey({
|
||||
networkName: config.networkName
|
||||
});
|
||||
|
@ -148,8 +155,7 @@ describe('Wallet model', function() {
|
|||
|
||||
var createW2 = function(privateKeys, N, conf) {
|
||||
if (!N) N = 3;
|
||||
var netKey = 'T0FbU2JLby0=';
|
||||
var w = createW(netKey, N, conf);
|
||||
var w = createW(N, conf);
|
||||
should.exist(w);
|
||||
|
||||
var pkr = w.publicKeyRing;
|
||||
|
@ -157,9 +163,9 @@ describe('Wallet model', function() {
|
|||
for (var i = 0; i < N - 1; i++) {
|
||||
if (privateKeys) {
|
||||
var k = privateKeys[i];
|
||||
pkr.addCopayer(k ? k.deriveBIP45Branch().extendedPublicKeyString() : null);
|
||||
pkr.addCopayer(k ? k.deriveBIP45Branch().extendedPublicKeyString() : getNewEpk());
|
||||
} else {
|
||||
pkr.addCopayer();
|
||||
pkr.addCopayer(getNewEpk());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,12 +218,12 @@ describe('Wallet model', function() {
|
|||
|
||||
var t = w.txProposals;
|
||||
var txp = t.txps[ntxid];
|
||||
Object.keys(txp._inputSignatures).length.should.equal(1);
|
||||
var tx = txp.builder.build();
|
||||
should.exist(tx);
|
||||
chai.expect(txp.comment).to.be.null;
|
||||
tx.isComplete().should.equal(false);
|
||||
Object.keys(txp.seenBy).length.should.equal(1);
|
||||
Object.keys(txp.signedBy).length.should.equal(1);
|
||||
});
|
||||
|
||||
it('#create with comment', function() {
|
||||
|
@ -502,7 +508,8 @@ describe('Wallet model', function() {
|
|||
var w = createW();
|
||||
var r = w.getRegisteredCopayerIds();
|
||||
r.length.should.equal(1);
|
||||
w.publicKeyRing.addCopayer();
|
||||
w.publicKeyRing.addCopayer(getNewEpk());
|
||||
|
||||
r = w.getRegisteredCopayerIds();
|
||||
r.length.should.equal(2);
|
||||
r[0].should.not.equal(r[1]);
|
||||
|
@ -512,7 +519,7 @@ describe('Wallet model', function() {
|
|||
var w = createW();
|
||||
var r = w.getRegisteredPeerIds();
|
||||
r.length.should.equal(1);
|
||||
w.publicKeyRing.addCopayer();
|
||||
w.publicKeyRing.addCopayer(getNewEpk());
|
||||
r = w.getRegisteredPeerIds();
|
||||
r.length.should.equal(2);
|
||||
r[0].should.not.equal(r[1]);
|
||||
|
@ -642,10 +649,11 @@ describe('Wallet model', function() {
|
|||
});
|
||||
});
|
||||
it('should create & sign transaction from received funds', function(done) {
|
||||
this.timeout(10000);
|
||||
var w = cachedCreateW2();
|
||||
var pk = w.privateKey;
|
||||
w.privateKey = null;
|
||||
var k2 = new PrivateKey({
|
||||
networkName: config.networkName
|
||||
});
|
||||
|
||||
var w = createW2([k2]);
|
||||
var utxo = createUTXO(w);
|
||||
w.blockchain.fixUnspent(utxo);
|
||||
w.createTx(toAddress, amountSatStr, null, function(ntxid) {
|
||||
|
@ -654,7 +662,7 @@ describe('Wallet model', function() {
|
|||
w.getTxProposals()[0].rejectedByUs.should.equal(false);
|
||||
done();
|
||||
});
|
||||
w.privateKey = pk;
|
||||
w.privateKey = k2;
|
||||
w.sign(ntxid, function(success) {
|
||||
success.should.equal(true);
|
||||
});
|
||||
|
@ -1031,9 +1039,9 @@ describe('Wallet model', function() {
|
|||
e.type.should.equal(result);
|
||||
done();
|
||||
});
|
||||
var txp = {
|
||||
'txProposal': { dummy: 1}
|
||||
};
|
||||
var txp = {dummy:1};
|
||||
// txp.prototype.getId = function() {return 'aa'};
|
||||
var txp = { 'txProposal': txp };
|
||||
var merge = sinon.stub(w.txProposals, 'mergeFromObj', function() {
|
||||
if (shouldThrow) throw new Error();
|
||||
return {events: [{type:'new'}]};
|
||||
|
|
Loading…
Reference in New Issue