From 9d6229df58938a9ec668a368bffb7ea3fe42d12e Mon Sep 17 00:00:00 2001 From: Sudarsan Balaji Date: Sat, 16 Oct 2021 20:10:07 +0530 Subject: [PATCH 1/4] Simplify logger --- bindings/bdk-kotlin/jvm/src/test/kotlin/uniffi/bdk/LibTest.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bindings/bdk-kotlin/jvm/src/test/kotlin/uniffi/bdk/LibTest.kt b/bindings/bdk-kotlin/jvm/src/test/kotlin/uniffi/bdk/LibTest.kt index abbe923..6e8c7b1 100644 --- a/bindings/bdk-kotlin/jvm/src/test/kotlin/uniffi/bdk/LibTest.kt +++ b/bindings/bdk-kotlin/jvm/src/test/kotlin/uniffi/bdk/LibTest.kt @@ -6,8 +6,7 @@ import org.junit.Test class LogProgress: BdkProgress { override fun update(progress: Float, message: String? ) { - println(progress); - println(message); + println("progress: $progress, message: $message") } } From 320771d7f8a58a0ae26f45abcaf7124b11c6935d Mon Sep 17 00:00:00 2001 From: Sudarsan Balaji Date: Sat, 16 Oct 2021 20:19:34 +0530 Subject: [PATCH 2/4] Add sign and broadcast to wallet --- .../bdk-kotlin/demo/src/main/kotlin/Main.kt | 23 +++-- .../jvm/src/main/kotlin/uniffi/bdk/bdk.kt | 88 ++++++++++++------- src/bdk.udl | 4 + src/lib.rs | 35 ++++++-- 4 files changed, 105 insertions(+), 45 deletions(-) diff --git a/bindings/bdk-kotlin/demo/src/main/kotlin/Main.kt b/bindings/bdk-kotlin/demo/src/main/kotlin/Main.kt index 84c270f..a9e64c6 100644 --- a/bindings/bdk-kotlin/demo/src/main/kotlin/Main.kt +++ b/bindings/bdk-kotlin/demo/src/main/kotlin/Main.kt @@ -9,11 +9,11 @@ class LogProgress: BdkProgress { fun main(args: Array) { println("Configuring an in-memory wallet on electrum..") val descriptor = - "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)"; - val amount = 10000uL; + "pkh(cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR)"; + val amount = 1000uL; val recipient = "tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt"; val db = DatabaseConfig.Memory("") - val client = BlockchainConfig.Electrum(ElectrumConfig("ssl://electrum.blockstream.info:60002", null, 5u, null, 100u)) + val client = BlockchainConfig.Electrum(ElectrumConfig("ssl://electrum.blockstream.info:60002", null, 5u, null, 10u)) val wallet = OnlineWallet(descriptor, Network.TESTNET, db, client) val address = wallet.getNewAddress() println("Please send $amount satoshis to address: $address") @@ -22,8 +22,19 @@ fun main(args: Array) { wallet.sync(LogProgress(), null) val balance = wallet.getBalance() println("New wallet balance: $balance") - println("Refunding $amount satoshis to $recipient") - val psbt = PartiallySignedBitcoinTransaction(wallet, recipient, amount) - println("Press any key to exit") + println("Press Enter to return funds") + readLine() + println("Creating a partially signed bitcoin transaction with recipient $recipient and amount $amount satoshis...") + val transaction = PartiallySignedBitcoinTransaction(wallet, recipient, amount) + println("Signing the transaction...") + wallet.sign(transaction) + println("Broadcasting the signed transaction...") + val transactionId = wallet.broadcast(transaction) + println("Refunded $amount satoshis to $recipient via transaction id $transactionId") + println("Syncing...") + wallet.sync(LogProgress(), null) + val final_balance = wallet.getBalance() + println("New wallet balance: $final_balance") + println("Press Enter to exit") readLine() } diff --git a/bindings/bdk-kotlin/jvm/src/main/kotlin/uniffi/bdk/bdk.kt b/bindings/bdk-kotlin/jvm/src/main/kotlin/uniffi/bdk/bdk.kt index b7777af..6ce2179 100644 --- a/bindings/bdk-kotlin/jvm/src/main/kotlin/uniffi/bdk/bdk.kt +++ b/bindings/bdk-kotlin/jvm/src/main/kotlin/uniffi/bdk/bdk.kt @@ -44,15 +44,15 @@ open class RustBuffer : Structure() { companion object { internal fun alloc(size: Int = 0) = rustCall() { status -> - _UniFFILib.INSTANCE.ffi_bdk_b7c7_rustbuffer_alloc(size, status) + _UniFFILib.INSTANCE.ffi_bdk_b468_rustbuffer_alloc(size, status) } internal fun free(buf: RustBuffer.ByValue) = rustCall() { status -> - _UniFFILib.INSTANCE.ffi_bdk_b7c7_rustbuffer_free(buf, status) + _UniFFILib.INSTANCE.ffi_bdk_b468_rustbuffer_free(buf, status) } internal fun reserve(buf: RustBuffer.ByValue, additional: Int) = rustCall() { status -> - _UniFFILib.INSTANCE.ffi_bdk_b7c7_rustbuffer_reserve(buf, additional, status) + _UniFFILib.INSTANCE.ffi_bdk_b468_rustbuffer_reserve(buf, additional, status) } } @@ -548,67 +548,75 @@ internal interface _UniFFILib : Library { } } - fun ffi_bdk_b7c7_OfflineWallet_object_free(ptr: Pointer, + fun ffi_bdk_b468_OfflineWallet_object_free(ptr: Pointer, uniffi_out_err: RustCallStatus ): Unit - fun bdk_b7c7_OfflineWallet_new(descriptor: RustBuffer.ByValue,network: RustBuffer.ByValue,database_config: RustBuffer.ByValue, + fun bdk_b468_OfflineWallet_new(descriptor: RustBuffer.ByValue,network: RustBuffer.ByValue,database_config: RustBuffer.ByValue, uniffi_out_err: RustCallStatus ): Pointer - fun bdk_b7c7_OfflineWallet_get_new_address(ptr: Pointer, + fun bdk_b468_OfflineWallet_get_new_address(ptr: Pointer, uniffi_out_err: RustCallStatus ): RustBuffer.ByValue - fun ffi_bdk_b7c7_OnlineWallet_object_free(ptr: Pointer, + fun ffi_bdk_b468_OnlineWallet_object_free(ptr: Pointer, uniffi_out_err: RustCallStatus ): Unit - fun bdk_b7c7_OnlineWallet_new(descriptor: RustBuffer.ByValue,network: RustBuffer.ByValue,database_config: RustBuffer.ByValue,blockchain_config: RustBuffer.ByValue, + fun bdk_b468_OnlineWallet_new(descriptor: RustBuffer.ByValue,network: RustBuffer.ByValue,database_config: RustBuffer.ByValue,blockchain_config: RustBuffer.ByValue, uniffi_out_err: RustCallStatus ): Pointer - fun bdk_b7c7_OnlineWallet_get_new_address(ptr: Pointer, + fun bdk_b468_OnlineWallet_get_new_address(ptr: Pointer, uniffi_out_err: RustCallStatus ): RustBuffer.ByValue - fun bdk_b7c7_OnlineWallet_get_network(ptr: Pointer, + fun bdk_b468_OnlineWallet_get_network(ptr: Pointer, uniffi_out_err: RustCallStatus ): RustBuffer.ByValue - fun bdk_b7c7_OnlineWallet_sync(ptr: Pointer,progress_update: Long,max_address_param: RustBuffer.ByValue, + fun bdk_b468_OnlineWallet_sync(ptr: Pointer,progress_update: Long,max_address_param: RustBuffer.ByValue, uniffi_out_err: RustCallStatus ): Unit - fun bdk_b7c7_OnlineWallet_get_balance(ptr: Pointer, + fun bdk_b468_OnlineWallet_get_balance(ptr: Pointer, uniffi_out_err: RustCallStatus ): Long - fun ffi_bdk_b7c7_PartiallySignedBitcoinTransaction_object_free(ptr: Pointer, + fun bdk_b468_OnlineWallet_sign(ptr: Pointer,psbt: Pointer, uniffi_out_err: RustCallStatus ): Unit - fun bdk_b7c7_PartiallySignedBitcoinTransaction_new(wallet: Pointer,recipient: RustBuffer.ByValue,amount: Long, + fun bdk_b468_OnlineWallet_broadcast(ptr: Pointer,psbt: Pointer, + uniffi_out_err: RustCallStatus + ): RustBuffer.ByValue + + fun ffi_bdk_b468_PartiallySignedBitcoinTransaction_object_free(ptr: Pointer, + uniffi_out_err: RustCallStatus + ): Unit + + fun bdk_b468_PartiallySignedBitcoinTransaction_new(wallet: Pointer,recipient: RustBuffer.ByValue,amount: Long, uniffi_out_err: RustCallStatus ): Pointer - fun ffi_bdk_b7c7_BdkProgress_init_callback(callback_stub: ForeignCallback, + fun ffi_bdk_b468_BdkProgress_init_callback(callback_stub: ForeignCallback, uniffi_out_err: RustCallStatus ): Unit - fun ffi_bdk_b7c7_rustbuffer_alloc(size: Int, + fun ffi_bdk_b468_rustbuffer_alloc(size: Int, uniffi_out_err: RustCallStatus ): RustBuffer.ByValue - fun ffi_bdk_b7c7_rustbuffer_from_bytes(bytes: ForeignBytes.ByValue, + fun ffi_bdk_b468_rustbuffer_from_bytes(bytes: ForeignBytes.ByValue, uniffi_out_err: RustCallStatus ): RustBuffer.ByValue - fun ffi_bdk_b7c7_rustbuffer_free(buf: RustBuffer.ByValue, + fun ffi_bdk_b468_rustbuffer_free(buf: RustBuffer.ByValue, uniffi_out_err: RustCallStatus ): Unit - fun ffi_bdk_b7c7_rustbuffer_reserve(buf: RustBuffer.ByValue,additional: Int, + fun ffi_bdk_b468_rustbuffer_reserve(buf: RustBuffer.ByValue,additional: Int, uniffi_out_err: RustCallStatus ): RustBuffer.ByValue @@ -1318,7 +1326,7 @@ class OfflineWallet( constructor(descriptor: String, network: Network, databaseConfig: DatabaseConfig ) : this( rustCallWithError(BdkException) { status -> - _UniFFILib.INSTANCE.bdk_b7c7_OfflineWallet_new(descriptor.lower(), network.lower(), databaseConfig.lower() ,status) + _UniFFILib.INSTANCE.bdk_b468_OfflineWallet_new(descriptor.lower(), network.lower(), databaseConfig.lower() ,status) }) /** @@ -1331,7 +1339,7 @@ class OfflineWallet( */ override protected fun freeRustArcPtr() { rustCall() { status -> - _UniFFILib.INSTANCE.ffi_bdk_b7c7_OfflineWallet_object_free(this.pointer, status) + _UniFFILib.INSTANCE.ffi_bdk_b468_OfflineWallet_object_free(this.pointer, status) } } @@ -1346,7 +1354,7 @@ class OfflineWallet( override fun getNewAddress(): String = callWithPointer { rustCall() { status -> - _UniFFILib.INSTANCE.bdk_b7c7_OfflineWallet_get_new_address(it, status) + _UniFFILib.INSTANCE.bdk_b468_OfflineWallet_get_new_address(it, status) } }.let { String.lift(it) @@ -1375,6 +1383,8 @@ public interface OnlineWalletInterface { fun getNetwork(): Network fun sync(progressUpdate: BdkProgress, maxAddressParam: UInt? ) fun getBalance(): ULong + fun sign(psbt: PartiallySignedBitcoinTransaction ) + fun broadcast(psbt: PartiallySignedBitcoinTransaction ): String } @@ -1385,7 +1395,7 @@ class OnlineWallet( constructor(descriptor: String, network: Network, databaseConfig: DatabaseConfig, blockchainConfig: BlockchainConfig ) : this( rustCallWithError(BdkException) { status -> - _UniFFILib.INSTANCE.bdk_b7c7_OnlineWallet_new(descriptor.lower(), network.lower(), databaseConfig.lower(), blockchainConfig.lower() ,status) + _UniFFILib.INSTANCE.bdk_b468_OnlineWallet_new(descriptor.lower(), network.lower(), databaseConfig.lower(), blockchainConfig.lower() ,status) }) /** @@ -1398,7 +1408,7 @@ class OnlineWallet( */ override protected fun freeRustArcPtr() { rustCall() { status -> - _UniFFILib.INSTANCE.ffi_bdk_b7c7_OnlineWallet_object_free(this.pointer, status) + _UniFFILib.INSTANCE.ffi_bdk_b468_OnlineWallet_object_free(this.pointer, status) } } @@ -1413,7 +1423,7 @@ class OnlineWallet( override fun getNewAddress(): String = callWithPointer { rustCall() { status -> - _UniFFILib.INSTANCE.bdk_b7c7_OnlineWallet_get_new_address(it, status) + _UniFFILib.INSTANCE.bdk_b468_OnlineWallet_get_new_address(it, status) } }.let { String.lift(it) @@ -1422,7 +1432,7 @@ class OnlineWallet( override fun getNetwork(): Network = callWithPointer { rustCall() { status -> - _UniFFILib.INSTANCE.bdk_b7c7_OnlineWallet_get_network(it, status) + _UniFFILib.INSTANCE.bdk_b468_OnlineWallet_get_network(it, status) } }.let { Network.lift(it) @@ -1431,19 +1441,35 @@ class OnlineWallet( override fun sync(progressUpdate: BdkProgress, maxAddressParam: UInt? ) = callWithPointer { rustCallWithError(BdkException) { status -> - _UniFFILib.INSTANCE.bdk_b7c7_OnlineWallet_sync(it, CallbackInterfaceBdkProgressInternals.lower(progressUpdate), lowerOptionalu32(maxAddressParam) , status) + _UniFFILib.INSTANCE.bdk_b468_OnlineWallet_sync(it, CallbackInterfaceBdkProgressInternals.lower(progressUpdate), lowerOptionalu32(maxAddressParam) , status) } } override fun getBalance(): ULong = callWithPointer { rustCallWithError(BdkException) { status -> - _UniFFILib.INSTANCE.bdk_b7c7_OnlineWallet_get_balance(it, status) + _UniFFILib.INSTANCE.bdk_b468_OnlineWallet_get_balance(it, status) } }.let { ULong.lift(it) } + override fun sign(psbt: PartiallySignedBitcoinTransaction ) = + callWithPointer { + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_b468_OnlineWallet_sign(it, psbt.lower() , status) +} + } + + override fun broadcast(psbt: PartiallySignedBitcoinTransaction ): String = + callWithPointer { + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_b468_OnlineWallet_broadcast(it, psbt.lower() , status) +} + }.let { + String.lift(it) + } + companion object { @@ -1473,7 +1499,7 @@ class PartiallySignedBitcoinTransaction( constructor(wallet: OnlineWallet, recipient: String, amount: ULong ) : this( rustCallWithError(BdkException) { status -> - _UniFFILib.INSTANCE.bdk_b7c7_PartiallySignedBitcoinTransaction_new(wallet.lower(), recipient.lower(), amount.lower() ,status) + _UniFFILib.INSTANCE.bdk_b468_PartiallySignedBitcoinTransaction_new(wallet.lower(), recipient.lower(), amount.lower() ,status) }) /** @@ -1486,7 +1512,7 @@ class PartiallySignedBitcoinTransaction( */ override protected fun freeRustArcPtr() { rustCall() { status -> - _UniFFILib.INSTANCE.ffi_bdk_b7c7_PartiallySignedBitcoinTransaction_object_free(this.pointer, status) + _UniFFILib.INSTANCE.ffi_bdk_b468_PartiallySignedBitcoinTransaction_object_free(this.pointer, status) } } @@ -1564,7 +1590,7 @@ internal object CallbackInterfaceBdkProgressInternals: CallbackInternals - lib.ffi_bdk_b7c7_BdkProgress_init_callback(this.foreignCallback, status) + lib.ffi_bdk_b468_BdkProgress_init_callback(this.foreignCallback, status) } } } diff --git a/src/bdk.udl b/src/bdk.udl index 6bc08b0..c0ac19d 100644 --- a/src/bdk.udl +++ b/src/bdk.udl @@ -104,6 +104,10 @@ interface OnlineWallet { void sync(BdkProgress progress_update, u32? max_address_param); [Throws=BdkError] u64 get_balance(); + [Throws=BdkError] + void sign([ByRef] PartiallySignedBitcoinTransaction psbt); + [Throws=BdkError] + string broadcast([ByRef] PartiallySignedBitcoinTransaction psbt); }; interface PartiallySignedBitcoinTransaction { diff --git a/src/lib.rs b/src/lib.rs index 99f50ed..3c232b4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,3 @@ -use bdk::address_validator::AddressValidatorError; use bdk::bitcoin::util::psbt::PartiallySignedTransaction; use bdk::bitcoin::{Address, Network}; use bdk::blockchain::any::{AnyBlockchain, AnyBlockchainConfig}; @@ -9,7 +8,7 @@ use bdk::blockchain::{ use bdk::database::any::{AnyDatabase, SledDbConfiguration}; use bdk::database::{AnyDatabaseConfig, ConfigurableDatabase}; use bdk::wallet::AddressIndex; -use bdk::{Error, Wallet}; +use bdk::{Error, SignOptions, Wallet}; use std::convert::TryFrom; use std::str::FromStr; use std::sync::{Mutex, MutexGuard}; @@ -114,15 +113,17 @@ impl PartiallySignedBitcoinTransaction { let wallet = online_wallet.get_wallet(); match Address::from_str(&recipient) { Ok(address) => { - let mut builder = wallet.build_tx(); - builder.add_recipient(address.script_pubkey(), amount); - let (pst, ..) = builder.finish()?; + let (psbt, _) = { + let mut builder = wallet.build_tx(); + builder.add_recipient(address.script_pubkey(), amount); + builder.finish()? + }; Ok(PartiallySignedBitcoinTransaction { - internal: Mutex::new(pst), + internal: Mutex::new(psbt), }) } - Err(..) => Err(BdkError::AddressValidator( - AddressValidatorError::InvalidScript, + Err(..) => Err(BdkError::Generic( + "failed to read wallet address".to_string(), )), } } @@ -190,6 +191,24 @@ impl OnlineWallet { fn get_balance(&self) -> Result { self.wallet.lock().unwrap().get_balance() } + + fn sign<'a>(&self, psbt: &'a PartiallySignedBitcoinTransaction) -> Result<(), Error> { + let mut psbt = psbt.internal.lock().unwrap(); + let finalized = self.get_wallet().sign(&mut psbt, SignOptions::default())?; + match finalized { + true => Ok(()), + false => Err(BdkError::Generic(format!( + "transaction signing not finalized {:?}", + psbt + ))), + } + } + + fn broadcast<'a>(&self, psbt: &'a PartiallySignedBitcoinTransaction) -> Result { + let tx = psbt.internal.lock().unwrap().clone().extract_tx(); + let tx_id = self.get_wallet().broadcast(tx)?; + Ok(tx_id.to_string()) + } } impl WalletHolder for OnlineWallet { From 58d774a3f3f78c9e5f815d0ca9f659c319dd8066 Mon Sep 17 00:00:00 2001 From: Sudarsan Balaji Date: Sat, 16 Oct 2021 20:19:56 +0530 Subject: [PATCH 3/4] Fix formatting --- src/bdk.udl | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/bdk.udl b/src/bdk.udl index c0ac19d..5ee8f95 100644 --- a/src/bdk.udl +++ b/src/bdk.udl @@ -64,25 +64,25 @@ interface DatabaseConfig { }; interface OfflineWallet { - [Throws=BdkError] - constructor(string descriptor, Network network, DatabaseConfig database_config); - string get_new_address(); + [Throws=BdkError] + constructor(string descriptor, Network network, DatabaseConfig database_config); + string get_new_address(); }; dictionary ElectrumConfig { - string url; - string? socks5; - u8 retry; - u8? timeout; - u64 stop_gap; + string url; + string? socks5; + u8 retry; + u8? timeout; + u64 stop_gap; }; dictionary EsploraConfig { - string base_url; - string? proxy; - u64 timeout_read; - u64 timeout_write; - u64 stop_gap; + string base_url; + string? proxy; + u64 timeout_read; + u64 timeout_write; + u64 stop_gap; }; [Enum] @@ -96,14 +96,14 @@ callback interface BdkProgress { }; interface OnlineWallet { - [Throws=BdkError] - constructor(string descriptor, Network network, DatabaseConfig database_config, BlockchainConfig blockchain_config); - string get_new_address(); - Network get_network(); - [Throws=BdkError] - void sync(BdkProgress progress_update, u32? max_address_param); - [Throws=BdkError] - u64 get_balance(); + [Throws=BdkError] + constructor(string descriptor, Network network, DatabaseConfig database_config, BlockchainConfig blockchain_config); + string get_new_address(); + Network get_network(); + [Throws=BdkError] + void sync(BdkProgress progress_update, u32? max_address_param); + [Throws=BdkError] + u64 get_balance(); [Throws=BdkError] void sign([ByRef] PartiallySignedBitcoinTransaction psbt); [Throws=BdkError] From ca0a2cba15fedb9c4f17955af954b4b541d0df51 Mon Sep 17 00:00:00 2001 From: Sudarsan Balaji Date: Sat, 16 Oct 2021 20:25:58 +0530 Subject: [PATCH 4/4] Share Wallet::getBalance and Wallet::sign --- .../jvm/src/main/kotlin/uniffi/bdk/bdk.kt | 176 ++++++++++-------- src/bdk.udl | 16 +- src/lib.rs | 32 ++-- 3 files changed, 130 insertions(+), 94 deletions(-) diff --git a/bindings/bdk-kotlin/jvm/src/main/kotlin/uniffi/bdk/bdk.kt b/bindings/bdk-kotlin/jvm/src/main/kotlin/uniffi/bdk/bdk.kt index 6ce2179..15731af 100644 --- a/bindings/bdk-kotlin/jvm/src/main/kotlin/uniffi/bdk/bdk.kt +++ b/bindings/bdk-kotlin/jvm/src/main/kotlin/uniffi/bdk/bdk.kt @@ -44,15 +44,15 @@ open class RustBuffer : Structure() { companion object { internal fun alloc(size: Int = 0) = rustCall() { status -> - _UniFFILib.INSTANCE.ffi_bdk_b468_rustbuffer_alloc(size, status) + _UniFFILib.INSTANCE.ffi_bdk_70ef_rustbuffer_alloc(size, status) } internal fun free(buf: RustBuffer.ByValue) = rustCall() { status -> - _UniFFILib.INSTANCE.ffi_bdk_b468_rustbuffer_free(buf, status) + _UniFFILib.INSTANCE.ffi_bdk_70ef_rustbuffer_free(buf, status) } internal fun reserve(buf: RustBuffer.ByValue, additional: Int) = rustCall() { status -> - _UniFFILib.INSTANCE.ffi_bdk_b468_rustbuffer_reserve(buf, additional, status) + _UniFFILib.INSTANCE.ffi_bdk_70ef_rustbuffer_reserve(buf, additional, status) } } @@ -548,75 +548,83 @@ internal interface _UniFFILib : Library { } } - fun ffi_bdk_b468_OfflineWallet_object_free(ptr: Pointer, + fun ffi_bdk_70ef_OfflineWallet_object_free(ptr: Pointer, uniffi_out_err: RustCallStatus ): Unit - fun bdk_b468_OfflineWallet_new(descriptor: RustBuffer.ByValue,network: RustBuffer.ByValue,database_config: RustBuffer.ByValue, + fun bdk_70ef_OfflineWallet_new(descriptor: RustBuffer.ByValue,network: RustBuffer.ByValue,database_config: RustBuffer.ByValue, uniffi_out_err: RustCallStatus ): Pointer - fun bdk_b468_OfflineWallet_get_new_address(ptr: Pointer, + fun bdk_70ef_OfflineWallet_get_new_address(ptr: Pointer, uniffi_out_err: RustCallStatus ): RustBuffer.ByValue - fun ffi_bdk_b468_OnlineWallet_object_free(ptr: Pointer, - uniffi_out_err: RustCallStatus - ): Unit - - fun bdk_b468_OnlineWallet_new(descriptor: RustBuffer.ByValue,network: RustBuffer.ByValue,database_config: RustBuffer.ByValue,blockchain_config: RustBuffer.ByValue, - uniffi_out_err: RustCallStatus - ): Pointer - - fun bdk_b468_OnlineWallet_get_new_address(ptr: Pointer, - uniffi_out_err: RustCallStatus - ): RustBuffer.ByValue - - fun bdk_b468_OnlineWallet_get_network(ptr: Pointer, - uniffi_out_err: RustCallStatus - ): RustBuffer.ByValue - - fun bdk_b468_OnlineWallet_sync(ptr: Pointer,progress_update: Long,max_address_param: RustBuffer.ByValue, - uniffi_out_err: RustCallStatus - ): Unit - - fun bdk_b468_OnlineWallet_get_balance(ptr: Pointer, + fun bdk_70ef_OfflineWallet_get_balance(ptr: Pointer, uniffi_out_err: RustCallStatus ): Long - fun bdk_b468_OnlineWallet_sign(ptr: Pointer,psbt: Pointer, + fun bdk_70ef_OfflineWallet_sign(ptr: Pointer,psbt: Pointer, uniffi_out_err: RustCallStatus ): Unit - fun bdk_b468_OnlineWallet_broadcast(ptr: Pointer,psbt: Pointer, - uniffi_out_err: RustCallStatus - ): RustBuffer.ByValue - - fun ffi_bdk_b468_PartiallySignedBitcoinTransaction_object_free(ptr: Pointer, + fun ffi_bdk_70ef_OnlineWallet_object_free(ptr: Pointer, uniffi_out_err: RustCallStatus ): Unit - fun bdk_b468_PartiallySignedBitcoinTransaction_new(wallet: Pointer,recipient: RustBuffer.ByValue,amount: Long, + fun bdk_70ef_OnlineWallet_new(descriptor: RustBuffer.ByValue,network: RustBuffer.ByValue,database_config: RustBuffer.ByValue,blockchain_config: RustBuffer.ByValue, uniffi_out_err: RustCallStatus ): Pointer - fun ffi_bdk_b468_BdkProgress_init_callback(callback_stub: ForeignCallback, - uniffi_out_err: RustCallStatus - ): Unit - - fun ffi_bdk_b468_rustbuffer_alloc(size: Int, + fun bdk_70ef_OnlineWallet_get_new_address(ptr: Pointer, uniffi_out_err: RustCallStatus ): RustBuffer.ByValue - fun ffi_bdk_b468_rustbuffer_from_bytes(bytes: ForeignBytes.ByValue, + fun bdk_70ef_OnlineWallet_get_balance(ptr: Pointer, uniffi_out_err: RustCallStatus - ): RustBuffer.ByValue + ): Long - fun ffi_bdk_b468_rustbuffer_free(buf: RustBuffer.ByValue, + fun bdk_70ef_OnlineWallet_sign(ptr: Pointer,psbt: Pointer, uniffi_out_err: RustCallStatus ): Unit - fun ffi_bdk_b468_rustbuffer_reserve(buf: RustBuffer.ByValue,additional: Int, + fun bdk_70ef_OnlineWallet_get_network(ptr: Pointer, + uniffi_out_err: RustCallStatus + ): RustBuffer.ByValue + + fun bdk_70ef_OnlineWallet_sync(ptr: Pointer,progress_update: Long,max_address_param: RustBuffer.ByValue, + uniffi_out_err: RustCallStatus + ): Unit + + fun bdk_70ef_OnlineWallet_broadcast(ptr: Pointer,psbt: Pointer, + uniffi_out_err: RustCallStatus + ): RustBuffer.ByValue + + fun ffi_bdk_70ef_PartiallySignedBitcoinTransaction_object_free(ptr: Pointer, + uniffi_out_err: RustCallStatus + ): Unit + + fun bdk_70ef_PartiallySignedBitcoinTransaction_new(wallet: Pointer,recipient: RustBuffer.ByValue,amount: Long, + uniffi_out_err: RustCallStatus + ): Pointer + + fun ffi_bdk_70ef_BdkProgress_init_callback(callback_stub: ForeignCallback, + uniffi_out_err: RustCallStatus + ): Unit + + fun ffi_bdk_70ef_rustbuffer_alloc(size: Int, + uniffi_out_err: RustCallStatus + ): RustBuffer.ByValue + + fun ffi_bdk_70ef_rustbuffer_from_bytes(bytes: ForeignBytes.ByValue, + uniffi_out_err: RustCallStatus + ): RustBuffer.ByValue + + fun ffi_bdk_70ef_rustbuffer_free(buf: RustBuffer.ByValue, + uniffi_out_err: RustCallStatus + ): Unit + + fun ffi_bdk_70ef_rustbuffer_reserve(buf: RustBuffer.ByValue,additional: Int, uniffi_out_err: RustCallStatus ): RustBuffer.ByValue @@ -1313,20 +1321,22 @@ data class EsploraConfig ( // Objects - +@ExperimentalUnsignedTypes public interface OfflineWalletInterface { fun getNewAddress(): String + fun getBalance(): ULong + fun sign(psbt: PartiallySignedBitcoinTransaction ) } - +@ExperimentalUnsignedTypes class OfflineWallet( pointer: Pointer ) : FFIObject(pointer), OfflineWalletInterface { constructor(descriptor: String, network: Network, databaseConfig: DatabaseConfig ) : this( rustCallWithError(BdkException) { status -> - _UniFFILib.INSTANCE.bdk_b468_OfflineWallet_new(descriptor.lower(), network.lower(), databaseConfig.lower() ,status) + _UniFFILib.INSTANCE.bdk_70ef_OfflineWallet_new(descriptor.lower(), network.lower(), databaseConfig.lower() ,status) }) /** @@ -1339,7 +1349,7 @@ class OfflineWallet( */ override protected fun freeRustArcPtr() { rustCall() { status -> - _UniFFILib.INSTANCE.ffi_bdk_b468_OfflineWallet_object_free(this.pointer, status) + _UniFFILib.INSTANCE.ffi_bdk_70ef_OfflineWallet_object_free(this.pointer, status) } } @@ -1354,12 +1364,28 @@ class OfflineWallet( override fun getNewAddress(): String = callWithPointer { rustCall() { status -> - _UniFFILib.INSTANCE.bdk_b468_OfflineWallet_get_new_address(it, status) + _UniFFILib.INSTANCE.bdk_70ef_OfflineWallet_get_new_address(it, status) } }.let { String.lift(it) } + override fun getBalance(): ULong = + callWithPointer { + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_70ef_OfflineWallet_get_balance(it, status) +} + }.let { + ULong.lift(it) + } + + override fun sign(psbt: PartiallySignedBitcoinTransaction ) = + callWithPointer { + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_70ef_OfflineWallet_sign(it, psbt.lower() , status) +} + } + companion object { @@ -1380,10 +1406,10 @@ class OfflineWallet( @ExperimentalUnsignedTypes public interface OnlineWalletInterface { fun getNewAddress(): String - fun getNetwork(): Network - fun sync(progressUpdate: BdkProgress, maxAddressParam: UInt? ) fun getBalance(): ULong fun sign(psbt: PartiallySignedBitcoinTransaction ) + fun getNetwork(): Network + fun sync(progressUpdate: BdkProgress, maxAddressParam: UInt? ) fun broadcast(psbt: PartiallySignedBitcoinTransaction ): String } @@ -1395,7 +1421,7 @@ class OnlineWallet( constructor(descriptor: String, network: Network, databaseConfig: DatabaseConfig, blockchainConfig: BlockchainConfig ) : this( rustCallWithError(BdkException) { status -> - _UniFFILib.INSTANCE.bdk_b468_OnlineWallet_new(descriptor.lower(), network.lower(), databaseConfig.lower(), blockchainConfig.lower() ,status) + _UniFFILib.INSTANCE.bdk_70ef_OnlineWallet_new(descriptor.lower(), network.lower(), databaseConfig.lower(), blockchainConfig.lower() ,status) }) /** @@ -1408,7 +1434,7 @@ class OnlineWallet( */ override protected fun freeRustArcPtr() { rustCall() { status -> - _UniFFILib.INSTANCE.ffi_bdk_b468_OnlineWallet_object_free(this.pointer, status) + _UniFFILib.INSTANCE.ffi_bdk_70ef_OnlineWallet_object_free(this.pointer, status) } } @@ -1423,32 +1449,16 @@ class OnlineWallet( override fun getNewAddress(): String = callWithPointer { rustCall() { status -> - _UniFFILib.INSTANCE.bdk_b468_OnlineWallet_get_new_address(it, status) + _UniFFILib.INSTANCE.bdk_70ef_OnlineWallet_get_new_address(it, status) } }.let { String.lift(it) } - override fun getNetwork(): Network = - callWithPointer { - rustCall() { status -> - _UniFFILib.INSTANCE.bdk_b468_OnlineWallet_get_network(it, status) -} - }.let { - Network.lift(it) - } - - override fun sync(progressUpdate: BdkProgress, maxAddressParam: UInt? ) = - callWithPointer { - rustCallWithError(BdkException) { status -> - _UniFFILib.INSTANCE.bdk_b468_OnlineWallet_sync(it, CallbackInterfaceBdkProgressInternals.lower(progressUpdate), lowerOptionalu32(maxAddressParam) , status) -} - } - override fun getBalance(): ULong = callWithPointer { rustCallWithError(BdkException) { status -> - _UniFFILib.INSTANCE.bdk_b468_OnlineWallet_get_balance(it, status) + _UniFFILib.INSTANCE.bdk_70ef_OnlineWallet_get_balance(it, status) } }.let { ULong.lift(it) @@ -1457,14 +1467,30 @@ class OnlineWallet( override fun sign(psbt: PartiallySignedBitcoinTransaction ) = callWithPointer { rustCallWithError(BdkException) { status -> - _UniFFILib.INSTANCE.bdk_b468_OnlineWallet_sign(it, psbt.lower() , status) + _UniFFILib.INSTANCE.bdk_70ef_OnlineWallet_sign(it, psbt.lower() , status) +} + } + + override fun getNetwork(): Network = + callWithPointer { + rustCall() { status -> + _UniFFILib.INSTANCE.bdk_70ef_OnlineWallet_get_network(it, status) +} + }.let { + Network.lift(it) + } + + override fun sync(progressUpdate: BdkProgress, maxAddressParam: UInt? ) = + callWithPointer { + rustCallWithError(BdkException) { status -> + _UniFFILib.INSTANCE.bdk_70ef_OnlineWallet_sync(it, CallbackInterfaceBdkProgressInternals.lower(progressUpdate), lowerOptionalu32(maxAddressParam) , status) } } override fun broadcast(psbt: PartiallySignedBitcoinTransaction ): String = callWithPointer { rustCallWithError(BdkException) { status -> - _UniFFILib.INSTANCE.bdk_b468_OnlineWallet_broadcast(it, psbt.lower() , status) + _UniFFILib.INSTANCE.bdk_70ef_OnlineWallet_broadcast(it, psbt.lower() , status) } }.let { String.lift(it) @@ -1499,7 +1525,7 @@ class PartiallySignedBitcoinTransaction( constructor(wallet: OnlineWallet, recipient: String, amount: ULong ) : this( rustCallWithError(BdkException) { status -> - _UniFFILib.INSTANCE.bdk_b468_PartiallySignedBitcoinTransaction_new(wallet.lower(), recipient.lower(), amount.lower() ,status) + _UniFFILib.INSTANCE.bdk_70ef_PartiallySignedBitcoinTransaction_new(wallet.lower(), recipient.lower(), amount.lower() ,status) }) /** @@ -1512,7 +1538,7 @@ class PartiallySignedBitcoinTransaction( */ override protected fun freeRustArcPtr() { rustCall() { status -> - _UniFFILib.INSTANCE.ffi_bdk_b468_PartiallySignedBitcoinTransaction_object_free(this.pointer, status) + _UniFFILib.INSTANCE.ffi_bdk_70ef_PartiallySignedBitcoinTransaction_object_free(this.pointer, status) } } @@ -1590,7 +1616,7 @@ internal object CallbackInterfaceBdkProgressInternals: CallbackInternals - lib.ffi_bdk_b468_BdkProgress_init_callback(this.foreignCallback, status) + lib.ffi_bdk_70ef_BdkProgress_init_callback(this.foreignCallback, status) } } } diff --git a/src/bdk.udl b/src/bdk.udl index 5ee8f95..9f386de 100644 --- a/src/bdk.udl +++ b/src/bdk.udl @@ -66,7 +66,13 @@ interface DatabaseConfig { interface OfflineWallet { [Throws=BdkError] constructor(string descriptor, Network network, DatabaseConfig database_config); + + // OfflineWalletOperations string get_new_address(); + [Throws=BdkError] + u64 get_balance(); + [Throws=BdkError] + void sign([ByRef] PartiallySignedBitcoinTransaction psbt); }; dictionary ElectrumConfig { @@ -98,14 +104,18 @@ callback interface BdkProgress { interface OnlineWallet { [Throws=BdkError] constructor(string descriptor, Network network, DatabaseConfig database_config, BlockchainConfig blockchain_config); + + // OfflineWalletOperations string get_new_address(); - Network get_network(); - [Throws=BdkError] - void sync(BdkProgress progress_update, u32? max_address_param); [Throws=BdkError] u64 get_balance(); [Throws=BdkError] void sign([ByRef] PartiallySignedBitcoinTransaction psbt); + + // OnlineWalletInterface + Network get_network(); + [Throws=BdkError] + void sync(BdkProgress progress_update, u32? max_address_param); [Throws=BdkError] string broadcast([ByRef] PartiallySignedBitcoinTransaction psbt); }; diff --git a/src/lib.rs b/src/lib.rs index 3c232b4..d9d375f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,6 +65,22 @@ trait OfflineWalletOperations: WalletHolder { .address .to_string() } + + fn get_balance(&self) -> Result { + self.get_wallet().get_balance() + } + + fn sign<'a>(&self, psbt: &'a PartiallySignedBitcoinTransaction) -> Result<(), Error> { + let mut psbt = psbt.internal.lock().unwrap(); + let finalized = self.get_wallet().sign(&mut psbt, SignOptions::default())?; + match finalized { + true => Ok(()), + false => Err(BdkError::Generic(format!( + "transaction signing not finalized {:?}", + psbt + ))), + } + } } impl OfflineWallet { @@ -188,22 +204,6 @@ impl OnlineWallet { .sync(BdkProgressHolder { progress_update }, max_address_param) } - fn get_balance(&self) -> Result { - self.wallet.lock().unwrap().get_balance() - } - - fn sign<'a>(&self, psbt: &'a PartiallySignedBitcoinTransaction) -> Result<(), Error> { - let mut psbt = psbt.internal.lock().unwrap(); - let finalized = self.get_wallet().sign(&mut psbt, SignOptions::default())?; - match finalized { - true => Ok(()), - false => Err(BdkError::Generic(format!( - "transaction signing not finalized {:?}", - psbt - ))), - } - } - fn broadcast<'a>(&self, psbt: &'a PartiallySignedBitcoinTransaction) -> Result { let tx = psbt.internal.lock().unwrap().clone().extract_tx(); let tx_id = self.get_wallet().broadcast(tx)?;