From 98e7381cc76864b12ddb6fc8b57ded968a9b448e Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 20 Sep 2024 10:50:41 +0200 Subject: [PATCH 1/4] fix: gets peer message when manual open channel fails --- .../main/java/com/reactnativeldk/LdkModule.kt | 38 ++++++++++- .../classes/LdkChannelManagerPersister.kt | 8 +++ .../Classes/LdkChannelManagerPersister.swift | 68 ++++++++++--------- lib/ios/Ldk.swift | 19 ++++++ lib/package.json | 2 +- lib/src/lightning-manager.ts | 10 ++- lib/src/utils/types.ts | 1 + 7 files changed, 108 insertions(+), 38 deletions(-) diff --git a/lib/android/src/main/java/com/reactnativeldk/LdkModule.kt b/lib/android/src/main/java/com/reactnativeldk/LdkModule.kt index fc869b0a..2465ea45 100644 --- a/lib/android/src/main/java/com/reactnativeldk/LdkModule.kt +++ b/lib/android/src/main/java/com/reactnativeldk/LdkModule.kt @@ -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 @@ -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 @@ -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) } @ReactMethod diff --git a/lib/android/src/main/java/com/reactnativeldk/classes/LdkChannelManagerPersister.kt b/lib/android/src/main/java/com/reactnativeldk/classes/LdkChannelManagerPersister.kt index 90f3345d..71ecb7af 100644 --- a/lib/android/src/main/java/com/reactnativeldk/classes/LdkChannelManagerPersister.kt +++ b/lib/android/src/main/java/com/reactnativeldk/classes/LdkChannelManagerPersister.kt @@ -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) } diff --git a/lib/ios/Classes/LdkChannelManagerPersister.swift b/lib/ios/Classes/LdkChannelManagerPersister.swift index b7ff3765..509413c8 100644 --- a/lib/ios/Classes/LdkChannelManagerPersister.swift +++ b/lib/ios/Classes/LdkChannelManagerPersister.swift @@ -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, @@ -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 @@ -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: @@ -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) } @@ -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: @@ -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: @@ -136,7 +136,7 @@ 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( @@ -144,7 +144,7 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister { "payment_id": paymentId, "payment_hash": paymentHash, "unix_timestamp": Int(Date().timeIntervalSince1970), - "state": paymentPathFailed.getPaymentFailedPermanently() ? "failed" : "pending" + "state": paymentPathFailed.getPaymentFailedPermanently() ? "failed" : "pending" ] ) return @@ -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 { @@ -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 @@ -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 @@ -208,6 +208,8 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister { } let reasonString: String + var peerMessage: String? = nil + switch channelClosed.getReason().getValueType() { case .CommitmentTxConfirmed: reasonString = "CommitmentTxConfirmed" @@ -215,6 +217,7 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister { reasonString = "CounterpartyCoopClosedUnfundedChannel" case .CounterpartyForceClosed: reasonString = "CounterpartyForceClosed" + peerMessage = channelClosed.getReason().getValueAsCounterpartyForceClosed()?.getPeerMsg().getA() case .DisconnectedPeer: reasonString = "DisconnectedPeer" case .FundingBatchClosure: @@ -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: [ @@ -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: @@ -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() { @@ -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: @@ -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) } @@ -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) } diff --git a/lib/ios/Ldk.swift b/lib/ios/Ldk.swift index 7f16ff7d..d98fc0b6 100644 --- a/lib/ios/Ldk.swift +++ b/lib/ios/Ldk.swift @@ -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) } diff --git a/lib/package.json b/lib/package.json index 8244781d..bb4c74e1 100644 --- a/lib/package.json +++ b/lib/package.json @@ -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", diff --git a/lib/src/lightning-manager.ts b/lib/src/lightning-manager.ts index 98038539..cbc1a80f 100644 --- a/lib/src/lightning-manager.ts +++ b/lib/src/lightning-manager.ts @@ -2449,7 +2449,7 @@ class LightningManager { return new Promise((resolve, reject) => { // 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 @@ -2465,8 +2465,14 @@ class LightningManager { 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}`)); } }, ); diff --git a/lib/src/utils/types.ts b/lib/src/utils/types.ts index a011cd4d..c43dae07 100644 --- a/lib/src/utils/types.ts +++ b/lib/src/utils/types.ts @@ -134,6 +134,7 @@ export type TChannelManagerChannelClosed = { user_channel_id: string; channel_id: string; reason: string; + peer_message?: string; }; export type TChannelManagerDiscardFunding = { From 5b9154acc944b4d8cdd07cca0d5dc4aab9fc4078 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 23 Sep 2024 17:26:23 +0200 Subject: [PATCH 2/4] chore: kotlin error handling cleanup --- .../main/java/com/reactnativeldk/LdkModule.kt | 36 +++++-------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/lib/android/src/main/java/com/reactnativeldk/LdkModule.kt b/lib/android/src/main/java/com/reactnativeldk/LdkModule.kt index 2465ea45..51dcc560 100644 --- a/lib/android/src/main/java/com/reactnativeldk/LdkModule.kt +++ b/lib/android/src/main/java/com/reactnativeldk/LdkModule.kt @@ -798,35 +798,17 @@ class LdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMod 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)) + 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 } - 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)) - } - - return handleReject(promise, LdkErrors.start_create_channel_fail) + return handleReject(promise, LdkErrors.start_create_channel_fail, failure) } @ReactMethod From 62708914bebefbadbae0da18f898d78b3fbc1913 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 23 Sep 2024 17:53:43 +0200 Subject: [PATCH 3/4] fix: reset backgroundedAt correctly --- lib/ios/Ldk.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/ios/Ldk.swift b/lib/ios/Ldk.swift index d98fc0b6..7cb441c1 100644 --- a/lib/ios/Ldk.swift +++ b/lib/ios/Ldk.swift @@ -532,6 +532,8 @@ 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 @@ -539,7 +541,6 @@ class Ldk: NSObject { 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 } } @@ -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) From 49502a3d967fc9c4f84be38262e941ac90b9b71c Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 25 Sep 2024 13:50:15 +0200 Subject: [PATCH 4/4] fix: android channel details confirmations value --- lib/android/src/main/java/com/reactnativeldk/Helpers.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/android/src/main/java/com/reactnativeldk/Helpers.kt b/lib/android/src/main/java/com/reactnativeldk/Helpers.kt index 1e68888b..8d2e6187 100644 --- a/lib/android/src/main/java/com/reactnativeldk/Helpers.kt +++ b/lib/android/src/main/java/com/reactnativeldk/Helpers.kt @@ -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 }