Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
3 Skipped Deployments
|
| mainAccount.currency.blockAvgTime | ||
| ? mainAccount.currency.blockAvgTime * 100 | ||
| : getEnv("DEFAULT_TRANSACTION_POLLING_INTERVAL"), |
Check failure
Code scanning / CodeQL
Resource exhaustion High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 13 days ago
In general, to fix resource-exhaustion risks from timers whose durations can be influenced by external input, we should clamp the computed delay to a reasonable range: enforce a minimum (e.g., 0) and a maximum (e.g., several minutes), and possibly fall back to a safe default if the value is invalid. This prevents malicious or buggy inputs from creating extremely long-running timers or huge numbers of pending timeouts/intervals.
For this specific case, we should adjust the setInterval in MethodSelection.tsx so that the delay is derived from a bounded value. Today it uses either mainAccount.currency.blockAvgTime * 100 or getEnv("DEFAULT_TRANSACTION_POLLING_INTERVAL") directly. We can compute a pollingInterval variable, normalize it to a number, and then clamp it between a small minimum and a reasonable maximum (for example, 1 second and 10 minutes). We then pass this safe pollingInterval to setInterval. This keeps existing behavior for normal values (typical Bitcoin blockAvgTime is small, and the env default is likely a modest delay) while protecting against arbitrarily large values injected via envs or unexpected currency definitions.
Concretely, within apps/ledger-live-mobile/src/families/bitcoin/EditTransactionFlow/MethodSelection.tsx, inside the useEffect that defines setTransactionHasBeenValidatedCallback, we will:
- Introduce a
const rawInterval = ...expression that mirrors the existing ternary choice. - Compute
const pollingInterval = Math.min(MAX, Math.max(MIN, Number(rawInterval) || DEFAULT));with chosen constants (defined immediately above in the same scope to avoid broader changes). - Use
pollingIntervalas the second argument tosetInterval.
No other files need modification, since the other alert variants either already use fixed delays (setTimeout(..., 0)) or are test-specific message passing without affecting timers.
| @@ -139,13 +139,21 @@ | ||
| } | ||
| }; | ||
|
|
||
| // Determine a safe polling interval based on currency average block time or env default. | ||
| const rawInterval = mainAccount.currency.blockAvgTime | ||
| ? mainAccount.currency.blockAvgTime * 100 | ||
| : getEnv("DEFAULT_TRANSACTION_POLLING_INTERVAL"); | ||
| // Clamp the interval to avoid excessively long or invalid durations. | ||
| const MIN_POLLING_INTERVAL_MS = 1000; // 1 second | ||
| const MAX_POLLING_INTERVAL_MS = 10 * 60 * 1000; // 10 minutes | ||
| const numericInterval = Number(rawInterval); | ||
| const pollingInterval = | ||
| Number.isFinite(numericInterval) && numericInterval > 0 | ||
| ? Math.min(MAX_POLLING_INTERVAL_MS, Math.max(MIN_POLLING_INTERVAL_MS, numericInterval)) | ||
| : MIN_POLLING_INTERVAL_MS; | ||
|
|
||
| setTransactionHasBeenValidatedCallback(); | ||
| const intervalId = setInterval( | ||
| () => setTransactionHasBeenValidatedCallback(), | ||
| mainAccount.currency.blockAvgTime | ||
| ? mainAccount.currency.blockAvgTime * 100 | ||
| : getEnv("DEFAULT_TRANSACTION_POLLING_INTERVAL"), | ||
| ); | ||
| const intervalId = setInterval(() => setTransactionHasBeenValidatedCallback(), pollingInterval); | ||
|
|
||
| return () => { | ||
| clearInterval(intervalId); |
There was a problem hiding this comment.
mainAccount.currency.blockAvgTime * 100 is enought
it's about 5min
There was a problem hiding this comment.
Pull request overview
This PR adds Bitcoin “edit transaction” (RBF) capabilities—speed up and cancel—spanning the coin-bitcoin module, Live Common integrations (stuck/editable ops), feature-flagging, and a dedicated Ledger Live Mobile flow/UI.
Changes:
- Introduces Bitcoin RBF helpers + editTransaction API surface (patch building, validation, fee bump rules, confirmation polling).
- Extends sync/operation logic to track inputs and filter replaced/unconfirmed operations and related UTXOs.
- Adds Mobile UI flow (method selection + summary + navigation wiring) gated behind a new
editBitcoinTxfeature flag.
Reviewed changes
Copilot reviewed 68 out of 70 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Adds @ledgerhq/coin-bitcoin workspace link to mobile importer. |
| libs/ledgerjs/packages/types-live/src/feature.ts | Adds editBitcoinTx feature flag type. |
| libs/ledger-live-common/src/operation.ts | Routes editable/stuck op logic to bitcoin coin-module operation helpers. |
| libs/ledger-live-common/src/featureFlags/defaultFeatures.ts | Defines default editBitcoinTx flag (disabled) with params. |
| libs/env/src/env.ts | Adds BITCOIN_STUCK_TRANSACTION_TIMEOUT + typo fix in ETH description. |
| libs/coin-modules/coin-evm/src/operation.ts | Comment typo fix (“weather” → “whether”). |
| libs/coin-modules/coin-bitcoin/src/wallet-btc/xpub.ts | RBF-aware tx building + script/address handling updates. |
| libs/coin-modules/coin-bitcoin/src/wallet-btc/wallet.ts | Computes min replacement fee for conflicts; adds tx block height accessor. |
| libs/coin-modules/coin-bitcoin/src/wallet-btc/utils.ts | Adds scriptToAddress + incremental fee floor helper. |
| libs/coin-modules/coin-bitcoin/src/wallet-btc/pickingstrategies/Merge.ts | Filters out UTXOs whose parent tx hex can’t be fetched. |
| libs/coin-modules/coin-bitcoin/src/wallet-btc/pickingstrategies/DeepFirst.ts | Filters out UTXOs whose parent tx hex can’t be fetched. |
| libs/coin-modules/coin-bitcoin/src/wallet-btc/pickingstrategies/CoinSelect.ts | Filters out UTXOs whose parent tx hex can’t be fetched. |
| libs/coin-modules/coin-bitcoin/src/wallet-btc/index.ts | Extracts getWalletAccount into dedicated module export. |
| libs/coin-modules/coin-bitcoin/src/wallet-btc/getWalletAccount.ts | New helper to avoid circular deps. |
| libs/coin-modules/coin-bitcoin/src/wallet-btc/explorer/types.ts | Adds getTxBlockHeight to explorer interface. |
| libs/coin-modules/coin-bitcoin/src/wallet-btc/explorer/index.ts | Implements getTxBlockHeight via /tx/:hash. |
| libs/coin-modules/coin-bitcoin/src/wallet-btc/tests/xpub.unit.test.ts | Minor formatting cleanup. |
| libs/coin-modules/coin-bitcoin/src/wallet-btc/tests/xpub.pickingStrategies.integration.test.ts | Updates fixture tx hashes used by tests. |
| libs/coin-modules/coin-bitcoin/src/wallet-btc/tests/utils.test.ts | Adds unit tests for incremental fee floor + scriptToAddress. |
| libs/coin-modules/coin-bitcoin/src/wallet-btc/tests/rbfReplaceCancel.integ.test.ts | New RBF integration test suite (cancel/speedup flows + history filtering). |
| libs/coin-modules/coin-bitcoin/src/wallet-btc/tests/fixtures/rbf.fixtures.ts | New fixture builder for RBF tx hex/id generation. |
| libs/coin-modules/coin-bitcoin/src/types.ts | Adds replaceTxId + EditType type. |
| libs/coin-modules/coin-bitcoin/src/transaction.ts | Serializes/deserializes replaceTxId. |
| libs/coin-modules/coin-bitcoin/src/synchronisation.ts | Adds input tracking + filters replaced ops & related UTXOs; recomputes balance from filtered UTXOs. |
| libs/coin-modules/coin-bitcoin/src/synchronisation.test.ts | Updates/removeReplaced expectations; adds two-weeks filtering behavior coverage. |
| libs/coin-modules/coin-bitcoin/src/rbfHelpers.ts | New helpers to compute RBF minimum bump fees, conflicts, and fee-rate requirements. |
| libs/coin-modules/coin-bitcoin/src/rbfHelpers.test.ts | Unit tests for RBF helpers. |
| libs/coin-modules/coin-bitcoin/src/prepareTransaction.ts | Auto-populates excludeUTXOs for unfetchable tx parents. |
| libs/coin-modules/coin-bitcoin/src/operation.ts | New bitcoin operation helpers (editable/stuck/stuck-op selection). |
| libs/coin-modules/coin-bitcoin/src/logic.ts | Adds extra.inputs when mapping tx → operations. |
| libs/coin-modules/coin-bitcoin/src/getTransactionStatus.ts | Special-cases amount-required validation for RBF cancel intent. |
| libs/coin-modules/coin-bitcoin/src/editTransaction/isTransactionConfirmed.ts | New confirmation check using explorer tx block height. |
| libs/coin-modules/coin-bitcoin/src/editTransaction/isStrategyDisabled.ts | New fee-strategy disabling rule based on minimum bump. |
| libs/coin-modules/coin-bitcoin/src/editTransaction/index.ts | Exports editTransaction API surface. |
| libs/coin-modules/coin-bitcoin/src/editTransaction/hasMinimumFunds.ts | New “has enough funds to bump” checks. |
| libs/coin-modules/coin-bitcoin/src/editTransaction/getTransactionStatus.ts | Validates edited tx fee bump and merges into status. |
| libs/coin-modules/coin-bitcoin/src/editTransaction/getMinEditTransactionFees.ts | Defines minimum bump rule (>=10% and >= +1 sat/vB). |
| libs/coin-modules/coin-bitcoin/src/editTransaction/getFormattedFeeFields.ts | Formats fee fields for UI display. |
| libs/coin-modules/coin-bitcoin/src/editTransaction/getEditTransactionPatch.ts | Builds cancel/speedup patch and bumps to at least “fast” network fee. |
| libs/coin-modules/coin-bitcoin/src/createTransaction.ts | Defaults BTC transactions to rbf: true. |
| libs/coin-modules/coin-bitcoin/src/cache.ts | Includes replaceTxId in fee-calculation cache key. |
| libs/coin-modules/coin-bitcoin/src/buildTransaction.ts | Passes replaceTx context + conflicting pending ops into wallet builder. |
| libs/coin-modules/coin-bitcoin/src/buildRbfTransaction.ts | Builds baseline speedup/cancel intents from on-chain tx hex + local wallet data. |
| libs/coin-modules/coin-bitcoin/src/buildRbfTransaction.test.ts | Unit tests for intent builder behavior. |
| libs/coin-modules/coin-bitcoin/src/buildOptimisticOperation.ts | Allows attaching transactionRaw into optimistic op. |
| libs/coin-modules/coin-bitcoin/src/tests/unit/editTransaction/isTransactionConfirmed.test.ts | Unit tests for confirmation check. |
| libs/coin-modules/coin-bitcoin/src/tests/unit/editTransaction/isStrategyDisabled.test.ts | Unit tests for strategy disabling rule. |
| libs/coin-modules/coin-bitcoin/src/tests/unit/editTransaction/hasMinimumFunds.test.ts | Unit tests for minimum funds checks. |
| libs/coin-modules/coin-bitcoin/src/tests/unit/editTransaction/getTransactionStatus.test.ts | Unit tests for edited-tx status validation. |
| libs/coin-modules/coin-bitcoin/src/tests/unit/editTransaction/getMinEditTransactionFees.test.ts | Unit tests for min bump fee rule. |
| libs/coin-modules/coin-bitcoin/src/tests/unit/editTransaction/getEditTransactionPatch.test.ts | Unit tests for patch building + network fee bump. |
| libs/coin-modules/coin-bitcoin/.unimportedrc.json | Marks newly-added entrypoints as intentionally present. |
| libs/coin-framework/src/operation.ts | Adds isOldestBitcoinPendingOperation. |
| apps/ledger-live-mobile/src/utils/urls.tsx | Adds urls.editBitcoinTx.learnMore placeholder. |
| apps/ledger-live-mobile/src/screens/Account/ListHeaderComponent.tsx | Sorts editable pending ops by date for BTC; sequence for EVM. |
| apps/ledger-live-mobile/src/families/bitcoin/EditTransactionFlow/TransactionAlreadyValidatedError.tsx | New error screen for already-confirmed tx. |
| apps/ledger-live-mobile/src/families/bitcoin/EditTransactionFlow/MethodSelection.tsx | New BTC edit method selection screen + polling. |
| apps/ledger-live-mobile/src/families/bitcoin/EditTransactionFlow/EditTransactionSummary.tsx | New BTC edit summary screen + validation integration. |
| apps/ledger-live-mobile/src/families/bitcoin/EditTransactionFlow/EditTransactionParamList.ts | New navigation param types for BTC edit flow. |
| apps/ledger-live-mobile/src/families/bitcoin/EditTransactionFlow/EditTransactionNavigator.tsx | Adds a dedicated navigator stack for BTC edit flow. |
| apps/ledger-live-mobile/src/families/bitcoin/EditTransactionFlow/EditOperationPanel.tsx | Adds feature-gated CTA panel for BTC edit. |
| apps/ledger-live-mobile/src/families/bitcoin/EditOperationPanel.tsx | Exposes BTC edit panel for sync-families dispatch. |
| apps/ledger-live-mobile/src/const/navigation.ts | Adds BTC edit screen + navigator names. |
| apps/ledger-live-mobile/src/components/RootNavigator/types/BaseNavigator.ts | Wires BTC edit navigator type into BaseNavigator stack params. |
| apps/ledger-live-mobile/src/components/RootNavigator/BaseNavigator.tsx | Registers BTC edit navigator in the root stack. |
| apps/ledger-live-mobile/src/components/EditOperationCard.tsx | Supports routing to BTC edit flow (in addition to EVM). |
| apps/ledger-live-mobile/package.json | Adds @ledgerhq/coin-bitcoin dependency. |
| .changeset/slimy-cobras-study.md | Changeset for coin-bitcoin/live-common/live-env minors. |
| .changeset/dull-knives-live.md | Changeset for types-live/live-mobile/live-common/coin-framework minors. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (1)
libs/coin-modules/coin-bitcoin/src/prepareTransaction.ts:88
- In prepareTransaction, the early return only compares excludeUTXOs array length. If the set/content of exclusions changes (same length, different items/order), this returns the old transaction and never updates excludeUTXOs, so coin selection can still use unfetchable/stale UTXOs. Consider doing a deep equality check (e.g., compare normalized "hash-outputIndex" sets) instead of only length.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
apps/ledger-live-mobile/src/families/bitcoin/EditTransactionFlow/MethodSelection.tsx
Show resolved
Hide resolved
apps/ledger-live-mobile/src/families/bitcoin/EditTransactionFlow/EditOperationPanel.tsx
Outdated
Show resolved
Hide resolved
apps/ledger-live-mobile/src/families/bitcoin/EditTransactionFlow/MethodSelection.tsx
Show resolved
Hide resolved
libs/coin-modules/coin-bitcoin/src/editTransaction/isTransactionConfirmed.ts
Show resolved
Hide resolved
apps/ledger-live-mobile/src/screens/Account/ListHeaderComponent.tsx
Outdated
Show resolved
Hide resolved
39a0418 to
9c12c70
Compare
98edb32 to
be33bfa
Compare
|
c5191f2 to
eb972a2
Compare
be33bfa to
74cfcf4
Compare
libs/coin-modules/coin-bitcoin/src/wallet-btc/pickingstrategies/DeepFirst.ts
Outdated
Show resolved
Hide resolved
d56cb7b to
87cfb66
Compare
906738d to
af8d6ee
Compare
libs/coin-modules/coin-bitcoin/src/wallet-btc/pickingstrategies/DeepFirst.ts
Outdated
Show resolved
Hide resolved
| const setTransactionHasBeenValidatedCallback = async () => { | ||
| const walletAccount = (mainAccount as BitcoinAccount).bitcoinResources?.walletAccount; | ||
| if (!walletAccount) return; | ||
| const hasBeenConfirmed = await isTransactionConfirmed(walletAccount, operation.hash); | ||
| if (hasBeenConfirmed) { | ||
| clearInterval(intervalId); | ||
| setTransactionHasBeenValidated(true); | ||
| } | ||
| }; | ||
|
|
||
| setTransactionHasBeenValidatedCallback(); | ||
| const intervalId = setInterval( |
There was a problem hiding this comment.
The variable intervalId is referenced on line 137 before it's declared on line 143. This creates a Temporal Dead Zone (TDZ) error in JavaScript when setTransactionHasBeenValidatedCallback is called immediately on line 142. The callback will try to access intervalId in the clearInterval call, but the variable doesn't exist yet, causing a ReferenceError if the transaction is already confirmed. Declare intervalId with let before defining the callback function.
9532f21 to
8b3f260
Compare
b603665 to
51f6182
Compare
apps/ledger-live-mobile/src/families/bitcoin/EditTransactionFlow/MethodSelection.tsx
Show resolved
Hide resolved
apps/ledger-live-desktop/src/renderer/families/bitcoin/EditTransaction/Body.tsx
Outdated
Show resolved
Hide resolved
82531ff to
9bb0f4b
Compare
51f6182 to
4ec3841
Compare
4ec3841 to
44a98ee
Compare
apps/ledger-live-desktop/src/renderer/families/bitcoin/EditTransaction/Body.tsx
Show resolved
Hide resolved
apps/ledger-live-desktop/src/renderer/drawers/OperationDetails/index.tsx
Show resolved
Hide resolved
apps/ledger-live-desktop/src/renderer/components/OperationsList/EditOperationPanel.tsx
Show resolved
Hide resolved
apps/ledger-live-mobile/src/screens/Account/__tests__/ListHeaderComponent.test.tsx
Show resolved
Hide resolved
apps/ledger-live-mobile/src/families/bitcoin/EditTransactionFlow/MethodSelection.tsx
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 90 out of 92 changed files in this pull request and generated 10 comments.
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (1)
libs/coin-modules/coin-bitcoin/src/wallet-btc/xpub.ts:68
BuildTxParams,BuildTxSelection, andTransactionare declared/imported twice in this file. These redeclarations will fail compilation; remove the duplicated blocks and keep a single source of truth for each type/import.
apps/ledger-live-mobile/src/families/bitcoin/EditTransactionFlow/MethodSelection.tsx
Show resolved
Hide resolved
...er-live-mobile/src/families/bitcoin/EditTransactionFlow/TransactionAlreadyValidatedError.tsx
Show resolved
Hide resolved
apps/ledger-live-mobile/src/families/bitcoin/EditTransactionFlow/MethodSelection.tsx
Show resolved
Hide resolved
apps/ledger-live-mobile/src/screens/Account/__tests__/ListHeaderComponent.test.tsx
Show resolved
Hide resolved
| * @param date The date of the transaction to edit | ||
| * @returns true if the date corresponds to the oldest pending operation | ||
| */ | ||
| export const isOldestBitcoinPendingOperation = (account: Account, date: Date): boolean => { |
There was a problem hiding this comment.
Maybe we should rename the function above isOldestEvmPendingOperation for better differentiation then
apps/ledger-live-mobile/src/families/bitcoin/EditTransactionFlow/MethodSelection.tsx
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 18 changed files in this pull request and generated no new comments.
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
You can also share your feedback on Copilot code review. Take the survey.
|




✅ Checklist
npx changesetwas attached.📝 Description
Front to speedup/cancel Bitcoin transaction, the same way we do for Ethereum
❓ Context
🧐 Checklist for the PR Reviewers