Skip to content

Commit

Permalink
Revert "Move LND node communication to background script (#244)"
Browse files Browse the repository at this point in the history
This reverts commit 85bac5c.
  • Loading branch information
wbobeirne committed Dec 16, 2021
1 parent c589485 commit 62d2ff5
Show file tree
Hide file tree
Showing 33 changed files with 106 additions and 314 deletions.
2 changes: 1 addition & 1 deletion src/app/components/ChannelInfo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Unit from 'components/Unit';
import DetailsTable, { DetailsRow } from 'components/DetailsTable';
import TransferIcons from 'components/TransferIcons';
import Copy from 'components/Copy';
import { CHANNEL_STATUS } from 'lnd/message';
import { CHANNEL_STATUS } from 'lib/lnd-http';
import { AppState } from 'store/reducers';
import { getAccountInfo } from 'modules/account/actions';
import { closeChannel } from 'modules/channels/actions';
Expand Down
2 changes: 1 addition & 1 deletion src/app/components/ChannelList/ChannelRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Unit from 'components/Unit';
import { enumToClassName } from 'utils/formatters';
import { channelStatusText } from 'utils/constants';
import { ChannelWithNode } from 'modules/channels/types';
import { CHANNEL_STATUS } from 'lnd/message';
import { CHANNEL_STATUS } from 'lib/lnd-http';
import './ChannelRow.less';

