feat: add trezor send - #688

Merged
ovitrif merged 3 commits into
masterfrom
feat/trezor-send
Sep 1, 2026
Merged

feat: add trezor send#688
ovitrif merged 3 commits into
masterfrom
feat/trezor-send

Conversation

@ben-kaufman

@ben-kaufmanben-kaufman commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Description

This PR:

  1. Adds paired Trezor wallets as funding sources throughout the normal on-chain Send flow, including scanner, paste, manual entry, contacts, fee selection, confirmation, signing, broadcasting, and success handling.
  2. Hardens Trezor session recovery and preserves hardware-wallet activity and contact metadata while wallet snapshots catch up.

The Send UI follows the Bitkit Wallet design.

Receive support will follow in a separate stacked PR.

Linked Issues/Tasks

Fixes#706

Screenshot / Video

QA Notes

Manual Tests

  • 1. Trezor wallet → Send → enter a Bitcoin address and amount → Continue: the button loads once, Confirm opens, and repeated taps do not duplicate preparation.
  • 2. Send Confirm → choose Trezor → Sign With Device → approve on Trezor: the transaction broadcasts and Success shows the hardware-wallet activity.
  • 3. Trezor passphrase wallet → Send → enter passphrase: the paired account reconnects and the operation resumes.
  • 4. Trezor-funded Send → scan a Lightning or LNURL request: Bitkit explains that a Bitcoin address is required.
  • 5.regression: Send → switch between Savings, Spending, and Trezor: available balance and fee-aware maximum update for each source.
  • 6.regression: cancel or disconnect during signing → retry: Bitkit reconnects without creating or broadcasting a duplicate transaction.

Automated Checks

  • Unit tests added or extended in HwFundingSignerTests.swift and TrezorSessionFailureTests.swift: cover source coordination, timeouts, stale-session retry, retained signed transactions, and failure classification.
  • Unit tests extended in HwSnapshotMergeTests.swift: cover pending sent activity and contact preservation during watcher reconciliation.
  • Unit tests extended in ShopPaymentRequestTests.swift: cover hardware-wallet on-chain-only scan handling.
  • Focused iOS unit tests passed.
  • All changed Swift files pass SwiftFormat; translation validation and diff checks pass.

@greptile-apps

Copy link
Copy Markdown

Greptile Summary

This PR integrates paired Trezor wallets into normal on-chain send and receive flows and hardens session recovery and hardware activity reconciliation.

  • Adds hardware-wallet funding-source selection, fee preparation, device signing, broadcast retry, and wallet-scoped success lookup.
  • Adds Trezor receive-address display, copying, QR presentation, passphrase reconnection, and on-device verification.
  • Serializes connection operations and preserves pending hardware activity and contact metadata during watcher reconciliation.

Confidence Score: 3/5

The PR should not merge until pending hardware activity survives process recreation and timeout cleanup can no longer tear down a retry’s newly established Trezor session.

A restart can remove a just-broadcast hardware activity before Electrum observes it, while an immediate retry after a device timeout can race delayed stale-session cleanup and lose the replacement connection.

Files Needing Attention: Bitkit/Services/CoreService.swift, Bitkit/Services/HwSnapshotMerge.swift, Bitkit/ViewModels/HwFundingSigner.swift, Bitkit/Managers/TrezorManager.swift

Important Files Changed

FilenameOverview
Bitkit/ViewModels/HwFundingSigner.swiftGeneralizes hardware signing for ordinary sends and adds non-structural timeouts, but asynchronous stale-session cleanup can race an immediate retry.
Bitkit/Managers/TrezorManager.swiftSerializes connection operations and retries stale sessions, while the separate reset path remains able to clear newer connection state.
Bitkit/Services/CoreService.swiftProtects newly broadcast hardware activity from watcher pruning, but stores the protection only in process memory.
Bitkit/Services/HwSnapshotMerge.swiftPreserves pending sends and contact metadata when supplied the pending-ID set, but intentionally prunes unprotected pending rows.
Bitkit/Managers/HwWalletManager.swiftAdds hardware receive-address derivation and verification plus funding-source balance support.
Bitkit/Views/Wallets/Send/SendSheet.swiftIntegrates hardware source selection and signing routes throughout the existing send lifecycle.
Bitkit/Views/Wallets/Receive/ReceiveQr.swiftAdds Trezor receive QR, copy, device verification, and passphrase recovery states.

Sequence Diagram

sequenceDiagram
participant User
participant Send as Send Flow
participant HW as Hardware Wallet Manager
participant Trezor
participant Electrum
participant Activity
User->>Send: Select Trezor funding source
Send->>HW: Compose payment and estimate fee
HW->>Electrum: Load account and UTXOs
Electrum-->>HW: Account state
Send->>HW: Sign and broadcast
HW->>Trezor: Verify identity and sign PSBT
Trezor-->>HW: Signed transaction
HW->>Electrum: Broadcast transaction
Electrum-->>HW: Transaction ID
Send->>Activity: Persist wallet-scoped sent activity
Send-->>User: Show success
Loading

Reviews (1): Last reviewed commit: "feat: add trezor send and receive" | Re-trigger Greptile

Comment threadBitkit/Services/CoreService.swift Outdated
Comment threadBitkit/ViewModels/HwFundingSigner.swift
@ben-kaufmanben-kaufman changed the title feat: add trezor send and receivefeat: add trezor sendAug 27, 2026
@piotr-iohk

Copy link
Copy Markdown
Collaborator

Testing... (note: there are conflicts on this branch)

@piotr-iohkpiotr-iohk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Quick pass on device: standard HW send, passphrase HW send, and cancel-during-sign all worked. Not a full review — branch is conflicting, so not approving.

Nit: pending sent rows already use the hourglass, but it's orange even for HW. That branch runs before the blue HW tint, so a pending Trezor send is orange in the list and blue once it's no longer in that pending-sent rule. Figma has the hourglass (this and this) in brand/orange. For HW it would be more consistent to keep the hourglass and tint it blue, same as the rest of the hardware chrome.

@ovitrifovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nothing would fail if HwSendCoordinator stopped reusing a signed payment after a flaky broadcast, or ran beforeBroadcast again on retry.

Comment threadBitkit/ViewModels/HwFundingSigner.swift
@ovitrifovitrif added this to the 2.5.0 milestone Aug 28, 2026

@piotr-iohkpiotr-iohk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

Conflicts are gone. Re-tested on device with a Trezor 7: standard HW send, passphrase HW send, and cancel-during-sign still work. Pending HW hourglass is blue now.

@ovitrif

ovitrif commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Pls ensure UI is ok before merging; or if not, create an issue to list what's to polish, so we know what remaining work is there.

OK UI means either:

  • matches Figma design (reused existing UI components win here, they are the translation of Figma designs to practical implementation)
  • matches Android if Figma designs are missing for some specific states/components, if Android is "ahead" in terms of polishing, or vice-versa
  • anything outside of the 2 should have an UI implementation that conforms to the UI design language of the app

Merging without enforcing UI polishing is ok-ish if author is not 100% available for Bitkit team, but going backwards over merged changes to figure out which UI implementation is done vs what needs polishing is quite a lot of work for one, and can be distributed.

@ovitrifovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

utACK

@ovitrif

ovitrif commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Pls ensure UI is ok before merging; or if not, create an issue to list what's to polish, so we know what remaining work is there.

OK UI means either:

  • matches Figma design (reused existing UI components win here, they are the translation of Figma designs to practical implementation)
  • matches Android if Figma designs are missing for some specific states/components, if Android is "ahead" in terms of polishing, or vice-versa
  • anything outside of the 2 should have an UI implementation that conforms to the UI design language of the app

Merging without enforcing UI polishing is ok-ish if author is not 100% available for Bitkit team, but going backwards over merged changes to figure out which UI implementation is done vs what needs polishing is quite a lot of work for one, and can be distributed.

I'm trying a new ai skill I'm building on this, the expected output is an issue, then we can merge this PR.

@ovitrifovitrif mentioned this pull request Aug 31, 2026
@ovitrif

Copy link
Copy Markdown
Collaborator

UI leftover is in #696. This PR can merge.

@ovitrif

Copy link
Copy Markdown
Collaborator

@ben-kaufman pls update branch w. base, so we can merge 🎉

@ovitrif
ovitrif enabled auto-merge August 31, 2026 18:21
@ovitrifovitrif mentioned this pull request Aug 31, 2026
@ovitrif
ovitrif merged commit 004a108 into masterSep 1, 2026
23 of 27 checks passed
@ovitrif
ovitrif deleted the feat/trezor-send branch September 1, 2026 08:43
Sign up for freeto 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.

Send from hardware wallet

3 participants

@ben-kaufman@piotr-iohk@ovitrif
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat: add trezor send - #688

