commit 5bd7a283d3d223d5b4a8db45e62e88c362490287
parent 5e855250787aea09c8e854545fc0539ca5ac0e86
Author: Iván Ávalos <avalos@disroot.org>
Date: Thu, 23 Jul 2026 21:42:53 +0200
[wallet] fix #11361 (default expiration)
Diffstat:
4 files changed, 36 insertions(+), 28 deletions(-)
diff --git a/taler-kotlin-android/src/main/java/net/taler/common/Time.kt b/taler-kotlin-android/src/main/java/net/taler/common/Time.kt
@@ -86,6 +86,8 @@ data class RelativeTime(
) {
val ms: Long = us / 1000L
+ fun toHours(): Long = ms / (60 * 60 * 1000L)
+
companion object {
internal const val FOREVER: Long = -1
fun forever(): RelativeTime = fromMillis(FOREVER)
diff --git a/wallet/src/main/java/net/taler/wallet/peer/OutgoingPushComposable.kt b/wallet/src/main/java/net/taler/wallet/peer/OutgoingPushComposable.kt
@@ -48,6 +48,7 @@ import androidx.compose.ui.unit.dp
import kotlinx.serialization.json.JsonPrimitive
import net.taler.common.Amount
import net.taler.common.CurrencySpecification
+import net.taler.common.RelativeTime
import net.taler.wallet.BottomInsetsSpacer
import net.taler.wallet.R
import net.taler.wallet.backend.TalerErrorCode
@@ -121,6 +122,10 @@ fun OutgoingPushIntroComposable(
amount.useDebounce {
feeResult = getFees(it) ?: None()
+ (feeResult as? Success)?.let { res ->
+ option = ExpirationOption.CUSTOM
+ hours = res.defaultExpiration.toHours()
+ }
}
val amountFocusRequester = remember { FocusRequester() }
@@ -247,21 +252,23 @@ fun OutgoingPushIntroComposable(
},
)
- Text(
- modifier = Modifier.padding(top = 8.dp, start = 16.dp, end = 16.dp),
- text = stringResource(R.string.send_peer_expiration_period),
- style = MaterialTheme.typography.bodyMedium,
- )
+ if (devMode) {
+ Text(
+ modifier = Modifier.padding(top = 8.dp, start = 16.dp, end = 16.dp),
+ text = stringResource(R.string.send_peer_expiration_period),
+ style = MaterialTheme.typography.bodyMedium,
+ )
- ExpirationComposable(
- modifier = Modifier.padding(
- vertical = 8.dp,
- horizontal = 16.dp,
- ),
- option = option,
- hours = hours,
- onOptionChange = { option = it }
- ) { hours = it }
+ ExpirationComposable(
+ modifier = Modifier.padding(
+ vertical = 8.dp,
+ horizontal = 16.dp,
+ ),
+ option = option,
+ hours = hours,
+ onOptionChange = { option = it }
+ ) { hours = it }
+ }
(feeResult as? Success)?.let {
if (amount.scope is ScopeInfo.Global) {
@@ -318,7 +325,8 @@ fun PeerPushComposableCreatingPreview() {
getFees = { Success(
amountEffective = Amount.fromJSONString("KUDOS:10"),
amountRaw = Amount.fromJSONString("KUDOS:12"),
- exchangeBaseUrl = "https://exchange.demo.taler.net"
+ exchangeBaseUrl = "https://exchange.demo.taler.net",
+ defaultExpiration = RelativeTime.fromMillis(10 * 24 * 60 * 60 * 1000),
) },
onSend = { _, _, _ -> },
)
@@ -344,7 +352,8 @@ fun PeerPushComposableCheckingPreview() {
amountEffective = Amount.fromJSONString("KUDOS:10"),
amountRaw = Amount.fromJSONString("KUDOS:12"),
maxDepositAmountEffective = Amount.fromJSONString("KUDOS:12"),
- exchangeBaseUrl = "https://exchange.demo.taler.net"
+ exchangeBaseUrl = "https://exchange.demo.taler.net",
+ defaultExpiration = RelativeTime.fromMillis(10 * 24 * 60 * 60 * 1000),
) },
onSend = { _, _, _ -> },
)
@@ -372,7 +381,8 @@ fun PeerPushComposableCheckedPreview() {
amountEffective = Amount.fromJSONString("KUDOS:10"),
amountRaw = Amount.fromJSONString("KUDOS:12"),
maxDepositAmountEffective = Amount.fromJSONString("KUDOS:12"),
- exchangeBaseUrl = "https://exchange.demo.taler.net"
+ exchangeBaseUrl = "https://exchange.demo.taler.net",
+ defaultExpiration = RelativeTime.fromMillis(10 * 24 * 60 * 60 * 1000),
) },
onSend = { _, _, _ -> },
)
@@ -399,7 +409,8 @@ fun PeerPushComposableErrorPreview() {
amountEffective = Amount.fromJSONString("KUDOS:10"),
amountRaw = Amount.fromJSONString("KUDOS:12"),
maxDepositAmountEffective = Amount.fromJSONString("KUDOS:12"),
- exchangeBaseUrl = "https://exchange.demo.taler.net"
+ exchangeBaseUrl = "https://exchange.demo.taler.net",
+ defaultExpiration = RelativeTime.fromMillis(10 * 24 * 60 * 60 * 1000),
) },
onSend = { _, _, _ -> },
)
diff --git a/wallet/src/main/java/net/taler/wallet/peer/OutgoingState.kt b/wallet/src/main/java/net/taler/wallet/peer/OutgoingState.kt
@@ -19,6 +19,7 @@ package net.taler.wallet.peer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import net.taler.common.Amount
+import net.taler.common.RelativeTime
import net.taler.common.Timestamp
import net.taler.wallet.backend.TalerErrorInfo
import net.taler.wallet.exchanges.ExchangeTosStatus
@@ -76,6 +77,7 @@ sealed class CheckPeerPushDebitResponse {
val amountEffective: Amount,
val exchangeBaseUrl: String,
val maxExpirationDate: Timestamp,
+ val defaultExpiration: RelativeTime,
) : CheckPeerPushDebitResponse()
@Serializable
diff --git a/wallet/src/main/java/net/taler/wallet/peer/PeerManager.kt b/wallet/src/main/java/net/taler/wallet/peer/PeerManager.kt
@@ -27,6 +27,7 @@ import kotlinx.coroutines.launch
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import net.taler.common.Amount
+import net.taler.common.RelativeTime
import net.taler.common.Timestamp
import net.taler.wallet.main.TAG
import net.taler.wallet.backend.BackendManager
@@ -65,6 +66,7 @@ sealed class CheckFeeResult {
val amountRaw: Amount,
val amountEffective: Amount,
val exchangeBaseUrl: String,
+ val defaultExpiration: RelativeTime,
override val maxDepositAmountEffective: Amount? = null,
override val maxDepositAmountRaw: Amount? = null,
): CheckFeeResult()
@@ -179,16 +181,6 @@ class PeerManager(
maxDepositAmountRaw = max?.rawAmount,
)
- if (amount.isZero() && exchangeBaseUrl != null) {
- return CheckFeeResult.Success(
- amountRaw = amount,
- amountEffective = amount,
- maxDepositAmountEffective = max?.effectiveAmount,
- maxDepositAmountRaw = max?.rawAmount,
- exchangeBaseUrl = exchangeBaseUrl,
- )
- }
-
api.request("checkPeerPushDebitV2", CheckPeerPushDebitResponse.serializer()) {
exchangeBaseUrl?.let { put("exchangeBaseUrl", it) }
restrictScope?.let { put("restrictScope", JSONObject(BackendManager.json.encodeToString(it))) }
@@ -201,6 +193,7 @@ class PeerManager(
maxDepositAmountEffective = max?.effectiveAmount,
maxDepositAmountRaw = max?.rawAmount,
exchangeBaseUrl = r.exchangeBaseUrl,
+ defaultExpiration = r.defaultExpiration,
)
is CheckPeerPushDebitInsufficientBalanceResponse -> CheckFeeResult.InsufficientBalance(