diff --git a/docs.patch b/docs.patch index 4b51bdd..8fb620f 100644 --- a/docs.patch +++ b/docs.patch @@ -1,7 +1,8 @@ -*** bdkwithoutdocs.kt 2022-04-05 16:38:27.692000000 -0700 ---- bdk.kt 2022-04-05 16:40:51.727000000 -0700 +*** tmp/bdkwithoutdocs.kt 2022-05-12 15:13:30.132174559 -0700 +--- jvm/src/main/kotlin/org/bitcoindevkit/bdk.kt 2022-05-12 15:36:05.744074453 -0700 *************** -*** 17,131 **** +*** 16,131 **** + // 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. @@ -21,7 +22,7 @@ // 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. - +! @Structure.FieldOrder("capacity", "len", "data") open class RustBuffer : Structure() { @JvmField var capacity: Int = 0 @@ -33,7 +34,7 @@ companion object { internal fun alloc(size: Int = 0) = rustCall() { status -> - _UniFFILib.INSTANCE.ffi_bdk_9c03_rustbuffer_alloc(size, status).also { + _UniFFILib.INSTANCE.ffi_bdk_360_rustbuffer_alloc(size, status).also { if(it.data == null) { throw RuntimeException("RustBuffer.alloc() returned null data pointer (size=${size})") } @@ -41,11 +42,11 @@ } internal fun free(buf: RustBuffer.ByValue) = rustCall() { status -> - _UniFFILib.INSTANCE.ffi_bdk_9c03_rustbuffer_free(buf, status) + _UniFFILib.INSTANCE.ffi_bdk_360_rustbuffer_free(buf, status) } internal fun reserve(buf: RustBuffer.ByValue, additional: Int) = rustCall() { status -> - _UniFFILib.INSTANCE.ffi_bdk_9c03_rustbuffer_reserve(buf, additional, status) + _UniFFILib.INSTANCE.ffi_bdk_360_rustbuffer_reserve(buf, additional, status) } } @@ -57,10 +58,10 @@ } /** -! * 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. + * 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. */ class RustBufferByReference : ByReference(16) { /** @@ -117,7 +118,8 @@ fun finalize() : RustBuffer.ByValue { val rbuf = this.rbuf ---- 17,145 ---- +--- 16,141 ---- + // 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. @@ -137,10 +139,9 @@ // 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 -+ */ +! /** +! * @suppress +! */ @Structure.FieldOrder("capacity", "len", "data") open class RustBuffer : Structure() { @JvmField var capacity: Int = 0 @@ -150,12 +151,9 @@ class ByValue : RustBuffer(), Structure.ByValue class ByReference : RustBuffer(), Structure.ByReference -+ /** -+ * @suppress -+ */ companion object { internal fun alloc(size: Int = 0) = rustCall() { status -> - _UniFFILib.INSTANCE.ffi_bdk_9c03_rustbuffer_alloc(size, status).also { + _UniFFILib.INSTANCE.ffi_bdk_360_rustbuffer_alloc(size, status).also { if(it.data == null) { throw RuntimeException("RustBuffer.alloc() returned null data pointer (size=${size})") } @@ -163,11 +161,11 @@ } internal fun free(buf: RustBuffer.ByValue) = rustCall() { status -> - _UniFFILib.INSTANCE.ffi_bdk_9c03_rustbuffer_free(buf, status) + _UniFFILib.INSTANCE.ffi_bdk_360_rustbuffer_free(buf, status) } internal fun reserve(buf: RustBuffer.ByValue, additional: Int) = rustCall() { status -> - _UniFFILib.INSTANCE.ffi_bdk_9c03_rustbuffer_reserve(buf, additional, status) + _UniFFILib.INSTANCE.ffi_bdk_360_rustbuffer_reserve(buf, additional, status) } } @@ -178,15 +176,15 @@ } } -+ ///** -+ // * 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 + * 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. @@ -248,8 +246,122 @@ fun finalize() : RustBuffer.ByValue { val rbuf = this.rbuf *************** -*** 232,304 **** ---- 246,327 ---- +*** 232,345 **** + // This would be a good candidate for isolating in its own ffi-support lib. + // Error runtime. + @Structure.FieldOrder("code", "error_buf") + internal open class RustCallStatus : Structure() { + @JvmField var code: Int = 0 + @JvmField var error_buf: RustBuffer.ByValue = RustBuffer.ByValue() + + fun isSuccess(): Boolean { + return code == 0 + } + + fun isError(): Boolean { + return code == 1 + } + + fun isPanic(): Boolean { + return code == 2 + } + } + + class InternalException(message: String) : Exception(message) + + // Each top-level error class has a companion object that can lift the error from the call status's rust buffer + interface CallStatusErrorHandler { + 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 rustCallWithError(errorHandler: CallStatusErrorHandler, callback: (RustCallStatus) -> U): U { + var status = RustCallStatus(); + val return_value = callback(status) + if (status.isSuccess()) { + return return_value + } 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(String.lift(status.error_buf)) + } else { + throw InternalException("Rust panic") + } + } else { + throw InternalException("Unknown rust call status: $status.code") + } + } + + // CallStatusErrorHandler implementation for times when we don't expect a CALL_ERROR + object NullCallStatusErrorHandler: CallStatusErrorHandler { + 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 rustCall(callback: (RustCallStatus) -> U): U { + return rustCallWithError(NullCallStatusErrorHandler, callback); + } + + // 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 "bdkffi" + } + + private inline fun loadIndirect( + componentName: String + ): Lib { + return Native.load(findLibraryName(componentName), Lib::class.java) + } + + // 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<_UniFFILib>(componentName = "bdk") + .also { lib: _UniFFILib -> + FfiConverterCallbackInterfaceProgress.register(lib) + } +! + } + } + + fun ffi_bdk_360_Blockchain_object_free(ptr: Pointer, + uniffi_out_err: RustCallStatus + ): Unit + + fun bdk_360_Blockchain_new(config: RustBuffer.ByValue, + uniffi_out_err: RustCallStatus + ): Pointer + + fun bdk_360_Blockchain_broadcast(ptr: Pointer,psbt: Pointer, + uniffi_out_err: RustCallStatus + ): Unit + + fun ffi_bdk_360_Wallet_object_free(ptr: Pointer, + uniffi_out_err: RustCallStatus + ): Unit + + fun bdk_360_Wallet_new(descriptor: RustBuffer.ByValue,change_descriptor: RustBuffer.ByValue,network: RustBuffer.ByValue,database_config: RustBuffer.ByValue, +--- 242,364 ---- // This would be a good candidate for isolating in its own ffi-support lib. // Error runtime. @Structure.FieldOrder("code", "error_buf") @@ -332,17 +444,134 @@ val libOverride = System.getProperty("uniffi.component.$componentName.libraryOverride") if (libOverride != null) { return libOverride -*************** -*** 430,479 **** ---- 453,508 ---- + } + return "bdkffi" + } + + private inline fun loadIndirect( + componentName: String + ): Lib { + return Native.load(findLibraryName(componentName), Lib::class.java) + } + + // 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<_UniFFILib>(componentName = "bdk") + .also { lib: _UniFFILib -> + FfiConverterCallbackInterfaceProgress.register(lib) + } +! + } + } + + fun ffi_bdk_360_Blockchain_object_free(ptr: Pointer, uniffi_out_err: RustCallStatus ): Unit - fun ffi_bdk_9c03_rustbuffer_reserve(buf: RustBuffer.ByValue,additional: Int, + fun bdk_360_Blockchain_new(config: RustBuffer.ByValue, + uniffi_out_err: RustCallStatus + ): Pointer + + fun bdk_360_Blockchain_broadcast(ptr: Pointer,psbt: Pointer, + uniffi_out_err: RustCallStatus + ): Unit + + fun ffi_bdk_360_Wallet_object_free(ptr: Pointer, + uniffi_out_err: RustCallStatus + ): Unit + + fun bdk_360_Wallet_new(descriptor: RustBuffer.ByValue,change_descriptor: RustBuffer.ByValue,network: RustBuffer.ByValue,database_config: RustBuffer.ByValue, +*************** +*** 461,523 **** + fun bdk_360_restore_extended_key(network: RustBuffer.ByValue,mnemonic: RustBuffer.ByValue,password: RustBuffer.ByValue, uniffi_out_err: RustCallStatus ): RustBuffer.ByValue - + fun ffi_bdk_360_rustbuffer_alloc(size: Int, + uniffi_out_err: RustCallStatus + ): RustBuffer.ByValue + + fun ffi_bdk_360_rustbuffer_from_bytes(bytes: ForeignBytes.ByValue, + uniffi_out_err: RustCallStatus + ): RustBuffer.ByValue + + fun ffi_bdk_360_rustbuffer_free(buf: RustBuffer.ByValue, + uniffi_out_err: RustCallStatus + ): Unit + + fun ffi_bdk_360_rustbuffer_reserve(buf: RustBuffer.ByValue,additional: Int, + uniffi_out_err: RustCallStatus + ): RustBuffer.ByValue + +! + } + + // 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) + } + } + } + + 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 + } + } + + // The base class for all UniFFI Object types. + // + // This class provides core operations for working with the Rust `Arc` pointer to + // 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 + // the Kotlin wrapper object in lieu of reliable finalizers. The core requirements are: +--- 480,548 ---- + fun bdk_360_restore_extended_key(network: RustBuffer.ByValue,mnemonic: RustBuffer.ByValue,password: RustBuffer.ByValue, + uniffi_out_err: RustCallStatus + ): RustBuffer.ByValue + + fun ffi_bdk_360_rustbuffer_alloc(size: Int, + uniffi_out_err: RustCallStatus + ): RustBuffer.ByValue + + fun ffi_bdk_360_rustbuffer_from_bytes(bytes: ForeignBytes.ByValue, + uniffi_out_err: RustCallStatus + ): RustBuffer.ByValue + + fun ffi_bdk_360_rustbuffer_free(buf: RustBuffer.ByValue, + uniffi_out_err: RustCallStatus + ): Unit + + fun ffi_bdk_360_rustbuffer_reserve(buf: RustBuffer.ByValue,additional: Int, + uniffi_out_err: RustCallStatus + ): RustBuffer.ByValue + +! } // Public interface members begin here. @@ -392,8 +621,8 @@ // struct after it has been dropped, and because we must expose a public API for freeing // the Kotlin wrapper object in lieu of reliable finalizers. The core requirements are: *************** -*** 533,572 **** ---- 562,604 ---- +*** 577,638 **** +--- 602,672 ---- // Otherwise we atomically decrement and check the counter. // If it has reached zero then we destroy the underlying Rust struct. // @@ -428,6 +657,9 @@ // To be overridden in subclasses. } ++ /** ++ * @suppress ++ */ override fun destroy() { // Only allow a single call to this method. // TODO: maybe we should log a warning if called more than once? @@ -437,9 +669,452 @@ this.freeRustArcPtr() } } + } + ++ /** ++ * @suppress ++ */ + @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.pointer) *************** -*** 619,736 **** ---- 651,777 ---- +*** 663,1080 **** + } + } + + fun get(handle: Handle) = lock.withLock { + leftMap[handle] + } + + fun delete(handle: Handle) { + this.remove(handle) + } + + fun remove(handle: Handle): T? = + lock.withLock { + leftMap.remove(handle)?.let { obj -> + rightMap.remove(obj) + obj + } + } + } + + interface ForeignCallback : com.sun.jna.Callback { + public fun invoke(handle: Handle, method: Int, args: RustBuffer.ByValue, outBuf: RustBufferByReference): Int + } + + // 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 + + internal abstract class FfiConverterCallbackInterface( + protected val foreignCallback: ForeignCallback + ) { + val handleMap = ConcurrentHandleMap() + + // Registers the foreign callback with the Rust side. + // This method is generated for each callback interface. + abstract fun register(lib: _UniFFILib) + + fun drop(handle: Handle): RustBuffer.ByValue { + return handleMap.remove(handle).let { RustBuffer.ByValue() } + } + + fun lift(n: Handle) = handleMap.get(n) + + fun read(buf: ByteBuffer) = lift(buf.getLong()) + + fun lower(v: CallbackInterface) = + handleMap.insert(v).also { + assert(handleMap.get(it) === v) { "Handle map is not returning the object we just placed there. This is a bug in the HandleMap." } + } + + fun write(v: CallbackInterface, buf: RustBufferBuilder) = + buf.putLong(lower(v)) + } + + + + enum class Network { + BITCOIN,TESTNET,SIGNET,REGTEST; + + companion object { + internal fun lift(rbuf: RustBuffer.ByValue): Network { + return liftFromRustBuffer(rbuf) { buf -> Network.read(buf) } + } + + internal fun read(buf: ByteBuffer) = + try { values()[buf.getInt() - 1] } + catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + } + + internal fun lower(): RustBuffer.ByValue { + return lowerIntoRustBuffer(this, {v, buf -> v.write(buf)}) + } + + internal fun write(buf: RustBufferBuilder) { + buf.putInt(this.ordinal + 1) + } + } + + + + + + + + sealed class DatabaseConfig { + object Memory : DatabaseConfig() +! + data class Sled( +! val config: SledDbConfiguration + ) : DatabaseConfig() +! + data class Sqlite( +! val config: SqliteDbConfiguration + ) : DatabaseConfig() +- + + companion object { + internal fun lift(rbuf: RustBuffer.ByValue): DatabaseConfig { + return liftFromRustBuffer(rbuf) { buf -> DatabaseConfig.read(buf) } + } + + internal fun read(buf: ByteBuffer): DatabaseConfig { + return when(buf.getInt()) { + 1 -> DatabaseConfig.Memory + 2 -> DatabaseConfig.Sled( + SledDbConfiguration.read(buf) + ) + 3 -> DatabaseConfig.Sqlite( + SqliteDbConfiguration.read(buf) + ) + else -> throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + } + + internal fun lower(): RustBuffer.ByValue { + return lowerIntoRustBuffer(this, {v, buf -> v.write(buf)}) + } + + internal fun write(buf: RustBufferBuilder) { + when(this) { + is DatabaseConfig.Memory -> { + buf.putInt(1) +! + } + is DatabaseConfig.Sled -> { + buf.putInt(2) + this.config.write(buf) +! + } + is DatabaseConfig.Sqlite -> { + buf.putInt(3) + this.config.write(buf) +! + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } + +! +! + } + + + + + + + + sealed class Transaction { +! + data class Unconfirmed( +! val details: TransactionDetails + ) : Transaction() +! + data class Confirmed( +! val details: TransactionDetails, +! val confirmation: BlockTime + ) : Transaction() +- + + companion object { + internal fun lift(rbuf: RustBuffer.ByValue): Transaction { + return liftFromRustBuffer(rbuf) { buf -> Transaction.read(buf) } + } + + internal fun read(buf: ByteBuffer): Transaction { + return when(buf.getInt()) { + 1 -> Transaction.Unconfirmed( + TransactionDetails.read(buf) + ) + 2 -> Transaction.Confirmed( + TransactionDetails.read(buf), + BlockTime.read(buf) + ) + else -> throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + } + + internal fun lower(): RustBuffer.ByValue { + return lowerIntoRustBuffer(this, {v, buf -> v.write(buf)}) + } + + internal fun write(buf: RustBufferBuilder) { + when(this) { + is Transaction.Unconfirmed -> { + buf.putInt(1) + this.details.write(buf) +! + } + is Transaction.Confirmed -> { + buf.putInt(2) + this.details.write(buf) + this.confirmation.write(buf) +! + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } + +! +! + } + + + + + + + + sealed class BlockchainConfig { +! + data class Electrum( +! val config: ElectrumConfig + ) : BlockchainConfig() +! + data class Esplora( +! val config: EsploraConfig + ) : BlockchainConfig() +- + + companion object { + internal fun lift(rbuf: RustBuffer.ByValue): BlockchainConfig { + return liftFromRustBuffer(rbuf) { buf -> BlockchainConfig.read(buf) } + } + + internal fun read(buf: ByteBuffer): BlockchainConfig { + return when(buf.getInt()) { + 1 -> BlockchainConfig.Electrum( + ElectrumConfig.read(buf) + ) + 2 -> BlockchainConfig.Esplora( + EsploraConfig.read(buf) + ) + else -> throw RuntimeException("invalid enum value, something is very wrong!!") + } + } + } + + internal fun lower(): RustBuffer.ByValue { + return lowerIntoRustBuffer(this, {v, buf -> v.write(buf)}) + } + + internal fun write(buf: RustBufferBuilder) { + when(this) { + is BlockchainConfig.Electrum -> { + buf.putInt(1) + this.config.write(buf) +! + } + is BlockchainConfig.Esplora -> { + buf.putInt(2) + this.config.write(buf) +! + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } + +! +! + } + + + + + + enum class WordCount { + WORDS12,WORDS15,WORDS18,WORDS21,WORDS24; + + companion object { + internal fun lift(rbuf: RustBuffer.ByValue): WordCount { + return liftFromRustBuffer(rbuf) { buf -> WordCount.read(buf) } + } + + internal fun read(buf: ByteBuffer) = + try { values()[buf.getInt() - 1] } + catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + } + + internal fun lower(): RustBuffer.ByValue { + return lowerIntoRustBuffer(this, {v, buf -> v.write(buf)}) + } + + internal fun write(buf: RustBufferBuilder) { + buf.putInt(this.ordinal + 1) + } + } + + + + @Throws(BdkException::class) + + fun generateExtendedKey(network: Network, wordCount: WordCount, password: String? ): ExtendedKeyInfo { +! val _retval = + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_360_generate_extended_key(network.lower(), wordCount.lower(), lowerOptionalString(password) ,status) + } + return ExtendedKeyInfo.lift(_retval) + } + + + @Throws(BdkException::class) + + fun restoreExtendedKey(network: Network, mnemonic: String, password: String? ): ExtendedKeyInfo { +! val _retval = + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_360_restore_extended_key(network.lower(), mnemonic.lower(), lowerOptionalString(password) ,status) + } + return ExtendedKeyInfo.lift(_retval) + } + + + public interface BlockchainInterface { +! + @Throws(BdkException::class) + fun broadcast(psbt: PartiallySignedBitcoinTransaction ) +! + } + + class Blockchain( + pointer: Pointer + ) : FFIObject(pointer), BlockchainInterface { + constructor(config: BlockchainConfig ) : + this( + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_360_Blockchain_new(config.lower() ,status) + }) + + /** + * Disconnect the object from the underlying Rust object. + * + * It can be called more than once, but once called, interacting with the object + * causes an `IllegalStateException`. + * + * Clients **must** call this method once done with the object, or cause a memory leak. + */ + override protected fun freeRustArcPtr() { + rustCall() { status -> + _UniFFILib.INSTANCE.ffi_bdk_360_Blockchain_object_free(this.pointer, status) + } + } + + internal fun lower(): Pointer = callWithPointer { it } + + internal fun write(buf: RustBufferBuilder) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(this.lower())) + } + +! + @Throws(BdkException::class)override fun broadcast(psbt: PartiallySignedBitcoinTransaction ) = + callWithPointer { + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_360_Blockchain_broadcast(it, psbt.lower() , status) + } + } +- +- + + companion object { + internal fun lift(ptr: Pointer): Blockchain { + return Blockchain(ptr) + } + + internal fun read(buf: ByteBuffer): Blockchain { + // The Rust code always writes pointers as 8 bytes, and will + // fail to compile if they don't fit. + return Blockchain.lift(Pointer(buf.getLong())) + } + +! + } + } + + public interface WalletInterface { +! + fun getNewAddress(): String +! + fun getLastUnusedAddress(): String +! + @Throws(BdkException::class) + fun getBalance(): ULong +! + @Throws(BdkException::class) + fun sign(psbt: PartiallySignedBitcoinTransaction ) +! + @Throws(BdkException::class) + fun getTransactions(): List +! + fun getNetwork(): Network +! + @Throws(BdkException::class) + fun sync(blockchain: Blockchain, progress: Progress? ) +! + } + + class Wallet( + pointer: Pointer + ) : FFIObject(pointer), WalletInterface { + constructor(descriptor: String, changeDescriptor: String?, network: Network, databaseConfig: DatabaseConfig ) : + this( + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_360_Wallet_new(descriptor.lower(), lowerOptionalString(changeDescriptor), network.lower(), databaseConfig.lower() ,status) + }) + + /** + * Disconnect the object from the underlying Rust object. + * + * It can be called more than once, but once called, interacting with the object + * causes an `IllegalStateException`. + * + * Clients **must** call this method once done with the object, or cause a memory leak. + */ + override protected fun freeRustArcPtr() { +--- 697,1130 ---- } } @@ -534,15 +1209,14 @@ sealed class DatabaseConfig { object Memory : DatabaseConfig() - +! data class Sled( - val config: SledDbConfiguration +! val config: SledDbConfiguration ) : DatabaseConfig() - +! data class Sqlite( - val config: SqliteDbConfiguration +! val config: SqliteDbConfiguration ) : DatabaseConfig() - + /** + * @suppress @@ -567,9 +1241,30 @@ } internal fun lower(): RustBuffer.ByValue { -*************** -*** 761,800 **** ---- 802,844 ---- + return lowerIntoRustBuffer(this, {v, buf -> v.write(buf)}) + } + + internal fun write(buf: RustBufferBuilder) { + when(this) { + is DatabaseConfig.Memory -> { + buf.putInt(1) +! + } + is DatabaseConfig.Sled -> { + buf.putInt(2) + this.config.write(buf) +! + } + is DatabaseConfig.Sqlite -> { + buf.putInt(3) + this.config.write(buf) +! + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } + +! +! } @@ -579,16 +1274,15 @@ sealed class Transaction { - +! data class Unconfirmed( - val details: TransactionDetails +! val details: TransactionDetails ) : Transaction() - +! data class Confirmed( - val details: TransactionDetails, - val confirmation: BlockTime +! val details: TransactionDetails, +! val confirmation: BlockTime ) : Transaction() - + /** + * @suppress @@ -613,10 +1307,27 @@ } internal fun lower(): RustBuffer.ByValue { -*************** -*** 821,860 **** ---- 865,907 ---- - + return lowerIntoRustBuffer(this, {v, buf -> v.write(buf)}) + } + + internal fun write(buf: RustBufferBuilder) { + when(this) { + is Transaction.Unconfirmed -> { + buf.putInt(1) + this.details.write(buf) +! + } + is Transaction.Confirmed -> { + buf.putInt(2) + this.details.write(buf) + this.confirmation.write(buf) +! + } + }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } + } + +! +! } @@ -626,15 +1337,14 @@ sealed class BlockchainConfig { - +! data class Electrum( - val config: ElectrumConfig +! val config: ElectrumConfig ) : BlockchainConfig() - +! data class Esplora( - val config: EsploraConfig +! val config: EsploraConfig ) : BlockchainConfig() - + /** + * @suppress @@ -659,20 +1369,25 @@ internal fun lower(): RustBuffer.ByValue { return lowerIntoRustBuffer(this, {v, buf -> v.write(buf)}) -*************** -*** 869,908 **** ---- 916,958 ---- + } + + internal fun write(buf: RustBufferBuilder) { + when(this) { + is BlockchainConfig.Electrum -> { + buf.putInt(1) + this.config.write(buf) +! } is BlockchainConfig.Esplora -> { buf.putInt(2) this.config.write(buf) - +! } }.let { /* this makes the `when` an expression, which ensures it is exhaustive */ } } - - +! +! } @@ -705,28 +1420,330 @@ buf.putInt(this.ordinal + 1) } } -*************** -*** 1045,1084 **** ---- 1095,1137 ---- - - @Throws(BdkException::class)override fun sync(progressUpdate: BdkProgress, maxAddressParam: UInt? ) = + + + + @Throws(BdkException::class) + + fun generateExtendedKey(network: Network, wordCount: WordCount, password: String? ): ExtendedKeyInfo { +! val _retval = + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_360_generate_extended_key(network.lower(), wordCount.lower(), lowerOptionalString(password) ,status) + } + return ExtendedKeyInfo.lift(_retval) + } + + + @Throws(BdkException::class) + + fun restoreExtendedKey(network: Network, mnemonic: String, password: String? ): ExtendedKeyInfo { +! val _retval = + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_360_restore_extended_key(network.lower(), mnemonic.lower(), lowerOptionalString(password) ,status) + } + return ExtendedKeyInfo.lift(_retval) + } + + + public interface BlockchainInterface { +! + @Throws(BdkException::class) + fun broadcast(psbt: PartiallySignedBitcoinTransaction ) +! + } + + class Blockchain( + pointer: Pointer + ) : FFIObject(pointer), BlockchainInterface { + constructor(config: BlockchainConfig ) : + this( + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_360_Blockchain_new(config.lower() ,status) + }) + + /** + * Disconnect the object from the underlying Rust object. + * + * It can be called more than once, but once called, interacting with the object + * causes an `IllegalStateException`. + * + * Clients **must** call this method once done with the object, or cause a memory leak. + */ + override protected fun freeRustArcPtr() { + rustCall() { status -> + _UniFFILib.INSTANCE.ffi_bdk_360_Blockchain_object_free(this.pointer, status) + } + } + + internal fun lower(): Pointer = callWithPointer { it } + + internal fun write(buf: RustBufferBuilder) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(this.lower())) + } + +! + @Throws(BdkException::class)override fun broadcast(psbt: PartiallySignedBitcoinTransaction ) = callWithPointer { rustCallWithError(BdkException) { status -> - _UniFFILib.INSTANCE.bdk_9c03_Wallet_sync(it, FfiConverterCallbackInterfaceBdkProgress.lower(progressUpdate), lowerOptionalUInt(maxAddressParam) , status) + _UniFFILib.INSTANCE.bdk_360_Blockchain_broadcast(it, psbt.lower() , status) } } - - - @Throws(BdkException::class)override fun broadcast(psbt: PartiallySignedBitcoinTransaction ): String = - callWithPointer { + ++ /** ++ * @suppress ++ */ + companion object { + internal fun lift(ptr: Pointer): Blockchain { + return Blockchain(ptr) + } + + internal fun read(buf: ByteBuffer): Blockchain { + // The Rust code always writes pointers as 8 bytes, and will + // fail to compile if they don't fit. + return Blockchain.lift(Pointer(buf.getLong())) + } + +! + } + } + + public interface WalletInterface { +! + fun getNewAddress(): String +! + fun getLastUnusedAddress(): String +! + @Throws(BdkException::class) + fun getBalance(): ULong +! + @Throws(BdkException::class) + fun sign(psbt: PartiallySignedBitcoinTransaction ) +! + @Throws(BdkException::class) + fun getTransactions(): List +! + fun getNetwork(): Network +! + @Throws(BdkException::class) + fun sync(blockchain: Blockchain, progress: Progress? ) +! + } + + class Wallet( + pointer: Pointer + ) : FFIObject(pointer), WalletInterface { + constructor(descriptor: String, changeDescriptor: String?, network: Network, databaseConfig: DatabaseConfig ) : + this( rustCallWithError(BdkException) { status -> - _UniFFILib.INSTANCE.bdk_9c03_Wallet_broadcast(it, psbt.lower() , status) + _UniFFILib.INSTANCE.bdk_360_Wallet_new(descriptor.lower(), lowerOptionalString(changeDescriptor), network.lower(), databaseConfig.lower() ,status) + }) + + /** + * Disconnect the object from the underlying Rust object. + * + * It can be called more than once, but once called, interacting with the object + * causes an `IllegalStateException`. + * + * Clients **must** call this method once done with the object, or cause a memory leak. + */ + override protected fun freeRustArcPtr() { +*************** +*** 1082,1199 **** + _UniFFILib.INSTANCE.ffi_bdk_360_Wallet_object_free(this.pointer, status) + } + } + + internal fun lower(): Pointer = callWithPointer { it } + + internal fun write(buf: RustBufferBuilder) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(this.lower())) + } + + override fun getNewAddress(): String = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_Wallet_get_new_address(it, status) } }.let { String.lift(it) } - - +! + override fun getLastUnusedAddress(): String = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_Wallet_get_last_unused_address(it, status) + } + }.let { + String.lift(it) + } +! +! + @Throws(BdkException::class)override fun getBalance(): ULong = + callWithPointer { + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_360_Wallet_get_balance(it, status) + } + }.let { + ULong.lift(it) + } +! +! + @Throws(BdkException::class)override fun sign(psbt: PartiallySignedBitcoinTransaction ) = + callWithPointer { + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_360_Wallet_sign(it, psbt.lower() , status) + } + } +! +! + @Throws(BdkException::class)override fun getTransactions(): List = + callWithPointer { + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_360_Wallet_get_transactions(it, status) + } + }.let { + liftSequenceEnumTransaction(it) + } +! + override fun getNetwork(): Network = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_Wallet_get_network(it, status) + } + }.let { + Network.lift(it) + } +! +! + @Throws(BdkException::class)override fun sync(blockchain: Blockchain, progress: Progress? ) = + callWithPointer { + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_360_Wallet_sync(it, blockchain.lower(), lowerOptionalCallbackInterfaceProgress(progress) , status) + } + } +- +- + + companion object { + internal fun lift(ptr: Pointer): Wallet { + return Wallet(ptr) + } + + internal fun read(buf: ByteBuffer): Wallet { + // The Rust code always writes pointers as 8 bytes, and will + // fail to compile if they don't fit. + return Wallet.lift(Pointer(buf.getLong())) + } + +! + } + } + + public interface PartiallySignedBitcoinTransactionInterface { +! + fun serialize(): String +! + fun txid(): String +! + } + + class PartiallySignedBitcoinTransaction( + pointer: Pointer + ) : FFIObject(pointer), PartiallySignedBitcoinTransactionInterface { + constructor(psbtBase64: String ) : + this( + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_360_PartiallySignedBitcoinTransaction_new(psbtBase64.lower() ,status) + }) + + /** + * Disconnect the object from the underlying Rust object. + * + * It can be called more than once, but once called, interacting with the object + * causes an `IllegalStateException`. + * + * Clients **must** call this method once done with the object, or cause a memory leak. + */ + override protected fun freeRustArcPtr() { +--- 1132,1250 ---- + _UniFFILib.INSTANCE.ffi_bdk_360_Wallet_object_free(this.pointer, status) + } + } + + internal fun lower(): Pointer = callWithPointer { it } + + internal fun write(buf: RustBufferBuilder) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(this.lower())) + } + + override fun getNewAddress(): String = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_Wallet_get_new_address(it, status) + } + }.let { + String.lift(it) + } +! + override fun getLastUnusedAddress(): String = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_Wallet_get_last_unused_address(it, status) + } + }.let { + String.lift(it) + } +! +! + @Throws(BdkException::class)override fun getBalance(): ULong = + callWithPointer { + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_360_Wallet_get_balance(it, status) + } + }.let { + ULong.lift(it) + } +! +! + @Throws(BdkException::class)override fun sign(psbt: PartiallySignedBitcoinTransaction ) = + callWithPointer { + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_360_Wallet_sign(it, psbt.lower() , status) + } + } +! +! + @Throws(BdkException::class)override fun getTransactions(): List = + callWithPointer { + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_360_Wallet_get_transactions(it, status) + } + }.let { + liftSequenceEnumTransaction(it) + } +! + override fun getNetwork(): Network = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_Wallet_get_network(it, status) + } + }.let { + Network.lift(it) + } +! +! + @Throws(BdkException::class)override fun sync(blockchain: Blockchain, progress: Progress? ) = + callWithPointer { + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_360_Wallet_sync(it, blockchain.lower(), lowerOptionalCallbackInterfaceProgress(progress) , status) + } + } + /** + * @suppress @@ -742,18 +1759,41 @@ return Wallet.lift(Pointer(buf.getLong())) } - +! } } public interface PartiallySignedBitcoinTransactionInterface { - +! fun serialize(): String - +! + fun txid(): String +! } + + class PartiallySignedBitcoinTransaction( + pointer: Pointer + ) : FFIObject(pointer), PartiallySignedBitcoinTransactionInterface { + constructor(psbtBase64: String ) : + this( + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_360_PartiallySignedBitcoinTransaction_new(psbtBase64.lower() ,status) + }) + + /** + * Disconnect the object from the underlying Rust object. + * + * It can be called more than once, but once called, interacting with the object + * causes an `IllegalStateException`. + * + * Clients **must** call this method once done with the object, or cause a memory leak. + */ + override protected fun freeRustArcPtr() { *************** -*** 1108,1147 **** ---- 1161,1203 ---- +*** 1201,1284 **** + _UniFFILib.INSTANCE.ffi_bdk_360_PartiallySignedBitcoinTransaction_object_free(this.pointer, status) + } + } internal fun lower(): Pointer = callWithPointer { it } @@ -766,13 +1806,105 @@ override fun serialize(): String = callWithPointer { rustCall() { status -> - _UniFFILib.INSTANCE.bdk_9c03_PartiallySignedBitcoinTransaction_serialize(it, status) + _UniFFILib.INSTANCE.bdk_360_PartiallySignedBitcoinTransaction_serialize(it, status) + } + }.let { + String.lift(it) + } +! + override fun txid(): String = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_PartiallySignedBitcoinTransaction_txid(it, status) + } + }.let { + String.lift(it) + } +- +- + + companion object { + internal fun lift(ptr: Pointer): PartiallySignedBitcoinTransaction { + return PartiallySignedBitcoinTransaction(ptr) + } + + internal fun read(buf: ByteBuffer): PartiallySignedBitcoinTransaction { + // The Rust code always writes pointers as 8 bytes, and will + // fail to compile if they don't fit. + return PartiallySignedBitcoinTransaction.lift(Pointer(buf.getLong())) + } + +! + } + } + + public interface TxBuilderInterface { +! + fun addRecipient(address: String, amount: ULong ): TxBuilder +! + fun feeRate(satPerVbyte: Float ): TxBuilder +! + fun drainWallet(): TxBuilder +! + fun drainTo(address: String ): TxBuilder +! + fun enableRbf(): TxBuilder +! + fun enableRbfWithSequence(nsequence: UInt ): TxBuilder +! + @Throws(BdkException::class) + fun finish(wallet: Wallet ): PartiallySignedBitcoinTransaction +! + } + + class TxBuilder( + pointer: Pointer + ) : FFIObject(pointer), TxBuilderInterface { + constructor() : + this( + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_TxBuilder_new(status) + }) + + /** + * Disconnect the object from the underlying Rust object. + * + * It can be called more than once, but once called, interacting with the object + * causes an `IllegalStateException`. + * + * Clients **must** call this method once done with the object, or cause a memory leak. + */ + override protected fun freeRustArcPtr() { +--- 1252,1336 ---- + _UniFFILib.INSTANCE.ffi_bdk_360_PartiallySignedBitcoinTransaction_object_free(this.pointer, status) + } + } + + internal fun lower(): Pointer = callWithPointer { it } + + internal fun write(buf: RustBufferBuilder) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(this.lower())) + } + + override fun serialize(): String = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_PartiallySignedBitcoinTransaction_serialize(it, status) + } + }.let { + String.lift(it) + } +! + override fun txid(): String = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_PartiallySignedBitcoinTransaction_txid(it, status) } }.let { String.lift(it) } - - + /** + * @suppress @@ -788,37 +1920,249 @@ return PartiallySignedBitcoinTransaction.lift(Pointer(buf.getLong())) } - +! } } public interface TxBuilderInterface { - +! fun addRecipient(address: String, amount: ULong ): TxBuilder - +! fun feeRate(satPerVbyte: Float ): TxBuilder +! + fun drainWallet(): TxBuilder +! + fun drainTo(address: String ): TxBuilder +! + fun enableRbf(): TxBuilder +! + fun enableRbfWithSequence(nsequence: UInt ): TxBuilder +! + @Throws(BdkException::class) + fun finish(wallet: Wallet ): PartiallySignedBitcoinTransaction +! + } + + class TxBuilder( + pointer: Pointer + ) : FFIObject(pointer), TxBuilderInterface { + constructor() : + this( + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_TxBuilder_new(status) + }) + + /** + * Disconnect the object from the underlying Rust object. + * + * It can be called more than once, but once called, interacting with the object + * causes an `IllegalStateException`. + * + * Clients **must** call this method once done with the object, or cause a memory leak. + */ + override protected fun freeRustArcPtr() { *************** -*** 1217,1410 **** ---- 1273,1486 ---- +*** 1286,1409 **** + _UniFFILib.INSTANCE.ffi_bdk_360_TxBuilder_object_free(this.pointer, status) + } + } + + internal fun lower(): Pointer = callWithPointer { it } + + internal fun write(buf: RustBufferBuilder) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(this.lower())) + } + + override fun addRecipient(address: String, amount: ULong ): TxBuilder = callWithPointer { rustCall() { status -> - _UniFFILib.INSTANCE.bdk_9c03_TxBuilder_drain_to(it, address.lower() , status) + _UniFFILib.INSTANCE.bdk_360_TxBuilder_add_recipient(it, address.lower(), amount.lower() , status) } }.let { TxBuilder.lift(it) } - - - @Throws(BdkException::class)override fun build(wallet: Wallet ): PartiallySignedBitcoinTransaction = +! + override fun feeRate(satPerVbyte: Float ): TxBuilder = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_TxBuilder_fee_rate(it, satPerVbyte.lower() , status) + } + }.let { + TxBuilder.lift(it) + } +! + override fun drainWallet(): TxBuilder = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_TxBuilder_drain_wallet(it, status) + } + }.let { + TxBuilder.lift(it) + } +! + override fun drainTo(address: String ): TxBuilder = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_TxBuilder_drain_to(it, address.lower() , status) + } + }.let { + TxBuilder.lift(it) + } +! + override fun enableRbf(): TxBuilder = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_TxBuilder_enable_rbf(it, status) + } + }.let { + TxBuilder.lift(it) + } +! + override fun enableRbfWithSequence(nsequence: UInt ): TxBuilder = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_TxBuilder_enable_rbf_with_sequence(it, nsequence.lower() , status) + } + }.let { + TxBuilder.lift(it) + } +! +! + @Throws(BdkException::class)override fun finish(wallet: Wallet ): PartiallySignedBitcoinTransaction = callWithPointer { rustCallWithError(BdkException) { status -> - _UniFFILib.INSTANCE.bdk_9c03_TxBuilder_build(it, wallet.lower() , status) + _UniFFILib.INSTANCE.bdk_360_TxBuilder_finish(it, wallet.lower() , status) + } + }.let { + PartiallySignedBitcoinTransaction.lift(it) + } +- +- + + companion object { + internal fun lift(ptr: Pointer): TxBuilder { + return TxBuilder(ptr) + } + + internal fun read(buf: ByteBuffer): TxBuilder { + // The Rust code always writes pointers as 8 bytes, and will + // fail to compile if they don't fit. + return TxBuilder.lift(Pointer(buf.getLong())) + } + +! + } + } + + public interface BumpFeeTxBuilderInterface { +! + fun allowShrinking(address: String ): BumpFeeTxBuilder +! + fun enableRbf(): BumpFeeTxBuilder +! + fun enableRbfWithSequence(nsequence: UInt ): BumpFeeTxBuilder +! + @Throws(BdkException::class) + fun finish(wallet: Wallet ): PartiallySignedBitcoinTransaction +! + } + + class BumpFeeTxBuilder( + pointer: Pointer + ) : FFIObject(pointer), BumpFeeTxBuilderInterface { + constructor(txid: String, newFeeRate: Float ) : + this( + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_BumpFeeTxBuilder_new(txid.lower(), newFeeRate.lower() ,status) + }) + + /** + * Disconnect the object from the underlying Rust object. + * + * It can be called more than once, but once called, interacting with the object + * causes an `IllegalStateException`. + * + * Clients **must** call this method once done with the object, or cause a memory leak. + */ + override protected fun freeRustArcPtr() { +--- 1338,1462 ---- + _UniFFILib.INSTANCE.ffi_bdk_360_TxBuilder_object_free(this.pointer, status) + } + } + + internal fun lower(): Pointer = callWithPointer { it } + + internal fun write(buf: RustBufferBuilder) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(this.lower())) + } + + override fun addRecipient(address: String, amount: ULong ): TxBuilder = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_TxBuilder_add_recipient(it, address.lower(), amount.lower() , status) + } + }.let { + TxBuilder.lift(it) + } +! + override fun feeRate(satPerVbyte: Float ): TxBuilder = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_TxBuilder_fee_rate(it, satPerVbyte.lower() , status) + } + }.let { + TxBuilder.lift(it) + } +! + override fun drainWallet(): TxBuilder = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_TxBuilder_drain_wallet(it, status) + } + }.let { + TxBuilder.lift(it) + } +! + override fun drainTo(address: String ): TxBuilder = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_TxBuilder_drain_to(it, address.lower() , status) + } + }.let { + TxBuilder.lift(it) + } +! + override fun enableRbf(): TxBuilder = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_TxBuilder_enable_rbf(it, status) + } + }.let { + TxBuilder.lift(it) + } +! + override fun enableRbfWithSequence(nsequence: UInt ): TxBuilder = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_TxBuilder_enable_rbf_with_sequence(it, nsequence.lower() , status) + } + }.let { + TxBuilder.lift(it) + } +! +! + @Throws(BdkException::class)override fun finish(wallet: Wallet ): PartiallySignedBitcoinTransaction = + callWithPointer { + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_360_TxBuilder_finish(it, wallet.lower() , status) } }.let { PartiallySignedBitcoinTransaction.lift(it) } - - + /** + * @suppress @@ -834,13 +2178,454 @@ return TxBuilder.lift(Pointer(buf.getLong())) } - +! + } + } + + public interface BumpFeeTxBuilderInterface { +! + fun allowShrinking(address: String ): BumpFeeTxBuilder +! + fun enableRbf(): BumpFeeTxBuilder +! + fun enableRbfWithSequence(nsequence: UInt ): BumpFeeTxBuilder +! + @Throws(BdkException::class) + fun finish(wallet: Wallet ): PartiallySignedBitcoinTransaction +! + } + + class BumpFeeTxBuilder( + pointer: Pointer + ) : FFIObject(pointer), BumpFeeTxBuilderInterface { + constructor(txid: String, newFeeRate: Float ) : + this( + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_BumpFeeTxBuilder_new(txid.lower(), newFeeRate.lower() ,status) + }) + + /** + * Disconnect the object from the underlying Rust object. + * + * It can be called more than once, but once called, interacting with the object + * causes an `IllegalStateException`. + * + * Clients **must** call this method once done with the object, or cause a memory leak. + */ + override protected fun freeRustArcPtr() { +*************** +*** 1411,1750 **** + _UniFFILib.INSTANCE.ffi_bdk_360_BumpFeeTxBuilder_object_free(this.pointer, status) + } + } + + internal fun lower(): Pointer = callWithPointer { it } + + internal fun write(buf: RustBufferBuilder) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(this.lower())) + } + + override fun allowShrinking(address: String ): BumpFeeTxBuilder = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_BumpFeeTxBuilder_allow_shrinking(it, address.lower() , status) + } + }.let { + BumpFeeTxBuilder.lift(it) + } +! + override fun enableRbf(): BumpFeeTxBuilder = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_BumpFeeTxBuilder_enable_rbf(it, status) + } + }.let { + BumpFeeTxBuilder.lift(it) + } +! + override fun enableRbfWithSequence(nsequence: UInt ): BumpFeeTxBuilder = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_BumpFeeTxBuilder_enable_rbf_with_sequence(it, nsequence.lower() , status) + } + }.let { + BumpFeeTxBuilder.lift(it) + } +! +! + @Throws(BdkException::class)override fun finish(wallet: Wallet ): PartiallySignedBitcoinTransaction = + callWithPointer { + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_360_BumpFeeTxBuilder_finish(it, wallet.lower() , status) + } + }.let { + PartiallySignedBitcoinTransaction.lift(it) + } +- +- + + companion object { + internal fun lift(ptr: Pointer): BumpFeeTxBuilder { + return BumpFeeTxBuilder(ptr) + } + + internal fun read(buf: ByteBuffer): BumpFeeTxBuilder { + // The Rust code always writes pointers as 8 bytes, and will + // fail to compile if they don't fit. + return BumpFeeTxBuilder.lift(Pointer(buf.getLong())) + } + +! } } data class SledDbConfiguration ( - var path: String, - var treeName: String +! var path: String, +! var treeName: String + ) { + companion object { + internal fun lift(rbuf: RustBuffer.ByValue): SledDbConfiguration { + return liftFromRustBuffer(rbuf) { buf -> SledDbConfiguration.read(buf) } + } + + internal fun read(buf: ByteBuffer): SledDbConfiguration { + return SledDbConfiguration( + String.read(buf), + String.read(buf) + ) + } + } + + internal fun lower(): RustBuffer.ByValue { + return lowerIntoRustBuffer(this, {v, buf -> v.write(buf)}) + } + + internal fun write(buf: RustBufferBuilder) { + this.path.write(buf) +! + this.treeName.write(buf) +! + } + +! +! + } + + data class SqliteDbConfiguration ( +! var path: String + ) { + companion object { + internal fun lift(rbuf: RustBuffer.ByValue): SqliteDbConfiguration { + return liftFromRustBuffer(rbuf) { buf -> SqliteDbConfiguration.read(buf) } + } + + internal fun read(buf: ByteBuffer): SqliteDbConfiguration { + return SqliteDbConfiguration( + String.read(buf) + ) + } + } + + internal fun lower(): RustBuffer.ByValue { + return lowerIntoRustBuffer(this, {v, buf -> v.write(buf)}) + } + + internal fun write(buf: RustBufferBuilder) { + this.path.write(buf) +! + } + +! +! + } + + data class TransactionDetails ( +! var fee: ULong?, +! var received: ULong, +! var sent: ULong, +! var txid: String + ) { + companion object { + internal fun lift(rbuf: RustBuffer.ByValue): TransactionDetails { + return liftFromRustBuffer(rbuf) { buf -> TransactionDetails.read(buf) } + } + + internal fun read(buf: ByteBuffer): TransactionDetails { + return TransactionDetails( + readOptionalULong(buf), + ULong.read(buf), + ULong.read(buf), + String.read(buf) + ) + } + } + + internal fun lower(): RustBuffer.ByValue { + return lowerIntoRustBuffer(this, {v, buf -> v.write(buf)}) + } + + internal fun write(buf: RustBufferBuilder) { + writeOptionalULong(this.fee, buf) +! + this.received.write(buf) +! + this.sent.write(buf) +! + this.txid.write(buf) +! + } + +! +! + } + + data class BlockTime ( +! var height: UInt, +! var timestamp: ULong + ) { + companion object { + internal fun lift(rbuf: RustBuffer.ByValue): BlockTime { + return liftFromRustBuffer(rbuf) { buf -> BlockTime.read(buf) } + } + + internal fun read(buf: ByteBuffer): BlockTime { + return BlockTime( + UInt.read(buf), + ULong.read(buf) + ) + } + } + + internal fun lower(): RustBuffer.ByValue { + return lowerIntoRustBuffer(this, {v, buf -> v.write(buf)}) + } + + internal fun write(buf: RustBufferBuilder) { + this.height.write(buf) +! + this.timestamp.write(buf) +! + } + +! +! + } + + data class ElectrumConfig ( +! var url: String, +! var socks5: String?, +! var retry: UByte, +! var timeout: UByte?, +! var stopGap: ULong + ) { + companion object { + internal fun lift(rbuf: RustBuffer.ByValue): ElectrumConfig { + return liftFromRustBuffer(rbuf) { buf -> ElectrumConfig.read(buf) } + } + + internal fun read(buf: ByteBuffer): ElectrumConfig { + return ElectrumConfig( + String.read(buf), + readOptionalString(buf), + UByte.read(buf), + readOptionalUByte(buf), + ULong.read(buf) + ) + } + } + + internal fun lower(): RustBuffer.ByValue { + return lowerIntoRustBuffer(this, {v, buf -> v.write(buf)}) + } + + internal fun write(buf: RustBufferBuilder) { + this.url.write(buf) +! + writeOptionalString(this.socks5, buf) +! + this.retry.write(buf) +! + writeOptionalUByte(this.timeout, buf) +! + this.stopGap.write(buf) +! + } + +! +! + } + + data class EsploraConfig ( +! var baseUrl: String, +! var proxy: String?, +! var concurrency: UByte?, +! var stopGap: ULong, +! var timeout: ULong? + ) { + companion object { + internal fun lift(rbuf: RustBuffer.ByValue): EsploraConfig { + return liftFromRustBuffer(rbuf) { buf -> EsploraConfig.read(buf) } + } + + internal fun read(buf: ByteBuffer): EsploraConfig { + return EsploraConfig( + String.read(buf), + readOptionalString(buf), + readOptionalUByte(buf), + ULong.read(buf), + readOptionalULong(buf) + ) + } + } + + internal fun lower(): RustBuffer.ByValue { + return lowerIntoRustBuffer(this, {v, buf -> v.write(buf)}) + } + + internal fun write(buf: RustBufferBuilder) { + this.baseUrl.write(buf) +! + writeOptionalString(this.proxy, buf) +! + writeOptionalUByte(this.concurrency, buf) +! + this.stopGap.write(buf) +! + writeOptionalULong(this.timeout, buf) +! + } + +! +! + } + + data class ExtendedKeyInfo ( +! var mnemonic: String, +! var xprv: String, +! var fingerprint: String + ) { + companion object { + internal fun lift(rbuf: RustBuffer.ByValue): ExtendedKeyInfo { + return liftFromRustBuffer(rbuf) { buf -> ExtendedKeyInfo.read(buf) } + } + + internal fun read(buf: ByteBuffer): ExtendedKeyInfo { + return ExtendedKeyInfo( + String.read(buf), + String.read(buf), + String.read(buf) + ) + } + } + + internal fun lower(): RustBuffer.ByValue { + return lowerIntoRustBuffer(this, {v, buf -> v.write(buf)}) + } + + internal fun write(buf: RustBufferBuilder) { + this.mnemonic.write(buf) +! + this.xprv.write(buf) +! + this.fingerprint.write(buf) +! + } + +! +! + } + + + + sealed class BdkException(message: String): Exception(message) { + // Each variant is a nested class + // Flat enums carries a string error message, so no special implementation is necessary. + class InvalidU32Bytes(message: String) : BdkException(message) + class Generic(message: String) : BdkException(message) + class ScriptDoesntHaveAddressForm(message: String) : BdkException(message) + class NoRecipients(message: String) : BdkException(message) + class NoUtxosSelected(message: String) : BdkException(message) + class OutputBelowDustLimit(message: String) : BdkException(message) + class InsufficientFunds(message: String) : BdkException(message) + class BnBTotalTriesExceeded(message: String) : BdkException(message) + class BnBNoExactMatch(message: String) : BdkException(message) + class UnknownUtxo(message: String) : BdkException(message) + class TransactionNotFound(message: String) : BdkException(message) + class TransactionConfirmed(message: String) : BdkException(message) + class IrreplaceableTransaction(message: String) : BdkException(message) +--- 1464,1825 ---- + _UniFFILib.INSTANCE.ffi_bdk_360_BumpFeeTxBuilder_object_free(this.pointer, status) + } + } + + internal fun lower(): Pointer = callWithPointer { it } + + internal fun write(buf: RustBufferBuilder) { + // The Rust code always expects pointers written as 8 bytes, + // and will fail to compile if they don't fit. + buf.putLong(Pointer.nativeValue(this.lower())) + } + + override fun allowShrinking(address: String ): BumpFeeTxBuilder = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_BumpFeeTxBuilder_allow_shrinking(it, address.lower() , status) + } + }.let { + BumpFeeTxBuilder.lift(it) + } +! + override fun enableRbf(): BumpFeeTxBuilder = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_BumpFeeTxBuilder_enable_rbf(it, status) + } + }.let { + BumpFeeTxBuilder.lift(it) + } +! + override fun enableRbfWithSequence(nsequence: UInt ): BumpFeeTxBuilder = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_360_BumpFeeTxBuilder_enable_rbf_with_sequence(it, nsequence.lower() , status) + } + }.let { + BumpFeeTxBuilder.lift(it) + } +! +! + @Throws(BdkException::class)override fun finish(wallet: Wallet ): PartiallySignedBitcoinTransaction = + callWithPointer { + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_360_BumpFeeTxBuilder_finish(it, wallet.lower() , status) + } + }.let { + PartiallySignedBitcoinTransaction.lift(it) + } + ++ /** ++ * @suppress ++ */ + companion object { + internal fun lift(ptr: Pointer): BumpFeeTxBuilder { + return BumpFeeTxBuilder(ptr) + } + + internal fun read(buf: ByteBuffer): BumpFeeTxBuilder { + // The Rust code always writes pointers as 8 bytes, and will + // fail to compile if they don't fit. + return BumpFeeTxBuilder.lift(Pointer(buf.getLong())) + } + +! + } + } + + data class SledDbConfiguration ( +! var path: String, +! var treeName: String ) { + /** + * @suppress @@ -864,19 +2649,18 @@ internal fun write(buf: RustBufferBuilder) { this.path.write(buf) - +! this.treeName.write(buf) - +! } - - +! +! } data class SqliteDbConfiguration ( - var path: String +! var path: String ) { -+ + /** + * @suppress + */ @@ -898,20 +2682,19 @@ internal fun write(buf: RustBufferBuilder) { this.path.write(buf) - +! } - - +! +! } data class TransactionDetails ( - var fees: ULong?, - var received: ULong, - var sent: ULong, - var txid: String +! var fee: ULong?, +! var received: ULong, +! var sent: ULong, +! var txid: String ) { -+ + /** + * @suppress + */ @@ -935,23 +2718,23 @@ } internal fun write(buf: RustBufferBuilder) { - writeOptionalULong(this.fees, buf) - + writeOptionalULong(this.fee, buf) +! this.received.write(buf) - +! this.sent.write(buf) - +! this.txid.write(buf) - +! } - - +! +! } data class BlockTime ( - var height: UInt, - var timestamp: ULong +! var height: UInt, +! var timestamp: ULong ) { + /** + * @suppress @@ -975,21 +2758,21 @@ internal fun write(buf: RustBufferBuilder) { this.height.write(buf) - +! this.timestamp.write(buf) - +! } - - +! +! } data class ElectrumConfig ( - var url: String, - var socks5: String?, - var retry: UByte, - var timeout: UByte?, - var stopGap: ULong +! var url: String, +! var socks5: String?, +! var retry: UByte, +! var timeout: UByte?, +! var stopGap: ULong ) { + /** + * @suppress @@ -1014,28 +2797,29 @@ return lowerIntoRustBuffer(this, {v, buf -> v.write(buf)}) } -*************** -*** 1415,1454 **** ---- 1491,1533 ---- - + internal fun write(buf: RustBufferBuilder) { + this.url.write(buf) +! + writeOptionalString(this.socks5, buf) +! this.retry.write(buf) - +! writeOptionalUByte(this.timeout, buf) - +! this.stopGap.write(buf) - +! } - - +! +! } data class EsploraConfig ( - var baseUrl: String, - var proxy: String?, - var timeoutRead: ULong, - var timeoutWrite: ULong, - var stopGap: ULong +! var baseUrl: String, +! var proxy: String?, +! var concurrency: UByte?, +! var stopGap: ULong, +! var timeout: ULong? ) { + /** + * @suppress @@ -1049,9 +2833,9 @@ return EsploraConfig( String.read(buf), readOptionalString(buf), + readOptionalUByte(buf), ULong.read(buf), - ULong.read(buf), - ULong.read(buf) + readOptionalULong(buf) ) } } @@ -1060,28 +2844,27 @@ return lowerIntoRustBuffer(this, {v, buf -> v.write(buf)}) } -*************** -*** 1457,1496 **** ---- 1536,1578 ---- - + internal fun write(buf: RustBufferBuilder) { + this.baseUrl.write(buf) +! writeOptionalString(this.proxy, buf) - - this.timeoutRead.write(buf) - - this.timeoutWrite.write(buf) - +! + writeOptionalUByte(this.concurrency, buf) +! this.stopGap.write(buf) - +! + writeOptionalULong(this.timeout, buf) +! } - - +! +! } data class ExtendedKeyInfo ( - var mnemonic: String, - var xprv: String, - var fingerprint: String +! var mnemonic: String, +! var xprv: String, +! var fingerprint: String ) { + /** + * @suppress @@ -1106,9 +2889,39 @@ internal fun write(buf: RustBufferBuilder) { this.mnemonic.write(buf) +! + this.xprv.write(buf) +! + this.fingerprint.write(buf) +! + } + +! +! + } + + + + sealed class BdkException(message: String): Exception(message) { + // Each variant is a nested class + // Flat enums carries a string error message, so no special implementation is necessary. + class InvalidU32Bytes(message: String) : BdkException(message) + class Generic(message: String) : BdkException(message) + class ScriptDoesntHaveAddressForm(message: String) : BdkException(message) + class NoRecipients(message: String) : BdkException(message) + class NoUtxosSelected(message: String) : BdkException(message) + class OutputBelowDustLimit(message: String) : BdkException(message) + class InsufficientFunds(message: String) : BdkException(message) + class BnBTotalTriesExceeded(message: String) : BdkException(message) + class BnBNoExactMatch(message: String) : BdkException(message) + class UnknownUtxo(message: String) : BdkException(message) + class TransactionNotFound(message: String) : BdkException(message) + class TransactionConfirmed(message: String) : BdkException(message) + class IrreplaceableTransaction(message: String) : BdkException(message) *************** -*** 1535,1574 **** ---- 1617,1659 ---- +*** 1758,1806 **** + class InvalidPolicyPathException(message: String) : BdkException(message) + class Signer(message: String) : BdkException(message) class InvalidNetwork(message: String) : BdkException(message) class InvalidProgressValue(message: String) : BdkException(message) class ProgressUpdateException(message: String) : BdkException(message) @@ -1127,18 +2940,15 @@ class Esplora(message: String) : BdkException(message) class Sled(message: String) : BdkException(message) class Rusqlite(message: String) : BdkException(message) - +- -+ /** -+ * @suppress -+ */ companion object ErrorHandler : CallStatusErrorHandler { override fun lift(error_buf: RustBuffer.ByValue): BdkException { return liftFromRustBuffer(error_buf) { error_buf -> read(error_buf) } } fun read(error_buf: ByteBuffer): BdkException { - +! return when(error_buf.getInt()) { 1 -> BdkException.InvalidU32Bytes(String.read(error_buf)) 2 -> BdkException.Generic(String.read(error_buf)) @@ -1152,3 +2962,264 @@ 10 -> BdkException.UnknownUtxo(String.read(error_buf)) 11 -> BdkException.TransactionNotFound(String.read(error_buf)) 12 -> BdkException.TransactionConfirmed(String.read(error_buf)) + 13 -> BdkException.IrreplaceableTransaction(String.read(error_buf)) + 14 -> BdkException.FeeRateTooLow(String.read(error_buf)) + 15 -> BdkException.FeeTooLow(String.read(error_buf)) + 16 -> BdkException.FeeRateUnavailable(String.read(error_buf)) + 17 -> BdkException.MissingKeyOrigin(String.read(error_buf)) + 18 -> BdkException.Key(String.read(error_buf)) + 19 -> BdkException.ChecksumMismatch(String.read(error_buf)) +--- 1833,1884 ---- + class InvalidPolicyPathException(message: String) : BdkException(message) + class Signer(message: String) : BdkException(message) + class InvalidNetwork(message: String) : BdkException(message) + class InvalidProgressValue(message: String) : BdkException(message) + class ProgressUpdateException(message: String) : BdkException(message) + class InvalidOutpoint(message: String) : BdkException(message) + class Descriptor(message: String) : BdkException(message) + class AddressValidator(message: String) : BdkException(message) + class Encode(message: String) : BdkException(message) + class Miniscript(message: String) : BdkException(message) + class Bip32(message: String) : BdkException(message) + class Secp256k1(message: String) : BdkException(message) + class Json(message: String) : BdkException(message) + class Hex(message: String) : BdkException(message) + class Psbt(message: String) : BdkException(message) + class PsbtParse(message: String) : BdkException(message) + class Electrum(message: String) : BdkException(message) + class Esplora(message: String) : BdkException(message) + class Sled(message: String) : BdkException(message) + class Rusqlite(message: String) : BdkException(message) + ++ ++ /** ++ * @suppress ++ */ + companion object ErrorHandler : CallStatusErrorHandler { + override fun lift(error_buf: RustBuffer.ByValue): BdkException { + return liftFromRustBuffer(error_buf) { error_buf -> read(error_buf) } + } + + fun read(error_buf: ByteBuffer): BdkException { +! + return when(error_buf.getInt()) { + 1 -> BdkException.InvalidU32Bytes(String.read(error_buf)) + 2 -> BdkException.Generic(String.read(error_buf)) + 3 -> BdkException.ScriptDoesntHaveAddressForm(String.read(error_buf)) + 4 -> BdkException.NoRecipients(String.read(error_buf)) + 5 -> BdkException.NoUtxosSelected(String.read(error_buf)) + 6 -> BdkException.OutputBelowDustLimit(String.read(error_buf)) + 7 -> BdkException.InsufficientFunds(String.read(error_buf)) + 8 -> BdkException.BnBTotalTriesExceeded(String.read(error_buf)) + 9 -> BdkException.BnBNoExactMatch(String.read(error_buf)) + 10 -> BdkException.UnknownUtxo(String.read(error_buf)) + 11 -> BdkException.TransactionNotFound(String.read(error_buf)) + 12 -> BdkException.TransactionConfirmed(String.read(error_buf)) + 13 -> BdkException.IrreplaceableTransaction(String.read(error_buf)) + 14 -> BdkException.FeeRateTooLow(String.read(error_buf)) + 15 -> BdkException.FeeTooLow(String.read(error_buf)) + 16 -> BdkException.FeeRateUnavailable(String.read(error_buf)) + 17 -> BdkException.MissingKeyOrigin(String.read(error_buf)) + 18 -> BdkException.Key(String.read(error_buf)) + 19 -> BdkException.ChecksumMismatch(String.read(error_buf)) +*************** +*** 1813,1911 **** + 26 -> BdkException.InvalidOutpoint(String.read(error_buf)) + 27 -> BdkException.Descriptor(String.read(error_buf)) + 28 -> BdkException.AddressValidator(String.read(error_buf)) + 29 -> BdkException.Encode(String.read(error_buf)) + 30 -> BdkException.Miniscript(String.read(error_buf)) + 31 -> BdkException.Bip32(String.read(error_buf)) + 32 -> BdkException.Secp256k1(String.read(error_buf)) + 33 -> BdkException.Json(String.read(error_buf)) + 34 -> BdkException.Hex(String.read(error_buf)) + 35 -> BdkException.Psbt(String.read(error_buf)) + 36 -> BdkException.PsbtParse(String.read(error_buf)) + 37 -> BdkException.Electrum(String.read(error_buf)) + 38 -> BdkException.Esplora(String.read(error_buf)) + 39 -> BdkException.Sled(String.read(error_buf)) + 40 -> BdkException.Rusqlite(String.read(error_buf)) + else -> throw RuntimeException("invalid error enum value, something is very wrong!!") + } + } + } + +! +! + } + + + // Declaration and FfiConverters for Progress Callback Interface + + public interface Progress { + fun update(progress: Float, message: String? ) +! + } + + // The ForeignCallback that is passed to Rust. + internal class ForeignCallbackCallbackInterfaceProgress : ForeignCallback { + @Suppress("TooGenericExceptionCaught") + override fun invoke(handle: Handle, method: Int, args: RustBuffer.ByValue, outBuf: RustBufferByReference): Int { + val cb = FfiConverterCallbackInterfaceProgress.lift(handle) ?: throw InternalException("No callback in handlemap; this is a Uniffi bug") + return when (method) { + IDX_CALLBACK_FREE -> { + FfiConverterCallbackInterfaceProgress.drop(handle) + // No return value. + // See docs of ForeignCallback in `uniffi/src/ffi/foreigncallbacks.rs` + 0 + } + 1 -> { + val buffer = this.invokeUpdate(cb, args) + outBuf.setValue(buffer) + // Value written to out buffer. + // See docs of ForeignCallback in `uniffi/src/ffi/foreigncallbacks.rs` + 1 + } +! + // This should never happen, because an out of bounds method index won't + // ever be used. Once we can catch errors, we should return an InternalException. + // https://github.com/mozilla/uniffi-rs/issues/351 + else -> { + // An unexpected error happened. + // See docs of ForeignCallback in `uniffi/src/ffi/foreigncallbacks.rs` + -1 + } + } + } + +! + private fun invokeUpdate(kotlinCallbackInterface: Progress, args: RustBuffer.ByValue): RustBuffer.ByValue = + try { + val buf = args.asByteBuffer() ?: throw InternalException("No ByteBuffer in RustBuffer; this is a Uniffi bug") + kotlinCallbackInterface.update( +! Float.read(buf), +! readOptionalString(buf) + ) + .let { RustBuffer.ByValue() } + // TODO catch errors and report them back to Rust. + // https://github.com/mozilla/uniffi-rs/issues/351 + } finally { + RustBuffer.free(args) + } + +! + } + + // The ffiConverter which transforms the Callbacks in to Handles to pass to Rust. + internal object FfiConverterCallbackInterfaceProgress: FfiConverterCallbackInterface( + foreignCallback = ForeignCallbackCallbackInterfaceProgress() + ) { + override fun register(lib: _UniFFILib) { + rustCall() { status -> + lib.ffi_bdk_360_Progress_init_callback(this.foreignCallback, status) + } + } + } + internal fun UByte.Companion.lift(v: Byte): UByte { + return v.toUByte() + } + + internal fun UByte.Companion.read(buf: ByteBuffer): UByte { + return UByte.lift(buf.get()) + } + +--- 1891,1989 ---- + 26 -> BdkException.InvalidOutpoint(String.read(error_buf)) + 27 -> BdkException.Descriptor(String.read(error_buf)) + 28 -> BdkException.AddressValidator(String.read(error_buf)) + 29 -> BdkException.Encode(String.read(error_buf)) + 30 -> BdkException.Miniscript(String.read(error_buf)) + 31 -> BdkException.Bip32(String.read(error_buf)) + 32 -> BdkException.Secp256k1(String.read(error_buf)) + 33 -> BdkException.Json(String.read(error_buf)) + 34 -> BdkException.Hex(String.read(error_buf)) + 35 -> BdkException.Psbt(String.read(error_buf)) + 36 -> BdkException.PsbtParse(String.read(error_buf)) + 37 -> BdkException.Electrum(String.read(error_buf)) + 38 -> BdkException.Esplora(String.read(error_buf)) + 39 -> BdkException.Sled(String.read(error_buf)) + 40 -> BdkException.Rusqlite(String.read(error_buf)) + else -> throw RuntimeException("invalid error enum value, something is very wrong!!") + } + } + } + +! +! + } + + + // Declaration and FfiConverters for Progress Callback Interface + + public interface Progress { + fun update(progress: Float, message: String? ) +! + } + + // The ForeignCallback that is passed to Rust. + internal class ForeignCallbackCallbackInterfaceProgress : ForeignCallback { + @Suppress("TooGenericExceptionCaught") + override fun invoke(handle: Handle, method: Int, args: RustBuffer.ByValue, outBuf: RustBufferByReference): Int { + val cb = FfiConverterCallbackInterfaceProgress.lift(handle) ?: throw InternalException("No callback in handlemap; this is a Uniffi bug") + return when (method) { + IDX_CALLBACK_FREE -> { + FfiConverterCallbackInterfaceProgress.drop(handle) + // No return value. + // See docs of ForeignCallback in `uniffi/src/ffi/foreigncallbacks.rs` + 0 + } + 1 -> { + val buffer = this.invokeUpdate(cb, args) + outBuf.setValue(buffer) + // Value written to out buffer. + // See docs of ForeignCallback in `uniffi/src/ffi/foreigncallbacks.rs` + 1 + } +! + // This should never happen, because an out of bounds method index won't + // ever be used. Once we can catch errors, we should return an InternalException. + // https://github.com/mozilla/uniffi-rs/issues/351 + else -> { + // An unexpected error happened. + // See docs of ForeignCallback in `uniffi/src/ffi/foreigncallbacks.rs` + -1 + } + } + } + +! + private fun invokeUpdate(kotlinCallbackInterface: Progress, args: RustBuffer.ByValue): RustBuffer.ByValue = + try { + val buf = args.asByteBuffer() ?: throw InternalException("No ByteBuffer in RustBuffer; this is a Uniffi bug") + kotlinCallbackInterface.update( +! Float.read(buf), +! readOptionalString(buf) + ) + .let { RustBuffer.ByValue() } + // TODO catch errors and report them back to Rust. + // https://github.com/mozilla/uniffi-rs/issues/351 + } finally { + RustBuffer.free(args) + } + +! + } + + // The ffiConverter which transforms the Callbacks in to Handles to pass to Rust. + internal object FfiConverterCallbackInterfaceProgress: FfiConverterCallbackInterface( + foreignCallback = ForeignCallbackCallbackInterfaceProgress() + ) { + override fun register(lib: _UniFFILib) { + rustCall() { status -> + lib.ffi_bdk_360_Progress_init_callback(this.foreignCallback, status) + } + } + } + internal fun UByte.Companion.lift(v: Byte): UByte { + return v.toUByte() + } + + internal fun UByte.Companion.read(buf: ByteBuffer): UByte { + return UByte.lift(buf.get()) + } +