diff --git a/bindings/c-ffi/example.c b/bindings/c-ffi/example.c index 3a58e38b..8b419167 100644 --- a/bindings/c-ffi/example.c +++ b/bindings/c-ffi/example.c @@ -1,9 +1,27 @@ #include "rgblib.h" #include #include +#include #include -int main() { +/* Run this method and monitor memory usage to check there are no memory leaks + */ +void checkMemoryLeak() { + for (int i = 0; i < 50; i++) { + CResultString keys_res = rgblib_generate_keys("Regtest", "Taproot"); + if (keys_res.result == Err) { + printf("ERR: %s\n", keys_res.inner); + return; + } + free_string(keys_res.inner); + } +} + +int main(int argc, char *argv[]) { + if (argc > 1 && strcmp(argv[1], "checkMemoryLeak") == 0) { + checkMemoryLeak(); + return EXIT_SUCCESS; + } const char *bitcoin_network = "Regtest"; const char *witness_version = "Taproot"; CResultString keys_res = @@ -180,7 +198,8 @@ int main() { CResultString fee_res = rgblib_get_fee_estimation(wlt, online, "7"); printf("Fee estimation: %s\n", fee_res.inner); - CResultString transfers_res = rgblib_list_transfers(wlt, NULL); + CResultString transfers_res = + rgblib_list_transfers(wlt, "\"AnyOrNone\"", NULL); if (transfers_res.result == Err) { printf("ERR: %s\n", transfers_res.inner); return EXIT_FAILURE; diff --git a/bindings/c-ffi/src/lib.rs b/bindings/c-ffi/src/lib.rs index c1d6a07e..0db42597 100644 --- a/bindings/c-ffi/src/lib.rs +++ b/bindings/c-ffi/src/lib.rs @@ -45,6 +45,17 @@ pub struct CResultString { inner: *mut c_char, } +#[allow(clippy::not_unsafe_ptr_arg_deref)] +#[unsafe(no_mangle)] +pub extern "C" fn free_string(ptr: *mut c_char) { + if ptr.is_null() { + return; + } + unsafe { + let _ = CString::from_raw(ptr); + } +} + #[unsafe(no_mangle)] pub extern "C" fn free_wallet(obj: COpaqueStruct) { unsafe { @@ -188,6 +199,26 @@ pub extern "C" fn rgblib_delete_transfers( delete_transfers(wallet, batch_transfer_idx_opt, no_asset_only).into() } +#[unsafe(no_mangle)] +pub extern "C" fn rgblib_drain_to_begin( + wallet: &COpaqueStruct, + online: *const c_char, + address: *const c_char, + fee_rate: *const c_char, + dry_run: bool, +) -> CResultString { + drain_to_begin(wallet, online, address, fee_rate, dry_run).into() +} + +#[unsafe(no_mangle)] +pub extern "C" fn rgblib_drain_to_end( + wallet: &COpaqueStruct, + online: *const c_char, + signed_psbt: *const c_char, +) -> CResultString { + drain_to_end(wallet, online, signed_psbt).into() +} + #[unsafe(no_mangle)] pub extern "C" fn rgblib_fail_transfers( wallet: &COpaqueStruct, @@ -289,6 +320,37 @@ pub extern "C" fn rgblib_inflate( .into() } +#[unsafe(no_mangle)] +pub extern "C" fn rgblib_inflate_begin( + wallet: &COpaqueStruct, + online: *const c_char, + asset_id: *const c_char, + inflation_amounts: *const c_char, + fee_rate: *const c_char, + min_confirmations: *const c_char, + dry_run: bool, +) -> CResultString { + inflate_begin( + wallet, + online, + asset_id, + inflation_amounts, + fee_rate, + min_confirmations, + dry_run, + ) + .into() +} + +#[unsafe(no_mangle)] +pub extern "C" fn rgblib_inflate_end( + wallet: &COpaqueStruct, + online: *const c_char, + signed_psbt: *const c_char, +) -> CResultString { + inflate_end(wallet, online, signed_psbt).into() +} + #[unsafe(no_mangle)] pub extern "C" fn rgblib_invoice_data(invoice_string: *const c_char) -> CResultString { invoice_data(invoice_string).into() @@ -498,6 +560,31 @@ pub extern "C" fn rgblib_send_btc( send_btc(wallet, online, address, amount, fee_rate, skip_sync).into() } +#[unsafe(no_mangle)] +pub extern "C" fn rgblib_send_btc_begin( + wallet: &COpaqueStruct, + online: *const c_char, + address: *const c_char, + amount: *const c_char, + fee_rate: *const c_char, + skip_sync: bool, + dry_run: bool, +) -> CResultString { + send_btc_begin( + wallet, online, address, amount, fee_rate, skip_sync, dry_run, + ) + .into() +} + +#[unsafe(no_mangle)] +pub extern "C" fn rgblib_send_btc_end( + wallet: &COpaqueStruct, + online: *const c_char, + signed_psbt: *const c_char, +) -> CResultString { + send_btc_end(wallet, online, signed_psbt).into() +} + #[unsafe(no_mangle)] pub extern "C" fn rgblib_send_end( wallet: &COpaqueStruct, diff --git a/bindings/c-ffi/src/utils.rs b/bindings/c-ffi/src/utils.rs index ece36cf8..7772fb86 100644 --- a/bindings/c-ffi/src/utils.rs +++ b/bindings/c-ffi/src/utils.rs @@ -327,6 +327,33 @@ pub(crate) fn delete_transfers( Ok(serde_json::to_string(&res)?) } +pub(crate) fn drain_to_begin( + wallet: &COpaqueStruct, + online: *const c_char, + address: *const c_char, + fee_rate: *const c_char, + dry_run: bool, +) -> Result { + let wallet = Wallet::from_opaque(wallet)?; + let online = convert_online(online)?; + let address = ptr_to_string(address); + let fee_rate = ptr_to_num(fee_rate)?; + let res = wallet.drain_to_begin(online, address, fee_rate, dry_run)?; + Ok(res) +} + +pub(crate) fn drain_to_end( + wallet: &COpaqueStruct, + online: *const c_char, + signed_psbt: *const c_char, +) -> Result { + let wallet = Wallet::from_opaque(wallet)?; + let online = convert_online(online)?; + let signed_psbt = ptr_to_string(signed_psbt); + let res = wallet.drain_to_end(online, signed_psbt)?; + Ok(res) +} + pub(crate) fn fail_transfers( wallet: &COpaqueStruct, online: *const c_char, @@ -442,6 +469,45 @@ pub(crate) fn inflate( Ok(serde_json::to_string(&res)?) } +#[allow(clippy::too_many_arguments)] +pub(crate) fn inflate_begin( + wallet: &COpaqueStruct, + online: *const c_char, + asset_id: *const c_char, + inflation_amounts: *const c_char, + fee_rate: *const c_char, + min_confirmations: *const c_char, + dry_run: bool, +) -> Result { + let wallet = Wallet::from_opaque(wallet)?; + let online = convert_online(online)?; + let asset_id = ptr_to_string(asset_id); + let inflation_amounts = convert_strings_array(inflation_amounts)?; + let fee_rate = ptr_to_num(fee_rate)?; + let min_confirmations = ptr_to_num(min_confirmations)?; + let res = wallet.inflate_begin( + online, + asset_id, + inflation_amounts, + fee_rate, + min_confirmations, + dry_run, + )?; + Ok(serde_json::to_string(&res)?) +} + +pub(crate) fn inflate_end( + wallet: &COpaqueStruct, + online: *const c_char, + signed_psbt: *const c_char, +) -> Result { + let wallet = Wallet::from_opaque(wallet)?; + let online = convert_online(online)?; + let signed_psbt = ptr_to_string(signed_psbt); + let res = wallet.inflate_end(online, signed_psbt)?; + Ok(serde_json::to_string(&res)?) +} + pub(crate) fn invoice_data(invoice_string: *const c_char) -> Result { let invoice_string = ptr_to_string(invoice_string); let invoice = rgb_lib::wallet::Invoice::new(invoice_string)?; @@ -715,6 +781,36 @@ pub(crate) fn send_btc( Ok(res) } +pub(crate) fn send_btc_begin( + wallet: &COpaqueStruct, + online: *const c_char, + address: *const c_char, + amount: *const c_char, + fee_rate: *const c_char, + skip_sync: bool, + dry_run: bool, +) -> Result { + let wallet = Wallet::from_opaque(wallet)?; + let online = convert_online(online)?; + let address = ptr_to_string(address); + let amount = ptr_to_num(amount)?; + let fee_rate = ptr_to_num(fee_rate)?; + let res = wallet.send_btc_begin(online, address, amount, fee_rate, skip_sync, dry_run)?; + Ok(res) +} + +pub(crate) fn send_btc_end( + wallet: &COpaqueStruct, + online: *const c_char, + signed_psbt: *const c_char, +) -> Result { + let wallet = Wallet::from_opaque(wallet)?; + let online = convert_online(online)?; + let signed_psbt = ptr_to_string(signed_psbt); + let res = wallet.send_btc_end(online, signed_psbt)?; + Ok(res) +} + pub(crate) fn send_end( wallet: &COpaqueStruct, online: *const c_char,