Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class AmountView(context: Context, attrs: AttributeSet) : ConstraintLayout(conte
var input: String
get() = _input
set(value) {
_input = value.ifEmpty { "0" }
_input = if (value.none { it.isDigit() } || value.trimStart().startsWith("-")) "0" else value
updateAmount()
}

Expand Down Expand Up @@ -96,8 +96,9 @@ class AmountView(context: Context, attrs: AttributeSet) : ConstraintLayout(conte

if (exchangeRate != null) {
fiatAmount = exchangeRate!!.coinToFiat(dashAmount)
_input = fiatFormat.minDecimals(0)
val fiatStr = fiatFormat.minDecimals(0)
.optionalDecimals(0, 2).format(fiatAmount).toString()
_input = if (fiatStr.trimStart().startsWith("-")) "0" else fiatStr
binding.inputAmount.text = formatInputWithCurrency()
} else {
binding.inputAmount.text = resources.getString(R.string.rate_not_available)
Expand Down
11 changes: 11 additions & 0 deletions wallet/res/layout/scan_activity.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,15 @@
android:layout_width="match_parent"
android:layout_height="match_parent" />

<ImageButton
android:id="@+id/scan_close_button"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="top|start"
android:layout_marginTop="16dp"
android:layout_marginStart="16dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/button_cancel"
android:src="@drawable/ic_close_white_24dp" />

</FrameLayout>
10 changes: 5 additions & 5 deletions wallet/res/values/strings-extra.xml
Original file line number Diff line number Diff line change
Expand Up @@ -444,11 +444,11 @@
<string name="reclassify_transactions_linked_accounts_message">by default all transactions to or from your linked accounts (exchanges, staking, etc) will be marked as transfers.</string>
<string name="reclassify_transactions_change_explanation">Choose any transaction from the homepage and change the category on the transaction details page.</string>

<string name="masternode_keys_title">Masternode Keys</string>
<string name="masternode_key_type_owner">Owner Keys</string>
<string name="masternode_key_type_voting">Voting Keys</string>
<string name="masternode_key_type_operator">Operator Keys</string>
<string name="masternode_key_type_platform">EvoNode operator keys</string>
<string name="masternode_keys_title">Masternode keys</string>
<string name="masternode_key_type_owner">Owner keys</string>
<string name="masternode_key_type_voting">Voting keys</string>
<string name="masternode_key_type_operator">Operator keys</string>
<string name="masternode_key_type_platform">HPMN operator keys</string>
<string name="masternode_key_type_total">%d keys</string>
<string name="masternode_key_type_used">%d used</string>
<string name="masternode_key_pair_index">Keypair %d</string>
Expand Down
1 change: 0 additions & 1 deletion wallet/src/de/schildbach/wallet/WalletApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,6 @@ private void initUphold() {

private void initPlatform() {
platformSyncService.init();
//PlatformRepo.getInstance().initGlobal();
}

private void initCoinbase() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ import de.schildbach.wallet.ui.dashpay.utils.DashPayConfig.Companion.UPGRADE_IDE
import io.grpc.StatusRuntimeException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
Expand Down Expand Up @@ -66,6 +69,7 @@ import javax.inject.Inject

interface IdentityRepository {
val blockchainIdentity: BlockchainIdentity?
val blockchainIdentityFlow: StateFlow<BlockchainIdentity?>
//suspend fun addMissingKeys(keyParameter: KeyParameter?): Boolean
suspend fun getIdentityBalance(): CreditBalanceInfo?
val hasBlockchainIdentity: Boolean
Expand Down Expand Up @@ -102,6 +106,7 @@ interface IdentityRepository {
suspend fun shouldShowAlert(): Boolean
fun getNextContactAddress(userId: String, accountReference: Int): Address?
suspend fun clearDatabase(includeInvitations: Boolean)
fun updateIdentity()
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify that updateIdentity() mutates identity without publishing a guaranteed new flow emission.
# Expected finding:
# - updateIdentity() does not re-publish a semantically new flow value
# - MainViewModel relies on blockchainIdentityFlow emissions for refresh

rg -n -C3 --type=kt 'override fun updateIdentity\(\)|_blockchainIdentityFlow\.value\s*=' wallet/src/de/schildbach/wallet/service/platform/IdentityRepository.kt
rg -n -C3 --type=kt 'blockchainIdentityFlow|distinctUntilChanged\(\)' wallet/src/de/schildbach/wallet/ui/main/MainViewModel.kt

Repository: dashpay/dash-wallet

Length of output: 116


🏁 Script executed:

#!/bin/bash
# Find and read the IdentityRepository.kt file
fd "IdentityRepository.kt" wallet/src

Repository: dashpay/dash-wallet

Length of output: 133


🏁 Script executed:

#!/bin/bash
# Read the IdentityRepository.kt file to understand updateIdentity() and blockchainIdentityFlow
cat -n wallet/src/de/schildbach/wallet/service/platform/IdentityRepository.kt

Repository: dashpay/dash-wallet

Length of output: 48829


🏁 Script executed:

#!/bin/bash
# Search for updateIdentity and blockchainIdentityFlow in IdentityRepository
rg -n -C5 'updateIdentity|blockchainIdentityFlow' wallet/src/de/schildbach/wallet/service/platform/IdentityRepository.kt

Repository: dashpay/dash-wallet

Length of output: 3668


🏁 Script executed:

#!/bin/bash
# Check MainViewModel.kt for blockchainIdentityFlow and distinctUntilChanged usage
rg -n -C5 'blockchainIdentityFlow|distinctUntilChanged' wallet/src/de/schildbach/wallet/ui/main/MainViewModel.kt

Repository: dashpay/dash-wallet

Length of output: 3419


updateIdentity() mutates identity without notifying blockchainIdentityFlow observers.

At lines 827-829, updateIdentity() calls _blockchainIdentity?.updateIdentity(), which mutates the existing BlockchainIdentity instance in place. Because the flow reference remains unchanged, MainViewModel's subscription (line 339-343) using distinctUntilChanged() will not detect the update, causing refreshContactsForAllTransactions() to be skipped.

Force a new emission by reassigning the flow value:

Fix pattern
 override fun updateIdentity() {
-    _blockchainIdentity?.updateIdentity()
+    _blockchainIdentity?.let { identity ->
+        identity.updateIdentity()
+        _blockchainIdentityFlow.value = identity
+    }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@wallet/src/de/schildbach/wallet/service/platform/IdentityRepository.kt` at
line 109, updateIdentity() mutates the existing _blockchainIdentity instance in
place so blockchainIdentityFlow observers using distinctUntilChanged() don't see
a change; after calling _blockchainIdentity?.updateIdentity() (and any in-place
mutation), reassign the flow with a new object to force emission (e.g. create a
new BlockchainIdentity instance or call a copy/clone and set the backing
MutableStateFlow/_blockchainIdentityFlow.value to that new instance). Update the
code in IdentityRepository around updateIdentity(), _blockchainIdentity and
blockchainIdentityFlow so the flow is set to a new instance after mutation so
MainViewModel (distinctUntilChanged()) will detect the change and trigger
refreshContactsForAllTransactions().

}

class IdentityRepositoryImpl @Inject constructor(
Expand All @@ -120,7 +125,12 @@ class IdentityRepositoryImpl @Inject constructor(
val authenticationGroupExtension: AuthenticationGroupExtension?
get() = walletApplication.authenticationGroupExtension

private var _blockchainIdentity: BlockchainIdentity? = null
private val _blockchainIdentityFlow = MutableStateFlow<BlockchainIdentity?>(null)
override val blockchainIdentityFlow: StateFlow<BlockchainIdentity?> = _blockchainIdentityFlow.asStateFlow()

private var _blockchainIdentity: BlockchainIdentity?
get() = _blockchainIdentityFlow.value
set(value) { _blockchainIdentityFlow.value = value }

override val blockchainIdentity: BlockchainIdentity?
get() = _blockchainIdentity
Expand Down Expand Up @@ -228,7 +238,6 @@ class IdentityRepositoryImpl @Inject constructor(
}
identity = blockchainIdentityData.identity
}
blockchainIdentity.updateIdentity()
log.info("loading identity ${blockchainIdentityData.userId} == ${_blockchainIdentity?.uniqueIdString}: {}", watch)
} else {
log.info("loading identity: {}", watch)
Expand Down Expand Up @@ -815,6 +824,10 @@ class IdentityRepositoryImpl @Inject constructor(
}
}

override fun updateIdentity() {
_blockchainIdentity?.updateIdentity()
}

// current unused
private suspend fun getContactRequestReport(): String {
val report = StringBuilder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,9 @@ class PlatformSynchronizationService @Inject constructor(
if (!initialSync) {
checkDatabaseIntegrity(userId)
updateSyncStatus(PreBlockStage.FixMissingProfiles)
} else {
// update the
identityRepository.updateIdentity()
}

// Get all out our contact requests
Expand Down
2 changes: 2 additions & 0 deletions wallet/src/de/schildbach/wallet/ui/LockScreenActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,12 @@ open class LockScreenActivity : SecureActivity() {
}

override fun setContentView(contentViewResId: Int) {
if (isFinishing) return
setContentView(layoutInflater.inflate(contentViewResId, null))
}

override fun setContentView(contentView: View?) {
if (isFinishing) return
binding.regularContent.removeAllViews()
binding.regularContent.addView(contentView)
}
Expand Down
11 changes: 9 additions & 2 deletions wallet/src/de/schildbach/wallet/ui/main/MainViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,12 @@ class MainViewModel @Inject constructor(
refreshContactsForAllTransactions()
}.launchIn(viewModelWorkerScope)

identityRepository.blockchainIdentityFlow
.filterNotNull()
.distinctUntilChanged()
.onEach { refreshContactsForAllTransactions() }
.launchIn(viewModelWorkerScope)

walletData.observeWalletReset()
.onEach {
txByHash = mapOf()
Expand Down Expand Up @@ -697,10 +703,11 @@ class MainViewModel @Inject constructor(
}

viewModelWorkerScope.launch {
val contactsMap = if (this@MainViewModel.contacts.isNotEmpty()) {
val blockchainIdentity = identityRepository.blockchainIdentity
val contactsMap = if (this@MainViewModel.contacts.isNotEmpty() && blockchainIdentity != null) {
txs.filterNot { it.isEntirelySelf(walletData.transactionBag) }
.mapNotNull { tx ->
identityRepository.blockchainIdentity!!.getContactForTransaction(tx)?.let { contactId ->
blockchainIdentity.getContactForTransaction(tx)?.let { contactId ->
contacts[contactId]?.let { contact ->
tx.txId to contact
}
Expand Down
12 changes: 10 additions & 2 deletions wallet/src/de/schildbach/wallet/ui/main/WalletFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,11 @@ class WalletFragment : Fragment(R.layout.home_content) {
R.id.paymentsFragment,
bundleOf(
PaymentsFragment.ARG_ACTIVE_TAB to PaymentsFragment.ACTIVE_TAB_PAY
)
),
NavOptions.Builder()
.setLaunchSingleTop(true)
.setPopUpTo(R.id.walletFragment, false)
.build()
)
}
ShortcutOption.RECEIVE -> {
Expand All @@ -439,7 +443,11 @@ class WalletFragment : Fragment(R.layout.home_content) {
R.id.paymentsFragment,
bundleOf(
PaymentsFragment.ARG_ACTIVE_TAB to PaymentsFragment.ACTIVE_TAB_RECEIVE
)
),
NavOptions.Builder()
.setLaunchSingleTop(true)
.setPopUpTo(R.id.walletFragment, false)
.build()
)
}
ShortcutOption.EXPLORE -> {
Expand Down
1 change: 1 addition & 0 deletions wallet/src/de/schildbach/wallet/ui/scan/ScanActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ public void onChanged(final Void v) {
scannerView = (ScannerView) findViewById(R.id.scan_activity_mask);
previewView = (TextureView) findViewById(R.id.scan_activity_preview);
previewView.setSurfaceTextureListener(this);
findViewById(R.id.scan_close_button).setOnClickListener(v -> onBackPressed());

cameraThread = new HandlerThread("cameraThread", Process.THREAD_PRIORITY_BACKGROUND);
cameraThread.start();
Expand Down
Loading