drop provider from wallet.

This commit is contained in:
Christopher Jeffrey 2016-05-27 01:45:41 -07:00
parent b7bc1cfe77
commit 9c747cde42
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
4 changed files with 190 additions and 631 deletions

View File

@ -44,7 +44,7 @@ function KeyRing(options) {
this.derived = !!options.derived;
this.addressMap = null;
this.key = options.key || bcoin.keypair(options);
this.key = options.key;
this.path = options.path;
this.change = !!options.change;
this.index = options.index;
@ -122,16 +122,6 @@ KeyRing.prototype.removeKey = function removeKey(key) {
this.keys = utils.sortKeys(this.keys);
};
/**
* Get private key.
* @param {String?} enc - `"hex"` or `null`.
* @returns {Buffer}
*/
KeyRing.prototype.getPrivateKey = function getPrivateKey(enc) {
return this.key.getPrivateKey(enc);
};
/**
* Get public key.
* @param {String?} enc - `"hex"` or `null`.
@ -461,45 +451,6 @@ KeyRing.prototype.scriptInputs = function scriptInputs(tx, index) {
return total;
};
/**
* Sign inputs for a transaction. Only attempts to sign inputs
* that are redeemable by this address.
* @param {MTX} tx
* @param {Number?} index - Index of input. If not present,
* it will attempt to sign all redeemable inputs.
* @param {SighashType?} type
* @returns {Number} Total number of inputs signed.
*/
KeyRing.prototype.signInputs = function signInputs(tx, index, type) {
var total = 0;
var i, input;
if (index && typeof index === 'object')
index = tx.inputs.indexOf(index);
if (!this.key.privateKey)
return 0;
for (i = 0; i < tx.inputs.length; i++) {
input = tx.inputs[i];
if (index != null && index !== i)
continue;
if (!input.coin)
continue;
if (!this.ownOutput(input.coin))
continue;
if (tx.signInput(i, this, type))
total++;
}
return total;
};
/**
* Build input scripts and sign inputs for a transaction. Only attempts
* to build/sign inputs that are redeemable by this address.
@ -510,16 +461,13 @@ KeyRing.prototype.signInputs = function signInputs(tx, index, type) {
* @returns {Number} Total number of inputs scripts built and signed.
*/
KeyRing.prototype.sign = function sign(tx, index, type) {
KeyRing.prototype.sign = function sign(tx, key, index, type) {
var total = 0;
var i, input;
if (index && typeof index === 'object')
index = tx.inputs.indexOf(index);
if (!this.key.privateKey)
return 0;
for (i = 0; i < tx.inputs.length; i++) {
input = tx.inputs[i];
@ -532,7 +480,7 @@ KeyRing.prototype.sign = function sign(tx, index, type) {
if (!this.ownOutput(input.coin))
continue;
if (tx.sign(i, this, type))
if (tx.sign(i, this, key, type))
total++;
}
@ -595,67 +543,6 @@ KeyRing.prototype.__defineGetter__('address', function() {
return this.getAddress();
});
/**
* Convert an KeyRing to a more json-friendly object.
* @param {String?} passphrase - KeyRing passphrase
* @returns {Object}
*/
KeyRing.prototype.toJSON = function toJSON(passphrase) {
var key = this.key;
if (!(key instanceof bcoin.keypair))
key = new bcoin.keypair({ privateKey: key.getPrivateKey() });
return {
v: 1,
name: 'address',
network: this.network.type,
label: this.label,
change: this.change,
derived: this.derived,
index: this.index,
path: this.path,
address: this.getAddress(),
key: key.toJSON(passphrase),
type: this.type,
witness: this.witness,
keys: this.keys.map(utils.toBase58),
m: this.m,
n: this.n
};
};
/**
* Instantiate an KeyRing from a jsonified transaction object.
* @param {Object} json - The jsonified transaction object.
* @param {String?} passphrase - KeyRing passphrase
* @returns {KeyRing}
*/
KeyRing.fromJSON = function fromJSON(json, passphrase) {
var w;
assert.equal(json.v, 1);
assert.equal(json.name, 'address');
w = new KeyRing({
label: json.label,
change: json.change,
derived: json.derived,
index: json.index,
path: json.path,
key: bcoin.keypair.fromJSON(json.key, passphrase),
type: json.type,
witness: json.witness,
keys: json.keys.map(utils.fromBase58),
m: json.m,
n: json.n
});
return w;
};
/*
* Expose
*/

View File

@ -360,7 +360,7 @@ MTX.prototype.createSignature = function createSignature(index, prev, key, type,
* @throws on unavailable coins.
*/
MTX.prototype.signInput = function signInput(index, addr, type) {
MTX.prototype.signInput = function signInput(index, addr, key, type) {
var input, prev, signature, keyIndex, signatures, i;
var len, m, n, keys, vector, dummy, version;
@ -410,7 +410,7 @@ MTX.prototype.signInput = function signInput(index, addr, type) {
}
// Create our signature.
signature = this.createSignature(index, prev, addr.key, type, version);
signature = this.createSignature(index, prev, key, type, version);
// P2PK
if (prev.isPubkey()) {
@ -630,7 +630,7 @@ MTX.prototype.isSigned = function isSigned() {
* @throws on unavailable coins.
*/
MTX.prototype.sign = function sign(index, addr, type) {
MTX.prototype.sign = function sign(index, addr, key, type) {
var input;
if (index && typeof index === 'object')
@ -644,7 +644,7 @@ MTX.prototype.sign = function sign(index, addr, type) {
return false;
// Sign input
if (!this.signInput(index, addr, type))
if (!this.signInput(index, addr, key, type))
return false;
return true;

View File

@ -17,7 +17,7 @@ var BufferWriter = require('./writer');
* @exports Wallet
* @constructor
* @param {Object} options
* @param {Provider?} options.provider - Wallet Provider. If not
* @param {Provider} options.provider
* present, no coins will be available.
* @param {(HDPrivateKey|HDPublicKey)?} options.master - Master HD key. If not
* present, it will be generated.
@ -45,8 +45,46 @@ var BufferWriter = require('./writer');
* (default=account key "address").
*/
function MasterKey(options) {
this.json = options.json;
this.key = options.key || null;
}
MasterKey.prototype.decrypt = function decrypt(passphrase) {
if (this.key)
return this.key;
if (!this.json.encrypted)
return bcoin.hd.fromJSON(this.json);
return bcoin.hd.fromJSON(this.json, passphrase);
};
MasterKey.prototype.toJSON = function toJSON() {
return this.json;
};
MasterKey.fromKey = function fromKey(key) {
return new MasterKey({
key: key,
json: key.toJSON()
});
};
MasterKey.fromJSON = function fromJSON(json) {
var key;
if (!json.encrypted)
key = bcoin.hd.fromJSON(json);
return new MasterKey({
key: key,
json: json
});
};
function Wallet(options) {
var i;
var i, key;
if (!(this instanceof Wallet))
return new Wallet(options);
@ -61,20 +99,18 @@ function Wallet(options) {
this.options = options;
this.network = bcoin.network.get(options.network);
if (typeof options.master === 'string')
options.master = { xkey: options.master };
if (options.master
&& typeof options.master === 'object'
&& !(options.master instanceof bcoin.hd)) {
options.master = bcoin.hd.fromAny(options.master, this.network);
}
if (!options.master)
options.master = bcoin.hd.fromMnemonic(null, this.network);
if (!(options.master instanceof bcoin.hd))
options.master = bcoin.hd.fromAny(options.master, this.network);
options.master = MasterKey.fromKey(options.master);
this.provider = options.provider || null;
this.id = options.id || null;
this.master = options.master || null;
this.accountKey = options.accountKey || null;
this.addressMap = options.addressMap || {};
this.witness = options.witness || false;
this.loaded = false;
@ -104,17 +140,21 @@ function Wallet(options) {
if (this.m < 1 || this.m > this.n)
throw new Error('m ranges between 1 and n');
if (this.derivation === 'bip45') {
this.accountKey = this.master.isPurpose45()
? this.master
: this.master.derivePurpose45();
} else if (this.derivation === 'bip44') {
this.accountKey = this.master.isAccount44()
? this.master
: this.master.deriveAccount44(this.accountIndex);
if (!this.accountKey) {
key = this.master.key;
assert(key);
if (this.derivation === 'bip45')
key = key.derivePurpose45().hdPublicKey;
else if (this.derivation === 'bip44')
key = key.deriveAccount44(this.accountIndex).hdPublicKey;
this.accountKey = key;
}
this.id = this.getID();
if (!this.id)
this.id = this.getID();
// Non-alphanumeric IDs will break leveldb sorting.
assert(/^[a-zA-Z0-9]+$/.test(this.id), 'Wallet IDs must be alphanumeric.');
@ -129,6 +169,25 @@ function Wallet(options) {
utils.inherits(Wallet, EventEmitter);
Wallet.prototype.fromMnemonic = function fromMnemonic(network) {
var master = bcoin.hd.fromMnemonic(null, network);
return Wallet.fromMaster(master, network);
};
Wallet.prototype.fromMaster = function fromMaster(master, network) {
if (!master)
master = bcoin.hd.generate();
return new Wallet({ master: master, network: network });
};
Wallet.prototype.fromAccount = function fromAccount(accountKey, network) {
if (!master)
master = bcoin.hd.generate();
return new Wallet({ accountKey: accountKey, network: network });
};
Wallet.prototype._init = function _init() {
var self = this;
var i;
@ -241,6 +300,12 @@ Wallet.prototype.addKey = function addKey(key) {
assert(key, 'Key required.');
if (Array.isArray(key)) {
for (i = 0; i < key.length; i++)
this.addKey(key[i]);
return;
}
if (key instanceof bcoin.wallet) {
assert(key.derivation === this.derivation);
key = key.accountKey;
@ -292,6 +357,12 @@ Wallet.prototype.removeKey = function removeKey(key) {
assert(!this._keysFinalized);
if (Array.isArray(key)) {
for (i = 0; i < key.length; i++)
this.removeKey(key[i]);
return;
}
assert(key, 'Key required.');
if (key instanceof bcoin.wallet) {
@ -414,11 +485,6 @@ Wallet.prototype.createAddress = function createAddress(change) {
this.receiveAddress = address;
}
if (this.provider && this.provider.sync) {
assert(!this.provider.update);
this.provider.sync(this, address);
}
return address;
};
@ -517,10 +583,6 @@ Wallet.prototype.deriveAddress = function deriveAddress(change, index) {
if (this.witness)
this.addressMap[address.getProgramHash('hex')] = data.path;
// Update the DB with the new address.
if (this.provider && this.provider.update)
this.provider.update(this, address);
this.emit('add address', address);
this.cache.set(data.path, address);
@ -834,10 +896,6 @@ Wallet.prototype.createTX = function createTX(options, outputs, callback) {
if (!tx.checkInputs(height))
return callback(new Error('CheckInputs failed.'));
// Sign the transaction
if (!self.sign(tx))
return callback(new Error('Could not sign transaction.'));
return callback(null, tx);
});
};
@ -1180,27 +1238,6 @@ Wallet.prototype.scriptInputs = function scriptInputs(tx, index) {
return total;
};
/**
* Sign inputs for a transaction. Only attempts to sign inputs
* that are redeemable by this wallet.
* @param {MTX} tx
* @param {Number?} index - Index of input. If not present,
* it will attempt to sign all redeemable inputs.
* @param {SighashType?} type
* @returns {Number} Total number of inputs signed.
*/
Wallet.prototype.signInputs = function signInputs(tx, index, type) {
var addresses = this.deriveInputs(tx, index);
var total = 0;
var i;
for (i = 0; i < addresses.length; i++)
total += addresses[i].signInputs(tx, index, type);
return total;
};
/**
* Build input scripts and sign inputs for a transaction. Only attempts
* to build/sign inputs that are redeemable by this wallet.
@ -1211,13 +1248,24 @@ Wallet.prototype.signInputs = function signInputs(tx, index, type) {
* @returns {Number} Total number of inputs scripts built and signed.
*/
Wallet.prototype.sign = function sign(tx, index, type) {
Wallet.prototype.sign = function sign(tx, passphrase, index, type) {
var addresses = this.deriveInputs(tx, index);
var key = this.master.decrypt(passphrase);
var total = 0;
var i;
var i, address, key;
for (i = 0; i < addresses.length; i++)
total += addresses[i].sign(tx, index, type);
for (i = 0; i < addresses.length; i++) {
address = addresses[i];
if (this.derivation === 'bip44')
key = key.deriveAccount44(this.accountIndex);
else if (this.derivation === 'bip45')
key = key.derivePurpose45();
key = key.derive(address.path);
total += address.sign(tx, key, index, type);
}
return total;
};
@ -1325,16 +1373,6 @@ Wallet.prototype.getTimeRange = function getTimeRange(options, callback) {
return this.provider.getTimeRange(options, callback);
};
/**
* Get private key for current receiving address.
* @param {String?} enc - `"hex"` or `null`.
* @returns {Buffer}
*/
Wallet.prototype.getPrivateKey = function getPrivateKey(enc) {
return this.receiveAddress.getPrivateKey(enc);
};
/**
* Get public key for current receiving address.
* @param {String?} enc - `"hex"` or `null`.
@ -1575,7 +1613,7 @@ Wallet.prototype.toJSON = function toJSON() {
accountIndex: this.accountIndex,
receiveDepth: this.receiveDepth,
changeDepth: this.changeDepth,
master: this.master.toJSON(this.options.passphrase),
master: this.master.toJSON(),
accountKey: this.accountKey.xpubkey,
addressMap: this.addressMap,
keys: this.keys.map(function(key) {
@ -1595,7 +1633,7 @@ Wallet.prototype.toJSON = function toJSON() {
* @throws Error on bad decrypt
*/
Wallet.parseJSON = function parseJSON(json, passphrase) {
Wallet.parseJSON = function parseJSON(json) {
assert.equal(json.v, 3);
assert.equal(json.name, 'wallet');
@ -1611,10 +1649,12 @@ Wallet.parseJSON = function parseJSON(json, passphrase) {
accountIndex: json.accountIndex,
receiveDepth: json.receiveDepth,
changeDepth: json.changeDepth,
master: bcoin.hd.fromJSON(json.master, passphrase),
master: MasterKey.fromJSON(json.master),
accountKey: bcoin.hd.fromBase58(json.accountKey),
addressMap: json.addressMap,
keys: json.keys,
passphrase: passphrase
keys: json.keys.map(function(key) {
return bcoin.hd.fromBase58(key);
})
};
};
@ -1622,160 +1662,11 @@ Wallet.parseJSON = function parseJSON(json, passphrase) {
* Instantiate a Wallet from a
* jsonified wallet object.
* @param {Object} json - The jsonified wallet object.
* @param {String?} passphrase
* @returns {Wallet}
*/
Wallet.fromJSON = function fromJSON(json, passphrase) {
return new Wallet(Wallet.parseJSON(json, passphrase));
};
Wallet._syncDepth = function _syncDepth(json, options) {
var master, wallet;
var res = false;
assert.equal(json.v, 3);
assert.equal(json.name, 'wallet');
master = json.master;
json.master = json.accountKey;
wallet = new Wallet(json);
if (!wallet._initialized)
return;
if (options.tx != null) {
if (wallet.syncOutputDepth(options.tx))
res = true;
}
if (options.receiveDepth != null) {
if (wallet.setReceiveDepth(options.receiveDepth))
res = true;
}
if (options.changeDepth != null) {
if (wallet.setChangeDepth(options.changeDepth))
res = true;
}
if (!res)
return;
wallet = wallet.toJSON();
wallet.master = master;
return wallet;
};
/**
* Sync output depth of a jsonified wallet object.
* Useful for increasing depth without decrypting
* the key and instantiating the wallet.
* @param {json}
* @param {TX} tx
* @returns {json}
*/
Wallet.syncOutputDepth = function syncOutputDepth(json, tx) {
return Wallet._syncDepth(json, { tx: tx });
};
/**
* Increase receive depth of a jsonified wallet object.
* Useful for increasing depth without decrypting
* the key and instantiating the wallet.
* @param {json}
* @param {Number} receiveDepth
* @returns {json}
*/
Wallet.setReceiveDepth = function setReceiveDepth(json, receiveDepth) {
return Wallet._syncDepth(json, {
receiveDepth: receiveDepth || 0
});
};
/**
* Increase change depth of a jsonified wallet object.
* Useful for increasing depth without decrypting
* the key and instantiating the wallet.
* @param {json}
* @param {Number} changeDepth
* @returns {json}
*/
Wallet.setChangeDepth = function setChangeDepth(json, changeDepth) {
return Wallet._syncDepth(json, {
changeDepth: changeDepth || 0
});
};
/**
* Increase depths of a jsonified wallet object.
* Useful for increasing depth without decrypting
* the key and instantiating the wallet.
* @param {json}
* @param {Number} receiveDepth
* @param {Number} changeDepth
* @returns {json}
*/
Wallet.setDepth = function setDepth(json, receiveDepth, changeDepth) {
return Wallet._syncDepth(json, {
receiveDepth: receiveDepth || 0,
changeDepth: changeDepth || 0
});
};
Wallet._addKey = function _addKey(json, keys, remove) {
var master, wallet;
assert.equal(json.v, 3);
assert.equal(json.name, 'wallet');
if (!Array.isArray(keys))
keys = [keys];
master = json.master;
json.master = json.accountKey;
wallet = new Wallet(json);
keys.forEach(function(key) {
if (remove)
wallet.removeKey(key);
else
wallet.addKey(key);
});
wallet = wallet.toJSON();
wallet.master = master;
return wallet;
};
/**
* Add keys to a jsonified wallet object.
* Useful for managing keys without decrypting
* the key and instantiating the wallet.
* @param {json}
* @param {Buffer[]|Base58String[]} keys
* @returns {json}
*/
Wallet.addKey = function addKey(json, keys) {
return Wallet._addKey(json, keys, false);
};
/**
* Remove keys from a jsonified wallet object.
* Useful for managing keys without decrypting
* the key and instantiating the wallet.
* @param {json}
* @param {Buffer[]|Base58String[]} keys
* @returns {json}
*/
Wallet.removeKey = function removeKey(json, keys) {
return Wallet._addKey(json, keys, true);
Wallet.fromJSON = function fromJSON(json) {
return new Wallet(Wallet.parseJSON(json));
};
/**

View File

@ -232,17 +232,16 @@ WalletDB.prototype.syncOutputDepth = function syncOutputDepth(id, tx, callback)
callback = utils.ensure(callback);
this.getJSON(id, function(err, json) {
this.get(id, function(err, wallet) {
if (err)
return callback(err);
// Allocate new addresses if necessary.
json = bcoin.wallet.syncOutputDepth(json, tx);
if (!wallet)
return callback(new Error('No wallet.'));
if (!json)
return callback();
wallet.syncOutputDepth(tx);
self.saveJSON(id, json, function(err) {
self.save(wallet, function(err) {
if (err)
return callback(err);
@ -253,42 +252,6 @@ WalletDB.prototype.syncOutputDepth = function syncOutputDepth(id, tx, callback)
});
};
/**
* Set receiving/change depth (depth is the index of the _next_ address).
* Allocate all addresses up to depth. Note that this also allocates
* new lookahead addresses.
* @param {WalletID} id
* @param {Number} receive - Receive address depth.
* @param {Number} change - Change address depth.
* @param {Function} callback
*/
WalletDB.prototype.setDepth = function setDepth(id, receive, change, callback) {
var self = this;
callback = utils.ensure(callback);
this.getJSON(id, function(err, json) {
if (err)
return callback(err);
// Allocate new addresses if necessary.
json = bcoin.wallet.setDepth(json, receive, change);
if (!json)
return callback();
self.saveJSON(id, json, function(err) {
if (err)
return callback(err);
self.emit('set depth', id, receive, change);
callback();
});
});
};
/**
* Add a public account/purpose key to the wallet for multisig.
* @param {WalletID} id
@ -302,17 +265,20 @@ WalletDB.prototype.addKey = function addKey(id, key, callback) {
callback = utils.ensure(callback);
this.getJSON(id, function(err, json) {
this.get(id, function(err, json) {
if (err)
return callback(err);
if (!wallet)
return callback(new Error('No wallet.'));
try {
json = bcoin.wallet.addKey(json, key);
wallet.addKey(key);
} catch (e) {
return callback(e);
}
self.saveJSON(id, json, callback);
self.save(wallet, callback);
});
};
@ -329,35 +295,23 @@ WalletDB.prototype.removeKey = function removeKey(id, key, callback) {
callback = utils.ensure(callback);
this.getJSON(id, function(err, json) {
this.get(id, function(err, wallet) {
if (err)
return callback(err);
if (!wallet)
return callback(new Error('No wallet.'));
try {
json = bcoin.wallet.removeKey(json, key);
wallet.removeKey(key);
} catch (e) {
return callback(e);
}
self.saveJSON(id, json, callback);
self.save(wallet, callback);
});
};
/**
* Retrieve wallet without instantiating it.
* @param {WalletID} id
* @param {Function} callback - Returns [Error, Object(nakedWallet)].
*/
WalletDB.prototype.getJSON = function getJSON(id, callback) {
if (typeof id === 'object')
id = id.id;
callback = utils.ensure(callback);
return this._getDB(id, callback);
};
/**
* Save a "naked" (non-instantiated) wallet. Will
* also index the address table.
@ -368,33 +322,27 @@ WalletDB.prototype.getJSON = function getJSON(id, callback) {
WalletDB.prototype.saveJSON = function saveJSON(id, json, callback) {
var self = this;
var data = new Buffer(JSON.stringify(json), 'utf8');
var batch;
callback = utils.ensure(callback);
return this._saveDB(id, json, function(err, json) {
var batch;
this.db.put('w/' + id, data, function(err) {
if (err)
return callback(err);
if (json) {
batch = self.db.batch();
batch = self.db.batch();
Object.keys(json.addressMap).forEach(function(address) {
if (self.tx.filter)
self.tx.filter.add(address, 'hex');
Object.keys(json.addressMap).forEach(function(address) {
if (self.tx.filter)
self.tx.filter.add(address, 'hex');
batch.put('W/' + address + '/' + json.id, DUMMY);
});
batch.put('W/' + address + '/' + json.id, DUMMY);
});
return batch.write(function(err) {
if (err)
return callback(err);
return callback(null, json);
});
}
return callback(null, json);
return batch.write(function(err) {
if (err)
return callback(err);
return callback(null, json);
});
});
};
@ -406,31 +354,31 @@ WalletDB.prototype.saveJSON = function saveJSON(id, json, callback) {
WalletDB.prototype.removeJSON = function removeJSON(id, callback) {
var self = this;
var batch;
callback = utils.ensure(callback);
if (typeof id === 'object')
id = id.id;
return this._removeDB(id, function(err, json) {
var batch;
this.getJSON(id, function(err, json) {
if (err)
return callback(err);
if (json) {
batch = self.db.batch();
Object.keys(json.addressMap).forEach(function(address) {
batch.del('W/' + address + '/' + json.id);
});
return batch.write(function(err) {
if (err)
batch = self.db.batch();
Object.keys(json.addressMap).forEach(function(address) {
batch.del('W/' + address + '/' + json.id);
});
batch.write(function(err) {
if (err)
return callback(err);
self.db.del(key, function(err) {
if (err && err.type !== 'NotFoundError')
return callback(err);
return callback(null, json);
});
}
return callback(null, json);
});
});
};
@ -441,12 +389,10 @@ WalletDB.prototype.removeJSON = function removeJSON(id, callback) {
* @param {Function} callback - Returns [Error, Object(nakedWallet)].
*/
WalletDB.prototype._getDB = function _getDB(id, callback) {
var key = 'w/' + id;
WalletDB.prototype.getJSON = function getJSON(id, callback) {
callback = utils.ensure(callback);
this.db.get(key, function(err, json) {
this.db.get('w/' + id, function(err, json) {
if (err && err.type === 'NotFoundError')
return callback();
@ -463,71 +409,15 @@ WalletDB.prototype._getDB = function _getDB(id, callback) {
});
};
/**
* Save object to the database.
* @private
* @param {WalletID} id
* @param {Object} json
* @param {Function} callback - Returns [Error, nakedWallet].
*/
WalletDB.prototype._saveDB = function _saveDB(id, json, callback) {
var key = 'w/' + id;
var data;
callback = utils.ensure(callback);
data = new Buffer(JSON.stringify(json), 'utf8');
this.db.put(key, data, function(err) {
if (err)
return callback(err);
return callback(null, json);
});
};
/**
* Remove object from the database.
* @private
* @param {WalletID} id
* @param {Function} callback - Returns [Error, Object].
*/
WalletDB.prototype._removeDB = function _removeDB(id, callback) {
var self = this;
var key = 'w/' + id;
callback = utils.ensure(callback);
this._getDB(id, function(err, json) {
if (err)
return callback(err);
self.db.del(key, function(err) {
if (err && err.type !== 'NotFoundError')
return callback(err);
return callback(null, json);
});
});
};
/**
* Get a wallet from the database, instantiate, decrypt, and setup provider.
* @param {WalletID} id
* @param {String?} passphrase
* @param {Function} callback - Returns [Error, {@link Wallet}].
*/
WalletDB.prototype.get = function get(id, passphrase, callback) {
WalletDB.prototype.get = function get(id, callback) {
var self = this;
if (typeof passphrase === 'function') {
callback = passphrase;
passphrase = null;
}
callback = utils.ensure(callback);
return this.getJSON(id, function(err, options) {
@ -540,7 +430,7 @@ WalletDB.prototype.get = function get(id, passphrase, callback) {
return callback();
try {
options = bcoin.wallet.parseJSON(options, passphrase);
options = bcoin.wallet.parseJSON(options);
options.provider = new Provider(self);
wallet = new bcoin.wallet(options);
} catch (e) {
@ -558,24 +448,8 @@ WalletDB.prototype.get = function get(id, passphrase, callback) {
* @param {Function} callback
*/
WalletDB.prototype.save = function save(id, options, callback) {
if (id && typeof id === 'object') {
callback = options;
options = id;
id = null;
}
if (!id)
id = options.id;
else
options.id = id;
callback = utils.ensure(callback);
assert(options instanceof bcoin.wallet);
options = options.toJSON();
this.saveJSON(id, options, callback);
WalletDB.prototype.save = function save(wallet, callback) {
this.saveJSON(wallet.id, wallet.toJSON(), callback);
};
/**
@ -585,14 +459,6 @@ WalletDB.prototype.save = function save(id, options, callback) {
*/
WalletDB.prototype.remove = function remove(id, callback) {
if (id instanceof bcoin.wallet)
id.destroy();
if (id && id.id)
id = id.id;
callback = utils.ensure(callback);
return this.removeJSON(id, callback);
};
@ -603,30 +469,21 @@ WalletDB.prototype.remove = function remove(id, callback) {
* @param {Function} callback - Returns [Error, {@link Wallet}].
*/
WalletDB.prototype.create = function create(id, options, callback) {
WalletDB.prototype.create = function create(options, callback) {
var self = this;
if (id && typeof id === 'object') {
callback = options;
options = id;
id = null;
}
if (!id)
id = options.id;
else
options.id = id;
callback = utils.ensure(callback);
function create(err, json) {
var wallet;
if (err)
return callback(err);
if (json)
return callback(new Error('`' + id + '` already exists.'), null, json);
if (json) {
return callback(
new Error('`' + options.id + '` already exists.'),
null,
json);
}
if (self.network.witness)
options.witness = options.witness !== false;
@ -635,7 +492,7 @@ WalletDB.prototype.create = function create(id, options, callback) {
options.network = self.network;
wallet = new bcoin.wallet(options);
self.saveJSON(wallet.id, wallet.toJSON(), function(err) {
self.save(wallet, function(err) {
if (err)
return callback(err);
@ -643,10 +500,10 @@ WalletDB.prototype.create = function create(id, options, callback) {
});
}
if (!id)
if (!options.id)
return create();
return this.getJSON(id, create);
return this.getJSON(options.id, create);
};
/**
@ -656,23 +513,9 @@ WalletDB.prototype.create = function create(id, options, callback) {
* @param {Function} callback
*/
WalletDB.prototype.ensure = function ensure(id, options, callback) {
WalletDB.prototype.ensure = function ensure(options, callback) {
var self = this;
if (id && typeof id === 'object') {
callback = options;
options = id;
id = null;
}
if (!id)
id = options.id;
else
options.id = id;
callback = utils.ensure(callback);
return this.create(id, options, function(err, wallet, json) {
return this.create(options, function(err, wallet, json) {
if (err && !json)
return callback(err);
@ -682,7 +525,7 @@ WalletDB.prototype.ensure = function ensure(id, options, callback) {
assert(json);
try {
options = bcoin.wallet.parseJSON(json, options.passphrase);
options = bcoin.wallet.parseJSON(json);
options.provider = new Provider(self);
wallet = new bcoin.wallet(options);
} catch (e) {
@ -693,60 +536,6 @@ WalletDB.prototype.ensure = function ensure(id, options, callback) {
});
};
/**
* Notify the database that a new address
* has been derived. Save to address table. Save wallet.
* @param {Wallet} wallet
* @param {Address} address
*/
WalletDB.prototype.update = function update(wallet, address) {
var self = this;
var batch;
// Ugly hack to avoid extra writes.
if (!wallet.changeAddress && wallet.changeDepth > 1)
return;
batch = this.db.batch();
batch.put(
'W/' + address.getKeyHash('hex') + '/' + wallet.id,
DUMMY);
if (this.tx.filter)
this.tx.filter.add(address.getKeyHash());
if (address.type === 'multisig') {
batch.put(
'W/' + address.getScriptHash('hex') + '/' + wallet.id,
DUMMY);
if (this.tx.filter)
this.tx.filter.add(address.getScriptHash());
}
if (address.witness) {
batch.put(
'W/' + address.getProgramHash('hex') + '/' + wallet.id,
DUMMY);
if (this.tx.filter)
this.tx.filter.add(address.getProgramHash());
}
batch.write(function(err) {
if (err)
self.emit('error', err);
// XXX might have to encrypt key - slow
self._saveDB(wallet.id, wallet.toJSON(), function(err) {
if (err)
self.emit('error', err);
});
});
};
/**
* @see {@link TXDB#add}.
*/
@ -776,7 +565,6 @@ WalletDB.prototype.getCoin = function getCoin(hash, index, callback) {
*/
WalletDB.prototype.getHistory = function getHistory(id, callback) {
id = id.id || id;
return this.tx.getHistoryByAddress(id, callback);
};
@ -785,7 +573,6 @@ WalletDB.prototype.getHistory = function getHistory(id, callback) {
*/
WalletDB.prototype.getCoins = function getCoins(id, callback) {
id = id.id || id;
return this.tx.getCoinsByAddress(id, callback);
};
@ -794,7 +581,6 @@ WalletDB.prototype.getCoins = function getCoins(id, callback) {
*/
WalletDB.prototype.getUnconfirmed = function getUnconfirmed(id, callback) {
id = id.id || id;
return this.tx.getUnconfirmedByAddress(id, callback);
};
@ -803,7 +589,6 @@ WalletDB.prototype.getUnconfirmed = function getUnconfirmed(id, callback) {
*/
WalletDB.prototype.getBalance = function getBalance(id, callback) {
id = id.id || id;
return this.tx.getBalanceByAddress(id, callback);
};
@ -812,7 +597,6 @@ WalletDB.prototype.getBalance = function getBalance(id, callback) {
*/
WalletDB.prototype.getLastTime = function getLastTime(id, callback) {
id = id.id || id;
return this.tx.getLastTime(id, callback);
};
@ -821,7 +605,6 @@ WalletDB.prototype.getLastTime = function getLastTime(id, callback) {
*/
WalletDB.prototype.getLast = function getLast(id, limit, callback) {
id = id.id || id;
return this.tx.getLast(id, limit, callback);
};
@ -830,7 +613,6 @@ WalletDB.prototype.getLast = function getLast(id, limit, callback) {
*/
WalletDB.prototype.getRange = function getRange(id, options, callback) {
id = id.id || id;
return this.tx.getRange(id, options, callback);
};
@ -904,7 +686,6 @@ WalletDB.prototype.zap = function zap(now, age, callback) {
*/
WalletDB.prototype.zapWallet = function zapWallet(id, now, age, callback) {
id = id.id || id;
return this.tx.zap(id, now, age, callback);
};
@ -1174,8 +955,8 @@ Provider.prototype.addTX = function addTX(tx, callback) {
* @param {Address} address
*/
Provider.prototype.update = function update(wallet, address) {
return this.db.update(wallet, address);
Provider.prototype.save = function save(wallet, callback) {
return this.db.save(wallet, callback);
};
/**