Skip to content

fix: add error handing for limit mismatch #1390

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
May 20, 2025

Conversation

HashEngineering
Copy link
Collaborator

@HashEngineering HashEngineering commented May 8, 2025

Issue being fixed or feature implemented

Related PR's and Dependencies

Screenshots / Videos

How Has This Been Tested?

  • QA (Mobile Team)

Checklist:

  • I have performed a self-review of my own code and added comments where necessary
  • I have added or updated relevant unit/integration/functional/e2e tests

Summary by CodeRabbit

  • New Features

    • Added specialized error handling for gift card purchase limit errors, including a new dialog with an option to contact CTX Support directly.
    • Introduced the ability to generate and send a detailed support email when encountering specific purchase errors.
  • Improvements

    • Enhanced error messages and support contact options for users experiencing merchant limit changes during gift card purchases.
  • Bug Fixes

    • Updated and consolidated string resources related to reporting issues and contacting support.

@HashEngineering HashEngineering self-assigned this May 8, 2025
Copy link
Contributor

coderabbitai bot commented May 8, 2025

Walkthrough

The changes introduce enhanced error handling for gift card purchases, specifically detecting and responding to spending limit errors. New string resources and constants support user messaging and reporting via email. The dialog now offers users a direct way to contact support when a limit error occurs, with structured error details included in the report. Additionally, unit tests were added to verify the new exception behavior.

Changes

File(s) Change Summary
common/src/main/res/values/strings.xml, wallet/res/values/strings.xml Moved the string resource report_issue_dialog_mail_intent_chooser from wallet/res/values/strings.xml to common/src/main/res/values/strings.xml.
features/exploredash/src/main/res/values/strings-explore-dash.xml Added two new string resources: gift_card_limit_error (limit error message) and gift_card_contact_ctx (support contact label).
features/exploredash/src/main/java/org/dash/wallet/features/exploredash/utils/CTXSpendConstants.kt Added new constant REPORT_EMAIL for CTX support email address.
features/exploredash/src/main/java/org/dash/wallet/features/exploredash/repository/CTXSpendRepository.kt Enhanced CTXSpendException to include error code, error body, error parsing, and a computed property isLimitError for structured error handling.
features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ctxspend/CTXSpendViewModel.kt Modified purchaseGiftCard to throw CTXSpendException with detailed error info; added createEmailIntent and createReportEmail for generating support emails with detailed error context.
features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ctxspend/dialogs/PurchaseGiftCardConfirmDialog.kt Refactored error handling to detect limit errors and present a dialog with an option to contact support, launching an email intent chooser via an activity result launcher.
features/exploredash/src/test/java/org/dash/wallet/features/exploredash/CTXSpendExceptionTest.kt Added unit tests for CTXSpendException to verify error code parsing and limit error detection.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Dialog
    participant ViewModel
    participant Repository
    participant EmailApp

    User->>Dialog: Confirm gift card purchase
    Dialog->>ViewModel: purchaseGiftCard()
    ViewModel->>Repository: Attempt purchase
    Repository-->>ViewModel: Throw CTXSpendException (limit error)
    ViewModel-->>Dialog: Exception thrown
    Dialog->>User: Show limit error dialog with "Contact CTX Support"
    User->>Dialog: Click "Contact CTX Support"
    Dialog->>ViewModel: createEmailIntent(subject, exception)
    ViewModel-->>Dialog: Email Intent
    Dialog->>EmailApp: Launch email intent chooser
Loading

Poem

In the warren of code, a new path appears,
With buttons for help when the limit nears.
If your gift card fails, don’t fret or frown—
A hop to support will smooth things down!
With emails sent swift, and errors in tow,
This bunny ensures the fixes will flow.
🐇📧✨

Note

⚡️ AI Code Reviews for VS Code, Cursor, Windsurf

CodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback.
Learn more here.


Note

⚡️ Faster reviews with caching

CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure Review - Disable Cache at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the Data Retention setting under your Organization Settings.
Enjoy the performance boost—your workflow just got faster.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 1b1ccfe and ba5c673.

📒 Files selected for processing (1)
  • features/exploredash/src/test/java/org/dash/wallet/features/exploredash/CTXSpendExceptionTest.kt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • features/exploredash/src/test/java/org/dash/wallet/features/exploredash/CTXSpendExceptionTest.kt
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@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

🧹 Nitpick comments (4)
features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ctxspend/CTXSpendViewModel.kt (1)

159-159: Remove commented out else branch.

