Add classes to wrap LibJna native types

This commit is contained in:
Steve Myers 2021-06-21 17:01:53 -07:00
parent 3a5d4816ac
commit 9f29eb0e86
3 changed files with 40 additions and 173 deletions

View File

@ -1,7 +1,6 @@
//use ::safer_ffi::prelude::*;
use bdk::Error;
pub fn error_name(error: &bdk::Error) -> &'static str {
pub fn get_name(error: &bdk::Error) -> String {
match error {
Error::InvalidU32Bytes(_) => "InvalidU32Bytes",
Error::Generic(_) => "Generic",
@ -39,159 +38,9 @@ pub fn error_name(error: &bdk::Error) -> &'static str {
Error::Hex(_) => "Hex",
Error::Psbt(_) => "Psbt",
Error::Electrum(_) => "Electrum",
// Error::Esplora(_) => {}
// Error::CompactFilters(_) => {}
// Error::Esplora(_) => {}
// Error::CompactFilters(_) => {}
Error::Sled(_) => "Sled",
_ => "Unknown",
}
.to_string()
}
//// Errors that can be thrown by the [`Wallet`](crate::wallet::Wallet)
//// Simplified to work over the FFI interface
//#[derive_ReprC]
//#[repr(i16)]
//#[derive(Debug)]
//pub enum WalletError {
// None,
// InvalidU32Bytes,
// Generic,
// ScriptDoesntHaveAddressForm,
// SingleRecipientMultipleOutputs,
// SingleRecipientNoInputs,
// NoRecipients,
// NoUtxosSelected,
// OutputBelowDustLimit,
// InsufficientFunds,
// BnBTotalTriesExceeded,
// BnBNoExactMatch,
// UnknownUtxo,
// TransactionNotFound,
// TransactionConfirmed,
// IrreplaceableTransaction,
// FeeRateTooLow,
// FeeTooLow,
// FeeRateUnavailable,
// MissingKeyOrigin,
// Key,
// ChecksumMismatch,
// SpendingPolicyRequired,
// InvalidPolicyPathError,
// Signer,
// InvalidNetwork,
// InvalidProgressValue,
// ProgressUpdateError,
// InvalidOutpoint,
// Descriptor,
// AddressValidator,
// Encode,
// Miniscript,
// Bip32,
// Secp256k1,
// Json,
// Hex,
// Psbt,
// PsbtParse,
// //#[cfg(feature = "electrum")]
// Electrum,
// //#[cfg(feature = "esplora")]
// //Esplora,
// //#[cfg(feature = "compact_filters")]
// //CompactFilters,
// //#[cfg(feature = "key-value-db")]
// Sled,
//}
//impl From<bdk::Error> for WalletError {
// fn from(error: bdk::Error) -> Self {
// match error {
// Error::InvalidU32Bytes(_) => WalletError::InvalidNetwork,
// Error::Generic(_) => WalletError::Generic,
// Error::ScriptDoesntHaveAddressForm => WalletError::ScriptDoesntHaveAddressForm,
// Error::SingleRecipientMultipleOutputs => WalletError::SingleRecipientMultipleOutputs,
// Error::SingleRecipientNoInputs => WalletError::SingleRecipientNoInputs,
// Error::NoRecipients => WalletError::NoRecipients,
// Error::NoUtxosSelected => WalletError::NoUtxosSelected,
// Error::OutputBelowDustLimit(_) => WalletError::OutputBelowDustLimit,
// Error::InsufficientFunds { .. } => WalletError::InsufficientFunds,
// Error::BnBTotalTriesExceeded => WalletError::BnBTotalTriesExceeded,
// Error::BnBNoExactMatch => WalletError::BnBNoExactMatch,
// Error::UnknownUtxo => WalletError::UnknownUtxo,
// Error::TransactionNotFound => WalletError::TransactionNotFound,
// Error::TransactionConfirmed => WalletError::TransactionConfirmed,
// Error::IrreplaceableTransaction => WalletError::IrreplaceableTransaction,
// Error::FeeRateTooLow { .. } => WalletError::FeeRateTooLow,
// Error::FeeTooLow { .. } => WalletError::FeeTooLow,
// Error::MissingKeyOrigin(_) => WalletError::MissingKeyOrigin,
// Error::Key(_) => WalletError::Key,
// Error::ChecksumMismatch => WalletError::ChecksumMismatch,
// Error::SpendingPolicyRequired(_) => WalletError::SpendingPolicyRequired,
// Error::InvalidPolicyPathError(_) => WalletError::InvalidPolicyPathError,
// Error::Signer(_) => WalletError::Signer,
// Error::InvalidProgressValue(_) => WalletError::InvalidProgressValue,
// Error::ProgressUpdateError => WalletError::ProgressUpdateError,
// Error::InvalidOutpoint(_) => WalletError::InvalidOutpoint,
// Error::Descriptor(_) => WalletError::Descriptor,
// Error::AddressValidator(_) => WalletError::AddressValidator,
// Error::Encode(_) => WalletError::Encode,
// Error::Miniscript(_) => WalletError::Miniscript,
// Error::Bip32(_) => WalletError::Bip32,
// Error::Secp256k1(_) => WalletError::Secp256k1,
// Error::Json(_) => WalletError::Json,
// Error::Hex(_) => WalletError::Hex,
// Error::Psbt(_) => WalletError::Psbt,
// Error::Electrum(_) => WalletError::Electrum,
// //Error::Esplora(_) => WalletError::Esplora,
// //Error::CompactFilters(_) => {}
// Error::Sled(_) => WalletError::Sled,
// }
// }
//}
//type error_code = i16;
//
//impl From<bdk::Error> for error_code {
// fn from(error: bdk::Error) -> Self {
// match error {
// Error::InvalidU32Bytes(_) => 1,
// Error::Generic(_) => 2,
// Error::ScriptDoesntHaveAddressForm => 3,
// Error::SingleRecipientMultipleOutputs => 4,
// Error::SingleRecipientNoInputs => 5,
// Error::NoRecipients => 6,
// Error::NoUtxosSelected => 7,
// Error::OutputBelowDustLimit(_) => 8,
// Error::InsufficientFunds { .. } => 9,
// Error::BnBTotalTriesExceeded => 10,
// Error::BnBNoExactMatch => 11,
// Error::UnknownUtxo => 12,
// Error::TransactionNotFound => 13,
// Error::TransactionConfirmed => 14,
// Error::IrreplaceableTransaction => 15,
// Error::FeeRateTooLow { .. } => 16,
// Error::FeeTooLow { .. } => 17,
// Error::MissingKeyOrigin(_) => 18,
// Error::Key(_) => 19,
// Error::ChecksumMismatch => 20,
// Error::SpendingPolicyRequired(_) => 21,
// Error::InvalidPolicyPathError(_) => 22,
// Error::Signer(_) => 23,
// Error::InvalidProgressValue(_) => 24,
// Error::ProgressUpdateError => 25,
// Error::InvalidOutpoint(_) => 26,
// Error::Descriptor(_) => 27,
// Error::AddressValidator(_) => 28,
// Error::Encode(_) => 29,
// Error::Miniscript(_) => 30,
// Error::Bip32(_) => 31,
// Error::Secp256k1(_) => 32,
// Error::Json(_) => 33,
// Error::Hex(_) => 34,
// Error::Psbt(_) => 35,
// Error::Electrum(_) => 36,
// //Error::Esplora(_) => WalletError::Esplora,
// //Error::CompactFilters(_) => {}
// Error::Sled(_) => 37,
// _ => -1
// }
// }
//}

