Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: gets peer message when manual open channel fails #272

Merged
merged 4 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 35 additions & 3 deletions lib/android/src/main/java/com/reactnativeldk/LdkModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import org.ldk.structs.Result_Bolt11InvoiceParseOrSemanticErrorZ.Result_Bolt11In
import org.ldk.structs.Result_Bolt11InvoiceSignOrCreationErrorZ.Result_Bolt11InvoiceSignOrCreationErrorZ_OK
import org.ldk.structs.Result_C2Tuple_ThirtyTwoBytesChannelMonitorZDecodeErrorZ.Result_C2Tuple_ThirtyTwoBytesChannelMonitorZDecodeErrorZ_OK
import org.ldk.structs.Result_C3Tuple_ThirtyTwoBytesRecipientOnionFieldsRouteParametersZNoneZ.Result_C3Tuple_ThirtyTwoBytesRecipientOnionFieldsRouteParametersZNoneZ_OK
import org.ldk.structs.Result_ChannelIdAPIErrorZ.Result_ChannelIdAPIErrorZ_OK
import org.ldk.structs.Result_NoneAPIErrorZ.Result_NoneAPIErrorZ_OK
import org.ldk.structs.Result_NoneRetryableSendFailureZ.Result_NoneRetryableSendFailureZ_Err
import org.ldk.structs.Result_PublicKeyNoneZ.Result_PublicKeyNoneZ_OK
import org.ldk.structs.Result_StrSecp256k1ErrorZ.Result_StrSecp256k1ErrorZ_OK
Expand Down Expand Up @@ -772,6 +774,8 @@ class LdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMod
channelManager ?: return handleReject(promise, LdkErrors.init_channel_manager)
keysManager ?: return handleReject(promise, LdkErrors.init_keys_manager)

println("Creating channel with counterPartyNodeId: $counterPartyNodeId, channelValueSats: $channelValueSats, pushSats: $pushSats")

val theirNetworkKey = counterPartyNodeId.hexa()
val channelValueSatoshis = channelValueSats.toLong()
val pushMsat = pushSats.toLong() * 1000
Expand All @@ -790,11 +794,39 @@ class LdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMod
UserConfig.with_default()
)

if (!res.is_ok) {
return handleReject(promise, LdkErrors.start_create_channel_fail)
if (res.is_ok) {
return promise.resolve((res as Result_ChannelIdAPIErrorZ_OK).res._a.hexEncodedString())
}

if ((res as Result_ChannelIdAPIErrorZ.Result_ChannelIdAPIErrorZ_Err).err is APIError.APIMisuseError) {
return handleReject(promise, LdkErrors.start_create_channel_fail, Error((res.err as APIError.APIMisuseError).err))
}

if (res.err is APIError.ChannelUnavailable) {
return handleReject(promise, LdkErrors.start_create_channel_fail, Error((res.err as APIError.ChannelUnavailable).err))
}

if (res.err is APIError.FeeRateTooHigh) {
return handleReject(promise, LdkErrors.start_create_channel_fail, Error((res.err as APIError.FeeRateTooHigh).err))
}

if (res.err is APIError.InvalidRoute) {
return handleReject(promise, LdkErrors.start_create_channel_fail, Error((res.err as APIError.InvalidRoute).err))
}

if (res.err is APIError.IncompatibleShutdownScript) {
return handleReject(promise, LdkErrors.start_create_channel_fail, Error("IncompatibleShutdownScript"))
}

if (res.err is APIError.MonitorUpdateInProgress) {
return handleReject(promise, LdkErrors.start_create_channel_fail, Error("MonitorUpdateInProgress"))
}

if (res.err is APIError.ChannelUnavailable) {
return handleReject(promise, LdkErrors.start_create_channel_fail, Error((res.err as APIError.ChannelUnavailable).err))
}

handleResolve(promise, LdkCallbackResponses.start_create_channel_fail)
return handleReject(promise, LdkErrors.start_create_channel_fail)
Jasonvdb marked this conversation as resolved.
Show resolved Hide resolved
}

@ReactMethod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,14 @@ class LdkChannelManagerPersister: ChannelManagerConstructor.EventHandler {
}
body.putString("reason", reasonString)

if (channelClosed.reason is ClosureReason.CounterpartyForceClosed) {
(channelClosed.reason as ClosureReason.CounterpartyForceClosed).peer_msg?.let {
body.putString("peer_message", it.to_str())
}
}

println("Channel closed: ${channelClosed.channel_id._a.hexEncodedString()}")

return LdkEventEmitter.send(EventTypes.channel_manager_channel_closed, body)
}

Expand Down
68 changes: 36 additions & 32 deletions lib/ios/Classes/LdkChannelManagerPersister.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Foundation
import LightningDevKit

