Skip to content

Require port for Monero node URLs#9386

Closed
omurovch wants to merge 4 commits into
version/0.50from
add-node
Closed

Require port for Monero node URLs#9386
omurovch wants to merge 4 commits into
version/0.50from
add-node

Conversation

@omurovch

@omurovch omurovch commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

omurovch and others added 4 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.
Passing base64-encoded contents of large `strings.xml` files as command-line arguments to `jq` can exceed the kernel's 128KB per-argument limit (`MAX_ARG_STRLEN`), causing the workflow to fail.

Update the script to write encoded file contents to temporary files and use `jq`'s `--rawfile` and `--slurpfile` flags to process the data, avoiding the argument length restriction.
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The translation workflow now constructs GraphQL file additions from temporary JSONL data. Monero node handling normalizes endpoints, requires explicit ports during addition, updates localized validation text, and displays a URL example.

Changes

Translation commit payload

Layer / File(s) Summary
Translation payload and snapshot updates
.github/workflows/translate.yml, translation_snapshot.json
The workflow builds and validates file additions through temporary JSONL and jq file inputs; the snapshot adds Monero port validation and “Manage Wallet” translations.

Monero node validation

Layer / File(s) Summary
Canonical Monero endpoint handling
walletkit/src/main/java/io/horizontalsystems/walletkit/core/managers/MoneroNodeManager.kt
Node serialization and existence checks use normalized host:port endpoints, with port 443 applied when absent.
Add-node URL validation
walletkit/src/main/java/io/horizontalsystems/walletkit/modules/moneronetwork/addnode/..., walletkit/src/main/res/values/strings.xml
The add-node screen shows a URL example, rejects URLs without explicit ports, uses normalized duplicate detection, and displays the new localized error.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant AddMoneroNodeScreen
  participant AddMoneroNodeViewModel
  participant MoneroNodeManager
  participant LocalizationResources
  User->>AddMoneroNodeScreen: Enter RPC node URL
  AddMoneroNodeScreen->>AddMoneroNodeViewModel: Submit URL
  AddMoneroNodeViewModel->>AddMoneroNodeViewModel: Parse URL and validate explicit port
  AddMoneroNodeViewModel->>LocalizationResources: Request port-required error
  AddMoneroNodeViewModel->>MoneroNodeManager: Check normalized endpoint with hasNode(url)
  MoneroNodeManager-->>AddMoneroNodeViewModel: Return node existence
  AddMoneroNodeViewModel-->>AddMoneroNodeScreen: Emit caution or continue state
Loading

Possibly related PRs

Suggested reviewers: rafaelekol

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Title check ✅ Passed The title clearly matches the main change: Monero node URLs now must include an explicit port.
✨ 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 add-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: 2

🧹 Nitpick comments (1)
walletkit/src/main/java/io/horizontalsystems/walletkit/modules/moneronetwork/addnode/AddMoneroNodeScreen.kt (1)

65-65: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Move the URL hint into a string resource.

This user-facing text bypasses localization and the translation workflow. Add an AddMoneroNode_NodeUrlHint resource and use stringResource(...) here.

🤖 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, Move the hardcoded URL hint from the AddMoneroNode screen’s input
configuration into the localized string resources as AddMoneroNode_NodeUrlHint,
then replace the literal with stringResource(...) at the existing hint
assignment.
🤖 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 @.github/workflows/translate.yml:
- Line 60: Update the count validation in the workflow step so a mismatch emits
a clear diagnostic containing the additions count and files count before exiting
nonzero. Preserve successful validation behavior and ensure the failure path
does not rely on a bare test command under set -e.

In
`@walletkit/src/main/java/io/horizontalsystems/walletkit/core/managers/MoneroNodeManager.kt`:
- Around line 157-160: Update endpoint() to lowercase the parsed Uri.host using
Locale.ROOT before constructing the host-and-port endpoint, ensuring
casing-insensitive values compare consistently in hasNode(). Add a regression
test covering equivalent uppercase and lowercase Monero node URLs.

---

Nitpick comments:
In
`@walletkit/src/main/java/io/horizontalsystems/walletkit/modules/moneronetwork/addnode/AddMoneroNodeScreen.kt`:
- Line 65: Move the hardcoded URL hint from the AddMoneroNode screen’s input
configuration into the localized string resources as AddMoneroNode_NodeUrlHint,
then replace the literal with stringResource(...) at the existing hint
assignment.
🪄 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: d8f6f0f0-39a5-471b-b89f-bd3e859a4646

📥 Commits

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

⛔ Files ignored due to path filters (9)
  • walletkit/src/main/res/values-de/strings.xml is excluded by !**/res/values-*/strings.xml
  • walletkit/src/main/res/values-es/strings.xml is excluded by !**/res/values-*/strings.xml
  • walletkit/src/main/res/values-fa/strings.xml is excluded by !**/res/values-*/strings.xml
  • walletkit/src/main/res/values-fr/strings.xml is excluded by !**/res/values-*/strings.xml
  • walletkit/src/main/res/values-ko/strings.xml is excluded by !**/res/values-*/strings.xml
  • walletkit/src/main/res/values-pt-rBR/strings.xml is excluded by !**/res/values-*/strings.xml
  • walletkit/src/main/res/values-ru/strings.xml is excluded by !**/res/values-*/strings.xml
  • walletkit/src/main/res/values-tr/strings.xml is excluded by !**/res/values-*/strings.xml
  • walletkit/src/main/res/values-zh/strings.xml is excluded by !**/res/values-*/strings.xml
📒 Files selected for processing (6)
  • .github/workflows/translate.yml
  • translation_snapshot.json
  • 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

jq -n --arg path "$f" --rawfile contents "$RUNNER_TEMP/file.b64" \
'{path: $path, contents: $contents}' >> "$additions"
done <<< "$files"
[ "$(jq -s length "$additions")" -eq "$(echo "$files" | wc -l)" ]

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

Count validation exits silently on mismatch.

Under GitHub Actions' default set -e, a failed [ ... -eq ... ] exits the script with no diagnostic output, making failures hard to debug.

🔧 Suggested fix
-          [ "$(jq -s length "$additions")" -eq "$(echo "$files" | wc -l)" ]
+          count_jsonl=$(jq -s length "$additions")
+          count_files=$(echo "$files" | wc -l)
+          if [ "$count_jsonl" -ne "$count_files" ]; then
+            echo "Error: JSONL record count ($count_jsonl) != file count ($count_files)" >&2
+            exit 1
+          fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[ "$(jq -s length "$additions")" -eq "$(echo "$files" | wc -l)" ]
count_jsonl=$(jq -s length "$additions")
count_files=$(echo "$files" | wc -l)
if [ "$count_jsonl" -ne "$count_files" ]; then
echo "Error: JSONL record count ($count_jsonl) != file count ($count_files)" >&2
exit 1
fi
🤖 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 @.github/workflows/translate.yml at line 60, Update the count validation in
the workflow step so a mismatch emits a clear diagnostic containing the
additions count and files count before exiting nonzero. Preserve successful
validation behavior and ensure the failure path does not rely on a bare test
command under set -e.

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

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

# Map the target file
ast-grep outline walletkit/src/main/java/io/horizontalsystems/walletkit/core/managers/MoneroNodeManager.kt --view expanded || true

# Read the relevant section with line numbers
sed -n '1,260p' walletkit/src/main/java/io/horizontalsystems/walletkit/core/managers/MoneroNodeManager.kt | cat -n

# Search for endpoint comparison / normalization and tests
rg -n "endpoint\\(|toUri\\(|effectivePort\\(|host\\.|lowercase|Locale\\.ROOT|MoneroNodeManager" walletkit/src/main/java walletkit/src/test walletkit/src/androidTest || true

Repository: horizontalsystems/unstoppable-wallet-android

Length of output: 27091


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect Monero add-node flow and any related normalization helpers
sed -n '1,220p' walletkit/src/main/java/io/horizontalsystems/walletkit/modules/moneronetwork/addnode/AddMoneroNodeViewModel.kt | cat -n
sed -n '1,220p' walletkit/src/main/java/io/horizontalsystems/walletkit/modules/zcashnetwork/addendpoint/AddZcashEndpointViewModel.kt | cat -n
sed -n '1,220p' walletkit/src/main/java/io/horizontalsystems/walletkit/modules/moneronetwork/MoneroNetworkViewModel.kt | cat -n

# Probe Android Uri host behavior if the sandbox has a suitable Kotlin/JVM setup; otherwise fall back to docs-free text inspection
python3 - <<'PY'
from urllib.parse import urlparse

samples = [
    "https://NODE.EXAMPLE:18081",
    "NODE.EXAMPLE:18081",
    "https://node.example:18081",
]
for s in samples:
    u = urlparse(s if "://" in s else "https://" + s)
    print(s, "-> hostname:", u.hostname, "netloc:", u.netloc)
PY

Repository: horizontalsystems/unstoppable-wallet-android

Length of output: 12416


🌐 Web query:

Android Uri.getHost case normalization host lowercase documentation

💡 Result:

The Android android.net.Uri.getHost method does not automatically normalize the host component to lowercase [1][2]. It returns the host exactly as it is encoded within the authority component of the URI [1][2]. Because this method does not perform case normalization, developers are responsible for handling case sensitivity when validating or comparing hostnames [3]. Official Android security documentation emphasizes that when validating hosts (for example, to prevent unsafe URI loading), you should perform robust validation on the host string returned by getHost rather than relying on internal normalization [3]. In contrast, the Java standard library's java.net.URI class documentation indicates that while its getHost method also returns the host component, equality checks for hierarchical URIs (using.equals) do compare hosts without regard to case [4]. Note that android.net.Uri and java.net.URI are distinct classes with different behaviors, and android.net.Uri is generally the preferred class for handling URIs within Android applications [1][2]. If you need a normalized scheme for intent filtering, android.net.Uri provides a separate normalizeScheme method, but this method specifically targets the scheme component and does not affect the host [5].

Citations:


Lowercase Monero node endpoints before comparing them.
endpoint() preserves the host casing from Uri.host, so https://NODE.EXAMPLE:18081 can bypass hasNode() next to https://node.example:18081. Lowercase the parsed host with Locale.ROOT before building the endpoint, and add a regression test.

🤖 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 - 160, Update endpoint() to lowercase the parsed Uri.host using
Locale.ROOT before constructing the host-and-port endpoint, ensuring
casing-insensitive values compare consistently in hasNode(). Add a regression
test covering equivalent uppercase and lowercase Monero node URLs.

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

2 participants