Skip to content

Commit edac1f1

Browse files
committed
chore(flipcash): reduce roundtrips to credential manager for restores
Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent cddf65b commit edac1f1

3 files changed

Lines changed: 48 additions & 29 deletions

File tree

apps/flipcash/features/login/src/main/kotlin/com/flipcash/app/login/seed/SeedInputViewModel.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,10 @@ class SeedInputViewModel @Inject constructor(
9999
}
100100

101101
@SuppressLint("CheckResult")
102-
fun performLogin(navigator: CodeNavigator, entropyB64: String, deeplink: Boolean = false) {
102+
fun performLogin(navigator: CodeNavigator, entropyB64: String, deeplink: Boolean = false, isRestore: Boolean = false) {
103103
viewModelScope.launch {
104104
setState(isLoading = true, isSuccess = false, isContinueEnabled = false)
105-
authManager.login(entropyB64)
105+
authManager.login(entropyB64, isFromSelection = isRestore)
106106
.onFailure {
107107
if (it is com.flipcash.app.auth.AuthManager.AuthManagerException.TimelockUnlockedException) {
108108
TopBarManager.showMessage(
@@ -137,7 +137,11 @@ class SeedInputViewModel @Inject constructor(
137137
suspend fun restoreAccount(navigator: CodeNavigator): Result<Unit> {
138138
return authManager.selectAccount()
139139
.onSuccess { mnemonic ->
140-
performLogin(navigator, mnemonic.getBase64EncodedEntropy())
140+
performLogin(
141+
navigator = navigator,
142+
entropyB64 = mnemonic.getBase64EncodedEntropy(),
143+
isRestore = true
144+
)
141145
}.onFailure { error ->
142146
when (error) {
143147
is SelectCredentialError.UserCancelled -> { /* no op */ }

apps/flipcash/shared/authentication/src/main/kotlin/com/flipcash/app/auth/AuthManager.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ class AuthManager @Inject constructor(
8585
suspend fun login(
8686
entropyB64: String,
8787
isSoftLogin: Boolean = false,
88+
isFromSelection: Boolean = false,
8889
rollbackOnError: Boolean = false
8990
): Result<ID> {
9091
taggedTrace("Login: isSoftLogin: $isSoftLogin, rollbackOnError: $rollbackOnError")
@@ -99,7 +100,7 @@ class AuthManager @Inject constructor(
99100
loginAnalytics()
100101
}
101102

102-
return credentialManager.login(entropyB64)
103+
return credentialManager.login(entropyB64, isFromSelection)
103104
.onSuccess { account ->
104105
persistence.openDatabase(entropyB64)
105106
// TODO: this will move to post IAP check

apps/flipcash/shared/authentication/src/main/kotlin/com/flipcash/app/auth/internal/credentials/PassphraseCredentialManager.kt

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.flipcash.app.auth.internal.credentials
22

33
import android.content.Context
44
import androidx.credentials.CreatePasswordRequest
5+
import androidx.credentials.Credential
56
import androidx.credentials.CredentialManager
67
import androidx.credentials.GetCredentialRequest
78
import androidx.credentials.GetPasswordOption
@@ -54,6 +55,8 @@ class PassphraseCredentialManager @Inject constructor(
5455

5556
private val credentialManager = CredentialManager.create(context)
5657

58+
private val credentialLookupCache = mutableMapOf<String, PasswordCredential>()
59+
5760
private val dataScope: CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
5861

5962
private val storage = PreferenceDataStoreFactory.create(
@@ -103,6 +106,7 @@ class PassphraseCredentialManager @Inject constructor(
103106

104107
suspend fun login(
105108
entropy: String,
109+
fromSelection: Boolean = false,
106110
): Result<AccountMetadata> {
107111
userManager.establish(entropy)
108112
userManager.set(AuthState.LoggedInAwaitingUser)
@@ -113,35 +117,41 @@ class PassphraseCredentialManager @Inject constructor(
113117
return Result.success(selectedMetadata)
114118
}
115119

116-
// Check existing credential
117-
val userId = getUserId(entropy)
118-
val existingCredential = getCredentialByEntropy(entropy, userId)
120+
if (!fromSelection) {
121+
// Check existing credential
122+
val userId = getUserId(entropy)
123+
val existingCredential =
124+
credentialLookupCache[entropy] ?: getCredentialByEntropy(entropy, userId)
125+
126+
if (existingCredential != null) {
127+
val metadata = getMetadata(userId.orEmpty())?.copy(isUnregistered = false)
128+
?: AccountMetadata(
129+
userId.orEmpty(),
130+
entropy,
131+
isUnregistered = false
132+
)
119133

120-
if (existingCredential != null) {
121-
val metadata = getMetadata(userId.orEmpty())?.copy(isUnregistered = false)
122-
?: AccountMetadata(
123-
userId.orEmpty(),
124-
entropy,
125-
isUnregistered = false
134+
storeMetadata(metadata, isSelected = true)
135+
updateUserManager(
136+
Base58.decode(existingCredential.password).toList(),
137+
AuthState.LoggedIn
126138
)
127139

128-
storeMetadata(metadata, isSelected = true)
129-
updateUserManager(
130-
Base58.decode(existingCredential.password).toList(),
131-
AuthState.LoggedIn
132-
)
133-
return Result.success(metadata)
134-
}
140+
credentialLookupCache.clear()
135141

136-
// Check fallback userId
137-
if (userId != null) {
138-
storeCredential(entropy, Base58.decode(userId).toList())
139-
storage.edit { it.remove(userIdKey(entropy)) }
142+
return Result.success(metadata)
143+
}
140144

141-
val metadata = AccountMetadata(userId, entropy, isUnregistered = false)
142-
storeMetadata(metadata, isSelected = true)
143-
updateUserManager(Base58.decode(userId).toList(), AuthState.LoggedIn)
144-
return Result.success(metadata)
145+
// Check fallback userId
146+
if (userId != null) {
147+
storeCredential(entropy, Base58.decode(userId).toList())
148+
storage.edit { it.remove(userIdKey(entropy)) }
149+
150+
val metadata = AccountMetadata(userId, entropy, isUnregistered = false)
151+
storeMetadata(metadata, isSelected = true)
152+
updateUserManager(Base58.decode(userId).toList(), AuthState.LoggedIn)
153+
return Result.success(metadata)
154+
}
145155
}
146156

147157
// Non-existent credential - check with backend
@@ -155,7 +165,10 @@ class PassphraseCredentialManager @Inject constructor(
155165

156166
val userIdBytes = backendResult.getOrNull()!!
157167
val userIdStr = userIdBytes.base58
158-
storeCredential(entropy, userIdBytes)
168+
169+
if (!fromSelection) {
170+
storeCredential(entropy, userIdBytes)
171+
}
159172

160173
val metadata = AccountMetadata(userIdStr, entropy, isUnregistered = false)
161174
storeMetadata(metadata, isSelected = true)
@@ -184,6 +197,7 @@ class PassphraseCredentialManager @Inject constructor(
184197
.replace(Regex("(\\s)+"), " ")
185198
.lowercase(Locale.getDefault()).split(" ")
186199
val mnemonic = MnemonicPhrase.newInstance(words)!!
200+
credentialLookupCache[mnemonic.wordString] = credential
187201
Result.success(mnemonic)
188202
} catch (e: Exception) {
189203
when (e) {

0 commit comments

Comments
 (0)