events. http wallet.

This commit is contained in:
Christopher Jeffrey 2016-06-02 06:19:47 -07:00
parent 2f492dfc89
commit 5b1ce02324
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
8 changed files with 411 additions and 273 deletions

View File

@ -76,6 +76,27 @@ function addKey(callback) {
});
}
function createAccount(callback) {
var id = getID();
var account = argv.args[0] || argv.account;
client.createWalletAccount(id, account, function(err, account) {
if (err)
return callback(err);
utils.print(account);
callback();
});
}
function getAccounts(callback) {
var id = getID();
client.getWalletAccounts(id, function(err, accounts) {
if (err)
return callback(err);
utils.print(accounts);
callback();
});
}
function removeKey(callback) {
var id = getID();
var keys = argv.keys || argv.key;
@ -290,6 +311,10 @@ function main(callback) {
return getCoin(callback);
case 'block':
return getBlock(callback);
case 'account':
return createAccount(callback);
case 'accounts':
return getAccounts(callback);
default:
utils.print('Unrecognized command.');
utils.print('Commands:');

View File

@ -102,6 +102,16 @@ HTTPClient.prototype._init = function _init() {
}, id);
});
self.socket.on('address', function(receive, change, map) {
receive = receive.map(function(address) {
return bcoin.keyring.fromJSON(address);
});
change = change.map(function(address) {
return bcoin.keyring.fromJSON(address);
});
self.emit('address', receive, change, map);
});
self.socket.on('balances', function(json) {
var balances = {};
Object.keys(json).forEach(function(id) {
@ -493,8 +503,8 @@ HTTPClient.prototype.getWalletLast = function getWalletLast(id, account, limit,
* Get wallet transactions by timestamp range.
* @param {WalletID} id
* @param {Object} options
* @param {Number} options.start - Start height.
* @param {Number} options.end - End height.
* @param {Number} options.start - Start time.
* @param {Number} options.end - End time.
* @param {Number?} options.limit - Max number of records.
* @param {Boolean?} options.reverse - Reverse order.
* @param {Function} callback - Returns [Error, {@link TX}[]].
@ -507,8 +517,13 @@ HTTPClient.prototype.getWalletRange = function getWalletRange(id, account, optio
account = null;
}
if (!options.account)
options.account = account;
options = {
account: account || options.account,
start: options.start,
end: options.end ,
limit: options.limit,
reverse: options.reverse
};
return this._get('/wallet/' + id + '/tx/range', options, function(err, body) {
if (err)
@ -793,7 +808,7 @@ HTTPClient.prototype.walletSend = function walletSend(id, options, outputs, call
? output.address.toBase58()
: output.address,
script: output.script ? output.script.toRaw('hex') : null
}
};
});
callback = utils.ensure(callback);
@ -840,7 +855,7 @@ HTTPClient.prototype.walletCreate = function walletCreate(id, options, outputs,
? output.address.toBase58()
: output.address,
script: output.script ? output.script.toRaw('hex') : null
}
};
});
callback = utils.ensure(callback);
@ -862,22 +877,22 @@ HTTPClient.prototype.walletCreate = function walletCreate(id, options, outputs,
/**
* Sign a transaction.
* @param {WalletID} id
* @param {TX} tx
* @param {Object} options
* @param {Function} callback - Returns [Error, {@link TX}].
*/
HTTPClient.prototype.walletSign = function walletCreate(id, account, options, callback) {
HTTPClient.prototype.walletSign = function walletCreate(id, tx, options, callback) {
var body;
if (typeof options === 'function') {
callback = options;
options = account;
account = null;
options = null;
}
body = {
account: account || options.account
};
body = utils.merge({}, options || {}, {
tx: tx.toRaw('hex')
});
callback = utils.ensure(callback);
@ -970,7 +985,7 @@ HTTPClient.prototype.addKey = function addKey(id, account, keys, callback) {
* @param {Function} callback
*/
HTTPClient.prototype.removeKey = function removeKey(id, keys, callback) {
HTTPClient.prototype.removeKey = function removeKey(id, account, keys, callback) {
var options;
if (typeof keys === 'function') {
@ -997,6 +1012,60 @@ HTTPClient.prototype.removeKey = function removeKey(id, keys, callback) {
});
};
/**
* Get wallet accounts.
* @param {WalletID} id
* @param {Function} callback - Returns [Error, Array].
*/
HTTPClient.prototype.getWalletAccounts = function getWalletAccounts(id, callback) {
var path = '/wallet/' + id + '/account';
return this._get(path, function(err, body) {
if (err)
return callback(err);
if (!body)
return callback(null, []);
return callback(null, body);
});
};
/**
* Create account.
* @param {WalletID} id
* @param {Object} options
* @param {Function} callback - Returns [Error, Array].
*/
HTTPClient.prototype.createWalletAccount = function createWalletAccount(id, options, callback) {
var path;
if (typeof options === 'function') {
callback = options;
options = null;
}
if (!options)
options = {};
if (typeof options === 'string')
options = { account: options };
path = '/wallet/' + id + '/account';
return this._post(path, options, function(err, body) {
if (err)
return callback(err);
if (!body)
return callback(null, []);
return callback(null, body);
});
};
/**
* Get a mempool snapshot.
* @param {Function} callback - Returns [Error, {@link TX}[]].

View File

@ -9,7 +9,7 @@ var utils = require('../utils');
exports.request = require('./request');
exports.client = require('./client');
exports.provider = require('./provider');
exports.wallet = require('./wallet');
if (!utils.isBrowser) {
exports.base = require('./ba' + 'se');

View File

@ -1,215 +0,0 @@
/*!
* provider.js - http provider for wallets
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
* https://github.com/indutny/bcoin
*/
var bcoin = require('../env');
var EventEmitter = require('events').EventEmitter;
var utils = require('../utils');
var assert = utils.assert;
var http = require('./');
var HTTPClient = http.client;
/**
* HTTPProvider
* @exports HTTPProvider
* @constructor
* @param {String} uri
*/
function HTTPProvider(options) {
if (!(this instanceof HTTPProvider))
return new HTTPProvider(options);
EventEmitter.call(this);
if (!options)
options = {};
if (typeof options === 'string')
options = { uri: options };
this.client = new HTTPClient(options);
this.network = bcoin.network.get(options.network);
this.uri = options.uri;
this.id = null;
this._init();
}
utils.inherits(HTTPProvider, EventEmitter);
HTTPProvider.prototype._init = function _init() {
var self = this;
this.client.on('tx', function(tx) {
self.emit('tx', tx);
});
this.client.on('confirmed', function(tx) {
self.emit('confirmed', tx);
});
this.client.on('updated', function(tx) {
self.emit('updated', tx);
});
this.client.on('balance', function(balance) {
self.emit('balance', balance);
});
this.client.on('error', function(err) {
self.emit('error', err);
});
};
/**
* @see HTTPProvider#setID
*/
HTTPProvider.prototype.setID = function setID(id) {
assert(!this.id, 'ID has already been set.');
this.id = id;
this.client.listenWallet(id);
};
/**
* @see HTTPProvider#open
*/
HTTPProvider.prototype.open = function open(callback) {
this.client.open(callback);
};
/**
* @see HTTPProvider#close
*/
HTTPProvider.prototype.close =
HTTPProvider.prototype.destroy = function destroy(callback) {
callback = utils.ensure(callback);
if (!this.client)
return utils.nextTick(callback);
this.client.destroy(callback);
this.client = null;
};
/**
* @see HTTPProvider#getHistory
*/
HTTPProvider.prototype.getHistory = function getHistory(callback) {
return this.client.getWalletHistory(this.id, callback);
};
/**
* @see HTTPProvider#getCoins
*/
HTTPProvider.prototype.getCoins = function getCoins(callback) {
return this.client.getWalletCoins(this.id, callback);
};
/**
* @see HTTPProvider#getUnconfirmed
*/
HTTPProvider.prototype.getUnconfirmed = function getUnconfirmed(callback) {
return this.client.getWalletUnconfirmed(this.id, callback);
};
/**
* @see HTTPProvider#getBalance
*/
HTTPProvider.prototype.getBalance = function getBalance(callback) {
return this.client.getWalletBalance(this.id, callback);
};
/**
* @see HTTPProvider#getLastTime
*/
HTTPProvider.prototype.getLastTime = function getLastTime(callback) {
assert(false);
};
/**
* @see HTTPProvider#getLast
*/
HTTPProvider.prototype.getLast = function getLast(limit, callback) {
return this.client.getWalletLast(this.id, limit, callback);
};
/**
* @see HTTPProvider#getRange
*/
HTTPProvider.prototype.getRange = function getRange(options, callback) {
return this.client.getWalletRange(this.id, options, callback);
};
/**
* @see HTTPProvider#getTX
*/
HTTPProvider.prototype.getTX = function getTX(hash, callback) {
return this.client.getWalletTX(this.id, hash, callback);
};
/**
* @see HTTPProvider#getCoin
*/
HTTPProvider.prototype.getCoin = function getCoin(hash, index, callback) {
return this.client.getWalletCoin(this.id, hash, index, callback);
};
/**
* @see HTTPProvider#fillHistory
*/
HTTPProvider.prototype.fillHistory = function fillHistory(tx, callback) {
assert(false);
};
/**
* @see HTTPProvider#fillCoins
*/
HTTPProvider.prototype.fillCoins = function fillCoins(tx, callback) {
assert(false);
};
/**
* Sync wallet address depths with server.
* @param {Wallet} wallet
* @param {Address?} address - Newly allocated address if available.
*/
HTTPProvider.prototype.sync = function sync(wallet, address) {
var self = this;
return this.client.syncWallet(this.id, wallet, function(err) {
if (err)
self.emit('error', err);
});
};
/**
* @see HTTPProvider#zap
*/
HTTPProvider.prototype.zap = function zap(now, age, callback) {
return this.client.zapWallet(this.id, now, age, callback);
};
/*
* Expose
*/
module.exports = HTTPProvider;

View File

@ -153,6 +153,9 @@ HTTPServer.prototype._init = function _init() {
if (params.account)
options.account = params.account;
if (params.name)
options.name = params.name;
if (params.now)
options.now = params.now >>> 0;
@ -383,12 +386,25 @@ HTTPServer.prototype._init = function _init() {
});
});
// List accounts
this.get('/wallet/:id/account', function(req, res, next, send) {
self.walletdb.getAccounts(req.options.id, function(err, accounts) {
if (err)
return next(err);
if (accounts.length === 0)
return send(404);
send(200, accounts);
});
});
// Create/get account
this.post('/wallet/:id/:account', function(req, res, next, send) {
this.post('/wallet/:id/account/:account?', function(req, res, next, send) {
var id = req.options.id;
var account = req.options.account;
var options = req.options;
self.walletdb.makeAccount(id, account, options, function(err, account) {
options.name = options.account || options.name;
self.walletdb.ensureAccount(id, options, function(err, account) {
if (err)
return next(err);
@ -400,7 +416,7 @@ HTTPServer.prototype._init = function _init() {
});
// Send TX
this.post('/wallet/:id/:account?/send', function(req, res, next, send) {
this.post('/wallet/:id/send', function(req, res, next, send) {
var id = req.options.id;
var options = req.options;
var outputs = req.options.outputs;
@ -427,7 +443,7 @@ HTTPServer.prototype._init = function _init() {
});
// Create TX
this.post('/wallet/:id/:account?/create', function(req, res, next, send) {
this.post('/wallet/:id/create', function(req, res, next, send) {
var id = req.options.id;
var options = req.options;
var outputs = req.options.outputs;
@ -444,9 +460,10 @@ HTTPServer.prototype._init = function _init() {
});
// Sign TX
this.post('/wallet/:id/:account?/sign', function(req, res, next, send) {
this.post('/wallet/:id/sign', function(req, res, next, send) {
var id = req.options.id;
var options = req.options;
var tx = req.options.tx;
self.walletdb.sign(id, tx, options, function(err) {
if (err)
@ -457,7 +474,7 @@ HTTPServer.prototype._init = function _init() {
});
// Zap Wallet TXs
this.post('/wallet/:id/:account?/zap', function(req, res, next, send) {
this.post('/wallet/:id/zap', function(req, res, next, send) {
var id = req.options.id;
var account = req.options.account;
var age = req.options.age;
@ -473,7 +490,7 @@ HTTPServer.prototype._init = function _init() {
});
// Add key
this.put('/wallet/:id/:account?/key', function(req, res, next, send) {
this.put('/wallet/:id/key', function(req, res, next, send) {
var id = req.options.id;
var account = req.options.account;
var keys = req.options.keys;
@ -486,7 +503,7 @@ HTTPServer.prototype._init = function _init() {
});
// Remove key
this.del('/wallet/:id/:account?/key', function(req, res, next, send) {
this.del('/wallet/:id/key', function(req, res, next, send) {
var id = req.options.id;
var account = req.options.account;
var keys = req.options.keys;
@ -499,7 +516,7 @@ HTTPServer.prototype._init = function _init() {
});
// Wallet Balance
this.get('/wallet/:id/:account?/balance', function(req, res, next, send) {
this.get('/wallet/:id/balance', function(req, res, next, send) {
var id = req.options.id;
var account = req.options.account;
self.walletdb.getBalance(id, account, function(err, balance) {
@ -518,7 +535,7 @@ HTTPServer.prototype._init = function _init() {
});
// Wallet UTXOs
this.get('/wallet/:id/:account?/coin', function(req, res, next, send) {
this.get('/wallet/:id/coin', function(req, res, next, send) {
var id = req.options.id;
var account = req.options.account;
self.walletdb.getCoins(id, account, function(err, coins) {
@ -535,9 +552,9 @@ HTTPServer.prototype._init = function _init() {
});
// Wallet Coin
this.get('/wallet/:id/:account?/coin/:hash/:index', function(req, res, next, send) {
var id = req.options.id;
var account = req.options.account;
this.get('/wallet/:id/coin/:hash/:index', function(req, res, next, send) {
var hash = req.options.hash;
var index = req.options.index;
self.walletdb.getCoin(hash, index, function(err, coin) {
if (err)
return next(err);
@ -550,7 +567,7 @@ HTTPServer.prototype._init = function _init() {
});
// Wallet TXs
this.get('/wallet/:id/:account?/tx/history', function(req, res, next, send) {
this.get('/wallet/:id/tx/history', function(req, res, next, send) {
var id = req.options.id;
var account = req.options.account;
self.walletdb.getHistory(id, account, function(err, txs) {
@ -574,7 +591,7 @@ HTTPServer.prototype._init = function _init() {
});
// Wallet Pending TXs
this.get('/wallet/:id/:account?/tx/unconfirmed', function(req, res, next, send) {
this.get('/wallet/:id/tx/unconfirmed', function(req, res, next, send) {
var id = req.options.id;
var account = req.options.account;
self.walletdb.getUnconfirmed(id, account, function(err, txs) {
@ -598,7 +615,7 @@ HTTPServer.prototype._init = function _init() {
});
// Wallet TXs within time range
this.get('/wallet/:id/:account?/tx/range', function(req, res, next, send) {
this.get('/wallet/:id/tx/range', function(req, res, next, send) {
var id = req.options.id;
var account = req.options.account;
var options = req.options;
@ -623,7 +640,7 @@ HTTPServer.prototype._init = function _init() {
});
// Wallet TXs within time range
this.get('/wallet/:id/:account?/tx/last', function(req, res, next, send) {
this.get('/wallet/:id/tx/last', function(req, res, next, send) {
var id = req.options.id;
var account = req.options.account;
var limit = req.options.limit;
@ -648,7 +665,7 @@ HTTPServer.prototype._init = function _init() {
});
// Wallet TX
this.get('/wallet/:id/:account?/tx/:hash', function(req, res, next, send) {
this.get('/wallet/:id/tx/:hash', function(req, res, next, send) {
self.walletdb.getTX(req.options.hash, function(err, tx) {
if (err)
return next(err);
@ -769,6 +786,19 @@ HTTPServer.prototype._initIO = function _initIO() {
});
self.server.io.to('!all').emit('balances', json);
});
this.walletdb.on('address', function(receive, change, map) {
receive = receive.map(function(address) {
return address.toJSON();
});
change = change.map(function(address) {
return address.toJSON();
});
map.all.forEach(function(id) {
self.server.io.to(id).emit('address', receive, change, map);
});
self.server.io.to('!all').emit('address', receive, change, map);
});
};
/**

224
lib/bcoin/http/wallet.js Normal file
View File

@ -0,0 +1,224 @@
/*!
* wallet.js - http wallet for bcoin
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
* https://github.com/indutny/bcoin
*/
var bcoin = require('../env');
var EventEmitter = require('events').EventEmitter;
var utils = require('../utils');
var http = require('./');
/**
* HTTPWallet
* @exports HTTPWallet
* @constructor
* @param {String} uri
*/
function HTTPWallet(options) {
if (!(this instanceof HTTPWallet))
return new HTTPWallet(options);
EventEmitter.call(this);
if (!options)
options = {};
if (typeof options === 'string')
options = { uri: options };
this.options = options;
this.client = new http.client(options);
this.network = bcoin.network.get(options.network);
this.uri = options.uri;
this._init();
}
utils.inherits(HTTPWallet, EventEmitter);
HTTPWallet.prototype._init = function _init() {
var self = this;
this.client.on('tx', function(tx, map) {
self.emit('tx', tx, map);
});
this.client.on('confirmed', function(tx, map) {
self.emit('confirmed', tx, map);
});
this.client.on('updated', function(tx, map) {
self.emit('updated', tx, map);
});
this.client.on('balance', function(balance, map) {
self.emit('balance', balance, map);
});
this.client.on('address', function(receive, change, map) {
self.emit('address', receive, change, map);
});
this.client.on('error', function(err) {
self.emit('error', err);
});
this.client.join(this.id);
};
/**
* @see Wallet#open
*/
HTTPWallet.prototype.open = function open(callback) {
var self = this;
this.client.open(function(err) {
if (err)
return callback(err);
self.createWallet(self.options, callback);
});
};
/**
* @see Wallet#close
*/
HTTPWallet.prototype.close =
HTTPWallet.prototype.destroy = function destroy(callback) {
callback = utils.ensure(callback);
if (!this.client)
return utils.nextTick(callback);
this.client.destroy(callback);
this.client = null;
};
/**
* @see Wallet#getHistory
*/
HTTPWallet.prototype.getHistory = function getHistory(account, callback) {
return this.client.getWalletHistory(this.id, account, callback);
};
/**
* @see Wallet#getCoins
*/
HTTPWallet.prototype.getCoins = function getCoins(account, callback) {
return this.client.getWalletCoins(this.id, account, callback);
};
/**
* @see Wallet#getUnconfirmed
*/
HTTPWallet.prototype.getUnconfirmed = function getUnconfirmed(account, callback) {
return this.client.getWalletUnconfirmed(this.id, account, callback);
};
/**
* @see Wallet#getBalance
*/
HTTPWallet.prototype.getBalance = function getBalance(account, callback) {
return this.client.getWalletBalance(this.id, account, callback);
};
/**
* @see Wallet#getLast
*/
HTTPWallet.prototype.getLast = function getLast(account, limit, callback) {
return this.client.getWalletLast(this.id, account, limit, callback);
};
/**
* @see Wallet#getRange
*/
HTTPWallet.prototype.getRange = function getRange(account, options, callback) {
return this.client.getWalletRange(this.id, account, options, callback);
};
/**
* @see Wallet#getTX
*/
HTTPWallet.prototype.getTX = function getTX(account, hash, callback) {
return this.client.getWalletTX(this.id, account, hash, callback);
};
/**
* @see Wallet#getCoin
*/
HTTPWallet.prototype.getCoin = function getCoin(account, hash, index, callback) {
return this.client.getWalletCoin(this.id, account, hash, index, callback);
};
/**
* @see Wallet#zap
*/
HTTPWallet.prototype.zap = function zap(account, age, callback) {
return this.client.walletZap(this.id, account, age, callback);
};
/**
* @see Wallet#createTX
*/
HTTPWallet.prototype.createTX = function createTX(tx, options, outputs, callback) {
return this.client.walletCreate(this.id, tx, options, outputs, callback);
};
/**
* @see HTTPClient#walletSend
*/
HTTPWallet.prototype.send = function send(tx, options, outputs, callback) {
return this.client.walletSend(this.id, tx, options, outputs, callback);
};
/**
* @see Wallet#sign
*/
HTTPWallet.prototype.sign = function sign(tx, options, callback) {
return this.client.walletSign(this.id, tx, options, callback);
};
/**
* @see HTTPClient#getWallet
*/
HTTPWallet.prototype.getInfo = function getInfo(callback) {
return this.client.getWallet(this.id, callback);
};
/**
* @see Wallet#getAccounts
*/
HTTPWallet.prototype.getAccounts = function getAccounts(callback) {
return this.client.getWalletAccounts(this.id, callback);
};
/**
* @see Wallet#createAccount
*/
HTTPWallet.prototype.createAccount = function createAccount(options, callback) {
return this.client.createWalletAccount(this.id, options, callback);
};
/*
* Expose
*/
module.exports = HTTPWallet;

View File

@ -1654,10 +1654,6 @@ Account.prototype.destroy = function destroy(callback) {
*/
Account.prototype.init = function init(callback) {
var self = this;
var addresses = [];
var i;
// Waiting for more keys.
if (this.keys.length !== this.n) {
assert(!this.initialized);
@ -1799,20 +1795,21 @@ Account.prototype.spliceKey = function spliceKey(key) {
Account.prototype.addKey = function addKey(key, callback) {
var result = false;
var error;
try {
result = this.pushKey(key);
} catch (e) {
return callback(e);
error = e;
}
if (!result)
return callback(null, result);
this.init(function(err) {
if (err)
return callback(err);
if (error)
return callback(error);
return callback(null, result);
});
};
@ -1826,20 +1823,21 @@ Account.prototype.addKey = function addKey(key, callback) {
Account.prototype.removeKey = function removeKey(key, callback) {
var result = false;
var error;
try {
result = this.spliceKey(key);
} catch (e) {
return callback(e);
error = e;
}
if (!result)
return callback(null, result);
this.save(function(err) {
if (err)
return callback(err);
if (error)
return callback(error);
return callback(null, result);
});
};
@ -2158,6 +2156,9 @@ Account.prototype.toJSON = function toJSON() {
receiveAddress: this.receiveAddress
? this.receiveAddress.getAddress()
: null,
programAddress: this.receiveAddress
? this.receiveAddress.getProgramAddress()
: null,
changeAddress: this.changeAddress
? this.changeAddress.getAddress()
: null,

View File

@ -205,7 +205,13 @@ WalletDB.prototype.updateBalances = function updateBalances(tx, map, callback) {
WalletDB.prototype.syncOutputs = function syncOutputs(tx, map, callback) {
var self = this;
utils.forEachSerial(map.output, function(path, next) {
self.syncOutputDepth(path.id, tx, next);
self.syncOutputDepth(path.id, tx, function(err, receive, change) {
if (err)
return next(err);
self.fire(path.id, 'address', receive, change, path.name);
self.emit('address', receive, change, map);
next();
});
}, callback);
};
@ -557,7 +563,6 @@ WalletDB.prototype.getAccountIndex = function getAccountIndex(id, name, callback
});
};
/**
* Save an account to the database.
* @param {Account} account
@ -828,9 +833,8 @@ WalletDB.prototype.getBalance = function getBalance(id, account, callback) {
WalletDB.prototype.getLastTime = function getLastTime(id, account, callback) {
var self = this;
if (typeof options === 'function') {
callback = options;
options = account;
if (typeof account === 'function') {
callback = account;
account = null;
}
@ -857,12 +861,12 @@ WalletDB.prototype.getLast = function getLast(id, account, limit, callback) {
});
};
WalletDB.prototype.getTimeRange = function getTimeRange(id, account, limit, callback) {
WalletDB.prototype.getTimeRange = function getTimeRange(id, account, options, callback) {
var self = this;
if (typeof limit === 'function') {
callback = limit;
limit = account;
if (typeof options === 'function') {
callback = options;
options = account;
account = null;
}
@ -935,8 +939,6 @@ WalletDB.prototype.zap = function zap(id, account, age, callback) {
*/
WalletDB.prototype._getKey = function _getKey(id, account, errback, callback) {
var self = this;
if (typeof account === 'function') {
errback = account;
account = null;
@ -1089,9 +1091,11 @@ WalletDB.prototype.getInfo = function getInfo(id, callback) {
});
};
WalletDB.prototype.makeAccount = function makeAccount(id, account, options, callback) {
WalletDB.prototype.ensureAccount = function ensureAccount(id, options, callback) {
var self = this;
var account = options.name || options.account;
this.fetchWallet(id, callback, function(wallet, callback) {
wallet.hasAccount(account, function(err, exists) {
self.hasAccount(wallet.id, account, function(err, exists) {
if (err)
return callback(err);
if (exists)