Skip to content

Commit

Permalink
LND: batch channel opens
Browse files Browse the repository at this point in the history
  • Loading branch information
kaloudis committed Apr 22, 2024
1 parent 3deecc7 commit c5f9d5b
Show file tree
Hide file tree
Showing 19 changed files with 680 additions and 220 deletions.
1 change: 1 addition & 0 deletions backends/CLightningREST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,5 +273,6 @@ export default class CLightningREST extends LND {
supportsCustomPreimages = () => false;
supportsSweep = () => true;
supportsOnchainBatching = () => false;
supportsChannelBatching = () => false;
isLNDBased = () => false;
}
1 change: 1 addition & 0 deletions backends/Eclair.ts
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,7 @@ export default class Eclair {
supportsCustomPreimages = () => false;
supportsSweep = () => false;
supportsOnchainBatching = () => false;
supportsChannelBatching = () => false;
isLNDBased = () => false;
}

Expand Down
18 changes: 15 additions & 3 deletions backends/EmbeddedLND.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const {
verifyMessageNodePubkey,
bumpFee,
fundPsbt,
signPsbt,
finalizePsbt,
publishTransaction,
listAccounts,
Expand Down Expand Up @@ -205,23 +206,33 @@ export default class EmbeddedLND extends LND {
// getForwardingHistory = () => N/A
// // Coin Control
fundPsbt = async (data: any) => await fundPsbt(data);
signPsbt = async (data: any) => await signPsbt(data);
finalizePsbt = async (data: any) => await finalizePsbt(data);
publishTransaction = async (data: any) => {
if (data.tx_hex) data.tx_hex = Base64Utils.hexToBase64(data.tx_hex);
return await publishTransaction(data);
};
fundingStateStep = async (data: any) => {
// Verify
if (data.psbt_finalize?.funded_psbt)
if (
data.psbt_finalize?.funded_psbt &&
Base64Utils.isHex(data.psbt_finalize?.funded_psbt)
)
data.psbt_finalize.funded_psbt = Base64Utils.hexToBase64(
data.psbt_finalize.funded_psbt
);
// Finalize
if (data.psbt_finalize?.final_raw_tx)
if (
data.psbt_finalize?.final_raw_tx &&
Base64Utils.isHex(data.psbt_finalize?.final_raw_tx)
)
data.psbt_finalize.final_raw_tx = Base64Utils.hexToBase64(
data.psbt_finalize.final_raw_tx
);
if (data.psbt_finalize?.signed_psbt)
if (
data.psbt_finalize?.signed_psbt &&
Base64Utils.isHex(data.psbt_finalize?.signed_psbt)
)
data.psbt_finalize.signed_psbt = Base64Utils.hexToBase64(
data.psbt_finalize.signed_psbt
);
Expand Down Expand Up @@ -268,5 +279,6 @@ export default class EmbeddedLND extends LND {
supportsCustomPreimages = () => true;
supportsSweep = () => true;
supportsOnchainBatching = () => true;
supportsChannelBatching = () => true;
isLNDBased = () => true;
}
2 changes: 2 additions & 0 deletions backends/LND.ts
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,7 @@ export default class LND {
};
// Coin Control
fundPsbt = (data: any) => this.postRequest('/v2/wallet/psbt/fund', data);
signPsbt = (data: any) => this.postRequest('/v2/wallet/psbt/sign', data);
finalizePsbt = (data: any) =>
this.postRequest('/v2/wallet/psbt/finalize', data);
publishTransaction = (data: any) => {
Expand Down Expand Up @@ -614,5 +615,6 @@ export default class LND {
supportsCustomPreimages = () => true;
supportsSweep = () => true;
supportsOnchainBatching = () => true;
supportsChannelBatching = () => true;
isLNDBased = () => true;
}
47 changes: 37 additions & 10 deletions backends/LightningNodeConnect.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { NativeModules, NativeEventEmitter } from 'react-native';

import LNC, { lnrpc, walletrpc } from '../zeus_modules/@lightninglabs/lnc-rn';

import stores from '../stores/Stores';
Expand All @@ -22,6 +24,7 @@ const ADDRESS_TYPES = [

export default class LightningNodeConnect {
lnc: any;
listener: any;

permOpenChannel: boolean;
permSendCoins: boolean;
Expand Down Expand Up @@ -223,7 +226,35 @@ export default class LightningNodeConnect {
delete request.sat_per_vbyte;
}

return this.lnc.lnd.lightning.openChannel(request);
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
Expand Down Expand Up @@ -340,6 +371,10 @@ export default class LightningNodeConnect {
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)
Expand All @@ -351,20 +386,11 @@ export default class LightningNodeConnect {
.then((data: walletrpc.PublishResponse) => snakeize(data));
};
fundingStateStep = async (req: lnrpc.FundingTransitionMsg) => {
// Verify
if (req.psbt_finalize?.funded_psbt)
req.psbt_finalize.funded_psbt = Base64Utils.hexToBase64(
req.psbt_finalize.funded_psbt
);
// Finalize
if (req.psbt_finalize?.final_raw_tx)
req.psbt_finalize.final_raw_tx = Base64Utils.hexToBase64(
req.psbt_finalize.final_raw_tx
);
if (req.psbt_finalize?.signed_psbt)
req.psbt_finalize.signed_psbt = Base64Utils.hexToBase64(
req.psbt_finalize.signed_psbt
);

return await this.lnc.lnd.lightning
.fundingStateStep(req)
Expand Down Expand Up @@ -452,5 +478,6 @@ export default class LightningNodeConnect {
supportsCustomPreimages = () => true;
supportsSweep = () => true;
supportsOnchainBatching = () => true;
supportsChannelBatching = () => true;
isLNDBased = () => true;
}
1 change: 1 addition & 0 deletions backends/LndHub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,5 +153,6 @@ export default class LndHub extends LND {
supportsCustomPreimages = () => false;
supportsSweep = () => false;
supportsOnchainBatching = () => false;
supportsChannelBatching = () => true;
isLNDBased = () => false;
}
1 change: 1 addition & 0 deletions backends/Spark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -379,5 +379,6 @@ export default class Spark {
supportsCustomPreimages = () => false;
supportsSweep = () => false;
supportsOnchainBatching = () => false;
supportsChannelBatching = () => true;
isLNDBased = () => false;
}
1 change: 1 addition & 0 deletions ios/LndMobile/Lnd.swift
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ open class Lnd {
"UnlockWallet": { bytes, cb in LndmobileUnlockWallet(bytes, cb) },
"WalletKitDeriveKey": { bytes, cb in LndmobileWalletKitDeriveKey(bytes, cb) },
"FundPsbt": { bytes, cb in LndmobileWalletKitFundPsbt(bytes, cb) },
"SignPsbt": { bytes, cb in LndmobileWalletKitSignPsbt(bytes, cb) },
"FinalizePsbt": { bytes, cb in LndmobileWalletKitFinalizePsbt(bytes, cb) },
"PublishTransaction": { bytes, cb in LndmobileWalletKitPublishTransaction(bytes, cb) },
"ListAccounts": { bytes, cb in LndmobileWalletKitListAccounts(bytes, cb) },
Expand Down
9 changes: 9 additions & 0 deletions lndmobile/LndMobileInjection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ import {
signMessageNodePubkey,
bumpFee,
fundPsbt,
signPsbt,
finalizePsbt,
publishTransaction,
listAccounts,
Expand Down Expand Up @@ -370,15 +371,22 @@ export interface ILndMobileInjections {
}) => Promise<walletrpc.BumpFeeResponse>;
fundPsbt: ({
account,
psbt,
raw,
spend_unconfirmed,
sat_per_vbyte
}: {
account?: string;
psbt?: Uint8Array;
raw: walletrpc.TxTemplate;
spend_unconfirmed?: boolean;
sat_per_vbyte?: Long;
}) => Promise<walletrpc.FundPsbtResponse>;
signPsbt: ({
funded_psbt
}: {
funded_psbt?: Uint8Array;
}) => Promise<walletrpc.SignPsbtResponse>;
finalizePsbt: ({
funded_psbt
}: {
Expand Down Expand Up @@ -498,6 +506,7 @@ export default {
signMessageNodePubkey,
bumpFee,
fundPsbt,
signPsbt,
finalizePsbt,
publishTransaction,
listAccounts,
Expand Down
29 changes: 28 additions & 1 deletion lndmobile/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,21 @@ export const bumpFee = async ({
*/
export const fundPsbt = async ({
account,
psbt,
raw,
spend_unconfirmed,
sat_per_vbyte
}: {
account?: string;
raw: walletrpc.TxTemplate;
psbt?: Uint8Array;
raw?: walletrpc.TxTemplate;
spend_unconfirmed?: boolean;
sat_per_vbyte?: Long;
}): Promise<walletrpc.FundPsbtResponse> => {
const options: walletrpc.IFundPsbtRequest = {
account,
raw,
psbt,
spend_unconfirmed,
sat_per_vbyte: sat_per_vbyte ? Long.fromValue(sat_per_vbyte) : undefined
};
Expand All @@ -73,6 +76,30 @@ export const fundPsbt = async ({
return response;
};

/**
* @throws
*/
export const signPsbt = async ({
funded_psbt
}: {
funded_psbt?: Uint8Array;
}): Promise<walletrpc.SignPsbtResponse> => {
const options: walletrpc.ISignPsbtRequest = {
funded_psbt
};
const response = await sendCommand<
walletrpc.ISignPsbtRequest,
walletrpc.SignPsbtRequest,
walletrpc.SignPsbtResponse
>({
request: walletrpc.SignPsbtRequest,
response: walletrpc.SignPsbtResponse,
method: 'SignPsbt',
options
});
return response;
};

/**
* @throws
*/
Expand Down
6 changes: 6 additions & 0 deletions locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,8 @@
"views.OpenChannel.openChannelToOlympus": "Open channel to Olympus",
"views.OpenChannel.peerToOlympus": "Peer to Olympus",
"views.OpenChannel.fundMax": "Use all possible funds",
"views.OpenChannel.openAdditionalChannel": "Open additional channel",
"views.OpenChannel.removeAdditionalChannel": "Remove additional channel",
"views.Wallet.BalancePane.sync.title": "Finishing sync",
"views.Wallet.BalancePane.sync.text": "Hang on tight! You will be ready to use Zeus soon.",
"views.Wallet.BalancePane.backup.title": "Back up your funds",
Expand Down Expand Up @@ -397,6 +399,7 @@
"views.Channel.SortButton.ascending": "ascending",
"views.Channel.SortButton.descending": "descending",
"views.Channel.channelId": "Channel ID",
"views.Channel.channelIds": "Channel IDs",
"views.Channel.displayName": "Display name",
"views.Channel.Total.outbound": "Total outbound",
"views.Channel.Total.inbound": "Total inbound",
Expand Down Expand Up @@ -485,12 +488,14 @@
"views.Intro.carousel4.text": "Go beyond a basic bitcoin wallet and manage your lightning channels, liquidity, and so much more.",
"views.Intro.errorCreatingWallet": "Error creating wallet. Restart the app and try again.",
"views.OpenChannel.openChannel": "Open Channel",
"views.OpenChannel.openChannels": "Open Channels",
"views.OpenChannel.connectPeer": "Connect Peer",
"views.OpenChannel.importText": "Detected the following Node URI in your clipboard",
"views.OpenChannel.importPrompt": "Would you like to import it?",
"views.OpenChannel.import": "Import",
"views.OpenChannel.peerSuccess": "Successfully connected to peer",
"views.OpenChannel.channelSuccess": "Successfully opened channel",
"views.OpenChannel.channelsSuccess": "Successfully opened channels",
"views.OpenChannel.nodePubkey": "Node pubkey",
"views.OpenChannel.host": "Host",
"views.OpenChannel.hostPort": "Hostname:Port",
Expand Down Expand Up @@ -1072,6 +1077,7 @@
"views.PSBT.scan": "Scan PSBT / TX Hex",
"views.PSBT.finalizePsbtAndBroadcast": "Finalize PSBT and Broadcast",
"views.PSBT.channelWarning": "DO NOT PUBLISH the finished transaction by yourself or with another tool. LND MUST publish it in the proper funding flow order OR THE FUNDS CAN BE LOST! Ensure you publish in ZEUS and only when the channel ID above is displayed.",
"views.PSBT.channelsWarning": "DO NOT PUBLISH the finished transaction by yourself or with another tool. LND MUST publish it in the proper funding flow order OR THE FUNDS CAN BE LOST! Ensure you publish in ZEUS and only when the channel IDs above are displayed.",
"views.PSBT.input": "Input",
"views.PSBT.inputCount": "Input count",
"views.PSBT.output": "Output",
Expand Down
9 changes: 9 additions & 0 deletions models/OpenChannelRequest.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import BaseModel from './BaseModel';

export interface AdditionalChannel {
node_pubkey_string: string;
host: string;
local_funding_amount: string;
satAmount: string | number;
}

export default class OpenChannelRequest extends BaseModel {
public min_confs?: number;
public spend_unconfirmed?: boolean;
Expand Down Expand Up @@ -27,8 +34,10 @@ export default class OpenChannelRequest extends BaseModel {
psbt_shim: {
pending_chan_id: any;
base_psbt: string;
no_publish?: boolean;
};
};
public additionalChannels?: Array<AdditionalChannel>;

constructor(data?: any) {
super(data);
Expand Down
Loading

0 comments on commit c5f9d5b

Please sign in to comment.