remotely add and remove keys.

This commit is contained in:
Christopher Jeffrey 2016-04-01 21:58:29 -07:00
parent 73832de55f
commit 4f03675b9f
5 changed files with 211 additions and 7 deletions

View File

@ -25,6 +25,9 @@ function getID() {
function createWallet(callback) {
var options = { id: getID() };
if (argv.type)
options.type = argv.type;
if (argv.master)
options.master = argv.master;
@ -61,6 +64,36 @@ function createWallet(callback) {
});
}
function addKey(callback) {
var id = getID();
var keys = argv.keys || argv.key;
if (keys)
keys = keys.split(',');
else
keys = argv.args;
client.addKey(id, keys, function(err, wallet) {
if (err)
return callback(err);
utils.print('added');
callback();
});
}
function removeKey(callback) {
var id = getID();
var keys = argv.keys || argv.key;
if (keys)
keys = keys.split(',');
else
keys = argv.args;
client.removeKey(id, keys, function(err) {
if (err)
return callback(err);
utils.print('removed');
callback();
});
}
function getWallet(callback) {
var options = { id: getID(), passphrase: argv.args[0] };
client.getWallet(options.id, options.passphrase, function(err, wallet) {
@ -188,6 +221,10 @@ function main(callback) {
return createWallet(callback);
case 'getwallet':
return getWallet(callback);
case 'addkey':
return addKey(callback);
case 'rmkey':
return removeKey(callback);
case 'balance':
return getBalance(callback);
case 'history':
@ -204,8 +241,25 @@ function main(callback) {
return getCoin(callback);
case 'block':
return getBlock(callback);
default:
utils.print('Unrecognized command.');
utils.print('Commands:');
utils.print(' $ wallet [id] --keys [hdkeys]'
+ ' --type [pubkeyhash/multisig] -m [m-value]
+ ' -n [n-value] --witness: View or create wallet by ID.');
utils.print(' $ getwallet [id]: View wallet by ID.');
utils.print(' $ addkey [id] --keys [hdkeys]: Add keys to wallet.');
utils.print(' $ rmkey [id] --keys [hdkeys]: Remove keys from wallet.');
utils.print(' $ balance [id]: Get wallet balance.');
utils.print(' $ history [id]: View wallet TX history.');
utils.print(' $ send [id] [address] [value] --script [code]: Send transaction.');
utils.print(' $ zap [id] --now [now] --age [age]: Zap pending wallet TXs.');
utils.print(' $ mempool: Get mempool snapshot.');
utils.print(' $ tx [hash/address]: View transactions.');
utils.print(' $ coin [hash+index/address]: View coins.');
utils.print(' $ block [hash/height]: View block.');
return callback();
}
return callback(new Error('Bad command.'));
}
function parseArg(argv) {

View File

@ -591,6 +591,40 @@ Client.prototype.zapWallet = function zapWallet(id, now, age, callback) {
});
};
Client.prototype.addKey = function addKey(id, keys, callback) {
if (!Array.isArray(keys))
keys = [keys];
keys = keys.map(function(key) {
return key || key.xpubkey;
});
callback = utils.ensure(callback);
return this._put('/wallet/' + id + '/key', keys, function(err) {
if (err)
return callback(err);
return callback();
});
};
Client.prototype.removeKey = function removeKey(id, keys, callback) {
if (!Array.isArray(keys))
keys = [keys];
keys = keys.map(function(key) {
return key || key.xpubkey;
});
callback = utils.ensure(callback);
return this._del('/wallet/' + id + '/key', keys, function(err) {
if (err)
return callback(err);
return callback();
});
};
Client.prototype.getMempool = function getMempool(callback) {
return this._get('/mempool', function(err, body) {
if (err)

View File

@ -121,6 +121,16 @@ NodeServer.prototype._init = function _init() {
if (params.age)
options.age = params.age >>> 0;
if (params.key)
params.keys = params.key;
if (params.keys) {
if (typeof params.keys === 'string')
options.keys = params.keys.split(',');
else
options.keys = params.keys;
}
if (params.passphrase)
options.passphrase = params.passphrase;
@ -332,6 +342,29 @@ NodeServer.prototype._init = function _init() {
});
});
// Add key
this.put('/wallet/:id/key', function(req, res, next, send) {
self.walletdb.addKey(req.options.id, req.options.keys, function(err) {
if (err)
return next(err);
send(200, { success: true });
});
});
// Remove key
this.del('/wallet/:id/key', function(req, res, next, send) {
self.walletdb.removeKey(req.options.id, req.options.keys, function(err) {
if (err)
return next(err);
if (!json)
return send(404);
send(200, { success: true });
});
});
// Wallet Balance
this.get('/wallet/:id/balance', function(req, res, next, send) {
self.walletdb.getBalance(req.options.id, function(err, balance) {

View File

@ -127,10 +127,14 @@ Wallet.prototype._init = function _init() {
this.provider.setID(this.id);
this.provider.on('error', function(err) {
this.on('error', function(err) {
utils.debug('Wallet Error: %s', err.message);
});
this.provider.on('error', function(err) {
self.emit('error', err);
});
this.provider.on('tx', function(tx) {
self.emit('tx', tx);
});
@ -1019,16 +1023,22 @@ Wallet.prototype.inspect = function inspect() {
network: network.type,
m: this.m,
n: this.n,
keyAddress: this.keyAddress,
scriptAddress: this.scriptAddress,
programAddress: this.programAddress,
keyAddress: this._initialized
? this.keyAddress
: null,
scriptAddress: this._initialized
? this.scriptAddress
: null,
programAddress: this._initialized
? this.programAddress
: null,
witness: this.witness,
derivation: this.derivation,
copayBIP45: this.copayBIP45,
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) {
@ -1092,7 +1102,7 @@ Wallet.fromJSON = function fromJSON(json, passphrase) {
// For updating the address table quickly
// without decrypting the master key.
Wallet._syncDepth = function sync(json, options) {
Wallet._syncDepth = function _syncDepth(json, options) {
var master, wallet;
var res = false;
@ -1156,6 +1166,41 @@ Wallet.setDepth = function setDepth(json, receiveDepth, changeDepth) {
});
};
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];
if (json.network)
assert.equal(json.network, network.type);
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;
};
Wallet.addKey = function addKey(json, keys) {
return Wallet._addKey(json, keys, false);
};
Wallet.removeKey = function removeKey(json, keys) {
return Wallet._addKey(json, keys, true);
};
Wallet.isWallet = function isWallet(obj) {
return obj
&& typeof obj.receiveDepth === 'number'

View File

@ -240,6 +240,44 @@ WalletDB.prototype.setDepth = function setDepth(id, receive, change, callback) {
});
};
WalletDB.prototype.addKey = function addKey(id, key, callback) {
var self = this;
callback = utils.ensure(callback);
this.getJSON(id, function(err, json) {
if (err)
return callback(err);
try {
json = bcoin.wallet.addKey(json, key);
} catch (e) {
return callback(e);
}
self.saveJSON(id, json, callback);
});
};
WalletDB.prototype.removeKey = function removeKey(id, key, callback) {
var self = this;
callback = utils.ensure(callback);
this.getJSON(id, function(err, json) {
if (err)
return callback(err);
try {
json = bcoin.wallet.removeKey(json, key);
} catch (e) {
return callback(e);
}
self.saveJSON(id, json, callback);
});
};
WalletDB.prototype.getJSON = function getJSON(id, callback) {
if (typeof id === 'object')
id = id.id;