Merged
ovitrif merged 3 commits into
masterfrom
feat/trezor-send
Sep 1, 2026
Merged

feat: add trezor send#688
ovitrif merged 3 commits into
masterfrom
feat/trezor-send

Conversation

@ben-kaufman

@ben-kaufmanben-kaufman commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Description

This PR:

  1. Adds paired Trezor wallets as funding sources throughout the normal on-chain Send flow, including scanner, paste, manual entry, contacts, fee selection, confirmation, signing, broadcasting, and success handling.
  2. Hardens Trezor session recovery and preserves hardware-wallet activity and contact metadata while wallet snapshots catch up.

The Send UI follows the Bitkit Wallet design.

Receive support will follow in a separate stacked PR.

Linked Issues/Tasks

Fixes#706

Screenshot / Video

QA Notes

Manual Tests

  • 1. Trezor wallet → Send → enter a Bitcoin address and amount → Continue: the button loads once, Confirm opens, and repeated taps do not duplicate preparation.
  • 2. Send Confirm → choose Trezor → Sign With Device → approve on Trezor: the transaction broadcasts and Success shows the hardware-wallet activity.
  • 3. Trezor passphrase wallet → Send → enter passphrase: the paired account reconnects and the operation resumes.
  • 4. Trezor-funded Send → scan a Lightning or LNURL request: Bitkit explains that a Bitcoin address is required.
  • 5.regression: Send → switch between Savings, Spending, and Trezor: available balance and fee-aware maximum update for each source.
  • 6.regression: cancel or disconnect during signing → retry: Bitkit reconnects without creating or broadcasting a duplicate transaction.

Automated Checks

  • Unit tests added or extended in HwFundingSignerTests.swift and TrezorSessionFailureTests.swift: cover source coordination, timeouts, stale-session retry, retained signed transactions, and failure classification.
  • Unit tests extended in HwSnapshotMergeTests.swift: cover pending sent activity and contact preservation during watcher reconciliation.
  • Unit tests extended in ShopPaymentRequestTests.swift: cover hardware-wallet on-chain-only scan handling.
  • Focused iOS unit tests passed.
  • All changed Swift files pass SwiftFormat; translation validation and diff checks pass.

@greptile-apps

Copy link
Copy Markdown

Greptile Summary

This PR integrates paired Trezor wallets into normal on-chain send and receive flows and hardens session recovery and hardware activity reconciliation.

  • Adds hardware-wallet funding-source selection, fee preparation, device signing, broadcast retry, and wallet-scoped success lookup.
  • Adds Trezor receive-address display, copying, QR presentation, passphrase reconnection, and on-device verification.
  • Serializes connection operations and preserves pending hardware activity and contact metadata during watcher reconciliation.

Confidence Score: 3/5

The PR should not merge until pending hardware activity survives process recreation and timeout cleanup can no longer tear down a retry’s newly established Trezor session.

A restart can remove a just-broadcast hardware activity before Electrum observes it, while an immediate retry after a device timeout can race delayed stale-session cleanup and lose the replacement connection.

Files Needing Attention: Bitkit/Services/CoreService.swift, Bitkit/Services/HwSnapshotMerge.swift, Bitkit/ViewModels/HwFundingSigner.swift, Bitkit/Managers/TrezorManager.swift

Important Files Changed

FilenameOverview
Bitkit/ViewModels/HwFundingSigner.swiftGeneralizes hardware signing for ordinary sends and adds non-structural timeouts, but asynchronous stale-session cleanup can race an immediate retry.
Bitkit/Managers/TrezorManager.swiftSerializes connection operations and retries stale sessions, while the separate reset path remains able to clear newer connection state.
Bitkit/Services/CoreService.swiftProtects newly broadcast hardware activity from watcher pruning, but stores the protection only in process memory.
Bitkit/Services/HwSnapshotMerge.swiftPreserves pending sends and contact metadata when supplied the pending-ID set, but intentionally prunes unprotected pending rows.
Bitkit/Managers/HwWalletManager.swiftAdds hardware receive-address derivation and verification plus funding-source balance support.
Bitkit/Views/Wallets/Send/SendSheet.swiftIntegrates hardware source selection and signing routes throughout the existing send lifecycle.
Bitkit/Views/Wallets/Receive/ReceiveQr.swiftAdds Trezor receive QR, copy, device verification, and passphrase recovery states.

Sequence Diagram

sequenceDiagram
participant User
participant Send as Send Flow
participant HW as Hardware Wallet Manager
participant Trezor
participant Electrum
participant Activity
User->>Send: Select Trezor funding source
Send->>HW: Compose payment and estimate fee
HW->>Electrum: Load account and UTXOs
Electrum-->>HW: Account state
Send->>HW: Sign and broadcast
HW->>Trezor: Verify identity and sign PSBT
Trezor-->>HW: Signed transaction
HW->>Electrum: Broadcast transaction
Electrum-->>HW: Transaction ID
Send->>Activity: Persist wallet-scoped sent activity
Send-->>User: Show success
Loading

Reviews (1): Last reviewed commit: "feat: add trezor send and receive" | Re-trigger Greptile

Comment threadBitkit/Services/CoreService.swift Outdated
Comment threadBitkit/ViewModels/HwFundingSigner.swift
@ben-kaufmanben-kaufman changed the title feat: add trezor send and receivefeat: add trezor sendAug 27, 2026
@piotr-iohk

Copy link
Copy Markdown
Collaborator

Testing... (note: there are conflicts on this branch)

@piotr-iohkpiotr-iohk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Quick pass on device: standard HW send, passphrase HW send, and cancel-during-sign all worked. Not a full review — branch is conflicting, so not approving.

Nit: pending sent rows already use the hourglass, but it's orange even for HW. That branch runs before the blue HW tint, so a pending Trezor send is orange in the list and blue once it's no longer in that pending-sent rule. Figma has the hourglass (this and this) in brand/orange. For HW it would be more consistent to keep the hourglass and tint it blue, same as the rest of the hardware chrome.

@ovitrifovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nothing would fail if HwSendCoordinator stopped reusing a signed payment after a flaky broadcast, or ran beforeBroadcast again on retry.

Comment threadBitkit/ViewModels/HwFundingSigner.swift
@ovitrifovitrif added this to the 2.5.0 milestone Aug 28, 2026

@piotr-iohkpiotr-iohk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

Conflicts are gone. Re-tested on device with a Trezor 7: standard HW send, passphrase HW send, and cancel-during-sign still work. Pending HW hourglass is blue now.

@ovitrif

ovitrif commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Pls ensure UI is ok before merging; or if not, create an issue to list what's to polish, so we know what remaining work is there.

OK UI means either:

  • matches Figma design (reused existing UI components win here, they are the translation of Figma designs to practical implementation)
  • matches Android if Figma designs are missing for some specific states/components, if Android is "ahead" in terms of polishing, or vice-versa
  • anything outside of the 2 should have an UI implementation that conforms to the UI design language of the app

Merging without enforcing UI polishing is ok-ish if author is not 100% available for Bitkit team, but going backwards over merged changes to figure out which UI implementation is done vs what needs polishing is quite a lot of work for one, and can be distributed.

@ovitrifovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

utACK

@ovitrif

ovitrif commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Pls ensure UI is ok before merging; or if not, create an issue to list what's to polish, so we know what remaining work is there.

OK UI means either:

  • matches Figma design (reused existing UI components win here, they are the translation of Figma designs to practical implementation)
  • matches Android if Figma designs are missing for some specific states/components, if Android is "ahead" in terms of polishing, or vice-versa
  • anything outside of the 2 should have an UI implementation that conforms to the UI design language of the app

Merging without enforcing UI polishing is ok-ish if author is not 100% available for Bitkit team, but going backwards over merged changes to figure out which UI implementation is done vs what needs polishing is quite a lot of work for one, and can be distributed.

I'm trying a new ai skill I'm building on this, the expected output is an issue, then we can merge this PR.

@ovitrifovitrif mentioned this pull request Aug 31, 2026
@ovitrif

Copy link
Copy Markdown
Collaborator

UI leftover is in #696. This PR can merge.

@ovitrif

Copy link
Copy Markdown
Collaborator

@ben-kaufman pls update branch w. base, so we can merge 🎉

@ovitrif
ovitrif enabled auto-merge August 31, 2026 18:21
@ovitrifovitrif mentioned this pull request Aug 31, 2026
@ovitrif
ovitrif merged commit 004a108 into masterSep 1, 2026
23 of 27 checks passed
@ovitrif
ovitrif deleted the feat/trezor-send branch September 1, 2026 08:43
Sign up for freeto 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.

Send from hardware wallet

3 participants

@ben-kaufman@piotr-iohk@ovitrif
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: add trezor send - #688

