xud
Version:
Exchange Union Daemon
753 lines • 35.8 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 rxjs_1 = require("rxjs");
const operators_1 = require("rxjs/operators");
const enums_1 = require("../constants/enums");
const Logger_1 = require("../Logger");
const types_1 = require("../orderbook/types");
const errors_1 = __importDefault(require("../swaps/errors"));
const aliasUtils_1 = require("../utils/aliasUtils");
const uriUtils_1 = require("../utils/uriUtils");
const utils_1 = require("../utils/utils");
const Version_1 = __importDefault(require("../Version"));
const errors_2 = __importDefault(require("./errors"));
/** Functions to check argument validity and throw [[INVALID_ARGUMENT]] when invalid. */
const argChecks = {
HAS_HOST: ({ host }) => { if (host === '')
throw errors_2.default.INVALID_ARGUMENT('host must be specified'); },
HAS_ORDER_ID: ({ orderId }) => { if (orderId === '')
throw errors_2.default.INVALID_ARGUMENT('orderId must be specified'); },
HAS_NODE_PUB_KEY: ({ nodePubKey }) => {
if (nodePubKey === '')
throw errors_2.default.INVALID_ARGUMENT('nodePubKey must be specified');
},
HAS_NODE_IDENTIFIER: ({ nodeIdentifier }) => {
if (nodeIdentifier === '')
throw errors_2.default.INVALID_ARGUMENT('peerPubKey or alias must be specified');
},
HAS_PAIR_ID: ({ pairId }) => { if (pairId === '')
throw errors_2.default.INVALID_ARGUMENT('pairId must be specified'); },
HAS_RHASH: ({ rHash }) => { if (rHash === '')
throw errors_2.default.INVALID_ARGUMENT('rHash must be specified'); },
POSITIVE_AMOUNT: ({ amount }) => { if (amount <= 0)
throw errors_2.default.INVALID_ARGUMENT('amount must be greater than 0'); },
PRICE_NON_NEGATIVE: ({ price }) => { if (price < 0)
throw errors_2.default.INVALID_ARGUMENT('price cannot be negative'); },
PRICE_MAX_DECIMAL_PLACES: ({ price }) => {
if (utils_1.checkDecimalPlaces(price))
throw errors_2.default.INVALID_ARGUMENT('price cannot have more than 12 decimal places');
},
VALID_CURRENCY: ({ currency }) => {
if (currency.length < 2 || currency.length > 5 || !currency.match(/^[A-Z0-9]+$/)) {
throw errors_2.default.INVALID_ARGUMENT('currency must consist of 2 to 5 upper case English letters or numbers');
}
},
VALID_PORT: ({ port }) => {
if (port < 1024 || port > 65535 || !Number.isInteger(port))
throw errors_2.default.INVALID_ARGUMENT('port must be an integer between 1024 and 65535');
},
VALID_SWAP_CLIENT: ({ swapClient }) => {
if (!enums_1.SwapClientType[swapClient])
throw errors_2.default.INVALID_ARGUMENT('swap client is not recognized');
},
VALID_FEE: ({ swapClient, fee }) => {
if (swapClient === enums_1.SwapClientType.Connext && fee)
throw errors_2.default.INVALID_ARGUMENT('fee is not valid for connext');
},
};
/** A class containing the available RPC methods for an unlocked, running instance of xud. */
class Service extends events_1.EventEmitter {
/** Create an instance of available RPC methods and bind all exposed functions. */
constructor(components) {
super();
/** Whether the service is disabled - in other words whether xud is locked. */
this.disabled = false;
/** Adds a currency. */
this.addCurrency = (args) => __awaiter(this, void 0, void 0, function* () {
argChecks.VALID_CURRENCY(args);
argChecks.VALID_SWAP_CLIENT(args);
const { currency, swapClient, tokenAddress, decimalPlaces } = args;
let address = tokenAddress;
if (args.swapClient === enums_1.SwapClientType.Connext && address) {
address = utils_1.toEip55Address(address);
}
yield this.orderBook.addCurrency({
swapClient,
decimalPlaces,
id: currency,
tokenAddress: address,
});
});
/** Adds a trading pair. */
this.addPair = (args) => __awaiter(this, void 0, void 0, function* () {
yield this.orderBook.addPair(args);
});
/*
* Remove placed order from the orderbook.
*/
this.removeOrder = (args) => {
const { orderId, quantity } = args;
argChecks.HAS_ORDER_ID(args);
return this.orderBook.removeOwnOrderByLocalId(orderId, true, quantity);
};
/*
* Removes all placed orders from the orderbook.
*/
this.removeAllOrders = () => __awaiter(this, void 0, void 0, function* () {
return this.orderBook.removeOwnOrders();
});
/** Gets the total balance for one or all currencies. */
this.getBalance = (args) => __awaiter(this, void 0, void 0, function* () {
const { currency } = args;
const channelBalances = new Map();
const walletBalances = new Map();
if (currency) {
argChecks.VALID_CURRENCY(args);
const swapClient = this.swapClientManager.get(currency.toUpperCase());
if (swapClient) {
const [channelBalance, walletBalance] = yield Promise.all([
yield swapClient.channelBalance(currency),
yield swapClient.walletBalance(currency),
]);
channelBalances.set(currency, channelBalance);
walletBalances.set(currency, walletBalance);
}
else {
throw errors_1.default.SWAP_CLIENT_NOT_FOUND(currency);
}
}
else {
const balancePromises = [];
this.swapClientManager.swapClients.forEach((swapClient, currency) => {
if (swapClient.isConnected()) {
balancePromises.push(swapClient.channelBalance(currency).then((channelBalance) => {
channelBalances.set(currency, channelBalance);
}).catch(this.logger.error));
balancePromises.push(swapClient.walletBalance(currency).then((walletBalance) => {
walletBalances.set(currency, walletBalance);
}).catch(this.logger.error));
}
});
yield Promise.all(balancePromises);
}
const balances = new Map();
channelBalances.forEach((channelBalance, currency) => {
const walletBalance = walletBalances.get(currency);
if (walletBalance) {
// check to make sure we have a wallet balance, which isn't guaranteed since it may involve
// a separate call from the one to get channel balance. unless we have both wallet and
// channel balances for a given currency, we don't want to return any balance for it
const totalBalance = channelBalance.balance + channelBalance.pendingOpenBalance + channelBalance.inactiveBalance +
walletBalance.confirmedBalance + walletBalance.unconfirmedBalance;
balances.set(currency, {
totalBalance,
channelBalance: channelBalance.balance,
pendingChannelBalance: channelBalance.pendingOpenBalance,
inactiveChannelBalance: channelBalance.inactiveBalance,
walletBalance: walletBalance.confirmedBalance,
unconfirmedWalletBalance: walletBalance.unconfirmedBalance,
});
}
});
return balances;
});
/** Gets the trading limits (max outbound and inbound capacities for a distinct channel) for one or all currencies. */
this.tradingLimits = (args) => __awaiter(this, void 0, void 0, function* () {
const { currency } = args;
const tradingLimitsMap = new Map();
if (currency) {
argChecks.VALID_CURRENCY(args);
const tradingLimits = yield this.swapClientManager.tradingLimits(currency.toUpperCase());
tradingLimitsMap.set(currency, tradingLimits);
}
else {
const promises = [];
this.swapClientManager.swapClients.forEach((swapClient, currency) => {
if (swapClient.isConnected()) {
promises.push(this.swapClientManager.tradingLimits(currency).then((tradingLimits) => {
tradingLimitsMap.set(currency, tradingLimits);
}).catch(this.logger.error));
}
});
yield Promise.all(promises);
}
return tradingLimitsMap;
});
/**
* Connect to an XU node on a given node uri.
*/
this.connect = (args) => __awaiter(this, void 0, void 0, function* () {
const { nodeUri, retryConnecting } = args;
let uriParts;
try {
uriParts = uriUtils_1.parseUri(nodeUri);
}
catch (err) {
throw errors_2.default.INVALID_ARGUMENT('uri is invalid');
}
const { nodePubKey, host, port } = uriParts;
argChecks.HAS_NODE_PUB_KEY({ nodePubKey });
argChecks.HAS_HOST({ host });
argChecks.VALID_PORT({ port });
yield this.pool.addOutbound({ host, port }, nodePubKey, retryConnecting, true);
});
this.walletDeposit = (args) => __awaiter(this, void 0, void 0, function* () {
const { currency } = args;
const address = yield this.swapClientManager.deposit(currency);
return address;
});
this.walletWithdraw = (args) => __awaiter(this, void 0, void 0, function* () {
const txId = yield this.swapClientManager.withdraw(args);
return txId;
});
/*
* Closes any payment channels for a specified node and currency.
*/
this.closeChannel = (args) => __awaiter(this, void 0, void 0, function* () {
const { nodeIdentifier, currency, force, destination, amount, fee } = args;
argChecks.VALID_CURRENCY({ currency });
const swapClientType = this.swapClientManager.getType(currency);
let remoteIdentifier;
if (nodeIdentifier) {
const nodePubKey = aliasUtils_1.isNodePubKey(nodeIdentifier) ? nodeIdentifier : this.pool.resolveAlias(nodeIdentifier);
if (swapClientType === undefined) {
throw errors_1.default.SWAP_CLIENT_NOT_FOUND(currency);
}
const peer = this.pool.getPeer(nodePubKey);
remoteIdentifier = peer.getIdentifier(swapClientType, currency);
}
const closeChannelTxs = yield this.swapClientManager.closeChannel({
currency,
force,
destination,
amount,
remoteIdentifier,
fee,
});
if (closeChannelTxs.length === 0) {
if (swapClientType === enums_1.SwapClientType.Connext) {
throw errors_2.default.NO_CHANNELS_TO_CLOSE('connext');
}
else {
throw errors_2.default.NO_CHANNELS_TO_CLOSE(nodeIdentifier);
}
}
return closeChannelTxs;
});
/*
* Opens a payment channel to a specified node, currency and amount.
*/
this.openChannel = (args) => __awaiter(this, void 0, void 0, function* () {
const { nodeIdentifier, amount, currency, pushAmount, fee } = args;
argChecks.POSITIVE_AMOUNT({ amount });
argChecks.VALID_CURRENCY({ currency });
argChecks.VALID_FEE({ fee, swapClient: this.swapClientManager.getType(currency) });
let remoteIdentifier;
let uris;
if (nodeIdentifier) {
const nodePubKey = aliasUtils_1.isNodePubKey(nodeIdentifier) ? nodeIdentifier : this.pool.resolveAlias(nodeIdentifier);
const swapClientType = this.swapClientManager.getType(currency);
if (swapClientType === undefined) {
throw errors_1.default.SWAP_CLIENT_NOT_FOUND(currency);
}
const peer = this.pool.getPeer(nodePubKey);
remoteIdentifier = peer.getIdentifier(swapClientType, currency);
if (swapClientType === enums_1.SwapClientType.Lnd) {
uris = peer.getLndUris(currency);
}
}
try {
return yield this.swapClientManager.openChannel({
remoteIdentifier,
uris,
amount,
currency,
pushAmount,
fee,
});
}
catch (e) {
const errorMessage = e.message || 'unknown';
throw errors_2.default.OPEN_CHANNEL_FAILURE(currency, amount, errorMessage, nodeIdentifier);
}
});
/*
* Ban a XU node manually and disconnect from it.
*/
this.ban = (args) => __awaiter(this, void 0, void 0, function* () {
argChecks.HAS_NODE_IDENTIFIER(args);
const nodePubKey = aliasUtils_1.isNodePubKey(args.nodeIdentifier) ? args.nodeIdentifier : this.pool.resolveAlias(args.nodeIdentifier);
yield this.pool.banNode(nodePubKey);
});
/*
* Remove ban from XU node manually and connenct to it.
*/
this.unban = (args) => __awaiter(this, void 0, void 0, function* () {
argChecks.HAS_NODE_IDENTIFIER(args);
const nodePubKey = aliasUtils_1.isNodePubKey(args.nodeIdentifier) ? args.nodeIdentifier : this.pool.resolveAlias(args.nodeIdentifier);
return this.pool.unbanNode(nodePubKey, args.reconnect);
});
this.executeSwap = (args) => __awaiter(this, void 0, void 0, function* () {
if (!this.orderBook.nomatching) {
throw errors_2.default.NOMATCHING_MODE_IS_REQUIRED();
}
const { orderId, pairId, peerPubKey } = args;
const quantity = args.quantity > 0 ? args.quantity : undefined; // passing 0 quantity will work fine, but it's prone to bugs
const maker = this.orderBook.removePeerOrder(orderId, pairId, peerPubKey, quantity).order;
const taker = this.orderBook.stampOwnOrder({
pairId,
localId: '',
price: maker.price,
isBuy: !maker.isBuy,
quantity: quantity || maker.quantity,
});
const swapSuccess = yield this.orderBook.executeSwap(maker, taker);
swapSuccess.localId = ''; // we shouldn't return the localId for ExecuteSwap in nomatching mode
return swapSuccess;
});
/**
* Gets information about a specified node.
*/
this.getMnemonic = () => __awaiter(this, void 0, void 0, function* () {
const mnemonic = yield this.nodekey.getMnemonic();
return mnemonic;
});
/**
* Gets Ethereum mnemonic
*/
this.getETHMnemonic = () => __awaiter(this, void 0, void 0, function* () {
return this.nodekey.childSeed(enums_1.SwapClientType.Connext);
});
/**
* Gets information about a specified node.
*/
this.getNodeInfo = (args) => __awaiter(this, void 0, void 0, function* () {
argChecks.HAS_NODE_IDENTIFIER(args);
const nodePubKey = aliasUtils_1.isNodePubKey(args.nodeIdentifier) ? args.nodeIdentifier : this.pool.resolveAlias(args.nodeIdentifier);
const info = yield this.pool.getNodeReputation(nodePubKey);
return info;
});
/**
* Get general information about this Exchange Union node.
*/
this.getInfo = () => __awaiter(this, void 0, void 0, function* () {
var _a;
const { nodePubKey, addresses, alias } = this.pool;
const uris = [];
if (addresses && addresses.length > 0) {
addresses.forEach((address) => {
uris.push(uriUtils_1.toUri({ nodePubKey, host: address.host, port: address.port }));
});
}
let peerOrdersCount = 0;
let ownOrdersCount = 0;
const network = this.pool.getNetwork();
let numPairs = 0;
for (const pairId of this.orderBook.pairIds) {
const peerOrders = this.orderBook.getPeersOrders(pairId);
const ownOrders = this.orderBook.getOwnOrders(pairId);
peerOrdersCount += Object.keys(peerOrders.buyArray).length + Object.keys(peerOrders.sellArray).length;
ownOrdersCount += Object.keys(ownOrders.buyArray).length + Object.keys(ownOrders.sellArray).length;
numPairs += 1;
}
const lnd = yield this.swapClientManager.getLndClientsInfo();
const connext = yield ((_a = this.swapClientManager.connextClient) === null || _a === void 0 ? void 0 : _a.getInfo());
if (connext) {
connext.chain = `${connext.chain ? connext.chain : ''}connext ${this.pool.getNetwork()}`;
}
return {
lnd,
connext,
nodePubKey,
uris,
numPairs,
network,
alias,
version: `${this.version}${Version_1.default}`,
numPeers: this.pool.peerCount,
orders: {
peer: peerOrdersCount,
own: ownOrdersCount,
},
pendingSwapHashes: this.swaps.getPendingSwapHashes(),
};
});
this.setLogLevel = (args) => __awaiter(this, void 0, void 0, function* () {
const level = Logger_1.LevelPriority[args.logLevel];
this.emit('logLevel', level);
});
this.toServiceOrder = (order, includeAliases = false) => {
var _a;
const { id, createdAt, pairId, price, quantity } = order;
let serviceOrder;
if (types_1.isOwnOrder(order)) {
serviceOrder = {
id,
createdAt,
pairId,
price,
quantity,
side: order.isBuy ? enums_1.OrderSide.Buy : enums_1.OrderSide.Sell,
isOwnOrder: true,
localId: order.localId,
hold: order.hold,
nodeIdentifier: {
nodePubKey: this.pool.nodePubKey,
alias: includeAliases ? this.pool.alias : undefined,
},
};
}
else {
serviceOrder = {
id,
createdAt,
pairId,
price,
quantity,
side: order.isBuy ? enums_1.OrderSide.Buy : enums_1.OrderSide.Sell,
isOwnOrder: false,
nodeIdentifier: {
nodePubKey: order.peerPubKey,
alias: includeAliases ? (_a = this.pool.getPeer(order.peerPubKey)) === null || _a === void 0 ? void 0 : _a.alias : undefined,
},
};
}
return serviceOrder;
};
/**
* Get a map between pair ids and its orders from the order book.
*/
this.listOrders = (args) => {
const { pairId, owner, limit, includeAliases } = args;
const includeOwnOrders = owner === enums_1.Owner.Both || owner === enums_1.Owner.Own;
const includePeerOrders = owner === enums_1.Owner.Both || owner === enums_1.Owner.Peer;
const result = new Map();
const listOrderTypes = (pairId) => {
let buyArray = [];
let sellArray = [];
if (includePeerOrders) {
const peerOrders = this.orderBook.getPeersOrders(pairId);
buyArray = buyArray.concat(peerOrders.buyArray);
sellArray = sellArray.concat(peerOrders.sellArray);
}
if (includeOwnOrders) {
const ownOrders = this.orderBook.getOwnOrders(pairId);
buyArray = buyArray.concat(ownOrders.buyArray);
sellArray = sellArray.concat(ownOrders.sellArray);
}
// sort all orders
buyArray = utils_1.sortOrders(buyArray, true);
sellArray = utils_1.sortOrders(sellArray, false);
if (limit > 0) {
buyArray = buyArray.slice(-limit);
sellArray = sellArray.slice(-limit);
}
return {
buyArray: buyArray.map(order => this.toServiceOrder(order, includeAliases)),
sellArray: sellArray.map(order => this.toServiceOrder(order, includeAliases)),
};
};
if (pairId) {
result.set(pairId, listOrderTypes(pairId));
}
else {
this.orderBook.pairIds.forEach((pairId) => {
result.set(pairId, listOrderTypes(pairId));
});
}
return result;
};
/**
* Get the list of the order book's supported currencies
* @returns A list of supported currency ticker symbols
*/
this.listCurrencies = () => {
return this.orderBook.currencies;
};
/**
* Get the list of the order book's supported pairs.
* @returns A list of supported trading pair tickers
*/
this.listPairs = () => {
return this.orderBook.pairIds;
};
/**
* Get information about currently connected peers.
* @returns A list of connected peers with key information for each peer
*/
this.listPeers = () => {
return this.pool.listPeers();
};
/**
* Gets trading history.
*/
this.tradeHistory = (args) => __awaiter(this, void 0, void 0, function* () {
const { limit } = args;
const trades = yield this.orderBook.getTrades(limit || undefined);
const orderInstanceToServiceOrder = (order, quantity) => {
const isOwnOrder = !!order.localId;
let nodeIdentifier;
if (isOwnOrder) {
nodeIdentifier = {
nodePubKey: this.pool.nodePubKey,
alias: this.pool.alias,
};
}
else {
const nodePubKey = this.pool.getNodePubKeyById(order.nodeId);
nodeIdentifier = {
nodePubKey,
alias: this.pool.getNodeAlias(nodePubKey),
};
}
return {
isOwnOrder,
nodeIdentifier,
quantity,
id: order.id,
pairId: order.pairId,
price: order.price,
side: order.isBuy ? enums_1.OrderSide.Buy : enums_1.OrderSide.Sell,
localId: order.localId,
createdAt: order.createdAt,
};
};
const serviceTrades = trades.map((trade) => {
const takerOrder = trade.takerOrder ? orderInstanceToServiceOrder(trade.takerOrder, trade.quantity) : undefined;
const makerOrder = orderInstanceToServiceOrder(trade.makerOrder, trade.quantity);
let role;
let side;
let counterparty;
if (takerOrder) {
if (makerOrder.isOwnOrder) {
role = enums_1.SwapRole.Internal;
side = enums_1.OrderSide.Both;
}
else {
role = enums_1.SwapRole.Taker;
side = takerOrder.side;
}
}
else {
// no taker order means we were the maker in a swap
role = enums_1.SwapRole.Maker;
side = makerOrder.side;
}
if (trade.SwapDeal) {
const nodePubKey = trade.SwapDeal.peerPubKey;
counterparty = {
nodePubKey,
alias: this.pool.getNodeAlias(nodePubKey),
};
}
return {
makerOrder,
takerOrder,
role,
side,
counterparty,
rHash: trade.rHash,
quantity: trade.quantity,
pairId: makerOrder.pairId,
price: makerOrder.price,
executedAt: trade.createdAt.getTime(),
};
});
return serviceTrades;
});
/**
* Add an order to the order book.
* If price is zero or unspecified a market order will get added.
*/
this.placeOrder = (args, callback) => __awaiter(this, void 0, void 0, function* () {
argChecks.PRICE_NON_NEGATIVE(args);
argChecks.PRICE_MAX_DECIMAL_PLACES(args);
argChecks.HAS_PAIR_ID(args);
const { pairId, price, quantity, orderId, side, replaceOrderId, immediateOrCancel } = args;
const order = {
pairId,
price,
quantity,
isBuy: side === enums_1.OrderSide.Buy,
localId: orderId || replaceOrderId,
};
/** Modified callback that converts Order to ServiceOrder before passing to callback. */
const serviceCallback = callback ? (e) => {
const { type, order, swapSuccess, swapFailure } = e;
callback({
type,
swapSuccess,
swapFailure,
order: order ? this.toServiceOrder(order, true) : undefined,
});
} : undefined;
const placeOrderRequest = {
order,
immediateOrCancel,
replaceOrderId,
onUpdate: serviceCallback,
};
return price > 0 ? yield this.orderBook.placeLimitOrder(placeOrderRequest) :
yield this.orderBook.placeMarketOrder(placeOrderRequest);
});
/** Removes a currency. */
this.removeCurrency = (args) => __awaiter(this, void 0, void 0, function* () {
argChecks.VALID_CURRENCY(args);
const { currency } = args;
yield this.orderBook.removeCurrency(currency);
});
/** Removes a trading pair. */
this.removePair = (args) => __awaiter(this, void 0, void 0, function* () {
argChecks.HAS_PAIR_ID(args);
const { pairId } = args;
return this.orderBook.removePair(pairId);
});
/** Discover nodes from a specific peer and apply new connections */
this.discoverNodes = (args) => __awaiter(this, void 0, void 0, function* () {
argChecks.HAS_NODE_IDENTIFIER(args);
const nodePubKey = aliasUtils_1.isNodePubKey(args.nodeIdentifier) ? args.nodeIdentifier : this.pool.resolveAlias(args.nodeIdentifier);
return this.pool.discoverNodes(nodePubKey);
});
/*
* Subscribe to orders being added to the order book.
*/
this.subscribeOrders = (args, callback, cancelled$) => {
if (args.existing) {
this.orderBook.pairIds.forEach((pair) => {
const ownOrders = this.orderBook.getOwnOrders(pair);
const peerOrders = this.orderBook.getPeersOrders(pair);
ownOrders.buyArray.forEach(order => callback(this.toServiceOrder(order, false)));
peerOrders.buyArray.forEach(order => callback(this.toServiceOrder(order, true)));
ownOrders.sellArray.forEach(order => callback(this.toServiceOrder(order, false)));
peerOrders.sellArray.forEach(order => callback(this.toServiceOrder(order, true)));
});
}
const orderAdded$ = rxjs_1.merge(rxjs_1.fromEvent(this.orderBook, 'peerOrder.incoming'), rxjs_1.fromEvent(this.orderBook, 'ownOrder.added')).pipe(operators_1.takeUntil(cancelled$)); // cleanup listeners when cancelled$ emits a value
orderAdded$.subscribe({
next: order => callback(this.toServiceOrder(order, true)),
error: this.logger.error,
});
const orderRemoved$ = rxjs_1.merge(rxjs_1.fromEvent(this.orderBook, 'peerOrder.invalidation'), rxjs_1.fromEvent(this.orderBook, 'peerOrder.filled'), rxjs_1.fromEvent(this.orderBook, 'ownOrder.filled'), rxjs_1.fromEvent(this.orderBook, 'ownOrder.removed')).pipe(operators_1.takeUntil(cancelled$)); // cleanup listeners when cancelled$ emits a value
orderRemoved$.subscribe({
next: (orderPortion) => { callback(undefined, orderPortion); },
error: this.logger.error,
});
};
/*
* Subscribe to completed swaps.
*/
this.subscribeSwaps = (args, callback, cancelled$) => __awaiter(this, void 0, void 0, function* () {
const onSwapPaid = (swapSuccess) => {
// always alert client for maker matches, taker matches only when specified
if (swapSuccess.role === enums_1.SwapRole.Maker || args.includeTaker) {
callback(swapSuccess);
}
};
const swapPaid$ = rxjs_1.fromEvent(this.swaps, 'swap.paid')
.pipe(operators_1.takeUntil(cancelled$));
swapPaid$.subscribe({
next: onSwapPaid,
error: this.logger.error,
});
});
/*
* Subscribe to completed swaps.
*/
this.subscribeSwapsAccepted = (_args, callback, cancelled$) => __awaiter(this, void 0, void 0, function* () {
const onSwapAccepted = (swapSuccess) => {
callback(swapSuccess);
};
const swapAccepted = rxjs_1.fromEvent(this.swaps, 'swap.accepted')
.pipe(operators_1.takeUntil(cancelled$));
swapAccepted.subscribe({
next: onSwapAccepted,
error: this.logger.error,
});
});
/*
* Subscribe to failed swaps.
*/
this.subscribeSwapFailures = (args, callback, cancelled$) => __awaiter(this, void 0, void 0, function* () {
const onSwapFailed = (deal) => {
this.logger.trace(`notifying SwapFailure subscription for ${deal.rHash} with role ${enums_1.SwapRole[deal.role]}`);
// always alert client for maker matches, taker matches only when specified
if (deal.role === enums_1.SwapRole.Maker || args.includeTaker) {
callback(deal);
}
};
const swapFailed$ = rxjs_1.fromEvent(this.swaps, 'swap.failed')
.pipe(operators_1.takeUntil(cancelled$));
swapFailed$.subscribe({
next: onSwapFailed,
error: this.logger.error,
});
});
/**
* Resolves a hash to its preimage.
*/
this.resolveHash = (request) => __awaiter(this, void 0, void 0, function* () {
argChecks.HAS_RHASH(request);
argChecks.POSITIVE_AMOUNT(request);
return this.swaps.handleResolveRequest(request);
});
/**
* Provides preimage for a hash.
*/
this.providePreimage = (event) => __awaiter(this, void 0, void 0, function* () {
var _b;
(_b = this.swapClientManager.connextClient) === null || _b === void 0 ? void 0 : _b.emit('preimage', event);
});
/**
* Notifies Connext client that a transfer has been received.
*/
this.transferReceived = (event) => __awaiter(this, void 0, void 0, function* () {
var _c;
(_c = this.swapClientManager.connextClient) === null || _c === void 0 ? void 0 : _c.emit('transferReceived', event);
});
/**
* Notifies Connext client that a deposit has been confirmed.
*/
this.depositConfirmed = (hash) => {
var _a;
(_a = this.swapClientManager.connextClient) === null || _a === void 0 ? void 0 : _a.emit('depositConfirmed', hash);
};
this.changePassword = ({ newPassword, oldPassword }) => __awaiter(this, void 0, void 0, function* () {
if (!this.nodekey.password) {
throw errors_2.default.NO_ENCRYPT_MODE_ENABLED;
}
if (newPassword.length < 8) {
// lnd requires 8+ character passwords, so we must as well
throw errors_2.default.INVALID_ARGUMENT('password must be at least 8 characters');
}
if (oldPassword !== this.nodekey.password) {
throw errors_2.default.INVALID_ARGUMENT('old password is incorrect');
}
// we change the password for our node key right away, then we queue up lnd password changes
yield this.nodekey.toFile(newPassword);
yield this.swapClientManager.changeLndPasswords(oldPassword, newPassword);
});
this.shutdown = components.shutdown;
this.orderBook = components.orderBook;
this.swapClientManager = components.swapClientManager;
this.pool = components.pool;
this.swaps = components.swaps;
this.logger = components.logger;
this.nodekey = components.nodeKey;
this.version = components.version;
}
}
exports.default = Service;
//# sourceMappingURL=Service.js.map