diff --git a/bin/xud b/bin/xud
index ed201e506..e6b1abd60 100755
--- a/bin/xud
+++ b/bin/xud
@@ -42,8 +42,8 @@ const { argv } = require('yargs')
type: 'boolean',
default: undefined,
},
- regnet: {
- describe: 'Whether to run XUD on regnet',
+ regtest: {
+ describe: 'Whether to run XUD on regtest',
type: 'boolean',
default: undefined,
},
diff --git a/docs/api.md b/docs/api.md
index 983ee48ed..98613f097 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -7,10 +7,12 @@
- [AddCurrencyResponse](#xudrpc.AddCurrencyResponse)
- [AddPairRequest](#xudrpc.AddPairRequest)
- [AddPairResponse](#xudrpc.AddPairResponse)
+ - [Alert](#xudrpc.Alert)
- [Balance](#xudrpc.Balance)
- [BanRequest](#xudrpc.BanRequest)
- [BanResponse](#xudrpc.BanResponse)
- [Chain](#xudrpc.Chain)
+ - [ChannelBalanceAlert](#xudrpc.ChannelBalanceAlert)
- [Channels](#xudrpc.Channels)
- [CloseChannelRequest](#xudrpc.CloseChannelRequest)
- [CloseChannelResponse](#xudrpc.CloseChannelResponse)
@@ -71,6 +73,7 @@
- [SetLogLevelResponse](#xudrpc.SetLogLevelResponse)
- [ShutdownRequest](#xudrpc.ShutdownRequest)
- [ShutdownResponse](#xudrpc.ShutdownResponse)
+ - [SubscribeAlertsRequest](#xudrpc.SubscribeAlertsRequest)
- [SubscribeOrdersRequest](#xudrpc.SubscribeOrdersRequest)
- [SubscribeSwapsAcceptedRequest](#xudrpc.SubscribeSwapsAcceptedRequest)
- [SubscribeSwapsRequest](#xudrpc.SubscribeSwapsRequest)
@@ -91,6 +94,8 @@
- [WithdrawRequest](#xudrpc.WithdrawRequest)
- [WithdrawResponse](#xudrpc.WithdrawResponse)
+ - [Alert.AlertType](#xudrpc.Alert.AlertType)
+ - [ChannelBalanceAlert.Side](#xudrpc.ChannelBalanceAlert.Side)
- [Currency.SwapClient](#xudrpc.Currency.SwapClient)
- [ListOrdersRequest.Owner](#xudrpc.ListOrdersRequest.Owner)
- [LogLevel](#xudrpc.LogLevel)
@@ -147,6 +152,23 @@
+
+
+### Alert
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| type | [Alert.AlertType](#xudrpc.Alert.AlertType) | | |
+| message | [string](#string) | | The human readable alert message. |
+| balance_alert | [ChannelBalanceAlert](#xudrpc.ChannelBalanceAlert) | | |
+
+
+
+
+
+
### Balance
@@ -208,6 +230,25 @@
+
+
+### ChannelBalanceAlert
+
+
+
+| Field | Type | Label | Description |
+| ----- | ---- | ----- | ----------- |
+| total_balance | [uint64](#uint64) | | The total balance of the channel. |
+| side | [ChannelBalanceAlert.Side](#xudrpc.ChannelBalanceAlert.Side) | | |
+| bound | [uint32](#uint32) | | The bound of the low balance in percentage. |
+| side_balance | [uint64](#uint64) | | The current side balance. |
+| channel_point | [string](#string) | | The point of the channel. |
+
+
+
+
+
+
### Channels
@@ -1017,6 +1058,9 @@
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| quantity_on_hold | [uint64](#uint64) | | Any portion of the order that was on hold due to ongoing swaps at the time of the request and could not be removed until after the swaps finish. |
+| remaining_quantity | [uint64](#uint64) | | Remaining portion of the order if it was a partial removal. |
+| removed_quantity | [uint64](#uint64) | | Successfully removed portion of the order. |
+| pair_id | [string](#string) | | Removed order's pairId. (e.g. ETH/BTC) |
@@ -1143,6 +1187,16 @@
+
+
+### SubscribeAlertsRequest
+
+
+
+
+
+
+
### SubscribeOrdersRequest
@@ -1316,10 +1370,10 @@
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
-| max_sell | [uint64](#uint64) | | Maximum outbound limit for an order denominated in satoshis. |
-| max_buy | [uint64](#uint64) | | Maximum inbound limit for an order denominated in satoshis. |
-| reserved_outbound | [uint64](#uint64) | | The outbound amount reserved for open orders. |
-| reserved_inbound | [uint64](#uint64) | | The inbound amount reserved for open orders. |
+| max_sell | [uint64](#uint64) | | Maximum outbound limit for a sell order denominated in satoshis. |
+| max_buy | [uint64](#uint64) | | Maximum inbound limit for a buy order denominated in satoshis. |
+| reserved_sell | [uint64](#uint64) | | The outbound amount reserved for open sell orders. |
+| reserved_buy | [uint64](#uint64) | | The inbound amount reserved for open buy orders. |
@@ -1465,6 +1519,29 @@
+
+
+### Alert.AlertType
+The type of the alert.
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| LOW_BALANCE | 0 | |
+
+
+
+
+
+### ChannelBalanceAlert.Side
+The side of the low balance.
+
+| Name | Number | Description |
+| ---- | ------ | ----------- |
+| REMOTE | 0 | |
+| LOCAL | 1 | |
+
+
+
### Currency.SwapClient
@@ -1569,6 +1646,7 @@ The primary service for interacting with a running xud node.
| SetLogLevel | [SetLogLevelRequest](#xudrpc.SetLogLevelRequest) | [SetLogLevelResponse](#xudrpc.SetLogLevelResponse) | Set the logging level. shell: xucli loglevel <level> |
| Shutdown | [ShutdownRequest](#xudrpc.ShutdownRequest) | [ShutdownResponse](#xudrpc.ShutdownResponse) | Begin gracefully shutting down xud. shell: xucli shutdown |
| 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. |
+| SubscribeAlerts | [SubscribeAlertsRequest](#xudrpc.SubscribeAlertsRequest) | [Alert](#xudrpc.Alert) stream | Subscribes to alerts such as low balance. |
| 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. |
| 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. |
| SubscribeSwapsAccepted | [SubscribeSwapsAcceptedRequest](#xudrpc.SubscribeSwapsAcceptedRequest) | [SwapAccepted](#xudrpc.SwapAccepted) stream | Subscribes to accepted swaps. This stream emits a message when the local xud node accepts a swap request from a peer, but before the swap has actually succeeded. |
diff --git a/lib/Xud.ts b/lib/Xud.ts
index df1e480a7..239c61c4b 100644
--- a/lib/Xud.ts
+++ b/lib/Xud.ts
@@ -130,6 +130,12 @@ class Xud extends EventEmitter {
nodeKey = await NodeKey.generate();
await nodeKey.toFile(nodeKeyPath);
}
+
+ // we need to initialize connext every time xud starts, even in noencrypt mode
+ // the call below is in lieu of the UnlockNode/CreateNode call flow
+ await this.swapClientManager.initConnext(
+ nodeKey.childSeed(SwapClientType.Connext),
+ );
} else if (this.rpcServer) {
this.rpcServer.grpcService.locked = true;
const initService = new InitService(this.swapClientManager, nodeKeyPath, nodeKeyExists, this.config.dbpath);
@@ -194,12 +200,6 @@ class Xud extends EventEmitter {
// wait for components to initialize in parallel
await Promise.all(initPromises);
- // We initialize Connext separately because it
- // requires a NodeKey.
- await this.swapClientManager.initConnext(
- nodeKey.childSeed(SwapClientType.Connext),
- );
-
// initialize pool and start listening/connecting only once other components are initialized
await this.pool.init();
diff --git a/lib/cli/command.ts b/lib/cli/command.ts
index b4787a486..1e2af8141 100644
--- a/lib/cli/command.ts
+++ b/lib/cli/command.ts
@@ -38,6 +38,18 @@ const loadXudConfig = async (argv: Arguments) => {
}
};
+const getTlsCert = (certPath: string) => {
+ try {
+ return fs.readFileSync(certPath);
+ } catch (err) {
+ if (err.code === 'ENOENT') {
+ throw `tls cert could not be found at ${certPath}, it may take several seconds to be created on xud's first run`;
+ }
+
+ throw err;
+ }
+};
+
/**
* A generic function to instantiate an XU client.
* @param argv the command line arguments
@@ -46,7 +58,7 @@ export const loadXudClient = async (argv: Arguments) => {
await loadXudConfig(argv);
const certPath = argv.tlscertpath || path.join(argv.xudir, 'tls.cert');
- const cert = fs.readFileSync(certPath);
+ const cert = getTlsCert(certPath);
const credentials = grpc.credentials.createSsl(cert);
return new XudClient(`${argv.rpchost}:${argv.rpcport}`, credentials);
@@ -56,7 +68,7 @@ export const loadXudInitClient = async (argv: Arguments) => {
await loadXudConfig(argv);
const certPath = argv.tlscertpath || path.join(argv.xudir, 'tls.cert');
- const cert = fs.readFileSync(certPath);
+ const cert = getTlsCert(certPath);
const credentials = grpc.credentials.createSsl(cert);
return new XudInitClient(`${argv.rpchost}:${argv.rpcport}`, credentials);
diff --git a/lib/cli/commands/openchannel.ts b/lib/cli/commands/openchannel.ts
index 2f37652ee..d51f52dfe 100644
--- a/lib/cli/commands/openchannel.ts
+++ b/lib/cli/commands/openchannel.ts
@@ -37,6 +37,10 @@ export const builder = (argv: Argv) => argv
.example('$0 openchannel ETH 0.5', 'deposit 0.5 into an ETH Connext channel without specifying a remote node');
export const handler = async (argv: Arguments) => {
+ if (isNaN(argv.amount)) {
+ throw 'amount must be a number';
+ }
+
const request = new OpenChannelRequest();
if (argv.node_identifier) {
request.setNodeIdentifier(argv.node_identifier);
diff --git a/lib/cli/commands/removeorder.ts b/lib/cli/commands/removeorder.ts
index ed61d17b8..06d32d809 100644
--- a/lib/cli/commands/removeorder.ts
+++ b/lib/cli/commands/removeorder.ts
@@ -1,7 +1,7 @@
import { Arguments, Argv } from 'yargs';
-import { RemoveOrderRequest } from '../../proto/xudrpc_pb';
+import { RemoveOrderRequest, RemoveOrderResponse } from '../../proto/xudrpc_pb';
import { callback, loadXudClient } from '../command';
-import { coinsToSats } from '../utils';
+import { coinsToSats, satsToCoinsStr } from '../utils';
export const command = 'removeorder [quantity]';
@@ -18,11 +18,23 @@ export const builder = (argv: Argv) => argv
.example('$0 removeorder 79d2cd30-8a26-11ea-90cf-439fb244cf44', 'remove an order by id')
.example('$0 removeorder 79d2cd30-8a26-11ea-90cf-439fb244cf44 0.1', 'remove 0.1 quantity from an order by id');
+const displayOutput = (orderId: string, removeOrderResponse: RemoveOrderResponse.AsObject) => {
+ const removedCurrency = removeOrderResponse.pairId.split('/')[0];
+ if (removeOrderResponse.quantityOnHold === 0 && removeOrderResponse.remainingQuantity === 0) {
+ console.log(`Order ${orderId} successfully removed.`);
+ } else {
+ console.log(`
+Order ${orderId} partially removed, remaining quantity: \
+${satsToCoinsStr(removeOrderResponse.remainingQuantity)} ${removedCurrency}, \
+on hold: ${satsToCoinsStr(removeOrderResponse.quantityOnHold)} ${removedCurrency}`);
+ }
+};
+
export const handler = async (argv: Arguments) => {
const request = new RemoveOrderRequest();
request.setOrderId(argv.order_id);
if (argv.quantity) {
request.setQuantity(coinsToSats(argv.quantity));
}
- (await loadXudClient(argv)).removeOrder(request, callback(argv));
+ (await loadXudClient(argv)).removeOrder(request, callback(argv, displayOutput.bind(undefined, argv.order_id)));
};
diff --git a/lib/cli/commands/streamorders.ts b/lib/cli/commands/streamorders.ts
index d987a3111..e4ff418ee 100644
--- a/lib/cli/commands/streamorders.ts
+++ b/lib/cli/commands/streamorders.ts
@@ -1,9 +1,8 @@
-import { ServiceError, status } from 'grpc';
import { Arguments, Argv } from 'yargs';
import { XudClient } from '../../proto/xudrpc_grpc_pb';
import * as xudrpc from '../../proto/xudrpc_pb';
-import { setTimeoutPromise } from '../../utils/utils';
import { loadXudClient } from '../command';
+import { onStreamError, waitForClient } from '../utils';
export const command = 'streamorders [existing]';
@@ -26,20 +25,8 @@ const ensureConnection = async (argv: Arguments, printError?: boolean) => {
if (!client) {
client = await loadXudClient(argv);
}
- client.waitForReady(Date.now() + 3000, (error: Error | null) => {
- if (error) {
- if (error.message === 'Failed to connect before the deadline') {
- console.error(`could not connect to xud at ${argv.rpchost}:${argv.rpcport}, is xud running?`);
- process.exit(1);
- }
- if (printError) console.error(`${error.name}: ${error.message}`);
- setTimeout(ensureConnection.bind(undefined, argv, printError), 3000);
- } else {
- console.log('Successfully connected, subscribing for orders');
- streamOrders(argv);
- }
- });
+ waitForClient(client, argv, ensureConnection, streamOrders, printError);
};
const streamOrders = (argv: Arguments) => {
@@ -57,15 +44,7 @@ const streamOrders = (argv: Arguments) => {
// adding end, close, error events only once,
// since they'll be thrown for three of subscriptions in the corresponding cases, catching once is enough.
ordersSubscription.on('end', reconnect.bind(undefined, argv));
- ordersSubscription.on('error', async (err: ServiceError) => {
- if (err.code === status.UNIMPLEMENTED) {
- console.error("xud is locked, run 'xucli unlock', 'xucli create', or 'xucli restore' then try again");
- process.exit(1);
- }
- console.warn(`Unexpected error occured: ${err.message}, reconnecting in 1 second`);
- await setTimeoutPromise(1000);
- await ensureConnection(argv);
- });
+ ordersSubscription.on('error', onStreamError.bind(undefined, ensureConnection.bind(undefined, argv)));
const swapsRequest = new xudrpc.SubscribeSwapsRequest();
swapsRequest.setIncludeTaker(true);
diff --git a/lib/cli/commands/subscribealerts.ts b/lib/cli/commands/subscribealerts.ts
new file mode 100644
index 000000000..f9bf6247e
--- /dev/null
+++ b/lib/cli/commands/subscribealerts.ts
@@ -0,0 +1,51 @@
+import { Arguments, Argv } from 'yargs';
+import { XudClient } from '../../proto/xudrpc_grpc_pb';
+import * as xudrpc from '../../proto/xudrpc_pb';
+import { loadXudClient } from '../command';
+import { AlertType } from '../../constants/enums';
+import { onStreamError, waitForClient } from '../utils';
+
+export const command = 'subscribealerts';
+
+export const describe = 'subscribe alerts such as low balance';
+
+export const builder = (argv: Argv) => argv
+ .option('pretty', {
+ type: 'boolean',
+ })
+ .example('$0 subscribealerts -j', 'prints alert payload in a JSON structure')
+ .example('$0 subscribealerts', 'prints alert message only');
+
+export const handler = async (argv: Arguments) => {
+ await ensureConnection(argv, true);
+};
+
+let client: XudClient;
+
+const ensureConnection = async (argv: Arguments, printError?: boolean) => {
+ if (!client) {
+ client = await loadXudClient(argv);
+ }
+
+ waitForClient(client, argv, ensureConnection, subscribeAlerts, printError);
+};
+
+const subscribeAlerts = (argv: Arguments) => {
+ const request = new xudrpc.SubscribeAlertsRequest();
+ const alertsSubscription = client.subscribeAlerts(request);
+
+ alertsSubscription.on('data', (alert: xudrpc.Alert) => {
+ if (argv.json) {
+ console.log(JSON.stringify(alert, undefined, 2));
+ } else {
+ console.log(`${AlertType[alert.getType()]}: ${alert.getMessage()}`);
+ }
+ });
+ alertsSubscription.on('end', reconnect.bind(undefined, argv));
+ alertsSubscription.on('error', onStreamError.bind(undefined, ensureConnection.bind(undefined, argv)));
+};
+
+const reconnect = async (argv: Arguments) => {
+ console.log('Stream has closed, trying to reconnect');
+ await ensureConnection(argv, false);
+};
diff --git a/lib/cli/commands/tradinglimits.ts b/lib/cli/commands/tradinglimits.ts
index 28b6a5415..0ab402409 100644
--- a/lib/cli/commands/tradinglimits.ts
+++ b/lib/cli/commands/tradinglimits.ts
@@ -9,8 +9,8 @@ const HEADERS = [
colors.blue('Currency'),
colors.blue('Max Buy'),
colors.blue('Max Sell'),
- colors.blue('Reserved Outbound'),
- colors.blue('Reserved Inbound'),
+ colors.blue('Reserved Buy'),
+ colors.blue('Reserved Sell'),
];
const formatTradingLimits = (tradingLimits: TradingLimitsResponse.AsObject) => {
@@ -23,8 +23,8 @@ const formatTradingLimits = (tradingLimits: TradingLimitsResponse.AsObject) => {
currency,
`${satsToCoinsStr(tradingLimit.maxBuy)}`,
`${satsToCoinsStr(tradingLimit.maxSell)}`,
- `${satsToCoinsStr(tradingLimit.reservedOutbound)}`,
- `${satsToCoinsStr(tradingLimit.reservedInbound)}`,
+ `${satsToCoinsStr(tradingLimit.reservedBuy)}`,
+ `${satsToCoinsStr(tradingLimit.reservedSell)}`,
);
formatted.push(row);
});
diff --git a/lib/cli/utils.ts b/lib/cli/utils.ts
index b79675f57..83ece1e24 100644
--- a/lib/cli/utils.ts
+++ b/lib/cli/utils.ts
@@ -2,6 +2,10 @@ import colors from 'colors/safe';
import { accessSync, watch } from 'fs';
import os from 'os';
import path from 'path';
+import { XudClient } from '../proto/xudrpc_grpc_pb';
+import { Arguments } from 'yargs';
+import { ServiceError, status } from 'grpc';
+import { setTimeoutPromise } from '../utils/utils';
const SATOSHIS_PER_COIN = 10 ** 8;
@@ -80,3 +84,30 @@ export const waitForCert = (certPath: string) => {
}
});
};
+
+export const waitForClient = (client: XudClient, argv: Arguments, ensureConnection: Function, successCallback: Function, printError?: boolean) => {
+ client.waitForReady(Date.now() + 3000, (error: Error | null) => {
+ if (error) {
+ if (error.message === 'Failed to connect before the deadline') {
+ console.error(`could not connect to xud at ${argv.rpchost}:${argv.rpcport}, is xud running?`);
+ process.exit(1);
+ }
+
+ if (printError) console.error(`${error.name}: ${error.message}`);
+ setTimeout(ensureConnection.bind(undefined, argv, printError), 3000);
+ } else {
+ console.log('Successfully connected, subscribing for alerts');
+ successCallback(argv);
+ }
+ });
+};
+
+export const onStreamError = async (ensureConnection: Function, err: ServiceError) => {
+ if (err.code === status.UNIMPLEMENTED) {
+ console.error("xud is locked, run 'xucli unlock', 'xucli create', or 'xucli restore' then try again");
+ process.exit(1);
+ }
+ console.warn(`Unexpected error occured: ${err.message}, reconnecting in 1 second`);
+ await setTimeoutPromise(1000);
+ await ensureConnection();
+};
diff --git a/lib/connextclient/ConnextClient.ts b/lib/connextclient/ConnextClient.ts
index 8a257eb75..448f132a5 100644
--- a/lib/connextclient/ConnextClient.ts
+++ b/lib/connextclient/ConnextClient.ts
@@ -14,7 +14,7 @@ import SwapClient, {
PaymentStatus,
WithdrawArguments,
} from '../swaps/SwapClient';
-import { SwapDeal, CloseChannelParams, OpenChannelParams, SwapCapacities } from '../swaps/types';
+import { SwapDeal, CloseChannelParams, OpenChannelParams, SwapCapacities, ChannelBalanceAlert } from '../swaps/types';
import { UnitConverter } from '../utils/UnitConverter';
import errors, { errorCodes } from './errors';
import {
@@ -47,6 +47,7 @@ interface ConnextClient {
on(event: 'htlcAccepted', listener: (rHash: string, amount: number, currency: string) => void): this;
on(event: 'connectionVerified', listener: (swapClientInfo: SwapClientInfo) => void): this;
on(event: 'depositConfirmed', listener: (hash: string) => void): this;
+ on(event: 'lowBalance', listener: (alert: ChannelBalanceAlert) => void): this;
once(event: 'initialized', listener: () => void): this;
emit(event: 'htlcAccepted', rHash: string, amount: number, currency: string): boolean;
emit(event: 'connectionVerified', swapClientInfo: SwapClientInfo): boolean;
@@ -54,6 +55,7 @@ interface ConnextClient {
emit(event: 'preimage', preimageRequest: ProvidePreimageEvent): void;
emit(event: 'transferReceived', transferReceivedRequest: TransferReceivedEvent): void;
emit(event: 'depositConfirmed', hash: string): void;
+ emit(event: 'lowBalance', alert: ChannelBalanceAlert): boolean;
}
/**
@@ -104,6 +106,7 @@ class ConnextClient extends SwapClient {
public address?: string;
/** A map of currency symbols to token addresses. */
public tokenAddresses = new Map();
+ public userIdentifier?: string;
/**
* A map of expected invoices by hash.
* This is equivalent to invoices of lnd with the difference
@@ -274,10 +277,6 @@ class ConnextClient extends SwapClient {
});
}
- public totalOutboundAmount = (currency: string): number => {
- return this.outboundAmounts.get(currency) || 0;
- }
-
/**
* Checks whether we have a pending collateral request for the currency and,
* if one doesn't exist, starts a new request for the specified amount. Then
@@ -302,6 +301,10 @@ class ConnextClient extends SwapClient {
this.requestCollateralPromises.set(currency, requestCollateralPromise);
}
+ /**
+ * Checks whether there is sufficient inbound capacity to receive the specified amount
+ * and throws an error if there isn't, otherwise does nothing.
+ */
public checkInboundCapacity = (inboundAmount: number, currency: string) => {
const inboundCapacity = this.inboundAmounts.get(currency) || 0;
if (inboundCapacity < inboundAmount) {
@@ -348,6 +351,23 @@ class ConnextClient extends SwapClient {
channelBalancePromises.push(this.channelBalance(currency));
}
await Promise.all(channelBalancePromises);
+
+ for (const [currency, address] of this.tokenAddresses) {
+ const remoteBalance = this.inboundAmounts.get(currency) || 0;
+ const localBalance = this.outboundAmounts.get(currency) || 0;
+ const totalBalance = remoteBalance + localBalance;
+ const alertThreshold = totalBalance * 0.1;
+
+ this.checkLowBalance(
+ remoteBalance,
+ localBalance,
+ totalBalance,
+ alertThreshold,
+ currency,
+ address,
+ this.emit,
+ );
+ }
} catch (e) {
this.logger.error('failed to update total outbound capacity', e);
}
@@ -915,7 +935,16 @@ class ConnextClient extends SwapClient {
if (!currency) {
throw errors.CURRENCY_MISSING;
}
- const amount = units || (await this.getBalance(currency)).freeBalanceOffChain;
+ const { freeBalanceOffChain } = await this.getBalance(currency);
+ const availableUnits = Number(freeBalanceOffChain);
+ if (units && availableUnits < units) {
+ throw errors.INSUFFICIENT_BALANCE;
+ }
+ const amount = units || freeBalanceOffChain;
+
+ if (Number(amount) === 0) {
+ return []; // there is nothing to withdraw and no tx to return
+ }
const withdrawResponse = await this.sendRequest('/withdraw', 'POST', {
recipient: destination,
diff --git a/lib/constants/enums.ts b/lib/constants/enums.ts
index e86a12080..f4f3fc009 100644
--- a/lib/constants/enums.ts
+++ b/lib/constants/enums.ts
@@ -180,3 +180,12 @@ export enum DisconnectionReason {
AuthFailureInvalidSignature = 12,
WireProtocolErr = 13,
}
+
+export enum AlertType {
+ LowBalance = 0,
+}
+
+export enum ChannelSide {
+ Remote = 0,
+ Local = 1,
+}
diff --git a/lib/grpc/GrpcService.ts b/lib/grpc/GrpcService.ts
index 79a0f75ff..893757b1a 100644
--- a/lib/grpc/GrpcService.ts
+++ b/lib/grpc/GrpcService.ts
@@ -2,13 +2,13 @@
import grpc, { ServerWritableStream, status } from 'grpc';
import { fromEvent } from 'rxjs';
import { take } from 'rxjs/operators';
-import { SwapFailureReason } from '../constants/enums';
+import { AlertType, SwapFailureReason } from '../constants/enums';
import { LndInfo } from '../lndclient/types';
import { isOwnOrder, Order, OrderPortion, PlaceOrderEventType, PlaceOrderResult } from '../orderbook/types';
import * as xudrpc from '../proto/xudrpc_pb';
import Service from '../service/Service';
import { ServiceOrder, ServicePlaceOrderEvent } from '../service/types';
-import { SwapAccepted, SwapFailure, SwapSuccess } from '../swaps/types';
+import { ChannelBalanceAlert, SwapAccepted, SwapFailure, SwapSuccess } from '../swaps/types';
import getGrpcError from './getGrpcError';
/**
@@ -279,9 +279,12 @@ class GrpcService {
return;
}
try {
- const quantityOnHold = this.service.removeOrder(call.request.toObject());
+ const { removedQuantity, remainingQuantity, onHoldQuantity, pairId } = this.service.removeOrder(call.request.toObject());
const response = new xudrpc.RemoveOrderResponse();
- response.setQuantityOnHold(quantityOnHold);
+ response.setQuantityOnHold(onHoldQuantity);
+ response.setRemainingQuantity(remainingQuantity);
+ response.setRemovedQuantity(removedQuantity);
+ response.setPairId(pairId);
callback(null, response);
} catch (err) {
callback(getGrpcError(err), null);
@@ -350,8 +353,8 @@ class GrpcService {
const tradingLimits = new xudrpc.TradingLimits();
tradingLimits.setMaxSell(tradingLimitsObj.maxSell);
tradingLimits.setMaxBuy(tradingLimitsObj.maxBuy);
- tradingLimits.setReservedInbound(tradingLimitsObj.reservedInbound);
- tradingLimits.setReservedOutbound(tradingLimitsObj.reservedOutbound);
+ tradingLimits.setReservedSell(tradingLimitsObj.reservedSell);
+ tradingLimits.setReservedBuy(tradingLimitsObj.reservedBuy);
limitsMap.set(currency, tradingLimits);
});
callback(null, response);
@@ -870,6 +873,32 @@ class GrpcService {
}
}
+ /*
+ * See [[Service.subscribeAlerts]]
+ */
+ public subscribeAlerts: grpc.handleServerStreamingCall = (call) => {
+ if (!this.isReady(this.service, call)) {
+ return;
+ }
+
+ const cancelled$ = getCancelled$(call);
+ this.service.subscribeAlerts((type: AlertType, message: string, payload: ChannelBalanceAlert) => {
+ const alert = new xudrpc.Alert();
+ alert.setType(type as number);
+ alert.setMessage(message);
+ const channelBalanceAlert = new xudrpc.ChannelBalanceAlert();
+ channelBalanceAlert.setBound(payload.bound);
+ channelBalanceAlert.setChannelPoint(payload.channelPoint);
+ channelBalanceAlert.setSide(payload.side as number);
+ channelBalanceAlert.setSideBalance(payload.sideBalance);
+ channelBalanceAlert.setTotalBalance(payload.totalBalance);
+ alert.setBalanceAlert(channelBalanceAlert);
+ call.write(alert);
+ },
+ cancelled$);
+ this.addStream(call);
+ }
+
/*
* See [[Service.subscribeOrders]]
*/
@@ -880,10 +909,10 @@ class GrpcService {
const cancelled$ = getCancelled$(call);
- this.service.subscribeOrders(call.request.toObject(), (order?: Order, orderRemoval?: OrderPortion) => {
+ this.service.subscribeOrders(call.request.toObject(), (order?: ServiceOrder, orderRemoval?: OrderPortion) => {
const orderUpdate = new xudrpc.OrderUpdate();
if (order) {
- orderUpdate.setOrder(createOrder(order));
+ orderUpdate.setOrder(createServiceOrder(order));
} else if (orderRemoval) {
const grpcOrderRemoval = new xudrpc.OrderRemoval();
grpcOrderRemoval.setPairId(orderRemoval.pairId);
diff --git a/lib/grpc/getGrpcError.ts b/lib/grpc/getGrpcError.ts
index 1d50636c3..1ff61d687 100644
--- a/lib/grpc/getGrpcError.ts
+++ b/lib/grpc/getGrpcError.ts
@@ -50,10 +50,12 @@ const getGrpcError = (err: any) => {
case orderErrorCodes.CURRENCY_CANNOT_BE_REMOVED:
case orderErrorCodes.MARKET_ORDERS_NOT_ALLOWED:
case serviceErrorCodes.NOMATCHING_MODE_IS_REQUIRED:
- case orderErrorCodes.INSUFFICIENT_OUTBOUND_BALANCE:
+ case swapErrorCodes.INSUFFICIENT_OUTBOUND_CAPACITY:
+ case swapErrorCodes.INSUFFICIENT_INBOUND_CAPACITY:
case orderErrorCodes.QUANTITY_ON_HOLD:
case swapErrorCodes.SWAP_CLIENT_NOT_FOUND:
case swapErrorCodes.SWAP_CLIENT_MISCONFIGURED:
+ case serviceErrorCodes.NO_CHANNELS_TO_CLOSE:
code = status.FAILED_PRECONDITION;
break;
case lndErrorCodes.UNAVAILABLE:
diff --git a/lib/lndclient/LndClient.ts b/lib/lndclient/LndClient.ts
index 9c55d7bd2..f8b1316ac 100644
--- a/lib/lndclient/LndClient.ts
+++ b/lib/lndclient/LndClient.ts
@@ -7,11 +7,16 @@ import { SwapClientType, SwapRole, SwapState } from '../constants/enums';
import Logger from '../Logger';
import { InvoicesClient } from '../proto/lndinvoices_grpc_pb';
import * as lndinvoices from '../proto/lndinvoices_pb';
-import { LightningClient, WalletUnlockerClient } from '../proto/lndrpc_grpc_pb';
+import { RouterClient } from '../proto/lndrouter_grpc_pb';
+import * as lndrouter from '../proto/lndrouter_pb';
+import { LightningClient } from '../proto/lndrpc_grpc_pb';
import * as lndrpc from '../proto/lndrpc_pb';
+import { WalletUnlockerClient } from '../proto/lndwalletunlocker_grpc_pb';
+import * as lndwalletunlocker from '../proto/lndwalletunlocker_pb';
+import { BASE_MAX_CLIENT_WAIT_TIME, MAX_FEE_RATIO, MAX_PAYMENT_TIME } from '../swaps/consts';
import swapErrors from '../swaps/errors';
-import SwapClient, { ChannelBalance, ClientStatus, PaymentState, SwapClientInfo, WithdrawArguments } from '../swaps/SwapClient';
-import { CloseChannelParams, OpenChannelParams, SwapCapacities, SwapDeal } from '../swaps/types';
+import SwapClient, { Channel, ChannelBalance, ClientStatus, PaymentState, SwapClientInfo, WithdrawArguments } from '../swaps/SwapClient';
+import { ChannelBalanceAlert, CloseChannelParams, OpenChannelParams, SwapCapacities, SwapDeal } from '../swaps/types';
import { deriveChild } from '../utils/seedutil';
import { base64ToHex, hexToUint8Array } from '../utils/utils';
import errors from './errors';
@@ -23,6 +28,7 @@ interface LndClient {
on(event: 'channelBackup', listener: (channelBackup: Uint8Array) => void): this;
on(event: 'channelBackupEnd', listener: () => void): this;
on(event: 'locked', listener: () => void): this;
+ on(event: 'lowBalance', listener: (alert: ChannelBalanceAlert) => void): this;
once(event: 'initialized', listener: () => void): this;
@@ -32,10 +38,13 @@ interface LndClient {
emit(event: 'channelBackupEnd'): boolean;
emit(event: 'locked'): boolean;
emit(event: 'initialized'): boolean;
+ emit(event: 'lowBalance', alert: ChannelBalanceAlert): boolean;
}
-const MAXFEE = 0.03;
-const BASE_MAX_CLIENT_WAIT_TIME = 6000;
+const GRPC_CLIENT_OPTIONS = {
+ 'grpc.ssl_target_name_override': 'localhost',
+ 'grpc.default_authority': 'localhost',
+};
/** A class representing a client to interact with lnd. */
class LndClient extends SwapClient {
@@ -48,6 +57,7 @@ class LndClient extends SwapClient {
/** The maximum time to wait for a client to be ready for making grpc calls, can be used for exponential backoff. */
private maxClientWaitTime = BASE_MAX_CLIENT_WAIT_TIME;
private invoices?: InvoicesClient;
+ private router?: RouterClient;
/** The path to the lnd admin macaroon, will be undefined if `nomacaroons` is enabled */
private macaroonpath?: string;
private meta = new grpc.Metadata();
@@ -62,7 +72,7 @@ class LndClient extends SwapClient {
private channelBackupSubscription?: ClientReadableStream;
private invoiceSubscriptions = new Map>();
private initRetryTimeout?: NodeJS.Timeout;
- private _totalOutboundAmount = 0;
+ private totalOutboundAmount = 0;
private totalInboundAmount = 0;
private maxChannelOutboundAmount = 0;
private maxChannelInboundAmount = 0;
@@ -192,14 +202,6 @@ class LndClient extends SwapClient {
return this.chainIdentifier;
}
- public totalOutboundAmount = () => {
- return this._totalOutboundAmount;
- }
-
- public checkInboundCapacity = (_inboundAmount: number) => {
- return; // we do not currently check inbound capacities for lnd
- }
-
public setReservedInboundAmount = (_reservedInboundAmount: number) => {
return; // not currently used for lnd
}
@@ -207,7 +209,7 @@ class LndClient extends SwapClient {
/** Lnd specific procedure to mark the client as locked. */
private lock = () => {
if (!this.walletUnlocker) {
- this.walletUnlocker = new WalletUnlockerClient(this.uri, this.credentials);
+ this.walletUnlocker = new WalletUnlockerClient(this.uri, this.credentials, GRPC_CLIENT_OPTIONS);
}
if (this.lightning) {
this.lightning.close();
@@ -238,7 +240,21 @@ class LndClient extends SwapClient {
}
protected updateCapacity = async () => {
- await this.channelBalance().catch(async (err) => {
+ await this.channelBalance().then(({ channels }) => {
+ channels?.forEach(({ remoteBalance, localBalance, channelPoint }) => {
+ const totalBalance = localBalance + remoteBalance;
+ const alertThreshold = totalBalance * 0.1;
+ this.checkLowBalance(
+ remoteBalance,
+ localBalance,
+ totalBalance,
+ alertThreshold,
+ this.currency,
+ channelPoint,
+ this.emit,
+ );
+ });
+ }).catch(async (err) => {
this.logger.error('failed to update total outbound capacity', err);
});
}
@@ -466,7 +482,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.lightning = new LightningClient(this.uri, this.credentials, GRPC_CLIENT_OPTIONS);
try {
await this.waitForClientReady(this.lightning);
@@ -501,7 +517,14 @@ class LndClient extends SwapClient {
this.setStatus(ClientStatus.Misconfigured);
}
+ if (this.walletUnlocker) {
+ // WalletUnlocker service is disabled when the main Lightning service is available
+ this.walletUnlocker.close();
+ this.walletUnlocker = undefined;
+ }
+
this.invoices = new InvoicesClient(this.uri, this.credentials);
+ this.router = new RouterClient(this.uri, this.credentials);
try {
const randomHash = crypto.randomBytes(32).toString('hex');
this.logger.debug(`checking hold invoice support with hash: ${randomHash}`);
@@ -509,16 +532,13 @@ class LndClient extends SwapClient {
await this.addInvoice({ rHash: randomHash, units: 1 });
await this.removeInvoice(randomHash);
} catch (err) {
- const errStr = typeof(err) === 'string' ? err : JSON.stringify(err);
-
- this.logger.error(`could not add hold invoice, error: ${errStr}`);
- this.setStatus(ClientStatus.NoHoldInvoiceSupport);
- }
-
- if (this.walletUnlocker) {
- // WalletUnlocker service is disabled when the main Lightning service is available
- this.walletUnlocker.close();
- this.walletUnlocker = undefined;
+ if (err.code !== grpc.status.UNAVAILABLE) {
+ // mark the client as not having hold invoice support if the invoice calls failed due to
+ // reasons other than generic grpc connectivity errors
+ this.logger.error('could not add hold invoice', err);
+ this.setStatus(ClientStatus.NoHoldInvoiceSupport);
+ }
+ throw err; // we don't want to proceed with marking the client as connected, regardless of the error
}
await this.setConnected(newPubKey, newUris);
@@ -577,13 +597,13 @@ class LndClient extends SwapClient {
// client's default.
finalCltvDelta: this.finalLock,
});
- const preimage = await this.executeSendRequest(request);
+ const preimage = await this.sendPaymentV2(request);
return preimage;
}
public sendPayment = async (deal: SwapDeal): Promise => {
assert(deal.state === SwapState.Active);
- let request: lndrpc.SendRequest;
+ let request: lndrouter.SendPaymentRequest;
assert(deal.makerCltvDelta, 'swap deal must have a makerCltvDelta');
if (deal.role === SwapRole.Taker) {
// we are the taker paying the maker
@@ -610,16 +630,71 @@ class LndClient extends SwapClient {
cltvLimit: deal.takerMaxTimeLock! + 3,
});
}
- const preimage = await this.executeSendRequest(request);
+ this.logger.debug(`sending payment of ${request.getAmt()} with hash ${deal.rHash}`);
+ const preimage = await this.sendPaymentV2(request);
return preimage;
}
/**
* Sends a payment through the Lightning Network.
+ * @returns the preimage in hex format
*/
- private sendPaymentSync = (request: lndrpc.SendRequest): Promise => {
- this.logger.trace(`sending payment with request: ${JSON.stringify(request.toObject())}`);
- return this.unaryCall('sendPaymentSync', request);
+ private sendPaymentV2 = (request: lndrouter.SendPaymentRequest): Promise => {
+ return new Promise((resolve, reject) => {
+ if (!this.router) {
+ reject(swapErrors.FINAL_PAYMENT_ERROR(errors.UNAVAILABLE(this.currency, this.status).message));
+ return;
+ }
+ if (!this.isConnected()) {
+ reject(swapErrors.FINAL_PAYMENT_ERROR(errors.UNAVAILABLE(this.currency, this.status).message));
+ return;
+ }
+
+ this.logger.trace(`sending payment with request: ${JSON.stringify(request.toObject())}`);
+
+ const call = this.router.sendPaymentV2(request, this.meta);
+
+ call.on('data', (response: lndrpc.Payment) => {
+ switch (response.getStatus()) {
+ case lndrpc.Payment.PaymentStatus.FAILED:
+ switch (response.getFailureReason()) {
+ case lndrpc.PaymentFailureReason.FAILURE_REASON_TIMEOUT:
+ case lndrpc.PaymentFailureReason.FAILURE_REASON_NO_ROUTE:
+ case lndrpc.PaymentFailureReason.FAILURE_REASON_ERROR:
+ case lndrpc.PaymentFailureReason.FAILURE_REASON_INSUFFICIENT_BALANCE:
+ reject(swapErrors.FINAL_PAYMENT_ERROR(lndrpc.PaymentFailureReason[response.getFailureReason()]));
+ break;
+ case lndrpc.PaymentFailureReason.FAILURE_REASON_INCORRECT_PAYMENT_DETAILS:
+ reject(swapErrors.PAYMENT_REJECTED);
+ break;
+ default:
+ reject(swapErrors.UNKNOWN_PAYMENT_ERROR(response.getFailureReason().toString()));
+ break;
+ }
+ break;
+ case lndrpc.Payment.PaymentStatus.SUCCEEDED:
+ resolve(response.getPaymentPreimage());
+ break;
+ default:
+ // in-flight status, we'll wait for a final status update event
+ break;
+ }
+ });
+
+ call.on('end', () => {
+ call.removeAllListeners();
+ });
+ call.on('error', (err) => {
+ call.removeAllListeners();
+ this.logger.error('error event from sendPaymentV2', err);
+
+ if (typeof err.message === 'string' && err.message.includes('chain backend is still syncing')) {
+ reject(swapErrors.FINAL_PAYMENT_ERROR(err.message));
+ } else {
+ reject(swapErrors.UNKNOWN_PAYMENT_ERROR(JSON.stringify(err)));
+ }
+ });
+ });
}
/**
@@ -628,15 +703,15 @@ class LndClient extends SwapClient {
private buildSendRequest = (
{ rHash, destination, amount, finalCltvDelta, cltvLimit }:
{ rHash: string, destination: string, amount: number, finalCltvDelta: number, cltvLimit?: number },
- ): lndrpc.SendRequest => {
- const request = new lndrpc.SendRequest();
- request.setPaymentHashString(rHash);
- request.setDestString(destination);
+ ): lndrouter.SendPaymentRequest => {
+ const request = new lndrouter.SendPaymentRequest();
+ request.setPaymentHash(Buffer.from(rHash, 'hex'));
+ request.setDest(Buffer.from(destination, 'hex'));
request.setAmt(amount);
request.setFinalCltvDelta(finalCltvDelta);
- const fee = new lndrpc.FeeLimit();
- fee.setFixed(Math.floor(MAXFEE * request.getAmt()));
- request.setFeeLimit(fee);
+ request.setTimeoutSeconds(MAX_PAYMENT_TIME / 1000);
+ const fee = Math.floor(MAX_FEE_RATIO * request.getAmt());
+ request.setFeeLimitSat(fee);
if (cltvLimit) {
// cltvLimit is used to enforce the maximum
// duration/length of the payment.
@@ -645,41 +720,6 @@ class LndClient extends SwapClient {
return request;
}
- /**
- * Executes the provided lndrpc.SendRequest
- */
- private executeSendRequest = async (
- request: lndrpc.SendRequest,
- ): Promise => {
- if (!this.isConnected()) {
- throw swapErrors.FINAL_PAYMENT_ERROR(errors.UNAVAILABLE(this.currency, this.status).message);
- }
- this.logger.debug(`sending payment of ${request.getAmt()} with hash ${request.getPaymentHashString()} to ${request.getDestString()}`);
- let sendPaymentResponse: lndrpc.SendResponse;
- try {
- sendPaymentResponse = await this.sendPaymentSync(request);
- } catch (err) {
- this.logger.error('got exception from sendPaymentSync', err);
- if (typeof err.message === 'string' && err.message.includes('chain backend is still syncing')) {
- throw swapErrors.FINAL_PAYMENT_ERROR(err.message);
- } else {
- throw swapErrors.UNKNOWN_PAYMENT_ERROR(err.message);
- }
- }
- const paymentError = sendPaymentResponse.getPaymentError();
- if (paymentError) {
- if (paymentError.includes('UnknownPaymentHash') || paymentError.includes('IncorrectOrUnknownPaymentDetails')) {
- throw swapErrors.PAYMENT_REJECTED;
- } else {
- throw swapErrors.FINAL_PAYMENT_ERROR(paymentError);
- }
- }
- const preimage = base64ToHex(sendPaymentResponse.getPaymentPreimage_asB64());
-
- this.logger.debug(`sent payment with hash ${request.getPaymentHashString()}, preimage is ${preimage}`);
- return preimage;
- }
-
/**
* Gets a new address for the internal lnd wallet.
*/
@@ -713,22 +753,29 @@ class LndClient extends SwapClient {
let inactiveBalance = 0;
let totalOutboundAmount = 0;
let totalInboundAmount = 0;
- channels.toObject().channelsList.forEach((channel) => {
- if (channel.active) {
- balance += channel.localBalance;
- const outbound = channel.localBalance - channel.localChanReserveSat;
+ const channelBalances: Channel[] = [];
+ channels.toObject().channelsList.forEach(({ localBalance, localChanReserveSat, remoteBalance,
+ remoteChanReserveSat, active, channelPoint }) => {
+ if (active) {
+ channelBalances.push({
+ localBalance,
+ remoteBalance,
+ channelPoint,
+ });
+ balance += localBalance;
+ const outbound = Math.max(0, localBalance - localChanReserveSat);
totalOutboundAmount += outbound;
if (maxOutbound < outbound) {
maxOutbound = outbound;
}
- const inbound = channel.remoteBalance - channel.remoteChanReserveSat;
+ const inbound = Math.max(0, remoteBalance - remoteChanReserveSat);
totalInboundAmount += inbound;
if (maxInbound < inbound) {
maxInbound = inbound;
}
} else {
- inactiveBalance += channel.localBalance;
+ inactiveBalance += localBalance;
}
});
@@ -742,8 +789,8 @@ class LndClient extends SwapClient {
this.logger.debug(`new channel inbound capacity: ${maxInbound}`);
}
- if (this._totalOutboundAmount !== totalOutboundAmount) {
- this._totalOutboundAmount = totalOutboundAmount;
+ if (this.totalOutboundAmount !== totalOutboundAmount) {
+ this.totalOutboundAmount = totalOutboundAmount;
this.logger.debug(`new channel total outbound capacity: ${totalOutboundAmount}`);
}
@@ -763,12 +810,13 @@ class LndClient extends SwapClient {
balance,
inactiveBalance,
pendingOpenBalance,
+ channels: channelBalances,
};
}
public channelBalance = async (): Promise => {
- const { balance, inactiveBalance, pendingOpenBalance } = await this.updateChannelBalances();
- return { balance, inactiveBalance, pendingOpenBalance };
+ const { balance, inactiveBalance, pendingOpenBalance, channels } = await this.updateChannelBalances();
+ return { balance, inactiveBalance, pendingOpenBalance, channels };
}
public swapCapacities = async (): Promise => {
@@ -879,7 +927,7 @@ class LndClient extends SwapClient {
request.setFinalCltvDelta(finalLock);
request.setPubKey(destination);
const fee = new lndrpc.FeeLimit();
- fee.setFixed(Math.floor(MAXFEE * request.getAmt()));
+ fee.setFixed(Math.floor(MAX_FEE_RATIO * request.getAmt()));
request.setFeeLimit(fee);
let route: lndrpc.Route | undefined;
@@ -925,8 +973,8 @@ class LndClient extends SwapClient {
}
public initWallet = async (walletPassword: string, seedMnemonic: string[], restore = false, backup?: Uint8Array):
- Promise => {
- const request = new lndrpc.InitWalletRequest();
+ Promise => {
+ const request = new lndwalletunlocker.InitWalletRequest();
// from the master seed/mnemonic we derive a child mnemonic for this specific client
const childMnemonic = await deriveChild(seedMnemonic, this.label);
@@ -943,7 +991,7 @@ class LndClient extends SwapClient {
snapshot.setMultiChanBackup(multiChanBackup);
request.setChannelBackups(snapshot);
}
- const initWalletResponse = await this.unaryWalletUnlockerCall(
+ const initWalletResponse = await this.unaryWalletUnlockerCall(
'initWallet', request,
);
if (this.initWalletResolve) {
@@ -956,9 +1004,9 @@ class LndClient extends SwapClient {
}
public unlockWallet = async (walletPassword: string): Promise => {
- const request = new lndrpc.UnlockWalletRequest();
+ const request = new lndwalletunlocker.UnlockWalletRequest();
request.setWalletPassword(Uint8Array.from(Buffer.from(walletPassword, 'utf8')));
- await this.unaryWalletUnlockerCall(
+ await this.unaryWalletUnlockerCall(
'unlockWallet', request,
);
this.setUnlocked();
@@ -1201,6 +1249,10 @@ class LndClient extends SwapClient {
this.invoices.close();
this.invoices = undefined;
}
+ if (this.router) {
+ this.router.close();
+ this.router = undefined;
+ }
if (this.initWalletResolve) {
this.initWalletResolve(false);
this.initWalletResolve = undefined;
diff --git a/lib/orderbook/OrderBook.ts b/lib/orderbook/OrderBook.ts
index 008456973..423c8472a 100644
--- a/lib/orderbook/OrderBook.ts
+++ b/lib/orderbook/OrderBook.ts
@@ -1,5 +1,6 @@
import assert from 'assert';
import { EventEmitter } from 'events';
+import { UnitConverter } from '../utils/UnitConverter';
import uuidv1 from 'uuid/v1';
import { SwapClientType, SwapFailureReason, SwapPhase, SwapRole } from '../constants/enums';
import { Models } from '../db/DB';
@@ -8,7 +9,6 @@ import Logger from '../Logger';
import { SwapFailedPacket, SwapRequestPacket } from '../p2p/packets';
import Peer from '../p2p/Peer';
import Pool from '../p2p/Pool';
-import swapsErrors from '../swaps/errors';
import Swaps from '../swaps/Swaps';
import { SwapDeal, SwapFailure, SwapSuccess } from '../swaps/types';
import { pubKeyToAlias } from '../utils/aliasUtils';
@@ -121,7 +121,7 @@ class OrderBook extends EventEmitter {
const onOrderRemoved = (order: OwnOrder) => {
const { inboundCurrency, outboundCurrency, inboundAmount, outboundAmount } =
- Swaps.calculateInboundOutboundAmounts(order.quantity, order.price, order.isBuy, order.pairId);
+ UnitConverter.calculateInboundOutboundAmounts(order.quantity, order.price, order.isBuy, order.pairId);
this.swaps.swapClientManager.subtractInboundReservedAmount(inboundCurrency, inboundAmount);
this.swaps.swapClientManager.subtractOutboundReservedAmount(outboundCurrency, outboundAmount);
};
@@ -130,7 +130,7 @@ class OrderBook extends EventEmitter {
this.on('ownOrder.added', (order) => {
const { inboundCurrency, outboundCurrency, inboundAmount, outboundAmount } =
- Swaps.calculateInboundOutboundAmounts(order.quantity, order.price, order.isBuy, order.pairId);
+ UnitConverter.calculateInboundOutboundAmounts(order.quantity, order.price, order.isBuy, order.pairId);
this.swaps.swapClientManager.addInboundReservedAmount(inboundCurrency, inboundAmount);
this.swaps.swapClientManager.addOutboundReservedAmount(outboundCurrency, outboundAmount);
});
@@ -307,6 +307,11 @@ class OrderBook extends EventEmitter {
this.pairInstances.set(pairInstance.id, pairInstance);
this.addTradingPair(pairInstance.id);
+ this.pool.rawPeers().forEach(async (peer) => {
+ this.checkPeerCurrencies(peer);
+ await this.verifyPeerPairs(peer);
+ });
+
this.pool.updatePairs(this.pairIds);
return pairInstance;
}
@@ -335,7 +340,7 @@ class OrderBook extends EventEmitter {
}
const currencyInstance = await this.repository.addCurrency({ ...currency, decimalPlaces: currency.decimalPlaces || 8 });
this.currencyInstances.set(currencyInstance.id, currencyInstance);
- this.swaps.swapClientManager.add(currencyInstance);
+ await this.swaps.swapClientManager.add(currencyInstance);
}
public removeCurrency = async (currencyId: string) => {
@@ -347,7 +352,6 @@ class OrderBook extends EventEmitter {
}
}
this.currencyInstances.delete(currencyId);
- this.swaps.swapClientManager.remove(currencyId);
await currency.destroy();
} else {
throw errors.CURRENCY_DOES_NOT_EXIST(currencyId);
@@ -363,6 +367,11 @@ class OrderBook extends EventEmitter {
this.pairInstances.delete(pairId);
this.tradingPairs.delete(pairId);
+ this.pool.rawPeers().forEach(async (peer) => {
+ this.checkPeerCurrencies(peer);
+ await this.verifyPeerPairs(peer);
+ });
+
this.pool.updatePairs(this.pairIds);
return pair.destroy();
}
@@ -487,27 +496,7 @@ class OrderBook extends EventEmitter {
(order.isBuy ? tp.quoteAsk() : tp.quoteBid()) :
order.price;
- const { outboundCurrency, inboundCurrency, outboundAmount, inboundAmount } =
- Swaps.calculateInboundOutboundAmounts(order.quantity, price, order.isBuy, order.pairId);
-
- // check if clients exists
- const outboundSwapClient = this.swaps.swapClientManager.get(outboundCurrency);
- const inboundSwapClient = this.swaps.swapClientManager.get(inboundCurrency);
- if (!outboundSwapClient) {
- throw swapsErrors.SWAP_CLIENT_NOT_FOUND(outboundCurrency);
- }
- if (!inboundSwapClient) {
- throw swapsErrors.SWAP_CLIENT_NOT_FOUND(inboundCurrency);
- }
-
- // check if sufficient outbound channel capacity exists
- const totalOutboundAmount = outboundSwapClient.totalOutboundAmount(outboundCurrency);
- if (outboundAmount > totalOutboundAmount) {
- throw errors.INSUFFICIENT_OUTBOUND_BALANCE(outboundCurrency, outboundAmount, totalOutboundAmount);
- }
-
- // check if sufficient inbound channel capacity exists
- inboundSwapClient.checkInboundCapacity(inboundAmount, inboundCurrency);
+ await this.swaps.swapClientManager.checkSwapCapacities({ ...order, price });
}
let replacedOrderIdentifier: OrderIdentifier | undefined;
@@ -849,8 +838,8 @@ class OrderBook extends EventEmitter {
const onHoldOrderLocalIds = [];
for (const localId of this.localIdMap.keys()) {
- const onHoldIndicator = this.removeOwnOrderByLocalId(localId, true);
- if (onHoldIndicator === 0) {
+ const { onHoldQuantity } = this.removeOwnOrderByLocalId(localId, true);
+ if (onHoldQuantity === 0) {
removedOrderLocalIds.push(localId);
} else {
onHoldOrderLocalIds.push(localId);
@@ -874,6 +863,8 @@ class OrderBook extends EventEmitter {
const order = this.getOwnOrderByLocalId(localId);
let remainingQuantityToRemove = quantityToRemove || order.quantity;
+ let onHoldQuantity = order.hold;
+ let removedQuantity = 0;
if (remainingQuantityToRemove > order.quantity) {
// quantity to be removed can't be higher than order's quantity.
@@ -887,6 +878,7 @@ class OrderBook extends EventEmitter {
pairId: order.pairId,
quantityToRemove: remainingQuantityToRemove,
});
+ removedQuantity += remainingQuantityToRemove;
remainingQuantityToRemove = 0;
} else {
// we can't immediately remove the entire quantity because of a hold on the order.
@@ -901,6 +893,7 @@ class OrderBook extends EventEmitter {
pairId: order.pairId,
quantityToRemove: removableQuantity,
});
+ removedQuantity += removableQuantity;
remainingQuantityToRemove -= removableQuantity;
}
@@ -926,6 +919,8 @@ class OrderBook extends EventEmitter {
const cleanup = (quantity: number) => {
remainingQuantityToRemove -= quantity;
+ removedQuantity += quantity;
+ onHoldQuantity -= quantity;
this.logger.debug(`removed hold of ${quantity} on local order ${localId}, ${remainingQuantityToRemove} remaining`);
if (remainingQuantityToRemove === 0) {
// we can stop listening for swaps once all holds are cleared
@@ -938,7 +933,12 @@ class OrderBook extends EventEmitter {
this.swaps.on('swap.paid', paidHandler);
}
- return remainingQuantityToRemove;
+ return {
+ removedQuantity,
+ onHoldQuantity,
+ pairId: order.pairId,
+ remainingQuantity: order.quantity - remainingQuantityToRemove,
+ };
}
private addOrderHold = (orderId: string, pairId: string, holdAmount?: number) => {
@@ -1009,7 +1009,11 @@ class OrderBook extends EventEmitter {
}
private removePeerPair = (peerPubKey: string, pairId: string) => {
- const tp = this.getTradingPair(pairId);
+ const tp = this.tradingPairs.get(pairId);
+ if (!tp) {
+ return;
+ }
+
const orders = tp.removePeerOrders(peerPubKey);
orders.forEach((order) => {
this.emit('peerOrder.invalidation', order);
diff --git a/lib/orderbook/errors.ts b/lib/orderbook/errors.ts
index e9c674bb3..e48278b59 100644
--- a/lib/orderbook/errors.ts
+++ b/lib/orderbook/errors.ts
@@ -13,7 +13,6 @@ const errorCodes = {
LOCAL_ID_DOES_NOT_EXIST: codesPrefix.concat('.9'),
QUANTITY_DOES_NOT_MATCH: codesPrefix.concat('.10'),
CURRENCY_MISSING_ETHEREUM_CONTRACT_ADDRESS: codesPrefix.concat('.11'),
- INSUFFICIENT_OUTBOUND_BALANCE: codesPrefix.concat('.12'),
MIN_QUANTITY_VIOLATED: codesPrefix.concat('.13'),
QUANTITY_ON_HOLD: codesPrefix.concat('.15'),
DUPLICATE_PAIR_CURRENCIES: codesPrefix.concat('.16'),
@@ -64,10 +63,6 @@ const errors = {
message: `requestedQuantity: ${requestedQuantity} is higher than order quantity: ${orderQuantity}`,
code: errorCodes.QUANTITY_DOES_NOT_MATCH,
}),
- INSUFFICIENT_OUTBOUND_BALANCE: (currency: string, amount: number, availableAmount: number) => ({
- message: `${currency} outbound balance of ${availableAmount} is not sufficient for order amount of ${amount}`,
- code: errorCodes.INSUFFICIENT_OUTBOUND_BALANCE,
- }),
MIN_QUANTITY_VIOLATED: (quantity: number, currency: string) => ({
message: `order does not meet the minimum ${currency} quantity of ${quantity} satoshis`,
code: errorCodes.MIN_QUANTITY_VIOLATED,
diff --git a/lib/p2p/Pool.ts b/lib/p2p/Pool.ts
index 353e6e183..9e4a6adcd 100644
--- a/lib/p2p/Pool.ts
+++ b/lib/p2p/Pool.ts
@@ -238,7 +238,9 @@ class Pool extends EventEmitter {
* packet to currently connected peers to notify them of the change.
*/
public updateConnextState = (tokenAddresses: Map, pubKey?: string) => {
- this.nodeState.connextIdentifier = pubKey || '';
+ if (pubKey) {
+ this.nodeState.connextIdentifier = pubKey;
+ }
tokenAddresses.forEach((tokenAddress, currency) => {
this.nodeState.tokenIdentifiers[currency] = tokenAddress;
});
@@ -431,6 +433,11 @@ class Pool extends EventEmitter {
throw errors.ATTEMPTED_CONNECTION_TO_SELF;
}
+ if (this.disconnecting || !this.connected) {
+ // if we are disconnected or disconnecting, don't make new connections to peers
+ throw errors.POOL_CLOSED;
+ }
+
// check if we allow connections to tor addresses
if (!this.config.tor && address.host.indexOf('.onion') !== -1) {
throw errors.NODE_TOR_ADDRESS(nodePubKey, address);
@@ -477,6 +484,10 @@ class Pool extends EventEmitter {
return peerInfos;
}
+ public rawPeers = (): Map => {
+ return this.peers;
+ }
+
private addressIsSelf = (address: Address): boolean => {
if (address.port === this.listenPort) {
switch (address.host) {
@@ -972,14 +983,19 @@ class Pool extends EventEmitter {
peer.active = false;
this.emit('peer.close', peer.nodePubKey);
- const shouldReconnect =
+ const doesDisconnectionReasonCallForReconnection =
(peer.sentDisconnectionReason === undefined || peer.sentDisconnectionReason === DisconnectionReason.ResponseStalling) &&
(peer.recvDisconnectionReason === undefined || peer.recvDisconnectionReason === DisconnectionReason.ResponseStalling ||
peer.recvDisconnectionReason === DisconnectionReason.AlreadyConnected ||
peer.recvDisconnectionReason === DisconnectionReason.Shutdown);
const addresses = peer.addresses || [];
- if (!peer.inbound && peer.nodePubKey && shouldReconnect && (addresses.length || peer.address)) {
+ if (doesDisconnectionReasonCallForReconnection
+ && !peer.inbound // we don't make reconnection attempts to peers that connected to use
+ && peer.nodePubKey // we only reconnect if we know the peer's node pubkey
+ && (addresses.length || peer.address) // we only reconnect if there's an address to connect to
+ && !this.disconnecting && this.connected // we don't reconnect if we're in the process of disconnecting or have disconnected the p2p pool
+ ) {
this.logger.debug(`attempting to reconnect to a disconnected peer ${peer.label}`);
const node = { addresses, lastAddress: peer.address, nodePubKey: peer.nodePubKey };
await this.tryConnectNode(node, true);
diff --git a/lib/proto/annotations_grpc_pb.js b/lib/proto/annotations_grpc_pb.js
index 97b3a2461..51b4d6959 100644
--- a/lib/proto/annotations_grpc_pb.js
+++ b/lib/proto/annotations_grpc_pb.js
@@ -1 +1 @@
-// GENERATED CODE -- NO SERVICES IN PROTO
\ No newline at end of file
+// GENERATED CODE -- NO SERVICES IN PROTO
diff --git a/lib/proto/lndrouter_grpc_pb.d.ts b/lib/proto/lndrouter_grpc_pb.d.ts
new file mode 100644
index 000000000..14665e3c6
--- /dev/null
+++ b/lib/proto/lndrouter_grpc_pb.d.ts
@@ -0,0 +1,234 @@
+// package: routerrpc
+// file: lndrouter.proto
+
+/* tslint:disable */
+
+import * as grpc from "grpc";
+import * as lndrouter_pb from "./lndrouter_pb";
+import * as lndrpc_pb from "./lndrpc_pb";
+
+interface IRouterService extends grpc.ServiceDefinition {
+ sendPaymentV2: IRouterService_ISendPaymentV2;
+ trackPaymentV2: IRouterService_ITrackPaymentV2;
+ estimateRouteFee: IRouterService_IEstimateRouteFee;
+ sendToRoute: IRouterService_ISendToRoute;
+ sendToRouteV2: IRouterService_ISendToRouteV2;
+ resetMissionControl: IRouterService_IResetMissionControl;
+ queryMissionControl: IRouterService_IQueryMissionControl;
+ queryProbability: IRouterService_IQueryProbability;
+ buildRoute: IRouterService_IBuildRoute;
+ subscribeHtlcEvents: IRouterService_ISubscribeHtlcEvents;
+ sendPayment: IRouterService_ISendPayment;
+ trackPayment: IRouterService_ITrackPayment;
+ htlcInterceptor: IRouterService_IHtlcInterceptor;
+}
+
+interface IRouterService_ISendPaymentV2 extends grpc.MethodDefinition {
+ path: string; // "/routerrpc.Router/SendPaymentV2"
+ requestStream: boolean; // false
+ responseStream: boolean; // true
+ requestSerialize: grpc.serialize;
+ requestDeserialize: grpc.deserialize;
+ responseSerialize: grpc.serialize;
+ responseDeserialize: grpc.deserialize;
+}
+interface IRouterService_ITrackPaymentV2 extends grpc.MethodDefinition {
+ path: string; // "/routerrpc.Router/TrackPaymentV2"
+ requestStream: boolean; // false
+ responseStream: boolean; // true
+ requestSerialize: grpc.serialize;
+ requestDeserialize: grpc.deserialize;
+ responseSerialize: grpc.serialize;
+ responseDeserialize: grpc.deserialize;
+}
+interface IRouterService_IEstimateRouteFee extends grpc.MethodDefinition {
+ path: string; // "/routerrpc.Router/EstimateRouteFee"
+ requestStream: boolean; // false
+ responseStream: boolean; // false
+ requestSerialize: grpc.serialize;
+ requestDeserialize: grpc.deserialize;
+ responseSerialize: grpc.serialize;
+ responseDeserialize: grpc.deserialize;
+}
+interface IRouterService_ISendToRoute extends grpc.MethodDefinition {
+ path: string; // "/routerrpc.Router/SendToRoute"
+ requestStream: boolean; // false
+ responseStream: boolean; // false
+ requestSerialize: grpc.serialize;
+ requestDeserialize: grpc.deserialize;
+ responseSerialize: grpc.serialize;
+ responseDeserialize: grpc.deserialize;
+}
+interface IRouterService_ISendToRouteV2 extends grpc.MethodDefinition {
+ path: string; // "/routerrpc.Router/SendToRouteV2"
+ requestStream: boolean; // false
+ responseStream: boolean; // false
+ requestSerialize: grpc.serialize;
+ requestDeserialize: grpc.deserialize;
+ responseSerialize: grpc.serialize;
+ responseDeserialize: grpc.deserialize;
+}
+interface IRouterService_IResetMissionControl extends grpc.MethodDefinition {
+ path: string; // "/routerrpc.Router/ResetMissionControl"
+ requestStream: boolean; // false
+ responseStream: boolean; // false
+ requestSerialize: grpc.serialize;
+ requestDeserialize: grpc.deserialize;
+ responseSerialize: grpc.serialize;
+ responseDeserialize: grpc.deserialize;
+}
+interface IRouterService_IQueryMissionControl extends grpc.MethodDefinition {
+ path: string; // "/routerrpc.Router/QueryMissionControl"
+ requestStream: boolean; // false
+ responseStream: boolean; // false
+ requestSerialize: grpc.serialize;
+ requestDeserialize: grpc.deserialize;
+ responseSerialize: grpc.serialize;
+ responseDeserialize: grpc.deserialize;
+}
+interface IRouterService_IQueryProbability extends grpc.MethodDefinition {
+ path: string; // "/routerrpc.Router/QueryProbability"
+ requestStream: boolean; // false
+ responseStream: boolean; // false
+ requestSerialize: grpc.serialize;
+ requestDeserialize: grpc.deserialize;
+ responseSerialize: grpc.serialize;
+ responseDeserialize: grpc.deserialize;
+}
+interface IRouterService_IBuildRoute extends grpc.MethodDefinition {
+ path: string; // "/routerrpc.Router/BuildRoute"
+ requestStream: boolean; // false
+ responseStream: boolean; // false
+ requestSerialize: grpc.serialize;
+ requestDeserialize: grpc.deserialize;
+ responseSerialize: grpc.serialize;
+ responseDeserialize: grpc.deserialize;
+}
+interface IRouterService_ISubscribeHtlcEvents extends grpc.MethodDefinition {
+ path: string; // "/routerrpc.Router/SubscribeHtlcEvents"
+ requestStream: boolean; // false
+ responseStream: boolean; // true
+ requestSerialize: grpc.serialize;
+ requestDeserialize: grpc.deserialize;
+ responseSerialize: grpc.serialize;
+ responseDeserialize: grpc.deserialize;
+}
+interface IRouterService_ISendPayment extends grpc.MethodDefinition {
+ path: string; // "/routerrpc.Router/SendPayment"
+ requestStream: boolean; // false
+ responseStream: boolean; // true
+ requestSerialize: grpc.serialize;
+ requestDeserialize: grpc.deserialize;
+ responseSerialize: grpc.serialize;
+ responseDeserialize: grpc.deserialize;
+}
+interface IRouterService_ITrackPayment extends grpc.MethodDefinition {
+ path: string; // "/routerrpc.Router/TrackPayment"
+ requestStream: boolean; // false
+ responseStream: boolean; // true
+ requestSerialize: grpc.serialize;
+ requestDeserialize: grpc.deserialize;
+ responseSerialize: grpc.serialize;
+ responseDeserialize: grpc.deserialize;
+}
+interface IRouterService_IHtlcInterceptor extends grpc.MethodDefinition {
+ path: string; // "/routerrpc.Router/HtlcInterceptor"
+ requestStream: boolean; // true
+ responseStream: boolean; // true
+ requestSerialize: grpc.serialize;
+ requestDeserialize: grpc.deserialize;
+ responseSerialize: grpc.serialize;
+ responseDeserialize: grpc.deserialize;
+}
+
+export const RouterService: IRouterService;
+
+export interface IRouterServer {
+ sendPaymentV2: grpc.handleServerStreamingCall;
+ trackPaymentV2: grpc.handleServerStreamingCall;
+ estimateRouteFee: grpc.handleUnaryCall;
+ sendToRoute: grpc.handleUnaryCall;
+ sendToRouteV2: grpc.handleUnaryCall;
+ resetMissionControl: grpc.handleUnaryCall;
+ queryMissionControl: grpc.handleUnaryCall;
+ queryProbability: grpc.handleUnaryCall;
+ buildRoute: grpc.handleUnaryCall;
+ subscribeHtlcEvents: grpc.handleServerStreamingCall;
+ sendPayment: grpc.handleServerStreamingCall;
+ trackPayment: grpc.handleServerStreamingCall;
+ htlcInterceptor: grpc.handleBidiStreamingCall;
+}
+
+export interface IRouterClient {
+ sendPaymentV2(request: lndrouter_pb.SendPaymentRequest, options?: Partial): grpc.ClientReadableStream;
+ sendPaymentV2(request: lndrouter_pb.SendPaymentRequest, metadata?: grpc.Metadata, options?: Partial): grpc.ClientReadableStream;
+ trackPaymentV2(request: lndrouter_pb.TrackPaymentRequest, options?: Partial): grpc.ClientReadableStream;
+ trackPaymentV2(request: lndrouter_pb.TrackPaymentRequest, metadata?: grpc.Metadata, options?: Partial): grpc.ClientReadableStream;
+ estimateRouteFee(request: lndrouter_pb.RouteFeeRequest, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.RouteFeeResponse) => void): grpc.ClientUnaryCall;
+ estimateRouteFee(request: lndrouter_pb.RouteFeeRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.RouteFeeResponse) => void): grpc.ClientUnaryCall;
+ estimateRouteFee(request: lndrouter_pb.RouteFeeRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.RouteFeeResponse) => void): grpc.ClientUnaryCall;
+ sendToRoute(request: lndrouter_pb.SendToRouteRequest, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.SendToRouteResponse) => void): grpc.ClientUnaryCall;
+ sendToRoute(request: lndrouter_pb.SendToRouteRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.SendToRouteResponse) => void): grpc.ClientUnaryCall;
+ sendToRoute(request: lndrouter_pb.SendToRouteRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.SendToRouteResponse) => void): grpc.ClientUnaryCall;
+ sendToRouteV2(request: lndrouter_pb.SendToRouteRequest, callback: (error: grpc.ServiceError | null, response: lndrpc_pb.HTLCAttempt) => void): grpc.ClientUnaryCall;
+ sendToRouteV2(request: lndrouter_pb.SendToRouteRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: lndrpc_pb.HTLCAttempt) => void): grpc.ClientUnaryCall;
+ sendToRouteV2(request: lndrouter_pb.SendToRouteRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: lndrpc_pb.HTLCAttempt) => void): grpc.ClientUnaryCall;
+ resetMissionControl(request: lndrouter_pb.ResetMissionControlRequest, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.ResetMissionControlResponse) => void): grpc.ClientUnaryCall;
+ resetMissionControl(request: lndrouter_pb.ResetMissionControlRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.ResetMissionControlResponse) => void): grpc.ClientUnaryCall;
+ resetMissionControl(request: lndrouter_pb.ResetMissionControlRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.ResetMissionControlResponse) => void): grpc.ClientUnaryCall;
+ queryMissionControl(request: lndrouter_pb.QueryMissionControlRequest, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.QueryMissionControlResponse) => void): grpc.ClientUnaryCall;
+ queryMissionControl(request: lndrouter_pb.QueryMissionControlRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.QueryMissionControlResponse) => void): grpc.ClientUnaryCall;
+ queryMissionControl(request: lndrouter_pb.QueryMissionControlRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.QueryMissionControlResponse) => void): grpc.ClientUnaryCall;
+ queryProbability(request: lndrouter_pb.QueryProbabilityRequest, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.QueryProbabilityResponse) => void): grpc.ClientUnaryCall;
+ queryProbability(request: lndrouter_pb.QueryProbabilityRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.QueryProbabilityResponse) => void): grpc.ClientUnaryCall;
+ queryProbability(request: lndrouter_pb.QueryProbabilityRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.QueryProbabilityResponse) => void): grpc.ClientUnaryCall;
+ buildRoute(request: lndrouter_pb.BuildRouteRequest, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.BuildRouteResponse) => void): grpc.ClientUnaryCall;
+ buildRoute(request: lndrouter_pb.BuildRouteRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.BuildRouteResponse) => void): grpc.ClientUnaryCall;
+ buildRoute(request: lndrouter_pb.BuildRouteRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.BuildRouteResponse) => void): grpc.ClientUnaryCall;
+ subscribeHtlcEvents(request: lndrouter_pb.SubscribeHtlcEventsRequest, options?: Partial): grpc.ClientReadableStream;
+ subscribeHtlcEvents(request: lndrouter_pb.SubscribeHtlcEventsRequest, metadata?: grpc.Metadata, options?: Partial): grpc.ClientReadableStream;
+ sendPayment(request: lndrouter_pb.SendPaymentRequest, options?: Partial): grpc.ClientReadableStream;
+ sendPayment(request: lndrouter_pb.SendPaymentRequest, metadata?: grpc.Metadata, options?: Partial): grpc.ClientReadableStream;
+ trackPayment(request: lndrouter_pb.TrackPaymentRequest, options?: Partial): grpc.ClientReadableStream;
+ trackPayment(request: lndrouter_pb.TrackPaymentRequest, metadata?: grpc.Metadata, options?: Partial): grpc.ClientReadableStream;
+ htlcInterceptor(): grpc.ClientDuplexStream;
+ htlcInterceptor(options: Partial): grpc.ClientDuplexStream;
+ htlcInterceptor(metadata: grpc.Metadata, options?: Partial): grpc.ClientDuplexStream;
+}
+
+export class RouterClient extends grpc.Client implements IRouterClient {
+ constructor(address: string, credentials: grpc.ChannelCredentials, options?: object);
+ public sendPaymentV2(request: lndrouter_pb.SendPaymentRequest, options?: Partial): grpc.ClientReadableStream;
+ public sendPaymentV2(request: lndrouter_pb.SendPaymentRequest, metadata?: grpc.Metadata, options?: Partial): grpc.ClientReadableStream;
+ public trackPaymentV2(request: lndrouter_pb.TrackPaymentRequest, options?: Partial): grpc.ClientReadableStream;
+ public trackPaymentV2(request: lndrouter_pb.TrackPaymentRequest, metadata?: grpc.Metadata, options?: Partial): grpc.ClientReadableStream;
+ public estimateRouteFee(request: lndrouter_pb.RouteFeeRequest, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.RouteFeeResponse) => void): grpc.ClientUnaryCall;
+ public estimateRouteFee(request: lndrouter_pb.RouteFeeRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.RouteFeeResponse) => void): grpc.ClientUnaryCall;
+ public estimateRouteFee(request: lndrouter_pb.RouteFeeRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.RouteFeeResponse) => void): grpc.ClientUnaryCall;
+ public sendToRoute(request: lndrouter_pb.SendToRouteRequest, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.SendToRouteResponse) => void): grpc.ClientUnaryCall;
+ public sendToRoute(request: lndrouter_pb.SendToRouteRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.SendToRouteResponse) => void): grpc.ClientUnaryCall;
+ public sendToRoute(request: lndrouter_pb.SendToRouteRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.SendToRouteResponse) => void): grpc.ClientUnaryCall;
+ public sendToRouteV2(request: lndrouter_pb.SendToRouteRequest, callback: (error: grpc.ServiceError | null, response: lndrpc_pb.HTLCAttempt) => void): grpc.ClientUnaryCall;
+ public sendToRouteV2(request: lndrouter_pb.SendToRouteRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: lndrpc_pb.HTLCAttempt) => void): grpc.ClientUnaryCall;
+ public sendToRouteV2(request: lndrouter_pb.SendToRouteRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: lndrpc_pb.HTLCAttempt) => void): grpc.ClientUnaryCall;
+ public resetMissionControl(request: lndrouter_pb.ResetMissionControlRequest, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.ResetMissionControlResponse) => void): grpc.ClientUnaryCall;
+ public resetMissionControl(request: lndrouter_pb.ResetMissionControlRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.ResetMissionControlResponse) => void): grpc.ClientUnaryCall;
+ public resetMissionControl(request: lndrouter_pb.ResetMissionControlRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.ResetMissionControlResponse) => void): grpc.ClientUnaryCall;
+ public queryMissionControl(request: lndrouter_pb.QueryMissionControlRequest, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.QueryMissionControlResponse) => void): grpc.ClientUnaryCall;
+ public queryMissionControl(request: lndrouter_pb.QueryMissionControlRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.QueryMissionControlResponse) => void): grpc.ClientUnaryCall;
+ public queryMissionControl(request: lndrouter_pb.QueryMissionControlRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.QueryMissionControlResponse) => void): grpc.ClientUnaryCall;
+ public queryProbability(request: lndrouter_pb.QueryProbabilityRequest, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.QueryProbabilityResponse) => void): grpc.ClientUnaryCall;
+ public queryProbability(request: lndrouter_pb.QueryProbabilityRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.QueryProbabilityResponse) => void): grpc.ClientUnaryCall;
+ public queryProbability(request: lndrouter_pb.QueryProbabilityRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.QueryProbabilityResponse) => void): grpc.ClientUnaryCall;
+ public buildRoute(request: lndrouter_pb.BuildRouteRequest, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.BuildRouteResponse) => void): grpc.ClientUnaryCall;
+ public buildRoute(request: lndrouter_pb.BuildRouteRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.BuildRouteResponse) => void): grpc.ClientUnaryCall;
+ public buildRoute(request: lndrouter_pb.BuildRouteRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: lndrouter_pb.BuildRouteResponse) => void): grpc.ClientUnaryCall;
+ public subscribeHtlcEvents(request: lndrouter_pb.SubscribeHtlcEventsRequest, options?: Partial): grpc.ClientReadableStream;
+ public subscribeHtlcEvents(request: lndrouter_pb.SubscribeHtlcEventsRequest, metadata?: grpc.Metadata, options?: Partial): grpc.ClientReadableStream;
+ public sendPayment(request: lndrouter_pb.SendPaymentRequest, options?: Partial): grpc.ClientReadableStream;
+ public sendPayment(request: lndrouter_pb.SendPaymentRequest, metadata?: grpc.Metadata, options?: Partial): grpc.ClientReadableStream;
+ public trackPayment(request: lndrouter_pb.TrackPaymentRequest, options?: Partial): grpc.ClientReadableStream;
+ public trackPayment(request: lndrouter_pb.TrackPaymentRequest, metadata?: grpc.Metadata, options?: Partial): grpc.ClientReadableStream;
+ public htlcInterceptor(options?: Partial): grpc.ClientDuplexStream;
+ public htlcInterceptor(metadata?: grpc.Metadata, options?: Partial): grpc.ClientDuplexStream;
+}
diff --git a/lib/proto/lndrouter_grpc_pb.js b/lib/proto/lndrouter_grpc_pb.js
new file mode 100644
index 000000000..61b0b85f5
--- /dev/null
+++ b/lib/proto/lndrouter_grpc_pb.js
@@ -0,0 +1,438 @@
+// GENERATED CODE -- DO NOT EDIT!
+
+'use strict';
+var grpc = require('grpc');
+var lndrouter_pb = require('./lndrouter_pb.js');
+var lndrpc_pb = require('./lndrpc_pb.js');
+
+function serialize_lnrpc_HTLCAttempt(arg) {
+ if (!(arg instanceof lndrpc_pb.HTLCAttempt)) {
+ throw new Error('Expected argument of type lnrpc.HTLCAttempt');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_lnrpc_HTLCAttempt(buffer_arg) {
+ return lndrpc_pb.HTLCAttempt.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_lnrpc_Payment(arg) {
+ if (!(arg instanceof lndrpc_pb.Payment)) {
+ throw new Error('Expected argument of type lnrpc.Payment');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_lnrpc_Payment(buffer_arg) {
+ return lndrpc_pb.Payment.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_routerrpc_BuildRouteRequest(arg) {
+ if (!(arg instanceof lndrouter_pb.BuildRouteRequest)) {
+ throw new Error('Expected argument of type routerrpc.BuildRouteRequest');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_routerrpc_BuildRouteRequest(buffer_arg) {
+ return lndrouter_pb.BuildRouteRequest.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_routerrpc_BuildRouteResponse(arg) {
+ if (!(arg instanceof lndrouter_pb.BuildRouteResponse)) {
+ throw new Error('Expected argument of type routerrpc.BuildRouteResponse');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_routerrpc_BuildRouteResponse(buffer_arg) {
+ return lndrouter_pb.BuildRouteResponse.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_routerrpc_ForwardHtlcInterceptRequest(arg) {
+ if (!(arg instanceof lndrouter_pb.ForwardHtlcInterceptRequest)) {
+ throw new Error('Expected argument of type routerrpc.ForwardHtlcInterceptRequest');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_routerrpc_ForwardHtlcInterceptRequest(buffer_arg) {
+ return lndrouter_pb.ForwardHtlcInterceptRequest.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_routerrpc_ForwardHtlcInterceptResponse(arg) {
+ if (!(arg instanceof lndrouter_pb.ForwardHtlcInterceptResponse)) {
+ throw new Error('Expected argument of type routerrpc.ForwardHtlcInterceptResponse');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_routerrpc_ForwardHtlcInterceptResponse(buffer_arg) {
+ return lndrouter_pb.ForwardHtlcInterceptResponse.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_routerrpc_HtlcEvent(arg) {
+ if (!(arg instanceof lndrouter_pb.HtlcEvent)) {
+ throw new Error('Expected argument of type routerrpc.HtlcEvent');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_routerrpc_HtlcEvent(buffer_arg) {
+ return lndrouter_pb.HtlcEvent.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_routerrpc_PaymentStatus(arg) {
+ if (!(arg instanceof lndrouter_pb.PaymentStatus)) {
+ throw new Error('Expected argument of type routerrpc.PaymentStatus');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_routerrpc_PaymentStatus(buffer_arg) {
+ return lndrouter_pb.PaymentStatus.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_routerrpc_QueryMissionControlRequest(arg) {
+ if (!(arg instanceof lndrouter_pb.QueryMissionControlRequest)) {
+ throw new Error('Expected argument of type routerrpc.QueryMissionControlRequest');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_routerrpc_QueryMissionControlRequest(buffer_arg) {
+ return lndrouter_pb.QueryMissionControlRequest.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_routerrpc_QueryMissionControlResponse(arg) {
+ if (!(arg instanceof lndrouter_pb.QueryMissionControlResponse)) {
+ throw new Error('Expected argument of type routerrpc.QueryMissionControlResponse');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_routerrpc_QueryMissionControlResponse(buffer_arg) {
+ return lndrouter_pb.QueryMissionControlResponse.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_routerrpc_QueryProbabilityRequest(arg) {
+ if (!(arg instanceof lndrouter_pb.QueryProbabilityRequest)) {
+ throw new Error('Expected argument of type routerrpc.QueryProbabilityRequest');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_routerrpc_QueryProbabilityRequest(buffer_arg) {
+ return lndrouter_pb.QueryProbabilityRequest.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_routerrpc_QueryProbabilityResponse(arg) {
+ if (!(arg instanceof lndrouter_pb.QueryProbabilityResponse)) {
+ throw new Error('Expected argument of type routerrpc.QueryProbabilityResponse');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_routerrpc_QueryProbabilityResponse(buffer_arg) {
+ return lndrouter_pb.QueryProbabilityResponse.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_routerrpc_ResetMissionControlRequest(arg) {
+ if (!(arg instanceof lndrouter_pb.ResetMissionControlRequest)) {
+ throw new Error('Expected argument of type routerrpc.ResetMissionControlRequest');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_routerrpc_ResetMissionControlRequest(buffer_arg) {
+ return lndrouter_pb.ResetMissionControlRequest.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_routerrpc_ResetMissionControlResponse(arg) {
+ if (!(arg instanceof lndrouter_pb.ResetMissionControlResponse)) {
+ throw new Error('Expected argument of type routerrpc.ResetMissionControlResponse');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_routerrpc_ResetMissionControlResponse(buffer_arg) {
+ return lndrouter_pb.ResetMissionControlResponse.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_routerrpc_RouteFeeRequest(arg) {
+ if (!(arg instanceof lndrouter_pb.RouteFeeRequest)) {
+ throw new Error('Expected argument of type routerrpc.RouteFeeRequest');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_routerrpc_RouteFeeRequest(buffer_arg) {
+ return lndrouter_pb.RouteFeeRequest.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_routerrpc_RouteFeeResponse(arg) {
+ if (!(arg instanceof lndrouter_pb.RouteFeeResponse)) {
+ throw new Error('Expected argument of type routerrpc.RouteFeeResponse');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_routerrpc_RouteFeeResponse(buffer_arg) {
+ return lndrouter_pb.RouteFeeResponse.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_routerrpc_SendPaymentRequest(arg) {
+ if (!(arg instanceof lndrouter_pb.SendPaymentRequest)) {
+ throw new Error('Expected argument of type routerrpc.SendPaymentRequest');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_routerrpc_SendPaymentRequest(buffer_arg) {
+ return lndrouter_pb.SendPaymentRequest.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_routerrpc_SendToRouteRequest(arg) {
+ if (!(arg instanceof lndrouter_pb.SendToRouteRequest)) {
+ throw new Error('Expected argument of type routerrpc.SendToRouteRequest');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_routerrpc_SendToRouteRequest(buffer_arg) {
+ return lndrouter_pb.SendToRouteRequest.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_routerrpc_SendToRouteResponse(arg) {
+ if (!(arg instanceof lndrouter_pb.SendToRouteResponse)) {
+ throw new Error('Expected argument of type routerrpc.SendToRouteResponse');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_routerrpc_SendToRouteResponse(buffer_arg) {
+ return lndrouter_pb.SendToRouteResponse.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_routerrpc_SubscribeHtlcEventsRequest(arg) {
+ if (!(arg instanceof lndrouter_pb.SubscribeHtlcEventsRequest)) {
+ throw new Error('Expected argument of type routerrpc.SubscribeHtlcEventsRequest');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_routerrpc_SubscribeHtlcEventsRequest(buffer_arg) {
+ return lndrouter_pb.SubscribeHtlcEventsRequest.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_routerrpc_TrackPaymentRequest(arg) {
+ if (!(arg instanceof lndrouter_pb.TrackPaymentRequest)) {
+ throw new Error('Expected argument of type routerrpc.TrackPaymentRequest');
+ }
+ return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_routerrpc_TrackPaymentRequest(buffer_arg) {
+ return lndrouter_pb.TrackPaymentRequest.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+
+// Router is a service that offers advanced interaction with the router
+// subsystem of the daemon.
+var RouterService = exports.RouterService = {
+ //
+ // SendPaymentV2 attempts to route a payment described by the passed
+ // PaymentRequest to the final destination. The call returns a stream of
+ // payment updates.
+ sendPaymentV2: {
+ path: '/routerrpc.Router/SendPaymentV2',
+ requestStream: false,
+ responseStream: true,
+ requestType: lndrouter_pb.SendPaymentRequest,
+ responseType: lndrpc_pb.Payment,
+ requestSerialize: serialize_routerrpc_SendPaymentRequest,
+ requestDeserialize: deserialize_routerrpc_SendPaymentRequest,
+ responseSerialize: serialize_lnrpc_Payment,
+ responseDeserialize: deserialize_lnrpc_Payment,
+ },
+ //
+ // TrackPaymentV2 returns an update stream for the payment identified by the
+ // payment hash.
+ trackPaymentV2: {
+ path: '/routerrpc.Router/TrackPaymentV2',
+ requestStream: false,
+ responseStream: true,
+ requestType: lndrouter_pb.TrackPaymentRequest,
+ responseType: lndrpc_pb.Payment,
+ requestSerialize: serialize_routerrpc_TrackPaymentRequest,
+ requestDeserialize: deserialize_routerrpc_TrackPaymentRequest,
+ responseSerialize: serialize_lnrpc_Payment,
+ responseDeserialize: deserialize_lnrpc_Payment,
+ },
+ //
+ // EstimateRouteFee allows callers to obtain a lower bound w.r.t how much it
+ // may cost to send an HTLC to the target end destination.
+ estimateRouteFee: {
+ path: '/routerrpc.Router/EstimateRouteFee',
+ requestStream: false,
+ responseStream: false,
+ requestType: lndrouter_pb.RouteFeeRequest,
+ responseType: lndrouter_pb.RouteFeeResponse,
+ requestSerialize: serialize_routerrpc_RouteFeeRequest,
+ requestDeserialize: deserialize_routerrpc_RouteFeeRequest,
+ responseSerialize: serialize_routerrpc_RouteFeeResponse,
+ responseDeserialize: deserialize_routerrpc_RouteFeeResponse,
+ },
+ //
+ // Deprecated, use SendToRouteV2. SendToRoute attempts to make a payment via
+ // the specified route. This method differs from SendPayment in that it
+ // allows users to specify a full route manually. This can be used for
+ // things like rebalancing, and atomic swaps. It differs from the newer
+ // SendToRouteV2 in that it doesn't return the full HTLC information.
+ sendToRoute: {
+ path: '/routerrpc.Router/SendToRoute',
+ requestStream: false,
+ responseStream: false,
+ requestType: lndrouter_pb.SendToRouteRequest,
+ responseType: lndrouter_pb.SendToRouteResponse,
+ requestSerialize: serialize_routerrpc_SendToRouteRequest,
+ requestDeserialize: deserialize_routerrpc_SendToRouteRequest,
+ responseSerialize: serialize_routerrpc_SendToRouteResponse,
+ responseDeserialize: deserialize_routerrpc_SendToRouteResponse,
+ },
+ //
+ // SendToRouteV2 attempts to make a payment via the specified route. This
+ // method differs from SendPayment in that it allows users to specify a full
+ // route manually. This can be used for things like rebalancing, and atomic
+ // swaps.
+ sendToRouteV2: {
+ path: '/routerrpc.Router/SendToRouteV2',
+ requestStream: false,
+ responseStream: false,
+ requestType: lndrouter_pb.SendToRouteRequest,
+ responseType: lndrpc_pb.HTLCAttempt,
+ requestSerialize: serialize_routerrpc_SendToRouteRequest,
+ requestDeserialize: deserialize_routerrpc_SendToRouteRequest,
+ responseSerialize: serialize_lnrpc_HTLCAttempt,
+ responseDeserialize: deserialize_lnrpc_HTLCAttempt,
+ },
+ //
+ // ResetMissionControl clears all mission control state and starts with a clean
+ // slate.
+ resetMissionControl: {
+ path: '/routerrpc.Router/ResetMissionControl',
+ requestStream: false,
+ responseStream: false,
+ requestType: lndrouter_pb.ResetMissionControlRequest,
+ responseType: lndrouter_pb.ResetMissionControlResponse,
+ requestSerialize: serialize_routerrpc_ResetMissionControlRequest,
+ requestDeserialize: deserialize_routerrpc_ResetMissionControlRequest,
+ responseSerialize: serialize_routerrpc_ResetMissionControlResponse,
+ responseDeserialize: deserialize_routerrpc_ResetMissionControlResponse,
+ },
+ //
+ // QueryMissionControl exposes the internal mission control state to callers.
+ // It is a development feature.
+ queryMissionControl: {
+ path: '/routerrpc.Router/QueryMissionControl',
+ requestStream: false,
+ responseStream: false,
+ requestType: lndrouter_pb.QueryMissionControlRequest,
+ responseType: lndrouter_pb.QueryMissionControlResponse,
+ requestSerialize: serialize_routerrpc_QueryMissionControlRequest,
+ requestDeserialize: deserialize_routerrpc_QueryMissionControlRequest,
+ responseSerialize: serialize_routerrpc_QueryMissionControlResponse,
+ responseDeserialize: deserialize_routerrpc_QueryMissionControlResponse,
+ },
+ //
+ // QueryProbability returns the current success probability estimate for a
+ // given node pair and amount.
+ queryProbability: {
+ path: '/routerrpc.Router/QueryProbability',
+ requestStream: false,
+ responseStream: false,
+ requestType: lndrouter_pb.QueryProbabilityRequest,
+ responseType: lndrouter_pb.QueryProbabilityResponse,
+ requestSerialize: serialize_routerrpc_QueryProbabilityRequest,
+ requestDeserialize: deserialize_routerrpc_QueryProbabilityRequest,
+ responseSerialize: serialize_routerrpc_QueryProbabilityResponse,
+ responseDeserialize: deserialize_routerrpc_QueryProbabilityResponse,
+ },
+ //
+ // BuildRoute builds a fully specified route based on a list of hop public
+ // keys. It retrieves the relevant channel policies from the graph in order to
+ // calculate the correct fees and time locks.
+ buildRoute: {
+ path: '/routerrpc.Router/BuildRoute',
+ requestStream: false,
+ responseStream: false,
+ requestType: lndrouter_pb.BuildRouteRequest,
+ responseType: lndrouter_pb.BuildRouteResponse,
+ requestSerialize: serialize_routerrpc_BuildRouteRequest,
+ requestDeserialize: deserialize_routerrpc_BuildRouteRequest,
+ responseSerialize: serialize_routerrpc_BuildRouteResponse,
+ responseDeserialize: deserialize_routerrpc_BuildRouteResponse,
+ },
+ //
+ // SubscribeHtlcEvents creates a uni-directional stream from the server to
+ // the client which delivers a stream of htlc events.
+ subscribeHtlcEvents: {
+ path: '/routerrpc.Router/SubscribeHtlcEvents',
+ requestStream: false,
+ responseStream: true,
+ requestType: lndrouter_pb.SubscribeHtlcEventsRequest,
+ responseType: lndrouter_pb.HtlcEvent,
+ requestSerialize: serialize_routerrpc_SubscribeHtlcEventsRequest,
+ requestDeserialize: deserialize_routerrpc_SubscribeHtlcEventsRequest,
+ responseSerialize: serialize_routerrpc_HtlcEvent,
+ responseDeserialize: deserialize_routerrpc_HtlcEvent,
+ },
+ //
+ // Deprecated, use SendPaymentV2. SendPayment attempts to route a payment
+ // described by the passed PaymentRequest to the final destination. The call
+ // returns a stream of payment status updates.
+ sendPayment: {
+ path: '/routerrpc.Router/SendPayment',
+ requestStream: false,
+ responseStream: true,
+ requestType: lndrouter_pb.SendPaymentRequest,
+ responseType: lndrouter_pb.PaymentStatus,
+ requestSerialize: serialize_routerrpc_SendPaymentRequest,
+ requestDeserialize: deserialize_routerrpc_SendPaymentRequest,
+ responseSerialize: serialize_routerrpc_PaymentStatus,
+ responseDeserialize: deserialize_routerrpc_PaymentStatus,
+ },
+ //
+ // Deprecated, use TrackPaymentV2. TrackPayment returns an update stream for
+ // the payment identified by the payment hash.
+ trackPayment: {
+ path: '/routerrpc.Router/TrackPayment',
+ requestStream: false,
+ responseStream: true,
+ requestType: lndrouter_pb.TrackPaymentRequest,
+ responseType: lndrouter_pb.PaymentStatus,
+ requestSerialize: serialize_routerrpc_TrackPaymentRequest,
+ requestDeserialize: deserialize_routerrpc_TrackPaymentRequest,
+ responseSerialize: serialize_routerrpc_PaymentStatus,
+ responseDeserialize: deserialize_routerrpc_PaymentStatus,
+ },
+ // *
+ // HtlcInterceptor dispatches a bi-directional streaming RPC in which
+ // Forwarded HTLC requests are sent to the client and the client responds with
+ // a boolean that tells LND if this htlc should be intercepted.
+ // In case of interception, the htlc can be either settled, cancelled or
+ // resumed later by using the ResolveHoldForward endpoint.
+ htlcInterceptor: {
+ path: '/routerrpc.Router/HtlcInterceptor',
+ requestStream: true,
+ responseStream: true,
+ requestType: lndrouter_pb.ForwardHtlcInterceptResponse,
+ responseType: lndrouter_pb.ForwardHtlcInterceptRequest,
+ requestSerialize: serialize_routerrpc_ForwardHtlcInterceptResponse,
+ requestDeserialize: deserialize_routerrpc_ForwardHtlcInterceptResponse,
+ responseSerialize: serialize_routerrpc_ForwardHtlcInterceptRequest,
+ responseDeserialize: deserialize_routerrpc_ForwardHtlcInterceptRequest,
+ },
+};
+
+exports.RouterClient = grpc.makeGenericClientConstructor(RouterService);
diff --git a/lib/proto/lndrouter_pb.d.ts b/lib/proto/lndrouter_pb.d.ts
new file mode 100644
index 000000000..e8144e533
--- /dev/null
+++ b/lib/proto/lndrouter_pb.d.ts
@@ -0,0 +1,953 @@
+// package: routerrpc
+// file: lndrouter.proto
+
+/* tslint:disable */
+
+import * as jspb from "google-protobuf";
+import * as lndrpc_pb from "./lndrpc_pb";
+
+export class SendPaymentRequest extends jspb.Message {
+ getDest(): Uint8Array | string;
+ getDest_asU8(): Uint8Array;
+ getDest_asB64(): string;
+ setDest(value: Uint8Array | string): void;
+
+ getAmt(): number;
+ setAmt(value: number): void;
+
+ getAmtMsat(): number;
+ setAmtMsat(value: number): void;
+
+ getPaymentHash(): Uint8Array | string;
+ getPaymentHash_asU8(): Uint8Array;
+ getPaymentHash_asB64(): string;
+ setPaymentHash(value: Uint8Array | string): void;
+
+ getFinalCltvDelta(): number;
+ setFinalCltvDelta(value: number): void;
+
+ getPaymentRequest(): string;
+ setPaymentRequest(value: string): void;
+
+ getTimeoutSeconds(): number;
+ setTimeoutSeconds(value: number): void;
+
+ getFeeLimitSat(): number;
+ setFeeLimitSat(value: number): void;
+
+ getFeeLimitMsat(): number;
+ setFeeLimitMsat(value: number): void;
+
+ getOutgoingChanId(): string;
+ setOutgoingChanId(value: string): void;
+
+ clearOutgoingChanIdsList(): void;
+ getOutgoingChanIdsList(): Array;
+ setOutgoingChanIdsList(value: Array): void;
+ addOutgoingChanIds(value: number, index?: number): number;
+
+ getLastHopPubkey(): Uint8Array | string;
+ getLastHopPubkey_asU8(): Uint8Array;
+ getLastHopPubkey_asB64(): string;
+ setLastHopPubkey(value: Uint8Array | string): void;
+
+ getCltvLimit(): number;
+ setCltvLimit(value: number): void;
+
+ clearRouteHintsList(): void;
+ getRouteHintsList(): Array;
+ setRouteHintsList(value: Array): void;
+ addRouteHints(value?: lndrpc_pb.RouteHint, index?: number): lndrpc_pb.RouteHint;
+
+
+ getDestCustomRecordsMap(): jspb.Map;
+ clearDestCustomRecordsMap(): void;
+
+ getAllowSelfPayment(): boolean;
+ setAllowSelfPayment(value: boolean): void;
+
+ clearDestFeaturesList(): void;
+ getDestFeaturesList(): Array;
+ setDestFeaturesList(value: Array): void;
+ addDestFeatures(value: lndrpc_pb.FeatureBit, index?: number): lndrpc_pb.FeatureBit;
+
+ getMaxParts(): number;
+ setMaxParts(value: number): void;
+
+ getNoInflightUpdates(): boolean;
+ setNoInflightUpdates(value: boolean): void;
+
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): SendPaymentRequest.AsObject;
+ static toObject(includeInstance: boolean, msg: SendPaymentRequest): SendPaymentRequest.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: SendPaymentRequest, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): SendPaymentRequest;
+ static deserializeBinaryFromReader(message: SendPaymentRequest, reader: jspb.BinaryReader): SendPaymentRequest;
+}
+
+export namespace SendPaymentRequest {
+ export type AsObject = {
+ dest: Uint8Array | string,
+ amt: number,
+ amtMsat: number,
+ paymentHash: Uint8Array | string,
+ finalCltvDelta: number,
+ paymentRequest: string,
+ timeoutSeconds: number,
+ feeLimitSat: number,
+ feeLimitMsat: number,
+ outgoingChanId: string,
+ outgoingChanIdsList: Array,
+ lastHopPubkey: Uint8Array | string,
+ cltvLimit: number,
+ routeHintsList: Array,
+
+ destCustomRecordsMap: Array<[number, Uint8Array | string]>,
+ allowSelfPayment: boolean,
+ destFeaturesList: Array,
+ maxParts: number,
+ noInflightUpdates: boolean,
+ }
+}
+
+export class TrackPaymentRequest extends jspb.Message {
+ getPaymentHash(): Uint8Array | string;
+ getPaymentHash_asU8(): Uint8Array;
+ getPaymentHash_asB64(): string;
+ setPaymentHash(value: Uint8Array | string): void;
+
+ getNoInflightUpdates(): boolean;
+ setNoInflightUpdates(value: boolean): void;
+
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): TrackPaymentRequest.AsObject;
+ static toObject(includeInstance: boolean, msg: TrackPaymentRequest): TrackPaymentRequest.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: TrackPaymentRequest, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): TrackPaymentRequest;
+ static deserializeBinaryFromReader(message: TrackPaymentRequest, reader: jspb.BinaryReader): TrackPaymentRequest;
+}
+
+export namespace TrackPaymentRequest {
+ export type AsObject = {
+ paymentHash: Uint8Array | string,
+ noInflightUpdates: boolean,
+ }
+}
+
+export class RouteFeeRequest extends jspb.Message {
+ getDest(): Uint8Array | string;
+ getDest_asU8(): Uint8Array;
+ getDest_asB64(): string;
+ setDest(value: Uint8Array | string): void;
+
+ getAmtSat(): number;
+ setAmtSat(value: number): void;
+
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): RouteFeeRequest.AsObject;
+ static toObject(includeInstance: boolean, msg: RouteFeeRequest): RouteFeeRequest.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: RouteFeeRequest, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): RouteFeeRequest;
+ static deserializeBinaryFromReader(message: RouteFeeRequest, reader: jspb.BinaryReader): RouteFeeRequest;
+}
+
+export namespace RouteFeeRequest {
+ export type AsObject = {
+ dest: Uint8Array | string,
+ amtSat: number,
+ }
+}
+
+export class RouteFeeResponse extends jspb.Message {
+ getRoutingFeeMsat(): number;
+ setRoutingFeeMsat(value: number): void;
+
+ getTimeLockDelay(): number;
+ setTimeLockDelay(value: number): void;
+
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): RouteFeeResponse.AsObject;
+ static toObject(includeInstance: boolean, msg: RouteFeeResponse): RouteFeeResponse.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: RouteFeeResponse, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): RouteFeeResponse;
+ static deserializeBinaryFromReader(message: RouteFeeResponse, reader: jspb.BinaryReader): RouteFeeResponse;
+}
+
+export namespace RouteFeeResponse {
+ export type AsObject = {
+ routingFeeMsat: number,
+ timeLockDelay: number,
+ }
+}
+
+export class SendToRouteRequest extends jspb.Message {
+ getPaymentHash(): Uint8Array | string;
+ getPaymentHash_asU8(): Uint8Array;
+ getPaymentHash_asB64(): string;
+ setPaymentHash(value: Uint8Array | string): void;
+
+
+ hasRoute(): boolean;
+ clearRoute(): void;
+ getRoute(): lndrpc_pb.Route | undefined;
+ setRoute(value?: lndrpc_pb.Route): void;
+
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): SendToRouteRequest.AsObject;
+ static toObject(includeInstance: boolean, msg: SendToRouteRequest): SendToRouteRequest.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: SendToRouteRequest, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): SendToRouteRequest;
+ static deserializeBinaryFromReader(message: SendToRouteRequest, reader: jspb.BinaryReader): SendToRouteRequest;
+}
+
+export namespace SendToRouteRequest {
+ export type AsObject = {
+ paymentHash: Uint8Array | string,
+ route?: lndrpc_pb.Route.AsObject,
+ }
+}
+
+export class SendToRouteResponse extends jspb.Message {
+ getPreimage(): Uint8Array | string;
+ getPreimage_asU8(): Uint8Array;
+ getPreimage_asB64(): string;
+ setPreimage(value: Uint8Array | string): void;
+
+
+ hasFailure(): boolean;
+ clearFailure(): void;
+ getFailure(): lndrpc_pb.Failure | undefined;
+ setFailure(value?: lndrpc_pb.Failure): void;
+
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): SendToRouteResponse.AsObject;
+ static toObject(includeInstance: boolean, msg: SendToRouteResponse): SendToRouteResponse.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: SendToRouteResponse, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): SendToRouteResponse;
+ static deserializeBinaryFromReader(message: SendToRouteResponse, reader: jspb.BinaryReader): SendToRouteResponse;
+}
+
+export namespace SendToRouteResponse {
+ export type AsObject = {
+ preimage: Uint8Array | string,
+ failure?: lndrpc_pb.Failure.AsObject,
+ }
+}
+
+export class ResetMissionControlRequest extends jspb.Message {
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): ResetMissionControlRequest.AsObject;
+ static toObject(includeInstance: boolean, msg: ResetMissionControlRequest): ResetMissionControlRequest.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: ResetMissionControlRequest, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): ResetMissionControlRequest;
+ static deserializeBinaryFromReader(message: ResetMissionControlRequest, reader: jspb.BinaryReader): ResetMissionControlRequest;
+}
+
+export namespace ResetMissionControlRequest {
+ export type AsObject = {
+ }
+}
+
+export class ResetMissionControlResponse extends jspb.Message {
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): ResetMissionControlResponse.AsObject;
+ static toObject(includeInstance: boolean, msg: ResetMissionControlResponse): ResetMissionControlResponse.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: ResetMissionControlResponse, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): ResetMissionControlResponse;
+ static deserializeBinaryFromReader(message: ResetMissionControlResponse, reader: jspb.BinaryReader): ResetMissionControlResponse;
+}
+
+export namespace ResetMissionControlResponse {
+ export type AsObject = {
+ }
+}
+
+export class QueryMissionControlRequest extends jspb.Message {
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): QueryMissionControlRequest.AsObject;
+ static toObject(includeInstance: boolean, msg: QueryMissionControlRequest): QueryMissionControlRequest.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: QueryMissionControlRequest, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): QueryMissionControlRequest;
+ static deserializeBinaryFromReader(message: QueryMissionControlRequest, reader: jspb.BinaryReader): QueryMissionControlRequest;
+}
+
+export namespace QueryMissionControlRequest {
+ export type AsObject = {
+ }
+}
+
+export class QueryMissionControlResponse extends jspb.Message {
+ clearPairsList(): void;
+ getPairsList(): Array;
+ setPairsList(value: Array): void;
+ addPairs(value?: PairHistory, index?: number): PairHistory;
+
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): QueryMissionControlResponse.AsObject;
+ static toObject(includeInstance: boolean, msg: QueryMissionControlResponse): QueryMissionControlResponse.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: QueryMissionControlResponse, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): QueryMissionControlResponse;
+ static deserializeBinaryFromReader(message: QueryMissionControlResponse, reader: jspb.BinaryReader): QueryMissionControlResponse;
+}
+
+export namespace QueryMissionControlResponse {
+ export type AsObject = {
+ pairsList: Array,
+ }
+}
+
+export class PairHistory extends jspb.Message {
+ getNodeFrom(): Uint8Array | string;
+ getNodeFrom_asU8(): Uint8Array;
+ getNodeFrom_asB64(): string;
+ setNodeFrom(value: Uint8Array | string): void;
+
+ getNodeTo(): Uint8Array | string;
+ getNodeTo_asU8(): Uint8Array;
+ getNodeTo_asB64(): string;
+ setNodeTo(value: Uint8Array | string): void;
+
+
+ hasHistory(): boolean;
+ clearHistory(): void;
+ getHistory(): PairData | undefined;
+ setHistory(value?: PairData): void;
+
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): PairHistory.AsObject;
+ static toObject(includeInstance: boolean, msg: PairHistory): PairHistory.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: PairHistory, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): PairHistory;
+ static deserializeBinaryFromReader(message: PairHistory, reader: jspb.BinaryReader): PairHistory;
+}
+
+export namespace PairHistory {
+ export type AsObject = {
+ nodeFrom: Uint8Array | string,
+ nodeTo: Uint8Array | string,
+ history?: PairData.AsObject,
+ }
+}
+
+export class PairData extends jspb.Message {
+ getFailTime(): number;
+ setFailTime(value: number): void;
+
+ getFailAmtSat(): number;
+ setFailAmtSat(value: number): void;
+
+ getFailAmtMsat(): number;
+ setFailAmtMsat(value: number): void;
+
+ getSuccessTime(): number;
+ setSuccessTime(value: number): void;
+
+ getSuccessAmtSat(): number;
+ setSuccessAmtSat(value: number): void;
+
+ getSuccessAmtMsat(): number;
+ setSuccessAmtMsat(value: number): void;
+
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): PairData.AsObject;
+ static toObject(includeInstance: boolean, msg: PairData): PairData.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: PairData, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): PairData;
+ static deserializeBinaryFromReader(message: PairData, reader: jspb.BinaryReader): PairData;
+}
+
+export namespace PairData {
+ export type AsObject = {
+ failTime: number,
+ failAmtSat: number,
+ failAmtMsat: number,
+ successTime: number,
+ successAmtSat: number,
+ successAmtMsat: number,
+ }
+}
+
+export class QueryProbabilityRequest extends jspb.Message {
+ getFromNode(): Uint8Array | string;
+ getFromNode_asU8(): Uint8Array;
+ getFromNode_asB64(): string;
+ setFromNode(value: Uint8Array | string): void;
+
+ getToNode(): Uint8Array | string;
+ getToNode_asU8(): Uint8Array;
+ getToNode_asB64(): string;
+ setToNode(value: Uint8Array | string): void;
+
+ getAmtMsat(): number;
+ setAmtMsat(value: number): void;
+
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): QueryProbabilityRequest.AsObject;
+ static toObject(includeInstance: boolean, msg: QueryProbabilityRequest): QueryProbabilityRequest.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: QueryProbabilityRequest, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): QueryProbabilityRequest;
+ static deserializeBinaryFromReader(message: QueryProbabilityRequest, reader: jspb.BinaryReader): QueryProbabilityRequest;
+}
+
+export namespace QueryProbabilityRequest {
+ export type AsObject = {
+ fromNode: Uint8Array | string,
+ toNode: Uint8Array | string,
+ amtMsat: number,
+ }
+}
+
+export class QueryProbabilityResponse extends jspb.Message {
+ getProbability(): number;
+ setProbability(value: number): void;
+
+
+ hasHistory(): boolean;
+ clearHistory(): void;
+ getHistory(): PairData | undefined;
+ setHistory(value?: PairData): void;
+
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): QueryProbabilityResponse.AsObject;
+ static toObject(includeInstance: boolean, msg: QueryProbabilityResponse): QueryProbabilityResponse.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: QueryProbabilityResponse, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): QueryProbabilityResponse;
+ static deserializeBinaryFromReader(message: QueryProbabilityResponse, reader: jspb.BinaryReader): QueryProbabilityResponse;
+}
+
+export namespace QueryProbabilityResponse {
+ export type AsObject = {
+ probability: number,
+ history?: PairData.AsObject,
+ }
+}
+
+export class BuildRouteRequest extends jspb.Message {
+ getAmtMsat(): number;
+ setAmtMsat(value: number): void;
+
+ getFinalCltvDelta(): number;
+ setFinalCltvDelta(value: number): void;
+
+ getOutgoingChanId(): string;
+ setOutgoingChanId(value: string): void;
+
+ clearHopPubkeysList(): void;
+ getHopPubkeysList(): Array;
+ getHopPubkeysList_asU8(): Array;
+ getHopPubkeysList_asB64(): Array;
+ setHopPubkeysList(value: Array): void;
+ addHopPubkeys(value: Uint8Array | string, index?: number): Uint8Array | string;
+
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): BuildRouteRequest.AsObject;
+ static toObject(includeInstance: boolean, msg: BuildRouteRequest): BuildRouteRequest.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: BuildRouteRequest, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): BuildRouteRequest;
+ static deserializeBinaryFromReader(message: BuildRouteRequest, reader: jspb.BinaryReader): BuildRouteRequest;
+}
+
+export namespace BuildRouteRequest {
+ export type AsObject = {
+ amtMsat: number,
+ finalCltvDelta: number,
+ outgoingChanId: string,
+ hopPubkeysList: Array,
+ }
+}
+
+export class BuildRouteResponse extends jspb.Message {
+
+ hasRoute(): boolean;
+ clearRoute(): void;
+ getRoute(): lndrpc_pb.Route | undefined;
+ setRoute(value?: lndrpc_pb.Route): void;
+
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): BuildRouteResponse.AsObject;
+ static toObject(includeInstance: boolean, msg: BuildRouteResponse): BuildRouteResponse.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: BuildRouteResponse, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): BuildRouteResponse;
+ static deserializeBinaryFromReader(message: BuildRouteResponse, reader: jspb.BinaryReader): BuildRouteResponse;
+}
+
+export namespace BuildRouteResponse {
+ export type AsObject = {
+ route?: lndrpc_pb.Route.AsObject,
+ }
+}
+
+export class SubscribeHtlcEventsRequest extends jspb.Message {
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): SubscribeHtlcEventsRequest.AsObject;
+ static toObject(includeInstance: boolean, msg: SubscribeHtlcEventsRequest): SubscribeHtlcEventsRequest.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: SubscribeHtlcEventsRequest, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): SubscribeHtlcEventsRequest;
+ static deserializeBinaryFromReader(message: SubscribeHtlcEventsRequest, reader: jspb.BinaryReader): SubscribeHtlcEventsRequest;
+}
+
+export namespace SubscribeHtlcEventsRequest {
+ export type AsObject = {
+ }
+}
+
+export class HtlcEvent extends jspb.Message {
+ getIncomingChannelId(): number;
+ setIncomingChannelId(value: number): void;
+
+ getOutgoingChannelId(): number;
+ setOutgoingChannelId(value: number): void;
+
+ getIncomingHtlcId(): number;
+ setIncomingHtlcId(value: number): void;
+
+ getOutgoingHtlcId(): number;
+ setOutgoingHtlcId(value: number): void;
+
+ getTimestampNs(): number;
+ setTimestampNs(value: number): void;
+
+ getEventType(): HtlcEvent.EventType;
+ setEventType(value: HtlcEvent.EventType): void;
+
+
+ hasForwardEvent(): boolean;
+ clearForwardEvent(): void;
+ getForwardEvent(): ForwardEvent | undefined;
+ setForwardEvent(value?: ForwardEvent): void;
+
+
+ hasForwardFailEvent(): boolean;
+ clearForwardFailEvent(): void;
+ getForwardFailEvent(): ForwardFailEvent | undefined;
+ setForwardFailEvent(value?: ForwardFailEvent): void;
+
+
+ hasSettleEvent(): boolean;
+ clearSettleEvent(): void;
+ getSettleEvent(): SettleEvent | undefined;
+ setSettleEvent(value?: SettleEvent): void;
+
+
+ hasLinkFailEvent(): boolean;
+ clearLinkFailEvent(): void;
+ getLinkFailEvent(): LinkFailEvent | undefined;
+ setLinkFailEvent(value?: LinkFailEvent): void;
+
+
+ getEventCase(): HtlcEvent.EventCase;
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): HtlcEvent.AsObject;
+ static toObject(includeInstance: boolean, msg: HtlcEvent): HtlcEvent.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: HtlcEvent, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): HtlcEvent;
+ static deserializeBinaryFromReader(message: HtlcEvent, reader: jspb.BinaryReader): HtlcEvent;
+}
+
+export namespace HtlcEvent {
+ export type AsObject = {
+ incomingChannelId: number,
+ outgoingChannelId: number,
+ incomingHtlcId: number,
+ outgoingHtlcId: number,
+ timestampNs: number,
+ eventType: HtlcEvent.EventType,
+ forwardEvent?: ForwardEvent.AsObject,
+ forwardFailEvent?: ForwardFailEvent.AsObject,
+ settleEvent?: SettleEvent.AsObject,
+ linkFailEvent?: LinkFailEvent.AsObject,
+ }
+
+ export enum EventType {
+ UNKNOWN = 0,
+ SEND = 1,
+ RECEIVE = 2,
+ FORWARD = 3,
+ }
+
+
+ export enum EventCase {
+ EVENT_NOT_SET = 0,
+
+ FORWARD_EVENT = 7,
+
+ FORWARD_FAIL_EVENT = 8,
+
+ SETTLE_EVENT = 9,
+
+ LINK_FAIL_EVENT = 10,
+
+ }
+
+}
+
+export class HtlcInfo extends jspb.Message {
+ getIncomingTimelock(): number;
+ setIncomingTimelock(value: number): void;
+
+ getOutgoingTimelock(): number;
+ setOutgoingTimelock(value: number): void;
+
+ getIncomingAmtMsat(): number;
+ setIncomingAmtMsat(value: number): void;
+
+ getOutgoingAmtMsat(): number;
+ setOutgoingAmtMsat(value: number): void;
+
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): HtlcInfo.AsObject;
+ static toObject(includeInstance: boolean, msg: HtlcInfo): HtlcInfo.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: HtlcInfo, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): HtlcInfo;
+ static deserializeBinaryFromReader(message: HtlcInfo, reader: jspb.BinaryReader): HtlcInfo;
+}
+
+export namespace HtlcInfo {
+ export type AsObject = {
+ incomingTimelock: number,
+ outgoingTimelock: number,
+ incomingAmtMsat: number,
+ outgoingAmtMsat: number,
+ }
+}
+
+export class ForwardEvent extends jspb.Message {
+
+ hasInfo(): boolean;
+ clearInfo(): void;
+ getInfo(): HtlcInfo | undefined;
+ setInfo(value?: HtlcInfo): void;
+
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): ForwardEvent.AsObject;
+ static toObject(includeInstance: boolean, msg: ForwardEvent): ForwardEvent.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: ForwardEvent, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): ForwardEvent;
+ static deserializeBinaryFromReader(message: ForwardEvent, reader: jspb.BinaryReader): ForwardEvent;
+}
+
+export namespace ForwardEvent {
+ export type AsObject = {
+ info?: HtlcInfo.AsObject,
+ }
+}
+
+export class ForwardFailEvent extends jspb.Message {
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): ForwardFailEvent.AsObject;
+ static toObject(includeInstance: boolean, msg: ForwardFailEvent): ForwardFailEvent.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: ForwardFailEvent, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): ForwardFailEvent;
+ static deserializeBinaryFromReader(message: ForwardFailEvent, reader: jspb.BinaryReader): ForwardFailEvent;
+}
+
+export namespace ForwardFailEvent {
+ export type AsObject = {
+ }
+}
+
+export class SettleEvent extends jspb.Message {
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): SettleEvent.AsObject;
+ static toObject(includeInstance: boolean, msg: SettleEvent): SettleEvent.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: SettleEvent, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): SettleEvent;
+ static deserializeBinaryFromReader(message: SettleEvent, reader: jspb.BinaryReader): SettleEvent;
+}
+
+export namespace SettleEvent {
+ export type AsObject = {
+ }
+}
+
+export class LinkFailEvent extends jspb.Message {
+
+ hasInfo(): boolean;
+ clearInfo(): void;
+ getInfo(): HtlcInfo | undefined;
+ setInfo(value?: HtlcInfo): void;
+
+ getWireFailure(): lndrpc_pb.Failure.FailureCode;
+ setWireFailure(value: lndrpc_pb.Failure.FailureCode): void;
+
+ getFailureDetail(): FailureDetail;
+ setFailureDetail(value: FailureDetail): void;
+
+ getFailureString(): string;
+ setFailureString(value: string): void;
+
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): LinkFailEvent.AsObject;
+ static toObject(includeInstance: boolean, msg: LinkFailEvent): LinkFailEvent.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: LinkFailEvent, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): LinkFailEvent;
+ static deserializeBinaryFromReader(message: LinkFailEvent, reader: jspb.BinaryReader): LinkFailEvent;
+}
+
+export namespace LinkFailEvent {
+ export type AsObject = {
+ info?: HtlcInfo.AsObject,
+ wireFailure: lndrpc_pb.Failure.FailureCode,
+ failureDetail: FailureDetail,
+ failureString: string,
+ }
+}
+
+export class PaymentStatus extends jspb.Message {
+ getState(): PaymentState;
+ setState(value: PaymentState): void;
+
+ getPreimage(): Uint8Array | string;
+ getPreimage_asU8(): Uint8Array;
+ getPreimage_asB64(): string;
+ setPreimage(value: Uint8Array | string): void;
+
+ clearHtlcsList(): void;
+ getHtlcsList(): Array;
+ setHtlcsList(value: Array): void;
+ addHtlcs(value?: lndrpc_pb.HTLCAttempt, index?: number): lndrpc_pb.HTLCAttempt;
+
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): PaymentStatus.AsObject;
+ static toObject(includeInstance: boolean, msg: PaymentStatus): PaymentStatus.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: PaymentStatus, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): PaymentStatus;
+ static deserializeBinaryFromReader(message: PaymentStatus, reader: jspb.BinaryReader): PaymentStatus;
+}
+
+export namespace PaymentStatus {
+ export type AsObject = {
+ state: PaymentState,
+ preimage: Uint8Array | string,
+ htlcsList: Array,
+ }
+}
+
+export class CircuitKey extends jspb.Message {
+ getChanId(): number;
+ setChanId(value: number): void;
+
+ getHtlcId(): number;
+ setHtlcId(value: number): void;
+
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): CircuitKey.AsObject;
+ static toObject(includeInstance: boolean, msg: CircuitKey): CircuitKey.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: CircuitKey, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): CircuitKey;
+ static deserializeBinaryFromReader(message: CircuitKey, reader: jspb.BinaryReader): CircuitKey;
+}
+
+export namespace CircuitKey {
+ export type AsObject = {
+ chanId: number,
+ htlcId: number,
+ }
+}
+
+export class ForwardHtlcInterceptRequest extends jspb.Message {
+
+ hasIncomingCircuitKey(): boolean;
+ clearIncomingCircuitKey(): void;
+ getIncomingCircuitKey(): CircuitKey | undefined;
+ setIncomingCircuitKey(value?: CircuitKey): void;
+
+ getIncomingAmountMsat(): number;
+ setIncomingAmountMsat(value: number): void;
+
+ getIncomingExpiry(): number;
+ setIncomingExpiry(value: number): void;
+
+ getPaymentHash(): Uint8Array | string;
+ getPaymentHash_asU8(): Uint8Array;
+ getPaymentHash_asB64(): string;
+ setPaymentHash(value: Uint8Array | string): void;
+
+ getOutgoingRequestedChanId(): number;
+ setOutgoingRequestedChanId(value: number): void;
+
+ getOutgoingAmountMsat(): number;
+ setOutgoingAmountMsat(value: number): void;
+
+ getOutgoingExpiry(): number;
+ setOutgoingExpiry(value: number): void;
+
+
+ getCustomRecordsMap(): jspb.Map;
+ clearCustomRecordsMap(): void;
+
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): ForwardHtlcInterceptRequest.AsObject;
+ static toObject(includeInstance: boolean, msg: ForwardHtlcInterceptRequest): ForwardHtlcInterceptRequest.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: ForwardHtlcInterceptRequest, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): ForwardHtlcInterceptRequest;
+ static deserializeBinaryFromReader(message: ForwardHtlcInterceptRequest, reader: jspb.BinaryReader): ForwardHtlcInterceptRequest;
+}
+
+export namespace ForwardHtlcInterceptRequest {
+ export type AsObject = {
+ incomingCircuitKey?: CircuitKey.AsObject,
+ incomingAmountMsat: number,
+ incomingExpiry: number,
+ paymentHash: Uint8Array | string,
+ outgoingRequestedChanId: number,
+ outgoingAmountMsat: number,
+ outgoingExpiry: number,
+
+ customRecordsMap: Array<[number, Uint8Array | string]>,
+ }
+}
+
+export class ForwardHtlcInterceptResponse extends jspb.Message {
+
+ hasIncomingCircuitKey(): boolean;
+ clearIncomingCircuitKey(): void;
+ getIncomingCircuitKey(): CircuitKey | undefined;
+ setIncomingCircuitKey(value?: CircuitKey): void;
+
+ getAction(): ResolveHoldForwardAction;
+ setAction(value: ResolveHoldForwardAction): void;
+
+ getPreimage(): Uint8Array | string;
+ getPreimage_asU8(): Uint8Array;
+ getPreimage_asB64(): string;
+ setPreimage(value: Uint8Array | string): void;
+
+
+ serializeBinary(): Uint8Array;
+ toObject(includeInstance?: boolean): ForwardHtlcInterceptResponse.AsObject;
+ static toObject(includeInstance: boolean, msg: ForwardHtlcInterceptResponse): ForwardHtlcInterceptResponse.AsObject;
+ static extensions: {[key: number]: jspb.ExtensionFieldInfo};
+ static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo};
+ static serializeBinaryToWriter(message: ForwardHtlcInterceptResponse, writer: jspb.BinaryWriter): void;
+ static deserializeBinary(bytes: Uint8Array): ForwardHtlcInterceptResponse;
+ static deserializeBinaryFromReader(message: ForwardHtlcInterceptResponse, reader: jspb.BinaryReader): ForwardHtlcInterceptResponse;
+}
+
+export namespace ForwardHtlcInterceptResponse {
+ export type AsObject = {
+ incomingCircuitKey?: CircuitKey.AsObject,
+ action: ResolveHoldForwardAction,
+ preimage: Uint8Array | string,
+ }
+}
+
+export enum FailureDetail {
+ UNKNOWN = 0,
+ NO_DETAIL = 1,
+ ONION_DECODE = 2,
+ LINK_NOT_ELIGIBLE = 3,
+ ON_CHAIN_TIMEOUT = 4,
+ HTLC_EXCEEDS_MAX = 5,
+ INSUFFICIENT_BALANCE = 6,
+ INCOMPLETE_FORWARD = 7,
+ HTLC_ADD_FAILED = 8,
+ FORWARDS_DISABLED = 9,
+ INVOICE_CANCELED = 10,
+ INVOICE_UNDERPAID = 11,
+ INVOICE_EXPIRY_TOO_SOON = 12,
+ INVOICE_NOT_OPEN = 13,
+ MPP_INVOICE_TIMEOUT = 14,
+ ADDRESS_MISMATCH = 15,
+ SET_TOTAL_MISMATCH = 16,
+ SET_TOTAL_TOO_LOW = 17,
+ SET_OVERPAID = 18,
+ UNKNOWN_INVOICE = 19,
+ INVALID_KEYSEND = 20,
+ MPP_IN_PROGRESS = 21,
+ CIRCULAR_ROUTE = 22,
+}
+
+export enum PaymentState {
+ IN_FLIGHT = 0,
+ SUCCEEDED = 1,
+ FAILED_TIMEOUT = 2,
+ FAILED_NO_ROUTE = 3,
+ FAILED_ERROR = 4,
+ FAILED_INCORRECT_PAYMENT_DETAILS = 5,
+ FAILED_INSUFFICIENT_BALANCE = 6,
+}
+
+export enum ResolveHoldForwardAction {
+ SETTLE = 0,
+ FAIL = 1,
+ RESUME = 2,
+}
diff --git a/lib/proto/lndrouter_pb.js b/lib/proto/lndrouter_pb.js
new file mode 100644
index 000000000..803f26d6f
--- /dev/null
+++ b/lib/proto/lndrouter_pb.js
@@ -0,0 +1,6233 @@
+/**
+ * @fileoverview
+ * @enhanceable
+ * @suppress {messageConventions} JS Compiler reports an error if a variable or
+ * field starts with 'MSG_' and isn't a translatable message.
+ * @public
+ */
+// GENERATED CODE -- DO NOT EDIT!
+
+var jspb = require('google-protobuf');
+var goog = jspb;
+var global = Function('return this')();
+
+var lndrpc_pb = require('./lndrpc_pb.js');
+goog.object.extend(proto, lndrpc_pb);
+goog.exportSymbol('proto.routerrpc.BuildRouteRequest', null, global);
+goog.exportSymbol('proto.routerrpc.BuildRouteResponse', null, global);
+goog.exportSymbol('proto.routerrpc.CircuitKey', null, global);
+goog.exportSymbol('proto.routerrpc.FailureDetail', null, global);
+goog.exportSymbol('proto.routerrpc.ForwardEvent', null, global);
+goog.exportSymbol('proto.routerrpc.ForwardFailEvent', null, global);
+goog.exportSymbol('proto.routerrpc.ForwardHtlcInterceptRequest', null, global);
+goog.exportSymbol('proto.routerrpc.ForwardHtlcInterceptResponse', null, global);
+goog.exportSymbol('proto.routerrpc.HtlcEvent', null, global);
+goog.exportSymbol('proto.routerrpc.HtlcEvent.EventType', null, global);
+goog.exportSymbol('proto.routerrpc.HtlcInfo', null, global);
+goog.exportSymbol('proto.routerrpc.LinkFailEvent', null, global);
+goog.exportSymbol('proto.routerrpc.PairData', null, global);
+goog.exportSymbol('proto.routerrpc.PairHistory', null, global);
+goog.exportSymbol('proto.routerrpc.PaymentState', null, global);
+goog.exportSymbol('proto.routerrpc.PaymentStatus', null, global);
+goog.exportSymbol('proto.routerrpc.QueryMissionControlRequest', null, global);
+goog.exportSymbol('proto.routerrpc.QueryMissionControlResponse', null, global);
+goog.exportSymbol('proto.routerrpc.QueryProbabilityRequest', null, global);
+goog.exportSymbol('proto.routerrpc.QueryProbabilityResponse', null, global);
+goog.exportSymbol('proto.routerrpc.ResetMissionControlRequest', null, global);
+goog.exportSymbol('proto.routerrpc.ResetMissionControlResponse', null, global);
+goog.exportSymbol('proto.routerrpc.ResolveHoldForwardAction', null, global);
+goog.exportSymbol('proto.routerrpc.RouteFeeRequest', null, global);
+goog.exportSymbol('proto.routerrpc.RouteFeeResponse', null, global);
+goog.exportSymbol('proto.routerrpc.SendPaymentRequest', null, global);
+goog.exportSymbol('proto.routerrpc.SendToRouteRequest', null, global);
+goog.exportSymbol('proto.routerrpc.SendToRouteResponse', null, global);
+goog.exportSymbol('proto.routerrpc.SettleEvent', null, global);
+goog.exportSymbol('proto.routerrpc.SubscribeHtlcEventsRequest', null, global);
+goog.exportSymbol('proto.routerrpc.TrackPaymentRequest', 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.routerrpc.SendPaymentRequest = function(opt_data) {
+ jspb.Message.initialize(this, opt_data, 0, -1, proto.routerrpc.SendPaymentRequest.repeatedFields_, null);
+};
+goog.inherits(proto.routerrpc.SendPaymentRequest, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+ proto.routerrpc.SendPaymentRequest.displayName = 'proto.routerrpc.SendPaymentRequest';
+}
+/**
+ * List of repeated fields within this message type.
+ * @private {!Array}
+ * @const
+ */
+proto.routerrpc.SendPaymentRequest.repeatedFields_ = [19,10,16];
+
+
+
+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.routerrpc.SendPaymentRequest.prototype.toObject = function(opt_includeInstance) {
+ return proto.routerrpc.SendPaymentRequest.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.routerrpc.SendPaymentRequest} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.routerrpc.SendPaymentRequest.toObject = function(includeInstance, msg) {
+ var f, obj = {
+ dest: msg.getDest_asB64(),
+ amt: jspb.Message.getFieldWithDefault(msg, 2, 0),
+ amtMsat: jspb.Message.getFieldWithDefault(msg, 12, 0),
+ paymentHash: msg.getPaymentHash_asB64(),
+ finalCltvDelta: jspb.Message.getFieldWithDefault(msg, 4, 0),
+ paymentRequest: jspb.Message.getFieldWithDefault(msg, 5, ""),
+ timeoutSeconds: jspb.Message.getFieldWithDefault(msg, 6, 0),
+ feeLimitSat: jspb.Message.getFieldWithDefault(msg, 7, 0),
+ feeLimitMsat: jspb.Message.getFieldWithDefault(msg, 13, 0),
+ outgoingChanId: jspb.Message.getFieldWithDefault(msg, 8, "0"),
+ outgoingChanIdsList: jspb.Message.getRepeatedField(msg, 19),
+ lastHopPubkey: msg.getLastHopPubkey_asB64(),
+ cltvLimit: jspb.Message.getFieldWithDefault(msg, 9, 0),
+ routeHintsList: jspb.Message.toObjectList(msg.getRouteHintsList(),
+ lndrpc_pb.RouteHint.toObject, includeInstance),
+ destCustomRecordsMap: (f = msg.getDestCustomRecordsMap()) ? f.toObject(includeInstance, undefined) : [],
+ allowSelfPayment: jspb.Message.getFieldWithDefault(msg, 15, false),
+ destFeaturesList: jspb.Message.getRepeatedField(msg, 16),
+ maxParts: jspb.Message.getFieldWithDefault(msg, 17, 0),
+ noInflightUpdates: jspb.Message.getFieldWithDefault(msg, 18, false)
+ };
+
+ if (includeInstance) {
+ obj.$jspbMessageInstance = msg;
+ }
+ return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.routerrpc.SendPaymentRequest}
+ */
+proto.routerrpc.SendPaymentRequest.deserializeBinary = function(bytes) {
+ var reader = new jspb.BinaryReader(bytes);
+ var msg = new proto.routerrpc.SendPaymentRequest;
+ return proto.routerrpc.SendPaymentRequest.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.routerrpc.SendPaymentRequest} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.routerrpc.SendPaymentRequest}
+ */
+proto.routerrpc.SendPaymentRequest.deserializeBinaryFromReader = function(msg, reader) {
+ while (reader.nextField()) {
+ if (reader.isEndGroup()) {
+ break;
+ }
+ var field = reader.getFieldNumber();
+ switch (field) {
+ case 1:
+ var value = /** @type {!Uint8Array} */ (reader.readBytes());
+ msg.setDest(value);
+ break;
+ case 2:
+ var value = /** @type {number} */ (reader.readInt64());
+ msg.setAmt(value);
+ break;
+ case 12:
+ var value = /** @type {number} */ (reader.readInt64());
+ msg.setAmtMsat(value);
+ break;
+ case 3:
+ var value = /** @type {!Uint8Array} */ (reader.readBytes());
+ msg.setPaymentHash(value);
+ break;
+ case 4:
+ var value = /** @type {number} */ (reader.readInt32());
+ msg.setFinalCltvDelta(value);
+ break;
+ case 5:
+ var value = /** @type {string} */ (reader.readString());
+ msg.setPaymentRequest(value);
+ break;
+ case 6:
+ var value = /** @type {number} */ (reader.readInt32());
+ msg.setTimeoutSeconds(value);
+ break;
+ case 7:
+ var value = /** @type {number} */ (reader.readInt64());
+ msg.setFeeLimitSat(value);
+ break;
+ case 13:
+ var value = /** @type {number} */ (reader.readInt64());
+ msg.setFeeLimitMsat(value);
+ break;
+ case 8:
+ var value = /** @type {string} */ (reader.readUint64String());
+ msg.setOutgoingChanId(value);
+ break;
+ case 19:
+ var value = /** @type {!Array} */ (reader.readPackedUint64());
+ msg.setOutgoingChanIdsList(value);
+ break;
+ case 14:
+ var value = /** @type {!Uint8Array} */ (reader.readBytes());
+ msg.setLastHopPubkey(value);
+ break;
+ case 9:
+ var value = /** @type {number} */ (reader.readInt32());
+ msg.setCltvLimit(value);
+ break;
+ case 10:
+ var value = new lndrpc_pb.RouteHint;
+ reader.readMessage(value,lndrpc_pb.RouteHint.deserializeBinaryFromReader);
+ msg.addRouteHints(value);
+ break;
+ case 11:
+ var value = msg.getDestCustomRecordsMap();
+ reader.readMessage(value, function(message, reader) {
+ jspb.Map.deserializeBinary(message, reader, jspb.BinaryReader.prototype.readUint64, jspb.BinaryReader.prototype.readBytes, null, 0);
+ });
+ break;
+ case 15:
+ var value = /** @type {boolean} */ (reader.readBool());
+ msg.setAllowSelfPayment(value);
+ break;
+ case 16:
+ var value = /** @type {!Array} */ (reader.readPackedEnum());
+ msg.setDestFeaturesList(value);
+ break;
+ case 17:
+ var value = /** @type {number} */ (reader.readUint32());
+ msg.setMaxParts(value);
+ break;
+ case 18:
+ var value = /** @type {boolean} */ (reader.readBool());
+ msg.setNoInflightUpdates(value);
+ break;
+ default:
+ reader.skipField();
+ break;
+ }
+ }
+ return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.routerrpc.SendPaymentRequest.prototype.serializeBinary = function() {
+ var writer = new jspb.BinaryWriter();
+ proto.routerrpc.SendPaymentRequest.serializeBinaryToWriter(this, writer);
+ return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.routerrpc.SendPaymentRequest} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.routerrpc.SendPaymentRequest.serializeBinaryToWriter = function(message, writer) {
+ var f = undefined;
+ f = message.getDest_asU8();
+ if (f.length > 0) {
+ writer.writeBytes(
+ 1,
+ f
+ );
+ }
+ f = message.getAmt();
+ if (f !== 0) {
+ writer.writeInt64(
+ 2,
+ f
+ );
+ }
+ f = message.getAmtMsat();
+ if (f !== 0) {
+ writer.writeInt64(
+ 12,
+ f
+ );
+ }
+ f = message.getPaymentHash_asU8();
+ if (f.length > 0) {
+ writer.writeBytes(
+ 3,
+ f
+ );
+ }
+ f = message.getFinalCltvDelta();
+ if (f !== 0) {
+ writer.writeInt32(
+ 4,
+ f
+ );
+ }
+ f = message.getPaymentRequest();
+ if (f.length > 0) {
+ writer.writeString(
+ 5,
+ f
+ );
+ }
+ f = message.getTimeoutSeconds();
+ if (f !== 0) {
+ writer.writeInt32(
+ 6,
+ f
+ );
+ }
+ f = message.getFeeLimitSat();
+ if (f !== 0) {
+ writer.writeInt64(
+ 7,
+ f
+ );
+ }
+ f = message.getFeeLimitMsat();
+ if (f !== 0) {
+ writer.writeInt64(
+ 13,
+ f
+ );
+ }
+ f = message.getOutgoingChanId();
+ if (parseInt(f, 10) !== 0) {
+ writer.writeUint64String(
+ 8,
+ f
+ );
+ }
+ f = message.getOutgoingChanIdsList();
+ if (f.length > 0) {
+ writer.writePackedUint64(
+ 19,
+ f
+ );
+ }
+ f = message.getLastHopPubkey_asU8();
+ if (f.length > 0) {
+ writer.writeBytes(
+ 14,
+ f
+ );
+ }
+ f = message.getCltvLimit();
+ if (f !== 0) {
+ writer.writeInt32(
+ 9,
+ f
+ );
+ }
+ f = message.getRouteHintsList();
+ if (f.length > 0) {
+ writer.writeRepeatedMessage(
+ 10,
+ f,
+ lndrpc_pb.RouteHint.serializeBinaryToWriter
+ );
+ }
+ f = message.getDestCustomRecordsMap(true);
+ if (f && f.getLength() > 0) {
+ f.serializeBinary(11, writer, jspb.BinaryWriter.prototype.writeUint64, jspb.BinaryWriter.prototype.writeBytes);
+ }
+ f = message.getAllowSelfPayment();
+ if (f) {
+ writer.writeBool(
+ 15,
+ f
+ );
+ }
+ f = message.getDestFeaturesList();
+ if (f.length > 0) {
+ writer.writePackedEnum(
+ 16,
+ f
+ );
+ }
+ f = message.getMaxParts();
+ if (f !== 0) {
+ writer.writeUint32(
+ 17,
+ f
+ );
+ }
+ f = message.getNoInflightUpdates();
+ if (f) {
+ writer.writeBool(
+ 18,
+ f
+ );
+ }
+};
+
+
+/**
+ * optional bytes dest = 1;
+ * @return {!(string|Uint8Array)}
+ */
+proto.routerrpc.SendPaymentRequest.prototype.getDest = function() {
+ return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
+};
+
+
+/**
+ * optional bytes dest = 1;
+ * This is a type-conversion wrapper around `getDest()`
+ * @return {string}
+ */
+proto.routerrpc.SendPaymentRequest.prototype.getDest_asB64 = function() {
+ return /** @type {string} */ (jspb.Message.bytesAsB64(
+ this.getDest()));
+};
+
+
+/**
+ * optional bytes dest = 1;
+ * Note that Uint8Array is not supported on all browsers.
+ * @see http://caniuse.com/Uint8Array
+ * This is a type-conversion wrapper around `getDest()`
+ * @return {!Uint8Array}
+ */
+proto.routerrpc.SendPaymentRequest.prototype.getDest_asU8 = function() {
+ return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8(
+ this.getDest()));
+};
+
+
+/** @param {!(string|Uint8Array)} value */
+proto.routerrpc.SendPaymentRequest.prototype.setDest = function(value) {
+ jspb.Message.setProto3BytesField(this, 1, value);
+};
+
+
+/**
+ * optional int64 amt = 2;
+ * @return {number}
+ */
+proto.routerrpc.SendPaymentRequest.prototype.getAmt = function() {
+ return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));
+};
+
+
+/** @param {number} value */
+proto.routerrpc.SendPaymentRequest.prototype.setAmt = function(value) {
+ jspb.Message.setProto3IntField(this, 2, value);
+};
+
+
+/**
+ * optional int64 amt_msat = 12;
+ * @return {number}
+ */
+proto.routerrpc.SendPaymentRequest.prototype.getAmtMsat = function() {
+ return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 12, 0));
+};
+
+
+/** @param {number} value */
+proto.routerrpc.SendPaymentRequest.prototype.setAmtMsat = function(value) {
+ jspb.Message.setProto3IntField(this, 12, value);
+};
+
+
+/**
+ * optional bytes payment_hash = 3;
+ * @return {!(string|Uint8Array)}
+ */
+proto.routerrpc.SendPaymentRequest.prototype.getPaymentHash = function() {
+ return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 3, ""));
+};
+
+
+/**
+ * optional bytes payment_hash = 3;
+ * This is a type-conversion wrapper around `getPaymentHash()`
+ * @return {string}
+ */
+proto.routerrpc.SendPaymentRequest.prototype.getPaymentHash_asB64 = function() {
+ return /** @type {string} */ (jspb.Message.bytesAsB64(
+ this.getPaymentHash()));
+};
+
+
+/**
+ * optional bytes payment_hash = 3;
+ * Note that Uint8Array is not supported on all browsers.
+ * @see http://caniuse.com/Uint8Array
+ * This is a type-conversion wrapper around `getPaymentHash()`
+ * @return {!Uint8Array}
+ */
+proto.routerrpc.SendPaymentRequest.prototype.getPaymentHash_asU8 = function() {
+ return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8(
+ this.getPaymentHash()));
+};
+
+
+/** @param {!(string|Uint8Array)} value */
+proto.routerrpc.SendPaymentRequest.prototype.setPaymentHash = function(value) {
+ jspb.Message.setProto3BytesField(this, 3, value);
+};
+
+
+/**
+ * optional int32 final_cltv_delta = 4;
+ * @return {number}
+ */
+proto.routerrpc.SendPaymentRequest.prototype.getFinalCltvDelta = function() {
+ return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0));
+};
+
+
+/** @param {number} value */
+proto.routerrpc.SendPaymentRequest.prototype.setFinalCltvDelta = function(value) {
+ jspb.Message.setProto3IntField(this, 4, value);
+};
+
+
+/**
+ * optional string payment_request = 5;
+ * @return {string}
+ */
+proto.routerrpc.SendPaymentRequest.prototype.getPaymentRequest = function() {
+ return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 5, ""));
+};
+
+
+/** @param {string} value */
+proto.routerrpc.SendPaymentRequest.prototype.setPaymentRequest = function(value) {
+ jspb.Message.setProto3StringField(this, 5, value);
+};
+
+
+/**
+ * optional int32 timeout_seconds = 6;
+ * @return {number}
+ */
+proto.routerrpc.SendPaymentRequest.prototype.getTimeoutSeconds = function() {
+ return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 6, 0));
+};
+
+
+/** @param {number} value */
+proto.routerrpc.SendPaymentRequest.prototype.setTimeoutSeconds = function(value) {
+ jspb.Message.setProto3IntField(this, 6, value);
+};
+
+
+/**
+ * optional int64 fee_limit_sat = 7;
+ * @return {number}
+ */
+proto.routerrpc.SendPaymentRequest.prototype.getFeeLimitSat = function() {
+ return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 7, 0));
+};
+
+
+/** @param {number} value */
+proto.routerrpc.SendPaymentRequest.prototype.setFeeLimitSat = function(value) {
+ jspb.Message.setProto3IntField(this, 7, value);
+};
+
+
+/**
+ * optional int64 fee_limit_msat = 13;
+ * @return {number}
+ */
+proto.routerrpc.SendPaymentRequest.prototype.getFeeLimitMsat = function() {
+ return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 13, 0));
+};
+
+
+/** @param {number} value */
+proto.routerrpc.SendPaymentRequest.prototype.setFeeLimitMsat = function(value) {
+ jspb.Message.setProto3IntField(this, 13, value);
+};
+
+
+/**
+ * optional uint64 outgoing_chan_id = 8;
+ * @return {string}
+ */
+proto.routerrpc.SendPaymentRequest.prototype.getOutgoingChanId = function() {
+ return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 8, "0"));
+};
+
+
+/** @param {string} value */
+proto.routerrpc.SendPaymentRequest.prototype.setOutgoingChanId = function(value) {
+ jspb.Message.setProto3StringIntField(this, 8, value);
+};
+
+
+/**
+ * repeated uint64 outgoing_chan_ids = 19;
+ * @return {!Array}
+ */
+proto.routerrpc.SendPaymentRequest.prototype.getOutgoingChanIdsList = function() {
+ return /** @type {!Array} */ (jspb.Message.getRepeatedField(this, 19));
+};
+
+
+/** @param {!Array} value */
+proto.routerrpc.SendPaymentRequest.prototype.setOutgoingChanIdsList = function(value) {
+ jspb.Message.setField(this, 19, value || []);
+};
+
+
+/**
+ * @param {number} value
+ * @param {number=} opt_index
+ */
+proto.routerrpc.SendPaymentRequest.prototype.addOutgoingChanIds = function(value, opt_index) {
+ jspb.Message.addToRepeatedField(this, 19, value, opt_index);
+};
+
+
+proto.routerrpc.SendPaymentRequest.prototype.clearOutgoingChanIdsList = function() {
+ this.setOutgoingChanIdsList([]);
+};
+
+
+/**
+ * optional bytes last_hop_pubkey = 14;
+ * @return {!(string|Uint8Array)}
+ */
+proto.routerrpc.SendPaymentRequest.prototype.getLastHopPubkey = function() {
+ return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 14, ""));
+};
+
+
+/**
+ * optional bytes last_hop_pubkey = 14;
+ * This is a type-conversion wrapper around `getLastHopPubkey()`
+ * @return {string}
+ */
+proto.routerrpc.SendPaymentRequest.prototype.getLastHopPubkey_asB64 = function() {
+ return /** @type {string} */ (jspb.Message.bytesAsB64(
+ this.getLastHopPubkey()));
+};
+
+
+/**
+ * optional bytes last_hop_pubkey = 14;
+ * Note that Uint8Array is not supported on all browsers.
+ * @see http://caniuse.com/Uint8Array
+ * This is a type-conversion wrapper around `getLastHopPubkey()`
+ * @return {!Uint8Array}
+ */
+proto.routerrpc.SendPaymentRequest.prototype.getLastHopPubkey_asU8 = function() {
+ return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8(
+ this.getLastHopPubkey()));
+};
+
+
+/** @param {!(string|Uint8Array)} value */
+proto.routerrpc.SendPaymentRequest.prototype.setLastHopPubkey = function(value) {
+ jspb.Message.setProto3BytesField(this, 14, value);
+};
+
+
+/**
+ * optional int32 cltv_limit = 9;
+ * @return {number}
+ */
+proto.routerrpc.SendPaymentRequest.prototype.getCltvLimit = function() {
+ return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 9, 0));
+};
+
+
+/** @param {number} value */
+proto.routerrpc.SendPaymentRequest.prototype.setCltvLimit = function(value) {
+ jspb.Message.setProto3IntField(this, 9, value);
+};
+
+
+/**
+ * repeated lnrpc.RouteHint route_hints = 10;
+ * @return {!Array}
+ */
+proto.routerrpc.SendPaymentRequest.prototype.getRouteHintsList = function() {
+ return /** @type{!Array} */ (
+ jspb.Message.getRepeatedWrapperField(this, lndrpc_pb.RouteHint, 10));
+};
+
+
+/** @param {!Array} value */
+proto.routerrpc.SendPaymentRequest.prototype.setRouteHintsList = function(value) {
+ jspb.Message.setRepeatedWrapperField(this, 10, value);
+};
+
+
+/**
+ * @param {!proto.lnrpc.RouteHint=} opt_value
+ * @param {number=} opt_index
+ * @return {!proto.lnrpc.RouteHint}
+ */
+proto.routerrpc.SendPaymentRequest.prototype.addRouteHints = function(opt_value, opt_index) {
+ return jspb.Message.addToRepeatedWrapperField(this, 10, opt_value, proto.lnrpc.RouteHint, opt_index);
+};
+
+
+proto.routerrpc.SendPaymentRequest.prototype.clearRouteHintsList = function() {
+ this.setRouteHintsList([]);
+};
+
+
+/**
+ * map