class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister {
//Custom function to manage any unlikely missing info from the event object
// Custom function to manage any unlikely missing info from the event object
func handleEventError(_ event: Event) {
LdkEventEmitter.shared.send(
withEvent: .native_log,
Expand All @@ -25,14 +25,14 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister {
guard let fundingGeneration = event.getValueAsFundingGenerationReady() else {
return handleEventError(event)
}

LdkEventEmitter.shared.send(
withEvent: .channel_manager_funding_generation_ready,
body: [
"temp_channel_id": Data(fundingGeneration.getTemporaryChannelId().getA() ?? []).hexEncodedString(),
"output_script": Data(fundingGeneration.getOutputScript()).hexEncodedString(),
"user_channel_id": Data(fundingGeneration.getUserChannelId()).hexEncodedString(),
"value_satoshis": fundingGeneration.getChannelValueSatoshis(),
"value_satoshis": fundingGeneration.getChannelValueSatoshis()
]
)
return
Expand Down Expand Up @@ -60,7 +60,7 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister {
body: body
)

//Save to disk for TX history
// Save to disk for TX history
persistPaymentClaimed(body)
return
case .PaymentSent:
Expand All @@ -82,11 +82,11 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister {
body: body
)

//Save to disk for tx history
// Save to disk for tx history
persistPaymentSent(body)
return
case .OpenChannelRequest:
//Use if we ever manually accept inbound channels. Setting in initConfig.
// Use if we ever manually accept inbound channels. Setting in initConfig.
guard let openChannelRequest = event.getValueAsOpenChannelRequest() else {
return handleEventError(event)
}
Expand All @@ -100,7 +100,7 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister {
"requires_zero_conf": openChannelRequest.getChannelType().requiresZeroConf(),
"supports_zero_conf": openChannelRequest.getChannelType().supportsZeroConf(),
"requires_anchors_zero_fee_htlc_tx": openChannelRequest.getChannelType().requiresAnchorsZeroFeeHtlcTx()
] as [String : Any]
] as [String: Any]
)
return
case .PaymentPathSuccessful:
Expand All @@ -116,8 +116,8 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister {
body: [
"payment_id": paymentId,
"payment_hash": paymentHash,
"path_hops": paymentPathSuccessful.getPath().getHops().map { $0.asJson },
] as [String : Any]
"path_hops": paymentPathSuccessful.getPath().getHops().map { $0.asJson }
] as [String: Any]
)
return
case .PaymentPathFailed:
Expand All @@ -136,15 +136,15 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister {
"payment_failed_permanently": paymentPathFailed.getPaymentFailedPermanently(),
"short_channel_id": String(paymentPathFailed.getShortChannelId() ?? 0),
"path_hops": paymentPathFailed.getPath().getHops().map { $0.asJson }
] as [String : Any]
] as [String: Any]
)

persistPaymentSent(
[
"payment_id": paymentId,
"payment_hash": paymentHash,
"unix_timestamp": Int(Date().timeIntervalSince1970),
"state": paymentPathFailed.getPaymentFailedPermanently() ? "failed" : "pending"
"state": paymentPathFailed.getPaymentFailedPermanently() ? "failed" : "pending"
]
)
return
Expand All @@ -160,23 +160,23 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister {
withEvent: .channel_manager_payment_failed,
body: [
"payment_id": paymentId,
"payment_hash": paymentHash,
"payment_hash": paymentHash
]
)

//MARK: Mark as failed
// MARK: Mark as failed

