rpc: better error codes.
This commit is contained in:
parent
5ee8a9b306
commit
3ae417795f
420
lib/http/rpc.js
420
lib/http/rpc.js
File diff suppressed because it is too large
Load Diff
@ -106,7 +106,7 @@ RPCBase.prototype.call = co(function* call(body, query) {
|
|||||||
var cmds = body;
|
var cmds = body;
|
||||||
var out = [];
|
var out = [];
|
||||||
var array = true;
|
var array = true;
|
||||||
var i, cmd, result;
|
var i, cmd, result, code;
|
||||||
|
|
||||||
if (!Array.isArray(cmds)) {
|
if (!Array.isArray(cmds)) {
|
||||||
cmds = [cmds];
|
cmds = [cmds];
|
||||||
@ -116,19 +116,56 @@ RPCBase.prototype.call = co(function* call(body, query) {
|
|||||||
for (i = 0; i < cmds.length; i++) {
|
for (i = 0; i < cmds.length; i++) {
|
||||||
cmd = cmds[i];
|
cmd = cmds[i];
|
||||||
|
|
||||||
assert(cmd && typeof cmd === 'object', 'Command must be an object.');
|
if (!cmd || typeof cmd !== 'object') {
|
||||||
assert(typeof cmd.method === 'string', 'Method must be a string.');
|
out.push({
|
||||||
|
result: null,
|
||||||
|
error: {
|
||||||
|
message: 'Invalid request.',
|
||||||
|
code: RPCBase.errors.INVALID_REQUEST
|
||||||
|
},
|
||||||
|
id: null
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd.id && typeof cmd.id === 'object') {
|
||||||
|
out.push({
|
||||||
|
result: null,
|
||||||
|
error: {
|
||||||
|
message: 'Invalid ID.',
|
||||||
|
code: RPCBase.errors.INVALID_REQUEST
|
||||||
|
},
|
||||||
|
id: null
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof cmd.method !== 'string') {
|
||||||
|
out.push({
|
||||||
|
result: null,
|
||||||
|
error: {
|
||||||
|
message: 'Method not found.',
|
||||||
|
code: RPCBase.errors.METHOD_NOT_FOUND
|
||||||
|
},
|
||||||
|
id: cmd.id
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!cmd.params)
|
if (!cmd.params)
|
||||||
cmd.params = [];
|
cmd.params = [];
|
||||||
|
|
||||||
assert(Array.isArray(cmd.params), 'Params must be an array.');
|
if (!Array.isArray(cmd.params)) {
|
||||||
|
out.push({
|
||||||
assert(!cmd.id || typeof cmd.id !== 'object', 'Invalid ID.');
|
result: null,
|
||||||
}
|
error: {
|
||||||
|
message: 'Invalid params.',
|
||||||
for (i = 0; i < cmds.length; i++) {
|
code: RPCBase.errors.INVALID_PARAMS
|
||||||
cmd = cmds[i];
|
},
|
||||||
|
id: cmd.id
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (cmd.method !== 'getwork'
|
if (cmd.method !== 'getwork'
|
||||||
&& cmd.method !== 'getblocktemplate'
|
&& cmd.method !== 'getblocktemplate'
|
||||||
@ -148,25 +185,25 @@ RPCBase.prototype.call = co(function* call(body, query) {
|
|||||||
try {
|
try {
|
||||||
result = yield this.execute(cmd);
|
result = yield this.execute(cmd);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.type === 'RPCError') {
|
switch (err.type) {
|
||||||
out.push({
|
case 'RPCError':
|
||||||
result: null,
|
code = err.code;
|
||||||
error: {
|
break;
|
||||||
message: err.message,
|
case 'ValidationError':
|
||||||
code: -1
|
code = RPCBase.errors.TYPE_ERROR;
|
||||||
},
|
break;
|
||||||
id: cmd.id
|
default:
|
||||||
});
|
code = RPCBase.errors.INTERNAL_ERROR;
|
||||||
continue;
|
this.logger.error('RPC internal error.');
|
||||||
|
this.logger.error(err);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.error(err);
|
|
||||||
|
|
||||||
out.push({
|
out.push({
|
||||||
result: null,
|
result: null,
|
||||||
error: {
|
error: {
|
||||||
message: err.message,
|
message: err.message,
|
||||||
code: 1
|
code: code
|
||||||
},
|
},
|
||||||
id: cmd.id
|
id: cmd.id
|
||||||
});
|
});
|
||||||
@ -254,15 +291,18 @@ RPCBase.prototype.attach = function attach(rpc) {
|
|||||||
* @ignore
|
* @ignore
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function RPCError(msg, code) {
|
function RPCError(code, msg) {
|
||||||
Error.call(this);
|
Error.call(this);
|
||||||
|
|
||||||
if (Error.captureStackTrace)
|
if (Error.captureStackTrace)
|
||||||
Error.captureStackTrace(this, RPCError);
|
Error.captureStackTrace(this, RPCError);
|
||||||
|
|
||||||
|
assert(typeof code === 'number');
|
||||||
|
assert(typeof msg === 'string');
|
||||||
|
|
||||||
this.type = 'RPCError';
|
this.type = 'RPCError';
|
||||||
this.message = msg;
|
this.message = msg;
|
||||||
this.code = code != null ? code : -1;
|
this.code = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
util.inherits(RPCError, Error);
|
util.inherits(RPCError, Error);
|
||||||
|
|||||||
@ -87,7 +87,7 @@ Validator.prototype.get = function get(key, fallback) {
|
|||||||
map = this.data[i];
|
map = this.data[i];
|
||||||
|
|
||||||
if (!map || typeof map !== 'object')
|
if (!map || typeof map !== 'object')
|
||||||
throw new Error('Data is not an object.');
|
throw new ValidationError('Data is not an object.');
|
||||||
|
|
||||||
value = map[key];
|
value = map[key];
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ Validator.prototype.str = function str(key, fallback) {
|
|||||||
return fallback;
|
return fallback;
|
||||||
|
|
||||||
if (typeof value !== 'string')
|
if (typeof value !== 'string')
|
||||||
throw new Error(fmt(key) + ' must be a string.');
|
throw new ValidationError(fmt(key) + ' must be a string.');
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
@ -138,17 +138,17 @@ Validator.prototype.num = function num(key, fallback) {
|
|||||||
|
|
||||||
if (typeof value !== 'string') {
|
if (typeof value !== 'string') {
|
||||||
if (typeof value !== 'number')
|
if (typeof value !== 'number')
|
||||||
throw new Error(fmt(key) + ' must be a number.');
|
throw new ValidationError(fmt(key) + ' must be a number.');
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!/^\d+$/.test(value))
|
if (!/^\d+$/.test(value))
|
||||||
throw new Error(fmt(key) + ' must be a number.');
|
throw new ValidationError(fmt(key) + ' must be a number.');
|
||||||
|
|
||||||
value = parseInt(value, 10);
|
value = parseInt(value, 10);
|
||||||
|
|
||||||
if (!isFinite(value))
|
if (!isFinite(value))
|
||||||
throw new Error(fmt(key) + ' must be a number.');
|
throw new ValidationError(fmt(key) + ' must be a number.');
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
@ -170,7 +170,7 @@ Validator.prototype.u32 = function u32(key, fallback) {
|
|||||||
return fallback;
|
return fallback;
|
||||||
|
|
||||||
if (value % 1 !== 0 || value < 0 || value > 0xffffffff)
|
if (value % 1 !== 0 || value < 0 || value > 0xffffffff)
|
||||||
throw new Error(fmt(key) + ' must be a uint32.');
|
throw new ValidationError(fmt(key) + ' must be a uint32.');
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
@ -192,7 +192,7 @@ Validator.prototype.u64 = function u64(key, fallback) {
|
|||||||
return fallback;
|
return fallback;
|
||||||
|
|
||||||
if (value % 1 !== 0 || value < 0 || value > 0x1fffffffffffff)
|
if (value % 1 !== 0 || value < 0 || value > 0x1fffffffffffff)
|
||||||
throw new Error(fmt(key) + ' must be a uint64.');
|
throw new ValidationError(fmt(key) + ' must be a uint64.');
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
@ -214,7 +214,7 @@ Validator.prototype.i32 = function i32(key, fallback) {
|
|||||||
return fallback;
|
return fallback;
|
||||||
|
|
||||||
if (value % 1 !== 0 || Math.abs(value) > 0x7fffffff)
|
if (value % 1 !== 0 || Math.abs(value) > 0x7fffffff)
|
||||||
throw new Error(fmt(key) + ' must be an int32.');
|
throw new ValidationError(fmt(key) + ' must be an int32.');
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
@ -236,7 +236,7 @@ Validator.prototype.i64 = function i64(key, fallback) {
|
|||||||
return fallback;
|
return fallback;
|
||||||
|
|
||||||
if (value % 1 !== 0 || Math.abs(value) > 0x1fffffffffffff)
|
if (value % 1 !== 0 || Math.abs(value) > 0x1fffffffffffff)
|
||||||
throw new Error(fmt(key) + ' must be an int64.');
|
throw new ValidationError(fmt(key) + ' must be an int64.');
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
@ -259,22 +259,22 @@ Validator.prototype.amt = function amt(key, fallback) {
|
|||||||
|
|
||||||
if (typeof value !== 'string') {
|
if (typeof value !== 'string') {
|
||||||
if (typeof value !== 'number')
|
if (typeof value !== 'number')
|
||||||
throw new Error(fmt(key) + ' must be a number.');
|
throw new ValidationError(fmt(key) + ' must be a number.');
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!/^\d+(\.\d{0,8})?$/.test(value))
|
if (!/^\d+(\.\d{0,8})?$/.test(value))
|
||||||
throw new Error(fmt(key) + ' must be a number.');
|
throw new ValidationError(fmt(key) + ' must be a number.');
|
||||||
|
|
||||||
value = parseFloat(value);
|
value = parseFloat(value);
|
||||||
|
|
||||||
if (!isFinite(value))
|
if (!isFinite(value))
|
||||||
throw new Error(fmt(key) + ' must be a number.');
|
throw new ValidationError(fmt(key) + ' must be a number.');
|
||||||
|
|
||||||
value *= 1e8;
|
value *= 1e8;
|
||||||
|
|
||||||
if (value % 1 !== 0 || value < 0 || value > 0x1fffffffffffff)
|
if (value % 1 !== 0 || value < 0 || value > 0x1fffffffffffff)
|
||||||
throw new Error(fmt(key) + ' must be a uint64.');
|
throw new ValidationError(fmt(key) + ' must be a uint64.');
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
@ -298,7 +298,7 @@ Validator.prototype.btc = function btc(key, fallback) {
|
|||||||
value *= 1e8;
|
value *= 1e8;
|
||||||
|
|
||||||
if (value % 1 !== 0 || value < 0 || value > 0x1fffffffffffff)
|
if (value % 1 !== 0 || value < 0 || value > 0x1fffffffffffff)
|
||||||
throw new Error(fmt(key) + ' must be a uint64.');
|
throw new ValidationError(fmt(key) + ' must be a uint64.');
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
@ -323,17 +323,17 @@ Validator.prototype.hash = function hash(key, fallback) {
|
|||||||
|
|
||||||
if (typeof value !== 'string') {
|
if (typeof value !== 'string') {
|
||||||
if (!Buffer.isBuffer(value))
|
if (!Buffer.isBuffer(value))
|
||||||
throw new Error(fmt(key) + ' must be a hash.');
|
throw new ValidationError(fmt(key) + ' must be a hash.');
|
||||||
if (value.length !== 32)
|
if (value.length !== 32)
|
||||||
throw new Error(fmt(key) + ' must be a hash.');
|
throw new ValidationError(fmt(key) + ' must be a hash.');
|
||||||
return value.toString('hex');
|
return value.toString('hex');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value.length !== 64)
|
if (value.length !== 64)
|
||||||
throw new Error(fmt(key) + ' must be a hex string.');
|
throw new ValidationError(fmt(key) + ' must be a hex string.');
|
||||||
|
|
||||||
if (!/^[0-9a-f]+$/i.test(value))
|
if (!/^[0-9a-f]+$/i.test(value))
|
||||||
throw new Error(fmt(key) + ' must be a hex string.');
|
throw new ValidationError(fmt(key) + ' must be a hex string.');
|
||||||
|
|
||||||
for (i = 0; i < value.length; i += 2)
|
for (i = 0; i < value.length; i += 2)
|
||||||
out = value.slice(i, i + 2) + out;
|
out = value.slice(i, i + 2) + out;
|
||||||
@ -379,7 +379,7 @@ Validator.prototype.numstr = function numstr(key, fallback) {
|
|||||||
|
|
||||||
if (typeof value !== 'string') {
|
if (typeof value !== 'string') {
|
||||||
if (typeof value !== 'number')
|
if (typeof value !== 'number')
|
||||||
throw new Error(fmt(key) + ' must be a number or string.');
|
throw new ValidationError(fmt(key) + ' must be a number or string.');
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -409,7 +409,7 @@ Validator.prototype.bool = function bool(key, fallback) {
|
|||||||
|
|
||||||
if (typeof value !== 'string') {
|
if (typeof value !== 'string') {
|
||||||
if (typeof value !== 'boolean')
|
if (typeof value !== 'boolean')
|
||||||
throw new Error(fmt(key) + ' must be a boolean.');
|
throw new ValidationError(fmt(key) + ' must be a boolean.');
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,7 +419,7 @@ Validator.prototype.bool = function bool(key, fallback) {
|
|||||||
if (value === 'false' || value === '0')
|
if (value === 'false' || value === '0')
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
throw new Error(fmt(key) + ' must be a boolean.');
|
throw new ValidationError(fmt(key) + ' must be a boolean.');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -445,14 +445,14 @@ Validator.prototype.buf = function buf(key, fallback, enc) {
|
|||||||
|
|
||||||
if (typeof value !== 'string') {
|
if (typeof value !== 'string') {
|
||||||
if (!Buffer.isBuffer(value))
|
if (!Buffer.isBuffer(value))
|
||||||
throw new Error(fmt(key) + ' must be a buffer.');
|
throw new ValidationError(fmt(key) + ' must be a buffer.');
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = new Buffer(value, enc);
|
data = new Buffer(value, enc);
|
||||||
|
|
||||||
if (data.length !== Buffer.byteLength(value, enc))
|
if (data.length !== Buffer.byteLength(value, enc))
|
||||||
throw new Error(fmt(key) + ' must be a ' + enc + ' string.');
|
throw new ValidationError(fmt(key) + ' must be a ' + enc + ' string.');
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
@ -476,7 +476,7 @@ Validator.prototype.array = function array(key, fallback) {
|
|||||||
|
|
||||||
if (typeof value !== 'string') {
|
if (typeof value !== 'string') {
|
||||||
if (!Array.isArray(value))
|
if (!Array.isArray(value))
|
||||||
throw new Error(fmt(key) + ' must be a list/array.');
|
throw new ValidationError(fmt(key) + ' must be a list/array.');
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -512,7 +512,7 @@ Validator.prototype.obj = function obj(key, fallback) {
|
|||||||
return fallback;
|
return fallback;
|
||||||
|
|
||||||
if (!value || typeof value !== 'object')
|
if (!value || typeof value !== 'object')
|
||||||
throw new Error(fmt(key) + ' must be an object.');
|
throw new ValidationError(fmt(key) + ' must be an object.');
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
@ -534,7 +534,7 @@ Validator.prototype.func = function func(key, fallback) {
|
|||||||
return fallback;
|
return fallback;
|
||||||
|
|
||||||
if (typeof value !== 'function')
|
if (typeof value !== 'function')
|
||||||
throw new Error(fmt(key) + ' must be a function.');
|
throw new ValidationError(fmt(key) + ' must be a function.');
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
@ -549,8 +549,31 @@ function fmt(key) {
|
|||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function inherits(obj, from) {
|
||||||
|
var f = function() {};
|
||||||
|
f.prototype = from.prototype;
|
||||||
|
obj.prototype = new f;
|
||||||
|
obj.prototype.constructor = obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ValidationError(msg) {
|
||||||
|
Error.call(this);
|
||||||
|
|
||||||
|
if (Error.captureStackTrace)
|
||||||
|
Error.captureStackTrace(this, ValidationError);
|
||||||
|
|
||||||
|
this.type = 'ValidationError';
|
||||||
|
this.message = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
inherits(ValidationError, Error);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = Validator;
|
exports = Validator;
|
||||||
|
exports.Validator = Validator;
|
||||||
|
exports.Error = ValidationError;
|
||||||
|
|
||||||
|
module.exports = exports;
|
||||||
|
|||||||
@ -26,6 +26,7 @@ var pkg = require('../pkg');
|
|||||||
var Validator = require('../utils/validator');
|
var Validator = require('../utils/validator');
|
||||||
var common = require('./common');
|
var common = require('./common');
|
||||||
var RPCError = RPCBase.RPCError;
|
var RPCError = RPCBase.RPCError;
|
||||||
|
var errs = RPCBase.errors;
|
||||||
var MAGIC_STRING = RPCBase.MAGIC_STRING;
|
var MAGIC_STRING = RPCBase.MAGIC_STRING;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -126,7 +127,7 @@ RPC.prototype.help = co(function* _help(args, help) {
|
|||||||
|
|
||||||
RPC.prototype.stop = co(function* stop(args, help) {
|
RPC.prototype.stop = co(function* stop(args, help) {
|
||||||
if (help || args.length !== 0)
|
if (help || args.length !== 0)
|
||||||
throw new RPCError('stop');
|
throw new RPCError(errs.MISC_ERROR, 'stop');
|
||||||
|
|
||||||
this.wdb.close();
|
this.wdb.close();
|
||||||
|
|
||||||
@ -141,16 +142,20 @@ RPC.prototype.fundRawTransaction = co(function* fundRawTransaction(args, help) {
|
|||||||
var rate = this.feeRate;
|
var rate = this.feeRate;
|
||||||
var change, tx;
|
var change, tx;
|
||||||
|
|
||||||
if (help || args.length < 1 || args.length > 2)
|
if (help || args.length < 1 || args.length > 2) {
|
||||||
throw new RPCError('fundrawtransaction "hexstring" ( options )');
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
|
'fundrawtransaction "hexstring" ( options )');
|
||||||
|
}
|
||||||
|
|
||||||
if (!data)
|
if (!data)
|
||||||
throw new RPCError('Invalid parameter.');
|
throw new RPCError(errs.TYPE_ERROR, 'Invalid hex string.');
|
||||||
|
|
||||||
tx = MTX.fromRaw(data);
|
tx = fromRaw(MTX, data);
|
||||||
|
|
||||||
if (tx.outputs.length === 0)
|
if (tx.outputs.length === 0) {
|
||||||
throw new RPCError('TX must have at least one output.');
|
throw new RPCError(errs.INVALID_PARAMETER,
|
||||||
|
'TX must have at least one output.');
|
||||||
|
}
|
||||||
|
|
||||||
if (options) {
|
if (options) {
|
||||||
valid = new Validator([options]);
|
valid = new Validator([options]);
|
||||||
@ -158,7 +163,7 @@ RPC.prototype.fundRawTransaction = co(function* fundRawTransaction(args, help) {
|
|||||||
rate = valid.btc('feeRate');
|
rate = valid.btc('feeRate');
|
||||||
|
|
||||||
if (change)
|
if (change)
|
||||||
change = Address.fromBase58(change, this.network);
|
change = parseAddress(change, this.network);
|
||||||
}
|
}
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
@ -166,7 +171,11 @@ RPC.prototype.fundRawTransaction = co(function* fundRawTransaction(args, help) {
|
|||||||
changeAddress: change
|
changeAddress: change
|
||||||
};
|
};
|
||||||
|
|
||||||
yield wallet.fund(tx, options);
|
try {
|
||||||
|
yield wallet.fund(tx, options);
|
||||||
|
} catch (e) {
|
||||||
|
throw new RPCError(errs.WALLET_INSUFFICIENT_FUNDS, e.message);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
hex: tx.toRaw().toString('hex'),
|
hex: tx.toRaw().toString('hex'),
|
||||||
@ -185,7 +194,7 @@ RPC.prototype.resendWalletTransactions = co(function* resendWalletTransactions(a
|
|||||||
var i, tx, txs;
|
var i, tx, txs;
|
||||||
|
|
||||||
if (help || args.length !== 0)
|
if (help || args.length !== 0)
|
||||||
throw new RPCError('resendwallettransactions');
|
throw new RPCError(errs.MISC_ERROR, 'resendwallettransactions');
|
||||||
|
|
||||||
txs = yield wallet.resend();
|
txs = yield wallet.resend();
|
||||||
|
|
||||||
@ -199,7 +208,7 @@ RPC.prototype.resendWalletTransactions = co(function* resendWalletTransactions(a
|
|||||||
|
|
||||||
RPC.prototype.addMultisigAddress = co(function* addMultisigAddress(args, help) {
|
RPC.prototype.addMultisigAddress = co(function* addMultisigAddress(args, help) {
|
||||||
if (help || args.length < 2 || args.length > 3) {
|
if (help || args.length < 2 || args.length > 3) {
|
||||||
throw new RPCError('addmultisigaddress'
|
throw new RPCError(errs.MISC_ERROR, 'addmultisigaddress'
|
||||||
+ ' nrequired ["key",...] ( "account" )');
|
+ ' nrequired ["key",...] ( "account" )');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,7 +218,7 @@ RPC.prototype.addMultisigAddress = co(function* addMultisigAddress(args, help) {
|
|||||||
|
|
||||||
RPC.prototype.addWitnessAddress = co(function* addWitnessAddress(args, help) {
|
RPC.prototype.addWitnessAddress = co(function* addWitnessAddress(args, help) {
|
||||||
if (help || args.length < 1 || args.length > 1)
|
if (help || args.length < 1 || args.length > 1)
|
||||||
throw new RPCError('addwitnessaddress "address"');
|
throw new RPCError(errs.MISC_ERROR, 'addwitnessaddress "address"');
|
||||||
|
|
||||||
// Unlikely to be implemented.
|
// Unlikely to be implemented.
|
||||||
throw new Error('Not implemented.');
|
throw new Error('Not implemented.');
|
||||||
@ -220,7 +229,7 @@ RPC.prototype.backupWallet = co(function* backupWallet(args, help) {
|
|||||||
var dest = valid.str(0);
|
var dest = valid.str(0);
|
||||||
|
|
||||||
if (help || args.length !== 1 || !dest)
|
if (help || args.length !== 1 || !dest)
|
||||||
throw new RPCError('backupwallet "destination"');
|
throw new RPCError(errs.MISC_ERROR, 'backupwallet "destination"');
|
||||||
|
|
||||||
yield this.wdb.backup(dest);
|
yield this.wdb.backup(dest);
|
||||||
|
|
||||||
@ -235,15 +244,15 @@ RPC.prototype.dumpPrivKey = co(function* dumpPrivKey(args, help) {
|
|||||||
var ring;
|
var ring;
|
||||||
|
|
||||||
if (help || args.length !== 1)
|
if (help || args.length !== 1)
|
||||||
throw new RPCError('dumpprivkey "bitcoinaddress"');
|
throw new RPCError(errs.MISC_ERROR, 'dumpprivkey "bitcoinaddress"');
|
||||||
|
|
||||||
if (!hash)
|
if (!hash)
|
||||||
throw new RPCError('Invalid address.');
|
throw new RPCError(errs.INVALID_ADDRESS_OR_KEY, 'Invalid address.');
|
||||||
|
|
||||||
ring = yield wallet.getPrivateKey(hash);
|
ring = yield wallet.getPrivateKey(hash);
|
||||||
|
|
||||||
if (!ring)
|
if (!ring)
|
||||||
throw new RPCError('Key not found.');
|
throw new RPCError(errs.MISC_ERROR, 'Key not found.');
|
||||||
|
|
||||||
return ring.toSecret();
|
return ring.toSecret();
|
||||||
});
|
});
|
||||||
@ -256,10 +265,10 @@ RPC.prototype.dumpWallet = co(function* dumpWallet(args, help) {
|
|||||||
var i, tip, addr, fmt, str, out, hash, hashes, ring;
|
var i, tip, addr, fmt, str, out, hash, hashes, ring;
|
||||||
|
|
||||||
if (help || args.length !== 1)
|
if (help || args.length !== 1)
|
||||||
throw new RPCError('dumpwallet "filename"');
|
throw new RPCError(errs.MISC_ERROR, 'dumpwallet "filename"');
|
||||||
|
|
||||||
if (!file)
|
if (!file)
|
||||||
throw new RPCError('Invalid parameter.');
|
throw new RPCError(errs.TYPE_ERROR, 'Invalid parameter.');
|
||||||
|
|
||||||
tip = yield this.wdb.getTip();
|
tip = yield this.wdb.getTip();
|
||||||
|
|
||||||
@ -312,15 +321,21 @@ RPC.prototype.encryptWallet = co(function* encryptWallet(args, help) {
|
|||||||
var passphrase = valid.str(0, '');
|
var passphrase = valid.str(0, '');
|
||||||
|
|
||||||
if (!wallet.master.encrypted && (help || args.length !== 1))
|
if (!wallet.master.encrypted && (help || args.length !== 1))
|
||||||
throw new RPCError('encryptwallet "passphrase"');
|
throw new RPCError(errs.MISC_ERROR, 'encryptwallet "passphrase"');
|
||||||
|
|
||||||
if (wallet.master.encrypted)
|
if (wallet.master.encrypted) {
|
||||||
throw new RPCError('Already running with an encrypted wallet');
|
throw new RPCError(errs.WALLET_WRONG_ENC_STATE,
|
||||||
|
'Already running with an encrypted wallet.');
|
||||||
|
}
|
||||||
|
|
||||||
if (passphrase.length < 1)
|
if (passphrase.length < 1)
|
||||||
throw new RPCError('encryptwallet "passphrase"');
|
throw new RPCError(errs.MISC_ERROR, 'encryptwallet "passphrase"');
|
||||||
|
|
||||||
yield wallet.setPassphrase(passphrase);
|
try {
|
||||||
|
yield wallet.setPassphrase(passphrase);
|
||||||
|
} catch (e) {
|
||||||
|
throw new RPCError(errs.WALLET_ENCRYPTION_FAILED, 'Encryption failed.');
|
||||||
|
}
|
||||||
|
|
||||||
return 'wallet encrypted; we do not need to stop!';
|
return 'wallet encrypted; we do not need to stop!';
|
||||||
});
|
});
|
||||||
@ -332,7 +347,7 @@ RPC.prototype.getAccountAddress = co(function* getAccountAddress(args, help) {
|
|||||||
var account;
|
var account;
|
||||||
|
|
||||||
if (help || args.length !== 1)
|
if (help || args.length !== 1)
|
||||||
throw new RPCError('getaccountaddress "account"');
|
throw new RPCError(errs.MISC_ERROR, 'getaccountaddress "account"');
|
||||||
|
|
||||||
if (!name)
|
if (!name)
|
||||||
name = 'default';
|
name = 'default';
|
||||||
@ -353,10 +368,10 @@ RPC.prototype.getAccount = co(function* getAccount(args, help) {
|
|||||||
var path;
|
var path;
|
||||||
|
|
||||||
if (help || args.length !== 1)
|
if (help || args.length !== 1)
|
||||||
throw new RPCError('getaccount "bitcoinaddress"');
|
throw new RPCError(errs.MISC_ERROR, 'getaccount "bitcoinaddress"');
|
||||||
|
|
||||||
if (!hash)
|
if (!hash)
|
||||||
throw new RPCError('Invalid address.');
|
throw new RPCError(errs.TYPE_ERROR, 'Invalid address.');
|
||||||
|
|
||||||
path = yield wallet.getPath(hash);
|
path = yield wallet.getPath(hash);
|
||||||
|
|
||||||
@ -373,7 +388,7 @@ RPC.prototype.getAddressesByAccount = co(function* getAddressesByAccount(args, h
|
|||||||
var i, path, address, addrs, paths;
|
var i, path, address, addrs, paths;
|
||||||
|
|
||||||
if (help || args.length !== 1)
|
if (help || args.length !== 1)
|
||||||
throw new RPCError('getaddressesbyaccount "account"');
|
throw new RPCError(errs.MISC_ERROR, 'getaddressesbyaccount "account"');
|
||||||
|
|
||||||
if (name === '')
|
if (name === '')
|
||||||
name = 'default';
|
name = 'default';
|
||||||
@ -399,8 +414,10 @@ RPC.prototype.getBalance = co(function* getBalance(args, help) {
|
|||||||
var watchOnly = valid.bool(2, false);
|
var watchOnly = valid.bool(2, false);
|
||||||
var value, balance;
|
var value, balance;
|
||||||
|
|
||||||
if (help || args.length > 3)
|
if (help || args.length > 3) {
|
||||||
throw new RPCError('getbalance ( "account" minconf includeWatchonly )');
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
|
'getbalance ( "account" minconf includeWatchonly )');
|
||||||
|
}
|
||||||
|
|
||||||
if (name === '')
|
if (name === '')
|
||||||
name = 'default';
|
name = 'default';
|
||||||
@ -428,7 +445,7 @@ RPC.prototype.getNewAddress = co(function* getNewAddress(args, help) {
|
|||||||
var address;
|
var address;
|
||||||
|
|
||||||
if (help || args.length > 1)
|
if (help || args.length > 1)
|
||||||
throw new RPCError('getnewaddress ( "account" )');
|
throw new RPCError(errs.MISC_ERROR, 'getnewaddress ( "account" )');
|
||||||
|
|
||||||
if (name === '')
|
if (name === '')
|
||||||
name = 'default';
|
name = 'default';
|
||||||
@ -443,7 +460,7 @@ RPC.prototype.getRawChangeAddress = co(function* getRawChangeAddress(args, help)
|
|||||||
var address;
|
var address;
|
||||||
|
|
||||||
if (help || args.length > 1)
|
if (help || args.length > 1)
|
||||||
throw new RPCError('getrawchangeaddress');
|
throw new RPCError(errs.MISC_ERROR, 'getrawchangeaddress');
|
||||||
|
|
||||||
address = yield wallet.createChange();
|
address = yield wallet.createChange();
|
||||||
|
|
||||||
@ -461,8 +478,10 @@ RPC.prototype.getReceivedByAccount = co(function* getReceivedByAccount(args, hel
|
|||||||
var lastConf = -1;
|
var lastConf = -1;
|
||||||
var i, j, path, wtx, output, conf, hash, paths, txs;
|
var i, j, path, wtx, output, conf, hash, paths, txs;
|
||||||
|
|
||||||
if (help || args.length < 1 || args.length > 2)
|
if (help || args.length < 1 || args.length > 2) {
|
||||||
throw new RPCError('getreceivedbyaccount "account" ( minconf )');
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
|
'getreceivedbyaccount "account" ( minconf )');
|
||||||
|
}
|
||||||
|
|
||||||
if (name === '')
|
if (name === '')
|
||||||
name = 'default';
|
name = 'default';
|
||||||
@ -508,11 +527,13 @@ RPC.prototype.getReceivedByAddress = co(function* getReceivedByAddress(args, hel
|
|||||||
var total = 0;
|
var total = 0;
|
||||||
var i, j, wtx, output, txs;
|
var i, j, wtx, output, txs;
|
||||||
|
|
||||||
if (help || args.length < 1 || args.length > 2)
|
if (help || args.length < 1 || args.length > 2) {
|
||||||
throw new RPCError('getreceivedbyaddress "bitcoinaddress" ( minconf )');
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
|
'getreceivedbyaddress "bitcoinaddress" ( minconf )');
|
||||||
|
}
|
||||||
|
|
||||||
if (!hash)
|
if (!hash)
|
||||||
throw new RPCError('Invalid address');
|
throw new RPCError(errs.TYPE_ERROR, 'Invalid address');
|
||||||
|
|
||||||
txs = yield wallet.getHistory();
|
txs = yield wallet.getHistory();
|
||||||
|
|
||||||
@ -542,7 +563,7 @@ RPC.prototype._toWalletTX = co(function* _toWalletTX(wtx) {
|
|||||||
var i, member;
|
var i, member;
|
||||||
|
|
||||||
if (!details)
|
if (!details)
|
||||||
throw new RPCError('TX not found.');
|
throw new RPCError(errs.WALLET_ERROR, 'TX not found.');
|
||||||
|
|
||||||
for (i = 0; i < details.inputs.length; i++) {
|
for (i = 0; i < details.inputs.length; i++) {
|
||||||
member = details.inputs[i];
|
member = details.inputs[i];
|
||||||
@ -613,16 +634,18 @@ RPC.prototype.getTransaction = co(function* getTransaction(args, help) {
|
|||||||
var watchOnly = valid.bool(1, false);
|
var watchOnly = valid.bool(1, false);
|
||||||
var wtx;
|
var wtx;
|
||||||
|
|
||||||
if (help || args.length < 1 || args.length > 2)
|
if (help || args.length < 1 || args.length > 2) {
|
||||||
throw new RPCError('gettransaction "txid" ( includeWatchonly )');
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
|
'gettransaction "txid" ( includeWatchonly )');
|
||||||
|
}
|
||||||
|
|
||||||
if (!hash)
|
if (!hash)
|
||||||
throw new RPCError('Invalid parameter');
|
throw new RPCError(errs.TYPE_ERROR, 'Invalid parameter');
|
||||||
|
|
||||||
wtx = yield wallet.getTX(hash);
|
wtx = yield wallet.getTX(hash);
|
||||||
|
|
||||||
if (!wtx)
|
if (!wtx)
|
||||||
throw new RPCError('TX not found.');
|
throw new RPCError(errs.WALLET_ERROR, 'TX not found.');
|
||||||
|
|
||||||
return yield this._toWalletTX(wtx, watchOnly);
|
return yield this._toWalletTX(wtx, watchOnly);
|
||||||
});
|
});
|
||||||
@ -634,15 +657,15 @@ RPC.prototype.abandonTransaction = co(function* abandonTransaction(args, help) {
|
|||||||
var result;
|
var result;
|
||||||
|
|
||||||
if (help || args.length !== 1)
|
if (help || args.length !== 1)
|
||||||
throw new RPCError('abandontransaction "txid"');
|
throw new RPCError(errs.MISC_ERROR, 'abandontransaction "txid"');
|
||||||
|
|
||||||
if (!hash)
|
if (!hash)
|
||||||
throw new RPCError('Invalid parameter.');
|
throw new RPCError(errs.TYPE_ERROR, 'Invalid parameter.');
|
||||||
|
|
||||||
result = yield wallet.abandon(hash);
|
result = yield wallet.abandon(hash);
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
throw new RPCError('Transaction not in wallet.');
|
throw new RPCError(errs.WALLET_ERROR, 'Transaction not in wallet.');
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
@ -652,7 +675,7 @@ RPC.prototype.getUnconfirmedBalance = co(function* getUnconfirmedBalance(args, h
|
|||||||
var balance;
|
var balance;
|
||||||
|
|
||||||
if (help || args.length > 0)
|
if (help || args.length > 0)
|
||||||
throw new RPCError('getunconfirmedbalance');
|
throw new RPCError(errs.MISC_ERROR, 'getunconfirmedbalance');
|
||||||
|
|
||||||
balance = yield wallet.getBalance();
|
balance = yield wallet.getBalance();
|
||||||
|
|
||||||
@ -664,7 +687,7 @@ RPC.prototype.getWalletInfo = co(function* getWalletInfo(args, help) {
|
|||||||
var balance;
|
var balance;
|
||||||
|
|
||||||
if (help || args.length !== 0)
|
if (help || args.length !== 0)
|
||||||
throw new RPCError('getwalletinfo');
|
throw new RPCError(errs.MISC_ERROR, 'getwalletinfo');
|
||||||
|
|
||||||
balance = yield wallet.getBalance();
|
balance = yield wallet.getBalance();
|
||||||
|
|
||||||
@ -690,10 +713,12 @@ RPC.prototype.importPrivKey = co(function* importPrivKey(args, help) {
|
|||||||
var rescan = valid.bool(2, false);
|
var rescan = valid.bool(2, false);
|
||||||
var key;
|
var key;
|
||||||
|
|
||||||
if (help || args.length < 1 || args.length > 3)
|
if (help || args.length < 1 || args.length > 3) {
|
||||||
throw new RPCError('importprivkey "bitcoinprivkey" ( "label" rescan )');
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
|
'importprivkey "bitcoinprivkey" ( "label" rescan )');
|
||||||
|
}
|
||||||
|
|
||||||
key = KeyRing.fromSecret(secret, this.network);
|
key = parseSecret(secret, this.network);
|
||||||
|
|
||||||
yield wallet.importKey(0, key);
|
yield wallet.importKey(0, key);
|
||||||
|
|
||||||
@ -714,10 +739,10 @@ RPC.prototype.importWallet = co(function* importWallet(args, help) {
|
|||||||
var data, key;
|
var data, key;
|
||||||
|
|
||||||
if (help || args.length !== 1)
|
if (help || args.length !== 1)
|
||||||
throw new RPCError('importwallet "filename" ( rescan )');
|
throw new RPCError(errs.MISC_ERROR, 'importwallet "filename" ( rescan )');
|
||||||
|
|
||||||
if (fs.unsupported)
|
if (fs.unsupported)
|
||||||
throw new RPCError('FS not available.');
|
throw new RPCError(errs.INTERNAL_ERROR, 'FS not available.');
|
||||||
|
|
||||||
data = yield fs.readFile(file, 'utf8');
|
data = yield fs.readFile(file, 'utf8');
|
||||||
|
|
||||||
@ -735,9 +760,9 @@ RPC.prototype.importWallet = co(function* importWallet(args, help) {
|
|||||||
parts = line.split(/\s+/);
|
parts = line.split(/\s+/);
|
||||||
|
|
||||||
if (parts.length < 4)
|
if (parts.length < 4)
|
||||||
throw new RPCError('Malformed wallet.');
|
throw new RPCError(errs.DESERIALIZATION_ERROR, 'Malformed wallet.');
|
||||||
|
|
||||||
secret = KeyRing.fromSecret(parts[0], this.network);
|
secret = parseSecret(parts[0], this.network);
|
||||||
|
|
||||||
time = +parts[1];
|
time = +parts[1];
|
||||||
label = parts[2];
|
label = parts[2];
|
||||||
@ -765,21 +790,23 @@ RPC.prototype.importAddress = co(function* importAddress(args, help) {
|
|||||||
var p2sh = valid.bool(3, false);
|
var p2sh = valid.bool(3, false);
|
||||||
var script;
|
var script;
|
||||||
|
|
||||||
if (help || args.length < 1 || args.length > 4)
|
if (help || args.length < 1 || args.length > 4) {
|
||||||
throw new RPCError('importaddress "address" ( "label" rescan p2sh )');
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
|
'importaddress "address" ( "label" rescan p2sh )');
|
||||||
|
}
|
||||||
|
|
||||||
if (p2sh) {
|
if (p2sh) {
|
||||||
script = valid.buf(0);
|
script = valid.buf(0);
|
||||||
|
|
||||||
if (!script)
|
if (!script)
|
||||||
throw new RPCError('Invalid parameters.');
|
throw new RPCError(errs.TYPE_ERROR, 'Invalid parameters.');
|
||||||
|
|
||||||
script = Script.fromRaw(script);
|
script = fromRaw(Script, script);
|
||||||
script = Script.fromScripthash(script.hash160());
|
script = Script.fromScripthash(script.hash160());
|
||||||
|
|
||||||
addr = script.getAddress();
|
addr = script.getAddress();
|
||||||
} else {
|
} else {
|
||||||
addr = Address.fromBase58(addr, this.network);
|
addr = parseAddress(addr, this.network);
|
||||||
}
|
}
|
||||||
|
|
||||||
yield wallet.importAddress(0, addr);
|
yield wallet.importAddress(0, addr);
|
||||||
@ -797,11 +824,13 @@ RPC.prototype.importPubkey = co(function* importPubkey(args, help) {
|
|||||||
var rescan = valid.bool(2, false);
|
var rescan = valid.bool(2, false);
|
||||||
var key;
|
var key;
|
||||||
|
|
||||||
if (help || args.length < 1 || args.length > 4)
|
if (help || args.length < 1 || args.length > 4) {
|
||||||
throw new RPCError('importpubkey "pubkey" ( "label" rescan )');
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
|
'importpubkey "pubkey" ( "label" rescan )');
|
||||||
|
}
|
||||||
|
|
||||||
if (!data)
|
if (!data)
|
||||||
throw new RPCError('Invalid parameter.');
|
throw new RPCError(errs.TYPE_ERROR, 'Invalid parameter.');
|
||||||
|
|
||||||
key = KeyRing.fromPublic(data, this.network);
|
key = KeyRing.fromPublic(data, this.network);
|
||||||
|
|
||||||
@ -815,7 +844,7 @@ RPC.prototype.importPubkey = co(function* importPubkey(args, help) {
|
|||||||
|
|
||||||
RPC.prototype.keyPoolRefill = co(function* keyPoolRefill(args, help) {
|
RPC.prototype.keyPoolRefill = co(function* keyPoolRefill(args, help) {
|
||||||
if (help || args.length > 1)
|
if (help || args.length > 1)
|
||||||
throw new RPCError('keypoolrefill ( newsize )');
|
throw new RPCError(errs.MISC_ERROR, 'keypoolrefill ( newsize )');
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -827,8 +856,10 @@ RPC.prototype.listAccounts = co(function* listAccounts(args, help) {
|
|||||||
var map = {};
|
var map = {};
|
||||||
var i, accounts, account, balance, value;
|
var i, accounts, account, balance, value;
|
||||||
|
|
||||||
if (help || args.length > 2)
|
if (help || args.length > 2) {
|
||||||
throw new RPCError('listaccounts ( minconf includeWatchonly)');
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
|
'listaccounts ( minconf includeWatchonly)');
|
||||||
|
}
|
||||||
|
|
||||||
accounts = yield wallet.getAccounts();
|
accounts = yield wallet.getAccounts();
|
||||||
|
|
||||||
@ -852,7 +883,7 @@ RPC.prototype.listAccounts = co(function* listAccounts(args, help) {
|
|||||||
|
|
||||||
RPC.prototype.listAddressGroupings = co(function* listAddressGroupings(args, help) {
|
RPC.prototype.listAddressGroupings = co(function* listAddressGroupings(args, help) {
|
||||||
if (help)
|
if (help)
|
||||||
throw new RPCError('listaddressgroupings');
|
throw new RPCError(errs.MISC_ERROR, 'listaddressgroupings');
|
||||||
throw new Error('Not implemented.');
|
throw new Error('Not implemented.');
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -861,7 +892,7 @@ RPC.prototype.listLockUnspent = co(function* listLockUnspent(args, help) {
|
|||||||
var i, outpoints, outpoint, out;
|
var i, outpoints, outpoint, out;
|
||||||
|
|
||||||
if (help || args.length > 0)
|
if (help || args.length > 0)
|
||||||
throw new RPCError('listlockunspent');
|
throw new RPCError(errs.MISC_ERROR, 'listlockunspent');
|
||||||
|
|
||||||
outpoints = wallet.getLocked();
|
outpoints = wallet.getLocked();
|
||||||
out = [];
|
out = [];
|
||||||
@ -884,8 +915,8 @@ RPC.prototype.listReceivedByAccount = co(function* listReceivedByAccount(args, h
|
|||||||
var watchOnly = valid.bool(2, false);
|
var watchOnly = valid.bool(2, false);
|
||||||
|
|
||||||
if (help || args.length > 3) {
|
if (help || args.length > 3) {
|
||||||
throw new RPCError('listreceivedbyaccount'
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
+ ' ( minconf includeempty includeWatchonly )');
|
'listreceivedbyaccount ( minconf includeempty includeWatchonly )');
|
||||||
}
|
}
|
||||||
|
|
||||||
return yield this._listReceived(minconf, includeEmpty, watchOnly, true);
|
return yield this._listReceived(minconf, includeEmpty, watchOnly, true);
|
||||||
@ -898,8 +929,8 @@ RPC.prototype.listReceivedByAddress = co(function* listReceivedByAddress(args, h
|
|||||||
var watchOnly = valid.bool(2, false);
|
var watchOnly = valid.bool(2, false);
|
||||||
|
|
||||||
if (help || args.length > 3) {
|
if (help || args.length > 3) {
|
||||||
throw new RPCError('listreceivedbyaddress'
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
+ ' ( minconf includeempty includeWatchonly )');
|
'listreceivedbyaddress ( minconf includeempty includeWatchonly )');
|
||||||
}
|
}
|
||||||
|
|
||||||
return yield this._listReceived(minconf, includeEmpty, watchOnly, false);
|
return yield this._listReceived(minconf, includeEmpty, watchOnly, false);
|
||||||
@ -1017,8 +1048,8 @@ RPC.prototype.listSinceBlock = co(function* listSinceBlock(args, help) {
|
|||||||
var i, entry, highest, txs, wtx, json;
|
var i, entry, highest, txs, wtx, json;
|
||||||
|
|
||||||
if (help) {
|
if (help) {
|
||||||
throw new RPCError('listsinceblock'
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
+ ' ( "blockhash" target-confirmations includeWatchonly)');
|
'listsinceblock ( "blockhash" target-confirmations includeWatchonly)');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wallet.watchOnly !== watchOnly)
|
if (wallet.watchOnly !== watchOnly)
|
||||||
@ -1070,7 +1101,7 @@ RPC.prototype._toListTX = co(function* _toListTX(wtx) {
|
|||||||
var i, member, index;
|
var i, member, index;
|
||||||
|
|
||||||
if (!details)
|
if (!details)
|
||||||
throw new RPCError('TX not found.');
|
throw new RPCError(errs.WALLET_ERROR, 'TX not found.');
|
||||||
|
|
||||||
for (i = 0; i < details.inputs.length; i++) {
|
for (i = 0; i < details.inputs.length; i++) {
|
||||||
member = details.inputs[i];
|
member = details.inputs[i];
|
||||||
@ -1145,7 +1176,7 @@ RPC.prototype.listTransactions = co(function* listTransactions(args, help) {
|
|||||||
var i, txs, wtx, json;
|
var i, txs, wtx, json;
|
||||||
|
|
||||||
if (help || args.length > 4) {
|
if (help || args.length > 4) {
|
||||||
throw new RPCError(
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
'listtransactions ( "account" count from includeWatchonly)');
|
'listtransactions ( "account" count from includeWatchonly)');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1182,8 +1213,8 @@ RPC.prototype.listUnspent = co(function* listUnspent(args, help) {
|
|||||||
var i, depth, address, hash, coins, coin, ring;
|
var i, depth, address, hash, coins, coin, ring;
|
||||||
|
|
||||||
if (help || args.length > 3) {
|
if (help || args.length > 3) {
|
||||||
throw new RPCError('listunspent'
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
+ ' ( minconf maxconf ["address",...] )');
|
'listunspent ( minconf maxconf ["address",...] )');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addrs) {
|
if (addrs) {
|
||||||
@ -1193,10 +1224,10 @@ RPC.prototype.listUnspent = co(function* listUnspent(args, help) {
|
|||||||
hash = Address.getHash(address, 'hex');
|
hash = Address.getHash(address, 'hex');
|
||||||
|
|
||||||
if (!hash)
|
if (!hash)
|
||||||
throw new RPCError('Invalid address.');
|
throw new RPCError(errs.INVALID_ADDRESS_OR_KEY, 'Invalid address.');
|
||||||
|
|
||||||
if (map[hash])
|
if (map[hash])
|
||||||
throw new RPCError('Duplicate address.');
|
throw new RPCError(errs.INVALID_PARAMETER, 'Duplicate address.');
|
||||||
|
|
||||||
map[hash] = true;
|
map[hash] = true;
|
||||||
}
|
}
|
||||||
@ -1254,8 +1285,8 @@ RPC.prototype.lockUnspent = co(function* lockUnspent(args, help) {
|
|||||||
var i, output, outpoint, hash, index;
|
var i, output, outpoint, hash, index;
|
||||||
|
|
||||||
if (help || args.length < 1 || args.length > 2) {
|
if (help || args.length < 1 || args.length > 2) {
|
||||||
throw new RPCError('lockunspent'
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
+ ' unlock ([{"txid":"txid","vout":n},...])');
|
'lockunspent unlock ([{"txid":"txid","vout":n},...])');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.length === 1) {
|
if (args.length === 1) {
|
||||||
@ -1265,7 +1296,7 @@ RPC.prototype.lockUnspent = co(function* lockUnspent(args, help) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!outputs)
|
if (!outputs)
|
||||||
throw new RPCError('Invalid parameter.');
|
throw new RPCError(errs.TYPE_ERROR, 'Invalid parameter.');
|
||||||
|
|
||||||
for (i = 0; i < outputs.length; i++) {
|
for (i = 0; i < outputs.length; i++) {
|
||||||
output = outputs[i];
|
output = outputs[i];
|
||||||
@ -1274,7 +1305,7 @@ RPC.prototype.lockUnspent = co(function* lockUnspent(args, help) {
|
|||||||
index = valid.u32('vout');
|
index = valid.u32('vout');
|
||||||
|
|
||||||
if (hash == null || index == null)
|
if (hash == null || index == null)
|
||||||
throw new RPCError('Invalid parameter.');
|
throw new RPCError(errs.INVALID_PARAMETER, 'Invalid parameter.');
|
||||||
|
|
||||||
outpoint = new Outpoint();
|
outpoint = new Outpoint();
|
||||||
outpoint.hash = hash;
|
outpoint.hash = hash;
|
||||||
@ -1306,15 +1337,15 @@ RPC.prototype.sendFrom = co(function* sendFrom(args, help) {
|
|||||||
var options, tx;
|
var options, tx;
|
||||||
|
|
||||||
if (help || args.length < 3 || args.length > 6) {
|
if (help || args.length < 3 || args.length > 6) {
|
||||||
throw new RPCError('sendfrom'
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
+ ' "fromaccount" "tobitcoinaddress"'
|
'sendfrom "fromaccount" "tobitcoinaddress"'
|
||||||
+ ' amount ( minconf "comment" "comment-to" )');
|
+ ' amount ( minconf "comment" "comment-to" )');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!addr || value == null)
|
if (!addr || value == null)
|
||||||
throw new RPCError('Invalid parameter.');
|
throw new RPCError(errs.TYPE_ERROR, 'Invalid parameter.');
|
||||||
|
|
||||||
addr = Address.fromBase58(addr, this.network);
|
addr = parseAddress(addr, this.network);
|
||||||
|
|
||||||
if (name === '')
|
if (name === '')
|
||||||
name = 'default';
|
name = 'default';
|
||||||
@ -1348,8 +1379,8 @@ RPC.prototype.sendMany = co(function* sendMany(args, help) {
|
|||||||
var hash, output, options;
|
var hash, output, options;
|
||||||
|
|
||||||
if (help || args.length < 2 || args.length > 5) {
|
if (help || args.length < 2 || args.length > 5) {
|
||||||
throw new RPCError('sendmany'
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
+ ' "fromaccount" {"address":amount,...}'
|
'sendmany "fromaccount" {"address":amount,...}'
|
||||||
+ ' ( minconf "comment" ["address",...] )');
|
+ ' ( minconf "comment" ["address",...] )');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1357,7 +1388,7 @@ RPC.prototype.sendMany = co(function* sendMany(args, help) {
|
|||||||
name = 'default';
|
name = 'default';
|
||||||
|
|
||||||
if (!sendTo)
|
if (!sendTo)
|
||||||
throw new RPCError('Invalid parameter.');
|
throw new RPCError(errs.TYPE_ERROR, 'Invalid parameter.');
|
||||||
|
|
||||||
keys = Object.keys(sendTo);
|
keys = Object.keys(sendTo);
|
||||||
valid = new Validator([sendTo]);
|
valid = new Validator([sendTo]);
|
||||||
@ -1365,14 +1396,14 @@ RPC.prototype.sendMany = co(function* sendMany(args, help) {
|
|||||||
for (i = 0; i < keys.length; i++) {
|
for (i = 0; i < keys.length; i++) {
|
||||||
key = keys[i];
|
key = keys[i];
|
||||||
value = valid.btc(key);
|
value = valid.btc(key);
|
||||||
address = Address.fromBase58(key, this.network);
|
address = parseAddress(key, this.network);
|
||||||
hash = address.getHash('hex');
|
hash = address.getHash('hex');
|
||||||
|
|
||||||
if (value == null)
|
if (value == null)
|
||||||
throw new RPCError('Invalid parameter.');
|
throw new RPCError(errs.INVALID_PARAMETER, 'Invalid parameter.');
|
||||||
|
|
||||||
if (uniq[hash])
|
if (uniq[hash])
|
||||||
throw new RPCError('Invalid parameter.');
|
throw new RPCError(errs.INVALID_PARAMETER, 'Invalid parameter.');
|
||||||
|
|
||||||
uniq[hash] = true;
|
uniq[hash] = true;
|
||||||
|
|
||||||
@ -1403,16 +1434,15 @@ RPC.prototype.sendToAddress = co(function* sendToAddress(args, help) {
|
|||||||
var options, tx;
|
var options, tx;
|
||||||
|
|
||||||
if (help || args.length < 2 || args.length > 5) {
|
if (help || args.length < 2 || args.length > 5) {
|
||||||
throw new RPCError('sendtoaddress'
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
+ ' "bitcoinaddress" amount'
|
'sendtoaddress "bitcoinaddress" amount'
|
||||||
+ ' ( "comment" "comment-to"'
|
+ ' ( "comment" "comment-to" subtractfeefromamount )');
|
||||||
+ ' subtractfeefromamount )');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addr = Address.fromBase58(addr, this.network);
|
addr = parseAddress(addr, this.network);
|
||||||
|
|
||||||
if (!addr || value == null)
|
if (!addr || value == null)
|
||||||
throw new RPCError('Invalid parameter.');
|
throw new RPCError(errs.TYPE_ERROR, 'Invalid parameter.');
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
subtractFee: subtractFee,
|
subtractFee: subtractFee,
|
||||||
@ -1429,8 +1459,10 @@ RPC.prototype.sendToAddress = co(function* sendToAddress(args, help) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
RPC.prototype.setAccount = co(function* setAccount(args, help) {
|
RPC.prototype.setAccount = co(function* setAccount(args, help) {
|
||||||
if (help || args.length < 1 || args.length > 2)
|
if (help || args.length < 1 || args.length > 2) {
|
||||||
throw new RPCError('setaccount "bitcoinaddress" "account"');
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
|
'setaccount "bitcoinaddress" "account"');
|
||||||
|
}
|
||||||
|
|
||||||
// Impossible to implement in bcoin:
|
// Impossible to implement in bcoin:
|
||||||
throw new Error('Not implemented.');
|
throw new Error('Not implemented.');
|
||||||
@ -1441,10 +1473,10 @@ RPC.prototype.setTXFee = co(function* setTXFee(args, help) {
|
|||||||
var rate = valid.btc(0);
|
var rate = valid.btc(0);
|
||||||
|
|
||||||
if (help || args.length < 1 || args.length > 1)
|
if (help || args.length < 1 || args.length > 1)
|
||||||
throw new RPCError('settxfee amount');
|
throw new RPCError(errs.MISC_ERROR, 'settxfee amount');
|
||||||
|
|
||||||
if (rate == null)
|
if (rate == null)
|
||||||
throw new RPCError('Invalid parameter.');
|
throw new RPCError(errs.TYPE_ERROR, 'Invalid parameter.');
|
||||||
|
|
||||||
this.feeRate = rate;
|
this.feeRate = rate;
|
||||||
|
|
||||||
@ -1458,21 +1490,23 @@ RPC.prototype.signMessage = co(function* signMessage(args, help) {
|
|||||||
var msg = valid.str(1, '');
|
var msg = valid.str(1, '');
|
||||||
var sig, ring;
|
var sig, ring;
|
||||||
|
|
||||||
if (help || args.length !== 2)
|
if (help || args.length !== 2) {
|
||||||
throw new RPCError('signmessage "bitcoinaddress" "message"');
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
|
'signmessage "bitcoinaddress" "message"');
|
||||||
|
}
|
||||||
|
|
||||||
addr = Address.getHash(addr, 'hex');
|
addr = Address.getHash(addr, 'hex');
|
||||||
|
|
||||||
if (!addr)
|
if (!addr)
|
||||||
throw new RPCError('Invalid address.');
|
throw new RPCError(errs.INVALID_ADDRESS_OR_KEY, 'Invalid address.');
|
||||||
|
|
||||||
ring = yield wallet.getKey(addr);
|
ring = yield wallet.getKey(addr);
|
||||||
|
|
||||||
if (!ring)
|
if (!ring)
|
||||||
throw new RPCError('Address not found.');
|
throw new RPCError(errs.WALLET_ERROR, 'Address not found.');
|
||||||
|
|
||||||
if (!wallet.master.key)
|
if (!wallet.master.key)
|
||||||
throw new RPCError('Wallet is locked.');
|
throw new RPCError(errs.WALLET_UNLOCK_NEEDED, 'Wallet is locked.');
|
||||||
|
|
||||||
msg = new Buffer(MAGIC_STRING + msg, 'utf8');
|
msg = new Buffer(MAGIC_STRING + msg, 'utf8');
|
||||||
msg = crypto.hash256(msg);
|
msg = crypto.hash256(msg);
|
||||||
@ -1486,10 +1520,10 @@ RPC.prototype.walletLock = co(function* walletLock(args, help) {
|
|||||||
var wallet = this.wallet;
|
var wallet = this.wallet;
|
||||||
|
|
||||||
if (help || (wallet.master.encrypted && args.length !== 0))
|
if (help || (wallet.master.encrypted && args.length !== 0))
|
||||||
throw new RPCError('walletlock');
|
throw new RPCError(errs.MISC_ERROR, 'walletlock');
|
||||||
|
|
||||||
if (!wallet.master.encrypted)
|
if (!wallet.master.encrypted)
|
||||||
throw new RPCError('Wallet is not encrypted.');
|
throw new RPCError(errs.WALLET_WRONG_ENC_STATE, 'Wallet is not encrypted.');
|
||||||
|
|
||||||
yield wallet.lock();
|
yield wallet.lock();
|
||||||
|
|
||||||
@ -1503,15 +1537,15 @@ RPC.prototype.walletPassphraseChange = co(function* walletPassphraseChange(args,
|
|||||||
var new_ = valid.str(1, '');
|
var new_ = valid.str(1, '');
|
||||||
|
|
||||||
if (help || (wallet.master.encrypted && args.length !== 2)) {
|
if (help || (wallet.master.encrypted && args.length !== 2)) {
|
||||||
throw new RPCError('walletpassphrasechange'
|
throw new RPCError(errs.MISC_ERROR, 'walletpassphrasechange'
|
||||||
+ ' "oldpassphrase" "newpassphrase"');
|
+ ' "oldpassphrase" "newpassphrase"');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wallet.master.encrypted)
|
if (!wallet.master.encrypted)
|
||||||
throw new RPCError('Wallet is not encrypted.');
|
throw new RPCError(errs.WALLET_WRONG_ENC_STATE, 'Wallet is not encrypted.');
|
||||||
|
|
||||||
if (old.length < 1 || new_.length < 1)
|
if (old.length < 1 || new_.length < 1)
|
||||||
throw new RPCError('Invalid parameter');
|
throw new RPCError(errs.INVALID_PARAMETER, 'Invalid parameter');
|
||||||
|
|
||||||
yield wallet.setPassphrase(old, new_);
|
yield wallet.setPassphrase(old, new_);
|
||||||
|
|
||||||
@ -1524,17 +1558,19 @@ RPC.prototype.walletPassphrase = co(function* walletPassphrase(args, help) {
|
|||||||
var passphrase = valid.str(0, '');
|
var passphrase = valid.str(0, '');
|
||||||
var timeout = valid.u32(1);
|
var timeout = valid.u32(1);
|
||||||
|
|
||||||
if (help || (wallet.master.encrypted && args.length !== 2))
|
if (help || (wallet.master.encrypted && args.length !== 2)) {
|
||||||
throw new RPCError('walletpassphrase "passphrase" timeout');
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
|
'walletpassphrase "passphrase" timeout');
|
||||||
|
}
|
||||||
|
|
||||||
if (!wallet.master.encrypted)
|
if (!wallet.master.encrypted)
|
||||||
throw new RPCError('Wallet is not encrypted.');
|
throw new RPCError(errs.WALLET_WRONG_ENC_STATE, 'Wallet is not encrypted.');
|
||||||
|
|
||||||
if (passphrase.length < 1)
|
if (passphrase.length < 1)
|
||||||
throw new RPCError('Invalid parameter');
|
throw new RPCError(errs.INVALID_PARAMETER, 'Invalid parameter');
|
||||||
|
|
||||||
if (timeout == null)
|
if (timeout == null)
|
||||||
throw new RPCError('Invalid parameter');
|
throw new RPCError(errs.TYPE_ERROR, 'Invalid parameter');
|
||||||
|
|
||||||
yield wallet.unlock(passphrase, timeout);
|
yield wallet.unlock(passphrase, timeout);
|
||||||
|
|
||||||
@ -1548,27 +1584,27 @@ RPC.prototype.importPrunedFunds = co(function* importPrunedFunds(args, help) {
|
|||||||
var hash, height;
|
var hash, height;
|
||||||
|
|
||||||
if (help || args.length < 2 || args.length > 3) {
|
if (help || args.length < 2 || args.length > 3) {
|
||||||
throw new RPCError('importprunedfunds'
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
+ ' "rawtransaction" "txoutproof" ( "label" )');
|
'importprunedfunds "rawtransaction" "txoutproof" ( "label" )');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tx || !block)
|
if (!tx || !block)
|
||||||
throw new RPCError('Invalid parameter.');
|
throw new RPCError(errs.TYPE_ERROR, 'Invalid parameter.');
|
||||||
|
|
||||||
tx = TX.fromRaw(tx);
|
tx = fromRaw(TX, tx);
|
||||||
block = MerkleBlock.fromRaw(block);
|
block = fromRaw(MerkleBlock, block);
|
||||||
hash = block.hash('hex');
|
hash = block.hash('hex');
|
||||||
|
|
||||||
if (!block.verify())
|
if (!block.verify())
|
||||||
throw new RPCError('Invalid proof.');
|
throw new RPCError(errs.VERIFY_ERROR, 'Invalid proof.');
|
||||||
|
|
||||||
if (!block.hasTX(tx.hash('hex')))
|
if (!block.hasTX(tx.hash('hex')))
|
||||||
throw new RPCError('Invalid proof.');
|
throw new RPCError(errs.VERIFY_ERROR, 'Invalid proof.');
|
||||||
|
|
||||||
height = yield this.client.getEntry(hash);
|
height = yield this.client.getEntry(hash);
|
||||||
|
|
||||||
if (height === -1)
|
if (height === -1)
|
||||||
throw new RPCError('Invalid proof.');
|
throw new RPCError(errs.VERIFY_ERROR, 'Invalid proof.');
|
||||||
|
|
||||||
block = {
|
block = {
|
||||||
hash: hash,
|
hash: hash,
|
||||||
@ -1577,7 +1613,7 @@ RPC.prototype.importPrunedFunds = co(function* importPrunedFunds(args, help) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (!(yield this.wdb.addTX(tx, block)))
|
if (!(yield this.wdb.addTX(tx, block)))
|
||||||
throw new RPCError('No tracked address for TX.');
|
throw new RPCError(errs.WALLET_ERROR, 'No tracked address for TX.');
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
@ -1588,13 +1624,13 @@ RPC.prototype.removePrunedFunds = co(function* removePrunedFunds(args, help) {
|
|||||||
var hash = valid.hash(0);
|
var hash = valid.hash(0);
|
||||||
|
|
||||||
if (help || args.length !== 1)
|
if (help || args.length !== 1)
|
||||||
throw new RPCError('removeprunedfunds "txid"');
|
throw new RPCError(errs.MISC_ERROR, 'removeprunedfunds "txid"');
|
||||||
|
|
||||||
if (!hash)
|
if (!hash)
|
||||||
throw new RPCError('Invalid parameter.');
|
throw new RPCError(errs.TYPE_ERROR, 'Invalid parameter.');
|
||||||
|
|
||||||
if (!(yield wallet.remove(hash)))
|
if (!(yield wallet.remove(hash)))
|
||||||
throw new RPCError('Transaction not in wallet.');
|
throw new RPCError(errs.WALLET_ERROR, 'Transaction not in wallet.');
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
@ -1605,12 +1641,12 @@ RPC.prototype.selectWallet = co(function* selectWallet(args, help) {
|
|||||||
var wallet;
|
var wallet;
|
||||||
|
|
||||||
if (help || args.length !== 1)
|
if (help || args.length !== 1)
|
||||||
throw new RPCError('selectwallet "id"');
|
throw new RPCError(errs.MISC_ERROR, 'selectwallet "id"');
|
||||||
|
|
||||||
wallet = yield this.wdb.get(id);
|
wallet = yield this.wdb.get(id);
|
||||||
|
|
||||||
if (!wallet)
|
if (!wallet)
|
||||||
throw new RPCError('Wallet not found.');
|
throw new RPCError(errs.WALLET_ERROR, 'Wallet not found.');
|
||||||
|
|
||||||
this.wallet = wallet;
|
this.wallet = wallet;
|
||||||
|
|
||||||
@ -1619,7 +1655,7 @@ RPC.prototype.selectWallet = co(function* selectWallet(args, help) {
|
|||||||
|
|
||||||
RPC.prototype.getMemoryInfo = co(function* getMemoryInfo(args, help) {
|
RPC.prototype.getMemoryInfo = co(function* getMemoryInfo(args, help) {
|
||||||
if (help || args.length !== 0)
|
if (help || args.length !== 0)
|
||||||
throw new RPCError('getmemoryinfo');
|
throw new RPCError(errs.MISC_ERROR, 'getmemoryinfo');
|
||||||
|
|
||||||
return util.memoryUsage();
|
return util.memoryUsage();
|
||||||
});
|
});
|
||||||
@ -1629,13 +1665,41 @@ RPC.prototype.setLogLevel = co(function* setLogLevel(args, help) {
|
|||||||
var level = valid.str(0, '');
|
var level = valid.str(0, '');
|
||||||
|
|
||||||
if (help || args.length !== 1)
|
if (help || args.length !== 1)
|
||||||
throw new RPCError('setloglevel "level"');
|
throw new RPCError(errs.MISC_ERROR, 'setloglevel "level"');
|
||||||
|
|
||||||
this.logger.setLevel(level);
|
this.logger.setLevel(level);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helpers
|
||||||
|
*/
|
||||||
|
|
||||||
|
function fromRaw(ctor, raw) {
|
||||||
|
try {
|
||||||
|
return ctor.fromRaw(raw);
|
||||||
|
} catch (e) {
|
||||||
|
throw new RPCError(errs.DESERIALIZATION_ERROR, 'Deserialization error.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseAddress(raw, network) {
|
||||||
|
try {
|
||||||
|
return Address.fromBase58(raw, network);
|
||||||
|
} catch (e) {
|
||||||
|
throw new RPCError(errs.INVALID_ADDRESS_OR_KEY, 'Invalid address.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseSecret(raw, network) {
|
||||||
|
try {
|
||||||
|
return KeyRing.fromSecret(raw, network);
|
||||||
|
} catch (e) {
|
||||||
|
throw new RPCError(errs.INVALID_ADDRESS_OR_KEY, 'Invalid key.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
*/
|
*/
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user