The commented-out else branch should be removed as it's unnecessary and creates noise in the code.

-                //else -> {}
features/exploredash/src/main/java/org/dash/wallet/features/exploredash/repository/CTXSpendRepository.kt (1)

53-55: Improve type safety in nested map traversal

The nested map traversal to determine isLimitError uses multiple unsafe casts which could lead to issues with unexpected JSON structures.

Consider using a more explicit traversal:

val isLimitError
    get() = errorCode == 400 &&
-       ((errorMap["fields"] as? Map<*, *>)?.get("fiatAmount") as? List<*>)?.firstOrNull() == "above threshold"
+       errorMap["fields"]?.let { fields ->
+           when (fields) {
+               is Map<*, *> -> fields["fiatAmount"]?.let { fiatAmount ->
+                   when (fiatAmount) {
+                       is List<*> -> fiatAmount.firstOrNull() == "above threshold"
+                       else -> false
+                   }
+               } ?: false
+               else -> false
+           }
+       } ?: false

Or use an extension function for more readable code:

private fun Map<String, Any>.getNestedValue(path: List<String>): Any? {
    var current: Any? = this
    for (key in path) {
        current = (current as? Map<*, *>)?.get(key)
        if (current == null) return null
    }
    return current
}
features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ctxspend/dialogs/PurchaseGiftCardConfirmDialog.kt (2)

111-140: Comprehensive error handling for limit errors

Good implementation of specialized error handling for spending limit errors, with a dedicated UI flow for contacting support.

However, there's a TODO comment on line 121 that should be addressed:

- // TODO: share

Also, consider providing more informative error messages to the user about:

  1. What the spending limit is
  2. When they can try again
  3. What information will be included in the support email

127-128: Use string resources for email subject

The email subject "CTX Issue: Spending Limit Problem" is hardcoded rather than using a string resource.

Consider moving this to a string resource:

+// Add to strings-explore-dash.xml:
+<string name="gift_card_limit_error_email_subject">CTX Issue: Spending Limit Problem</string>

// In code:
-"CTX Issue: Spending Limit Problem",
+getString(R.string.gift_card_limit_error_email_subject),
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8da553c and 4aed1d2.

📒 Files selected for processing (7)
  • common/src/main/res/values/strings.xml (1 hunks)
  • features/exploredash/src/main/java/org/dash/wallet/features/exploredash/repository/CTXSpendRepository.kt (2 hunks)
  • features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ctxspend/CTXSpendViewModel.kt (4 hunks)
  • features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ctxspend/dialogs/PurchaseGiftCardConfirmDialog.kt (4 hunks)
  • features/exploredash/src/main/java/org/dash/wallet/features/exploredash/utils/CTXSpendConstants.kt (1 hunks)
  • features/exploredash/src/main/res/values/strings-explore-dash.xml (2 hunks)
  • wallet/res/values/strings.xml (0 hunks)
💤 Files with no reviewable changes (1)
  • wallet/res/values/strings.xml
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (10)
features/exploredash/src/main/java/org/dash/wallet/features/exploredash/utils/CTXSpendConstants.kt (1)

25-25: LGTM: Support email constant added.

The addition of this constant is appropriate for centralizing the support email address used in error reporting.

common/src/main/res/values/strings.xml (1)

113-113: LGTM: String resource for email intent chooser.

This string resource is appropriately positioned and will be used when launching the email client selection dialog.

features/exploredash/src/main/res/values/strings-explore-dash.xml (2)

231-231: LGTM: Clear error message for limit errors.

This string resource provides a specific error message for the purchase limit error case, directing users to contact support.


241-241: LGTM: Support contact button text.

This string resource will be used for the button to contact CTX support, providing a clear action for users.

features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ctxspend/CTXSpendViewModel.kt (3)

153-158: LGTM: Enhanced error handling.

The improved error handling now includes error code and error body in the exception, which provides more context for better troubleshooting.


294-303: LGTM: Email intent creation.

This function creates a properly formatted email intent with the support email address, subject, and report body.


305-332: LGTM: Detailed report email generation.

This function generates a comprehensive error report including merchant details, purchase amount, and error information, which will be extremely helpful for troubleshooting.

features/exploredash/src/main/java/org/dash/wallet/features/exploredash/repository/CTXSpendRepository.kt (1)

36-40: Enhanced error handling with structured data

Good enhancement to the CTXSpendException class by adding errorCode and errorBody parameters. This allows for more precise error handling and diagnosis.

features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ctxspend/dialogs/PurchaseGiftCardConfirmDialog.kt (2)