Merged
ovitrif merged 3 commits into
masterfrom
feat/trezor-send
Sep 1, 2026
Merged

feat: add trezor send#688
ovitrif merged 3 commits into
masterfrom
feat/trezor-send

Conversation

@ben-kaufman

@ben-kaufmanben-kaufman commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Description

This PR:

  1. Adds paired Trezor wallets as funding sources throughout the normal on-chain Send flow, including scanner, paste, manual entry, contacts, fee selection, confirmation, signing, broadcasting, and success handling.
  2. Hardens Trezor session recovery and preserves hardware-wallet activity and contact metadata while wallet snapshots catch up.

The Send UI follows the Bitkit Wallet design.

Receive support will follow in a separate stacked PR.

Linked Issues/Tasks

Fixes#706

Screenshot / Video

QA Notes

Manual Tests

  • 1. Trezor wallet → Send → enter a Bitcoin address and amount → Continue: the button loads once, Confirm opens, and repeated taps do not duplicate preparation.
  • 2. Send Confirm → choose Trezor → Sign With Device → approve on Trezor: the transaction broadcasts and Success shows the hardware-wallet activity.
  • 3. Trezor passphrase wallet → Send → enter passphrase: the paired account reconnects and the operation resumes.
  • 4. Trezor-funded Send → scan a Lightning or LNURL request: Bitkit explains that a Bitcoin address is required.
  • 5.regression: Send → switch between Savings, Spending, and Trezor: available balance and fee-aware maximum update for each source.
  • 6.regression: cancel or disconnect during signing → retry: Bitkit reconnects without creating or broadcasting a duplicate transaction.

Automated Checks

  • Unit tests added or extended in HwFundingSignerTests.swift and TrezorSessionFailureTests.swift: cover source coordination, timeouts, stale-session retry, retained signed transactions, and failure classification.
  • Unit tests extended in HwSnapshotMergeTests.swift: cover pending sent activity and contact preservation during watcher reconciliation.
  • Unit tests extended in ShopPaymentRequestTests.swift: cover hardware-wallet on-chain-only scan handling.
  • Focused iOS unit tests passed.
  • All changed Swift files pass SwiftFormat; translation validation and diff checks pass.

@greptile-apps

Copy link
Copy Markdown

Greptile Summary

This PR integrates paired Trezor wallets into normal on-chain send and receive flows and hardens session recovery and hardware activity reconciliation.

  • Adds hardware-wallet funding-source selection, fee preparation, device signing, broadcast retry, and wallet-scoped success lookup.
  • Adds Trezor receive-address display, copying, QR presentation, passphrase reconnection, and on-device verification.
  • Serializes connection operations and preserves pending hardware activity and contact metadata during watcher reconciliation.

Confidence Score: 3/5

The PR should not merge until pending hardware activity survives process recreation and timeout cleanup can no longer tear down a retry’s newly established Trezor session.

A restart can remove a just-broadcast hardware activity before Electrum observes it, while an immediate retry after a device timeout can race delayed stale-session cleanup and lose the replacement connection.

Files Needing Attention: Bitkit/Services/CoreService.swift, Bitkit/Services/HwSnapshotMerge.swift, Bitkit/ViewModels/HwFundingSigner.swift, Bitkit/Managers/TrezorManager.swift

Important Files Changed

FilenameOverview
Bitkit/ViewModels/HwFundingSigner.swiftGeneralizes hardware signing for ordinary sends and adds non-structural timeouts, but asynchronous stale-session cleanup can race an immediate retry.
Bitkit/Managers/TrezorManager.swiftSerializes connection operations and retries stale sessions, while the separate reset path remains able to clear newer connection state.
Bitkit/Services/CoreService.swiftProtects newly broadcast hardware activity from watcher pruning, but stores the protection only in process memory.
Bitkit/Services/HwSnapshotMerge.swiftPreserves pending sends and contact metadata when supplied the pending-ID set, but intentionally prunes unprotected pending rows.
Bitkit/Managers/HwWalletManager.swiftAdds hardware receive-address derivation and verification plus funding-source balance support.
Bitkit/Views/Wallets/Send/SendSheet.swiftIntegrates hardware source selection and signing routes throughout the existing send lifecycle.
Bitkit/Views/Wallets/Receive/ReceiveQr.swiftAdds Trezor receive QR, copy, device verification, and passphrase recovery states.

Sequence Diagram

sequenceDiagram
participant User
participant Send as Send Flow
participant HW as Hardware Wallet Manager
participant Trezor
participant Electrum
participant Activity
User->>Send: Select Trezor funding source
Send->>HW: Compose payment and estimate fee
HW->>Electrum: Load account and UTXOs
Electrum-->>HW: Account state
Send->>HW: Sign and broadcast
HW->>Trezor: Verify identity and sign PSBT
Trezor-->>HW: Signed transaction
HW->>Electrum: Broadcast transaction
Electrum-->>HW: Transaction ID
Send->>Activity: Persist wallet-scoped sent activity
Send-->>User: Show success
Loading

Reviews (1): Last reviewed commit: "feat: add trezor send and receive" | Re-trigger Greptile

Comment threadBitkit/Services/CoreService.swift Outdated
Comment threadBitkit/ViewModels/HwFundingSigner.swift
@ben-kaufmanben-kaufman changed the title feat: add trezor send and receivefeat: add trezor sendAug 27, 2026
@piotr-iohk

Copy link
Copy Markdown
Collaborator

Testing... (note: there are conflicts on this branch)

@piotr-iohkpiotr-iohk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Quick pass on device: standard HW send, passphrase HW send, and cancel-during-sign all worked. Not a full review — branch is conflicting, so not approving.

Nit: pending sent rows already use the hourglass, but it's orange even for HW. That branch runs before the blue HW tint, so a pending Trezor send is orange in the list and blue once it's no longer in that pending-sent rule. Figma has the hourglass (this and this) in brand/orange. For HW it would be more consistent to keep the hourglass and tint it blue, same as the rest of the hardware chrome.

@ovitrifovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nothing would fail if HwSendCoordinator stopped reusing a signed payment after a flaky broadcast, or ran beforeBroadcast again on retry.

Comment threadBitkit/ViewModels/HwFundingSigner.swift
@ovitrifovitrif added this to the 2.5.0 milestone Aug 28, 2026

@piotr-iohkpiotr-iohk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

Conflicts are gone. Re-tested on device with a Trezor 7: standard HW send, passphrase HW send, and cancel-during-sign still work. Pending HW hourglass is blue now.

@ovitrif

ovitrif commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Pls ensure UI is ok before merging; or if not, create an issue to list what's to polish, so we know what remaining work is there.

OK UI means either:

  • matches Figma design (reused existing UI components win here, they are the translation of Figma designs to practical implementation)
  • matches Android if Figma designs are missing for some specific states/components, if Android is "ahead" in terms of polishing, or vice-versa
  • anything outside of the 2 should have an UI implementation that conforms to the UI design language of the app

Merging without enforcing UI polishing is ok-ish if author is not 100% available for Bitkit team, but going backwards over merged changes to figure out which UI implementation is done vs what needs polishing is quite a lot of work for one, and can be distributed.

@ovitrifovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

utACK

@ovitrif

ovitrif commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Pls ensure UI is ok before merging; or if not, create an issue to list what's to polish, so we know what remaining work is there.

OK UI means either:

  • matches Figma design (reused existing UI components win here, they are the translation of Figma designs to practical implementation)
  • matches Android if Figma designs are missing for some specific states/components, if Android is "ahead" in terms of polishing, or vice-versa
  • anything outside of the 2 should have an UI implementation that conforms to the UI design language of the app

Merging without enforcing UI polishing is ok-ish if author is not 100% available for Bitkit team, but going backwards over merged changes to figure out which UI implementation is done vs what needs polishing is quite a lot of work for one, and can be distributed.

I'm trying a new ai skill I'm building on this, the expected output is an issue, then we can merge this PR.

@ovitrifovitrif mentioned this pull request Aug 31, 2026
@ovitrif

Copy link
Copy Markdown
Collaborator

UI leftover is in #696. This PR can merge.

@ovitrif

Copy link
Copy Markdown
Collaborator

@ben-kaufman pls update branch w. base, so we can merge 🎉

@ovitrif
ovitrif enabled auto-merge August 31, 2026 18:21
@ovitrifovitrif mentioned this pull request Aug 31, 2026
@ovitrif
ovitrif merged commit 004a108 into masterSep 1, 2026
23 of 27 checks passed
@ovitrif
ovitrif deleted the feat/trezor-send branch September 1, 2026 08:43
Sign up for freeto 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.

Send from hardware wallet

3 participants

@ben-kaufman@piotr-iohk@ovitrif
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: add trezor send - #688

