Skip to content

feat: handle maya halted coins#1469

Merged
HashEngineering merged 7 commits intofeature-mayafrom
feat/maya-halted-coins
Mar 10, 2026
Merged

feat: handle maya halted coins#1469
HashEngineering merged 7 commits intofeature-mayafrom
feat/maya-halted-coins

Conversation

@HashEngineering
Copy link
Collaborator

@HashEngineering HashEngineering commented Mar 6, 2026

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 visual indicators and disabled state handling for halted coins in Maya crypto currency selection.
    • Enhanced radio button UI with enabled/disabled state support and customizable action button styling.
  • Documentation

    • Added comprehensive Maya Protocol integration documentation.
  • Bug Fixes

    • Improved null safety in Maya crypto conversion flow.

@HashEngineering HashEngineering self-assigned this Mar 6, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 6, 2026

📝 Walkthrough

Walkthrough

The pull request enhances the Dash Wallet UI with radio group styling for action buttons (enabled/disabled states, custom colors) and significantly expands the Maya integration by adding Parcelable support across model classes, improving state management with StateFlow reactivity, and implementing a halted coins indicator in the currency picker interface.

Changes

Cohort / File(s) Summary
Radio Group UI Enhancements
common/.../IconifiedViewItem.kt, common/.../RadioGroupAdapter.kt
Added three new properties (isEnabled, actionBackgroundColor, actionTextColor) to IconifiedViewItem data class. RadioGroupAdapter now applies custom text/background colors to action buttons and dims UI elements when disabled.
Model Parcelable Support
integrations/maya/src/main/java/org/dash/wallet/integrations/maya/model/{CurrencyBeaconResponse, ExchangeRateResponse, FreeCurrencyResponse, InboundAddress, NetworkResponse, PoolInfo, SwapTransactionInfo}.kt
Added @Parcelize annotation and Parcelable implementation to seven model classes. InboundAddress and PoolInfo gained default parameter values. NetworkResponse added two new fields (gasWithheldCacao, outboundFeeMultiplier). SwapTransactionInfo's KeysignMetric uses @RawValue annotation for nodeTssTimes field.
Maya Configuration & ProGuard
integrations/maya/build.gradle, integrations/maya/proguard-rules.pro
Added lifecycle-runtime-compose dependency, lint suppression for NullSafeMutableLiveData, and ProGuard rules preserving Maya model constructors/members for Gson deserialization.
Maya Fragment & ViewModel State Management
integrations/maya/src/main/java/org/dash/wallet/integrations/maya/ui/{MayaConvertCryptoFragment, MayaCryptoCurrencyPickerFragment}.kt, integrations/maya/src/main/java/org/dash/wallet/integrations/maya/ui/MayaViewModel.kt
Changed inboundAddresses from mutable list to MutableStateFlow. Added hasHaltedCoins StateFlow observable. MayaCryptoCurrencyPickerFragment now combines poolList and inboundAddresses reactively, filters halted coins, and updates FullDiffCallback logic. MayaConvertCryptoFragment improved null-safety by safely resolving DASH address from inbound addresses.
Maya UI Resources
integrations/maya/src/main/res/layout/fragment_currency_picker.xml, integrations/maya/src/main/res/values/strings-maya.xml
Added ComposeView for halted coins toast notification with constraints and margin. Added two string resources (maya_halted_label, maya_halted_coins_toast).
Documentation & Minor Updates
integrations/maya/MAYA_PROTOCOL.md, features/exploredash/.../FakeDashSpendService.kt, wallet/build.gradle, wallet/.../BlockchainServiceImpl.kt
Added comprehensive MAYA_PROTOCOL.md documentation describing protocol integration. Removed whitespace in FakeDashSpendService. Added lint suppression in wallet build.gradle. Uncommented diagnostic log statement in BlockchainServiceImpl.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 The coins now dance with halted grace,
Their states cascading through the space,
Parceled safe in streams that flow,
While radios wear colors bright and low.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main feature: adding Maya halted coins handling across UI, model, and state management layers.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/maya-halted-coins

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.

@HashEngineering
Copy link
Collaborator Author

@coderabbitai review

1 similar comment
@HashEngineering
Copy link
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 6, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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: 5

Caution

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

⚠️ Outside diff range comments (1)
common/src/main/java/org/dash/wallet/common/ui/radio_group/RadioGroupAdapter.kt (1)

65-73: ⚠️ Potential issue | 🟠 Major

Disabled items remain clickable.

The isEnabled flag controls visual appearance (alpha at lines 225-229), but the click listener still fires for disabled items. Based on the usage in MayaCryptoCurrencyPickerFragment, halted coins set isEnabled = false but users can still tap and select them.

🔧 Proposed fix to block clicks on disabled items
         holder.binding.root.setOnClickListener {
+            val item = getItem(holder.adapterPosition)
+            if (!item.isEnabled) return@setOnClickListener
+
             if (holder.adapterPosition != selectedIndex) {
                 notifyItemChanged(selectedIndex)
                 selectedIndex = holder.adapterPosition
                 notifyItemChanged(holder.adapterPosition)
             }

-            clickListener.invoke(item, position)
+            clickListener.invoke(item, holder.adapterPosition)
         }

