Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import androidx.compose.ui.test.swipeRight
import androidx.compose.ui.test.swipeUp
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.dp
import com.synonym.bitkitcore.FeeRates
import com.synonym.paykit.PaymentRequestLifecycleState
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
Expand All @@ -41,6 +42,7 @@ import to.bitkit.models.PaykitAmount
import to.bitkit.models.PaykitAsset
import to.bitkit.models.PaykitRequestPricing
import to.bitkit.models.PubkyProfile
import to.bitkit.models.TransactionSpeed
import to.bitkit.repositories.MethodId
import to.bitkit.repositories.PaykitPaymentRequest
import to.bitkit.repositories.PaykitRecurrenceUnit
Expand Down Expand Up @@ -340,4 +342,31 @@ class SendConfirmScreenTest {
assertEquals(amountBounds, amount.getUnclippedBoundsInRoot())
assertEquals(swipeBounds, swipe.getUnclippedBoundsInRoot())
}

@Test
fun customFeeShowsTheConfirmationTimeOfItsTier() {
composeTestRule.setContent {
AppThemeSurface {
SendConfirmContent(
uiState = SendUiState(
amount = 25_000u,
address = "bcrt1qkgfgyxyqhvkdqh04sklnzxphmcds6vft6y7h0r",
isAmountInputValid = true,
payMethod = SendMethod.ONCHAIN,
speed = TransactionSpeed.Custom(4u),
feeRates = FeeRates(fast = 2u, mid = 1u, slow = 1u),
onchainFeeUi = OnchainFeeUi(rate = FeeRate.CUSTOM),
),
isNodeRunning = true,
isLoading = false,
showBiometrics = false,
modifier = Modifier.sheetHeight(),
)
}
}

composeTestRule.onNodeWithTag("SendConfirmToggleDetails").performClick()
composeTestRule.onNodeWithText("±10-20 minutes").performScrollTo().assertIsDisplayed()
composeTestRule.onNodeWithText("Depends on the fee").assertDoesNotExist()
}
}
7 changes: 7 additions & 0 deletions app/src/main/java/to/bitkit/models/FeeRate.kt
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,13 @@ enum class FeeRate(
}
}

/** The tier whose confirmation time applies to [speed], so a custom rate reads like the presets. */
fun forConfirmation(speed: TransactionSpeed, feeRates: FeeRates?): FeeRate {
val custom = speed as? TransactionSpeed.Custom ?: return fromSpeed(speed)
if (feeRates == null || custom.satsPerVByte == 0u) return CUSTOM
return fromSatsPerVByte(custom.satsPerVByte.toULong(), feeRates)
}

fun Context.getFeeShortDescription(
feeRate: ULong,
feeRates: FeeRates?,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,12 @@ private fun OnChainDetails(
tint = Colors.Brand,
modifier = Modifier.size(16.dp)
)
BodySSB(stringResource(feeUi.rate.description))
val confirmationRate = if (feeUi.rate == FeeRate.CUSTOM) {
FeeRate.forConfirmation(uiState.speed, uiState.feeRates)
Comment thread
ovitrif marked this conversation as resolved.
} else {
feeUi.rate
}
BodySSB(stringResource(confirmationRate.description))
}
}
}
Expand Down
39 changes: 39 additions & 0 deletions app/src/test/java/to/bitkit/models/FeeRateTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package to.bitkit.models

import com.synonym.bitkitcore.FeeRates
import org.junit.Test
import kotlin.test.assertEquals

class FeeRateTest {
private val feeRates = FeeRates(fast = 10u, mid = 5u, slow = 2u)

@Test
fun `custom rate at or above the fast tier confirms like fast`() {
assertEquals(FeeRate.FAST, FeeRate.forConfirmation(TransactionSpeed.Custom(10u), feeRates))
assertEquals(FeeRate.FAST, FeeRate.forConfirmation(TransactionSpeed.Custom(40u), feeRates))
}

@Test
fun `custom rate between tiers confirms like the tier below it`() {
assertEquals(FeeRate.NORMAL, FeeRate.forConfirmation(TransactionSpeed.Custom(7u), feeRates))
assertEquals(FeeRate.SLOW, FeeRate.forConfirmation(TransactionSpeed.Custom(3u), feeRates))
}

@Test
fun `custom rate below the slow tier confirms like minimum`() {
assertEquals(FeeRate.MINIMUM, FeeRate.forConfirmation(TransactionSpeed.Custom(1u), feeRates))
}

@Test
fun `custom rate without fee tiers keeps the custom description`() {
assertEquals(FeeRate.CUSTOM, FeeRate.forConfirmation(TransactionSpeed.Custom(4u), null))
assertEquals(FeeRate.CUSTOM, FeeRate.forConfirmation(TransactionSpeed.Custom(0u), feeRates))
}

@Test
fun `preset speeds keep their own tier`() {
assertEquals(FeeRate.FAST, FeeRate.forConfirmation(TransactionSpeed.Fast, feeRates))
assertEquals(FeeRate.NORMAL, FeeRate.forConfirmation(TransactionSpeed.Medium, feeRates))
assertEquals(FeeRate.SLOW, FeeRate.forConfirmation(TransactionSpeed.Slow, feeRates))
}
}
1 change: 1 addition & 0 deletions changelog.d/next/1634.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The send confirmation now estimates the confirmation time for a custom on-chain fee from the current fee tiers.
16 changes: 16 additions & 0 deletions journeys/send/custom-fee-confirmation-estimate.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<journey name="custom fee confirmation estimate">
<description>
Verifies that a custom on-chain fee shows the confirmation time of the fee tier it reaches,
the same text the preset speeds use, instead of "Depends on the fee". Preconditions: a synced
regtest wallet with at least 30,000 confirmed sats in Savings and the current fee tiers loaded.
The custom rate of 50 ₿/vbyte is above the regtest backend's Fast tier; on a backend whose Fast
tier is higher, use a rate above it.
</description>
<actions>
<action>Start an on-chain send of 5,000 sats from Savings to a fresh regtest address and reach the confirmation screen (testTag "SendConfirmContent")</action>
<action>Tap Show details (testTag "SendConfirmToggleDetails")</action>
<action>Open the speed picker by tapping the Speed and Fee value, then tap Custom (testTag "fee_CUSTOM_button")</action>
<action>On the custom fee screen (testTag "fee_screen"), clear the field with Remove (testTag "NRemove") and enter 50 with the number pad (testTags "N5", "N0"), then tap Continue (testTag "continue_btn")</action>
<action>Back on confirmation with details shown, verify Speed and Fee reads Custom and Confirming In reads "±10-20 minutes", the Fast speed's time, not "Depends on the fee"</action>
</actions>
</journey>
Loading