Merged
ovitrif merged 3 commits into
masterfrom
feat/trezor-send
Sep 1, 2026
Merged

feat: add trezor send#688
ovitrif merged 3 commits into
masterfrom
feat/trezor-send

Conversation

@ben-kaufman

@ben-kaufmanben-kaufman commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Description

This PR:

  1. Adds paired Trezor wallets as funding sources throughout the normal on-chain Send flow, including scanner, paste, manual entry, contacts, fee selection, confirmation, signing, broadcasting, and success handling.
  2. Hardens Trezor session recovery and preserves hardware-wallet activity and contact metadata while wallet snapshots catch up.

The Send UI follows the Bitkit Wallet design.

Receive support will follow in a separate stacked PR.

Linked Issues/Tasks

Fixes#706

Screenshot / Video

QA Notes

Manual Tests

  • 1. Trezor wallet → Send → enter a Bitcoin address and amount → Continue: the button loads once, Confirm opens, and repeated taps do not duplicate preparation.
  • 2. Send Confirm → choose Trezor → Sign With Device → approve on Trezor: the transaction broadcasts and Success shows the hardware-wallet activity.
  • 3. Trezor passphrase wallet → Send → enter passphrase: the paired account reconnects and the operation resumes.
  • 4. Trezor-funded Send → scan a Lightning or LNURL request: Bitkit explains that a Bitcoin address is required.
  • 5.regression: Send → switch between Savings, Spending, and Trezor: available balance and fee-aware maximum update for each source.
  • 6.regression: cancel or disconnect during signing → retry: Bitkit reconnects without creating or broadcasting a duplicate transaction.

Automated Checks

  • Unit tests added or extended in HwFundingSignerTests.swift and TrezorSessionFailureTests.swift: cover source coordination, timeouts, stale-session retry, retained signed transactions, and failure classification.
  • Unit tests extended in HwSnapshotMergeTests.swift: cover pending sent activity and contact preservation during watcher reconciliation.
  • Unit tests extended in ShopPaymentRequestTests.swift: cover hardware-wallet on-chain-only scan handling.
  • Focused iOS unit tests passed.
  • All changed Swift files pass SwiftFormat; translation validation and diff checks pass.

@greptile-apps

Copy link
Copy Markdown

Greptile Summary

This PR integrates paired Trezor wallets into normal on-chain send and receive flows and hardens session recovery and hardware activity reconciliation.

  • Adds hardware-wallet funding-source selection, fee preparation, device signing, broadcast retry, and wallet-scoped success lookup.
  • Adds Trezor receive-address display, copying, QR presentation, passphrase reconnection, and on-device verification.
  • Serializes connection operations and preserves pending hardware activity and contact metadata during watcher reconciliation.

Confidence Score: 3/5

The PR should not merge until pending hardware activity survives process recreation and timeout cleanup can no longer tear down a retry’s newly established Trezor session.

A restart can remove a just-broadcast hardware activity before Electrum observes it, while an immediate retry after a device timeout can race delayed stale-session cleanup and lose the replacement connection.

Files Needing Attention: Bitkit/Services/CoreService.swift, Bitkit/Services/HwSnapshotMerge.swift, Bitkit/ViewModels/HwFundingSigner.swift, Bitkit/Managers/TrezorManager.swift

Important Files Changed

FilenameOverview
Bitkit/ViewModels/HwFundingSigner.swiftGeneralizes hardware signing for ordinary sends and adds non-structural timeouts, but asynchronous stale-session cleanup can race an immediate retry.
Bitkit/Managers/TrezorManager.swiftSerializes connection operations and retries stale sessions, while the separate reset path remains able to clear newer connection state.
Bitkit/Services/CoreService.swiftProtects newly broadcast hardware activity from watcher pruning, but stores the protection only in process memory.
Bitkit/Services/HwSnapshotMerge.swiftPreserves pending sends and contact metadata when supplied the pending-ID set, but intentionally prunes unprotected pending rows.
Bitkit/Managers/HwWalletManager.swiftAdds hardware receive-address derivation and verification plus funding-source balance support.
Bitkit/Views/Wallets/Send/SendSheet.swiftIntegrates hardware source selection and signing routes throughout the existing send lifecycle.
Bitkit/Views/Wallets/Receive/ReceiveQr.swiftAdds Trezor receive QR, copy, device verification, and passphrase recovery states.

Sequence Diagram

sequenceDiagram
participant User
participant Send as Send Flow
participant HW as Hardware Wallet Manager
participant Trezor
participant Electrum
participant Activity
User->>Send: Select Trezor funding source
Send->>HW: Compose payment and estimate fee
HW->>Electrum: Load account and UTXOs
Electrum-->>HW: Account state
Send->>HW: Sign and broadcast
HW->>Trezor: Verify identity and sign PSBT
Trezor-->>HW: Signed transaction
HW->>Electrum: Broadcast transaction
Electrum-->>HW: Transaction ID
Send->>Activity: Persist wallet-scoped sent activity
Send-->>User: Show success
Loading

Reviews (1): Last reviewed commit: "feat: add trezor send and receive" | Re-trigger Greptile

Comment threadBitkit/Services/CoreService.swift Outdated
Comment threadBitkit/ViewModels/HwFundingSigner.swift
@ben-kaufmanben-kaufman changed the title feat: add trezor send and receivefeat: add trezor sendAug 27, 2026
@piotr-iohk

Copy link
Copy Markdown
Collaborator

Testing... (note: there are conflicts on this branch)

@piotr-iohkpiotr-iohk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Quick pass on device: standard HW send, passphrase HW send, and cancel-during-sign all worked. Not a full review — branch is conflicting, so not approving.

Nit: pending sent rows already use the hourglass, but it's orange even for HW. That branch runs before the blue HW tint, so a pending Trezor send is orange in the list and blue once it's no longer in that pending-sent rule. Figma has the hourglass (this and this) in brand/orange. For HW it would be more consistent to keep the hourglass and tint it blue, same as the rest of the hardware chrome.

@ovitrifovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nothing would fail if HwSendCoordinator stopped reusing a signed payment after a flaky broadcast, or ran beforeBroadcast again on retry.

Comment threadBitkit/ViewModels/HwFundingSigner.swift
@ovitrifovitrif added this to the 2.5.0 milestone Aug 28, 2026

@piotr-iohkpiotr-iohk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

Conflicts are gone. Re-tested on device with a Trezor 7: standard HW send, passphrase HW send, and cancel-during-sign still work. Pending HW hourglass is blue now.

@ovitrif

ovitrif commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Pls ensure UI is ok before merging; or if not, create an issue to list what's to polish, so we know what remaining work is there.

OK UI means either:

  • matches Figma design (reused existing UI components win here, they are the translation of Figma designs to practical implementation)
  • matches Android if Figma designs are missing for some specific states/components, if Android is "ahead" in terms of polishing, or vice-versa
  • anything outside of the 2 should have an UI implementation that conforms to the UI design language of the app

Merging without enforcing UI polishing is ok-ish if author is not 100% available for Bitkit team, but going backwards over merged changes to figure out which UI implementation is done vs what needs polishing is quite a lot of work for one, and can be distributed.

@ovitrifovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

utACK

@ovitrif

ovitrif commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Pls ensure UI is ok before merging; or if not, create an issue to list what's to polish, so we know what remaining work is there.

OK UI means either:

  • matches Figma design (reused existing UI components win here, they are the translation of Figma designs to practical implementation)
  • matches Android if Figma designs are missing for some specific states/components, if Android is "ahead" in terms of polishing, or vice-versa
  • anything outside of the 2 should have an UI implementation that conforms to the UI design language of the app

Merging without enforcing UI polishing is ok-ish if author is not 100% available for Bitkit team, but going backwards over merged changes to figure out which UI implementation is done vs what needs polishing is quite a lot of work for one, and can be distributed.

I'm trying a new ai skill I'm building on this, the expected output is an issue, then we can merge this PR.

@ovitrifovitrif mentioned this pull request Aug 31, 2026
@ovitrif

Copy link
Copy Markdown
Collaborator

UI leftover is in #696. This PR can merge.

@ovitrif

Copy link
Copy Markdown
Collaborator

@ben-kaufman pls update branch w. base, so we can merge 🎉

@ovitrif
ovitrif enabled auto-merge August 31, 2026 18:21
@ovitrifovitrif mentioned this pull request Aug 31, 2026
@ovitrif
ovitrif merged commit 004a108 into masterSep 1, 2026
23 of 27 checks passed
@ovitrif
ovitrif deleted the feat/trezor-send branch September 1, 2026 08:43
Sign up for freeto 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.

Send from hardware wallet

3 participants

@ben-kaufman@piotr-iohk@ovitrif
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat: add trezor send - #688

