Skip to content

Add Tor proxy support for node connections#682

Open
guptapratykshh wants to merge 1 commit intobitcoinppl:masterfrom
guptapratykshh:feat/tor-support
Open

Add Tor proxy support for node connections#682
guptapratykshh wants to merge 1 commit intobitcoinppl:masterfrom
guptapratykshh:feat/tor-support

Conversation

@guptapratykshh
Copy link
Copy Markdown
Contributor

@guptapratykshh guptapratykshh commented Apr 18, 2026

Route Electrum, Esplora, and HTTP client traffic through a SOCKS5 proxy when Tor is enabled. This lets users connect to their own .onion Electrum/Esplora servers via a local Tor proxy such as Orbot.

  • Add TorConfig (enabled, proxy_address) to the Node model
  • Use electrum-client's Client::from_config with Socks5Config
  • Pass socks5 proxy URL to esplora-client Builder::proxy
  • Add reqwest socks feature to cove-http for fee/fiat clients
  • Force tcp:// scheme for .onion addresses (Tor encrypts)
  • Add Tor toggle and proxy address fields to iOS and Android node settings UI
  • Backward-compatible: serde(default) on tor field

Closes #256

Summary

Testing

Platform Coverage

  • Tested on iOS device
  • Tested on Android device
  • Tested on iOS simulator
  • Tested on Android simulator
  • Not tested

Checklist

Summary by CodeRabbit

Release Notes

  • New Features
    • Added Tor support for custom node configurations on Android and iOS, with a toggle to enable Tor and configurable proxy address settings.
    • Support for connecting to Tor hidden services (.onion addresses).
    • HTTP requests automatically route through SOCKS5 proxy when Tor is enabled.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 18, 2026

Warning

Rate limit exceeded

@guptapratykshh has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 58 minutes and 4 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 58 minutes and 4 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 87a5a8d9-b947-4ff8-a4b5-b6b31007c86e

📥 Commits

Reviewing files that changed from the base of the PR and between 662fbae and 3afaae4.

