Simplify Kotlin Wallet api
This commit is contained in:
parent
110dfbd13c
commit
757113c002
@ -1,9 +1,6 @@
|
||||
package org.bitcoindevkit.bdk
|
||||
|
||||
import android.util.Log
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.sun.jna.Native
|
||||
import org.junit.*
|
||||
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@ -16,5 +13,5 @@ import org.junit.Assert.*
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class AndroidLibTest : LibTest() {
|
||||
|
||||
|
||||
}
|
||||
|
@ -17,8 +17,7 @@ dependencies {
|
||||
api "org.slf4j:slf4j-api:1.7.30"
|
||||
testImplementation "ch.qos.logback:logback-classic:1.2.3"
|
||||
testImplementation "ch.qos.logback:logback-core:1.2.3"
|
||||
testImplementation 'org.jetbrains.kotlin:kotlin-test-junit'
|
||||
testImplementation (project(':test-fixtures'))
|
||||
testImplementation(project(':test-fixtures'))
|
||||
}
|
||||
|
||||
publishing {
|
||||
|
@ -1,6 +1,6 @@
|
||||
package org.bitcoindevkit.bdk
|
||||
|
||||
enum class Error {
|
||||
enum class JnaError {
|
||||
InvalidU32Bytes,
|
||||
Generic,
|
||||
ScriptDoesntHaveAddressForm,
|
||||
@ -37,7 +37,8 @@ enum class Error {
|
||||
Hex,
|
||||
Psbt,
|
||||
Electrum,
|
||||
// Esplora
|
||||
|
||||
// Esplora
|
||||
// CompactFilters
|
||||
Sled,
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
package org.bitcoindevkit.bdk
|
||||
|
||||
class JnaException internal constructor(val err: JnaError) : Exception()
|
@ -3,7 +3,7 @@ package org.bitcoindevkit.bdk
|
||||
import com.sun.jna.Native
|
||||
|
||||
abstract class LibBase {
|
||||
|
||||
|
||||
protected val libJna: LibJna
|
||||
get() = Native.load("bdk_ffi", LibJna::class.java)
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
package org.bitcoindevkit.bdk
|
||||
|
||||
import com.sun.jna.*
|
||||
import com.sun.jna.Library
|
||||
import com.sun.jna.Pointer
|
||||
import com.sun.jna.PointerType
|
||||
|
||||
interface LibJna : Library {
|
||||
|
||||
@ -35,13 +37,13 @@ interface LibJna : Library {
|
||||
// void free_string_result (
|
||||
// StringResult_t * string_result);
|
||||
fun free_string_result(string_result: StringResult_t)
|
||||
|
||||
|
||||
// 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)
|
||||
@ -61,11 +63,11 @@ interface LibJna : Library {
|
||||
descriptor: String,
|
||||
changeDescriptor: String?
|
||||
): WalletResult_t
|
||||
|
||||
|
||||
// char * get_wallet_err (
|
||||
// WalletResult_t const * wallet_result);
|
||||
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?
|
||||
|
@ -0,0 +1,37 @@
|
||||
package org.bitcoindevkit.bdk
|
||||
|
||||
import com.sun.jna.Pointer
|
||||
import com.sun.jna.PointerType
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
abstract class ResultBase<PT : PointerType, RT : Any> internal constructor(protected val resultT: PT) :
|
||||
LibBase() {
|
||||
|
||||
protected open val log: Logger = LoggerFactory.getLogger(ResultBase::class.java)
|
||||
|
||||
protected abstract fun err(): Pointer?
|
||||
|
||||
protected abstract fun ok(): RT
|
||||
|
||||
protected abstract fun free(pointer: PT)
|
||||
|
||||
private fun checkErr() {
|
||||
val errPointer = err()
|
||||
val err = errPointer?.getString(0)
|
||||
libJna.free_string(errPointer)
|
||||
if (err != null) {
|
||||
throw JnaException(JnaError.valueOf(err))
|
||||
}
|
||||
}
|
||||
|
||||
fun value(): RT {
|
||||
checkErr()
|
||||
return ok()
|
||||
}
|
||||
|
||||
protected fun finalize() {
|
||||
free(resultT)
|
||||
log.debug("$resultT freed")
|
||||
}
|
||||
}
|
@ -1,32 +1,26 @@
|
||||
package org.bitcoindevkit.bdk
|
||||
|
||||
import com.sun.jna.Pointer
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
class StringResult internal constructor(private val stringResultT: LibJna.StringResult_t) : LibBase() {
|
||||
class StringResult internal constructor(stringResultT: LibJna.StringResult_t) :
|
||||
ResultBase<LibJna.StringResult_t, String>(stringResultT) {
|
||||
|
||||
private val log: Logger = LoggerFactory.getLogger(StringResult::class.java)
|
||||
override val log: Logger = LoggerFactory.getLogger(StringResult::class.java)
|
||||
|
||||
fun isErr(): Boolean {
|
||||
return libJna.get_string_err(stringResultT) != null
|
||||
override fun err(): Pointer? {
|
||||
return libJna.get_string_err(resultT)
|
||||
}
|
||||
|
||||
fun err(): Error? {
|
||||
val errPointer = libJna.get_string_err(stringResultT)
|
||||
val err = errPointer?.getString(0)
|
||||
libJna.free_string(errPointer)
|
||||
return err?.let { Error.valueOf(it) }
|
||||
}
|
||||
|
||||
fun ok(): String? {
|
||||
val okPointer = libJna.get_string_ok(stringResultT)
|
||||
val ok = okPointer?.getString(0)
|
||||
|
||||
override fun ok(): String {
|
||||
val okPointer = libJna.get_string_ok(resultT)
|
||||
val ok = okPointer!!.getString(0)
|
||||
libJna.free_string(okPointer)
|
||||
return ok
|
||||
}
|
||||
|
||||
protected fun finalize() {
|
||||
libJna.free_string_result(stringResultT)
|
||||
log.debug("StringResult_t freed")
|
||||
|
||||
override fun free(pointer: LibJna.StringResult_t) {
|
||||
libJna.free_string_result(resultT)
|
||||
}
|
||||
}
|
@ -1,25 +1,23 @@
|
||||
package org.bitcoindevkit.bdk
|
||||
|
||||
import com.sun.jna.Pointer
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
class VoidResult internal constructor(private val voidResultT: LibJna.VoidResult_t) : LibBase() {
|
||||
class VoidResult internal constructor(voidResultT: LibJna.VoidResult_t) :
|
||||
ResultBase<LibJna.VoidResult_t, Unit>(voidResultT) {
|
||||
|
||||
private val log: Logger = LoggerFactory.getLogger(VoidResult::class.java)
|
||||
override val log: Logger = LoggerFactory.getLogger(VoidResult::class.java)
|
||||
|
||||
fun isErr(): Boolean {
|
||||
return libJna.get_void_err(voidResultT) != null
|
||||
override fun err(): Pointer? {
|
||||
return libJna.get_void_err(resultT)
|
||||
}
|
||||
|
||||
fun err(): Error? {
|
||||
val errPointer = libJna.get_void_err(voidResultT)
|
||||
val err = errPointer?.getString(0)
|
||||
libJna.free_string(errPointer)
|
||||
return err?.let { Error.valueOf(it) }
|
||||
|
||||
override fun ok() {
|
||||
// Void
|
||||
}
|
||||
|
||||
protected fun finalize() {
|
||||
libJna.free_void_result(voidResultT)
|
||||
log.debug("VoidResult_t freed")
|
||||
|
||||
override fun free(pointer: LibJna.VoidResult_t) {
|
||||
libJna.free_void_result(resultT)
|
||||
}
|
||||
}
|
@ -3,23 +3,30 @@ package org.bitcoindevkit.bdk
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
class Wallet internal constructor(
|
||||
private val walletRefT: LibJna.WalletRef_t,
|
||||
class Wallet constructor(
|
||||
name: String,
|
||||
descriptor: String,
|
||||
changeDescriptor: String?,
|
||||
) : 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))
|
||||
|
||||
val log: Logger = LoggerFactory.getLogger(Wallet::class.java)
|
||||
|
||||
private val walletResult =
|
||||
WalletResult(libJna.new_wallet_result(name, descriptor, changeDescriptor))
|
||||
private val walletRefT = walletResult.value()
|
||||
|
||||
fun sync() {
|
||||
val voidResult = VoidResult(libJna.sync_wallet(walletRefT.pointer))
|
||||
return voidResult.value()
|
||||
}
|
||||
|
||||
protected fun finalize() {
|
||||
fun getAddress(): String {
|
||||
val stringResult = StringResult(libJna.new_address(walletRefT.pointer))
|
||||
return stringResult.value()
|
||||
}
|
||||
|
||||
protected fun finalize(pointer: LibJna.WalletResult_t) {
|
||||
libJna.free_wallet_ref(walletRefT)
|
||||
log.debug("WalletRef_t freed")
|
||||
log.debug("$walletRefT freed")
|
||||
}
|
||||
|
||||
}
|
@ -1,36 +1,23 @@
|
||||
package org.bitcoindevkit.bdk
|
||||
|
||||
import com.sun.jna.Pointer
|
||||
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
|
||||
class WalletResult internal constructor(walletResultT: LibJna.WalletResult_t) :
|
||||
ResultBase<LibJna.WalletResult_t, LibJna.WalletRef_t>(walletResultT) {
|
||||
|
||||
override val log: Logger = LoggerFactory.getLogger(WalletResult::class.java)
|
||||
|
||||
override fun err(): Pointer? {
|
||||
return libJna.get_wallet_err(resultT)
|
||||
}
|
||||
|
||||
fun err(): Error? {
|
||||
val errPointer = libJna.get_wallet_err(walletResultT)
|
||||
val err = errPointer?.getString(0)
|
||||
libJna.free_string(errPointer)
|
||||
return err?.let { Error.valueOf(it) }
|
||||
override fun ok(): LibJna.WalletRef_t {
|
||||
return libJna.get_wallet_ok(resultT)!!
|
||||
}
|
||||
|
||||
fun ok(): Wallet? {
|
||||
val okWalletRef = libJna.get_wallet_ok(walletResultT)
|
||||
return if (okWalletRef != null) Wallet(okWalletRef) else null
|
||||
override fun free(pointer: LibJna.WalletResult_t) {
|
||||
libJna.free_wallet_result(resultT)
|
||||
}
|
||||
|
||||
protected fun finalize() {
|
||||
libJna.free_wallet_result(walletResultT)
|
||||
log.debug("WalletResult_t freed")
|
||||
}
|
||||
|
||||
}
|
@ -1,15 +1,9 @@
|
||||
package org.bitcoindevkit.bdk
|
||||
|
||||
import com.sun.jna.Native
|
||||
import org.junit.*
|
||||
import org.junit.Assert.assertEquals
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertNull
|
||||
|
||||
/**
|
||||
* Library test, which will execute on linux host.
|
||||
*
|
||||
*/
|
||||
class JvmLibTest : LibTest() {
|
||||
|
||||
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation "net.java.dev.jna:jna:5.8.0"
|
||||
implementation (project(':jvm'))
|
||||
implementation 'org.jetbrains.kotlin:kotlin-test-junit'
|
||||
implementation "junit:junit:4.13.2"
|
||||
//implementation "org.mockito.kotlin:mockito-kotlin:3.2.0"
|
||||
api "org.slf4j:slf4j-api:1.7.30"
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import org.junit.*
|
||||
import org.junit.Assert.*
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import javax.management.Descriptor
|
||||
|
||||
/**
|
||||
* Library test, which will execute on linux host.
|
||||
@ -21,21 +22,17 @@ abstract class LibTest : LibBase() {
|
||||
|
||||
@Test
|
||||
fun walletResultError() {
|
||||
val badWalletResult = WalletResult("bad", "bad", "bad")
|
||||
assertTrue(badWalletResult.isErr())
|
||||
val walletErr = badWalletResult.err()
|
||||
assertNotNull(walletErr)
|
||||
log.debug("wallet error $walletErr")
|
||||
assertEquals(Error.Descriptor, walletErr)
|
||||
val wallet = badWalletResult.ok()
|
||||
assertNull(wallet)
|
||||
val jnaException = assertThrows(JnaException::class.java) {
|
||||
Wallet("bad", "bad", "bad")
|
||||
}
|
||||
assertEquals(jnaException.err, JnaError.Descriptor)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun walletResultFinalize() {
|
||||
val names = listOf("one", "two", "three")
|
||||
names.map {
|
||||
val wallet = WalletResult(it, desc, change)
|
||||
val wallet = Wallet(it, desc, change)
|
||||
assertNotNull(wallet)
|
||||
}
|
||||
System.gc()
|
||||
@ -44,23 +41,16 @@ abstract class LibTest : LibBase() {
|
||||
|
||||
@Test
|
||||
fun walletSync() {
|
||||
val walletResult = WalletResult(name, desc, change)
|
||||
val wallet = walletResult.ok()
|
||||
val wallet = Wallet(name, desc, change)
|
||||
assertNotNull(wallet)
|
||||
val syncResult = wallet!!.sync();
|
||||
assertFalse(syncResult.isErr())
|
||||
assertNull(syncResult.err())
|
||||
wallet.sync()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun walletNewAddress() {
|
||||
val walletResult = WalletResult(name, desc, change)
|
||||
val wallet = walletResult.ok()
|
||||
val wallet = Wallet(name, desc, change)
|
||||
assertNotNull(wallet)
|
||||
val addressResult = wallet!!.getAddress()
|
||||
assertFalse(addressResult.isErr())
|
||||
assertNull(addressResult.err())
|
||||
val address = addressResult.ok()
|
||||
val address = wallet.getAddress()
|
||||
assertNotNull(address)
|
||||
log.debug("address created from kotlin: $address")
|
||||
assertEquals(address, "tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e")
|
||||
|
@ -129,13 +129,12 @@ fn get_wallet_ok<'lt>(wallet_result: &'lt WalletResult) -> Option<Box<WalletRef<
|
||||
.raw
|
||||
.as_ref()
|
||||
.ok()
|
||||
.map(|w| Box::new(WalletRef { raw: w}))
|
||||
.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));
|
||||
let void_result = wallet_ref.raw.sync(log_progress(), Some(100));
|
||||
Box::new(VoidResult { raw: void_result })
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user