Skip to content

Commit 634ce3e

Browse files
committed
Expose wallet get_transaction_details
1 parent 754a1bd commit 634ce3e

File tree

11 files changed

+228
-0
lines changed

11 files changed

+228
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
transaction information in onchain events, including inputs and outputs. This enables
2020
applications to analyze transaction data themselves to detect channel funding, closures,
2121
and other transaction types.
22+
- Added `Node::get_transaction_details()` method to retrieve transaction details for any
23+
transaction ID that exists in the wallet, returning `None` if the transaction is not found.
2224
- Added `SyncType` enum to distinguish between onchain wallet sync, Lightning
2325
wallet sync, and fee rate cache updates.
2426
- Balance tracking is now persisted in `NodeMetrics` to detect changes across restarts.

MOBILE_DEVELOPER_GUIDE.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,25 @@ The `TransactionDetails` struct provides comprehensive information about transac
114114

115115
**Note**: You can analyze transaction inputs and outputs to detect channel funding, channel closures, and other transaction types. This provides more flexibility than the previous `TransactionContext` enum.
116116

117+
#### Retrieving Transaction Details
118+
119+
You can also retrieve transaction details directly using `Node::get_transaction_details()`:
120+
121+
```swift
122+
// Get transaction details for a specific transaction ID
123+
if let details = node.getTransactionDetails(txid: txid) {
124+
// Analyze the transaction details
125+
print("Transaction amount: \(details.amountSats) sats")
126+
print("Number of inputs: \(details.inputs.count)")
127+
print("Number of outputs: \(details.outputs.count)")
128+
} else {
129+
// Transaction not found in wallet
130+
print("Transaction not found")
131+
}
132+
```
133+
134+
This method returns `nil` if the transaction is not found in the wallet.
135+
117136
---
118137

119138
## iOS/Swift Implementation
@@ -544,6 +563,11 @@ class TransactionNotificationManager(private val context: Context) {
544563
}
545564
}
546565

