Skip to content
This repository was archived by the owner on Feb 9, 2026. It is now read-only.

Commit 241e106

Browse files
committed
Write payments claimed to file natively
1 parent c11744a commit 241e106

6 files changed

Lines changed: 98 additions & 37 deletions

File tree

lib/android/src/main/java/com/reactnativeldk/LdkModule.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ enum class LdkCallbackResponses {
111111
enum class LdkFileNames(val fileName: String) {
112112
network_graph("network_graph.bin"),
113113
channel_manager("channel_manager.bin"),
114-
scorer("scorer.bin")
114+
scorer("scorer.bin"),
115+
paymentsClaimed("payments_claimed.json"),
115116
}
116117

117118
class LdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {

lib/android/src/main/java/com/reactnativeldk/classes/LdkChannelManagerPersister.kt

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package com.reactnativeldk.classes
22

33
import com.facebook.react.bridge.Arguments
4+
import com.facebook.react.bridge.WritableMap
45
import com.reactnativeldk.*
6+
import org.json.JSONArray
57
import org.ldk.batteries.ChannelManagerConstructor
68
import org.ldk.structs.Event
79
import org.ldk.structs.Option_u64Z
@@ -132,6 +134,9 @@ class LdkChannelManagerPersister: ChannelManagerConstructor.EventHandler {
132134
(paymentClaimed.purpose as? PaymentPurpose.SpontaneousPayment)?.let {
133135
body.putHexString("spontaneous_payment_preimage", it.spontaneous_payment)
134136
}
137+
body.putInt("unix_timestamp", (System.currentTimeMillis() / 1000).toInt())
138+
139+
persistPaymentClaimed(body)
135140
return LdkEventEmitter.send(EventTypes.channel_manager_payment_claimed, body)
136141
}
137142
}
@@ -159,4 +164,38 @@ class LdkChannelManagerPersister: ChannelManagerConstructor.EventHandler {
159164
LdkEventEmitter.send(EventTypes.native_log, "Persisted scorer to disk")
160165
}
161166
}
167+
168+
private fun persistPaymentClaimed(payment: WritableMap) {
169+
if (LdkModule.accountStoragePath == "") {
170+
LdkEventEmitter.send(EventTypes.native_log, "Error. Failed to persist claimed payment to disk (No set storage)")
171+
return
172+
}
173+
174+
var newContent: Array<HashMap<String, Any>> = arrayOf()
175+
176+
try {
177+
if (File(LdkModule.accountStoragePath + "/" + LdkFileNames.paymentsClaimed.fileName).exists()) {
178+
val data = File(LdkModule.accountStoragePath + "/" + LdkFileNames.paymentsClaimed.fileName).readBytes()
179+
println(String(data))
180+
val existingContent = JSONArray(String(data))
181+
for (i in 0 until existingContent.length()) {
182+
val map = HashMap<String, Any>()
183+
for (key in existingContent.getJSONObject(i).keys()) {
184+
map[key] = existingContent.getJSONObject(i).get(key)
185+
}
186+
187+
newContent = newContent.plus(map)
188+
}
189+
}
190+
} catch (e: Exception) {
191+
LdkEventEmitter.send(EventTypes.native_log, "Error could not read exisitng claimed payments")
192+
}
193+
194+
newContent = newContent.plus(payment.toHashMap())
195+
196+
println("New content")
197+
newContent.iterator().forEach { println(it) }
198+
199+
File(LdkModule.accountStoragePath + "/" + LdkFileNames.paymentsClaimed.fileName).writeText(JSONArray(newContent).toString())
200+
}
162201
}