interface Props {
Expand Down
2 changes: 1 addition & 1 deletion src/app/components/SelectNode/ConfirmNode.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { Button } from 'antd';
import { GetInfoResponse } from 'lnd/message';
import { GetInfoResponse } from 'lib/lnd-http';
import { blockchainDisplayName, CHAIN_TYPE } from 'utils/constants';
import './ConfirmNode.less';

Expand Down
File renamed without changes.
78 changes: 36 additions & 42 deletions src/lnd/http/index.ts → src/app/lib/lnd-http/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { stringify } from 'query-string';
import { txIdBytesToHex } from '../utils';
import * as T from '../types';
export * from '../errors';
export * from '../types';
import { parseNodeErrorResponse, txIdBytesToHex } from './utils';
import { NetworkError, SendTransactionError } from './errors';
import * as T from './types';
export * from './errors';
export * from './types';

export type ApiMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';

export class LndHttpClient implements T.LndAPI {
export class LndHttpClient {
url: string;
macaroon: undefined | T.Macaroon;

Expand Down Expand Up @@ -279,8 +280,7 @@ export class LndHttpClient implements T.LndAPI {
args,
).then(res => {
if (res.payment_error) {
// Make it easy to convert on the other side
throw new Error(`SendTransactionError: ${res.payment_error}`);
throw new SendTransactionError(res.payment_error);
}
return {
...res,
Expand Down Expand Up @@ -393,12 +393,12 @@ export class LndHttpClient implements T.LndAPI {
};

// Internal fetch function
protected async request<R extends object, A extends object | undefined = undefined>(
protected request<R extends object, A extends object | undefined = undefined>(
method: ApiMethod,
path: string,
args?: A,
defaultValues?: Partial<R>,
): Promise<R> {
): T.Response<R> {
let body = null;
let query = '';
const headers = new Headers();
Expand All @@ -416,42 +416,36 @@ export class LndHttpClient implements T.LndAPI {
headers.append('Grpc-Metadata-macaroon', this.macaroon);
}

try {
const res = await fetch(this.url + path + query, {
method,
headers,
body,
});
if (!res.ok) {
let errBody: any;
try {
errBody = await res.json();
if (!errBody.error) {
throw new Error();
return fetch(this.url + path + query, {
method,
headers,
body,
})
.then(async res => {
if (!res.ok) {
let errBody: any;
try {
errBody = await res.json();
if (!errBody.error) throw new Error();
} catch (err) {
throw new NetworkError(res.statusText, res.status);
}
} catch (err) {
throw {
statusText: res.statusText,
status: res.status,
} as T.LndAPIResponseError;
const error = parseNodeErrorResponse(errBody);
throw error;
}
console.log('errBody', errBody);
throw errBody as T.LndAPIResponseError;
}
const json = await res.json();
if (defaultValues) {
// TS can't handle generic spreadables
return { ...(defaultValues as any), ...(json as any) } as R;
}
return json as R;
} catch (err) {
console.error(`API error calling ${method} ${path}`, err);
// Thrown errors must be JSON serializable, so include metadata if possible
if (err.code || err.status || !err.message) {
return res.json();
})
.then((res: Partial<R>) => {
if (defaultValues) {
// TS can't handle generic spreadables
return { ...(defaultValues as any), ...(res as any) } as R;
}
return res as R;
})
.catch(err => {
console.error(`API error calling ${method} ${path}`, err);
throw err;
}
throw err.message;
}
});
}
}

Expand Down
71 changes: 2 additions & 69 deletions src/lnd/types.ts → src/app/lib/lnd-http/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Shared Types
export type Macaroon = string;

export type Response<T> = Promise<T>;

export type AddressType = '0' | '2';

export type UtxoAddressType = 'NESTED_PUBKEY_HASH' | 'WITNESS_PUBKEY_HASH';
Expand Down Expand Up @@ -405,72 +407,3 @@ export interface GetUtxosParams {
export interface GetUtxosResponse {
utxos: Utxo[];
}

// Shared API interface
export interface LndAPI {
getInfo(): Promise<GetInfoResponse>;
getNodeInfo(pubKey: string): Promise<GetNodeInfoResponse>;
getChannels(): Promise<GetChannelsResponse>;
getPendingChannels(): Promise<GetPendingChannelsResponse>;
getBlockchainBalance(): Promise<GetBlockchainBalanceResponse>;
getChannelsBalance(): Promise<GetChannelsBalanceResponse>;
getTransactions(): Promise<GetTransactionsResponse>;
getPayments(): Promise<GetPaymentsResponse>;
getInvoices(args?: GetInvoicesArguments): Promise<GetInvoicesResponse>;
getInvoice(paymentHash: string): Promise<GetInvoiceResponse>;
createInvoice(args: CreateInvoiceArguments): Promise<CreateInvoiceResponse>;
decodePaymentRequest(paymentRequest: string): Promise<DecodePaymentRequestResponse>;
queryRoutes(
pubKey: string,
amount: string,
args: QueryRoutesArguments,
): Promise<QueryRoutesResponse>;
sendPayment(args: SendPaymentArguments): Promise<SendPaymentResponse>;
sendOnChain(args: SendOnChainArguments): Promise<SendOnChainResponse>;
getAddress(args: NewAddressArguments): Promise<NewAddressResponse>;
getPeers(): Promise<GetPeersResponse>;
connectPeer(address: string, perm?: boolean): Promise<{}>;
openChannel(params: OpenChannelParams): Promise<OpenChannelResponse>;
closeChannel(fundingTxid: string, outputIndex: string): Promise<CloseChannelResponse>;
signMessage(message: string): Promise<SignMessageResponse>;
verifyMessage(params: VerifyMessageParams): Promise<VerifyMessageResponse>;
getUtxos(params?: GetUtxosParams): Promise<GetUtxosResponse>;
}

export type LndAPIMethod = keyof LndAPI;

// Browser message interface
export interface LndAPIRequestMessage<M extends LndAPIMethod> {
type: 'lnd-api-request';
url: string;
macaroon: undefined | Macaroon;
method: M;
args: Parameters<LndAPI[M]>;
}

export interface LndAPIResponseNetworkError {
statusText: string;
status: number;
}

export type LndAPIResponseError =
// Fetch error
| LndAPIResponseNetworkError
// LND error
| ErrorResponse
// Generic error
| string;

export type LndAPIResponseMessage<M extends LndAPIMethod> =
| {
type: 'lnd-api-response';
method: M;
data: ReturnType<LndAPI[M]>;
error: undefined;
}
| {
type: 'lnd-api-response';
method: M;
error: LndAPIResponseError;
data: undefined;
};
32 changes: 32 additions & 0 deletions src/app/lib/lnd-http/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import * as Errors from './errors';
import { ErrorResponse } from './types';

export function parseNodeErrorResponse(res: ErrorResponse): Error {
if (res.error.includes('expected 1 macaroon')) {
return new Errors.MacaroonAuthError('Macaroon is required');
}

if (res.error.includes('permission denied')) {
return new Errors.PermissionDeniedError('You lack permission to do that');
}

if (res.error.includes('unable to find a path to destination')) {
return new Errors.NoRouteError('No route available for payment');
}

if (res.error.includes('already connected to peer')) {
return new Errors.AlreadyConnectedError('You are already peers with that node');
}

return new Errors.UnknownServerError(res.error);
}

export function txIdBytesToHex(txbytes: string) {
const txbinary = Buffer.from(txbytes, 'base64').toString('binary');
const txarray = new Uint8Array(txbinary.length);
for (let i = 0; i < txbinary.length; i++) {
txarray[i] = txbinary.charCodeAt(i);
}
txarray.reverse();
return new Buffer(txarray).toString('hex');
}
2 changes: 1 addition & 1 deletion src/app/modules/account/actions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NewAddressArguments } from 'lnd/message';
import { NewAddressArguments } from 'lib/lnd-http';
import types from './types';

export function getAccountInfo() {
Expand Down
2 changes: 1 addition & 1 deletion src/app/modules/account/reducers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import types, { Account, LightningPaymentWithToNode } from './types';
import { LightningInvoice, ChainTransaction } from 'lnd/message';
import { LightningInvoice, ChainTransaction } from 'lib/lnd-http';

export interface AccountState {
account: Account | null;
Expand Down
2 changes: 1 addition & 1 deletion src/app/modules/account/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
LightningInvoice,
LightningPayment,
ChainTransaction,
} from 'lnd/message';
} from 'lib/lnd-http';

enum AccountTypes {
GET_ACCOUNT_INFO = 'GET_ACCOUNT_INFO',
Expand Down
2 changes: 1 addition & 1 deletion src/app/modules/channels/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
ForceClosingChannel,
WaitingChannel,
LightningNode,
} from 'lnd/message';
} from 'lib/lnd-http';

enum ChannelsTypes {
GET_CHANNELS = 'GET_CHANNELS',
Expand Down
8 changes: 4 additions & 4 deletions src/app/modules/node/actions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import LndMessageClient, { Macaroon } from 'lnd/message';
import LndHttpClient, { Macaroon } from 'lib/lnd-http';
import {
selectSyncedUnencryptedNodeState,
selectSyncedEncryptedNodeState,
Expand Down Expand Up @@ -63,7 +63,7 @@ export function setNode(
url,
adminMacaroon,
readonlyMacaroon,
lib: new LndMessageClient(url, adminMacaroon),
lib: new LndHttpClient(url, adminMacaroon),
},
};
}
Expand All @@ -81,7 +81,7 @@ export function setSyncedUnencryptedNodeState(
payload: {
url,
readonlyMacaroon,
lib: url ? new LndMessageClient(url as string, readonlyMacaroon as string) : null,
lib: url ? new LndHttpClient(url as string, readonlyMacaroon as string) : null,
},
};
}
Expand All @@ -95,7 +95,7 @@ export function setSyncedEncryptedNodeState(
payload: {
url,
adminMacaroon,
lib: url ? new LndMessageClient(url as string, adminMacaroon as string) : null,
lib: url ? new LndHttpClient(url as string, adminMacaroon as string) : null,
},
};
}
4 changes: 2 additions & 2 deletions src/app/modules/node/reducers.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Macaroon, GetInfoResponse, LndAPI } from 'lnd/message';
import LndHttpClient, { Macaroon, GetInfoResponse } from 'lib/lnd-http';
import types from './types';
import settingsTypes from 'modules/settings/types';

export interface NodeState {
lib: LndAPI | null;
lib: LndHttpClient | null;
url: string | null;
isNodeChecked: boolean;
adminMacaroon: Macaroon | null;
Expand Down
10 changes: 5 additions & 5 deletions src/app/modules/node/sagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import {
import { requirePassword } from 'modules/crypto/sagas';
import { accountTypes } from 'modules/account';
import { channelsTypes } from 'modules/channels';
import LndMessageClient, { MacaroonAuthError, PermissionDeniedError } from 'lnd/message';
import LndHttpClient, { MacaroonAuthError, PermissionDeniedError } from 'lib/lnd-http';
import types from './types';

export function* handleCheckNode(action: ReturnType<typeof actions.checkNode>) {
const url = action.payload;
const client = new LndMessageClient(url);
const client = new LndHttpClient(url);
try {
yield call(client.getInfo);
} catch (err) {
Expand All @@ -36,7 +36,7 @@ export function* handleCheckNodes(action: ReturnType<typeof actions.checkNodes>)
const requests = urls.map(url => {
return new Promise<string | null>(async resolve => {
try {
const client = new LndMessageClient(url);
const client = new LndHttpClient(url);
await client.getInfo();
resolve(url);
} catch (err) {
Expand All @@ -62,7 +62,7 @@ export function* handleCheckAuth(action: ReturnType<typeof actions.checkAuth>) {
const { url, admin, readonly } = action.payload;

// Check read-only by making sure request doesn't error
let client = new LndMessageClient(url, readonly);
let client = new LndHttpClient(url, readonly);
let nodeInfo;
try {
nodeInfo = yield call(client.getInfo);
Expand All @@ -78,7 +78,7 @@ export function* handleCheckAuth(action: ReturnType<typeof actions.checkAuth>) {
// Test admin by intentionally send an invalid payment,
// but make sure we didn't error out with a macaroon auth error
// TODO: Replace with sign message once REST supports it
client = new LndMessageClient(url, admin);
client = new LndHttpClient(url, admin);
try {
yield call(client.sendPayment, { payment_request: 'testing admin' });
} catch (err) {
Expand Down
2 changes: 1 addition & 1 deletion src/app/modules/onchain/reducers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import types from './types';
import { Utxo } from 'lnd/message';
import { Utxo } from 'lib/lnd-http';

export interface OnChainState {
utxos: Utxo[] | null;
Expand Down
2 changes: 1 addition & 1 deletion src/app/modules/onchain/sagas.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { SagaIterator } from 'redux-saga';
import { takeLatest, select, call, put } from 'redux-saga/effects';
import { selectNodeLibOrThrow } from 'modules/node/selectors';
import { GetUtxosResponse } from 'lnd/types';
import { GetUtxosResponse } from 'lib/lnd-http/types';
import types from './types';

export function* handleGetUtxos() {
Expand Down
2 changes: 1 addition & 1 deletion src/app/modules/payment/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
SendPaymentArguments,
CreateInvoiceArguments,
SendOnChainArguments,
} from 'lnd/message';
} from 'lib/lnd-http';
import types from './types';

export function checkPaymentRequest(paymentRequest: string, amount?: string) {
Expand Down
Loading

0 comments on commit 62d2ff5

Please sign in to comment.