Merged
ovitrif merged 3 commits into
masterfrom
feat/trezor-send
Sep 1, 2026
Merged

feat: add trezor send#688
ovitrif merged 3 commits into
masterfrom
feat/trezor-send

Conversation

@ben-kaufman

@ben-kaufmanben-kaufman commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Description

This PR:

  1. Adds paired Trezor wallets as funding sources throughout the normal on-chain Send flow, including scanner, paste, manual entry, contacts, fee selection, confirmation, signing, broadcasting, and success handling.
  2. Hardens Trezor session recovery and preserves hardware-wallet activity and contact metadata while wallet snapshots catch up.

The Send UI follows the Bitkit Wallet design.

Receive support will follow in a separate stacked PR.

Linked Issues/Tasks

Fixes#706

Screenshot / Video

QA Notes

Manual Tests

  • 1. Trezor wallet → Send → enter a Bitcoin address and amount → Continue: the button loads once, Confirm opens, and repeated taps do not duplicate preparation.
  • 2. Send Confirm → choose Trezor → Sign With Device → approve on Trezor: the transaction broadcasts and Success shows the hardware-wallet activity.
  • 3. Trezor passphrase wallet → Send → enter passphrase: the paired account reconnects and the operation resumes.
  • 4. Trezor-funded Send → scan a Lightning or LNURL request: Bitkit explains that a Bitcoin address is required.
  • 5.regression: Send → switch between Savings, Spending, and Trezor: available balance and fee-aware maximum update for each source.
  • 6.regression: cancel or disconnect during signing → retry: Bitkit reconnects without creating or broadcasting a duplicate transaction.

Automated Checks

  • Unit tests added or extended in HwFundingSignerTests.swift and TrezorSessionFailureTests.swift: cover source coordination, timeouts, stale-session retry, retained signed transactions, and failure classification.
  • Unit tests extended in HwSnapshotMergeTests.swift: cover pending sent activity and contact preservation during watcher reconciliation.
  • Unit tests extended in ShopPaymentRequestTests.swift: cover hardware-wallet on-chain-only scan handling.
  • Focused iOS unit tests passed.
  • All changed Swift files pass SwiftFormat; translation validation and diff checks pass.

@greptile-apps

Copy link
Copy Markdown

Greptile Summary

This PR integrates paired Trezor wallets into normal on-chain send and receive flows and hardens session recovery and hardware activity reconciliation.

  • Adds hardware-wallet funding-source selection, fee preparation, device signing, broadcast retry, and wallet-scoped success lookup.
  • Adds Trezor receive-address display, copying, QR presentation, passphrase reconnection, and on-device verification.
  • Serializes connection operations and preserves pending hardware activity and contact metadata during watcher reconciliation.

Confidence Score: 3/5

The PR should not merge until pending hardware activity survives process recreation and timeout cleanup can no longer tear down a retry’s newly established Trezor session.

A restart can remove a just-broadcast hardware activity before Electrum observes it, while an immediate retry after a device timeout can race delayed stale-session cleanup and lose the replacement connection.

Files Needing Attention: Bitkit/Services/CoreService.swift, Bitkit/Services/HwSnapshotMerge.swift, Bitkit/ViewModels/HwFundingSigner.swift, Bitkit/Managers/TrezorManager.swift

Important Files Changed

FilenameOverview
Bitkit/ViewModels/HwFundingSigner.swiftGeneralizes hardware signing for ordinary sends and adds non-structural timeouts, but asynchronous stale-session cleanup can race an immediate retry.
Bitkit/Managers/TrezorManager.swiftSerializes connection operations and retries stale sessions, while the separate reset path remains able to clear newer connection state.
Bitkit/Services/CoreService.swiftProtects newly broadcast hardware activity from watcher pruning, but stores the protection only in process memory.
Bitkit/Services/HwSnapshotMerge.swiftPreserves pending sends and contact metadata when supplied the pending-ID set, but intentionally prunes unprotected pending rows.
Bitkit/Managers/HwWalletManager.swiftAdds hardware receive-address derivation and verification plus funding-source balance support.
Bitkit/Views/Wallets/Send/SendSheet.swiftIntegrates hardware source selection and signing routes throughout the existing send lifecycle.
Bitkit/Views/Wallets/Receive/ReceiveQr.swiftAdds Trezor receive QR, copy, device verification, and passphrase recovery states.

Sequence Diagram

sequenceDiagram
participant User
participant Send as Send Flow
participant HW as Hardware Wallet Manager
participant Trezor
participant Electrum
participant Activity
User->>Send: Select Trezor funding source
Send->>HW: Compose payment and estimate fee
HW->>Electrum: Load account and UTXOs
Electrum-->>HW: Account state
Send->>HW: Sign and broadcast
HW->>Trezor: Verify identity and sign PSBT
Trezor-->>HW: Signed transaction
HW->>Electrum: Broadcast transaction
Electrum-->>HW: Transaction ID
Send->>Activity: Persist wallet-scoped sent activity
Send-->>User: Show success
Loading

Reviews (1): Last reviewed commit: "feat: add trezor send and receive" | Re-trigger Greptile

Comment threadBitkit/Services/CoreService.swift Outdated
Comment threadBitkit/ViewModels/HwFundingSigner.swift
@ben-kaufmanben-kaufman changed the title feat: add trezor send and receivefeat: add trezor sendAug 27, 2026
@piotr-iohk

Copy link
Copy Markdown
Collaborator

Testing... (note: there are conflicts on this branch)

@piotr-iohkpiotr-iohk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Quick pass on device: standard HW send, passphrase HW send, and cancel-during-sign all worked. Not a full review — branch is conflicting, so not approving.

Nit: pending sent rows already use the hourglass, but it's orange even for HW. That branch runs before the blue HW tint, so a pending Trezor send is orange in the list and blue once it's no longer in that pending-sent rule. Figma has the hourglass (this and this) in brand/orange. For HW it would be more consistent to keep the hourglass and tint it blue, same as the rest of the hardware chrome.

@ovitrifovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nothing would fail if HwSendCoordinator stopped reusing a signed payment after a flaky broadcast, or ran beforeBroadcast again on retry.

Comment threadBitkit/ViewModels/HwFundingSigner.swift
@ovitrifovitrif added this to the 2.5.0 milestone Aug 28, 2026

@piotr-iohkpiotr-iohk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

Conflicts are gone. Re-tested on device with a Trezor 7: standard HW send, passphrase HW send, and cancel-during-sign still work. Pending HW hourglass is blue now.

@ovitrif

ovitrif commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Pls ensure UI is ok before merging; or if not, create an issue to list what's to polish, so we know what remaining work is there.

OK UI means either:

  • matches Figma design (reused existing UI components win here, they are the translation of Figma designs to practical implementation)
  • matches Android if Figma designs are missing for some specific states/components, if Android is "ahead" in terms of polishing, or vice-versa
  • anything outside of the 2 should have an UI implementation that conforms to the UI design language of the app

Merging without enforcing UI polishing is ok-ish if author is not 100% available for Bitkit team, but going backwards over merged changes to figure out which UI implementation is done vs what needs polishing is quite a lot of work for one, and can be distributed.

@ovitrifovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

utACK

@ovitrif

ovitrif commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Pls ensure UI is ok before merging; or if not, create an issue to list what's to polish, so we know what remaining work is there.

OK UI means either:

  • matches Figma design (reused existing UI components win here, they are the translation of Figma designs to practical implementation)
  • matches Android if Figma designs are missing for some specific states/components, if Android is "ahead" in terms of polishing, or vice-versa
  • anything outside of the 2 should have an UI implementation that conforms to the UI design language of the app

Merging without enforcing UI polishing is ok-ish if author is not 100% available for Bitkit team, but going backwards over merged changes to figure out which UI implementation is done vs what needs polishing is quite a lot of work for one, and can be distributed.

I'm trying a new ai skill I'm building on this, the expected output is an issue, then we can merge this PR.

@ovitrifovitrif mentioned this pull request Aug 31, 2026
@ovitrif

Copy link
Copy Markdown
Collaborator

UI leftover is in #696. This PR can merge.

@ovitrif

Copy link
Copy Markdown
Collaborator

@ben-kaufman pls update branch w. base, so we can merge 🎉

@ovitrif
ovitrif enabled auto-merge August 31, 2026 18:21
@ovitrifovitrif mentioned this pull request Aug 31, 2026
@ovitrif
ovitrif merged commit 004a108 into masterSep 1, 2026
23 of 27 checks passed
@ovitrif
ovitrif deleted the feat/trezor-send branch September 1, 2026 08:43
Sign up for freeto 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.

Send from hardware wallet

3 participants

@ben-kaufman@piotr-iohk@ovitrif
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: add trezor send - #688