lib/ios/Classes/LdkChannelManagerPersister.swift

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -194,16 +194,22 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister {
194194
let paymentSecret = paymentClaimed.getPurpose().getValueAsInvoicePayment()?.getPaymentSecret()
195195
let spontaneousPayment = paymentClaimed.getPurpose().getValueAsSpontaneousPayment()
196196

197+
let body: [String: Encodable] = [
198+
"payment_hash": Data(paymentClaimed.getPaymentHash()).hexEncodedString(),
199+
"amount_sat": paymentClaimed.getAmountMsat() / 1000,
200+
"payment_preimage": Data(paymentPreimage ?? []).hexEncodedString(),
201+
"payment_secret": Data(paymentSecret ?? []).hexEncodedString(),
202+
"spontaneous_payment_preimage": Data(spontaneousPayment ?? []).hexEncodedString(),
203+
"unix_timestamp": Int(Date().timeIntervalSince1970)
204+
]
205+
197206
LdkEventEmitter.shared.send(
198207
withEvent: .channel_manager_payment_claimed,
199-
body: [
200-
"payment_hash": Data(paymentClaimed.getPaymentHash()).hexEncodedString(),
201-
"amount_sat": paymentClaimed.getAmountMsat() / 1000,
202-
"payment_preimage": Data(paymentPreimage ?? []).hexEncodedString(),
203-
"payment_secret": Data(paymentSecret ?? []).hexEncodedString(),
204-
"spontaneous_payment_preimage": Data(spontaneousPayment ?? []).hexEncodedString(),
205-
]
208+
body: body
206209
)
210+
211+
//Save to disk for TX history
212+
persistPaymentClaimed(body)
207213
default:
208214
LdkEventEmitter.shared.send(withEvent: .native_log, body: "ERROR: unknown LdkChannelManagerPersister.handle_event type")
209215
}
@@ -217,7 +223,7 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister {
217223
do {
218224
try Data(channelManager.write()).write(to: managerStorage)
219225
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Persisted channel manager to disk")
220-
226+
221227
LdkEventEmitter.shared.send(withEvent: .backup, body: "")
222228

223229
return Result_NoneErrorZ.initWithOk()
@@ -231,11 +237,11 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister {
231237
guard let graphStorage = Ldk.accountStoragePath?.appendingPathComponent(LdkFileNames.network_graph.rawValue) else {
232238
return Result_NoneErrorZ.initWithErr(e: .Other)
233239
}
234-
240+
235241
do {
236242
try Data(networkGraph.write()).write(to: graphStorage)
237243
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Persisted network graph to disk")
238-
244+
239245
return Result_NoneErrorZ.initWithOk()
240246
} catch {
241247
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error. Failed to persist network graph to disk Error \(error.localizedDescription).")
@@ -247,14 +253,49 @@ class LdkChannelManagerPersister: Persister, ExtendedChannelManagerPersister {
247253
guard let scorerStorage = Ldk.accountStoragePath?.appendingPathComponent(LdkFileNames.scorer.rawValue) else {
248254
return Result_NoneErrorZ.initWithErr(e: .Other)
249255
}
250-
256+
251257
do {
252258
try Data(scorer.write()).write(to: scorerStorage)
253-
259+
254260
return Result_NoneErrorZ.initWithOk()
255261
} catch {
256262
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error. Failed to persist scorer to disk Error \(error.localizedDescription).")
257263
return Result_NoneErrorZ.initWithErr(e: .Other)
258264
}
259265
}
266+
267+
private func persistPaymentClaimed(_ payment: [String: Any]) {
268+
guard let claimedPaymentsStorage = Ldk.accountStoragePath?.appendingPathComponent(LdkFileNames.paymentsClaimed.rawValue) else {
269+
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error. Failed to persist claimed payment to disk (No set storage)")
270+
return
271+
}
272+
273+
var newContent: [[String: Any]] = []
274+
275+
do {
276+
if FileManager.default.fileExists(atPath: claimedPaymentsStorage.path) {
277+
let data = try Data(contentsOf: URL(fileURLWithPath: claimedPaymentsStorage.path), options: .mappedIfSafe)
278+
279+
if let existingContent = try JSONSerialization.jsonObject(with: data, options: []) as? [[String: Any]] {
280+
newContent = existingContent
281+
} else {
282+
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error could not read existing claimed payments")
283+
}
284+
}
285+
286+
newContent.append(payment)
287+
guard let jsonData = try? JSONSerialization.data(withJSONObject: newContent, options: []) else {
288+
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error could not serialize claimed payments")
289+
return
290+
}
291+
292+
guard let jsonString = String(data: jsonData, encoding: .utf8) else {
293+
return
294+
}
295+
296+
try jsonString.write(to: claimedPaymentsStorage, atomically: true, encoding: .utf8)
297+
} catch {
298+
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Error writing payment claimed to file: \(error)")
299+
}
300+
}
260301
}

lib/ios/Ldk.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ enum LdkFileNames: String {
9595
case network_graph = "network_graph.bin"
9696
case channel_manager = "channel_manager.bin"
9797
case scorer = "scorer.bin"
98+
case paymentsClaimed = "payments_claimed.json"
9899
}
99100

100101
@objc(Ldk)
@@ -125,7 +126,6 @@ class Ldk: NSObject {
125126
var currentBlockchainTipHash: NSString?
126127
var currentBlockchainHeight: NSInteger?
127128

128-
129129
//Static to be accessed from other classes
130130
static var accountStoragePath: URL?
131131
static var channelStoragePath: URL?

lib/src/lightning-manager.ts

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1207,26 +1207,6 @@ class LightningManager {
12071207
});
12081208
};
12091209

1210-
/**
1211-
* Adds payment claimed to storage.
1212-
* @param payment {@link TChannelManagerClaim}
1213-
* @returns void
1214-
*/
1215-
private appendLdkPaymentsClaimed = async (
1216-
payment: TChannelManagerClaim,
1217-
): Promise<void> => {
1218-
let paymentsClaimed = await this.getLdkPaymentsClaimed();
1219-
if (paymentsClaimed.includes(payment)) {
1220-
return;
1221-
}
1222-
1223-
paymentsClaimed.push(payment);
1224-
await ldk.writeToFile({
1225-
fileName: ELdkFiles.payments_claimed,
1226-
content: JSON.stringify(paymentsClaimed),
1227-
});
1228-
};
1229-
12301210
/**
12311211
* Returns the payments claimed in storage.
12321212
* @returns {@link TChannelManagerClaim[]}
@@ -1652,7 +1632,6 @@ class LightningManager {
16521632
res: TChannelManagerClaim,
16531633
): Promise<void> {
16541634
// Payment Received/Invoice Paid.
1655-
await this.appendLdkPaymentsClaimed(res);
16561635
console.log(`onChannelManagerPaymentClaimed: ${JSON.stringify(res)}`);
16571636
this.syncLdk().then();
16581637
}

lib/src/utils/types.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export type TChannelManagerClaim = {
5454
payment_preimage: string;
5555
payment_secret: string;
5656
spontaneous_payment_preimage: string;
57+
unix_timestamp: number;
5758
};
5859

5960
export type TChannelManagerPaymentSent = {
@@ -419,12 +420,12 @@ export enum ELdkFiles {
419420
seed = 'seed', //32 bytes of entropy saved natively
420421
channel_manager = 'channel_manager.bin', //Serialised rust object
421422
channels = 'channels', //Path containing multiple files of serialised channels
422-
peers = 'peers.json', //JSON file saved from JS
423+
peers = 'peers.json', //File saved from JS
423424
unconfirmed_transactions = 'unconfirmed_transactions.json',
424425
broadcasted_transactions = 'broadcasted_transactions.json',
425426
payment_ids = 'payment_ids.json',
426427
spendable_outputs = 'spendable_outputs.json',
427-
payments_claimed = 'payments_claimed.json', // JSON file saved from JS
428+
payments_claimed = 'payments_claimed.json', // Written in swift/kotlin and read from JS
428429
}
429430

430431
export enum ELdkData {

0 commit comments

Comments
 (0)