xud
Version:
Exchange Union Daemon
155 lines • 7.4 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const events_1 = require("events");
const fs_1 = require("fs");
const enums_1 = require("../constants/enums");
const errors_1 = require("../lndclient/errors");
const NodeKey_1 = __importDefault(require("../nodekey/NodeKey"));
const errors_2 = __importDefault(require("../swaps/errors"));
const seedutil_1 = require("../utils/seedutil");
const errors_3 = __importDefault(require("./errors"));
/** A class containing the methods available for a locked, uninitialized instance of xud. */
class InitService extends events_1.EventEmitter {
constructor(swapClientManager, nodeKeyPath, nodeKeyExists, databasePath) {
super();
this.swapClientManager = swapClientManager;
this.nodeKeyPath = nodeKeyPath;
this.nodeKeyExists = nodeKeyExists;
this.databasePath = databasePath;
/** Whether there is a pending `CreateNode` or `UnlockNode` call. */
this.pendingCall = false;
this.createNode = (args) => __awaiter(this, void 0, void 0, function* () {
const { password } = args;
this.newWalletValidation(password);
try {
yield this.prepareCall(true);
const seedMnemonic = yield seedutil_1.generate();
// we use the deciphered seed (without the salt and extra fields that make up the enciphered seed)
// to generate an xud nodekey from the same seed used for wallets
const decipheredSeed = yield seedutil_1.decipher(seedMnemonic);
const nodeKey = NodeKey_1.default.fromBytes(decipheredSeed, this.nodeKeyPath);
// use this seed to init any lnd wallets that are uninitialized
const initWalletResult = yield this.swapClientManager.initWallets({
seedMnemonic,
nodeKey,
walletPassword: password,
});
yield nodeKey.toFile(password);
this.emit('nodekey', nodeKey);
return {
initializedLndWallets: initWalletResult.initializedLndWallets,
initializedConnext: initWalletResult.initializedConnext,
mnemonic: seedMnemonic,
};
}
finally {
this.pendingCall = false;
}
});
this.unlockNode = (args) => __awaiter(this, void 0, void 0, function* () {
const { password } = args;
if (!this.nodeKeyExists) {
throw errors_3.default.NODE_DOES_NOT_EXIST;
}
try {
yield this.prepareCall(true);
const nodeKey = yield NodeKey_1.default.fromFile(this.nodeKeyPath, password);
this.emit('nodekey', nodeKey);
return this.swapClientManager.unlockWallets({
nodeKey,
walletPassword: password,
connextSeed: nodeKey.childSeed(enums_1.SwapClientType.Connext),
});
}
catch (err) {
if (err.code === 'ERR_OSSL_EVP_BAD_DECRYPT') {
throw errors_3.default.INVALID_ARGUMENT('password is incorrect');
}
else {
throw err;
}
}
finally {
this.pendingCall = false;
}
});
this.restoreNode = (args) => __awaiter(this, void 0, void 0, function* () {
const { password, xudDatabase, lndBackupsMap, seedMnemonicList, } = args;
if (seedMnemonicList.length !== 24) {
throw errors_3.default.INVALID_ARGUMENT('mnemonic must be exactly 24 words');
}
this.newWalletValidation(password);
try {
yield this.prepareCall();
const decipheredSeed = yield seedutil_1.decipher(seedMnemonicList);
const nodeKey = NodeKey_1.default.fromBytes(decipheredSeed, this.nodeKeyPath);
// use the seed and database backups to restore any swap clients' wallets
// that are uninitialized
const initWalletResult = yield this.swapClientManager.initWallets({
nodeKey,
lndBackups: lndBackupsMap,
walletPassword: password,
seedMnemonic: seedMnemonicList,
restore: true,
});
if (xudDatabase.byteLength) {
yield fs_1.promises.writeFile(this.databasePath, xudDatabase);
}
yield nodeKey.toFile(password);
this.emit('nodekey', nodeKey);
return {
initializedLndWallets: initWalletResult.initializedLndWallets,
initializedConnext: initWalletResult.initializedConnext,
};
}
finally {
this.pendingCall = false;
}
});
this.newWalletValidation = (password) => {
if (this.nodeKeyExists) {
throw errors_3.default.NODE_ALREADY_EXISTS;
}
if (password.length < 8) {
// lnd requires 8+ character passwords, so we must as well
throw errors_3.default.INVALID_ARGUMENT('password must be at least 8 characters');
}
if (this.swapClientManager.misconfiguredClients.size > 0) {
const misconfiguredClientLabels = [];
this.swapClientManager.misconfiguredClients.forEach((client) => {
misconfiguredClientLabels.push(client.label);
});
throw errors_2.default.SWAP_CLIENT_MISCONFIGURED(misconfiguredClientLabels);
}
};
this.prepareCall = (ignoreUnavailableClients = false) => __awaiter(this, void 0, void 0, function* () {
if (this.pendingCall) {
throw errors_3.default.PENDING_CALL_CONFLICT;
}
this.pendingCall = true;
// wait briefly for all lnd instances to be available
try {
yield this.swapClientManager.waitForLnd();
}
catch (err) {
if (!ignoreUnavailableClients || err.code !== errors_1.errorCodes.UNAVAILABLE) {
throw err;
}
}
});
}
}
exports.default = InitService;
//# sourceMappingURL=InitService.js.map