diff --git a/.gitignore b/.gitignore index 9d8b73d65..dfe51a623 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,8 @@ swift.swiftdoc # fork !/bindings/kotlin/ldk-node-android/lib/src/main/jniLibs !/bindings/kotlin/ldk-node-android/lib/src/main/kotlin/org/lightningdevkit/ldknode/ldk_node.kt +!/bindings/kotlin/ldk-node-jvm/lib/src/main/kotlin/org/lightningdevkit/ldknode/ldk_node.kt +!/bindings/kotlin/ldk-node-jvm/lib/src/main/resources/ # IDE and local files .idea @@ -38,3 +40,4 @@ swift.swiftdoc .cursor .claude *.local.* +.ai diff --git a/CHANGELOG.md b/CHANGELOG.md index e3f82a125..0cbd86faf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,11 @@ -# 0.7.0-rc.15 (Synonym Fork) +# 0.7.0-rc.16 (Synonym Fork) ## Bug Fixes - Fixed duplicate payment events (`PaymentReceived`, `PaymentSuccessful`, `PaymentFailed`) being emitted when LDK replays events after node restart. ## Synonym Fork Additions +- Added JitPack support for `ldk-node-jvm` module to enable unit testing in consuming apps - Added runtime-adjustable wallet sync intervals for battery optimization on mobile: - `RuntimeSyncIntervals` struct with configurable `onchain_wallet_sync_interval_secs`, `lightning_wallet_sync_interval_secs`, and `fee_rate_cache_update_interval_secs` diff --git a/Cargo.toml b/Cargo.toml index 9e7d218f3..1ea862e18 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ldk-node" -version = "0.7.0-rc.15" +version = "0.7.0-rc.16" authors = ["Elias Rohrer "] homepage = "https://lightningdevkit.org/" license = "MIT OR Apache-2.0" diff --git a/Package.swift b/Package.swift index 0db27a7d4..4f18fe075 100644 --- a/Package.swift +++ b/Package.swift @@ -3,8 +3,8 @@ import PackageDescription -let tag = "v0.7.0-rc.15" -let checksum = "34f5a8403ba9816893e416da93eefaabc6a3d9f25c7967d73a6094c9b8f45808" +let tag = "v0.7.0-rc.16" +let checksum = "5ca612e30639e86d4a215c7819d93e55aba3c9a9ea704a79ab18d6df78c38b32" let url = "https://github.com/synonymdev/ldk-node/releases/download/\(tag)/LDKNodeFFI.xcframework.zip" let package = Package( diff --git a/bindings/README.md b/bindings/README.md index 045fd91b2..4e35d7840 100644 --- a/bindings/README.md +++ b/bindings/README.md @@ -11,7 +11,9 @@ RUSTFLAGS="--cfg no_download" cargo build && ./scripts/uniffi_bindgen_generate.s Detailed instructions for publishing a new version of the bindings. 1. Update `Cargo.toml` -2. Update `libraryVersion` in `bindings/kotlin/ldk-node-android/gradle.properties` +2. Update `libraryVersion` in: + - `bindings/kotlin/ldk-node-android/gradle.properties` + - `bindings/kotlin/ldk-node-jvm/gradle.properties` 3. Run the above command to build all bindings 4. Open a PR with the changes 5. Create a new GitHub release with a new tag like `v0.1.0`, uploading the following files: diff --git a/bindings/kotlin/ldk-node-android/gradle.properties b/bindings/kotlin/ldk-node-android/gradle.properties index a37477966..f3459cb75 100644 --- a/bindings/kotlin/ldk-node-android/gradle.properties +++ b/bindings/kotlin/ldk-node-android/gradle.properties @@ -2,4 +2,4 @@ org.gradle.jvmargs=-Xmx1536m android.useAndroidX=true android.enableJetifier=true kotlin.code.style=official -libraryVersion=0.7.0-rc.15 +libraryVersion=0.7.0-rc.16 diff --git a/bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/arm64-v8a/libldk_node.so b/bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/arm64-v8a/libldk_node.so index 8104939fa..eeb161ae0 100755 Binary files a/bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/arm64-v8a/libldk_node.so and b/bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/arm64-v8a/libldk_node.so differ diff --git a/bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/armeabi-v7a/libldk_node.so b/bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/armeabi-v7a/libldk_node.so index c4a1a5c9f..203d05a38 100755 Binary files a/bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/armeabi-v7a/libldk_node.so and b/bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/armeabi-v7a/libldk_node.so differ diff --git a/bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/x86_64/libldk_node.so b/bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/x86_64/libldk_node.so index 58b203cb5..2a180f8e6 100755 Binary files a/bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/x86_64/libldk_node.so and b/bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/x86_64/libldk_node.so differ diff --git a/bindings/kotlin/ldk-node-jvm/gradle.properties b/bindings/kotlin/ldk-node-jvm/gradle.properties index fe6475673..a8937fec6 100644 --- a/bindings/kotlin/ldk-node-jvm/gradle.properties +++ b/bindings/kotlin/ldk-node-jvm/gradle.properties @@ -1,3 +1,3 @@ org.gradle.jvmargs=-Xmx1536m kotlin.code.style=official -libraryVersion=0.7.0-rc.15 +libraryVersion=0.7.0-rc.16 diff --git a/bindings/kotlin/ldk-node-jvm/lib/build.gradle.kts b/bindings/kotlin/ldk-node-jvm/lib/build.gradle.kts index 5c9e6c47c..7d6f66f1d 100644 --- a/bindings/kotlin/ldk-node-jvm/lib/build.gradle.kts +++ b/bindings/kotlin/ldk-node-jvm/lib/build.gradle.kts @@ -128,10 +128,8 @@ afterEvaluate { } signing { -// val signingKeyId: String? by project -// val signingKey: String? by project -// val signingPassword: String? by project -// useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword) + // Only sign if signing key is available (not on JitPack) + setRequired { gradle.taskGraph.hasTask("publish") && project.hasProperty("signingKey") } sign(publishing.publications) } diff --git a/bindings/kotlin/ldk-node-jvm/lib/src/main/kotlin/org/lightningdevkit/ldknode/ldk_node.kt b/bindings/kotlin/ldk-node-jvm/lib/src/main/kotlin/org/lightningdevkit/ldknode/ldk_node.kt new file mode 100644 index 000000000..0805f6bcf --- /dev/null +++ b/bindings/kotlin/ldk-node-jvm/lib/src/main/kotlin/org/lightningdevkit/ldknode/ldk_node.kt @@ -0,0 +1,17556 @@ +// This file was autogenerated by some hot garbage in the `uniffi` crate. +// Trust me, you don't want to mess with it! + +@file:Suppress("NAME_SHADOWING") + +package org.lightningdevkit.ldknode + +// Common helper code. +// +// Ideally this would live in a separate .kt file where it can be unittested etc +// in isolation, and perhaps even published as a re-useable package. +// +// However, it's important that the details of how this helper code works (e.g. the +// way that different builtin types are passed across the FFI) exactly match what's +// expected by the Rust code on the other side of the interface. In practice right +// now that means coming from the exact some version of `uniffi` that was used to +// compile the Rust component. The easiest way to ensure this is to bundle the Kotlin +// helpers directly inline like we're doing here. + +import com.sun.jna.Callback +import com.sun.jna.IntegerType +import com.sun.jna.Library +import com.sun.jna.Native +import com.sun.jna.Pointer +import com.sun.jna.Structure +import com.sun.jna.ptr.* +import kotlinx.coroutines.CancellableContinuation +import kotlinx.coroutines.DelicateCoroutinesApi +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import kotlinx.coroutines.suspendCancellableCoroutine +import java.nio.ByteBuffer +import java.nio.ByteOrder +import java.nio.CharBuffer +import java.nio.charset.CodingErrorAction +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.atomic.AtomicBoolean +import java.util.concurrent.atomic.AtomicLong +import kotlin.coroutines.resume + +// This is a helper for safely working with byte buffers returned from the Rust code. +// A rust-owned buffer is represented by its capacity, its current length, and a +// pointer to the underlying data. + +/** + * @suppress + */ +@Structure.FieldOrder("capacity", "len", "data") +open class RustBuffer : Structure() { + // Note: `capacity` and `len` are actually `ULong` values, but JVM only supports signed values. + // When dealing with these fields, make sure to call `toULong()`. + @JvmField var capacity: Long = 0 + + @JvmField var len: Long = 0 + + @JvmField var data: Pointer? = null + + class ByValue : + RustBuffer(), + Structure.ByValue + + class ByReference : + RustBuffer(), + Structure.ByReference + + internal fun setValue(other: RustBuffer) { + capacity = other.capacity + len = other.len + data = other.data + } + + companion object { + internal fun alloc(size: ULong = 0UL) = + uniffiRustCall { status -> + // Note: need to convert the size to a `Long` value to make this work with JVM. + UniffiLib.INSTANCE.ffi_ldk_node_rustbuffer_alloc(size.toLong(), status) + }.also { + if (it.data == null) { + throw RuntimeException("RustBuffer.alloc() returned null data pointer (size=$size)") + } + } + + internal fun create( + capacity: ULong, + len: ULong, + data: Pointer?, + ): RustBuffer.ByValue { + var buf = RustBuffer.ByValue() + buf.capacity = capacity.toLong() + buf.len = len.toLong() + buf.data = data + return buf + } + + internal fun free(buf: RustBuffer.ByValue) = + uniffiRustCall { status -> + UniffiLib.INSTANCE.ffi_ldk_node_rustbuffer_free(buf, status) + } + } + + @Suppress("TooGenericExceptionThrown") + fun asByteBuffer() = + this.data?.getByteBuffer(0, this.len.toLong())?.also { + it.order(ByteOrder.BIG_ENDIAN) + } +} + +/** + * The equivalent of the `*mut RustBuffer` type. + * Required for callbacks taking in an out pointer. + * + * Size is the sum of all values in the struct. + * + * @suppress + */ +class RustBufferByReference : ByReference(16) { + /** + * Set the pointed-to `RustBuffer` to the given value. + */ + fun setValue(value: RustBuffer.ByValue) { + // NOTE: The offsets are as they are in the C-like struct. + val pointer = getPointer() + pointer.setLong(0, value.capacity) + pointer.setLong(8, value.len) + pointer.setPointer(16, value.data) + } + + /** + * Get a `RustBuffer.ByValue` from this reference. + */ + fun getValue(): RustBuffer.ByValue { + val pointer = getPointer() + val value = RustBuffer.ByValue() + value.writeField("capacity", pointer.getLong(0)) + value.writeField("len", pointer.getLong(8)) + value.writeField("data", pointer.getLong(16)) + + return value + } +} + +// This is a helper for safely passing byte references into the rust code. +// It's not actually used at the moment, because there aren't many things that you +// can take a direct pointer to in the JVM, and if we're going to copy something +// then we might as well copy it into a `RustBuffer`. But it's here for API +// completeness. + +@Structure.FieldOrder("len", "data") +internal open class ForeignBytes : Structure() { + @JvmField var len: Int = 0 + + @JvmField var data: Pointer? = null + + class ByValue : + ForeignBytes(), + Structure.ByValue +} + +/** + * The FfiConverter interface handles converter types to and from the FFI + * + * All implementing objects should be public to support external types. When a + * type is external we need to import it's FfiConverter. + * + * @suppress + */ +public interface FfiConverter { + // Convert an FFI type to a Kotlin type + fun lift(value: FfiType): KotlinType + + // Convert an Kotlin type to an FFI type + fun lower(value: KotlinType): FfiType + + // Read a Kotlin type from a `ByteBuffer` + fun read(buf: ByteBuffer): KotlinType + + // Calculate bytes to allocate when creating a `RustBuffer` + // + // This must return at least as many bytes as the write() function will + // write. It can return more bytes than needed, for example when writing + // Strings we can't know the exact bytes needed until we the UTF-8 + // encoding, so we pessimistically allocate the largest size possible (3 + // bytes per codepoint). Allocating extra bytes is not really a big deal + // because the `RustBuffer` is short-lived. + fun allocationSize(value: KotlinType): ULong + + // Write a Kotlin type to a `ByteBuffer` + fun write( + value: KotlinType, + buf: ByteBuffer, + ) + + // Lower a value into a `RustBuffer` + // + // This method lowers a value into a `RustBuffer` rather than the normal + // FfiType. It's used by the callback interface code. Callback interface + // returns are always serialized into a `RustBuffer` regardless of their + // normal FFI type. + fun lowerIntoRustBuffer(value: KotlinType): RustBuffer.ByValue { + val rbuf = RustBuffer.alloc(allocationSize(value)) + try { + val bbuf = + rbuf.data!!.getByteBuffer(0, rbuf.capacity).also { + it.order(ByteOrder.BIG_ENDIAN) + } + write(value, bbuf) + rbuf.writeField("len", bbuf.position().toLong()) + return rbuf + } catch (e: Throwable) { + RustBuffer.free(rbuf) + throw e + } + } + + // Lift a value from a `RustBuffer`. + // + // This here mostly because of the symmetry with `lowerIntoRustBuffer()`. + // It's currently only used by the `FfiConverterRustBuffer` class below. + fun liftFromRustBuffer(rbuf: RustBuffer.ByValue): KotlinType { + val byteBuf = rbuf.asByteBuffer()!! + try { + val item = read(byteBuf) + if (byteBuf.hasRemaining()) { + throw RuntimeException("junk remaining in buffer after lifting, something is very wrong!!") + } + return item + } finally { + RustBuffer.free(rbuf) + } + } +} + +/** + * FfiConverter that uses `RustBuffer` as the FfiType + * + * @suppress + */ +public interface FfiConverterRustBuffer : FfiConverter { + override fun lift(value: RustBuffer.ByValue) = liftFromRustBuffer(value) + + override fun lower(value: KotlinType) = lowerIntoRustBuffer(value) +} +// A handful of classes and functions to support the generated data structures. +// This would be a good candidate for isolating in its own ffi-support lib. + +internal const val UNIFFI_CALL_SUCCESS = 0.toByte() +internal const val UNIFFI_CALL_ERROR = 1.toByte() +internal const val UNIFFI_CALL_UNEXPECTED_ERROR = 2.toByte() + +@Structure.FieldOrder("code", "error_buf") +internal open class UniffiRustCallStatus : Structure() { + @JvmField var code: Byte = 0 + + @JvmField var error_buf: RustBuffer.ByValue = RustBuffer.ByValue() + + class ByValue : + UniffiRustCallStatus(), + Structure.ByValue + + fun isSuccess(): Boolean = code == UNIFFI_CALL_SUCCESS + + fun isError(): Boolean = code == UNIFFI_CALL_ERROR + + fun isPanic(): Boolean = code == UNIFFI_CALL_UNEXPECTED_ERROR + + companion object { + fun create( + code: Byte, + errorBuf: RustBuffer.ByValue, + ): UniffiRustCallStatus.ByValue { + val callStatus = UniffiRustCallStatus.ByValue() + callStatus.code = code + callStatus.error_buf = errorBuf + return callStatus + } + } +} + +class InternalException( + message: String, +) : kotlin.Exception(message) + +/** + * Each top-level error class has a companion object that can lift the error from the call status's rust buffer + * + * @suppress + */ +interface UniffiRustCallStatusErrorHandler { + fun lift(error_buf: RustBuffer.ByValue): E +} + +// Helpers for calling Rust +// In practice we usually need to be synchronized to call this safely, so it doesn't +// synchronize itself + +// Call a rust function that returns a Result<>. Pass in the Error class companion that corresponds to the Err +private inline fun uniffiRustCallWithError( + errorHandler: UniffiRustCallStatusErrorHandler, + callback: (UniffiRustCallStatus) -> U, +): U { + var status = UniffiRustCallStatus() + val return_value = callback(status) + uniffiCheckCallStatus(errorHandler, status) + return return_value +} + +// Check UniffiRustCallStatus and throw an error if the call wasn't successful +private fun uniffiCheckCallStatus( + errorHandler: UniffiRustCallStatusErrorHandler, + status: UniffiRustCallStatus, +) { + if (status.isSuccess()) { + return + } else if (status.isError()) { + throw errorHandler.lift(status.error_buf) + } else if (status.isPanic()) { + // when the rust code sees a panic, it tries to construct a rustbuffer + // with the message. but if that code panics, then it just sends back + // an empty buffer. + if (status.error_buf.len > 0) { + throw InternalException(FfiConverterString.lift(status.error_buf)) + } else { + throw InternalException("Rust panic") + } + } else { + throw InternalException("Unknown rust call status: $status.code") + } +} + +/** + * UniffiRustCallStatusErrorHandler implementation for times when we don't expect a CALL_ERROR + * + * @suppress + */ +object UniffiNullRustCallStatusErrorHandler : UniffiRustCallStatusErrorHandler { + override fun lift(error_buf: RustBuffer.ByValue): InternalException { + RustBuffer.free(error_buf) + return InternalException("Unexpected CALL_ERROR") + } +} + +// Call a rust function that returns a plain value +private inline fun uniffiRustCall(callback: (UniffiRustCallStatus) -> U): U = + uniffiRustCallWithError(UniffiNullRustCallStatusErrorHandler, callback) + +internal inline fun uniffiTraitInterfaceCall( + callStatus: UniffiRustCallStatus, + makeCall: () -> T, + writeReturn: (T) -> Unit, +) { + try { + writeReturn(makeCall()) + } catch (e: kotlin.Exception) { + callStatus.code = UNIFFI_CALL_UNEXPECTED_ERROR + callStatus.error_buf = FfiConverterString.lower(e.toString()) + } +} + +internal inline fun uniffiTraitInterfaceCallWithError( + callStatus: UniffiRustCallStatus, + makeCall: () -> T, + writeReturn: (T) -> Unit, + lowerError: (E) -> RustBuffer.ByValue, +) { + try { + writeReturn(makeCall()) + } catch (e: kotlin.Exception) { + if (e is E) { + callStatus.code = UNIFFI_CALL_ERROR + callStatus.error_buf = lowerError(e) + } else { + callStatus.code = UNIFFI_CALL_UNEXPECTED_ERROR + callStatus.error_buf = FfiConverterString.lower(e.toString()) + } + } +} + +// Map handles to objects +// +// This is used pass an opaque 64-bit handle representing a foreign object to the Rust code. +internal class UniffiHandleMap { + private val map = ConcurrentHashMap() + private val counter = + java.util.concurrent.atomic + .AtomicLong(0) + + val size: Int + get() = map.size + + // Insert a new object into the handle map and get a handle for it + fun insert(obj: T): Long { + val handle = counter.getAndAdd(1) + map.put(handle, obj) + return handle + } + + // Get an object from the handle map + fun get(handle: Long): T = map.get(handle) ?: throw InternalException("UniffiHandleMap.get: Invalid handle") + + // Remove an entry from the handlemap and get the Kotlin object back + fun remove(handle: Long): T = map.remove(handle) ?: throw InternalException("UniffiHandleMap: Invalid handle") +} + +// Contains loading, initialization code, +// and the FFI Function declarations in a com.sun.jna.Library. +@Synchronized +private fun findLibraryName(componentName: String): String { + val libOverride = System.getProperty("uniffi.component.$componentName.libraryOverride") + if (libOverride != null) { + return libOverride + } + return "ldk_node" +} + +private inline fun loadIndirect(componentName: String): Lib = + Native.load(findLibraryName(componentName), Lib::class.java) + +// Define FFI callback types +internal interface UniffiRustFutureContinuationCallback : com.sun.jna.Callback { + fun callback( + `data`: Long, + `pollResult`: Byte, + ) +} + +internal interface UniffiForeignFutureFree : com.sun.jna.Callback { + fun callback(`handle`: Long) +} + +internal interface UniffiCallbackInterfaceFree : com.sun.jna.Callback { + fun callback(`handle`: Long) +} + +@Structure.FieldOrder("handle", "free") +internal open class UniffiForeignFuture( + @JvmField internal var `handle`: Long = 0.toLong(), + @JvmField internal var `free`: UniffiForeignFutureFree? = null, +) : Structure() { + class UniffiByValue( + `handle`: Long = 0.toLong(), + `free`: UniffiForeignFutureFree? = null, + ) : UniffiForeignFuture(`handle`, `free`), + Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFuture) { + `handle` = other.`handle` + `free` = other.`free` + } +} + +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructU8( + @JvmField internal var `returnValue`: Byte = 0.toByte(), + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Byte = 0.toByte(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ) : UniffiForeignFutureStructU8(`returnValue`, `callStatus`), + Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructU8) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompleteU8 : com.sun.jna.Callback { + fun callback( + `callbackData`: Long, + `result`: UniffiForeignFutureStructU8.UniffiByValue, + ) +} + +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructI8( + @JvmField internal var `returnValue`: Byte = 0.toByte(), + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Byte = 0.toByte(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ) : UniffiForeignFutureStructI8(`returnValue`, `callStatus`), + Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructI8) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompleteI8 : com.sun.jna.Callback { + fun callback( + `callbackData`: Long, + `result`: UniffiForeignFutureStructI8.UniffiByValue, + ) +} + +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructU16( + @JvmField internal var `returnValue`: Short = 0.toShort(), + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Short = 0.toShort(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ) : UniffiForeignFutureStructU16(`returnValue`, `callStatus`), + Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructU16) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompleteU16 : com.sun.jna.Callback { + fun callback( + `callbackData`: Long, + `result`: UniffiForeignFutureStructU16.UniffiByValue, + ) +} + +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructI16( + @JvmField internal var `returnValue`: Short = 0.toShort(), + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Short = 0.toShort(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ) : UniffiForeignFutureStructI16(`returnValue`, `callStatus`), + Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructI16) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompleteI16 : com.sun.jna.Callback { + fun callback( + `callbackData`: Long, + `result`: UniffiForeignFutureStructI16.UniffiByValue, + ) +} + +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructU32( + @JvmField internal var `returnValue`: Int = 0, + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Int = 0, + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ) : UniffiForeignFutureStructU32(`returnValue`, `callStatus`), + Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructU32) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompleteU32 : com.sun.jna.Callback { + fun callback( + `callbackData`: Long, + `result`: UniffiForeignFutureStructU32.UniffiByValue, + ) +} + +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructI32( + @JvmField internal var `returnValue`: Int = 0, + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Int = 0, + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ) : UniffiForeignFutureStructI32(`returnValue`, `callStatus`), + Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructI32) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompleteI32 : com.sun.jna.Callback { + fun callback( + `callbackData`: Long, + `result`: UniffiForeignFutureStructI32.UniffiByValue, + ) +} + +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructU64( + @JvmField internal var `returnValue`: Long = 0.toLong(), + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Long = 0.toLong(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ) : UniffiForeignFutureStructU64(`returnValue`, `callStatus`), + Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructU64) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompleteU64 : com.sun.jna.Callback { + fun callback( + `callbackData`: Long, + `result`: UniffiForeignFutureStructU64.UniffiByValue, + ) +} + +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructI64( + @JvmField internal var `returnValue`: Long = 0.toLong(), + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Long = 0.toLong(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ) : UniffiForeignFutureStructI64(`returnValue`, `callStatus`), + Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructI64) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompleteI64 : com.sun.jna.Callback { + fun callback( + `callbackData`: Long, + `result`: UniffiForeignFutureStructI64.UniffiByValue, + ) +} + +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructF32( + @JvmField internal var `returnValue`: Float = 0.0f, + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Float = 0.0f, + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ) : UniffiForeignFutureStructF32(`returnValue`, `callStatus`), + Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructF32) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompleteF32 : com.sun.jna.Callback { + fun callback( + `callbackData`: Long, + `result`: UniffiForeignFutureStructF32.UniffiByValue, + ) +} + +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructF64( + @JvmField internal var `returnValue`: Double = 0.0, + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Double = 0.0, + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ) : UniffiForeignFutureStructF64(`returnValue`, `callStatus`), + Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructF64) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompleteF64 : com.sun.jna.Callback { + fun callback( + `callbackData`: Long, + `result`: UniffiForeignFutureStructF64.UniffiByValue, + ) +} + +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructPointer( + @JvmField internal var `returnValue`: Pointer = Pointer.NULL, + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: Pointer = Pointer.NULL, + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ) : UniffiForeignFutureStructPointer(`returnValue`, `callStatus`), + Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructPointer) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompletePointer : com.sun.jna.Callback { + fun callback( + `callbackData`: Long, + `result`: UniffiForeignFutureStructPointer.UniffiByValue, + ) +} + +@Structure.FieldOrder("returnValue", "callStatus") +internal open class UniffiForeignFutureStructRustBuffer( + @JvmField internal var `returnValue`: RustBuffer.ByValue = RustBuffer.ByValue(), + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `returnValue`: RustBuffer.ByValue = RustBuffer.ByValue(), + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ) : UniffiForeignFutureStructRustBuffer(`returnValue`, `callStatus`), + Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructRustBuffer) { + `returnValue` = other.`returnValue` + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompleteRustBuffer : com.sun.jna.Callback { + fun callback( + `callbackData`: Long, + `result`: UniffiForeignFutureStructRustBuffer.UniffiByValue, + ) +} + +@Structure.FieldOrder("callStatus") +internal open class UniffiForeignFutureStructVoid( + @JvmField internal var `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), +) : Structure() { + class UniffiByValue( + `callStatus`: UniffiRustCallStatus.ByValue = UniffiRustCallStatus.ByValue(), + ) : UniffiForeignFutureStructVoid(`callStatus`), + Structure.ByValue + + internal fun uniffiSetValue(other: UniffiForeignFutureStructVoid) { + `callStatus` = other.`callStatus` + } +} + +internal interface UniffiForeignFutureCompleteVoid : com.sun.jna.Callback { + fun callback( + `callbackData`: Long, + `result`: UniffiForeignFutureStructVoid.UniffiByValue, + ) +} + +internal interface UniffiCallbackInterfaceLogWriterMethod0 : com.sun.jna.Callback { + fun callback( + `uniffiHandle`: Long, + `record`: RustBuffer.ByValue, + `uniffiOutReturn`: Pointer, + uniffiCallStatus: UniffiRustCallStatus, + ) +} + +internal interface UniffiCallbackInterfaceVssHeaderProviderMethod0 : com.sun.jna.Callback { + fun callback( + `uniffiHandle`: Long, + `request`: RustBuffer.ByValue, + `uniffiFutureCallback`: UniffiForeignFutureCompleteRustBuffer, + `uniffiCallbackData`: Long, + `uniffiOutReturn`: UniffiForeignFuture, + ) +} + +@Structure.FieldOrder("log", "uniffiFree") +internal open class UniffiVTableCallbackInterfaceLogWriter( + @JvmField internal var `log`: UniffiCallbackInterfaceLogWriterMethod0? = null, + @JvmField internal var `uniffiFree`: UniffiCallbackInterfaceFree? = null, +) : Structure() { + class UniffiByValue( + `log`: UniffiCallbackInterfaceLogWriterMethod0? = null, + `uniffiFree`: UniffiCallbackInterfaceFree? = null, + ) : UniffiVTableCallbackInterfaceLogWriter(`log`, `uniffiFree`), + Structure.ByValue + + internal fun uniffiSetValue(other: UniffiVTableCallbackInterfaceLogWriter) { + `log` = other.`log` + `uniffiFree` = other.`uniffiFree` + } +} + +@Structure.FieldOrder("getHeaders", "uniffiFree") +internal open class UniffiVTableCallbackInterfaceVssHeaderProvider( + @JvmField internal var `getHeaders`: UniffiCallbackInterfaceVssHeaderProviderMethod0? = null, + @JvmField internal var `uniffiFree`: UniffiCallbackInterfaceFree? = null, +) : Structure() { + class UniffiByValue( + `getHeaders`: UniffiCallbackInterfaceVssHeaderProviderMethod0? = null, + `uniffiFree`: UniffiCallbackInterfaceFree? = null, + ) : UniffiVTableCallbackInterfaceVssHeaderProvider(`getHeaders`, `uniffiFree`), + Structure.ByValue + + internal fun uniffiSetValue(other: UniffiVTableCallbackInterfaceVssHeaderProvider) { + `getHeaders` = other.`getHeaders` + `uniffiFree` = other.`uniffiFree` + } +} + +// A JNA Library to expose the extern-C FFI definitions. +// This is an implementation detail which will be called internally by the public API. + +internal interface UniffiLib : Library { + companion object { + internal val INSTANCE: UniffiLib by lazy { + loadIndirect(componentName = "ldk_node") + .also { lib: UniffiLib -> + uniffiCheckContractApiVersion(lib) + uniffiCheckApiChecksums(lib) + uniffiCallbackInterfaceLogWriter.register(lib) + } + } + + // The Cleaner for the whole library + internal val CLEANER: UniffiCleaner by lazy { + UniffiCleaner.create() + } + } + + fun uniffi_ldk_node_fn_clone_bolt11invoice( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_free_bolt11invoice( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_constructor_bolt11invoice_from_str( + `invoiceStr`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_bolt11invoice_amount_milli_satoshis( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt11invoice_currency( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt11invoice_expiry_time_seconds( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Long + + fun uniffi_ldk_node_fn_method_bolt11invoice_fallback_addresses( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt11invoice_invoice_description( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt11invoice_is_expired( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Byte + + fun uniffi_ldk_node_fn_method_bolt11invoice_min_final_cltv_expiry_delta( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Long + + fun uniffi_ldk_node_fn_method_bolt11invoice_network( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt11invoice_payment_hash( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt11invoice_payment_secret( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt11invoice_recover_payee_pub_key( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt11invoice_route_hints( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt11invoice_seconds_since_epoch( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Long + + fun uniffi_ldk_node_fn_method_bolt11invoice_seconds_until_expiry( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Long + + fun uniffi_ldk_node_fn_method_bolt11invoice_signable_hash( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt11invoice_would_expire( + `ptr`: Pointer, + `atTimeSeconds`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Byte + + fun uniffi_ldk_node_fn_method_bolt11invoice_uniffi_trait_debug( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt11invoice_uniffi_trait_display( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt11invoice_uniffi_trait_eq_eq( + `ptr`: Pointer, + `other`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Byte + + fun uniffi_ldk_node_fn_method_bolt11invoice_uniffi_trait_eq_ne( + `ptr`: Pointer, + `other`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Byte + + fun uniffi_ldk_node_fn_clone_bolt11payment( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_free_bolt11payment( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_bolt11payment_claim_for_hash( + `ptr`: Pointer, + `paymentHash`: RustBuffer.ByValue, + `claimableAmountMsat`: Long, + `preimage`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_bolt11payment_estimate_routing_fees( + `ptr`: Pointer, + `invoice`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Long + + fun uniffi_ldk_node_fn_method_bolt11payment_estimate_routing_fees_using_amount( + `ptr`: Pointer, + `invoice`: Pointer, + `amountMsat`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Long + + fun uniffi_ldk_node_fn_method_bolt11payment_fail_for_hash( + `ptr`: Pointer, + `paymentHash`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_bolt11payment_receive( + `ptr`: Pointer, + `amountMsat`: Long, + `description`: RustBuffer.ByValue, + `expirySecs`: Int, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_bolt11payment_receive_for_hash( + `ptr`: Pointer, + `amountMsat`: Long, + `description`: RustBuffer.ByValue, + `expirySecs`: Int, + `paymentHash`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_bolt11payment_receive_variable_amount( + `ptr`: Pointer, + `description`: RustBuffer.ByValue, + `expirySecs`: Int, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_bolt11payment_receive_variable_amount_for_hash( + `ptr`: Pointer, + `description`: RustBuffer.ByValue, + `expirySecs`: Int, + `paymentHash`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_bolt11payment_receive_variable_amount_via_jit_channel( + `ptr`: Pointer, + `description`: RustBuffer.ByValue, + `expirySecs`: Int, + `maxProportionalLspFeeLimitPpmMsat`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_bolt11payment_receive_variable_amount_via_jit_channel_for_hash( + `ptr`: Pointer, + `description`: RustBuffer.ByValue, + `expirySecs`: Int, + `maxProportionalLspFeeLimitPpmMsat`: RustBuffer.ByValue, + `paymentHash`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_bolt11payment_receive_via_jit_channel( + `ptr`: Pointer, + `amountMsat`: Long, + `description`: RustBuffer.ByValue, + `expirySecs`: Int, + `maxLspFeeLimitMsat`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_bolt11payment_receive_via_jit_channel_for_hash( + `ptr`: Pointer, + `amountMsat`: Long, + `description`: RustBuffer.ByValue, + `expirySecs`: Int, + `maxLspFeeLimitMsat`: RustBuffer.ByValue, + `paymentHash`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_bolt11payment_send( + `ptr`: Pointer, + `invoice`: Pointer, + `routeParameters`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt11payment_send_probes( + `ptr`: Pointer, + `invoice`: Pointer, + `routeParameters`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_bolt11payment_send_probes_using_amount( + `ptr`: Pointer, + `invoice`: Pointer, + `amountMsat`: Long, + `routeParameters`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_bolt11payment_send_using_amount( + `ptr`: Pointer, + `invoice`: Pointer, + `amountMsat`: Long, + `routeParameters`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_clone_bolt12invoice( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_free_bolt12invoice( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_constructor_bolt12invoice_from_str( + `invoiceStr`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_bolt12invoice_absolute_expiry_seconds( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt12invoice_amount( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt12invoice_amount_msats( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Long + + fun uniffi_ldk_node_fn_method_bolt12invoice_chain( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt12invoice_created_at( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Long + + fun uniffi_ldk_node_fn_method_bolt12invoice_encode( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt12invoice_fallback_addresses( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt12invoice_invoice_description( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt12invoice_is_expired( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Byte + + fun uniffi_ldk_node_fn_method_bolt12invoice_issuer( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt12invoice_issuer_signing_pubkey( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt12invoice_metadata( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt12invoice_offer_chains( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt12invoice_payer_note( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt12invoice_payer_signing_pubkey( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt12invoice_payment_hash( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt12invoice_quantity( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt12invoice_relative_expiry( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Long + + fun uniffi_ldk_node_fn_method_bolt12invoice_signable_hash( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt12invoice_signing_pubkey( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_clone_bolt12payment( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_free_bolt12payment( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_bolt12payment_blinded_paths_for_async_recipient( + `ptr`: Pointer, + `recipientId`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt12payment_initiate_refund( + `ptr`: Pointer, + `amountMsat`: Long, + `expirySecs`: Int, + `quantity`: RustBuffer.ByValue, + `payerNote`: RustBuffer.ByValue, + `routeParameters`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_bolt12payment_receive( + `ptr`: Pointer, + `amountMsat`: Long, + `description`: RustBuffer.ByValue, + `expirySecs`: RustBuffer.ByValue, + `quantity`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_bolt12payment_receive_async( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_bolt12payment_receive_variable_amount( + `ptr`: Pointer, + `description`: RustBuffer.ByValue, + `expirySecs`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_bolt12payment_request_refund_payment( + `ptr`: Pointer, + `refund`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_bolt12payment_send( + `ptr`: Pointer, + `offer`: Pointer, + `quantity`: RustBuffer.ByValue, + `payerNote`: RustBuffer.ByValue, + `routeParameters`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt12payment_send_using_amount( + `ptr`: Pointer, + `offer`: Pointer, + `amountMsat`: Long, + `quantity`: RustBuffer.ByValue, + `payerNote`: RustBuffer.ByValue, + `routeParameters`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_bolt12payment_set_paths_to_static_invoice_server( + `ptr`: Pointer, + `paths`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_clone_builder( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_free_builder( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_constructor_builder_from_config( + `config`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_constructor_builder_new(uniffi_out_err: UniffiRustCallStatus): Pointer + + fun uniffi_ldk_node_fn_method_builder_build( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_builder_build_with_fs_store( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_builder_build_with_vss_store( + `ptr`: Pointer, + `vssUrl`: RustBuffer.ByValue, + `storeId`: RustBuffer.ByValue, + `lnurlAuthServerUrl`: RustBuffer.ByValue, + `fixedHeaders`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_builder_build_with_vss_store_and_fixed_headers( + `ptr`: Pointer, + `vssUrl`: RustBuffer.ByValue, + `storeId`: RustBuffer.ByValue, + `fixedHeaders`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_builder_build_with_vss_store_and_header_provider( + `ptr`: Pointer, + `vssUrl`: RustBuffer.ByValue, + `storeId`: RustBuffer.ByValue, + `headerProvider`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_builder_set_announcement_addresses( + `ptr`: Pointer, + `announcementAddresses`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_builder_set_async_payments_role( + `ptr`: Pointer, + `role`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_builder_set_chain_source_bitcoind_rest( + `ptr`: Pointer, + `restHost`: RustBuffer.ByValue, + `restPort`: Short, + `rpcHost`: RustBuffer.ByValue, + `rpcPort`: Short, + `rpcUser`: RustBuffer.ByValue, + `rpcPassword`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_builder_set_chain_source_bitcoind_rpc( + `ptr`: Pointer, + `rpcHost`: RustBuffer.ByValue, + `rpcPort`: Short, + `rpcUser`: RustBuffer.ByValue, + `rpcPassword`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_builder_set_chain_source_electrum( + `ptr`: Pointer, + `serverUrl`: RustBuffer.ByValue, + `config`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_builder_set_chain_source_esplora( + `ptr`: Pointer, + `serverUrl`: RustBuffer.ByValue, + `config`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_builder_set_channel_data_migration( + `ptr`: Pointer, + `migration`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_builder_set_custom_logger( + `ptr`: Pointer, + `logWriter`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_builder_set_entropy_bip39_mnemonic( + `ptr`: Pointer, + `mnemonic`: RustBuffer.ByValue, + `passphrase`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_builder_set_entropy_seed_bytes( + `ptr`: Pointer, + `seedBytes`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_builder_set_entropy_seed_path( + `ptr`: Pointer, + `seedPath`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_builder_set_filesystem_logger( + `ptr`: Pointer, + `logFilePath`: RustBuffer.ByValue, + `maxLogLevel`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_builder_set_gossip_source_p2p( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_builder_set_gossip_source_rgs( + `ptr`: Pointer, + `rgsServerUrl`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_builder_set_liquidity_source_lsps1( + `ptr`: Pointer, + `nodeId`: RustBuffer.ByValue, + `address`: RustBuffer.ByValue, + `token`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_builder_set_liquidity_source_lsps2( + `ptr`: Pointer, + `nodeId`: RustBuffer.ByValue, + `address`: RustBuffer.ByValue, + `token`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_builder_set_listening_addresses( + `ptr`: Pointer, + `listeningAddresses`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_builder_set_log_facade_logger( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_builder_set_network( + `ptr`: Pointer, + `network`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_builder_set_node_alias( + `ptr`: Pointer, + `nodeAlias`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_builder_set_pathfinding_scores_source( + `ptr`: Pointer, + `url`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_builder_set_storage_dir_path( + `ptr`: Pointer, + `storageDirPath`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_clone_feerate( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_free_feerate( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_constructor_feerate_from_sat_per_kwu( + `satKwu`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_constructor_feerate_from_sat_per_vb_unchecked( + `satVb`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_feerate_to_sat_per_kwu( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Long + + fun uniffi_ldk_node_fn_method_feerate_to_sat_per_vb_ceil( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Long + + fun uniffi_ldk_node_fn_method_feerate_to_sat_per_vb_floor( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Long + + fun uniffi_ldk_node_fn_clone_lsps1liquidity( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_free_lsps1liquidity( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_lsps1liquidity_check_order_status( + `ptr`: Pointer, + `orderId`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_lsps1liquidity_request_channel( + `ptr`: Pointer, + `lspBalanceSat`: Long, + `clientBalanceSat`: Long, + `channelExpiryBlocks`: Int, + `announceChannel`: Byte, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_clone_logwriter( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_free_logwriter( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_init_callback_vtable_logwriter(`vtable`: UniffiVTableCallbackInterfaceLogWriter): Unit + + fun uniffi_ldk_node_fn_method_logwriter_log( + `ptr`: Pointer, + `record`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_clone_networkgraph( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_free_networkgraph( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_networkgraph_channel( + `ptr`: Pointer, + `shortChannelId`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_networkgraph_list_channels( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_networkgraph_list_nodes( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_networkgraph_node( + `ptr`: Pointer, + `nodeId`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_clone_node( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_free_node( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_node_announcement_addresses( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_node_bolt11_payment( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_node_bolt12_payment( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_node_close_channel( + `ptr`: Pointer, + `userChannelId`: RustBuffer.ByValue, + `counterpartyNodeId`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_node_config( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_node_connect( + `ptr`: Pointer, + `nodeId`: RustBuffer.ByValue, + `address`: RustBuffer.ByValue, + `persist`: Byte, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_node_current_sync_intervals( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_node_disconnect( + `ptr`: Pointer, + `nodeId`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_node_event_handled( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_node_export_pathfinding_scores( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_node_force_close_channel( + `ptr`: Pointer, + `userChannelId`: RustBuffer.ByValue, + `counterpartyNodeId`: RustBuffer.ByValue, + `reason`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_node_get_address_balance( + `ptr`: Pointer, + `addressStr`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Long + + fun uniffi_ldk_node_fn_method_node_get_transaction_details( + `ptr`: Pointer, + `txid`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_node_list_balances( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_node_list_channels( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_node_list_payments( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_node_list_peers( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_node_listening_addresses( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_node_lsps1_liquidity( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_node_network_graph( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_node_next_event( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_node_next_event_async(`ptr`: Pointer): Long + + fun uniffi_ldk_node_fn_method_node_node_alias( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_node_node_id( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_node_onchain_payment( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_node_open_announced_channel( + `ptr`: Pointer, + `nodeId`: RustBuffer.ByValue, + `address`: RustBuffer.ByValue, + `channelAmountSats`: Long, + `pushToCounterpartyMsat`: RustBuffer.ByValue, + `channelConfig`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_node_open_channel( + `ptr`: Pointer, + `nodeId`: RustBuffer.ByValue, + `address`: RustBuffer.ByValue, + `channelAmountSats`: Long, + `pushToCounterpartyMsat`: RustBuffer.ByValue, + `channelConfig`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_node_payment( + `ptr`: Pointer, + `paymentId`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_node_remove_payment( + `ptr`: Pointer, + `paymentId`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_node_sign_message( + `ptr`: Pointer, + `msg`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_node_splice_in( + `ptr`: Pointer, + `userChannelId`: RustBuffer.ByValue, + `counterpartyNodeId`: RustBuffer.ByValue, + `spliceAmountSats`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_node_splice_out( + `ptr`: Pointer, + `userChannelId`: RustBuffer.ByValue, + `counterpartyNodeId`: RustBuffer.ByValue, + `address`: RustBuffer.ByValue, + `spliceAmountSats`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_node_spontaneous_payment( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_node_start( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_node_status( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_node_stop( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_node_sync_wallets( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_node_unified_qr_payment( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_node_update_channel_config( + `ptr`: Pointer, + `userChannelId`: RustBuffer.ByValue, + `counterpartyNodeId`: RustBuffer.ByValue, + `channelConfig`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_node_update_sync_intervals( + `ptr`: Pointer, + `intervals`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_node_verify_signature( + `ptr`: Pointer, + `msg`: RustBuffer.ByValue, + `sig`: RustBuffer.ByValue, + `pkey`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Byte + + fun uniffi_ldk_node_fn_method_node_wait_next_event( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_clone_offer( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_free_offer( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_constructor_offer_from_str( + `offerStr`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_offer_absolute_expiry_seconds( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_offer_amount( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_offer_chains( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_offer_expects_quantity( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Byte + + fun uniffi_ldk_node_fn_method_offer_id( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_offer_is_expired( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Byte + + fun uniffi_ldk_node_fn_method_offer_is_valid_quantity( + `ptr`: Pointer, + `quantity`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Byte + + fun uniffi_ldk_node_fn_method_offer_issuer( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_offer_issuer_signing_pubkey( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_offer_metadata( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_offer_offer_description( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_offer_supports_chain( + `ptr`: Pointer, + `chain`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Byte + + fun uniffi_ldk_node_fn_method_offer_uniffi_trait_debug( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_offer_uniffi_trait_display( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_offer_uniffi_trait_eq_eq( + `ptr`: Pointer, + `other`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Byte + + fun uniffi_ldk_node_fn_method_offer_uniffi_trait_eq_ne( + `ptr`: Pointer, + `other`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Byte + + fun uniffi_ldk_node_fn_clone_onchainpayment( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_free_onchainpayment( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_onchainpayment_accelerate_by_cpfp( + `ptr`: Pointer, + `txid`: RustBuffer.ByValue, + `feeRate`: RustBuffer.ByValue, + `destinationAddress`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_onchainpayment_bump_fee_by_rbf( + `ptr`: Pointer, + `txid`: RustBuffer.ByValue, + `feeRate`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_onchainpayment_calculate_cpfp_fee_rate( + `ptr`: Pointer, + `parentTxid`: RustBuffer.ByValue, + `urgent`: Byte, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_onchainpayment_calculate_total_fee( + `ptr`: Pointer, + `address`: RustBuffer.ByValue, + `amountSats`: Long, + `feeRate`: RustBuffer.ByValue, + `utxosToSpend`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Long + + fun uniffi_ldk_node_fn_method_onchainpayment_list_spendable_outputs( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_onchainpayment_new_address( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_onchainpayment_select_utxos_with_algorithm( + `ptr`: Pointer, + `targetAmountSats`: Long, + `feeRate`: RustBuffer.ByValue, + `algorithm`: RustBuffer.ByValue, + `utxos`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_onchainpayment_send_all_to_address( + `ptr`: Pointer, + `address`: RustBuffer.ByValue, + `retainReserve`: Byte, + `feeRate`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_onchainpayment_send_to_address( + `ptr`: Pointer, + `address`: RustBuffer.ByValue, + `amountSats`: Long, + `feeRate`: RustBuffer.ByValue, + `utxosToSpend`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_clone_refund( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_free_refund( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_constructor_refund_from_str( + `refundStr`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_method_refund_absolute_expiry_seconds( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_refund_amount_msats( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Long + + fun uniffi_ldk_node_fn_method_refund_chain( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_refund_is_expired( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Byte + + fun uniffi_ldk_node_fn_method_refund_issuer( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_refund_payer_metadata( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_refund_payer_note( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_refund_payer_signing_pubkey( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_refund_quantity( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_refund_refund_description( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_refund_uniffi_trait_debug( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_refund_uniffi_trait_display( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_refund_uniffi_trait_eq_eq( + `ptr`: Pointer, + `other`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Byte + + fun uniffi_ldk_node_fn_method_refund_uniffi_trait_eq_ne( + `ptr`: Pointer, + `other`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Byte + + fun uniffi_ldk_node_fn_clone_spontaneouspayment( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_free_spontaneouspayment( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_spontaneouspayment_send( + `ptr`: Pointer, + `amountMsat`: Long, + `nodeId`: RustBuffer.ByValue, + `routeParameters`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_spontaneouspayment_send_probes( + `ptr`: Pointer, + `amountMsat`: Long, + `nodeId`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_spontaneouspayment_send_with_custom_tlvs( + `ptr`: Pointer, + `amountMsat`: Long, + `nodeId`: RustBuffer.ByValue, + `routeParameters`: RustBuffer.ByValue, + `customTlvs`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_spontaneouspayment_send_with_preimage( + `ptr`: Pointer, + `amountMsat`: Long, + `nodeId`: RustBuffer.ByValue, + `preimage`: RustBuffer.ByValue, + `routeParameters`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_spontaneouspayment_send_with_preimage_and_custom_tlvs( + `ptr`: Pointer, + `amountMsat`: Long, + `nodeId`: RustBuffer.ByValue, + `customTlvs`: RustBuffer.ByValue, + `preimage`: RustBuffer.ByValue, + `routeParameters`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_clone_unifiedqrpayment( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_free_unifiedqrpayment( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_unifiedqrpayment_receive( + `ptr`: Pointer, + `amountSats`: Long, + `message`: RustBuffer.ByValue, + `expirySec`: Int, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_method_unifiedqrpayment_send( + `ptr`: Pointer, + `uriStr`: RustBuffer.ByValue, + `routeParameters`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_clone_vssheaderprovider( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun uniffi_ldk_node_fn_free_vssheaderprovider( + `ptr`: Pointer, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_fn_method_vssheaderprovider_get_headers( + `ptr`: Pointer, + `request`: RustBuffer.ByValue, + ): Long + + fun uniffi_ldk_node_fn_func_battery_saving_sync_intervals(uniffi_out_err: UniffiRustCallStatus): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_func_default_config(uniffi_out_err: UniffiRustCallStatus): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_func_derive_node_secret_from_mnemonic( + `mnemonic`: RustBuffer.ByValue, + `passphrase`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun uniffi_ldk_node_fn_func_generate_entropy_mnemonic( + `wordCount`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun ffi_ldk_node_rustbuffer_alloc( + `size`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun ffi_ldk_node_rustbuffer_from_bytes( + `bytes`: ForeignBytes.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun ffi_ldk_node_rustbuffer_free( + `buf`: RustBuffer.ByValue, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun ffi_ldk_node_rustbuffer_reserve( + `buf`: RustBuffer.ByValue, + `additional`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun ffi_ldk_node_rust_future_poll_u8( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + fun ffi_ldk_node_rust_future_cancel_u8(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_free_u8(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_complete_u8( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Byte + + fun ffi_ldk_node_rust_future_poll_i8( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + fun ffi_ldk_node_rust_future_cancel_i8(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_free_i8(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_complete_i8( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Byte + + fun ffi_ldk_node_rust_future_poll_u16( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + fun ffi_ldk_node_rust_future_cancel_u16(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_free_u16(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_complete_u16( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Short + + fun ffi_ldk_node_rust_future_poll_i16( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + fun ffi_ldk_node_rust_future_cancel_i16(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_free_i16(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_complete_i16( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Short + + fun ffi_ldk_node_rust_future_poll_u32( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + fun ffi_ldk_node_rust_future_cancel_u32(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_free_u32(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_complete_u32( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Int + + fun ffi_ldk_node_rust_future_poll_i32( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + fun ffi_ldk_node_rust_future_cancel_i32(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_free_i32(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_complete_i32( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Int + + fun ffi_ldk_node_rust_future_poll_u64( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + fun ffi_ldk_node_rust_future_cancel_u64(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_free_u64(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_complete_u64( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Long + + fun ffi_ldk_node_rust_future_poll_i64( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + fun ffi_ldk_node_rust_future_cancel_i64(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_free_i64(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_complete_i64( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Long + + fun ffi_ldk_node_rust_future_poll_f32( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + fun ffi_ldk_node_rust_future_cancel_f32(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_free_f32(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_complete_f32( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Float + + fun ffi_ldk_node_rust_future_poll_f64( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + fun ffi_ldk_node_rust_future_cancel_f64(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_free_f64(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_complete_f64( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Double + + fun ffi_ldk_node_rust_future_poll_pointer( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + fun ffi_ldk_node_rust_future_cancel_pointer(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_free_pointer(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_complete_pointer( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Pointer + + fun ffi_ldk_node_rust_future_poll_rust_buffer( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + fun ffi_ldk_node_rust_future_cancel_rust_buffer(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_free_rust_buffer(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_complete_rust_buffer( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): RustBuffer.ByValue + + fun ffi_ldk_node_rust_future_poll_void( + `handle`: Long, + `callback`: UniffiRustFutureContinuationCallback, + `callbackData`: Long, + ): Unit + + fun ffi_ldk_node_rust_future_cancel_void(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_free_void(`handle`: Long): Unit + + fun ffi_ldk_node_rust_future_complete_void( + `handle`: Long, + uniffi_out_err: UniffiRustCallStatus, + ): Unit + + fun uniffi_ldk_node_checksum_func_battery_saving_sync_intervals(): Short + + fun uniffi_ldk_node_checksum_func_default_config(): Short + + fun uniffi_ldk_node_checksum_func_derive_node_secret_from_mnemonic(): Short + + fun uniffi_ldk_node_checksum_func_generate_entropy_mnemonic(): Short + + fun uniffi_ldk_node_checksum_method_bolt11invoice_amount_milli_satoshis(): Short + + fun uniffi_ldk_node_checksum_method_bolt11invoice_currency(): Short + + fun uniffi_ldk_node_checksum_method_bolt11invoice_expiry_time_seconds(): Short + + fun uniffi_ldk_node_checksum_method_bolt11invoice_fallback_addresses(): Short + + fun uniffi_ldk_node_checksum_method_bolt11invoice_invoice_description(): Short + + fun uniffi_ldk_node_checksum_method_bolt11invoice_is_expired(): Short + + fun uniffi_ldk_node_checksum_method_bolt11invoice_min_final_cltv_expiry_delta(): Short + + fun uniffi_ldk_node_checksum_method_bolt11invoice_network(): Short + + fun uniffi_ldk_node_checksum_method_bolt11invoice_payment_hash(): Short + + fun uniffi_ldk_node_checksum_method_bolt11invoice_payment_secret(): Short + + fun uniffi_ldk_node_checksum_method_bolt11invoice_recover_payee_pub_key(): Short + + fun uniffi_ldk_node_checksum_method_bolt11invoice_route_hints(): Short + + fun uniffi_ldk_node_checksum_method_bolt11invoice_seconds_since_epoch(): Short + + fun uniffi_ldk_node_checksum_method_bolt11invoice_seconds_until_expiry(): Short + + fun uniffi_ldk_node_checksum_method_bolt11invoice_signable_hash(): Short + + fun uniffi_ldk_node_checksum_method_bolt11invoice_would_expire(): Short + + fun uniffi_ldk_node_checksum_method_bolt11payment_claim_for_hash(): Short + + fun uniffi_ldk_node_checksum_method_bolt11payment_estimate_routing_fees(): Short + + fun uniffi_ldk_node_checksum_method_bolt11payment_estimate_routing_fees_using_amount(): Short + + fun uniffi_ldk_node_checksum_method_bolt11payment_fail_for_hash(): Short + + fun uniffi_ldk_node_checksum_method_bolt11payment_receive(): Short + + fun uniffi_ldk_node_checksum_method_bolt11payment_receive_for_hash(): Short + + fun uniffi_ldk_node_checksum_method_bolt11payment_receive_variable_amount(): Short + + fun uniffi_ldk_node_checksum_method_bolt11payment_receive_variable_amount_for_hash(): Short + + fun uniffi_ldk_node_checksum_method_bolt11payment_receive_variable_amount_via_jit_channel(): Short + + fun uniffi_ldk_node_checksum_method_bolt11payment_receive_variable_amount_via_jit_channel_for_hash(): Short + + fun uniffi_ldk_node_checksum_method_bolt11payment_receive_via_jit_channel(): Short + + fun uniffi_ldk_node_checksum_method_bolt11payment_receive_via_jit_channel_for_hash(): Short + + fun uniffi_ldk_node_checksum_method_bolt11payment_send(): Short + + fun uniffi_ldk_node_checksum_method_bolt11payment_send_probes(): Short + + fun uniffi_ldk_node_checksum_method_bolt11payment_send_probes_using_amount(): Short + + fun uniffi_ldk_node_checksum_method_bolt11payment_send_using_amount(): Short + + fun uniffi_ldk_node_checksum_method_bolt12invoice_absolute_expiry_seconds(): Short + + fun uniffi_ldk_node_checksum_method_bolt12invoice_amount(): Short + + fun uniffi_ldk_node_checksum_method_bolt12invoice_amount_msats(): Short + + fun uniffi_ldk_node_checksum_method_bolt12invoice_chain(): Short + + fun uniffi_ldk_node_checksum_method_bolt12invoice_created_at(): Short + + fun uniffi_ldk_node_checksum_method_bolt12invoice_encode(): Short + + fun uniffi_ldk_node_checksum_method_bolt12invoice_fallback_addresses(): Short + + fun uniffi_ldk_node_checksum_method_bolt12invoice_invoice_description(): Short + + fun uniffi_ldk_node_checksum_method_bolt12invoice_is_expired(): Short + + fun uniffi_ldk_node_checksum_method_bolt12invoice_issuer(): Short + + fun uniffi_ldk_node_checksum_method_bolt12invoice_issuer_signing_pubkey(): Short + + fun uniffi_ldk_node_checksum_method_bolt12invoice_metadata(): Short + + fun uniffi_ldk_node_checksum_method_bolt12invoice_offer_chains(): Short + + fun uniffi_ldk_node_checksum_method_bolt12invoice_payer_note(): Short + + fun uniffi_ldk_node_checksum_method_bolt12invoice_payer_signing_pubkey(): Short + + fun uniffi_ldk_node_checksum_method_bolt12invoice_payment_hash(): Short + + fun uniffi_ldk_node_checksum_method_bolt12invoice_quantity(): Short + + fun uniffi_ldk_node_checksum_method_bolt12invoice_relative_expiry(): Short + + fun uniffi_ldk_node_checksum_method_bolt12invoice_signable_hash(): Short + + fun uniffi_ldk_node_checksum_method_bolt12invoice_signing_pubkey(): Short + + fun uniffi_ldk_node_checksum_method_bolt12payment_blinded_paths_for_async_recipient(): Short + + fun uniffi_ldk_node_checksum_method_bolt12payment_initiate_refund(): Short + + fun uniffi_ldk_node_checksum_method_bolt12payment_receive(): Short + + fun uniffi_ldk_node_checksum_method_bolt12payment_receive_async(): Short + + fun uniffi_ldk_node_checksum_method_bolt12payment_receive_variable_amount(): Short + + fun uniffi_ldk_node_checksum_method_bolt12payment_request_refund_payment(): Short + + fun uniffi_ldk_node_checksum_method_bolt12payment_send(): Short + + fun uniffi_ldk_node_checksum_method_bolt12payment_send_using_amount(): Short + + fun uniffi_ldk_node_checksum_method_bolt12payment_set_paths_to_static_invoice_server(): Short + + fun uniffi_ldk_node_checksum_method_builder_build(): Short + + fun uniffi_ldk_node_checksum_method_builder_build_with_fs_store(): Short + + fun uniffi_ldk_node_checksum_method_builder_build_with_vss_store(): Short + + fun uniffi_ldk_node_checksum_method_builder_build_with_vss_store_and_fixed_headers(): Short + + fun uniffi_ldk_node_checksum_method_builder_build_with_vss_store_and_header_provider(): Short + + fun uniffi_ldk_node_checksum_method_builder_set_announcement_addresses(): Short + + fun uniffi_ldk_node_checksum_method_builder_set_async_payments_role(): Short + + fun uniffi_ldk_node_checksum_method_builder_set_chain_source_bitcoind_rest(): Short + + fun uniffi_ldk_node_checksum_method_builder_set_chain_source_bitcoind_rpc(): Short + + fun uniffi_ldk_node_checksum_method_builder_set_chain_source_electrum(): Short + + fun uniffi_ldk_node_checksum_method_builder_set_chain_source_esplora(): Short + + fun uniffi_ldk_node_checksum_method_builder_set_channel_data_migration(): Short + + fun uniffi_ldk_node_checksum_method_builder_set_custom_logger(): Short + + fun uniffi_ldk_node_checksum_method_builder_set_entropy_bip39_mnemonic(): Short + + fun uniffi_ldk_node_checksum_method_builder_set_entropy_seed_bytes(): Short + + fun uniffi_ldk_node_checksum_method_builder_set_entropy_seed_path(): Short + + fun uniffi_ldk_node_checksum_method_builder_set_filesystem_logger(): Short + + fun uniffi_ldk_node_checksum_method_builder_set_gossip_source_p2p(): Short + + fun uniffi_ldk_node_checksum_method_builder_set_gossip_source_rgs(): Short + + fun uniffi_ldk_node_checksum_method_builder_set_liquidity_source_lsps1(): Short + + fun uniffi_ldk_node_checksum_method_builder_set_liquidity_source_lsps2(): Short + + fun uniffi_ldk_node_checksum_method_builder_set_listening_addresses(): Short + + fun uniffi_ldk_node_checksum_method_builder_set_log_facade_logger(): Short + + fun uniffi_ldk_node_checksum_method_builder_set_network(): Short + + fun uniffi_ldk_node_checksum_method_builder_set_node_alias(): Short + + fun uniffi_ldk_node_checksum_method_builder_set_pathfinding_scores_source(): Short + + fun uniffi_ldk_node_checksum_method_builder_set_storage_dir_path(): Short + + fun uniffi_ldk_node_checksum_method_feerate_to_sat_per_kwu(): Short + + fun uniffi_ldk_node_checksum_method_feerate_to_sat_per_vb_ceil(): Short + + fun uniffi_ldk_node_checksum_method_feerate_to_sat_per_vb_floor(): Short + + fun uniffi_ldk_node_checksum_method_lsps1liquidity_check_order_status(): Short + + fun uniffi_ldk_node_checksum_method_lsps1liquidity_request_channel(): Short + + fun uniffi_ldk_node_checksum_method_logwriter_log(): Short + + fun uniffi_ldk_node_checksum_method_networkgraph_channel(): Short + + fun uniffi_ldk_node_checksum_method_networkgraph_list_channels(): Short + + fun uniffi_ldk_node_checksum_method_networkgraph_list_nodes(): Short + + fun uniffi_ldk_node_checksum_method_networkgraph_node(): Short + + fun uniffi_ldk_node_checksum_method_node_announcement_addresses(): Short + + fun uniffi_ldk_node_checksum_method_node_bolt11_payment(): Short + + fun uniffi_ldk_node_checksum_method_node_bolt12_payment(): Short + + fun uniffi_ldk_node_checksum_method_node_close_channel(): Short + + fun uniffi_ldk_node_checksum_method_node_config(): Short + + fun uniffi_ldk_node_checksum_method_node_connect(): Short + + fun uniffi_ldk_node_checksum_method_node_current_sync_intervals(): Short + + fun uniffi_ldk_node_checksum_method_node_disconnect(): Short + + fun uniffi_ldk_node_checksum_method_node_event_handled(): Short + + fun uniffi_ldk_node_checksum_method_node_export_pathfinding_scores(): Short + + fun uniffi_ldk_node_checksum_method_node_force_close_channel(): Short + + fun uniffi_ldk_node_checksum_method_node_get_address_balance(): Short + + fun uniffi_ldk_node_checksum_method_node_get_transaction_details(): Short + + fun uniffi_ldk_node_checksum_method_node_list_balances(): Short + + fun uniffi_ldk_node_checksum_method_node_list_channels(): Short + + fun uniffi_ldk_node_checksum_method_node_list_payments(): Short + + fun uniffi_ldk_node_checksum_method_node_list_peers(): Short + + fun uniffi_ldk_node_checksum_method_node_listening_addresses(): Short + + fun uniffi_ldk_node_checksum_method_node_lsps1_liquidity(): Short + + fun uniffi_ldk_node_checksum_method_node_network_graph(): Short + + fun uniffi_ldk_node_checksum_method_node_next_event(): Short + + fun uniffi_ldk_node_checksum_method_node_next_event_async(): Short + + fun uniffi_ldk_node_checksum_method_node_node_alias(): Short + + fun uniffi_ldk_node_checksum_method_node_node_id(): Short + + fun uniffi_ldk_node_checksum_method_node_onchain_payment(): Short + + fun uniffi_ldk_node_checksum_method_node_open_announced_channel(): Short + + fun uniffi_ldk_node_checksum_method_node_open_channel(): Short + + fun uniffi_ldk_node_checksum_method_node_payment(): Short + + fun uniffi_ldk_node_checksum_method_node_remove_payment(): Short + + fun uniffi_ldk_node_checksum_method_node_sign_message(): Short + + fun uniffi_ldk_node_checksum_method_node_splice_in(): Short + + fun uniffi_ldk_node_checksum_method_node_splice_out(): Short + + fun uniffi_ldk_node_checksum_method_node_spontaneous_payment(): Short + + fun uniffi_ldk_node_checksum_method_node_start(): Short + + fun uniffi_ldk_node_checksum_method_node_status(): Short + + fun uniffi_ldk_node_checksum_method_node_stop(): Short + + fun uniffi_ldk_node_checksum_method_node_sync_wallets(): Short + + fun uniffi_ldk_node_checksum_method_node_unified_qr_payment(): Short + + fun uniffi_ldk_node_checksum_method_node_update_channel_config(): Short + + fun uniffi_ldk_node_checksum_method_node_update_sync_intervals(): Short + + fun uniffi_ldk_node_checksum_method_node_verify_signature(): Short + + fun uniffi_ldk_node_checksum_method_node_wait_next_event(): Short + + fun uniffi_ldk_node_checksum_method_offer_absolute_expiry_seconds(): Short + + fun uniffi_ldk_node_checksum_method_offer_amount(): Short + + fun uniffi_ldk_node_checksum_method_offer_chains(): Short + + fun uniffi_ldk_node_checksum_method_offer_expects_quantity(): Short + + fun uniffi_ldk_node_checksum_method_offer_id(): Short + + fun uniffi_ldk_node_checksum_method_offer_is_expired(): Short + + fun uniffi_ldk_node_checksum_method_offer_is_valid_quantity(): Short + + fun uniffi_ldk_node_checksum_method_offer_issuer(): Short + + fun uniffi_ldk_node_checksum_method_offer_issuer_signing_pubkey(): Short + + fun uniffi_ldk_node_checksum_method_offer_metadata(): Short + + fun uniffi_ldk_node_checksum_method_offer_offer_description(): Short + + fun uniffi_ldk_node_checksum_method_offer_supports_chain(): Short + + fun uniffi_ldk_node_checksum_method_onchainpayment_accelerate_by_cpfp(): Short + + fun uniffi_ldk_node_checksum_method_onchainpayment_bump_fee_by_rbf(): Short + + fun uniffi_ldk_node_checksum_method_onchainpayment_calculate_cpfp_fee_rate(): Short + + fun uniffi_ldk_node_checksum_method_onchainpayment_calculate_total_fee(): Short + + fun uniffi_ldk_node_checksum_method_onchainpayment_list_spendable_outputs(): Short + + fun uniffi_ldk_node_checksum_method_onchainpayment_new_address(): Short + + fun uniffi_ldk_node_checksum_method_onchainpayment_select_utxos_with_algorithm(): Short + + fun uniffi_ldk_node_checksum_method_onchainpayment_send_all_to_address(): Short + + fun uniffi_ldk_node_checksum_method_onchainpayment_send_to_address(): Short + + fun uniffi_ldk_node_checksum_method_refund_absolute_expiry_seconds(): Short + + fun uniffi_ldk_node_checksum_method_refund_amount_msats(): Short + + fun uniffi_ldk_node_checksum_method_refund_chain(): Short + + fun uniffi_ldk_node_checksum_method_refund_is_expired(): Short + + fun uniffi_ldk_node_checksum_method_refund_issuer(): Short + + fun uniffi_ldk_node_checksum_method_refund_payer_metadata(): Short + + fun uniffi_ldk_node_checksum_method_refund_payer_note(): Short + + fun uniffi_ldk_node_checksum_method_refund_payer_signing_pubkey(): Short + + fun uniffi_ldk_node_checksum_method_refund_quantity(): Short + + fun uniffi_ldk_node_checksum_method_refund_refund_description(): Short + + fun uniffi_ldk_node_checksum_method_spontaneouspayment_send(): Short + + fun uniffi_ldk_node_checksum_method_spontaneouspayment_send_probes(): Short + + fun uniffi_ldk_node_checksum_method_spontaneouspayment_send_with_custom_tlvs(): Short + + fun uniffi_ldk_node_checksum_method_spontaneouspayment_send_with_preimage(): Short + + fun uniffi_ldk_node_checksum_method_spontaneouspayment_send_with_preimage_and_custom_tlvs(): Short + + fun uniffi_ldk_node_checksum_method_unifiedqrpayment_receive(): Short + + fun uniffi_ldk_node_checksum_method_unifiedqrpayment_send(): Short + + fun uniffi_ldk_node_checksum_method_vssheaderprovider_get_headers(): Short + + fun uniffi_ldk_node_checksum_constructor_bolt11invoice_from_str(): Short + + fun uniffi_ldk_node_checksum_constructor_bolt12invoice_from_str(): Short + + fun uniffi_ldk_node_checksum_constructor_builder_from_config(): Short + + fun uniffi_ldk_node_checksum_constructor_builder_new(): Short + + fun uniffi_ldk_node_checksum_constructor_feerate_from_sat_per_kwu(): Short + + fun uniffi_ldk_node_checksum_constructor_feerate_from_sat_per_vb_unchecked(): Short + + fun uniffi_ldk_node_checksum_constructor_offer_from_str(): Short + + fun uniffi_ldk_node_checksum_constructor_refund_from_str(): Short + + fun ffi_ldk_node_uniffi_contract_version(): Int +} + +private fun uniffiCheckContractApiVersion(lib: UniffiLib) { + // Get the bindings contract version from our ComponentInterface + val bindings_contract_version = 26 + // Get the scaffolding contract version by calling the into the dylib + val scaffolding_contract_version = lib.ffi_ldk_node_uniffi_contract_version() + if (bindings_contract_version != scaffolding_contract_version) { + throw RuntimeException("UniFFI contract version mismatch: try cleaning and rebuilding your project") + } +} + +@Suppress("UNUSED_PARAMETER") +private fun uniffiCheckApiChecksums(lib: UniffiLib) { + if (lib.uniffi_ldk_node_checksum_func_battery_saving_sync_intervals() != 25473.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_func_default_config() != 55381.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_func_derive_node_secret_from_mnemonic() != 15067.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_func_generate_entropy_mnemonic() != 48014.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11invoice_amount_milli_satoshis() != 50823.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11invoice_currency() != 32179.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11invoice_expiry_time_seconds() != 23625.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11invoice_fallback_addresses() != 55276.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11invoice_invoice_description() != 395.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11invoice_is_expired() != 15932.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11invoice_min_final_cltv_expiry_delta() != 8855.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11invoice_network() != 10420.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11invoice_payment_hash() != 42571.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11invoice_payment_secret() != 26081.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11invoice_recover_payee_pub_key() != 18874.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11invoice_route_hints() != 63051.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11invoice_seconds_since_epoch() != 53979.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11invoice_seconds_until_expiry() != 64193.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11invoice_signable_hash() != 30910.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11invoice_would_expire() != 30331.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11payment_claim_for_hash() != 52848.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11payment_estimate_routing_fees() != 5123.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11payment_estimate_routing_fees_using_amount() != 46411.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11payment_fail_for_hash() != 24516.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11payment_receive() != 6073.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11payment_receive_for_hash() != 27050.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11payment_receive_variable_amount() != 4893.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11payment_receive_variable_amount_for_hash() != 1402.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11payment_receive_variable_amount_via_jit_channel() != 24506.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11payment_receive_variable_amount_via_jit_channel_for_hash() != 38025.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11payment_receive_via_jit_channel() != 16532.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11payment_receive_via_jit_channel_for_hash() != 1143.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11payment_send() != 12953.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11payment_send_probes() != 19286.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11payment_send_probes_using_amount() != 5976.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt11payment_send_using_amount() != 42793.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12invoice_absolute_expiry_seconds() != 28589.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12invoice_amount() != 5213.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12invoice_amount_msats() != 9297.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12invoice_chain() != 3308.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12invoice_created_at() != 56866.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12invoice_encode() != 13200.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12invoice_fallback_addresses() != 7925.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12invoice_invoice_description() != 1713.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12invoice_is_expired() != 39560.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12invoice_issuer() != 65270.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12invoice_issuer_signing_pubkey() != 55411.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12invoice_metadata() != 37374.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12invoice_offer_chains() != 39622.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12invoice_payer_note() != 28018.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12invoice_payer_signing_pubkey() != 12798.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12invoice_payment_hash() != 63778.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12invoice_quantity() != 43105.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12invoice_relative_expiry() != 14024.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12invoice_signable_hash() != 39303.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12invoice_signing_pubkey() != 35202.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12payment_blinded_paths_for_async_recipient() != 14695.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12payment_initiate_refund() != 15019.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12payment_receive() != 59252.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12payment_receive_async() != 23867.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12payment_receive_variable_amount() != 35484.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12payment_request_refund_payment() != 43248.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12payment_send() != 27679.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12payment_send_using_amount() != 33255.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_bolt12payment_set_paths_to_static_invoice_server() != 20921.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_build() != 785.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_build_with_fs_store() != 61304.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_build_with_vss_store() != 2871.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_build_with_vss_store_and_fixed_headers() != 24910.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_build_with_vss_store_and_header_provider() != 9090.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_set_announcement_addresses() != 39271.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_set_async_payments_role() != 16463.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_set_chain_source_bitcoind_rest() != 37382.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_set_chain_source_bitcoind_rpc() != 2111.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_set_chain_source_electrum() != 55552.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_set_chain_source_esplora() != 1781.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_set_channel_data_migration() != 58453.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_set_custom_logger() != 51232.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_set_entropy_bip39_mnemonic() != 827.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_set_entropy_seed_bytes() != 44799.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_set_entropy_seed_path() != 64056.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_set_filesystem_logger() != 10249.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_set_gossip_source_p2p() != 9279.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_set_gossip_source_rgs() != 64312.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_set_liquidity_source_lsps1() != 51527.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_set_liquidity_source_lsps2() != 14430.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_set_listening_addresses() != 14051.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_set_log_facade_logger() != 58410.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_set_network() != 27539.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_set_node_alias() != 18342.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_set_pathfinding_scores_source() != 63501.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_builder_set_storage_dir_path() != 59019.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_feerate_to_sat_per_kwu() != 58911.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_feerate_to_sat_per_vb_ceil() != 58575.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_feerate_to_sat_per_vb_floor() != 59617.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_lsps1liquidity_check_order_status() != 57147.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_lsps1liquidity_request_channel() != 18153.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_logwriter_log() != 3299.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_networkgraph_channel() != 38070.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_networkgraph_list_channels() != 4693.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_networkgraph_list_nodes() != 36715.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_networkgraph_node() != 48925.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_announcement_addresses() != 61426.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_bolt11_payment() != 41402.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_bolt12_payment() != 49254.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_close_channel() != 62479.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_config() != 7511.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_connect() != 34120.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_current_sync_intervals() != 51918.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_disconnect() != 43538.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_event_handled() != 38712.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_export_pathfinding_scores() != 62331.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_force_close_channel() != 48831.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_get_address_balance() != 45284.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_get_transaction_details() != 65000.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_list_balances() != 57528.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_list_channels() != 7954.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_list_payments() != 35002.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_list_peers() != 14889.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_listening_addresses() != 2665.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_lsps1_liquidity() != 38201.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_network_graph() != 2695.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_next_event() != 7682.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_next_event_async() != 25426.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_node_alias() != 29526.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_node_id() != 51489.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_onchain_payment() != 6092.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_open_announced_channel() != 36623.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_open_channel() != 40283.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_payment() != 60296.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_remove_payment() != 47952.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_sign_message() != 49319.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_splice_in() != 46431.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_splice_out() != 22115.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_spontaneous_payment() != 37403.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_start() != 58480.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_status() != 55952.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_stop() != 42188.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_sync_wallets() != 32474.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_unified_qr_payment() != 9837.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_update_channel_config() != 37852.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_update_sync_intervals() != 42322.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_verify_signature() != 20486.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_node_wait_next_event() != 55101.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_offer_absolute_expiry_seconds() != 22836.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_offer_amount() != 59890.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_offer_chains() != 59522.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_offer_expects_quantity() != 58457.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_offer_id() != 8391.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_offer_is_expired() != 22651.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_offer_is_valid_quantity() != 58469.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_offer_issuer() != 41632.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_offer_issuer_signing_pubkey() != 38162.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_offer_metadata() != 18979.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_offer_offer_description() != 11122.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_offer_supports_chain() != 2135.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_onchainpayment_accelerate_by_cpfp() != 31954.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_onchainpayment_bump_fee_by_rbf() != 53877.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_onchainpayment_calculate_cpfp_fee_rate() != 32879.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_onchainpayment_calculate_total_fee() != 57218.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_onchainpayment_list_spendable_outputs() != 19144.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_onchainpayment_new_address() != 37251.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_onchainpayment_select_utxos_with_algorithm() != 14084.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_onchainpayment_send_all_to_address() != 37748.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_onchainpayment_send_to_address() != 28826.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_refund_absolute_expiry_seconds() != 43722.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_refund_amount_msats() != 26467.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_refund_chain() != 36565.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_refund_is_expired() != 10232.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_refund_issuer() != 40306.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_refund_payer_metadata() != 23501.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_refund_payer_note() != 47799.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_refund_payer_signing_pubkey() != 40880.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_refund_quantity() != 15192.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_refund_refund_description() != 39295.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_spontaneouspayment_send() != 27905.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_spontaneouspayment_send_probes() != 25937.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_spontaneouspayment_send_with_custom_tlvs() != 17876.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_spontaneouspayment_send_with_preimage() != 30854.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_spontaneouspayment_send_with_preimage_and_custom_tlvs() != 12104.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_unifiedqrpayment_receive() != 913.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_unifiedqrpayment_send() != 28285.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_method_vssheaderprovider_get_headers() != 7788.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_constructor_bolt11invoice_from_str() != 349.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_constructor_bolt12invoice_from_str() != 22276.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_constructor_builder_from_config() != 994.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_constructor_builder_new() != 40499.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_constructor_feerate_from_sat_per_kwu() != 50548.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_constructor_feerate_from_sat_per_vb_unchecked() != 41808.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_constructor_offer_from_str() != 37070.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } + if (lib.uniffi_ldk_node_checksum_constructor_refund_from_str() != 64884.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } +} + +// Async support +// Async return type handlers + +internal const val UNIFFI_RUST_FUTURE_POLL_READY = 0.toByte() +internal const val UNIFFI_RUST_FUTURE_POLL_MAYBE_READY = 1.toByte() + +internal val uniffiContinuationHandleMap = UniffiHandleMap>() + +// FFI type for Rust future continuations +internal object uniffiRustFutureContinuationCallbackImpl : UniffiRustFutureContinuationCallback { + override fun callback( + data: Long, + pollResult: Byte, + ) { + uniffiContinuationHandleMap.remove(data).resume(pollResult) + } +} + +internal suspend fun uniffiRustCallAsync( + rustFuture: Long, + pollFunc: (Long, UniffiRustFutureContinuationCallback, Long) -> Unit, + completeFunc: (Long, UniffiRustCallStatus) -> F, + freeFunc: (Long) -> Unit, + liftFunc: (F) -> T, + errorHandler: UniffiRustCallStatusErrorHandler, +): T { + try { + do { + val pollResult = + suspendCancellableCoroutine { continuation -> + pollFunc( + rustFuture, + uniffiRustFutureContinuationCallbackImpl, + uniffiContinuationHandleMap.insert(continuation), + ) + } + } while (pollResult != UNIFFI_RUST_FUTURE_POLL_READY) + + return liftFunc( + uniffiRustCallWithError(errorHandler, { status -> completeFunc(rustFuture, status) }), + ) + } finally { + freeFunc(rustFuture) + } +} + +// Public interface members begin here. + +// Interface implemented by anything that can contain an object reference. +// +// Such types expose a `destroy()` method that must be called to cleanly +// dispose of the contained objects. Failure to call this method may result +// in memory leaks. +// +// The easiest way to ensure this method is called is to use the `.use` +// helper method to execute a block and destroy the object at the end. +interface Disposable { + fun destroy() + + companion object { + fun destroy(vararg args: Any?) { + args + .filterIsInstance() + .forEach(Disposable::destroy) + } + } +} + +/** + * @suppress + */ +inline fun T.use(block: (T) -> R) = + try { + block(this) + } finally { + try { + // N.B. our implementation is on the nullable type `Disposable?`. + this?.destroy() + } catch (e: Throwable) { + // swallow + } + } + +/** + * Used to instantiate an interface without an actual pointer, for fakes in tests, mostly. + * + * @suppress + * */ +object NoPointer + +/** + * @suppress + */ +public object FfiConverterUByte : FfiConverter { + override fun lift(value: Byte): UByte = value.toUByte() + + override fun read(buf: ByteBuffer): UByte = lift(buf.get()) + + override fun lower(value: UByte): Byte = value.toByte() + + override fun allocationSize(value: UByte) = 1UL + + override fun write( + value: UByte, + buf: ByteBuffer, + ) { + buf.put(value.toByte()) + } +} + +/** + * @suppress + */ +public object FfiConverterUShort : FfiConverter { + override fun lift(value: Short): UShort = value.toUShort() + + override fun read(buf: ByteBuffer): UShort = lift(buf.getShort()) + + override fun lower(value: UShort): Short = value.toShort() + + override fun allocationSize(value: UShort) = 2UL + + override fun write( + value: UShort, + buf: ByteBuffer, + ) { + buf.putShort(value.toShort()) + } +} + +/** + * @suppress + */ +public object FfiConverterUInt : FfiConverter { + override fun lift(value: Int): UInt = value.toUInt() + + override fun read(buf: ByteBuffer): UInt = lift(buf.getInt()) + + override fun lower(value: UInt): Int = value.toInt() + + override fun allocationSize(value: UInt) = 4UL + + override fun write( + value: UInt, + buf: ByteBuffer, + ) { + buf.putInt(value.toInt()) + } +} + +/** + * @suppress + */ +public object FfiConverterULong : FfiConverter { + override fun lift(value: Long): ULong = value.toULong() + + override fun read(buf: ByteBuffer): ULong = lift(buf.getLong()) + + override fun lower(value: ULong): Long = value.toLong() + + override fun allocationSize(value: ULong) = 8UL + + override fun write( + value: ULong, + buf: ByteBuffer, + ) { + buf.putLong(value.toLong()) + } +} + +/** + * @suppress + */ +public object FfiConverterLong : FfiConverter { + override fun lift(value: Long): Long = value + + override fun read(buf: ByteBuffer): Long = buf.getLong() + + override fun lower(value: Long): Long = value + + override fun allocationSize(value: Long) = 8UL + + override fun write( + value: Long, + buf: ByteBuffer, + ) { + buf.putLong(value) + } +} + +/** + * @suppress + */ +public object FfiConverterBoolean : FfiConverter { + override fun lift(value: Byte): Boolean = value.toInt() != 0 + + override fun read(buf: ByteBuffer): Boolean = lift(buf.get()) + + override fun lower(value: Boolean): Byte = if (value) 1.toByte() else 0.toByte() + + override fun allocationSize(value: Boolean) = 1UL + + override fun write( + value: Boolean, + buf: ByteBuffer, + ) { + buf.put(lower(value)) + } +} + +/** + * @suppress + */ +public object FfiConverterString : FfiConverter { + // Note: we don't inherit from FfiConverterRustBuffer, because we use a + // special encoding when lowering/lifting. We can use `RustBuffer.len` to + // store our length and avoid writing it out to the buffer. + override fun lift(value: RustBuffer.ByValue): String { + try { + val byteArr = ByteArray(value.len.toInt()) + value.asByteBuffer()!!.get(byteArr) + return byteArr.toString(Charsets.UTF_8) + } finally { + RustBuffer.free(value) + } + } + + override fun read(buf: ByteBuffer): String { + val len = buf.getInt() + val byteArr = ByteArray(len) + buf.get(byteArr) + return byteArr.toString(Charsets.UTF_8) + } + + fun toUtf8(value: String): ByteBuffer { + // Make sure we don't have invalid UTF-16, check for lone surrogates. + return Charsets.UTF_8.newEncoder().run { + onMalformedInput(CodingErrorAction.REPORT) + encode(CharBuffer.wrap(value)) + } + } + + override fun lower(value: String): RustBuffer.ByValue { + val byteBuf = toUtf8(value) + // Ideally we'd pass these bytes to `ffi_bytebuffer_from_bytes`, but doing so would require us + // to copy them into a JNA `Memory`. So we might as well directly copy them into a `RustBuffer`. + val rbuf = RustBuffer.alloc(byteBuf.limit().toULong()) + rbuf.asByteBuffer()!!.put(byteBuf) + return rbuf + } + + // We aren't sure exactly how many bytes our string will be once it's UTF-8 + // encoded. Allocate 3 bytes per UTF-16 code unit which will always be + // enough. + override fun allocationSize(value: String): ULong { + val sizeForLength = 4UL + val sizeForString = value.length.toULong() * 3UL + return sizeForLength + sizeForString + } + + override fun write( + value: String, + buf: ByteBuffer, + ) { + val byteBuf = toUtf8(value) + buf.putInt(byteBuf.limit()) + buf.put(byteBuf) + } +} + +/** + * @suppress + */ +public object FfiConverterByteArray : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): ByteArray { + val len = buf.getInt() + val byteArr = ByteArray(len) + buf.get(byteArr) + return byteArr + } + + override fun allocationSize(value: ByteArray): ULong = 4UL + value.size.toULong() + + override fun write( + value: ByteArray, + buf: ByteBuffer, + ) { + buf.putInt(value.size) + buf.put(value) + } +} + +// This template implements a class for working with a Rust struct via a Pointer/Arc +// to the live Rust struct on the other side of the FFI. +// +// Each instance implements core operations for working with the Rust `Arc` and the +// Kotlin Pointer to work with the live Rust struct on the other side of the FFI. +// +// There's some subtlety here, because we have to be careful not to operate on a Rust +// struct after it has been dropped, and because we must expose a public API for freeing +// theq Kotlin wrapper object in lieu of reliable finalizers. The core requirements are: +// +// * Each instance holds an opaque pointer to the underlying Rust struct. +// Method calls need to read this pointer from the object's state and pass it in to +// the Rust FFI. +// +// * When an instance is no longer needed, its pointer should be passed to a +// special destructor function provided by the Rust FFI, which will drop the +// underlying Rust struct. +// +// * Given an instance, calling code is expected to call the special +// `destroy` method in order to free it after use, either by calling it explicitly +// or by using a higher-level helper like the `use` method. Failing to do so risks +// leaking the underlying Rust struct. +// +// * We can't assume that calling code will do the right thing, and must be prepared +// to handle Kotlin method calls executing concurrently with or even after a call to +// `destroy`, and to handle multiple (possibly concurrent!) calls to `destroy`. +// +// * We must never allow Rust code to operate on the underlying Rust struct after +// the destructor has been called, and must never call the destructor more than once. +// Doing so may trigger memory unsafety. +// +// * To mitigate many of the risks of leaking memory and use-after-free unsafety, a `Cleaner` +// is implemented to call the destructor when the Kotlin object becomes unreachable. +// This is done in a background thread. This is not a panacea, and client code should be aware that +// 1. the thread may starve if some there are objects that have poorly performing +// `drop` methods or do significant work in their `drop` methods. +// 2. the thread is shared across the whole library. This can be tuned by using `android_cleaner = true`, +// or `android = true` in the [`kotlin` section of the `uniffi.toml` file](https://mozilla.github.io/uniffi-rs/kotlin/configuration.html). +// +// If we try to implement this with mutual exclusion on access to the pointer, there is the +// possibility of a race between a method call and a concurrent call to `destroy`: +// +// * Thread A starts a method call, reads the value of the pointer, but is interrupted +// before it can pass the pointer over the FFI to Rust. +// * Thread B calls `destroy` and frees the underlying Rust struct. +// * Thread A resumes, passing the already-read pointer value to Rust and triggering +// a use-after-free. +// +// One possible solution would be to use a `ReadWriteLock`, with each method call taking +// a read lock (and thus allowed to run concurrently) and the special `destroy` method +// taking a write lock (and thus blocking on live method calls). However, we aim not to +// generate methods with any hidden blocking semantics, and a `destroy` method that might +// block if called incorrectly seems to meet that bar. +// +// So, we achieve our goals by giving each instance an associated `AtomicLong` counter to track +// the number of in-flight method calls, and an `AtomicBoolean` flag to indicate whether `destroy` +// has been called. These are updated according to the following rules: +// +// * The initial value of the counter is 1, indicating a live object with no in-flight calls. +// The initial value for the flag is false. +// +// * At the start of each method call, we atomically check the counter. +// If it is 0 then the underlying Rust struct has already been destroyed and the call is aborted. +// If it is nonzero them we atomically increment it by 1 and proceed with the method call. +// +// * At the end of each method call, we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// * When `destroy` is called, we atomically flip the flag from false to true. +// If the flag was already true we silently fail. +// Otherwise we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// Astute readers may observe that this all sounds very similar to the way that Rust's `Arc` works, +// and indeed it is, with the addition of a flag to guard against multiple calls to `destroy`. +// +// The overall effect is that the underlying Rust struct is destroyed only when `destroy` has been +// called *and* all in-flight method calls have completed, avoiding violating any of the expectations +// of the underlying Rust code. +// +// This makes a cleaner a better alternative to _not_ calling `destroy()` as +// and when the object is finished with, but the abstraction is not perfect: if the Rust object's `drop` +// method is slow, and/or there are many objects to cleanup, and it's on a low end Android device, then the cleaner +// thread may be starved, and the app will leak memory. +// +// In this case, `destroy`ing manually may be a better solution. +// +// The cleaner can live side by side with the manual calling of `destroy`. In the order of responsiveness, uniffi objects +// with Rust peers are reclaimed: +// +// 1. By calling the `destroy` method of the object, which calls `rustObject.free()`. If that doesn't happen: +// 2. When the object becomes unreachable, AND the Cleaner thread gets to call `rustObject.free()`. If the thread is starved then: +// 3. The memory is reclaimed when the process terminates. +// +// [1] https://stackoverflow.com/questions/24376768/can-java-finalize-an-object-when-it-is-still-in-scope/24380219 +// + +/** + * The cleaner interface for Object finalization code to run. + * This is the entry point to any implementation that we're using. + * + * The cleaner registers objects and returns cleanables, so now we are + * defining a `UniffiCleaner` with a `UniffiClenaer.Cleanable` to abstract the + * different implmentations available at compile time. + * + * @suppress + */ +interface UniffiCleaner { + interface Cleanable { + fun clean() + } + + fun register( + value: Any, + cleanUpTask: Runnable, + ): UniffiCleaner.Cleanable + + companion object +} + +// The fallback Jna cleaner, which is available for both Android, and the JVM. +private class UniffiJnaCleaner : UniffiCleaner { + private val cleaner = + com.sun.jna.internal.Cleaner + .getCleaner() + + override fun register( + value: Any, + cleanUpTask: Runnable, + ): UniffiCleaner.Cleanable = UniffiJnaCleanable(cleaner.register(value, cleanUpTask)) +} + +private class UniffiJnaCleanable( + private val cleanable: com.sun.jna.internal.Cleaner.Cleanable, +) : UniffiCleaner.Cleanable { + override fun clean() = cleanable.clean() +} + +// We decide at uniffi binding generation time whether we were +// using Android or not. +// There are further runtime checks to chose the correct implementation +// of the cleaner. +private fun UniffiCleaner.Companion.create(): UniffiCleaner = + try { + // For safety's sake: if the library hasn't been run in android_cleaner = true + // mode, but is being run on Android, then we still need to think about + // Android API versions. + // So we check if java.lang.ref.Cleaner is there, and use that… + java.lang.Class.forName("java.lang.ref.Cleaner") + JavaLangRefCleaner() + } catch (e: ClassNotFoundException) { + // … otherwise, fallback to the JNA cleaner. + UniffiJnaCleaner() + } + +private class JavaLangRefCleaner : UniffiCleaner { + val cleaner = + java.lang.ref.Cleaner + .create() + + override fun register( + value: Any, + cleanUpTask: Runnable, + ): UniffiCleaner.Cleanable = JavaLangRefCleanable(cleaner.register(value, cleanUpTask)) +} + +private class JavaLangRefCleanable( + val cleanable: java.lang.ref.Cleaner.Cleanable, +) : UniffiCleaner.Cleanable { + override fun clean() = cleanable.clean() +} + +public interface Bolt11InvoiceInterface { + fun `amountMilliSatoshis`(): kotlin.ULong? + + fun `currency`(): Currency + + fun `expiryTimeSeconds`(): kotlin.ULong + + fun `fallbackAddresses`(): List
+ + fun `invoiceDescription`(): Bolt11InvoiceDescription + + fun `isExpired`(): kotlin.Boolean + + fun `minFinalCltvExpiryDelta`(): kotlin.ULong + + fun `network`(): Network + + fun `paymentHash`(): PaymentHash + + fun `paymentSecret`(): PaymentSecret + + fun `recoverPayeePubKey`(): PublicKey + + fun `routeHints`(): List> + + fun `secondsSinceEpoch`(): kotlin.ULong + + fun `secondsUntilExpiry`(): kotlin.ULong + + fun `signableHash`(): List + + fun `wouldExpire`(`atTimeSeconds`: kotlin.ULong): kotlin.Boolean + + companion object +} + +open class Bolt11Invoice : + Disposable, + AutoCloseable, + Bolt11InvoiceInterface { + constructor(pointer: Pointer) { + this.pointer = pointer + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + /** + * This constructor can be used to instantiate a fake object. Only used for tests. Any + * attempt to actually use an object constructed this way will fail as there is no + * connected Rust object. + */ + @Suppress("UNUSED_PARAMETER") + constructor(noPointer: NoPointer) { + this.pointer = null + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + protected val pointer: Pointer? + protected val cleanable: UniffiCleaner.Cleanable + + private val wasDestroyed = AtomicBoolean(false) + private val callCounter = AtomicLong(1) + + override fun destroy() { + // Only allow a single call to this method. + // TODO: maybe we should log a warning if called more than once? + if (this.wasDestroyed.compareAndSet(false, true)) { + // This decrement always matches the initial count of 1 given at creation time. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + @Synchronized + override fun close() { + this.destroy() + } + + internal inline fun callWithPointer(block: (ptr: Pointer) -> R): R { + // Check and increment the call counter, to keep the object alive. + // This needs a compare-and-set retry loop in case of concurrent updates. + do { + val c = this.callCounter.get() + if (c == 0L) { + throw IllegalStateException("${this.javaClass.simpleName} object has already been destroyed") + } + if (c == Long.MAX_VALUE) { + throw IllegalStateException("${this.javaClass.simpleName} call counter would overflow") + } + } while (!this.callCounter.compareAndSet(c, c + 1L)) + // Now we can safely do the method call without the pointer being freed concurrently. + try { + return block(this.uniffiClonePointer()) + } finally { + // This decrement always matches the increment we performed above. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + // Use a static inner class instead of a closure so as not to accidentally + // capture `this` as part of the cleanable's action. + private class UniffiCleanAction( + private val pointer: Pointer?, + ) : Runnable { + override fun run() { + pointer?.let { ptr -> + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_free_bolt11invoice(ptr, status) + } + } + } + } + + fun uniffiClonePointer(): Pointer = + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_clone_bolt11invoice(pointer!!, status) + } + + override fun `amountMilliSatoshis`(): kotlin.ULong? = + FfiConverterOptionalULong.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11invoice_amount_milli_satoshis(it, _status) + } + }, + ) + + override fun `currency`(): Currency = + FfiConverterTypeCurrency.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11invoice_currency(it, _status) + } + }, + ) + + override fun `expiryTimeSeconds`(): kotlin.ULong = + FfiConverterULong.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11invoice_expiry_time_seconds(it, _status) + } + }, + ) + + override fun `fallbackAddresses`(): List
= + FfiConverterSequenceTypeAddress.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11invoice_fallback_addresses(it, _status) + } + }, + ) + + override fun `invoiceDescription`(): Bolt11InvoiceDescription = + FfiConverterTypeBolt11InvoiceDescription.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11invoice_invoice_description(it, _status) + } + }, + ) + + override fun `isExpired`(): kotlin.Boolean = + FfiConverterBoolean.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11invoice_is_expired(it, _status) + } + }, + ) + + override fun `minFinalCltvExpiryDelta`(): kotlin.ULong = + FfiConverterULong.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11invoice_min_final_cltv_expiry_delta(it, _status) + } + }, + ) + + override fun `network`(): Network = + FfiConverterTypeNetwork.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11invoice_network(it, _status) + } + }, + ) + + override fun `paymentHash`(): PaymentHash = + FfiConverterTypePaymentHash.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11invoice_payment_hash(it, _status) + } + }, + ) + + override fun `paymentSecret`(): PaymentSecret = + FfiConverterTypePaymentSecret.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11invoice_payment_secret(it, _status) + } + }, + ) + + override fun `recoverPayeePubKey`(): PublicKey = + FfiConverterTypePublicKey.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11invoice_recover_payee_pub_key(it, _status) + } + }, + ) + + override fun `routeHints`(): List> = + FfiConverterSequenceSequenceTypeRouteHintHop.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11invoice_route_hints(it, _status) + } + }, + ) + + override fun `secondsSinceEpoch`(): kotlin.ULong = + FfiConverterULong.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11invoice_seconds_since_epoch(it, _status) + } + }, + ) + + override fun `secondsUntilExpiry`(): kotlin.ULong = + FfiConverterULong.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11invoice_seconds_until_expiry(it, _status) + } + }, + ) + + override fun `signableHash`(): List = + FfiConverterSequenceUByte.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11invoice_signable_hash(it, _status) + } + }, + ) + + override fun `wouldExpire`(`atTimeSeconds`: kotlin.ULong): kotlin.Boolean = + FfiConverterBoolean.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11invoice_would_expire( + it, + FfiConverterULong.lower(`atTimeSeconds`), + _status, + ) + } + }, + ) + + override fun toString(): String = + FfiConverterString.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11invoice_uniffi_trait_display(it, _status) + } + }, + ) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is Bolt11Invoice) return false + return FfiConverterBoolean.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11invoice_uniffi_trait_eq_eq( + it, + FfiConverterTypeBolt11Invoice.lower(`other`), + _status, + ) + } + }, + ) + } + + companion object { + @Throws(NodeException::class) + fun `fromStr`(`invoiceStr`: kotlin.String): Bolt11Invoice = + FfiConverterTypeBolt11Invoice.lift( + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_constructor_bolt11invoice_from_str( + FfiConverterString.lower(`invoiceStr`), + _status, + ) + }, + ) + } +} + +/** + * @suppress + */ +public object FfiConverterTypeBolt11Invoice : FfiConverter { + override fun lower(value: Bolt11Invoice): Pointer = value.uniffiClonePointer() + + override fun lift(value: Pointer): Bolt11Invoice = Bolt11Invoice(value) + + override fun read(buf: ByteBuffer): Bolt11Invoice { + // The Rust code always writes pointers as 8 bytes, and will + // fail to compile if they don't fit. + return lift(Pointer(buf.getLong())) + } + + override fun allocationSize(value: Bolt11Invoice) = 8UL + + override fun write( + value: Bolt11Invoice, + buf: ByteBuffer, + ) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(lower(value))) + } +} + +// This template implements a class for working with a Rust struct via a Pointer/Arc +// to the live Rust struct on the other side of the FFI. +// +// Each instance implements core operations for working with the Rust `Arc` and the +// Kotlin Pointer to work with the live Rust struct on the other side of the FFI. +// +// There's some subtlety here, because we have to be careful not to operate on a Rust +// struct after it has been dropped, and because we must expose a public API for freeing +// theq Kotlin wrapper object in lieu of reliable finalizers. The core requirements are: +// +// * Each instance holds an opaque pointer to the underlying Rust struct. +// Method calls need to read this pointer from the object's state and pass it in to +// the Rust FFI. +// +// * When an instance is no longer needed, its pointer should be passed to a +// special destructor function provided by the Rust FFI, which will drop the +// underlying Rust struct. +// +// * Given an instance, calling code is expected to call the special +// `destroy` method in order to free it after use, either by calling it explicitly +// or by using a higher-level helper like the `use` method. Failing to do so risks +// leaking the underlying Rust struct. +// +// * We can't assume that calling code will do the right thing, and must be prepared +// to handle Kotlin method calls executing concurrently with or even after a call to +// `destroy`, and to handle multiple (possibly concurrent!) calls to `destroy`. +// +// * We must never allow Rust code to operate on the underlying Rust struct after +// the destructor has been called, and must never call the destructor more than once. +// Doing so may trigger memory unsafety. +// +// * To mitigate many of the risks of leaking memory and use-after-free unsafety, a `Cleaner` +// is implemented to call the destructor when the Kotlin object becomes unreachable. +// This is done in a background thread. This is not a panacea, and client code should be aware that +// 1. the thread may starve if some there are objects that have poorly performing +// `drop` methods or do significant work in their `drop` methods. +// 2. the thread is shared across the whole library. This can be tuned by using `android_cleaner = true`, +// or `android = true` in the [`kotlin` section of the `uniffi.toml` file](https://mozilla.github.io/uniffi-rs/kotlin/configuration.html). +// +// If we try to implement this with mutual exclusion on access to the pointer, there is the +// possibility of a race between a method call and a concurrent call to `destroy`: +// +// * Thread A starts a method call, reads the value of the pointer, but is interrupted +// before it can pass the pointer over the FFI to Rust. +// * Thread B calls `destroy` and frees the underlying Rust struct. +// * Thread A resumes, passing the already-read pointer value to Rust and triggering +// a use-after-free. +// +// One possible solution would be to use a `ReadWriteLock`, with each method call taking +// a read lock (and thus allowed to run concurrently) and the special `destroy` method +// taking a write lock (and thus blocking on live method calls). However, we aim not to +// generate methods with any hidden blocking semantics, and a `destroy` method that might +// block if called incorrectly seems to meet that bar. +// +// So, we achieve our goals by giving each instance an associated `AtomicLong` counter to track +// the number of in-flight method calls, and an `AtomicBoolean` flag to indicate whether `destroy` +// has been called. These are updated according to the following rules: +// +// * The initial value of the counter is 1, indicating a live object with no in-flight calls. +// The initial value for the flag is false. +// +// * At the start of each method call, we atomically check the counter. +// If it is 0 then the underlying Rust struct has already been destroyed and the call is aborted. +// If it is nonzero them we atomically increment it by 1 and proceed with the method call. +// +// * At the end of each method call, we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// * When `destroy` is called, we atomically flip the flag from false to true. +// If the flag was already true we silently fail. +// Otherwise we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// Astute readers may observe that this all sounds very similar to the way that Rust's `Arc` works, +// and indeed it is, with the addition of a flag to guard against multiple calls to `destroy`. +// +// The overall effect is that the underlying Rust struct is destroyed only when `destroy` has been +// called *and* all in-flight method calls have completed, avoiding violating any of the expectations +// of the underlying Rust code. +// +// This makes a cleaner a better alternative to _not_ calling `destroy()` as +// and when the object is finished with, but the abstraction is not perfect: if the Rust object's `drop` +// method is slow, and/or there are many objects to cleanup, and it's on a low end Android device, then the cleaner +// thread may be starved, and the app will leak memory. +// +// In this case, `destroy`ing manually may be a better solution. +// +// The cleaner can live side by side with the manual calling of `destroy`. In the order of responsiveness, uniffi objects +// with Rust peers are reclaimed: +// +// 1. By calling the `destroy` method of the object, which calls `rustObject.free()`. If that doesn't happen: +// 2. When the object becomes unreachable, AND the Cleaner thread gets to call `rustObject.free()`. If the thread is starved then: +// 3. The memory is reclaimed when the process terminates. +// +// [1] https://stackoverflow.com/questions/24376768/can-java-finalize-an-object-when-it-is-still-in-scope/24380219 +// + +public interface Bolt11PaymentInterface { + fun `claimForHash`( + `paymentHash`: PaymentHash, + `claimableAmountMsat`: kotlin.ULong, + `preimage`: PaymentPreimage, + ) + + fun `estimateRoutingFees`(`invoice`: Bolt11Invoice): kotlin.ULong + + fun `estimateRoutingFeesUsingAmount`( + `invoice`: Bolt11Invoice, + `amountMsat`: kotlin.ULong, + ): kotlin.ULong + + fun `failForHash`(`paymentHash`: PaymentHash) + + fun `receive`( + `amountMsat`: kotlin.ULong, + `description`: Bolt11InvoiceDescription, + `expirySecs`: kotlin.UInt, + ): Bolt11Invoice + + fun `receiveForHash`( + `amountMsat`: kotlin.ULong, + `description`: Bolt11InvoiceDescription, + `expirySecs`: kotlin.UInt, + `paymentHash`: PaymentHash, + ): Bolt11Invoice + + fun `receiveVariableAmount`( + `description`: Bolt11InvoiceDescription, + `expirySecs`: kotlin.UInt, + ): Bolt11Invoice + + fun `receiveVariableAmountForHash`( + `description`: Bolt11InvoiceDescription, + `expirySecs`: kotlin.UInt, + `paymentHash`: PaymentHash, + ): Bolt11Invoice + + fun `receiveVariableAmountViaJitChannel`( + `description`: Bolt11InvoiceDescription, + `expirySecs`: kotlin.UInt, + `maxProportionalLspFeeLimitPpmMsat`: kotlin.ULong?, + ): Bolt11Invoice + + fun `receiveVariableAmountViaJitChannelForHash`( + `description`: Bolt11InvoiceDescription, + `expirySecs`: kotlin.UInt, + `maxProportionalLspFeeLimitPpmMsat`: kotlin.ULong?, + `paymentHash`: PaymentHash, + ): Bolt11Invoice + + fun `receiveViaJitChannel`( + `amountMsat`: kotlin.ULong, + `description`: Bolt11InvoiceDescription, + `expirySecs`: kotlin.UInt, + `maxLspFeeLimitMsat`: kotlin.ULong?, + ): Bolt11Invoice + + fun `receiveViaJitChannelForHash`( + `amountMsat`: kotlin.ULong, + `description`: Bolt11InvoiceDescription, + `expirySecs`: kotlin.UInt, + `maxLspFeeLimitMsat`: kotlin.ULong?, + `paymentHash`: PaymentHash, + ): Bolt11Invoice + + fun `send`( + `invoice`: Bolt11Invoice, + `routeParameters`: RouteParametersConfig?, + ): PaymentId + + fun `sendProbes`( + `invoice`: Bolt11Invoice, + `routeParameters`: RouteParametersConfig?, + ) + + fun `sendProbesUsingAmount`( + `invoice`: Bolt11Invoice, + `amountMsat`: kotlin.ULong, + `routeParameters`: RouteParametersConfig?, + ) + + fun `sendUsingAmount`( + `invoice`: Bolt11Invoice, + `amountMsat`: kotlin.ULong, + `routeParameters`: RouteParametersConfig?, + ): PaymentId + + companion object +} + +open class Bolt11Payment : + Disposable, + AutoCloseable, + Bolt11PaymentInterface { + constructor(pointer: Pointer) { + this.pointer = pointer + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + /** + * This constructor can be used to instantiate a fake object. Only used for tests. Any + * attempt to actually use an object constructed this way will fail as there is no + * connected Rust object. + */ + @Suppress("UNUSED_PARAMETER") + constructor(noPointer: NoPointer) { + this.pointer = null + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + protected val pointer: Pointer? + protected val cleanable: UniffiCleaner.Cleanable + + private val wasDestroyed = AtomicBoolean(false) + private val callCounter = AtomicLong(1) + + override fun destroy() { + // Only allow a single call to this method. + // TODO: maybe we should log a warning if called more than once? + if (this.wasDestroyed.compareAndSet(false, true)) { + // This decrement always matches the initial count of 1 given at creation time. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + @Synchronized + override fun close() { + this.destroy() + } + + internal inline fun callWithPointer(block: (ptr: Pointer) -> R): R { + // Check and increment the call counter, to keep the object alive. + // This needs a compare-and-set retry loop in case of concurrent updates. + do { + val c = this.callCounter.get() + if (c == 0L) { + throw IllegalStateException("${this.javaClass.simpleName} object has already been destroyed") + } + if (c == Long.MAX_VALUE) { + throw IllegalStateException("${this.javaClass.simpleName} call counter would overflow") + } + } while (!this.callCounter.compareAndSet(c, c + 1L)) + // Now we can safely do the method call without the pointer being freed concurrently. + try { + return block(this.uniffiClonePointer()) + } finally { + // This decrement always matches the increment we performed above. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + // Use a static inner class instead of a closure so as not to accidentally + // capture `this` as part of the cleanable's action. + private class UniffiCleanAction( + private val pointer: Pointer?, + ) : Runnable { + override fun run() { + pointer?.let { ptr -> + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_free_bolt11payment(ptr, status) + } + } + } + } + + fun uniffiClonePointer(): Pointer = + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_clone_bolt11payment(pointer!!, status) + } + + @Throws(NodeException::class) + override fun `claimForHash`( + `paymentHash`: PaymentHash, + `claimableAmountMsat`: kotlin.ULong, + `preimage`: PaymentPreimage, + ) = callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11payment_claim_for_hash( + it, + FfiConverterTypePaymentHash.lower(`paymentHash`), + FfiConverterULong.lower(`claimableAmountMsat`), + FfiConverterTypePaymentPreimage.lower(`preimage`), + _status, + ) + } + } + + @Throws(NodeException::class) + override fun `estimateRoutingFees`(`invoice`: Bolt11Invoice): kotlin.ULong = + FfiConverterULong.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11payment_estimate_routing_fees( + it, + FfiConverterTypeBolt11Invoice.lower(`invoice`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `estimateRoutingFeesUsingAmount`( + `invoice`: Bolt11Invoice, + `amountMsat`: kotlin.ULong, + ): kotlin.ULong = + FfiConverterULong.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11payment_estimate_routing_fees_using_amount( + it, + FfiConverterTypeBolt11Invoice.lower(`invoice`), + FfiConverterULong.lower(`amountMsat`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `failForHash`(`paymentHash`: PaymentHash) = + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11payment_fail_for_hash( + it, + FfiConverterTypePaymentHash.lower(`paymentHash`), + _status, + ) + } + } + + @Throws(NodeException::class) + override fun `receive`( + `amountMsat`: kotlin.ULong, + `description`: Bolt11InvoiceDescription, + `expirySecs`: kotlin.UInt, + ): Bolt11Invoice = + FfiConverterTypeBolt11Invoice.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11payment_receive( + it, + FfiConverterULong.lower(`amountMsat`), + FfiConverterTypeBolt11InvoiceDescription.lower(`description`), + FfiConverterUInt.lower(`expirySecs`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `receiveForHash`( + `amountMsat`: kotlin.ULong, + `description`: Bolt11InvoiceDescription, + `expirySecs`: kotlin.UInt, + `paymentHash`: PaymentHash, + ): Bolt11Invoice = + FfiConverterTypeBolt11Invoice.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11payment_receive_for_hash( + it, + FfiConverterULong.lower(`amountMsat`), + FfiConverterTypeBolt11InvoiceDescription.lower(`description`), + FfiConverterUInt.lower(`expirySecs`), + FfiConverterTypePaymentHash.lower(`paymentHash`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `receiveVariableAmount`( + `description`: Bolt11InvoiceDescription, + `expirySecs`: kotlin.UInt, + ): Bolt11Invoice = + FfiConverterTypeBolt11Invoice.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11payment_receive_variable_amount( + it, + FfiConverterTypeBolt11InvoiceDescription.lower(`description`), + FfiConverterUInt.lower(`expirySecs`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `receiveVariableAmountForHash`( + `description`: Bolt11InvoiceDescription, + `expirySecs`: kotlin.UInt, + `paymentHash`: PaymentHash, + ): Bolt11Invoice = + FfiConverterTypeBolt11Invoice.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11payment_receive_variable_amount_for_hash( + it, + FfiConverterTypeBolt11InvoiceDescription.lower(`description`), + FfiConverterUInt.lower(`expirySecs`), + FfiConverterTypePaymentHash.lower(`paymentHash`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `receiveVariableAmountViaJitChannel`( + `description`: Bolt11InvoiceDescription, + `expirySecs`: kotlin.UInt, + `maxProportionalLspFeeLimitPpmMsat`: kotlin.ULong?, + ): Bolt11Invoice = + FfiConverterTypeBolt11Invoice.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11payment_receive_variable_amount_via_jit_channel( + it, + FfiConverterTypeBolt11InvoiceDescription.lower(`description`), + FfiConverterUInt.lower(`expirySecs`), + FfiConverterOptionalULong.lower(`maxProportionalLspFeeLimitPpmMsat`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `receiveVariableAmountViaJitChannelForHash`( + `description`: Bolt11InvoiceDescription, + `expirySecs`: kotlin.UInt, + `maxProportionalLspFeeLimitPpmMsat`: kotlin.ULong?, + `paymentHash`: PaymentHash, + ): Bolt11Invoice = + FfiConverterTypeBolt11Invoice.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11payment_receive_variable_amount_via_jit_channel_for_hash( + it, + FfiConverterTypeBolt11InvoiceDescription.lower(`description`), + FfiConverterUInt.lower(`expirySecs`), + FfiConverterOptionalULong.lower(`maxProportionalLspFeeLimitPpmMsat`), + FfiConverterTypePaymentHash.lower(`paymentHash`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `receiveViaJitChannel`( + `amountMsat`: kotlin.ULong, + `description`: Bolt11InvoiceDescription, + `expirySecs`: kotlin.UInt, + `maxLspFeeLimitMsat`: kotlin.ULong?, + ): Bolt11Invoice = + FfiConverterTypeBolt11Invoice.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11payment_receive_via_jit_channel( + it, + FfiConverterULong.lower(`amountMsat`), + FfiConverterTypeBolt11InvoiceDescription.lower(`description`), + FfiConverterUInt.lower(`expirySecs`), + FfiConverterOptionalULong.lower(`maxLspFeeLimitMsat`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `receiveViaJitChannelForHash`( + `amountMsat`: kotlin.ULong, + `description`: Bolt11InvoiceDescription, + `expirySecs`: kotlin.UInt, + `maxLspFeeLimitMsat`: kotlin.ULong?, + `paymentHash`: PaymentHash, + ): Bolt11Invoice = + FfiConverterTypeBolt11Invoice.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11payment_receive_via_jit_channel_for_hash( + it, + FfiConverterULong.lower(`amountMsat`), + FfiConverterTypeBolt11InvoiceDescription.lower(`description`), + FfiConverterUInt.lower(`expirySecs`), + FfiConverterOptionalULong.lower(`maxLspFeeLimitMsat`), + FfiConverterTypePaymentHash.lower(`paymentHash`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `send`( + `invoice`: Bolt11Invoice, + `routeParameters`: RouteParametersConfig?, + ): PaymentId = + FfiConverterTypePaymentId.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11payment_send( + it, + FfiConverterTypeBolt11Invoice.lower(`invoice`), + FfiConverterOptionalTypeRouteParametersConfig.lower(`routeParameters`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `sendProbes`( + `invoice`: Bolt11Invoice, + `routeParameters`: RouteParametersConfig?, + ) = callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11payment_send_probes( + it, + FfiConverterTypeBolt11Invoice.lower(`invoice`), + FfiConverterOptionalTypeRouteParametersConfig.lower(`routeParameters`), + _status, + ) + } + } + + @Throws(NodeException::class) + override fun `sendProbesUsingAmount`( + `invoice`: Bolt11Invoice, + `amountMsat`: kotlin.ULong, + `routeParameters`: RouteParametersConfig?, + ) = callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11payment_send_probes_using_amount( + it, + FfiConverterTypeBolt11Invoice.lower(`invoice`), + FfiConverterULong.lower(`amountMsat`), + FfiConverterOptionalTypeRouteParametersConfig.lower(`routeParameters`), + _status, + ) + } + } + + @Throws(NodeException::class) + override fun `sendUsingAmount`( + `invoice`: Bolt11Invoice, + `amountMsat`: kotlin.ULong, + `routeParameters`: RouteParametersConfig?, + ): PaymentId = + FfiConverterTypePaymentId.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt11payment_send_using_amount( + it, + FfiConverterTypeBolt11Invoice.lower(`invoice`), + FfiConverterULong.lower(`amountMsat`), + FfiConverterOptionalTypeRouteParametersConfig.lower(`routeParameters`), + _status, + ) + } + }, + ) + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeBolt11Payment : FfiConverter { + override fun lower(value: Bolt11Payment): Pointer = value.uniffiClonePointer() + + override fun lift(value: Pointer): Bolt11Payment = Bolt11Payment(value) + + override fun read(buf: ByteBuffer): Bolt11Payment { + // The Rust code always writes pointers as 8 bytes, and will + // fail to compile if they don't fit. + return lift(Pointer(buf.getLong())) + } + + override fun allocationSize(value: Bolt11Payment) = 8UL + + override fun write( + value: Bolt11Payment, + buf: ByteBuffer, + ) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(lower(value))) + } +} + +// This template implements a class for working with a Rust struct via a Pointer/Arc +// to the live Rust struct on the other side of the FFI. +// +// Each instance implements core operations for working with the Rust `Arc` and the +// Kotlin Pointer to work with the live Rust struct on the other side of the FFI. +// +// There's some subtlety here, because we have to be careful not to operate on a Rust +// struct after it has been dropped, and because we must expose a public API for freeing +// theq Kotlin wrapper object in lieu of reliable finalizers. The core requirements are: +// +// * Each instance holds an opaque pointer to the underlying Rust struct. +// Method calls need to read this pointer from the object's state and pass it in to +// the Rust FFI. +// +// * When an instance is no longer needed, its pointer should be passed to a +// special destructor function provided by the Rust FFI, which will drop the +// underlying Rust struct. +// +// * Given an instance, calling code is expected to call the special +// `destroy` method in order to free it after use, either by calling it explicitly +// or by using a higher-level helper like the `use` method. Failing to do so risks +// leaking the underlying Rust struct. +// +// * We can't assume that calling code will do the right thing, and must be prepared +// to handle Kotlin method calls executing concurrently with or even after a call to +// `destroy`, and to handle multiple (possibly concurrent!) calls to `destroy`. +// +// * We must never allow Rust code to operate on the underlying Rust struct after +// the destructor has been called, and must never call the destructor more than once. +// Doing so may trigger memory unsafety. +// +// * To mitigate many of the risks of leaking memory and use-after-free unsafety, a `Cleaner` +// is implemented to call the destructor when the Kotlin object becomes unreachable. +// This is done in a background thread. This is not a panacea, and client code should be aware that +// 1. the thread may starve if some there are objects that have poorly performing +// `drop` methods or do significant work in their `drop` methods. +// 2. the thread is shared across the whole library. This can be tuned by using `android_cleaner = true`, +// or `android = true` in the [`kotlin` section of the `uniffi.toml` file](https://mozilla.github.io/uniffi-rs/kotlin/configuration.html). +// +// If we try to implement this with mutual exclusion on access to the pointer, there is the +// possibility of a race between a method call and a concurrent call to `destroy`: +// +// * Thread A starts a method call, reads the value of the pointer, but is interrupted +// before it can pass the pointer over the FFI to Rust. +// * Thread B calls `destroy` and frees the underlying Rust struct. +// * Thread A resumes, passing the already-read pointer value to Rust and triggering +// a use-after-free. +// +// One possible solution would be to use a `ReadWriteLock`, with each method call taking +// a read lock (and thus allowed to run concurrently) and the special `destroy` method +// taking a write lock (and thus blocking on live method calls). However, we aim not to +// generate methods with any hidden blocking semantics, and a `destroy` method that might +// block if called incorrectly seems to meet that bar. +// +// So, we achieve our goals by giving each instance an associated `AtomicLong` counter to track +// the number of in-flight method calls, and an `AtomicBoolean` flag to indicate whether `destroy` +// has been called. These are updated according to the following rules: +// +// * The initial value of the counter is 1, indicating a live object with no in-flight calls. +// The initial value for the flag is false. +// +// * At the start of each method call, we atomically check the counter. +// If it is 0 then the underlying Rust struct has already been destroyed and the call is aborted. +// If it is nonzero them we atomically increment it by 1 and proceed with the method call. +// +// * At the end of each method call, we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// * When `destroy` is called, we atomically flip the flag from false to true. +// If the flag was already true we silently fail. +// Otherwise we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// Astute readers may observe that this all sounds very similar to the way that Rust's `Arc` works, +// and indeed it is, with the addition of a flag to guard against multiple calls to `destroy`. +// +// The overall effect is that the underlying Rust struct is destroyed only when `destroy` has been +// called *and* all in-flight method calls have completed, avoiding violating any of the expectations +// of the underlying Rust code. +// +// This makes a cleaner a better alternative to _not_ calling `destroy()` as +// and when the object is finished with, but the abstraction is not perfect: if the Rust object's `drop` +// method is slow, and/or there are many objects to cleanup, and it's on a low end Android device, then the cleaner +// thread may be starved, and the app will leak memory. +// +// In this case, `destroy`ing manually may be a better solution. +// +// The cleaner can live side by side with the manual calling of `destroy`. In the order of responsiveness, uniffi objects +// with Rust peers are reclaimed: +// +// 1. By calling the `destroy` method of the object, which calls `rustObject.free()`. If that doesn't happen: +// 2. When the object becomes unreachable, AND the Cleaner thread gets to call `rustObject.free()`. If the thread is starved then: +// 3. The memory is reclaimed when the process terminates. +// +// [1] https://stackoverflow.com/questions/24376768/can-java-finalize-an-object-when-it-is-still-in-scope/24380219 +// + +public interface Bolt12InvoiceInterface { + fun `absoluteExpirySeconds`(): kotlin.ULong? + + fun `amount`(): OfferAmount? + + fun `amountMsats`(): kotlin.ULong + + fun `chain`(): List + + fun `createdAt`(): kotlin.ULong + + fun `encode`(): List + + fun `fallbackAddresses`(): List
+ + fun `invoiceDescription`(): kotlin.String? + + fun `isExpired`(): kotlin.Boolean + + fun `issuer`(): kotlin.String? + + fun `issuerSigningPubkey`(): PublicKey? + + fun `metadata`(): List? + + fun `offerChains`(): List>? + + fun `payerNote`(): kotlin.String? + + fun `payerSigningPubkey`(): PublicKey + + fun `paymentHash`(): PaymentHash + + fun `quantity`(): kotlin.ULong? + + fun `relativeExpiry`(): kotlin.ULong + + fun `signableHash`(): List + + fun `signingPubkey`(): PublicKey + + companion object +} + +open class Bolt12Invoice : + Disposable, + AutoCloseable, + Bolt12InvoiceInterface { + constructor(pointer: Pointer) { + this.pointer = pointer + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + /** + * This constructor can be used to instantiate a fake object. Only used for tests. Any + * attempt to actually use an object constructed this way will fail as there is no + * connected Rust object. + */ + @Suppress("UNUSED_PARAMETER") + constructor(noPointer: NoPointer) { + this.pointer = null + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + protected val pointer: Pointer? + protected val cleanable: UniffiCleaner.Cleanable + + private val wasDestroyed = AtomicBoolean(false) + private val callCounter = AtomicLong(1) + + override fun destroy() { + // Only allow a single call to this method. + // TODO: maybe we should log a warning if called more than once? + if (this.wasDestroyed.compareAndSet(false, true)) { + // This decrement always matches the initial count of 1 given at creation time. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + @Synchronized + override fun close() { + this.destroy() + } + + internal inline fun callWithPointer(block: (ptr: Pointer) -> R): R { + // Check and increment the call counter, to keep the object alive. + // This needs a compare-and-set retry loop in case of concurrent updates. + do { + val c = this.callCounter.get() + if (c == 0L) { + throw IllegalStateException("${this.javaClass.simpleName} object has already been destroyed") + } + if (c == Long.MAX_VALUE) { + throw IllegalStateException("${this.javaClass.simpleName} call counter would overflow") + } + } while (!this.callCounter.compareAndSet(c, c + 1L)) + // Now we can safely do the method call without the pointer being freed concurrently. + try { + return block(this.uniffiClonePointer()) + } finally { + // This decrement always matches the increment we performed above. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + // Use a static inner class instead of a closure so as not to accidentally + // capture `this` as part of the cleanable's action. + private class UniffiCleanAction( + private val pointer: Pointer?, + ) : Runnable { + override fun run() { + pointer?.let { ptr -> + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_free_bolt12invoice(ptr, status) + } + } + } + } + + fun uniffiClonePointer(): Pointer = + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_clone_bolt12invoice(pointer!!, status) + } + + override fun `absoluteExpirySeconds`(): kotlin.ULong? = + FfiConverterOptionalULong.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12invoice_absolute_expiry_seconds(it, _status) + } + }, + ) + + override fun `amount`(): OfferAmount? = + FfiConverterOptionalTypeOfferAmount.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12invoice_amount(it, _status) + } + }, + ) + + override fun `amountMsats`(): kotlin.ULong = + FfiConverterULong.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12invoice_amount_msats(it, _status) + } + }, + ) + + override fun `chain`(): List = + FfiConverterSequenceUByte.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12invoice_chain(it, _status) + } + }, + ) + + override fun `createdAt`(): kotlin.ULong = + FfiConverterULong.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12invoice_created_at(it, _status) + } + }, + ) + + override fun `encode`(): List = + FfiConverterSequenceUByte.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12invoice_encode(it, _status) + } + }, + ) + + override fun `fallbackAddresses`(): List
= + FfiConverterSequenceTypeAddress.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12invoice_fallback_addresses(it, _status) + } + }, + ) + + override fun `invoiceDescription`(): kotlin.String? = + FfiConverterOptionalString.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12invoice_invoice_description(it, _status) + } + }, + ) + + override fun `isExpired`(): kotlin.Boolean = + FfiConverterBoolean.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12invoice_is_expired(it, _status) + } + }, + ) + + override fun `issuer`(): kotlin.String? = + FfiConverterOptionalString.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12invoice_issuer(it, _status) + } + }, + ) + + override fun `issuerSigningPubkey`(): PublicKey? = + FfiConverterOptionalTypePublicKey.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12invoice_issuer_signing_pubkey(it, _status) + } + }, + ) + + override fun `metadata`(): List? = + FfiConverterOptionalSequenceUByte.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12invoice_metadata(it, _status) + } + }, + ) + + override fun `offerChains`(): List>? = + FfiConverterOptionalSequenceSequenceUByte.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12invoice_offer_chains(it, _status) + } + }, + ) + + override fun `payerNote`(): kotlin.String? = + FfiConverterOptionalString.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12invoice_payer_note(it, _status) + } + }, + ) + + override fun `payerSigningPubkey`(): PublicKey = + FfiConverterTypePublicKey.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12invoice_payer_signing_pubkey(it, _status) + } + }, + ) + + override fun `paymentHash`(): PaymentHash = + FfiConverterTypePaymentHash.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12invoice_payment_hash(it, _status) + } + }, + ) + + override fun `quantity`(): kotlin.ULong? = + FfiConverterOptionalULong.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12invoice_quantity(it, _status) + } + }, + ) + + override fun `relativeExpiry`(): kotlin.ULong = + FfiConverterULong.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12invoice_relative_expiry(it, _status) + } + }, + ) + + override fun `signableHash`(): List = + FfiConverterSequenceUByte.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12invoice_signable_hash(it, _status) + } + }, + ) + + override fun `signingPubkey`(): PublicKey = + FfiConverterTypePublicKey.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12invoice_signing_pubkey(it, _status) + } + }, + ) + + companion object { + @Throws(NodeException::class) + fun `fromStr`(`invoiceStr`: kotlin.String): Bolt12Invoice = + FfiConverterTypeBolt12Invoice.lift( + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_constructor_bolt12invoice_from_str( + FfiConverterString.lower(`invoiceStr`), + _status, + ) + }, + ) + } +} + +/** + * @suppress + */ +public object FfiConverterTypeBolt12Invoice : FfiConverter { + override fun lower(value: Bolt12Invoice): Pointer = value.uniffiClonePointer() + + override fun lift(value: Pointer): Bolt12Invoice = Bolt12Invoice(value) + + override fun read(buf: ByteBuffer): Bolt12Invoice { + // The Rust code always writes pointers as 8 bytes, and will + // fail to compile if they don't fit. + return lift(Pointer(buf.getLong())) + } + + override fun allocationSize(value: Bolt12Invoice) = 8UL + + override fun write( + value: Bolt12Invoice, + buf: ByteBuffer, + ) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(lower(value))) + } +} + +// This template implements a class for working with a Rust struct via a Pointer/Arc +// to the live Rust struct on the other side of the FFI. +// +// Each instance implements core operations for working with the Rust `Arc` and the +// Kotlin Pointer to work with the live Rust struct on the other side of the FFI. +// +// There's some subtlety here, because we have to be careful not to operate on a Rust +// struct after it has been dropped, and because we must expose a public API for freeing +// theq Kotlin wrapper object in lieu of reliable finalizers. The core requirements are: +// +// * Each instance holds an opaque pointer to the underlying Rust struct. +// Method calls need to read this pointer from the object's state and pass it in to +// the Rust FFI. +// +// * When an instance is no longer needed, its pointer should be passed to a +// special destructor function provided by the Rust FFI, which will drop the +// underlying Rust struct. +// +// * Given an instance, calling code is expected to call the special +// `destroy` method in order to free it after use, either by calling it explicitly +// or by using a higher-level helper like the `use` method. Failing to do so risks +// leaking the underlying Rust struct. +// +// * We can't assume that calling code will do the right thing, and must be prepared +// to handle Kotlin method calls executing concurrently with or even after a call to +// `destroy`, and to handle multiple (possibly concurrent!) calls to `destroy`. +// +// * We must never allow Rust code to operate on the underlying Rust struct after +// the destructor has been called, and must never call the destructor more than once. +// Doing so may trigger memory unsafety. +// +// * To mitigate many of the risks of leaking memory and use-after-free unsafety, a `Cleaner` +// is implemented to call the destructor when the Kotlin object becomes unreachable. +// This is done in a background thread. This is not a panacea, and client code should be aware that +// 1. the thread may starve if some there are objects that have poorly performing +// `drop` methods or do significant work in their `drop` methods. +// 2. the thread is shared across the whole library. This can be tuned by using `android_cleaner = true`, +// or `android = true` in the [`kotlin` section of the `uniffi.toml` file](https://mozilla.github.io/uniffi-rs/kotlin/configuration.html). +// +// If we try to implement this with mutual exclusion on access to the pointer, there is the +// possibility of a race between a method call and a concurrent call to `destroy`: +// +// * Thread A starts a method call, reads the value of the pointer, but is interrupted +// before it can pass the pointer over the FFI to Rust. +// * Thread B calls `destroy` and frees the underlying Rust struct. +// * Thread A resumes, passing the already-read pointer value to Rust and triggering +// a use-after-free. +// +// One possible solution would be to use a `ReadWriteLock`, with each method call taking +// a read lock (and thus allowed to run concurrently) and the special `destroy` method +// taking a write lock (and thus blocking on live method calls). However, we aim not to +// generate methods with any hidden blocking semantics, and a `destroy` method that might +// block if called incorrectly seems to meet that bar. +// +// So, we achieve our goals by giving each instance an associated `AtomicLong` counter to track +// the number of in-flight method calls, and an `AtomicBoolean` flag to indicate whether `destroy` +// has been called. These are updated according to the following rules: +// +// * The initial value of the counter is 1, indicating a live object with no in-flight calls. +// The initial value for the flag is false. +// +// * At the start of each method call, we atomically check the counter. +// If it is 0 then the underlying Rust struct has already been destroyed and the call is aborted. +// If it is nonzero them we atomically increment it by 1 and proceed with the method call. +// +// * At the end of each method call, we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// * When `destroy` is called, we atomically flip the flag from false to true. +// If the flag was already true we silently fail. +// Otherwise we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// Astute readers may observe that this all sounds very similar to the way that Rust's `Arc` works, +// and indeed it is, with the addition of a flag to guard against multiple calls to `destroy`. +// +// The overall effect is that the underlying Rust struct is destroyed only when `destroy` has been +// called *and* all in-flight method calls have completed, avoiding violating any of the expectations +// of the underlying Rust code. +// +// This makes a cleaner a better alternative to _not_ calling `destroy()` as +// and when the object is finished with, but the abstraction is not perfect: if the Rust object's `drop` +// method is slow, and/or there are many objects to cleanup, and it's on a low end Android device, then the cleaner +// thread may be starved, and the app will leak memory. +// +// In this case, `destroy`ing manually may be a better solution. +// +// The cleaner can live side by side with the manual calling of `destroy`. In the order of responsiveness, uniffi objects +// with Rust peers are reclaimed: +// +// 1. By calling the `destroy` method of the object, which calls `rustObject.free()`. If that doesn't happen: +// 2. When the object becomes unreachable, AND the Cleaner thread gets to call `rustObject.free()`. If the thread is starved then: +// 3. The memory is reclaimed when the process terminates. +// +// [1] https://stackoverflow.com/questions/24376768/can-java-finalize-an-object-when-it-is-still-in-scope/24380219 +// + +public interface Bolt12PaymentInterface { + fun `blindedPathsForAsyncRecipient`(`recipientId`: kotlin.ByteArray): kotlin.ByteArray + + fun `initiateRefund`( + `amountMsat`: kotlin.ULong, + `expirySecs`: kotlin.UInt, + `quantity`: kotlin.ULong?, + `payerNote`: kotlin.String?, + `routeParameters`: RouteParametersConfig?, + ): Refund + + fun `receive`( + `amountMsat`: kotlin.ULong, + `description`: kotlin.String, + `expirySecs`: kotlin.UInt?, + `quantity`: kotlin.ULong?, + ): Offer + + fun `receiveAsync`(): Offer + + fun `receiveVariableAmount`( + `description`: kotlin.String, + `expirySecs`: kotlin.UInt?, + ): Offer + + fun `requestRefundPayment`(`refund`: Refund): Bolt12Invoice + + fun `send`( + `offer`: Offer, + `quantity`: kotlin.ULong?, + `payerNote`: kotlin.String?, + `routeParameters`: RouteParametersConfig?, + ): PaymentId + + fun `sendUsingAmount`( + `offer`: Offer, + `amountMsat`: kotlin.ULong, + `quantity`: kotlin.ULong?, + `payerNote`: kotlin.String?, + `routeParameters`: RouteParametersConfig?, + ): PaymentId + + fun `setPathsToStaticInvoiceServer`(`paths`: kotlin.ByteArray) + + companion object +} + +open class Bolt12Payment : + Disposable, + AutoCloseable, + Bolt12PaymentInterface { + constructor(pointer: Pointer) { + this.pointer = pointer + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + /** + * This constructor can be used to instantiate a fake object. Only used for tests. Any + * attempt to actually use an object constructed this way will fail as there is no + * connected Rust object. + */ + @Suppress("UNUSED_PARAMETER") + constructor(noPointer: NoPointer) { + this.pointer = null + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + protected val pointer: Pointer? + protected val cleanable: UniffiCleaner.Cleanable + + private val wasDestroyed = AtomicBoolean(false) + private val callCounter = AtomicLong(1) + + override fun destroy() { + // Only allow a single call to this method. + // TODO: maybe we should log a warning if called more than once? + if (this.wasDestroyed.compareAndSet(false, true)) { + // This decrement always matches the initial count of 1 given at creation time. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + @Synchronized + override fun close() { + this.destroy() + } + + internal inline fun callWithPointer(block: (ptr: Pointer) -> R): R { + // Check and increment the call counter, to keep the object alive. + // This needs a compare-and-set retry loop in case of concurrent updates. + do { + val c = this.callCounter.get() + if (c == 0L) { + throw IllegalStateException("${this.javaClass.simpleName} object has already been destroyed") + } + if (c == Long.MAX_VALUE) { + throw IllegalStateException("${this.javaClass.simpleName} call counter would overflow") + } + } while (!this.callCounter.compareAndSet(c, c + 1L)) + // Now we can safely do the method call without the pointer being freed concurrently. + try { + return block(this.uniffiClonePointer()) + } finally { + // This decrement always matches the increment we performed above. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + // Use a static inner class instead of a closure so as not to accidentally + // capture `this` as part of the cleanable's action. + private class UniffiCleanAction( + private val pointer: Pointer?, + ) : Runnable { + override fun run() { + pointer?.let { ptr -> + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_free_bolt12payment(ptr, status) + } + } + } + } + + fun uniffiClonePointer(): Pointer = + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_clone_bolt12payment(pointer!!, status) + } + + @Throws(NodeException::class) + override fun `blindedPathsForAsyncRecipient`(`recipientId`: kotlin.ByteArray): kotlin.ByteArray = + FfiConverterByteArray.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12payment_blinded_paths_for_async_recipient( + it, + FfiConverterByteArray.lower(`recipientId`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `initiateRefund`( + `amountMsat`: kotlin.ULong, + `expirySecs`: kotlin.UInt, + `quantity`: kotlin.ULong?, + `payerNote`: kotlin.String?, + `routeParameters`: RouteParametersConfig?, + ): Refund = + FfiConverterTypeRefund.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12payment_initiate_refund( + it, + FfiConverterULong.lower(`amountMsat`), + FfiConverterUInt.lower(`expirySecs`), + FfiConverterOptionalULong.lower(`quantity`), + FfiConverterOptionalString.lower(`payerNote`), + FfiConverterOptionalTypeRouteParametersConfig.lower(`routeParameters`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `receive`( + `amountMsat`: kotlin.ULong, + `description`: kotlin.String, + `expirySecs`: kotlin.UInt?, + `quantity`: kotlin.ULong?, + ): Offer = + FfiConverterTypeOffer.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12payment_receive( + it, + FfiConverterULong.lower(`amountMsat`), + FfiConverterString.lower(`description`), + FfiConverterOptionalUInt.lower(`expirySecs`), + FfiConverterOptionalULong.lower(`quantity`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `receiveAsync`(): Offer = + FfiConverterTypeOffer.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12payment_receive_async(it, _status) + } + }, + ) + + @Throws(NodeException::class) + override fun `receiveVariableAmount`( + `description`: kotlin.String, + `expirySecs`: kotlin.UInt?, + ): Offer = + FfiConverterTypeOffer.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12payment_receive_variable_amount( + it, + FfiConverterString.lower(`description`), + FfiConverterOptionalUInt.lower(`expirySecs`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `requestRefundPayment`(`refund`: Refund): Bolt12Invoice = + FfiConverterTypeBolt12Invoice.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12payment_request_refund_payment( + it, + FfiConverterTypeRefund.lower(`refund`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `send`( + `offer`: Offer, + `quantity`: kotlin.ULong?, + `payerNote`: kotlin.String?, + `routeParameters`: RouteParametersConfig?, + ): PaymentId = + FfiConverterTypePaymentId.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12payment_send( + it, + FfiConverterTypeOffer.lower(`offer`), + FfiConverterOptionalULong.lower(`quantity`), + FfiConverterOptionalString.lower(`payerNote`), + FfiConverterOptionalTypeRouteParametersConfig.lower(`routeParameters`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `sendUsingAmount`( + `offer`: Offer, + `amountMsat`: kotlin.ULong, + `quantity`: kotlin.ULong?, + `payerNote`: kotlin.String?, + `routeParameters`: RouteParametersConfig?, + ): PaymentId = + FfiConverterTypePaymentId.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12payment_send_using_amount( + it, + FfiConverterTypeOffer.lower(`offer`), + FfiConverterULong.lower(`amountMsat`), + FfiConverterOptionalULong.lower(`quantity`), + FfiConverterOptionalString.lower(`payerNote`), + FfiConverterOptionalTypeRouteParametersConfig.lower(`routeParameters`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `setPathsToStaticInvoiceServer`(`paths`: kotlin.ByteArray) = + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_bolt12payment_set_paths_to_static_invoice_server( + it, + FfiConverterByteArray.lower(`paths`), + _status, + ) + } + } + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeBolt12Payment : FfiConverter { + override fun lower(value: Bolt12Payment): Pointer = value.uniffiClonePointer() + + override fun lift(value: Pointer): Bolt12Payment = Bolt12Payment(value) + + override fun read(buf: ByteBuffer): Bolt12Payment { + // The Rust code always writes pointers as 8 bytes, and will + // fail to compile if they don't fit. + return lift(Pointer(buf.getLong())) + } + + override fun allocationSize(value: Bolt12Payment) = 8UL + + override fun write( + value: Bolt12Payment, + buf: ByteBuffer, + ) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(lower(value))) + } +} + +// This template implements a class for working with a Rust struct via a Pointer/Arc +// to the live Rust struct on the other side of the FFI. +// +// Each instance implements core operations for working with the Rust `Arc` and the +// Kotlin Pointer to work with the live Rust struct on the other side of the FFI. +// +// There's some subtlety here, because we have to be careful not to operate on a Rust +// struct after it has been dropped, and because we must expose a public API for freeing +// theq Kotlin wrapper object in lieu of reliable finalizers. The core requirements are: +// +// * Each instance holds an opaque pointer to the underlying Rust struct. +// Method calls need to read this pointer from the object's state and pass it in to +// the Rust FFI. +// +// * When an instance is no longer needed, its pointer should be passed to a +// special destructor function provided by the Rust FFI, which will drop the +// underlying Rust struct. +// +// * Given an instance, calling code is expected to call the special +// `destroy` method in order to free it after use, either by calling it explicitly +// or by using a higher-level helper like the `use` method. Failing to do so risks +// leaking the underlying Rust struct. +// +// * We can't assume that calling code will do the right thing, and must be prepared +// to handle Kotlin method calls executing concurrently with or even after a call to +// `destroy`, and to handle multiple (possibly concurrent!) calls to `destroy`. +// +// * We must never allow Rust code to operate on the underlying Rust struct after +// the destructor has been called, and must never call the destructor more than once. +// Doing so may trigger memory unsafety. +// +// * To mitigate many of the risks of leaking memory and use-after-free unsafety, a `Cleaner` +// is implemented to call the destructor when the Kotlin object becomes unreachable. +// This is done in a background thread. This is not a panacea, and client code should be aware that +// 1. the thread may starve if some there are objects that have poorly performing +// `drop` methods or do significant work in their `drop` methods. +// 2. the thread is shared across the whole library. This can be tuned by using `android_cleaner = true`, +// or `android = true` in the [`kotlin` section of the `uniffi.toml` file](https://mozilla.github.io/uniffi-rs/kotlin/configuration.html). +// +// If we try to implement this with mutual exclusion on access to the pointer, there is the +// possibility of a race between a method call and a concurrent call to `destroy`: +// +// * Thread A starts a method call, reads the value of the pointer, but is interrupted +// before it can pass the pointer over the FFI to Rust. +// * Thread B calls `destroy` and frees the underlying Rust struct. +// * Thread A resumes, passing the already-read pointer value to Rust and triggering +// a use-after-free. +// +// One possible solution would be to use a `ReadWriteLock`, with each method call taking +// a read lock (and thus allowed to run concurrently) and the special `destroy` method +// taking a write lock (and thus blocking on live method calls). However, we aim not to +// generate methods with any hidden blocking semantics, and a `destroy` method that might +// block if called incorrectly seems to meet that bar. +// +// So, we achieve our goals by giving each instance an associated `AtomicLong` counter to track +// the number of in-flight method calls, and an `AtomicBoolean` flag to indicate whether `destroy` +// has been called. These are updated according to the following rules: +// +// * The initial value of the counter is 1, indicating a live object with no in-flight calls. +// The initial value for the flag is false. +// +// * At the start of each method call, we atomically check the counter. +// If it is 0 then the underlying Rust struct has already been destroyed and the call is aborted. +// If it is nonzero them we atomically increment it by 1 and proceed with the method call. +// +// * At the end of each method call, we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// * When `destroy` is called, we atomically flip the flag from false to true. +// If the flag was already true we silently fail. +// Otherwise we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// Astute readers may observe that this all sounds very similar to the way that Rust's `Arc` works, +// and indeed it is, with the addition of a flag to guard against multiple calls to `destroy`. +// +// The overall effect is that the underlying Rust struct is destroyed only when `destroy` has been +// called *and* all in-flight method calls have completed, avoiding violating any of the expectations +// of the underlying Rust code. +// +// This makes a cleaner a better alternative to _not_ calling `destroy()` as +// and when the object is finished with, but the abstraction is not perfect: if the Rust object's `drop` +// method is slow, and/or there are many objects to cleanup, and it's on a low end Android device, then the cleaner +// thread may be starved, and the app will leak memory. +// +// In this case, `destroy`ing manually may be a better solution. +// +// The cleaner can live side by side with the manual calling of `destroy`. In the order of responsiveness, uniffi objects +// with Rust peers are reclaimed: +// +// 1. By calling the `destroy` method of the object, which calls `rustObject.free()`. If that doesn't happen: +// 2. When the object becomes unreachable, AND the Cleaner thread gets to call `rustObject.free()`. If the thread is starved then: +// 3. The memory is reclaimed when the process terminates. +// +// [1] https://stackoverflow.com/questions/24376768/can-java-finalize-an-object-when-it-is-still-in-scope/24380219 +// + +public interface BuilderInterface { + fun `build`(): Node + + fun `buildWithFsStore`(): Node + + fun `buildWithVssStore`( + `vssUrl`: kotlin.String, + `storeId`: kotlin.String, + `lnurlAuthServerUrl`: kotlin.String, + `fixedHeaders`: Map, + ): Node + + fun `buildWithVssStoreAndFixedHeaders`( + `vssUrl`: kotlin.String, + `storeId`: kotlin.String, + `fixedHeaders`: Map, + ): Node + + fun `buildWithVssStoreAndHeaderProvider`( + `vssUrl`: kotlin.String, + `storeId`: kotlin.String, + `headerProvider`: VssHeaderProvider, + ): Node + + fun `setAnnouncementAddresses`(`announcementAddresses`: List) + + fun `setAsyncPaymentsRole`(`role`: AsyncPaymentsRole?) + + fun `setChainSourceBitcoindRest`( + `restHost`: kotlin.String, + `restPort`: kotlin.UShort, + `rpcHost`: kotlin.String, + `rpcPort`: kotlin.UShort, + `rpcUser`: kotlin.String, + `rpcPassword`: kotlin.String, + ) + + fun `setChainSourceBitcoindRpc`( + `rpcHost`: kotlin.String, + `rpcPort`: kotlin.UShort, + `rpcUser`: kotlin.String, + `rpcPassword`: kotlin.String, + ) + + fun `setChainSourceElectrum`( + `serverUrl`: kotlin.String, + `config`: ElectrumSyncConfig?, + ) + + fun `setChainSourceEsplora`( + `serverUrl`: kotlin.String, + `config`: EsploraSyncConfig?, + ) + + fun `setChannelDataMigration`(`migration`: ChannelDataMigration) + + fun `setCustomLogger`(`logWriter`: LogWriter) + + fun `setEntropyBip39Mnemonic`( + `mnemonic`: Mnemonic, + `passphrase`: kotlin.String?, + ) + + fun `setEntropySeedBytes`(`seedBytes`: List) + + fun `setEntropySeedPath`(`seedPath`: kotlin.String) + + fun `setFilesystemLogger`( + `logFilePath`: kotlin.String?, + `maxLogLevel`: LogLevel?, + ) + + fun `setGossipSourceP2p`() + + fun `setGossipSourceRgs`(`rgsServerUrl`: kotlin.String) + + fun `setLiquiditySourceLsps1`( + `nodeId`: PublicKey, + `address`: SocketAddress, + `token`: kotlin.String?, + ) + + fun `setLiquiditySourceLsps2`( + `nodeId`: PublicKey, + `address`: SocketAddress, + `token`: kotlin.String?, + ) + + fun `setListeningAddresses`(`listeningAddresses`: List) + + fun `setLogFacadeLogger`() + + fun `setNetwork`(`network`: Network) + + fun `setNodeAlias`(`nodeAlias`: kotlin.String) + + fun `setPathfindingScoresSource`(`url`: kotlin.String) + + fun `setStorageDirPath`(`storageDirPath`: kotlin.String) + + companion object +} + +open class Builder : + Disposable, + AutoCloseable, + BuilderInterface { + constructor(pointer: Pointer) { + this.pointer = pointer + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + /** + * This constructor can be used to instantiate a fake object. Only used for tests. Any + * attempt to actually use an object constructed this way will fail as there is no + * connected Rust object. + */ + @Suppress("UNUSED_PARAMETER") + constructor(noPointer: NoPointer) { + this.pointer = null + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + constructor() : + this( + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_constructor_builder_new(_status) + }, + ) + + protected val pointer: Pointer? + protected val cleanable: UniffiCleaner.Cleanable + + private val wasDestroyed = AtomicBoolean(false) + private val callCounter = AtomicLong(1) + + override fun destroy() { + // Only allow a single call to this method. + // TODO: maybe we should log a warning if called more than once? + if (this.wasDestroyed.compareAndSet(false, true)) { + // This decrement always matches the initial count of 1 given at creation time. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + @Synchronized + override fun close() { + this.destroy() + } + + internal inline fun callWithPointer(block: (ptr: Pointer) -> R): R { + // Check and increment the call counter, to keep the object alive. + // This needs a compare-and-set retry loop in case of concurrent updates. + do { + val c = this.callCounter.get() + if (c == 0L) { + throw IllegalStateException("${this.javaClass.simpleName} object has already been destroyed") + } + if (c == Long.MAX_VALUE) { + throw IllegalStateException("${this.javaClass.simpleName} call counter would overflow") + } + } while (!this.callCounter.compareAndSet(c, c + 1L)) + // Now we can safely do the method call without the pointer being freed concurrently. + try { + return block(this.uniffiClonePointer()) + } finally { + // This decrement always matches the increment we performed above. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + // Use a static inner class instead of a closure so as not to accidentally + // capture `this` as part of the cleanable's action. + private class UniffiCleanAction( + private val pointer: Pointer?, + ) : Runnable { + override fun run() { + pointer?.let { ptr -> + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_free_builder(ptr, status) + } + } + } + } + + fun uniffiClonePointer(): Pointer = + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_clone_builder(pointer!!, status) + } + + @Throws(BuildException::class) + override fun `build`(): Node = + FfiConverterTypeNode.lift( + callWithPointer { + uniffiRustCallWithError(BuildException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_build(it, _status) + } + }, + ) + + @Throws(BuildException::class) + override fun `buildWithFsStore`(): Node = + FfiConverterTypeNode.lift( + callWithPointer { + uniffiRustCallWithError(BuildException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_build_with_fs_store(it, _status) + } + }, + ) + + @Throws(BuildException::class) + override fun `buildWithVssStore`( + `vssUrl`: kotlin.String, + `storeId`: kotlin.String, + `lnurlAuthServerUrl`: kotlin.String, + `fixedHeaders`: Map, + ): Node = + FfiConverterTypeNode.lift( + callWithPointer { + uniffiRustCallWithError(BuildException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_build_with_vss_store( + it, + FfiConverterString.lower(`vssUrl`), + FfiConverterString.lower(`storeId`), + FfiConverterString.lower(`lnurlAuthServerUrl`), + FfiConverterMapStringString.lower(`fixedHeaders`), + _status, + ) + } + }, + ) + + @Throws(BuildException::class) + override fun `buildWithVssStoreAndFixedHeaders`( + `vssUrl`: kotlin.String, + `storeId`: kotlin.String, + `fixedHeaders`: Map, + ): Node = + FfiConverterTypeNode.lift( + callWithPointer { + uniffiRustCallWithError(BuildException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_build_with_vss_store_and_fixed_headers( + it, + FfiConverterString.lower(`vssUrl`), + FfiConverterString.lower(`storeId`), + FfiConverterMapStringString.lower(`fixedHeaders`), + _status, + ) + } + }, + ) + + @Throws(BuildException::class) + override fun `buildWithVssStoreAndHeaderProvider`( + `vssUrl`: kotlin.String, + `storeId`: kotlin.String, + `headerProvider`: VssHeaderProvider, + ): Node = + FfiConverterTypeNode.lift( + callWithPointer { + uniffiRustCallWithError(BuildException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_build_with_vss_store_and_header_provider( + it, + FfiConverterString.lower(`vssUrl`), + FfiConverterString.lower(`storeId`), + FfiConverterTypeVssHeaderProvider.lower(`headerProvider`), + _status, + ) + } + }, + ) + + @Throws(BuildException::class) + override fun `setAnnouncementAddresses`(`announcementAddresses`: List) = + callWithPointer { + uniffiRustCallWithError(BuildException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_set_announcement_addresses( + it, + FfiConverterSequenceTypeSocketAddress.lower(`announcementAddresses`), + _status, + ) + } + } + + @Throws(BuildException::class) + override fun `setAsyncPaymentsRole`(`role`: AsyncPaymentsRole?) = + callWithPointer { + uniffiRustCallWithError(BuildException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_set_async_payments_role( + it, + FfiConverterOptionalTypeAsyncPaymentsRole.lower(`role`), + _status, + ) + } + } + + override fun `setChainSourceBitcoindRest`( + `restHost`: kotlin.String, + `restPort`: kotlin.UShort, + `rpcHost`: kotlin.String, + `rpcPort`: kotlin.UShort, + `rpcUser`: kotlin.String, + `rpcPassword`: kotlin.String, + ) = callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_set_chain_source_bitcoind_rest( + it, + FfiConverterString.lower(`restHost`), + FfiConverterUShort.lower(`restPort`), + FfiConverterString.lower(`rpcHost`), + FfiConverterUShort.lower(`rpcPort`), + FfiConverterString.lower(`rpcUser`), + FfiConverterString.lower(`rpcPassword`), + _status, + ) + } + } + + override fun `setChainSourceBitcoindRpc`( + `rpcHost`: kotlin.String, + `rpcPort`: kotlin.UShort, + `rpcUser`: kotlin.String, + `rpcPassword`: kotlin.String, + ) = callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_set_chain_source_bitcoind_rpc( + it, + FfiConverterString.lower(`rpcHost`), + FfiConverterUShort.lower(`rpcPort`), + FfiConverterString.lower(`rpcUser`), + FfiConverterString.lower(`rpcPassword`), + _status, + ) + } + } + + override fun `setChainSourceElectrum`( + `serverUrl`: kotlin.String, + `config`: ElectrumSyncConfig?, + ) = callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_set_chain_source_electrum( + it, + FfiConverterString.lower(`serverUrl`), + FfiConverterOptionalTypeElectrumSyncConfig.lower(`config`), + _status, + ) + } + } + + override fun `setChainSourceEsplora`( + `serverUrl`: kotlin.String, + `config`: EsploraSyncConfig?, + ) = callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_set_chain_source_esplora( + it, + FfiConverterString.lower(`serverUrl`), + FfiConverterOptionalTypeEsploraSyncConfig.lower(`config`), + _status, + ) + } + } + + override fun `setChannelDataMigration`(`migration`: ChannelDataMigration) = + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_set_channel_data_migration( + it, + FfiConverterTypeChannelDataMigration.lower(`migration`), + _status, + ) + } + } + + override fun `setCustomLogger`(`logWriter`: LogWriter) = + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_set_custom_logger( + it, + FfiConverterTypeLogWriter.lower(`logWriter`), + _status, + ) + } + } + + override fun `setEntropyBip39Mnemonic`( + `mnemonic`: Mnemonic, + `passphrase`: kotlin.String?, + ) = callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_set_entropy_bip39_mnemonic( + it, + FfiConverterTypeMnemonic.lower(`mnemonic`), + FfiConverterOptionalString.lower(`passphrase`), + _status, + ) + } + } + + @Throws(BuildException::class) + override fun `setEntropySeedBytes`(`seedBytes`: List) = + callWithPointer { + uniffiRustCallWithError(BuildException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_set_entropy_seed_bytes( + it, + FfiConverterSequenceUByte.lower(`seedBytes`), + _status, + ) + } + } + + override fun `setEntropySeedPath`(`seedPath`: kotlin.String) = + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_set_entropy_seed_path( + it, + FfiConverterString.lower(`seedPath`), + _status, + ) + } + } + + override fun `setFilesystemLogger`( + `logFilePath`: kotlin.String?, + `maxLogLevel`: LogLevel?, + ) = callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_set_filesystem_logger( + it, + FfiConverterOptionalString.lower(`logFilePath`), + FfiConverterOptionalTypeLogLevel.lower(`maxLogLevel`), + _status, + ) + } + } + + override fun `setGossipSourceP2p`() = + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_set_gossip_source_p2p(it, _status) + } + } + + override fun `setGossipSourceRgs`(`rgsServerUrl`: kotlin.String) = + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_set_gossip_source_rgs( + it, + FfiConverterString.lower(`rgsServerUrl`), + _status, + ) + } + } + + override fun `setLiquiditySourceLsps1`( + `nodeId`: PublicKey, + `address`: SocketAddress, + `token`: kotlin.String?, + ) = callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_set_liquidity_source_lsps1( + it, + FfiConverterTypePublicKey.lower(`nodeId`), + FfiConverterTypeSocketAddress.lower(`address`), + FfiConverterOptionalString.lower(`token`), + _status, + ) + } + } + + override fun `setLiquiditySourceLsps2`( + `nodeId`: PublicKey, + `address`: SocketAddress, + `token`: kotlin.String?, + ) = callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_set_liquidity_source_lsps2( + it, + FfiConverterTypePublicKey.lower(`nodeId`), + FfiConverterTypeSocketAddress.lower(`address`), + FfiConverterOptionalString.lower(`token`), + _status, + ) + } + } + + @Throws(BuildException::class) + override fun `setListeningAddresses`(`listeningAddresses`: List) = + callWithPointer { + uniffiRustCallWithError(BuildException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_set_listening_addresses( + it, + FfiConverterSequenceTypeSocketAddress.lower(`listeningAddresses`), + _status, + ) + } + } + + override fun `setLogFacadeLogger`() = + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_set_log_facade_logger(it, _status) + } + } + + override fun `setNetwork`(`network`: Network) = + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_set_network(it, FfiConverterTypeNetwork.lower(`network`), _status) + } + } + + @Throws(BuildException::class) + override fun `setNodeAlias`(`nodeAlias`: kotlin.String) = + callWithPointer { + uniffiRustCallWithError(BuildException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_set_node_alias(it, FfiConverterString.lower(`nodeAlias`), _status) + } + } + + override fun `setPathfindingScoresSource`(`url`: kotlin.String) = + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_set_pathfinding_scores_source( + it, + FfiConverterString.lower(`url`), + _status, + ) + } + } + + override fun `setStorageDirPath`(`storageDirPath`: kotlin.String) = + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_builder_set_storage_dir_path( + it, + FfiConverterString.lower(`storageDirPath`), + _status, + ) + } + } + + companion object { + fun `fromConfig`(`config`: Config): Builder = + FfiConverterTypeBuilder.lift( + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_constructor_builder_from_config(FfiConverterTypeConfig.lower(`config`), _status) + }, + ) + } +} + +/** + * @suppress + */ +public object FfiConverterTypeBuilder : FfiConverter { + override fun lower(value: Builder): Pointer = value.uniffiClonePointer() + + override fun lift(value: Pointer): Builder = Builder(value) + + override fun read(buf: ByteBuffer): Builder { + // The Rust code always writes pointers as 8 bytes, and will + // fail to compile if they don't fit. + return lift(Pointer(buf.getLong())) + } + + override fun allocationSize(value: Builder) = 8UL + + override fun write( + value: Builder, + buf: ByteBuffer, + ) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(lower(value))) + } +} + +// This template implements a class for working with a Rust struct via a Pointer/Arc +// to the live Rust struct on the other side of the FFI. +// +// Each instance implements core operations for working with the Rust `Arc` and the +// Kotlin Pointer to work with the live Rust struct on the other side of the FFI. +// +// There's some subtlety here, because we have to be careful not to operate on a Rust +// struct after it has been dropped, and because we must expose a public API for freeing +// theq Kotlin wrapper object in lieu of reliable finalizers. The core requirements are: +// +// * Each instance holds an opaque pointer to the underlying Rust struct. +// Method calls need to read this pointer from the object's state and pass it in to +// the Rust FFI. +// +// * When an instance is no longer needed, its pointer should be passed to a +// special destructor function provided by the Rust FFI, which will drop the +// underlying Rust struct. +// +// * Given an instance, calling code is expected to call the special +// `destroy` method in order to free it after use, either by calling it explicitly +// or by using a higher-level helper like the `use` method. Failing to do so risks +// leaking the underlying Rust struct. +// +// * We can't assume that calling code will do the right thing, and must be prepared +// to handle Kotlin method calls executing concurrently with or even after a call to +// `destroy`, and to handle multiple (possibly concurrent!) calls to `destroy`. +// +// * We must never allow Rust code to operate on the underlying Rust struct after +// the destructor has been called, and must never call the destructor more than once. +// Doing so may trigger memory unsafety. +// +// * To mitigate many of the risks of leaking memory and use-after-free unsafety, a `Cleaner` +// is implemented to call the destructor when the Kotlin object becomes unreachable. +// This is done in a background thread. This is not a panacea, and client code should be aware that +// 1. the thread may starve if some there are objects that have poorly performing +// `drop` methods or do significant work in their `drop` methods. +// 2. the thread is shared across the whole library. This can be tuned by using `android_cleaner = true`, +// or `android = true` in the [`kotlin` section of the `uniffi.toml` file](https://mozilla.github.io/uniffi-rs/kotlin/configuration.html). +// +// If we try to implement this with mutual exclusion on access to the pointer, there is the +// possibility of a race between a method call and a concurrent call to `destroy`: +// +// * Thread A starts a method call, reads the value of the pointer, but is interrupted +// before it can pass the pointer over the FFI to Rust. +// * Thread B calls `destroy` and frees the underlying Rust struct. +// * Thread A resumes, passing the already-read pointer value to Rust and triggering +// a use-after-free. +// +// One possible solution would be to use a `ReadWriteLock`, with each method call taking +// a read lock (and thus allowed to run concurrently) and the special `destroy` method +// taking a write lock (and thus blocking on live method calls). However, we aim not to +// generate methods with any hidden blocking semantics, and a `destroy` method that might +// block if called incorrectly seems to meet that bar. +// +// So, we achieve our goals by giving each instance an associated `AtomicLong` counter to track +// the number of in-flight method calls, and an `AtomicBoolean` flag to indicate whether `destroy` +// has been called. These are updated according to the following rules: +// +// * The initial value of the counter is 1, indicating a live object with no in-flight calls. +// The initial value for the flag is false. +// +// * At the start of each method call, we atomically check the counter. +// If it is 0 then the underlying Rust struct has already been destroyed and the call is aborted. +// If it is nonzero them we atomically increment it by 1 and proceed with the method call. +// +// * At the end of each method call, we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// * When `destroy` is called, we atomically flip the flag from false to true. +// If the flag was already true we silently fail. +// Otherwise we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// Astute readers may observe that this all sounds very similar to the way that Rust's `Arc` works, +// and indeed it is, with the addition of a flag to guard against multiple calls to `destroy`. +// +// The overall effect is that the underlying Rust struct is destroyed only when `destroy` has been +// called *and* all in-flight method calls have completed, avoiding violating any of the expectations +// of the underlying Rust code. +// +// This makes a cleaner a better alternative to _not_ calling `destroy()` as +// and when the object is finished with, but the abstraction is not perfect: if the Rust object's `drop` +// method is slow, and/or there are many objects to cleanup, and it's on a low end Android device, then the cleaner +// thread may be starved, and the app will leak memory. +// +// In this case, `destroy`ing manually may be a better solution. +// +// The cleaner can live side by side with the manual calling of `destroy`. In the order of responsiveness, uniffi objects +// with Rust peers are reclaimed: +// +// 1. By calling the `destroy` method of the object, which calls `rustObject.free()`. If that doesn't happen: +// 2. When the object becomes unreachable, AND the Cleaner thread gets to call `rustObject.free()`. If the thread is starved then: +// 3. The memory is reclaimed when the process terminates. +// +// [1] https://stackoverflow.com/questions/24376768/can-java-finalize-an-object-when-it-is-still-in-scope/24380219 +// + +public interface FeeRateInterface { + fun `toSatPerKwu`(): kotlin.ULong + + fun `toSatPerVbCeil`(): kotlin.ULong + + fun `toSatPerVbFloor`(): kotlin.ULong + + companion object +} + +open class FeeRate : + Disposable, + AutoCloseable, + FeeRateInterface { + constructor(pointer: Pointer) { + this.pointer = pointer + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + /** + * This constructor can be used to instantiate a fake object. Only used for tests. Any + * attempt to actually use an object constructed this way will fail as there is no + * connected Rust object. + */ + @Suppress("UNUSED_PARAMETER") + constructor(noPointer: NoPointer) { + this.pointer = null + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + protected val pointer: Pointer? + protected val cleanable: UniffiCleaner.Cleanable + + private val wasDestroyed = AtomicBoolean(false) + private val callCounter = AtomicLong(1) + + override fun destroy() { + // Only allow a single call to this method. + // TODO: maybe we should log a warning if called more than once? + if (this.wasDestroyed.compareAndSet(false, true)) { + // This decrement always matches the initial count of 1 given at creation time. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + @Synchronized + override fun close() { + this.destroy() + } + + internal inline fun callWithPointer(block: (ptr: Pointer) -> R): R { + // Check and increment the call counter, to keep the object alive. + // This needs a compare-and-set retry loop in case of concurrent updates. + do { + val c = this.callCounter.get() + if (c == 0L) { + throw IllegalStateException("${this.javaClass.simpleName} object has already been destroyed") + } + if (c == Long.MAX_VALUE) { + throw IllegalStateException("${this.javaClass.simpleName} call counter would overflow") + } + } while (!this.callCounter.compareAndSet(c, c + 1L)) + // Now we can safely do the method call without the pointer being freed concurrently. + try { + return block(this.uniffiClonePointer()) + } finally { + // This decrement always matches the increment we performed above. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + // Use a static inner class instead of a closure so as not to accidentally + // capture `this` as part of the cleanable's action. + private class UniffiCleanAction( + private val pointer: Pointer?, + ) : Runnable { + override fun run() { + pointer?.let { ptr -> + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_free_feerate(ptr, status) + } + } + } + } + + fun uniffiClonePointer(): Pointer = + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_clone_feerate(pointer!!, status) + } + + override fun `toSatPerKwu`(): kotlin.ULong = + FfiConverterULong.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_feerate_to_sat_per_kwu(it, _status) + } + }, + ) + + override fun `toSatPerVbCeil`(): kotlin.ULong = + FfiConverterULong.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_feerate_to_sat_per_vb_ceil(it, _status) + } + }, + ) + + override fun `toSatPerVbFloor`(): kotlin.ULong = + FfiConverterULong.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_feerate_to_sat_per_vb_floor(it, _status) + } + }, + ) + + companion object { + fun `fromSatPerKwu`(`satKwu`: kotlin.ULong): FeeRate = + FfiConverterTypeFeeRate.lift( + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_constructor_feerate_from_sat_per_kwu(FfiConverterULong.lower(`satKwu`), _status) + }, + ) + + fun `fromSatPerVbUnchecked`(`satVb`: kotlin.ULong): FeeRate = + FfiConverterTypeFeeRate.lift( + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_constructor_feerate_from_sat_per_vb_unchecked( + FfiConverterULong.lower(`satVb`), + _status, + ) + }, + ) + } +} + +/** + * @suppress + */ +public object FfiConverterTypeFeeRate : FfiConverter { + override fun lower(value: FeeRate): Pointer = value.uniffiClonePointer() + + override fun lift(value: Pointer): FeeRate = FeeRate(value) + + override fun read(buf: ByteBuffer): FeeRate { + // The Rust code always writes pointers as 8 bytes, and will + // fail to compile if they don't fit. + return lift(Pointer(buf.getLong())) + } + + override fun allocationSize(value: FeeRate) = 8UL + + override fun write( + value: FeeRate, + buf: ByteBuffer, + ) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(lower(value))) + } +} + +// This template implements a class for working with a Rust struct via a Pointer/Arc +// to the live Rust struct on the other side of the FFI. +// +// Each instance implements core operations for working with the Rust `Arc` and the +// Kotlin Pointer to work with the live Rust struct on the other side of the FFI. +// +// There's some subtlety here, because we have to be careful not to operate on a Rust +// struct after it has been dropped, and because we must expose a public API for freeing +// theq Kotlin wrapper object in lieu of reliable finalizers. The core requirements are: +// +// * Each instance holds an opaque pointer to the underlying Rust struct. +// Method calls need to read this pointer from the object's state and pass it in to +// the Rust FFI. +// +// * When an instance is no longer needed, its pointer should be passed to a +// special destructor function provided by the Rust FFI, which will drop the +// underlying Rust struct. +// +// * Given an instance, calling code is expected to call the special +// `destroy` method in order to free it after use, either by calling it explicitly +// or by using a higher-level helper like the `use` method. Failing to do so risks +// leaking the underlying Rust struct. +// +// * We can't assume that calling code will do the right thing, and must be prepared +// to handle Kotlin method calls executing concurrently with or even after a call to +// `destroy`, and to handle multiple (possibly concurrent!) calls to `destroy`. +// +// * We must never allow Rust code to operate on the underlying Rust struct after +// the destructor has been called, and must never call the destructor more than once. +// Doing so may trigger memory unsafety. +// +// * To mitigate many of the risks of leaking memory and use-after-free unsafety, a `Cleaner` +// is implemented to call the destructor when the Kotlin object becomes unreachable. +// This is done in a background thread. This is not a panacea, and client code should be aware that +// 1. the thread may starve if some there are objects that have poorly performing +// `drop` methods or do significant work in their `drop` methods. +// 2. the thread is shared across the whole library. This can be tuned by using `android_cleaner = true`, +// or `android = true` in the [`kotlin` section of the `uniffi.toml` file](https://mozilla.github.io/uniffi-rs/kotlin/configuration.html). +// +// If we try to implement this with mutual exclusion on access to the pointer, there is the +// possibility of a race between a method call and a concurrent call to `destroy`: +// +// * Thread A starts a method call, reads the value of the pointer, but is interrupted +// before it can pass the pointer over the FFI to Rust. +// * Thread B calls `destroy` and frees the underlying Rust struct. +// * Thread A resumes, passing the already-read pointer value to Rust and triggering +// a use-after-free. +// +// One possible solution would be to use a `ReadWriteLock`, with each method call taking +// a read lock (and thus allowed to run concurrently) and the special `destroy` method +// taking a write lock (and thus blocking on live method calls). However, we aim not to +// generate methods with any hidden blocking semantics, and a `destroy` method that might +// block if called incorrectly seems to meet that bar. +// +// So, we achieve our goals by giving each instance an associated `AtomicLong` counter to track +// the number of in-flight method calls, and an `AtomicBoolean` flag to indicate whether `destroy` +// has been called. These are updated according to the following rules: +// +// * The initial value of the counter is 1, indicating a live object with no in-flight calls. +// The initial value for the flag is false. +// +// * At the start of each method call, we atomically check the counter. +// If it is 0 then the underlying Rust struct has already been destroyed and the call is aborted. +// If it is nonzero them we atomically increment it by 1 and proceed with the method call. +// +// * At the end of each method call, we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// * When `destroy` is called, we atomically flip the flag from false to true. +// If the flag was already true we silently fail. +// Otherwise we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// Astute readers may observe that this all sounds very similar to the way that Rust's `Arc` works, +// and indeed it is, with the addition of a flag to guard against multiple calls to `destroy`. +// +// The overall effect is that the underlying Rust struct is destroyed only when `destroy` has been +// called *and* all in-flight method calls have completed, avoiding violating any of the expectations +// of the underlying Rust code. +// +// This makes a cleaner a better alternative to _not_ calling `destroy()` as +// and when the object is finished with, but the abstraction is not perfect: if the Rust object's `drop` +// method is slow, and/or there are many objects to cleanup, and it's on a low end Android device, then the cleaner +// thread may be starved, and the app will leak memory. +// +// In this case, `destroy`ing manually may be a better solution. +// +// The cleaner can live side by side with the manual calling of `destroy`. In the order of responsiveness, uniffi objects +// with Rust peers are reclaimed: +// +// 1. By calling the `destroy` method of the object, which calls `rustObject.free()`. If that doesn't happen: +// 2. When the object becomes unreachable, AND the Cleaner thread gets to call `rustObject.free()`. If the thread is starved then: +// 3. The memory is reclaimed when the process terminates. +// +// [1] https://stackoverflow.com/questions/24376768/can-java-finalize-an-object-when-it-is-still-in-scope/24380219 +// + +public interface Lsps1LiquidityInterface { + fun `checkOrderStatus`(`orderId`: Lsps1OrderId): Lsps1OrderStatus + + fun `requestChannel`( + `lspBalanceSat`: kotlin.ULong, + `clientBalanceSat`: kotlin.ULong, + `channelExpiryBlocks`: kotlin.UInt, + `announceChannel`: kotlin.Boolean, + ): Lsps1OrderStatus + + companion object +} + +open class Lsps1Liquidity : + Disposable, + AutoCloseable, + Lsps1LiquidityInterface { + constructor(pointer: Pointer) { + this.pointer = pointer + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + /** + * This constructor can be used to instantiate a fake object. Only used for tests. Any + * attempt to actually use an object constructed this way will fail as there is no + * connected Rust object. + */ + @Suppress("UNUSED_PARAMETER") + constructor(noPointer: NoPointer) { + this.pointer = null + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + protected val pointer: Pointer? + protected val cleanable: UniffiCleaner.Cleanable + + private val wasDestroyed = AtomicBoolean(false) + private val callCounter = AtomicLong(1) + + override fun destroy() { + // Only allow a single call to this method. + // TODO: maybe we should log a warning if called more than once? + if (this.wasDestroyed.compareAndSet(false, true)) { + // This decrement always matches the initial count of 1 given at creation time. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + @Synchronized + override fun close() { + this.destroy() + } + + internal inline fun callWithPointer(block: (ptr: Pointer) -> R): R { + // Check and increment the call counter, to keep the object alive. + // This needs a compare-and-set retry loop in case of concurrent updates. + do { + val c = this.callCounter.get() + if (c == 0L) { + throw IllegalStateException("${this.javaClass.simpleName} object has already been destroyed") + } + if (c == Long.MAX_VALUE) { + throw IllegalStateException("${this.javaClass.simpleName} call counter would overflow") + } + } while (!this.callCounter.compareAndSet(c, c + 1L)) + // Now we can safely do the method call without the pointer being freed concurrently. + try { + return block(this.uniffiClonePointer()) + } finally { + // This decrement always matches the increment we performed above. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + // Use a static inner class instead of a closure so as not to accidentally + // capture `this` as part of the cleanable's action. + private class UniffiCleanAction( + private val pointer: Pointer?, + ) : Runnable { + override fun run() { + pointer?.let { ptr -> + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_free_lsps1liquidity(ptr, status) + } + } + } + } + + fun uniffiClonePointer(): Pointer = + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_clone_lsps1liquidity(pointer!!, status) + } + + @Throws(NodeException::class) + override fun `checkOrderStatus`(`orderId`: Lsps1OrderId): Lsps1OrderStatus = + FfiConverterTypeLSPS1OrderStatus.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_lsps1liquidity_check_order_status( + it, + FfiConverterTypeLSPS1OrderId.lower(`orderId`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `requestChannel`( + `lspBalanceSat`: kotlin.ULong, + `clientBalanceSat`: kotlin.ULong, + `channelExpiryBlocks`: kotlin.UInt, + `announceChannel`: kotlin.Boolean, + ): Lsps1OrderStatus = + FfiConverterTypeLSPS1OrderStatus.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_lsps1liquidity_request_channel( + it, + FfiConverterULong.lower(`lspBalanceSat`), + FfiConverterULong.lower(`clientBalanceSat`), + FfiConverterUInt.lower(`channelExpiryBlocks`), + FfiConverterBoolean.lower(`announceChannel`), + _status, + ) + } + }, + ) + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeLSPS1Liquidity : FfiConverter { + override fun lower(value: Lsps1Liquidity): Pointer = value.uniffiClonePointer() + + override fun lift(value: Pointer): Lsps1Liquidity = Lsps1Liquidity(value) + + override fun read(buf: ByteBuffer): Lsps1Liquidity { + // The Rust code always writes pointers as 8 bytes, and will + // fail to compile if they don't fit. + return lift(Pointer(buf.getLong())) + } + + override fun allocationSize(value: Lsps1Liquidity) = 8UL + + override fun write( + value: Lsps1Liquidity, + buf: ByteBuffer, + ) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(lower(value))) + } +} + +// This template implements a class for working with a Rust struct via a Pointer/Arc +// to the live Rust struct on the other side of the FFI. +// +// Each instance implements core operations for working with the Rust `Arc` and the +// Kotlin Pointer to work with the live Rust struct on the other side of the FFI. +// +// There's some subtlety here, because we have to be careful not to operate on a Rust +// struct after it has been dropped, and because we must expose a public API for freeing +// theq Kotlin wrapper object in lieu of reliable finalizers. The core requirements are: +// +// * Each instance holds an opaque pointer to the underlying Rust struct. +// Method calls need to read this pointer from the object's state and pass it in to +// the Rust FFI. +// +// * When an instance is no longer needed, its pointer should be passed to a +// special destructor function provided by the Rust FFI, which will drop the +// underlying Rust struct. +// +// * Given an instance, calling code is expected to call the special +// `destroy` method in order to free it after use, either by calling it explicitly +// or by using a higher-level helper like the `use` method. Failing to do so risks +// leaking the underlying Rust struct. +// +// * We can't assume that calling code will do the right thing, and must be prepared +// to handle Kotlin method calls executing concurrently with or even after a call to +// `destroy`, and to handle multiple (possibly concurrent!) calls to `destroy`. +// +// * We must never allow Rust code to operate on the underlying Rust struct after +// the destructor has been called, and must never call the destructor more than once. +// Doing so may trigger memory unsafety. +// +// * To mitigate many of the risks of leaking memory and use-after-free unsafety, a `Cleaner` +// is implemented to call the destructor when the Kotlin object becomes unreachable. +// This is done in a background thread. This is not a panacea, and client code should be aware that +// 1. the thread may starve if some there are objects that have poorly performing +// `drop` methods or do significant work in their `drop` methods. +// 2. the thread is shared across the whole library. This can be tuned by using `android_cleaner = true`, +// or `android = true` in the [`kotlin` section of the `uniffi.toml` file](https://mozilla.github.io/uniffi-rs/kotlin/configuration.html). +// +// If we try to implement this with mutual exclusion on access to the pointer, there is the +// possibility of a race between a method call and a concurrent call to `destroy`: +// +// * Thread A starts a method call, reads the value of the pointer, but is interrupted +// before it can pass the pointer over the FFI to Rust. +// * Thread B calls `destroy` and frees the underlying Rust struct. +// * Thread A resumes, passing the already-read pointer value to Rust and triggering +// a use-after-free. +// +// One possible solution would be to use a `ReadWriteLock`, with each method call taking +// a read lock (and thus allowed to run concurrently) and the special `destroy` method +// taking a write lock (and thus blocking on live method calls). However, we aim not to +// generate methods with any hidden blocking semantics, and a `destroy` method that might +// block if called incorrectly seems to meet that bar. +// +// So, we achieve our goals by giving each instance an associated `AtomicLong` counter to track +// the number of in-flight method calls, and an `AtomicBoolean` flag to indicate whether `destroy` +// has been called. These are updated according to the following rules: +// +// * The initial value of the counter is 1, indicating a live object with no in-flight calls. +// The initial value for the flag is false. +// +// * At the start of each method call, we atomically check the counter. +// If it is 0 then the underlying Rust struct has already been destroyed and the call is aborted. +// If it is nonzero them we atomically increment it by 1 and proceed with the method call. +// +// * At the end of each method call, we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// * When `destroy` is called, we atomically flip the flag from false to true. +// If the flag was already true we silently fail. +// Otherwise we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// Astute readers may observe that this all sounds very similar to the way that Rust's `Arc` works, +// and indeed it is, with the addition of a flag to guard against multiple calls to `destroy`. +// +// The overall effect is that the underlying Rust struct is destroyed only when `destroy` has been +// called *and* all in-flight method calls have completed, avoiding violating any of the expectations +// of the underlying Rust code. +// +// This makes a cleaner a better alternative to _not_ calling `destroy()` as +// and when the object is finished with, but the abstraction is not perfect: if the Rust object's `drop` +// method is slow, and/or there are many objects to cleanup, and it's on a low end Android device, then the cleaner +// thread may be starved, and the app will leak memory. +// +// In this case, `destroy`ing manually may be a better solution. +// +// The cleaner can live side by side with the manual calling of `destroy`. In the order of responsiveness, uniffi objects +// with Rust peers are reclaimed: +// +// 1. By calling the `destroy` method of the object, which calls `rustObject.free()`. If that doesn't happen: +// 2. When the object becomes unreachable, AND the Cleaner thread gets to call `rustObject.free()`. If the thread is starved then: +// 3. The memory is reclaimed when the process terminates. +// +// [1] https://stackoverflow.com/questions/24376768/can-java-finalize-an-object-when-it-is-still-in-scope/24380219 +// + +public interface LogWriter { + fun `log`(`record`: LogRecord) + + companion object +} + +open class LogWriterImpl : + Disposable, + AutoCloseable, + LogWriter { + constructor(pointer: Pointer) { + this.pointer = pointer + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + /** + * This constructor can be used to instantiate a fake object. Only used for tests. Any + * attempt to actually use an object constructed this way will fail as there is no + * connected Rust object. + */ + @Suppress("UNUSED_PARAMETER") + constructor(noPointer: NoPointer) { + this.pointer = null + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + protected val pointer: Pointer? + protected val cleanable: UniffiCleaner.Cleanable + + private val wasDestroyed = AtomicBoolean(false) + private val callCounter = AtomicLong(1) + + override fun destroy() { + // Only allow a single call to this method. + // TODO: maybe we should log a warning if called more than once? + if (this.wasDestroyed.compareAndSet(false, true)) { + // This decrement always matches the initial count of 1 given at creation time. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + @Synchronized + override fun close() { + this.destroy() + } + + internal inline fun callWithPointer(block: (ptr: Pointer) -> R): R { + // Check and increment the call counter, to keep the object alive. + // This needs a compare-and-set retry loop in case of concurrent updates. + do { + val c = this.callCounter.get() + if (c == 0L) { + throw IllegalStateException("${this.javaClass.simpleName} object has already been destroyed") + } + if (c == Long.MAX_VALUE) { + throw IllegalStateException("${this.javaClass.simpleName} call counter would overflow") + } + } while (!this.callCounter.compareAndSet(c, c + 1L)) + // Now we can safely do the method call without the pointer being freed concurrently. + try { + return block(this.uniffiClonePointer()) + } finally { + // This decrement always matches the increment we performed above. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + // Use a static inner class instead of a closure so as not to accidentally + // capture `this` as part of the cleanable's action. + private class UniffiCleanAction( + private val pointer: Pointer?, + ) : Runnable { + override fun run() { + pointer?.let { ptr -> + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_free_logwriter(ptr, status) + } + } + } + } + + fun uniffiClonePointer(): Pointer = + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_clone_logwriter(pointer!!, status) + } + + override fun `log`(`record`: LogRecord) = + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_logwriter_log(it, FfiConverterTypeLogRecord.lower(`record`), _status) + } + } + + companion object +} + +// Magic number for the Rust proxy to call using the same mechanism as every other method, +// to free the callback once it's dropped by Rust. +internal const val IDX_CALLBACK_FREE = 0 + +// Callback return codes +internal const val UNIFFI_CALLBACK_SUCCESS = 0 +internal const val UNIFFI_CALLBACK_ERROR = 1 +internal const val UNIFFI_CALLBACK_UNEXPECTED_ERROR = 2 + +/** + * @suppress + */ +public abstract class FfiConverterCallbackInterface : FfiConverter { + internal val handleMap = UniffiHandleMap() + + internal fun drop(handle: Long) { + handleMap.remove(handle) + } + + override fun lift(value: Long): CallbackInterface = handleMap.get(value) + + override fun read(buf: ByteBuffer) = lift(buf.getLong()) + + override fun lower(value: CallbackInterface) = handleMap.insert(value) + + override fun allocationSize(value: CallbackInterface) = 8UL + + override fun write( + value: CallbackInterface, + buf: ByteBuffer, + ) { + buf.putLong(lower(value)) + } +} + +// Put the implementation in an object so we don't pollute the top-level namespace +internal object uniffiCallbackInterfaceLogWriter { + internal object `log` : UniffiCallbackInterfaceLogWriterMethod0 { + override fun callback( + `uniffiHandle`: Long, + `record`: RustBuffer.ByValue, + `uniffiOutReturn`: Pointer, + uniffiCallStatus: UniffiRustCallStatus, + ) { + val uniffiObj = FfiConverterTypeLogWriter.handleMap.get(uniffiHandle) + val makeCall = { uniffiObj.`log`( + FfiConverterTypeLogRecord.lift(`record`), + ) + } + val writeReturn = { _: Unit -> Unit } + uniffiTraitInterfaceCall(uniffiCallStatus, makeCall, writeReturn) + } + } + + internal object uniffiFree : UniffiCallbackInterfaceFree { + override fun callback(handle: Long) { + FfiConverterTypeLogWriter.handleMap.remove(handle) + } + } + + internal var vtable = + UniffiVTableCallbackInterfaceLogWriter.UniffiByValue( + `log`, + uniffiFree, + ) + + // Registers the foreign callback with the Rust side. + // This method is generated for each callback interface. + internal fun register(lib: UniffiLib) { + lib.uniffi_ldk_node_fn_init_callback_vtable_logwriter(vtable) + } +} + +/** + * @suppress + */ +public object FfiConverterTypeLogWriter : FfiConverter { + internal val handleMap = UniffiHandleMap() + + override fun lower(value: LogWriter): Pointer = Pointer(handleMap.insert(value)) + + override fun lift(value: Pointer): LogWriter = LogWriterImpl(value) + + override fun read(buf: ByteBuffer): LogWriter { + // The Rust code always writes pointers as 8 bytes, and will + // fail to compile if they don't fit. + return lift(Pointer(buf.getLong())) + } + + override fun allocationSize(value: LogWriter) = 8UL + + override fun write( + value: LogWriter, + buf: ByteBuffer, + ) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(lower(value))) + } +} + +// This template implements a class for working with a Rust struct via a Pointer/Arc +// to the live Rust struct on the other side of the FFI. +// +// Each instance implements core operations for working with the Rust `Arc` and the +// Kotlin Pointer to work with the live Rust struct on the other side of the FFI. +// +// There's some subtlety here, because we have to be careful not to operate on a Rust +// struct after it has been dropped, and because we must expose a public API for freeing +// theq Kotlin wrapper object in lieu of reliable finalizers. The core requirements are: +// +// * Each instance holds an opaque pointer to the underlying Rust struct. +// Method calls need to read this pointer from the object's state and pass it in to +// the Rust FFI. +// +// * When an instance is no longer needed, its pointer should be passed to a +// special destructor function provided by the Rust FFI, which will drop the +// underlying Rust struct. +// +// * Given an instance, calling code is expected to call the special +// `destroy` method in order to free it after use, either by calling it explicitly +// or by using a higher-level helper like the `use` method. Failing to do so risks +// leaking the underlying Rust struct. +// +// * We can't assume that calling code will do the right thing, and must be prepared +// to handle Kotlin method calls executing concurrently with or even after a call to +// `destroy`, and to handle multiple (possibly concurrent!) calls to `destroy`. +// +// * We must never allow Rust code to operate on the underlying Rust struct after +// the destructor has been called, and must never call the destructor more than once. +// Doing so may trigger memory unsafety. +// +// * To mitigate many of the risks of leaking memory and use-after-free unsafety, a `Cleaner` +// is implemented to call the destructor when the Kotlin object becomes unreachable. +// This is done in a background thread. This is not a panacea, and client code should be aware that +// 1. the thread may starve if some there are objects that have poorly performing +// `drop` methods or do significant work in their `drop` methods. +// 2. the thread is shared across the whole library. This can be tuned by using `android_cleaner = true`, +// or `android = true` in the [`kotlin` section of the `uniffi.toml` file](https://mozilla.github.io/uniffi-rs/kotlin/configuration.html). +// +// If we try to implement this with mutual exclusion on access to the pointer, there is the +// possibility of a race between a method call and a concurrent call to `destroy`: +// +// * Thread A starts a method call, reads the value of the pointer, but is interrupted +// before it can pass the pointer over the FFI to Rust. +// * Thread B calls `destroy` and frees the underlying Rust struct. +// * Thread A resumes, passing the already-read pointer value to Rust and triggering +// a use-after-free. +// +// One possible solution would be to use a `ReadWriteLock`, with each method call taking +// a read lock (and thus allowed to run concurrently) and the special `destroy` method +// taking a write lock (and thus blocking on live method calls). However, we aim not to +// generate methods with any hidden blocking semantics, and a `destroy` method that might +// block if called incorrectly seems to meet that bar. +// +// So, we achieve our goals by giving each instance an associated `AtomicLong` counter to track +// the number of in-flight method calls, and an `AtomicBoolean` flag to indicate whether `destroy` +// has been called. These are updated according to the following rules: +// +// * The initial value of the counter is 1, indicating a live object with no in-flight calls. +// The initial value for the flag is false. +// +// * At the start of each method call, we atomically check the counter. +// If it is 0 then the underlying Rust struct has already been destroyed and the call is aborted. +// If it is nonzero them we atomically increment it by 1 and proceed with the method call. +// +// * At the end of each method call, we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// * When `destroy` is called, we atomically flip the flag from false to true. +// If the flag was already true we silently fail. +// Otherwise we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// Astute readers may observe that this all sounds very similar to the way that Rust's `Arc` works, +// and indeed it is, with the addition of a flag to guard against multiple calls to `destroy`. +// +// The overall effect is that the underlying Rust struct is destroyed only when `destroy` has been +// called *and* all in-flight method calls have completed, avoiding violating any of the expectations +// of the underlying Rust code. +// +// This makes a cleaner a better alternative to _not_ calling `destroy()` as +// and when the object is finished with, but the abstraction is not perfect: if the Rust object's `drop` +// method is slow, and/or there are many objects to cleanup, and it's on a low end Android device, then the cleaner +// thread may be starved, and the app will leak memory. +// +// In this case, `destroy`ing manually may be a better solution. +// +// The cleaner can live side by side with the manual calling of `destroy`. In the order of responsiveness, uniffi objects +// with Rust peers are reclaimed: +// +// 1. By calling the `destroy` method of the object, which calls `rustObject.free()`. If that doesn't happen: +// 2. When the object becomes unreachable, AND the Cleaner thread gets to call `rustObject.free()`. If the thread is starved then: +// 3. The memory is reclaimed when the process terminates. +// +// [1] https://stackoverflow.com/questions/24376768/can-java-finalize-an-object-when-it-is-still-in-scope/24380219 +// + +public interface NetworkGraphInterface { + fun `channel`(`shortChannelId`: kotlin.ULong): ChannelInfo? + + fun `listChannels`(): List + + fun `listNodes`(): List + + fun `node`(`nodeId`: NodeId): NodeInfo? + + companion object +} + +open class NetworkGraph : + Disposable, + AutoCloseable, + NetworkGraphInterface { + constructor(pointer: Pointer) { + this.pointer = pointer + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + /** + * This constructor can be used to instantiate a fake object. Only used for tests. Any + * attempt to actually use an object constructed this way will fail as there is no + * connected Rust object. + */ + @Suppress("UNUSED_PARAMETER") + constructor(noPointer: NoPointer) { + this.pointer = null + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + protected val pointer: Pointer? + protected val cleanable: UniffiCleaner.Cleanable + + private val wasDestroyed = AtomicBoolean(false) + private val callCounter = AtomicLong(1) + + override fun destroy() { + // Only allow a single call to this method. + // TODO: maybe we should log a warning if called more than once? + if (this.wasDestroyed.compareAndSet(false, true)) { + // This decrement always matches the initial count of 1 given at creation time. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + @Synchronized + override fun close() { + this.destroy() + } + + internal inline fun callWithPointer(block: (ptr: Pointer) -> R): R { + // Check and increment the call counter, to keep the object alive. + // This needs a compare-and-set retry loop in case of concurrent updates. + do { + val c = this.callCounter.get() + if (c == 0L) { + throw IllegalStateException("${this.javaClass.simpleName} object has already been destroyed") + } + if (c == Long.MAX_VALUE) { + throw IllegalStateException("${this.javaClass.simpleName} call counter would overflow") + } + } while (!this.callCounter.compareAndSet(c, c + 1L)) + // Now we can safely do the method call without the pointer being freed concurrently. + try { + return block(this.uniffiClonePointer()) + } finally { + // This decrement always matches the increment we performed above. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + // Use a static inner class instead of a closure so as not to accidentally + // capture `this` as part of the cleanable's action. + private class UniffiCleanAction( + private val pointer: Pointer?, + ) : Runnable { + override fun run() { + pointer?.let { ptr -> + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_free_networkgraph(ptr, status) + } + } + } + } + + fun uniffiClonePointer(): Pointer = + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_clone_networkgraph(pointer!!, status) + } + + override fun `channel`(`shortChannelId`: kotlin.ULong): ChannelInfo? = + FfiConverterOptionalTypeChannelInfo.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_networkgraph_channel( + it, + FfiConverterULong.lower(`shortChannelId`), + _status, + ) + } + }, + ) + + override fun `listChannels`(): List = + FfiConverterSequenceULong.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_networkgraph_list_channels(it, _status) + } + }, + ) + + override fun `listNodes`(): List = + FfiConverterSequenceTypeNodeId.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_networkgraph_list_nodes(it, _status) + } + }, + ) + + override fun `node`(`nodeId`: NodeId): NodeInfo? = + FfiConverterOptionalTypeNodeInfo.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_networkgraph_node(it, FfiConverterTypeNodeId.lower(`nodeId`), _status) + } + }, + ) + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeNetworkGraph : FfiConverter { + override fun lower(value: NetworkGraph): Pointer = value.uniffiClonePointer() + + override fun lift(value: Pointer): NetworkGraph = NetworkGraph(value) + + override fun read(buf: ByteBuffer): NetworkGraph { + // The Rust code always writes pointers as 8 bytes, and will + // fail to compile if they don't fit. + return lift(Pointer(buf.getLong())) + } + + override fun allocationSize(value: NetworkGraph) = 8UL + + override fun write( + value: NetworkGraph, + buf: ByteBuffer, + ) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(lower(value))) + } +} + +// This template implements a class for working with a Rust struct via a Pointer/Arc +// to the live Rust struct on the other side of the FFI. +// +// Each instance implements core operations for working with the Rust `Arc` and the +// Kotlin Pointer to work with the live Rust struct on the other side of the FFI. +// +// There's some subtlety here, because we have to be careful not to operate on a Rust +// struct after it has been dropped, and because we must expose a public API for freeing +// theq Kotlin wrapper object in lieu of reliable finalizers. The core requirements are: +// +// * Each instance holds an opaque pointer to the underlying Rust struct. +// Method calls need to read this pointer from the object's state and pass it in to +// the Rust FFI. +// +// * When an instance is no longer needed, its pointer should be passed to a +// special destructor function provided by the Rust FFI, which will drop the +// underlying Rust struct. +// +// * Given an instance, calling code is expected to call the special +// `destroy` method in order to free it after use, either by calling it explicitly +// or by using a higher-level helper like the `use` method. Failing to do so risks +// leaking the underlying Rust struct. +// +// * We can't assume that calling code will do the right thing, and must be prepared +// to handle Kotlin method calls executing concurrently with or even after a call to +// `destroy`, and to handle multiple (possibly concurrent!) calls to `destroy`. +// +// * We must never allow Rust code to operate on the underlying Rust struct after +// the destructor has been called, and must never call the destructor more than once. +// Doing so may trigger memory unsafety. +// +// * To mitigate many of the risks of leaking memory and use-after-free unsafety, a `Cleaner` +// is implemented to call the destructor when the Kotlin object becomes unreachable. +// This is done in a background thread. This is not a panacea, and client code should be aware that +// 1. the thread may starve if some there are objects that have poorly performing +// `drop` methods or do significant work in their `drop` methods. +// 2. the thread is shared across the whole library. This can be tuned by using `android_cleaner = true`, +// or `android = true` in the [`kotlin` section of the `uniffi.toml` file](https://mozilla.github.io/uniffi-rs/kotlin/configuration.html). +// +// If we try to implement this with mutual exclusion on access to the pointer, there is the +// possibility of a race between a method call and a concurrent call to `destroy`: +// +// * Thread A starts a method call, reads the value of the pointer, but is interrupted +// before it can pass the pointer over the FFI to Rust. +// * Thread B calls `destroy` and frees the underlying Rust struct. +// * Thread A resumes, passing the already-read pointer value to Rust and triggering +// a use-after-free. +// +// One possible solution would be to use a `ReadWriteLock`, with each method call taking +// a read lock (and thus allowed to run concurrently) and the special `destroy` method +// taking a write lock (and thus blocking on live method calls). However, we aim not to +// generate methods with any hidden blocking semantics, and a `destroy` method that might +// block if called incorrectly seems to meet that bar. +// +// So, we achieve our goals by giving each instance an associated `AtomicLong` counter to track +// the number of in-flight method calls, and an `AtomicBoolean` flag to indicate whether `destroy` +// has been called. These are updated according to the following rules: +// +// * The initial value of the counter is 1, indicating a live object with no in-flight calls. +// The initial value for the flag is false. +// +// * At the start of each method call, we atomically check the counter. +// If it is 0 then the underlying Rust struct has already been destroyed and the call is aborted. +// If it is nonzero them we atomically increment it by 1 and proceed with the method call. +// +// * At the end of each method call, we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// * When `destroy` is called, we atomically flip the flag from false to true. +// If the flag was already true we silently fail. +// Otherwise we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// Astute readers may observe that this all sounds very similar to the way that Rust's `Arc` works, +// and indeed it is, with the addition of a flag to guard against multiple calls to `destroy`. +// +// The overall effect is that the underlying Rust struct is destroyed only when `destroy` has been +// called *and* all in-flight method calls have completed, avoiding violating any of the expectations +// of the underlying Rust code. +// +// This makes a cleaner a better alternative to _not_ calling `destroy()` as +// and when the object is finished with, but the abstraction is not perfect: if the Rust object's `drop` +// method is slow, and/or there are many objects to cleanup, and it's on a low end Android device, then the cleaner +// thread may be starved, and the app will leak memory. +// +// In this case, `destroy`ing manually may be a better solution. +// +// The cleaner can live side by side with the manual calling of `destroy`. In the order of responsiveness, uniffi objects +// with Rust peers are reclaimed: +// +// 1. By calling the `destroy` method of the object, which calls `rustObject.free()`. If that doesn't happen: +// 2. When the object becomes unreachable, AND the Cleaner thread gets to call `rustObject.free()`. If the thread is starved then: +// 3. The memory is reclaimed when the process terminates. +// +// [1] https://stackoverflow.com/questions/24376768/can-java-finalize-an-object-when-it-is-still-in-scope/24380219 +// + +public interface NodeInterface { + fun `announcementAddresses`(): List? + + fun `bolt11Payment`(): Bolt11Payment + + fun `bolt12Payment`(): Bolt12Payment + + fun `closeChannel`( + `userChannelId`: UserChannelId, + `counterpartyNodeId`: PublicKey, + ) + + fun `config`(): Config + + fun `connect`( + `nodeId`: PublicKey, + `address`: SocketAddress, + `persist`: kotlin.Boolean, + ) + + fun `currentSyncIntervals`(): RuntimeSyncIntervals + + fun `disconnect`(`nodeId`: PublicKey) + + fun `eventHandled`() + + fun `exportPathfindingScores`(): kotlin.ByteArray + + fun `forceCloseChannel`( + `userChannelId`: UserChannelId, + `counterpartyNodeId`: PublicKey, + `reason`: kotlin.String?, + ) + + fun `getAddressBalance`(`addressStr`: kotlin.String): kotlin.ULong + + fun `getTransactionDetails`(`txid`: Txid): TransactionDetails? + + fun `listBalances`(): BalanceDetails + + fun `listChannels`(): List + + fun `listPayments`(): List + + fun `listPeers`(): List + + fun `listeningAddresses`(): List? + + fun `lsps1Liquidity`(): Lsps1Liquidity + + fun `networkGraph`(): NetworkGraph + + fun `nextEvent`(): Event? + + suspend fun `nextEventAsync`(): Event + + fun `nodeAlias`(): NodeAlias? + + fun `nodeId`(): PublicKey + + fun `onchainPayment`(): OnchainPayment + + fun `openAnnouncedChannel`( + `nodeId`: PublicKey, + `address`: SocketAddress, + `channelAmountSats`: kotlin.ULong, + `pushToCounterpartyMsat`: kotlin.ULong?, + `channelConfig`: ChannelConfig?, + ): UserChannelId + + fun `openChannel`( + `nodeId`: PublicKey, + `address`: SocketAddress, + `channelAmountSats`: kotlin.ULong, + `pushToCounterpartyMsat`: kotlin.ULong?, + `channelConfig`: ChannelConfig?, + ): UserChannelId + + fun `payment`(`paymentId`: PaymentId): PaymentDetails? + + fun `removePayment`(`paymentId`: PaymentId) + + fun `signMessage`(`msg`: List): kotlin.String + + fun `spliceIn`( + `userChannelId`: UserChannelId, + `counterpartyNodeId`: PublicKey, + `spliceAmountSats`: kotlin.ULong, + ) + + fun `spliceOut`( + `userChannelId`: UserChannelId, + `counterpartyNodeId`: PublicKey, + `address`: Address, + `spliceAmountSats`: kotlin.ULong, + ) + + fun `spontaneousPayment`(): SpontaneousPayment + + fun `start`() + + fun `status`(): NodeStatus + + fun `stop`() + + fun `syncWallets`() + + fun `unifiedQrPayment`(): UnifiedQrPayment + + fun `updateChannelConfig`( + `userChannelId`: UserChannelId, + `counterpartyNodeId`: PublicKey, + `channelConfig`: ChannelConfig, + ) + + fun `updateSyncIntervals`(`intervals`: RuntimeSyncIntervals) + + fun `verifySignature`( + `msg`: List, + `sig`: kotlin.String, + `pkey`: PublicKey, + ): kotlin.Boolean + + fun `waitNextEvent`(): Event + + companion object +} + +open class Node : + Disposable, + AutoCloseable, + NodeInterface { + constructor(pointer: Pointer) { + this.pointer = pointer + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + /** + * This constructor can be used to instantiate a fake object. Only used for tests. Any + * attempt to actually use an object constructed this way will fail as there is no + * connected Rust object. + */ + @Suppress("UNUSED_PARAMETER") + constructor(noPointer: NoPointer) { + this.pointer = null + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + protected val pointer: Pointer? + protected val cleanable: UniffiCleaner.Cleanable + + private val wasDestroyed = AtomicBoolean(false) + private val callCounter = AtomicLong(1) + + override fun destroy() { + // Only allow a single call to this method. + // TODO: maybe we should log a warning if called more than once? + if (this.wasDestroyed.compareAndSet(false, true)) { + // This decrement always matches the initial count of 1 given at creation time. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + @Synchronized + override fun close() { + this.destroy() + } + + internal inline fun callWithPointer(block: (ptr: Pointer) -> R): R { + // Check and increment the call counter, to keep the object alive. + // This needs a compare-and-set retry loop in case of concurrent updates. + do { + val c = this.callCounter.get() + if (c == 0L) { + throw IllegalStateException("${this.javaClass.simpleName} object has already been destroyed") + } + if (c == Long.MAX_VALUE) { + throw IllegalStateException("${this.javaClass.simpleName} call counter would overflow") + } + } while (!this.callCounter.compareAndSet(c, c + 1L)) + // Now we can safely do the method call without the pointer being freed concurrently. + try { + return block(this.uniffiClonePointer()) + } finally { + // This decrement always matches the increment we performed above. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + // Use a static inner class instead of a closure so as not to accidentally + // capture `this` as part of the cleanable's action. + private class UniffiCleanAction( + private val pointer: Pointer?, + ) : Runnable { + override fun run() { + pointer?.let { ptr -> + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_free_node(ptr, status) + } + } + } + } + + fun uniffiClonePointer(): Pointer = + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_clone_node(pointer!!, status) + } + + override fun `announcementAddresses`(): List? = + FfiConverterOptionalSequenceTypeSocketAddress.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_announcement_addresses(it, _status) + } + }, + ) + + override fun `bolt11Payment`(): Bolt11Payment = + FfiConverterTypeBolt11Payment.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_bolt11_payment(it, _status) + } + }, + ) + + override fun `bolt12Payment`(): Bolt12Payment = + FfiConverterTypeBolt12Payment.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_bolt12_payment(it, _status) + } + }, + ) + + @Throws(NodeException::class) + override fun `closeChannel`( + `userChannelId`: UserChannelId, + `counterpartyNodeId`: PublicKey, + ) = callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_close_channel( + it, + FfiConverterTypeUserChannelId.lower(`userChannelId`), + FfiConverterTypePublicKey.lower(`counterpartyNodeId`), + _status, + ) + } + } + + override fun `config`(): Config = + FfiConverterTypeConfig.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_config(it, _status) + } + }, + ) + + @Throws(NodeException::class) + override fun `connect`( + `nodeId`: PublicKey, + `address`: SocketAddress, + `persist`: kotlin.Boolean, + ) = callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_connect( + it, + FfiConverterTypePublicKey.lower(`nodeId`), + FfiConverterTypeSocketAddress.lower(`address`), + FfiConverterBoolean.lower(`persist`), + _status, + ) + } + } + + override fun `currentSyncIntervals`(): RuntimeSyncIntervals = + FfiConverterTypeRuntimeSyncIntervals.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_current_sync_intervals(it, _status) + } + }, + ) + + @Throws(NodeException::class) + override fun `disconnect`(`nodeId`: PublicKey) = + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_disconnect(it, FfiConverterTypePublicKey.lower(`nodeId`), _status) + } + } + + @Throws(NodeException::class) + override fun `eventHandled`() = + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_event_handled(it, _status) + } + } + + @Throws(NodeException::class) + override fun `exportPathfindingScores`(): kotlin.ByteArray = + FfiConverterByteArray.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_export_pathfinding_scores(it, _status) + } + }, + ) + + @Throws(NodeException::class) + override fun `forceCloseChannel`( + `userChannelId`: UserChannelId, + `counterpartyNodeId`: PublicKey, + `reason`: kotlin.String?, + ) = callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_force_close_channel( + it, + FfiConverterTypeUserChannelId.lower(`userChannelId`), + FfiConverterTypePublicKey.lower(`counterpartyNodeId`), + FfiConverterOptionalString.lower(`reason`), + _status, + ) + } + } + + @Throws(NodeException::class) + override fun `getAddressBalance`(`addressStr`: kotlin.String): kotlin.ULong = + FfiConverterULong.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_get_address_balance( + it, + FfiConverterString.lower(`addressStr`), + _status, + ) + } + }, + ) + + override fun `getTransactionDetails`(`txid`: Txid): TransactionDetails? = + FfiConverterOptionalTypeTransactionDetails.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_get_transaction_details( + it, + FfiConverterTypeTxid.lower(`txid`), + _status, + ) + } + }, + ) + + override fun `listBalances`(): BalanceDetails = + FfiConverterTypeBalanceDetails.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_list_balances(it, _status) + } + }, + ) + + override fun `listChannels`(): List = + FfiConverterSequenceTypeChannelDetails.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_list_channels(it, _status) + } + }, + ) + + override fun `listPayments`(): List = + FfiConverterSequenceTypePaymentDetails.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_list_payments(it, _status) + } + }, + ) + + override fun `listPeers`(): List = + FfiConverterSequenceTypePeerDetails.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_list_peers(it, _status) + } + }, + ) + + override fun `listeningAddresses`(): List? = + FfiConverterOptionalSequenceTypeSocketAddress.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_listening_addresses(it, _status) + } + }, + ) + + override fun `lsps1Liquidity`(): Lsps1Liquidity = + FfiConverterTypeLSPS1Liquidity.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_lsps1_liquidity(it, _status) + } + }, + ) + + override fun `networkGraph`(): NetworkGraph = + FfiConverterTypeNetworkGraph.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_network_graph(it, _status) + } + }, + ) + + override fun `nextEvent`(): Event? = + FfiConverterOptionalTypeEvent.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_next_event(it, _status) + } + }, + ) + + @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE") + override suspend fun `nextEventAsync`(): Event = + uniffiRustCallAsync( + callWithPointer { thisPtr -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_next_event_async( + thisPtr, + ) + }, + { + future, + callback, + continuation, + -> + UniffiLib.INSTANCE.ffi_ldk_node_rust_future_poll_rust_buffer(future, callback, continuation) + }, + { future, continuation -> UniffiLib.INSTANCE.ffi_ldk_node_rust_future_complete_rust_buffer(future, continuation) }, + { future -> UniffiLib.INSTANCE.ffi_ldk_node_rust_future_free_rust_buffer(future) }, + // lift function + { FfiConverterTypeEvent.lift(it) }, + // Error FFI converter + UniffiNullRustCallStatusErrorHandler, + ) + + override fun `nodeAlias`(): NodeAlias? = + FfiConverterOptionalTypeNodeAlias.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_node_alias(it, _status) + } + }, + ) + + override fun `nodeId`(): PublicKey = + FfiConverterTypePublicKey.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_node_id(it, _status) + } + }, + ) + + override fun `onchainPayment`(): OnchainPayment = + FfiConverterTypeOnchainPayment.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_onchain_payment(it, _status) + } + }, + ) + + @Throws(NodeException::class) + override fun `openAnnouncedChannel`( + `nodeId`: PublicKey, + `address`: SocketAddress, + `channelAmountSats`: kotlin.ULong, + `pushToCounterpartyMsat`: kotlin.ULong?, + `channelConfig`: ChannelConfig?, + ): UserChannelId = + FfiConverterTypeUserChannelId.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_open_announced_channel( + it, + FfiConverterTypePublicKey.lower(`nodeId`), + FfiConverterTypeSocketAddress.lower(`address`), + FfiConverterULong.lower(`channelAmountSats`), + FfiConverterOptionalULong.lower(`pushToCounterpartyMsat`), + FfiConverterOptionalTypeChannelConfig.lower(`channelConfig`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `openChannel`( + `nodeId`: PublicKey, + `address`: SocketAddress, + `channelAmountSats`: kotlin.ULong, + `pushToCounterpartyMsat`: kotlin.ULong?, + `channelConfig`: ChannelConfig?, + ): UserChannelId = + FfiConverterTypeUserChannelId.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_open_channel( + it, + FfiConverterTypePublicKey.lower(`nodeId`), + FfiConverterTypeSocketAddress.lower(`address`), + FfiConverterULong.lower(`channelAmountSats`), + FfiConverterOptionalULong.lower(`pushToCounterpartyMsat`), + FfiConverterOptionalTypeChannelConfig.lower(`channelConfig`), + _status, + ) + } + }, + ) + + override fun `payment`(`paymentId`: PaymentId): PaymentDetails? = + FfiConverterOptionalTypePaymentDetails.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_payment(it, FfiConverterTypePaymentId.lower(`paymentId`), _status) + } + }, + ) + + @Throws(NodeException::class) + override fun `removePayment`(`paymentId`: PaymentId) = + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_remove_payment(it, FfiConverterTypePaymentId.lower(`paymentId`), _status) + } + } + + override fun `signMessage`(`msg`: List): kotlin.String = + FfiConverterString.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_sign_message(it, FfiConverterSequenceUByte.lower(`msg`), _status) + } + }, + ) + + @Throws(NodeException::class) + override fun `spliceIn`( + `userChannelId`: UserChannelId, + `counterpartyNodeId`: PublicKey, + `spliceAmountSats`: kotlin.ULong, + ) = callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_splice_in( + it, + FfiConverterTypeUserChannelId.lower(`userChannelId`), + FfiConverterTypePublicKey.lower(`counterpartyNodeId`), + FfiConverterULong.lower(`spliceAmountSats`), + _status, + ) + } + } + + @Throws(NodeException::class) + override fun `spliceOut`( + `userChannelId`: UserChannelId, + `counterpartyNodeId`: PublicKey, + `address`: Address, + `spliceAmountSats`: kotlin.ULong, + ) = callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_splice_out( + it, + FfiConverterTypeUserChannelId.lower(`userChannelId`), + FfiConverterTypePublicKey.lower(`counterpartyNodeId`), + FfiConverterTypeAddress.lower(`address`), + FfiConverterULong.lower(`spliceAmountSats`), + _status, + ) + } + } + + override fun `spontaneousPayment`(): SpontaneousPayment = + FfiConverterTypeSpontaneousPayment.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_spontaneous_payment(it, _status) + } + }, + ) + + @Throws(NodeException::class) + override fun `start`() = + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_start(it, _status) + } + } + + override fun `status`(): NodeStatus = + FfiConverterTypeNodeStatus.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_status(it, _status) + } + }, + ) + + @Throws(NodeException::class) + override fun `stop`() = + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_stop(it, _status) + } + } + + @Throws(NodeException::class) + override fun `syncWallets`() = + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_sync_wallets(it, _status) + } + } + + override fun `unifiedQrPayment`(): UnifiedQrPayment = + FfiConverterTypeUnifiedQrPayment.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_unified_qr_payment(it, _status) + } + }, + ) + + @Throws(NodeException::class) + override fun `updateChannelConfig`( + `userChannelId`: UserChannelId, + `counterpartyNodeId`: PublicKey, + `channelConfig`: ChannelConfig, + ) = callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_update_channel_config( + it, + FfiConverterTypeUserChannelId.lower(`userChannelId`), + FfiConverterTypePublicKey.lower(`counterpartyNodeId`), + FfiConverterTypeChannelConfig.lower(`channelConfig`), + _status, + ) + } + } + + @Throws(NodeException::class) + override fun `updateSyncIntervals`(`intervals`: RuntimeSyncIntervals) = + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_update_sync_intervals( + it, + FfiConverterTypeRuntimeSyncIntervals.lower(`intervals`), + _status, + ) + } + } + + override fun `verifySignature`( + `msg`: List, + `sig`: kotlin.String, + `pkey`: PublicKey, + ): kotlin.Boolean = + FfiConverterBoolean.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_verify_signature( + it, + FfiConverterSequenceUByte.lower(`msg`), + FfiConverterString.lower(`sig`), + FfiConverterTypePublicKey.lower(`pkey`), + _status, + ) + } + }, + ) + + override fun `waitNextEvent`(): Event = + FfiConverterTypeEvent.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_node_wait_next_event(it, _status) + } + }, + ) + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeNode : FfiConverter { + override fun lower(value: Node): Pointer = value.uniffiClonePointer() + + override fun lift(value: Pointer): Node = Node(value) + + override fun read(buf: ByteBuffer): Node { + // The Rust code always writes pointers as 8 bytes, and will + // fail to compile if they don't fit. + return lift(Pointer(buf.getLong())) + } + + override fun allocationSize(value: Node) = 8UL + + override fun write( + value: Node, + buf: ByteBuffer, + ) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(lower(value))) + } +} + +// This template implements a class for working with a Rust struct via a Pointer/Arc +// to the live Rust struct on the other side of the FFI. +// +// Each instance implements core operations for working with the Rust `Arc` and the +// Kotlin Pointer to work with the live Rust struct on the other side of the FFI. +// +// There's some subtlety here, because we have to be careful not to operate on a Rust +// struct after it has been dropped, and because we must expose a public API for freeing +// theq Kotlin wrapper object in lieu of reliable finalizers. The core requirements are: +// +// * Each instance holds an opaque pointer to the underlying Rust struct. +// Method calls need to read this pointer from the object's state and pass it in to +// the Rust FFI. +// +// * When an instance is no longer needed, its pointer should be passed to a +// special destructor function provided by the Rust FFI, which will drop the +// underlying Rust struct. +// +// * Given an instance, calling code is expected to call the special +// `destroy` method in order to free it after use, either by calling it explicitly +// or by using a higher-level helper like the `use` method. Failing to do so risks +// leaking the underlying Rust struct. +// +// * We can't assume that calling code will do the right thing, and must be prepared +// to handle Kotlin method calls executing concurrently with or even after a call to +// `destroy`, and to handle multiple (possibly concurrent!) calls to `destroy`. +// +// * We must never allow Rust code to operate on the underlying Rust struct after +// the destructor has been called, and must never call the destructor more than once. +// Doing so may trigger memory unsafety. +// +// * To mitigate many of the risks of leaking memory and use-after-free unsafety, a `Cleaner` +// is implemented to call the destructor when the Kotlin object becomes unreachable. +// This is done in a background thread. This is not a panacea, and client code should be aware that +// 1. the thread may starve if some there are objects that have poorly performing +// `drop` methods or do significant work in their `drop` methods. +// 2. the thread is shared across the whole library. This can be tuned by using `android_cleaner = true`, +// or `android = true` in the [`kotlin` section of the `uniffi.toml` file](https://mozilla.github.io/uniffi-rs/kotlin/configuration.html). +// +// If we try to implement this with mutual exclusion on access to the pointer, there is the +// possibility of a race between a method call and a concurrent call to `destroy`: +// +// * Thread A starts a method call, reads the value of the pointer, but is interrupted +// before it can pass the pointer over the FFI to Rust. +// * Thread B calls `destroy` and frees the underlying Rust struct. +// * Thread A resumes, passing the already-read pointer value to Rust and triggering +// a use-after-free. +// +// One possible solution would be to use a `ReadWriteLock`, with each method call taking +// a read lock (and thus allowed to run concurrently) and the special `destroy` method +// taking a write lock (and thus blocking on live method calls). However, we aim not to +// generate methods with any hidden blocking semantics, and a `destroy` method that might +// block if called incorrectly seems to meet that bar. +// +// So, we achieve our goals by giving each instance an associated `AtomicLong` counter to track +// the number of in-flight method calls, and an `AtomicBoolean` flag to indicate whether `destroy` +// has been called. These are updated according to the following rules: +// +// * The initial value of the counter is 1, indicating a live object with no in-flight calls. +// The initial value for the flag is false. +// +// * At the start of each method call, we atomically check the counter. +// If it is 0 then the underlying Rust struct has already been destroyed and the call is aborted. +// If it is nonzero them we atomically increment it by 1 and proceed with the method call. +// +// * At the end of each method call, we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// * When `destroy` is called, we atomically flip the flag from false to true. +// If the flag was already true we silently fail. +// Otherwise we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// Astute readers may observe that this all sounds very similar to the way that Rust's `Arc` works, +// and indeed it is, with the addition of a flag to guard against multiple calls to `destroy`. +// +// The overall effect is that the underlying Rust struct is destroyed only when `destroy` has been +// called *and* all in-flight method calls have completed, avoiding violating any of the expectations +// of the underlying Rust code. +// +// This makes a cleaner a better alternative to _not_ calling `destroy()` as +// and when the object is finished with, but the abstraction is not perfect: if the Rust object's `drop` +// method is slow, and/or there are many objects to cleanup, and it's on a low end Android device, then the cleaner +// thread may be starved, and the app will leak memory. +// +// In this case, `destroy`ing manually may be a better solution. +// +// The cleaner can live side by side with the manual calling of `destroy`. In the order of responsiveness, uniffi objects +// with Rust peers are reclaimed: +// +// 1. By calling the `destroy` method of the object, which calls `rustObject.free()`. If that doesn't happen: +// 2. When the object becomes unreachable, AND the Cleaner thread gets to call `rustObject.free()`. If the thread is starved then: +// 3. The memory is reclaimed when the process terminates. +// +// [1] https://stackoverflow.com/questions/24376768/can-java-finalize-an-object-when-it-is-still-in-scope/24380219 +// + +public interface OfferInterface { + fun `absoluteExpirySeconds`(): kotlin.ULong? + + fun `amount`(): OfferAmount? + + fun `chains`(): List + + fun `expectsQuantity`(): kotlin.Boolean + + fun `id`(): OfferId + + fun `isExpired`(): kotlin.Boolean + + fun `isValidQuantity`(`quantity`: kotlin.ULong): kotlin.Boolean + + fun `issuer`(): kotlin.String? + + fun `issuerSigningPubkey`(): PublicKey? + + fun `metadata`(): List? + + fun `offerDescription`(): kotlin.String? + + fun `supportsChain`(`chain`: Network): kotlin.Boolean + + companion object +} + +open class Offer : + Disposable, + AutoCloseable, + OfferInterface { + constructor(pointer: Pointer) { + this.pointer = pointer + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + /** + * This constructor can be used to instantiate a fake object. Only used for tests. Any + * attempt to actually use an object constructed this way will fail as there is no + * connected Rust object. + */ + @Suppress("UNUSED_PARAMETER") + constructor(noPointer: NoPointer) { + this.pointer = null + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + protected val pointer: Pointer? + protected val cleanable: UniffiCleaner.Cleanable + + private val wasDestroyed = AtomicBoolean(false) + private val callCounter = AtomicLong(1) + + override fun destroy() { + // Only allow a single call to this method. + // TODO: maybe we should log a warning if called more than once? + if (this.wasDestroyed.compareAndSet(false, true)) { + // This decrement always matches the initial count of 1 given at creation time. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + @Synchronized + override fun close() { + this.destroy() + } + + internal inline fun callWithPointer(block: (ptr: Pointer) -> R): R { + // Check and increment the call counter, to keep the object alive. + // This needs a compare-and-set retry loop in case of concurrent updates. + do { + val c = this.callCounter.get() + if (c == 0L) { + throw IllegalStateException("${this.javaClass.simpleName} object has already been destroyed") + } + if (c == Long.MAX_VALUE) { + throw IllegalStateException("${this.javaClass.simpleName} call counter would overflow") + } + } while (!this.callCounter.compareAndSet(c, c + 1L)) + // Now we can safely do the method call without the pointer being freed concurrently. + try { + return block(this.uniffiClonePointer()) + } finally { + // This decrement always matches the increment we performed above. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + // Use a static inner class instead of a closure so as not to accidentally + // capture `this` as part of the cleanable's action. + private class UniffiCleanAction( + private val pointer: Pointer?, + ) : Runnable { + override fun run() { + pointer?.let { ptr -> + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_free_offer(ptr, status) + } + } + } + } + + fun uniffiClonePointer(): Pointer = + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_clone_offer(pointer!!, status) + } + + override fun `absoluteExpirySeconds`(): kotlin.ULong? = + FfiConverterOptionalULong.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_offer_absolute_expiry_seconds(it, _status) + } + }, + ) + + override fun `amount`(): OfferAmount? = + FfiConverterOptionalTypeOfferAmount.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_offer_amount(it, _status) + } + }, + ) + + override fun `chains`(): List = + FfiConverterSequenceTypeNetwork.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_offer_chains(it, _status) + } + }, + ) + + override fun `expectsQuantity`(): kotlin.Boolean = + FfiConverterBoolean.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_offer_expects_quantity(it, _status) + } + }, + ) + + override fun `id`(): OfferId = + FfiConverterTypeOfferId.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_offer_id(it, _status) + } + }, + ) + + override fun `isExpired`(): kotlin.Boolean = + FfiConverterBoolean.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_offer_is_expired(it, _status) + } + }, + ) + + override fun `isValidQuantity`(`quantity`: kotlin.ULong): kotlin.Boolean = + FfiConverterBoolean.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_offer_is_valid_quantity(it, FfiConverterULong.lower(`quantity`), _status) + } + }, + ) + + override fun `issuer`(): kotlin.String? = + FfiConverterOptionalString.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_offer_issuer(it, _status) + } + }, + ) + + override fun `issuerSigningPubkey`(): PublicKey? = + FfiConverterOptionalTypePublicKey.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_offer_issuer_signing_pubkey(it, _status) + } + }, + ) + + override fun `metadata`(): List? = + FfiConverterOptionalSequenceUByte.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_offer_metadata(it, _status) + } + }, + ) + + override fun `offerDescription`(): kotlin.String? = + FfiConverterOptionalString.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_offer_offer_description(it, _status) + } + }, + ) + + override fun `supportsChain`(`chain`: Network): kotlin.Boolean = + FfiConverterBoolean.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_offer_supports_chain(it, FfiConverterTypeNetwork.lower(`chain`), _status) + } + }, + ) + + override fun toString(): String = + FfiConverterString.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_offer_uniffi_trait_display(it, _status) + } + }, + ) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is Offer) return false + return FfiConverterBoolean.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_offer_uniffi_trait_eq_eq(it, FfiConverterTypeOffer.lower(`other`), _status) + } + }, + ) + } + + companion object { + @Throws(NodeException::class) + fun `fromStr`(`offerStr`: kotlin.String): Offer = + FfiConverterTypeOffer.lift( + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_constructor_offer_from_str(FfiConverterString.lower(`offerStr`), _status) + }, + ) + } +} + +/** + * @suppress + */ +public object FfiConverterTypeOffer : FfiConverter { + override fun lower(value: Offer): Pointer = value.uniffiClonePointer() + + override fun lift(value: Pointer): Offer = Offer(value) + + override fun read(buf: ByteBuffer): Offer { + // The Rust code always writes pointers as 8 bytes, and will + // fail to compile if they don't fit. + return lift(Pointer(buf.getLong())) + } + + override fun allocationSize(value: Offer) = 8UL + + override fun write( + value: Offer, + buf: ByteBuffer, + ) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(lower(value))) + } +} + +// This template implements a class for working with a Rust struct via a Pointer/Arc +// to the live Rust struct on the other side of the FFI. +// +// Each instance implements core operations for working with the Rust `Arc` and the +// Kotlin Pointer to work with the live Rust struct on the other side of the FFI. +// +// There's some subtlety here, because we have to be careful not to operate on a Rust +// struct after it has been dropped, and because we must expose a public API for freeing +// theq Kotlin wrapper object in lieu of reliable finalizers. The core requirements are: +// +// * Each instance holds an opaque pointer to the underlying Rust struct. +// Method calls need to read this pointer from the object's state and pass it in to +// the Rust FFI. +// +// * When an instance is no longer needed, its pointer should be passed to a +// special destructor function provided by the Rust FFI, which will drop the +// underlying Rust struct. +// +// * Given an instance, calling code is expected to call the special +// `destroy` method in order to free it after use, either by calling it explicitly +// or by using a higher-level helper like the `use` method. Failing to do so risks +// leaking the underlying Rust struct. +// +// * We can't assume that calling code will do the right thing, and must be prepared +// to handle Kotlin method calls executing concurrently with or even after a call to +// `destroy`, and to handle multiple (possibly concurrent!) calls to `destroy`. +// +// * We must never allow Rust code to operate on the underlying Rust struct after +// the destructor has been called, and must never call the destructor more than once. +// Doing so may trigger memory unsafety. +// +// * To mitigate many of the risks of leaking memory and use-after-free unsafety, a `Cleaner` +// is implemented to call the destructor when the Kotlin object becomes unreachable. +// This is done in a background thread. This is not a panacea, and client code should be aware that +// 1. the thread may starve if some there are objects that have poorly performing +// `drop` methods or do significant work in their `drop` methods. +// 2. the thread is shared across the whole library. This can be tuned by using `android_cleaner = true`, +// or `android = true` in the [`kotlin` section of the `uniffi.toml` file](https://mozilla.github.io/uniffi-rs/kotlin/configuration.html). +// +// If we try to implement this with mutual exclusion on access to the pointer, there is the +// possibility of a race between a method call and a concurrent call to `destroy`: +// +// * Thread A starts a method call, reads the value of the pointer, but is interrupted +// before it can pass the pointer over the FFI to Rust. +// * Thread B calls `destroy` and frees the underlying Rust struct. +// * Thread A resumes, passing the already-read pointer value to Rust and triggering +// a use-after-free. +// +// One possible solution would be to use a `ReadWriteLock`, with each method call taking +// a read lock (and thus allowed to run concurrently) and the special `destroy` method +// taking a write lock (and thus blocking on live method calls). However, we aim not to +// generate methods with any hidden blocking semantics, and a `destroy` method that might +// block if called incorrectly seems to meet that bar. +// +// So, we achieve our goals by giving each instance an associated `AtomicLong` counter to track +// the number of in-flight method calls, and an `AtomicBoolean` flag to indicate whether `destroy` +// has been called. These are updated according to the following rules: +// +// * The initial value of the counter is 1, indicating a live object with no in-flight calls. +// The initial value for the flag is false. +// +// * At the start of each method call, we atomically check the counter. +// If it is 0 then the underlying Rust struct has already been destroyed and the call is aborted. +// If it is nonzero them we atomically increment it by 1 and proceed with the method call. +// +// * At the end of each method call, we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// * When `destroy` is called, we atomically flip the flag from false to true. +// If the flag was already true we silently fail. +// Otherwise we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// Astute readers may observe that this all sounds very similar to the way that Rust's `Arc` works, +// and indeed it is, with the addition of a flag to guard against multiple calls to `destroy`. +// +// The overall effect is that the underlying Rust struct is destroyed only when `destroy` has been +// called *and* all in-flight method calls have completed, avoiding violating any of the expectations +// of the underlying Rust code. +// +// This makes a cleaner a better alternative to _not_ calling `destroy()` as +// and when the object is finished with, but the abstraction is not perfect: if the Rust object's `drop` +// method is slow, and/or there are many objects to cleanup, and it's on a low end Android device, then the cleaner +// thread may be starved, and the app will leak memory. +// +// In this case, `destroy`ing manually may be a better solution. +// +// The cleaner can live side by side with the manual calling of `destroy`. In the order of responsiveness, uniffi objects +// with Rust peers are reclaimed: +// +// 1. By calling the `destroy` method of the object, which calls `rustObject.free()`. If that doesn't happen: +// 2. When the object becomes unreachable, AND the Cleaner thread gets to call `rustObject.free()`. If the thread is starved then: +// 3. The memory is reclaimed when the process terminates. +// +// [1] https://stackoverflow.com/questions/24376768/can-java-finalize-an-object-when-it-is-still-in-scope/24380219 +// + +public interface OnchainPaymentInterface { + fun `accelerateByCpfp`( + `txid`: Txid, + `feeRate`: FeeRate?, + `destinationAddress`: Address?, + ): Txid + + fun `bumpFeeByRbf`( + `txid`: Txid, + `feeRate`: FeeRate, + ): Txid + + fun `calculateCpfpFeeRate`( + `parentTxid`: Txid, + `urgent`: kotlin.Boolean, + ): FeeRate + + fun `calculateTotalFee`( + `address`: Address, + `amountSats`: kotlin.ULong, + `feeRate`: FeeRate?, + `utxosToSpend`: List?, + ): kotlin.ULong + + fun `listSpendableOutputs`(): List + + fun `newAddress`(): Address + + fun `selectUtxosWithAlgorithm`( + `targetAmountSats`: kotlin.ULong, + `feeRate`: FeeRate?, + `algorithm`: CoinSelectionAlgorithm, + `utxos`: List?, + ): List + + fun `sendAllToAddress`( + `address`: Address, + `retainReserve`: kotlin.Boolean, + `feeRate`: FeeRate?, + ): Txid + + fun `sendToAddress`( + `address`: Address, + `amountSats`: kotlin.ULong, + `feeRate`: FeeRate?, + `utxosToSpend`: List?, + ): Txid + + companion object +} + +open class OnchainPayment : + Disposable, + AutoCloseable, + OnchainPaymentInterface { + constructor(pointer: Pointer) { + this.pointer = pointer + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + /** + * This constructor can be used to instantiate a fake object. Only used for tests. Any + * attempt to actually use an object constructed this way will fail as there is no + * connected Rust object. + */ + @Suppress("UNUSED_PARAMETER") + constructor(noPointer: NoPointer) { + this.pointer = null + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + protected val pointer: Pointer? + protected val cleanable: UniffiCleaner.Cleanable + + private val wasDestroyed = AtomicBoolean(false) + private val callCounter = AtomicLong(1) + + override fun destroy() { + // Only allow a single call to this method. + // TODO: maybe we should log a warning if called more than once? + if (this.wasDestroyed.compareAndSet(false, true)) { + // This decrement always matches the initial count of 1 given at creation time. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + @Synchronized + override fun close() { + this.destroy() + } + + internal inline fun callWithPointer(block: (ptr: Pointer) -> R): R { + // Check and increment the call counter, to keep the object alive. + // This needs a compare-and-set retry loop in case of concurrent updates. + do { + val c = this.callCounter.get() + if (c == 0L) { + throw IllegalStateException("${this.javaClass.simpleName} object has already been destroyed") + } + if (c == Long.MAX_VALUE) { + throw IllegalStateException("${this.javaClass.simpleName} call counter would overflow") + } + } while (!this.callCounter.compareAndSet(c, c + 1L)) + // Now we can safely do the method call without the pointer being freed concurrently. + try { + return block(this.uniffiClonePointer()) + } finally { + // This decrement always matches the increment we performed above. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + // Use a static inner class instead of a closure so as not to accidentally + // capture `this` as part of the cleanable's action. + private class UniffiCleanAction( + private val pointer: Pointer?, + ) : Runnable { + override fun run() { + pointer?.let { ptr -> + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_free_onchainpayment(ptr, status) + } + } + } + } + + fun uniffiClonePointer(): Pointer = + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_clone_onchainpayment(pointer!!, status) + } + + @Throws(NodeException::class) + override fun `accelerateByCpfp`( + `txid`: Txid, + `feeRate`: FeeRate?, + `destinationAddress`: Address?, + ): Txid = + FfiConverterTypeTxid.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_onchainpayment_accelerate_by_cpfp( + it, + FfiConverterTypeTxid.lower(`txid`), + FfiConverterOptionalTypeFeeRate.lower(`feeRate`), + FfiConverterOptionalTypeAddress.lower(`destinationAddress`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `bumpFeeByRbf`( + `txid`: Txid, + `feeRate`: FeeRate, + ): Txid = + FfiConverterTypeTxid.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_onchainpayment_bump_fee_by_rbf( + it, + FfiConverterTypeTxid.lower(`txid`), + FfiConverterTypeFeeRate.lower(`feeRate`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `calculateCpfpFeeRate`( + `parentTxid`: Txid, + `urgent`: kotlin.Boolean, + ): FeeRate = + FfiConverterTypeFeeRate.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_onchainpayment_calculate_cpfp_fee_rate( + it, + FfiConverterTypeTxid.lower(`parentTxid`), + FfiConverterBoolean.lower(`urgent`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `calculateTotalFee`( + `address`: Address, + `amountSats`: kotlin.ULong, + `feeRate`: FeeRate?, + `utxosToSpend`: List?, + ): kotlin.ULong = + FfiConverterULong.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_onchainpayment_calculate_total_fee( + it, + FfiConverterTypeAddress.lower(`address`), + FfiConverterULong.lower(`amountSats`), + FfiConverterOptionalTypeFeeRate.lower(`feeRate`), + FfiConverterOptionalSequenceTypeSpendableUtxo.lower(`utxosToSpend`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `listSpendableOutputs`(): List = + FfiConverterSequenceTypeSpendableUtxo.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_onchainpayment_list_spendable_outputs(it, _status) + } + }, + ) + + @Throws(NodeException::class) + override fun `newAddress`(): Address = + FfiConverterTypeAddress.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_onchainpayment_new_address(it, _status) + } + }, + ) + + @Throws(NodeException::class) + override fun `selectUtxosWithAlgorithm`( + `targetAmountSats`: kotlin.ULong, + `feeRate`: FeeRate?, + `algorithm`: CoinSelectionAlgorithm, + `utxos`: List?, + ): List = + FfiConverterSequenceTypeSpendableUtxo.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_onchainpayment_select_utxos_with_algorithm( + it, + FfiConverterULong.lower(`targetAmountSats`), + FfiConverterOptionalTypeFeeRate.lower(`feeRate`), + FfiConverterTypeCoinSelectionAlgorithm.lower(`algorithm`), + FfiConverterOptionalSequenceTypeSpendableUtxo.lower(`utxos`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `sendAllToAddress`( + `address`: Address, + `retainReserve`: kotlin.Boolean, + `feeRate`: FeeRate?, + ): Txid = + FfiConverterTypeTxid.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_onchainpayment_send_all_to_address( + it, + FfiConverterTypeAddress.lower(`address`), + FfiConverterBoolean.lower(`retainReserve`), + FfiConverterOptionalTypeFeeRate.lower(`feeRate`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `sendToAddress`( + `address`: Address, + `amountSats`: kotlin.ULong, + `feeRate`: FeeRate?, + `utxosToSpend`: List?, + ): Txid = + FfiConverterTypeTxid.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_onchainpayment_send_to_address( + it, + FfiConverterTypeAddress.lower(`address`), + FfiConverterULong.lower(`amountSats`), + FfiConverterOptionalTypeFeeRate.lower(`feeRate`), + FfiConverterOptionalSequenceTypeSpendableUtxo.lower(`utxosToSpend`), + _status, + ) + } + }, + ) + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeOnchainPayment : FfiConverter { + override fun lower(value: OnchainPayment): Pointer = value.uniffiClonePointer() + + override fun lift(value: Pointer): OnchainPayment = OnchainPayment(value) + + override fun read(buf: ByteBuffer): OnchainPayment { + // The Rust code always writes pointers as 8 bytes, and will + // fail to compile if they don't fit. + return lift(Pointer(buf.getLong())) + } + + override fun allocationSize(value: OnchainPayment) = 8UL + + override fun write( + value: OnchainPayment, + buf: ByteBuffer, + ) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(lower(value))) + } +} + +// This template implements a class for working with a Rust struct via a Pointer/Arc +// to the live Rust struct on the other side of the FFI. +// +// Each instance implements core operations for working with the Rust `Arc` and the +// Kotlin Pointer to work with the live Rust struct on the other side of the FFI. +// +// There's some subtlety here, because we have to be careful not to operate on a Rust +// struct after it has been dropped, and because we must expose a public API for freeing +// theq Kotlin wrapper object in lieu of reliable finalizers. The core requirements are: +// +// * Each instance holds an opaque pointer to the underlying Rust struct. +// Method calls need to read this pointer from the object's state and pass it in to +// the Rust FFI. +// +// * When an instance is no longer needed, its pointer should be passed to a +// special destructor function provided by the Rust FFI, which will drop the +// underlying Rust struct. +// +// * Given an instance, calling code is expected to call the special +// `destroy` method in order to free it after use, either by calling it explicitly +// or by using a higher-level helper like the `use` method. Failing to do so risks +// leaking the underlying Rust struct. +// +// * We can't assume that calling code will do the right thing, and must be prepared +// to handle Kotlin method calls executing concurrently with or even after a call to +// `destroy`, and to handle multiple (possibly concurrent!) calls to `destroy`. +// +// * We must never allow Rust code to operate on the underlying Rust struct after +// the destructor has been called, and must never call the destructor more than once. +// Doing so may trigger memory unsafety. +// +// * To mitigate many of the risks of leaking memory and use-after-free unsafety, a `Cleaner` +// is implemented to call the destructor when the Kotlin object becomes unreachable. +// This is done in a background thread. This is not a panacea, and client code should be aware that +// 1. the thread may starve if some there are objects that have poorly performing +// `drop` methods or do significant work in their `drop` methods. +// 2. the thread is shared across the whole library. This can be tuned by using `android_cleaner = true`, +// or `android = true` in the [`kotlin` section of the `uniffi.toml` file](https://mozilla.github.io/uniffi-rs/kotlin/configuration.html). +// +// If we try to implement this with mutual exclusion on access to the pointer, there is the +// possibility of a race between a method call and a concurrent call to `destroy`: +// +// * Thread A starts a method call, reads the value of the pointer, but is interrupted +// before it can pass the pointer over the FFI to Rust. +// * Thread B calls `destroy` and frees the underlying Rust struct. +// * Thread A resumes, passing the already-read pointer value to Rust and triggering +// a use-after-free. +// +// One possible solution would be to use a `ReadWriteLock`, with each method call taking +// a read lock (and thus allowed to run concurrently) and the special `destroy` method +// taking a write lock (and thus blocking on live method calls). However, we aim not to +// generate methods with any hidden blocking semantics, and a `destroy` method that might +// block if called incorrectly seems to meet that bar. +// +// So, we achieve our goals by giving each instance an associated `AtomicLong` counter to track +// the number of in-flight method calls, and an `AtomicBoolean` flag to indicate whether `destroy` +// has been called. These are updated according to the following rules: +// +// * The initial value of the counter is 1, indicating a live object with no in-flight calls. +// The initial value for the flag is false. +// +// * At the start of each method call, we atomically check the counter. +// If it is 0 then the underlying Rust struct has already been destroyed and the call is aborted. +// If it is nonzero them we atomically increment it by 1 and proceed with the method call. +// +// * At the end of each method call, we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// * When `destroy` is called, we atomically flip the flag from false to true. +// If the flag was already true we silently fail. +// Otherwise we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// Astute readers may observe that this all sounds very similar to the way that Rust's `Arc` works, +// and indeed it is, with the addition of a flag to guard against multiple calls to `destroy`. +// +// The overall effect is that the underlying Rust struct is destroyed only when `destroy` has been +// called *and* all in-flight method calls have completed, avoiding violating any of the expectations +// of the underlying Rust code. +// +// This makes a cleaner a better alternative to _not_ calling `destroy()` as +// and when the object is finished with, but the abstraction is not perfect: if the Rust object's `drop` +// method is slow, and/or there are many objects to cleanup, and it's on a low end Android device, then the cleaner +// thread may be starved, and the app will leak memory. +// +// In this case, `destroy`ing manually may be a better solution. +// +// The cleaner can live side by side with the manual calling of `destroy`. In the order of responsiveness, uniffi objects +// with Rust peers are reclaimed: +// +// 1. By calling the `destroy` method of the object, which calls `rustObject.free()`. If that doesn't happen: +// 2. When the object becomes unreachable, AND the Cleaner thread gets to call `rustObject.free()`. If the thread is starved then: +// 3. The memory is reclaimed when the process terminates. +// +// [1] https://stackoverflow.com/questions/24376768/can-java-finalize-an-object-when-it-is-still-in-scope/24380219 +// + +public interface RefundInterface { + fun `absoluteExpirySeconds`(): kotlin.ULong? + + fun `amountMsats`(): kotlin.ULong + + fun `chain`(): Network? + + fun `isExpired`(): kotlin.Boolean + + fun `issuer`(): kotlin.String? + + fun `payerMetadata`(): List + + fun `payerNote`(): kotlin.String? + + fun `payerSigningPubkey`(): PublicKey + + fun `quantity`(): kotlin.ULong? + + fun `refundDescription`(): kotlin.String + + companion object +} + +open class Refund : + Disposable, + AutoCloseable, + RefundInterface { + constructor(pointer: Pointer) { + this.pointer = pointer + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + /** + * This constructor can be used to instantiate a fake object. Only used for tests. Any + * attempt to actually use an object constructed this way will fail as there is no + * connected Rust object. + */ + @Suppress("UNUSED_PARAMETER") + constructor(noPointer: NoPointer) { + this.pointer = null + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + protected val pointer: Pointer? + protected val cleanable: UniffiCleaner.Cleanable + + private val wasDestroyed = AtomicBoolean(false) + private val callCounter = AtomicLong(1) + + override fun destroy() { + // Only allow a single call to this method. + // TODO: maybe we should log a warning if called more than once? + if (this.wasDestroyed.compareAndSet(false, true)) { + // This decrement always matches the initial count of 1 given at creation time. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + @Synchronized + override fun close() { + this.destroy() + } + + internal inline fun callWithPointer(block: (ptr: Pointer) -> R): R { + // Check and increment the call counter, to keep the object alive. + // This needs a compare-and-set retry loop in case of concurrent updates. + do { + val c = this.callCounter.get() + if (c == 0L) { + throw IllegalStateException("${this.javaClass.simpleName} object has already been destroyed") + } + if (c == Long.MAX_VALUE) { + throw IllegalStateException("${this.javaClass.simpleName} call counter would overflow") + } + } while (!this.callCounter.compareAndSet(c, c + 1L)) + // Now we can safely do the method call without the pointer being freed concurrently. + try { + return block(this.uniffiClonePointer()) + } finally { + // This decrement always matches the increment we performed above. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + // Use a static inner class instead of a closure so as not to accidentally + // capture `this` as part of the cleanable's action. + private class UniffiCleanAction( + private val pointer: Pointer?, + ) : Runnable { + override fun run() { + pointer?.let { ptr -> + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_free_refund(ptr, status) + } + } + } + } + + fun uniffiClonePointer(): Pointer = + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_clone_refund(pointer!!, status) + } + + override fun `absoluteExpirySeconds`(): kotlin.ULong? = + FfiConverterOptionalULong.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_refund_absolute_expiry_seconds(it, _status) + } + }, + ) + + override fun `amountMsats`(): kotlin.ULong = + FfiConverterULong.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_refund_amount_msats(it, _status) + } + }, + ) + + override fun `chain`(): Network? = + FfiConverterOptionalTypeNetwork.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_refund_chain(it, _status) + } + }, + ) + + override fun `isExpired`(): kotlin.Boolean = + FfiConverterBoolean.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_refund_is_expired(it, _status) + } + }, + ) + + override fun `issuer`(): kotlin.String? = + FfiConverterOptionalString.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_refund_issuer(it, _status) + } + }, + ) + + override fun `payerMetadata`(): List = + FfiConverterSequenceUByte.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_refund_payer_metadata(it, _status) + } + }, + ) + + override fun `payerNote`(): kotlin.String? = + FfiConverterOptionalString.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_refund_payer_note(it, _status) + } + }, + ) + + override fun `payerSigningPubkey`(): PublicKey = + FfiConverterTypePublicKey.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_refund_payer_signing_pubkey(it, _status) + } + }, + ) + + override fun `quantity`(): kotlin.ULong? = + FfiConverterOptionalULong.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_refund_quantity(it, _status) + } + }, + ) + + override fun `refundDescription`(): kotlin.String = + FfiConverterString.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_refund_refund_description(it, _status) + } + }, + ) + + override fun toString(): String = + FfiConverterString.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_refund_uniffi_trait_display(it, _status) + } + }, + ) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is Refund) return false + return FfiConverterBoolean.lift( + callWithPointer { + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_refund_uniffi_trait_eq_eq( + it, + FfiConverterTypeRefund.lower(`other`), + _status, + ) + } + }, + ) + } + + companion object { + @Throws(NodeException::class) + fun `fromStr`(`refundStr`: kotlin.String): Refund = + FfiConverterTypeRefund.lift( + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_constructor_refund_from_str(FfiConverterString.lower(`refundStr`), _status) + }, + ) + } +} + +/** + * @suppress + */ +public object FfiConverterTypeRefund : FfiConverter { + override fun lower(value: Refund): Pointer = value.uniffiClonePointer() + + override fun lift(value: Pointer): Refund = Refund(value) + + override fun read(buf: ByteBuffer): Refund { + // The Rust code always writes pointers as 8 bytes, and will + // fail to compile if they don't fit. + return lift(Pointer(buf.getLong())) + } + + override fun allocationSize(value: Refund) = 8UL + + override fun write( + value: Refund, + buf: ByteBuffer, + ) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(lower(value))) + } +} + +// This template implements a class for working with a Rust struct via a Pointer/Arc +// to the live Rust struct on the other side of the FFI. +// +// Each instance implements core operations for working with the Rust `Arc` and the +// Kotlin Pointer to work with the live Rust struct on the other side of the FFI. +// +// There's some subtlety here, because we have to be careful not to operate on a Rust +// struct after it has been dropped, and because we must expose a public API for freeing +// theq Kotlin wrapper object in lieu of reliable finalizers. The core requirements are: +// +// * Each instance holds an opaque pointer to the underlying Rust struct. +// Method calls need to read this pointer from the object's state and pass it in to +// the Rust FFI. +// +// * When an instance is no longer needed, its pointer should be passed to a +// special destructor function provided by the Rust FFI, which will drop the +// underlying Rust struct. +// +// * Given an instance, calling code is expected to call the special +// `destroy` method in order to free it after use, either by calling it explicitly +// or by using a higher-level helper like the `use` method. Failing to do so risks +// leaking the underlying Rust struct. +// +// * We can't assume that calling code will do the right thing, and must be prepared +// to handle Kotlin method calls executing concurrently with or even after a call to +// `destroy`, and to handle multiple (possibly concurrent!) calls to `destroy`. +// +// * We must never allow Rust code to operate on the underlying Rust struct after +// the destructor has been called, and must never call the destructor more than once. +// Doing so may trigger memory unsafety. +// +// * To mitigate many of the risks of leaking memory and use-after-free unsafety, a `Cleaner` +// is implemented to call the destructor when the Kotlin object becomes unreachable. +// This is done in a background thread. This is not a panacea, and client code should be aware that +// 1. the thread may starve if some there are objects that have poorly performing +// `drop` methods or do significant work in their `drop` methods. +// 2. the thread is shared across the whole library. This can be tuned by using `android_cleaner = true`, +// or `android = true` in the [`kotlin` section of the `uniffi.toml` file](https://mozilla.github.io/uniffi-rs/kotlin/configuration.html). +// +// If we try to implement this with mutual exclusion on access to the pointer, there is the +// possibility of a race between a method call and a concurrent call to `destroy`: +// +// * Thread A starts a method call, reads the value of the pointer, but is interrupted +// before it can pass the pointer over the FFI to Rust. +// * Thread B calls `destroy` and frees the underlying Rust struct. +// * Thread A resumes, passing the already-read pointer value to Rust and triggering +// a use-after-free. +// +// One possible solution would be to use a `ReadWriteLock`, with each method call taking +// a read lock (and thus allowed to run concurrently) and the special `destroy` method +// taking a write lock (and thus blocking on live method calls). However, we aim not to +// generate methods with any hidden blocking semantics, and a `destroy` method that might +// block if called incorrectly seems to meet that bar. +// +// So, we achieve our goals by giving each instance an associated `AtomicLong` counter to track +// the number of in-flight method calls, and an `AtomicBoolean` flag to indicate whether `destroy` +// has been called. These are updated according to the following rules: +// +// * The initial value of the counter is 1, indicating a live object with no in-flight calls. +// The initial value for the flag is false. +// +// * At the start of each method call, we atomically check the counter. +// If it is 0 then the underlying Rust struct has already been destroyed and the call is aborted. +// If it is nonzero them we atomically increment it by 1 and proceed with the method call. +// +// * At the end of each method call, we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// * When `destroy` is called, we atomically flip the flag from false to true. +// If the flag was already true we silently fail. +// Otherwise we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// Astute readers may observe that this all sounds very similar to the way that Rust's `Arc` works, +// and indeed it is, with the addition of a flag to guard against multiple calls to `destroy`. +// +// The overall effect is that the underlying Rust struct is destroyed only when `destroy` has been +// called *and* all in-flight method calls have completed, avoiding violating any of the expectations +// of the underlying Rust code. +// +// This makes a cleaner a better alternative to _not_ calling `destroy()` as +// and when the object is finished with, but the abstraction is not perfect: if the Rust object's `drop` +// method is slow, and/or there are many objects to cleanup, and it's on a low end Android device, then the cleaner +// thread may be starved, and the app will leak memory. +// +// In this case, `destroy`ing manually may be a better solution. +// +// The cleaner can live side by side with the manual calling of `destroy`. In the order of responsiveness, uniffi objects +// with Rust peers are reclaimed: +// +// 1. By calling the `destroy` method of the object, which calls `rustObject.free()`. If that doesn't happen: +// 2. When the object becomes unreachable, AND the Cleaner thread gets to call `rustObject.free()`. If the thread is starved then: +// 3. The memory is reclaimed when the process terminates. +// +// [1] https://stackoverflow.com/questions/24376768/can-java-finalize-an-object-when-it-is-still-in-scope/24380219 +// + +public interface SpontaneousPaymentInterface { + fun `send`( + `amountMsat`: kotlin.ULong, + `nodeId`: PublicKey, + `routeParameters`: RouteParametersConfig?, + ): PaymentId + + fun `sendProbes`( + `amountMsat`: kotlin.ULong, + `nodeId`: PublicKey, + ) + + fun `sendWithCustomTlvs`( + `amountMsat`: kotlin.ULong, + `nodeId`: PublicKey, + `routeParameters`: RouteParametersConfig?, + `customTlvs`: List, + ): PaymentId + + fun `sendWithPreimage`( + `amountMsat`: kotlin.ULong, + `nodeId`: PublicKey, + `preimage`: PaymentPreimage, + `routeParameters`: RouteParametersConfig?, + ): PaymentId + + fun `sendWithPreimageAndCustomTlvs`( + `amountMsat`: kotlin.ULong, + `nodeId`: PublicKey, + `customTlvs`: List, + `preimage`: PaymentPreimage, + `routeParameters`: RouteParametersConfig?, + ): PaymentId + + companion object +} + +open class SpontaneousPayment : + Disposable, + AutoCloseable, + SpontaneousPaymentInterface { + constructor(pointer: Pointer) { + this.pointer = pointer + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + /** + * This constructor can be used to instantiate a fake object. Only used for tests. Any + * attempt to actually use an object constructed this way will fail as there is no + * connected Rust object. + */ + @Suppress("UNUSED_PARAMETER") + constructor(noPointer: NoPointer) { + this.pointer = null + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + protected val pointer: Pointer? + protected val cleanable: UniffiCleaner.Cleanable + + private val wasDestroyed = AtomicBoolean(false) + private val callCounter = AtomicLong(1) + + override fun destroy() { + // Only allow a single call to this method. + // TODO: maybe we should log a warning if called more than once? + if (this.wasDestroyed.compareAndSet(false, true)) { + // This decrement always matches the initial count of 1 given at creation time. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + @Synchronized + override fun close() { + this.destroy() + } + + internal inline fun callWithPointer(block: (ptr: Pointer) -> R): R { + // Check and increment the call counter, to keep the object alive. + // This needs a compare-and-set retry loop in case of concurrent updates. + do { + val c = this.callCounter.get() + if (c == 0L) { + throw IllegalStateException("${this.javaClass.simpleName} object has already been destroyed") + } + if (c == Long.MAX_VALUE) { + throw IllegalStateException("${this.javaClass.simpleName} call counter would overflow") + } + } while (!this.callCounter.compareAndSet(c, c + 1L)) + // Now we can safely do the method call without the pointer being freed concurrently. + try { + return block(this.uniffiClonePointer()) + } finally { + // This decrement always matches the increment we performed above. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + // Use a static inner class instead of a closure so as not to accidentally + // capture `this` as part of the cleanable's action. + private class UniffiCleanAction( + private val pointer: Pointer?, + ) : Runnable { + override fun run() { + pointer?.let { ptr -> + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_free_spontaneouspayment(ptr, status) + } + } + } + } + + fun uniffiClonePointer(): Pointer = + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_clone_spontaneouspayment(pointer!!, status) + } + + @Throws(NodeException::class) + override fun `send`( + `amountMsat`: kotlin.ULong, + `nodeId`: PublicKey, + `routeParameters`: RouteParametersConfig?, + ): PaymentId = + FfiConverterTypePaymentId.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_spontaneouspayment_send( + it, + FfiConverterULong.lower(`amountMsat`), + FfiConverterTypePublicKey.lower(`nodeId`), + FfiConverterOptionalTypeRouteParametersConfig.lower(`routeParameters`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `sendProbes`( + `amountMsat`: kotlin.ULong, + `nodeId`: PublicKey, + ) = callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_spontaneouspayment_send_probes( + it, + FfiConverterULong.lower(`amountMsat`), + FfiConverterTypePublicKey.lower(`nodeId`), + _status, + ) + } + } + + @Throws(NodeException::class) + override fun `sendWithCustomTlvs`( + `amountMsat`: kotlin.ULong, + `nodeId`: PublicKey, + `routeParameters`: RouteParametersConfig?, + `customTlvs`: List, + ): PaymentId = + FfiConverterTypePaymentId.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_spontaneouspayment_send_with_custom_tlvs( + it, + FfiConverterULong.lower(`amountMsat`), + FfiConverterTypePublicKey.lower(`nodeId`), + FfiConverterOptionalTypeRouteParametersConfig.lower(`routeParameters`), + FfiConverterSequenceTypeCustomTlvRecord.lower(`customTlvs`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `sendWithPreimage`( + `amountMsat`: kotlin.ULong, + `nodeId`: PublicKey, + `preimage`: PaymentPreimage, + `routeParameters`: RouteParametersConfig?, + ): PaymentId = + FfiConverterTypePaymentId.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_spontaneouspayment_send_with_preimage( + it, + FfiConverterULong.lower(`amountMsat`), + FfiConverterTypePublicKey.lower(`nodeId`), + FfiConverterTypePaymentPreimage.lower(`preimage`), + FfiConverterOptionalTypeRouteParametersConfig.lower(`routeParameters`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `sendWithPreimageAndCustomTlvs`( + `amountMsat`: kotlin.ULong, + `nodeId`: PublicKey, + `customTlvs`: List, + `preimage`: PaymentPreimage, + `routeParameters`: RouteParametersConfig?, + ): PaymentId = + FfiConverterTypePaymentId.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_spontaneouspayment_send_with_preimage_and_custom_tlvs( + it, + FfiConverterULong.lower(`amountMsat`), + FfiConverterTypePublicKey.lower(`nodeId`), + FfiConverterSequenceTypeCustomTlvRecord.lower(`customTlvs`), + FfiConverterTypePaymentPreimage.lower(`preimage`), + FfiConverterOptionalTypeRouteParametersConfig.lower(`routeParameters`), + _status, + ) + } + }, + ) + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeSpontaneousPayment : FfiConverter { + override fun lower(value: SpontaneousPayment): Pointer = value.uniffiClonePointer() + + override fun lift(value: Pointer): SpontaneousPayment = SpontaneousPayment(value) + + override fun read(buf: ByteBuffer): SpontaneousPayment { + // The Rust code always writes pointers as 8 bytes, and will + // fail to compile if they don't fit. + return lift(Pointer(buf.getLong())) + } + + override fun allocationSize(value: SpontaneousPayment) = 8UL + + override fun write( + value: SpontaneousPayment, + buf: ByteBuffer, + ) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(lower(value))) + } +} + +// This template implements a class for working with a Rust struct via a Pointer/Arc +// to the live Rust struct on the other side of the FFI. +// +// Each instance implements core operations for working with the Rust `Arc` and the +// Kotlin Pointer to work with the live Rust struct on the other side of the FFI. +// +// There's some subtlety here, because we have to be careful not to operate on a Rust +// struct after it has been dropped, and because we must expose a public API for freeing +// theq Kotlin wrapper object in lieu of reliable finalizers. The core requirements are: +// +// * Each instance holds an opaque pointer to the underlying Rust struct. +// Method calls need to read this pointer from the object's state and pass it in to +// the Rust FFI. +// +// * When an instance is no longer needed, its pointer should be passed to a +// special destructor function provided by the Rust FFI, which will drop the +// underlying Rust struct. +// +// * Given an instance, calling code is expected to call the special +// `destroy` method in order to free it after use, either by calling it explicitly +// or by using a higher-level helper like the `use` method. Failing to do so risks +// leaking the underlying Rust struct. +// +// * We can't assume that calling code will do the right thing, and must be prepared +// to handle Kotlin method calls executing concurrently with or even after a call to +// `destroy`, and to handle multiple (possibly concurrent!) calls to `destroy`. +// +// * We must never allow Rust code to operate on the underlying Rust struct after +// the destructor has been called, and must never call the destructor more than once. +// Doing so may trigger memory unsafety. +// +// * To mitigate many of the risks of leaking memory and use-after-free unsafety, a `Cleaner` +// is implemented to call the destructor when the Kotlin object becomes unreachable. +// This is done in a background thread. This is not a panacea, and client code should be aware that +// 1. the thread may starve if some there are objects that have poorly performing +// `drop` methods or do significant work in their `drop` methods. +// 2. the thread is shared across the whole library. This can be tuned by using `android_cleaner = true`, +// or `android = true` in the [`kotlin` section of the `uniffi.toml` file](https://mozilla.github.io/uniffi-rs/kotlin/configuration.html). +// +// If we try to implement this with mutual exclusion on access to the pointer, there is the +// possibility of a race between a method call and a concurrent call to `destroy`: +// +// * Thread A starts a method call, reads the value of the pointer, but is interrupted +// before it can pass the pointer over the FFI to Rust. +// * Thread B calls `destroy` and frees the underlying Rust struct. +// * Thread A resumes, passing the already-read pointer value to Rust and triggering +// a use-after-free. +// +// One possible solution would be to use a `ReadWriteLock`, with each method call taking +// a read lock (and thus allowed to run concurrently) and the special `destroy` method +// taking a write lock (and thus blocking on live method calls). However, we aim not to +// generate methods with any hidden blocking semantics, and a `destroy` method that might +// block if called incorrectly seems to meet that bar. +// +// So, we achieve our goals by giving each instance an associated `AtomicLong` counter to track +// the number of in-flight method calls, and an `AtomicBoolean` flag to indicate whether `destroy` +// has been called. These are updated according to the following rules: +// +// * The initial value of the counter is 1, indicating a live object with no in-flight calls. +// The initial value for the flag is false. +// +// * At the start of each method call, we atomically check the counter. +// If it is 0 then the underlying Rust struct has already been destroyed and the call is aborted. +// If it is nonzero them we atomically increment it by 1 and proceed with the method call. +// +// * At the end of each method call, we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// * When `destroy` is called, we atomically flip the flag from false to true. +// If the flag was already true we silently fail. +// Otherwise we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// Astute readers may observe that this all sounds very similar to the way that Rust's `Arc` works, +// and indeed it is, with the addition of a flag to guard against multiple calls to `destroy`. +// +// The overall effect is that the underlying Rust struct is destroyed only when `destroy` has been +// called *and* all in-flight method calls have completed, avoiding violating any of the expectations +// of the underlying Rust code. +// +// This makes a cleaner a better alternative to _not_ calling `destroy()` as +// and when the object is finished with, but the abstraction is not perfect: if the Rust object's `drop` +// method is slow, and/or there are many objects to cleanup, and it's on a low end Android device, then the cleaner +// thread may be starved, and the app will leak memory. +// +// In this case, `destroy`ing manually may be a better solution. +// +// The cleaner can live side by side with the manual calling of `destroy`. In the order of responsiveness, uniffi objects +// with Rust peers are reclaimed: +// +// 1. By calling the `destroy` method of the object, which calls `rustObject.free()`. If that doesn't happen: +// 2. When the object becomes unreachable, AND the Cleaner thread gets to call `rustObject.free()`. If the thread is starved then: +// 3. The memory is reclaimed when the process terminates. +// +// [1] https://stackoverflow.com/questions/24376768/can-java-finalize-an-object-when-it-is-still-in-scope/24380219 +// + +public interface UnifiedQrPaymentInterface { + fun `receive`( + `amountSats`: kotlin.ULong, + `message`: kotlin.String, + `expirySec`: kotlin.UInt, + ): kotlin.String + + fun `send`( + `uriStr`: kotlin.String, + `routeParameters`: RouteParametersConfig?, + ): QrPaymentResult + + companion object +} + +open class UnifiedQrPayment : + Disposable, + AutoCloseable, + UnifiedQrPaymentInterface { + constructor(pointer: Pointer) { + this.pointer = pointer + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + /** + * This constructor can be used to instantiate a fake object. Only used for tests. Any + * attempt to actually use an object constructed this way will fail as there is no + * connected Rust object. + */ + @Suppress("UNUSED_PARAMETER") + constructor(noPointer: NoPointer) { + this.pointer = null + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + protected val pointer: Pointer? + protected val cleanable: UniffiCleaner.Cleanable + + private val wasDestroyed = AtomicBoolean(false) + private val callCounter = AtomicLong(1) + + override fun destroy() { + // Only allow a single call to this method. + // TODO: maybe we should log a warning if called more than once? + if (this.wasDestroyed.compareAndSet(false, true)) { + // This decrement always matches the initial count of 1 given at creation time. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + @Synchronized + override fun close() { + this.destroy() + } + + internal inline fun callWithPointer(block: (ptr: Pointer) -> R): R { + // Check and increment the call counter, to keep the object alive. + // This needs a compare-and-set retry loop in case of concurrent updates. + do { + val c = this.callCounter.get() + if (c == 0L) { + throw IllegalStateException("${this.javaClass.simpleName} object has already been destroyed") + } + if (c == Long.MAX_VALUE) { + throw IllegalStateException("${this.javaClass.simpleName} call counter would overflow") + } + } while (!this.callCounter.compareAndSet(c, c + 1L)) + // Now we can safely do the method call without the pointer being freed concurrently. + try { + return block(this.uniffiClonePointer()) + } finally { + // This decrement always matches the increment we performed above. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + // Use a static inner class instead of a closure so as not to accidentally + // capture `this` as part of the cleanable's action. + private class UniffiCleanAction( + private val pointer: Pointer?, + ) : Runnable { + override fun run() { + pointer?.let { ptr -> + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_free_unifiedqrpayment(ptr, status) + } + } + } + } + + fun uniffiClonePointer(): Pointer = + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_clone_unifiedqrpayment(pointer!!, status) + } + + @Throws(NodeException::class) + override fun `receive`( + `amountSats`: kotlin.ULong, + `message`: kotlin.String, + `expirySec`: kotlin.UInt, + ): kotlin.String = + FfiConverterString.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_unifiedqrpayment_receive( + it, + FfiConverterULong.lower(`amountSats`), + FfiConverterString.lower(`message`), + FfiConverterUInt.lower(`expirySec`), + _status, + ) + } + }, + ) + + @Throws(NodeException::class) + override fun `send`( + `uriStr`: kotlin.String, + `routeParameters`: RouteParametersConfig?, + ): QrPaymentResult = + FfiConverterTypeQrPaymentResult.lift( + callWithPointer { + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_unifiedqrpayment_send( + it, + FfiConverterString.lower(`uriStr`), + FfiConverterOptionalTypeRouteParametersConfig.lower(`routeParameters`), + _status, + ) + } + }, + ) + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeUnifiedQrPayment : FfiConverter { + override fun lower(value: UnifiedQrPayment): Pointer = value.uniffiClonePointer() + + override fun lift(value: Pointer): UnifiedQrPayment = UnifiedQrPayment(value) + + override fun read(buf: ByteBuffer): UnifiedQrPayment { + // The Rust code always writes pointers as 8 bytes, and will + // fail to compile if they don't fit. + return lift(Pointer(buf.getLong())) + } + + override fun allocationSize(value: UnifiedQrPayment) = 8UL + + override fun write( + value: UnifiedQrPayment, + buf: ByteBuffer, + ) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(lower(value))) + } +} + +// This template implements a class for working with a Rust struct via a Pointer/Arc +// to the live Rust struct on the other side of the FFI. +// +// Each instance implements core operations for working with the Rust `Arc` and the +// Kotlin Pointer to work with the live Rust struct on the other side of the FFI. +// +// There's some subtlety here, because we have to be careful not to operate on a Rust +// struct after it has been dropped, and because we must expose a public API for freeing +// theq Kotlin wrapper object in lieu of reliable finalizers. The core requirements are: +// +// * Each instance holds an opaque pointer to the underlying Rust struct. +// Method calls need to read this pointer from the object's state and pass it in to +// the Rust FFI. +// +// * When an instance is no longer needed, its pointer should be passed to a +// special destructor function provided by the Rust FFI, which will drop the +// underlying Rust struct. +// +// * Given an instance, calling code is expected to call the special +// `destroy` method in order to free it after use, either by calling it explicitly +// or by using a higher-level helper like the `use` method. Failing to do so risks +// leaking the underlying Rust struct. +// +// * We can't assume that calling code will do the right thing, and must be prepared +// to handle Kotlin method calls executing concurrently with or even after a call to +// `destroy`, and to handle multiple (possibly concurrent!) calls to `destroy`. +// +// * We must never allow Rust code to operate on the underlying Rust struct after +// the destructor has been called, and must never call the destructor more than once. +// Doing so may trigger memory unsafety. +// +// * To mitigate many of the risks of leaking memory and use-after-free unsafety, a `Cleaner` +// is implemented to call the destructor when the Kotlin object becomes unreachable. +// This is done in a background thread. This is not a panacea, and client code should be aware that +// 1. the thread may starve if some there are objects that have poorly performing +// `drop` methods or do significant work in their `drop` methods. +// 2. the thread is shared across the whole library. This can be tuned by using `android_cleaner = true`, +// or `android = true` in the [`kotlin` section of the `uniffi.toml` file](https://mozilla.github.io/uniffi-rs/kotlin/configuration.html). +// +// If we try to implement this with mutual exclusion on access to the pointer, there is the +// possibility of a race between a method call and a concurrent call to `destroy`: +// +// * Thread A starts a method call, reads the value of the pointer, but is interrupted +// before it can pass the pointer over the FFI to Rust. +// * Thread B calls `destroy` and frees the underlying Rust struct. +// * Thread A resumes, passing the already-read pointer value to Rust and triggering +// a use-after-free. +// +// One possible solution would be to use a `ReadWriteLock`, with each method call taking +// a read lock (and thus allowed to run concurrently) and the special `destroy` method +// taking a write lock (and thus blocking on live method calls). However, we aim not to +// generate methods with any hidden blocking semantics, and a `destroy` method that might +// block if called incorrectly seems to meet that bar. +// +// So, we achieve our goals by giving each instance an associated `AtomicLong` counter to track +// the number of in-flight method calls, and an `AtomicBoolean` flag to indicate whether `destroy` +// has been called. These are updated according to the following rules: +// +// * The initial value of the counter is 1, indicating a live object with no in-flight calls. +// The initial value for the flag is false. +// +// * At the start of each method call, we atomically check the counter. +// If it is 0 then the underlying Rust struct has already been destroyed and the call is aborted. +// If it is nonzero them we atomically increment it by 1 and proceed with the method call. +// +// * At the end of each method call, we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// * When `destroy` is called, we atomically flip the flag from false to true. +// If the flag was already true we silently fail. +// Otherwise we atomically decrement and check the counter. +// If it has reached zero then we destroy the underlying Rust struct. +// +// Astute readers may observe that this all sounds very similar to the way that Rust's `Arc` works, +// and indeed it is, with the addition of a flag to guard against multiple calls to `destroy`. +// +// The overall effect is that the underlying Rust struct is destroyed only when `destroy` has been +// called *and* all in-flight method calls have completed, avoiding violating any of the expectations +// of the underlying Rust code. +// +// This makes a cleaner a better alternative to _not_ calling `destroy()` as +// and when the object is finished with, but the abstraction is not perfect: if the Rust object's `drop` +// method is slow, and/or there are many objects to cleanup, and it's on a low end Android device, then the cleaner +// thread may be starved, and the app will leak memory. +// +// In this case, `destroy`ing manually may be a better solution. +// +// The cleaner can live side by side with the manual calling of `destroy`. In the order of responsiveness, uniffi objects +// with Rust peers are reclaimed: +// +// 1. By calling the `destroy` method of the object, which calls `rustObject.free()`. If that doesn't happen: +// 2. When the object becomes unreachable, AND the Cleaner thread gets to call `rustObject.free()`. If the thread is starved then: +// 3. The memory is reclaimed when the process terminates. +// +// [1] https://stackoverflow.com/questions/24376768/can-java-finalize-an-object-when-it-is-still-in-scope/24380219 +// + +public interface VssHeaderProviderInterface { + suspend fun `getHeaders`(`request`: List): Map + + companion object +} + +open class VssHeaderProvider : + Disposable, + AutoCloseable, + VssHeaderProviderInterface { + constructor(pointer: Pointer) { + this.pointer = pointer + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + /** + * This constructor can be used to instantiate a fake object. Only used for tests. Any + * attempt to actually use an object constructed this way will fail as there is no + * connected Rust object. + */ + @Suppress("UNUSED_PARAMETER") + constructor(noPointer: NoPointer) { + this.pointer = null + this.cleanable = UniffiLib.CLEANER.register(this, UniffiCleanAction(pointer)) + } + + protected val pointer: Pointer? + protected val cleanable: UniffiCleaner.Cleanable + + private val wasDestroyed = AtomicBoolean(false) + private val callCounter = AtomicLong(1) + + override fun destroy() { + // Only allow a single call to this method. + // TODO: maybe we should log a warning if called more than once? + if (this.wasDestroyed.compareAndSet(false, true)) { + // This decrement always matches the initial count of 1 given at creation time. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + @Synchronized + override fun close() { + this.destroy() + } + + internal inline fun callWithPointer(block: (ptr: Pointer) -> R): R { + // Check and increment the call counter, to keep the object alive. + // This needs a compare-and-set retry loop in case of concurrent updates. + do { + val c = this.callCounter.get() + if (c == 0L) { + throw IllegalStateException("${this.javaClass.simpleName} object has already been destroyed") + } + if (c == Long.MAX_VALUE) { + throw IllegalStateException("${this.javaClass.simpleName} call counter would overflow") + } + } while (!this.callCounter.compareAndSet(c, c + 1L)) + // Now we can safely do the method call without the pointer being freed concurrently. + try { + return block(this.uniffiClonePointer()) + } finally { + // This decrement always matches the increment we performed above. + if (this.callCounter.decrementAndGet() == 0L) { + cleanable.clean() + } + } + } + + // Use a static inner class instead of a closure so as not to accidentally + // capture `this` as part of the cleanable's action. + private class UniffiCleanAction( + private val pointer: Pointer?, + ) : Runnable { + override fun run() { + pointer?.let { ptr -> + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_free_vssheaderprovider(ptr, status) + } + } + } + } + + fun uniffiClonePointer(): Pointer = + uniffiRustCall { status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_clone_vssheaderprovider(pointer!!, status) + } + + @Throws(VssHeaderProviderException::class) + @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE") + override suspend fun `getHeaders`(`request`: List): Map = + uniffiRustCallAsync( + callWithPointer { thisPtr -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_method_vssheaderprovider_get_headers( + thisPtr, + FfiConverterSequenceUByte.lower(`request`), + ) + }, + { + future, + callback, + continuation, + -> + UniffiLib.INSTANCE.ffi_ldk_node_rust_future_poll_rust_buffer(future, callback, continuation) + }, + { future, continuation -> UniffiLib.INSTANCE.ffi_ldk_node_rust_future_complete_rust_buffer(future, continuation) }, + { future -> UniffiLib.INSTANCE.ffi_ldk_node_rust_future_free_rust_buffer(future) }, + // lift function + { FfiConverterMapStringString.lift(it) }, + // Error FFI converter + VssHeaderProviderException.ErrorHandler, + ) + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeVssHeaderProvider : FfiConverter { + override fun lower(value: VssHeaderProvider): Pointer = value.uniffiClonePointer() + + override fun lift(value: Pointer): VssHeaderProvider = VssHeaderProvider(value) + + override fun read(buf: ByteBuffer): VssHeaderProvider { + // The Rust code always writes pointers as 8 bytes, and will + // fail to compile if they don't fit. + return lift(Pointer(buf.getLong())) + } + + override fun allocationSize(value: VssHeaderProvider) = 8UL + + override fun write( + value: VssHeaderProvider, + buf: ByteBuffer, + ) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(lower(value))) + } +} + +data class AnchorChannelsConfig( + var `trustedPeersNoReserve`: List, + var `perChannelReserveSats`: kotlin.ULong, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeAnchorChannelsConfig : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): AnchorChannelsConfig = + AnchorChannelsConfig( + FfiConverterSequenceTypePublicKey.read(buf), + FfiConverterULong.read(buf), + ) + + override fun allocationSize(value: AnchorChannelsConfig) = + ( + FfiConverterSequenceTypePublicKey.allocationSize(value.`trustedPeersNoReserve`) + + FfiConverterULong.allocationSize(value.`perChannelReserveSats`) + ) + + override fun write( + value: AnchorChannelsConfig, + buf: ByteBuffer, + ) { + FfiConverterSequenceTypePublicKey.write(value.`trustedPeersNoReserve`, buf) + FfiConverterULong.write(value.`perChannelReserveSats`, buf) + } +} + +data class BackgroundSyncConfig( + var `onchainWalletSyncIntervalSecs`: kotlin.ULong, + var `lightningWalletSyncIntervalSecs`: kotlin.ULong, + var `feeRateCacheUpdateIntervalSecs`: kotlin.ULong, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeBackgroundSyncConfig : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): BackgroundSyncConfig = + BackgroundSyncConfig( + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + ) + + override fun allocationSize(value: BackgroundSyncConfig) = + ( + FfiConverterULong.allocationSize(value.`onchainWalletSyncIntervalSecs`) + + FfiConverterULong.allocationSize(value.`lightningWalletSyncIntervalSecs`) + + FfiConverterULong.allocationSize(value.`feeRateCacheUpdateIntervalSecs`) + ) + + override fun write( + value: BackgroundSyncConfig, + buf: ByteBuffer, + ) { + FfiConverterULong.write(value.`onchainWalletSyncIntervalSecs`, buf) + FfiConverterULong.write(value.`lightningWalletSyncIntervalSecs`, buf) + FfiConverterULong.write(value.`feeRateCacheUpdateIntervalSecs`, buf) + } +} + +data class BalanceDetails( + var `totalOnchainBalanceSats`: kotlin.ULong, + var `spendableOnchainBalanceSats`: kotlin.ULong, + var `totalAnchorChannelsReserveSats`: kotlin.ULong, + var `totalLightningBalanceSats`: kotlin.ULong, + var `lightningBalances`: List, + var `pendingBalancesFromChannelClosures`: List, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeBalanceDetails : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): BalanceDetails = + BalanceDetails( + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterSequenceTypeLightningBalance.read(buf), + FfiConverterSequenceTypePendingSweepBalance.read(buf), + ) + + override fun allocationSize(value: BalanceDetails) = + ( + FfiConverterULong.allocationSize(value.`totalOnchainBalanceSats`) + + FfiConverterULong.allocationSize(value.`spendableOnchainBalanceSats`) + + FfiConverterULong.allocationSize(value.`totalAnchorChannelsReserveSats`) + + FfiConverterULong.allocationSize(value.`totalLightningBalanceSats`) + + FfiConverterSequenceTypeLightningBalance.allocationSize(value.`lightningBalances`) + + FfiConverterSequenceTypePendingSweepBalance.allocationSize(value.`pendingBalancesFromChannelClosures`) + ) + + override fun write( + value: BalanceDetails, + buf: ByteBuffer, + ) { + FfiConverterULong.write(value.`totalOnchainBalanceSats`, buf) + FfiConverterULong.write(value.`spendableOnchainBalanceSats`, buf) + FfiConverterULong.write(value.`totalAnchorChannelsReserveSats`, buf) + FfiConverterULong.write(value.`totalLightningBalanceSats`, buf) + FfiConverterSequenceTypeLightningBalance.write(value.`lightningBalances`, buf) + FfiConverterSequenceTypePendingSweepBalance.write(value.`pendingBalancesFromChannelClosures`, buf) + } +} + +data class BestBlock( + var `blockHash`: BlockHash, + var `height`: kotlin.UInt, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeBestBlock : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): BestBlock = + BestBlock( + FfiConverterTypeBlockHash.read(buf), + FfiConverterUInt.read(buf), + ) + + override fun allocationSize(value: BestBlock) = + ( + FfiConverterTypeBlockHash.allocationSize(value.`blockHash`) + + FfiConverterUInt.allocationSize(value.`height`) + ) + + override fun write( + value: BestBlock, + buf: ByteBuffer, + ) { + FfiConverterTypeBlockHash.write(value.`blockHash`, buf) + FfiConverterUInt.write(value.`height`, buf) + } +} + +data class ChannelConfig( + var `forwardingFeeProportionalMillionths`: kotlin.UInt, + var `forwardingFeeBaseMsat`: kotlin.UInt, + var `cltvExpiryDelta`: kotlin.UShort, + var `maxDustHtlcExposure`: MaxDustHtlcExposure, + var `forceCloseAvoidanceMaxFeeSatoshis`: kotlin.ULong, + var `acceptUnderpayingHtlcs`: kotlin.Boolean, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeChannelConfig : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): ChannelConfig = + ChannelConfig( + FfiConverterUInt.read(buf), + FfiConverterUInt.read(buf), + FfiConverterUShort.read(buf), + FfiConverterTypeMaxDustHTLCExposure.read(buf), + FfiConverterULong.read(buf), + FfiConverterBoolean.read(buf), + ) + + override fun allocationSize(value: ChannelConfig) = + ( + FfiConverterUInt.allocationSize(value.`forwardingFeeProportionalMillionths`) + + FfiConverterUInt.allocationSize(value.`forwardingFeeBaseMsat`) + + FfiConverterUShort.allocationSize(value.`cltvExpiryDelta`) + + FfiConverterTypeMaxDustHTLCExposure.allocationSize(value.`maxDustHtlcExposure`) + + FfiConverterULong.allocationSize(value.`forceCloseAvoidanceMaxFeeSatoshis`) + + FfiConverterBoolean.allocationSize(value.`acceptUnderpayingHtlcs`) + ) + + override fun write( + value: ChannelConfig, + buf: ByteBuffer, + ) { + FfiConverterUInt.write(value.`forwardingFeeProportionalMillionths`, buf) + FfiConverterUInt.write(value.`forwardingFeeBaseMsat`, buf) + FfiConverterUShort.write(value.`cltvExpiryDelta`, buf) + FfiConverterTypeMaxDustHTLCExposure.write(value.`maxDustHtlcExposure`, buf) + FfiConverterULong.write(value.`forceCloseAvoidanceMaxFeeSatoshis`, buf) + FfiConverterBoolean.write(value.`acceptUnderpayingHtlcs`, buf) + } +} + +data class ChannelDataMigration( + var `channelManager`: List?, + var `channelMonitors`: List>, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeChannelDataMigration : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): ChannelDataMigration = + ChannelDataMigration( + FfiConverterOptionalSequenceUByte.read(buf), + FfiConverterSequenceSequenceUByte.read(buf), + ) + + override fun allocationSize(value: ChannelDataMigration) = + ( + FfiConverterOptionalSequenceUByte.allocationSize(value.`channelManager`) + + FfiConverterSequenceSequenceUByte.allocationSize(value.`channelMonitors`) + ) + + override fun write( + value: ChannelDataMigration, + buf: ByteBuffer, + ) { + FfiConverterOptionalSequenceUByte.write(value.`channelManager`, buf) + FfiConverterSequenceSequenceUByte.write(value.`channelMonitors`, buf) + } +} + +data class ChannelDetails( + var `channelId`: ChannelId, + var `counterpartyNodeId`: PublicKey, + var `fundingTxo`: OutPoint?, + var `shortChannelId`: kotlin.ULong?, + var `outboundScidAlias`: kotlin.ULong?, + var `inboundScidAlias`: kotlin.ULong?, + var `channelValueSats`: kotlin.ULong, + var `unspendablePunishmentReserve`: kotlin.ULong?, + var `userChannelId`: UserChannelId, + var `feerateSatPer1000Weight`: kotlin.UInt, + var `outboundCapacityMsat`: kotlin.ULong, + var `inboundCapacityMsat`: kotlin.ULong, + var `confirmationsRequired`: kotlin.UInt?, + var `confirmations`: kotlin.UInt?, + var `isOutbound`: kotlin.Boolean, + var `isChannelReady`: kotlin.Boolean, + var `isUsable`: kotlin.Boolean, + var `isAnnounced`: kotlin.Boolean, + var `cltvExpiryDelta`: kotlin.UShort?, + var `counterpartyUnspendablePunishmentReserve`: kotlin.ULong, + var `counterpartyOutboundHtlcMinimumMsat`: kotlin.ULong?, + var `counterpartyOutboundHtlcMaximumMsat`: kotlin.ULong?, + var `counterpartyForwardingInfoFeeBaseMsat`: kotlin.UInt?, + var `counterpartyForwardingInfoFeeProportionalMillionths`: kotlin.UInt?, + var `counterpartyForwardingInfoCltvExpiryDelta`: kotlin.UShort?, + var `nextOutboundHtlcLimitMsat`: kotlin.ULong, + var `nextOutboundHtlcMinimumMsat`: kotlin.ULong, + var `forceCloseSpendDelay`: kotlin.UShort?, + var `inboundHtlcMinimumMsat`: kotlin.ULong, + var `inboundHtlcMaximumMsat`: kotlin.ULong?, + var `config`: ChannelConfig, + var `claimableOnCloseSats`: kotlin.ULong?, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeChannelDetails : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): ChannelDetails = + ChannelDetails( + FfiConverterTypeChannelId.read(buf), + FfiConverterTypePublicKey.read(buf), + FfiConverterOptionalTypeOutPoint.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterTypeUserChannelId.read(buf), + FfiConverterUInt.read(buf), + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterOptionalUInt.read(buf), + FfiConverterOptionalUInt.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterOptionalUShort.read(buf), + FfiConverterULong.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterOptionalUInt.read(buf), + FfiConverterOptionalUInt.read(buf), + FfiConverterOptionalUShort.read(buf), + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterOptionalUShort.read(buf), + FfiConverterULong.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterTypeChannelConfig.read(buf), + FfiConverterOptionalULong.read(buf), + ) + + override fun allocationSize(value: ChannelDetails) = + ( + FfiConverterTypeChannelId.allocationSize(value.`channelId`) + + FfiConverterTypePublicKey.allocationSize(value.`counterpartyNodeId`) + + FfiConverterOptionalTypeOutPoint.allocationSize(value.`fundingTxo`) + + FfiConverterOptionalULong.allocationSize(value.`shortChannelId`) + + FfiConverterOptionalULong.allocationSize(value.`outboundScidAlias`) + + FfiConverterOptionalULong.allocationSize(value.`inboundScidAlias`) + + FfiConverterULong.allocationSize(value.`channelValueSats`) + + FfiConverterOptionalULong.allocationSize(value.`unspendablePunishmentReserve`) + + FfiConverterTypeUserChannelId.allocationSize(value.`userChannelId`) + + FfiConverterUInt.allocationSize(value.`feerateSatPer1000Weight`) + + FfiConverterULong.allocationSize(value.`outboundCapacityMsat`) + + FfiConverterULong.allocationSize(value.`inboundCapacityMsat`) + + FfiConverterOptionalUInt.allocationSize(value.`confirmationsRequired`) + + FfiConverterOptionalUInt.allocationSize(value.`confirmations`) + + FfiConverterBoolean.allocationSize(value.`isOutbound`) + + FfiConverterBoolean.allocationSize(value.`isChannelReady`) + + FfiConverterBoolean.allocationSize(value.`isUsable`) + + FfiConverterBoolean.allocationSize(value.`isAnnounced`) + + FfiConverterOptionalUShort.allocationSize(value.`cltvExpiryDelta`) + + FfiConverterULong.allocationSize(value.`counterpartyUnspendablePunishmentReserve`) + + FfiConverterOptionalULong.allocationSize(value.`counterpartyOutboundHtlcMinimumMsat`) + + FfiConverterOptionalULong.allocationSize(value.`counterpartyOutboundHtlcMaximumMsat`) + + FfiConverterOptionalUInt.allocationSize(value.`counterpartyForwardingInfoFeeBaseMsat`) + + FfiConverterOptionalUInt.allocationSize(value.`counterpartyForwardingInfoFeeProportionalMillionths`) + + FfiConverterOptionalUShort.allocationSize(value.`counterpartyForwardingInfoCltvExpiryDelta`) + + FfiConverterULong.allocationSize(value.`nextOutboundHtlcLimitMsat`) + + FfiConverterULong.allocationSize(value.`nextOutboundHtlcMinimumMsat`) + + FfiConverterOptionalUShort.allocationSize(value.`forceCloseSpendDelay`) + + FfiConverterULong.allocationSize(value.`inboundHtlcMinimumMsat`) + + FfiConverterOptionalULong.allocationSize(value.`inboundHtlcMaximumMsat`) + + FfiConverterTypeChannelConfig.allocationSize(value.`config`) + + FfiConverterOptionalULong.allocationSize(value.`claimableOnCloseSats`) + ) + + override fun write( + value: ChannelDetails, + buf: ByteBuffer, + ) { + FfiConverterTypeChannelId.write(value.`channelId`, buf) + FfiConverterTypePublicKey.write(value.`counterpartyNodeId`, buf) + FfiConverterOptionalTypeOutPoint.write(value.`fundingTxo`, buf) + FfiConverterOptionalULong.write(value.`shortChannelId`, buf) + FfiConverterOptionalULong.write(value.`outboundScidAlias`, buf) + FfiConverterOptionalULong.write(value.`inboundScidAlias`, buf) + FfiConverterULong.write(value.`channelValueSats`, buf) + FfiConverterOptionalULong.write(value.`unspendablePunishmentReserve`, buf) + FfiConverterTypeUserChannelId.write(value.`userChannelId`, buf) + FfiConverterUInt.write(value.`feerateSatPer1000Weight`, buf) + FfiConverterULong.write(value.`outboundCapacityMsat`, buf) + FfiConverterULong.write(value.`inboundCapacityMsat`, buf) + FfiConverterOptionalUInt.write(value.`confirmationsRequired`, buf) + FfiConverterOptionalUInt.write(value.`confirmations`, buf) + FfiConverterBoolean.write(value.`isOutbound`, buf) + FfiConverterBoolean.write(value.`isChannelReady`, buf) + FfiConverterBoolean.write(value.`isUsable`, buf) + FfiConverterBoolean.write(value.`isAnnounced`, buf) + FfiConverterOptionalUShort.write(value.`cltvExpiryDelta`, buf) + FfiConverterULong.write(value.`counterpartyUnspendablePunishmentReserve`, buf) + FfiConverterOptionalULong.write(value.`counterpartyOutboundHtlcMinimumMsat`, buf) + FfiConverterOptionalULong.write(value.`counterpartyOutboundHtlcMaximumMsat`, buf) + FfiConverterOptionalUInt.write(value.`counterpartyForwardingInfoFeeBaseMsat`, buf) + FfiConverterOptionalUInt.write(value.`counterpartyForwardingInfoFeeProportionalMillionths`, buf) + FfiConverterOptionalUShort.write(value.`counterpartyForwardingInfoCltvExpiryDelta`, buf) + FfiConverterULong.write(value.`nextOutboundHtlcLimitMsat`, buf) + FfiConverterULong.write(value.`nextOutboundHtlcMinimumMsat`, buf) + FfiConverterOptionalUShort.write(value.`forceCloseSpendDelay`, buf) + FfiConverterULong.write(value.`inboundHtlcMinimumMsat`, buf) + FfiConverterOptionalULong.write(value.`inboundHtlcMaximumMsat`, buf) + FfiConverterTypeChannelConfig.write(value.`config`, buf) + FfiConverterOptionalULong.write(value.`claimableOnCloseSats`, buf) + } +} + +data class ChannelInfo( + var `nodeOne`: NodeId, + var `oneToTwo`: ChannelUpdateInfo?, + var `nodeTwo`: NodeId, + var `twoToOne`: ChannelUpdateInfo?, + var `capacitySats`: kotlin.ULong?, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeChannelInfo : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): ChannelInfo = + ChannelInfo( + FfiConverterTypeNodeId.read(buf), + FfiConverterOptionalTypeChannelUpdateInfo.read(buf), + FfiConverterTypeNodeId.read(buf), + FfiConverterOptionalTypeChannelUpdateInfo.read(buf), + FfiConverterOptionalULong.read(buf), + ) + + override fun allocationSize(value: ChannelInfo) = + ( + FfiConverterTypeNodeId.allocationSize(value.`nodeOne`) + + FfiConverterOptionalTypeChannelUpdateInfo.allocationSize(value.`oneToTwo`) + + FfiConverterTypeNodeId.allocationSize(value.`nodeTwo`) + + FfiConverterOptionalTypeChannelUpdateInfo.allocationSize(value.`twoToOne`) + + FfiConverterOptionalULong.allocationSize(value.`capacitySats`) + ) + + override fun write( + value: ChannelInfo, + buf: ByteBuffer, + ) { + FfiConverterTypeNodeId.write(value.`nodeOne`, buf) + FfiConverterOptionalTypeChannelUpdateInfo.write(value.`oneToTwo`, buf) + FfiConverterTypeNodeId.write(value.`nodeTwo`, buf) + FfiConverterOptionalTypeChannelUpdateInfo.write(value.`twoToOne`, buf) + FfiConverterOptionalULong.write(value.`capacitySats`, buf) + } +} + +data class ChannelUpdateInfo( + var `lastUpdate`: kotlin.UInt, + var `enabled`: kotlin.Boolean, + var `cltvExpiryDelta`: kotlin.UShort, + var `htlcMinimumMsat`: kotlin.ULong, + var `htlcMaximumMsat`: kotlin.ULong, + var `fees`: RoutingFees, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeChannelUpdateInfo : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): ChannelUpdateInfo = + ChannelUpdateInfo( + FfiConverterUInt.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterUShort.read(buf), + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterTypeRoutingFees.read(buf), + ) + + override fun allocationSize(value: ChannelUpdateInfo) = + ( + FfiConverterUInt.allocationSize(value.`lastUpdate`) + + FfiConverterBoolean.allocationSize(value.`enabled`) + + FfiConverterUShort.allocationSize(value.`cltvExpiryDelta`) + + FfiConverterULong.allocationSize(value.`htlcMinimumMsat`) + + FfiConverterULong.allocationSize(value.`htlcMaximumMsat`) + + FfiConverterTypeRoutingFees.allocationSize(value.`fees`) + ) + + override fun write( + value: ChannelUpdateInfo, + buf: ByteBuffer, + ) { + FfiConverterUInt.write(value.`lastUpdate`, buf) + FfiConverterBoolean.write(value.`enabled`, buf) + FfiConverterUShort.write(value.`cltvExpiryDelta`, buf) + FfiConverterULong.write(value.`htlcMinimumMsat`, buf) + FfiConverterULong.write(value.`htlcMaximumMsat`, buf) + FfiConverterTypeRoutingFees.write(value.`fees`, buf) + } +} + +data class Config( + var `storageDirPath`: kotlin.String, + var `network`: Network, + var `listeningAddresses`: List?, + var `announcementAddresses`: List?, + var `nodeAlias`: NodeAlias?, + var `trustedPeers0conf`: List, + var `probingLiquidityLimitMultiplier`: kotlin.ULong, + var `anchorChannelsConfig`: AnchorChannelsConfig?, + var `routeParameters`: RouteParametersConfig?, + var `includeUntrustedPendingInSpendable`: kotlin.Boolean, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeConfig : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): Config = + Config( + FfiConverterString.read(buf), + FfiConverterTypeNetwork.read(buf), + FfiConverterOptionalSequenceTypeSocketAddress.read(buf), + FfiConverterOptionalSequenceTypeSocketAddress.read(buf), + FfiConverterOptionalTypeNodeAlias.read(buf), + FfiConverterSequenceTypePublicKey.read(buf), + FfiConverterULong.read(buf), + FfiConverterOptionalTypeAnchorChannelsConfig.read(buf), + FfiConverterOptionalTypeRouteParametersConfig.read(buf), + FfiConverterBoolean.read(buf), + ) + + override fun allocationSize(value: Config) = + ( + FfiConverterString.allocationSize(value.`storageDirPath`) + + FfiConverterTypeNetwork.allocationSize(value.`network`) + + FfiConverterOptionalSequenceTypeSocketAddress.allocationSize(value.`listeningAddresses`) + + FfiConverterOptionalSequenceTypeSocketAddress.allocationSize(value.`announcementAddresses`) + + FfiConverterOptionalTypeNodeAlias.allocationSize(value.`nodeAlias`) + + FfiConverterSequenceTypePublicKey.allocationSize(value.`trustedPeers0conf`) + + FfiConverterULong.allocationSize(value.`probingLiquidityLimitMultiplier`) + + FfiConverterOptionalTypeAnchorChannelsConfig.allocationSize(value.`anchorChannelsConfig`) + + FfiConverterOptionalTypeRouteParametersConfig.allocationSize(value.`routeParameters`) + + FfiConverterBoolean.allocationSize(value.`includeUntrustedPendingInSpendable`) + ) + + override fun write( + value: Config, + buf: ByteBuffer, + ) { + FfiConverterString.write(value.`storageDirPath`, buf) + FfiConverterTypeNetwork.write(value.`network`, buf) + FfiConverterOptionalSequenceTypeSocketAddress.write(value.`listeningAddresses`, buf) + FfiConverterOptionalSequenceTypeSocketAddress.write(value.`announcementAddresses`, buf) + FfiConverterOptionalTypeNodeAlias.write(value.`nodeAlias`, buf) + FfiConverterSequenceTypePublicKey.write(value.`trustedPeers0conf`, buf) + FfiConverterULong.write(value.`probingLiquidityLimitMultiplier`, buf) + FfiConverterOptionalTypeAnchorChannelsConfig.write(value.`anchorChannelsConfig`, buf) + FfiConverterOptionalTypeRouteParametersConfig.write(value.`routeParameters`, buf) + FfiConverterBoolean.write(value.`includeUntrustedPendingInSpendable`, buf) + } +} + +data class CustomTlvRecord( + var `typeNum`: kotlin.ULong, + var `value`: List, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeCustomTlvRecord : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): CustomTlvRecord = + CustomTlvRecord( + FfiConverterULong.read(buf), + FfiConverterSequenceUByte.read(buf), + ) + + override fun allocationSize(value: CustomTlvRecord) = + ( + FfiConverterULong.allocationSize(value.`typeNum`) + + FfiConverterSequenceUByte.allocationSize(value.`value`) + ) + + override fun write( + value: CustomTlvRecord, + buf: ByteBuffer, + ) { + FfiConverterULong.write(value.`typeNum`, buf) + FfiConverterSequenceUByte.write(value.`value`, buf) + } +} + +data class ElectrumSyncConfig( + var `backgroundSyncConfig`: BackgroundSyncConfig?, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeElectrumSyncConfig : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): ElectrumSyncConfig = + ElectrumSyncConfig( + FfiConverterOptionalTypeBackgroundSyncConfig.read(buf), + ) + + override fun allocationSize(value: ElectrumSyncConfig) = + ( + FfiConverterOptionalTypeBackgroundSyncConfig.allocationSize(value.`backgroundSyncConfig`) + ) + + override fun write( + value: ElectrumSyncConfig, + buf: ByteBuffer, + ) { + FfiConverterOptionalTypeBackgroundSyncConfig.write(value.`backgroundSyncConfig`, buf) + } +} + +data class EsploraSyncConfig( + var `backgroundSyncConfig`: BackgroundSyncConfig?, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeEsploraSyncConfig : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): EsploraSyncConfig = + EsploraSyncConfig( + FfiConverterOptionalTypeBackgroundSyncConfig.read(buf), + ) + + override fun allocationSize(value: EsploraSyncConfig) = + ( + FfiConverterOptionalTypeBackgroundSyncConfig.allocationSize(value.`backgroundSyncConfig`) + ) + + override fun write( + value: EsploraSyncConfig, + buf: ByteBuffer, + ) { + FfiConverterOptionalTypeBackgroundSyncConfig.write(value.`backgroundSyncConfig`, buf) + } +} + +data class LspFeeLimits( + var `maxTotalOpeningFeeMsat`: kotlin.ULong?, + var `maxProportionalOpeningFeePpmMsat`: kotlin.ULong?, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeLSPFeeLimits : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): LspFeeLimits = + LspFeeLimits( + FfiConverterOptionalULong.read(buf), + FfiConverterOptionalULong.read(buf), + ) + + override fun allocationSize(value: LspFeeLimits) = + ( + FfiConverterOptionalULong.allocationSize(value.`maxTotalOpeningFeeMsat`) + + FfiConverterOptionalULong.allocationSize(value.`maxProportionalOpeningFeePpmMsat`) + ) + + override fun write( + value: LspFeeLimits, + buf: ByteBuffer, + ) { + FfiConverterOptionalULong.write(value.`maxTotalOpeningFeeMsat`, buf) + FfiConverterOptionalULong.write(value.`maxProportionalOpeningFeePpmMsat`, buf) + } +} + +data class Lsps1Bolt11PaymentInfo( + var `state`: Lsps1PaymentState, + var `expiresAt`: LspsDateTime, + var `feeTotalSat`: kotlin.ULong, + var `orderTotalSat`: kotlin.ULong, + var `invoice`: Bolt11Invoice, +) : Disposable { + @Suppress("UNNECESSARY_SAFE_CALL") // codegen is much simpler if we unconditionally emit safe calls here + override fun destroy() { + Disposable.destroy(this.`state`) + + Disposable.destroy(this.`expiresAt`) + + Disposable.destroy(this.`feeTotalSat`) + + Disposable.destroy(this.`orderTotalSat`) + + Disposable.destroy(this.`invoice`) + } + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeLSPS1Bolt11PaymentInfo : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): Lsps1Bolt11PaymentInfo = + Lsps1Bolt11PaymentInfo( + FfiConverterTypeLSPS1PaymentState.read(buf), + FfiConverterTypeLSPSDateTime.read(buf), + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterTypeBolt11Invoice.read(buf), + ) + + override fun allocationSize(value: Lsps1Bolt11PaymentInfo) = + ( + FfiConverterTypeLSPS1PaymentState.allocationSize(value.`state`) + + FfiConverterTypeLSPSDateTime.allocationSize(value.`expiresAt`) + + FfiConverterULong.allocationSize(value.`feeTotalSat`) + + FfiConverterULong.allocationSize(value.`orderTotalSat`) + + FfiConverterTypeBolt11Invoice.allocationSize(value.`invoice`) + ) + + override fun write( + value: Lsps1Bolt11PaymentInfo, + buf: ByteBuffer, + ) { + FfiConverterTypeLSPS1PaymentState.write(value.`state`, buf) + FfiConverterTypeLSPSDateTime.write(value.`expiresAt`, buf) + FfiConverterULong.write(value.`feeTotalSat`, buf) + FfiConverterULong.write(value.`orderTotalSat`, buf) + FfiConverterTypeBolt11Invoice.write(value.`invoice`, buf) + } +} + +data class Lsps1ChannelInfo( + var `fundedAt`: LspsDateTime, + var `fundingOutpoint`: OutPoint, + var `expiresAt`: LspsDateTime, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeLSPS1ChannelInfo : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): Lsps1ChannelInfo = + Lsps1ChannelInfo( + FfiConverterTypeLSPSDateTime.read(buf), + FfiConverterTypeOutPoint.read(buf), + FfiConverterTypeLSPSDateTime.read(buf), + ) + + override fun allocationSize(value: Lsps1ChannelInfo) = + ( + FfiConverterTypeLSPSDateTime.allocationSize(value.`fundedAt`) + + FfiConverterTypeOutPoint.allocationSize(value.`fundingOutpoint`) + + FfiConverterTypeLSPSDateTime.allocationSize(value.`expiresAt`) + ) + + override fun write( + value: Lsps1ChannelInfo, + buf: ByteBuffer, + ) { + FfiConverterTypeLSPSDateTime.write(value.`fundedAt`, buf) + FfiConverterTypeOutPoint.write(value.`fundingOutpoint`, buf) + FfiConverterTypeLSPSDateTime.write(value.`expiresAt`, buf) + } +} + +data class Lsps1OnchainPaymentInfo( + var `state`: Lsps1PaymentState, + var `expiresAt`: LspsDateTime, + var `feeTotalSat`: kotlin.ULong, + var `orderTotalSat`: kotlin.ULong, + var `address`: Address, + var `minOnchainPaymentConfirmations`: kotlin.UShort?, + var `minFeeFor0conf`: FeeRate, + var `refundOnchainAddress`: Address?, +) : Disposable { + @Suppress("UNNECESSARY_SAFE_CALL") // codegen is much simpler if we unconditionally emit safe calls here + override fun destroy() { + Disposable.destroy(this.`state`) + + Disposable.destroy(this.`expiresAt`) + + Disposable.destroy(this.`feeTotalSat`) + + Disposable.destroy(this.`orderTotalSat`) + + Disposable.destroy(this.`address`) + + Disposable.destroy(this.`minOnchainPaymentConfirmations`) + + Disposable.destroy(this.`minFeeFor0conf`) + + Disposable.destroy(this.`refundOnchainAddress`) + } + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeLSPS1OnchainPaymentInfo : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): Lsps1OnchainPaymentInfo = + Lsps1OnchainPaymentInfo( + FfiConverterTypeLSPS1PaymentState.read(buf), + FfiConverterTypeLSPSDateTime.read(buf), + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterTypeAddress.read(buf), + FfiConverterOptionalUShort.read(buf), + FfiConverterTypeFeeRate.read(buf), + FfiConverterOptionalTypeAddress.read(buf), + ) + + override fun allocationSize(value: Lsps1OnchainPaymentInfo) = + ( + FfiConverterTypeLSPS1PaymentState.allocationSize(value.`state`) + + FfiConverterTypeLSPSDateTime.allocationSize(value.`expiresAt`) + + FfiConverterULong.allocationSize(value.`feeTotalSat`) + + FfiConverterULong.allocationSize(value.`orderTotalSat`) + + FfiConverterTypeAddress.allocationSize(value.`address`) + + FfiConverterOptionalUShort.allocationSize(value.`minOnchainPaymentConfirmations`) + + FfiConverterTypeFeeRate.allocationSize(value.`minFeeFor0conf`) + + FfiConverterOptionalTypeAddress.allocationSize(value.`refundOnchainAddress`) + ) + + override fun write( + value: Lsps1OnchainPaymentInfo, + buf: ByteBuffer, + ) { + FfiConverterTypeLSPS1PaymentState.write(value.`state`, buf) + FfiConverterTypeLSPSDateTime.write(value.`expiresAt`, buf) + FfiConverterULong.write(value.`feeTotalSat`, buf) + FfiConverterULong.write(value.`orderTotalSat`, buf) + FfiConverterTypeAddress.write(value.`address`, buf) + FfiConverterOptionalUShort.write(value.`minOnchainPaymentConfirmations`, buf) + FfiConverterTypeFeeRate.write(value.`minFeeFor0conf`, buf) + FfiConverterOptionalTypeAddress.write(value.`refundOnchainAddress`, buf) + } +} + +data class Lsps1OrderParams( + var `lspBalanceSat`: kotlin.ULong, + var `clientBalanceSat`: kotlin.ULong, + var `requiredChannelConfirmations`: kotlin.UShort, + var `fundingConfirmsWithinBlocks`: kotlin.UShort, + var `channelExpiryBlocks`: kotlin.UInt, + var `token`: kotlin.String?, + var `announceChannel`: kotlin.Boolean, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeLSPS1OrderParams : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): Lsps1OrderParams = + Lsps1OrderParams( + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterUShort.read(buf), + FfiConverterUShort.read(buf), + FfiConverterUInt.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterBoolean.read(buf), + ) + + override fun allocationSize(value: Lsps1OrderParams) = + ( + FfiConverterULong.allocationSize(value.`lspBalanceSat`) + + FfiConverterULong.allocationSize(value.`clientBalanceSat`) + + FfiConverterUShort.allocationSize(value.`requiredChannelConfirmations`) + + FfiConverterUShort.allocationSize(value.`fundingConfirmsWithinBlocks`) + + FfiConverterUInt.allocationSize(value.`channelExpiryBlocks`) + + FfiConverterOptionalString.allocationSize(value.`token`) + + FfiConverterBoolean.allocationSize(value.`announceChannel`) + ) + + override fun write( + value: Lsps1OrderParams, + buf: ByteBuffer, + ) { + FfiConverterULong.write(value.`lspBalanceSat`, buf) + FfiConverterULong.write(value.`clientBalanceSat`, buf) + FfiConverterUShort.write(value.`requiredChannelConfirmations`, buf) + FfiConverterUShort.write(value.`fundingConfirmsWithinBlocks`, buf) + FfiConverterUInt.write(value.`channelExpiryBlocks`, buf) + FfiConverterOptionalString.write(value.`token`, buf) + FfiConverterBoolean.write(value.`announceChannel`, buf) + } +} + +data class Lsps1OrderStatus( + var `orderId`: Lsps1OrderId, + var `orderParams`: Lsps1OrderParams, + var `paymentOptions`: Lsps1PaymentInfo, + var `channelState`: Lsps1ChannelInfo?, +) : Disposable { + @Suppress("UNNECESSARY_SAFE_CALL") // codegen is much simpler if we unconditionally emit safe calls here + override fun destroy() { + Disposable.destroy(this.`orderId`) + + Disposable.destroy(this.`orderParams`) + + Disposable.destroy(this.`paymentOptions`) + + Disposable.destroy(this.`channelState`) + } + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeLSPS1OrderStatus : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): Lsps1OrderStatus = + Lsps1OrderStatus( + FfiConverterTypeLSPS1OrderId.read(buf), + FfiConverterTypeLSPS1OrderParams.read(buf), + FfiConverterTypeLSPS1PaymentInfo.read(buf), + FfiConverterOptionalTypeLSPS1ChannelInfo.read(buf), + ) + + override fun allocationSize(value: Lsps1OrderStatus) = + ( + FfiConverterTypeLSPS1OrderId.allocationSize(value.`orderId`) + + FfiConverterTypeLSPS1OrderParams.allocationSize(value.`orderParams`) + + FfiConverterTypeLSPS1PaymentInfo.allocationSize(value.`paymentOptions`) + + FfiConverterOptionalTypeLSPS1ChannelInfo.allocationSize(value.`channelState`) + ) + + override fun write( + value: Lsps1OrderStatus, + buf: ByteBuffer, + ) { + FfiConverterTypeLSPS1OrderId.write(value.`orderId`, buf) + FfiConverterTypeLSPS1OrderParams.write(value.`orderParams`, buf) + FfiConverterTypeLSPS1PaymentInfo.write(value.`paymentOptions`, buf) + FfiConverterOptionalTypeLSPS1ChannelInfo.write(value.`channelState`, buf) + } +} + +data class Lsps1PaymentInfo( + var `bolt11`: Lsps1Bolt11PaymentInfo?, + var `onchain`: Lsps1OnchainPaymentInfo?, +) : Disposable { + @Suppress("UNNECESSARY_SAFE_CALL") // codegen is much simpler if we unconditionally emit safe calls here + override fun destroy() { + Disposable.destroy(this.`bolt11`) + + Disposable.destroy(this.`onchain`) + } + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeLSPS1PaymentInfo : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): Lsps1PaymentInfo = + Lsps1PaymentInfo( + FfiConverterOptionalTypeLSPS1Bolt11PaymentInfo.read(buf), + FfiConverterOptionalTypeLSPS1OnchainPaymentInfo.read(buf), + ) + + override fun allocationSize(value: Lsps1PaymentInfo) = + ( + FfiConverterOptionalTypeLSPS1Bolt11PaymentInfo.allocationSize(value.`bolt11`) + + FfiConverterOptionalTypeLSPS1OnchainPaymentInfo.allocationSize(value.`onchain`) + ) + + override fun write( + value: Lsps1PaymentInfo, + buf: ByteBuffer, + ) { + FfiConverterOptionalTypeLSPS1Bolt11PaymentInfo.write(value.`bolt11`, buf) + FfiConverterOptionalTypeLSPS1OnchainPaymentInfo.write(value.`onchain`, buf) + } +} + +data class Lsps2ServiceConfig( + var `requireToken`: kotlin.String?, + var `advertiseService`: kotlin.Boolean, + var `channelOpeningFeePpm`: kotlin.UInt, + var `channelOverProvisioningPpm`: kotlin.UInt, + var `minChannelOpeningFeeMsat`: kotlin.ULong, + var `minChannelLifetime`: kotlin.UInt, + var `maxClientToSelfDelay`: kotlin.UInt, + var `minPaymentSizeMsat`: kotlin.ULong, + var `maxPaymentSizeMsat`: kotlin.ULong, + var `clientTrustsLsp`: kotlin.Boolean, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeLSPS2ServiceConfig : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): Lsps2ServiceConfig = + Lsps2ServiceConfig( + FfiConverterOptionalString.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterUInt.read(buf), + FfiConverterUInt.read(buf), + FfiConverterULong.read(buf), + FfiConverterUInt.read(buf), + FfiConverterUInt.read(buf), + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterBoolean.read(buf), + ) + + override fun allocationSize(value: Lsps2ServiceConfig) = + ( + FfiConverterOptionalString.allocationSize(value.`requireToken`) + + FfiConverterBoolean.allocationSize(value.`advertiseService`) + + FfiConverterUInt.allocationSize(value.`channelOpeningFeePpm`) + + FfiConverterUInt.allocationSize(value.`channelOverProvisioningPpm`) + + FfiConverterULong.allocationSize(value.`minChannelOpeningFeeMsat`) + + FfiConverterUInt.allocationSize(value.`minChannelLifetime`) + + FfiConverterUInt.allocationSize(value.`maxClientToSelfDelay`) + + FfiConverterULong.allocationSize(value.`minPaymentSizeMsat`) + + FfiConverterULong.allocationSize(value.`maxPaymentSizeMsat`) + + FfiConverterBoolean.allocationSize(value.`clientTrustsLsp`) + ) + + override fun write( + value: Lsps2ServiceConfig, + buf: ByteBuffer, + ) { + FfiConverterOptionalString.write(value.`requireToken`, buf) + FfiConverterBoolean.write(value.`advertiseService`, buf) + FfiConverterUInt.write(value.`channelOpeningFeePpm`, buf) + FfiConverterUInt.write(value.`channelOverProvisioningPpm`, buf) + FfiConverterULong.write(value.`minChannelOpeningFeeMsat`, buf) + FfiConverterUInt.write(value.`minChannelLifetime`, buf) + FfiConverterUInt.write(value.`maxClientToSelfDelay`, buf) + FfiConverterULong.write(value.`minPaymentSizeMsat`, buf) + FfiConverterULong.write(value.`maxPaymentSizeMsat`, buf) + FfiConverterBoolean.write(value.`clientTrustsLsp`, buf) + } +} + +data class LogRecord( + var `level`: LogLevel, + var `args`: kotlin.String, + var `modulePath`: kotlin.String, + var `line`: kotlin.UInt, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeLogRecord : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): LogRecord = + LogRecord( + FfiConverterTypeLogLevel.read(buf), + FfiConverterString.read(buf), + FfiConverterString.read(buf), + FfiConverterUInt.read(buf), + ) + + override fun allocationSize(value: LogRecord) = + ( + FfiConverterTypeLogLevel.allocationSize(value.`level`) + + FfiConverterString.allocationSize(value.`args`) + + FfiConverterString.allocationSize(value.`modulePath`) + + FfiConverterUInt.allocationSize(value.`line`) + ) + + override fun write( + value: LogRecord, + buf: ByteBuffer, + ) { + FfiConverterTypeLogLevel.write(value.`level`, buf) + FfiConverterString.write(value.`args`, buf) + FfiConverterString.write(value.`modulePath`, buf) + FfiConverterUInt.write(value.`line`, buf) + } +} + +data class NodeAnnouncementInfo( + var `lastUpdate`: kotlin.UInt, + var `alias`: kotlin.String, + var `addresses`: List, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeNodeAnnouncementInfo : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): NodeAnnouncementInfo = + NodeAnnouncementInfo( + FfiConverterUInt.read(buf), + FfiConverterString.read(buf), + FfiConverterSequenceTypeSocketAddress.read(buf), + ) + + override fun allocationSize(value: NodeAnnouncementInfo) = + ( + FfiConverterUInt.allocationSize(value.`lastUpdate`) + + FfiConverterString.allocationSize(value.`alias`) + + FfiConverterSequenceTypeSocketAddress.allocationSize(value.`addresses`) + ) + + override fun write( + value: NodeAnnouncementInfo, + buf: ByteBuffer, + ) { + FfiConverterUInt.write(value.`lastUpdate`, buf) + FfiConverterString.write(value.`alias`, buf) + FfiConverterSequenceTypeSocketAddress.write(value.`addresses`, buf) + } +} + +data class NodeInfo( + var `channels`: List, + var `announcementInfo`: NodeAnnouncementInfo?, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeNodeInfo : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): NodeInfo = + NodeInfo( + FfiConverterSequenceULong.read(buf), + FfiConverterOptionalTypeNodeAnnouncementInfo.read(buf), + ) + + override fun allocationSize(value: NodeInfo) = + ( + FfiConverterSequenceULong.allocationSize(value.`channels`) + + FfiConverterOptionalTypeNodeAnnouncementInfo.allocationSize(value.`announcementInfo`) + ) + + override fun write( + value: NodeInfo, + buf: ByteBuffer, + ) { + FfiConverterSequenceULong.write(value.`channels`, buf) + FfiConverterOptionalTypeNodeAnnouncementInfo.write(value.`announcementInfo`, buf) + } +} + +data class NodeStatus( + var `isRunning`: kotlin.Boolean, + var `currentBestBlock`: BestBlock, + var `latestLightningWalletSyncTimestamp`: kotlin.ULong?, + var `latestOnchainWalletSyncTimestamp`: kotlin.ULong?, + var `latestFeeRateCacheUpdateTimestamp`: kotlin.ULong?, + var `latestRgsSnapshotTimestamp`: kotlin.ULong?, + var `latestPathfindingScoresSyncTimestamp`: kotlin.ULong?, + var `latestNodeAnnouncementBroadcastTimestamp`: kotlin.ULong?, + var `latestChannelMonitorArchivalHeight`: kotlin.UInt?, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeNodeStatus : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): NodeStatus = + NodeStatus( + FfiConverterBoolean.read(buf), + FfiConverterTypeBestBlock.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterOptionalUInt.read(buf), + ) + + override fun allocationSize(value: NodeStatus) = + ( + FfiConverterBoolean.allocationSize(value.`isRunning`) + + FfiConverterTypeBestBlock.allocationSize(value.`currentBestBlock`) + + FfiConverterOptionalULong.allocationSize(value.`latestLightningWalletSyncTimestamp`) + + FfiConverterOptionalULong.allocationSize(value.`latestOnchainWalletSyncTimestamp`) + + FfiConverterOptionalULong.allocationSize(value.`latestFeeRateCacheUpdateTimestamp`) + + FfiConverterOptionalULong.allocationSize(value.`latestRgsSnapshotTimestamp`) + + FfiConverterOptionalULong.allocationSize(value.`latestPathfindingScoresSyncTimestamp`) + + FfiConverterOptionalULong.allocationSize(value.`latestNodeAnnouncementBroadcastTimestamp`) + + FfiConverterOptionalUInt.allocationSize(value.`latestChannelMonitorArchivalHeight`) + ) + + override fun write( + value: NodeStatus, + buf: ByteBuffer, + ) { + FfiConverterBoolean.write(value.`isRunning`, buf) + FfiConverterTypeBestBlock.write(value.`currentBestBlock`, buf) + FfiConverterOptionalULong.write(value.`latestLightningWalletSyncTimestamp`, buf) + FfiConverterOptionalULong.write(value.`latestOnchainWalletSyncTimestamp`, buf) + FfiConverterOptionalULong.write(value.`latestFeeRateCacheUpdateTimestamp`, buf) + FfiConverterOptionalULong.write(value.`latestRgsSnapshotTimestamp`, buf) + FfiConverterOptionalULong.write(value.`latestPathfindingScoresSyncTimestamp`, buf) + FfiConverterOptionalULong.write(value.`latestNodeAnnouncementBroadcastTimestamp`, buf) + FfiConverterOptionalUInt.write(value.`latestChannelMonitorArchivalHeight`, buf) + } +} + +data class OutPoint( + var `txid`: Txid, + var `vout`: kotlin.UInt, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeOutPoint : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): OutPoint = + OutPoint( + FfiConverterTypeTxid.read(buf), + FfiConverterUInt.read(buf), + ) + + override fun allocationSize(value: OutPoint) = + ( + FfiConverterTypeTxid.allocationSize(value.`txid`) + + FfiConverterUInt.allocationSize(value.`vout`) + ) + + override fun write( + value: OutPoint, + buf: ByteBuffer, + ) { + FfiConverterTypeTxid.write(value.`txid`, buf) + FfiConverterUInt.write(value.`vout`, buf) + } +} + +data class PaymentDetails( + var `id`: PaymentId, + var `kind`: PaymentKind, + var `amountMsat`: kotlin.ULong?, + var `feePaidMsat`: kotlin.ULong?, + var `direction`: PaymentDirection, + var `status`: PaymentStatus, + var `latestUpdateTimestamp`: kotlin.ULong, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypePaymentDetails : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): PaymentDetails = + PaymentDetails( + FfiConverterTypePaymentId.read(buf), + FfiConverterTypePaymentKind.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterTypePaymentDirection.read(buf), + FfiConverterTypePaymentStatus.read(buf), + FfiConverterULong.read(buf), + ) + + override fun allocationSize(value: PaymentDetails) = + ( + FfiConverterTypePaymentId.allocationSize(value.`id`) + + FfiConverterTypePaymentKind.allocationSize(value.`kind`) + + FfiConverterOptionalULong.allocationSize(value.`amountMsat`) + + FfiConverterOptionalULong.allocationSize(value.`feePaidMsat`) + + FfiConverterTypePaymentDirection.allocationSize(value.`direction`) + + FfiConverterTypePaymentStatus.allocationSize(value.`status`) + + FfiConverterULong.allocationSize(value.`latestUpdateTimestamp`) + ) + + override fun write( + value: PaymentDetails, + buf: ByteBuffer, + ) { + FfiConverterTypePaymentId.write(value.`id`, buf) + FfiConverterTypePaymentKind.write(value.`kind`, buf) + FfiConverterOptionalULong.write(value.`amountMsat`, buf) + FfiConverterOptionalULong.write(value.`feePaidMsat`, buf) + FfiConverterTypePaymentDirection.write(value.`direction`, buf) + FfiConverterTypePaymentStatus.write(value.`status`, buf) + FfiConverterULong.write(value.`latestUpdateTimestamp`, buf) + } +} + +data class PeerDetails( + var `nodeId`: PublicKey, + var `address`: SocketAddress, + var `isPersisted`: kotlin.Boolean, + var `isConnected`: kotlin.Boolean, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypePeerDetails : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): PeerDetails = + PeerDetails( + FfiConverterTypePublicKey.read(buf), + FfiConverterTypeSocketAddress.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterBoolean.read(buf), + ) + + override fun allocationSize(value: PeerDetails) = + ( + FfiConverterTypePublicKey.allocationSize(value.`nodeId`) + + FfiConverterTypeSocketAddress.allocationSize(value.`address`) + + FfiConverterBoolean.allocationSize(value.`isPersisted`) + + FfiConverterBoolean.allocationSize(value.`isConnected`) + ) + + override fun write( + value: PeerDetails, + buf: ByteBuffer, + ) { + FfiConverterTypePublicKey.write(value.`nodeId`, buf) + FfiConverterTypeSocketAddress.write(value.`address`, buf) + FfiConverterBoolean.write(value.`isPersisted`, buf) + FfiConverterBoolean.write(value.`isConnected`, buf) + } +} + +data class RouteHintHop( + var `srcNodeId`: PublicKey, + var `shortChannelId`: kotlin.ULong, + var `cltvExpiryDelta`: kotlin.UShort, + var `htlcMinimumMsat`: kotlin.ULong?, + var `htlcMaximumMsat`: kotlin.ULong?, + var `fees`: RoutingFees, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeRouteHintHop : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RouteHintHop = + RouteHintHop( + FfiConverterTypePublicKey.read(buf), + FfiConverterULong.read(buf), + FfiConverterUShort.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterTypeRoutingFees.read(buf), + ) + + override fun allocationSize(value: RouteHintHop) = + ( + FfiConverterTypePublicKey.allocationSize(value.`srcNodeId`) + + FfiConverterULong.allocationSize(value.`shortChannelId`) + + FfiConverterUShort.allocationSize(value.`cltvExpiryDelta`) + + FfiConverterOptionalULong.allocationSize(value.`htlcMinimumMsat`) + + FfiConverterOptionalULong.allocationSize(value.`htlcMaximumMsat`) + + FfiConverterTypeRoutingFees.allocationSize(value.`fees`) + ) + + override fun write( + value: RouteHintHop, + buf: ByteBuffer, + ) { + FfiConverterTypePublicKey.write(value.`srcNodeId`, buf) + FfiConverterULong.write(value.`shortChannelId`, buf) + FfiConverterUShort.write(value.`cltvExpiryDelta`, buf) + FfiConverterOptionalULong.write(value.`htlcMinimumMsat`, buf) + FfiConverterOptionalULong.write(value.`htlcMaximumMsat`, buf) + FfiConverterTypeRoutingFees.write(value.`fees`, buf) + } +} + +data class RouteParametersConfig( + var `maxTotalRoutingFeeMsat`: kotlin.ULong?, + var `maxTotalCltvExpiryDelta`: kotlin.UInt, + var `maxPathCount`: kotlin.UByte, + var `maxChannelSaturationPowerOfHalf`: kotlin.UByte, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeRouteParametersConfig : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RouteParametersConfig = + RouteParametersConfig( + FfiConverterOptionalULong.read(buf), + FfiConverterUInt.read(buf), + FfiConverterUByte.read(buf), + FfiConverterUByte.read(buf), + ) + + override fun allocationSize(value: RouteParametersConfig) = + ( + FfiConverterOptionalULong.allocationSize(value.`maxTotalRoutingFeeMsat`) + + FfiConverterUInt.allocationSize(value.`maxTotalCltvExpiryDelta`) + + FfiConverterUByte.allocationSize(value.`maxPathCount`) + + FfiConverterUByte.allocationSize(value.`maxChannelSaturationPowerOfHalf`) + ) + + override fun write( + value: RouteParametersConfig, + buf: ByteBuffer, + ) { + FfiConverterOptionalULong.write(value.`maxTotalRoutingFeeMsat`, buf) + FfiConverterUInt.write(value.`maxTotalCltvExpiryDelta`, buf) + FfiConverterUByte.write(value.`maxPathCount`, buf) + FfiConverterUByte.write(value.`maxChannelSaturationPowerOfHalf`, buf) + } +} + +data class RoutingFees( + var `baseMsat`: kotlin.UInt, + var `proportionalMillionths`: kotlin.UInt, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeRoutingFees : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RoutingFees = + RoutingFees( + FfiConverterUInt.read(buf), + FfiConverterUInt.read(buf), + ) + + override fun allocationSize(value: RoutingFees) = + ( + FfiConverterUInt.allocationSize(value.`baseMsat`) + + FfiConverterUInt.allocationSize(value.`proportionalMillionths`) + ) + + override fun write( + value: RoutingFees, + buf: ByteBuffer, + ) { + FfiConverterUInt.write(value.`baseMsat`, buf) + FfiConverterUInt.write(value.`proportionalMillionths`, buf) + } +} + +data class RuntimeSyncIntervals( + var `onchainWalletSyncIntervalSecs`: kotlin.ULong, + var `lightningWalletSyncIntervalSecs`: kotlin.ULong, + var `feeRateCacheUpdateIntervalSecs`: kotlin.ULong, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeRuntimeSyncIntervals : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RuntimeSyncIntervals = + RuntimeSyncIntervals( + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + ) + + override fun allocationSize(value: RuntimeSyncIntervals) = + ( + FfiConverterULong.allocationSize(value.`onchainWalletSyncIntervalSecs`) + + FfiConverterULong.allocationSize(value.`lightningWalletSyncIntervalSecs`) + + FfiConverterULong.allocationSize(value.`feeRateCacheUpdateIntervalSecs`) + ) + + override fun write( + value: RuntimeSyncIntervals, + buf: ByteBuffer, + ) { + FfiConverterULong.write(value.`onchainWalletSyncIntervalSecs`, buf) + FfiConverterULong.write(value.`lightningWalletSyncIntervalSecs`, buf) + FfiConverterULong.write(value.`feeRateCacheUpdateIntervalSecs`, buf) + } +} + +data class SpendableUtxo( + var `outpoint`: OutPoint, + var `valueSats`: kotlin.ULong, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeSpendableUtxo : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): SpendableUtxo = + SpendableUtxo( + FfiConverterTypeOutPoint.read(buf), + FfiConverterULong.read(buf), + ) + + override fun allocationSize(value: SpendableUtxo) = + ( + FfiConverterTypeOutPoint.allocationSize(value.`outpoint`) + + FfiConverterULong.allocationSize(value.`valueSats`) + ) + + override fun write( + value: SpendableUtxo, + buf: ByteBuffer, + ) { + FfiConverterTypeOutPoint.write(value.`outpoint`, buf) + FfiConverterULong.write(value.`valueSats`, buf) + } +} + +data class TransactionDetails( + var `amountSats`: kotlin.Long, + var `inputs`: List, + var `outputs`: List, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeTransactionDetails : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): TransactionDetails = + TransactionDetails( + FfiConverterLong.read(buf), + FfiConverterSequenceTypeTxInput.read(buf), + FfiConverterSequenceTypeTxOutput.read(buf), + ) + + override fun allocationSize(value: TransactionDetails) = + ( + FfiConverterLong.allocationSize(value.`amountSats`) + + FfiConverterSequenceTypeTxInput.allocationSize(value.`inputs`) + + FfiConverterSequenceTypeTxOutput.allocationSize(value.`outputs`) + ) + + override fun write( + value: TransactionDetails, + buf: ByteBuffer, + ) { + FfiConverterLong.write(value.`amountSats`, buf) + FfiConverterSequenceTypeTxInput.write(value.`inputs`, buf) + FfiConverterSequenceTypeTxOutput.write(value.`outputs`, buf) + } +} + +data class TxInput( + var `txid`: Txid, + var `vout`: kotlin.UInt, + var `scriptsig`: kotlin.String, + var `witness`: List, + var `sequence`: kotlin.UInt, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeTxInput : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): TxInput = + TxInput( + FfiConverterTypeTxid.read(buf), + FfiConverterUInt.read(buf), + FfiConverterString.read(buf), + FfiConverterSequenceString.read(buf), + FfiConverterUInt.read(buf), + ) + + override fun allocationSize(value: TxInput) = + ( + FfiConverterTypeTxid.allocationSize(value.`txid`) + + FfiConverterUInt.allocationSize(value.`vout`) + + FfiConverterString.allocationSize(value.`scriptsig`) + + FfiConverterSequenceString.allocationSize(value.`witness`) + + FfiConverterUInt.allocationSize(value.`sequence`) + ) + + override fun write( + value: TxInput, + buf: ByteBuffer, + ) { + FfiConverterTypeTxid.write(value.`txid`, buf) + FfiConverterUInt.write(value.`vout`, buf) + FfiConverterString.write(value.`scriptsig`, buf) + FfiConverterSequenceString.write(value.`witness`, buf) + FfiConverterUInt.write(value.`sequence`, buf) + } +} + +data class TxOutput( + var `scriptpubkey`: kotlin.String, + var `scriptpubkeyType`: kotlin.String?, + var `scriptpubkeyAddress`: kotlin.String?, + var `value`: kotlin.Long, + var `n`: kotlin.UInt, +) { + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeTxOutput : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): TxOutput = + TxOutput( + FfiConverterString.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterLong.read(buf), + FfiConverterUInt.read(buf), + ) + + override fun allocationSize(value: TxOutput) = + ( + FfiConverterString.allocationSize(value.`scriptpubkey`) + + FfiConverterOptionalString.allocationSize(value.`scriptpubkeyType`) + + FfiConverterOptionalString.allocationSize(value.`scriptpubkeyAddress`) + + FfiConverterLong.allocationSize(value.`value`) + + FfiConverterUInt.allocationSize(value.`n`) + ) + + override fun write( + value: TxOutput, + buf: ByteBuffer, + ) { + FfiConverterString.write(value.`scriptpubkey`, buf) + FfiConverterOptionalString.write(value.`scriptpubkeyType`, buf) + FfiConverterOptionalString.write(value.`scriptpubkeyAddress`, buf) + FfiConverterLong.write(value.`value`, buf) + FfiConverterUInt.write(value.`n`, buf) + } +} + +enum class AsyncPaymentsRole { + CLIENT, + SERVER, + ; + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeAsyncPaymentsRole : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer) = + try { + AsyncPaymentsRole.values()[buf.getInt() - 1] + } catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + + override fun allocationSize(value: AsyncPaymentsRole) = 4UL + + override fun write( + value: AsyncPaymentsRole, + buf: ByteBuffer, + ) { + buf.putInt(value.ordinal + 1) + } +} + +enum class BalanceSource { + HOLDER_FORCE_CLOSED, + COUNTERPARTY_FORCE_CLOSED, + COOP_CLOSE, + HTLC, + ; + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeBalanceSource : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer) = + try { + BalanceSource.values()[buf.getInt() - 1] + } catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + + override fun allocationSize(value: BalanceSource) = 4UL + + override fun write( + value: BalanceSource, + buf: ByteBuffer, + ) { + buf.putInt(value.ordinal + 1) + } +} + +sealed class Bolt11InvoiceDescription { + data class Hash( + val `hash`: kotlin.String, + ) : Bolt11InvoiceDescription() { + companion object + } + + data class Direct( + val `description`: kotlin.String, + ) : Bolt11InvoiceDescription() { + companion object + } + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeBolt11InvoiceDescription : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): Bolt11InvoiceDescription = + when (buf.getInt()) { + 1 -> { + Bolt11InvoiceDescription.Hash( + FfiConverterString.read(buf), + ) + } + + 2 -> { + Bolt11InvoiceDescription.Direct( + FfiConverterString.read(buf), + ) + } + + else -> { + throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: Bolt11InvoiceDescription) = + when (value) { + is Bolt11InvoiceDescription.Hash -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterString.allocationSize(value.`hash`) + ) + } + + is Bolt11InvoiceDescription.Direct -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterString.allocationSize(value.`description`) + ) + } + } + + override fun write( + value: Bolt11InvoiceDescription, + buf: ByteBuffer, + ) { + when (value) { + is Bolt11InvoiceDescription.Hash -> { + buf.putInt(1) + FfiConverterString.write(value.`hash`, buf) + Unit + } + + is Bolt11InvoiceDescription.Direct -> { + buf.putInt(2) + FfiConverterString.write(value.`description`, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +sealed class BuildException( + message: String, +) : kotlin.Exception(message) { + class InvalidSeedBytes( + message: String, + ) : BuildException(message) + + class InvalidSeedFile( + message: String, + ) : BuildException(message) + + class InvalidSystemTime( + message: String, + ) : BuildException(message) + + class InvalidChannelMonitor( + message: String, + ) : BuildException(message) + + class InvalidListeningAddresses( + message: String, + ) : BuildException(message) + + class InvalidAnnouncementAddresses( + message: String, + ) : BuildException(message) + + class InvalidNodeAlias( + message: String, + ) : BuildException(message) + + class RuntimeSetupFailed( + message: String, + ) : BuildException(message) + + class ReadFailed( + message: String, + ) : BuildException(message) + + class WriteFailed( + message: String, + ) : BuildException(message) + + class StoragePathAccessFailed( + message: String, + ) : BuildException(message) + + class KvStoreSetupFailed( + message: String, + ) : BuildException(message) + + class WalletSetupFailed( + message: String, + ) : BuildException(message) + + class LoggerSetupFailed( + message: String, + ) : BuildException(message) + + class NetworkMismatch( + message: String, + ) : BuildException(message) + + class AsyncPaymentsConfigMismatch( + message: String, + ) : BuildException(message) + + companion object ErrorHandler : UniffiRustCallStatusErrorHandler { + override fun lift(error_buf: RustBuffer.ByValue): BuildException = FfiConverterTypeBuildError.lift(error_buf) + } +} + +/** + * @suppress + */ +public object FfiConverterTypeBuildError : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): BuildException = + when (buf.getInt()) { + 1 -> BuildException.InvalidSeedBytes(FfiConverterString.read(buf)) + 2 -> BuildException.InvalidSeedFile(FfiConverterString.read(buf)) + 3 -> BuildException.InvalidSystemTime(FfiConverterString.read(buf)) + 4 -> BuildException.InvalidChannelMonitor(FfiConverterString.read(buf)) + 5 -> BuildException.InvalidListeningAddresses(FfiConverterString.read(buf)) + 6 -> BuildException.InvalidAnnouncementAddresses(FfiConverterString.read(buf)) + 7 -> BuildException.InvalidNodeAlias(FfiConverterString.read(buf)) + 8 -> BuildException.RuntimeSetupFailed(FfiConverterString.read(buf)) + 9 -> BuildException.ReadFailed(FfiConverterString.read(buf)) + 10 -> BuildException.WriteFailed(FfiConverterString.read(buf)) + 11 -> BuildException.StoragePathAccessFailed(FfiConverterString.read(buf)) + 12 -> BuildException.KvStoreSetupFailed(FfiConverterString.read(buf)) + 13 -> BuildException.WalletSetupFailed(FfiConverterString.read(buf)) + 14 -> BuildException.LoggerSetupFailed(FfiConverterString.read(buf)) + 15 -> BuildException.NetworkMismatch(FfiConverterString.read(buf)) + 16 -> BuildException.AsyncPaymentsConfigMismatch(FfiConverterString.read(buf)) + else -> throw RuntimeException("invalid error enum value, something is very wrong!!") + } + + override fun allocationSize(value: BuildException): ULong = 4UL + + override fun write( + value: BuildException, + buf: ByteBuffer, + ) { + when (value) { + is BuildException.InvalidSeedBytes -> { + buf.putInt(1) + Unit + } + + is BuildException.InvalidSeedFile -> { + buf.putInt(2) + Unit + } + + is BuildException.InvalidSystemTime -> { + buf.putInt(3) + Unit + } + + is BuildException.InvalidChannelMonitor -> { + buf.putInt(4) + Unit + } + + is BuildException.InvalidListeningAddresses -> { + buf.putInt(5) + Unit + } + + is BuildException.InvalidAnnouncementAddresses -> { + buf.putInt(6) + Unit + } + + is BuildException.InvalidNodeAlias -> { + buf.putInt(7) + Unit + } + + is BuildException.RuntimeSetupFailed -> { + buf.putInt(8) + Unit + } + + is BuildException.ReadFailed -> { + buf.putInt(9) + Unit + } + + is BuildException.WriteFailed -> { + buf.putInt(10) + Unit + } + + is BuildException.StoragePathAccessFailed -> { + buf.putInt(11) + Unit + } + + is BuildException.KvStoreSetupFailed -> { + buf.putInt(12) + Unit + } + + is BuildException.WalletSetupFailed -> { + buf.putInt(13) + Unit + } + + is BuildException.LoggerSetupFailed -> { + buf.putInt(14) + Unit + } + + is BuildException.NetworkMismatch -> { + buf.putInt(15) + Unit + } + + is BuildException.AsyncPaymentsConfigMismatch -> { + buf.putInt(16) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +sealed class ClosureReason { + data class CounterpartyForceClosed( + val `peerMsg`: UntrustedString, + ) : ClosureReason() { + companion object + } + + data class HolderForceClosed( + val `broadcastedLatestTxn`: kotlin.Boolean?, + val `message`: kotlin.String, + ) : ClosureReason() { + companion object + } + + object LegacyCooperativeClosure : ClosureReason() + + object CounterpartyInitiatedCooperativeClosure : ClosureReason() + + object LocallyInitiatedCooperativeClosure : ClosureReason() + + object CommitmentTxConfirmed : ClosureReason() + + object FundingTimedOut : ClosureReason() + + data class ProcessingError( + val `err`: kotlin.String, + ) : ClosureReason() { + companion object + } + + object DisconnectedPeer : ClosureReason() + + object OutdatedChannelManager : ClosureReason() + + object CounterpartyCoopClosedUnfundedChannel : ClosureReason() + + object LocallyCoopClosedUnfundedChannel : ClosureReason() + + object FundingBatchClosure : ClosureReason() + + data class HtlCsTimedOut( + val `paymentHash`: PaymentHash?, + ) : ClosureReason() { + companion object + } + + data class PeerFeerateTooLow( + val `peerFeerateSatPerKw`: kotlin.UInt, + val `requiredFeerateSatPerKw`: kotlin.UInt, + ) : ClosureReason() { + companion object + } + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeClosureReason : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): ClosureReason = + when (buf.getInt()) { + 1 -> { + ClosureReason.CounterpartyForceClosed( + FfiConverterTypeUntrustedString.read(buf), + ) + } + + 2 -> { + ClosureReason.HolderForceClosed( + FfiConverterOptionalBoolean.read(buf), + FfiConverterString.read(buf), + ) + } + + 3 -> { + ClosureReason.LegacyCooperativeClosure + } + + 4 -> { + ClosureReason.CounterpartyInitiatedCooperativeClosure + } + + 5 -> { + ClosureReason.LocallyInitiatedCooperativeClosure + } + + 6 -> { + ClosureReason.CommitmentTxConfirmed + } + + 7 -> { + ClosureReason.FundingTimedOut + } + + 8 -> { + ClosureReason.ProcessingError( + FfiConverterString.read(buf), + ) + } + + 9 -> { + ClosureReason.DisconnectedPeer + } + + 10 -> { + ClosureReason.OutdatedChannelManager + } + + 11 -> { + ClosureReason.CounterpartyCoopClosedUnfundedChannel + } + + 12 -> { + ClosureReason.LocallyCoopClosedUnfundedChannel + } + + 13 -> { + ClosureReason.FundingBatchClosure + } + + 14 -> { + ClosureReason.HtlCsTimedOut( + FfiConverterOptionalTypePaymentHash.read(buf), + ) + } + + 15 -> { + ClosureReason.PeerFeerateTooLow( + FfiConverterUInt.read(buf), + FfiConverterUInt.read(buf), + ) + } + + else -> { + throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: ClosureReason) = + when (value) { + is ClosureReason.CounterpartyForceClosed -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypeUntrustedString.allocationSize(value.`peerMsg`) + ) + } + + is ClosureReason.HolderForceClosed -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterOptionalBoolean.allocationSize(value.`broadcastedLatestTxn`) + + FfiConverterString.allocationSize(value.`message`) + ) + } + + is ClosureReason.LegacyCooperativeClosure -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + ) + } + + is ClosureReason.CounterpartyInitiatedCooperativeClosure -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + ) + } + + is ClosureReason.LocallyInitiatedCooperativeClosure -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + ) + } + + is ClosureReason.CommitmentTxConfirmed -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + ) + } + + is ClosureReason.FundingTimedOut -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + ) + } + + is ClosureReason.ProcessingError -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterString.allocationSize(value.`err`) + ) + } + + is ClosureReason.DisconnectedPeer -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + ) + } + + is ClosureReason.OutdatedChannelManager -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + ) + } + + is ClosureReason.CounterpartyCoopClosedUnfundedChannel -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + ) + } + + is ClosureReason.LocallyCoopClosedUnfundedChannel -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + ) + } + + is ClosureReason.FundingBatchClosure -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + ) + } + + is ClosureReason.HtlCsTimedOut -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterOptionalTypePaymentHash.allocationSize(value.`paymentHash`) + ) + } + + is ClosureReason.PeerFeerateTooLow -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterUInt.allocationSize(value.`peerFeerateSatPerKw`) + + FfiConverterUInt.allocationSize(value.`requiredFeerateSatPerKw`) + ) + } + } + + override fun write( + value: ClosureReason, + buf: ByteBuffer, + ) { + when (value) { + is ClosureReason.CounterpartyForceClosed -> { + buf.putInt(1) + FfiConverterTypeUntrustedString.write(value.`peerMsg`, buf) + Unit + } + + is ClosureReason.HolderForceClosed -> { + buf.putInt(2) + FfiConverterOptionalBoolean.write(value.`broadcastedLatestTxn`, buf) + FfiConverterString.write(value.`message`, buf) + Unit + } + + is ClosureReason.LegacyCooperativeClosure -> { + buf.putInt(3) + Unit + } + + is ClosureReason.CounterpartyInitiatedCooperativeClosure -> { + buf.putInt(4) + Unit + } + + is ClosureReason.LocallyInitiatedCooperativeClosure -> { + buf.putInt(5) + Unit + } + + is ClosureReason.CommitmentTxConfirmed -> { + buf.putInt(6) + Unit + } + + is ClosureReason.FundingTimedOut -> { + buf.putInt(7) + Unit + } + + is ClosureReason.ProcessingError -> { + buf.putInt(8) + FfiConverterString.write(value.`err`, buf) + Unit + } + + is ClosureReason.DisconnectedPeer -> { + buf.putInt(9) + Unit + } + + is ClosureReason.OutdatedChannelManager -> { + buf.putInt(10) + Unit + } + + is ClosureReason.CounterpartyCoopClosedUnfundedChannel -> { + buf.putInt(11) + Unit + } + + is ClosureReason.LocallyCoopClosedUnfundedChannel -> { + buf.putInt(12) + Unit + } + + is ClosureReason.FundingBatchClosure -> { + buf.putInt(13) + Unit + } + + is ClosureReason.HtlCsTimedOut -> { + buf.putInt(14) + FfiConverterOptionalTypePaymentHash.write(value.`paymentHash`, buf) + Unit + } + + is ClosureReason.PeerFeerateTooLow -> { + buf.putInt(15) + FfiConverterUInt.write(value.`peerFeerateSatPerKw`, buf) + FfiConverterUInt.write(value.`requiredFeerateSatPerKw`, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +enum class CoinSelectionAlgorithm { + BRANCH_AND_BOUND, + LARGEST_FIRST, + OLDEST_FIRST, + SINGLE_RANDOM_DRAW, + ; + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeCoinSelectionAlgorithm : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer) = + try { + CoinSelectionAlgorithm.values()[buf.getInt() - 1] + } catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + + override fun allocationSize(value: CoinSelectionAlgorithm) = 4UL + + override fun write( + value: CoinSelectionAlgorithm, + buf: ByteBuffer, + ) { + buf.putInt(value.ordinal + 1) + } +} + +sealed class ConfirmationStatus { + data class Confirmed( + val `blockHash`: BlockHash, + val `height`: kotlin.UInt, + val `timestamp`: kotlin.ULong, + ) : ConfirmationStatus() { + companion object + } + + object Unconfirmed : ConfirmationStatus() + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeConfirmationStatus : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): ConfirmationStatus = + when (buf.getInt()) { + 1 -> { + ConfirmationStatus.Confirmed( + FfiConverterTypeBlockHash.read(buf), + FfiConverterUInt.read(buf), + FfiConverterULong.read(buf), + ) + } + + 2 -> { + ConfirmationStatus.Unconfirmed + } + + else -> { + throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: ConfirmationStatus) = + when (value) { + is ConfirmationStatus.Confirmed -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypeBlockHash.allocationSize(value.`blockHash`) + + FfiConverterUInt.allocationSize(value.`height`) + + FfiConverterULong.allocationSize(value.`timestamp`) + ) + } + + is ConfirmationStatus.Unconfirmed -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + ) + } + } + + override fun write( + value: ConfirmationStatus, + buf: ByteBuffer, + ) { + when (value) { + is ConfirmationStatus.Confirmed -> { + buf.putInt(1) + FfiConverterTypeBlockHash.write(value.`blockHash`, buf) + FfiConverterUInt.write(value.`height`, buf) + FfiConverterULong.write(value.`timestamp`, buf) + Unit + } + + is ConfirmationStatus.Unconfirmed -> { + buf.putInt(2) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +enum class Currency { + BITCOIN, + BITCOIN_TESTNET, + REGTEST, + SIMNET, + SIGNET, + ; + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeCurrency : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer) = + try { + Currency.values()[buf.getInt() - 1] + } catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + + override fun allocationSize(value: Currency) = 4UL + + override fun write( + value: Currency, + buf: ByteBuffer, + ) { + buf.putInt(value.ordinal + 1) + } +} + +sealed class Event { + data class PaymentSuccessful( + val `paymentId`: PaymentId?, + val `paymentHash`: PaymentHash, + val `paymentPreimage`: PaymentPreimage?, + val `feePaidMsat`: kotlin.ULong?, + ) : Event() { + companion object + } + + data class PaymentFailed( + val `paymentId`: PaymentId?, + val `paymentHash`: PaymentHash?, + val `reason`: PaymentFailureReason?, + ) : Event() { + companion object + } + + data class PaymentReceived( + val `paymentId`: PaymentId?, + val `paymentHash`: PaymentHash, + val `amountMsat`: kotlin.ULong, + val `customRecords`: List, + ) : Event() { + companion object + } + + data class PaymentClaimable( + val `paymentId`: PaymentId, + val `paymentHash`: PaymentHash, + val `claimableAmountMsat`: kotlin.ULong, + val `claimDeadline`: kotlin.UInt?, + val `customRecords`: List, + ) : Event() { + companion object + } + + data class PaymentForwarded( + val `prevChannelId`: ChannelId, + val `nextChannelId`: ChannelId, + val `prevUserChannelId`: UserChannelId?, + val `nextUserChannelId`: UserChannelId?, + val `prevNodeId`: PublicKey?, + val `nextNodeId`: PublicKey?, + val `totalFeeEarnedMsat`: kotlin.ULong?, + val `skimmedFeeMsat`: kotlin.ULong?, + val `claimFromOnchainTx`: kotlin.Boolean, + val `outboundAmountForwardedMsat`: kotlin.ULong?, + ) : Event() { + companion object + } + + data class ChannelPending( + val `channelId`: ChannelId, + val `userChannelId`: UserChannelId, + val `formerTemporaryChannelId`: ChannelId, + val `counterpartyNodeId`: PublicKey, + val `fundingTxo`: OutPoint, + ) : Event() { + companion object + } + + data class ChannelReady( + val `channelId`: ChannelId, + val `userChannelId`: UserChannelId, + val `counterpartyNodeId`: PublicKey?, + val `fundingTxo`: OutPoint?, + ) : Event() { + companion object + } + + data class ChannelClosed( + val `channelId`: ChannelId, + val `userChannelId`: UserChannelId, + val `counterpartyNodeId`: PublicKey?, + val `reason`: ClosureReason?, + ) : Event() { + companion object + } + + data class SplicePending( + val `channelId`: ChannelId, + val `userChannelId`: UserChannelId, + val `counterpartyNodeId`: PublicKey, + val `newFundingTxo`: OutPoint, + ) : Event() { + companion object + } + + data class SpliceFailed( + val `channelId`: ChannelId, + val `userChannelId`: UserChannelId, + val `counterpartyNodeId`: PublicKey, + val `abandonedFundingTxo`: OutPoint?, + ) : Event() { + companion object + } + + data class OnchainTransactionConfirmed( + val `txid`: Txid, + val `blockHash`: BlockHash, + val `blockHeight`: kotlin.UInt, + val `confirmationTime`: kotlin.ULong, + val `details`: TransactionDetails, + ) : Event() { + companion object + } + + data class OnchainTransactionReceived( + val `txid`: Txid, + val `details`: TransactionDetails, + ) : Event() { + companion object + } + + data class OnchainTransactionReplaced( + val `txid`: Txid, + val `conflicts`: List, + ) : Event() { + companion object + } + + data class OnchainTransactionReorged( + val `txid`: Txid, + ) : Event() { + companion object + } + + data class OnchainTransactionEvicted( + val `txid`: Txid, + ) : Event() { + companion object + } + + data class SyncProgress( + val `syncType`: SyncType, + val `progressPercent`: kotlin.UByte, + val `currentBlockHeight`: kotlin.UInt, + val `targetBlockHeight`: kotlin.UInt, + ) : Event() { + companion object + } + + data class SyncCompleted( + val `syncType`: SyncType, + val `syncedBlockHeight`: kotlin.UInt, + ) : Event() { + companion object + } + + data class BalanceChanged( + val `oldSpendableOnchainBalanceSats`: kotlin.ULong, + val `newSpendableOnchainBalanceSats`: kotlin.ULong, + val `oldTotalOnchainBalanceSats`: kotlin.ULong, + val `newTotalOnchainBalanceSats`: kotlin.ULong, + val `oldTotalLightningBalanceSats`: kotlin.ULong, + val `newTotalLightningBalanceSats`: kotlin.ULong, + ) : Event() { + companion object + } + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeEvent : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): Event = + when (buf.getInt()) { + 1 -> { + Event.PaymentSuccessful( + FfiConverterOptionalTypePaymentId.read(buf), + FfiConverterTypePaymentHash.read(buf), + FfiConverterOptionalTypePaymentPreimage.read(buf), + FfiConverterOptionalULong.read(buf), + ) + } + + 2 -> { + Event.PaymentFailed( + FfiConverterOptionalTypePaymentId.read(buf), + FfiConverterOptionalTypePaymentHash.read(buf), + FfiConverterOptionalTypePaymentFailureReason.read(buf), + ) + } + + 3 -> { + Event.PaymentReceived( + FfiConverterOptionalTypePaymentId.read(buf), + FfiConverterTypePaymentHash.read(buf), + FfiConverterULong.read(buf), + FfiConverterSequenceTypeCustomTlvRecord.read(buf), + ) + } + + 4 -> { + Event.PaymentClaimable( + FfiConverterTypePaymentId.read(buf), + FfiConverterTypePaymentHash.read(buf), + FfiConverterULong.read(buf), + FfiConverterOptionalUInt.read(buf), + FfiConverterSequenceTypeCustomTlvRecord.read(buf), + ) + } + + 5 -> { + Event.PaymentForwarded( + FfiConverterTypeChannelId.read(buf), + FfiConverterTypeChannelId.read(buf), + FfiConverterOptionalTypeUserChannelId.read(buf), + FfiConverterOptionalTypeUserChannelId.read(buf), + FfiConverterOptionalTypePublicKey.read(buf), + FfiConverterOptionalTypePublicKey.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterBoolean.read(buf), + FfiConverterOptionalULong.read(buf), + ) + } + + 6 -> { + Event.ChannelPending( + FfiConverterTypeChannelId.read(buf), + FfiConverterTypeUserChannelId.read(buf), + FfiConverterTypeChannelId.read(buf), + FfiConverterTypePublicKey.read(buf), + FfiConverterTypeOutPoint.read(buf), + ) + } + + 7 -> { + Event.ChannelReady( + FfiConverterTypeChannelId.read(buf), + FfiConverterTypeUserChannelId.read(buf), + FfiConverterOptionalTypePublicKey.read(buf), + FfiConverterOptionalTypeOutPoint.read(buf), + ) + } + + 8 -> { + Event.ChannelClosed( + FfiConverterTypeChannelId.read(buf), + FfiConverterTypeUserChannelId.read(buf), + FfiConverterOptionalTypePublicKey.read(buf), + FfiConverterOptionalTypeClosureReason.read(buf), + ) + } + + 9 -> { + Event.SplicePending( + FfiConverterTypeChannelId.read(buf), + FfiConverterTypeUserChannelId.read(buf), + FfiConverterTypePublicKey.read(buf), + FfiConverterTypeOutPoint.read(buf), + ) + } + + 10 -> { + Event.SpliceFailed( + FfiConverterTypeChannelId.read(buf), + FfiConverterTypeUserChannelId.read(buf), + FfiConverterTypePublicKey.read(buf), + FfiConverterOptionalTypeOutPoint.read(buf), + ) + } + + 11 -> { + Event.OnchainTransactionConfirmed( + FfiConverterTypeTxid.read(buf), + FfiConverterTypeBlockHash.read(buf), + FfiConverterUInt.read(buf), + FfiConverterULong.read(buf), + FfiConverterTypeTransactionDetails.read(buf), + ) + } + + 12 -> { + Event.OnchainTransactionReceived( + FfiConverterTypeTxid.read(buf), + FfiConverterTypeTransactionDetails.read(buf), + ) + } + + 13 -> { + Event.OnchainTransactionReplaced( + FfiConverterTypeTxid.read(buf), + FfiConverterSequenceTypeTxid.read(buf), + ) + } + + 14 -> { + Event.OnchainTransactionReorged( + FfiConverterTypeTxid.read(buf), + ) + } + + 15 -> { + Event.OnchainTransactionEvicted( + FfiConverterTypeTxid.read(buf), + ) + } + + 16 -> { + Event.SyncProgress( + FfiConverterTypeSyncType.read(buf), + FfiConverterUByte.read(buf), + FfiConverterUInt.read(buf), + FfiConverterUInt.read(buf), + ) + } + + 17 -> { + Event.SyncCompleted( + FfiConverterTypeSyncType.read(buf), + FfiConverterUInt.read(buf), + ) + } + + 18 -> { + Event.BalanceChanged( + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + ) + } + + else -> { + throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: Event) = + when (value) { + is Event.PaymentSuccessful -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterOptionalTypePaymentId.allocationSize(value.`paymentId`) + + FfiConverterTypePaymentHash.allocationSize(value.`paymentHash`) + + FfiConverterOptionalTypePaymentPreimage.allocationSize(value.`paymentPreimage`) + + FfiConverterOptionalULong.allocationSize(value.`feePaidMsat`) + ) + } + + is Event.PaymentFailed -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterOptionalTypePaymentId.allocationSize(value.`paymentId`) + + FfiConverterOptionalTypePaymentHash.allocationSize(value.`paymentHash`) + + FfiConverterOptionalTypePaymentFailureReason.allocationSize(value.`reason`) + ) + } + + is Event.PaymentReceived -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterOptionalTypePaymentId.allocationSize(value.`paymentId`) + + FfiConverterTypePaymentHash.allocationSize(value.`paymentHash`) + + FfiConverterULong.allocationSize(value.`amountMsat`) + + FfiConverterSequenceTypeCustomTlvRecord.allocationSize(value.`customRecords`) + ) + } + + is Event.PaymentClaimable -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypePaymentId.allocationSize(value.`paymentId`) + + FfiConverterTypePaymentHash.allocationSize(value.`paymentHash`) + + FfiConverterULong.allocationSize(value.`claimableAmountMsat`) + + FfiConverterOptionalUInt.allocationSize(value.`claimDeadline`) + + FfiConverterSequenceTypeCustomTlvRecord.allocationSize(value.`customRecords`) + ) + } + + is Event.PaymentForwarded -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypeChannelId.allocationSize(value.`prevChannelId`) + + FfiConverterTypeChannelId.allocationSize(value.`nextChannelId`) + + FfiConverterOptionalTypeUserChannelId.allocationSize(value.`prevUserChannelId`) + + FfiConverterOptionalTypeUserChannelId.allocationSize(value.`nextUserChannelId`) + + FfiConverterOptionalTypePublicKey.allocationSize(value.`prevNodeId`) + + FfiConverterOptionalTypePublicKey.allocationSize(value.`nextNodeId`) + + FfiConverterOptionalULong.allocationSize(value.`totalFeeEarnedMsat`) + + FfiConverterOptionalULong.allocationSize(value.`skimmedFeeMsat`) + + FfiConverterBoolean.allocationSize(value.`claimFromOnchainTx`) + + FfiConverterOptionalULong.allocationSize(value.`outboundAmountForwardedMsat`) + ) + } + + is Event.ChannelPending -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypeChannelId.allocationSize(value.`channelId`) + + FfiConverterTypeUserChannelId.allocationSize(value.`userChannelId`) + + FfiConverterTypeChannelId.allocationSize(value.`formerTemporaryChannelId`) + + FfiConverterTypePublicKey.allocationSize(value.`counterpartyNodeId`) + + FfiConverterTypeOutPoint.allocationSize(value.`fundingTxo`) + ) + } + + is Event.ChannelReady -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypeChannelId.allocationSize(value.`channelId`) + + FfiConverterTypeUserChannelId.allocationSize(value.`userChannelId`) + + FfiConverterOptionalTypePublicKey.allocationSize(value.`counterpartyNodeId`) + + FfiConverterOptionalTypeOutPoint.allocationSize(value.`fundingTxo`) + ) + } + + is Event.ChannelClosed -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypeChannelId.allocationSize(value.`channelId`) + + FfiConverterTypeUserChannelId.allocationSize(value.`userChannelId`) + + FfiConverterOptionalTypePublicKey.allocationSize(value.`counterpartyNodeId`) + + FfiConverterOptionalTypeClosureReason.allocationSize(value.`reason`) + ) + } + + is Event.SplicePending -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypeChannelId.allocationSize(value.`channelId`) + + FfiConverterTypeUserChannelId.allocationSize(value.`userChannelId`) + + FfiConverterTypePublicKey.allocationSize(value.`counterpartyNodeId`) + + FfiConverterTypeOutPoint.allocationSize(value.`newFundingTxo`) + ) + } + + is Event.SpliceFailed -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypeChannelId.allocationSize(value.`channelId`) + + FfiConverterTypeUserChannelId.allocationSize(value.`userChannelId`) + + FfiConverterTypePublicKey.allocationSize(value.`counterpartyNodeId`) + + FfiConverterOptionalTypeOutPoint.allocationSize(value.`abandonedFundingTxo`) + ) + } + + is Event.OnchainTransactionConfirmed -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypeTxid.allocationSize(value.`txid`) + + FfiConverterTypeBlockHash.allocationSize(value.`blockHash`) + + FfiConverterUInt.allocationSize(value.`blockHeight`) + + FfiConverterULong.allocationSize(value.`confirmationTime`) + + FfiConverterTypeTransactionDetails.allocationSize(value.`details`) + ) + } + + is Event.OnchainTransactionReceived -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypeTxid.allocationSize(value.`txid`) + + FfiConverterTypeTransactionDetails.allocationSize(value.`details`) + ) + } + + is Event.OnchainTransactionReplaced -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypeTxid.allocationSize(value.`txid`) + + FfiConverterSequenceTypeTxid.allocationSize(value.`conflicts`) + ) + } + + is Event.OnchainTransactionReorged -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypeTxid.allocationSize(value.`txid`) + ) + } + + is Event.OnchainTransactionEvicted -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypeTxid.allocationSize(value.`txid`) + ) + } + + is Event.SyncProgress -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypeSyncType.allocationSize(value.`syncType`) + + FfiConverterUByte.allocationSize(value.`progressPercent`) + + FfiConverterUInt.allocationSize(value.`currentBlockHeight`) + + FfiConverterUInt.allocationSize(value.`targetBlockHeight`) + ) + } + + is Event.SyncCompleted -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypeSyncType.allocationSize(value.`syncType`) + + FfiConverterUInt.allocationSize(value.`syncedBlockHeight`) + ) + } + + is Event.BalanceChanged -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterULong.allocationSize(value.`oldSpendableOnchainBalanceSats`) + + FfiConverterULong.allocationSize(value.`newSpendableOnchainBalanceSats`) + + FfiConverterULong.allocationSize(value.`oldTotalOnchainBalanceSats`) + + FfiConverterULong.allocationSize(value.`newTotalOnchainBalanceSats`) + + FfiConverterULong.allocationSize(value.`oldTotalLightningBalanceSats`) + + FfiConverterULong.allocationSize(value.`newTotalLightningBalanceSats`) + ) + } + } + + override fun write( + value: Event, + buf: ByteBuffer, + ) { + when (value) { + is Event.PaymentSuccessful -> { + buf.putInt(1) + FfiConverterOptionalTypePaymentId.write(value.`paymentId`, buf) + FfiConverterTypePaymentHash.write(value.`paymentHash`, buf) + FfiConverterOptionalTypePaymentPreimage.write(value.`paymentPreimage`, buf) + FfiConverterOptionalULong.write(value.`feePaidMsat`, buf) + Unit + } + + is Event.PaymentFailed -> { + buf.putInt(2) + FfiConverterOptionalTypePaymentId.write(value.`paymentId`, buf) + FfiConverterOptionalTypePaymentHash.write(value.`paymentHash`, buf) + FfiConverterOptionalTypePaymentFailureReason.write(value.`reason`, buf) + Unit + } + + is Event.PaymentReceived -> { + buf.putInt(3) + FfiConverterOptionalTypePaymentId.write(value.`paymentId`, buf) + FfiConverterTypePaymentHash.write(value.`paymentHash`, buf) + FfiConverterULong.write(value.`amountMsat`, buf) + FfiConverterSequenceTypeCustomTlvRecord.write(value.`customRecords`, buf) + Unit + } + + is Event.PaymentClaimable -> { + buf.putInt(4) + FfiConverterTypePaymentId.write(value.`paymentId`, buf) + FfiConverterTypePaymentHash.write(value.`paymentHash`, buf) + FfiConverterULong.write(value.`claimableAmountMsat`, buf) + FfiConverterOptionalUInt.write(value.`claimDeadline`, buf) + FfiConverterSequenceTypeCustomTlvRecord.write(value.`customRecords`, buf) + Unit + } + + is Event.PaymentForwarded -> { + buf.putInt(5) + FfiConverterTypeChannelId.write(value.`prevChannelId`, buf) + FfiConverterTypeChannelId.write(value.`nextChannelId`, buf) + FfiConverterOptionalTypeUserChannelId.write(value.`prevUserChannelId`, buf) + FfiConverterOptionalTypeUserChannelId.write(value.`nextUserChannelId`, buf) + FfiConverterOptionalTypePublicKey.write(value.`prevNodeId`, buf) + FfiConverterOptionalTypePublicKey.write(value.`nextNodeId`, buf) + FfiConverterOptionalULong.write(value.`totalFeeEarnedMsat`, buf) + FfiConverterOptionalULong.write(value.`skimmedFeeMsat`, buf) + FfiConverterBoolean.write(value.`claimFromOnchainTx`, buf) + FfiConverterOptionalULong.write(value.`outboundAmountForwardedMsat`, buf) + Unit + } + + is Event.ChannelPending -> { + buf.putInt(6) + FfiConverterTypeChannelId.write(value.`channelId`, buf) + FfiConverterTypeUserChannelId.write(value.`userChannelId`, buf) + FfiConverterTypeChannelId.write(value.`formerTemporaryChannelId`, buf) + FfiConverterTypePublicKey.write(value.`counterpartyNodeId`, buf) + FfiConverterTypeOutPoint.write(value.`fundingTxo`, buf) + Unit + } + + is Event.ChannelReady -> { + buf.putInt(7) + FfiConverterTypeChannelId.write(value.`channelId`, buf) + FfiConverterTypeUserChannelId.write(value.`userChannelId`, buf) + FfiConverterOptionalTypePublicKey.write(value.`counterpartyNodeId`, buf) + FfiConverterOptionalTypeOutPoint.write(value.`fundingTxo`, buf) + Unit + } + + is Event.ChannelClosed -> { + buf.putInt(8) + FfiConverterTypeChannelId.write(value.`channelId`, buf) + FfiConverterTypeUserChannelId.write(value.`userChannelId`, buf) + FfiConverterOptionalTypePublicKey.write(value.`counterpartyNodeId`, buf) + FfiConverterOptionalTypeClosureReason.write(value.`reason`, buf) + Unit + } + + is Event.SplicePending -> { + buf.putInt(9) + FfiConverterTypeChannelId.write(value.`channelId`, buf) + FfiConverterTypeUserChannelId.write(value.`userChannelId`, buf) + FfiConverterTypePublicKey.write(value.`counterpartyNodeId`, buf) + FfiConverterTypeOutPoint.write(value.`newFundingTxo`, buf) + Unit + } + + is Event.SpliceFailed -> { + buf.putInt(10) + FfiConverterTypeChannelId.write(value.`channelId`, buf) + FfiConverterTypeUserChannelId.write(value.`userChannelId`, buf) + FfiConverterTypePublicKey.write(value.`counterpartyNodeId`, buf) + FfiConverterOptionalTypeOutPoint.write(value.`abandonedFundingTxo`, buf) + Unit + } + + is Event.OnchainTransactionConfirmed -> { + buf.putInt(11) + FfiConverterTypeTxid.write(value.`txid`, buf) + FfiConverterTypeBlockHash.write(value.`blockHash`, buf) + FfiConverterUInt.write(value.`blockHeight`, buf) + FfiConverterULong.write(value.`confirmationTime`, buf) + FfiConverterTypeTransactionDetails.write(value.`details`, buf) + Unit + } + + is Event.OnchainTransactionReceived -> { + buf.putInt(12) + FfiConverterTypeTxid.write(value.`txid`, buf) + FfiConverterTypeTransactionDetails.write(value.`details`, buf) + Unit + } + + is Event.OnchainTransactionReplaced -> { + buf.putInt(13) + FfiConverterTypeTxid.write(value.`txid`, buf) + FfiConverterSequenceTypeTxid.write(value.`conflicts`, buf) + Unit + } + + is Event.OnchainTransactionReorged -> { + buf.putInt(14) + FfiConverterTypeTxid.write(value.`txid`, buf) + Unit + } + + is Event.OnchainTransactionEvicted -> { + buf.putInt(15) + FfiConverterTypeTxid.write(value.`txid`, buf) + Unit + } + + is Event.SyncProgress -> { + buf.putInt(16) + FfiConverterTypeSyncType.write(value.`syncType`, buf) + FfiConverterUByte.write(value.`progressPercent`, buf) + FfiConverterUInt.write(value.`currentBlockHeight`, buf) + FfiConverterUInt.write(value.`targetBlockHeight`, buf) + Unit + } + + is Event.SyncCompleted -> { + buf.putInt(17) + FfiConverterTypeSyncType.write(value.`syncType`, buf) + FfiConverterUInt.write(value.`syncedBlockHeight`, buf) + Unit + } + + is Event.BalanceChanged -> { + buf.putInt(18) + FfiConverterULong.write(value.`oldSpendableOnchainBalanceSats`, buf) + FfiConverterULong.write(value.`newSpendableOnchainBalanceSats`, buf) + FfiConverterULong.write(value.`oldTotalOnchainBalanceSats`, buf) + FfiConverterULong.write(value.`newTotalOnchainBalanceSats`, buf) + FfiConverterULong.write(value.`oldTotalLightningBalanceSats`, buf) + FfiConverterULong.write(value.`newTotalLightningBalanceSats`, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +enum class Lsps1PaymentState { + EXPECT_PAYMENT, + PAID, + REFUNDED, + ; + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeLSPS1PaymentState : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer) = + try { + Lsps1PaymentState.values()[buf.getInt() - 1] + } catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + + override fun allocationSize(value: Lsps1PaymentState) = 4UL + + override fun write( + value: Lsps1PaymentState, + buf: ByteBuffer, + ) { + buf.putInt(value.ordinal + 1) + } +} + +sealed class LightningBalance { + data class ClaimableOnChannelClose( + val `channelId`: ChannelId, + val `counterpartyNodeId`: PublicKey, + val `amountSatoshis`: kotlin.ULong, + val `transactionFeeSatoshis`: kotlin.ULong, + val `outboundPaymentHtlcRoundedMsat`: kotlin.ULong, + val `outboundForwardedHtlcRoundedMsat`: kotlin.ULong, + val `inboundClaimingHtlcRoundedMsat`: kotlin.ULong, + val `inboundHtlcRoundedMsat`: kotlin.ULong, + ) : LightningBalance() { + companion object + } + + data class ClaimableAwaitingConfirmations( + val `channelId`: ChannelId, + val `counterpartyNodeId`: PublicKey, + val `amountSatoshis`: kotlin.ULong, + val `confirmationHeight`: kotlin.UInt, + val `source`: BalanceSource, + ) : LightningBalance() { + companion object + } + + data class ContentiousClaimable( + val `channelId`: ChannelId, + val `counterpartyNodeId`: PublicKey, + val `amountSatoshis`: kotlin.ULong, + val `timeoutHeight`: kotlin.UInt, + val `paymentHash`: PaymentHash, + val `paymentPreimage`: PaymentPreimage, + ) : LightningBalance() { + companion object + } + + data class MaybeTimeoutClaimableHtlc( + val `channelId`: ChannelId, + val `counterpartyNodeId`: PublicKey, + val `amountSatoshis`: kotlin.ULong, + val `claimableHeight`: kotlin.UInt, + val `paymentHash`: PaymentHash, + val `outboundPayment`: kotlin.Boolean, + ) : LightningBalance() { + companion object + } + + data class MaybePreimageClaimableHtlc( + val `channelId`: ChannelId, + val `counterpartyNodeId`: PublicKey, + val `amountSatoshis`: kotlin.ULong, + val `expiryHeight`: kotlin.UInt, + val `paymentHash`: PaymentHash, + ) : LightningBalance() { + companion object + } + + data class CounterpartyRevokedOutputClaimable( + val `channelId`: ChannelId, + val `counterpartyNodeId`: PublicKey, + val `amountSatoshis`: kotlin.ULong, + ) : LightningBalance() { + companion object + } + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeLightningBalance : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): LightningBalance = + when (buf.getInt()) { + 1 -> { + LightningBalance.ClaimableOnChannelClose( + FfiConverterTypeChannelId.read(buf), + FfiConverterTypePublicKey.read(buf), + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + FfiConverterULong.read(buf), + ) + } + + 2 -> { + LightningBalance.ClaimableAwaitingConfirmations( + FfiConverterTypeChannelId.read(buf), + FfiConverterTypePublicKey.read(buf), + FfiConverterULong.read(buf), + FfiConverterUInt.read(buf), + FfiConverterTypeBalanceSource.read(buf), + ) + } + + 3 -> { + LightningBalance.ContentiousClaimable( + FfiConverterTypeChannelId.read(buf), + FfiConverterTypePublicKey.read(buf), + FfiConverterULong.read(buf), + FfiConverterUInt.read(buf), + FfiConverterTypePaymentHash.read(buf), + FfiConverterTypePaymentPreimage.read(buf), + ) + } + + 4 -> { + LightningBalance.MaybeTimeoutClaimableHtlc( + FfiConverterTypeChannelId.read(buf), + FfiConverterTypePublicKey.read(buf), + FfiConverterULong.read(buf), + FfiConverterUInt.read(buf), + FfiConverterTypePaymentHash.read(buf), + FfiConverterBoolean.read(buf), + ) + } + + 5 -> { + LightningBalance.MaybePreimageClaimableHtlc( + FfiConverterTypeChannelId.read(buf), + FfiConverterTypePublicKey.read(buf), + FfiConverterULong.read(buf), + FfiConverterUInt.read(buf), + FfiConverterTypePaymentHash.read(buf), + ) + } + + 6 -> { + LightningBalance.CounterpartyRevokedOutputClaimable( + FfiConverterTypeChannelId.read(buf), + FfiConverterTypePublicKey.read(buf), + FfiConverterULong.read(buf), + ) + } + + else -> { + throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: LightningBalance) = + when (value) { + is LightningBalance.ClaimableOnChannelClose -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypeChannelId.allocationSize(value.`channelId`) + + FfiConverterTypePublicKey.allocationSize(value.`counterpartyNodeId`) + + FfiConverterULong.allocationSize(value.`amountSatoshis`) + + FfiConverterULong.allocationSize(value.`transactionFeeSatoshis`) + + FfiConverterULong.allocationSize(value.`outboundPaymentHtlcRoundedMsat`) + + FfiConverterULong.allocationSize(value.`outboundForwardedHtlcRoundedMsat`) + + FfiConverterULong.allocationSize(value.`inboundClaimingHtlcRoundedMsat`) + + FfiConverterULong.allocationSize(value.`inboundHtlcRoundedMsat`) + ) + } + + is LightningBalance.ClaimableAwaitingConfirmations -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypeChannelId.allocationSize(value.`channelId`) + + FfiConverterTypePublicKey.allocationSize(value.`counterpartyNodeId`) + + FfiConverterULong.allocationSize(value.`amountSatoshis`) + + FfiConverterUInt.allocationSize(value.`confirmationHeight`) + + FfiConverterTypeBalanceSource.allocationSize(value.`source`) + ) + } + + is LightningBalance.ContentiousClaimable -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypeChannelId.allocationSize(value.`channelId`) + + FfiConverterTypePublicKey.allocationSize(value.`counterpartyNodeId`) + + FfiConverterULong.allocationSize(value.`amountSatoshis`) + + FfiConverterUInt.allocationSize(value.`timeoutHeight`) + + FfiConverterTypePaymentHash.allocationSize(value.`paymentHash`) + + FfiConverterTypePaymentPreimage.allocationSize(value.`paymentPreimage`) + ) + } + + is LightningBalance.MaybeTimeoutClaimableHtlc -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypeChannelId.allocationSize(value.`channelId`) + + FfiConverterTypePublicKey.allocationSize(value.`counterpartyNodeId`) + + FfiConverterULong.allocationSize(value.`amountSatoshis`) + + FfiConverterUInt.allocationSize(value.`claimableHeight`) + + FfiConverterTypePaymentHash.allocationSize(value.`paymentHash`) + + FfiConverterBoolean.allocationSize(value.`outboundPayment`) + ) + } + + is LightningBalance.MaybePreimageClaimableHtlc -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypeChannelId.allocationSize(value.`channelId`) + + FfiConverterTypePublicKey.allocationSize(value.`counterpartyNodeId`) + + FfiConverterULong.allocationSize(value.`amountSatoshis`) + + FfiConverterUInt.allocationSize(value.`expiryHeight`) + + FfiConverterTypePaymentHash.allocationSize(value.`paymentHash`) + ) + } + + is LightningBalance.CounterpartyRevokedOutputClaimable -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypeChannelId.allocationSize(value.`channelId`) + + FfiConverterTypePublicKey.allocationSize(value.`counterpartyNodeId`) + + FfiConverterULong.allocationSize(value.`amountSatoshis`) + ) + } + } + + override fun write( + value: LightningBalance, + buf: ByteBuffer, + ) { + when (value) { + is LightningBalance.ClaimableOnChannelClose -> { + buf.putInt(1) + FfiConverterTypeChannelId.write(value.`channelId`, buf) + FfiConverterTypePublicKey.write(value.`counterpartyNodeId`, buf) + FfiConverterULong.write(value.`amountSatoshis`, buf) + FfiConverterULong.write(value.`transactionFeeSatoshis`, buf) + FfiConverterULong.write(value.`outboundPaymentHtlcRoundedMsat`, buf) + FfiConverterULong.write(value.`outboundForwardedHtlcRoundedMsat`, buf) + FfiConverterULong.write(value.`inboundClaimingHtlcRoundedMsat`, buf) + FfiConverterULong.write(value.`inboundHtlcRoundedMsat`, buf) + Unit + } + + is LightningBalance.ClaimableAwaitingConfirmations -> { + buf.putInt(2) + FfiConverterTypeChannelId.write(value.`channelId`, buf) + FfiConverterTypePublicKey.write(value.`counterpartyNodeId`, buf) + FfiConverterULong.write(value.`amountSatoshis`, buf) + FfiConverterUInt.write(value.`confirmationHeight`, buf) + FfiConverterTypeBalanceSource.write(value.`source`, buf) + Unit + } + + is LightningBalance.ContentiousClaimable -> { + buf.putInt(3) + FfiConverterTypeChannelId.write(value.`channelId`, buf) + FfiConverterTypePublicKey.write(value.`counterpartyNodeId`, buf) + FfiConverterULong.write(value.`amountSatoshis`, buf) + FfiConverterUInt.write(value.`timeoutHeight`, buf) + FfiConverterTypePaymentHash.write(value.`paymentHash`, buf) + FfiConverterTypePaymentPreimage.write(value.`paymentPreimage`, buf) + Unit + } + + is LightningBalance.MaybeTimeoutClaimableHtlc -> { + buf.putInt(4) + FfiConverterTypeChannelId.write(value.`channelId`, buf) + FfiConverterTypePublicKey.write(value.`counterpartyNodeId`, buf) + FfiConverterULong.write(value.`amountSatoshis`, buf) + FfiConverterUInt.write(value.`claimableHeight`, buf) + FfiConverterTypePaymentHash.write(value.`paymentHash`, buf) + FfiConverterBoolean.write(value.`outboundPayment`, buf) + Unit + } + + is LightningBalance.MaybePreimageClaimableHtlc -> { + buf.putInt(5) + FfiConverterTypeChannelId.write(value.`channelId`, buf) + FfiConverterTypePublicKey.write(value.`counterpartyNodeId`, buf) + FfiConverterULong.write(value.`amountSatoshis`, buf) + FfiConverterUInt.write(value.`expiryHeight`, buf) + FfiConverterTypePaymentHash.write(value.`paymentHash`, buf) + Unit + } + + is LightningBalance.CounterpartyRevokedOutputClaimable -> { + buf.putInt(6) + FfiConverterTypeChannelId.write(value.`channelId`, buf) + FfiConverterTypePublicKey.write(value.`counterpartyNodeId`, buf) + FfiConverterULong.write(value.`amountSatoshis`, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +enum class LogLevel { + GOSSIP, + TRACE, + DEBUG, + INFO, + WARN, + ERROR, + ; + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeLogLevel : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer) = + try { + LogLevel.values()[buf.getInt() - 1] + } catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + + override fun allocationSize(value: LogLevel) = 4UL + + override fun write( + value: LogLevel, + buf: ByteBuffer, + ) { + buf.putInt(value.ordinal + 1) + } +} + +sealed class MaxDustHtlcExposure { + data class FixedLimit( + val `limitMsat`: kotlin.ULong, + ) : MaxDustHtlcExposure() { + companion object + } + + data class FeeRateMultiplier( + val `multiplier`: kotlin.ULong, + ) : MaxDustHtlcExposure() { + companion object + } + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeMaxDustHTLCExposure : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): MaxDustHtlcExposure = + when (buf.getInt()) { + 1 -> { + MaxDustHtlcExposure.FixedLimit( + FfiConverterULong.read(buf), + ) + } + + 2 -> { + MaxDustHtlcExposure.FeeRateMultiplier( + FfiConverterULong.read(buf), + ) + } + + else -> { + throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: MaxDustHtlcExposure) = + when (value) { + is MaxDustHtlcExposure.FixedLimit -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterULong.allocationSize(value.`limitMsat`) + ) + } + + is MaxDustHtlcExposure.FeeRateMultiplier -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterULong.allocationSize(value.`multiplier`) + ) + } + } + + override fun write( + value: MaxDustHtlcExposure, + buf: ByteBuffer, + ) { + when (value) { + is MaxDustHtlcExposure.FixedLimit -> { + buf.putInt(1) + FfiConverterULong.write(value.`limitMsat`, buf) + Unit + } + + is MaxDustHtlcExposure.FeeRateMultiplier -> { + buf.putInt(2) + FfiConverterULong.write(value.`multiplier`, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +enum class Network { + BITCOIN, + TESTNET, + SIGNET, + REGTEST, + ; + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeNetwork : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer) = + try { + Network.values()[buf.getInt() - 1] + } catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + + override fun allocationSize(value: Network) = 4UL + + override fun write( + value: Network, + buf: ByteBuffer, + ) { + buf.putInt(value.ordinal + 1) + } +} + +sealed class NodeException( + message: String, +) : kotlin.Exception(message) { + class AlreadyRunning( + message: String, + ) : NodeException(message) + + class NotRunning( + message: String, + ) : NodeException(message) + + class OnchainTxCreationFailed( + message: String, + ) : NodeException(message) + + class ConnectionFailed( + message: String, + ) : NodeException(message) + + class InvoiceCreationFailed( + message: String, + ) : NodeException(message) + + class InvoiceRequestCreationFailed( + message: String, + ) : NodeException(message) + + class OfferCreationFailed( + message: String, + ) : NodeException(message) + + class RefundCreationFailed( + message: String, + ) : NodeException(message) + + class PaymentSendingFailed( + message: String, + ) : NodeException(message) + + class InvalidCustomTlvs( + message: String, + ) : NodeException(message) + + class ProbeSendingFailed( + message: String, + ) : NodeException(message) + + class RouteNotFound( + message: String, + ) : NodeException(message) + + class ChannelCreationFailed( + message: String, + ) : NodeException(message) + + class ChannelClosingFailed( + message: String, + ) : NodeException(message) + + class ChannelSplicingFailed( + message: String, + ) : NodeException(message) + + class ChannelConfigUpdateFailed( + message: String, + ) : NodeException(message) + + class PersistenceFailed( + message: String, + ) : NodeException(message) + + class FeerateEstimationUpdateFailed( + message: String, + ) : NodeException(message) + + class FeerateEstimationUpdateTimeout( + message: String, + ) : NodeException(message) + + class WalletOperationFailed( + message: String, + ) : NodeException(message) + + class WalletOperationTimeout( + message: String, + ) : NodeException(message) + + class OnchainTxSigningFailed( + message: String, + ) : NodeException(message) + + class TxSyncFailed( + message: String, + ) : NodeException(message) + + class TxSyncTimeout( + message: String, + ) : NodeException(message) + + class GossipUpdateFailed( + message: String, + ) : NodeException(message) + + class GossipUpdateTimeout( + message: String, + ) : NodeException(message) + + class LiquidityRequestFailed( + message: String, + ) : NodeException(message) + + class UriParameterParsingFailed( + message: String, + ) : NodeException(message) + + class InvalidAddress( + message: String, + ) : NodeException(message) + + class InvalidSocketAddress( + message: String, + ) : NodeException(message) + + class InvalidPublicKey( + message: String, + ) : NodeException(message) + + class InvalidSecretKey( + message: String, + ) : NodeException(message) + + class InvalidOfferId( + message: String, + ) : NodeException(message) + + class InvalidNodeId( + message: String, + ) : NodeException(message) + + class InvalidPaymentId( + message: String, + ) : NodeException(message) + + class InvalidPaymentHash( + message: String, + ) : NodeException(message) + + class InvalidPaymentPreimage( + message: String, + ) : NodeException(message) + + class InvalidPaymentSecret( + message: String, + ) : NodeException(message) + + class InvalidAmount( + message: String, + ) : NodeException(message) + + class InvalidInvoice( + message: String, + ) : NodeException(message) + + class InvalidOffer( + message: String, + ) : NodeException(message) + + class InvalidRefund( + message: String, + ) : NodeException(message) + + class InvalidChannelId( + message: String, + ) : NodeException(message) + + class InvalidNetwork( + message: String, + ) : NodeException(message) + + class InvalidUri( + message: String, + ) : NodeException(message) + + class InvalidQuantity( + message: String, + ) : NodeException(message) + + class InvalidNodeAlias( + message: String, + ) : NodeException(message) + + class InvalidDateTime( + message: String, + ) : NodeException(message) + + class InvalidFeeRate( + message: String, + ) : NodeException(message) + + class DuplicatePayment( + message: String, + ) : NodeException(message) + + class UnsupportedCurrency( + message: String, + ) : NodeException(message) + + class InsufficientFunds( + message: String, + ) : NodeException(message) + + class LiquiditySourceUnavailable( + message: String, + ) : NodeException(message) + + class LiquidityFeeTooHigh( + message: String, + ) : NodeException(message) + + class InvalidBlindedPaths( + message: String, + ) : NodeException(message) + + class AsyncPaymentServicesDisabled( + message: String, + ) : NodeException(message) + + class CannotRbfFundingTransaction( + message: String, + ) : NodeException(message) + + class TransactionNotFound( + message: String, + ) : NodeException(message) + + class TransactionAlreadyConfirmed( + message: String, + ) : NodeException(message) + + class NoSpendableOutputs( + message: String, + ) : NodeException(message) + + class CoinSelectionFailed( + message: String, + ) : NodeException(message) + + class InvalidMnemonic( + message: String, + ) : NodeException(message) + + class BackgroundSyncNotEnabled( + message: String, + ) : NodeException(message) + + companion object ErrorHandler : UniffiRustCallStatusErrorHandler { + override fun lift(error_buf: RustBuffer.ByValue): NodeException = FfiConverterTypeNodeError.lift(error_buf) + } +} + +/** + * @suppress + */ +public object FfiConverterTypeNodeError : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): NodeException = + when (buf.getInt()) { + 1 -> NodeException.AlreadyRunning(FfiConverterString.read(buf)) + 2 -> NodeException.NotRunning(FfiConverterString.read(buf)) + 3 -> NodeException.OnchainTxCreationFailed(FfiConverterString.read(buf)) + 4 -> NodeException.ConnectionFailed(FfiConverterString.read(buf)) + 5 -> NodeException.InvoiceCreationFailed(FfiConverterString.read(buf)) + 6 -> NodeException.InvoiceRequestCreationFailed(FfiConverterString.read(buf)) + 7 -> NodeException.OfferCreationFailed(FfiConverterString.read(buf)) + 8 -> NodeException.RefundCreationFailed(FfiConverterString.read(buf)) + 9 -> NodeException.PaymentSendingFailed(FfiConverterString.read(buf)) + 10 -> NodeException.InvalidCustomTlvs(FfiConverterString.read(buf)) + 11 -> NodeException.ProbeSendingFailed(FfiConverterString.read(buf)) + 12 -> NodeException.RouteNotFound(FfiConverterString.read(buf)) + 13 -> NodeException.ChannelCreationFailed(FfiConverterString.read(buf)) + 14 -> NodeException.ChannelClosingFailed(FfiConverterString.read(buf)) + 15 -> NodeException.ChannelSplicingFailed(FfiConverterString.read(buf)) + 16 -> NodeException.ChannelConfigUpdateFailed(FfiConverterString.read(buf)) + 17 -> NodeException.PersistenceFailed(FfiConverterString.read(buf)) + 18 -> NodeException.FeerateEstimationUpdateFailed(FfiConverterString.read(buf)) + 19 -> NodeException.FeerateEstimationUpdateTimeout(FfiConverterString.read(buf)) + 20 -> NodeException.WalletOperationFailed(FfiConverterString.read(buf)) + 21 -> NodeException.WalletOperationTimeout(FfiConverterString.read(buf)) + 22 -> NodeException.OnchainTxSigningFailed(FfiConverterString.read(buf)) + 23 -> NodeException.TxSyncFailed(FfiConverterString.read(buf)) + 24 -> NodeException.TxSyncTimeout(FfiConverterString.read(buf)) + 25 -> NodeException.GossipUpdateFailed(FfiConverterString.read(buf)) + 26 -> NodeException.GossipUpdateTimeout(FfiConverterString.read(buf)) + 27 -> NodeException.LiquidityRequestFailed(FfiConverterString.read(buf)) + 28 -> NodeException.UriParameterParsingFailed(FfiConverterString.read(buf)) + 29 -> NodeException.InvalidAddress(FfiConverterString.read(buf)) + 30 -> NodeException.InvalidSocketAddress(FfiConverterString.read(buf)) + 31 -> NodeException.InvalidPublicKey(FfiConverterString.read(buf)) + 32 -> NodeException.InvalidSecretKey(FfiConverterString.read(buf)) + 33 -> NodeException.InvalidOfferId(FfiConverterString.read(buf)) + 34 -> NodeException.InvalidNodeId(FfiConverterString.read(buf)) + 35 -> NodeException.InvalidPaymentId(FfiConverterString.read(buf)) + 36 -> NodeException.InvalidPaymentHash(FfiConverterString.read(buf)) + 37 -> NodeException.InvalidPaymentPreimage(FfiConverterString.read(buf)) + 38 -> NodeException.InvalidPaymentSecret(FfiConverterString.read(buf)) + 39 -> NodeException.InvalidAmount(FfiConverterString.read(buf)) + 40 -> NodeException.InvalidInvoice(FfiConverterString.read(buf)) + 41 -> NodeException.InvalidOffer(FfiConverterString.read(buf)) + 42 -> NodeException.InvalidRefund(FfiConverterString.read(buf)) + 43 -> NodeException.InvalidChannelId(FfiConverterString.read(buf)) + 44 -> NodeException.InvalidNetwork(FfiConverterString.read(buf)) + 45 -> NodeException.InvalidUri(FfiConverterString.read(buf)) + 46 -> NodeException.InvalidQuantity(FfiConverterString.read(buf)) + 47 -> NodeException.InvalidNodeAlias(FfiConverterString.read(buf)) + 48 -> NodeException.InvalidDateTime(FfiConverterString.read(buf)) + 49 -> NodeException.InvalidFeeRate(FfiConverterString.read(buf)) + 50 -> NodeException.DuplicatePayment(FfiConverterString.read(buf)) + 51 -> NodeException.UnsupportedCurrency(FfiConverterString.read(buf)) + 52 -> NodeException.InsufficientFunds(FfiConverterString.read(buf)) + 53 -> NodeException.LiquiditySourceUnavailable(FfiConverterString.read(buf)) + 54 -> NodeException.LiquidityFeeTooHigh(FfiConverterString.read(buf)) + 55 -> NodeException.InvalidBlindedPaths(FfiConverterString.read(buf)) + 56 -> NodeException.AsyncPaymentServicesDisabled(FfiConverterString.read(buf)) + 57 -> NodeException.CannotRbfFundingTransaction(FfiConverterString.read(buf)) + 58 -> NodeException.TransactionNotFound(FfiConverterString.read(buf)) + 59 -> NodeException.TransactionAlreadyConfirmed(FfiConverterString.read(buf)) + 60 -> NodeException.NoSpendableOutputs(FfiConverterString.read(buf)) + 61 -> NodeException.CoinSelectionFailed(FfiConverterString.read(buf)) + 62 -> NodeException.InvalidMnemonic(FfiConverterString.read(buf)) + 63 -> NodeException.BackgroundSyncNotEnabled(FfiConverterString.read(buf)) + else -> throw RuntimeException("invalid error enum value, something is very wrong!!") + } + + override fun allocationSize(value: NodeException): ULong = 4UL + + override fun write( + value: NodeException, + buf: ByteBuffer, + ) { + when (value) { + is NodeException.AlreadyRunning -> { + buf.putInt(1) + Unit + } + + is NodeException.NotRunning -> { + buf.putInt(2) + Unit + } + + is NodeException.OnchainTxCreationFailed -> { + buf.putInt(3) + Unit + } + + is NodeException.ConnectionFailed -> { + buf.putInt(4) + Unit + } + + is NodeException.InvoiceCreationFailed -> { + buf.putInt(5) + Unit + } + + is NodeException.InvoiceRequestCreationFailed -> { + buf.putInt(6) + Unit + } + + is NodeException.OfferCreationFailed -> { + buf.putInt(7) + Unit + } + + is NodeException.RefundCreationFailed -> { + buf.putInt(8) + Unit + } + + is NodeException.PaymentSendingFailed -> { + buf.putInt(9) + Unit + } + + is NodeException.InvalidCustomTlvs -> { + buf.putInt(10) + Unit + } + + is NodeException.ProbeSendingFailed -> { + buf.putInt(11) + Unit + } + + is NodeException.RouteNotFound -> { + buf.putInt(12) + Unit + } + + is NodeException.ChannelCreationFailed -> { + buf.putInt(13) + Unit + } + + is NodeException.ChannelClosingFailed -> { + buf.putInt(14) + Unit + } + + is NodeException.ChannelSplicingFailed -> { + buf.putInt(15) + Unit + } + + is NodeException.ChannelConfigUpdateFailed -> { + buf.putInt(16) + Unit + } + + is NodeException.PersistenceFailed -> { + buf.putInt(17) + Unit + } + + is NodeException.FeerateEstimationUpdateFailed -> { + buf.putInt(18) + Unit + } + + is NodeException.FeerateEstimationUpdateTimeout -> { + buf.putInt(19) + Unit + } + + is NodeException.WalletOperationFailed -> { + buf.putInt(20) + Unit + } + + is NodeException.WalletOperationTimeout -> { + buf.putInt(21) + Unit + } + + is NodeException.OnchainTxSigningFailed -> { + buf.putInt(22) + Unit + } + + is NodeException.TxSyncFailed -> { + buf.putInt(23) + Unit + } + + is NodeException.TxSyncTimeout -> { + buf.putInt(24) + Unit + } + + is NodeException.GossipUpdateFailed -> { + buf.putInt(25) + Unit + } + + is NodeException.GossipUpdateTimeout -> { + buf.putInt(26) + Unit + } + + is NodeException.LiquidityRequestFailed -> { + buf.putInt(27) + Unit + } + + is NodeException.UriParameterParsingFailed -> { + buf.putInt(28) + Unit + } + + is NodeException.InvalidAddress -> { + buf.putInt(29) + Unit + } + + is NodeException.InvalidSocketAddress -> { + buf.putInt(30) + Unit + } + + is NodeException.InvalidPublicKey -> { + buf.putInt(31) + Unit + } + + is NodeException.InvalidSecretKey -> { + buf.putInt(32) + Unit + } + + is NodeException.InvalidOfferId -> { + buf.putInt(33) + Unit + } + + is NodeException.InvalidNodeId -> { + buf.putInt(34) + Unit + } + + is NodeException.InvalidPaymentId -> { + buf.putInt(35) + Unit + } + + is NodeException.InvalidPaymentHash -> { + buf.putInt(36) + Unit + } + + is NodeException.InvalidPaymentPreimage -> { + buf.putInt(37) + Unit + } + + is NodeException.InvalidPaymentSecret -> { + buf.putInt(38) + Unit + } + + is NodeException.InvalidAmount -> { + buf.putInt(39) + Unit + } + + is NodeException.InvalidInvoice -> { + buf.putInt(40) + Unit + } + + is NodeException.InvalidOffer -> { + buf.putInt(41) + Unit + } + + is NodeException.InvalidRefund -> { + buf.putInt(42) + Unit + } + + is NodeException.InvalidChannelId -> { + buf.putInt(43) + Unit + } + + is NodeException.InvalidNetwork -> { + buf.putInt(44) + Unit + } + + is NodeException.InvalidUri -> { + buf.putInt(45) + Unit + } + + is NodeException.InvalidQuantity -> { + buf.putInt(46) + Unit + } + + is NodeException.InvalidNodeAlias -> { + buf.putInt(47) + Unit + } + + is NodeException.InvalidDateTime -> { + buf.putInt(48) + Unit + } + + is NodeException.InvalidFeeRate -> { + buf.putInt(49) + Unit + } + + is NodeException.DuplicatePayment -> { + buf.putInt(50) + Unit + } + + is NodeException.UnsupportedCurrency -> { + buf.putInt(51) + Unit + } + + is NodeException.InsufficientFunds -> { + buf.putInt(52) + Unit + } + + is NodeException.LiquiditySourceUnavailable -> { + buf.putInt(53) + Unit + } + + is NodeException.LiquidityFeeTooHigh -> { + buf.putInt(54) + Unit + } + + is NodeException.InvalidBlindedPaths -> { + buf.putInt(55) + Unit + } + + is NodeException.AsyncPaymentServicesDisabled -> { + buf.putInt(56) + Unit + } + + is NodeException.CannotRbfFundingTransaction -> { + buf.putInt(57) + Unit + } + + is NodeException.TransactionNotFound -> { + buf.putInt(58) + Unit + } + + is NodeException.TransactionAlreadyConfirmed -> { + buf.putInt(59) + Unit + } + + is NodeException.NoSpendableOutputs -> { + buf.putInt(60) + Unit + } + + is NodeException.CoinSelectionFailed -> { + buf.putInt(61) + Unit + } + + is NodeException.InvalidMnemonic -> { + buf.putInt(62) + Unit + } + + is NodeException.BackgroundSyncNotEnabled -> { + buf.putInt(63) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +sealed class OfferAmount { + data class Bitcoin( + val `amountMsats`: kotlin.ULong, + ) : OfferAmount() { + companion object + } + + data class Currency( + val `iso4217Code`: kotlin.String, + val `amount`: kotlin.ULong, + ) : OfferAmount() { + companion object + } + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeOfferAmount : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): OfferAmount = + when (buf.getInt()) { + 1 -> { + OfferAmount.Bitcoin( + FfiConverterULong.read(buf), + ) + } + + 2 -> { + OfferAmount.Currency( + FfiConverterString.read(buf), + FfiConverterULong.read(buf), + ) + } + + else -> { + throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: OfferAmount) = + when (value) { + is OfferAmount.Bitcoin -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterULong.allocationSize(value.`amountMsats`) + ) + } + + is OfferAmount.Currency -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterString.allocationSize(value.`iso4217Code`) + + FfiConverterULong.allocationSize(value.`amount`) + ) + } + } + + override fun write( + value: OfferAmount, + buf: ByteBuffer, + ) { + when (value) { + is OfferAmount.Bitcoin -> { + buf.putInt(1) + FfiConverterULong.write(value.`amountMsats`, buf) + Unit + } + + is OfferAmount.Currency -> { + buf.putInt(2) + FfiConverterString.write(value.`iso4217Code`, buf) + FfiConverterULong.write(value.`amount`, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +enum class PaymentDirection { + INBOUND, + OUTBOUND, + ; + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypePaymentDirection : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer) = + try { + PaymentDirection.values()[buf.getInt() - 1] + } catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + + override fun allocationSize(value: PaymentDirection) = 4UL + + override fun write( + value: PaymentDirection, + buf: ByteBuffer, + ) { + buf.putInt(value.ordinal + 1) + } +} + +enum class PaymentFailureReason { + RECIPIENT_REJECTED, + USER_ABANDONED, + RETRIES_EXHAUSTED, + PAYMENT_EXPIRED, + ROUTE_NOT_FOUND, + UNEXPECTED_ERROR, + UNKNOWN_REQUIRED_FEATURES, + INVOICE_REQUEST_EXPIRED, + INVOICE_REQUEST_REJECTED, + BLINDED_PATH_CREATION_FAILED, + ; + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypePaymentFailureReason : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer) = + try { + PaymentFailureReason.values()[buf.getInt() - 1] + } catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + + override fun allocationSize(value: PaymentFailureReason) = 4UL + + override fun write( + value: PaymentFailureReason, + buf: ByteBuffer, + ) { + buf.putInt(value.ordinal + 1) + } +} + +sealed class PaymentKind { + data class Onchain( + val `txid`: Txid, + val `status`: ConfirmationStatus, + ) : PaymentKind() { + companion object + } + + data class Bolt11( + val `hash`: PaymentHash, + val `preimage`: PaymentPreimage?, + val `secret`: PaymentSecret?, + val `description`: kotlin.String?, + val `bolt11`: kotlin.String?, + ) : PaymentKind() { + companion object + } + + data class Bolt11Jit( + val `hash`: PaymentHash, + val `preimage`: PaymentPreimage?, + val `secret`: PaymentSecret?, + val `counterpartySkimmedFeeMsat`: kotlin.ULong?, + val `lspFeeLimits`: LspFeeLimits, + val `description`: kotlin.String?, + val `bolt11`: kotlin.String?, + ) : PaymentKind() { + companion object + } + + data class Bolt12Offer( + val `hash`: PaymentHash?, + val `preimage`: PaymentPreimage?, + val `secret`: PaymentSecret?, + val `offerId`: OfferId, + val `payerNote`: UntrustedString?, + val `quantity`: kotlin.ULong?, + ) : PaymentKind() { + companion object + } + + data class Bolt12Refund( + val `hash`: PaymentHash?, + val `preimage`: PaymentPreimage?, + val `secret`: PaymentSecret?, + val `payerNote`: UntrustedString?, + val `quantity`: kotlin.ULong?, + ) : PaymentKind() { + companion object + } + + data class Spontaneous( + val `hash`: PaymentHash, + val `preimage`: PaymentPreimage?, + ) : PaymentKind() { + companion object + } + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypePaymentKind : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): PaymentKind = + when (buf.getInt()) { + 1 -> { + PaymentKind.Onchain( + FfiConverterTypeTxid.read(buf), + FfiConverterTypeConfirmationStatus.read(buf), + ) + } + + 2 -> { + PaymentKind.Bolt11( + FfiConverterTypePaymentHash.read(buf), + FfiConverterOptionalTypePaymentPreimage.read(buf), + FfiConverterOptionalTypePaymentSecret.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalString.read(buf), + ) + } + + 3 -> { + PaymentKind.Bolt11Jit( + FfiConverterTypePaymentHash.read(buf), + FfiConverterOptionalTypePaymentPreimage.read(buf), + FfiConverterOptionalTypePaymentSecret.read(buf), + FfiConverterOptionalULong.read(buf), + FfiConverterTypeLSPFeeLimits.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalString.read(buf), + ) + } + + 4 -> { + PaymentKind.Bolt12Offer( + FfiConverterOptionalTypePaymentHash.read(buf), + FfiConverterOptionalTypePaymentPreimage.read(buf), + FfiConverterOptionalTypePaymentSecret.read(buf), + FfiConverterTypeOfferId.read(buf), + FfiConverterOptionalTypeUntrustedString.read(buf), + FfiConverterOptionalULong.read(buf), + ) + } + + 5 -> { + PaymentKind.Bolt12Refund( + FfiConverterOptionalTypePaymentHash.read(buf), + FfiConverterOptionalTypePaymentPreimage.read(buf), + FfiConverterOptionalTypePaymentSecret.read(buf), + FfiConverterOptionalTypeUntrustedString.read(buf), + FfiConverterOptionalULong.read(buf), + ) + } + + 6 -> { + PaymentKind.Spontaneous( + FfiConverterTypePaymentHash.read(buf), + FfiConverterOptionalTypePaymentPreimage.read(buf), + ) + } + + else -> { + throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: PaymentKind) = + when (value) { + is PaymentKind.Onchain -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypeTxid.allocationSize(value.`txid`) + + FfiConverterTypeConfirmationStatus.allocationSize(value.`status`) + ) + } + + is PaymentKind.Bolt11 -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypePaymentHash.allocationSize(value.`hash`) + + FfiConverterOptionalTypePaymentPreimage.allocationSize(value.`preimage`) + + FfiConverterOptionalTypePaymentSecret.allocationSize(value.`secret`) + + FfiConverterOptionalString.allocationSize(value.`description`) + + FfiConverterOptionalString.allocationSize(value.`bolt11`) + ) + } + + is PaymentKind.Bolt11Jit -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypePaymentHash.allocationSize(value.`hash`) + + FfiConverterOptionalTypePaymentPreimage.allocationSize(value.`preimage`) + + FfiConverterOptionalTypePaymentSecret.allocationSize(value.`secret`) + + FfiConverterOptionalULong.allocationSize(value.`counterpartySkimmedFeeMsat`) + + FfiConverterTypeLSPFeeLimits.allocationSize(value.`lspFeeLimits`) + + FfiConverterOptionalString.allocationSize(value.`description`) + + FfiConverterOptionalString.allocationSize(value.`bolt11`) + ) + } + + is PaymentKind.Bolt12Offer -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterOptionalTypePaymentHash.allocationSize(value.`hash`) + + FfiConverterOptionalTypePaymentPreimage.allocationSize(value.`preimage`) + + FfiConverterOptionalTypePaymentSecret.allocationSize(value.`secret`) + + FfiConverterTypeOfferId.allocationSize(value.`offerId`) + + FfiConverterOptionalTypeUntrustedString.allocationSize(value.`payerNote`) + + FfiConverterOptionalULong.allocationSize(value.`quantity`) + ) + } + + is PaymentKind.Bolt12Refund -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterOptionalTypePaymentHash.allocationSize(value.`hash`) + + FfiConverterOptionalTypePaymentPreimage.allocationSize(value.`preimage`) + + FfiConverterOptionalTypePaymentSecret.allocationSize(value.`secret`) + + FfiConverterOptionalTypeUntrustedString.allocationSize(value.`payerNote`) + + FfiConverterOptionalULong.allocationSize(value.`quantity`) + ) + } + + is PaymentKind.Spontaneous -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypePaymentHash.allocationSize(value.`hash`) + + FfiConverterOptionalTypePaymentPreimage.allocationSize(value.`preimage`) + ) + } + } + + override fun write( + value: PaymentKind, + buf: ByteBuffer, + ) { + when (value) { + is PaymentKind.Onchain -> { + buf.putInt(1) + FfiConverterTypeTxid.write(value.`txid`, buf) + FfiConverterTypeConfirmationStatus.write(value.`status`, buf) + Unit + } + + is PaymentKind.Bolt11 -> { + buf.putInt(2) + FfiConverterTypePaymentHash.write(value.`hash`, buf) + FfiConverterOptionalTypePaymentPreimage.write(value.`preimage`, buf) + FfiConverterOptionalTypePaymentSecret.write(value.`secret`, buf) + FfiConverterOptionalString.write(value.`description`, buf) + FfiConverterOptionalString.write(value.`bolt11`, buf) + Unit + } + + is PaymentKind.Bolt11Jit -> { + buf.putInt(3) + FfiConverterTypePaymentHash.write(value.`hash`, buf) + FfiConverterOptionalTypePaymentPreimage.write(value.`preimage`, buf) + FfiConverterOptionalTypePaymentSecret.write(value.`secret`, buf) + FfiConverterOptionalULong.write(value.`counterpartySkimmedFeeMsat`, buf) + FfiConverterTypeLSPFeeLimits.write(value.`lspFeeLimits`, buf) + FfiConverterOptionalString.write(value.`description`, buf) + FfiConverterOptionalString.write(value.`bolt11`, buf) + Unit + } + + is PaymentKind.Bolt12Offer -> { + buf.putInt(4) + FfiConverterOptionalTypePaymentHash.write(value.`hash`, buf) + FfiConverterOptionalTypePaymentPreimage.write(value.`preimage`, buf) + FfiConverterOptionalTypePaymentSecret.write(value.`secret`, buf) + FfiConverterTypeOfferId.write(value.`offerId`, buf) + FfiConverterOptionalTypeUntrustedString.write(value.`payerNote`, buf) + FfiConverterOptionalULong.write(value.`quantity`, buf) + Unit + } + + is PaymentKind.Bolt12Refund -> { + buf.putInt(5) + FfiConverterOptionalTypePaymentHash.write(value.`hash`, buf) + FfiConverterOptionalTypePaymentPreimage.write(value.`preimage`, buf) + FfiConverterOptionalTypePaymentSecret.write(value.`secret`, buf) + FfiConverterOptionalTypeUntrustedString.write(value.`payerNote`, buf) + FfiConverterOptionalULong.write(value.`quantity`, buf) + Unit + } + + is PaymentKind.Spontaneous -> { + buf.putInt(6) + FfiConverterTypePaymentHash.write(value.`hash`, buf) + FfiConverterOptionalTypePaymentPreimage.write(value.`preimage`, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +enum class PaymentStatus { + PENDING, + SUCCEEDED, + FAILED, + ; + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypePaymentStatus : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer) = + try { + PaymentStatus.values()[buf.getInt() - 1] + } catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + + override fun allocationSize(value: PaymentStatus) = 4UL + + override fun write( + value: PaymentStatus, + buf: ByteBuffer, + ) { + buf.putInt(value.ordinal + 1) + } +} + +sealed class PendingSweepBalance { + data class PendingBroadcast( + val `channelId`: ChannelId?, + val `amountSatoshis`: kotlin.ULong, + ) : PendingSweepBalance() { + companion object + } + + data class BroadcastAwaitingConfirmation( + val `channelId`: ChannelId?, + val `latestBroadcastHeight`: kotlin.UInt, + val `latestSpendingTxid`: Txid, + val `amountSatoshis`: kotlin.ULong, + ) : PendingSweepBalance() { + companion object + } + + data class AwaitingThresholdConfirmations( + val `channelId`: ChannelId?, + val `latestSpendingTxid`: Txid, + val `confirmationHash`: BlockHash, + val `confirmationHeight`: kotlin.UInt, + val `amountSatoshis`: kotlin.ULong, + ) : PendingSweepBalance() { + companion object + } + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypePendingSweepBalance : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): PendingSweepBalance = + when (buf.getInt()) { + 1 -> { + PendingSweepBalance.PendingBroadcast( + FfiConverterOptionalTypeChannelId.read(buf), + FfiConverterULong.read(buf), + ) + } + + 2 -> { + PendingSweepBalance.BroadcastAwaitingConfirmation( + FfiConverterOptionalTypeChannelId.read(buf), + FfiConverterUInt.read(buf), + FfiConverterTypeTxid.read(buf), + FfiConverterULong.read(buf), + ) + } + + 3 -> { + PendingSweepBalance.AwaitingThresholdConfirmations( + FfiConverterOptionalTypeChannelId.read(buf), + FfiConverterTypeTxid.read(buf), + FfiConverterTypeBlockHash.read(buf), + FfiConverterUInt.read(buf), + FfiConverterULong.read(buf), + ) + } + + else -> { + throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: PendingSweepBalance) = + when (value) { + is PendingSweepBalance.PendingBroadcast -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterOptionalTypeChannelId.allocationSize(value.`channelId`) + + FfiConverterULong.allocationSize(value.`amountSatoshis`) + ) + } + + is PendingSweepBalance.BroadcastAwaitingConfirmation -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterOptionalTypeChannelId.allocationSize(value.`channelId`) + + FfiConverterUInt.allocationSize(value.`latestBroadcastHeight`) + + FfiConverterTypeTxid.allocationSize(value.`latestSpendingTxid`) + + FfiConverterULong.allocationSize(value.`amountSatoshis`) + ) + } + + is PendingSweepBalance.AwaitingThresholdConfirmations -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterOptionalTypeChannelId.allocationSize(value.`channelId`) + + FfiConverterTypeTxid.allocationSize(value.`latestSpendingTxid`) + + FfiConverterTypeBlockHash.allocationSize(value.`confirmationHash`) + + FfiConverterUInt.allocationSize(value.`confirmationHeight`) + + FfiConverterULong.allocationSize(value.`amountSatoshis`) + ) + } + } + + override fun write( + value: PendingSweepBalance, + buf: ByteBuffer, + ) { + when (value) { + is PendingSweepBalance.PendingBroadcast -> { + buf.putInt(1) + FfiConverterOptionalTypeChannelId.write(value.`channelId`, buf) + FfiConverterULong.write(value.`amountSatoshis`, buf) + Unit + } + + is PendingSweepBalance.BroadcastAwaitingConfirmation -> { + buf.putInt(2) + FfiConverterOptionalTypeChannelId.write(value.`channelId`, buf) + FfiConverterUInt.write(value.`latestBroadcastHeight`, buf) + FfiConverterTypeTxid.write(value.`latestSpendingTxid`, buf) + FfiConverterULong.write(value.`amountSatoshis`, buf) + Unit + } + + is PendingSweepBalance.AwaitingThresholdConfirmations -> { + buf.putInt(3) + FfiConverterOptionalTypeChannelId.write(value.`channelId`, buf) + FfiConverterTypeTxid.write(value.`latestSpendingTxid`, buf) + FfiConverterTypeBlockHash.write(value.`confirmationHash`, buf) + FfiConverterUInt.write(value.`confirmationHeight`, buf) + FfiConverterULong.write(value.`amountSatoshis`, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +sealed class QrPaymentResult { + data class Onchain( + val `txid`: Txid, + ) : QrPaymentResult() { + companion object + } + + data class Bolt11( + val `paymentId`: PaymentId, + ) : QrPaymentResult() { + companion object + } + + data class Bolt12( + val `paymentId`: PaymentId, + ) : QrPaymentResult() { + companion object + } + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeQrPaymentResult : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): QrPaymentResult = + when (buf.getInt()) { + 1 -> { + QrPaymentResult.Onchain( + FfiConverterTypeTxid.read(buf), + ) + } + + 2 -> { + QrPaymentResult.Bolt11( + FfiConverterTypePaymentId.read(buf), + ) + } + + 3 -> { + QrPaymentResult.Bolt12( + FfiConverterTypePaymentId.read(buf), + ) + } + + else -> { + throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + + override fun allocationSize(value: QrPaymentResult) = + when (value) { + is QrPaymentResult.Onchain -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypeTxid.allocationSize(value.`txid`) + ) + } + + is QrPaymentResult.Bolt11 -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypePaymentId.allocationSize(value.`paymentId`) + ) + } + + is QrPaymentResult.Bolt12 -> { + // Add the size for the Int that specifies the variant plus the size needed for all fields + ( + 4UL + + FfiConverterTypePaymentId.allocationSize(value.`paymentId`) + ) + } + } + + override fun write( + value: QrPaymentResult, + buf: ByteBuffer, + ) { + when (value) { + is QrPaymentResult.Onchain -> { + buf.putInt(1) + FfiConverterTypeTxid.write(value.`txid`, buf) + Unit + } + + is QrPaymentResult.Bolt11 -> { + buf.putInt(2) + FfiConverterTypePaymentId.write(value.`paymentId`, buf) + Unit + } + + is QrPaymentResult.Bolt12 -> { + buf.putInt(3) + FfiConverterTypePaymentId.write(value.`paymentId`, buf) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +enum class SyncType { + ONCHAIN_WALLET, + LIGHTNING_WALLET, + FEE_RATE_CACHE, + ; + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeSyncType : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer) = + try { + SyncType.values()[buf.getInt() - 1] + } catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + + override fun allocationSize(value: SyncType) = 4UL + + override fun write( + value: SyncType, + buf: ByteBuffer, + ) { + buf.putInt(value.ordinal + 1) + } +} + +sealed class VssHeaderProviderException( + message: String, +) : kotlin.Exception(message) { + class InvalidData( + message: String, + ) : VssHeaderProviderException(message) + + class RequestException( + message: String, + ) : VssHeaderProviderException(message) + + class AuthorizationException( + message: String, + ) : VssHeaderProviderException(message) + + class InternalException( + message: String, + ) : VssHeaderProviderException(message) + + companion object ErrorHandler : UniffiRustCallStatusErrorHandler { + override fun lift(error_buf: RustBuffer.ByValue): VssHeaderProviderException = + FfiConverterTypeVssHeaderProviderError.lift(error_buf) + } +} + +/** + * @suppress + */ +public object FfiConverterTypeVssHeaderProviderError : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): VssHeaderProviderException = + when (buf.getInt()) { + 1 -> VssHeaderProviderException.InvalidData(FfiConverterString.read(buf)) + 2 -> VssHeaderProviderException.RequestException(FfiConverterString.read(buf)) + 3 -> VssHeaderProviderException.AuthorizationException(FfiConverterString.read(buf)) + 4 -> VssHeaderProviderException.InternalException(FfiConverterString.read(buf)) + else -> throw RuntimeException("invalid error enum value, something is very wrong!!") + } + + override fun allocationSize(value: VssHeaderProviderException): ULong = 4UL + + override fun write( + value: VssHeaderProviderException, + buf: ByteBuffer, + ) { + when (value) { + is VssHeaderProviderException.InvalidData -> { + buf.putInt(1) + Unit + } + + is VssHeaderProviderException.RequestException -> { + buf.putInt(2) + Unit + } + + is VssHeaderProviderException.AuthorizationException -> { + buf.putInt(3) + Unit + } + + is VssHeaderProviderException.InternalException -> { + buf.putInt(4) + Unit + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } +} + +enum class WordCount { + WORDS12, + WORDS15, + WORDS18, + WORDS21, + WORDS24, + ; + + companion object +} + +/** + * @suppress + */ +public object FfiConverterTypeWordCount : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer) = + try { + WordCount.values()[buf.getInt() - 1] + } catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + + override fun allocationSize(value: WordCount) = 4UL + + override fun write( + value: WordCount, + buf: ByteBuffer, + ) { + buf.putInt(value.ordinal + 1) + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalUShort : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): kotlin.UShort? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterUShort.read(buf) + } + + override fun allocationSize(value: kotlin.UShort?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterUShort.allocationSize(value) + } + } + + override fun write( + value: kotlin.UShort?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterUShort.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalUInt : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): kotlin.UInt? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterUInt.read(buf) + } + + override fun allocationSize(value: kotlin.UInt?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterUInt.allocationSize(value) + } + } + + override fun write( + value: kotlin.UInt?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterUInt.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalULong : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): kotlin.ULong? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterULong.read(buf) + } + + override fun allocationSize(value: kotlin.ULong?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterULong.allocationSize(value) + } + } + + override fun write( + value: kotlin.ULong?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterULong.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalBoolean : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): kotlin.Boolean? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterBoolean.read(buf) + } + + override fun allocationSize(value: kotlin.Boolean?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterBoolean.allocationSize(value) + } + } + + override fun write( + value: kotlin.Boolean?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterBoolean.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalString : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): kotlin.String? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterString.read(buf) + } + + override fun allocationSize(value: kotlin.String?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterString.allocationSize(value) + } + } + + override fun write( + value: kotlin.String?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterString.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeFeeRate : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): FeeRate? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeFeeRate.read(buf) + } + + override fun allocationSize(value: FeeRate?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeFeeRate.allocationSize(value) + } + } + + override fun write( + value: FeeRate?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeFeeRate.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeAnchorChannelsConfig : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): AnchorChannelsConfig? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeAnchorChannelsConfig.read(buf) + } + + override fun allocationSize(value: AnchorChannelsConfig?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeAnchorChannelsConfig.allocationSize(value) + } + } + + override fun write( + value: AnchorChannelsConfig?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeAnchorChannelsConfig.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeBackgroundSyncConfig : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): BackgroundSyncConfig? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeBackgroundSyncConfig.read(buf) + } + + override fun allocationSize(value: BackgroundSyncConfig?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeBackgroundSyncConfig.allocationSize(value) + } + } + + override fun write( + value: BackgroundSyncConfig?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeBackgroundSyncConfig.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeChannelConfig : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): ChannelConfig? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeChannelConfig.read(buf) + } + + override fun allocationSize(value: ChannelConfig?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeChannelConfig.allocationSize(value) + } + } + + override fun write( + value: ChannelConfig?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeChannelConfig.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeChannelInfo : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): ChannelInfo? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeChannelInfo.read(buf) + } + + override fun allocationSize(value: ChannelInfo?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeChannelInfo.allocationSize(value) + } + } + + override fun write( + value: ChannelInfo?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeChannelInfo.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeChannelUpdateInfo : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): ChannelUpdateInfo? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeChannelUpdateInfo.read(buf) + } + + override fun allocationSize(value: ChannelUpdateInfo?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeChannelUpdateInfo.allocationSize(value) + } + } + + override fun write( + value: ChannelUpdateInfo?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeChannelUpdateInfo.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeElectrumSyncConfig : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): ElectrumSyncConfig? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeElectrumSyncConfig.read(buf) + } + + override fun allocationSize(value: ElectrumSyncConfig?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeElectrumSyncConfig.allocationSize(value) + } + } + + override fun write( + value: ElectrumSyncConfig?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeElectrumSyncConfig.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeEsploraSyncConfig : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): EsploraSyncConfig? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeEsploraSyncConfig.read(buf) + } + + override fun allocationSize(value: EsploraSyncConfig?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeEsploraSyncConfig.allocationSize(value) + } + } + + override fun write( + value: EsploraSyncConfig?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeEsploraSyncConfig.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeLSPS1Bolt11PaymentInfo : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): Lsps1Bolt11PaymentInfo? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeLSPS1Bolt11PaymentInfo.read(buf) + } + + override fun allocationSize(value: Lsps1Bolt11PaymentInfo?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeLSPS1Bolt11PaymentInfo.allocationSize(value) + } + } + + override fun write( + value: Lsps1Bolt11PaymentInfo?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeLSPS1Bolt11PaymentInfo.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeLSPS1ChannelInfo : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): Lsps1ChannelInfo? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeLSPS1ChannelInfo.read(buf) + } + + override fun allocationSize(value: Lsps1ChannelInfo?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeLSPS1ChannelInfo.allocationSize(value) + } + } + + override fun write( + value: Lsps1ChannelInfo?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeLSPS1ChannelInfo.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeLSPS1OnchainPaymentInfo : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): Lsps1OnchainPaymentInfo? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeLSPS1OnchainPaymentInfo.read(buf) + } + + override fun allocationSize(value: Lsps1OnchainPaymentInfo?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeLSPS1OnchainPaymentInfo.allocationSize(value) + } + } + + override fun write( + value: Lsps1OnchainPaymentInfo?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeLSPS1OnchainPaymentInfo.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeNodeAnnouncementInfo : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): NodeAnnouncementInfo? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeNodeAnnouncementInfo.read(buf) + } + + override fun allocationSize(value: NodeAnnouncementInfo?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeNodeAnnouncementInfo.allocationSize(value) + } + } + + override fun write( + value: NodeAnnouncementInfo?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeNodeAnnouncementInfo.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeNodeInfo : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): NodeInfo? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeNodeInfo.read(buf) + } + + override fun allocationSize(value: NodeInfo?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeNodeInfo.allocationSize(value) + } + } + + override fun write( + value: NodeInfo?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeNodeInfo.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeOutPoint : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): OutPoint? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeOutPoint.read(buf) + } + + override fun allocationSize(value: OutPoint?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeOutPoint.allocationSize(value) + } + } + + override fun write( + value: OutPoint?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeOutPoint.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypePaymentDetails : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): PaymentDetails? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypePaymentDetails.read(buf) + } + + override fun allocationSize(value: PaymentDetails?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypePaymentDetails.allocationSize(value) + } + } + + override fun write( + value: PaymentDetails?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypePaymentDetails.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeRouteParametersConfig : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): RouteParametersConfig? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeRouteParametersConfig.read(buf) + } + + override fun allocationSize(value: RouteParametersConfig?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeRouteParametersConfig.allocationSize(value) + } + } + + override fun write( + value: RouteParametersConfig?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeRouteParametersConfig.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeTransactionDetails : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): TransactionDetails? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeTransactionDetails.read(buf) + } + + override fun allocationSize(value: TransactionDetails?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeTransactionDetails.allocationSize(value) + } + } + + override fun write( + value: TransactionDetails?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeTransactionDetails.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeAsyncPaymentsRole : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): AsyncPaymentsRole? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeAsyncPaymentsRole.read(buf) + } + + override fun allocationSize(value: AsyncPaymentsRole?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeAsyncPaymentsRole.allocationSize(value) + } + } + + override fun write( + value: AsyncPaymentsRole?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeAsyncPaymentsRole.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeClosureReason : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): ClosureReason? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeClosureReason.read(buf) + } + + override fun allocationSize(value: ClosureReason?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeClosureReason.allocationSize(value) + } + } + + override fun write( + value: ClosureReason?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeClosureReason.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeEvent : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): Event? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeEvent.read(buf) + } + + override fun allocationSize(value: Event?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeEvent.allocationSize(value) + } + } + + override fun write( + value: Event?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeEvent.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeLogLevel : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): LogLevel? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeLogLevel.read(buf) + } + + override fun allocationSize(value: LogLevel?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeLogLevel.allocationSize(value) + } + } + + override fun write( + value: LogLevel?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeLogLevel.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeNetwork : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): Network? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeNetwork.read(buf) + } + + override fun allocationSize(value: Network?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeNetwork.allocationSize(value) + } + } + + override fun write( + value: Network?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeNetwork.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeOfferAmount : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): OfferAmount? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeOfferAmount.read(buf) + } + + override fun allocationSize(value: OfferAmount?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeOfferAmount.allocationSize(value) + } + } + + override fun write( + value: OfferAmount?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeOfferAmount.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypePaymentFailureReason : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): PaymentFailureReason? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypePaymentFailureReason.read(buf) + } + + override fun allocationSize(value: PaymentFailureReason?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypePaymentFailureReason.allocationSize(value) + } + } + + override fun write( + value: PaymentFailureReason?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypePaymentFailureReason.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeWordCount : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): WordCount? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeWordCount.read(buf) + } + + override fun allocationSize(value: WordCount?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeWordCount.allocationSize(value) + } + } + + override fun write( + value: WordCount?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeWordCount.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalSequenceUByte : FfiConverterRustBuffer?> { + override fun read(buf: ByteBuffer): List? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterSequenceUByte.read(buf) + } + + override fun allocationSize(value: List?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterSequenceUByte.allocationSize(value) + } + } + + override fun write( + value: List?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterSequenceUByte.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalSequenceTypeSpendableUtxo : FfiConverterRustBuffer?> { + override fun read(buf: ByteBuffer): List? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterSequenceTypeSpendableUtxo.read(buf) + } + + override fun allocationSize(value: List?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterSequenceTypeSpendableUtxo.allocationSize(value) + } + } + + override fun write( + value: List?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterSequenceTypeSpendableUtxo.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalSequenceSequenceUByte : FfiConverterRustBuffer>?> { + override fun read(buf: ByteBuffer): List>? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterSequenceSequenceUByte.read(buf) + } + + override fun allocationSize(value: List>?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterSequenceSequenceUByte.allocationSize(value) + } + } + + override fun write( + value: List>?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterSequenceSequenceUByte.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalSequenceTypeSocketAddress : FfiConverterRustBuffer?> { + override fun read(buf: ByteBuffer): List? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterSequenceTypeSocketAddress.read(buf) + } + + override fun allocationSize(value: List?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterSequenceTypeSocketAddress.allocationSize(value) + } + } + + override fun write( + value: List?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterSequenceTypeSocketAddress.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeAddress : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): Address? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeAddress.read(buf) + } + + override fun allocationSize(value: Address?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeAddress.allocationSize(value) + } + } + + override fun write( + value: Address?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeAddress.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeChannelId : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): ChannelId? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeChannelId.read(buf) + } + + override fun allocationSize(value: ChannelId?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeChannelId.allocationSize(value) + } + } + + override fun write( + value: ChannelId?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeChannelId.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeNodeAlias : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): NodeAlias? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeNodeAlias.read(buf) + } + + override fun allocationSize(value: NodeAlias?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeNodeAlias.allocationSize(value) + } + } + + override fun write( + value: NodeAlias?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeNodeAlias.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypePaymentHash : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): PaymentHash? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypePaymentHash.read(buf) + } + + override fun allocationSize(value: PaymentHash?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypePaymentHash.allocationSize(value) + } + } + + override fun write( + value: PaymentHash?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypePaymentHash.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypePaymentId : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): PaymentId? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypePaymentId.read(buf) + } + + override fun allocationSize(value: PaymentId?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypePaymentId.allocationSize(value) + } + } + + override fun write( + value: PaymentId?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypePaymentId.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypePaymentPreimage : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): PaymentPreimage? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypePaymentPreimage.read(buf) + } + + override fun allocationSize(value: PaymentPreimage?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypePaymentPreimage.allocationSize(value) + } + } + + override fun write( + value: PaymentPreimage?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypePaymentPreimage.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypePaymentSecret : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): PaymentSecret? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypePaymentSecret.read(buf) + } + + override fun allocationSize(value: PaymentSecret?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypePaymentSecret.allocationSize(value) + } + } + + override fun write( + value: PaymentSecret?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypePaymentSecret.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypePublicKey : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): PublicKey? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypePublicKey.read(buf) + } + + override fun allocationSize(value: PublicKey?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypePublicKey.allocationSize(value) + } + } + + override fun write( + value: PublicKey?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypePublicKey.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeUntrustedString : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): UntrustedString? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeUntrustedString.read(buf) + } + + override fun allocationSize(value: UntrustedString?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeUntrustedString.allocationSize(value) + } + } + + override fun write( + value: UntrustedString?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeUntrustedString.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterOptionalTypeUserChannelId : FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): UserChannelId? { + if (buf.get().toInt() == 0) { + return null + } + return FfiConverterTypeUserChannelId.read(buf) + } + + override fun allocationSize(value: UserChannelId?): ULong { + if (value == null) { + return 1UL + } else { + return 1UL + FfiConverterTypeUserChannelId.allocationSize(value) + } + } + + override fun write( + value: UserChannelId?, + buf: ByteBuffer, + ) { + if (value == null) { + buf.put(0) + } else { + buf.put(1) + FfiConverterTypeUserChannelId.write(value, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterSequenceUByte : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterUByte.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterUByte.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write( + value: List, + buf: ByteBuffer, + ) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterUByte.write(it, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterSequenceULong : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterULong.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterULong.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write( + value: List, + buf: ByteBuffer, + ) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterULong.write(it, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterSequenceString : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterString.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterString.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write( + value: List, + buf: ByteBuffer, + ) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterString.write(it, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterSequenceTypeChannelDetails : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterTypeChannelDetails.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeChannelDetails.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write( + value: List, + buf: ByteBuffer, + ) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterTypeChannelDetails.write(it, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterSequenceTypeCustomTlvRecord : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterTypeCustomTlvRecord.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeCustomTlvRecord.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write( + value: List, + buf: ByteBuffer, + ) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterTypeCustomTlvRecord.write(it, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterSequenceTypePaymentDetails : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterTypePaymentDetails.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypePaymentDetails.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write( + value: List, + buf: ByteBuffer, + ) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterTypePaymentDetails.write(it, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterSequenceTypePeerDetails : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterTypePeerDetails.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypePeerDetails.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write( + value: List, + buf: ByteBuffer, + ) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterTypePeerDetails.write(it, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterSequenceTypeRouteHintHop : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterTypeRouteHintHop.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeRouteHintHop.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write( + value: List, + buf: ByteBuffer, + ) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterTypeRouteHintHop.write(it, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterSequenceTypeSpendableUtxo : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterTypeSpendableUtxo.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeSpendableUtxo.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write( + value: List, + buf: ByteBuffer, + ) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterTypeSpendableUtxo.write(it, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterSequenceTypeTxInput : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterTypeTxInput.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeTxInput.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write( + value: List, + buf: ByteBuffer, + ) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterTypeTxInput.write(it, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterSequenceTypeTxOutput : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterTypeTxOutput.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeTxOutput.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write( + value: List, + buf: ByteBuffer, + ) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterTypeTxOutput.write(it, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterSequenceTypeLightningBalance : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterTypeLightningBalance.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeLightningBalance.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write( + value: List, + buf: ByteBuffer, + ) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterTypeLightningBalance.write(it, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterSequenceTypeNetwork : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterTypeNetwork.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeNetwork.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write( + value: List, + buf: ByteBuffer, + ) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterTypeNetwork.write(it, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterSequenceTypePendingSweepBalance : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterTypePendingSweepBalance.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypePendingSweepBalance.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write( + value: List, + buf: ByteBuffer, + ) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterTypePendingSweepBalance.write(it, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterSequenceSequenceUByte : FfiConverterRustBuffer>> { + override fun read(buf: ByteBuffer): List> { + val len = buf.getInt() + return List>(len) { + FfiConverterSequenceUByte.read(buf) + } + } + + override fun allocationSize(value: List>): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterSequenceUByte.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write( + value: List>, + buf: ByteBuffer, + ) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterSequenceUByte.write(it, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterSequenceSequenceTypeRouteHintHop : FfiConverterRustBuffer>> { + override fun read(buf: ByteBuffer): List> { + val len = buf.getInt() + return List>(len) { + FfiConverterSequenceTypeRouteHintHop.read(buf) + } + } + + override fun allocationSize(value: List>): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterSequenceTypeRouteHintHop.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write( + value: List>, + buf: ByteBuffer, + ) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterSequenceTypeRouteHintHop.write(it, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterSequenceTypeAddress : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List
{ + val len = buf.getInt() + return List
(len) { + FfiConverterTypeAddress.read(buf) + } + } + + override fun allocationSize(value: List
): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeAddress.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write( + value: List
, + buf: ByteBuffer, + ) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterTypeAddress.write(it, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterSequenceTypeNodeId : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterTypeNodeId.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeNodeId.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write( + value: List, + buf: ByteBuffer, + ) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterTypeNodeId.write(it, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterSequenceTypePublicKey : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterTypePublicKey.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypePublicKey.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write( + value: List, + buf: ByteBuffer, + ) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterTypePublicKey.write(it, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterSequenceTypeSocketAddress : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterTypeSocketAddress.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeSocketAddress.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write( + value: List, + buf: ByteBuffer, + ) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterTypeSocketAddress.write(it, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterSequenceTypeTxid : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): List { + val len = buf.getInt() + return List(len) { + FfiConverterTypeTxid.read(buf) + } + } + + override fun allocationSize(value: List): ULong { + val sizeForLength = 4UL + val sizeForItems = value.map { FfiConverterTypeTxid.allocationSize(it) }.sum() + return sizeForLength + sizeForItems + } + + override fun write( + value: List, + buf: ByteBuffer, + ) { + buf.putInt(value.size) + value.iterator().forEach { + FfiConverterTypeTxid.write(it, buf) + } + } +} + +/** + * @suppress + */ +public object FfiConverterMapStringString : FfiConverterRustBuffer> { + override fun read(buf: ByteBuffer): Map { + val len = buf.getInt() + return buildMap(len) { + repeat(len) { + val k = FfiConverterString.read(buf) + val v = FfiConverterString.read(buf) + this[k] = v + } + } + } + + override fun allocationSize(value: Map): ULong { + val spaceForMapSize = 4UL + val spaceForChildren = + value + .map { (k, v) -> + FfiConverterString.allocationSize(k) + + FfiConverterString.allocationSize(v) + }.sum() + return spaceForMapSize + spaceForChildren + } + + override fun write( + value: Map, + buf: ByteBuffer, + ) { + buf.putInt(value.size) + // The parens on `(k, v)` here ensure we're calling the right method, + // which is important for compatibility with older android devices. + // Ref https://blog.danlew.net/2017/03/16/kotlin-puzzler-whose-line-is-it-anyways/ + value.forEach { (k, v) -> + FfiConverterString.write(k, buf) + FfiConverterString.write(v, buf) + } + } +} + +/** + * Typealias from the type name used in the UDL file to the builtin type. This + * is needed because the UDL type name is used in function/method signatures. + * It's also what we have an external type that references a custom type. + */ +public typealias Address = kotlin.String +public typealias FfiConverterTypeAddress = FfiConverterString + +/** + * Typealias from the type name used in the UDL file to the builtin type. This + * is needed because the UDL type name is used in function/method signatures. + * It's also what we have an external type that references a custom type. + */ +public typealias BlockHash = kotlin.String +public typealias FfiConverterTypeBlockHash = FfiConverterString + +/** + * Typealias from the type name used in the UDL file to the builtin type. This + * is needed because the UDL type name is used in function/method signatures. + * It's also what we have an external type that references a custom type. + */ +public typealias ChannelId = kotlin.String +public typealias FfiConverterTypeChannelId = FfiConverterString + +/** + * Typealias from the type name used in the UDL file to the builtin type. This + * is needed because the UDL type name is used in function/method signatures. + * It's also what we have an external type that references a custom type. + */ +public typealias Lsps1OrderId = kotlin.String +public typealias FfiConverterTypeLSPS1OrderId = FfiConverterString + +/** + * Typealias from the type name used in the UDL file to the builtin type. This + * is needed because the UDL type name is used in function/method signatures. + * It's also what we have an external type that references a custom type. + */ +public typealias LspsDateTime = kotlin.String +public typealias FfiConverterTypeLSPSDateTime = FfiConverterString + +/** + * Typealias from the type name used in the UDL file to the builtin type. This + * is needed because the UDL type name is used in function/method signatures. + * It's also what we have an external type that references a custom type. + */ +public typealias Mnemonic = kotlin.String +public typealias FfiConverterTypeMnemonic = FfiConverterString + +/** + * Typealias from the type name used in the UDL file to the builtin type. This + * is needed because the UDL type name is used in function/method signatures. + * It's also what we have an external type that references a custom type. + */ +public typealias NodeAlias = kotlin.String +public typealias FfiConverterTypeNodeAlias = FfiConverterString + +/** + * Typealias from the type name used in the UDL file to the builtin type. This + * is needed because the UDL type name is used in function/method signatures. + * It's also what we have an external type that references a custom type. + */ +public typealias NodeId = kotlin.String +public typealias FfiConverterTypeNodeId = FfiConverterString + +/** + * Typealias from the type name used in the UDL file to the builtin type. This + * is needed because the UDL type name is used in function/method signatures. + * It's also what we have an external type that references a custom type. + */ +public typealias OfferId = kotlin.String +public typealias FfiConverterTypeOfferId = FfiConverterString + +/** + * Typealias from the type name used in the UDL file to the builtin type. This + * is needed because the UDL type name is used in function/method signatures. + * It's also what we have an external type that references a custom type. + */ +public typealias PaymentHash = kotlin.String +public typealias FfiConverterTypePaymentHash = FfiConverterString + +/** + * Typealias from the type name used in the UDL file to the builtin type. This + * is needed because the UDL type name is used in function/method signatures. + * It's also what we have an external type that references a custom type. + */ +public typealias PaymentId = kotlin.String +public typealias FfiConverterTypePaymentId = FfiConverterString + +/** + * Typealias from the type name used in the UDL file to the builtin type. This + * is needed because the UDL type name is used in function/method signatures. + * It's also what we have an external type that references a custom type. + */ +public typealias PaymentPreimage = kotlin.String +public typealias FfiConverterTypePaymentPreimage = FfiConverterString + +/** + * Typealias from the type name used in the UDL file to the builtin type. This + * is needed because the UDL type name is used in function/method signatures. + * It's also what we have an external type that references a custom type. + */ +public typealias PaymentSecret = kotlin.String +public typealias FfiConverterTypePaymentSecret = FfiConverterString + +/** + * Typealias from the type name used in the UDL file to the builtin type. This + * is needed because the UDL type name is used in function/method signatures. + * It's also what we have an external type that references a custom type. + */ +public typealias PublicKey = kotlin.String +public typealias FfiConverterTypePublicKey = FfiConverterString + +/** + * Typealias from the type name used in the UDL file to the builtin type. This + * is needed because the UDL type name is used in function/method signatures. + * It's also what we have an external type that references a custom type. + */ +public typealias SocketAddress = kotlin.String +public typealias FfiConverterTypeSocketAddress = FfiConverterString + +/** + * Typealias from the type name used in the UDL file to the builtin type. This + * is needed because the UDL type name is used in function/method signatures. + * It's also what we have an external type that references a custom type. + */ +public typealias Txid = kotlin.String +public typealias FfiConverterTypeTxid = FfiConverterString + +/** + * Typealias from the type name used in the UDL file to the builtin type. This + * is needed because the UDL type name is used in function/method signatures. + * It's also what we have an external type that references a custom type. + */ +public typealias UntrustedString = kotlin.String +public typealias FfiConverterTypeUntrustedString = FfiConverterString + +/** + * Typealias from the type name used in the UDL file to the builtin type. This + * is needed because the UDL type name is used in function/method signatures. + * It's also what we have an external type that references a custom type. + */ +public typealias UserChannelId = kotlin.String +public typealias FfiConverterTypeUserChannelId = FfiConverterString + +fun `batterySavingSyncIntervals`(): RuntimeSyncIntervals = + FfiConverterTypeRuntimeSyncIntervals.lift( + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_func_battery_saving_sync_intervals(_status) + }, + ) + +fun `defaultConfig`(): Config = + FfiConverterTypeConfig.lift( + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_func_default_config(_status) + }, + ) + +@Throws(NodeException::class) +fun `deriveNodeSecretFromMnemonic`( + `mnemonic`: kotlin.String, + `passphrase`: kotlin.String?, +): List = + FfiConverterSequenceUByte.lift( + uniffiRustCallWithError(NodeException) { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_func_derive_node_secret_from_mnemonic( + FfiConverterString.lower(`mnemonic`), + FfiConverterOptionalString.lower(`passphrase`), + _status, + ) + }, + ) + +fun `generateEntropyMnemonic`(`wordCount`: WordCount?): Mnemonic = + FfiConverterTypeMnemonic.lift( + uniffiRustCall { _status -> + UniffiLib.INSTANCE.uniffi_ldk_node_fn_func_generate_entropy_mnemonic( + FfiConverterOptionalTypeWordCount.lower(`wordCount`), + _status, + ) + }, + ) diff --git a/bindings/kotlin/ldk-node-jvm/lib/src/main/resources/darwin-aarch64/libldk_node.dylib b/bindings/kotlin/ldk-node-jvm/lib/src/main/resources/darwin-aarch64/libldk_node.dylib new file mode 100644 index 000000000..173c7b955 Binary files /dev/null and b/bindings/kotlin/ldk-node-jvm/lib/src/main/resources/darwin-aarch64/libldk_node.dylib differ diff --git a/bindings/kotlin/ldk-node-jvm/lib/src/main/resources/darwin-x86-64/libldk_node.dylib b/bindings/kotlin/ldk-node-jvm/lib/src/main/resources/darwin-x86-64/libldk_node.dylib new file mode 100644 index 000000000..199ee9332 Binary files /dev/null and b/bindings/kotlin/ldk-node-jvm/lib/src/main/resources/darwin-x86-64/libldk_node.dylib differ diff --git a/bindings/python/pyproject.toml b/bindings/python/pyproject.toml index 21b72ae6a..c617af13e 100644 --- a/bindings/python/pyproject.toml +++ b/bindings/python/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "ldk_node" -version = "0.7.0-rc.15" +version = "0.7.0-rc.16" authors = [ { name="Elias Rohrer", email="dev@tnull.de" }, ] diff --git a/jitpack.yml b/jitpack.yml index 498f41fcb..be1c0b44e 100644 --- a/jitpack.yml +++ b/jitpack.yml @@ -1,3 +1,4 @@ jdk: openjdk17 -before_install: - - cd bindings/kotlin/ldk-node-android +install: + - bindings/kotlin/ldk-node-android/gradlew -p bindings/kotlin/ldk-node-android publishToMavenLocal + - bindings/kotlin/ldk-node-jvm/gradlew -p bindings/kotlin/ldk-node-jvm publishToMavenLocal diff --git a/scripts/uniffi_bindgen_generate_kotlin.sh b/scripts/uniffi_bindgen_generate_kotlin.sh index a1085600e..8242c2bc5 100755 --- a/scripts/uniffi_bindgen_generate_kotlin.sh +++ b/scripts/uniffi_bindgen_generate_kotlin.sh @@ -32,3 +32,11 @@ mkdir -p "$BINDINGS_DIR"/"$PROJECT_DIR"/lib/src/main/kotlin/"$PACKAGE_DIR" || ex $UNIFFI_BINDGEN_BIN generate bindings/ldk_node.udl --language kotlin -o "$TARGET_DIR" || exit 1 cp "$TARGET_DIR"/"$PACKAGE_DIR"/ldk_node.kt "$BINDINGS_DIR"/"$PROJECT_DIR"/lib/src/main/kotlin/"$PACKAGE_DIR"/ || exit 1 + +# Sync version from Cargo.toml +echo "Syncing version from Cargo.toml..." +CARGO_VERSION=$(grep '^version = ' Cargo.toml | sed 's/version = "\(.*\)"/\1/' | head -1) +JVM_LIB_DIR="$BINDINGS_DIR/$PROJECT_DIR" +sed -i.bak "s/^libraryVersion=.*/libraryVersion=$CARGO_VERSION/" "$JVM_LIB_DIR/gradle.properties" +rm -f "$JVM_LIB_DIR/gradle.properties.bak" +echo "JVM version synced: $CARGO_VERSION"