⛔ Files ignored due to path filters (1)
  • ios/CoveCore/Sources/CoveCore/generated/cove.swift is excluded by !**/generated/**
📒 Files selected for processing (11)
  • android/app/src/main/java/org/bitcoinppl/cove/flows/SettingsFlow/NodeSettingsScreen.kt
  • android/app/src/main/java/org/bitcoinppl/cove_core/cove.kt
  • ios/Cove/Flows/SettingsFlow/SettingsScreen/NodeSelectionView.swift
  • rust/crates/cove-http/Cargo.toml
  • rust/crates/cove-http/src/lib.rs
  • rust/src/fee_client.rs
  • rust/src/fiat/client.rs
  • rust/src/node.rs
  • rust/src/node/client/electrum.rs
  • rust/src/node/client/esplora.rs
  • rust/src/node_connect.rs
📝 Walkthrough

Walkthrough

This PR adds Tor support across Android, iOS, and Rust components of the application. It introduces TorConfig data structures, extends node parsing to accept Tor configurations, updates HTTP clients to support SOCKS5 proxies, and adds UI elements for toggling Tor and configuring proxy addresses on both platforms.

Changes

Cohort / File(s) Summary
Android UI
android/app/src/main/java/org/bitcoinppl/cove/flows/SettingsFlow/NodeSettingsScreen.kt
Added UI state for Tor (torEnabled, torProxyAddress) with toggle and conditional proxy address input. Modified custom node save flow to construct TorConfig and call parseCustomNodeWithTor() instead of parseCustomNode(). Pre-fills Tor settings when loading previously-saved custom nodes.
iOS UI
ios/Cove/Flows/SettingsFlow/SettingsScreen/NodeSelectionView.swift
Added Tor-related state (torEnabled, torProxyAddress) initialized from selected node. Extended custom node UI with Tor toggle and proxy address field. Updated save flow to construct TorConfig and call parseCustomNodeWithTor(). Restores Tor config when switching between preset and custom selections.
Kotlin FFI Bindings
android/app/src/main/java/org/bitcoinppl/cove_core/cove.kt
Added UniFFI bindings for parseCustomNodeWithTor() with checksum verification. Extended NodeSelectorInterface and NodeSelector with new Tor-aware method. Updated Node data class with tor: TorConfig field. Introduced TorConfig data class and FfiConverterTypeTorConfig for FFI encoding/decoding.
Rust Core Model
rust/src/node.rs
Introduced TorConfig struct with enabled and proxy_address fields, including socks5_url() helper and default impl. Extended Node struct with tor: TorConfig field. Changed new_electrum() and new_esplora() from const fn to pub fn due to Tor initialization.
Rust Node Parsing
rust/src/node_connect.rs
Added parse_custom_node_with_tor() method accepting TorConfig parameter. Updated URL parsing logic to handle .onion addresses and Esplora URLs correctly. Made parse_custom_node() delegate to parse_custom_node_with_tor() with default TorConfig. Sets tor config on parsed nodes.
Rust HTTP Infrastructure
rust/crates/cove-http/Cargo.toml, rust/crates/cove-http/src/lib.rs
Enabled socks feature in reqwest dependency. Refactored client construction into shared build_client() helper supporting optional SOCKS5 proxy. Added new_client_with_proxy() function; updated new_client() to delegate to build_client(None).
Rust HTTP Client Users
rust/src/fee_client.rs, rust/src/fiat/client.rs
Removed per-instance OnceCell<reqwest::Client> storage and lazy initialization. Updated HTTP requests to build clients on-demand via build_client() function, selecting proxy-enabled or direct client based on node Tor config.
Rust Node Clients
rust/src/node/client/electrum.rs, rust/src/node/client/esplora.rs
Updated Electrum client construction to use Socks5Config when node.tor.enabled is true. Updated Esplora client construction to apply .proxy() when Tor is enabled. Both now use node.tor.socks5_url() for proxy configuration.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant UI as Mobile UI
    participant NodeSel as NodeSelector
    participant NodeModel as Node Model
    participant HTTPClient as HTTP Client
    participant Proxy as SOCKS5 Proxy

    User->>UI: Enable Tor & Enter Proxy Address
    User->>UI: Save Custom Node
    UI->>NodeSel: parseCustomNodeWithTor(url, name, torConfig)
    NodeSel->>NodeModel: Parse URL, Create Node with TorConfig
    NodeModel-->>NodeSel: Return Node(tor=TorConfig)
    NodeSel-->>UI: Node with Tor enabled
    
    Note over User,Proxy: Later: Making HTTP Request
    
    User->>UI: Fetch Fee/Price Data
    UI->>HTTPClient: build_client(tor.enabled)
    alt Tor Enabled
        HTTPClient->>HTTPClient: new_client_with_proxy(socks5_url)
        HTTPClient->>Proxy: Connect via SOCKS5
        Proxy-->>HTTPClient: Proxy connection ready
    else Tor Disabled
        HTTPClient->>HTTPClient: new_client()
        HTTPClient->>HTTPClient: Direct connection
    end
    HTTPClient-->>UI: Client ready
    UI->>HTTPClient: Make request
    HTTPClient->>Proxy: Forward request through SOCKS5
    Proxy->>Proxy: Route to destination (possibly .onion)
    Proxy-->>HTTPClient: Response
    HTTPClient-->>UI: Data
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 Through onion layers, deep and far,
Our rabbit hops without a scar,
SOCKS5 guards each hidden way,
Bitcoin nodes now safely play! 🧅✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.48% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add Tor proxy support for node connections' is clear, concise, and accurately summarizes the main feature being added across the codebase.
Description check ✅ Passed The description clearly outlines the changes made, references the closed issue, and includes the required checklists confirming documentation was reviewed.
Linked Issues check ✅ Passed The PR successfully implements Tor support for connecting to .onion-addressed Electrum/Esplora servers as requested in issue #256, with SOCKS5 proxy configuration throughout the stack.
Out of Scope Changes check ✅ Passed All changes are focused on adding Tor proxy support; no unrelated modifications or scope creep detected across the Android, iOS, and Rust layers.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 18, 2026

Greptile Summary

This PR adds SOCKS5 Tor proxy support for Electrum, Esplora, and HTTP (fee/fiat) clients, routing traffic through a local proxy (e.g., Orbot) when enabled. The TorConfig struct is backward-compatible via serde(default), and the UI additions on both platforms are clean. Three P1 issues need to be addressed before merge:

  • reqwest::Proxy::all(proxy_url).expect(...) in cove-http/src/lib.rs will panic in production on any malformed user-supplied proxy address; replace with ?.
  • The OnceCell-cached reqwest client in FeeClient and FiatClient captures the Tor setting at first use and never updates — toggling Tor in settings is silently ignored for fee/fiat requests until app restart.
  • parse_node_url converts http:// to tcp:// before the onion-scheme logic runs, so Esplora .onion nodes get a tcp:// URL stored in node.url, which breaks esplora_client::Builder::new (HTTP-only) and makes the advertised Esplora-over-Tor path non-functional.

Confidence Score: 3/5

Not safe to merge: three P1 issues — a production panic, a silently stale proxy config, and a broken Esplora-over-Tor path.

All three P1 findings are present in changed code: the .expect() panic is directly triggered by user input with no validation guard; the OnceCell stale-client issue makes Tor settings changes ineffective for fee/fiat without a restart; and Esplora .onion nodes receive a tcp://-scheme URL that will fail every HTTP request, making the primary advertised use case (Esplora-over-Tor/.onion) non-functional.

rust/crates/cove-http/src/lib.rs (expect panic), rust/src/node_connect.rs (wrong URL scheme for Esplora onion), rust/src/fee_client.rs and rust/src/fiat/client.rs (stale OnceCell proxy client)

Important Files Changed

Filename Overview
rust/crates/cove-http/src/lib.rs Adds proxy-aware client builder; .expect() on user-supplied proxy URL causes a production panic — must use ? instead.
rust/src/fee_client.rs Tor-aware reqwest client init via OnceCell is stale after first use; Tor enable/disable in settings won't apply to fee requests until app restart.
rust/src/fiat/client.rs Same stale OnceCell proxy issue as fee_client.rs; Tor settings changes silently ignored for fiat price requests.
rust/src/node_connect.rs parse_node_url converts http:// to tcp:// before applying onion-scheme logic, giving Esplora .onion nodes a tcp:// URL that breaks esplora_client::Builder.
rust/src/node.rs Adds TorConfig struct with enabled/proxy_address fields and socks5_url() helper; well-structured, serde(default) ensures backward compatibility.
rust/src/node/client/electrum.rs Adds Socks5Config-based Electrum client creation when Tor is enabled; correctly uses proxy_address (host:port) for electrum-client's Socks5Config.
rust/src/node/client/esplora.rs Adds SOCKS5 proxy to esplora builder; proxy wiring is correct, but node.url will have wrong tcp:// scheme for .onion addresses due to parse_node_url bug.
rust/crates/cove-http/Cargo.toml Adds reqwest 'socks' feature to enable SOCKS5 proxy support; straightforward dependency change.
ios/Cove/Flows/SettingsFlow/SettingsScreen/NodeSelectionView.swift Adds Tor toggle and proxy address input to node settings; correctly restores saved Tor settings and falls back to default proxy address when empty.
android/app/src/main/java/org/bitcoinppl/cove/flows/SettingsFlow/NodeSettingsScreen.kt Adds Tor toggle and proxy address fields to Android node settings; correctly uses LaunchedEffect for pre-fill and ifEmpty fallback for proxy address.

Sequence Diagram

sequenceDiagram
    participant UI as iOS/Android UI
    participant NS as NodeSelector
    participant PNU as parse_node_url
    participant EC as ElectrumClient
    participant ESC as EsploraClient
    participant HC as cove-http (Fee/Fiat)
    participant TOR as Tor SOCKS5 Proxy

    UI->>NS: parseCustomNodeWithTor(url, tor)
    NS->>PNU: parse_node_url(url, is_onion)
    Note over PNU: http:// → tcp://<br/>https:// → ssl://<br/>[onion] none/ssl/https → tcp
    PNU-->>NS: Node { url: tcp://... or ssl://..., tor }

    alt Electrum node + Tor enabled
        NS->>EC: new_from_node(node)
        EC->>TOR: TCP via Socks5Config (proxy_address)
        TOR-->>EC: Electrum response ✅
    end

    alt Esplora node + Tor enabled
        NS->>ESC: new_from_node(node)
        Note over ESC: node.url = tcp://xxx.onion/api/ ❌
        ESC->>ESC: Builder::new(tcp://xxx.onion) FAILS
    end

    alt Fee/Fiat client (OnceCell issue)
        HC->>HC: get_or_try_init (first call, Tor disabled)
        Note over HC: Client cached without proxy
        UI->>UI: User enables Tor in settings
        HC->>HC: get_or_try_init (already initialized)
        Note over HC: Stale client — no proxy ❌
    end
Loading

Reviews (1): Last reviewed commit: "Add Tor proxy support for node connectio..." | Re-trigger Greptile

Comment thread rust/crates/cove-http/src/lib.rs Outdated
Comment thread rust/src/fee_client.rs Outdated
Comment thread rust/src/node_connect.rs Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
ios/Cove/Flows/SettingsFlow/SettingsScreen/NodeSelectionView.swift (1)

233-248: ⚠️ Potential issue | 🟡 Minor

Reset Tor defaults before restoring a saved custom node.

When switching into a custom node option with no matching saved custom node, torEnabled and torProxyAddress keep their previous values and can be saved into the new node.

🛠️ Proposed adjustment
         .onChange(of: selectedNodeName) { _, newSelectedNodeName in
-            if selectedNodeName.hasPrefix("Custom") {
+            if newSelectedNodeName.hasPrefix("Custom") {
+                torEnabled = false
+                torProxyAddress = "127.0.0.1:9050"
+
                 if case let .custom(savedSelectedNode) = nodeSelector.selectedNode() {
-                    if savedSelectedNode.apiType == .electrum, selectedNodeName.contains("Electrum") {
+                    if savedSelectedNode.apiType == .electrum, newSelectedNodeName.contains("Electrum") {
                         customUrl = savedSelectedNode.url
                         customNodeName = savedSelectedNode.name
                         torEnabled = savedSelectedNode.tor.enabled
                         torProxyAddress = savedSelectedNode.tor.proxyAddress
                     }
 
-                    if savedSelectedNode.apiType == .esplora, selectedNodeName.contains("Esplora") {
+                    if savedSelectedNode.apiType == .esplora, newSelectedNodeName.contains("Esplora") {
                         customUrl = savedSelectedNode.url
                         customNodeName = savedSelectedNode.name
                         torEnabled = savedSelectedNode.tor.enabled
                         torProxyAddress = savedSelectedNode.tor.proxyAddress

Also applies to: 135-146

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ios/Cove/Flows/SettingsFlow/SettingsScreen/NodeSelectionView.swift` around
lines 233 - 248, When handling selectedNodeName changes in NodeSelectionView's
.onChange closure (and the similar block around lines 135-146), ensure
torEnabled and torProxyAddress are reset to their default values before
attempting to restore a saved custom node; specifically, when
selectedNodeName.hasPrefix("Custom") but nodeSelector.selectedNode() does not
return a matching .custom(savedSelectedNode), set torEnabled = false (or the
app's default) and torProxyAddress = "" (or default) so stale values are not
carried into a new custom node, and only overwrite these defaults if a matching
.custom(savedSelectedNode) is found and its values are applied.
android/app/src/main/java/org/bitcoinppl/cove/flows/SettingsFlow/NodeSettingsScreen.kt (1)

138-142: ⚠️ Potential issue | 🟡 Minor

Reset Tor fields when clearing custom-node state.

selectPresetNode() clears customUrl and customNodeName, but leaves torEnabled/torProxyAddress intact. Returning to a custom node flow can then save stale Tor settings through parseCustomNodeWithTor(...).

🛠️ Proposed adjustment
+    val defaultTorProxyAddress = "127.0.0.1:9050"
+
     fun selectPresetNode(nodeName: String) {
         selectedNodeName = nodeName
         customUrl = ""
         customNodeName = ""
+        torEnabled = false
+        torProxyAddress = defaultTorProxyAddress
                 val torConfig = TorConfig(
                     enabled = torEnabled,
-                    proxyAddress = torProxyAddress.ifEmpty { "127.0.0.1:9050" },
+                    proxyAddress = torProxyAddress.ifBlank { defaultTorProxyAddress },
                 )

Also applies to: 191-203

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@android/app/src/main/java/org/bitcoinppl/cove/flows/SettingsFlow/NodeSettingsScreen.kt`
around lines 138 - 142, selectPresetNode currently clears customUrl and
customNodeName but leaves Tor settings intact, so update selectPresetNode to
also reset torEnabled to false and clear torProxyAddress (empty string or null
consistent with your state types) and do the same in the other method that
clears custom node state (the function that currently clears
customUrl/customNodeName) so that parseCustomNodeWithTor cannot reuse stale tor
settings; reference selectPresetNode and parseCustomNodeWithTor when making
these changes.
🧹 Nitpick comments (3)
rust/crates/cove-http/src/lib.rs (1)

9-31: Optional: Consider documenting SOCKS5H requirement for .onion proxies.

The technical distinction between SOCKS5 (local DNS) and SOCKS5H (remote DNS via proxy) is correct — .onion addresses require remote DNS resolution. However, the current codebase does not route .onion traffic through cove_http. Esplora nodes use esplora_client::Builder::proxy() and Electrum nodes use Socks5Config::new() directly, both with independent proxy mechanisms. The clients using cove_http (fiat and fee) connect only to hardcoded clearnet URLs (https://mempool.space), which do not require remote DNS.

If cove_http is used for .onion hosts in the future, normalizing to socks5h:// at this layer would be beneficial. For now, this could be addressed via documentation or left to the caller to normalize the scheme as needed based on their destination.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rust/crates/cove-http/src/lib.rs` around lines 9 - 31, Note the distinction
between SOCKS5 and SOCKS5H and add a short comment in new_client_with_proxy /
build_client documenting that .onion hosts require remote DNS (SOCKS5H) and
callers must pass a socks5h:// URL if they intend to reach .onion addresses;
mention that the current clients (fiat/fee) use clearnet URLs so this is left to
callers but future use for .onion should normalize the scheme to socks5h:// at
this layer.
rust/src/node_connect.rs (2)

156-158: Use map_err_str for the parse error conversion.

This follows the repo-wide Rust error-conversion helper and keeps this new path consistent.

Suggested change
+use cove_util::ResultExt;
+
         let url =
-            parse_node_url(&url, is_onion, is_esplora).map_err(|error| Error::ParseNodeUrlError(error.to_string()))?;
+            parse_node_url(&url, is_onion, is_esplora).map_err_str(Error::ParseNodeUrlError)?;

As per coding guidelines, use cove_util::ResultExt::map_err_str instead of .map_err(|e| Error::Variant(e.to_string())).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rust/src/node_connect.rs` around lines 156 - 158, Replace the current
explicit error mapping when calling parse_node_url with the repository helper:
instead of using .map_err(|error| Error::ParseNodeUrlError(error.to_string())),
call .map_err_str(Error::ParseNodeUrlError) (from cove_util::ResultExt) so the
parse_node_url call converts errors via map_err_str; update the use/imports if
needed to bring ResultExt into scope and ensure Error::ParseNodeUrlError remains
the target constructor.

153-157: Extract .onion detection from the parsed URL domain, not the raw string.

url.contains(".onion") is case-sensitive and matches substrings in paths and hostnames—for example, http://attacker.com/.onion/api or http://evil.onion.com would be incorrectly classified, while http://example.ONION would be missed. After parse_node_url() parses the URL, check url.domain().ends_with(".onion") to reliably detect actual .onion TLDs.

This would require restructuring to determine is_onion from the parsed Url object rather than before parsing, or refactoring the function signature to pass back the detection status.

Also applies to: 282-290

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rust/src/node_connect.rs` around lines 153 - 157, Determine .onion from the
parsed Url instead of the raw string: call parse_node_url(&url, /*is_onion*/
false, is_esplora) (or refactor parse_node_url to return a Url) and then set
is_onion by checking the parsed url's domain() with something like
parsed.domain().map(|d| d.ends_with(".onion")).unwrap_or(false); update
downstream uses to use this computed is_onion (or change parse_node_url
signature to return the detection) and remove the original
url.contains(".onion") check; apply the same change for the other occurrence
around lines 282-290 referencing parse_node_url, is_onion and node_type.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@rust/src/node.rs`:
- Around line 87-90: The Testnet match arm currently takes (name, url) from
TESTNET_ESPLORA but calls Self::new_electrum, creating an Electrum client for an
HTTP Esplora URL; change the constructor call to the Esplora/HTTP API
initializer (e.g., Self::new_esplora(name.to_string(), url.to_string(),
network)) so Node::default(Network::Testnet) builds an Esplora client that
matches TESTNET_ESPLORA.

In `@rust/src/node/client/esplora.rs`:
- Around line 32-37: The Esplora client is currently configured with a SOCKS5
proxy that uses node.tor.socks5_url() which must use the "socks5h://" scheme to
force proxy-side DNS resolution for .onion addresses; update the proxy usage in
the Esplora client setup (the esplora_client::Builder proxy call) and the other
occurrence in this file to use a socks5h URL, ideally by changing
TorConfig::socks5_url() to return a "socks5h://" URL so all calls (including the
builder.proxy(...) and the second usage) consistently use proxy-side DNS
resolution for .onion endpoints.

---

Outside diff comments:
In
`@android/app/src/main/java/org/bitcoinppl/cove/flows/SettingsFlow/NodeSettingsScreen.kt`:
- Around line 138-142: selectPresetNode currently clears customUrl and
customNodeName but leaves Tor settings intact, so update selectPresetNode to
also reset torEnabled to false and clear torProxyAddress (empty string or null
consistent with your state types) and do the same in the other method that
clears custom node state (the function that currently clears
customUrl/customNodeName) so that parseCustomNodeWithTor cannot reuse stale tor
settings; reference selectPresetNode and parseCustomNodeWithTor when making
these changes.

In `@ios/Cove/Flows/SettingsFlow/SettingsScreen/NodeSelectionView.swift`:
- Around line 233-248: When handling selectedNodeName changes in
NodeSelectionView's .onChange closure (and the similar block around lines
135-146), ensure torEnabled and torProxyAddress are reset to their default
values before attempting to restore a saved custom node; specifically, when
selectedNodeName.hasPrefix("Custom") but nodeSelector.selectedNode() does not
return a matching .custom(savedSelectedNode), set torEnabled = false (or the
app's default) and torProxyAddress = "" (or default) so stale values are not
carried into a new custom node, and only overwrite these defaults if a matching
.custom(savedSelectedNode) is found and its values are applied.

---

Nitpick comments:
In `@rust/crates/cove-http/src/lib.rs`:
- Around line 9-31: Note the distinction between SOCKS5 and SOCKS5H and add a
short comment in new_client_with_proxy / build_client documenting that .onion
hosts require remote DNS (SOCKS5H) and callers must pass a socks5h:// URL if
they intend to reach .onion addresses; mention that the current clients
(fiat/fee) use clearnet URLs so this is left to callers but future use for
.onion should normalize the scheme to socks5h:// at this layer.

In `@rust/src/node_connect.rs`:
- Around line 156-158: Replace the current explicit error mapping when calling
parse_node_url with the repository helper: instead of using .map_err(|error|
Error::ParseNodeUrlError(error.to_string())), call
.map_err_str(Error::ParseNodeUrlError) (from cove_util::ResultExt) so the
parse_node_url call converts errors via map_err_str; update the use/imports if
needed to bring ResultExt into scope and ensure Error::ParseNodeUrlError remains
the target constructor.
- Around line 153-157: Determine .onion from the parsed Url instead of the raw
string: call parse_node_url(&url, /*is_onion*/ false, is_esplora) (or refactor
parse_node_url to return a Url) and then set is_onion by checking the parsed
url's domain() with something like parsed.domain().map(|d|
d.ends_with(".onion")).unwrap_or(false); update downstream uses to use this
computed is_onion (or change parse_node_url signature to return the detection)
and remove the original url.contains(".onion") check; apply the same change for
the other occurrence around lines 282-290 referencing parse_node_url, is_onion
and node_type.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c938660c-9b91-4538-9e7c-0c51c644e3c7

📥 Commits

Reviewing files that changed from the base of the PR and between ba61cd2 and 662fbae.

📒 Files selected for processing (11)
  • android/app/src/main/java/org/bitcoinppl/cove/flows/SettingsFlow/NodeSettingsScreen.kt
  • android/app/src/main/java/org/bitcoinppl/cove_core/cove.kt
  • ios/Cove/Flows/SettingsFlow/SettingsScreen/NodeSelectionView.swift
  • rust/crates/cove-http/Cargo.toml
  • rust/crates/cove-http/src/lib.rs
  • rust/src/fee_client.rs
  • rust/src/fiat/client.rs
  • rust/src/node.rs
  • rust/src/node/client/electrum.rs
  • rust/src/node/client/esplora.rs
  • rust/src/node_connect.rs

Comment thread rust/src/node.rs
Comment thread rust/src/node/client/esplora.rs
@pradhyum6144
Copy link
Copy Markdown
Collaborator

@praveenperera is yet not commited to adding TOR support yet he need to know how may deps it adds and how much heavier it makes the app bundle on ios and android

Route Electrum, Esplora, and HTTP client traffic through a
SOCKS5 proxy when Tor is enabled. This lets users connect to
their own .onion Electrum/Esplora servers via a local Tor
proxy such as Orbot.

- Add TorConfig (enabled, proxy_address) to the Node model
- Use electrum-client's Client::from_config with Socks5Config
- Pass socks5 proxy URL to esplora-client Builder::proxy
- Add reqwest socks feature to cove-http for fee/fiat clients
- Force tcp:// scheme for .onion addresses (Tor encrypts)
- Add Tor toggle and proxy address fields to iOS and Android
  node settings UI
- Backward-compatible: serde(default) on tor field

Closes bitcoinppl#256
)
@praveenperera
Copy link
Copy Markdown
Contributor

hey @guptapratykshh, @Justxd22 is also working on TOR, can you guys combine efforts?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add TOR support

3 participants