Skip to content

Commit 75ea218

Browse files
feat: upgrade security system (#1450)
* feat: new security system (phase 1) * feat: new security system (phase 2) * feat: add fallback testing * fix: add propagate context * feat: add add security status and track * feat: add add security status and track * feat: add another test failure mode * feat: new security system phase 3, recovery * feat: remove obsolete files * feat: notify user of lost password/PIN * feat: other updates * feat: update dialogs with new components * feat: restore migration step * feat: prevent crashes * fixes: minor fixes * fix: minor fixes * docs: add QA test protocol * fix: remove debug UI elements * fix: remove password dumps in debug mode * fix: only set healthy status if encryption is true
1 parent 1e7b9f4 commit 75ea218

File tree

56 files changed

+8429
-341
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+8429
-341
lines changed

.claude/agents/DEVELOPMENT-PATTERNS.md

Lines changed: 915 additions & 0 deletions
Large diffs are not rendered by default.

build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,5 +76,9 @@ allprojects {
7676
mavenCentral()
7777
maven { url 'https://jitpack.io' }
7878
maven { url 'https://s01.oss.sonatype.org/content/repositories/snapshots/' }
79+
maven {
80+
name 'Central Portal Snapshots'
81+
url 'https://central.sonatype.com/repository/maven-snapshots/'
82+
}
7983
}
8084
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 2025 Dash Core Group.
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package org.dash.wallet.common.data
19+
20+
enum class SecuritySystemStatus(
21+
val value: Int,
22+
val isHealthy: Boolean,
23+
val hasFallback: Boolean
24+
) {
25+
DEAD(0, false, false),
26+
FALLBACKS(2, false, true),
27+
HEALTHY(1, true, false),
28+
HEALTHY_WITH_FALLBACKS(3, true, true);
29+
}

common/src/main/java/org/dash/wallet/common/data/entity/BlockchainState.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ data class BlockchainState(var bestChainDate: Date?,
4141
}
4242

4343
enum class Impediment {
44-
STORAGE, NETWORK
44+
STORAGE, NETWORK, SECURITY
4545
}
4646

4747
fun syncFailed(): Boolean {

common/src/main/java/org/dash/wallet/common/services/AuthenticationManager.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,14 @@
1818
package org.dash.wallet.common.services
1919

2020
import androidx.fragment.app.FragmentActivity
21+
import kotlinx.coroutines.flow.Flow
2122
import org.bitcoinj.core.Address
23+
import org.dash.wallet.common.data.SecuritySystemStatus
2224

2325
interface AuthenticationManager {
2426
fun authenticate(activity: FragmentActivity, pinOnly: Boolean = false, callback: (String?) -> Unit)
2527
suspend fun authenticate(activity: FragmentActivity, pinOnly: Boolean = false): String?
2628
suspend fun signMessage(address: Address, message: String): String
29+
fun getHealth(): SecuritySystemStatus
30+
fun observeHealth(): Flow<SecuritySystemStatus>
2731
}
Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
/*
2+
* Copyright 2025 Dash Core Group.
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package org.dash.wallet.common.ui.components
19+
20+
import androidx.compose.foundation.background
21+
import androidx.compose.foundation.border
22+
import androidx.compose.foundation.layout.Arrangement
23+
import androidx.compose.foundation.layout.Box
24+
import androidx.compose.foundation.layout.Column
25+
import androidx.compose.foundation.layout.Row
26+
import androidx.compose.foundation.layout.fillMaxWidth
27+
import androidx.compose.foundation.layout.padding
28+
import androidx.compose.foundation.layout.size
29+
import androidx.compose.foundation.shape.RoundedCornerShape
30+
import androidx.compose.material3.Icon
31+
import androidx.compose.material3.Text
32+
import androidx.compose.runtime.Composable
33+
import androidx.compose.ui.Alignment
34+
import androidx.compose.ui.Modifier
35+
import androidx.compose.ui.graphics.Color
36+
import androidx.compose.ui.graphics.vector.ImageVector
37+
import androidx.compose.ui.res.vectorResource
38+
import androidx.compose.ui.tooling.preview.Preview
39+
import androidx.compose.ui.text.style.TextAlign
40+
import androidx.compose.ui.unit.dp
41+
import androidx.compose.ui.unit.sp
42+
import org.dash.wallet.common.R
43+
44+
data class FeatureItem(
45+
val heading: String,
46+
val text: String? = null,
47+
val icon: ImageVector? = null,
48+
val number: String? = null
49+
)
50+
51+
@Composable
52+
fun FeatureItemNumber(
53+
number: String,
54+
modifier: Modifier = Modifier
55+
) {
56+
Box(
57+
modifier = modifier
58+
.size(24.dp)
59+
.background(
60+
color = MyTheme.Colors.dashBlue,
61+
shape = RoundedCornerShape(8.dp)
62+
),
63+
contentAlignment = Alignment.Center
64+
) {
65+
Text(
66+
text = number,
67+
fontSize = 14.sp,
68+
color = Color.White,
69+
textAlign = TextAlign.Center
70+
)
71+
}
72+
}
73+
74+
@Composable
75+
fun FeatureSingleItem(
76+
heading: String,
77+
text: String? = null,
78+
modifier: Modifier = Modifier,
79+
icon: ImageVector? = null,
80+
number: String? = null
81+
) {
82+
Row(
83+
modifier = modifier.fillMaxWidth(),
84+
horizontalArrangement = Arrangement.spacedBy(12.dp),
85+
verticalAlignment = Alignment.Top
86+
) {
87+
Box(
88+
modifier = Modifier
89+
.size(40.dp)
90+
.padding(top = 10.dp),
91+
contentAlignment = Alignment.TopCenter
92+
) {
93+
when {
94+
number != null -> {
95+
FeatureItemNumber(number = number)
96+
}
97+
icon != null -> {
98+
Icon(
99+
imageVector = icon,
100+
contentDescription = null,
101+
modifier = Modifier.size(20.dp),
102+
tint = MyTheme.Colors.gray300
103+
)
104+
}
105+
else -> {
106+
Box(
107+
modifier = Modifier
108+
.size(20.dp)
109+
.border(
110+
width = 2.5.dp,
111+
color = MyTheme.Colors.gray300,
112+
shape = RoundedCornerShape(5.dp)
113+
)
114+
)
115+
}
116+
}
117+
}
118+
119+
Column(
120+
modifier = Modifier
121+
.weight(1f)
122+
.padding(top = 10.dp),
123+
verticalArrangement = Arrangement.spacedBy(2.dp)
124+
) {
125+
Text(
126+
text = heading,
127+
style = MyTheme.Typography.TitleSmallMedium,
128+
color = MyTheme.Colors.textPrimary
129+
)
130+
if (text != null) {
131+
Text(
132+
text = text,
133+
style = MyTheme.Typography.BodyMedium,
134+
color = MyTheme.Colors.textSecondary
135+
)
136+
}
137+
}
138+
}
139+
}
140+
141+
@Composable
142+
fun FeatureList(
143+
items: List<FeatureItem>,
144+
modifier: Modifier = Modifier
145+
) {
146+
Column(
147+
modifier = modifier.fillMaxWidth(),
148+
verticalArrangement = Arrangement.spacedBy(16.dp)
149+
) {
150+
items.forEach { item ->
151+
FeatureSingleItem(
152+
heading = item.heading,
153+
text = item.text,
154+
icon = item.icon,
155+
number = item.number
156+
)
157+
}
158+
}
159+
}
160+
161+
@Preview(showBackground = true)
162+
@Composable
163+
private fun FeatureSingleItemPreview() {
164+
Box(
165+
modifier = Modifier
166+
.fillMaxWidth()
167+
.background(Color.White)
168+
.padding(20.dp)
169+
) {
170+
FeatureSingleItem(
171+
heading = "heading",
172+
text = "text"
173+
)
174+
}
175+
}
176+
177+
@Preview(showBackground = true)
178+
@Composable
179+
private fun FeatureListPreview() {
180+
Box(
181+
modifier = Modifier
182+
.fillMaxWidth()
183+
.background(Color.White)
184+
.padding(20.dp)
185+
) {
186+
FeatureList(
187+
items = listOf(
188+
FeatureItem("heading", "text"),
189+
FeatureItem("heading", "text"),
190+
FeatureItem("heading", "text"),
191+
FeatureItem("heading", "text")
192+
)
193+
)
194+
}
195+
}
196+
197+
@Preview(showBackground = true)
198+
@Composable
199+
private fun FeatureListWithIconsPreview() {
200+
Box(
201+
modifier = Modifier
202+
.fillMaxWidth()
203+
.background(Color.White)
204+
.padding(20.dp)
205+
) {
206+
FeatureList(
207+
items = listOf(
208+
FeatureItem(
209+
"Enhanced Security",
210+
"Your wallet will use the latest encryption technology",
211+
ImageVector.vectorResource(R.drawable.ic_preview)
212+
),
213+
FeatureItem(
214+
"Biometric Support",
215+
"Unlock your wallet with fingerprint or face recognition",
216+
ImageVector.vectorResource(R.drawable.ic_preview)
217+
),
218+
FeatureItem(
219+
"PIN Protection",
220+
"Set a secure PIN to protect your funds",
221+
ImageVector.vectorResource(R.drawable.ic_preview)
222+
),
223+
FeatureItem(
224+
"Recovery Options",
225+
"Multiple ways to recover your wallet if needed",
226+
ImageVector.vectorResource(R.drawable.ic_preview)
227+
)
228+
)
229+
)
230+
}
231+
}
232+
233+
@Preview(showBackground = true)
234+
@Composable
235+
private fun FeatureListWithNumbersPreview() {
236+
Box(
237+
modifier = Modifier
238+
.fillMaxWidth()
239+
.background(Color.White)
240+
.padding(20.dp)
241+
) {
242+
FeatureList(
243+
items = listOf(
244+
FeatureItem(
245+
heading = "Create a secure PIN",
246+
text = "Choose a 6-digit PIN that you'll use to unlock your wallet",
247+
number = "1"
248+
),
249+
FeatureItem(
250+
heading = "Write down your recovery phrase",
251+
text = "Save your 12-word recovery phrase in a safe place",
252+
number = "2"
253+
),
254+
FeatureItem(
255+
heading = "Enable biometric authentication",
256+
text = "Use fingerprint or face recognition for quick access",
257+
number = "3"
258+
),
259+
FeatureItem(
260+
heading = "Start using your wallet",
261+
text = "You're all set! Begin sending and receiving Dash",
262+
number = "4"
263+
)
264+
)
265+
)
266+
}
267+
}

0 commit comments

Comments
 (0)