755 lines
28 KiB
TypeScript
755 lines
28 KiB
TypeScript
import { NativeModules, NativeEventEmitter } from 'react-native';
|
|
|
|
import LNC from '../zeus_modules/@lightninglabs/lnc-rn';
|
|
import { lnrpc, walletrpc } from '../zeus_modules/@lightninglabs/lnc-core';
|
|
|
|
import { settingsStore, nodeInfoStore } from '../stores/Stores';
|
|
import CredentialStore from './LNC/credentialStore';
|
|
|
|
import OpenChannelRequest from '../models/OpenChannelRequest';
|
|
|
|
import Base64Utils from '../utils/Base64Utils';
|
|
import { snakeize } from '../utils/DataFormatUtils';
|
|
import VersionUtils from '../utils/VersionUtils';
|
|
|
|
import { Hash as sha256Hash } from 'fast-sha256';
|
|
import BigNumber from 'bignumber.js';
|
|
|
|
const ADDRESS_TYPES = [
|
|
'WITNESS_PUBKEY_HASH',
|
|
'NESTED_PUBKEY_HASH',
|
|
'UNUSED_WITNESS_PUBKEY_HASH',
|
|
'UNUSED_NESTED_PUBKEY_HASH',
|
|
'TAPROOT_PUBKEY',
|
|
'UNUSED_TAPROOT_PUBKEY'
|
|
];
|
|
|
|
const NEXT_ADDR_MAP: any = {
|
|
WITNESS_PUBKEY_HASH: 0,
|
|
NESTED_PUBKEY_HASH: 1,
|
|
UNUSED_WITNESS_PUBKEY_HASH: 2,
|
|
UNUSED_NESTED_PUBKEY_HASH: 3,
|
|
TAPROOT_PUBKEY: 4,
|
|
UNUSED_TAPROOT_PUBKEY: 5
|
|
};
|
|
|
|
export default class LightningNodeConnect {
|
|
lnc: any;
|
|
listener: any;
|
|
|
|
permOpenChannel: boolean;
|
|
permSendCoins: boolean;
|
|
permSendLN: boolean;
|
|
permNewAddress: boolean;
|
|
permImportAccount: boolean;
|
|
permForwardingHistory: boolean;
|
|
permSignMessage: boolean;
|
|
|
|
initLNC = async () => {
|
|
const { pairingPhrase, mailboxServer, customMailboxServer } =
|
|
settingsStore;
|
|
|
|
this.lnc = new LNC({
|
|
credentialStore: await new CredentialStore(
|
|
pairingPhrase
|
|
).initialize()
|
|
});
|
|
|
|
this.lnc.credentials.pairingPhrase = pairingPhrase;
|
|
this.lnc.credentials.serverHost =
|
|
mailboxServer === 'custom-defined'
|
|
? customMailboxServer
|
|
: mailboxServer;
|
|
|
|
return await this.lnc.credentials.load(pairingPhrase);
|
|
};
|
|
|
|
connect = async () => await this.lnc.connect();
|
|
checkPerms = async () => {
|
|
// ZEUS-3642: we are temporarily returning all perms
|
|
// as true until resolved
|
|
// https://github.com/ZeusLN/zeus/issues/3642
|
|
//
|
|
// this.permOpenChannel = await this.lnc.hasPerms(
|
|
// 'lnrpc.Lightning.OpenChannel'
|
|
// );
|
|
// this.permSendCoins = await this.lnc.hasPerms(
|
|
// 'lnrpc.Lightning.SendCoins'
|
|
// );
|
|
// this.permSendLN = await this.lnc.hasPerms(
|
|
// 'routerrpc.Router.SendPaymentV2'
|
|
// );
|
|
// this.permNewAddress = await this.lnc.hasPerms(
|
|
// 'lnrpc.Lightning.NewAddress'
|
|
// );
|
|
// this.permImportAccount = await this.lnc.hasPerms(
|
|
// 'walletrpc.WalletKit.ImportAccount'
|
|
// );
|
|
// this.permForwardingHistory = await this.lnc.hasPerms(
|
|
// 'lnrpc.Lightning.ForwardingHistory'
|
|
// );
|
|
// this.permSignMessage = await this.lnc.hasPerms(
|
|
// 'signrpc.Signer.SignMessage'
|
|
// );
|
|
this.permOpenChannel = true;
|
|
this.permSendCoins = true;
|
|
this.permSendLN = true;
|
|
this.permNewAddress = true;
|
|
this.permImportAccount = true;
|
|
this.permForwardingHistory = true;
|
|
this.permSignMessage = true;
|
|
};
|
|
isConnected = async () => await this.lnc.isConnected();
|
|
disconnect = () => this.lnc && this.lnc.disconnect();
|
|
|
|
getTransactions = async () =>
|
|
await this.lnc.lnd.lightning
|
|
.getTransactions({})
|
|
.then((data: lnrpc.TransactionDetails) => {
|
|
const formatted = snakeize(data);
|
|
return {
|
|
transactions: formatted.transactions.reverse()
|
|
};
|
|
});
|
|
getChannels = async () =>
|
|
await this.lnc.lnd.lightning
|
|
.listChannels({})
|
|
.then((data: lnrpc.ListChannelsResponse) => snakeize(data));
|
|
getPendingChannels = async () =>
|
|
await this.lnc.lnd.lightning
|
|
.pendingChannels({})
|
|
.then((data: lnrpc.PendingChannelsResponse) => snakeize(data));
|
|
getClosedChannels = async () =>
|
|
await this.lnc.lnd.lightning
|
|
.closedChannels({})
|
|
.then((data: lnrpc.ClosedChannelsResponse) => snakeize(data));
|
|
getChannelInfo = async (chanId: string) => {
|
|
const request: lnrpc.ChanInfoRequest = { chanId, chanPoint: '' };
|
|
return await this.lnc.lnd.lightning
|
|
.getChanInfo(request)
|
|
.then((data: lnrpc.ChannelEdge) => snakeize(data));
|
|
};
|
|
getBlockchainBalance = async (req: lnrpc.WalletBalanceRequest) =>
|
|
await this.lnc.lnd.lightning
|
|
.walletBalance(req)
|
|
.then((data: lnrpc.WalletBalanceResponse) => snakeize(data));
|
|
getLightningBalance = async (req: lnrpc.ChannelBalanceRequest) =>
|
|
await this.lnc.lnd.lightning
|
|
.channelBalance(req)
|
|
.then((data: lnrpc.ChannelBalanceResponse) => snakeize(data));
|
|
sendCoins = async (data: any) =>
|
|
await this.lnc.lnd.lightning
|
|
.sendCoins({
|
|
addr: data.addr,
|
|
sat_per_vbyte: data.sat_per_vbyte,
|
|
amount: data.amount,
|
|
spend_unconfirmed: data.spend_unconfirmed,
|
|
send_all: data.send_all,
|
|
outpoints: data.outpoints
|
|
})
|
|
.then((data: lnrpc.SendCoinsResponse) => snakeize(data));
|
|
sendCustomMessage = async (data: any) =>
|
|
await this.lnc.lnd.lightning
|
|
.sendCustomMessage({
|
|
peer: Base64Utils.hexToBase64(data.peer),
|
|
type: data.type,
|
|
data: Base64Utils.hexToBase64(data.data)
|
|
})
|
|
.then((data: lnrpc.SendCustomMessageResponse) => snakeize(data));
|
|
subscribeCustomMessages = () =>
|
|
this.lnc.lnd.lightning.subscribeCustomMessages({});
|
|
getMyNodeInfo = async () =>
|
|
await this.lnc.lnd.lightning
|
|
.getInfo({})
|
|
.then((data: lnrpc.GetInfoResponse) => snakeize(data));
|
|
getNetworkInfo = async () =>
|
|
await this.lnc.lnd.lightning
|
|
.getNetworkInfo({})
|
|
.then((data: lnrpc.NetworkInfo) => snakeize(data));
|
|
getInvoices = async (
|
|
params: { limit?: number; reversed?: boolean } = {
|
|
limit: 500,
|
|
reversed: true
|
|
}
|
|
) =>
|
|
await this.lnc.lnd.lightning
|
|
.listInvoices({
|
|
reversed:
|
|
params?.reversed !== undefined ? params.reversed : true,
|
|
...(params?.limit && {
|
|
num_max_invoices: params.limit
|
|
})
|
|
})
|
|
.then((data: lnrpc.ListInvoiceResponse) => snakeize(data));
|
|
createInvoice = async (data: any) =>
|
|
await this.lnc.lnd.lightning
|
|
.addInvoice({
|
|
memo: data.memo,
|
|
value_msat: data.value_msat || Number(data.value) * 1000,
|
|
expiry: data.expiry_seconds,
|
|
is_amp: data.is_amp,
|
|
is_blinded: data.is_blinded,
|
|
private: data.private,
|
|
r_preimage: data.preimage
|
|
? Base64Utils.hexToBase64(data.preimage)
|
|
: undefined,
|
|
route_hints: data.route_hints
|
|
})
|
|
.then((data: lnrpc.AddInvoiceResponse) => snakeize(data));
|
|
getPayments = async (
|
|
params: {
|
|
maxPayments?: number;
|
|
reversed?: boolean;
|
|
} = {
|
|
maxPayments: 500,
|
|
reversed: true
|
|
}
|
|
) =>
|
|
await this.lnc.lnd.lightning
|
|
.listPayments({
|
|
include_incomplete: true,
|
|
...(params?.maxPayments && {
|
|
max_payments: params.maxPayments
|
|
}),
|
|
reversed:
|
|
params?.reversed !== undefined ? params.reversed : true
|
|
})
|
|
.then((data: lnrpc.ListPaymentsResponse) => snakeize(data));
|
|
getNewAddress = async (data: any) =>
|
|
await this.lnc.lnd.lightning
|
|
.newAddress({
|
|
type: ADDRESS_TYPES[data.type] || data.type,
|
|
account: data.account || 'default'
|
|
})
|
|
.then((data: walletrpc.AddrRequest) => snakeize(data));
|
|
getNewChangeAddress = async (data: any) =>
|
|
await this.lnc.lnd.walletKit
|
|
.nextAddr({
|
|
type: NEXT_ADDR_MAP[data.type],
|
|
account: data.account || 'default',
|
|
change: true
|
|
})
|
|
.then((data: walletrpc.AddrResponse) => snakeize(data));
|
|
openChannelSync = async (data: OpenChannelRequest) => {
|
|
let request: any = {
|
|
private: data.privateChannel,
|
|
scid_alias: data.scidAlias,
|
|
local_funding_amount: data.local_funding_amount || 0,
|
|
min_confs: data.min_confs,
|
|
node_pubkey_string: data.node_pubkey_string,
|
|
sat_per_vbyte: data.sat_per_vbyte,
|
|
spend_unconfirmed: data.spend_unconfirmed,
|
|
close_address: data.close_address
|
|
};
|
|
|
|
if (data.fundMax) {
|
|
request.fund_max = true;
|
|
delete request.local_funding_amount;
|
|
}
|
|
|
|
if (data.simpleTaprootChannel) {
|
|
request.commitment_type = lnrpc.CommitmentType['SIMPLE_TAPROOT'];
|
|
}
|
|
|
|
if (data.utxos && data.utxos.length > 0) {
|
|
request.outpoints = data.utxos.map((utxo: string) => {
|
|
const [txid_str, output_index] = utxo.split(':');
|
|
return {
|
|
txid_str,
|
|
output_index: Number(output_index)
|
|
};
|
|
});
|
|
}
|
|
return await this.lnc.lnd.lightning
|
|
.openChannelSync(request)
|
|
.then((data: lnrpc.ChannelPoint) => snakeize(data));
|
|
};
|
|
|
|
openChannelStream = (data: OpenChannelRequest) => {
|
|
let request: any = {
|
|
private: data.privateChannel || false,
|
|
scid_alias: data.scidAlias,
|
|
local_funding_amount: data.local_funding_amount,
|
|
min_confs: data.min_confs,
|
|
node_pubkey: Base64Utils.hexToBase64(data.node_pubkey_string),
|
|
sat_per_vbyte: !data.funding_shim ? data.sat_per_vbyte : undefined,
|
|
spend_unconfirmed: data.spend_unconfirmed,
|
|
funding_shim: data.funding_shim
|
|
};
|
|
|
|
if (data.fundMax) {
|
|
request.fund_max = true;
|
|
}
|
|
|
|
if (data.simpleTaprootChannel) {
|
|
request.commitment_type = lnrpc.CommitmentType['SIMPLE_TAPROOT'];
|
|
}
|
|
|
|
if (data.utxos && data.utxos.length > 0) {
|
|
request.outpoints = data.utxos.map((utxo: string) => {
|
|
const [txid_str, output_index] = utxo.split(':');
|
|
return {
|
|
txid_str,
|
|
output_index: Number(output_index)
|
|
};
|
|
});
|
|
}
|
|
|
|
if (data.funding_shim) {
|
|
request.funding_shim = data.funding_shim;
|
|
delete request.sat_per_vbyte;
|
|
}
|
|
|
|
const streamingCall = this.lnc.lnd.lightning.openChannel(request);
|
|
|
|
const { LncModule } = NativeModules;
|
|
const eventEmitter = new NativeEventEmitter(LncModule);
|
|
return new Promise((resolve, reject) => {
|
|
this.listener = eventEmitter.addListener(
|
|
streamingCall,
|
|
(event: any) => {
|
|
if (event.result && event.result !== 'EOF') {
|
|
let result;
|
|
try {
|
|
result = JSON.parse(event.result);
|
|
|
|
resolve({ result });
|
|
this.listener.remove();
|
|
} catch (e) {
|
|
try {
|
|
result = JSON.parse(event);
|
|
} catch (e2) {
|
|
result = event.result || event;
|
|
}
|
|
|
|
reject(result);
|
|
this.listener.remove();
|
|
}
|
|
}
|
|
}
|
|
);
|
|
});
|
|
};
|
|
connectPeer = async (data: any) =>
|
|
await this.lnc.lnd.lightning
|
|
.connectPeer(data)
|
|
.then((data: lnrpc.ConnectPeerRequest) => snakeize(data));
|
|
decodePaymentRequest = async (urlParams?: Array<string>) =>
|
|
await this.lnc.lnd.lightning
|
|
.decodePayReq({ pay_req: urlParams && urlParams[0] })
|
|
.then((data: lnrpc.PayReq) => snakeize(data));
|
|
payLightningInvoice = (data: any) => {
|
|
if (data.pubkey) delete data.pubkey;
|
|
return this.lnc.lnd.router.sendPaymentV2({
|
|
...data,
|
|
allow_self_payment: true
|
|
});
|
|
};
|
|
closeChannel = async (urlParams?: Array<string>) => {
|
|
let params: any = {
|
|
channel_point: {
|
|
funding_txid_str: urlParams && urlParams[0],
|
|
output_index: urlParams && urlParams[1] && Number(urlParams[1])
|
|
},
|
|
force: urlParams && urlParams[2]
|
|
};
|
|
|
|
if (urlParams && urlParams[3] && !urlParams[2]) {
|
|
params.sat_per_vbyte = Number(urlParams[3]);
|
|
}
|
|
|
|
if (urlParams && urlParams[4]) {
|
|
params.delivery_address = urlParams[4];
|
|
}
|
|
|
|
return this.lnc.lnd.lightning.closeChannel(params);
|
|
};
|
|
abandonChannel = async (
|
|
urlParams?: Array<string | boolean | undefined>
|
|
) => {
|
|
const fundingTxidStr =
|
|
urlParams && typeof urlParams[0] === 'string'
|
|
? urlParams[0]
|
|
: undefined;
|
|
const outputIndex =
|
|
urlParams && typeof urlParams[1] === 'string'
|
|
? Number(urlParams[1])
|
|
: 0;
|
|
|
|
const params: any = {
|
|
channelPoint: {
|
|
fundingTxidStr,
|
|
fundingTxidBytes: undefined,
|
|
outputIndex
|
|
}
|
|
};
|
|
|
|
// Only include boolean parameters if they are explicitly set (not undefined)
|
|
if (urlParams && urlParams[2]) {
|
|
params.pendingFundingShimOnly = Boolean(urlParams[2]);
|
|
}
|
|
|
|
if (urlParams && urlParams[3]) {
|
|
params.iKnowWhatIAmDoing = Boolean(urlParams[3]);
|
|
}
|
|
|
|
return this.lnc.lnd.lightning.abandonChannel(params);
|
|
};
|
|
getNodeInfo = async (urlParams?: Array<string>) =>
|
|
await this.lnc.lnd.lightning
|
|
.getNodeInfo({ pub_key: urlParams && urlParams[0] })
|
|
.then((data: lnrpc.NodeInfo) => snakeize(data));
|
|
getFees = async () =>
|
|
await this.lnc.lnd.lightning
|
|
.feeReport({})
|
|
.then((data: lnrpc.FeeReportResponse) => snakeize(data));
|
|
setFees = async (data: any) => {
|
|
// handle commas in place of decimals
|
|
const base_fee_msat = data.base_fee_msat.replace(/,/g, '.');
|
|
const fee_rate = data.fee_rate.replace(/,/g, '.');
|
|
|
|
let params;
|
|
|
|
if (data.global) {
|
|
params = {
|
|
base_fee_msat,
|
|
fee_rate: `${Number(fee_rate) / 100}`,
|
|
...(this.supportInboundFees() && {
|
|
inboundFee: {
|
|
...(data.base_fee_msat_inbound !== '' && {
|
|
base_fee_msat: data.base_fee_msat_inbound
|
|
}),
|
|
...(data.fee_rate_inbound !== '' &&
|
|
data.fee_rate_inbound !== undefined && {
|
|
fee_rate_ppm: `${new BigNumber(
|
|
data.fee_rate_inbound
|
|
)
|
|
.multipliedBy(10000)
|
|
.toFixed(0)}`
|
|
})
|
|
}
|
|
}),
|
|
|
|
global: true,
|
|
time_lock_delta: Number(data.time_lock_delta),
|
|
min_htlc_msat: data.min_htlc
|
|
? `${Number(data.min_htlc) * 1000}`
|
|
: null,
|
|
max_htlc_msat: data.max_htlc
|
|
? `${Number(data.max_htlc) * 1000}`
|
|
: null,
|
|
min_htlc_msat_specified: data.min_htlc ? true : false
|
|
};
|
|
} else {
|
|
params = {
|
|
base_fee_msat,
|
|
fee_rate: `${Number(fee_rate) / 100}`,
|
|
...(this.supportInboundFees() && {
|
|
inboundFee: {
|
|
...(data.base_fee_msat_inbound !== '' && {
|
|
base_fee_msat: data.base_fee_msat_inbound
|
|
}),
|
|
...(data.fee_rate_inbound !== '' &&
|
|
data.fee_rate_inbound !== undefined && {
|
|
fee_rate_ppm: `${new BigNumber(
|
|
data.fee_rate_inbound
|
|
)
|
|
.multipliedBy(10000)
|
|
.toFixed(0)}`
|
|
})
|
|
}
|
|
}),
|
|
chan_point: {
|
|
funding_txid_str: data.chan_point.funding_txid_str,
|
|
output_index: data.chan_point.output_index
|
|
},
|
|
time_lock_delta: Number(data.time_lock_delta),
|
|
min_htlc_msat: data.min_htlc
|
|
? `${Number(data.min_htlc) * 1000}`
|
|
: null,
|
|
max_htlc_msat: data.max_htlc
|
|
? `${Number(data.max_htlc) * 1000}`
|
|
: null,
|
|
min_htlc_msat_specified: data.min_htlc ? true : false
|
|
};
|
|
}
|
|
|
|
return await this.lnc.lnd.lightning
|
|
.updateChannelPolicy(params)
|
|
.then((data: lnrpc.PolicyUpdateResponse) => snakeize(data));
|
|
};
|
|
getRoutes = async (urlParams?: Array<string>) =>
|
|
await this.lnc.lnd.lightning
|
|
.queryRoutes({
|
|
pub_key: urlParams && urlParams[0],
|
|
amt: urlParams && urlParams[1] && Number(urlParams[1])
|
|
})
|
|
.then((data: lnrpc.QueryRoutesResponse) => snakeize(data));
|
|
getForwardingHistory = async (
|
|
hours = 24,
|
|
chanIdIn?: string,
|
|
chanIdOut?: string
|
|
) => {
|
|
const req: any = {
|
|
numMaxEvents: 10000000,
|
|
startTime: Math.round(
|
|
new Date(Date.now() - hours * 60 * 60 * 1000).getTime() / 1000
|
|
).toString(),
|
|
endTime: Math.round(new Date().getTime() / 1000).toString(),
|
|
indexOffset: 0
|
|
};
|
|
if (this.supports('v0.20.0')) {
|
|
if (chanIdIn) {
|
|
req.incomingChanIds = [chanIdIn];
|
|
}
|
|
if (chanIdOut) {
|
|
req.outgoingChanIds = [chanIdOut];
|
|
}
|
|
}
|
|
return await this.lnc.lnd.lightning
|
|
.forwardingHistory(req)
|
|
.then((data: lnrpc.ForwardingHistoryResponse) => snakeize(data));
|
|
};
|
|
// Coin Control
|
|
fundPsbt = async (req: walletrpc.FundPsbtRequest) =>
|
|
await this.lnc.lnd.walletKit
|
|
.fundPsbt(req)
|
|
.then((data: walletrpc.FundPsbtResponse) => snakeize(data));
|
|
signPsbt = async (req: walletrpc.SignPsbtRequest) =>
|
|
await this.lnc.lnd.walletKit
|
|
.signPsbt(req)
|
|
.then((data: walletrpc.SignPsbtResponse) => snakeize(data));
|
|
finalizePsbt = async (req: walletrpc.FinalizePsbtRequest) =>
|
|
await this.lnc.lnd.walletKit
|
|
.finalizePsbt(req)
|
|
.then((data: walletrpc.FinalizePsbtResponse) => snakeize(data));
|
|
publishTransaction = async (req: any) => {
|
|
if (req.tx_hex) req.tx_hex = Base64Utils.hexToBase64(req.tx_hex);
|
|
return await this.lnc.lnd.walletKit
|
|
.publishTransaction(req)
|
|
.then((data: walletrpc.PublishResponse) => snakeize(data));
|
|
};
|
|
fundingStateStep = async (req: any) => {
|
|
// Finalize
|
|
if (req.psbt_finalize?.final_raw_tx)
|
|
req.psbt_finalize.final_raw_tx = Base64Utils.hexToBase64(
|
|
req.psbt_finalize.final_raw_tx
|
|
);
|
|
|
|
return await this.lnc.lnd.lightning
|
|
.fundingStateStep(req)
|
|
.then((data: lnrpc.FundingStateStepResp) => snakeize(data));
|
|
};
|
|
getUTXOs = async (req: walletrpc.ListUnspentRequest) =>
|
|
await this.lnc.lnd.walletKit
|
|
.listUnspent(req)
|
|
.then((data: walletrpc.ListUnspentResponse) => snakeize(data));
|
|
bumpFee = async (req: walletrpc.BumpFeeRequest) =>
|
|
await this.lnc.lnd.walletKit
|
|
.bumpFee(snakeize(req))
|
|
.then((data: walletrpc.BumpFeeResponse) => snakeize(data));
|
|
bumpForceCloseFee = async (req: walletrpc.BumpForceCloseFeeRequest) =>
|
|
await this.lnc.lnd.walletKit
|
|
.bumpForceCloseFee(snakeize(req))
|
|
.then((data: walletrpc.BumpForceCloseFeeResponse) =>
|
|
snakeize(data)
|
|
);
|
|
listAccounts = async () =>
|
|
await this.lnc.lnd.walletKit
|
|
.listAccounts({})
|
|
.then((data: walletrpc.ListAccountsResponse) => snakeize(data));
|
|
listAddresses = async () =>
|
|
await this.lnc.lnd.walletKit
|
|
.listAddresses({})
|
|
.then((data: walletrpc.ListAddressesResponse) => snakeize(data));
|
|
importAccount = async (req: walletrpc.ImportAccountRequest) =>
|
|
await this.lnc.lnd.walletKit
|
|
.importAccount(req)
|
|
.then((data: walletrpc.ImportAccountResponse) => snakeize(data));
|
|
signMessage = async (message: string) =>
|
|
await this.lnc.lnd.lightning
|
|
.signMessage({ msg: Base64Utils.utf8ToBase64(message) })
|
|
.then((data: lnrpc.SignMessageResponse) => snakeize(data));
|
|
verifyMessage = async (req: lnrpc.VerifyMessageRequest) =>
|
|
await this.lnc.lnd.lightning
|
|
.verifyMessage({
|
|
msg:
|
|
typeof req.msg === 'string'
|
|
? Base64Utils.utf8ToBase64(req.msg)
|
|
: req.msg,
|
|
signature: req.signature
|
|
})
|
|
.then((data: lnrpc.VerifyMessageResponse) => snakeize(data));
|
|
signMessageWithAddr = async (msg: string, addr: string) =>
|
|
await this.lnc.lnd.walletKit
|
|
.signMessageWithAddr({
|
|
msg:
|
|
typeof msg === 'string'
|
|
? Base64Utils.utf8ToBase64(msg)
|
|
: Base64Utils.bytesToBase64(msg as Uint8Array),
|
|
addr
|
|
})
|
|
.then((data: walletrpc.SignMessageWithAddrResponse) =>
|
|
snakeize(data)
|
|
);
|
|
verifyMessageWithAddr = async (
|
|
msg: string,
|
|
signature: string,
|
|
addr: string
|
|
) =>
|
|
await this.lnc.lnd.walletKit
|
|
.verifyMessageWithAddr({
|
|
msg:
|
|
typeof msg === 'string'
|
|
? Base64Utils.utf8ToBase64(msg)
|
|
: Base64Utils.bytesToBase64(msg as Uint8Array),
|
|
signature,
|
|
addr
|
|
})
|
|
.then((data: walletrpc.VerifyMessageWithAddrResponse) =>
|
|
snakeize(data)
|
|
);
|
|
lnurlAuth = async (r_hash: string) => {
|
|
const signed = await this.signMessage(r_hash);
|
|
return {
|
|
signature: new sha256Hash()
|
|
.update(Base64Utils.stringToUint8Array(signed.signature))
|
|
.digest()
|
|
};
|
|
};
|
|
lookupInvoice = async (data: any) =>
|
|
await this.lnc.lnd.lightning
|
|
.lookupInvoice({ r_hash: Base64Utils.hexToBase64(data.r_hash) })
|
|
.then((data: lnrpc.Invoice) => snakeize(data));
|
|
subscribeInvoice = (r_hash: string) =>
|
|
this.lnc.lnd.invoices.subscribeSingleInvoice({ r_hash });
|
|
subscribeInvoices = () => this.lnc.lnd.lightning.subscribeInvoices();
|
|
subscribeTransactions = () =>
|
|
this.lnc.lnd.lightning.subscribeTransactions();
|
|
|
|
supports = (minVersion: string, eosVersion?: string) => {
|
|
const { nodeInfo } = nodeInfoStore;
|
|
const { version } = nodeInfo;
|
|
const { isSupportedVersion } = VersionUtils;
|
|
return isSupportedVersion(version, minVersion, eosVersion);
|
|
};
|
|
|
|
listPeers = async () => {
|
|
try {
|
|
const res = await this.lnc.lnd.lightning.listPeers({});
|
|
return res.peers ?? [];
|
|
} catch (err) {
|
|
console.error('listPeers error:', err);
|
|
}
|
|
};
|
|
|
|
disconnectPeer = async (pubkey: string) => {
|
|
try {
|
|
await this.lnc.lnd.lightning.disconnectPeer({ pubKey: pubkey });
|
|
return true;
|
|
} catch (error) {
|
|
console.error(`Error disconnecting peer ${pubkey}:`, error);
|
|
return null;
|
|
}
|
|
};
|
|
|
|
getWatchtowerInfo = async (pubkey: string) =>
|
|
await this.lnc.lnd.watchtowerClient
|
|
.getTowerInfo({
|
|
pubkey,
|
|
includeSessions: true
|
|
})
|
|
.then((data: any) => snakeize(data));
|
|
|
|
listWatchtowers = async (includeSessions = true) =>
|
|
await this.lnc.lnd.watchtowerClient
|
|
.listTowers({
|
|
includeSessions,
|
|
excludeExhaustedSessions: false
|
|
})
|
|
.then((data: any) => snakeize(data));
|
|
|
|
removeWatchtower = async (pubkey: string, address?: string) =>
|
|
await this.lnc.lnd.watchtowerClient
|
|
.removeTower({
|
|
pubkey,
|
|
address
|
|
})
|
|
.then((data: any) => snakeize(data));
|
|
|
|
deactivateWatchtower = async (pubkey: string) =>
|
|
await this.lnc.lnd.watchtowerClient
|
|
.deactivateTower({
|
|
pubkey
|
|
})
|
|
.then((data: any) => snakeize(data));
|
|
|
|
terminateWatchtowerSession = async (sessionId: string) =>
|
|
await this.lnc.lnd.watchtowerClient
|
|
.terminateSession({
|
|
sessionId
|
|
})
|
|
.then((data: any) => snakeize(data));
|
|
|
|
getWatchtowerStats = async () =>
|
|
await this.lnc.lnd.watchtowerClient
|
|
.stats({})
|
|
.then((data: any) => snakeize(data));
|
|
|
|
getWatchtowerPolicy = async (policyType: string) =>
|
|
await this.lnc.lnd.watchtowerClient
|
|
.policy({
|
|
policyType
|
|
})
|
|
.then((data: any) => snakeize(data));
|
|
|
|
supportsWatchtowerClient = () => true;
|
|
supportsPeers = () => true;
|
|
supportsMessageSigning = () => this.permSignMessage;
|
|
supportsAddressMessageSigning = () => true;
|
|
supportsLnurlAuth = () => true;
|
|
supportsOnchainBalance = () => true;
|
|
supportsOnchainSends = () => this.permSendCoins;
|
|
supportsOnchainReceiving = () => this.permNewAddress;
|
|
supportsLightningSends = () => this.permSendLN;
|
|
supportsKeysend = () => true;
|
|
supportsChannelManagement = () => this.permOpenChannel;
|
|
supportsPendingChannels = () => true;
|
|
supportsClosedChannels = () => true;
|
|
supportsMPP = () => this.supports('v0.10.0');
|
|
supportsAMP = () => this.supports('v0.13.0');
|
|
supportsCoinControl = () => this.permNewAddress;
|
|
supportsChannelCoinControl = () =>
|
|
this.permNewAddress && this.supports('v0.17.0');
|
|
supportsHopPicking = () => this.permOpenChannel;
|
|
supportsAccounts = () => this.permImportAccount;
|
|
supportsRouting = () => this.permForwardingHistory;
|
|
supportsNodeInfo = () => true;
|
|
supportsWithdrawalRequests = () => false;
|
|
singleFeesEarnedTotal = () => false;
|
|
supportsAddressTypeSelection = () => true;
|
|
supportsNestedSegWit = () => true;
|
|
supportsTaproot = () => this.supports('v0.15.0');
|
|
supportsBumpFee = () => true;
|
|
supportsFlowLSP = () => false;
|
|
supportsNetworkInfo = () => true;
|
|
supportsSimpleTaprootChannels = () => this.supports('v0.17.0');
|
|
supportsCustomPreimages = () => true;
|
|
supportsSweep = () => true;
|
|
supportsOnchainSendMax = () => this.supports('v0.18.3');
|
|
supportsOnchainBatching = () => true;
|
|
supportsChannelBatching = () => true;
|
|
supportsChannelFundMax = () => true;
|
|
supportsLSPScustomMessage = () => true;
|
|
supportsLSPS1rest = () => true;
|
|
supportsOffers = () => false;
|
|
supportsBolt11BlindedRoutes = () => this.supports('v0.18.3');
|
|
supportsAddressesWithDerivationPaths = () => this.supports('v0.18.0');
|
|
isLNDBased = () => true;
|
|
supportsForwardingHistory = () => true;
|
|
supportInboundFees = () => this.supports('v0.18.0');
|
|
supportsCashuWallet = () => false;
|
|
supportsSettingInvoiceExpiration = () => true;
|
|
supportsNostrWalletConnectService = () => true;
|
|
}
|