Skip to content

Handle BTC fee fallback without raw transaction#6188

Open
SeniorZhai wants to merge 1 commit intomasterfrom
opt/btc-fee-fallback
Open

Handle BTC fee fallback without raw transaction#6188
SeniorZhai wants to merge 1 commit intomasterfrom
opt/btc-fee-fallback

Conversation

@SeniorZhai
Copy link
Member

No description provided.

@SeniorZhai SeniorZhai requested a review from Copilot March 6, 2026 08:08
@SeniorZhai SeniorZhai added the testing Now testing, but you can review label Mar 6, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a BTC-specific fee estimation fallback path so the UI can still display a fee when building a raw BTC transaction fails (e.g., missing/invalid UTXOs), by allowing fee-rate estimation without providing a raw transaction.

Changes:

  • Add a BTC fallback flow in InputFragment.refreshGas to estimate/display fee even when the raw transaction cannot be built.
  • Introduce applyFallbackBtcFeeWithoutRawTransaction to apply the fallback fee/rate/minFee to UI/state.
  • Update Web3ViewModel.estimateBtcFeeRate to accept an optional raw transaction hex.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
app/src/main/java/one/mixin/android/ui/wallet/InputFragment.kt Adds BTC fallback fee estimation path when raw tx build or fee calc fails; updates UI accordingly.
app/src/main/java/one/mixin/android/ui/home/web3/Web3ViewModel.kt Allows BTC fee estimation API call with rawTransactionHex omitted/empty.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1452 to +1457
if (handledByBtcFallback) {
binding.iconImageView.isVisible = false
binding.contentTextView.isVisible = true
binding.loadingProgressBar.isVisible = false
applyFeeUi()
return
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fallback handling repeats the same UI state toggles (iconImageView/contentTextView/loadingProgressBar + applyFeeUi()) in multiple branches. This duplication makes it easy for the branches to drift (e.g., one path missing a UI update). Consider extracting a small helper to apply the common UI state for "fee resolved" and call it from all branches.

Copilot uses AI. Check for mistakes.
val estimate = web3ViewModel.estimateBtcFeeRate(currentRate = rate?.toPlainString()) ?: return false
rate = estimate.feeRate?.toBigDecimalOrNull() ?: rate
miniFee = estimate.minFee ?: miniFee
val fallbackFee: BigDecimal = estimate.minFee?.toBigDecimalOrNull()?.movePointLeft(1) ?: return false
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fallbackFee is derived from estimate.minFee by doing movePointLeft(1), which changes the unit/scale (÷10) compared to how minFee is treated elsewhere (e.g., Web3ViewModel.calcFee compares minFee directly against a BTC-denominated estimatedFee). This is likely to under-estimate the BTC fee and can produce invalid/underfunded transactions. Consider using estimate.minFee directly (same unit as calcFee) or clearly converting based on documented API units, but keep it consistent across the codepaths.

Suggested change
val fallbackFee: BigDecimal = estimate.minFee?.toBigDecimalOrNull()?.movePointLeft(1) ?: return false
val fallbackFee: BigDecimal = estimate.minFee?.toBigDecimalOrNull() ?: return false

Copilot uses AI. Check for mistakes.
Comment on lines +1459 to +1461
delay(3000)
refreshGas(t)
return
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refreshGas retries by calling itself after delay(3000) (both when transaction == null and when gas == null). If the underlying condition never resolves (e.g., persistent BTC UTXO/build failures), this creates unbounded recursion and can eventually overflow the stack. Prefer an iterative retry loop (or a bounded retry with backoff) and ensure it stops when the coroutine is cancelled / fragment is no longer active.

Copilot uses AI. Check for mistakes.
@SeniorZhai SeniorZhai removed the testing Now testing, but you can review label Mar 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants