Skip to content

Require port for Monero node URLs#9383

Closed
omurovch wants to merge 3 commits into
version/0.50from
custom-node
Closed

Require port for Monero node URLs#9383
omurovch wants to merge 3 commits into
version/0.50from
custom-node

Conversation

@omurovch

@omurovch omurovch commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Added clearer guidance for entering Monero node URLs, including an example with a port.
    • Added validation requiring node URLs to include an explicit port.
  • Bug Fixes

    • Improved node URL normalization for consistent connection and duplicate-node checks.
    • Added a clear error message when a required port is missing.

omurovch and others added 3 commits July 13, 2026 15:39
Add validation to ensure that manually entered Monero node URLs include a port number. If a port is missing, an error message is displayed to the user.

- Update `AddMoneroNodeViewModel` to validate the presence of a port in the RPC URL.
- Update `AddMoneroNodeScreen` input hint to show the expected format (e.g., `https://node.com:port`).
- Add a fallback to port 443 in `MoneroNodeManager` for nodes saved before this validation was implemented.
- Add `AddMoneroNode_Error_PortRequired` string resource.
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Monero node URLs now use normalized host-port endpoints for serialization and duplicate detection. The add-node flow requires an explicit port and provides corresponding validation text and input guidance.

Changes

Monero node validation

Layer / File(s) Summary
Endpoint normalization and lookup
walletkit/src/main/java/io/horizontalsystems/walletkit/core/managers/MoneroNodeManager.kt
Missing ports default to 443, and node existence checks compare canonical host:port endpoints.
Add-node port validation
walletkit/src/main/java/io/horizontalsystems/walletkit/modules/moneronetwork/addnode/AddMoneroNodeViewModel.kt, walletkit/src/main/res/values/strings.xml, walletkit/src/main/java/io/horizontalsystems/walletkit/modules/moneronetwork/addnode/AddMoneroNodeScreen.kt
URLs without explicit ports are rejected, duplicate checks use normalized endpoints, and the UI displays port-format guidance.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: abdrasulov, rafaelekol

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: Monero node URLs now must include a port.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch custom-node

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@walletkit/src/main/java/io/horizontalsystems/walletkit/core/managers/MoneroNodeManager.kt`:
- Around line 157-164: Update endpoint() to lowercase the parsed URI host before
constructing the normalized host-and-port value, so hasNode() compares hosts
case-insensitively while preserving the existing fallback behavior. Add a
regression test covering mixed-case URLs that represent the same Monero node.

In
`@walletkit/src/main/java/io/horizontalsystems/walletkit/modules/moneronetwork/addnode/AddMoneroNodeScreen.kt`:
- Line 65: Replace the hardcoded hint in AddMoneroNodeScreen with a localized
string resource containing a copy-paste-valid example such as
https://node.com:18081, and pass that resource through stringResource(...).

In
`@walletkit/src/main/java/io/horizontalsystems/walletkit/modules/moneronetwork/addnode/AddMoneroNodeViewModel.kt`:
- Around line 61-65: Update the port validation in the add-node flow around
sourceUri and before persistence to accept only values in 1..65535. Reject port
0 and any out-of-range value with the existing AddMoneroNode_Error_PortRequired
caution, emit the state, and return before saving.
🪄 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 Plus

Run ID: 54f6c7ec-27b6-4d9c-b4b4-c601a3f34f79

📥 Commits

Reviewing files that changed from the base of the PR and between 05a42b4 and 44e6a92.

⛔ Files ignored due to path filters (1)
  • walletkit/src/main/res/values-fa/strings.xml is excluded by !**/res/values-*/strings.xml
📒 Files selected for processing (4)
  • walletkit/src/main/java/io/horizontalsystems/walletkit/core/managers/MoneroNodeManager.kt
  • walletkit/src/main/java/io/horizontalsystems/walletkit/modules/moneronetwork/addnode/AddMoneroNodeScreen.kt
  • walletkit/src/main/java/io/horizontalsystems/walletkit/modules/moneronetwork/addnode/AddMoneroNodeViewModel.kt
  • walletkit/src/main/res/values/strings.xml

Comment on lines +157 to +164
private fun endpoint(hostOrUrl: String): String {
val uri = hostOrUrl.toUri()
return uri.host?.let { "$it:${effectivePort(uri)}" } ?: hostOrUrl
}

fun hasNode(url: String): Boolean {
val endpoint = endpoint(url)
return allNodes.any { endpoint(it.host) == endpoint }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="walletkit/src/main/java/io/horizontalsystems/walletkit/core/managers/MoneroNodeManager.kt"

echo "== file outline =="
ast-grep outline "$FILE" --view expanded || true

echo
echo "== relevant lines =="
nl -ba "$FILE" | sed -n '130,210p'

echo
echo "== search for endpoint/hasNode usage =="
rg -n "endpoint\(|hasNode\(|allNodes" walletkit/src/main/java walletkit/src/test kotlin || true

echo
echo "== search tests for MoneroNodeManager =="
fd -a "MoneroNodeManager" . || true
rg -n "MoneroNodeManager|hasNode|endpoint\(" walletkit/src/test walletkit/src/androidTest . || true

Repository: horizontalsystems/unstoppable-wallet-android

Length of output: 1753


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="walletkit/src/main/java/io/horizontalsystems/walletkit/core/managers/MoneroNodeManager.kt"

echo "== excerpt =="
sed -n '1,230p' "$FILE"

echo
echo "== search for toUri import/definition =="
rg -n "toUri\\(|import .*toUri" walletkit/src/main/java walletkit/src/test . || true

echo
echo "== search for MoneroNodeManager tests =="
rg -n "MoneroNodeManager|hasNode|addMoneroNode|delete\\(" walletkit/src/test walletkit/src/androidTest . || true

Repository: horizontalsystems/unstoppable-wallet-android

Length of output: 22689


Normalize Monero node host comparison
endpoint() preserves the parsed host’s casing, so hasNode() can miss duplicates when the same node is entered with different host case. Lowercase the host before comparing, and add a regression test for mixed-case URLs.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@walletkit/src/main/java/io/horizontalsystems/walletkit/core/managers/MoneroNodeManager.kt`
around lines 157 - 164, Update endpoint() to lowercase the parsed URI host
before constructing the normalized host-and-port value, so hasNode() compares
hosts case-insensitively while preserving the existing fallback behavior. Add a
regression test covering mixed-case URLs that represent the same Monero node.

qrScannerEnabled = true,
onValueChange = viewModel::onEnterRpcUrl,
hint = "",
hint = "https://node.com:port",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use a localized, copy-paste-valid hint.

The hardcoded https://node.com:port string cannot be translated, and port is not a valid numeric port. Add a string resource using an example such as https://node.com:18081, then pass it through stringResource(...).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@walletkit/src/main/java/io/horizontalsystems/walletkit/modules/moneronetwork/addnode/AddMoneroNodeScreen.kt`
at line 65, Replace the hardcoded hint in AddMoneroNodeScreen with a localized
string resource containing a copy-paste-valid example such as
https://node.com:18081, and pass that resource through stringResource(...).

Comment on lines +61 to +65
if (sourceUri.port == -1) {
urlCaution = Caution(Translator.getString(R.string.AddMoneroNode_Error_PortRequired), Caution.Type.Error)
emitState()
return
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="walletkit/src/main/java/io/horizontalsystems/walletkit/modules/moneronetwork/addnode/AddMoneroNodeViewModel.kt"

echo "== File outline =="
ast-grep outline "$file" --view expanded || true

echo
echo "== Relevant lines =="
nl -ba "$file" | sed -n '1,140p'

echo
echo "== Search for similar port validation =="
rg -n "port == -1|port in 1..65535|hasNode\\(|sourceUri\\.port" walletkit/src/main/java || true

echo
echo "== Java URI port semantics probe =="
python3 - <<'PY'
from urllib.parse import urlparse

# Python URL parser isn't the target, so just document intended checks here.
# Actual Java URI semantics are probed by compiling against the JDK in a tiny JShell-free way.
print("Python urlparse not used for Java URI semantics.")
PY

cat > /tmp/UriPortProbe.java <<'JAVA'
import java.net.URI;

public class UriPortProbe {
    public static void main(String[] args) throws Exception {
        String[] uris = {
            "http://example.com",
            "http://example.com:0",
            "http://example.com:1",
            "http://example.com:65535",
            "http://example.com:65536",
            "http://example.com:-1"
        };
        for (String s : uris) {
            try {
                URI u = URI.create(s);
                System.out.println(s + " -> port=" + u.getPort());
            } catch (Exception e) {
                System.out.println(s + " -> EXCEPTION: " + e.getClass().getSimpleName() + ": " + e.getMessage());
            }
        }
    }
}
JAVA

javac /tmp/UriPortProbe.java && java -cp /tmp UriPortProbe

Repository: horizontalsystems/unstoppable-wallet-android

Length of output: 895


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="walletkit/src/main/java/io/horizontalsystems/walletkit/modules/moneronetwork/addnode/AddMoneroNodeViewModel.kt"

echo "== File contents (focused) =="
sed -n '1,140p' "$file"

echo
echo "== Java URI port probe =="
cat > /tmp/UriPortProbe.java <<'JAVA'
import java.net.URI;

public class UriPortProbe {
    public static void main(String[] args) {
        String[] uris = {
            "http://example.com",
            "http://example.com:0",
            "http://example.com:1",
            "http://example.com:65535",
            "http://example.com:65536",
            "http://example.com:-1"
        };

        for (String s : uris) {
            try {
                URI u = URI.create(s);
                System.out.println(s + " -> port=" + u.getPort());
            } catch (Exception e) {
                System.out.println(s + " -> EXCEPTION " + e.getClass().getSimpleName() + ": " + e.getMessage());
            }
        }
    }
}
JAVA

javac /tmp/UriPortProbe.java && java -cp /tmp UriPortProbe

Repository: horizontalsystems/unstoppable-wallet-android

Length of output: 2918


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n "fun addMoneroNode|class MoneroNodeManager|hasNode\\(|addMoneroNode\\(" walletkit/src/main/java

echo
echo "== MoneroNodeManager slice =="
file="$(rg -l "class MoneroNodeManager|fun addMoneroNode" walletkit/src/main/java | head -n 1)"
sed -n '1,220p' "$file"

Repository: horizontalsystems/unstoppable-wallet-android

Length of output: 9272


Reject port 0 here. sourceUri.port == -1 still lets https://host:0 through, and that value is persisted as-is. Check sourceUri.port in 1..65535 before saving.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@walletkit/src/main/java/io/horizontalsystems/walletkit/modules/moneronetwork/addnode/AddMoneroNodeViewModel.kt`
around lines 61 - 65, Update the port validation in the add-node flow around
sourceUri and before persistence to accept only values in 1..65535. Reject port
0 and any out-of-range value with the existing AddMoneroNode_Error_PortRequired
caution, emit the state, and return before saving.

@omurovch omurovch closed this Jul 13, 2026
@omurovch omurovch deleted the custom-node branch July 13, 2026 11:08
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.

1 participant