Merged
ovitrif merged 3 commits into
masterfrom
feat/trezor-send
Sep 1, 2026
Merged

feat: add trezor send#688
ovitrif merged 3 commits into
masterfrom
feat/trezor-send

Conversation

@ben-kaufman

@ben-kaufmanben-kaufman commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Description

This PR:

  1. Adds paired Trezor wallets as funding sources throughout the normal on-chain Send flow, including scanner, paste, manual entry, contacts, fee selection, confirmation, signing, broadcasting, and success handling.
  2. Hardens Trezor session recovery and preserves hardware-wallet activity and contact metadata while wallet snapshots catch up.

The Send UI follows the Bitkit Wallet design.

Receive support will follow in a separate stacked PR.

Linked Issues/Tasks

Fixes#706

Screenshot / Video

QA Notes

Manual Tests

  • 1. Trezor wallet → Send → enter a Bitcoin address and amount → Continue: the button loads once, Confirm opens, and repeated taps do not duplicate preparation.
  • 2. Send Confirm → choose Trezor → Sign With Device → approve on Trezor: the transaction broadcasts and Success shows the hardware-wallet activity.
  • 3. Trezor passphrase wallet → Send → enter passphrase: the paired account reconnects and the operation resumes.
  • 4. Trezor-funded Send → scan a Lightning or LNURL request: Bitkit explains that a Bitcoin address is required.
  • 5.regression: Send → switch between Savings, Spending, and Trezor: available balance and fee-aware maximum update for each source.
  • 6.regression: cancel or disconnect during signing → retry: Bitkit reconnects without creating or broadcasting a duplicate transaction.

Automated Checks

  • Unit tests added or extended in HwFundingSignerTests.swift and TrezorSessionFailureTests.swift: cover source coordination, timeouts, stale-session retry, retained signed transactions, and failure classification.
  • Unit tests extended in HwSnapshotMergeTests.swift: cover pending sent activity and contact preservation during watcher reconciliation.
  • Unit tests extended in ShopPaymentRequestTests.swift: cover hardware-wallet on-chain-only scan handling.
  • Focused iOS unit tests passed.
  • All changed Swift files pass SwiftFormat; translation validation and diff checks pass.

@greptile-apps

Copy link
Copy Markdown

Greptile Summary

This PR integrates paired Trezor wallets into normal on-chain send and receive flows and hardens session recovery and hardware activity reconciliation.

  • Adds hardware-wallet funding-source selection, fee preparation, device signing, broadcast retry, and wallet-scoped success lookup.
  • Adds Trezor receive-address display, copying, QR presentation, passphrase reconnection, and on-device verification.
  • Serializes connection operations and preserves pending hardware activity and contact metadata during watcher reconciliation.

Confidence Score: 3/5

The PR should not merge until pending hardware activity survives process recreation and timeout cleanup can no longer tear down a retry’s newly established Trezor session.

A restart can remove a just-broadcast hardware activity before Electrum observes it, while an immediate retry after a device timeout can race delayed stale-session cleanup and lose the replacement connection.

Files Needing Attention: Bitkit/Services/CoreService.swift, Bitkit/Services/HwSnapshotMerge.swift, Bitkit/ViewModels/HwFundingSigner.swift, Bitkit/Managers/TrezorManager.swift

Important Files Changed

FilenameOverview
Bitkit/ViewModels/HwFundingSigner.swiftGeneralizes hardware signing for ordinary sends and adds non-structural timeouts, but asynchronous stale-session cleanup can race an immediate retry.
Bitkit/Managers/TrezorManager.swiftSerializes connection operations and retries stale sessions, while the separate reset path remains able to clear newer connection state.
Bitkit/Services/CoreService.swiftProtects newly broadcast hardware activity from watcher pruning, but stores the protection only in process memory.
Bitkit/Services/HwSnapshotMerge.swiftPreserves pending sends and contact metadata when supplied the pending-ID set, but intentionally prunes unprotected pending rows.
Bitkit/Managers/HwWalletManager.swiftAdds hardware receive-address derivation and verification plus funding-source balance support.
Bitkit/Views/Wallets/Send/SendSheet.swiftIntegrates hardware source selection and signing routes throughout the existing send lifecycle.
Bitkit/Views/Wallets/Receive/ReceiveQr.swiftAdds Trezor receive QR, copy, device verification, and passphrase recovery states.

Sequence Diagram

sequenceDiagram
participant User
participant Send as Send Flow
participant HW as Hardware Wallet Manager
participant Trezor
participant Electrum
participant Activity
User->>Send: Select Trezor funding source
Send->>HW: Compose payment and estimate fee
HW->>Electrum: Load account and UTXOs
Electrum-->>HW: Account state
Send->>HW: Sign and broadcast
HW->>Trezor: Verify identity and sign PSBT
Trezor-->>HW: Signed transaction
HW->>Electrum: Broadcast transaction
Electrum-->>HW: Transaction ID
Send->>Activity: Persist wallet-scoped sent activity
Send-->>User: Show success
Loading

Reviews (1): Last reviewed commit: "feat: add trezor send and receive" | Re-trigger Greptile

Comment threadBitkit/Services/CoreService.swift Outdated
Comment threadBitkit/ViewModels/HwFundingSigner.swift
@ben-kaufmanben-kaufman changed the title feat: add trezor send and receivefeat: add trezor sendAug 27, 2026
@piotr-iohk

Copy link
Copy Markdown
Collaborator

Testing... (note: there are conflicts on this branch)

@piotr-iohkpiotr-iohk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Quick pass on device: standard HW send, passphrase HW send, and cancel-during-sign all worked. Not a full review — branch is conflicting, so not approving.

Nit: pending sent rows already use the hourglass, but it's orange even for HW. That branch runs before the blue HW tint, so a pending Trezor send is orange in the list and blue once it's no longer in that pending-sent rule. Figma has the hourglass (this and this) in brand/orange. For HW it would be more consistent to keep the hourglass and tint it blue, same as the rest of the hardware chrome.

@ovitrifovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nothing would fail if HwSendCoordinator stopped reusing a signed payment after a flaky broadcast, or ran beforeBroadcast again on retry.

Comment threadBitkit/ViewModels/HwFundingSigner.swift
@ovitrifovitrif added this to the 2.5.0 milestone Aug 28, 2026

@piotr-iohkpiotr-iohk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

Conflicts are gone. Re-tested on device with a Trezor 7: standard HW send, passphrase HW send, and cancel-during-sign still work. Pending HW hourglass is blue now.

@ovitrif

ovitrif commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Pls ensure UI is ok before merging; or if not, create an issue to list what's to polish, so we know what remaining work is there.

OK UI means either:

  • matches Figma design (reused existing UI components win here, they are the translation of Figma designs to practical implementation)
  • matches Android if Figma designs are missing for some specific states/components, if Android is "ahead" in terms of polishing, or vice-versa
  • anything outside of the 2 should have an UI implementation that conforms to the UI design language of the app

Merging without enforcing UI polishing is ok-ish if author is not 100% available for Bitkit team, but going backwards over merged changes to figure out which UI implementation is done vs what needs polishing is quite a lot of work for one, and can be distributed.

@ovitrifovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

utACK

@ovitrif

ovitrif commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Pls ensure UI is ok before merging; or if not, create an issue to list what's to polish, so we know what remaining work is there.

OK UI means either:

  • matches Figma design (reused existing UI components win here, they are the translation of Figma designs to practical implementation)
  • matches Android if Figma designs are missing for some specific states/components, if Android is "ahead" in terms of polishing, or vice-versa
  • anything outside of the 2 should have an UI implementation that conforms to the UI design language of the app

Merging without enforcing UI polishing is ok-ish if author is not 100% available for Bitkit team, but going backwards over merged changes to figure out which UI implementation is done vs what needs polishing is quite a lot of work for one, and can be distributed.

I'm trying a new ai skill I'm building on this, the expected output is an issue, then we can merge this PR.

@ovitrifovitrif mentioned this pull request Aug 31, 2026
@ovitrif

Copy link
Copy Markdown
Collaborator

UI leftover is in #696. This PR can merge.

@ovitrif

Copy link
Copy Markdown
Collaborator

@ben-kaufman pls update branch w. base, so we can merge 🎉

@ovitrif
ovitrif enabled auto-merge August 31, 2026 18:21
@ovitrifovitrif mentioned this pull request Aug 31, 2026
@ovitrif
ovitrif merged commit 004a108 into masterSep 1, 2026
23 of 27 checks passed
@ovitrif
ovitrif deleted the feat/trezor-send branch September 1, 2026 08:43
Sign up for freeto 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.

Send from hardware wallet

3 participants

@ben-kaufman@piotr-iohk@ovitrif
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: add trezor send - #688

