Wallet/js/models/core/Wallet.js

570 lines
14 KiB
JavaScript
Raw Normal View History

2014-04-10 17:57:41 -03:00
'use strict';
2014-04-24 20:56:36 -03:00
var imports = require('soop').imports();
2014-04-14 17:17:56 -03:00
2014-04-24 20:56:36 -03:00
var bitcore = require('bitcore');
var coinUtil = bitcore.util;
2014-04-14 18:30:08 -03:00
var buffertools = bitcore.buffertools;
2014-04-24 20:56:36 -03:00
var Builder = bitcore.TransactionBuilder;
var http = require('http');
var EventEmitter = imports.EventEmitter || require('events').EventEmitter;
var copay = copay || require('../../../copay');
2014-04-30 12:58:40 -03:00
var SecureRandom = bitcore.SecureRandom;
var Base58Check = bitcore.Base58.base58Check;
2014-04-10 17:57:41 -03:00
2014-04-16 17:50:10 -03:00
function Wallet(opts) {
var self = this;
2014-04-14 17:17:56 -03:00
2014-04-16 17:50:10 -03:00
//required params
['storage', 'network', 'blockchain',
'requiredCopayers', 'totalCopayers', 'spendUnconfirmed',
'publicKeyRing', 'txProposals', 'privateKey'
2014-04-24 20:56:36 -03:00
].forEach(function(k) {
2014-04-16 17:50:10 -03:00
if (typeof opts[k] === 'undefined') throw new Error('missing key:' + k);
self[k] = opts[k];
});
2014-04-14 17:17:56 -03:00
2014-04-24 20:56:36 -03:00
this.log('creating ' + opts.requiredCopayers + ' of ' + opts.totalCopayers + ' wallet');
2014-04-16 19:45:22 -03:00
2014-04-16 17:50:10 -03:00
this.id = opts.id || Wallet.getRandomId();
this.name = opts.name;
2014-04-30 12:58:40 -03:00
this.netKey = opts.netKey || SecureRandom.getRandomBuffer(8).toString('base64');
2014-04-16 22:12:30 -03:00
this.verbose = opts.verbose;
2014-04-16 17:50:10 -03:00
this.publicKeyRing.walletId = this.id;
this.txProposals.walletId = this.id;
2014-04-24 23:13:55 -03:00
this.network.maxPeers = this.totalCopayers;
2014-05-01 09:41:18 -03:00
this.registeredPeerIds = [];
2014-04-14 17:42:10 -03:00
}
2014-04-10 17:57:41 -03:00
2014-04-24 20:56:36 -03:00
Wallet.parent = EventEmitter;
Wallet.prototype.log = function() {
if (!this.verbose) return;
2014-04-20 20:24:24 -03:00
if (console)
2014-04-24 20:56:36 -03:00
console.log.apply(console, arguments);
2014-04-16 17:50:10 -03:00
};
2014-04-15 14:28:49 -03:00
2014-04-16 17:50:10 -03:00
Wallet.getRandomId = function() {
2014-04-24 15:49:37 -03:00
var r = bitcore.SecureRandom.getPseudoRandomBuffer(8).toString('hex');
return r;
2014-04-16 17:50:10 -03:00
};
2014-04-15 14:28:49 -03:00
2014-04-16 17:50:10 -03:00
Wallet.prototype._handlePublicKeyRing = function(senderId, data, isInbound) {
2014-04-24 20:56:36 -03:00
this.log('RECV PUBLICKEYRING:', data);
2014-04-16 17:50:10 -03:00
var recipients, pkr = this.publicKeyRing;
var inPKR = copay.PublicKeyRing.fromObj(data.publicKeyRing);
2014-04-18 18:25:51 -03:00
var hasChanged = pkr.merge(inPKR, true);
2014-04-24 20:56:36 -03:00
if (hasChanged) {
2014-04-24 23:13:55 -03:00
if (this.publicKeyRing.isComplete()) {
this._lockIncomming();
}
2014-04-28 15:15:09 -03:00
this.log('### BROADCASTING PKR');
recipients = null;
this.sendPublicKeyRing(recipients);
2014-04-16 17:50:10 -03:00
}
this.emit('publicKeyRingUpdated', this.publicKeyRing);
2014-04-16 17:50:10 -03:00
this.store();
2014-04-14 17:42:10 -03:00
};
2014-04-14 17:17:56 -03:00
2014-04-14 18:30:08 -03:00
2014-04-16 17:50:10 -03:00
Wallet.prototype._handleTxProposals = function(senderId, data, isInbound) {
2014-04-24 23:13:55 -03:00
this.log('RECV TXPROPOSAL:', data);
2014-04-14 17:17:56 -03:00
2014-04-16 17:50:10 -03:00
var recipients;
var inTxp = copay.TxProposals.fromObj(data.txProposals);
var mergeInfo = this.txProposals.merge(inTxp, true);
var addSeen = this.addSeenToTxProposals();
2014-04-24 20:56:36 -03:00
if (mergeInfo.hasChanged || addSeen) {
this.log('### BROADCASTING txProposals. ');
2014-04-16 17:50:10 -03:00
recipients = null;
this.sendTxProposals(recipients);
2014-04-24 23:13:55 -03:00
}
this.emit('txProposalsUpdated', this.txProposals);
2014-04-16 17:50:10 -03:00
this.store();
2014-04-14 17:42:10 -03:00
};
2014-04-16 17:50:10 -03:00
Wallet.prototype._handleData = function(senderId, data, isInbound) {
2014-04-20 16:16:09 -03:00
// TODO check message signature
if (this.id !== data.walletId) {
2014-04-24 20:56:36 -03:00
this.emit('badMessage', senderId);
this.log('badMessage FROM:', senderId); //TODO
return;
}
2014-04-24 20:56:36 -03:00
this.log('[Wallet.js.98]', data.type); //TODO
switch (data.type) {
2014-04-20 17:16:21 -03:00
// This handler is repeaded on WalletFactory (#join). TODO
case 'walletId':
this.sendWalletReady(senderId);
break;
2014-04-20 16:16:09 -03:00
case 'walletReady':
this.sendPublicKeyRing(senderId);
this.sendTxProposals(senderId);
break;
2014-04-16 17:50:10 -03:00
case 'publicKeyRing':
this._handlePublicKeyRing(senderId, data, isInbound);
2014-04-24 20:56:36 -03:00
break;
2014-04-16 17:50:10 -03:00
case 'txProposals':
this._handleTxProposals(senderId, data, isInbound);
2014-04-24 20:56:36 -03:00
break;
2014-04-16 17:50:10 -03:00
}
};
2014-04-14 17:42:10 -03:00
2014-04-23 13:44:20 -03:00
Wallet.prototype._handleNetworkChange = function(newCopayerId) {
2014-04-23 16:02:23 -03:00
if (newCopayerId) {
2014-04-25 17:36:00 -03:00
this.log('#### Setting new COPAYER:', newCopayerId);
2014-04-23 13:44:20 -03:00
this.sendWalletId(newCopayerId);
2014-04-24 20:56:36 -03:00
this.emit('peer', this.network.peerFromCopayer(newCopayerId));
}
2014-04-17 11:46:49 -03:00
this.emit('refresh');
2014-04-14 17:42:10 -03:00
};
2014-04-20 16:16:09 -03:00
2014-04-24 20:56:36 -03:00
Wallet.prototype._optsToObj = function() {
2014-04-17 18:02:20 -03:00
var obj = {
id: this.id,
spendUnconfirmed: this.spendUnconfirmed,
requiredCopayers: this.requiredCopayers,
totalCopayers: this.totalCopayers,
name: this.name,
2014-04-30 12:58:40 -03:00
netKey: this.netKey,
2014-04-17 18:02:20 -03:00
};
return obj;
};
2014-04-18 14:40:16 -03:00
2014-04-23 13:44:20 -03:00
Wallet.prototype.getCopayerId = function(index) {
return this.publicKeyRing.getCopayerId(index || 0);
2014-04-20 12:41:28 -03:00
};
2014-04-18 18:25:51 -03:00
2014-04-23 13:44:20 -03:00
Wallet.prototype.getMyCopayerId = function() {
return this.getCopayerId(0);
2014-04-18 14:40:16 -03:00
};
2014-04-30 12:58:40 -03:00
Wallet.prototype.getSecret = function() {
var i = new Buffer(this.getMyCopayerId(),'hex');
var k = new Buffer(this.netKey,'base64');
var b = Buffer.concat([i,k]);
var str = Base58Check.encode(b);
return str;
};
Wallet.decodeSecret = function(secretB) {
var secret = Base58Check.decode(secretB);
var netKeyBuf = secret.slice(-8);
var pubKeyBuf = secret.slice(0,33);
return {
pubKey: pubKeyBuf.toString('hex'),
netKey: netKeyBuf.toString('base64'),
}
};
2014-04-24 23:13:55 -03:00
Wallet.prototype._lockIncomming = function() {
this.network.lockIncommingConnections(this.publicKeyRing.getAllCopayerIds());
};
2014-04-16 19:18:19 -03:00
Wallet.prototype.netStart = function() {
2014-04-16 17:50:10 -03:00
var self = this;
var net = this.network;
2014-04-17 16:50:48 -03:00
net.removeAllListeners();
2014-04-24 20:56:36 -03:00
net.on('networkChange', self._handleNetworkChange.bind(self));
net.on('data', self._handleData.bind(self));
net.on('open', function() {}); // TODO
net.on('openError', function() {
2014-04-18 18:25:51 -03:00
self.log('[Wallet.js.132:openError:] GOT openError'); //TODO
self.emit('openError');
});
net.on('close', function() {
self.emit('close');
});
2014-04-20 12:41:28 -03:00
2014-04-23 13:44:20 -03:00
var myId = self.getMyCopayerId();
2014-04-24 20:56:36 -03:00
var startOpts = {
2014-04-23 22:43:17 -03:00
copayerId: myId,
2014-04-24 23:13:55 -03:00
maxPeers: self.totalCopayers,
2014-04-30 12:58:40 -03:00
netKey: this.netKey,
2014-04-20 12:41:28 -03:00
};
2014-04-24 23:13:55 -03:00
if (this.publicKeyRing.isComplete()) {
this._lockIncomming();
}
2014-04-24 20:56:36 -03:00
net.start(startOpts, function() {
2014-04-23 21:20:44 -03:00
self.emit('created', net.getPeer());
2014-04-24 20:56:36 -03:00
for (var i = 0; i < self.publicKeyRing.registeredCopayers(); i++) {
var otherId = self.getCopayerId(i);
if (otherId !== myId) {
net.connectTo(otherId);
2014-04-18 18:25:51 -03:00
}
2014-04-24 20:56:36 -03:00
if (self.firstCopayerId) {
self.sendWalletReady(self.firstCopayerId);
self.firstCopayerId = null;
}
self.emit('refresh');
2014-04-18 18:25:51 -03:00
}
2014-04-23 22:43:17 -03:00
});
2014-04-16 17:50:10 -03:00
};
2014-04-15 10:22:50 -03:00
2014-04-24 16:07:49 -03:00
Wallet.prototype.getOnlinePeerIDs = function() {
return this.network.getOnlinePeerIDs();
};
Wallet.prototype.getRegisteredPeerIds = function() {
2014-05-01 09:41:18 -03:00
var l = this.publicKeyRing.registeredCopayers();
if (this.registeredPeerIds.length !== l) {
this.registeredPeerIds = [];
for (var i = 0; i < l; i++) {
var cid = this.getCopayerId(i);
var pid = this.network.peerFromCopayer(cid);
this.registeredPeerIds.push({
peerId: pid,
nick: this.publicKeyRing.nicknameForCopayer(cid)
});
}
2014-04-24 16:07:49 -03:00
}
2014-05-01 09:41:18 -03:00
return this.registeredPeerIds;
2014-04-24 16:07:49 -03:00
};
2014-04-18 13:20:35 -03:00
Wallet.prototype.store = function(isSync) {
2014-04-17 18:02:20 -03:00
var wallet = this.toObj();
this.storage.setFromObj(this.id, wallet);
2014-04-16 22:12:30 -03:00
2014-04-18 13:20:35 -03:00
if (isSync) {
this.log('Wallet stored.'); //TODO
2014-04-24 20:56:36 -03:00
} else {
2014-04-18 13:20:35 -03:00
this.log('Wallet stored. REFRESH Emitted'); //TODO
this.emit('refresh');
}
2014-04-17 18:02:20 -03:00
};
Wallet.prototype.toObj = function() {
var optsObj = this._optsToObj();
var walletObj = {
opts: optsObj,
publicKeyRing: this.publicKeyRing.toObj(),
2014-04-17 18:02:20 -03:00
txProposals: this.txProposals.toObj(),
privateKey: this.privateKey.toObj()
};
return walletObj;
2014-04-15 10:22:50 -03:00
};
Wallet.fromObj = function(o, storage, network, blockchain) {
var opts = JSON.parse(JSON.stringify(o.opts));
opts.publicKeyRing = copay.PublicKeyRing.fromObj(o.publicKeyRing);
opts.txProposals = copay.TxProposals.fromObj(o.txProposals);
opts.privateKey = copay.PrivateKey.fromObj(o.privateKey);
opts.storage = storage;
opts.network = network;
opts.blockchain = blockchain;
2014-04-17 18:02:20 -03:00
var w = new Wallet(opts);
return w;
};
2014-04-15 12:17:28 -03:00
Wallet.prototype.sendTxProposals = function(recipients) {
2014-04-24 20:56:36 -03:00
this.log('### SENDING txProposals TO:', recipients || 'All', this.txProposals);
2014-04-15 12:17:28 -03:00
2014-04-24 20:56:36 -03:00
this.network.send(recipients, {
type: 'txProposals',
2014-04-15 12:17:28 -03:00
txProposals: this.txProposals.toObj(),
walletId: this.id,
});
};
2014-04-20 16:16:09 -03:00
Wallet.prototype.sendWalletReady = function(recipients) {
this.log('### SENDING WalletReady TO:', recipients);
2014-04-24 20:56:36 -03:00
this.network.send(recipients, {
type: 'walletReady',
2014-04-20 16:16:09 -03:00
walletId: this.id,
});
this.emit('walletReady');
};
2014-04-16 20:58:57 -03:00
Wallet.prototype.sendWalletId = function(recipients) {
2014-04-25 17:36:00 -03:00
this.log('### SENDING walletId TO:', recipients || 'All', this.id);
2014-04-16 20:58:57 -03:00
2014-04-24 20:56:36 -03:00
this.network.send(recipients, {
type: 'walletId',
2014-04-16 20:58:57 -03:00
walletId: this.id,
2014-04-18 18:25:51 -03:00
opts: this._optsToObj()
2014-04-16 20:58:57 -03:00
});
};
2014-04-15 12:17:28 -03:00
Wallet.prototype.sendPublicKeyRing = function(recipients) {
2014-04-24 20:56:36 -03:00
this.log('### SENDING publicKeyRing TO:', recipients || 'All', this.publicKeyRing.toObj());
2014-04-15 12:17:28 -03:00
2014-04-24 20:56:36 -03:00
this.network.send(recipients, {
type: 'publicKeyRing',
2014-04-15 12:17:28 -03:00
publicKeyRing: this.publicKeyRing.toObj(),
walletId: this.id,
});
};
2014-04-21 11:28:25 -03:00
Wallet.prototype.generateAddress = function(isChange) {
var addr = this.publicKeyRing.generateAddress(isChange);
2014-04-16 17:50:10 -03:00
this.sendPublicKeyRing();
2014-04-18 13:20:35 -03:00
this.store(true);
2014-04-15 16:50:16 -03:00
return addr;
};
2014-04-15 12:17:28 -03:00
2014-04-23 02:01:54 -03:00
2014-04-15 15:25:55 -03:00
Wallet.prototype.getTxProposals = function() {
var ret = [];
2014-04-24 20:56:36 -03:00
for (var k in this.txProposals.txps) {
2014-04-23 02:01:54 -03:00
var i = this.txProposals.getTxProposal(k);
2014-04-24 20:56:36 -03:00
i.signedByUs = i.signedBy[this.getMyCopayerId()] ? true : false;
i.rejectedByUs = i.rejectedBy[this.getMyCopayerId()] ? true : false;
if (this.totalCopayers - i.rejectCount < this.requiredCopayers)
i.finallyRejected = true;
2014-04-21 07:27:45 -03:00
2014-04-15 15:25:55 -03:00
ret.push(i);
2014-04-16 17:50:10 -03:00
}
return ret;
};
2014-04-23 02:01:54 -03:00
Wallet.prototype.reject = function(ntxid) {
2014-04-24 20:56:36 -03:00
var myId = this.getMyCopayerId();
2014-04-18 19:28:28 -03:00
var txp = this.txProposals.txps[ntxid];
2014-04-23 02:01:54 -03:00
if (!txp || txp.rejectedBy[myId] || txp.signedBy[myId]) return;
txp.rejectedBy[myId] = Date.now();
this.sendTxProposals();
this.store(true);
2014-04-18 19:28:28 -03:00
};
2014-04-16 17:50:10 -03:00
2014-04-23 02:01:54 -03:00
2014-04-16 17:50:10 -03:00
Wallet.prototype.sign = function(ntxid) {
2014-04-18 19:28:28 -03:00
var self = this;
2014-04-24 20:56:36 -03:00
var myId = this.getMyCopayerId();
2014-04-18 19:28:28 -03:00
var txp = self.txProposals.txps[ntxid];
2014-04-23 02:01:54 -03:00
if (!txp || txp.rejectedBy[myId] || txp.signedBy[myId]) return;
2014-04-16 17:50:10 -03:00
2014-04-18 19:28:28 -03:00
var pkr = self.publicKeyRing;
var keys = self.privateKey.getAll(pkr.addressIndex, pkr.changeAddressIndex);
var b = txp.builder;
var before = b.signaturesAdded;
b.sign(keys);
var ret = false;
2014-04-24 20:56:36 -03:00
if (b.signaturesAdded > before) {
2014-04-23 02:01:54 -03:00
txp.signedBy[myId] = Date.now();
2014-04-18 19:28:28 -03:00
this.sendTxProposals();
this.store(true);
ret = true;
2014-04-16 17:50:10 -03:00
}
2014-04-15 15:25:55 -03:00
return ret;
};
2014-04-20 21:53:54 -03:00
Wallet.prototype.sendTx = function(ntxid, cb) {
2014-04-18 19:28:28 -03:00
var txp = this.txProposals.txps[ntxid];
if (!txp) return;
var tx = txp.builder.build();
if (!tx.isComplete()) return;
this.log('[Wallet.js.231] BROADCASTING TX!!!'); //TODO
var txHex = tx.serialize().toString('hex');
2014-04-24 20:56:36 -03:00
this.log('[Wallet.js.261:txHex:]', txHex); //TODO
2014-04-18 19:28:28 -03:00
var self = this;
2014-04-21 11:28:25 -03:00
2014-04-18 19:28:28 -03:00
this.blockchain.sendRawTransaction(txHex, function(txid) {
2014-04-24 20:56:36 -03:00
self.log('BITCOND txid:', txid); //TODO
2014-04-18 19:28:28 -03:00
if (txid) {
2014-04-21 07:30:46 -03:00
self.txProposals.setSent(ntxid, txid);
2014-04-18 19:28:28 -03:00
}
2014-04-20 21:53:54 -03:00
self.sendTxProposals();
self.store();
return cb(txid);
2014-04-18 19:28:28 -03:00
});
};
2014-04-15 15:25:55 -03:00
Wallet.prototype.addSeenToTxProposals = function() {
2014-04-24 20:56:36 -03:00
var ret = false;
var myId = this.getMyCopayerId();
2014-04-16 17:50:10 -03:00
2014-04-24 20:56:36 -03:00
for (var k in this.txProposals.txps) {
2014-04-18 19:28:28 -03:00
var txp = this.txProposals.txps[k];
2014-04-20 20:24:24 -03:00
if (!txp.seenBy[myId]) {
txp.seenBy[myId] = Date.now();
2014-04-15 15:25:55 -03:00
ret = true;
}
2014-04-18 19:28:28 -03:00
}
2014-04-15 15:25:55 -03:00
return ret;
};
2014-04-30 19:50:13 -03:00
// TODO: remove this method and use getAddressesInfo everywhere
2014-04-30 12:25:33 -03:00
Wallet.prototype.getAddresses = function(excludeChange) {
return this.publicKeyRing.getAddresses(excludeChange);
2014-04-15 15:50:22 -03:00
};
2014-04-30 12:25:33 -03:00
Wallet.prototype.getAddressesStr = function(excludeChange) {
return this.getAddresses(excludeChange).map(function(a) {
return a.toString();
2014-04-15 18:23:35 -03:00
});
};
2014-04-30 19:50:13 -03:00
Wallet.prototype.getAddressesInfo = function(excludeChange) {
return this.publicKeyRing.getAddressesInfo(excludeChange);
};
2014-05-01 09:41:18 -03:00
Wallet.prototype.addressIsOwn = function(addrStr, excludeChange) {
var addrList = this.getAddressesStr(excludeChange);
2014-04-18 11:19:39 -03:00
var l = addrList.length;
var ret = false;
2014-04-24 20:56:36 -03:00
for (var i = 0; i < l; i++) {
2014-04-18 11:19:39 -03:00
if (addrList[i] === addrStr) {
2014-04-24 20:56:36 -03:00
ret = true;
2014-04-18 11:19:39 -03:00
break;
}
}
return ret;
};
2014-04-21 12:37:32 -03:00
Wallet.prototype.getBalance = function(safe, cb) {
2014-04-18 13:20:35 -03:00
var balance = 0;
var balanceByAddr = {};
2014-04-21 11:28:25 -03:00
var isMain = {};
2014-04-18 13:20:35 -03:00
var COIN = bitcore.util.COIN;
2014-04-24 20:56:36 -03:00
var f = safe ? this.getSafeUnspent.bind(this) : this.getUnspent.bind(this);
2014-04-21 12:37:32 -03:00
f(function(utxos) {
2014-04-24 20:56:36 -03:00
for (var i = 0; i < utxos.length; i++) {
var u = utxos[i];
2014-04-18 13:20:35 -03:00
var amt = u.amount * COIN;
2014-04-30 12:25:33 -03:00
balance += amt;
2014-04-24 20:56:36 -03:00
balanceByAddr[u.address] = (balanceByAddr[u.address] || 0) + amt;
2014-04-17 11:51:56 -03:00
}
2014-04-30 12:25:33 -03:00
// we multiply and divide by COIN to avoid rounding errors when adding
2014-04-24 20:56:36 -03:00
for (var a in balanceByAddr) {
balanceByAddr[a] = balanceByAddr[a] / COIN;
2014-04-21 12:00:14 -03:00
}
2014-04-30 12:25:33 -03:00
balance = balance / COIN;
return cb(balance, balanceByAddr, isMain);
});
};
2014-04-15 18:23:35 -03:00
2014-04-18 13:20:35 -03:00
Wallet.prototype.getUnspent = function(cb) {
this.blockchain.getUnspent(this.getAddressesStr(), function(unspentList) {
return cb(unspentList);
2014-04-17 16:42:27 -03:00
});
2014-04-15 18:23:35 -03:00
};
2014-04-21 12:37:32 -03:00
Wallet.prototype.getSafeUnspent = function(cb) {
var self = this;
this.blockchain.getUnspent(this.getAddressesStr(), function(unspentList) {
2014-04-24 20:56:36 -03:00
var ret = [];
2014-04-23 02:01:54 -03:00
var maxRejectCount = self.totalCopayers - self.requiredCopayers;
var uu = self.txProposals.getUsedUnspent(maxRejectCount);
2014-04-21 12:37:32 -03:00
2014-04-24 20:56:36 -03:00
for (var i in unspentList) {
if (uu.indexOf(unspentList[i].txid) === -1)
2014-04-21 12:37:32 -03:00
ret.push(unspentList[i]);
}
return cb(ret);
});
};
2014-04-16 17:50:10 -03:00
Wallet.prototype.createTx = function(toAddress, amountSatStr, opts, cb) {
var self = this;
if (typeof opts === 'function') {
cb = opts;
opts = {};
}
opts = opts || {};
if (typeof opts.spendUnconfirmed === 'undefined') {
opts.spendUnconfirmed = this.spendUnconfirmed;
}
2014-04-21 12:37:32 -03:00
self.getSafeUnspent(function(unspentList) {
2014-04-22 22:07:18 -03:00
if (self.createTxSync(toAddress, amountSatStr, unspentList, opts)) {
2014-04-24 20:56:36 -03:00
self.sendPublicKeyRing(); // Change Address
2014-04-22 22:07:18 -03:00
self.sendTxProposals();
self.store();
}
2014-04-16 17:50:10 -03:00
return cb();
});
};
Wallet.prototype.createTxSync = function(toAddress, amountSatStr, utxos, opts) {
2014-04-24 20:56:36 -03:00
var pkr = this.publicKeyRing;
2014-04-15 18:23:35 -03:00
var priv = this.privateKey;
opts = opts || {};
var amountSat = bitcore.bignum(amountSatStr);
2014-04-24 20:56:36 -03:00
if (!pkr.isComplete()) {
2014-04-15 18:23:35 -03:00
throw new Error('publicKeyRing is not complete');
}
if (!opts.remainderOut) {
2014-04-24 20:56:36 -03:00
opts.remainderOut = {
address: this.generateAddress(true).toString()
};
2014-04-21 11:28:25 -03:00
}
2014-04-15 18:23:35 -03:00
var b = new Builder(opts)
.setUnspent(utxos)
.setHashToScriptMap(pkr.getRedeemScriptMap())
2014-04-24 20:56:36 -03:00
.setOutputs([{
address: toAddress,
amountSat: amountSat
}]);
2014-04-15 18:23:35 -03:00
2014-04-24 20:56:36 -03:00
var signRet;
2014-04-15 18:23:35 -03:00
if (priv) {
2014-04-24 20:56:36 -03:00
b.sign(priv.getAll(pkr.addressIndex, pkr.changeAddressIndex));
2014-04-15 18:23:35 -03:00
}
2014-04-23 13:44:20 -03:00
var myId = this.getMyCopayerId();
2014-04-20 20:24:24 -03:00
var now = Date.now();
2014-04-23 02:01:54 -03:00
var me = {};
if (priv && b.signaturesAdded) me[myId] = now;
var meSeen = {};
if (priv) meSeen[myId] = now;
2014-04-20 20:24:24 -03:00
var data = {
2014-04-23 02:01:54 -03:00
signedBy: me,
2014-04-24 20:56:36 -03:00
seenBy: meSeen,
creator: myId,
2014-04-20 20:24:24 -03:00
createdTs: now,
2014-04-15 18:23:35 -03:00
builder: b,
2014-04-20 20:24:24 -03:00
};
this.txProposals.add(data);
2014-04-23 02:01:54 -03:00
return true;
2014-04-15 18:23:35 -03:00
};
2014-04-16 17:50:10 -03:00
Wallet.prototype.connectTo = function(peerId) {
2014-04-16 20:58:57 -03:00
throw new Error('Wallet.connectTo.. not yet implemented!');
2014-04-15 15:50:22 -03:00
};
2014-04-16 20:58:57 -03:00
Wallet.prototype.disconnect = function() {
2014-04-24 23:13:55 -03:00
this.log('## DISCONNECTING');
2014-04-16 20:58:57 -03:00
this.network.disconnect();
};
2014-04-23 21:20:44 -03:00
Wallet.prototype.getNetwork = function() {
return this.network;
};
2014-04-14 18:30:08 -03:00
module.exports = require('soop')(Wallet);