Note: If some consumers need to handle disabled item clicks differently (e.g., show a toast explaining why it's disabled), consider adding a separate disabledClickListener callback instead.

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

In
`@common/src/main/java/org/dash/wallet/common/ui/radio_group/RadioGroupAdapter.kt`
around lines 65 - 73, The click handler on holder.binding.root currently always
runs even when the item is disabled; update the listener in RadioGroupAdapter
(the block that sets holder.binding.root.setOnClickListener) to first check the
item's isEnabled flag and return early (or skip selection change and
clickListener.invoke) when false. Ensure selectedIndex and notifyItemChanged
calls only happen for enabled items, and keep clickListener.invoke(item,
position) gated by the same check; if you need alternate behavior for disabled
taps, add a separate disabledClickListener callback instead of invoking the
normal click path.
🧹 Nitpick comments (1)
wallet/src/de/schildbach/wallet/service/BlockchainServiceImpl.kt (1)

527-532: Consider using log.debug and simplifying the log message.

This log statement fires for every monitored transaction on each new block, which can generate significant log output. Additionally, the comparison {} == {} is redundant since depthInBlocks was just assigned that exact calculation on line 526—they will always be equal.

♻️ Suggested improvement
-                    log.info(
-                        "tx {}; {} == {}",
+                    log.debug(
+                        "tx {} depth: {}",
                         transactionConfidence.transactionHash,
-                        transactionConfidence.depthInBlocks,
-                        wallet.lastBlockSeenHeight - transactionConfidence.appearedAtChainHeight + 1
+                        transactionConfidence.depthInBlocks
                     )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@wallet/src/de/schildbach/wallet/service/BlockchainServiceImpl.kt` around
lines 527 - 532, Change the verbose info-level log in BlockchainServiceImpl that
prints transactionConfidence.transactionHash,
transactionConfidence.depthInBlocks and the redundant computed value to a
debug-level message and simplify it to avoid duplicate data; log only the tx
hash and the depth (use transactionConfidence.depthInBlocks or the computed
wallet.lastBlockSeenHeight - transactionConfidence.appearedAtChainHeight + 1,
not both) and call log.debug instead of log.info so the statement no longer
floods logs on every new block.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@integrations/maya/build.gradle`:
- Line 74: Replace the hardcoded dependency
"androidx.lifecycle:lifecycle-runtime-compose-android:2.10.0" with the project
variable and canonical artifact name: use
"androidx.lifecycle:lifecycle-runtime-compose:$lifecycleVersion" (i.e., remove
the "-android" suffix and reference $lifecycleVersion) so the integrations/maya
build.gradle aligns with other modules (e.g., wallet) and avoids version drift.

In `@integrations/maya/proguard-rules.pro`:
- Around line 1-2: Replace the ProGuard constructor keep rule so all
constructors are preserved for Gson deserialization: locate the rule targeting
org.dash.wallet.integrations.maya.model.** (the existing "-keep class
org.dash.wallet.integrations.maya.model.** { <init(); *; }") and change the
constructor spec to preserve all-arg constructors by using "<init>(...);"
instead of "<init();", i.e. keep the class pattern and members but use
"<init>(...);" so ProGuard retains all constructors required by Gson.

In
`@integrations/maya/src/main/java/org/dash/wallet/integrations/maya/ui/MayaConvertCryptoFragment.kt`:
- Around line 135-153: The current observer on swapTradeOrder in
MayaConvertCryptoFragment uses mayaViewModel.inboundAddresses.value directly and
may use a stale or halted DASH vault; change the flow to explicitly
refresh/fetch the latest inbound addresses before building the payment intent
(call whatever fetch method on mayaViewModel or add one if missing), then find
the DASH InboundAddress and ensure its halted flag is false; only call
getUpdatedPaymentIntent and safeNavigate when you have a fresh, non-halted
Address (use Address.fromBase58 with that address); if refresh fails, or no
valid DASH inbound address exists, do not navigate—surface an explicit error/
retry path (e.g., show an error UI or trigger
convertViewModel.retryFetchInboundAddresses) so the user can retry. Ensure you
update references in MayaConvertCryptoFragment: the swapTradeOrder observer, the
fetch call on mayaViewModel, the inboundAddress validation (!halted), and the
subsequent getUpdatedPaymentIntent/safeNavigate usage.

In
`@integrations/maya/src/main/java/org/dash/wallet/integrations/maya/ui/MayaCryptoCurrencyPickerFragment.kt`:
- Around line 132-171: The current mapping treats missing inbound address as not
halted (uses ?: false), causing items to appear enabled before addresses are
known; update the logic in the combine block (the mapping over
viewModel.poolList and viewModel.inboundAddresses) to distinguish "no address
yet" from "not halted": look up the inbound address for the pool into a nullable
(e.g., val inbound = addresses.find { it.chain == chain }), derive isHalted as
inbound?.halted (nullable) and compute isEnabled as inbound != null &&
inbound.halted == false; only compute price when inbound != null and
inbound.halted == false, and only show haltedLabel when inbound?.halted == true
so rows stay disabled/neutral until an inbound address is present.

In
`@integrations/maya/src/main/java/org/dash/wallet/integrations/maya/ui/MayaViewModel.kt`:
- Around line 81-84: The MutableStateFlow inboundAddresses should be made
private and exposed as a read-only StateFlow via asStateFlow(), and
updateInboundAddresses() must stop trying to call .clear()/.addAll() and instead
assign the new list to the flow's .value; specifically, replace the public
MutableStateFlow inboundAddresses with a private MutableStateFlow (e.g.,
_inboundAddresses) and a public val inboundAddresses =
_inboundAddresses.asStateFlow(), update updateInboundAddresses() to launch in
viewModelScope and set _inboundAddresses.value = mayaApi.getInboundAddresses(),
and ensure hasHaltedCoins still maps the exposed inboundAddresses StateFlow.

---

Outside diff comments:
In
`@common/src/main/java/org/dash/wallet/common/ui/radio_group/RadioGroupAdapter.kt`:
- Around line 65-73: The click handler on holder.binding.root currently always
runs even when the item is disabled; update the listener in RadioGroupAdapter
(the block that sets holder.binding.root.setOnClickListener) to first check the
item's isEnabled flag and return early (or skip selection change and
clickListener.invoke) when false. Ensure selectedIndex and notifyItemChanged
calls only happen for enabled items, and keep clickListener.invoke(item,
position) gated by the same check; if you need alternate behavior for disabled
taps, add a separate disabledClickListener callback instead of invoking the
normal click path.

---

Nitpick comments:
In `@wallet/src/de/schildbach/wallet/service/BlockchainServiceImpl.kt`:
- Around line 527-532: Change the verbose info-level log in
BlockchainServiceImpl that prints transactionConfidence.transactionHash,
transactionConfidence.depthInBlocks and the redundant computed value to a
debug-level message and simplify it to avoid duplicate data; log only the tx
hash and the depth (use transactionConfidence.depthInBlocks or the computed
wallet.lastBlockSeenHeight - transactionConfidence.appearedAtChainHeight + 1,
not both) and call log.debug instead of log.info so the statement no longer
floods logs on every new block.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 98fcda10-a750-464b-85a4-4dbd276412c5

📥 Commits

Reviewing files that changed from the base of the PR and between 1a2afea and 6404281.

📒 Files selected for processing (20)
  • common/src/main/java/org/dash/wallet/common/ui/radio_group/IconifiedViewItem.kt
  • common/src/main/java/org/dash/wallet/common/ui/radio_group/RadioGroupAdapter.kt
  • features/exploredash/src/main/java/org/dash/wallet/features/exploredash/network/service/stubs/FakeDashSpendService.kt
  • integrations/maya/MAYA_PROTOCOL.md
  • integrations/maya/build.gradle
  • integrations/maya/proguard-rules.pro
  • integrations/maya/src/main/java/org/dash/wallet/integrations/maya/model/CurrencyBeaconResponse.kt
  • integrations/maya/src/main/java/org/dash/wallet/integrations/maya/model/ExchangeRateResponse.kt
  • integrations/maya/src/main/java/org/dash/wallet/integrations/maya/model/FreeCurrencyResponse.kt
  • integrations/maya/src/main/java/org/dash/wallet/integrations/maya/model/InboundAddress.kt
  • integrations/maya/src/main/java/org/dash/wallet/integrations/maya/model/NetworkResponse.kt
  • integrations/maya/src/main/java/org/dash/wallet/integrations/maya/model/PoolInfo.kt
  • integrations/maya/src/main/java/org/dash/wallet/integrations/maya/model/SwapTransactionInfo.kt
  • integrations/maya/src/main/java/org/dash/wallet/integrations/maya/ui/MayaConvertCryptoFragment.kt
  • integrations/maya/src/main/java/org/dash/wallet/integrations/maya/ui/MayaCryptoCurrencyPickerFragment.kt
  • integrations/maya/src/main/java/org/dash/wallet/integrations/maya/ui/MayaViewModel.kt
  • integrations/maya/src/main/res/layout/fragment_currency_picker.xml
  • integrations/maya/src/main/res/values/strings-maya.xml
  • wallet/build.gradle
  • wallet/src/de/schildbach/wallet/service/BlockchainServiceImpl.kt
💤 Files with no reviewable changes (1)
  • features/exploredash/src/main/java/org/dash/wallet/features/exploredash/network/service/stubs/FakeDashSpendService.kt

@HashEngineering HashEngineering changed the title Feat/maya halted coins feat: handle maya halted coins Mar 8, 2026
@HashEngineering HashEngineering merged commit acdfbe5 into feature-maya Mar 10, 2026
2 of 3 checks passed
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