Merged
ovitrif merged 3 commits into
masterfrom
feat/trezor-send
Sep 1, 2026
Merged

feat: add trezor send#688
ovitrif merged 3 commits into
masterfrom
feat/trezor-send

Conversation

@ben-kaufman

@ben-kaufmanben-kaufman commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Description

This PR:

  1. Adds paired Trezor wallets as funding sources throughout the normal on-chain Send flow, including scanner, paste, manual entry, contacts, fee selection, confirmation, signing, broadcasting, and success handling.
  2. Hardens Trezor session recovery and preserves hardware-wallet activity and contact metadata while wallet snapshots catch up.

The Send UI follows the Bitkit Wallet design.

Receive support will follow in a separate stacked PR.

Linked Issues/Tasks

Fixes#706

Screenshot / Video

QA Notes

Manual Tests

  • 1. Trezor wallet → Send → enter a Bitcoin address and amount → Continue: the button loads once, Confirm opens, and repeated taps do not duplicate preparation.
  • 2. Send Confirm → choose Trezor → Sign With Device → approve on Trezor: the transaction broadcasts and Success shows the hardware-wallet activity.
  • 3. Trezor passphrase wallet → Send → enter passphrase: the paired account reconnects and the operation resumes.
  • 4. Trezor-funded Send → scan a Lightning or LNURL request: Bitkit explains that a Bitcoin address is required.
  • 5.regression: Send → switch between Savings, Spending, and Trezor: available balance and fee-aware maximum update for each source.
  • 6.regression: cancel or disconnect during signing → retry: Bitkit reconnects without creating or broadcasting a duplicate transaction.

Automated Checks

  • Unit tests added or extended in HwFundingSignerTests.swift and TrezorSessionFailureTests.swift: cover source coordination, timeouts, stale-session retry, retained signed transactions, and failure classification.
  • Unit tests extended in HwSnapshotMergeTests.swift: cover pending sent activity and contact preservation during watcher reconciliation.
  • Unit tests extended in ShopPaymentRequestTests.swift: cover hardware-wallet on-chain-only scan handling.
  • Focused iOS unit tests passed.
  • All changed Swift files pass SwiftFormat; translation validation and diff checks pass.

@greptile-apps

Copy link
Copy Markdown

Greptile Summary

This PR integrates paired Trezor wallets into normal on-chain send and receive flows and hardens session recovery and hardware activity reconciliation.

  • Adds hardware-wallet funding-source selection, fee preparation, device signing, broadcast retry, and wallet-scoped success lookup.
  • Adds Trezor receive-address display, copying, QR presentation, passphrase reconnection, and on-device verification.
  • Serializes connection operations and preserves pending hardware activity and contact metadata during watcher reconciliation.

Confidence Score: 3/5

The PR should not merge until pending hardware activity survives process recreation and timeout cleanup can no longer tear down a retry’s newly established Trezor session.

A restart can remove a just-broadcast hardware activity before Electrum observes it, while an immediate retry after a device timeout can race delayed stale-session cleanup and lose the replacement connection.

Files Needing Attention: Bitkit/Services/CoreService.swift, Bitkit/Services/HwSnapshotMerge.swift, Bitkit/ViewModels/HwFundingSigner.swift, Bitkit/Managers/TrezorManager.swift

Important Files Changed

FilenameOverview
Bitkit/ViewModels/HwFundingSigner.swiftGeneralizes hardware signing for ordinary sends and adds non-structural timeouts, but asynchronous stale-session cleanup can race an immediate retry.
Bitkit/Managers/TrezorManager.swiftSerializes connection operations and retries stale sessions, while the separate reset path remains able to clear newer connection state.
Bitkit/Services/CoreService.swiftProtects newly broadcast hardware activity from watcher pruning, but stores the protection only in process memory.
Bitkit/Services/HwSnapshotMerge.swiftPreserves pending sends and contact metadata when supplied the pending-ID set, but intentionally prunes unprotected pending rows.
Bitkit/Managers/HwWalletManager.swiftAdds hardware receive-address derivation and verification plus funding-source balance support.
Bitkit/Views/Wallets/Send/SendSheet.swiftIntegrates hardware source selection and signing routes throughout the existing send lifecycle.
Bitkit/Views/Wallets/Receive/ReceiveQr.swiftAdds Trezor receive QR, copy, device verification, and passphrase recovery states.

Sequence Diagram

sequenceDiagram
participant User
participant Send as Send Flow
participant HW as Hardware Wallet Manager
participant Trezor
participant Electrum
participant Activity
User->>Send: Select Trezor funding source
Send->>HW: Compose payment and estimate fee
HW->>Electrum: Load account and UTXOs
Electrum-->>HW: Account state
Send->>HW: Sign and broadcast
HW->>Trezor: Verify identity and sign PSBT
Trezor-->>HW: Signed transaction
HW->>Electrum: Broadcast transaction
Electrum-->>HW: Transaction ID
Send->>Activity: Persist wallet-scoped sent activity
Send-->>User: Show success
Loading

Reviews (1): Last reviewed commit: "feat: add trezor send and receive" | Re-trigger Greptile

Comment threadBitkit/Services/CoreService.swift Outdated
Comment threadBitkit/ViewModels/HwFundingSigner.swift
@ben-kaufmanben-kaufman changed the title feat: add trezor send and receivefeat: add trezor sendAug 27, 2026
@piotr-iohk

Copy link
Copy Markdown
Collaborator

Testing... (note: there are conflicts on this branch)

@piotr-iohkpiotr-iohk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Quick pass on device: standard HW send, passphrase HW send, and cancel-during-sign all worked. Not a full review — branch is conflicting, so not approving.

Nit: pending sent rows already use the hourglass, but it's orange even for HW. That branch runs before the blue HW tint, so a pending Trezor send is orange in the list and blue once it's no longer in that pending-sent rule. Figma has the hourglass (this and this) in brand/orange. For HW it would be more consistent to keep the hourglass and tint it blue, same as the rest of the hardware chrome.

@ovitrifovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nothing would fail if HwSendCoordinator stopped reusing a signed payment after a flaky broadcast, or ran beforeBroadcast again on retry.

Comment threadBitkit/ViewModels/HwFundingSigner.swift
@ovitrifovitrif added this to the 2.5.0 milestone Aug 28, 2026

@piotr-iohkpiotr-iohk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

Conflicts are gone. Re-tested on device with a Trezor 7: standard HW send, passphrase HW send, and cancel-during-sign still work. Pending HW hourglass is blue now.

@ovitrif

ovitrif commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Pls ensure UI is ok before merging; or if not, create an issue to list what's to polish, so we know what remaining work is there.

OK UI means either:

  • matches Figma design (reused existing UI components win here, they are the translation of Figma designs to practical implementation)
  • matches Android if Figma designs are missing for some specific states/components, if Android is "ahead" in terms of polishing, or vice-versa
  • anything outside of the 2 should have an UI implementation that conforms to the UI design language of the app

Merging without enforcing UI polishing is ok-ish if author is not 100% available for Bitkit team, but going backwards over merged changes to figure out which UI implementation is done vs what needs polishing is quite a lot of work for one, and can be distributed.

@ovitrifovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

utACK

@ovitrif

ovitrif commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Pls ensure UI is ok before merging; or if not, create an issue to list what's to polish, so we know what remaining work is there.

OK UI means either:

  • matches Figma design (reused existing UI components win here, they are the translation of Figma designs to practical implementation)
  • matches Android if Figma designs are missing for some specific states/components, if Android is "ahead" in terms of polishing, or vice-versa
  • anything outside of the 2 should have an UI implementation that conforms to the UI design language of the app

Merging without enforcing UI polishing is ok-ish if author is not 100% available for Bitkit team, but going backwards over merged changes to figure out which UI implementation is done vs what needs polishing is quite a lot of work for one, and can be distributed.

I'm trying a new ai skill I'm building on this, the expected output is an issue, then we can merge this PR.

@ovitrifovitrif mentioned this pull request Aug 31, 2026
@ovitrif

Copy link
Copy Markdown
Collaborator

UI leftover is in #696. This PR can merge.

@ovitrif

Copy link
Copy Markdown
Collaborator

@ben-kaufman pls update branch w. base, so we can merge 🎉

@ovitrif
ovitrif enabled auto-merge August 31, 2026 18:21
@ovitrifovitrif mentioned this pull request Aug 31, 2026
@ovitrif
ovitrif merged commit 004a108 into masterSep 1, 2026
23 of 27 checks passed
@ovitrif
ovitrif deleted the feat/trezor-send branch September 1, 2026 08:43
Sign up for freeto 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.

Send from hardware wallet

3 participants

@ben-kaufman@piotr-iohk@ovitrif
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat: add trezor send - #688

