drop provider from wallet.
This commit is contained in:
parent
b7bc1cfe77
commit
9c747cde42
@ -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
|
||||
*/
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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));
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user