Add classes to wrap LibJna native types
This commit is contained in:
parent
90c4fd3328
commit
d248bca299
@ -4,6 +4,12 @@ plugins {
|
||||
id 'maven-publish'
|
||||
}
|
||||
|
||||
test {
|
||||
testLogging {
|
||||
events "PASSED", "SKIPPED", "FAILED", "STANDARD_OUT", "STANDARD_ERROR"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation platform('org.jetbrains.kotlin:kotlin-bom')
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
|
43
bdk-kotlin/jvm/src/main/java/org/bitcoindevkit/bdk/Error.kt
Normal file
43
bdk-kotlin/jvm/src/main/java/org/bitcoindevkit/bdk/Error.kt
Normal file
@ -0,0 +1,43 @@
|
||||
package org.bitcoindevkit.bdk
|
||||
|
||||
enum class Error {
|
||||
InvalidU32Bytes,
|
||||
Generic,
|
||||
ScriptDoesntHaveAddressForm,
|
||||
SingleRecipientMultipleOutputs,
|
||||
SingleRecipientNoInputs,
|
||||
NoRecipients,
|
||||
NoUtxosSelected,
|
||||
OutputBelowDustLimit,
|
||||
InsufficientFunds,
|
||||
BnBTotalTriesExceeded,
|
||||
BnBNoExactMatch,
|
||||
UnknownUtxo,
|
||||
TransactionNotFound,
|
||||
TransactionConfirmed,
|
||||
IrreplaceableTransaction,
|
||||
FeeRateTooLow,
|
||||
FeeTooLow,
|
||||
MissingKeyOrigin,
|
||||
Key,
|
||||
ChecksumMismatch,
|
||||
SpendingPolicyRequired,
|
||||
InvalidPolicyPathError,
|
||||
Signer,
|
||||
InvalidProgressValue,
|
||||
ProgressUpdateError,
|
||||
InvalidOutpoint,
|
||||
Descriptor,
|
||||
AddressValidator,
|
||||
Encode,
|
||||
Miniscript,
|
||||
Bip32,
|
||||
Secp256k1,
|
||||
Json,
|
||||
Hex,
|
||||
Psbt,
|
||||
Electrum,
|
||||
// Esplora
|
||||
// CompactFilters
|
||||
Sled,
|
||||
}
|
@ -35,10 +35,16 @@ interface LibJna : Library {
|
||||
// void free_string_result (
|
||||
// StringResult_t * string_result);
|
||||
fun free_string_result(string_result: StringResult_t)
|
||||
|
||||
// void free_string (
|
||||
// char * string);
|
||||
fun free_string(string: Pointer?)
|
||||
|
||||
// typedef struct WalletRef WalletRef_t;
|
||||
class WalletRef_t : PointerType {
|
||||
constructor() : super()
|
||||
constructor(pointer: Pointer) : super(pointer)
|
||||
}
|
||||
|
||||
// void free_wallet_ref (
|
||||
// WalletRef_t * wallet_ref);
|
||||
fun free_wallet_ref(wallet_ref: WalletRef_t)
|
||||
|
||||
// typedef struct WalletResult WalletResult_t;
|
||||
class WalletResult_t : PointerType {
|
||||
@ -58,17 +64,25 @@ interface LibJna : Library {
|
||||
|
||||
// char * get_wallet_err (
|
||||
// WalletResult_t const * wallet_result);
|
||||
// TODO
|
||||
fun get_wallet_err(wallet_result: WalletResult_t): Pointer?
|
||||
|
||||
// WalletRef_t * get_wallet_ok (
|
||||
// WalletResult_t const * wallet_result);
|
||||
fun get_wallet_ok(wallet_result: WalletResult_t): WalletRef_t?
|
||||
|
||||
// VoidResult_t * sync_wallet (
|
||||
// WalletResult_t const * wallet_result);
|
||||
fun sync_wallet(wallet_result: WalletResult_t): VoidResult_t
|
||||
// WalletRef_t const * wallet_ref);
|
||||
fun sync_wallet(wallet_ref: Pointer): VoidResult_t
|
||||
|
||||
// StringResult_t * new_address (
|
||||
// WalletResult_t const * wallet_result);
|
||||
fun new_address(wallet_result: WalletResult_t): StringResult_t
|
||||
// WalletRef_t const * wallet_ref);
|
||||
fun new_address(wallet_ref: Pointer): StringResult_t
|
||||
|
||||
// void free_wallet_result (
|
||||
// WalletResult_t * wallet_result);
|
||||
fun free_wallet_result(wallet_result: WalletResult_t)
|
||||
|
||||
// void free_string (
|
||||
// char * string);
|
||||
fun free_string(string: Pointer?)
|
||||
}
|
||||
|
@ -0,0 +1,32 @@
|
||||
package org.bitcoindevkit.bdk
|
||||
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
class StringResult internal constructor(private val stringResultT: LibJna.StringResult_t) : LibBase() {
|
||||
|
||||
private val log: Logger = LoggerFactory.getLogger(StringResult::class.java)
|
||||
|
||||
fun isErr(): Boolean {
|
||||
return libJna.get_string_err(stringResultT) != null
|
||||
}
|
||||
|
||||
fun err(): String? {
|
||||
val errPointer = libJna.get_string_err(stringResultT)
|
||||
val err = errPointer?.getString(0)
|
||||
libJna.free_string(errPointer)
|
||||
return err
|
||||
}
|
||||
|
||||
fun ok(): String? {
|
||||
val okPointer = libJna.get_string_ok(stringResultT)
|
||||
val ok = okPointer?.getString(0)
|
||||
libJna.free_string(okPointer)
|
||||
return ok
|
||||
}
|
||||
|
||||
protected fun finalize() {
|
||||
libJna.free_string_result(stringResultT)
|
||||
log.debug("StringResult_t freed")
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package org.bitcoindevkit.bdk
|
||||
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
class VoidResult internal constructor(private val voidResultT: LibJna.VoidResult_t) : LibBase() {
|
||||
|
||||
private val log: Logger = LoggerFactory.getLogger(VoidResult::class.java)
|
||||
|
||||
fun isErr(): Boolean {
|
||||
return libJna.get_void_err(voidResultT) != null
|
||||
}
|
||||
|
||||
fun err(): String? {
|
||||
val errPointer = libJna.get_void_err(voidResultT)
|
||||
val err = errPointer?.getString(0)
|
||||
libJna.free_string(errPointer)
|
||||
return err
|
||||
}
|
||||
|
||||
protected fun finalize() {
|
||||
libJna.free_void_result(voidResultT)
|
||||
log.debug("VoidResult_t freed")
|
||||
}
|
||||
}
|
25
bdk-kotlin/jvm/src/main/java/org/bitcoindevkit/bdk/Wallet.kt
Normal file
25
bdk-kotlin/jvm/src/main/java/org/bitcoindevkit/bdk/Wallet.kt
Normal file
@ -0,0 +1,25 @@
|
||||
package org.bitcoindevkit.bdk
|
||||
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
class Wallet internal constructor(
|
||||
private val walletRefT: LibJna.WalletRef_t,
|
||||
) : LibBase() {
|
||||
|
||||
private val log: Logger = LoggerFactory.getLogger(Wallet::class.java)
|
||||
|
||||
fun sync(): VoidResult {
|
||||
return VoidResult(libJna.sync_wallet(walletRefT.pointer))
|
||||
}
|
||||
|
||||
fun getAddress(): StringResult {
|
||||
return StringResult(libJna.new_address(walletRefT.pointer))
|
||||
}
|
||||
|
||||
protected fun finalize() {
|
||||
libJna.free_wallet_ref(walletRefT)
|
||||
log.debug("WalletRef_t freed")
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package org.bitcoindevkit.bdk
|
||||
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
class WalletResult(
|
||||
name: String,
|
||||
descriptor: String,
|
||||
changeDescriptor: String?,
|
||||
) : LibBase() {
|
||||
|
||||
private val log: Logger = LoggerFactory.getLogger(WalletResult::class.java)
|
||||
private val walletResultT = libJna.new_wallet_result(name, descriptor, changeDescriptor)
|
||||
|
||||
fun isErr(): Boolean {
|
||||
return libJna.get_wallet_err(walletResultT) != null
|
||||
}
|
||||
|
||||
fun err(): String? {
|
||||
val errPointer = libJna.get_wallet_err(walletResultT)
|
||||
val err = errPointer?.getString(0)
|
||||
libJna.free_string(errPointer)
|
||||
return err
|
||||
}
|
||||
|
||||
fun ok(): Wallet? {
|
||||
val okWalletRef = libJna.get_wallet_ok(walletResultT)
|
||||
return if (okWalletRef != null) Wallet(okWalletRef) else null
|
||||
}
|
||||
|
||||
protected fun finalize() {
|
||||
libJna.free_wallet_result(walletResultT)
|
||||
log.debug("WalletResult_t freed")
|
||||
}
|
||||
|
||||
}
|
@ -9,6 +9,7 @@ dependencies {
|
||||
implementation "net.java.dev.jna:jna:5.8.0"
|
||||
implementation (project(':jvm'))
|
||||
implementation 'org.jetbrains.kotlin:kotlin-test-junit'
|
||||
//implementation "org.mockito.kotlin:mockito-kotlin:3.2.0"
|
||||
api "org.slf4j:slf4j-api:1.7.30"
|
||||
}
|
||||
|
||||
|
@ -1,71 +1,67 @@
|
||||
package org.bitcoindevkit.bdk
|
||||
|
||||
import org.junit.*
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.*
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertNull
|
||||
|
||||
/**
|
||||
* Library test, which will execute on linux host.
|
||||
*
|
||||
*/
|
||||
abstract class LibTest {
|
||||
abstract class LibTest : LibBase() {
|
||||
|
||||
companion object : LibBase() {
|
||||
private val log: Logger = LoggerFactory.getLogger(LibTest::class.java)
|
||||
|
||||
private lateinit var wallet_result: LibJna.WalletResult_t
|
||||
private val log: Logger = LoggerFactory.getLogger(LibTest::class.java)
|
||||
|
||||
@BeforeClass
|
||||
@JvmStatic
|
||||
fun new_wallet() {
|
||||
val name = "test_wallet"
|
||||
val desc =
|
||||
"wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)"
|
||||
val change =
|
||||
"wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"
|
||||
val name = "test_wallet"
|
||||
val desc =
|
||||
"wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)"
|
||||
val change =
|
||||
"wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"
|
||||
|
||||
wallet_result = libJna.new_wallet_result(name, desc, change)
|
||||
log.debug("wallet created")
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
@JvmStatic
|
||||
fun free_wallet() {
|
||||
libJna.free_wallet_result(wallet_result)
|
||||
log.debug("wallet freed")
|
||||
@Test
|
||||
fun walletResultError() {
|
||||
val badWalletResult = WalletResult("bad", "bad", "bad")
|
||||
assertTrue(badWalletResult.isErr())
|
||||
val walletErr = badWalletResult.err()
|
||||
assertNotNull(walletErr)
|
||||
log.debug("wallet error $walletErr")
|
||||
assertEquals("Descriptor", walletErr)
|
||||
val wallet = badWalletResult.ok()
|
||||
assertNull(wallet)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun walletResultFinalize() {
|
||||
val names = listOf("one", "two", "three")
|
||||
names.map {
|
||||
val wallet = WalletResult(it, desc, change)
|
||||
assertNotNull(wallet)
|
||||
}
|
||||
System.gc()
|
||||
// The only way to verify wallets freed is by checking the log
|
||||
}
|
||||
|
||||
@Test
|
||||
fun wallet_sync_error() {
|
||||
val bad_wallet_result = libJna.new_wallet_result("test", "bad", null)
|
||||
log.debug("wallet result created")
|
||||
val sync_result = libJna.sync_wallet(bad_wallet_result)
|
||||
val sync_err_pointer = libJna.get_void_err(sync_result)
|
||||
assertNotNull(sync_err_pointer)
|
||||
val sync_err = sync_err_pointer.getString(0)
|
||||
log.debug("wallet sync error $sync_err")
|
||||
fun walletSync() {
|
||||
val walletResult = WalletResult(name, desc, change)
|
||||
val wallet = walletResult.ok()
|
||||
assertNotNull(wallet)
|
||||
val syncResult = wallet!!.sync();
|
||||
assertFalse(syncResult.isErr())
|
||||
assertNull(syncResult.err())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun sync() {
|
||||
val sync_result = libJna.sync_wallet(wallet_result)
|
||||
assertNull(libJna.get_void_err(sync_result))
|
||||
libJna.free_void_result(sync_result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun new_newaddress_wallet() {
|
||||
val address_result = libJna.new_address(wallet_result)
|
||||
assertNull(libJna.get_string_err(address_result))
|
||||
val address_pointer = libJna.get_string_ok(address_result);
|
||||
val address = address_pointer!!.getString(0)
|
||||
|
||||
libJna.free_string_result(address_result)
|
||||
libJna.free_string(address_pointer)
|
||||
fun walletNewAddress() {
|
||||
val walletResult = WalletResult(name, desc, change)
|
||||
val wallet = walletResult.ok()
|
||||
assertNotNull(wallet)
|
||||
val addressResult = wallet!!.getAddress()
|
||||
assertFalse(addressResult.isErr())
|
||||
assertNull(addressResult.err())
|
||||
val address = addressResult.ok()
|
||||
assertNotNull(address)
|
||||
log.debug("address created from kotlin: $address")
|
||||
assertEquals(address, "tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e")
|
||||
}
|
||||
|
@ -10,10 +10,13 @@ int main (int argc, char const * const argv[])
|
||||
{
|
||||
WalletResult_t *wallet_result = new_wallet_result("bad", "bad", NULL);
|
||||
assert(wallet_result != NULL);
|
||||
char *wallet_error = get_wallet_err(wallet_result);
|
||||
assert(wallet_error != NULL);
|
||||
//printf("wallet error: %s\n", wallet_error);
|
||||
free_string(wallet_error);
|
||||
char *wallet_err = get_wallet_err(wallet_result);
|
||||
assert(wallet_err != NULL);
|
||||
assert( 0 == strcmp(wallet_err,"Descriptor") );
|
||||
//printf("wallet err: %s\n", wallet_err);
|
||||
WalletRef_t *wallet_ref = get_wallet_ok(wallet_result);
|
||||
assert(wallet_ref == NULL);
|
||||
free_string(wallet_err);
|
||||
free_wallet_result(wallet_result);
|
||||
}
|
||||
|
||||
@ -25,26 +28,32 @@ int main (int argc, char const * const argv[])
|
||||
|
||||
WalletResult_t *wallet_result = new_wallet_result(name, desc, change);
|
||||
assert(wallet_result != NULL);
|
||||
char *wallet_err = get_wallet_err(wallet_result);
|
||||
assert(wallet_err == NULL);
|
||||
WalletRef_t *wallet_ref = get_wallet_ok(wallet_result);
|
||||
assert(wallet_ref != NULL);
|
||||
|
||||
// test sync_wallet
|
||||
VoidResult_t *sync_result = sync_wallet(wallet_result);
|
||||
VoidResult_t *sync_result = sync_wallet(wallet_ref);
|
||||
free_void_result(sync_result);
|
||||
|
||||
// test new_address
|
||||
StringResult_t *address_result1 = new_address(wallet_result);
|
||||
StringResult_t *address_result1 = new_address(wallet_ref);
|
||||
char *address1 = get_string_ok(address_result1);
|
||||
//printf("address1: %s\n", address1);
|
||||
assert( 0 == strcmp(address1,"tb1qgkhp034fyxeta00h0nne9tzfm0vsxq4prduzxp"));
|
||||
free_string(address1);
|
||||
free_string_result(address_result1);
|
||||
|
||||
StringResult_t *address_result2 = new_address(wallet_result);
|
||||
StringResult_t *address_result2 = new_address(wallet_ref);
|
||||
char *address2 = get_string_ok(address_result2);
|
||||
//printf("address2: %s\n", address2);
|
||||
assert(0 == strcmp(address2,"tb1qd6u9q327sru2ljvwzdtfrdg36sapax7udz97wf"));
|
||||
free_string(address2);
|
||||
free_string_result(address_result2);
|
||||
|
||||
free_wallet_ref(wallet_ref);
|
||||
|
||||
// test free_wallet
|
||||
free_wallet_result(wallet_result);
|
||||
|
||||
|
159
src/error.rs
159
src/error.rs
@ -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
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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 })
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user