diff --git a/bin/xud b/bin/xud
index 2b623ca32..c126eb769 100755
--- a/bin/xud
+++ b/bin/xud
@@ -47,6 +47,11 @@ const { argv } = require('yargs')
type: 'boolean',
default: undefined,
},
+ noencrypt: {
+ describe: 'Whether to disable xud nodekey encription',
+ type: 'boolean',
+ default: undefined,
+ },
nomatching: {
describe: 'Whether to disable matching within xud',
type: 'boolean',
diff --git a/docs/api.md b/docs/api.md
index f6e02f35d..8ab4a6cb2 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -17,6 +17,8 @@
- [ChannelBalanceResponse.BalancesEntry](#xudrpc.ChannelBalanceResponse.BalancesEntry)
- [ConnectRequest](#xudrpc.ConnectRequest)
- [ConnectResponse](#xudrpc.ConnectResponse)
+ - [CreateNodeRequest](#xudrpc.CreateNodeRequest)
+ - [CreateNodeResponse](#xudrpc.CreateNodeResponse)
- [DiscoverNodesRequest](#xudrpc.DiscoverNodesRequest)
- [DiscoverNodesResponse](#xudrpc.DiscoverNodesResponse)
- [ExecuteSwapRequest](#xudrpc.ExecuteSwapRequest)
@@ -61,6 +63,8 @@
- [SwapSuccess](#xudrpc.SwapSuccess)
- [UnbanRequest](#xudrpc.UnbanRequest)
- [UnbanResponse](#xudrpc.UnbanResponse)
+ - [UnlockNodeRequest](#xudrpc.UnlockNodeRequest)
+ - [UnlockNodeResponse](#xudrpc.UnlockNodeResponse)
- [AddCurrencyRequest.SwapClient](#xudrpc.AddCurrencyRequest.SwapClient)
- [OrderSide](#xudrpc.OrderSide)
@@ -68,6 +72,7 @@
- [Xud](#xudrpc.Xud)
+ - [XudInit](#xudrpc.XudInit)
- [Scalar Value Types](#scalar-value-types)
@@ -263,6 +268,36 @@
+
+
+### CreateNodeRequest
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| password | [string](#string) | | The password in utf-8 with which to encrypt the new xud node key as well as underlying client wallets such as lnd. |
+
+
+
+
+
+
+
+
+### CreateNodeResponse
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| seed_mnemonic | [string](#string) | repeated | |
+
+
+
+
+
+
### DiscoverNodesRequest
@@ -955,6 +990,31 @@
+
+
+
+### UnlockNodeRequest
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| password | [string](#string) | | The password in utf-8 with which to unlock an existing xud node key as well as underlying client wallets such as lnd. |
+
+
+
+
+
+
+
+
+### UnlockNodeResponse
+
+
+
+
+
+
@@ -1023,12 +1083,23 @@
| ExecuteSwap | [ExecuteSwapRequest](#xudrpc.ExecuteSwapRequest) | [SwapSuccess](#xudrpc.SwapSuccess) | Execute a swap on a maker peer order |
| RemoveCurrency | [RemoveCurrencyRequest](#xudrpc.RemoveCurrencyRequest) | [RemoveCurrencyResponse](#xudrpc.RemoveCurrencyResponse) | Removes a currency from the list of supported currencies. Only currencies that are not in use for any currently supported trading pairs may be removed. Once removed, the currency can no longer be used for any supported trading pairs. |
| RemovePair | [RemovePairRequest](#xudrpc.RemovePairRequest) | [RemovePairResponse](#xudrpc.RemovePairResponse) | Removes a trading pair from the list of currently supported trading pair. This call will effectively cancel any standing orders for that trading pair. Peers are informed when a pair is no longer supported so that they will know to stop sending orders for it. |
-| DiscoverNodes | [DiscoverNodesRequest](#xudrpc.DiscoverNodesRequest) | [DiscoverNodesResponse](#xudrpc.DiscoverNodesResponse) | Discover nodes from a specific peer. Apply new connection and return the list. |
+| DiscoverNodes | [DiscoverNodesRequest](#xudrpc.DiscoverNodesRequest) | [DiscoverNodesResponse](#xudrpc.DiscoverNodesResponse) | Discover nodes from a specific peer and apply new connections |
| Shutdown | [ShutdownRequest](#xudrpc.ShutdownRequest) | [ShutdownResponse](#xudrpc.ShutdownResponse) | Begin gracefully shutting down xud. |
| SubscribeOrders | [SubscribeOrdersRequest](#xudrpc.SubscribeOrdersRequest) | [OrderUpdate](#xudrpc.OrderUpdate) stream | Subscribes to orders being added to and removed from the order book. This call allows the client to maintain an up-to-date view of the order book. For example, an exchange that wants to show its users a real time view of the orders available to them would subscribe to this streaming call to be alerted as new orders are added and expired orders are removed. |
| SubscribeSwaps | [SubscribeSwapsRequest](#xudrpc.SubscribeSwapsRequest) | [SwapSuccess](#xudrpc.SwapSuccess) stream | Subscribes to completed swaps. By default, only swaps that are initiated by a remote peer are transmitted unless a flag is set to include swaps initiated by the local node. This call allows the client to get real-time notifications when its orders are filled by a peer. It can be used for tracking order executions, updating balances, and informing a trader when one of their orders is settled through the Exchange Union network. |
| SubscribeSwapFailures | [SubscribeSwapsRequest](#xudrpc.SubscribeSwapsRequest) | [SwapFailure](#xudrpc.SwapFailure) stream | Subscribes to failed swaps. By default, only swaps that are initiated by a remote peer are transmitted unless a flag is set to include swaps initiated by the local node. This call allows the client to get real-time notifications when swap attempts are failing. It can be used for status monitoring, debugging, and testing purposes. |
+
+
+
+### XudInit
+
+
+| Method Name | Request Type | Response Type | Description |
+| ----------- | ------------ | ------------- | ------------|
+| CreateNode | [CreateNodeRequest](#xudrpc.CreateNodeRequest) | [CreateNodeResponse](#xudrpc.CreateNodeResponse) | |
+| UnlockNode | [UnlockNodeRequest](#xudrpc.UnlockNodeRequest) | [UnlockNodeResponse](#xudrpc.UnlockNodeResponse) | |
+
diff --git a/lib/Config.ts b/lib/Config.ts
index ba2bb3492..45c3b1138 100644
--- a/lib/Config.ts
+++ b/lib/Config.ts
@@ -23,16 +23,19 @@ class Config {
public webproxy: { port: number, disable: boolean };
public instanceid = 0;
/** Whether to intialize a new database with default values. */
- public initdb: boolean;
+ public initdb = true;
/** The file path for the database, or ':memory:' if the database should be kept in memory. */
public dbpath: string;
/** Whether matching will be disabled */
- public nomatching: boolean;
+ public nomatching = false;
+ /** Whether a password should not be used to encrypt the xud key and underlying wallets. */
+ public noencrypt = true; // TODO: enable encryption by default
+
/**
* Whether to disable sanity checks that verify that the orders can possibly be swapped
* before adding them to the order book, can be enabled for testing & debugging purposes.
*/
- public nosanitychecks: boolean;
+ public nosanitychecks = false;
constructor() {
const platform = os.platform();
@@ -59,14 +62,11 @@ class Config {
}
// default configuration
- this.initdb = true;
- this.nomatching = false;
this.loglevel = this.getDefaultLogLevel();
this.logpath = this.getDefaultLogPath();
this.logdateformat = 'DD/MM/YYYY HH:mm:ss.SSS';
this.network = this.getDefaultNetwork();
this.dbpath = this.getDefaultDbPath();
- this.nosanitychecks = false;
this.p2p = {
listen: true,
diff --git a/lib/Xud.ts b/lib/Xud.ts
index 6c7a7fc14..e51e463b8 100644
--- a/lib/Xud.ts
+++ b/lib/Xud.ts
@@ -13,6 +13,8 @@ import { EventEmitter } from 'events';
import Swaps from './swaps/Swaps';
import HttpServer from './http/HttpServer';
import SwapClientManager from './swaps/SwapClientManager';
+import InitService from './service/InitService';
+import { promises as fs } from 'fs';
const version: string = require('../package.json').version;
@@ -65,8 +67,34 @@ class Xud extends EventEmitter {
this.db = new DB(loggers.db, this.config.dbpath);
await this.db.init(this.config.network, this.config.initdb);
- const nodeKey = await NodeKey.load(this.config.xudir, this.config.instanceid);
- this.logger.info(`Local nodePubKey is ${nodeKey.nodePubKey}`);
+ this.swapClientManager = new SwapClientManager(this.config, loggers);
+ await this.swapClientManager.init(this.db.models);
+
+ const nodeKeyPath = NodeKey.getPath(this.config.xudir, this.config.instanceid);
+ let nodeKey: NodeKey;
+ if (this.config.noencrypt) {
+ nodeKey = await NodeKey.load(nodeKeyPath);
+ } else {
+ const nodeKeyExists = await fs.access(nodeKeyPath).then(() => true).catch(() => false);
+ const initService = new InitService(this.swapClientManager, nodeKeyPath, nodeKeyExists);
+
+ const initRpcServer = new GrpcServer(loggers.rpc);
+ initRpcServer.addXudInitService(initService);
+ await initRpcServer.listen(
+ this.config.rpc.port,
+ this.config.rpc.host,
+ path.join(this.config.xudir, 'tls.cert'),
+ path.join(this.config.xudir, 'tls.key'),
+ );
+
+ this.logger.info('awaiting password...');
+ nodeKey = await new Promise((resolve) => {
+ initService.once('nodekey', resolve);
+ });
+ await initRpcServer.close();
+ }
+
+ this.logger.info(`Local nodePubKey is ${nodeKey.pubKey}`);
this.pool = new Pool({
nodeKey,
@@ -117,21 +145,15 @@ class Xud extends EventEmitter {
// start rpc server last
if (!this.config.rpc.disable) {
- this.rpcServer = new GrpcServer(loggers.rpc, this.service);
- const listening = await this.rpcServer.listen(
+ this.rpcServer = new GrpcServer(loggers.rpc);
+ this.rpcServer.addXudService(this.service);
+ await this.rpcServer.listen(
this.config.rpc.port,
this.config.rpc.host,
path.join(this.config.xudir, 'tls.cert'),
path.join(this.config.xudir, 'tls.key'),
);
- if (!listening) {
- // if rpc should be enabled but fails to start, treat it as a fatal error
- this.logger.error('Could not start gRPC server, exiting...');
- await this.shutdown();
- return;
- }
-
if (!this.config.webproxy.disable) {
this.grpcAPIProxy = new GrpcWebProxyServer(loggers.rpc);
try {
@@ -149,7 +171,7 @@ class Xud extends EventEmitter {
this.logger.warn('RPC server is disabled.');
}
} catch (err) {
- this.logger.error(err);
+ this.logger.error('Unexpected error during initialization', err);
}
}
diff --git a/lib/cli/command.ts b/lib/cli/command.ts
index 410402e97..067fd32fb 100644
--- a/lib/cli/command.ts
+++ b/lib/cli/command.ts
@@ -3,30 +3,30 @@ import fs from 'fs';
import os from 'os';
import path from 'path';
import grpc from 'grpc';
-import { XudClient } from '../proto/xudrpc_grpc_pb';
+import { XudClient, XudInitClient } from '../proto/xudrpc_grpc_pb';
+
+function getXudDir() {
+ switch (os.platform()) {
+ case 'win32': {
+ const homeDir = process.env.LOCALAPPDATA!;
+ return path.join(homeDir, 'Xud');
+ }
+ case 'darwin': {
+ const homeDir = process.env.HOME!;
+ return path.join(homeDir, '.xud');
+ }
+ default: {
+ const homeDir = process.env.HOME!;
+ return path.join(homeDir, '.xud');
+ }
+ }
+}
/**
* A generic function to instantiate an XU client.
* @param argv the command line arguments
*/
export const loadXudClient = (argv: Arguments) => {
- const getXudDir = () => {
- switch (os.platform()) {
- case 'win32': {
- const homeDir = process.env.LOCALAPPDATA!;
- return path.join(homeDir, 'Xud');
- }
- case 'darwin': {
- const homeDir = process.env.HOME!;
- return path.join(homeDir, '.xud');
- }
- default: {
- const homeDir = process.env.HOME!;
- return path.join(homeDir, '.xud');
- }
- }
- };
-
const certPath = argv.tlscertpath ? argv.tlscertpath : path.join(getXudDir(), 'tls.cert');
const cert = fs.readFileSync(certPath);
const credentials = grpc.credentials.createSsl(cert);
@@ -34,6 +34,14 @@ export const loadXudClient = (argv: Arguments) => {
return new XudClient(`${argv.rpchost}:${argv.rpcport}`, credentials);
};
+export const loadXudInitClient = (argv: Arguments) => {
+ const certPath = argv.tlscertpath ? argv.tlscertpath : path.join(getXudDir(), 'tls.cert');
+ const cert = fs.readFileSync(certPath);
+ const credentials = grpc.credentials.createSsl(cert);
+
+ return new XudInitClient(`${argv.rpchost}:${argv.rpcport}`, credentials);
+};
+
interface GrpcResponse {
toObject: Function;
}
diff --git a/lib/cli/commands/create.ts b/lib/cli/commands/create.ts
new file mode 100644
index 000000000..ec63948cc
--- /dev/null
+++ b/lib/cli/commands/create.ts
@@ -0,0 +1,20 @@
+import { Arguments } from 'yargs';
+import { callback, loadXudInitClient } from '../command';
+import { CreateNodeRequest } from '../../proto/xudrpc_pb';
+
+export const command = 'create ';
+
+export const describe = 'create an xud node';
+
+export const builder = {
+ password: {
+ description: 'password to encrypt xud key and wallets',
+ type: 'string',
+ },
+};
+
+export const handler = (argv: Arguments) => {
+ const request = new CreateNodeRequest();
+ request.setPassword(argv.password);
+ loadXudInitClient(argv).createNode(request, callback(argv));
+};
diff --git a/lib/cli/commands/unlock.ts b/lib/cli/commands/unlock.ts
new file mode 100644
index 000000000..cbd2e70d1
--- /dev/null
+++ b/lib/cli/commands/unlock.ts
@@ -0,0 +1,20 @@
+import { Arguments } from 'yargs';
+import { callback, loadXudInitClient } from '../command';
+import { UnlockNodeRequest } from '../../proto/xudrpc_pb';
+
+export const command = 'unlock ';
+
+export const describe = 'unlock an xud node';
+
+export const builder = {
+ password: {
+ description: 'password to decrypt xud key and wallets',
+ type: 'string',
+ },
+};
+
+export const handler = (argv: Arguments) => {
+ const request = new UnlockNodeRequest();
+ request.setPassword(argv.password);
+ loadXudInitClient(argv).unlockNode(request, callback(argv));
+};
diff --git a/lib/grpc/GrpcInitService.ts b/lib/grpc/GrpcInitService.ts
new file mode 100644
index 000000000..83e2fea9f
--- /dev/null
+++ b/lib/grpc/GrpcInitService.ts
@@ -0,0 +1,66 @@
+/* tslint:disable no-null-keyword */
+import grpc, { status } from 'grpc';
+import * as xudrpc from '../proto/xudrpc_pb';
+import { errorCodes as serviceErrorCodes } from '../service/errors';
+import InitService from 'lib/service/InitService';
+
+class GrpcInitService {
+ constructor(private initService: InitService) {}
+
+ private getGrpcError = (err: any) => {
+ // if we recognize this error, use a proper gRPC ServiceError with a descriptive and appropriate code
+ let code: grpc.status | undefined;
+ switch (err.code) {
+ case serviceErrorCodes.PENDING_CALL_CONFLICT:
+ code = status.RESOURCE_EXHAUSTED;
+ break;
+ case serviceErrorCodes.UNIMPLEMENTED:
+ code = status.UNIMPLEMENTED;
+ break;
+ }
+
+ // return a grpc error with the code if we've assigned one, otherwise pass along the caught error as UNKNOWN
+ const grpcError: grpc.ServiceError = {
+ code: code || status.UNKNOWN,
+ message: err.message,
+ name: err.name,
+ };
+
+ return grpcError;
+ }
+
+ /**
+ * See [[InitService.createNode]]
+ */
+ public createNode: grpc.handleUnaryCall = async (call, callback) => {
+ try {
+ const mnemonic = await this.initService.createNode(call.request.toObject());
+ const response = new xudrpc.CreateNodeResponse();
+ if (mnemonic) {
+ response.setSeedMnemonicList(mnemonic);
+ }
+
+ callback(null, response);
+ } catch (err) {
+ callback(this.getGrpcError(err), null);
+ }
+ this.initService.pendingCall = false;
+ }
+
+ /**
+ * See [[InitService.unlockNode]]
+ */
+ public unlockNode: grpc.handleUnaryCall = async (call, callback) => {
+ try {
+ await this.initService.unlockNode(call.request.toObject());
+ const response = new xudrpc.UnlockNodeResponse();
+
+ callback(null, response);
+ } catch (err) {
+ callback(this.getGrpcError(err), null);
+ }
+ this.initService.pendingCall = false;
+ }
+}
+
+export default GrpcInitService;
diff --git a/lib/grpc/GrpcServer.ts b/lib/grpc/GrpcServer.ts
index fddcaa4dd..a3e335ccf 100644
--- a/lib/grpc/GrpcServer.ts
+++ b/lib/grpc/GrpcServer.ts
@@ -6,57 +6,40 @@ import Logger from '../Logger';
import GrpcService from './GrpcService';
import Service from '../service/Service';
import errors from './errors';
-import { XudService } from '../proto/xudrpc_grpc_pb';
+import { XudService, XudInitService } from '../proto/xudrpc_grpc_pb';
import { promises as fs } from 'fs';
import serverProxy from './serverProxy';
+import InitService from 'lib/service/InitService';
+import GrpcInitService from './GrpcInitService';
class GrpcServer {
private server: any;
- private grpcService: GrpcService;
+ private grpcService?: GrpcService;
- constructor(private logger: Logger, service: Service) {
+ constructor(private logger: Logger) {
this.server = serverProxy(new grpc.Server());
- const grpcService = new GrpcService(logger, service);
- this.server.addService(XudService, {
- addCurrency: grpcService.addCurrency,
- addPair: grpcService.addPair,
- removeOrder: grpcService.removeOrder,
- channelBalance: grpcService.channelBalance,
- connect: grpcService.connect,
- ban: grpcService.ban,
- unban: grpcService.unban,
- executeSwap: grpcService.executeSwap,
- getInfo: grpcService.getInfo,
- getNodeInfo: grpcService.getNodeInfo,
- listOrders: grpcService.listOrders,
- listCurrencies: grpcService.listCurrencies,
- listPairs: grpcService.listPairs,
- listPeers: grpcService.listPeers,
- placeOrder: grpcService.placeOrder,
- placeOrderSync: grpcService.placeOrderSync,
- removeCurrency: grpcService.removeCurrency,
- removePair: grpcService.removePair,
- discoverNodes: grpcService.discoverNodes,
- shutdown: grpcService.shutdown,
- subscribeOrders: grpcService.subscribeOrders,
- subscribeSwapFailures: grpcService.subscribeSwapFailures,
- subscribeSwaps: grpcService.subscribeSwaps,
- });
-
- this.grpcService = grpcService;
-
this.server.use((ctx: any, next: any) => {
logger.debug(`received call ${ctx.service.path}`);
next();
});
}
+ public addXudInitService = (initService: InitService) => {
+ const grpcInitService = new GrpcInitService(initService);
+ this.server.addService(XudInitService, grpcInitService);
+ }
+
+ public addXudService = (service: Service) => {
+ this.grpcService = new GrpcService(this.logger, service);
+ this.server.addService(XudService, this.grpcService);
+ }
+
/**
* Start the server and begin listening on the provided port
* @returns true if the server started listening successfully, false otherwise
*/
- public listen = async (port: number, host: string, tlsCertPath: string, tlsKeyPath: string): Promise => {
+ public listen = async (port: number, host: string, tlsCertPath: string, tlsKeyPath: string): Promise => {
assert(Number.isInteger(port) && port > 1023 && port < 65536, 'port must be an integer between 1024 and 65535');
let certificate: Buffer;
@@ -84,19 +67,20 @@ class GrpcServer {
if (bindCode !== port) {
const error = errors.COULD_NOT_BIND(port.toString());
this.logger.error(error.message);
- return false;
+ throw error;
}
this.server.start();
this.logger.info(`gRPC server listening on ${host}:${port}`);
- return true;
}
/**
* Stop listening for requests
*/
public close = (): Promise => {
- this.grpcService.closeStreams();
+ if (this.grpcService) {
+ this.grpcService.closeStreams();
+ }
return new Promise((resolve) => {
this.server.tryShutdown(() => {
this.logger.info('GRPC server completed shutdown');
diff --git a/lib/http/HttpServer.ts b/lib/http/HttpServer.ts
index a2363fb09..d104356e7 100644
--- a/lib/http/HttpServer.ts
+++ b/lib/http/HttpServer.ts
@@ -82,7 +82,6 @@ class HttpServer {
/**
* Starts the server and begins listening on the provided port.
- * @returns true if the server started listening successfully, false otherwise
*/
public listen = async (port: number) => {
return new Promise((resolve, reject) => {
diff --git a/lib/lndclient/LndClient.ts b/lib/lndclient/LndClient.ts
index e5a149795..9f49d9e32 100644
--- a/lib/lndclient/LndClient.ts
+++ b/lib/lndclient/LndClient.ts
@@ -2,7 +2,7 @@ import grpc, { ChannelCredentials, ClientReadableStream } from 'grpc';
import Logger from '../Logger';
import SwapClient, { ClientStatus } from '../swaps/SwapClient';
import errors from './errors';
-import { LightningClient } from '../proto/lndrpc_grpc_pb';
+import { LightningClient, WalletUnlockerClient } from '../proto/lndrpc_grpc_pb';
import { InvoicesClient } from '../proto/lndinvoices_grpc_pb';
import * as lndrpc from '../proto/lndrpc_pb';
import * as lndinvoices from '../proto/lndinvoices_pb';
@@ -17,6 +17,10 @@ interface LightningMethodIndex extends LightningClient {
[methodName: string]: Function;
}
+interface WalletUnlockerMethodIndex extends WalletUnlockerClient {
+ [methodName: string]: Function;
+}
+
interface InvoicesMethodIndex extends InvoicesClient {
[methodName: string]: Function;
}
@@ -33,6 +37,7 @@ class LndClient extends SwapClient {
public readonly type = SwapClientType.Lnd;
public readonly cltvDelta: number;
private lightning!: LightningClient | LightningMethodIndex;
+ private walletUnlocker!: WalletUnlockerClient | InvoicesMethodIndex;
private invoices!: InvoicesClient | InvoicesMethodIndex;
private meta!: grpc.Metadata;
private uri!: string;
@@ -123,6 +128,22 @@ class LndClient extends SwapClient {
});
}
+ private unaryWalletUnlockerCall = (methodName: string, params: T): Promise => {
+ return new Promise((resolve, reject) => {
+ if (this.isDisabled()) {
+ reject(errors.LND_IS_DISABLED);
+ return;
+ }
+ (this.walletUnlocker as WalletUnlockerMethodIndex)[methodName](params, this.meta, (err: grpc.ServiceError, response: U) => {
+ if (err) {
+ reject(err);
+ } else {
+ resolve(response);
+ }
+ });
+ });
+ }
+
public getLndInfo = async (): Promise => {
let channels: ChannelCount | undefined;
let chains: Chain[] | undefined;
@@ -172,6 +193,7 @@ class LndClient extends SwapClient {
this.logger.info(`trying to verify connection to lnd at ${this.uri}`);
this.lightning = new LightningClient(this.uri, this.credentials);
this.invoices = new InvoicesClient(this.uri, this.credentials);
+ this.walletUnlocker = new WalletUnlockerClient(this.uri, this.credentials);
try {
const getInfoResponse = await this.getInfo();
@@ -192,9 +214,14 @@ class LndClient extends SwapClient {
this.logger.warn(`lnd is out of sync with chain, retrying in ${LndClient.RECONNECT_TIMER} ms`);
}
} catch (err) {
- this.logger.error(`could not verify connection to lnd at ${this.uri}, error: ${JSON.stringify(err)},
- retrying in ${LndClient.RECONNECT_TIMER} ms`);
- await this.setStatus(ClientStatus.Disconnected);
+ if (err.code === grpc.status.UNIMPLEMENTED) {
+ // if GetInfo is unimplemented, it means this lnd instance is online but locked
+ await this.setStatus(ClientStatus.WaitingUnlock);
+ } else {
+ this.logger.error(`could not verify connection to lnd at ${this.uri}, error: ${JSON.stringify(err)},
+ retrying in ${LndClient.RECONNECT_TIMER} ms`);
+ await this.setStatus(ClientStatus.Disconnected);
+ }
}
}
}
@@ -387,6 +414,34 @@ class LndClient extends SwapClient {
return this.unaryCall('sendToRouteSync', request);
}
+ public genSeed = async (): Promise => {
+ const genSeedResponse = await this.unaryWalletUnlockerCall(
+ 'genSeed', new lndrpc.GenSeedRequest(),
+ );
+ return genSeedResponse.toObject();
+ }
+
+ public initWallet = async (walletPassword: string, seedMnemonic: string[]): Promise => {
+ const request = new lndrpc.InitWalletRequest();
+ request.setCipherSeedMnemonicList(seedMnemonic);
+ request.setWalletPassword(walletPassword);
+ const initWalletResponse = await this.unaryWalletUnlockerCall(
+ 'initWallet', new lndrpc.InitWalletRequest(),
+ );
+ this.logger.info('wallet initialized');
+ return initWalletResponse.toObject();
+ }
+
+ public unlockWallet = async (walletPassword: string): Promise => {
+ const request = new lndrpc.UnlockWalletRequest();
+ request.setWalletPassword(walletPassword);
+ const unlockWalletResponse = await this.unaryWalletUnlockerCall(
+ 'unlockWallet', new lndrpc.UnlockWalletRequest(),
+ );
+ this.logger.info('wallet unlocked');
+ return unlockWalletResponse.toObject();
+ }
+
public addInvoice = async (rHash: string, amount: number) => {
const addHoldInvoiceRequest = new lndinvoices.AddHoldInvoiceRequest();
addHoldInvoiceRequest.setHash(hexToUint8Array(rHash));
diff --git a/lib/nodekey/NodeKey.ts b/lib/nodekey/NodeKey.ts
index aa9220613..5469c761b 100644
--- a/lib/nodekey/NodeKey.ts
+++ b/lib/nodekey/NodeKey.ts
@@ -1,32 +1,29 @@
-import CryptoJS from 'crypto-js';
import secp256k1 from 'secp256k1';
import { randomBytes } from '../utils/utils';
import { promises as fs } from 'fs';
+import { createCipheriv, createDecipheriv, createHash } from 'crypto';
/**
* A class representing an ECDSA public/private key pair that identifies an XU node on the network
* and can sign messages to prove their veracity.
*/
class NodeKey {
- private pubKeyStr: string;
-
- constructor(private privKey: Buffer) {
- const pubKey = secp256k1.publicKeyCreate(privKey);
- this.pubKeyStr = pubKey.toString('hex');
- }
+ /**
+ * The public key in hex string format.
+ */
+ public readonly pubKey: string;
- public get nodePubKey(): string {
- return this.pubKeyStr;
- }
+ private static ENCRYPTION_IV_LENGTH = 16;
- public get nodePrivKey(): Buffer {
- return this.privKey;
+ constructor(public readonly privKey: Buffer) {
+ const pubKey = secp256k1.publicKeyCreate(privKey);
+ this.pubKey = pubKey.toString('hex');
}
/**
* Generates a random NodeKey.
*/
- private static generate = async (): Promise => {
+ public static generate = async (): Promise => {
let privKey: Buffer;
do {
privKey = await randomBytes(32);
@@ -35,23 +32,33 @@ class NodeKey {
return new NodeKey(privKey);
}
+ private static getCipherKey = (password: string) => {
+ return createHash('sha256').update(password).digest();
+ }
+
/**
* Load a NodeKey from a file.
* @param path the path to the file
* @param password an optional password to decrypt the file
* @returns a NodeKey if a file containing a valid ECDSA private key exists at the given path
*/
- private static fromFile = async (path: string, password?: string): Promise => {
- let buf = await fs.readFile(path);
+ public static fromFile = async (path: string, password?: string): Promise => {
+ let privKey: Buffer;
+ const fileBuffer = await fs.readFile(path);
if (password) {
- const encryptedString = buf.toString('utf8');
- const decryptedString = CryptoJS.AES.decrypt(encryptedString, password).toString(CryptoJS.enc.Hex);
- buf = Buffer.from(decryptedString, 'hex');
+ // decrypt file using the password
+ // the first 16 bytes contain the initialization vector
+ const iv = fileBuffer.slice(0, NodeKey.ENCRYPTION_IV_LENGTH);
+ const key = NodeKey.getCipherKey(password);
+ const encrypted = fileBuffer.slice(NodeKey.ENCRYPTION_IV_LENGTH);
+ const decipher = createDecipheriv('aes-256-cbc', key, iv);
+ privKey = Buffer.concat([decipher.update(encrypted), decipher.final()]);
+ } else {
+ privKey = fileBuffer;
}
-
- if (secp256k1.privateKeyVerify(buf)) {
- return new NodeKey(buf);
+ if (secp256k1.privateKeyVerify(privKey)) {
+ return new NodeKey(privKey);
} else {
throw new Error(`${path} does not contain a valid ECDSA private key`);
}
@@ -60,11 +67,7 @@ class NodeKey {
/**
* Loads a node key from a file or creates one if none exists. See [[fromFile]] and [[generate]].
*/
- public static load = async (xudir: string, instanceId = 0): Promise => {
- const path: string = instanceId > 0
- ? `${xudir}/nodekey_${instanceId}.dat`
- : `${xudir}/nodekey.dat`;
-
+ public static load = async (path: string): Promise => {
let nodeKey: NodeKey;
try {
nodeKey = await NodeKey.fromFile(path);
@@ -80,6 +83,12 @@ class NodeKey {
return nodeKey;
}
+ public static getPath = (xudir: string, instanceId = 0) => {
+ return instanceId > 0
+ ? `${xudir}/nodekey_${instanceId}.dat`
+ : `${xudir}/nodekey.dat`;
+ }
+
/**
* Signs a message with the private key.
* @param msg the data to sign
@@ -94,15 +103,17 @@ class NodeKey {
* @param path the path at which to save the file
* @param password an optional password parameter for encrypting the private key
*/
- private toFile = (path: string, password?: string): Promise => {
+ public toFile = async (path: string, password?: string): Promise => {
let buf: Buffer | CryptoJS.WordArray;
if (password) {
- const lwa = CryptoJS.lib.WordArray.create(this.privKey.buffer);
- buf = CryptoJS.AES.encrypt(lwa, password);
+ const iv = await randomBytes(NodeKey.ENCRYPTION_IV_LENGTH);
+ const key = NodeKey.getCipherKey(password);
+ const cipher = createCipheriv('aes-256-cbc', key, iv);
+ buf = Buffer.concat([iv, cipher.update(this.privKey), cipher.final()]);
} else {
buf = this.privKey;
}
- return fs.writeFile(path, buf);
+ await fs.writeFile(path, buf);
}
}
diff --git a/lib/p2p/Peer.ts b/lib/p2p/Peer.ts
index 69a5cddf3..6f77f448e 100644
--- a/lib/p2p/Peer.ts
+++ b/lib/p2p/Peer.ts
@@ -781,11 +781,11 @@ class Peer extends EventEmitter {
assert(this.expectedNodePubKey);
await this.initSession(ownNodeState, nodeKey, this.expectedNodePubKey!);
sessionInit = await this.waitSessionInit();
- await this.authenticateSessionInit(sessionInit, nodeKey.nodePubKey, this.expectedNodePubKey);
+ await this.authenticateSessionInit(sessionInit, nodeKey.pubKey, this.expectedNodePubKey);
} else {
// inbound handshake
sessionInit = await this.waitSessionInit();
- await this.authenticateSessionInit(sessionInit, nodeKey.nodePubKey);
+ await this.authenticateSessionInit(sessionInit, nodeKey.pubKey);
}
return sessionInit;
}
@@ -852,7 +852,7 @@ class Peer extends EventEmitter {
const msg = stringify(body);
const msgHash = createHash('sha256').update(msg).digest();
- const { signature } = secp256k1.sign(msgHash, nodeKey.nodePrivKey);
+ const { signature } = secp256k1.sign(msgHash, nodeKey.privKey);
body = { ...body, sign: signature.toString('hex') };
diff --git a/lib/p2p/Pool.ts b/lib/p2p/Pool.ts
index a1f9e7227..4f45737f3 100644
--- a/lib/p2p/Pool.ts
+++ b/lib/p2p/Pool.ts
@@ -107,7 +107,7 @@ class Pool extends EventEmitter {
this.nodeState = {
version,
- nodePubKey: nodeKey.nodePubKey,
+ nodePubKey: nodeKey.pubKey,
addresses: [],
pairs: [],
raidenAddress: '',
diff --git a/lib/proto/xudrpc.swagger.json b/lib/proto/xudrpc.swagger.json
index c3d2c6589..6b935e93b 100644
--- a/lib/proto/xudrpc.swagger.json
+++ b/lib/proto/xudrpc.swagger.json
@@ -21,7 +21,7 @@
"operationId": "AddCurrency",
"responses": {
"200": {
- "description": "A successful response.",
+ "description": "",
"schema": {
"$ref": "#/definitions/xudrpcAddCurrencyResponse"
}
@@ -48,7 +48,7 @@
"operationId": "AddPair",
"responses": {
"200": {
- "description": "A successful response.",
+ "description": "",
"schema": {
"$ref": "#/definitions/xudrpcAddPairResponse"
}
@@ -75,7 +75,7 @@
"operationId": "Ban",
"responses": {
"200": {
- "description": "A successful response.",
+ "description": "",
"schema": {
"$ref": "#/definitions/xudrpcBanResponse"
}
@@ -102,7 +102,7 @@
"operationId": "ChannelBalance",
"responses": {
"200": {
- "description": "A successful response.",
+ "description": "",
"schema": {
"$ref": "#/definitions/xudrpcChannelBalanceResponse"
}
@@ -128,7 +128,7 @@
"operationId": "Connect",
"responses": {
"200": {
- "description": "A successful response.",
+ "description": "",
"schema": {
"$ref": "#/definitions/xudrpcConnectResponse"
}
@@ -155,7 +155,7 @@
"operationId": "ListCurrencies",
"responses": {
"200": {
- "description": "A successful response.",
+ "description": "",
"schema": {
"$ref": "#/definitions/xudrpcListCurrenciesResponse"
}
@@ -168,11 +168,11 @@
},
"/v1/discovernodes": {
"post": {
- "summary": "Discover nodes from a specific peer. Apply new connection and return the list.",
+ "summary": "Discover nodes from a specific peer and apply new connections",
"operationId": "DiscoverNodes",
"responses": {
"200": {
- "description": "A successful response.",
+ "description": "",
"schema": {
"$ref": "#/definitions/xudrpcDiscoverNodesResponse"
}
@@ -199,7 +199,7 @@
"operationId": "ExecuteSwap",
"responses": {
"200": {
- "description": "A successful response.",
+ "description": "",
"schema": {
"$ref": "#/definitions/xudrpcSwapSuccess"
}
@@ -226,7 +226,7 @@
"operationId": "GetInfo",
"responses": {
"200": {
- "description": "A successful response.",
+ "description": "",
"schema": {
"$ref": "#/definitions/xudrpcGetInfoResponse"
}
@@ -243,7 +243,7 @@
"operationId": "GetNodeInfo",
"responses": {
"200": {
- "description": "A successful response.",
+ "description": "",
"schema": {
"$ref": "#/definitions/xudrpcGetNodeInfoResponse"
}
@@ -269,7 +269,7 @@
"operationId": "ListOrders",
"responses": {
"200": {
- "description": "A successful response.",
+ "description": "",
"schema": {
"$ref": "#/definitions/xudrpcListOrdersResponse"
}
@@ -311,7 +311,7 @@
"operationId": "ListPairs",
"responses": {
"200": {
- "description": "A successful response.",
+ "description": "",
"schema": {
"$ref": "#/definitions/xudrpcListPairsResponse"
}
@@ -328,7 +328,7 @@
"operationId": "ListPeers",
"responses": {
"200": {
- "description": "A successful response.",
+ "description": "",
"schema": {
"$ref": "#/definitions/xudrpcListPeersResponse"
}
@@ -345,9 +345,9 @@
"operationId": "PlaceOrder",
"responses": {
"200": {
- "description": "A successful response.(streaming responses)",
+ "description": "(streaming responses)",
"schema": {
- "$ref": "#/x-stream-definitions/xudrpcPlaceOrderEvent"
+ "$ref": "#/definitions/xudrpcPlaceOrderEvent"
}
}
},
@@ -372,7 +372,7 @@
"operationId": "PlaceOrderSync",
"responses": {
"200": {
- "description": "A successful response.",
+ "description": "",
"schema": {
"$ref": "#/definitions/xudrpcPlaceOrderResponse"
}
@@ -399,7 +399,7 @@
"operationId": "RemoveCurrency",
"responses": {
"200": {
- "description": "A successful response.",
+ "description": "",
"schema": {
"$ref": "#/definitions/xudrpcRemoveCurrencyResponse"
}
@@ -426,7 +426,7 @@
"operationId": "RemoveOrder",
"responses": {
"200": {
- "description": "A successful response.",
+ "description": "",
"schema": {
"$ref": "#/definitions/xudrpcRemoveOrderResponse"
}
@@ -453,7 +453,7 @@
"operationId": "RemovePair",
"responses": {
"200": {
- "description": "A successful response.",
+ "description": "",
"schema": {
"$ref": "#/definitions/xudrpcRemovePairResponse"
}
@@ -480,7 +480,7 @@
"operationId": "Shutdown",
"responses": {
"200": {
- "description": "A successful response.",
+ "description": "",
"schema": {
"$ref": "#/definitions/xudrpcShutdownResponse"
}
@@ -507,9 +507,9 @@
"operationId": "SubscribeOrders",
"responses": {
"200": {
- "description": "A successful response.(streaming responses)",
+ "description": "(streaming responses)",
"schema": {
- "$ref": "#/x-stream-definitions/xudrpcOrderUpdate"
+ "$ref": "#/definitions/xudrpcOrderUpdate"
}
}
},
@@ -534,9 +534,9 @@
"operationId": "SubscribeSwapFailures",
"responses": {
"200": {
- "description": "A successful response.(streaming responses)",
+ "description": "(streaming responses)",
"schema": {
- "$ref": "#/x-stream-definitions/xudrpcSwapFailure"
+ "$ref": "#/definitions/xudrpcSwapFailure"
}
}
},
@@ -561,9 +561,9 @@
"operationId": "SubscribeSwaps",
"responses": {
"200": {
- "description": "A successful response.(streaming responses)",
+ "description": "(streaming responses)",
"schema": {
- "$ref": "#/x-stream-definitions/xudrpcSwapSuccess"
+ "$ref": "#/definitions/xudrpcSwapSuccess"
}
}
},
@@ -588,7 +588,7 @@
"operationId": "Unban",
"responses": {
"200": {
- "description": "A successful response.",
+ "description": "",
"schema": {
"$ref": "#/definitions/xudrpcUnbanResponse"
}
@@ -627,43 +627,6 @@
],
"default": "TAKER"
},
- "protobufAny": {
- "type": "object",
- "properties": {
- "type_url": {
- "type": "string"
- },
- "value": {
- "type": "string",
- "format": "byte"
- }
- }
- },
- "runtimeStreamError": {
- "type": "object",
- "properties": {
- "grpc_code": {
- "type": "integer",
- "format": "int32"
- },
- "http_code": {
- "type": "integer",
- "format": "int32"
- },
- "message": {
- "type": "string"
- },
- "http_status": {
- "type": "string"
- },
- "details": {
- "type": "array",
- "items": {
- "$ref": "#/definitions/protobufAny"
- }
- }
- }
- },
"xudrpcAddCurrencyRequest": {
"type": "object",
"properties": {
@@ -769,6 +732,17 @@
"xudrpcConnectResponse": {
"type": "object"
},
+ "xudrpcCreateNodeResponse": {
+ "type": "object",
+ "properties": {
+ "seed_mnemonic": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
"xudrpcDiscoverNodesRequest": {
"type": "object",
"properties": {
@@ -1398,56 +1372,9 @@
},
"xudrpcUnbanResponse": {
"type": "object"
- }
- },
- "x-stream-definitions": {
- "xudrpcOrderUpdate": {
- "type": "object",
- "properties": {
- "result": {
- "$ref": "#/definitions/xudrpcOrderUpdate"
- },
- "error": {
- "$ref": "#/definitions/runtimeStreamError"
- }
- },
- "title": "Stream result of xudrpcOrderUpdate"
- },
- "xudrpcPlaceOrderEvent": {
- "type": "object",
- "properties": {
- "result": {
- "$ref": "#/definitions/xudrpcPlaceOrderEvent"
- },
- "error": {
- "$ref": "#/definitions/runtimeStreamError"
- }
- },
- "title": "Stream result of xudrpcPlaceOrderEvent"
- },
- "xudrpcSwapFailure": {
- "type": "object",
- "properties": {
- "result": {
- "$ref": "#/definitions/xudrpcSwapFailure"
- },
- "error": {
- "$ref": "#/definitions/runtimeStreamError"
- }
- },
- "title": "Stream result of xudrpcSwapFailure"
},
- "xudrpcSwapSuccess": {
- "type": "object",
- "properties": {
- "result": {
- "$ref": "#/definitions/xudrpcSwapSuccess"
- },
- "error": {
- "$ref": "#/definitions/runtimeStreamError"
- }
- },
- "title": "Stream result of xudrpcSwapSuccess"
+ "xudrpcUnlockNodeResponse": {
+ "type": "object"
}
}
}
diff --git a/lib/proto/xudrpc_grpc_pb.d.ts b/lib/proto/xudrpc_grpc_pb.d.ts
index 696f25352..a849c0769 100644
--- a/lib/proto/xudrpc_grpc_pb.d.ts
+++ b/lib/proto/xudrpc_grpc_pb.d.ts
@@ -7,6 +7,56 @@ import * as grpc from "grpc";
import * as xudrpc_pb from "./xudrpc_pb";
import * as annotations_pb from "./annotations_pb";
+interface IXudInitService extends grpc.ServiceDefinition {
+ createNode: IXudInitService_ICreateNode;
+ unlockNode: IXudInitService_IUnlockNode;
+}
+
+interface IXudInitService_ICreateNode extends grpc.MethodDefinition {
+ path: string; // "/xudrpc.XudInit/CreateNode"
+ requestStream: boolean; // false
+ responseStream: boolean; // false
+ requestSerialize: grpc.serialize;
+ requestDeserialize: grpc.deserialize;
+ responseSerialize: grpc.serialize;
+ responseDeserialize: grpc.deserialize;
+}
+interface IXudInitService_IUnlockNode extends grpc.MethodDefinition {
+ path: string; // "/xudrpc.XudInit/UnlockNode"
+ requestStream: boolean; // false
+ responseStream: boolean; // false
+ requestSerialize: grpc.serialize;
+ requestDeserialize: grpc.deserialize;
+ responseSerialize: grpc.serialize;
+ responseDeserialize: grpc.deserialize;
+}
+
+export const XudInitService: IXudInitService;
+
+export interface IXudInitServer {
+ createNode: grpc.handleUnaryCall;
+ unlockNode: grpc.handleUnaryCall;
+}
+
+export interface IXudInitClient {
+ createNode(request: xudrpc_pb.CreateNodeRequest, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.CreateNodeResponse) => void): grpc.ClientUnaryCall;
+ createNode(request: xudrpc_pb.CreateNodeRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.CreateNodeResponse) => void): grpc.ClientUnaryCall;
+ createNode(request: xudrpc_pb.CreateNodeRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.CreateNodeResponse) => void): grpc.ClientUnaryCall;
+ unlockNode(request: xudrpc_pb.UnlockNodeRequest, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.UnlockNodeResponse) => void): grpc.ClientUnaryCall;
+ unlockNode(request: xudrpc_pb.UnlockNodeRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.UnlockNodeResponse) => void): grpc.ClientUnaryCall;
+ unlockNode(request: xudrpc_pb.UnlockNodeRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.UnlockNodeResponse) => void): grpc.ClientUnaryCall;
+}
+
+export class XudInitClient extends grpc.Client implements IXudInitClient {
+ constructor(address: string, credentials: grpc.ChannelCredentials, options?: object);
+ public createNode(request: xudrpc_pb.CreateNodeRequest, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.CreateNodeResponse) => void): grpc.ClientUnaryCall;
+ public createNode(request: xudrpc_pb.CreateNodeRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.CreateNodeResponse) => void): grpc.ClientUnaryCall;
+ public createNode(request: xudrpc_pb.CreateNodeRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.CreateNodeResponse) => void): grpc.ClientUnaryCall;
+ public unlockNode(request: xudrpc_pb.UnlockNodeRequest, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.UnlockNodeResponse) => void): grpc.ClientUnaryCall;
+ public unlockNode(request: xudrpc_pb.UnlockNodeRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.UnlockNodeResponse) => void): grpc.ClientUnaryCall;
+ public unlockNode(request: xudrpc_pb.UnlockNodeRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: xudrpc_pb.UnlockNodeResponse) => void): grpc.ClientUnaryCall;
+}
+
interface IXudService extends grpc.ServiceDefinition {
addCurrency: IXudService_IAddCurrency;
addPair: IXudService_IAddPair;
diff --git a/lib/proto/xudrpc_grpc_pb.js b/lib/proto/xudrpc_grpc_pb.js
index cc56a5a81..910c13361 100644
--- a/lib/proto/xudrpc_grpc_pb.js
+++ b/lib/proto/xudrpc_grpc_pb.js
@@ -136,6 +136,28 @@ function deserialize_xudrpc_ConnectResponse(buffer_arg) {
return xudrpc_pb.ConnectResponse.deserializeBinary(new Uint8Array(buffer_arg));
}
+function serialize_xudrpc_CreateNodeRequest(arg) {
+ if (!(arg instanceof xudrpc_pb.CreateNodeRequest)) {
+ throw new Error('Expected argument of type xudrpc.CreateNodeRequest');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_xudrpc_CreateNodeRequest(buffer_arg) {
+ return xudrpc_pb.CreateNodeRequest.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_xudrpc_CreateNodeResponse(arg) {
+ if (!(arg instanceof xudrpc_pb.CreateNodeResponse)) {
+ throw new Error('Expected argument of type xudrpc.CreateNodeResponse');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_xudrpc_CreateNodeResponse(buffer_arg) {
+ return xudrpc_pb.CreateNodeResponse.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
function serialize_xudrpc_DiscoverNodesRequest(arg) {
if (!(arg instanceof xudrpc_pb.DiscoverNodesRequest)) {
throw new Error('Expected argument of type xudrpc.DiscoverNodesRequest');
@@ -499,7 +521,55 @@ function deserialize_xudrpc_UnbanResponse(buffer_arg) {
return xudrpc_pb.UnbanResponse.deserializeBinary(new Uint8Array(buffer_arg));
}
+function serialize_xudrpc_UnlockNodeRequest(arg) {
+ if (!(arg instanceof xudrpc_pb.UnlockNodeRequest)) {
+ throw new Error('Expected argument of type xudrpc.UnlockNodeRequest');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_xudrpc_UnlockNodeRequest(buffer_arg) {
+ return xudrpc_pb.UnlockNodeRequest.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_xudrpc_UnlockNodeResponse(arg) {
+ if (!(arg instanceof xudrpc_pb.UnlockNodeResponse)) {
+ throw new Error('Expected argument of type xudrpc.UnlockNodeResponse');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_xudrpc_UnlockNodeResponse(buffer_arg) {
+ return xudrpc_pb.UnlockNodeResponse.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+
+var XudInitService = exports.XudInitService = {
+ createNode: {
+ path: '/xudrpc.XudInit/CreateNode',
+ requestStream: false,
+ responseStream: false,
+ requestType: xudrpc_pb.CreateNodeRequest,
+ responseType: xudrpc_pb.CreateNodeResponse,
+ requestSerialize: serialize_xudrpc_CreateNodeRequest,
+ requestDeserialize: deserialize_xudrpc_CreateNodeRequest,
+ responseSerialize: serialize_xudrpc_CreateNodeResponse,
+ responseDeserialize: deserialize_xudrpc_CreateNodeResponse,
+ },
+ unlockNode: {
+ path: '/xudrpc.XudInit/UnlockNode',
+ requestStream: false,
+ responseStream: false,
+ requestType: xudrpc_pb.UnlockNodeRequest,
+ responseType: xudrpc_pb.UnlockNodeResponse,
+ requestSerialize: serialize_xudrpc_UnlockNodeRequest,
+ requestDeserialize: deserialize_xudrpc_UnlockNodeRequest,
+ responseSerialize: serialize_xudrpc_UnlockNodeResponse,
+ responseDeserialize: deserialize_xudrpc_UnlockNodeResponse,
+ },
+};
+exports.XudInitClient = grpc.makeGenericClientConstructor(XudInitService);
var XudService = exports.XudService = {
// Adds a currency to the list of supported currencies. Once added, the currency may be used for
// new trading pairs.
@@ -735,7 +805,7 @@ var XudService = exports.XudService = {
responseSerialize: serialize_xudrpc_RemovePairResponse,
responseDeserialize: deserialize_xudrpc_RemovePairResponse,
},
- // Discover nodes from a specific peer. Apply new connection and return the list.
+ // Discover nodes from a specific peer and apply new connections
discoverNodes: {
path: '/xudrpc.Xud/DiscoverNodes',
requestStream: false,
diff --git a/lib/proto/xudrpc_pb.d.ts b/lib/proto/xudrpc_pb.d.ts
index f06b8987a..6ee6022b3 100644
--- a/lib/proto/xudrpc_pb.d.ts
+++ b/lib/proto/xudrpc_pb.d.ts
@@ -6,6 +6,88 @@
import * as jspb from "google-protobuf";
import * as annotations_pb from "./annotations_pb";
+export class CreateNodeRequest extends jspb.Message {
+ getPassword(): string;
+ setPassword(value: string): void;
+
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): CreateNodeRequest.AsObject;
+ static toObject(includeInstance: boolean, msg: CreateNodeRequest): CreateNodeRequest.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: CreateNodeRequest, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): CreateNodeRequest;
+ static deserializeBinaryFromReader(message: CreateNodeRequest, reader: jspb.BinaryReader): CreateNodeRequest;
+}
+
+export namespace CreateNodeRequest {
+ export type AsObject = {
+ password: string,
+ }
+}
+
+export class CreateNodeResponse extends jspb.Message {
+ clearSeedMnemonicList(): void;
+ getSeedMnemonicList(): Array;
+ setSeedMnemonicList(value: Array): void;
+ addSeedMnemonic(value: string, index?: number): string;
+
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): CreateNodeResponse.AsObject;
+ static toObject(includeInstance: boolean, msg: CreateNodeResponse): CreateNodeResponse.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: CreateNodeResponse, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): CreateNodeResponse;
+ static deserializeBinaryFromReader(message: CreateNodeResponse, reader: jspb.BinaryReader): CreateNodeResponse;
+}
+
+export namespace CreateNodeResponse {
+ export type AsObject = {
+ seedMnemonicList: Array,
+ }
+}
+
+export class UnlockNodeRequest extends jspb.Message {
+ getPassword(): string;
+ setPassword(value: string): void;
+
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): UnlockNodeRequest.AsObject;
+ static toObject(includeInstance: boolean, msg: UnlockNodeRequest): UnlockNodeRequest.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: UnlockNodeRequest, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): UnlockNodeRequest;
+ static deserializeBinaryFromReader(message: UnlockNodeRequest, reader: jspb.BinaryReader): UnlockNodeRequest;
+}
+
+export namespace UnlockNodeRequest {
+ export type AsObject = {
+ password: string,
+ }
+}
+
+export class UnlockNodeResponse extends jspb.Message {
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): UnlockNodeResponse.AsObject;
+ static toObject(includeInstance: boolean, msg: UnlockNodeResponse): UnlockNodeResponse.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: UnlockNodeResponse, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): UnlockNodeResponse;
+ static deserializeBinaryFromReader(message: UnlockNodeResponse, reader: jspb.BinaryReader): UnlockNodeResponse;
+}
+
+export namespace UnlockNodeResponse {
+ export type AsObject = {
+ }
+}
+
export class AddCurrencyRequest extends jspb.Message {
getCurrency(): string;
setCurrency(value: string): void;
diff --git a/lib/proto/xudrpc_pb.js b/lib/proto/xudrpc_pb.js
index 1675fb984..0fed21551 100644
--- a/lib/proto/xudrpc_pb.js
+++ b/lib/proto/xudrpc_pb.js
@@ -25,6 +25,8 @@ goog.exportSymbol('proto.xudrpc.ChannelBalanceRequest', null, global);
goog.exportSymbol('proto.xudrpc.ChannelBalanceResponse', null, global);
goog.exportSymbol('proto.xudrpc.ConnectRequest', null, global);
goog.exportSymbol('proto.xudrpc.ConnectResponse', null, global);
+goog.exportSymbol('proto.xudrpc.CreateNodeRequest', null, global);
+goog.exportSymbol('proto.xudrpc.CreateNodeResponse', null, global);
goog.exportSymbol('proto.xudrpc.DiscoverNodesRequest', null, global);
goog.exportSymbol('proto.xudrpc.DiscoverNodesResponse', null, global);
goog.exportSymbol('proto.xudrpc.ExecuteSwapRequest', null, global);
@@ -68,6 +70,571 @@ goog.exportSymbol('proto.xudrpc.SwapSuccess', null, global);
goog.exportSymbol('proto.xudrpc.SwapSuccess.Role', null, global);
goog.exportSymbol('proto.xudrpc.UnbanRequest', null, global);
goog.exportSymbol('proto.xudrpc.UnbanResponse', null, global);
+goog.exportSymbol('proto.xudrpc.UnlockNodeRequest', null, global);
+goog.exportSymbol('proto.xudrpc.UnlockNodeResponse', null, global);
+
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.xudrpc.CreateNodeRequest = function(opt_data) {
+ jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.xudrpc.CreateNodeRequest, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+ proto.xudrpc.CreateNodeRequest.displayName = 'proto.xudrpc.CreateNodeRequest';
+}
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto suitable for use in Soy templates.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * To access a reserved field use, foo.pb_, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
+ * @param {boolean=} opt_includeInstance Whether to include the JSPB instance
+ * for transitional soy proto support: http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.xudrpc.CreateNodeRequest.prototype.toObject = function(opt_includeInstance) {
+ return proto.xudrpc.CreateNodeRequest.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Whether to include the JSPB
+ * instance for transitional soy proto support:
+ * http://goto/soy-param-migration
+ * @param {!proto.xudrpc.CreateNodeRequest} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.xudrpc.CreateNodeRequest.toObject = function(includeInstance, msg) {
+ var f, obj = {
+ password: jspb.Message.getFieldWithDefault(msg, 1, "")
+ };
+
+ if (includeInstance) {
+ obj.$jspbMessageInstance = msg;
+ }
+ return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.xudrpc.CreateNodeRequest}
+ */
+proto.xudrpc.CreateNodeRequest.deserializeBinary = function(bytes) {
+ var reader = new jspb.BinaryReader(bytes);
+ var msg = new proto.xudrpc.CreateNodeRequest;
+ return proto.xudrpc.CreateNodeRequest.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.xudrpc.CreateNodeRequest} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.xudrpc.CreateNodeRequest}
+ */
+proto.xudrpc.CreateNodeRequest.deserializeBinaryFromReader = function(msg, reader) {
+ while (reader.nextField()) {
+ if (reader.isEndGroup()) {
+ break;
+ }
+ var field = reader.getFieldNumber();
+ switch (field) {
+ case 1:
+ var value = /** @type {string} */ (reader.readString());
+ msg.setPassword(value);
+ break;
+ default:
+ reader.skipField();
+ break;
+ }
+ }
+ return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.xudrpc.CreateNodeRequest.prototype.serializeBinary = function() {
+ var writer = new jspb.BinaryWriter();
+ proto.xudrpc.CreateNodeRequest.serializeBinaryToWriter(this, writer);
+ return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.xudrpc.CreateNodeRequest} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.xudrpc.CreateNodeRequest.serializeBinaryToWriter = function(message, writer) {
+ var f = undefined;
+ f = message.getPassword();
+ if (f.length > 0) {
+ writer.writeString(
+ 1,
+ f
+ );
+ }
+};
+
+
+/**
+ * optional string password = 1;
+ * @return {string}
+ */
+proto.xudrpc.CreateNodeRequest.prototype.getPassword = function() {
+ return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
+};
+
+
+/** @param {string} value */
+proto.xudrpc.CreateNodeRequest.prototype.setPassword = function(value) {
+ jspb.Message.setField(this, 1, value);
+};
+
+
+
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.xudrpc.CreateNodeResponse = function(opt_data) {
+ jspb.Message.initialize(this, opt_data, 0, -1, proto.xudrpc.CreateNodeResponse.repeatedFields_, null);
+};
+goog.inherits(proto.xudrpc.CreateNodeResponse, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+ proto.xudrpc.CreateNodeResponse.displayName = 'proto.xudrpc.CreateNodeResponse';
+}
+/**
+ * List of repeated fields within this message type.
+ * @private {!Array}
+ * @const
+ */
+proto.xudrpc.CreateNodeResponse.repeatedFields_ = [1];
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto suitable for use in Soy templates.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * To access a reserved field use, foo.pb_, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
+ * @param {boolean=} opt_includeInstance Whether to include the JSPB instance
+ * for transitional soy proto support: http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.xudrpc.CreateNodeResponse.prototype.toObject = function(opt_includeInstance) {
+ return proto.xudrpc.CreateNodeResponse.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Whether to include the JSPB
+ * instance for transitional soy proto support:
+ * http://goto/soy-param-migration
+ * @param {!proto.xudrpc.CreateNodeResponse} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.xudrpc.CreateNodeResponse.toObject = function(includeInstance, msg) {
+ var f, obj = {
+ seedMnemonicList: jspb.Message.getRepeatedField(msg, 1)
+ };
+
+ if (includeInstance) {
+ obj.$jspbMessageInstance = msg;
+ }
+ return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.xudrpc.CreateNodeResponse}
+ */
+proto.xudrpc.CreateNodeResponse.deserializeBinary = function(bytes) {
+ var reader = new jspb.BinaryReader(bytes);
+ var msg = new proto.xudrpc.CreateNodeResponse;
+ return proto.xudrpc.CreateNodeResponse.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.xudrpc.CreateNodeResponse} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.xudrpc.CreateNodeResponse}
+ */
+proto.xudrpc.CreateNodeResponse.deserializeBinaryFromReader = function(msg, reader) {
+ while (reader.nextField()) {
+ if (reader.isEndGroup()) {
+ break;
+ }
+ var field = reader.getFieldNumber();
+ switch (field) {
+ case 1:
+ var value = /** @type {string} */ (reader.readString());
+ msg.addSeedMnemonic(value);
+ break;
+ default:
+ reader.skipField();
+ break;
+ }
+ }
+ return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.xudrpc.CreateNodeResponse.prototype.serializeBinary = function() {
+ var writer = new jspb.BinaryWriter();
+ proto.xudrpc.CreateNodeResponse.serializeBinaryToWriter(this, writer);
+ return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.xudrpc.CreateNodeResponse} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.xudrpc.CreateNodeResponse.serializeBinaryToWriter = function(message, writer) {
+ var f = undefined;
+ f = message.getSeedMnemonicList();
+ if (f.length > 0) {
+ writer.writeRepeatedString(
+ 1,
+ f
+ );
+ }
+};
+
+
+/**
+ * repeated string seed_mnemonic = 1;
+ * @return {!Array.}
+ */
+proto.xudrpc.CreateNodeResponse.prototype.getSeedMnemonicList = function() {
+ return /** @type {!Array.} */ (jspb.Message.getRepeatedField(this, 1));
+};
+
+
+/** @param {!Array.} value */
+proto.xudrpc.CreateNodeResponse.prototype.setSeedMnemonicList = function(value) {
+ jspb.Message.setField(this, 1, value || []);
+};
+
+
+/**
+ * @param {!string} value
+ * @param {number=} opt_index
+ */
+proto.xudrpc.CreateNodeResponse.prototype.addSeedMnemonic = function(value, opt_index) {
+ jspb.Message.addToRepeatedField(this, 1, value, opt_index);
+};
+
+
+proto.xudrpc.CreateNodeResponse.prototype.clearSeedMnemonicList = function() {
+ this.setSeedMnemonicList([]);
+};
+
+
+
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.xudrpc.UnlockNodeRequest = function(opt_data) {
+ jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.xudrpc.UnlockNodeRequest, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+ proto.xudrpc.UnlockNodeRequest.displayName = 'proto.xudrpc.UnlockNodeRequest';
+}
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto suitable for use in Soy templates.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * To access a reserved field use, foo.pb_, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
+ * @param {boolean=} opt_includeInstance Whether to include the JSPB instance
+ * for transitional soy proto support: http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.xudrpc.UnlockNodeRequest.prototype.toObject = function(opt_includeInstance) {
+ return proto.xudrpc.UnlockNodeRequest.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Whether to include the JSPB
+ * instance for transitional soy proto support:
+ * http://goto/soy-param-migration
+ * @param {!proto.xudrpc.UnlockNodeRequest} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.xudrpc.UnlockNodeRequest.toObject = function(includeInstance, msg) {
+ var f, obj = {
+ password: jspb.Message.getFieldWithDefault(msg, 1, "")
+ };
+
+ if (includeInstance) {
+ obj.$jspbMessageInstance = msg;
+ }
+ return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.xudrpc.UnlockNodeRequest}
+ */
+proto.xudrpc.UnlockNodeRequest.deserializeBinary = function(bytes) {
+ var reader = new jspb.BinaryReader(bytes);
+ var msg = new proto.xudrpc.UnlockNodeRequest;
+ return proto.xudrpc.UnlockNodeRequest.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.xudrpc.UnlockNodeRequest} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.xudrpc.UnlockNodeRequest}
+ */
+proto.xudrpc.UnlockNodeRequest.deserializeBinaryFromReader = function(msg, reader) {
+ while (reader.nextField()) {
+ if (reader.isEndGroup()) {
+ break;
+ }
+ var field = reader.getFieldNumber();
+ switch (field) {
+ case 1:
+ var value = /** @type {string} */ (reader.readString());
+ msg.setPassword(value);
+ break;
+ default:
+ reader.skipField();
+ break;
+ }
+ }
+ return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.xudrpc.UnlockNodeRequest.prototype.serializeBinary = function() {
+ var writer = new jspb.BinaryWriter();
+ proto.xudrpc.UnlockNodeRequest.serializeBinaryToWriter(this, writer);
+ return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.xudrpc.UnlockNodeRequest} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.xudrpc.UnlockNodeRequest.serializeBinaryToWriter = function(message, writer) {
+ var f = undefined;
+ f = message.getPassword();
+ if (f.length > 0) {
+ writer.writeString(
+ 1,
+ f
+ );
+ }
+};
+
+
+/**
+ * optional string password = 1;
+ * @return {string}
+ */
+proto.xudrpc.UnlockNodeRequest.prototype.getPassword = function() {
+ return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
+};
+
+
+/** @param {string} value */
+proto.xudrpc.UnlockNodeRequest.prototype.setPassword = function(value) {
+ jspb.Message.setField(this, 1, value);
+};
+
+
+
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.xudrpc.UnlockNodeResponse = function(opt_data) {
+ jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.xudrpc.UnlockNodeResponse, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+ proto.xudrpc.UnlockNodeResponse.displayName = 'proto.xudrpc.UnlockNodeResponse';
+}
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto suitable for use in Soy templates.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * To access a reserved field use, foo.pb_, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
+ * @param {boolean=} opt_includeInstance Whether to include the JSPB instance
+ * for transitional soy proto support: http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.xudrpc.UnlockNodeResponse.prototype.toObject = function(opt_includeInstance) {
+ return proto.xudrpc.UnlockNodeResponse.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Whether to include the JSPB
+ * instance for transitional soy proto support:
+ * http://goto/soy-param-migration
+ * @param {!proto.xudrpc.UnlockNodeResponse} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.xudrpc.UnlockNodeResponse.toObject = function(includeInstance, msg) {
+ var f, obj = {
+
+ };
+
+ if (includeInstance) {
+ obj.$jspbMessageInstance = msg;
+ }
+ return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.xudrpc.UnlockNodeResponse}
+ */
+proto.xudrpc.UnlockNodeResponse.deserializeBinary = function(bytes) {
+ var reader = new jspb.BinaryReader(bytes);
+ var msg = new proto.xudrpc.UnlockNodeResponse;
+ return proto.xudrpc.UnlockNodeResponse.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.xudrpc.UnlockNodeResponse} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.xudrpc.UnlockNodeResponse}
+ */
+proto.xudrpc.UnlockNodeResponse.deserializeBinaryFromReader = function(msg, reader) {
+ while (reader.nextField()) {
+ if (reader.isEndGroup()) {
+ break;
+ }
+ var field = reader.getFieldNumber();
+ switch (field) {
+ default:
+ reader.skipField();
+ break;
+ }
+ }
+ return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.xudrpc.UnlockNodeResponse.prototype.serializeBinary = function() {
+ var writer = new jspb.BinaryWriter();
+ proto.xudrpc.UnlockNodeResponse.serializeBinaryToWriter(this, writer);
+ return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.xudrpc.UnlockNodeResponse} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.xudrpc.UnlockNodeResponse.serializeBinaryToWriter = function(message, writer) {
+ var f = undefined;
+};
+
+
/**
* Generated by JsPbCodeGenerator.
diff --git a/lib/service/InitService.ts b/lib/service/InitService.ts
new file mode 100644
index 000000000..3ec5035ff
--- /dev/null
+++ b/lib/service/InitService.ts
@@ -0,0 +1,74 @@
+import errors from '../service/errors';
+import { EventEmitter } from 'events';
+import SwapClientManager from '../swaps/SwapClientManager';
+import NodeKey from '../nodekey/NodeKey';
+import assert = require('assert');
+
+interface InitService {
+ once(event: 'nodekey', listener: (nodeKey: NodeKey) => void): this;
+ emit(event: 'nodekey', nodeKey: NodeKey): boolean;
+}
+
+class InitService extends EventEmitter {
+ /** Whether there is a pending `CreateNode` or `UnlockNode` call. */
+ public pendingCall = false;
+
+ constructor(private swapClientManager: SwapClientManager, private nodeKeyPath: string, private nodeKeyExists: boolean) {
+ super();
+ }
+
+ public createNode = async (args: { password: string }) => {
+ const { password } = args;
+ if (this.nodeKeyExists) {
+ throw errors.UNIMPLEMENTED;
+ }
+ if (this.pendingCall) {
+ throw errors.PENDING_CALL_CONFLICT;
+ }
+
+ this.pendingCall = true;
+ const seed = await this.swapClientManager.genSeed();
+ let nodeKey: NodeKey;
+
+ if (seed) {
+ const seedBytes = typeof seed.encipheredSeed === 'string' ?
+ Buffer.from(seed.encipheredSeed, 'base64') :
+ Buffer.from(seed.encipheredSeed);
+ assert.equal(seedBytes.length, 33);
+
+ // the seed is 33 bytes, the first byte of which is the version
+ // so we use the remaining 32 bytes to generate our private key
+ const privKey = Buffer.from(seedBytes.slice(1));
+ nodeKey = new NodeKey(privKey);
+
+ // use this seed to init any lnd wallets that are uninitialized
+ await this.swapClientManager.initWallets(password, seed.cipherSeedMnemonicList);
+ } else {
+ // we couldn't generate a seed externally, so we must create one locally
+ nodeKey = await NodeKey.generate();
+ }
+
+ await nodeKey.toFile(this.nodeKeyPath, password);
+ this.emit('nodekey', nodeKey);
+ return seed ? seed.cipherSeedMnemonicList : undefined;
+ }
+
+ public unlockNode = async (args: { password: string }) => {
+ const { password } = args;
+ if (!this.nodeKeyExists) {
+ throw errors.UNIMPLEMENTED;
+ }
+ if (this.pendingCall) {
+ throw errors.PENDING_CALL_CONFLICT;
+ }
+
+ this.pendingCall = true;
+
+ const nodeKey = await NodeKey.fromFile(this.nodeKeyPath, password);
+ this.emit('nodekey', nodeKey);
+
+ await this.swapClientManager.unlockWallets(password);
+ }
+}
+
+export default InitService;
diff --git a/lib/service/Service.ts b/lib/service/Service.ts
index 96d9bb8a9..81a198d8c 100644
--- a/lib/service/Service.ts
+++ b/lib/service/Service.ts
@@ -2,7 +2,6 @@ import Pool from '../p2p/Pool';
import OrderBook from '../orderbook/OrderBook';
import { LndInfo } from '../lndclient/types';
import { RaidenInfo } from '../raidenclient/types';
-import { EventEmitter } from 'events';
import errors from './errors';
import { SwapClientType, OrderSide, SwapRole } from '../constants/enums';
import { parseUri, toUri, UriParts } from '../utils/uriUtils';
@@ -68,7 +67,7 @@ const argChecks = {
};
/** Class containing the available RPC methods for XUD */
-class Service extends EventEmitter {
+class Service {
public shutdown: () => void;
private orderBook: OrderBook;
private swapClientManager: SwapClientManager;
@@ -78,8 +77,6 @@ class Service extends EventEmitter {
/** Create an instance of available RPC methods and bind all exposed functions. */
constructor(components: ServiceComponents) {
- super();
-
this.shutdown = components.shutdown;
this.orderBook = components.orderBook;
this.swapClientManager = components.swapClientManager;
diff --git a/lib/service/errors.ts b/lib/service/errors.ts
index 6bb19fc56..c4dbba307 100644
--- a/lib/service/errors.ts
+++ b/lib/service/errors.ts
@@ -4,6 +4,8 @@ const codesPrefix = errorCodesPrefix.SERVICE;
const errorCodes = {
INVALID_ARGUMENT: codesPrefix.concat('.1'),
NOMATCHING_MODE_IS_REQUIRED: codesPrefix.concat('.2'),
+ UNIMPLEMENTED: codesPrefix.concat('.3'),
+ PENDING_CALL_CONFLICT: codesPrefix.concat('.4'),
};
const errors = {
@@ -15,6 +17,14 @@ const errors = {
message: 'nomatching mode is required',
code: errorCodes.NOMATCHING_MODE_IS_REQUIRED,
}),
+ UNIMPLEMENTED: {
+ message: 'call is not supported by the current state of xud',
+ code: errorCodes.UNIMPLEMENTED,
+ },
+ PENDING_CALL_CONFLICT: {
+ message: 'a pending call is ongoing that conflicts with this call',
+ code: errorCodes.PENDING_CALL_CONFLICT,
+ },
};
export { errorCodes };
diff --git a/lib/swaps/SwapClient.ts b/lib/swaps/SwapClient.ts
index f398ea389..94aa238e1 100644
--- a/lib/swaps/SwapClient.ts
+++ b/lib/swaps/SwapClient.ts
@@ -9,6 +9,7 @@ enum ClientStatus {
Disconnected,
ConnectionVerified,
OutOfSync,
+ WaitingUnlock,
}
type ChannelBalance = {
@@ -37,7 +38,7 @@ abstract class SwapClient extends EventEmitter {
/** Time in milliseconds between updating the maximum outbound capacity */
private static CAPACITY_REFRESH_INTERVAL = 60000;
- constructor(protected logger: Logger) {
+ constructor(public logger: Logger) {
super();
}
@@ -134,6 +135,9 @@ abstract class SwapClient extends EventEmitter {
public isDisconnected(): boolean {
return this.status === ClientStatus.Disconnected;
}
+ public isWaitingUnlock(): boolean {
+ return this.status === ClientStatus.WaitingUnlock;
+ }
/** Ends all connections, subscriptions, and timers for for this client. */
public close() {
if (this.reconnectionTimer) {
diff --git a/lib/swaps/SwapClientManager.ts b/lib/swaps/SwapClientManager.ts
index 1b88d612c..b509df2e7 100644
--- a/lib/swaps/SwapClientManager.ts
+++ b/lib/swaps/SwapClientManager.ts
@@ -103,6 +103,63 @@ class SwapClientManager extends EventEmitter {
}
}
+ /**
+ * Generates a cryptographically random 24 word seed mnemonic from an lnd client.
+ */
+ public genSeed = async () => {
+ // loop through swap clients until we find a connected lnd client
+ for (const swapClient of this.swapClients.values()) {
+ // if (isLndClient(swapClient) && swapClient.isConnected()) {
+ if (isLndClient(swapClient)) {
+ try {
+ return swapClient.genSeed();
+ } catch (err) {
+ swapClient.logger.debug('could not generate seed');
+ }
+ }
+ }
+
+ return undefined;
+ }
+
+ /**
+ * Initializes wallets with seed and password.
+ */
+ public initWallets = async (walletPassword: string, seedMnemonic: string[]) => {
+ // loop through swap clients to find locked lnd clients
+ const initWalletPromises: Promise[] = [];
+ for (const swapClient of this.swapClients.values()) {
+ if (isLndClient(swapClient) && swapClient.isWaitingUnlock()) {
+ initWalletPromises.push(swapClient.initWallet(walletPassword, seedMnemonic));
+ }
+ }
+
+ await Promise.all(initWalletPromises).catch((err) => {
+ this.loggers.lnd.debug(`could not initialize one or more wallets: ${JSON.stringify(err)}`);
+ });
+
+ // TODO: create raiden address
+ }
+
+ /**
+ * Initializes wallets with seed and password.
+ */
+ public unlockWallets = async (walletPassword: string) => {
+ // loop through swap clients to find locked lnd clients
+ const unlockWalletPromises: Promise[] = [];
+ for (const swapClient of this.swapClients.values()) {
+ if (isLndClient(swapClient) && swapClient.isWaitingUnlock()) {
+ unlockWalletPromises.push(swapClient.unlockWallet(walletPassword));
+ }
+ }
+
+ await Promise.all(unlockWalletPromises).catch((err) => {
+ this.loggers.lnd.debug(`could not unlock one or more wallets: ${JSON.stringify(err)}`);
+ });
+
+ // TODO: unlock raiden
+ }
+
/**
* Gets a swap client instance.
* @param currency a currency that the swap client is linked to.
diff --git a/package-lock.json b/package-lock.json
index 421d00df3..bfc5e878e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2320,7 +2320,6 @@
"anymatch": "^2.0.0",
"async-each": "^1.0.0",
"braces": "^2.3.0",
- "fsevents": "^1.1.2",
"glob-parent": "^3.1.0",
"inherits": "^2.0.1",
"is-binary-path": "^1.0.0",
@@ -3204,11 +3203,6 @@
"which": "^1.2.9"
}
},
- "crypto-js": {
- "version": "3.1.9-1",
- "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.9-1.tgz",
- "integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg="
- },
"crypto-random-string": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz",
@@ -4256,619 +4250,132 @@
},
"fined": {
"version": "1.1.0",
- "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz",
- "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=",
- "requires": {
- "expand-tilde": "^2.0.2",
- "is-plain-object": "^2.0.3",
- "object.defaults": "^1.1.0",
- "object.pick": "^1.2.0",
- "parse-filepath": "^1.0.1"
- }
- },
- "flagged-respawn": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz",
- "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c="
- },
- "flush-write-stream": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz",
- "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==",
- "requires": {
- "inherits": "^2.0.1",
- "readable-stream": "^2.0.4"
- }
- },
- "for-in": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
- "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="
- },
- "for-own": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz",
- "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=",
- "requires": {
- "for-in": "^1.0.1"
- }
- },
- "foreach": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
- "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k="
- },
- "forever-agent": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
- "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
- },
- "form-data": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
- "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
- "requires": {
- "asynckit": "^0.4.0",
- "combined-stream": "^1.0.6",
- "mime-types": "^2.1.12"
- }
- },
- "formidable": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz",
- "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==",
- "dev": true
- },
- "forwarded": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
- "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
- },
- "fragment-cache": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
- "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
- "requires": {
- "map-cache": "^0.2.2"
- }
- },
- "fresh": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
- "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
- },
- "from": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz",
- "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=",
- "dev": true
- },
- "fs-exists-sync": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz",
- "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=",
- "dev": true
- },
- "fs-extra": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
- "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.2",
- "jsonfile": "^4.0.0",
- "universalify": "^0.1.0"
- }
- },
- "fs-minipass": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz",
- "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==",
- "requires": {
- "minipass": "^2.2.1"
- }
- },
- "fs-mkdirp-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz",
- "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=",
- "requires": {
- "graceful-fs": "^4.1.11",
- "through2": "^2.0.3"
- }
- },
- "fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
- },
- "fsevents": {
- "version": "1.2.9",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz",
- "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==",
- "optional": true,
- "requires": {
- "nan": "^2.12.1",
- "node-pre-gyp": "^0.12.0"
- },
- "dependencies": {
- "abbrev": {
- "version": "1.1.1",
- "bundled": true,
- "optional": true
- },
- "ansi-regex": {
- "version": "2.1.1",
- "bundled": true,
- "optional": true
- },
- "aproba": {
- "version": "1.2.0",
- "bundled": true,
- "optional": true
- },
- "are-we-there-yet": {
- "version": "1.1.5",
- "bundled": true,
- "optional": true,
- "requires": {
- "delegates": "^1.0.0",
- "readable-stream": "^2.0.6"
- }
- },
- "balanced-match": {
- "version": "1.0.0",
- "bundled": true,
- "optional": true
- },
- "brace-expansion": {
- "version": "1.1.11",
- "bundled": true,
- "optional": true,
- "requires": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "chownr": {
- "version": "1.1.1",
- "bundled": true,
- "optional": true
- },
- "code-point-at": {
- "version": "1.1.0",
- "bundled": true,
- "optional": true
- },
- "concat-map": {
- "version": "0.0.1",
- "bundled": true,
- "optional": true
- },
- "console-control-strings": {
- "version": "1.1.0",
- "bundled": true,
- "optional": true
- },
- "core-util-is": {
- "version": "1.0.2",
- "bundled": true,
- "optional": true
- },
- "debug": {
- "version": "4.1.1",
- "bundled": true,
- "optional": true,
- "requires": {
- "ms": "^2.1.1"
- }
- },
- "deep-extend": {
- "version": "0.6.0",
- "bundled": true,
- "optional": true
- },
- "delegates": {
- "version": "1.0.0",
- "bundled": true,
- "optional": true
- },
- "detect-libc": {
- "version": "1.0.3",
- "bundled": true,
- "optional": true
- },
- "fs-minipass": {
- "version": "1.2.5",
- "bundled": true,
- "optional": true,
- "requires": {
- "minipass": "^2.2.1"
- }
- },
- "fs.realpath": {
- "version": "1.0.0",
- "bundled": true,
- "optional": true
- },
- "gauge": {
- "version": "2.7.4",
- "bundled": true,
- "optional": true,
- "requires": {
- "aproba": "^1.0.3",
- "console-control-strings": "^1.0.0",
- "has-unicode": "^2.0.0",
- "object-assign": "^4.1.0",
- "signal-exit": "^3.0.0",
- "string-width": "^1.0.1",
- "strip-ansi": "^3.0.1",
- "wide-align": "^1.1.0"
- }
- },
- "glob": {
- "version": "7.1.3",
- "bundled": true,
- "optional": true,
- "requires": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- }
- },
- "has-unicode": {
- "version": "2.0.1",
- "bundled": true,
- "optional": true
- },
- "iconv-lite": {
- "version": "0.4.24",
- "bundled": true,
- "optional": true,
- "requires": {
- "safer-buffer": ">= 2.1.2 < 3"
- }
- },
- "ignore-walk": {
- "version": "3.0.1",
- "bundled": true,
- "optional": true,
- "requires": {
- "minimatch": "^3.0.4"
- }
- },
- "inflight": {
- "version": "1.0.6",
- "bundled": true,
- "optional": true,
- "requires": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "inherits": {
- "version": "2.0.3",
- "bundled": true,
- "optional": true
- },
- "ini": {
- "version": "1.3.5",
- "bundled": true,
- "optional": true
- },
- "is-fullwidth-code-point": {
- "version": "1.0.0",
- "bundled": true,
- "optional": true,
- "requires": {
- "number-is-nan": "^1.0.0"
- }
- },
- "isarray": {
- "version": "1.0.0",
- "bundled": true,
- "optional": true
- },
- "minimatch": {
- "version": "3.0.4",
- "bundled": true,
- "optional": true,
- "requires": {
- "brace-expansion": "^1.1.7"
- }
- },
- "minimist": {
- "version": "0.0.8",
- "bundled": true,
- "optional": true
- },
- "minipass": {
- "version": "2.3.5",
- "bundled": true,
- "optional": true,
- "requires": {
- "safe-buffer": "^5.1.2",
- "yallist": "^3.0.0"
- }
- },
- "minizlib": {
- "version": "1.2.1",
- "bundled": true,
- "optional": true,
- "requires": {
- "minipass": "^2.2.1"
- }
- },
- "mkdirp": {
- "version": "0.5.1",
- "bundled": true,
- "optional": true,
- "requires": {
- "minimist": "0.0.8"
- }
- },
- "ms": {
- "version": "2.1.1",
- "bundled": true,
- "optional": true
- },
- "nan": {
- "version": "2.14.0",
- "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
- "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
- "optional": true
- },
- "needle": {
- "version": "2.3.0",
- "bundled": true,
- "optional": true,
- "requires": {
- "debug": "^4.1.0",
- "iconv-lite": "^0.4.4",
- "sax": "^1.2.4"
- }
- },
- "node-pre-gyp": {
- "version": "0.12.0",
- "bundled": true,
- "optional": true,
- "requires": {
- "detect-libc": "^1.0.2",
- "mkdirp": "^0.5.1",
- "needle": "^2.2.1",
- "nopt": "^4.0.1",
- "npm-packlist": "^1.1.6",
- "npmlog": "^4.0.2",
- "rc": "^1.2.7",
- "rimraf": "^2.6.1",
- "semver": "^5.3.0",
- "tar": "^4"
- }
- },
- "nopt": {
- "version": "4.0.1",
- "bundled": true,
- "optional": true,
- "requires": {
- "abbrev": "1",
- "osenv": "^0.1.4"
- }
- },
- "npm-bundled": {
- "version": "1.0.6",
- "bundled": true,
- "optional": true
- },
- "npm-packlist": {
- "version": "1.4.1",
- "bundled": true,
- "optional": true,
- "requires": {
- "ignore-walk": "^3.0.1",
- "npm-bundled": "^1.0.1"
- }
- },
- "npmlog": {
- "version": "4.1.2",
- "bundled": true,
- "optional": true,
- "requires": {
- "are-we-there-yet": "~1.1.2",
- "console-control-strings": "~1.1.0",
- "gauge": "~2.7.3",
- "set-blocking": "~2.0.0"
- }
- },
- "number-is-nan": {
- "version": "1.0.1",
- "bundled": true,
- "optional": true
- },
- "object-assign": {
- "version": "4.1.1",
- "bundled": true,
- "optional": true
- },
- "once": {
- "version": "1.4.0",
- "bundled": true,
- "optional": true,
- "requires": {
- "wrappy": "1"
- }
- },
- "os-homedir": {
- "version": "1.0.2",
- "bundled": true,
- "optional": true
- },
- "os-tmpdir": {
- "version": "1.0.2",
- "bundled": true,
- "optional": true
- },
- "osenv": {
- "version": "0.1.5",
- "bundled": true,
- "optional": true,
- "requires": {
- "os-homedir": "^1.0.0",
- "os-tmpdir": "^1.0.0"
- }
- },
- "path-is-absolute": {
- "version": "1.0.1",
- "bundled": true,
- "optional": true
- },
- "process-nextick-args": {
- "version": "2.0.0",
- "bundled": true,
- "optional": true
- },
- "rc": {
- "version": "1.2.8",
- "bundled": true,
- "optional": true,
- "requires": {
- "deep-extend": "^0.6.0",
- "ini": "~1.3.0",
- "minimist": "^1.2.0",
- "strip-json-comments": "~2.0.1"
- },
- "dependencies": {
- "minimist": {
- "version": "1.2.0",
- "bundled": true,
- "optional": true
- }
- }
- },
- "readable-stream": {
- "version": "2.3.6",
- "bundled": true,
- "optional": true,
- "requires": {
- "core-util-is": "~1.0.0",
- "inherits": "~2.0.3",
- "isarray": "~1.0.0",
- "process-nextick-args": "~2.0.0",
- "safe-buffer": "~5.1.1",
- "string_decoder": "~1.1.1",
- "util-deprecate": "~1.0.1"
- }
- },
- "rimraf": {
- "version": "2.6.3",
- "bundled": true,
- "optional": true,
- "requires": {
- "glob": "^7.1.3"
- }
- },
- "safe-buffer": {
- "version": "5.1.2",
- "bundled": true,
- "optional": true
- },
- "safer-buffer": {
- "version": "2.1.2",
- "bundled": true,
- "optional": true
- },
- "sax": {
- "version": "1.2.4",
- "bundled": true,
- "optional": true
- },
- "semver": {
- "version": "5.7.0",
- "bundled": true,
- "optional": true
- },
- "set-blocking": {
- "version": "2.0.0",
- "bundled": true,
- "optional": true
- },
- "signal-exit": {
- "version": "3.0.2",
- "bundled": true,
- "optional": true
- },
- "string-width": {
- "version": "1.0.2",
- "bundled": true,
- "optional": true,
- "requires": {
- "code-point-at": "^1.0.0",
- "is-fullwidth-code-point": "^1.0.0",
- "strip-ansi": "^3.0.0"
- }
- },
- "string_decoder": {
- "version": "1.1.1",
- "bundled": true,
- "optional": true,
- "requires": {
- "safe-buffer": "~5.1.0"
- }
- },
- "strip-ansi": {
- "version": "3.0.1",
- "bundled": true,
- "optional": true,
- "requires": {
- "ansi-regex": "^2.0.0"
- }
- },
- "strip-json-comments": {
- "version": "2.0.1",
- "bundled": true,
- "optional": true
- },
- "tar": {
- "version": "4.4.8",
- "bundled": true,
- "optional": true,
- "requires": {
- "chownr": "^1.1.1",
- "fs-minipass": "^1.2.5",
- "minipass": "^2.3.4",
- "minizlib": "^1.1.1",
- "mkdirp": "^0.5.0",
- "safe-buffer": "^5.1.2",
- "yallist": "^3.0.2"
- }
- },
- "util-deprecate": {
- "version": "1.0.2",
- "bundled": true,
- "optional": true
- },
- "wide-align": {
- "version": "1.1.3",
- "bundled": true,
- "optional": true,
- "requires": {
- "string-width": "^1.0.2 || 2"
- }
- },
- "wrappy": {
- "version": "1.0.2",
- "bundled": true,
- "optional": true
- },
- "yallist": {
- "version": "3.0.3",
- "bundled": true,
- "optional": true
- }
+ "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz",
+ "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=",
+ "requires": {
+ "expand-tilde": "^2.0.2",
+ "is-plain-object": "^2.0.3",
+ "object.defaults": "^1.1.0",
+ "object.pick": "^1.2.0",
+ "parse-filepath": "^1.0.1"
+ }
+ },
+ "flagged-respawn": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz",
+ "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c="
+ },
+ "flush-write-stream": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz",
+ "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==",
+ "requires": {
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.4"
+ }
+ },
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="
+ },
+ "for-own": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz",
+ "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=",
+ "requires": {
+ "for-in": "^1.0.1"
+ }
+ },
+ "foreach": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
+ "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k="
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
+ },
+ "form-data": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+ "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ }
+ },
+ "formidable": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz",
+ "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==",
+ "dev": true
+ },
+ "forwarded": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
+ "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
+ },
+ "fragment-cache": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
+ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+ "requires": {
+ "map-cache": "^0.2.2"
+ }
+ },
+ "fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
+ },
+ "from": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz",
+ "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=",
+ "dev": true
+ },
+ "fs-exists-sync": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz",
+ "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=",
+ "dev": true
+ },
+ "fs-extra": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
+ "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ }
+ },
+ "fs-minipass": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz",
+ "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==",
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
+ "fs-mkdirp-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz",
+ "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=",
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "through2": "^2.0.3"
}
},
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@@ -5298,22 +4805,22 @@
"dependencies": {
"abbrev": {
"version": "1.1.1",
- "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "resolved": false,
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
},
"ansi-regex": {
"version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "resolved": false,
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
},
"aproba": {
"version": "1.2.0",
- "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+ "resolved": false,
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
},
"are-we-there-yet": {
"version": "1.1.5",
- "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
+ "resolved": false,
"integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
"requires": {
"delegates": "^1.0.0",
@@ -5322,12 +4829,12 @@
},
"balanced-match": {
"version": "1.0.0",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "resolved": false,
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
"brace-expansion": {
"version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "resolved": false,
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"requires": {
"balanced-match": "^1.0.0",
@@ -5336,27 +4843,27 @@
},
"chownr": {
"version": "1.1.1",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz",
+ "resolved": false,
"integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g=="
},
"code-point-at": {
"version": "1.1.0",
- "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+ "resolved": false,
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
},
"concat-map": {
"version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "resolved": false,
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"console-control-strings": {
"version": "1.1.0",
- "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+ "resolved": false,
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
},
"core-util-is": {
"version": "1.0.2",
- "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "resolved": false,
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"debug": {
@@ -5369,22 +4876,22 @@
},
"deep-extend": {
"version": "0.6.0",
- "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "resolved": false,
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
},
"delegates": {
"version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+ "resolved": false,
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
},
"detect-libc": {
"version": "1.0.3",
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
+ "resolved": false,
"integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups="
},
"fs-minipass": {
"version": "1.2.5",
- "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz",
+ "resolved": false,
"integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==",
"requires": {
"minipass": "^2.2.1"
@@ -5392,12 +4899,12 @@
},
"fs.realpath": {
"version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "resolved": false,
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"gauge": {
"version": "2.7.4",
- "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+ "resolved": false,
"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
"requires": {
"aproba": "^1.0.3",
@@ -5412,12 +4919,12 @@
},
"has-unicode": {
"version": "2.0.1",
- "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+ "resolved": false,
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
},
"iconv-lite": {
"version": "0.4.23",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
+ "resolved": false,
"integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
@@ -5425,7 +4932,7 @@
},
"ignore-walk": {
"version": "3.0.1",
- "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz",
+ "resolved": false,
"integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==",
"requires": {
"minimatch": "^3.0.4"
@@ -5433,7 +4940,7 @@
},
"inflight": {
"version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "resolved": false,
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"requires": {
"once": "^1.3.0",
@@ -5442,12 +4949,12 @@
},
"inherits": {
"version": "2.0.3",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "resolved": false,
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"ini": {
"version": "1.3.5",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+ "resolved": false,
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
},
"is-fullwidth-code-point": {
@@ -5460,12 +4967,12 @@
},
"isarray": {
"version": "1.0.0",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "resolved": false,
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"minimatch": {
"version": "3.0.4",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "resolved": false,
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"requires": {
"brace-expansion": "^1.1.7"
@@ -5478,7 +4985,7 @@
},
"minipass": {
"version": "2.3.5",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz",
+ "resolved": false,
"integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==",
"requires": {
"safe-buffer": "^5.1.2",
@@ -5487,7 +4994,7 @@
},
"mkdirp": {
"version": "0.5.1",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "resolved": false,
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"requires": {
"minimist": "0.0.8"
@@ -5495,7 +5002,7 @@
"dependencies": {
"minimist": {
"version": "0.0.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "resolved": false,
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
}
}
@@ -5528,7 +5035,7 @@
},
"npmlog": {
"version": "4.1.2",
- "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
+ "resolved": false,
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
"requires": {
"are-we-there-yet": "~1.1.2",
@@ -5539,17 +5046,17 @@
},
"number-is-nan": {
"version": "1.0.1",
- "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+ "resolved": false,
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
},
"object-assign": {
"version": "4.1.1",
- "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "resolved": false,
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
"once": {
"version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "resolved": false,
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
"wrappy": "1"
@@ -5557,17 +5064,17 @@
},
"os-homedir": {
"version": "1.0.2",
- "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+ "resolved": false,
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
},
"os-tmpdir": {
"version": "1.0.2",
- "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "resolved": false,
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
},
"osenv": {
"version": "0.1.5",
- "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
+ "resolved": false,
"integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
"requires": {
"os-homedir": "^1.0.0",
@@ -5576,17 +5083,17 @@
},
"path-is-absolute": {
"version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "resolved": false,
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"process-nextick-args": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+ "resolved": false,
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
},
"rc": {
"version": "1.2.8",
- "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+ "resolved": false,
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
"requires": {
"deep-extend": "^0.6.0",
@@ -5597,7 +5104,7 @@
},
"readable-stream": {
"version": "2.3.6",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "resolved": false,
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"requires": {
"core-util-is": "~1.0.0",
@@ -5616,22 +5123,22 @@
},
"safer-buffer": {
"version": "2.1.2",
- "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "resolved": false,
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"sax": {
"version": "1.2.4",
- "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "resolved": false,
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
},
"set-blocking": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "resolved": false,
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
},
"signal-exit": {
"version": "3.0.2",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+ "resolved": false,
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
},
"string-width": {
@@ -5662,12 +5169,12 @@
},
"strip-json-comments": {
"version": "2.0.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "resolved": false,
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
},
"tar": {
"version": "4.4.8",
- "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz",
+ "resolved": false,
"integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==",
"requires": {
"chownr": "^1.1.1",
@@ -5681,12 +5188,12 @@
},
"util-deprecate": {
"version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "resolved": false,
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"wide-align": {
"version": "1.1.3",
- "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
+ "resolved": false,
"integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
"requires": {
"string-width": "^1.0.2 || 2"
@@ -5694,12 +5201,12 @@
},
"wrappy": {
"version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "resolved": false,
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"yallist": {
"version": "3.0.3",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
+ "resolved": false,
"integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A=="
}
}
@@ -5715,13 +5222,13 @@
"dependencies": {
"abbrev": {
"version": "1.1.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz",
"integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=",
"dev": true
},
"ajv": {
"version": "4.11.8",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz",
"integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=",
"dev": true,
"requires": {
@@ -5737,13 +5244,13 @@
},
"aproba": {
"version": "1.1.2",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.2.tgz",
"integrity": "sha512-ZpYajIfO0j2cOFTO955KUMIKNmj6zhX8kVztMAxFsDaMwz+9Z9SV0uou2pC9HJqcfpffOsjnbrDMvkNy+9RXPw==",
"dev": true
},
"are-we-there-yet": {
"version": "1.1.4",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz",
"integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=",
"dev": true,
"requires": {
@@ -5753,31 +5260,31 @@
},
"asn1": {
"version": "0.2.3",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
"integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=",
"dev": true
},
"assert-plus": {
"version": "0.2.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
"integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=",
"dev": true
},
"asynckit": {
"version": "0.4.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
"dev": true
},
"aws-sign2": {
"version": "0.6.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
"integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=",
"dev": true
},
"aws4": {
"version": "1.6.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz",
"integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=",
"dev": true
},
@@ -5789,7 +5296,7 @@
},
"bcrypt-pbkdf": {
"version": "1.0.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
"integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
"dev": true,
"optional": true,
@@ -5799,7 +5306,7 @@
},
"block-stream": {
"version": "0.0.9",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
"integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
"dev": true,
"requires": {
@@ -5808,7 +5315,7 @@
},
"boom": {
"version": "2.10.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
"integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=",
"dev": true,
"requires": {
@@ -5817,7 +5324,7 @@
},
"brace-expansion": {
"version": "1.1.8",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
"integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
"dev": true,
"requires": {
@@ -5827,13 +5334,13 @@
},
"caseless": {
"version": "0.12.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
"dev": true
},
"co": {
"version": "4.6.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
"dev": true
},
@@ -5845,7 +5352,7 @@
},
"combined-stream": {
"version": "1.0.5",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz",
"integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=",
"dev": true,
"requires": {
@@ -5872,7 +5379,7 @@
},
"cryptiles": {
"version": "2.0.5",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz",
"integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=",
"dev": true,
"requires": {
@@ -5881,7 +5388,7 @@
},
"dashdash": {
"version": "1.14.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
"dev": true,
"requires": {
@@ -5890,7 +5397,7 @@
"dependencies": {
"assert-plus": {
"version": "1.0.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
"dev": true
}
@@ -5898,7 +5405,7 @@
},
"debug": {
"version": "2.6.8",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
"integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=",
"dev": true,
"requires": {
@@ -5907,13 +5414,13 @@
},
"deep-extend": {
"version": "0.4.2",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz",
"integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=",
"dev": true
},
"delayed-stream": {
"version": "1.0.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
"dev": true
},
@@ -5925,7 +5432,7 @@
},
"ecc-jsbn": {
"version": "0.1.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
"integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
"dev": true,
"optional": true,
@@ -5935,25 +5442,25 @@
},
"extend": {
"version": "3.0.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
"integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=",
"dev": true
},
"extsprintf": {
"version": "1.3.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
"dev": true
},
"forever-agent": {
"version": "0.6.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
"dev": true
},
"form-data": {
"version": "2.1.4",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz",
"integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=",
"dev": true,
"requires": {
@@ -5970,7 +5477,7 @@
},
"fstream": {
"version": "1.0.11",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz",
"integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=",
"dev": true,
"requires": {
@@ -5982,7 +5489,7 @@
},
"fstream-ignore": {
"version": "1.0.5",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz",
"integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=",
"dev": true,
"requires": {
@@ -6009,7 +5516,7 @@
},
"getpass": {
"version": "0.1.7",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
"dev": true,
"requires": {
@@ -6018,7 +5525,7 @@
"dependencies": {
"assert-plus": {
"version": "1.0.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
"dev": true
}
@@ -6026,7 +5533,7 @@
},
"glob": {
"version": "7.1.2",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
"dev": true,
"requires": {
@@ -6040,19 +5547,19 @@
},
"graceful-fs": {
"version": "4.1.11",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
"dev": true
},
"har-schema": {
"version": "1.0.5",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz",
"integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=",
"dev": true
},
"har-validator": {
"version": "4.2.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz",
"integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=",
"dev": true,
"requires": {
@@ -6068,7 +5575,7 @@
},
"hawk": {
"version": "3.1.3",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
"integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=",
"dev": true,
"requires": {
@@ -6080,13 +5587,13 @@
},
"hoek": {
"version": "2.16.3",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
"integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=",
"dev": true
},
"http-signature": {
"version": "1.1.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
"integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=",
"dev": true,
"requires": {
@@ -6113,7 +5620,7 @@
},
"ini": {
"version": "1.3.4",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz",
"integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=",
"dev": true
},
@@ -6128,7 +5635,7 @@
},
"is-typedarray": {
"version": "1.0.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
"dev": true
},
@@ -6140,26 +5647,26 @@
},
"isstream": {
"version": "0.1.2",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
"dev": true
},
"jsbn": {
"version": "0.1.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
"dev": true,
"optional": true
},
"json-schema": {
"version": "0.2.3",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
"dev": true
},
"json-stable-stringify": {
"version": "1.0.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
"integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
"dev": true,
"requires": {
@@ -6168,19 +5675,19 @@
},
"json-stringify-safe": {
"version": "5.0.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
"dev": true
},
"jsonify": {
"version": "0.0.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
"integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
"dev": true
},
"jsprim": {
"version": "1.4.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
"dev": true,
"requires": {
@@ -6192,7 +5699,7 @@
"dependencies": {
"assert-plus": {
"version": "1.0.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
"dev": true
}
@@ -6200,13 +5707,13 @@
},
"mime-db": {
"version": "1.29.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.29.0.tgz",
"integrity": "sha1-SNJtI1WJZRcErFkWygYAGRQmaHg=",
"dev": true
},
"mime-types": {
"version": "2.1.16",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz",
"integrity": "sha1-K4WKUuXs1RbbiXrCvodIeDBpjiM=",
"dev": true,
"requires": {
@@ -6245,7 +5752,7 @@
},
"node-pre-gyp": {
"version": "0.6.36",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz",
"integrity": "sha1-22BBEst04NR3VU6bUFsXq936t4Y=",
"dev": true,
"requires": {
@@ -6290,7 +5797,7 @@
},
"oauth-sign": {
"version": "0.8.2",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
"integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=",
"dev": true
},
@@ -6323,7 +5830,7 @@
},
"osenv": {
"version": "0.1.4",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz",
"integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=",
"dev": true,
"requires": {
@@ -6339,31 +5846,31 @@
},
"performance-now": {
"version": "0.2.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz",
"integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=",
"dev": true
},
"process-nextick-args": {
"version": "1.0.7",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=",
"dev": true
},
"punycode": {
"version": "1.4.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
"dev": true
},
"qs": {
"version": "6.4.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz",
"integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=",
"dev": true
},
"rc": {
"version": "1.2.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz",
"integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=",
"dev": true,
"requires": {
@@ -6383,7 +5890,7 @@
},
"readable-stream": {
"version": "2.3.3",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
"integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
"dev": true,
"requires": {
@@ -6398,7 +5905,7 @@
},
"request": {
"version": "2.81.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz",
"integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=",
"dev": true,
"requires": {
@@ -6428,7 +5935,7 @@
},
"rimraf": {
"version": "2.6.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz",
"integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=",
"dev": true,
"requires": {
@@ -6437,13 +5944,13 @@
},
"safe-buffer": {
"version": "5.1.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
"dev": true
},
"semver": {
"version": "5.4.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
"integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==",
"dev": true
},
@@ -6461,7 +5968,7 @@
},
"sntp": {
"version": "1.0.9",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
"integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=",
"dev": true,
"requires": {
@@ -6470,7 +5977,7 @@
},
"sshpk": {
"version": "1.13.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz",
"integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=",
"dev": true,
"requires": {
@@ -6486,7 +5993,7 @@
"dependencies": {
"assert-plus": {
"version": "1.0.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
"dev": true
}
@@ -6505,7 +6012,7 @@
},
"string_decoder": {
"version": "1.0.3",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
"dev": true,
"requires": {
@@ -6514,7 +6021,7 @@
},
"stringstream": {
"version": "0.0.5",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
"integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=",
"dev": true
},
@@ -6535,7 +6042,7 @@
},
"tar": {
"version": "2.2.1",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz",
"integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=",
"dev": true,
"requires": {
@@ -6546,7 +6053,7 @@
},
"tar-pack": {
"version": "3.4.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.0.tgz",
"integrity": "sha1-I74tf2cagzk3bL2wuP4/3r8xeYQ=",
"dev": true,
"requires": {
@@ -6562,7 +6069,7 @@
},
"tough-cookie": {
"version": "2.3.2",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz",
"integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=",
"dev": true,
"requires": {
@@ -6571,7 +6078,7 @@
},
"tunnel-agent": {
"version": "0.6.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
"dev": true,
"requires": {
@@ -6580,14 +6087,14 @@
},
"tweetnacl": {
"version": "0.14.5",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
"dev": true,
"optional": true
},
"uid-number": {
"version": "0.0.6",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz",
"integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=",
"dev": true
},
@@ -6599,13 +6106,13 @@
},
"uuid": {
"version": "3.1.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz",
"integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==",
"dev": true
},
"verror": {
"version": "1.10.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
"dev": true,
"requires": {
@@ -6616,7 +6123,7 @@
"dependencies": {
"assert-plus": {
"version": "1.0.0",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
"dev": true
}
@@ -6624,7 +6131,7 @@
},
"wide-align": {
"version": "1.1.2",
- "resolved": false,
+ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz",
"integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==",
"dev": true,
"requires": {
@@ -8105,7 +7612,6 @@
"@jest/types": "^24.8.0",
"anymatch": "^2.0.0",
"fb-watchman": "^2.0.0",
- "fsevents": "^1.2.7",
"graceful-fs": "^4.1.15",
"invariant": "^2.2.4",
"jest-serializer": "^24.4.0",
diff --git a/package.json b/package.json
index 022507645..3c66d7525 100644
--- a/package.json
+++ b/package.json
@@ -118,7 +118,6 @@
"cli-table3": "^0.5.1",
"colors": "^1.3.3",
"cross-os": "^1.3.0",
- "crypto-js": "^3.1.9-1",
"dotenv": "^5.0.1",
"express": "^4.16.3",
"fastpriorityqueue": "^0.6.1",
diff --git a/proto/xudrpc.proto b/proto/xudrpc.proto
index 4e9b5fdf4..cf1b5b903 100644
--- a/proto/xudrpc.proto
+++ b/proto/xudrpc.proto
@@ -24,6 +24,28 @@ import "annotations.proto";
package xudrpc;
+service XudInit {
+ rpc CreateNode(CreateNodeRequest) returns (CreateNodeResponse) { }
+
+ rpc UnlockNode(UnlockNodeRequest) returns (UnlockNodeResponse) { }
+}
+
+message CreateNodeRequest {
+ // The password in utf-8 with which to encrypt the new xud node key as well
+ // as underlying client wallets such as lnd.
+ string password = 1;
+}
+message CreateNodeResponse {
+ repeated string seed_mnemonic = 1;
+}
+
+message UnlockNodeRequest {
+ // The password in utf-8 with which to unlock an existing xud node key as
+ // well as underlying client wallets such as lnd.
+ string password = 1;
+}
+message UnlockNodeResponse { }
+
service Xud {
/* Adds a currency to the list of supported currencies. Once added, the currency may be used for
* new trading pairs. */
diff --git a/test/crypto/handshake.ts b/test/crypto/handshake.ts
index b0d6477c9..d5fa0e862 100644
--- a/test/crypto/handshake.ts
+++ b/test/crypto/handshake.ts
@@ -41,8 +41,8 @@ describe('key exchange and symmetric encryption', () => {
describe('authentication', () => {
it('alice should sign its session init data and bob should be able to verify it', async () => {
const aliceNodeKey = await NodeKey['generate']();
- const aliceNodePubKey = aliceNodeKey.nodePubKey;
- const aliceNodePrivKey = aliceNodeKey['privKey'];
+ const aliceNodePubKey = aliceNodeKey.pubKey;
+ const aliceNodePrivKey = aliceNodeKey.privKey;
const alice = createECDH('secp256k1');
const aliceEphemeralPubKey = alice.generateKeys();
diff --git a/test/simulation/tests.go b/test/simulation/tests.go
index 5dd1193bb..b4c69c773 100644
--- a/test/simulation/tests.go
+++ b/test/simulation/tests.go
@@ -26,7 +26,10 @@ func testNetworkInit(net *xudtest.NetworkHarness, ht *harnessTest) {
for {
req := &xudrpc.GetInfoRequest{}
res, err := node.Client.GetInfo(ht.ctx, req)
+
ht.assert.NoError(err)
+ ht.assert.NotNil(res.Lnd["BTC"])
+ ht.assert.NotNil(res.Lnd["LTC"])
if len(res.Lnd["BTC"].Chains) == 1 && len(res.Lnd["LTC"].Chains) == 1 {
ht.assert.Equal(res.Lnd["BTC"].Chains[0].Chain, "bitcoin")
ht.assert.Equal(res.Lnd["BTC"].Chains[0].Network, "simnet")
diff --git a/test/unit/NodeKey.spec.ts b/test/unit/NodeKey.spec.ts
index 4868a92a8..2fe3112fb 100644
--- a/test/unit/NodeKey.spec.ts
+++ b/test/unit/NodeKey.spec.ts
@@ -1,12 +1,38 @@
import { expect } from 'chai';
import NodeKey from '../../lib/nodekey/NodeKey';
import secp256k1 from 'secp256k1';
+import { getTempDir } from '../utils';
describe('NodeKey', () => {
it('should generate a valid node key', async () => {
const nodeKey = await NodeKey['generate']();
- expect(nodeKey.nodePubKey).to.have.length(66);
+ expect(nodeKey.pubKey).to.have.length(66);
expect(secp256k1.privateKeyVerify(nodeKey['privKey'])).to.be.true;
- expect(secp256k1.publicKeyVerify(Buffer.from(nodeKey.nodePubKey, 'hex'))).to.be.true;
+ expect(secp256k1.publicKeyVerify(Buffer.from(nodeKey.pubKey, 'hex'))).to.be.true;
+ });
+
+ it('should write a nodekey to disk and read it back without encryption', async () => {
+ const nodeKey = await NodeKey['generate']();
+ const path = NodeKey.getPath(getTempDir(true));
+ await nodeKey.toFile(path);
+ const nodeKeyFromDisk = await NodeKey.fromFile(path);
+ expect(nodeKey.privKey.compare(nodeKeyFromDisk.privKey)).to.equal(0);
+ });
+
+ it('should write a nodekey to disk and read it back with encryption', async () => {
+ const password = 'wasspord';
+ const nodeKey = await NodeKey['generate']();
+ const path = NodeKey.getPath(getTempDir(true));
+ await nodeKey.toFile(path, password);
+ const nodeKeyFromDisk = await NodeKey.fromFile(path, password);
+ expect(nodeKey.privKey.compare(nodeKeyFromDisk.privKey)).to.equal(0);
+ });
+
+ it('should write a nodekey to disk with encryption and fail reading it with the wrong password', async () => {
+ const password = 'wasspord';
+ const nodeKey = await NodeKey['generate']();
+ const path = NodeKey.getPath(getTempDir(true));
+ await nodeKey.toFile(path, password);
+ expect(NodeKey.fromFile(path, 'wrongpassword')).to.eventually.throw;
});
});