70-72: Good implementation of Activity Result API

Using the modern Activity Result API is a good practice for handling intent results.


122-129:

❓ Verification inconclusive

Validate email intent launch

The email intent may not resolve if the user doesn't have an email app installed.


🏁 Script executed:

#!/bin/bash
# Check if the launcher.launch() call is handling cases where no email app is installed

# Look for Intent.resolveActivity() check or similar validation
rg -A 5 -B 5 "createEmailIntent|Intent.createChooser" --type kotlin

Length of output: 8455


I need to inspect the dialog’s Kotlin code around the intent launch to confirm whether it guards against missing email apps. Let me pull the surrounding lines.

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Contributor

@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: 0

🔭 Outside diff range comments (1)
features/exploredash/src/main/java/org/dash/wallet/features/exploredash/repository/CTXSpendRepository.kt (1)

111-118: 💡 Verification agent

🧩 Analysis chain

Verify hardcoded currency values

The purchaseGiftCard method uses hardcoded values "DASH" for cryptoCurrency and "USD" for fiatCurrency instead of using the parameters passed to the function.

Is this intentional? The implementation ignores the function parameters and always uses hardcoded values. This could limit the functionality if multiple currencies need to be supported.


🏁 Script executed:

#!/bin/bash
# Investigate if these hardcoded values are intentional by checking:
# 1. If there are other usages of this function with different currencies
# 2. If there are related TODO comments or discussions

# Check for usages of this function with different currency parameters
echo "Checking for usages of purchaseGiftCard with different currencies:"
rg "purchaseGiftCard\(.+,.+,.+,.+\)" -A 1 -B 1

# Check for any related TODOs about currency hardcoding
echo "Checking for related TODOs about currency hardcoding:"
rg "TODO.*currency" -i

Length of output: 333


#!/bin/bash
# Locate CTXSpendRepository.kt and inspect the repository's purchaseGiftCard function signature
file=$(fd CTXSpendRepository.kt)
echo "File located at: $file"
echo "Extracting signature and parameters of repository's purchaseGiftCard method:"
rg "fun purchaseGiftCard" -n "$file" -A 3 -B 1

🏁 Script executed:

#!/bin/bash
# Locate CTXSpendRepository.kt and inspect the purchaseGiftCard function signature
repo_file=$(fd CTXSpendRepository.kt)
echo "CTXSpendRepository.kt path: $repo_file"
rg -n "fun purchaseGiftCard" -A3 -B1 "$repo_file"

Length of output: 889


Replace hardcoded currency values with method parameters

In features/exploredash/src/main/java/org/dash/wallet/features/exploredash/repository/CTXSpendRepository.kt (lines 111–118), the override of purchaseGiftCard ignores its cryptoCurrency and fiatCurrency parameters and always uses "DASH"/"USD". This breaks multi-currency support.

• File: features/exploredash/src/main/java/org/dash/wallet/features/exploredash/repository/CTXSpendRepository.kt
Lines 111–118

Suggested fix:

- api.purchaseGiftCard(
-     purchaseGiftCardRequest = PurchaseGiftCardRequest(
-         cryptoCurrency = "DASH",
-         fiatCurrency = "USD",
-         fiatAmount    = fiatAmount,
-         merchantId    = merchantId
-     )
- )
+ api.purchaseGiftCard(
+     purchaseGiftCardRequest = PurchaseGiftCardRequest(
+         cryptoCurrency = cryptoCurrency,
+         fiatCurrency   = fiatCurrency,
+         fiatAmount     = fiatAmount,
+         merchantId     = merchantId
+     )
+ )

Or, if only DASH/USD are supported, remove the unused parameters from the method signature.

🧹 Nitpick comments (2)
features/exploredash/src/main/java/org/dash/wallet/features/exploredash/repository/CTXSpendRepository.kt (2)

56-58: Consider logging the swallowed exception

While providing a default empty map is appropriate for error recovery, the caught exception is swallowed without any logging, which might make debugging difficult in case of unexpected JSON parsing errors.

        } catch (e: Exception) {
+           Log.w("CTXSpendException", "Failed to parse error body", e)
            emptyMap()
        }
🧰 Tools
🪛 detekt (1.23.7)

[warning] 56-56: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)


61-63: Consider improving readability of nested property access

The property access chain with multiple casts and null checks is complex and could be improved for better readability and maintainability.

    val isLimitError
        get() = errorCode == 400 &&
-            ((errorMap["fields"] as? Map<*, *>)?.get("fiatAmount") as? List<*>)?.firstOrNull() == "above threshold"
+            getNestedErrorValue("fields", "fiatAmount") == "above threshold"
+
+    @Suppress("UNCHECKED_CAST")
+    private fun getNestedErrorValue(firstKey: String, secondKey: String): String? {
+        val fieldsMap = errorMap[firstKey] as? Map<*, *> ?: return null
+        val valueList = fieldsMap[secondKey] as? List<*> ?: return null
+        return valueList.firstOrNull() as? String
+    }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4aed1d2 and e70e874.

📒 Files selected for processing (1)
  • features/exploredash/src/main/java/org/dash/wallet/features/exploredash/repository/CTXSpendRepository.kt (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: HashEngineering
PR: dashpay/dash-wallet#1390
File: features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ctxspend/CTXSpendViewModel.kt:129-145
Timestamp: 2025-05-08T18:11:40.208Z
Learning: The hardcoded test data in the purchaseGiftCard() function of CTXSpendViewModel is intentionally left in place for testing the error handling for limit mismatch, and will be fixed later before release.
🪛 detekt (1.23.7)
features/exploredash/src/main/java/org/dash/wallet/features/exploredash/repository/CTXSpendRepository.kt

[warning] 56-56: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (1)
features/exploredash/src/main/java/org/dash/wallet/features/exploredash/repository/CTXSpendRepository.kt (1)

36-59: Good implementation of error handling with proper JSON parsing

The changes to the CTXSpendException class properly implement error handling for limit mismatch scenarios. The implementation correctly follows the previous review suggestion for safe JSON parsing with appropriate null checks and exception handling.

🧰 Tools
🪛 detekt (1.23.7)

[warning] 56-56: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)

Copy link
Contributor

@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: 1

🧹 Nitpick comments (1)
features/exploredash/src/test/java/org/dash/wallet/features/exploredash/CTXSpendExceptionTest.kt (1)

25-41: Consider testing additional limit error conditions.

The current test only verifies "above threshold" limit errors. Based on the PR objectives, there are likely other limit conditions (like "below threshold") that should also be tested.

@Test
fun limitErrorTest() {
    val errorBody = """
        {
          "fields": {
            "fiatAmount": [
              "above threshold"
            ],
            "message": "Bad request"
          }
        }
    """
    val exception = CTXSpendException("response error", 400, errorBody)
    assertEquals(400, exception.errorCode)
    assertTrue(exception.isLimitError)
+
+    // Test "below threshold" limit error
+    val belowThresholdErrorBody = """
+        {
+          "fields": {
+            "fiatAmount": [
+              "below threshold"
+            ],
+            "message": "Bad request"
+          }
+        }
+    """
+    val belowThresholdException = CTXSpendException("response error", 400, belowThresholdErrorBody)
+    assertEquals(400, belowThresholdException.errorCode)
+    assertTrue(belowThresholdException.isLimitError)
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 6c5e381 and 1b1ccfe.

📒 Files selected for processing (3)
  • features/exploredash/src/main/java/org/dash/wallet/features/exploredash/repository/CTXSpendRepository.kt (2 hunks)
  • features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ctxspend/CTXSpendViewModel.kt (4 hunks)
  • features/exploredash/src/test/java/org/dash/wallet/features/exploredash/CTXSpendExceptionTest.kt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • features/exploredash/src/main/java/org/dash/wallet/features/exploredash/ui/ctxspend/CTXSpendViewModel.kt
  • features/exploredash/src/main/java/org/dash/wallet/features/exploredash/repository/CTXSpendRepository.kt
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (3)
features/exploredash/src/test/java/org/dash/wallet/features/exploredash/CTXSpendExceptionTest.kt (3)

1-15: LGTM: Standard license header.

The license header is well-formed and includes appropriate copyright and GPL licensing information.


17-23: Appropriate imports.

All necessary imports are included for the test class, including the target exception class and JUnit test assertions.


43-48: LGTM: Effectively tests non-limit error case.

The test appropriately verifies that non-limit errors are correctly identified when no error code is provided.

@HashEngineering HashEngineering requested a review from Syn-McJ May 18, 2025 07:21
Copy link
Member

@Syn-McJ Syn-McJ left a comment

Choose a reason for hiding this comment

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

Looks good

@HashEngineering HashEngineering added this to the 11.3 milestone May 19, 2025
@HashEngineering HashEngineering merged commit c6e05e7 into master May 20, 2025
3 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Jul 30, 2025
3 tasks
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