Skip to content

Commit

Permalink
Merge pull request #272 from synonymdev/open-channe-error
Browse files Browse the repository at this point in the history
fix: gets peer message when manual open channel fails
  • Loading branch information
Jasonvdb authored Sep 25, 2024
2 parents f4b580e + 49502a3 commit 452c098
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 40 deletions.
2 changes: 1 addition & 1 deletion lib/android/src/main/java/com/reactnativeldk/Helpers.kt
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ val ChannelDetails.asJson: WritableMap
result.putInt("unspendable_punishment_reserve", (_unspendable_punishment_reserve as Option_u64Z.Some).some.toInt())
result.putInt("config_forwarding_fee_base_msat", (_config?._forwarding_fee_base_msat ?: 0))
result.putInt("config_forwarding_fee_proportional_millionths", (_config?._forwarding_fee_proportional_millionths ?: 0))
result.putInt("confirmations", (_confirmations_required as Option_u32Z.Some).some)
result.putInt("confirmations", (_confirmations as Option_u32Z.Some).some)

return result
}
Expand Down
20 changes: 17 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,21 @@ 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())
}

val failure = when(val error = (res as? Result_ChannelIdAPIErrorZ.Result_ChannelIdAPIErrorZ_Err)?.err) {
is APIError.APIMisuseError -> Error(error.err)
is APIError.ChannelUnavailable -> Error(error.err)
is APIError.FeeRateTooHigh -> Error(error.err)
is APIError.InvalidRoute -> Error(error.err)
is APIError.IncompatibleShutdownScript -> Error("IncompatibleShutdownScript")
is APIError.MonitorUpdateInProgress -> Error("MonitorUpdateInProgress")
else -> null
}

handleResolve(promise, LdkCallbackResponses.start_create_channel_fail)
return handleReject(promise, LdkErrors.start_create_channel_fail, failure)
}

@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
27 changes: 26 additions & 1 deletion lib/ios/Ldk.swift
Original file line number Diff line number Diff line change
Expand Up @@ -532,14 +532,15 @@ class Ldk: NSObject {
@objc
func restartOnForeground() {
let secondsSinceBackgrounded = Date().timeIntervalSince(backgroundedAt ?? .distantPast)
backgroundedAt = nil

guard secondsSinceBackgrounded > 5 else {
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Skipping restart. App was only backgrounded \(Int(secondsSinceBackgrounded))s ago")
return
}

LdkEventEmitter.shared.send(withEvent: .native_log, body: "Restarting LDK on move to foreground. App was backgrounded \(Int(secondsSinceBackgrounded))s ago")

backgroundedAt = nil
restart { _ in } reject: { _, _, _ in }
}

Expand Down Expand Up @@ -729,6 +730,11 @@ class Ldk: NSObject {
func addPeer(_ address: NSString, port: NSInteger, pubKey: NSString, timeout: NSInteger, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
// timeout param not used. Only for android.

if backgroundedAt != nil {
// Give it a second maybe it's just restarting
sleep(1)
}

guard backgroundedAt == nil else {
LdkEventEmitter.shared.send(withEvent: .native_log, body: "App was backgrounded, skipping addPeer()")
return handleResolve(resolve, .add_peer_skipped)
Expand Down Expand Up @@ -937,6 +943,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)
}

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
Loading

0 comments on commit 452c098

Please sign in to comment.