Skip to content

Commit

Permalink
refactor: use new hold invoice plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
michael1011 committed Aug 22, 2024
1 parent 401a21f commit 72f35ed
Show file tree
Hide file tree
Showing 43 changed files with 1,714 additions and 9,632 deletions.
4 changes: 2 additions & 2 deletions lib/VersionCheck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ class VersionCheck {
maximal: '24.05',
},
[ClnClient.serviceNameHold]: {
minimal: '0.0.3',
maximal: '0.0.5',
minimal: '0.1.0',
maximal: '0.1.0',
},
[MpayClient.serviceName]: {
minimal: '0.1.0',
Expand Down
151 changes: 49 additions & 102 deletions lib/lightning/cln/ClnClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,7 @@ import * as primitivesrpc from '../../proto/cln/primitives_pb';
import { HoldClient } from '../../proto/hold/hold_grpc_pb';
import * as holdrpc from '../../proto/hold/hold_pb';
import { WalletBalance } from '../../wallet/providers/WalletProviderInterface';
import {
msatToSat,
satToMsat,
scidClnToLnd,
scidLndToCln,
} from '../ChannelUtils';
import { msatToSat, satToMsat, scidClnToLnd } from '../ChannelUtils';
import Errors from '../Errors';
import { grpcOptions, unaryCall } from '../GrpcUtils';
import {
Expand Down Expand Up @@ -354,14 +349,26 @@ class ClnClient
};

public routingHints = async (node: string): Promise<HopHint[][]> => {
const req = new holdrpc.RoutingHintsRequest();
req.setNode(node);
const req = new noderpc.ListpeerchannelsRequest();
req.setId(node);

const res = await this.unaryHoldCall<
holdrpc.RoutingHintsRequest,
holdrpc.RoutingHintsResponse.AsObject
>('routingHints', req);
return ClnClient.routingHintsFromGrpc(res.hintsList);
const channels = await this.unaryNodeCall<
noderpc.ListpeerchannelsRequest,
noderpc.ListpeerchannelsResponse.AsObject
>('listPeerChannels', req, true);

return channels.channelsList
.filter((chan) => chan.pb_private)
.map((channel) => [
{
nodeId: node,
chanId: scidClnToLnd(getHexString(Buffer.from(channel.channelId))),
feeBaseMsat: channel.updates!.remote!.feeBaseMsat!.msat,
feeProportionalMillionths:
channel.updates!.remote!.feeProportionalMillionths,
cltvExpiryDelta: channel.updates!.remote!.cltvExpiryDelta,
},
]);
};

public addHoldInvoice = async (
Expand All @@ -375,7 +382,7 @@ class ClnClient
): Promise<string> => {
const req = new holdrpc.InvoiceRequest();
req.setAmountMsat(satToMsat(value));
req.setPaymentHash(getHexString(preimageHash));
req.setPaymentHash(preimageHash);

if (cltvExpiry) {
req.setMinFinalCltvExpiry(cltvExpiry);
Expand All @@ -386,11 +393,11 @@ class ClnClient
}

if (memo) {
req.setDescription(memo);
req.setMemo(memo);
}

if (descriptionHash) {
req.setDescriptionHash(getHexString(descriptionHash));
req.setHash(descriptionHash);
}

if (routingHints) {
Expand All @@ -407,7 +414,7 @@ class ClnClient

public lookupHoldInvoice = async (preimageHash: Buffer): Promise<Invoice> => {
const req = new holdrpc.ListRequest();
req.setPaymentHash(getHexString(preimageHash));
req.setPaymentHash(preimageHash);

const res = await this.unaryHoldCall<
holdrpc.ListRequest,
Expand All @@ -427,7 +434,7 @@ class ClnClient

public cancelHoldInvoice = async (preimageHash: Buffer): Promise<void> => {
const req = new holdrpc.CancelRequest();
req.setPaymentHash(getHexString(preimageHash));
req.setPaymentHash(preimageHash);

await this.unaryHoldCall<
holdrpc.CancelRequest,
Expand All @@ -437,7 +444,7 @@ class ClnClient

public settleHoldInvoice = async (preimage: Buffer): Promise<void> => {
const req = new holdrpc.SettleRequest();
req.setPaymentPreimage(getHexString(preimage));
req.setPaymentPreimage(preimage);

await this.unaryHoldCall<
holdrpc.SettleRequest,
Expand Down Expand Up @@ -614,7 +621,7 @@ class ClnClient
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public subscribeSingleInvoice = (_: Buffer): void => {
// Just here for interface compatibility;
// with CLN we can subscribe to all hold invoice with one gRPC subscription
// with CLN we can subscribe to all hold invoices with one gRPC subscription
return;
};

Expand All @@ -625,8 +632,8 @@ class ClnClient
const routeHint = new holdrpc.RoutingHint();
for (const hint of hints) {
const hopHint = new holdrpc.Hop();
hopHint.setPublicKey(hint.nodeId);
hopHint.setShortChannelId(scidLndToCln(hint.chanId));
hopHint.setPublicKey(getHexBuffer(hint.nodeId));
hopHint.setShortChannelId(Number(hint.chanId));
hopHint.setBaseFee(hint.feeBaseMsat);
hopHint.setPpmFee(hint.feeProportionalMillionths);
hopHint.setCltvExpiryDelta(hint.cltvExpiryDelta);
Expand All @@ -638,49 +645,39 @@ class ClnClient
});
};

private static routingHintsFromGrpc = (
routingHints: holdrpc.RoutingHint.AsObject[],
): HopHint[][] => {
return routingHints.map((hint) =>
hint.hopsList.map((hop) => ({
nodeId: hop.publicKey,
chanId: hop.shortChannelId,
feeBaseMsat: hop.baseFee,
feeProportionalMillionths: hop.ppmFee,
cltvExpiryDelta: hop.cltvExpiryDelta,
})),
);
};

private static invoiceStateFromGrpc = (
state: holdrpc.InvoiceState,
): InvoiceState => {
switch (state) {
case holdrpc.InvoiceState.INVOICE_UNPAID:
case holdrpc.InvoiceState.UNPAID:
return InvoiceState.Open;
case holdrpc.InvoiceState.INVOICE_ACCEPTED:
case holdrpc.InvoiceState.ACCEPTED:
return InvoiceState.Accepted;
case holdrpc.InvoiceState.INVOICE_CANCELLED:
case holdrpc.InvoiceState.CANCELLED:
return InvoiceState.Cancelled;
case holdrpc.InvoiceState.INVOICE_PAID:
case holdrpc.InvoiceState.PAID:
return InvoiceState.Settled;
}
};

private static htlcFromGrpc = (htlc: holdrpc.Htlc.AsObject): Htlc => {
return {
state: ClnClient.htlcStateFromGrpc(htlc.state),
valueMsat: htlc.msat,
state: ClnClient.htlcStateFromGrpc(htlc.state),
};
};

private static htlcStateFromGrpc = (state: holdrpc.HtlcState): HtlcState => {
private static htlcStateFromGrpc = (
state: holdrpc.InvoiceState,
): HtlcState => {
switch (state) {
case holdrpc.HtlcState.HTLC_ACCEPTED:
case holdrpc.InvoiceState.UNPAID:
throw 'invalid HTLC state';
case holdrpc.InvoiceState.ACCEPTED:
return HtlcState.Accepted;
case holdrpc.HtlcState.HTLC_CANCELLED:
case holdrpc.InvoiceState.CANCELLED:
return HtlcState.Cancelled;
case holdrpc.HtlcState.HTLC_SETTLED:
case holdrpc.InvoiceState.PAID:
return HtlcState.Settled;
}
};
Expand Down Expand Up @@ -721,25 +718,6 @@ class ClnClient
};
}

// ... has failed
// TODO: mpay incorrect payment details detection
for (const payStatus of (await this.payStatus(invoice)).statusList) {
for (const attempt of payStatus.attemptsList) {
if (
attempt.state ===
holdrpc.PayStatusResponse.PayStatus.Attempt.AttemptState
.ATTEMPT_PENDING ||
attempt.failure === undefined
) {
continue;
}

if (ClnClient.errIsIncorrectPaymentDetails(attempt.failure.message)) {
throw attempt.failure.message;
}
}
}

// ... or is still pending
const hasPendingPayments = pays.some(
(pay) => pay.getStatus() === ListpaysPaysStatus.PENDING,
Expand Down Expand Up @@ -771,44 +749,13 @@ class ClnClient
return undefined;
};

private payStatus = (invoice: string) => {
const req = new holdrpc.PayStatusRequest();
req.setBolt11(invoice);

return this.unaryHoldCall<
holdrpc.PayStatusRequest,
holdrpc.PayStatusResponse.AsObject
>('payStatus', req);
};

private queryRoute = async (
destination: string,
amt: number,
cltvLimit?: number,
finalCltvDelta?: number,
_destination: string,

Check failure on line 753 in lib/lightning/cln/ClnClient.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 20, 3.10, stable)

'_destination' is defined but never used

Check failure on line 753 in lib/lightning/cln/ClnClient.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 20, 3.10, stable)

'_destination' is defined but never used
_amt: number,

Check failure on line 754 in lib/lightning/cln/ClnClient.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 20, 3.10, stable)

'_amt' is defined but never used

Check failure on line 754 in lib/lightning/cln/ClnClient.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 20, 3.10, stable)

