Skip to content

Commit

Permalink
Merge branch 'master' into test/framework
Browse files Browse the repository at this point in the history
# Conflicts:
#	lib/android/src/main/java/com/reactnativeldk/LdkModule.kt
  • Loading branch information
ovitrif committed Mar 25, 2024
2 parents f91d4ab + 067f7b6 commit 2e4e77d
Show file tree
Hide file tree
Showing 43 changed files with 53,380 additions and 41,234 deletions.
17 changes: 17 additions & 0 deletions example/Dev.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,23 @@ const Dev = (): ReactElement => {
}}
/>

<Button
title={'List channel monitors'}
onPress={async (): Promise<void> => {
const monitorsRes = await ldk.listChannelMonitors(true);
if (monitorsRes.isErr()) {
return setMessage(monitorsRes.error.message);
}

let msg = `Channel Monitors (${monitorsRes.value.length}): \n`;
monitorsRes.value.forEach((monitor) => {
msg += `\n\n${JSON.stringify(monitor)}`;
});

setMessage(msg);
}}
/>

<Button
title={'Show version'}
onPress={async (): Promise<void> => {
Expand Down
Binary file modified lib/android/libs/LDK-release.aar
Binary file not shown.
Binary file modified lib/android/libs/ldk-java-javadoc.jar
Binary file not shown.
45 changes: 32 additions & 13 deletions lib/android/src/main/java/com/reactnativeldk/Helpers.kt
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ val Bolt11Invoice.asJson: WritableMap
val rawInvoice = signedInv.raw_invoice()

if (amount_milli_satoshis() is Option_u64Z.Some) result.putInt("amount_satoshis", ((amount_milli_satoshis() as Option_u64Z.Some).some.toInt() / 1000)) else result.putNull("amount_satoshis")
result.putString("description", rawInvoice.description()?.into_inner())
result.putString("description", rawInvoice.description()?.to_str())
result.putBoolean("check_signature", signedInv.check_signature())
result.putBoolean("is_expired", is_expired)
result.putInt("duration_since_epoch", duration_since_epoch().toInt())
Expand Down Expand Up @@ -199,6 +199,21 @@ val RouteHop.asJson: WritableMap
return hop
}


fun ChannelMonitor.asJson(channelId: String): WritableMap {
val result = Arguments.createMap()
result.putString("channel_id", channelId)
result.putHexString("funding_txo", _funding_txo._b)
result.putHexString("counterparty_node_id", _counterparty_node_id)

val balances = Arguments.createArray()
_claimable_balances.iterator().forEach { balance ->
balances.pushMap(balance.asJson)
}
result.putArray("claimable_balances", balances)
return result
}

fun WritableMap.putHexString(key: String, bytes: ByteArray?) {
if (bytes != null) {
putString(key, bytes.hexEncodedString())
Expand Down Expand Up @@ -434,56 +449,60 @@ fun UserConfig.mergeWithMap(map: ReadableMap): UserConfig {
return this
}

fun ChainMonitor.getClaimableBalancesAsJson(ignoredChannels: Array<ChannelDetails>): WritableArray {
val result = Arguments.createArray()

get_claimable_balances(ignoredChannels).iterator().forEach { balance ->
val Balance.asJson: WritableMap
get() {
val map = Arguments.createMap()
//Defaults if all castings for balance fail
map.putInt("amount_satoshis", 0)
map.putString("type", "Unknown")

(balance as? Balance.ClaimableAwaitingConfirmations)?.let { claimableAwaitingConfirmations ->
(this as? Balance.ClaimableAwaitingConfirmations)?.let { claimableAwaitingConfirmations ->
map.putInt("amount_satoshis", claimableAwaitingConfirmations.amount_satoshis.toInt())
map.putInt("confirmation_height", claimableAwaitingConfirmations.confirmation_height)
map.putString("type", "ClaimableAwaitingConfirmations")
}

(balance as? Balance.ClaimableOnChannelClose)?.let { claimableOnChannelClose ->
(this as? Balance.ClaimableOnChannelClose)?.let { claimableOnChannelClose ->
map.putInt("amount_satoshis", claimableOnChannelClose.amount_satoshis.toInt())
map.putString("type", "ClaimableOnChannelClose")
}

(balance as? Balance.ContentiousClaimable)?.let { contentiousClaimable ->
(this as? Balance.ContentiousClaimable)?.let { contentiousClaimable ->
map.putInt("amount_satoshis", contentiousClaimable.amount_satoshis.toInt())
map.putInt("timeout_height", contentiousClaimable.timeout_height)
map.putString("type", "ContentiousClaimable")
}

(balance as? Balance.CounterpartyRevokedOutputClaimable)?.let { counterpartyRevokedOutputClaimable ->
(this as? Balance.CounterpartyRevokedOutputClaimable)?.let { counterpartyRevokedOutputClaimable ->
map.putInt("amount_satoshis", counterpartyRevokedOutputClaimable.amount_satoshis.toInt())
map.putString("type", "CounterpartyRevokedOutputClaimable")
}

(balance as? Balance.MaybePreimageClaimableHTLC)?.let { maybePreimageClaimableHTLC ->
(this as? Balance.MaybePreimageClaimableHTLC)?.let { maybePreimageClaimableHTLC ->
map.putInt("amount_satoshis", maybePreimageClaimableHTLC.amount_satoshis.toInt())
map.putInt("expiry_height", maybePreimageClaimableHTLC.expiry_height)
map.putString("type", "MaybePreimageClaimableHTLC")
}

(balance as? Balance.MaybeTimeoutClaimableHTLC)?.let { maybeTimeoutClaimableHTLC ->
(this as? Balance.MaybeTimeoutClaimableHTLC)?.let { maybeTimeoutClaimableHTLC ->
map.putInt("amount_satoshis", maybeTimeoutClaimableHTLC.amount_satoshis.toInt())
map.putInt("claimable_height", maybeTimeoutClaimableHTLC.claimable_height)
map.putString("type", "MaybeTimeoutClaimableHTLC")
}

result.pushMap(map)
return map
}

fun ChainMonitor.getClaimableBalancesAsJson(ignoredChannels: Array<ChannelDetails>): WritableArray {
val result = Arguments.createArray()

get_claimable_balances(ignoredChannels).iterator().forEach { balance ->
result.pushMap(balance.asJson)
}

return result
}


/// Helper for returning real network and currency as a tuple from a string
fun getNetwork(chain: String): Pair<Network, Currency> {
return when (chain) {
Expand Down
110 changes: 72 additions & 38 deletions lib/android/src/main/java/com/reactnativeldk/LdkModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@ import org.ldk.batteries.NioPeerHandler
import org.ldk.enums.Currency
import org.ldk.enums.Network
import org.ldk.enums.Recipient
import org.ldk.enums.RetryableSendFailure
import org.ldk.impl.bindings.LDKPaymentSendFailure.DuplicatePayment
import org.ldk.impl.bindings.get_ldk_c_bindings_version
import org.ldk.impl.bindings.get_ldk_version
import org.ldk.structs.*
import org.ldk.structs.Result_Bolt11InvoiceParseOrSemanticErrorZ.Result_Bolt11InvoiceParseOrSemanticErrorZ_OK
import org.ldk.structs.Result_Bolt11InvoiceSignOrCreationErrorZ.Result_Bolt11InvoiceSignOrCreationErrorZ_OK
import org.ldk.structs.Result_C2Tuple_ThirtyTwoBytesChannelMonitorZDecodeErrorZ.Result_C2Tuple_ThirtyTwoBytesChannelMonitorZDecodeErrorZ_OK
import org.ldk.structs.Result_C3Tuple_ThirtyTwoBytesRecipientOnionFieldsRouteParametersZNoneZ.Result_C3Tuple_ThirtyTwoBytesRecipientOnionFieldsRouteParametersZNoneZ_OK
import org.ldk.structs.Result_NoneRetryableSendFailureZ.Result_NoneRetryableSendFailureZ_Err
import org.ldk.structs.Result_PublicKeyNoneZ.Result_PublicKeyNoneZ_OK
import org.ldk.structs.Result_StrSecp256k1ErrorZ.Result_StrSecp256k1ErrorZ_OK
import org.ldk.util.UInt128
Expand Down Expand Up @@ -75,11 +79,9 @@ enum class LdkErrors {
invoice_payment_fail_must_specify_amount,
invoice_payment_fail_must_not_specify_amount,
invoice_payment_fail_invoice,
invoice_payment_fail_sending,
invoice_payment_fail_resend_safe,
invoice_payment_fail_parameter_error,
invoice_payment_fail_partial,
invoice_payment_fail_path_parameter_error,
invoice_payment_fail_duplicate_payment,
invoice_payment_fail_payment_expired,
invoice_payment_fail_route_not_found,
init_ldk_currency,
invoice_create_failed,
init_scorer_failed,
Expand Down Expand Up @@ -580,8 +582,8 @@ class LdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMod
//MARK: Update methods

@ReactMethod
fun updateFees(anchorChannelFee: Double, nonAnchorChannelFee: Double, channelCloseMinimum: Double, minAllowedAnchorChannelRemoteFee: Double, maxAllowedNonAnchorChannelRemoteFee: Double, onChainSweep: Double, minAllowedNonAnchorChannelRemoteFee: Double, promise: Promise) {
feeEstimator.update(anchorChannelFee.toInt(), nonAnchorChannelFee.toInt(), channelCloseMinimum.toInt(), minAllowedAnchorChannelRemoteFee.toInt(), maxAllowedNonAnchorChannelRemoteFee.toInt(), onChainSweep.toInt(), minAllowedNonAnchorChannelRemoteFee.toInt())
fun updateFees(anchorChannelFee: Double, nonAnchorChannelFee: Double, channelCloseMinimum: Double, minAllowedAnchorChannelRemoteFee: Double, onChainSweep: Double, minAllowedNonAnchorChannelRemoteFee: Double, promise: Promise) {
feeEstimator.update(anchorChannelFee.toInt(), nonAnchorChannelFee.toInt(), channelCloseMinimum.toInt(), minAllowedAnchorChannelRemoteFee.toInt(), onChainSweep.toInt(), minAllowedNonAnchorChannelRemoteFee.toInt())
handleResolve(promise, LdkCallbackResponses.fees_updated)
}

Expand Down Expand Up @@ -792,14 +794,27 @@ class LdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMod
return handleReject(promise, LdkErrors.invoice_payment_fail_must_not_specify_amount)
}

val res = if (isZeroValueInvoice)
UtilMethods.pay_zero_value_invoice(invoice, amountSats.toLong() * 1000, Retry.timeout(timeoutSeconds.toLong()), channelManager) else
UtilMethods.pay_invoice(invoice, Retry.timeout(timeoutSeconds.toLong()), channelManager)
val paymentId = invoice.payment_hash()
val detailsRes = if (isZeroValueInvoice)
UtilMethods.payment_parameters_from_zero_amount_invoice(invoice, amountSats.toLong()) else
UtilMethods.payment_parameters_from_invoice(invoice)

if (!detailsRes.is_ok) {
return handleReject(promise, LdkErrors.invoice_payment_fail_invoice)
}

val sendDetails = detailsRes as Result_C3Tuple_ThirtyTwoBytesRecipientOnionFieldsRouteParametersZNoneZ_OK
val paymentHash = sendDetails.res._a
val recipientOnion = sendDetails.res._b
val routeParams = sendDetails.res._c

val res = channelManager!!.send_payment(paymentHash, recipientOnion, paymentId, routeParams, Retry.timeout(timeoutSeconds.toLong()))

if (res.is_ok) {
channelManagerPersister.persistPaymentSent(hashMapOf(
"bolt11_invoice" to paymentRequest,
"description" to (invoice.into_signed_raw().raw_invoice().description()?.into_inner() ?: ""),
"payment_id" to (res as Result_ThirtyTwoBytesPaymentErrorZ.Result_ThirtyTwoBytesPaymentErrorZ_OK).res.hexEncodedString(),
"description" to (invoice.into_signed_raw().raw_invoice().description()?.to_str() ?: ""),
"payment_id" to paymentId.hexEncodedString(),
"payment_hash" to invoice.payment_hash().hexEncodedString(),
"amount_sat" to if (isZeroValueInvoice) amountSats.toLong() else ((invoice.amount_milli_satoshis() as Option_u64Z.Some).some.toInt() / 1000),
"unix_timestamp" to (System.currentTimeMillis() / 1000).toInt(),
Expand All @@ -809,39 +824,24 @@ class LdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMod
return handleResolve(promise, LdkCallbackResponses.invoice_payment_success)
}

val error = res as? Result_ThirtyTwoBytesPaymentErrorZ.Result_ThirtyTwoBytesPaymentErrorZ_Err

val invoiceError = error?.err as? PaymentError.Invoice
if (invoiceError != null) {
return handleReject(promise, LdkErrors.invoice_payment_fail_invoice, Error(invoiceError.invoice))
}

val sendingError = error?.err as? PaymentError.Sending
if (sendingError != null) {
val paymentAllFailedResendSafe = sendingError.sending as? PaymentSendFailure.AllFailedResendSafe
if (paymentAllFailedResendSafe != null) {
return handleReject(promise, LdkErrors.invoice_payment_fail_resend_safe, Error(paymentAllFailedResendSafe.all_failed_resend_safe.map { it.toString() }.toString()))
}
val error = res as? Result_NoneRetryableSendFailureZ_Err
?: return handleReject(promise, LdkErrors.invoice_payment_fail_unknown)

val paymentParameterError = sendingError.sending as? PaymentSendFailure.ParameterError
if (paymentParameterError != null) {
return handleReject(promise, LdkErrors.invoice_payment_fail_parameter_error, Error(paymentParameterError.parameter_error.toString()))
when (error.err) {
RetryableSendFailure.LDKRetryableSendFailure_DuplicatePayment -> {
handleReject(promise, LdkErrors.invoice_payment_fail_duplicate_payment)
}

val paymentPartialFailure = sendingError.sending as? PaymentSendFailure.PartialFailure
if (paymentPartialFailure != null) {
return handleReject(promise, LdkErrors.invoice_payment_fail_partial, Error(paymentPartialFailure.toString()))
RetryableSendFailure.LDKRetryableSendFailure_PaymentExpired -> {
handleReject(promise, LdkErrors.invoice_payment_fail_payment_expired)
}

val paymentPathParameterError = sendingError.sending as? PaymentSendFailure.PathParameterError
if (paymentPathParameterError != null) {
return handleReject(promise, LdkErrors.invoice_payment_fail_path_parameter_error, Error(paymentPartialFailure.toString()))
RetryableSendFailure.LDKRetryableSendFailure_RouteNotFound -> {
handleReject(promise, LdkErrors.invoice_payment_fail_route_not_found)
}

return handleReject(promise, LdkErrors.invoice_payment_fail_sending, Error("PaymentError.Sending: ${sendingError.sending.name}"))
else -> handleReject(promise, LdkErrors.invoice_payment_fail_unknown)
}

return handleReject(promise, LdkErrors.invoice_payment_fail_unknown)
}

@ReactMethod
Expand Down Expand Up @@ -963,6 +963,40 @@ class LdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMod
promise.resolve(list)
}

@ReactMethod
fun listChannelMonitors(ignoreOpenChannels: Boolean, promise: Promise) {
val channelManager = channelManager ?: return handleReject(promise, LdkErrors.init_channel_manager)
val keysManager = keysManager ?: return handleReject(promise, LdkErrors.init_keys_manager)
if (channelStoragePath == "") {
return handleReject(promise, LdkErrors.init_storage_path)
}

val ignoredChannels = if (ignoreOpenChannels)
channelManager.list_channels().map { it._channel_id.hexEncodedString() }.toTypedArray() else
arrayOf()

val channelFiles = File(channelStoragePath).listFiles()

val result = Arguments.createArray()
for (channelFile in channelFiles) {
val channelId = channelFile.nameWithoutExtension

//Ignore open channels
if (ignoredChannels.contains(channelId)) {
continue
}

val channelMonitor = UtilMethods.C2Tuple_ThirtyTwoBytesChannelMonitorZ_read(channelFile.readBytes(), keysManager!!.inner.as_EntropySource(), SignerProvider.new_impl(keysManager!!.signerProvider))

if (channelMonitor.is_ok) {
val channelMonitorResult = (channelMonitor as Result_C2Tuple_ThirtyTwoBytesChannelMonitorZDecodeErrorZ_OK)
result.pushMap(channelMonitorResult.res._b.asJson(channelMonitorResult.res._a.hexEncodedString()))
}
}

promise.resolve(result)
}

@ReactMethod
fun networkGraphListNodeIds(promise: Promise) {
val graph = networkGraph?.read_only() ?: return handleReject(promise, LdkErrors.init_network_graph)
Expand Down Expand Up @@ -1111,7 +1145,7 @@ class LdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMod

val output = TxOut(outputValue.toLong(), outputScriptPubKey.hexa())
val outpoint = OutPoint.of(outpointTxId.hexa().reversedArray(), outpointIndex.toInt().toShort())
val descriptor = SpendableOutputDescriptor.static_output(outpoint, output)
val descriptor = SpendableOutputDescriptor.static_output(outpoint, output, byteArrayOf())

val ldkDescriptors: MutableList<SpendableOutputDescriptor> = arrayListOf()
ldkDescriptors.add(descriptor)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import org.ldk.structs.Result_ShutdownScriptNoneZ
import org.ldk.structs.Result_TransactionNoneZ
import org.ldk.structs.Result_WriteableEcdsaChannelSignerDecodeErrorZ
import org.ldk.structs.ShutdownScript
import org.ldk.structs.SignerProvider
import org.ldk.structs.SignerProvider.SignerProviderInterface
import org.ldk.structs.SpendableOutputDescriptor
import org.ldk.structs.TxOut
import org.ldk.structs.WitnessProgram
import org.ldk.structs.WriteableEcdsaChannelSigner
import org.ldk.util.UInt128
import org.ldk.util.WitnessVersion
Expand Down Expand Up @@ -59,15 +59,13 @@ class CustomKeysManager(
class CustomSignerProvider : SignerProviderInterface {
lateinit var customKeysManager: CustomKeysManager

override fun get_destination_script(): Result_CVec_u8ZNoneZ {
override fun get_destination_script(p0: ByteArray?): Result_CVec_u8ZNoneZ {
return Result_CVec_u8ZNoneZ.ok(customKeysManager.destinationScriptPublicKey)
}

override fun get_shutdown_scriptpubkey(): Result_ShutdownScriptNoneZ {
val res = ShutdownScript.new_witness_program(
WitnessVersion(customKeysManager.witnessProgramVersion),
customKeysManager.witnessProgram
)
val witness = WitnessProgram(customKeysManager.witnessProgram, WitnessVersion(customKeysManager.witnessProgramVersion))
val res = ShutdownScript.new_witness_program(witness)

return if (res.is_ok) {
Result_ShutdownScriptNoneZ.ok((res as Result_ShutdownScriptInvalidShutdownScriptZ.Result_ShutdownScriptInvalidShutdownScriptZ_OK).res)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,14 @@ class LdkFeeEstimator {
var nonAnchorChannelFee: Int = 0
var channelCloseMinimum: Int = 0
var minAllowedAnchorChannelRemoteFee: Int = 0
var maxAllowedNonAnchorChannelRemoteFee: Int = 0
var onChainSweep: Int = 0
var minAllowedNonAnchorChannelRemoteFee: Int = 0

fun update(anchorChannelFee: Int, nonAnchorChannelFee: Int, channelCloseMinimum: Int, minAllowedAnchorChannelRemoteFee: Int, maxAllowedNonAnchorChannelRemoteFee: Int, onChainSweep: Int, minAllowedNonAnchorChannelRemoteFee: Int) {
fun update(anchorChannelFee: Int, nonAnchorChannelFee: Int, channelCloseMinimum: Int, minAllowedAnchorChannelRemoteFee: Int, onChainSweep: Int, minAllowedNonAnchorChannelRemoteFee: Int) {
this.anchorChannelFee = anchorChannelFee
this.nonAnchorChannelFee = nonAnchorChannelFee
this.channelCloseMinimum = channelCloseMinimum
this.minAllowedAnchorChannelRemoteFee = minAllowedAnchorChannelRemoteFee
this.maxAllowedNonAnchorChannelRemoteFee = maxAllowedNonAnchorChannelRemoteFee
this.onChainSweep = onChainSweep
this.minAllowedNonAnchorChannelRemoteFee = minAllowedNonAnchorChannelRemoteFee

Expand All @@ -31,7 +29,6 @@ class LdkFeeEstimator {
ConfirmationTarget.LDKConfirmationTarget_NonAnchorChannelFee -> nonAnchorChannelFee
ConfirmationTarget.LDKConfirmationTarget_ChannelCloseMinimum -> channelCloseMinimum
ConfirmationTarget.LDKConfirmationTarget_MinAllowedAnchorChannelRemoteFee -> minAllowedAnchorChannelRemoteFee
ConfirmationTarget.LDKConfirmationTarget_MaxAllowedNonAnchorChannelRemoteFee -> maxAllowedNonAnchorChannelRemoteFee
ConfirmationTarget.LDKConfirmationTarget_OnChainSweep -> onChainSweep
ConfirmationTarget.LDKConfirmationTarget_MinAllowedNonAnchorChannelRemoteFee -> minAllowedNonAnchorChannelRemoteFee
else -> {
Expand Down
Loading

0 comments on commit 2e4e77d

Please sign in to comment.