persistPaymentSent(
[
"payment_id": paymentId,
"payment_hash": paymentHash,
"unix_timestamp": Int(Date().timeIntervalSince1970),
"state": "failed"
"state": "failed"
]
)
return
case .PaymentForwarded:
//Unused on mobile
// Unused on mobile
return
case .PendingHTLCsForwardable:
guard let pendingHtlcsForwardable = event.getValueAsPendingHtlcsForwardable() else {
Expand All @@ -186,7 +186,7 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister {
LdkEventEmitter.shared.send(
withEvent: .channel_manager_pending_htlcs_forwardable,
body: [
"time_forwardable": pendingHtlcsForwardable.getTimeForwardable(),
"time_forwardable": pendingHtlcsForwardable.getTimeForwardable()
]
)
return
Expand All @@ -198,7 +198,7 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister {
LdkEventEmitter.shared.send(
withEvent: .channel_manager_spendable_outputs,
body: [
"outputsSerialized": spendableOutputs.getOutputs().map { Data($0.write()).hexEncodedString() },
"outputsSerialized": spendableOutputs.getOutputs().map { Data($0.write()).hexEncodedString() }
]
)
return
Expand All @@ -208,13 +208,16 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister {
}

let reasonString: String
var peerMessage: String? = nil

switch channelClosed.getReason().getValueType() {
case .CommitmentTxConfirmed:
reasonString = "CommitmentTxConfirmed"
case .CounterpartyCoopClosedUnfundedChannel:
reasonString = "CounterpartyCoopClosedUnfundedChannel"
case .CounterpartyForceClosed:
reasonString = "CounterpartyForceClosed"
peerMessage = channelClosed.getReason().getValueAsCounterpartyForceClosed()?.getPeerMsg().getA()
case .DisconnectedPeer:
reasonString = "DisconnectedPeer"
case .FundingBatchClosure:
Expand Down Expand Up @@ -244,17 +247,18 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister {
body: [
"user_channel_id": Data(channelClosed.getUserChannelId()).hexEncodedString(),
"channel_id": Data(channelClosed.getChannelId().getA() ?? []).hexEncodedString(),
"reason": reasonString
"reason": reasonString,
"peer_message": peerMessage
]
)

return
case .DiscardFunding:
guard let discardFunding = event.getValueAsDiscardFunding() else {
return handleEventError(event)
}

//Wallet should probably "lock" the UTXOs spent in funding transactions until the funding transaction either confirms, or this event is generated.
// Wallet should probably "lock" the UTXOs spent in funding transactions until the funding transaction either confirms, or this event is generated.
LdkEventEmitter.shared.send(
withEvent: .channel_manager_discard_funding,
body: [
Expand Down Expand Up @@ -287,7 +291,7 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister {
body: body
)

//Save to disk for TX history
// Save to disk for TX history
persistPaymentClaimed(body)
return
case .ChannelReady:
Expand All @@ -300,7 +304,7 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister {
guard let bumpTransaction = event.getValueAsBumpTransaction() else {
return handleEventError(event)
}

LdkEventEmitter.shared.send(withEvent: .native_log, body: "BumpTransaction request")

if let channelClose = bumpTransaction.getValueAsChannelClose() {
Expand All @@ -309,11 +313,11 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister {
"commitment_tx_fee": channelClose.getCommitmentTxFeeSatoshis(),
"pending_htlcs_count": channelClose.getPendingHtlcs().count
]

LdkEventEmitter.shared.send(withEvent: .lsp_log, body: body)
return
}

LdkEventEmitter.shared.send(withEvent: .native_log, body: "BumpTransaction event not handled")
return
case .ProbeFailed:
Expand Down Expand Up @@ -413,23 +417,23 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister {
}
}

//Replace entry if payment hash exists (Confirmed payment replacing pending)
// Replace entry if payment hash exists (Confirmed payment replacing pending)
var paymentReplaced = false
for (index, existingPayment) in payments.enumerated() {
if let existingPaymentHash = existingPayment["payment_hash"] as? String, let newPaymentHash = payment["payment_hash"] as? String {
if existingPaymentHash == newPaymentHash {
//Don't replace a successful payment. If a 2nd wallet tries to pay an invoice the first successful one should not be overwritten.
// Don't replace a successful payment. If a 2nd wallet tries to pay an invoice the first successful one should not be overwritten.
if existingPayment["state"] as? String == "successful" {
return
}
payments[index] = mergeObj(payments[index], payment) //Merges update into orginal entry

payments[index] = mergeObj(payments[index], payment) // Merges update into orginal entry
paymentReplaced = true
}
}
}

//No existing payment found, append as new payment
// No existing payment found, append as new payment
if !paymentReplaced {
payments.append(payment)
}
Expand Down Expand Up @@ -472,18 +476,18 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister {
}
}

//Replace entry if payment hash exists (Confirmed payment replacing pending)
// Replace entry if payment hash exists (Confirmed payment replacing pending)
var paymentReplaced = false
for (index, existingPayment) in payments.enumerated() {
if let existingPaymentId = existingPayment["payment_id"] as? String, let newPaymentId = payment["payment_id"] as? String {
if existingPaymentId == newPaymentId {
payments[index] = mergeObj(payments[index], payment) //Merges update into orginal entry
payments[index] = mergeObj(payments[index], payment) // Merges update into orginal entry
paymentReplaced = true
}
}
}

//No existing payment found, append as new payment
// No existing payment found, append as new payment
if !paymentReplaced {
payments.append(payment)
}
Expand Down
19 changes: 19 additions & 0 deletions lib/ios/Ldk.swift
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,25 @@ class Ldk: NSObject {
return resolve(Data(res.getValue()?.getA() ?? []).hexEncodedString())
}

if let error = res.getError() {
switch error.getValueType() {
case .APIMisuseError:
return handleReject(reject, .start_create_channel_fail, nil, error.getValueAsApiMisuseError()?.getErr())
case .ChannelUnavailable:
return handleReject(reject, .start_create_channel_fail, nil, error.getValueAsChannelUnavailable()?.getErr())
case .FeeRateTooHigh:
return handleReject(reject, .start_create_channel_fail, nil, error.getValueAsFeeRateTooHigh()?.getErr())
case .InvalidRoute:
return handleReject(reject, .start_create_channel_fail, nil, error.getValueAsInvalidRoute()?.getErr())
case .IncompatibleShutdownScript:
return handleReject(reject, .start_create_channel_fail, nil, "IncompatibleShutdownScript")
case .MonitorUpdateInProgress:
return handleReject(reject, .start_create_channel_fail, nil, "MonitorUpdateInProgress")
@unknown default:
handleReject(reject, .start_create_channel_fail, "Unhandled error")
}
}

handleReject(reject, .start_create_channel_fail)
ovitrif marked this conversation as resolved.
Show resolved Hide resolved
}

Expand Down
2 changes: 1 addition & 1 deletion lib/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@synonymdev/react-native-ldk",
"title": "React Native LDK",
"version": "0.0.151",
"version": "0.0.152",
"description": "React Native wrapper for LDK",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
Expand Down
10 changes: 8 additions & 2 deletions lib/src/lightning-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
TCreatePaymentReq,
TBackupServerDetails,
IAddress,
TLspLogPayload,

Check warning on line 58 in lib/src/lightning-manager.ts

View workflow job for this annotation

GitHub Actions / Run lint check

'TLspLogPayload' is defined but never used

Check warning on line 58 in lib/src/lightning-manager.ts

View workflow job for this annotation

GitHub Actions / Run lint check

'TLspLogPayload' is defined but never used

Check warning on line 58 in lib/src/lightning-manager.ts

View workflow job for this annotation

GitHub Actions / e2e-ios

'TLspLogPayload' is defined but never used

Check warning on line 58 in lib/src/lightning-manager.ts

View workflow job for this annotation

GitHub Actions / e2e-android

'TLspLogPayload' is defined but never used
TLspLogEvent,
TChannelMonitor,
TCreateChannelReq,
Expand Down Expand Up @@ -2183,7 +2183,7 @@
}

private onChannelManagerPendingHtlcsForwardable(
res: TChannelManagerPendingHtlcsForwardable,

Check warning on line 2186 in lib/src/lightning-manager.ts

View workflow job for this annotation

GitHub Actions / Run lint check

'res' is defined but never used. Allowed unused args must match /^_/u

Check warning on line 2186 in lib/src/lightning-manager.ts

View workflow job for this annotation

GitHub Actions / Run lint check

'res' is defined but never used. Allowed unused args must match /^_/u

Check warning on line 2186 in lib/src/lightning-manager.ts

View workflow job for this annotation

GitHub Actions / e2e-ios

'res' is defined but never used. Allowed unused args must match /^_/u

Check warning on line 2186 in lib/src/lightning-manager.ts

View workflow job for this annotation

GitHub Actions / e2e-android

'res' is defined but never used. Allowed unused args must match /^_/u
): void {
ldk.processPendingHtlcForwards().catch(console.error);
}
Expand Down Expand Up @@ -2446,10 +2446,10 @@
return err(res.error);
}

return new Promise((resolve, reject) => {

Check warning on line 2449 in lib/src/lightning-manager.ts

View workflow job for this annotation

GitHub Actions / Run lint check

'reject' is defined but never used. Allowed unused args must match /^_/u

Check warning on line 2449 in lib/src/lightning-manager.ts

View workflow job for this annotation

GitHub Actions / Run lint check

'reject' is defined but never used. Allowed unused args must match /^_/u

Check warning on line 2449 in lib/src/lightning-manager.ts

View workflow job for this annotation

GitHub Actions / e2e-ios

'reject' is defined but never used. Allowed unused args must match /^_/u

Check warning on line 2449 in lib/src/lightning-manager.ts

View workflow job for this annotation

GitHub Actions / e2e-android

'reject' is defined but never used. Allowed unused args must match /^_/u
// Channel funding ready event should be instant but if it fails and we don't get the event, we should reject.
const timeout = setTimeout(() => {
reject(err(new Error('Event not triggered within 5 seconds')));
resolve(err(new Error('Event not triggered within 5 seconds')));
}, 5000);

// Listen for the event for the channel funding details
Expand All @@ -2465,8 +2465,14 @@
EEventTypes.channel_manager_channel_closed,
(eventRes: TChannelManagerChannelClosed) => {
if (eventRes.channel_id === res.value) {

clearTimeout(timeout);
reject(err('Channel closed before funding'));
if (eventRes.peer_message) {
resolve(err(eventRes.peer_message));
return;
}

resolve(err(`Channel open failed: ${eventRes.reason}`));
}
},
);
Expand Down
1 change: 1 addition & 0 deletions lib/src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ export type TChannelManagerChannelClosed = {
user_channel_id: string;
channel_id: string;
reason: string;
peer_message?: string;
};

export type TChannelManagerDiscardFunding = {
Expand Down
Loading