bitcore-wallet-service/lib/model/wallet.js

144 lines
3.3 KiB
JavaScript
Raw Normal View History

2015-01-27 05:18:45 -08:00
'use strict';
var _ = require('lodash');
2015-02-02 06:55:03 -08:00
var util = require('util');
var $ = require('preconditions').singleton();
2015-01-27 05:18:45 -08:00
2015-02-02 11:16:14 -08:00
var Bitcore = require('bitcore');
var BitcoreAddress = Bitcore.Address;
2015-02-07 08:13:29 -08:00
var Uuid = require('uuid');
2015-02-02 11:16:14 -08:00
var Address = require('./address');
2015-01-28 09:21:09 -08:00
var Copayer = require('./copayer');
2015-02-03 10:44:44 -08:00
var AddressManager = require('./addressmanager');
2015-02-02 06:55:03 -08:00
2015-02-02 10:29:14 -08:00
var VERSION = '1.0.0';
2015-01-28 09:21:09 -08:00
2015-01-27 05:18:45 -08:00
function Wallet(opts) {
2015-02-02 12:07:18 -08:00
opts = opts || {};
2015-01-27 05:18:45 -08:00
2015-02-02 10:29:14 -08:00
this.version = VERSION;
2015-02-02 12:07:18 -08:00
this.createdOn = Math.floor(Date.now() / 1000);
2015-02-07 08:13:29 -08:00
this.id = Uuid.v4();
2015-02-02 12:07:18 -08:00
this.name = opts.name;
this.m = opts.m;
this.n = opts.n;
this.status = 'pending';
this.publicKeyRing = [];
this.addressIndex = 0;
this.copayers = [];
2015-02-02 04:15:50 -08:00
this.pubKey = opts.pubKey;
2015-02-13 08:35:20 -08:00
this.isTestnet = opts.isTestnet;
2015-02-03 10:44:44 -08:00
this.addressManager = new AddressManager();
2015-01-27 05:18:45 -08:00
};
2015-02-02 10:29:14 -08:00
/* For compressed keys, m*73 + n*34 <= 496 */
Wallet.COPAYER_PAIR_LIMITS = {
1: 1,
2: 2,
3: 3,
4: 4,
5: 4,
6: 4,
7: 3,
8: 3,
9: 2,
10: 2,
11: 1,
12: 1,
};
2015-02-01 11:50:58 -08:00
2015-02-02 10:29:14 -08:00
/**
* Get the maximum allowed number of required copayers.
* This is a limit imposed by the maximum allowed size of the scriptSig.
* @param {number} totalCopayers - the total number of copayers
* @return {number}
*/
Wallet.getMaxRequiredCopayers = function(totalCopayers) {
return Wallet.COPAYER_PAIR_LIMITS[totalCopayers];
};
2015-02-01 06:41:16 -08:00
2015-02-02 15:13:13 -08:00
Wallet.verifyCopayerLimits = function(m, n) {
2015-02-02 12:07:18 -08:00
return (n >= 1 && n <= 12) && (m >= 1 && m <= Wallet.COPAYER_PAIR_LIMITS[n]);
2015-02-01 11:50:58 -08:00
};
2015-02-02 15:13:13 -08:00
Wallet.fromObj = function(obj) {
2015-02-02 12:07:18 -08:00
var x = new Wallet();
2015-02-01 11:50:58 -08:00
2015-02-02 12:07:18 -08:00
x.createdOn = obj.createdOn;
x.id = obj.id;
x.name = obj.name;
x.m = obj.m;
x.n = obj.n;
x.status = obj.status;
x.publicKeyRing = obj.publicKeyRing;
2015-02-02 15:13:13 -08:00
x.copayers = _.map(obj.copayers, function(copayer) {
2015-02-07 07:48:57 -08:00
return Copayer.fromObj(copayer);
2015-02-02 12:07:18 -08:00
});
2015-02-02 04:15:50 -08:00
x.pubKey = obj.pubKey;
2015-02-02 11:16:14 -08:00
x.isTestnet = obj.isTestnet;
2015-02-03 10:44:44 -08:00
x.addressManager = AddressManager.fromObj(obj.addressManager);
2015-02-01 06:41:16 -08:00
2015-02-02 12:07:18 -08:00
return x;
2015-01-27 05:18:45 -08:00
};
2015-02-10 05:22:23 -08:00
Wallet.prototype.isShared = function() {
return this.n > 1;
};
2015-02-02 15:13:13 -08:00
Wallet.prototype.addCopayer = function(copayer) {
2015-02-02 12:07:18 -08:00
this.copayers.push(copayer);
2015-01-28 09:21:09 -08:00
2015-02-02 12:07:18 -08:00
if (this.copayers.length < this.n) return;
2015-02-02 15:13:13 -08:00
2015-02-02 12:07:18 -08:00
this.status = 'complete';
this.publicKeyRing = _.pluck(this.copayers, 'xPubKey');
2015-01-28 09:21:09 -08:00
};
2015-02-02 15:13:13 -08:00
Wallet.prototype.getCopayer = function(copayerId) {
return _.find(this.copayers, {
id: copayerId
});
2015-01-28 09:21:09 -08:00
};
2015-02-02 11:16:14 -08:00
2015-02-05 12:22:38 -08:00
Wallet.prototype.getNetworkName = function() {
return this.isTestnet ? 'testnet' : 'livenet';
};
2015-02-02 15:13:13 -08:00
Wallet.prototype._getBitcoreNetwork = function() {
2015-02-02 11:16:14 -08:00
return this.isTestnet ? Bitcore.Networks.testnet : Bitcore.Networks.livenet;
};
2015-02-05 10:50:18 -08:00
Wallet.prototype.getPublicKey = function(copayerId, path) {
var copayer = this.getCopayer(copayerId);
return copayer.getPublicKey(path);
};
Wallet.prototype.isComplete = function() {
return this.status == 'complete';
};
2015-02-03 10:44:44 -08:00
Wallet.prototype.createAddress = function(isChange) {
$.checkState(this.isComplete());
2015-02-03 10:44:44 -08:00
var path = this.addressManager.getNewAddressPath(isChange);
2015-02-02 11:16:14 -08:00
var publicKeys = _.map(this.copayers, function(copayer) {
var xpub = new Bitcore.HDPublicKey(copayer.xPubKey);
return xpub.derive(path).publicKey;
});
var bitcoreAddress = BitcoreAddress.createMultisig(publicKeys, this.m, this._getBitcoreNetwork());
return new Address({
address: bitcoreAddress.toString(),
path: path,
2015-02-03 18:17:06 -08:00
publicKeys: _.invoke(publicKeys, 'toString'),
2015-02-02 11:16:14 -08:00
});
};
2015-01-27 05:18:45 -08:00
module.exports = Wallet;