Remove unneeded pointers from FfiResult types
This commit is contained in:
parent
62f18bdc2c
commit
d00cc73261
@ -1,15 +0,0 @@
|
|||||||
package org.bitcoindevkit.bdk
|
|
||||||
|
|
||||||
import com.sun.jna.Pointer
|
|
||||||
import com.sun.jna.Structure
|
|
||||||
|
|
||||||
abstract class FfiResult : Structure {
|
|
||||||
constructor() : super()
|
|
||||||
constructor(pointer: Pointer) : super(pointer)
|
|
||||||
|
|
||||||
@JvmField
|
|
||||||
var ok: Pointer? = null
|
|
||||||
|
|
||||||
@JvmField
|
|
||||||
var err: Pointer? = null
|
|
||||||
}
|
|
@ -6,15 +6,21 @@ interface LibJna : Library {
|
|||||||
|
|
||||||
// typedef struct {
|
// typedef struct {
|
||||||
//
|
//
|
||||||
// char * * ok;
|
// char * ok;
|
||||||
//
|
//
|
||||||
// char * * err;
|
// char * err;
|
||||||
//
|
//
|
||||||
// } FfiResult_char_ptr_t;
|
//} FfiResult_char_ptr_t;
|
||||||
open class FfiResult_char_ptr_t : FfiResult() {
|
open class FfiResult_char_ptr_t : Structure() {
|
||||||
class ByValue : FfiResult_char_ptr_t(), Structure.ByValue
|
class ByValue : FfiResult_char_ptr_t(), Structure.ByValue
|
||||||
class ByReference : FfiResult_char_ptr_t(), Structure.ByReference
|
class ByReference : FfiResult_char_ptr_t(), Structure.ByReference
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var ok: String = ""
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var err: String = ""
|
||||||
|
|
||||||
override fun getFieldOrder() = listOf("ok", "err")
|
override fun getFieldOrder() = listOf("ok", "err")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,21 +30,27 @@ interface LibJna : Library {
|
|||||||
|
|
||||||
// typedef struct {
|
// typedef struct {
|
||||||
//
|
//
|
||||||
// void * ok;
|
// int32_t ok;
|
||||||
//
|
//
|
||||||
// char * * err;
|
// char * err;
|
||||||
//
|
//
|
||||||
// } FfiResult_void_t;
|
//} FfiResult_int32_t;
|
||||||
open class FfiResult_void_t : FfiResult() {
|
open class FfiResult_int32_t : Structure() {
|
||||||
class ByValue : FfiResult_void_t(), Structure.ByValue
|
class ByValue : FfiResult_int32_t(), Structure.ByValue
|
||||||
class ByReference : FfiResult_void_t(), Structure.ByReference
|
class ByReference : FfiResult_int32_t(), Structure.ByReference
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var ok: Int = 0
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var err: String = ""
|
||||||
|
|
||||||
override fun getFieldOrder() = listOf("ok", "err")
|
override fun getFieldOrder() = listOf("ok", "err")
|
||||||
}
|
}
|
||||||
|
|
||||||
// void free_void_result (
|
// void free_int_result (
|
||||||
// FfiResult_void_t void_result);
|
// FfiResult_int32_t int_result);
|
||||||
fun free_void_result(void_result: FfiResult_void_t.ByValue)
|
fun free_int_result(void_result: FfiResult_int32_t.ByValue)
|
||||||
|
|
||||||
// void free_string (
|
// void free_string (
|
||||||
// char * string);
|
// char * string);
|
||||||
@ -82,17 +94,23 @@ interface LibJna : Library {
|
|||||||
//
|
//
|
||||||
// OpaqueWallet_t * ok;
|
// OpaqueWallet_t * ok;
|
||||||
//
|
//
|
||||||
// char * * err;
|
// char * err;
|
||||||
//
|
//
|
||||||
// } FfiResult_OpaqueWallet_t;
|
// } FfiResult_OpaqueWallet_ptr_t;
|
||||||
open class FfiResult_OpaqueWallet_t : FfiResult() {
|
open class FfiResult_OpaqueWallet_ptr_t : Structure() {
|
||||||
class ByValue : FfiResult_OpaqueWallet_t(), Structure.ByValue
|
class ByValue : FfiResult_OpaqueWallet_ptr_t(), Structure.ByValue
|
||||||
class ByReference : FfiResult_OpaqueWallet_t(), Structure.ByReference
|
class ByReference : FfiResult_OpaqueWallet_ptr_t(), Structure.ByReference
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var ok: OpaqueWallet_t = OpaqueWallet_t()
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var err: String = ""
|
||||||
|
|
||||||
override fun getFieldOrder() = listOf("ok", "err")
|
override fun getFieldOrder() = listOf("ok", "err")
|
||||||
}
|
}
|
||||||
|
|
||||||
// FfiResult_OpaqueWallet_t new_wallet_result (
|
// FfiResult_OpaqueWallet_ptr_t new_wallet_result (
|
||||||
// char const * descriptor,
|
// char const * descriptor,
|
||||||
// char const * change_descriptor,
|
// char const * change_descriptor,
|
||||||
// BlockchainConfig_t const * blockchain_config,
|
// BlockchainConfig_t const * blockchain_config,
|
||||||
@ -102,11 +120,11 @@ interface LibJna : Library {
|
|||||||
changeDescriptor: String?,
|
changeDescriptor: String?,
|
||||||
blockchainConfig: BlockchainConfig_t,
|
blockchainConfig: BlockchainConfig_t,
|
||||||
databaseConfig: DatabaseConfig_t,
|
databaseConfig: DatabaseConfig_t,
|
||||||
): FfiResult_OpaqueWallet_t.ByValue
|
): FfiResult_OpaqueWallet_ptr_t.ByValue
|
||||||
|
|
||||||
// void free_wallet_result (
|
// void free_wallet_result (
|
||||||
// FfiResult_OpaqueWallet_t wallet_result);
|
// FfiResult_OpaqueWallet_ptr_t wallet_result);
|
||||||
fun free_wallet_result(wallet_result: FfiResult_OpaqueWallet_t.ByValue)
|
fun free_wallet_result(wallet_result: FfiResult_OpaqueWallet_ptr_t.ByValue)
|
||||||
|
|
||||||
// typedef struct {
|
// typedef struct {
|
||||||
//
|
//
|
||||||
@ -155,19 +173,10 @@ interface LibJna : Library {
|
|||||||
// uint16_t keychain;
|
// uint16_t keychain;
|
||||||
//
|
//
|
||||||
// } LocalUtxo_t;
|
// } LocalUtxo_t;
|
||||||
open class LocalUtxo_t : Structure {
|
open class LocalUtxo_t : Structure() {
|
||||||
constructor() : super()
|
|
||||||
constructor(pointer: Pointer) : super(pointer)
|
class ByValue : LocalUtxo_t(), Structure.ByValue
|
||||||
|
class ByReference : LocalUtxo_t(), Structure.ByReference
|
||||||
class ByValue : LocalUtxo_t, Structure.ByValue {
|
|
||||||
constructor() : super()
|
|
||||||
constructor(pointer: Pointer) : super(pointer)
|
|
||||||
}
|
|
||||||
|
|
||||||
class ByReference : LocalUtxo_t, Structure.ByReference {
|
|
||||||
constructor() : super()
|
|
||||||
constructor(pointer: Pointer) : super(pointer)
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
var outpoint: OutPoint_t? = null
|
var outpoint: OutPoint_t? = null
|
||||||
@ -190,19 +199,10 @@ interface LibJna : Library {
|
|||||||
// size_t cap;
|
// size_t cap;
|
||||||
//
|
//
|
||||||
// } Vec_LocalUtxo_t;
|
// } Vec_LocalUtxo_t;
|
||||||
open class Vec_LocalUtxo_t : Structure {
|
open class Vec_LocalUtxo_t : Structure() {
|
||||||
constructor() : super()
|
|
||||||
constructor(pointer: Pointer) : super(pointer)
|
class ByReference : Vec_LocalUtxo_t(), Structure.ByReference
|
||||||
|
class ByValue : Vec_LocalUtxo_t(), Structure.ByValue
|
||||||
class ByReference : Vec_LocalUtxo_t, Structure.ByReference {
|
|
||||||
constructor() : super()
|
|
||||||
constructor(pointer: Pointer) : super(pointer)
|
|
||||||
}
|
|
||||||
|
|
||||||
class ByValue : Vec_LocalUtxo_t, Structure.ByValue {
|
|
||||||
constructor() : super()
|
|
||||||
constructor(pointer: Pointer) : super(pointer)
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
var ptr: LocalUtxo_t.ByReference? = null
|
var ptr: LocalUtxo_t.ByReference? = null
|
||||||
@ -220,9 +220,9 @@ interface LibJna : Library {
|
|||||||
//
|
//
|
||||||
// Vec_LocalUtxo_t ok;
|
// Vec_LocalUtxo_t ok;
|
||||||
//
|
//
|
||||||
// char * * err;
|
// char * err;
|
||||||
//
|
//
|
||||||
// } FfiResultVec_LocalUtxo_t;
|
// } FfiResult_Vec_LocalUtxo_t;
|
||||||
open class FfiResultVec_LocalUtxo_t : Structure() {
|
open class FfiResultVec_LocalUtxo_t : Structure() {
|
||||||
|
|
||||||
class ByValue : FfiResultVec_LocalUtxo_t(), Structure.ByValue
|
class ByValue : FfiResultVec_LocalUtxo_t(), Structure.ByValue
|
||||||
@ -232,18 +232,18 @@ interface LibJna : Library {
|
|||||||
var ok: Vec_LocalUtxo_t = Vec_LocalUtxo_t()
|
var ok: Vec_LocalUtxo_t = Vec_LocalUtxo_t()
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
var err: Pointer? = null
|
var err: String = ""
|
||||||
|
|
||||||
override fun getFieldOrder() = listOf("ok", "err")
|
override fun getFieldOrder() = listOf("ok", "err")
|
||||||
}
|
}
|
||||||
|
|
||||||
// void free_unspent_result (
|
// void free_unspent_result (
|
||||||
// FfiResultVec_LocalUtxo_t unspent_result);
|
// FfiResult_Vec_LocalUtxo_t unspent_result);
|
||||||
fun free_unspent_result(unspent_result: FfiResultVec_LocalUtxo_t.ByValue)
|
fun free_unspent_result(unspent_result: FfiResultVec_LocalUtxo_t.ByValue)
|
||||||
|
|
||||||
// FfiResult_void_t sync_wallet (
|
// FfiResult_int32_t sync_wallet (
|
||||||
// OpaqueWallet_t const * opaque_wallet);
|
// OpaqueWallet_t const * opaque_wallet);
|
||||||
fun sync_wallet(opaque_wallet: OpaqueWallet_t): FfiResult_void_t.ByValue
|
fun sync_wallet(opaque_wallet: OpaqueWallet_t): FfiResult_int32_t.ByValue
|
||||||
|
|
||||||
// FfiResult_char_ptr_t new_address (
|
// FfiResult_char_ptr_t new_address (
|
||||||
// OpaqueWallet_t const * opaque_wallet);
|
// OpaqueWallet_t const * opaque_wallet);
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
package org.bitcoindevkit.bdk.types
|
|
||||||
|
|
||||||
import com.sun.jna.Pointer
|
|
||||||
import org.bitcoindevkit.bdk.FfiResult
|
|
||||||
import org.bitcoindevkit.bdk.JnaError
|
|
||||||
import org.bitcoindevkit.bdk.JnaException
|
|
||||||
import org.bitcoindevkit.bdk.LibBase
|
|
||||||
import org.slf4j.Logger
|
|
||||||
import org.slf4j.LoggerFactory
|
|
||||||
|
|
||||||
abstract class Result<T : FfiResult, RT : Any>(private val ffiResult: T): LibBase() {
|
|
||||||
|
|
||||||
protected open val log: Logger = LoggerFactory.getLogger(Result::class.java)
|
|
||||||
|
|
||||||
protected abstract fun getOkValue(pointer: Pointer): RT
|
|
||||||
|
|
||||||
protected abstract fun freeResult(ffiResult: T)
|
|
||||||
|
|
||||||
fun value(): RT {
|
|
||||||
val err = ffiResult.err
|
|
||||||
val ok = ffiResult.ok
|
|
||||||
when {
|
|
||||||
err != null -> {
|
|
||||||
val errString = err.getPointer(0).getString(0)
|
|
||||||
log.error("JnaError: $errString")
|
|
||||||
throw JnaException(JnaError.valueOf(errString))
|
|
||||||
}
|
|
||||||
ok != null -> {
|
|
||||||
return getOkValue(ok)
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
throw JnaException(JnaError.Generic)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun finalize() {
|
|
||||||
freeResult(ffiResult)
|
|
||||||
log.debug("$ffiResult freed")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,16 +1,33 @@
|
|||||||
package org.bitcoindevkit.bdk.types
|
package org.bitcoindevkit.bdk.types
|
||||||
|
|
||||||
import com.sun.jna.Pointer
|
import org.bitcoindevkit.bdk.JnaError
|
||||||
|
import org.bitcoindevkit.bdk.JnaException
|
||||||
|
import org.bitcoindevkit.bdk.LibBase
|
||||||
import org.bitcoindevkit.bdk.LibJna
|
import org.bitcoindevkit.bdk.LibJna
|
||||||
|
import org.slf4j.Logger
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
class StringResult constructor(stringResultPtr: LibJna.FfiResult_char_ptr_t.ByValue) :
|
class StringResult constructor(private val ffiResultCharPtrT: LibJna.FfiResult_char_ptr_t.ByValue) :
|
||||||
Result<LibJna.FfiResult_char_ptr_t.ByValue, String>(stringResultPtr) {
|
LibBase() {
|
||||||
|
|
||||||
override fun getOkValue(pointer: Pointer): String {
|
private val log: Logger = LoggerFactory.getLogger(StringResult::class.java)
|
||||||
return pointer.getPointer(0).getString(0)
|
|
||||||
|
fun value(): String {
|
||||||
|
val err = ffiResultCharPtrT.err
|
||||||
|
val ok = ffiResultCharPtrT.ok
|
||||||
|
when {
|
||||||
|
err.isNotEmpty() -> {
|
||||||
|
log.error("JnaError: $err")
|
||||||
|
throw JnaException(JnaError.valueOf(err))
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun freeResult(ffiResult: LibJna.FfiResult_char_ptr_t.ByValue) {
|
protected fun finalize() {
|
||||||
libJna.free_string_result(ffiResult)
|
libJna.free_string_result(ffiResultCharPtrT)
|
||||||
|
log.debug("$ffiResultCharPtrT freed")
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,16 +1,33 @@
|
|||||||
package org.bitcoindevkit.bdk.types
|
package org.bitcoindevkit.bdk.types
|
||||||
|
|
||||||
import com.sun.jna.Pointer
|
import org.bitcoindevkit.bdk.JnaError
|
||||||
|
import org.bitcoindevkit.bdk.JnaException
|
||||||
|
import org.bitcoindevkit.bdk.LibBase
|
||||||
import org.bitcoindevkit.bdk.LibJna
|
import org.bitcoindevkit.bdk.LibJna
|
||||||
|
import org.slf4j.Logger
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
class VoidResult constructor(voidResultPtr: LibJna.FfiResult_void_t.ByValue) :
|
class VoidResult constructor(private val ffiResultInt32T: LibJna.FfiResult_int32_t.ByValue) :
|
||||||
Result<LibJna.FfiResult_void_t.ByValue, Unit>(voidResultPtr) {
|
LibBase() {
|
||||||
|
|
||||||
override fun getOkValue(pointer: Pointer) {
|
private val log: Logger = LoggerFactory.getLogger(VoidResult::class.java)
|
||||||
// No value
|
|
||||||
|
fun value(): Unit {
|
||||||
|
val err = ffiResultInt32T.err
|
||||||
|
//val ok = ffiResultInt32T.ok
|
||||||
|
when {
|
||||||
|
err.isNotEmpty() -> {
|
||||||
|
log.error("JnaError: $err")
|
||||||
|
throw JnaException(JnaError.valueOf(err))
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun freeResult(ffiResult: LibJna.FfiResult_void_t.ByValue) {
|
protected fun finalize() {
|
||||||
libJna.free_void_result(ffiResult)
|
libJna.free_int_result(ffiResultInt32T)
|
||||||
|
log.debug("$ffiResultInt32T freed")
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,19 +7,18 @@ import org.bitcoindevkit.bdk.LibJna
|
|||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
class VecLocalUtxoResult(private val ffiResult: LibJna.FfiResultVec_LocalUtxo_t.ByValue) :
|
class VecLocalUtxoResult(private val ffiResultVecLocalUtxoT: LibJna.FfiResultVec_LocalUtxo_t.ByValue) :
|
||||||
LibBase() {
|
LibBase() {
|
||||||
|
|
||||||
protected open val log: Logger = LoggerFactory.getLogger(VecLocalUtxoResult::class.java)
|
private val log: Logger = LoggerFactory.getLogger(VecLocalUtxoResult::class.java)
|
||||||
|
|
||||||
fun value(): Array<LibJna.LocalUtxo_t.ByReference> {
|
fun value(): Array<LibJna.LocalUtxo_t.ByReference> {
|
||||||
val err = ffiResult.err
|
val err = ffiResultVecLocalUtxoT.err
|
||||||
val ok = ffiResult.ok
|
val ok = ffiResultVecLocalUtxoT.ok
|
||||||
when {
|
when {
|
||||||
err != null -> {
|
err .isNotEmpty() -> {
|
||||||
val errString = err.getPointer(0).getString(0)
|
log.error("JnaError: $err")
|
||||||
log.error("JnaError: $errString")
|
throw JnaException(JnaError.valueOf(err))
|
||||||
throw JnaException(JnaError.valueOf(errString))
|
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val first = ok.ptr!!
|
val first = ok.ptr!!
|
||||||
@ -29,7 +28,7 @@ class VecLocalUtxoResult(private val ffiResult: LibJna.FfiResultVec_LocalUtxo_t.
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected fun finalize() {
|
protected fun finalize() {
|
||||||
libJna.free_unspent_result(ffiResult)
|
libJna.free_unspent_result(ffiResultVecLocalUtxoT)
|
||||||
log.debug("$ffiResult freed")
|
log.debug("$ffiResultVecLocalUtxoT freed")
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,17 +1,33 @@
|
|||||||
package org.bitcoindevkit.bdk.wallet
|
package org.bitcoindevkit.bdk.wallet
|
||||||
|
|
||||||
import com.sun.jna.Pointer
|
import org.bitcoindevkit.bdk.JnaError
|
||||||
|
import org.bitcoindevkit.bdk.JnaException
|
||||||
|
import org.bitcoindevkit.bdk.LibBase
|
||||||
import org.bitcoindevkit.bdk.LibJna
|
import org.bitcoindevkit.bdk.LibJna
|
||||||
import org.bitcoindevkit.bdk.types.Result
|
import org.slf4j.Logger
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
class WalletResult constructor(walletResultPtr: LibJna.FfiResult_OpaqueWallet_t.ByValue) :
|
class WalletResult constructor(private val ffiResultOpaqueWalletPtrT: LibJna.FfiResult_OpaqueWallet_ptr_t.ByValue) :
|
||||||
Result<LibJna.FfiResult_OpaqueWallet_t.ByValue, LibJna.OpaqueWallet_t>(walletResultPtr) {
|
LibBase() {
|
||||||
|
|
||||||
override fun getOkValue(pointer: Pointer): LibJna.OpaqueWallet_t {
|
private val log: Logger = LoggerFactory.getLogger(WalletResult::class.java)
|
||||||
return LibJna.OpaqueWallet_t(pointer)
|
|
||||||
|
fun value(): LibJna.OpaqueWallet_t {
|
||||||
|
val err = ffiResultOpaqueWalletPtrT.err
|
||||||
|
val ok = ffiResultOpaqueWalletPtrT.ok
|
||||||
|
when {
|
||||||
|
err.isNotEmpty() -> {
|
||||||
|
log.error("JnaError: $err")
|
||||||
|
throw JnaException(JnaError.valueOf(err))
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun freeResult(ffiResult: LibJna.FfiResult_OpaqueWallet_t.ByValue) {
|
protected fun finalize() {
|
||||||
libJna.free_wallet_result(ffiResult)
|
libJna.free_wallet_result(ffiResultOpaqueWalletPtrT)
|
||||||
|
log.debug("$ffiResultOpaqueWalletPtrT freed")
|
||||||
}
|
}
|
||||||
}
|
}
|
58
cc/bdk_ffi.h
58
cc/bdk_ffi.h
@ -14,21 +14,8 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
typedef struct BlockchainConfig BlockchainConfig_t;
|
typedef struct BlockchainConfig BlockchainConfig_t;
|
||||||
|
|
||||||
BlockchainConfig_t * new_electrum_config (
|
|
||||||
char const * url,
|
|
||||||
char const * socks5,
|
|
||||||
int16_t retry,
|
|
||||||
int16_t timeout);
|
|
||||||
|
|
||||||
void free_blockchain_config (
|
|
||||||
BlockchainConfig_t * blockchain_config);
|
|
||||||
|
|
||||||
typedef struct DatabaseConfig DatabaseConfig_t;
|
typedef struct DatabaseConfig DatabaseConfig_t;
|
||||||
|
|
||||||
typedef struct OpaqueWallet OpaqueWallet_t;
|
typedef struct OpaqueWallet OpaqueWallet_t;
|
||||||
@ -37,35 +24,39 @@ typedef struct {
|
|||||||
|
|
||||||
OpaqueWallet_t * ok;
|
OpaqueWallet_t * ok;
|
||||||
|
|
||||||
char * * err;
|
char * err;
|
||||||
|
|
||||||
} FfiResult_OpaqueWallet_t;
|
} FfiResult_OpaqueWallet_ptr_t;
|
||||||
|
|
||||||
FfiResult_OpaqueWallet_t new_wallet_result (
|
FfiResult_OpaqueWallet_ptr_t new_wallet_result (
|
||||||
char const * descriptor,
|
char const * descriptor,
|
||||||
char const * change_descriptor,
|
char const * change_descriptor,
|
||||||
BlockchainConfig_t const * blockchain_config,
|
BlockchainConfig_t const * blockchain_config,
|
||||||
DatabaseConfig_t const * database_config);
|
DatabaseConfig_t const * database_config);
|
||||||
|
|
||||||
void free_wallet_result (
|
void free_wallet_result (
|
||||||
FfiResult_OpaqueWallet_t wallet_result);
|
FfiResult_OpaqueWallet_ptr_t wallet_result);
|
||||||
|
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
||||||
void * ok;
|
int32_t ok;
|
||||||
|
|
||||||
char * * err;
|
char * err;
|
||||||
|
|
||||||
} FfiResult_void_t;
|
} FfiResult_int32_t;
|
||||||
|
|
||||||
FfiResult_void_t sync_wallet (
|
FfiResult_int32_t sync_wallet (
|
||||||
OpaqueWallet_t const * opaque_wallet);
|
OpaqueWallet_t const * opaque_wallet);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
||||||
char * * ok;
|
char * ok;
|
||||||
|
|
||||||
char * * err;
|
char * err;
|
||||||
|
|
||||||
} FfiResult_char_ptr_t;
|
} FfiResult_char_ptr_t;
|
||||||
|
|
||||||
@ -115,15 +106,24 @@ typedef struct {
|
|||||||
|
|
||||||
Vec_LocalUtxo_t ok;
|
Vec_LocalUtxo_t ok;
|
||||||
|
|
||||||
char * * err;
|
char * err;
|
||||||
|
|
||||||
} FfiResultVec_LocalUtxo_t;
|
} FfiResult_Vec_LocalUtxo_t;
|
||||||
|
|
||||||
FfiResultVec_LocalUtxo_t list_unspent (
|
FfiResult_Vec_LocalUtxo_t list_unspent (
|
||||||
OpaqueWallet_t const * opaque_wallet);
|
OpaqueWallet_t const * opaque_wallet);
|
||||||
|
|
||||||
void free_unspent_result (
|
void free_unspent_result (
|
||||||
FfiResultVec_LocalUtxo_t unspent_result);
|
FfiResult_Vec_LocalUtxo_t unspent_result);
|
||||||
|
|
||||||
|
BlockchainConfig_t * new_electrum_config (
|
||||||
|
char const * url,
|
||||||
|
char const * socks5,
|
||||||
|
int16_t retry,
|
||||||
|
int16_t timeout);
|
||||||
|
|
||||||
|
void free_blockchain_config (
|
||||||
|
BlockchainConfig_t * blockchain_config);
|
||||||
|
|
||||||
DatabaseConfig_t * new_memory_config (void);
|
DatabaseConfig_t * new_memory_config (void);
|
||||||
|
|
||||||
@ -137,8 +137,8 @@ void free_database_config (
|
|||||||
void free_string_result (
|
void free_string_result (
|
||||||
FfiResult_char_ptr_t string_result);
|
FfiResult_char_ptr_t string_result);
|
||||||
|
|
||||||
void free_void_result (
|
void free_int_result (
|
||||||
FfiResult_void_t void_result);
|
FfiResult_int32_t int_result);
|
||||||
|
|
||||||
/** \brief
|
/** \brief
|
||||||
* Free a Rust-allocated string
|
* Free a Rust-allocated string
|
||||||
|
@ -13,14 +13,14 @@ int main (int argc, char const * const argv[])
|
|||||||
DatabaseConfig_t *db_config = new_memory_config();
|
DatabaseConfig_t *db_config = new_memory_config();
|
||||||
|
|
||||||
// new wallet with bad descriptor
|
// new wallet with bad descriptor
|
||||||
FfiResult_OpaqueWallet_t wallet_result = new_wallet_result("bad","bad",bc_config,db_config);
|
FfiResult_OpaqueWallet_ptr_t wallet_result = new_wallet_result("bad","bad",bc_config,db_config);
|
||||||
assert(wallet_result.err != NULL);
|
assert(strlen(wallet_result.err) > 0);
|
||||||
assert(wallet_result.ok == NULL);
|
assert(wallet_result.ok == NULL);
|
||||||
|
|
||||||
free_blockchain_config(bc_config);
|
free_blockchain_config(bc_config);
|
||||||
free_database_config(db_config);
|
free_database_config(db_config);
|
||||||
|
|
||||||
char *wallet_err = *wallet_result.err;
|
char *wallet_err = wallet_result.err;
|
||||||
assert(wallet_err != NULL);
|
assert(wallet_err != NULL);
|
||||||
assert( 0 == strcmp(wallet_err,"Descriptor") );
|
assert( 0 == strcmp(wallet_err,"Descriptor") );
|
||||||
// printf("wallet err: %s\n", wallet_err);
|
// printf("wallet err: %s\n", wallet_err);
|
||||||
@ -37,8 +37,9 @@ int main (int argc, char const * const argv[])
|
|||||||
DatabaseConfig_t *db_config = new_memory_config();
|
DatabaseConfig_t *db_config = new_memory_config();
|
||||||
|
|
||||||
// new wallet
|
// new wallet
|
||||||
FfiResult_OpaqueWallet_t wallet_result = new_wallet_result(desc,change,bc_config,db_config);
|
FfiResult_OpaqueWallet_ptr_t wallet_result = new_wallet_result(desc,change,bc_config,db_config);
|
||||||
assert(wallet_result.err == NULL);
|
// printf("wallet_result.err = %ld\n", strlen(wallet_result.err));
|
||||||
|
assert(strlen(wallet_result.err) == 0);
|
||||||
assert(wallet_result.ok != NULL);
|
assert(wallet_result.ok != NULL);
|
||||||
|
|
||||||
free_blockchain_config(bc_config);
|
free_blockchain_config(bc_config);
|
||||||
@ -46,35 +47,35 @@ int main (int argc, char const * const argv[])
|
|||||||
|
|
||||||
OpaqueWallet_t *wallet = wallet_result.ok;
|
OpaqueWallet_t *wallet = wallet_result.ok;
|
||||||
|
|
||||||
// test sync wallet
|
// sync wallet
|
||||||
FfiResult_void_t sync_result = sync_wallet(wallet);
|
FfiResult_int32_t sync_result = sync_wallet(wallet);
|
||||||
assert(sync_result.ok != NULL);
|
assert(sync_result.ok == 0);
|
||||||
assert(sync_result.err == NULL);
|
assert(strlen(sync_result.err) == 0);
|
||||||
free_void_result(sync_result);
|
free_int_result(sync_result);
|
||||||
|
|
||||||
// test new address
|
// new address
|
||||||
FfiResult_char_ptr_t address_result1 = new_address(wallet);
|
FfiResult_char_ptr_t address1_result = new_address(wallet);
|
||||||
assert(address_result1.ok != NULL);
|
assert(address1_result.ok != NULL);
|
||||||
assert(address_result1.err == NULL);
|
assert(strlen(address1_result.err) == 0);
|
||||||
// printf("address1 = %s\n", *address_result1.ok);
|
// printf("address1 = %s\n", *address1_result.ok);
|
||||||
assert( 0 == strcmp(*address_result1.ok,"tb1qgkhp034fyxeta00h0nne9tzfm0vsxq4prduzxp"));
|
assert( 0 == strcmp(address1_result.ok,"tb1qgkhp034fyxeta00h0nne9tzfm0vsxq4prduzxp"));
|
||||||
free_string_result(address_result1);
|
free_string_result(address1_result);
|
||||||
|
|
||||||
FfiResult_char_ptr_t address_result2 = new_address(wallet);
|
FfiResult_char_ptr_t address2_result = new_address(wallet);
|
||||||
assert(address_result2.ok != NULL);
|
assert(address2_result.ok != NULL);
|
||||||
assert(address_result2.err == NULL);
|
assert(strlen(address2_result.err) == 0);
|
||||||
// printf("address2 = %s\n", *address_result2.ok);
|
// printf("address2 = %s\n", *address2_result.ok);
|
||||||
assert( 0 == strcmp(*address_result2.ok,"tb1qd6u9q327sru2ljvwzdtfrdg36sapax7udz97wf"));
|
assert( 0 == strcmp(address2_result.ok,"tb1qd6u9q327sru2ljvwzdtfrdg36sapax7udz97wf"));
|
||||||
free_string_result(address_result2);
|
free_string_result(address2_result);
|
||||||
|
|
||||||
// test free_wallet
|
// free_wallet
|
||||||
free_wallet_result(wallet_result);
|
free_wallet_result(wallet_result);
|
||||||
|
|
||||||
// verify free_wallet after free_wallet fails (core dumped)
|
// verify free_wallet after free_wallet fails (core dumped)
|
||||||
//// free_wallet_result(wallet_result);
|
//// free_wallet_result(wallet_result);
|
||||||
|
|
||||||
// verify sync_wallet after free_wallet fails (core dumped)
|
// verify sync_wallet after free_wallet fails (core dumped)
|
||||||
//// FfiResult_void_t sync_result2 = sync_wallet(wallet);
|
//// FfiResult_int32_t sync_result2 = sync_wallet(wallet);
|
||||||
}
|
}
|
||||||
|
|
||||||
// test get unspent utxos
|
// test get unspent utxos
|
||||||
@ -86,8 +87,8 @@ int main (int argc, char const * const argv[])
|
|||||||
DatabaseConfig_t *db_config = new_memory_config();
|
DatabaseConfig_t *db_config = new_memory_config();
|
||||||
|
|
||||||
// new wallet
|
// new wallet
|
||||||
FfiResult_OpaqueWallet_t wallet_result = new_wallet_result(desc,change,bc_config,db_config);
|
FfiResult_OpaqueWallet_ptr_t wallet_result = new_wallet_result(desc,change,bc_config,db_config);
|
||||||
assert(wallet_result.err == NULL);
|
assert(strlen(wallet_result.err) == 0);
|
||||||
assert(wallet_result.ok != NULL);
|
assert(wallet_result.ok != NULL);
|
||||||
|
|
||||||
free_blockchain_config(bc_config);
|
free_blockchain_config(bc_config);
|
||||||
@ -95,16 +96,16 @@ int main (int argc, char const * const argv[])
|
|||||||
|
|
||||||
OpaqueWallet_t *wallet = wallet_result.ok;
|
OpaqueWallet_t *wallet = wallet_result.ok;
|
||||||
|
|
||||||
// test sync wallet
|
// sync wallet
|
||||||
FfiResult_void_t sync_result = sync_wallet(wallet);
|
FfiResult_int32_t sync_result = sync_wallet(wallet);
|
||||||
assert(sync_result.ok != NULL);
|
assert(sync_result.ok == 0);
|
||||||
assert(sync_result.err == NULL);
|
assert(strlen(sync_result.err) == 0);
|
||||||
free_void_result(sync_result);
|
free_int_result(sync_result);
|
||||||
|
|
||||||
// list unspent
|
// list unspent
|
||||||
FfiResultVec_LocalUtxo_t unspent_result = list_unspent(wallet);
|
FfiResult_Vec_LocalUtxo_t unspent_result = list_unspent(wallet);
|
||||||
assert(unspent_result.ok.len == 7);
|
assert(unspent_result.ok.len == 7);
|
||||||
assert(unspent_result.err == NULL);
|
assert(strlen(unspent_result.err) == 0);
|
||||||
|
|
||||||
LocalUtxo_t * unspent_ptr = unspent_result.ok.ptr;
|
LocalUtxo_t * unspent_ptr = unspent_result.ok.ptr;
|
||||||
for (int i = 0; i < unspent_result.ok.len; i++) {
|
for (int i = 0; i < unspent_result.ok.len; i++) {
|
||||||
@ -123,6 +124,41 @@ int main (int argc, char const * const argv[])
|
|||||||
free_unspent_result(unspent_result);
|
free_unspent_result(unspent_result);
|
||||||
free_wallet_result(wallet_result);
|
free_wallet_result(wallet_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// test balance
|
||||||
|
/*{
|
||||||
|
char const *desc = "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)";
|
||||||
|
char const *change = "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)";
|
||||||
|
|
||||||
|
BlockchainConfig_t *bc_config = new_electrum_config("ssl://electrum.blockstream.info:60002", NULL, 5, 30);
|
||||||
|
DatabaseConfig_t *db_config = new_memory_config();
|
||||||
|
|
||||||
|
// new wallet
|
||||||
|
FfiResult_OpaqueWallet_ptr_t wallet_result = new_wallet_result(desc,change,bc_config,db_config);
|
||||||
|
assert(wallet_result.err == NULL);
|
||||||
|
assert(wallet_result.ok != NULL);
|
||||||
|
|
||||||
|
free_blockchain_config(bc_config);
|
||||||
|
free_database_config(db_config);
|
||||||
|
|
||||||
|
OpaqueWallet_t *wallet = wallet_result.ok;
|
||||||
|
|
||||||
|
// sync wallet
|
||||||
|
FfiResult_int32_t sync_result = sync_wallet(wallet);
|
||||||
|
assert(sync_result.ok == 0);
|
||||||
|
assert(sync_result.err == NULL);
|
||||||
|
free_int_result(sync_result);
|
||||||
|
|
||||||
|
// get balance
|
||||||
|
FfiResultT_uint64_t balance_result = balance(wallet);
|
||||||
|
assert(balance_result.err == NULL);
|
||||||
|
printf("balance = %lu\n", balance_result.ok);
|
||||||
|
assert(balance_result.ok > 0);
|
||||||
|
|
||||||
|
// free balance and wallet results
|
||||||
|
free_u64_result(balance_result);
|
||||||
|
free_wallet_result(wallet_result);
|
||||||
|
}*/
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
15
src/types.rs
15
src/types.rs
@ -5,15 +5,8 @@ use safer_ffi::char_p::char_p_boxed;
|
|||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct FfiResult<T> {
|
pub struct FfiResult<T> {
|
||||||
pub ok: Option<repr_c::Box<T>>,
|
pub ok: T,
|
||||||
pub err: Option<repr_c::Box<char_p_boxed>>,
|
pub err: char_p_boxed,
|
||||||
}
|
|
||||||
|
|
||||||
#[derive_ReprC]
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct FfiResultVec<T> {
|
|
||||||
pub ok: repr_c::Vec<T>,
|
|
||||||
pub err: Option<repr_c::Box<char_p_boxed>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ffi_export]
|
#[ffi_export]
|
||||||
@ -22,8 +15,8 @@ fn free_string_result(string_result: FfiResult<char_p_boxed>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[ffi_export]
|
#[ffi_export]
|
||||||
fn free_void_result(void_result: FfiResult<()>) {
|
fn free_int_result(int_result: FfiResult<i32>) {
|
||||||
drop(void_result)
|
drop(int_result)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO do we need this? remove?
|
// TODO do we need this? remove?
|
||||||
|
@ -13,7 +13,8 @@ use blockchain::BlockchainConfig;
|
|||||||
use database::DatabaseConfig;
|
use database::DatabaseConfig;
|
||||||
|
|
||||||
use crate::error::get_name;
|
use crate::error::get_name;
|
||||||
use crate::types::{FfiResult, FfiResultVec};
|
use crate::types::FfiResult;
|
||||||
|
use std::ffi::CString;
|
||||||
|
|
||||||
mod blockchain;
|
mod blockchain;
|
||||||
mod database;
|
mod database;
|
||||||
@ -32,7 +33,7 @@ fn new_wallet_result(
|
|||||||
change_descriptor: Option<char_p_ref>,
|
change_descriptor: Option<char_p_ref>,
|
||||||
blockchain_config: &BlockchainConfig,
|
blockchain_config: &BlockchainConfig,
|
||||||
database_config: &DatabaseConfig,
|
database_config: &DatabaseConfig,
|
||||||
) -> FfiResult<OpaqueWallet> {
|
) -> FfiResult<Option<Box<OpaqueWallet>>> {
|
||||||
let descriptor = descriptor.to_string();
|
let descriptor = descriptor.to_string();
|
||||||
let change_descriptor = change_descriptor.map(|s| s.to_string());
|
let change_descriptor = change_descriptor.map(|s| s.to_string());
|
||||||
let bc_config = &blockchain_config.raw;
|
let bc_config = &blockchain_config.raw;
|
||||||
@ -42,11 +43,11 @@ fn new_wallet_result(
|
|||||||
match wallet_result {
|
match wallet_result {
|
||||||
Ok(w) => FfiResult {
|
Ok(w) => FfiResult {
|
||||||
ok: Some(Box::new(OpaqueWallet { raw: w })),
|
ok: Some(Box::new(OpaqueWallet { raw: w })),
|
||||||
err: None,
|
err: char_p_boxed::from(CString::default()),
|
||||||
},
|
},
|
||||||
Err(e) => FfiResult {
|
Err(e) => FfiResult {
|
||||||
ok: None,
|
ok: None,
|
||||||
err: Some(Box::new(char_p_boxed::try_from(get_name(&e)).unwrap())),
|
err: char_p_boxed::try_from(get_name(&e)).unwrap(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,23 +70,23 @@ fn new_wallet(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[ffi_export]
|
#[ffi_export]
|
||||||
fn free_wallet_result(wallet_result: FfiResult<OpaqueWallet>) {
|
fn free_wallet_result(wallet_result: FfiResult<Option<Box<OpaqueWallet>>>) {
|
||||||
drop(wallet_result);
|
drop(wallet_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// wallet operations
|
// wallet operations
|
||||||
|
|
||||||
#[ffi_export]
|
#[ffi_export]
|
||||||
fn sync_wallet(opaque_wallet: &OpaqueWallet) -> FfiResult<()> {
|
fn sync_wallet(opaque_wallet: &OpaqueWallet) -> FfiResult<i32> {
|
||||||
let void_result = opaque_wallet.raw.sync(log_progress(), Some(100));
|
let int_result = opaque_wallet.raw.sync(log_progress(), Some(100));
|
||||||
match void_result {
|
match int_result {
|
||||||
Ok(v) => FfiResult {
|
Ok(_v) => FfiResult {
|
||||||
ok: Some(Box::new(v)),
|
ok: 0,
|
||||||
err: None,
|
err: char_p_boxed::from(CString::default()),
|
||||||
},
|
},
|
||||||
Err(e) => FfiResult {
|
Err(e) => FfiResult {
|
||||||
ok: None,
|
ok: -1,
|
||||||
err: Some(Box::new(char_p_boxed::try_from(get_name(&e)).unwrap())),
|
err: char_p_boxed::try_from(get_name(&e)).unwrap(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,37 +97,37 @@ fn new_address(opaque_wallet: &OpaqueWallet) -> FfiResult<char_p_boxed> {
|
|||||||
let string_result = new_address.map(|a| a.to_string());
|
let string_result = new_address.map(|a| a.to_string());
|
||||||
match string_result {
|
match string_result {
|
||||||
Ok(a) => FfiResult {
|
Ok(a) => FfiResult {
|
||||||
ok: Some(Box::new(char_p_boxed::try_from(a).unwrap())),
|
ok: char_p_boxed::try_from(a).unwrap(),
|
||||||
err: None,
|
err: char_p_boxed::from(CString::default()),
|
||||||
},
|
},
|
||||||
Err(e) => FfiResult {
|
Err(e) => FfiResult {
|
||||||
ok: None,
|
ok: char_p_boxed::from(CString::default()),
|
||||||
err: Some(Box::new(char_p_boxed::try_from(get_name(&e)).unwrap())),
|
err: char_p_boxed::try_from(get_name(&e)).unwrap(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ffi_export]
|
#[ffi_export]
|
||||||
fn list_unspent(opaque_wallet: &OpaqueWallet) -> FfiResultVec<LocalUtxo> {
|
fn list_unspent(opaque_wallet: &OpaqueWallet) -> FfiResult<repr_c::Vec<LocalUtxo>> {
|
||||||
let unspent_result = opaque_wallet.raw.list_unspent();
|
let unspent_result = opaque_wallet.raw.list_unspent();
|
||||||
|
|
||||||
match unspent_result {
|
match unspent_result {
|
||||||
Ok(v) => FfiResultVec {
|
Ok(v) => FfiResult {
|
||||||
ok: {
|
ok: {
|
||||||
let ve: Vec<LocalUtxo> = v.iter().map(|lu| LocalUtxo::from(lu)).collect();
|
let ve: Vec<LocalUtxo> = v.iter().map(|lu| LocalUtxo::from(lu)).collect();
|
||||||
repr_c::Vec::from(ve)
|
repr_c::Vec::from(ve)
|
||||||
},
|
},
|
||||||
err: None,
|
err: char_p_boxed::from(CString::default()),
|
||||||
},
|
},
|
||||||
Err(e) => FfiResultVec {
|
Err(e) => FfiResult {
|
||||||
ok: repr_c::Vec::EMPTY,
|
ok: repr_c::Vec::EMPTY,
|
||||||
err: Some(Box::new(char_p_boxed::try_from(get_name(&e)).unwrap())),
|
err: char_p_boxed::try_from(get_name(&e)).unwrap(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ffi_export]
|
#[ffi_export]
|
||||||
fn free_unspent_result(unspent_result: FfiResultVec<LocalUtxo>) {
|
fn free_unspent_result(unspent_result: FfiResult<repr_c::Vec<LocalUtxo>>) {
|
||||||
drop(unspent_result)
|
drop(unspent_result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
test.sh
4
test.sh
@ -6,8 +6,8 @@ cargo test --features c-headers -- generate_headers
|
|||||||
|
|
||||||
# cc
|
# cc
|
||||||
export LD_LIBRARY_PATH=`pwd`/target/debug
|
export LD_LIBRARY_PATH=`pwd`/target/debug
|
||||||
valgrind --leak-check=full --show-leak-kinds=all cc/bdk_ffi_test
|
#valgrind --leak-check=full --show-leak-kinds=all cc/bdk_ffi_test
|
||||||
#cc/bdk_ffi_test
|
cc/bdk_ffi_test
|
||||||
|
|
||||||
# bdk-kotlin
|
# bdk-kotlin
|
||||||
(cd bdk-kotlin && gradle test)
|
(cd bdk-kotlin && gradle test)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user