View File

@ -1,5 +1,6 @@
#![deny(unsafe_code)] /* No `unsafe` needed! */
mod error;
mod wallet;
/// The following test function is necessary for the header generation.
@ -7,6 +8,7 @@ mod wallet;
#[test]
fn generate_headers() -> ::std::io::Result<()> {
::safer_ffi::headers::builder()
.with_guard("__RUST_BDK_FFI__")
.to_file("cc/bdk_ffi.h")?
.generate()
}

View File

@ -1,3 +1,4 @@
use crate::error::get_name;
use ::safer_ffi::prelude::*;
use bdk::bitcoin::network::constants::Network::Testnet;
use bdk::blockchain::{
@ -13,7 +14,7 @@ use safer_ffi::char_p::{char_p_boxed, char_p_ref};
#[derive_ReprC]
#[ReprC::opaque]
pub struct VoidResult {
raw: Result<(), String>,
raw: Result<(), Error>,
}
#[ffi_export]
@ -22,7 +23,7 @@ fn get_void_err(void_result: &VoidResult) -> Option<char_p_boxed> {
.raw
.as_ref()
.err()
.map(|s| char_p_boxed::try_from(s.clone()).unwrap())
.map(|e| char_p_boxed::try_from(get_name(e)).unwrap())
}
#[ffi_export]
@ -33,7 +34,7 @@ fn free_void_result(void_result: Option<Box<VoidResult>>) {
#[derive_ReprC]
#[ReprC::opaque]
pub struct StringResult {
raw: Result<String, String>,
raw: Result<String, Error>,
}
#[ffi_export]
@ -51,7 +52,7 @@ fn get_string_err(string_result: &StringResult) -> Option<char_p_boxed> {
.raw
.as_ref()
.err()
.map(|s| char_p_boxed::try_from(s.clone()).unwrap())
.map(|e| char_p_boxed::try_from(get_name(e)).unwrap())
}
#[ffi_export]
@ -59,10 +60,21 @@ fn free_string_result(string_result: Option<Box<StringResult>>) {
drop(string_result)
}
#[derive_ReprC]
#[ReprC::opaque]
pub struct WalletRef<'lt> {
raw: &'lt Wallet<AnyBlockchain, AnyDatabase>,
}
#[ffi_export]
fn free_wallet_ref(wallet_ref: Option<Box<WalletRef>>) {
drop(wallet_ref)
}
#[derive_ReprC]
#[ReprC::opaque]
pub struct WalletResult {
raw: Result<Wallet<AnyBlockchain, AnyDatabase>, String>,
raw: Result<Wallet<AnyBlockchain, AnyDatabase>, Error>,
}
#[ffi_export]
@ -74,12 +86,12 @@ fn new_wallet_result(
let name = name.to_string();
let descriptor = descriptor.to_string();
let change_descriptor = change_descriptor.map(|s| s.to_string());
let wallet_result = new_wallet(name, descriptor, change_descriptor).map_err(|e| e.to_string());
let wallet_result = new_wallet(name, descriptor, change_descriptor);
Box::new(WalletResult { raw: wallet_result })
}
fn new_wallet(
name: String,
_name: String,
descriptor: String,
change_descriptor: Option<String>,
) -> Result<Wallet<AnyBlockchain, AnyDatabase>, Error> {
@ -108,24 +120,28 @@ fn get_wallet_err(wallet_result: &WalletResult) -> Option<char_p_boxed> {
.raw
.as_ref()
.err()
.map(|s| char_p_boxed::try_from(s.clone()).unwrap())
.map(|e| char_p_boxed::try_from(get_name(&e)).unwrap())
}
#[ffi_export]
fn sync_wallet(wallet_result: &WalletResult) -> Box<VoidResult> {
let wallet_result_ref = wallet_result.raw.as_ref().map_err(|error| error.clone());
let void_result = wallet_result_ref
.and_then(|w| w.sync(log_progress(), Some(100)).map_err(|e| e.to_string()));
fn get_wallet_ok<'lt>(wallet_result: &'lt WalletResult) -> Option<Box<WalletRef<'lt>>> {
wallet_result
.raw
.as_ref()
.ok()
.map(|w| Box::new(WalletRef { raw: w}))
}
#[ffi_export]
fn sync_wallet<'lt>(wallet_ref: &'lt WalletRef<'lt>) -> Box<VoidResult> {
let void_result = wallet_ref
.raw.sync(log_progress(), Some(100));
Box::new(VoidResult { raw: void_result })
}
#[ffi_export]
fn new_address(wallet_result: &WalletResult) -> Box<StringResult> {
let new_address = wallet_result
.raw
.as_ref()
.map_err(|error| error.clone())
.and_then(|w| w.get_address(New).map_err(|error| error.to_string()));
fn new_address<'lt>(wallet_ref: &'lt WalletRef<'lt>) -> Box<StringResult> {
let new_address = wallet_ref.raw.get_address(New);
let string_result = new_address.map(|a| a.to_string());
Box::new(StringResult { raw: string_result })
}