walletdb: remove global methods. in-memory balance.
This commit is contained in:
parent
9a1ba962fd
commit
1e98ce25d9
@ -298,7 +298,7 @@ Fullnode.prototype._open = function open(callback) {
|
|||||||
},
|
},
|
||||||
function(next) {
|
function(next) {
|
||||||
if (self.options.noScan) {
|
if (self.options.noScan) {
|
||||||
self.walletdb.writeTip(self.chain.tip.hash, next);
|
self.walletdb.setTip(self.chain.tip.hash, 0, next);
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
// Always rescan to make sure we didn't miss anything:
|
// Always rescan to make sure we didn't miss anything:
|
||||||
|
|||||||
@ -48,12 +48,39 @@ function TXDB(wallet) {
|
|||||||
this.logger = wallet.db.logger;
|
this.logger = wallet.db.logger;
|
||||||
this.network = wallet.db.network;
|
this.network = wallet.db.network;
|
||||||
this.options = wallet.db.options;
|
this.options = wallet.db.options;
|
||||||
|
|
||||||
this.locker = new bcoin.locker(this);
|
this.locker = new bcoin.locker(this);
|
||||||
this.current = null;
|
|
||||||
this.coinCache = new bcoin.lru(10000, 1);
|
this.coinCache = new bcoin.lru(10000, 1);
|
||||||
this.balance = new Balance();
|
|
||||||
|
this.current = null;
|
||||||
|
this.balance = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open TXDB.
|
||||||
|
* @param {Function} callback
|
||||||
|
*/
|
||||||
|
|
||||||
|
TXDB.prototype.open = function open(callback) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.getBalance(function(err, balance) {
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
|
||||||
|
self.logger.info('TXDB loaded for %s.', self.wallet.id);
|
||||||
|
self.logger.info(
|
||||||
|
'Balance: unconfirmed=%s confirmed=%s total=%s.',
|
||||||
|
utils.btc(balance.unconfirmed),
|
||||||
|
utils.btc(balance.confirmed),
|
||||||
|
utils.btc(balance.total));
|
||||||
|
|
||||||
|
self.balance = balance;
|
||||||
|
|
||||||
|
return callback();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compile wallet prefix.
|
* Compile wallet prefix.
|
||||||
* @param {String} key
|
* @param {String} key
|
||||||
@ -1086,11 +1113,11 @@ TXDB.prototype.getHistoryHashes = function getHistoryHashes(account, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.iterate({
|
this.iterate({
|
||||||
gte: account ? 'T/' + account + '/' : 't',
|
gte: account != null ? 'T/' + account + '/' : 't',
|
||||||
lte: account ? 'T/' + account + '/~' : 't~',
|
lte: account != null ? 'T/' + account + '/~' : 't~',
|
||||||
transform: function(key) {
|
transform: function(key) {
|
||||||
key = key.split('/');
|
key = key.split('/');
|
||||||
if (account)
|
if (account != null)
|
||||||
return key[4];
|
return key[4];
|
||||||
return key[3];
|
return key[3];
|
||||||
}
|
}
|
||||||
@ -1110,11 +1137,11 @@ TXDB.prototype.getUnconfirmedHashes = function getUnconfirmedHashes(account, cal
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.iterate({
|
this.iterate({
|
||||||
gte: account ? 'P/' + account + '/' : 'p',
|
gte: account != null ? 'P/' + account + '/' : 'p',
|
||||||
lte: account ? 'P/' + account + '/~' : 'p~',
|
lte: account != null ? 'P/' + account + '/~' : 'p~',
|
||||||
transform: function(key) {
|
transform: function(key) {
|
||||||
key = key.split('/');
|
key = key.split('/');
|
||||||
if (account)
|
if (account != null)
|
||||||
return key[4];
|
return key[4];
|
||||||
return key[3];
|
return key[3];
|
||||||
}
|
}
|
||||||
@ -1134,11 +1161,11 @@ TXDB.prototype.getCoinHashes = function getCoinHashes(account, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.iterate({
|
this.iterate({
|
||||||
gte: account ? 'C/' + account + '/' : 'c',
|
gte: account != null ? 'C/' + account + '/' : 'c',
|
||||||
lte: account ? 'C/' + account + '/~' : 'c~',
|
lte: account != null ? 'C/' + account + '/~' : 'c~',
|
||||||
transform: function(key) {
|
transform: function(key) {
|
||||||
key = key.split('/');
|
key = key.split('/');
|
||||||
if (account)
|
if (account != null)
|
||||||
return [key[4], +key[5]];
|
return [key[4], +key[5]];
|
||||||
return [key[3], +key[4]];
|
return [key[3], +key[4]];
|
||||||
}
|
}
|
||||||
@ -1157,24 +1184,24 @@ TXDB.prototype.getCoinHashes = function getCoinHashes(account, callback) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
TXDB.prototype.getHeightRangeHashes = function getHeightRangeHashes(account, options, callback) {
|
TXDB.prototype.getHeightRangeHashes = function getHeightRangeHashes(account, options, callback) {
|
||||||
if (typeof account !== 'string') {
|
if (typeof account !== 'number') {
|
||||||
callback = options;
|
callback = options;
|
||||||
options = account;
|
options = account;
|
||||||
account = null;
|
account = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.iterate({
|
this.iterate({
|
||||||
gte: account
|
gte: account != null
|
||||||
? 'H/' + account + '/' + pad32(options.start) + '/'
|
? 'H/' + account + '/' + pad32(options.start) + '/'
|
||||||
: 'h/' + pad32(options.start) + '/',
|
: 'h/' + pad32(options.start) + '/',
|
||||||
lte: account
|
lte: account != null
|
||||||
? 'H/' + account + '/' + pad32(options.end) + '/~'
|
? 'H/' + account + '/' + pad32(options.end) + '/~'
|
||||||
: 'h/' + pad32(options.end) + '/~',
|
: 'h/' + pad32(options.end) + '/~',
|
||||||
limit: options.limit,
|
limit: options.limit,
|
||||||
reverse: options.reverse,
|
reverse: options.reverse,
|
||||||
transform: function(key) {
|
transform: function(key) {
|
||||||
key = key.split('/');
|
key = key.split('/');
|
||||||
if (account)
|
if (account != null)
|
||||||
return key[4];
|
return key[4];
|
||||||
return key[3];
|
return key[3];
|
||||||
}
|
}
|
||||||
@ -1209,17 +1236,17 @@ TXDB.prototype.getRangeHashes = function getRangeHashes(account, options, callba
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.iterate({
|
this.iterate({
|
||||||
gte: account
|
gte: account != null
|
||||||
? 'M/' + account + '/' + pad32(options.start) + '/'
|
? 'M/' + account + '/' + pad32(options.start) + '/'
|
||||||
: 'm/' + pad32(options.start) + '/',
|
: 'm/' + pad32(options.start) + '/',
|
||||||
lte: account
|
lte: account != null
|
||||||
? 'M/' + account + '/' + pad32(options.end) + '/~'
|
? 'M/' + account + '/' + pad32(options.end) + '/~'
|
||||||
: 'm/' + pad32(options.end) + '/~',
|
: 'm/' + pad32(options.end) + '/~',
|
||||||
limit: options.limit,
|
limit: options.limit,
|
||||||
reverse: options.reverse,
|
reverse: options.reverse,
|
||||||
transform: function(key) {
|
transform: function(key) {
|
||||||
key = key.split('/');
|
key = key.split('/');
|
||||||
if (account)
|
if (account != null)
|
||||||
return key[4];
|
return key[4];
|
||||||
return key[3];
|
return key[3];
|
||||||
}
|
}
|
||||||
@ -1237,7 +1264,7 @@ TXDB.prototype.getRangeHashes = function getRangeHashes(account, options, callba
|
|||||||
* @param {Function} callback - Returns [Error, {@link TX}[]].
|
* @param {Function} callback - Returns [Error, {@link TX}[]].
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXDB.prototype.getRange = function getLast(account, options, callback) {
|
TXDB.prototype.getRange = function getRange(account, options, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var txs = [];
|
var txs = [];
|
||||||
|
|
||||||
@ -1308,6 +1335,36 @@ TXDB.prototype.getHistory = function getHistory(account, callback) {
|
|||||||
account = null;
|
account = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Slow case
|
||||||
|
if (account != null)
|
||||||
|
return this.getAccountHistory(account, callback);
|
||||||
|
|
||||||
|
// Fast case
|
||||||
|
this.iterate({
|
||||||
|
gte: 't',
|
||||||
|
lte: 't~',
|
||||||
|
values: true,
|
||||||
|
parse: function(data) {
|
||||||
|
return bcoin.tx.fromExtended(data);
|
||||||
|
}
|
||||||
|
}, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all account transactions.
|
||||||
|
* @param {Number?} account
|
||||||
|
* @param {Function} callback - Returns [Error, {@link TX}[]].
|
||||||
|
*/
|
||||||
|
|
||||||
|
TXDB.prototype.getAccountHistory = function getAccountHistory(account, callback) {
|
||||||
|
var self = this;
|
||||||
|
var txs = [];
|
||||||
|
|
||||||
|
if (typeof account === 'function') {
|
||||||
|
callback = account;
|
||||||
|
account = null;
|
||||||
|
}
|
||||||
|
|
||||||
this.getHistoryHashes(account, function(err, hashes) {
|
this.getHistoryHashes(account, function(err, hashes) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
@ -1423,7 +1480,7 @@ TXDB.prototype.getCoins = function getCoins(account, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Slow case
|
// Slow case
|
||||||
if (account)
|
if (account != null)
|
||||||
return this.getAccountCoins(account, callback);
|
return this.getAccountCoins(account, callback);
|
||||||
|
|
||||||
// Fast case
|
// Fast case
|
||||||
@ -1623,7 +1680,7 @@ TXDB.prototype.toDetails = function toDetails(tx, callback) {
|
|||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
if (!info)
|
if (!info)
|
||||||
return callback();
|
return callback(new Error('Info not found.'));
|
||||||
|
|
||||||
return callback(null, info.toDetails());
|
return callback(null, info.toDetails());
|
||||||
});
|
});
|
||||||
@ -1695,7 +1752,7 @@ TXDB.prototype.hasCoin = function hasCoin(hash, index, callback) {
|
|||||||
|
|
||||||
TXDB.prototype.getBalance = function getBalance(account, callback) {
|
TXDB.prototype.getBalance = function getBalance(account, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var balance = new Balance(this.wallet.id);
|
var balance;
|
||||||
|
|
||||||
if (typeof account === 'function') {
|
if (typeof account === 'function') {
|
||||||
callback = account;
|
callback = account;
|
||||||
@ -1703,10 +1760,16 @@ TXDB.prototype.getBalance = function getBalance(account, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Slow case
|
// Slow case
|
||||||
if (account)
|
if (account != null)
|
||||||
return this.getAccountBalance(account, callback);
|
return this.getAccountBalance(account, callback);
|
||||||
|
|
||||||
|
// Really fast case
|
||||||
|
if (this.balance)
|
||||||
|
return callback(null, this.balance);
|
||||||
|
|
||||||
// Fast case
|
// Fast case
|
||||||
|
balance = new Balance(this.wallet.id);
|
||||||
|
|
||||||
this.iterate({
|
this.iterate({
|
||||||
gte: 'c',
|
gte: 'c',
|
||||||
lte: 'c~',
|
lte: 'c~',
|
||||||
@ -1832,7 +1895,7 @@ TXDB.prototype.zap = function zap(account, age, callback, force) {
|
|||||||
|
|
||||||
callback = utils.wrap(callback, unlock);
|
callback = utils.wrap(callback, unlock);
|
||||||
|
|
||||||
if (!utils.isNumber(age))
|
if (!utils.isUInt32(age))
|
||||||
return callback(new Error('Age must be a number.'));
|
return callback(new Error('Age must be a number.'));
|
||||||
|
|
||||||
this.getRange(account, {
|
this.getRange(account, {
|
||||||
@ -1863,7 +1926,7 @@ TXDB.prototype.abandon = function abandon(hash, callback, force) {
|
|||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
return callback(new Error('TX not found.'));
|
return callback(new Error('TX not eligible.'));
|
||||||
|
|
||||||
self.remove(hash, callback, force);
|
self.remove(hash, callback, force);
|
||||||
});
|
});
|
||||||
@ -2016,6 +2079,14 @@ Balance.prototype.toJSON = function toJSON() {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Balance.prototype.toString = function toString() {
|
||||||
|
return '<Balance'
|
||||||
|
+ ' unconfirmed=' + utils.btc(this.unconfirmed)
|
||||||
|
+ ' confirmed=' + utils.btc(this.confirmed)
|
||||||
|
+ ' total=' + utils.btc(this.total)
|
||||||
|
+ '>';
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helpers
|
* Helpers
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -170,7 +170,7 @@ Wallet.prototype.init = function init(options, callback) {
|
|||||||
|
|
||||||
self.account = account;
|
self.account = account;
|
||||||
|
|
||||||
return callback();
|
self.tx.open(callback);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -194,7 +194,7 @@ Wallet.prototype.open = function open(callback) {
|
|||||||
|
|
||||||
self.account = account;
|
self.account = account;
|
||||||
|
|
||||||
return callback();
|
self.tx.open(callback);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -207,8 +207,8 @@ Wallet.prototype.destroy = function destroy(callback) {
|
|||||||
callback = utils.ensure(callback);
|
callback = utils.ensure(callback);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (this.db.unregister(this))
|
this.db.unregister(this);
|
||||||
this.master.destroy();
|
this.master.destroy();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.emit('error', e);
|
this.emit('error', e);
|
||||||
return callback(e);
|
return callback(e);
|
||||||
@ -792,7 +792,7 @@ Wallet.prototype.fund = function fund(tx, options, callback, force) {
|
|||||||
fee: options.fee,
|
fee: options.fee,
|
||||||
subtractFee: options.subtractFee,
|
subtractFee: options.subtractFee,
|
||||||
changeAddress: account.changeAddress.getAddress(),
|
changeAddress: account.changeAddress.getAddress(),
|
||||||
height: self.network.height,
|
height: self.db.height,
|
||||||
rate: rate,
|
rate: rate,
|
||||||
wallet: self,
|
wallet: self,
|
||||||
m: self.m,
|
m: self.m,
|
||||||
@ -850,12 +850,12 @@ Wallet.prototype.createTX = function createTX(options, callback, force) {
|
|||||||
// if (options.locktime != null)
|
// if (options.locktime != null)
|
||||||
// tx.setLocktime(options.locktime);
|
// tx.setLocktime(options.locktime);
|
||||||
// else
|
// else
|
||||||
// tx.avoidFeeSniping(options.height);
|
// tx.avoidFeeSniping(self.db.height);
|
||||||
|
|
||||||
if (!tx.isSane())
|
if (!tx.isSane())
|
||||||
return callback(new Error('CheckTransaction failed.'));
|
return callback(new Error('CheckTransaction failed.'));
|
||||||
|
|
||||||
if (!tx.checkInputs(options.height))
|
if (!tx.checkInputs(self.db.height))
|
||||||
return callback(new Error('CheckInputs failed.'));
|
return callback(new Error('CheckInputs failed.'));
|
||||||
|
|
||||||
self.scriptInputs(tx, function(err, total) {
|
self.scriptInputs(tx, function(err, total) {
|
||||||
|
|||||||
@ -52,9 +52,12 @@ function WalletDB(options) {
|
|||||||
this.fees = options.fees;
|
this.fees = options.fees;
|
||||||
this.logger = options.logger || bcoin.defaultLogger;
|
this.logger = options.logger || bcoin.defaultLogger;
|
||||||
this.batches = {};
|
this.batches = {};
|
||||||
this.watchers = {};
|
this.wallets = {};
|
||||||
this.workerPool = null;
|
this.workerPool = null;
|
||||||
|
|
||||||
|
this.tip = this.network.genesis.hash;
|
||||||
|
this.height = 0;
|
||||||
|
|
||||||
// We need one read lock for `get` and `create`.
|
// We need one read lock for `get` and `create`.
|
||||||
// It will hold locks specific to wallet ids.
|
// It will hold locks specific to wallet ids.
|
||||||
this.readLock = new ReadLock(this);
|
this.readLock = new ReadLock(this);
|
||||||
@ -140,13 +143,12 @@ WalletDB.prototype._open = function open(callback) {
|
|||||||
|
|
||||||
WalletDB.prototype._close = function close(callback) {
|
WalletDB.prototype._close = function close(callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var keys = Object.keys(this.watchers);
|
var keys = Object.keys(this.wallets);
|
||||||
var watcher;
|
var wallet;
|
||||||
|
|
||||||
utils.forEachSerial(keys, function(key, next) {
|
utils.forEachSerial(keys, function(key, next) {
|
||||||
watcher = self.watchers[key];
|
wallet = self.wallets[key];
|
||||||
watcher.refs = 1;
|
wallet.destroy(next);
|
||||||
watcher.object.destroy(next);
|
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
@ -286,19 +288,9 @@ WalletDB.prototype.dump = function dump(callback) {
|
|||||||
* @param {Object} object
|
* @param {Object} object
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype.register = function register(object) {
|
WalletDB.prototype.register = function register(wallet) {
|
||||||
var id = object.id;
|
assert(!this.wallets[wallet.id]);
|
||||||
|
this.wallets[wallet.id] = wallet;
|
||||||
if (!this.watchers[id])
|
|
||||||
this.watchers[id] = { object: object, refs: 0 };
|
|
||||||
|
|
||||||
// Should never happen, and if it does, I will cry.
|
|
||||||
assert(this.watchers[id].object === object, 'I\'m crying.');
|
|
||||||
|
|
||||||
// We do some reference counting here
|
|
||||||
// because we're thug like that (police
|
|
||||||
// have a fit when your papers legit).
|
|
||||||
this.watchers[id].refs++;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -307,25 +299,9 @@ WalletDB.prototype.register = function register(object) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype.unregister = function unregister(object) {
|
WalletDB.prototype.unregister = function unregister(wallet) {
|
||||||
var id = object.id;
|
assert(this.wallets[wallet.id]);
|
||||||
var watcher = this.watchers[id];
|
delete this.wallets[wallet.id];
|
||||||
|
|
||||||
// NOP for now!
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!watcher)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
assert(watcher.object === object);
|
|
||||||
assert(watcher.refs !== 0, '`destroy()` called twice!');
|
|
||||||
|
|
||||||
if (--watcher.refs === 0) {
|
|
||||||
delete this.watchers[id];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -336,7 +312,7 @@ WalletDB.prototype.unregister = function unregister(object) {
|
|||||||
|
|
||||||
WalletDB.prototype.get = function get(id, callback) {
|
WalletDB.prototype.get = function get(id, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var unlock, watcher;
|
var unlock, wallet;
|
||||||
|
|
||||||
unlock = this._lock(id, get, [id, callback]);
|
unlock = this._lock(id, get, [id, callback]);
|
||||||
|
|
||||||
@ -348,12 +324,10 @@ WalletDB.prototype.get = function get(id, callback) {
|
|||||||
if (!id)
|
if (!id)
|
||||||
return callback();
|
return callback();
|
||||||
|
|
||||||
watcher = this.watchers[id];
|
wallet = this.wallets[id];
|
||||||
|
|
||||||
if (watcher) {
|
if (wallet)
|
||||||
watcher.refs++;
|
return callback(null, wallet);
|
||||||
return callback(null, watcher.object);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._get(id, function(err, wallet) {
|
this._get(id, function(err, wallet) {
|
||||||
if (err)
|
if (err)
|
||||||
@ -521,7 +495,7 @@ WalletDB.prototype.has = function has(id, callback) {
|
|||||||
if (!id)
|
if (!id)
|
||||||
return callback(null, false);
|
return callback(null, false);
|
||||||
|
|
||||||
if (this.watchers[id])
|
if (this.wallets[id])
|
||||||
return callback(null, true);
|
return callback(null, true);
|
||||||
|
|
||||||
if (this.walletCache.has(id))
|
if (this.walletCache.has(id))
|
||||||
@ -948,7 +922,7 @@ WalletDB.prototype.getWallets = function getWallets(callback) {
|
|||||||
|
|
||||||
WalletDB.prototype.rescan = function rescan(chaindb, callback) {
|
WalletDB.prototype.rescan = function rescan(chaindb, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
this.getTip(function(err, hash) {
|
this.getTip(function(err, hash, height) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
@ -965,7 +939,7 @@ WalletDB.prototype.rescan = function rescan(chaindb, callback) {
|
|||||||
self.addTX(tx, function(err) {
|
self.addTX(tx, function(err) {
|
||||||
if (err)
|
if (err)
|
||||||
return next(err);
|
return next(err);
|
||||||
self.writeTip(block.hash, next);
|
self.setTip(block.hash, block.height, next);
|
||||||
});
|
});
|
||||||
}, callback);
|
}, callback);
|
||||||
});
|
});
|
||||||
@ -989,9 +963,6 @@ WalletDB.prototype.fetchWallet = function fetchWallet(id, callback, handler) {
|
|||||||
return callback(new Error('No wallet.'));
|
return callback(new Error('No wallet.'));
|
||||||
|
|
||||||
handler(wallet, function(err, res1, res2) {
|
handler(wallet, function(err, res1, res2) {
|
||||||
// Kill the reference.
|
|
||||||
// wallet.destroy();
|
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
@ -1102,18 +1073,18 @@ WalletDB.prototype.getTable = function getTable(address, callback) {
|
|||||||
|
|
||||||
WalletDB.prototype.writeGenesis = function writeGenesis(callback) {
|
WalletDB.prototype.writeGenesis = function writeGenesis(callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var hash;
|
|
||||||
|
|
||||||
this.db.has('R', function(err, result) {
|
this.getTip(function(err, hash, height) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
if (result)
|
if (hash) {
|
||||||
|
self.tip = hash;
|
||||||
|
self.height = height;
|
||||||
return callback();
|
return callback();
|
||||||
|
}
|
||||||
|
|
||||||
hash = new Buffer(self.network.genesis.hash, 'hex');
|
self.setTip(self.tip, self.height, callback);
|
||||||
|
|
||||||
self.db.put('R', hash, callback);
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1124,8 +1095,17 @@ WalletDB.prototype.writeGenesis = function writeGenesis(callback) {
|
|||||||
|
|
||||||
WalletDB.prototype.getTip = function getTip(callback) {
|
WalletDB.prototype.getTip = function getTip(callback) {
|
||||||
this.db.fetch('R', function(data) {
|
this.db.fetch('R', function(data) {
|
||||||
return data.toString('hex');
|
var p = new BufferReader(data);
|
||||||
}, callback);
|
return [p.readHash('hex'), p.readU32()];
|
||||||
|
}, function(err, items) {
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
|
||||||
|
if (!items)
|
||||||
|
return callback(null, null, -1);
|
||||||
|
|
||||||
|
return callback(null, items[0], items[1]);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1134,10 +1114,22 @@ WalletDB.prototype.getTip = function getTip(callback) {
|
|||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype.writeTip = function writeTip(hash, callback) {
|
WalletDB.prototype.setTip = function setTip(hash, height, callback) {
|
||||||
if (typeof hash === 'string')
|
var self = this;
|
||||||
hash = new Buffer(hash, 'hex');
|
var p = new BufferWriter();
|
||||||
this.db.put('R', hash, callback);
|
|
||||||
|
p.writeHash(hash);
|
||||||
|
p.writeU32(height);
|
||||||
|
|
||||||
|
this.db.put('R', p.render(), function(err) {
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
|
||||||
|
self.tip = hash;
|
||||||
|
self.height = height;
|
||||||
|
|
||||||
|
return callback();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1159,7 +1151,7 @@ WalletDB.prototype.addBlock = function addBlock(block, txs, callback, force) {
|
|||||||
|
|
||||||
if (this.options.useCheckpoints) {
|
if (this.options.useCheckpoints) {
|
||||||
if (block.height < this.network.checkpoints.lastHeight)
|
if (block.height < this.network.checkpoints.lastHeight)
|
||||||
return this.writeTip(block.hash, callback);
|
return this.setTip(block.hash, block.height, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Array.isArray(txs))
|
if (!Array.isArray(txs))
|
||||||
@ -1171,7 +1163,7 @@ WalletDB.prototype.addBlock = function addBlock(block, txs, callback, force) {
|
|||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
self.writeTip(block.hash, callback);
|
self.setTip(block.hash, block.height, callback);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1217,7 +1209,7 @@ WalletDB.prototype.removeBlock = function removeBlock(block, callback, force) {
|
|||||||
}, function(err) {
|
}, function(err) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
self.writeTip(block.prevBlock, callback);
|
self.setTip(block.prevBlock, block.height - 1, callback);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -1283,300 +1275,6 @@ WalletDB.prototype.getPath = function getPath(id, address, callback) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @see {@link TXDB#toDetails}.
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype.toDetails = function toDetails(id, tx, callback) {
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.tx.toDetails(tx, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see {@link TXDB#getTX}.
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype.getTX = function getTX(id, hash, callback) {
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.tx.getTX(hash, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see {@link TXDB#getCoin}.
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype.getCoin = function getCoin(id, hash, index, callback) {
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.tx.getCoin(hash, index, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see {@link TXDB#getHistory}.
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype.getHistory = function getHistory(id, account, callback) {
|
|
||||||
if (typeof account === 'function') {
|
|
||||||
callback = account;
|
|
||||||
account = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.tx.getHistory(account, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see {@link TXDB#getCoins}.
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype.getCoins = function getCoins(id, account, callback) {
|
|
||||||
if (typeof account === 'function') {
|
|
||||||
callback = account;
|
|
||||||
account = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.tx.getCoins(account, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see {@link TXDB#getUnconfirmed}.
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype.getUnconfirmed = function getUnconfirmed(id, account, callback) {
|
|
||||||
if (typeof account === 'function') {
|
|
||||||
callback = account;
|
|
||||||
account = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.tx.getUnconfirmed(account, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see {@link TXDB#getBalance}.
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype.getBalance = function getBalance(id, account, callback) {
|
|
||||||
if (typeof account === 'function') {
|
|
||||||
callback = account;
|
|
||||||
account = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.tx.getBalance(account, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see {@link TXDB#getLastTime}.
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype.getLastTime = function getLastTime(id, account, callback) {
|
|
||||||
if (typeof account === 'function') {
|
|
||||||
callback = account;
|
|
||||||
account = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.tx.getLastTime(account, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see {@link TXDB#getLast}.
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype.getLast = function getLast(id, account, limit, callback) {
|
|
||||||
if (typeof limit === 'function') {
|
|
||||||
callback = limit;
|
|
||||||
limit = account;
|
|
||||||
account = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.tx.getLast(account, limit, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
WalletDB.prototype.getTimeRange = function getTimeRange(id, account, options, callback) {
|
|
||||||
if (typeof options === 'function') {
|
|
||||||
callback = options;
|
|
||||||
options = account;
|
|
||||||
account = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.tx.getTimeRange(account, options, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see {@link TXDB#getRange}.
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype.getRange = function getRange(id, account, options, callback) {
|
|
||||||
if (typeof options === 'function') {
|
|
||||||
callback = options;
|
|
||||||
options = account;
|
|
||||||
account = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.tx.getRange(account, options, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see {@link TXDB#fillHistory}.
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype.fillHistory = function fillHistory(id, tx, callback) {
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.tx.fillHistory(tx, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see {@link TXDB#fillCoins}.
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype.fillCoins = function fillCoins(id, tx, callback) {
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.tx.fillCoins(tx, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Zap all walletdb transactions.
|
|
||||||
* @see {@link TXDB#zap}.
|
|
||||||
*/
|
|
||||||
|
|
||||||
WalletDB.prototype.zap = function zap(id, account, age, callback) {
|
|
||||||
if (typeof age === 'function') {
|
|
||||||
callback = age;
|
|
||||||
age = account;
|
|
||||||
account = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.tx.zap(account, age, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
WalletDB.prototype.createAddress = function createAddress(id, name, change, callback) {
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.createAddress(name, change, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
WalletDB.prototype.fund = function fund(id, tx, options, callback) {
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.fund(tx, options, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
WalletDB.prototype.scriptInputs = function scriptInputs(id, tx, callback) {
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.scriptInputs(tx, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
WalletDB.prototype.sign = function sign(id, tx, options, callback) {
|
|
||||||
if (typeof options === 'function') {
|
|
||||||
callback = options;
|
|
||||||
options = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.sign(tx, options, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
WalletDB.prototype.createTX = function createTX(id, options, callback) {
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.createTX(options, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
WalletDB.prototype.send = function send(id, options, callback) {
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.send(options, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
WalletDB.prototype.addKey = function addKey(id, name, key, callback) {
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.addKey(name, key, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
WalletDB.prototype.removeKey = function removeKey(id, name, key, callback) {
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.removeKey(name, key, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
WalletDB.prototype.setPassphrase = function setPassphrase(id, old, new_, callback) {
|
|
||||||
if (typeof new_ === 'function') {
|
|
||||||
callback = new_;
|
|
||||||
new_ = old;
|
|
||||||
old = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.setPassphrase(old, new_, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
WalletDB.prototype.retoken = function retoken(id, passphrase, callback) {
|
|
||||||
if (typeof passphrase === 'function') {
|
|
||||||
callback = passphrase;
|
|
||||||
passphrase = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.retoken(passphrase, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
WalletDB.prototype.getInfo = function getInfo(id, callback) {
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
callback(null, wallet);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
WalletDB.prototype.ensureAccount = function ensureAccount(id, options, callback) {
|
|
||||||
var self = this;
|
|
||||||
var account = options.account;
|
|
||||||
|
|
||||||
if (typeof options.name === 'string')
|
|
||||||
account = options.name;
|
|
||||||
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.hasAccount(account, function(err, exists) {
|
|
||||||
if (err)
|
|
||||||
return callback(err);
|
|
||||||
|
|
||||||
if (exists)
|
|
||||||
return wallet.getAccount(account, callback);
|
|
||||||
|
|
||||||
wallet.createAccount(options, callback);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
WalletDB.prototype.getRedeem = function getRedeem(id, hash, callback) {
|
|
||||||
this.fetchWallet(id, callback, function(wallet, callback) {
|
|
||||||
wallet.getRedeem(hash, callback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Path
|
* Path
|
||||||
* @constructor
|
* @constructor
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user