566+
// Retrieve transaction details directly
567+
fun getTransactionDetails(txid: String): TransactionDetails? {
568+
return node.getTransactionDetails(txid = txid)
569+
}
570+
547571
// Helper functions to analyze transaction details
548572
private fun isChannelFundingTransaction(details: TransactionDetails): Boolean {
549573
// Analyze inputs/outputs to detect channel funding
Binary file not shown.
Binary file not shown.
Binary file not shown.

bindings/kotlin/ldk-node-android/lib/src/main/kotlin/org/lightningdevkit/ldknode/ldk_node.android.kt

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,6 +1345,8 @@ internal typealias UniffiVTableCallbackInterfaceVssHeaderProviderUniffiByValue =
13451345

13461346

13471347

1348+
1349+
13481350

13491351

13501352

@@ -1918,6 +1920,11 @@ internal interface UniffiLib : Library {
19181920
`reason`: RustBufferByValue,
19191921
uniffiCallStatus: UniffiRustCallStatus,
19201922
): Unit
1923+
fun uniffi_ldk_node_fn_method_node_get_transaction_details(
1924+
`ptr`: Pointer?,
1925+
`txid`: RustBufferByValue,
1926+
uniffiCallStatus: UniffiRustCallStatus,
1927+
): RustBufferByValue
19211928
fun uniffi_ldk_node_fn_method_node_list_balances(
19221929
`ptr`: Pointer?,
19231930
uniffiCallStatus: UniffiRustCallStatus,
@@ -2547,6 +2554,8 @@ internal interface UniffiLib : Library {
25472554
): Short
25482555
fun uniffi_ldk_node_checksum_method_node_force_close_channel(
25492556
): Short
2557+
fun uniffi_ldk_node_checksum_method_node_get_transaction_details(
2558+
): Short
25502559
fun uniffi_ldk_node_checksum_method_node_list_balances(
25512560
): Short
25522561
fun uniffi_ldk_node_checksum_method_node_list_channels(
@@ -2899,6 +2908,9 @@ private fun uniffiCheckApiChecksums(lib: UniffiLib) {
28992908
if (lib.uniffi_ldk_node_checksum_method_node_force_close_channel() != 48831.toShort()) {
29002909
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
29012910
}
2911+
if (lib.uniffi_ldk_node_checksum_method_node_get_transaction_details() != 65000.toShort()) {
2912+
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
2913+
}
29022914
if (lib.uniffi_ldk_node_checksum_method_node_list_balances() != 57528.toShort()) {
29032915
throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project")
29042916
}
@@ -5601,6 +5613,18 @@ open class Node: Disposable, NodeInterface {
56015613
}
56025614
}
56035615

5616+
override fun `getTransactionDetails`(`txid`: Txid): TransactionDetails? {
5617+
return FfiConverterOptionalTypeTransactionDetails.lift(callWithPointer {
5618+
uniffiRustCall { uniffiRustCallStatus ->
5619+
UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_get_transaction_details(
5620+
it,
5621+
FfiConverterTypeTxid.lower(`txid`),
5622+
uniffiRustCallStatus,
5623+
)
5624+
}
5625+
})
5626+
}
5627+
56045628
override fun `listBalances`(): BalanceDetails {
56055629
return FfiConverterTypeBalanceDetails.lift(callWithPointer {
56065630
uniffiRustCall { uniffiRustCallStatus ->
@@ -10344,6 +10368,35 @@ object FfiConverterOptionalTypeSendingParameters: FfiConverterRustBuffer<Sending
1034410368

1034510369

1034610370

10371+
object FfiConverterOptionalTypeTransactionDetails: FfiConverterRustBuffer<TransactionDetails?> {
10372+
override fun read(buf: ByteBuffer): TransactionDetails? {
10373+
if (buf.get().toInt() == 0) {
10374+
return null
10375+
}
10376+
return FfiConverterTypeTransactionDetails.read(buf)
10377+
}
10378+
10379+
override fun allocationSize(value: TransactionDetails?): ULong {
10380+
if (value == null) {
10381+
return 1UL
10382+
} else {
10383+
return 1UL + FfiConverterTypeTransactionDetails.allocationSize(value)
10384+
}
10385+
}
10386+
10387+
override fun write(value: TransactionDetails?, buf: ByteBuffer) {
10388+
if (value == null) {
10389+
buf.put(0)
10390+
} else {
10391+
buf.put(1)
10392+
FfiConverterTypeTransactionDetails.write(value, buf)
10393+
}
10394+
}
10395+
}
10396+
10397+
10398+
10399+
1034710400
object FfiConverterOptionalTypeClosureReason: FfiConverterRustBuffer<ClosureReason?> {
1034810401
override fun read(buf: ByteBuffer): ClosureReason? {
1034910402
if (buf.get().toInt() == 0) {

bindings/kotlin/ldk-node-android/lib/src/main/kotlin/org/lightningdevkit/ldknode/ldk_node.common.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,8 @@ interface NodeInterface {
364364
@Throws(NodeException::class)
365365
fun `forceCloseChannel`(`userChannelId`: UserChannelId, `counterpartyNodeId`: PublicKey, `reason`: kotlin.String?)
366366

367+
fun `getTransactionDetails`(`txid`: Txid): TransactionDetails?
368+
367369
fun `listBalances`(): BalanceDetails
368370

369371
fun `listChannels`(): List<ChannelDetails>
@@ -1909,6 +1911,8 @@ sealed class VssHeaderProviderException(message: String): kotlin.Exception(messa
19091911

19101912

19111913

1914+
1915+
19121916

19131917

19141918

bindings/ldk_node.udl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ interface Node {
126126
Bolt12Payment bolt12_payment();
127127
SpontaneousPayment spontaneous_payment();
128128
OnchainPayment onchain_payment();
129+
TransactionDetails? get_transaction_details([ByRef]Txid txid);
129130
UnifiedQrPayment unified_qr_payment();
130131
LSPS1Liquidity lsps1_liquidity();
131132
[Throws=NodeError]

bindings/swift/Sources/LDKNode/LDKNode.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1937,6 +1937,8 @@ public protocol NodeProtocol: AnyObject {
19371937

19381938
func forceCloseChannel(userChannelId: UserChannelId, counterpartyNodeId: PublicKey, reason: String?) throws
19391939

1940+
func getTransactionDetails(txid: Txid) -> TransactionDetails?
1941+
19401942
func listBalances() -> BalanceDetails
19411943

19421944
func listChannels() -> [ChannelDetails]
@@ -2094,6 +2096,13 @@ open class Node:
20942096
}
20952097
}
20962098

2099+
open func getTransactionDetails(txid: Txid) -> TransactionDetails? {
2100+
return try! FfiConverterOptionTypeTransactionDetails.lift(try! rustCall {
2101+
uniffi_ldk_node_fn_method_node_get_transaction_details(self.uniffiClonePointer(),
2102+
FfiConverterTypeTxid.lower(txid), $0)
2103+
})
2104+
}
2105+
20972106
open func listBalances() -> BalanceDetails {
20982107
return try! FfiConverterTypeBalanceDetails.lift(try! rustCall {
20992108
uniffi_ldk_node_fn_method_node_list_balances(self.uniffiClonePointer(), $0)
@@ -7821,6 +7830,27 @@ private struct FfiConverterOptionTypeSendingParameters: FfiConverterRustBuffer {
78217830
}
78227831
}
78237832

7833+
private struct FfiConverterOptionTypeTransactionDetails: FfiConverterRustBuffer {
7834+
typealias SwiftType = TransactionDetails?
7835+
7836+
static func write(_ value: SwiftType, into buf: inout [UInt8]) {
7837+
guard let value = value else {
7838+
writeInt(&buf, Int8(0))
7839+
return
7840+
}
7841+
writeInt(&buf, Int8(1))
7842+
FfiConverterTypeTransactionDetails.write(value, into: &buf)
7843+
}
7844+
7845+
static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> SwiftType {
7846+
switch try readInt(&buf) as Int8 {
7847+
case 0: return nil
7848+
case 1: return try FfiConverterTypeTransactionDetails.read(from: &buf)
7849+
default: throw UniffiInternalError.unexpectedOptionalTag
7850+
}
7851+
}
7852+
}
7853+
78247854
private struct FfiConverterOptionTypeClosureReason: FfiConverterRustBuffer {
78257855
typealias SwiftType = ClosureReason?
78267856

@@ -9568,6 +9598,9 @@ private var initializationResult: InitializationResult {
95689598
if uniffi_ldk_node_checksum_method_node_force_close_channel() != 48831 {
95699599
return InitializationResult.apiChecksumMismatch
95709600
}
9601+
if uniffi_ldk_node_checksum_method_node_get_transaction_details() != 65000 {
9602+
return InitializationResult.apiChecksumMismatch
9603+
}
95719604
if uniffi_ldk_node_checksum_method_node_list_balances() != 57528 {
95729605
return InitializationResult.apiChecksumMismatch
95739606
}

src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,14 @@ impl Node {
10121012
))
10131013
}
10141014

1015+
/// Returns transaction details for the given transaction ID, if available in the wallet.
1016+
///
1017+
/// Returns `None` if the transaction is not found in the wallet.
1018+
pub fn get_transaction_details(&self, txid: &bitcoin::Txid) -> Option<TransactionDetails> {
1019+
let (amount_sats, inputs, outputs) = self.wallet.get_tx_details(txid)?;
1020+
Some(TransactionDetails { amount_sats, inputs, outputs })
1021+
}
1022+
10151023
/// Returns a payment handler allowing to create [BIP 21] URIs with an on-chain, [BOLT 11],
10161024
/// and [BOLT 12] payment options.
10171025
///

0 commit comments

Comments
 (0)