'_amt' is defined but never used
_cltvLimit?: number,

Check failure on line 755 in lib/lightning/cln/ClnClient.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 20, 3.10, stable)

'_cltvLimit' is defined but never used

Check failure on line 755 in lib/lightning/cln/ClnClient.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 20, 3.10, stable)

'_cltvLimit' is defined but never used
_finalCltvDelta?: number,

Check failure on line 756 in lib/lightning/cln/ClnClient.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 20, 3.10, stable)

'_finalCltvDelta' is defined but never used

Check failure on line 756 in lib/lightning/cln/ClnClient.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 20, 3.10, stable)

'_finalCltvDelta' is defined but never used
): Promise<Route> => {
const req = new holdrpc.GetRouteRequest();
req.setDestination(destination);
req.setRiskFactor(0);
req.setAmountMsat(amt);

if (cltvLimit) {
req.setMaxCltv(cltvLimit);
}

if (finalCltvDelta) {
req.setFinalCltvDelta(finalCltvDelta);
}

const res = await this.unaryHoldCall<
holdrpc.GetRouteRequest,
holdrpc.GetRouteResponse.AsObject
>('getRoute', req);

return {
ctlv: res.hopsList[0].delay,
feesMsat: res.feesMsat,
};
throw 'not implemented';
};

private subscribeTrackHoldInvoices = () => {
Expand All @@ -822,7 +769,7 @@ class ClnClient

this.trackAllSubscription.on('data', (update: holdrpc.TrackAllResponse) => {
switch (update.getState()) {
case holdrpc.InvoiceState.INVOICE_ACCEPTED:
case holdrpc.InvoiceState.ACCEPTED:
this.logger.debug(
`${ClnClient.serviceName} ${
this.symbol
Expand All @@ -832,7 +779,7 @@ class ClnClient
this.emit('htlc.accepted', update.getBolt11());
break;

case holdrpc.InvoiceState.INVOICE_PAID:
case holdrpc.InvoiceState.PAID:
this.logger.debug(
`${ClnClient.serviceName} ${
this.symbol
Expand Down
Loading

0 comments on commit 72f35ed

Please sign in to comment.