Merged
ovitrif merged 3 commits into
masterfrom
feat/trezor-send
Sep 1, 2026
Merged

feat: add trezor send#688
ovitrif merged 3 commits into
masterfrom
feat/trezor-send

Conversation

@ben-kaufman

@ben-kaufmanben-kaufman commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Description

This PR:

  1. Adds paired Trezor wallets as funding sources throughout the normal on-chain Send flow, including scanner, paste, manual entry, contacts, fee selection, confirmation, signing, broadcasting, and success handling.
  2. Hardens Trezor session recovery and preserves hardware-wallet activity and contact metadata while wallet snapshots catch up.

The Send UI follows the Bitkit Wallet design.

Receive support will follow in a separate stacked PR.

Linked Issues/Tasks

Fixes#706

Screenshot / Video

QA Notes

Manual Tests

  • 1. Trezor wallet → Send → enter a Bitcoin address and amount → Continue: the button loads once, Confirm opens, and repeated taps do not duplicate preparation.
  • 2. Send Confirm → choose Trezor → Sign With Device → approve on Trezor: the transaction broadcasts and Success shows the hardware-wallet activity.
  • 3. Trezor passphrase wallet → Send → enter passphrase: the paired account reconnects and the operation resumes.
  • 4. Trezor-funded Send → scan a Lightning or LNURL request: Bitkit explains that a Bitcoin address is required.
  • 5.regression: Send → switch between Savings, Spending, and Trezor: available balance and fee-aware maximum update for each source.
  • 6.regression: cancel or disconnect during signing → retry: Bitkit reconnects without creating or broadcasting a duplicate transaction.

Automated Checks

  • Unit tests added or extended in HwFundingSignerTests.swift and TrezorSessionFailureTests.swift: cover source coordination, timeouts, stale-session retry, retained signed transactions, and failure classification.
  • Unit tests extended in HwSnapshotMergeTests.swift: cover pending sent activity and contact preservation during watcher reconciliation.
  • Unit tests extended in ShopPaymentRequestTests.swift: cover hardware-wallet on-chain-only scan handling.
  • Focused iOS unit tests passed.
  • All changed Swift files pass SwiftFormat; translation validation and diff checks pass.

@greptile-apps

Copy link
Copy Markdown

Greptile Summary

This PR integrates paired Trezor wallets into normal on-chain send and receive flows and hardens session recovery and hardware activity reconciliation.

  • Adds hardware-wallet funding-source selection, fee preparation, device signing, broadcast retry, and wallet-scoped success lookup.
  • Adds Trezor receive-address display, copying, QR presentation, passphrase reconnection, and on-device verification.
  • Serializes connection operations and preserves pending hardware activity and contact metadata during watcher reconciliation.

Confidence Score: 3/5

The PR should not merge until pending hardware activity survives process recreation and timeout cleanup can no longer tear down a retry’s newly established Trezor session.

A restart can remove a just-broadcast hardware activity before Electrum observes it, while an immediate retry after a device timeout can race delayed stale-session cleanup and lose the replacement connection.

Files Needing Attention: Bitkit/Services/CoreService.swift, Bitkit/Services/HwSnapshotMerge.swift, Bitkit/ViewModels/HwFundingSigner.swift, Bitkit/Managers/TrezorManager.swift

Important Files Changed

FilenameOverview
Bitkit/ViewModels/HwFundingSigner.swiftGeneralizes hardware signing for ordinary sends and adds non-structural timeouts, but asynchronous stale-session cleanup can race an immediate retry.
Bitkit/Managers/TrezorManager.swiftSerializes connection operations and retries stale sessions, while the separate reset path remains able to clear newer connection state.
Bitkit/Services/CoreService.swiftProtects newly broadcast hardware activity from watcher pruning, but stores the protection only in process memory.
Bitkit/Services/HwSnapshotMerge.swiftPreserves pending sends and contact metadata when supplied the pending-ID set, but intentionally prunes unprotected pending rows.
Bitkit/Managers/HwWalletManager.swiftAdds hardware receive-address derivation and verification plus funding-source balance support.
Bitkit/Views/Wallets/Send/SendSheet.swiftIntegrates hardware source selection and signing routes throughout the existing send lifecycle.
Bitkit/Views/Wallets/Receive/ReceiveQr.swiftAdds Trezor receive QR, copy, device verification, and passphrase recovery states.

Sequence Diagram

sequenceDiagram
participant User
participant Send as Send Flow
participant HW as Hardware Wallet Manager
participant Trezor
participant Electrum
participant Activity
User->>Send: Select Trezor funding source
Send->>HW: Compose payment and estimate fee
HW->>Electrum: Load account and UTXOs
Electrum-->>HW: Account state
Send->>HW: Sign and broadcast
HW->>Trezor: Verify identity and sign PSBT
Trezor-->>HW: Signed transaction
HW->>Electrum: Broadcast transaction
Electrum-->>HW: Transaction ID
Send->>Activity: Persist wallet-scoped sent activity
Send-->>User: Show success
Loading

Reviews (1): Last reviewed commit: "feat: add trezor send and receive" | Re-trigger Greptile

Comment threadBitkit/Services/CoreService.swift Outdated
Comment threadBitkit/ViewModels/HwFundingSigner.swift
@ben-kaufmanben-kaufman changed the title feat: add trezor send and receivefeat: add trezor sendAug 27, 2026
@piotr-iohk

Copy link
Copy Markdown
Collaborator

Testing... (note: there are conflicts on this branch)

@piotr-iohkpiotr-iohk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Quick pass on device: standard HW send, passphrase HW send, and cancel-during-sign all worked. Not a full review — branch is conflicting, so not approving.

Nit: pending sent rows already use the hourglass, but it's orange even for HW. That branch runs before the blue HW tint, so a pending Trezor send is orange in the list and blue once it's no longer in that pending-sent rule. Figma has the hourglass (this and this) in brand/orange. For HW it would be more consistent to keep the hourglass and tint it blue, same as the rest of the hardware chrome.

@ovitrifovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nothing would fail if HwSendCoordinator stopped reusing a signed payment after a flaky broadcast, or ran beforeBroadcast again on retry.

Comment threadBitkit/ViewModels/HwFundingSigner.swift
@ovitrifovitrif added this to the 2.5.0 milestone Aug 28, 2026

@piotr-iohkpiotr-iohk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

Conflicts are gone. Re-tested on device with a Trezor 7: standard HW send, passphrase HW send, and cancel-during-sign still work. Pending HW hourglass is blue now.

@ovitrif

ovitrif commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Pls ensure UI is ok before merging; or if not, create an issue to list what's to polish, so we know what remaining work is there.

OK UI means either:

  • matches Figma design (reused existing UI components win here, they are the translation of Figma designs to practical implementation)
  • matches Android if Figma designs are missing for some specific states/components, if Android is "ahead" in terms of polishing, or vice-versa
  • anything outside of the 2 should have an UI implementation that conforms to the UI design language of the app

Merging without enforcing UI polishing is ok-ish if author is not 100% available for Bitkit team, but going backwards over merged changes to figure out which UI implementation is done vs what needs polishing is quite a lot of work for one, and can be distributed.

@ovitrifovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

utACK

@ovitrif

ovitrif commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Pls ensure UI is ok before merging; or if not, create an issue to list what's to polish, so we know what remaining work is there.

OK UI means either:

  • matches Figma design (reused existing UI components win here, they are the translation of Figma designs to practical implementation)
  • matches Android if Figma designs are missing for some specific states/components, if Android is "ahead" in terms of polishing, or vice-versa
  • anything outside of the 2 should have an UI implementation that conforms to the UI design language of the app

Merging without enforcing UI polishing is ok-ish if author is not 100% available for Bitkit team, but going backwards over merged changes to figure out which UI implementation is done vs what needs polishing is quite a lot of work for one, and can be distributed.

I'm trying a new ai skill I'm building on this, the expected output is an issue, then we can merge this PR.

@ovitrifovitrif mentioned this pull request Aug 31, 2026
@ovitrif

Copy link
Copy Markdown
Collaborator

UI leftover is in #696. This PR can merge.

@ovitrif

Copy link
Copy Markdown
Collaborator

@ben-kaufman pls update branch w. base, so we can merge 🎉

@ovitrif
ovitrif enabled auto-merge August 31, 2026 18:21
@ovitrifovitrif mentioned this pull request Aug 31, 2026
@ovitrif
ovitrif merged commit 004a108 into masterSep 1, 2026
23 of 27 checks passed
@ovitrif
ovitrif deleted the feat/trezor-send branch September 1, 2026 08:43
Sign up for freeto 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.

Send from hardware wallet

3 participants

@ben-kaufman@piotr-iohk@ovitrif