wallet refactor.
This commit is contained in:
parent
2a18a76973
commit
f1376e5a99
@ -2809,25 +2809,14 @@ Script.prototype.isNulldata = function isNulldata(sloppy) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.raw.length === 2) {
|
||||
if (this.raw[1] === opcodes.OP_0)
|
||||
return true;
|
||||
if (this.raw[1] >= opcodes.OP_1 && this.raw[1] <= opcodes.OP_16)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
if (this.raw.length === 2)
|
||||
return Script.getSmall(this.raw[1]) !== -1;
|
||||
|
||||
if (this.raw[1] >= 0x01 && this.raw[1] <= 0x4b) {
|
||||
if (this.raw[1] + 2 !== this.raw.length)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
if (this.raw[1] >= 0x01 && this.raw[1] <= 0x4b)
|
||||
return this.raw[1] + 2 === this.raw.length;
|
||||
|
||||
if (this.raw[1] === opcodes.OP_PUSHDATA1) {
|
||||
if (this.raw[2] + 3 !== this.raw.length)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
if (this.raw[1] === opcodes.OP_PUSHDATA1)
|
||||
return this.raw[2] > 75 && this.raw[2] + 3 === this.raw.length;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
@ -39,23 +39,37 @@ var BufferWriter = require('./writer');
|
||||
* (default=account key "address").
|
||||
*/
|
||||
|
||||
function Wallet(options) {
|
||||
var master;
|
||||
|
||||
function Wallet(db, options) {
|
||||
if (!(this instanceof Wallet))
|
||||
return new Wallet(options);
|
||||
return new Wallet(db, options);
|
||||
|
||||
EventEmitter.call(this);
|
||||
|
||||
assert(options, 'Options required.');
|
||||
assert(options.db, 'DB required.');
|
||||
assert(db, 'DB required.');
|
||||
|
||||
this.options = options;
|
||||
this.network = bcoin.network.get(options.network);
|
||||
this.db = options.db;
|
||||
this.db = db;
|
||||
this.network = db.network;
|
||||
this.locker = new bcoin.locker(this);
|
||||
|
||||
master = options.master;
|
||||
this.id = null;
|
||||
this.master = null;
|
||||
this.initialized = false;
|
||||
this.accountDepth = 0;
|
||||
|
||||
this.account = null;
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
}
|
||||
|
||||
utils.inherits(Wallet, EventEmitter);
|
||||
|
||||
Wallet.fromOptions = function fromOptions(db, options) {
|
||||
return new Wallet(db).fromOptions(options);
|
||||
};
|
||||
|
||||
Wallet.prototype.fromOptions = function fromOptions(options) {
|
||||
var master = options.master;
|
||||
|
||||
if (!master)
|
||||
master = bcoin.hd.fromMnemonic(null, this.network);
|
||||
@ -66,58 +80,47 @@ function Wallet(options) {
|
||||
if (!MasterKey.isMasterKey(master))
|
||||
master = MasterKey.fromKey(master);
|
||||
|
||||
this.id = options.id || null;
|
||||
this.master = master;
|
||||
this.initialized = options.initialized || false;
|
||||
this.accountDepth = options.accountDepth || 0;
|
||||
this.id = options.id || this.getID();
|
||||
|
||||
this.loaded = false;
|
||||
this.loading = false;
|
||||
this.account = null;
|
||||
return this;
|
||||
};
|
||||
|
||||
if (!this.id)
|
||||
this.id = this.getID();
|
||||
Wallet.prototype.init = function init(options, callback) {
|
||||
var self = this;
|
||||
|
||||
if (this.options.passphrase)
|
||||
this.master.encrypt(this.options.passphrase);
|
||||
}
|
||||
assert(!this.initialized);
|
||||
this.initialized = true;
|
||||
|
||||
utils.inherits(Wallet, EventEmitter);
|
||||
if (options.passphrase)
|
||||
this.master.encrypt(options.passphrase);
|
||||
|
||||
/**
|
||||
* Open the wallet, register with the database.
|
||||
* @param {Function} callback
|
||||
*/
|
||||
this.createAccount(options, function(err, account) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
assert(account);
|
||||
|
||||
self.account = account;
|
||||
|
||||
return callback();
|
||||
});
|
||||
};
|
||||
|
||||
Wallet.prototype.open = function open(callback) {
|
||||
var self = this;
|
||||
assert(this.initialized);
|
||||
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
if (this.loaded)
|
||||
return utils.nextTick(callback);
|
||||
|
||||
if (this.loading)
|
||||
return this.once('open', callback);
|
||||
|
||||
this.loading = true;
|
||||
|
||||
try {
|
||||
this.db.register(this);
|
||||
} catch (e) {
|
||||
this.emit('error', e);
|
||||
return callback(e);
|
||||
}
|
||||
|
||||
this.init(function(err) {
|
||||
if (err) {
|
||||
self.emit('error', err);
|
||||
this.getAccount(0, function(err, account) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
self.loading = false;
|
||||
self.loaded = true;
|
||||
self.emit('open');
|
||||
if (!account)
|
||||
return callback(new Error('Default account not found.'));
|
||||
|
||||
self.account = account;
|
||||
|
||||
return callback();
|
||||
});
|
||||
@ -129,15 +132,9 @@ Wallet.prototype.open = function open(callback) {
|
||||
* @param {Function} callback
|
||||
*/
|
||||
|
||||
Wallet.prototype.close =
|
||||
Wallet.prototype.destroy = function destroy(callback) {
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
if (!this.loaded)
|
||||
return utils.nextTick(callback);
|
||||
|
||||
assert(!this.loading);
|
||||
|
||||
this.master.destroy();
|
||||
|
||||
try {
|
||||
@ -147,8 +144,6 @@ Wallet.prototype.destroy = function destroy(callback) {
|
||||
return callback(e);
|
||||
}
|
||||
|
||||
this.loaded = false;
|
||||
|
||||
return utils.nextTick(callback);
|
||||
};
|
||||
|
||||
@ -160,33 +155,6 @@ Wallet.prototype.destroy = function destroy(callback) {
|
||||
* @param {Function} callback
|
||||
*/
|
||||
|
||||
Wallet.prototype.init = function init(callback) {
|
||||
var self = this;
|
||||
|
||||
function done(err, account) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!account)
|
||||
return callback(new Error('Account not found.'));
|
||||
|
||||
self.account = account;
|
||||
|
||||
return callback();
|
||||
}
|
||||
|
||||
this.db.open(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (self.initialized)
|
||||
return self.getAccount(0, done);
|
||||
|
||||
self.initialized = true;
|
||||
self.createAccount(self.options, done);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a public account key to the wallet (multisig).
|
||||
* Saves the key in the wallet database.
|
||||
@ -686,6 +654,34 @@ Wallet.prototype.deriveInputs = function deriveInputs(tx, callback) {
|
||||
});
|
||||
};
|
||||
|
||||
Wallet.prototype.getKeyring = function getKeyring(hash, callback) {
|
||||
var self = this;
|
||||
var address;
|
||||
|
||||
if (!hash)
|
||||
return callback();
|
||||
|
||||
this.getPath(hash, function(err, path) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!path)
|
||||
return callback();
|
||||
|
||||
self.getAccount(path.account, function(err, account) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!account)
|
||||
return callback();
|
||||
|
||||
address = account.deriveAddress(path.change, path.index);
|
||||
|
||||
return callback(null, address);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Map input addresses to paths.
|
||||
* @param {TX|Input} tx
|
||||
@ -1419,14 +1415,13 @@ Wallet.prototype.toJSON = function toJSON() {
|
||||
* @throws Error on bad decrypt
|
||||
*/
|
||||
|
||||
Wallet.parseJSON = function parseJSON(json) {
|
||||
return {
|
||||
network: json.network,
|
||||
id: json.id,
|
||||
initialized: json.initialized,
|
||||
accountDepth: json.accountDepth,
|
||||
master: MasterKey.fromJSON(json.master)
|
||||
};
|
||||
Wallet.prototype.fromJSON = function fromJSON(json) {
|
||||
this.network = bcoin.network.get(json.network);
|
||||
this.id = json.id;
|
||||
this.initialized = json.initialized;
|
||||
this.accountDepth = json.accountDepth;
|
||||
this.master = MasterKey.fromJSON(json.master);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1457,21 +1452,14 @@ Wallet.prototype.toRaw = function toRaw(writer) {
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
Wallet.parseRaw = function parseRaw(data) {
|
||||
Wallet.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = new BufferReader(data);
|
||||
var network = bcoin.network.fromMagic(p.readU32());
|
||||
var id = p.readVarString('utf8');
|
||||
var initialized = p.readU8() === 1;
|
||||
var accountDepth = p.readU32();
|
||||
var master = MasterKey.fromRaw(p.readVarBytes());
|
||||
|
||||
return {
|
||||
network: network.type,
|
||||
id: id,
|
||||
initialized: initialized,
|
||||
accountDepth: accountDepth,
|
||||
master: master
|
||||
};
|
||||
this.network = bcoin.network.fromMagic(p.readU32());
|
||||
this.id = p.readVarString('utf8');
|
||||
this.initialized = p.readU8() === 1;
|
||||
this.accountDepth = p.readU32();
|
||||
this.master = MasterKey.fromRaw(p.readVarBytes());
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1480,8 +1468,8 @@ Wallet.parseRaw = function parseRaw(data) {
|
||||
* @returns {Wallet}
|
||||
*/
|
||||
|
||||
Wallet.fromRaw = function fromRaw(data) {
|
||||
return new Wallet(Wallet.parseRaw(data));
|
||||
Wallet.fromRaw = function fromRaw(db, data) {
|
||||
return new Wallet(db).fromRaw(data);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1491,8 +1479,8 @@ Wallet.fromRaw = function fromRaw(data) {
|
||||
* @returns {Wallet}
|
||||
*/
|
||||
|
||||
Wallet.fromJSON = function fromJSON(json) {
|
||||
return new Wallet(Wallet.parseJSON(json));
|
||||
Wallet.fromJSON = function fromJSON(db, json) {
|
||||
return new Wallet(db).fromJSON(json);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1531,28 +1519,60 @@ Wallet.isWallet = function isWallet(obj) {
|
||||
* @param {String?} options.name - Account name
|
||||
*/
|
||||
|
||||
function Account(options) {
|
||||
function Account(db, options) {
|
||||
var i;
|
||||
|
||||
if (!(this instanceof Account))
|
||||
return new Account(options);
|
||||
return new Account(db, options);
|
||||
|
||||
EventEmitter.call(this);
|
||||
|
||||
assert(db, 'Database is required.');
|
||||
|
||||
this.db = db;
|
||||
this.network = db.network;
|
||||
this.lookahead = Account.LOOKAHEAD;
|
||||
this.cache = new bcoin.lru(20, 1);
|
||||
|
||||
this.loaded = false;
|
||||
this.loading = false;
|
||||
this.receiveAddress = null;
|
||||
this.changeAddress = null;
|
||||
|
||||
this.id = null;
|
||||
this.name = null;
|
||||
this.witness = false;
|
||||
this.accountKey = null;
|
||||
this.accountIndex = 0;
|
||||
this.receiveDepth = 0;
|
||||
this.changeDepth = 0;
|
||||
this.type = null;
|
||||
this.keys = [];
|
||||
this.m = 1;
|
||||
this.n = 1;
|
||||
this.initialized = false;
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
}
|
||||
|
||||
utils.inherits(Account, EventEmitter);
|
||||
|
||||
Account.fromOptions = function fromOptions(db, options) {
|
||||
return new Account(db).fromOptions(options);
|
||||
};
|
||||
|
||||
Account.prototype.fromOptions = function fromOptions(options) {
|
||||
assert(options, 'Options are required.');
|
||||
assert(options.db, 'Database is required.');
|
||||
assert(options.id, 'Wallet ID is required.');
|
||||
assert(options.accountKey, 'Account key is required.');
|
||||
assert(utils.isNumber(options.accountIndex), 'Account index is required.');
|
||||
|
||||
this.options = options;
|
||||
this.network = bcoin.network.get(options.network);
|
||||
this.db = options.db;
|
||||
this.lookahead = Account.LOOKAHEAD;
|
||||
|
||||
this.id = options.id;
|
||||
this.name = options.name;
|
||||
this.witness = options.witness || false;
|
||||
this.witness = options.witness != null
|
||||
? options.witness
|
||||
: this.network.witness;
|
||||
this.accountKey = options.accountKey;
|
||||
this.accountIndex = options.accountIndex;
|
||||
this.receiveDepth = options.receiveDepth || 0;
|
||||
@ -1563,13 +1583,6 @@ function Account(options) {
|
||||
this.n = options.n || 1;
|
||||
this.initialized = options.initialized || false;
|
||||
|
||||
this.loaded = false;
|
||||
this.loading = false;
|
||||
this.receiveAddress = null;
|
||||
this.changeAddress = null;
|
||||
|
||||
this.cache = new bcoin.lru(20, 1);
|
||||
|
||||
if (this.n > 1)
|
||||
this.type = 'multisig';
|
||||
|
||||
@ -1588,9 +1601,9 @@ function Account(options) {
|
||||
for (i = 0; i < options.keys.length; i++)
|
||||
this.pushKey(options.keys[i]);
|
||||
}
|
||||
}
|
||||
|
||||
utils.inherits(Account, EventEmitter);
|
||||
return this;
|
||||
};
|
||||
|
||||
/*
|
||||
* Default address lookahead.
|
||||
@ -1599,58 +1612,6 @@ utils.inherits(Account, EventEmitter);
|
||||
|
||||
Account.LOOKAHEAD = 5;
|
||||
|
||||
/**
|
||||
* Open the account, register with the database.
|
||||
* @param {Function} callback
|
||||
*/
|
||||
|
||||
Account.prototype.open = function open(callback) {
|
||||
var self = this;
|
||||
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
if (this.loaded)
|
||||
return utils.nextTick(callback);
|
||||
|
||||
if (this.loading)
|
||||
return this.once('open', callback);
|
||||
|
||||
this.loading = true;
|
||||
|
||||
this.init(function(err) {
|
||||
if (err) {
|
||||
self.emit('error', err);
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
self.loading = false;
|
||||
self.loaded = true;
|
||||
self.emit('open');
|
||||
|
||||
return callback();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Close the account, unregister with the database.
|
||||
* @method
|
||||
* @param {Function} callback
|
||||
*/
|
||||
|
||||
Account.prototype.close =
|
||||
Account.prototype.destroy = function destroy(callback) {
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
if (!this.loaded)
|
||||
return utils.nextTick(callback);
|
||||
|
||||
assert(!this.loading);
|
||||
|
||||
this.loaded = false;
|
||||
|
||||
return utils.nextTick(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Attempt to intialize the account (generating
|
||||
* the first addresses along with the lookahead
|
||||
@ -1666,12 +1627,6 @@ Account.prototype.init = function init(callback) {
|
||||
return this.save(callback);
|
||||
}
|
||||
|
||||
if (this.initialized) {
|
||||
this.receiveAddress = this.deriveReceive(this.receiveDepth - 1);
|
||||
this.changeAddress = this.deriveChange(this.changeDepth - 1);
|
||||
return callback();
|
||||
}
|
||||
|
||||
this.initialized = true;
|
||||
|
||||
assert(this.receiveDepth === 0);
|
||||
@ -1680,6 +1635,16 @@ Account.prototype.init = function init(callback) {
|
||||
this.setDepth(1, 1, callback);
|
||||
};
|
||||
|
||||
Account.prototype.open = function open(callback) {
|
||||
if (!this.initialized)
|
||||
return callback();
|
||||
|
||||
this.receiveAddress = this.deriveReceive(this.receiveDepth - 1);
|
||||
this.changeAddress = this.deriveChange(this.changeDepth - 1);
|
||||
|
||||
return callback();
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a public account key to the account (multisig).
|
||||
* Does not update the database.
|
||||
@ -1809,6 +1774,7 @@ Account.prototype.addKey = function addKey(key, callback) {
|
||||
error = e;
|
||||
}
|
||||
|
||||
// Try to initialize again.
|
||||
this.init(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
@ -2186,24 +2152,27 @@ Account.prototype.toJSON = function toJSON() {
|
||||
* @throws Error on bad decrypt
|
||||
*/
|
||||
|
||||
Account.parseJSON = function parseJSON(json) {
|
||||
return {
|
||||
network: json.network,
|
||||
id: json.id,
|
||||
name: json.name,
|
||||
initialized: json.initialized,
|
||||
type: json.type,
|
||||
m: json.m,
|
||||
n: json.n,
|
||||
witness: json.witness,
|
||||
accountIndex: json.accountIndex,
|
||||
receiveDepth: json.receiveDepth,
|
||||
changeDepth: json.changeDepth,
|
||||
accountKey: bcoin.hd.fromBase58(json.accountKey),
|
||||
keys: json.keys.map(function(key) {
|
||||
return bcoin.hd.fromBase58(key);
|
||||
})
|
||||
};
|
||||
Account.prototype.fromJSON = function fromJSON(json) {
|
||||
var i;
|
||||
|
||||
this.network = bcoin.network.get(json.network);
|
||||
this.id = json.id;
|
||||
this.name = json.name;
|
||||
this.initialized = json.initialized;
|
||||
this.type = json.type;
|
||||
this.m = json.m;
|
||||
this.n = json.n;
|
||||
this.witness = json.witness;
|
||||
this.accountIndex = json.accountIndex;
|
||||
this.receiveDepth = json.receiveDepth;
|
||||
this.changeDepth = json.changeDepth;
|
||||
this.accountKey = bcoin.hd.fromBase58(json.accountKey);
|
||||
this.keys = [];
|
||||
|
||||
for (i = 0; i < json.keys.length; i++)
|
||||
this.keys.push(bcoin.hd.fromBase58(key));
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2246,42 +2215,30 @@ Account.prototype.toRaw = function toRaw(writer) {
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
Account.parseRaw = function parseRaw(data) {
|
||||
Account.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = new BufferReader(data);
|
||||
var network = bcoin.network.fromMagic(p.readU32());
|
||||
var id = p.readVarString('utf8');
|
||||
var name = p.readVarString('utf8');
|
||||
var initialized = p.readU8() === 1;
|
||||
var type = p.readU8() === 0 ? 'pubkeyhash' : 'multisig';
|
||||
var m = p.readU8();
|
||||
var n = p.readU8();
|
||||
var witness = p.readU8() === 1;
|
||||
var accountIndex = p.readU32();
|
||||
var receiveDepth = p.readU32();
|
||||
var changeDepth = p.readU32();
|
||||
var accountKey = bcoin.hd.fromRaw(p.readBytes(82));
|
||||
var count = p.readU8();
|
||||
var keys = [];
|
||||
var i;
|
||||
var i, count;
|
||||
|
||||
this.network = bcoin.network.fromMagic(p.readU32());
|
||||
this.id = p.readVarString('utf8');
|
||||
this.name = p.readVarString('utf8');
|
||||
this.initialized = p.readU8() === 1;
|
||||
this.type = p.readU8() === 0 ? 'pubkeyhash' : 'multisig';
|
||||
this.m = p.readU8();
|
||||
this.n = p.readU8();
|
||||
this.witness = p.readU8() === 1;
|
||||
this.accountIndex = p.readU32();
|
||||
this.receiveDepth = p.readU32();
|
||||
this.changeDepth = p.readU32();
|
||||
this.accountKey = bcoin.hd.fromRaw(p.readBytes(82));
|
||||
this.keys = [];
|
||||
|
||||
count = p.readU8();
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
keys.push(bcoin.hd.fromRaw(p.readBytes(82)));
|
||||
this.keys.push(bcoin.hd.fromRaw(p.readBytes(82)));
|
||||
|
||||
return {
|
||||
network: network.type,
|
||||
id: id,
|
||||
name: name,
|
||||
initialized: initialized,
|
||||
type: type,
|
||||
m: m,
|
||||
n: n,
|
||||
witness: witness,
|
||||
accountIndex: accountIndex,
|
||||
receiveDepth: receiveDepth,
|
||||
changeDepth: changeDepth,
|
||||
accountKey: accountKey,
|
||||
keys: keys
|
||||
};
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2290,8 +2247,8 @@ Account.parseRaw = function parseRaw(data) {
|
||||
* @returns {Account}
|
||||
*/
|
||||
|
||||
Account.fromRaw = function fromRaw(data) {
|
||||
return new Account(Account.parseRaw(data));
|
||||
Account.fromRaw = function fromRaw(db, data) {
|
||||
return new Account(db).fromRaw(data);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2301,8 +2258,8 @@ Account.fromRaw = function fromRaw(data) {
|
||||
* @returns {Account}
|
||||
*/
|
||||
|
||||
Account.fromJSON = function fromJSON(json) {
|
||||
return new Account(Account.parseJSON(json));
|
||||
Account.fromJSON = function fromJSON(db, json) {
|
||||
return new Account(db).fromJSON(json);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -45,7 +45,7 @@ function WalletDB(options) {
|
||||
|
||||
EventEmitter.call(this);
|
||||
|
||||
this.watchers = [];
|
||||
this.watchers = {};
|
||||
this.options = options;
|
||||
this.loaded = false;
|
||||
this.network = bcoin.network.get(options.network);
|
||||
@ -249,19 +249,18 @@ WalletDB.prototype.destroy = function destroy(callback) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Register a wallet with the walletdb.
|
||||
* @param {WalletID} id
|
||||
* @param {Wallet} wallet
|
||||
* Register an object with the walletdb.
|
||||
* @param {Object} object
|
||||
*/
|
||||
|
||||
WalletDB.prototype.register = function register(wallet) {
|
||||
var id = wallet.id;
|
||||
WalletDB.prototype.register = function register(object) {
|
||||
var id = object.id;
|
||||
|
||||
if (!this.watchers[id])
|
||||
this.watchers[id] = { wallet: wallet, refs: 0 };
|
||||
this.watchers[id] = { object: object, refs: 0 };
|
||||
|
||||
// Should never happen, and if it does, I will cry.
|
||||
assert(this.watchers[id].wallet === wallet, 'I\'m crying.');
|
||||
assert(this.watchers[id].object === object, 'I\'m crying.');
|
||||
|
||||
// We do some reference counting here
|
||||
// because we're thug like that (police
|
||||
@ -270,27 +269,41 @@ WalletDB.prototype.register = function register(wallet) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Unregister a wallet with the walletdb.
|
||||
* @param {WalletID} id
|
||||
* @param {Wallet} wallet
|
||||
* Unregister a object with the walletdb.
|
||||
* @param {Object} object
|
||||
*/
|
||||
|
||||
WalletDB.prototype.unregister = function unregister(wallet) {
|
||||
var id = wallet.id;
|
||||
WalletDB.prototype.unregister = function unregister(object) {
|
||||
var id = object.id;
|
||||
var watcher = this.watchers[id];
|
||||
|
||||
if (!watcher)
|
||||
return;
|
||||
|
||||
assert(watcher.wallet === wallet);
|
||||
assert(watcher.refs !== 0, '`wallet.destroy()` called twice!');
|
||||
assert(watcher.object === object);
|
||||
assert(watcher.refs !== 0, '`destroy()` called twice!');
|
||||
|
||||
if (--watcher.refs === 0)
|
||||
delete this.watchers[id];
|
||||
};
|
||||
|
||||
/**
|
||||
* Fire an event for a registered wallet.
|
||||
* Watch an object (increment reference count).
|
||||
* @param {Object} object
|
||||
*/
|
||||
|
||||
WalletDB.prototype.watch = function watch(object) {
|
||||
var id = object.id;
|
||||
var watcher = this.watchers[id];
|
||||
|
||||
if (!watcher)
|
||||
return;
|
||||
|
||||
watcher.refs++;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fire an event for a registered object.
|
||||
* @param {WalletID} id
|
||||
* @param {...Object} args
|
||||
*/
|
||||
@ -307,11 +320,11 @@ WalletDB.prototype.fire = function fire(id) {
|
||||
for (i = 1; i < arguments.length; i++)
|
||||
args[i - 1] = arguments[i];
|
||||
|
||||
watcher.wallet.emit.apply(watcher.wallet, args);
|
||||
watcher.object.emit.apply(watcher.object, args);
|
||||
};
|
||||
|
||||
/**
|
||||
* Test for a listener on a registered wallet.
|
||||
* Test for a listener on a registered object.
|
||||
* @param {WalletID} id
|
||||
* @param {String} event
|
||||
* @returns {Boolean}
|
||||
@ -323,7 +336,7 @@ WalletDB.prototype.hasListener = function hasListener(id, event) {
|
||||
if (!watcher)
|
||||
return false;
|
||||
|
||||
if (watcher.wallet.listeners(event).length !== 0)
|
||||
if (watcher.object.listeners(event).length !== 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@ -337,14 +350,16 @@ WalletDB.prototype.hasListener = function hasListener(id, event) {
|
||||
|
||||
WalletDB.prototype.get = function get(id, callback) {
|
||||
var self = this;
|
||||
var wallet;
|
||||
var watcher, wallet;
|
||||
|
||||
if (!id)
|
||||
return callback();
|
||||
|
||||
if (this.watchers[id]) {
|
||||
this.watchers[id].refs++;
|
||||
return callback(null, this.watchers[id].wallet);
|
||||
watcher = this.watchers[id];
|
||||
|
||||
if (watcher) {
|
||||
watcher.refs++;
|
||||
return callback(null, watcher.object);
|
||||
}
|
||||
|
||||
this.db.get('w/' + id, function(err, data) {
|
||||
@ -355,9 +370,13 @@ WalletDB.prototype.get = function get(id, callback) {
|
||||
return callback();
|
||||
|
||||
try {
|
||||
data = bcoin.wallet.parseRaw(data);
|
||||
data.db = self;
|
||||
wallet = new bcoin.wallet(data);
|
||||
wallet = bcoin.wallet.fromRaw(self, data);
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
|
||||
try {
|
||||
self.register(wallet);
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
@ -371,33 +390,6 @@ WalletDB.prototype.get = function get(id, callback) {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Get raw wallet from the database, do not instantiate.
|
||||
* @param {WalletID} id
|
||||
* @param {Function} callback - Returns [Error, {@link Wallet}].
|
||||
*/
|
||||
|
||||
WalletDB.prototype.getRaw = function getRaw(id, callback) {
|
||||
if (!id)
|
||||
return callback();
|
||||
|
||||
this.db.get('w/' + id, function(err, data) {
|
||||
if (err && err.type !== 'NotFoundError')
|
||||
return callback();
|
||||
|
||||
if (!data)
|
||||
return callback();
|
||||
|
||||
try {
|
||||
data = bcoin.wallet.parseRaw(data);
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
|
||||
return callback(null, data);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Save a wallet to the database.
|
||||
* @param {Wallet} wallet
|
||||
@ -436,13 +428,19 @@ WalletDB.prototype.create = function create(options, callback) {
|
||||
if (exists)
|
||||
return callback(new Error('Wallet already exists.'));
|
||||
|
||||
options = utils.merge({}, options);
|
||||
try {
|
||||
wallet = bcoin.wallet.fromOptions(self, options);
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
|
||||
options.network = self.network;
|
||||
options.db = self;
|
||||
wallet = new bcoin.wallet(options);
|
||||
try {
|
||||
self.register(wallet);
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
|
||||
wallet.open(function(err) {
|
||||
wallet.init(options, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
@ -510,9 +508,7 @@ WalletDB.prototype.getAccount = function getAccount(id, name, callback) {
|
||||
return callback();
|
||||
|
||||
try {
|
||||
data = bcoin.account.parseRaw(data);
|
||||
data.db = self;
|
||||
account = new bcoin.account(data);
|
||||
account = bcoin.account.fromRaw(self, data);
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
@ -620,16 +616,9 @@ WalletDB.prototype.createAccount = function createAccount(options, callback) {
|
||||
if (exists)
|
||||
return callback(new Error('Account already exists.'));
|
||||
|
||||
options = utils.merge({}, options);
|
||||
account = bcoin.account.fromOptions(self, options);
|
||||
|
||||
if (self.network.witness)
|
||||
options.witness = options.witness !== false;
|
||||
|
||||
options.network = self.network;
|
||||
options.db = self;
|
||||
account = new bcoin.account(options);
|
||||
|
||||
account.open(function(err) {
|
||||
account.init(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user