Require port for Monero node URLs#9383
Conversation
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.
📝 WalkthroughWalkthroughMonero 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. ChangesMonero node validation
Estimated code review effort: 2 (Simple) | ~10 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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
⛔ Files ignored due to path filters (1)
walletkit/src/main/res/values-fa/strings.xmlis excluded by!**/res/values-*/strings.xml
📒 Files selected for processing (4)
walletkit/src/main/java/io/horizontalsystems/walletkit/core/managers/MoneroNodeManager.ktwalletkit/src/main/java/io/horizontalsystems/walletkit/modules/moneronetwork/addnode/AddMoneroNodeScreen.ktwalletkit/src/main/java/io/horizontalsystems/walletkit/modules/moneronetwork/addnode/AddMoneroNodeViewModel.ktwalletkit/src/main/res/values/strings.xml
| 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 } |
There was a problem hiding this comment.
🎯 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 . || trueRepository: 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 . || trueRepository: 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", |
There was a problem hiding this comment.
📐 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(...).
| if (sourceUri.port == -1) { | ||
| urlCaution = Caution(Translator.getString(R.string.AddMoneroNode_Error_PortRequired), Caution.Type.Error) | ||
| emitState() | ||
| return | ||
| } |
There was a problem hiding this comment.
🎯 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 UriPortProbeRepository: 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 UriPortProbeRepository: 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.
Summary by CodeRabbit
New Features
Bug Fixes