Updated on 2026-08-14

This commit is contained in:
Tangem 2025-09-17 16:39:05 +03:00
parent 587a0c8624
commit 88cf7ec1af
212 changed files with 1223 additions and 1128 deletions

View file

@ -5,6 +5,39 @@
<JavaCodeStyleSettings>
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="5" />
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="3" />
<option name="IMPORT_LAYOUT_TABLE">
<value>
<package name="" withSubpackages="true" static="false" module="true" />
<package name="android" withSubpackages="true" static="true" />
<package name="androidx" withSubpackages="true" static="true" />
<package name="com" withSubpackages="true" static="true" />
<package name="junit" withSubpackages="true" static="true" />
<package name="net" withSubpackages="true" static="true" />
<package name="org" withSubpackages="true" static="true" />
<package name="java" withSubpackages="true" static="true" />
<package name="javax" withSubpackages="true" static="true" />
<package name="" withSubpackages="true" static="true" />
<emptyLine />
<package name="android" withSubpackages="true" static="false" />
<emptyLine />
<package name="androidx" withSubpackages="true" static="false" />
<emptyLine />
<package name="com" withSubpackages="true" static="false" />
<emptyLine />
<package name="junit" withSubpackages="true" static="false" />
<emptyLine />
<package name="net" withSubpackages="true" static="false" />
<emptyLine />
<package name="org" withSubpackages="true" static="false" />
<emptyLine />
<package name="java" withSubpackages="true" static="false" />
<emptyLine />
<package name="javax" withSubpackages="true" static="false" />
<emptyLine />
<package name="" withSubpackages="true" static="false" />
<emptyLine />
</value>
</option>
</JavaCodeStyleSettings>
<JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS">

View file

@ -263,7 +263,7 @@ class MainActivity : AppCompatActivity(), ActivityResultCallbackHolder {
tangemSdkManager = injectedTangemSdkManager
backupServiceHolder.createAndSetService(cardSdkConfigRepository.sdk, this)
backupService = backupServiceHolder.backupService.get()!! // will be deleted eventually
backupService = requireNotNull(backupServiceHolder.backupService.get()) // will be deleted eventually
lockUserWalletsTimer = LockUserWalletsTimer(
context = this,
@ -370,8 +370,8 @@ class MainActivity : AppCompatActivity(), ActivityResultCallbackHolder {
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
val fromPush = intent?.extras?.containsKey(OPENED_FROM_GCM_PUSH) ?: false
if (fromPush) {
val isFromPush = intent?.extras?.containsKey(OPENED_FROM_GCM_PUSH) == true
if (isFromPush) {
analyticsEventsHandler.send(Push.PushNotificationOpened)
}
@ -402,8 +402,8 @@ class MainActivity : AppCompatActivity(), ActivityResultCallbackHolder {
}
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
val result = WindowObscurationObserver.dispatchTouchEvent(event, analyticsEventsHandler)
return if (result) super.dispatchTouchEvent(event) else false
val isHandled = WindowObscurationObserver.dispatchTouchEvent(event, analyticsEventsHandler)
return if (isHandled) super.dispatchTouchEvent(event) else false
}
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
@ -447,9 +447,9 @@ class MainActivity : AppCompatActivity(), ActivityResultCallbackHolder {
getPolkadotCheckHasImmortalUseCase()
.flowWithLifecycle(lifecycle, minActiveState = Lifecycle.State.CREATED)
.distinctUntilChanged()
.collect {
.collect { (_, hasImmortalTransaction) ->
analyticsEventsHandler.send(
WalletScreenAnalyticsEvent.Token.PolkadotImmortalTransactions(it.second),
WalletScreenAnalyticsEvent.Token.PolkadotImmortalTransactions(hasImmortalTransaction),
)
}
}

View file

@ -88,7 +88,7 @@ lateinit var store: Store<AppState>
lateinit var foregroundActivityObserver: ForegroundActivityObserver
internal lateinit var derivationsFinder: DerivationsFinder
abstract class TangemApplication : Application(), ImageLoaderFactory, Configuration.Provider {
open class TangemApplication : Application(), ImageLoaderFactory, Configuration.Provider {
// region DI
private val entryPoint: ApplicationEntryPoint

View file

@ -7,7 +7,7 @@ package com.tangem.tap.common
object TestActions {
// It used only for the test actions in debug or debug_beta builds
var testAmountInjectionForWalletManagerEnabled = false
var isTestAmountInjectionForWalletManagerEnabled = false
}
typealias TestAction = Pair<String, () -> Unit>

View file

@ -58,7 +58,7 @@ private class BlockchainSdkErrorConverter(
if (value.customMessage.contains(DemoTransactionSender.ID)) return emptyMap()
if (value is BlockchainSdkError.WrappedTangemError) {
return (value.tangemError as? TangemSdkError)?.let { cardSdkErrorConverter.convert(it) } ?: emptyMap()
return (value.tangemError as? TangemSdkError)?.let { cardSdkErrorConverter.convert(it) }.orEmpty()
}
return mapOf(

View file

@ -7,7 +7,7 @@ import com.tangem.core.analytics.models.AnalyticsEvent
*/
sealed class Chat(
event: String,
params: Map<String, String> = mapOf(),
params: Map<String, String> = emptyMap(),
) : AnalyticsEvent("Chat", event, params) {
class ScreenOpened : Chat("Chat Screen Opened")

View file

@ -8,7 +8,7 @@ import com.tangem.core.analytics.models.AnalyticsEvent
sealed class Onboarding(
category: String,
event: String,
params: Map<String, String> = mapOf(),
params: Map<String, String> = emptyMap(),
) : AnalyticsEvent(category, event, params) {
class Started : Onboarding("Onboarding", "Onboarding Started")
@ -16,7 +16,7 @@ sealed class Onboarding(
sealed class CreateWallet(
event: String,
params: Map<String, String> = mapOf(),
params: Map<String, String> = emptyMap(),
) : Onboarding("Onboarding / Create Wallet", event, params) {
class ScreenOpened : CreateWallet("Create Wallet Screen Opened")
@ -36,7 +36,7 @@ sealed class Onboarding(
sealed class Backup(
event: String,
params: Map<String, String> = mapOf(),
params: Map<String, String> = emptyMap(),
) : Onboarding("Onboarding / Backup", event, params) {
class ScreenOpened : Backup("Backup Screen Opened")
@ -64,7 +64,7 @@ sealed class Onboarding(
sealed class Topup(
event: String,
params: Map<String, String> = mapOf(),
params: Map<String, String> = emptyMap(),
) : Onboarding("Onboarding / Top Up", event, params) {
class ScreenOpened : Topup("Activation Screen Opened")
@ -79,7 +79,7 @@ sealed class Onboarding(
sealed class Twins(
event: String,
params: Map<String, String> = mapOf(),
params: Map<String, String> = emptyMap(),
) : Onboarding("Onboarding / Twins", event, params) {
class ScreenOpened : Twins("Twinning Screen Opened")

View file

@ -8,7 +8,7 @@ import com.tangem.core.analytics.models.AnalyticsEvent
sealed class Settings(
category: String = "Settings",
event: String,
params: Map<String, String> = mapOf(),
params: Map<String, String> = emptyMap(),
) : AnalyticsEvent(category, event, params) {
class ScreenOpened : Settings(event = "Settings Screen Opened")
@ -17,7 +17,7 @@ sealed class Settings(
sealed class CardSettings(
event: String,
params: Map<String, String> = mapOf(),
params: Map<String, String> = emptyMap(),
) : Settings("Settings / Card Settings", event, params) {
class ButtonFactoryReset : CardSettings("Button - Factory Reset")
@ -54,7 +54,7 @@ sealed class Settings(
sealed class AppSettings(
event: String,
params: Map<String, String> = mapOf(),
params: Map<String, String> = emptyMap(),
) : Settings(category = "Settings / App Settings", event = event, params = params) {
class SaveWalletSwitcherChanged(state: AnalyticsParam.OnOffState) : AppSettings(

View file

@ -7,7 +7,7 @@ import com.tangem.core.analytics.models.AnalyticsEvent
*/
sealed class SignIn(
event: String,
params: Map<String, String> = mapOf(),
params: Map<String, String> = emptyMap(),
) : AnalyticsEvent("Sign In", event, params) {
class ScreenOpened : SignIn(event = "Sign In Screen Opened")

View file

@ -9,12 +9,12 @@ import com.tangem.core.analytics.models.AnalyticsParam.Key.TOKEN_PARAM
sealed class Token(
category: String,
event: String,
params: Map<String, String> = mapOf(),
params: Map<String, String> = emptyMap(),
) : AnalyticsEvent(category, event, params) {
sealed class Receive(
event: String,
params: Map<String, String> = mapOf(),
params: Map<String, String> = emptyMap(),
) : Token("Token / Receive", event, params) {
class ScreenOpened(
@ -29,7 +29,7 @@ sealed class Token(
sealed class Topup(
event: String,
params: Map<String, String> = mapOf(),
params: Map<String, String> = emptyMap(),
) : Token("Token / Topup", event, params) {
class ScreenOpened : Topup("Top Up Screen Opened")
@ -38,7 +38,7 @@ sealed class Token(
sealed class Withdraw(
event: String,
params: Map<String, String> = mapOf(),
params: Map<String, String> = emptyMap(),
) : Token("Token / Withdraw", event, params) {
class ScreenOpened : Withdraw("Withdraw Screen Opened")

View file

@ -19,6 +19,7 @@ internal class DefaultClipboardManager(private val clipboardManager: AndroidClip
clipboardManager.setPrimaryClip(clip)
}
@Suppress("UseIsNullOrEmpty")
override fun getText(default: String?): String? {
val clip = clipboardManager.primaryClip

View file

@ -90,6 +90,6 @@ fun Store<AppState>.dispatchNavigationAction(action: AppRouter.() -> Unit) {
inline fun <reified T> Store<AppState>.inject(getDependency: DaggerGraphState.() -> T?): T {
return requireNotNull(state.daggerGraphState.getDependency()) {
"${T::class.simpleName} isn't initialized "
"${T::class.simpleName.orEmpty()} isn't initialized "
}
}

View file

@ -22,9 +22,9 @@ import timber.log.Timber
)
@Suppress("MagicNumber")
suspend fun WalletManager.safeUpdate(isDemoCard: Boolean): Result<Wallet> = try {
if (isDemoCard || TestActions.testAmountInjectionForWalletManagerEnabled) {
if (isDemoCard || TestActions.isTestAmountInjectionForWalletManagerEnabled) {
delay(500)
TestActions.testAmountInjectionForWalletManagerEnabled = false
TestActions.isTestAmountInjectionForWalletManagerEnabled = false
Result.Success(wallet)
} else {
update()
@ -35,7 +35,7 @@ suspend fun WalletManager.safeUpdate(isDemoCard: Boolean): Result<Wallet> = try
val networkConnectionManager = store.inject(DaggerGraphState::networkConnectionManager)
if (!networkConnectionManager.isOnline) {
Result.Failure(TapError.NoInternetConnection)
Result.Failure(TapError.NoInternetConnection())
} else {
val blockchain = wallet.blockchain
val amountToCreateAccount = blockchain.amountToCreateAccount(this, wallet.getFirstToken())

View file

@ -44,6 +44,7 @@ class TangemAppLoggerInitializer(
}
}
@Suppress("BooleanPropertyNaming")
private companion object {
val IS_LOG_ENABLED: Boolean = BuildConfig.LOG_ENABLED
val PERMITTED_PRIORITY = listOf(Log.ERROR, Log.INFO)

View file

@ -20,6 +20,6 @@ data class GlobalState(
typealias CryptoCurrencyName = String
data class OnboardingState(
val onboardingStarted: Boolean = false,
val isOnboardingStarted: Boolean = false,
val shouldResetOnCreate: Boolean = false,
)

View file

@ -61,9 +61,9 @@ internal class AndroidEmailSender : EmailSender {
.setSubject(email.subject)
.setText(email.message)
email.attachment?.let {
email.attachment?.let { file ->
builder.setStream(
FileProvider.getUriForFile(activity, "${activity.packageName}.provider", it),
FileProvider.getUriForFile(activity, "${activity.packageName}.provider", file),
)
}

View file

@ -39,7 +39,7 @@ class TangemSigner(
TangemSignerResponse(
totalSignedHashes = result.data.totalSignedHashes,
remainingSignatures = result.data.remainingSignatures,
isRing = result.data.batchId?.let(::isRing) ?: false,
isRing = result.data.batchId?.let(::isRing) == true,
),
)
if (continuation.isActive) {
@ -85,7 +85,7 @@ class TangemSigner(
TangemSignerResponse(
totalSignedHashes = result.data.totalSignedHashes,
remainingSignatures = result.data.remainingSignatures,
isRing = result.data.batchId?.let(::isRing) ?: false,
isRing = result.data.batchId?.let(::isRing) == true,
),
)
if (continuation.isActive) {

View file

@ -20,23 +20,23 @@ sealed class TapError(
override val args: List<Any>? = null,
) : Throwable(), TapErrors, ArgError {
object UnknownError : TapError(R.string.send_error_unknown)
class UnknownError : TapError(R.string.send_error_unknown)
open class CustomError(val customMessage: String) : TapError(R.string.common_custom_string, listOf(customMessage))
object NoInternetConnection : TapError(R.string.wallet_notification_no_internet)
class NoInternetConnection : TapError(R.string.wallet_notification_no_internet)
sealed class WalletManager {
class NoAccountError(amountToCreateAccount: String) : CustomError(amountToCreateAccount)
class InternalError(message: String) : CustomError(message)
object BlockchainIsUnreachableTryLater : TapError(R.string.wallet_balance_blockchain_unreachable_try_later)
class BlockchainIsUnreachableTryLater : TapError(R.string.wallet_balance_blockchain_unreachable_try_later)
}
}
sealed class TapSdkError(override val messageResId: Int?) : TangemError(code = 50100) {
override var customMessage: String = code.toString()
object CardForDifferentApp : TapSdkError(R.string.alert_unsupported_card)
object CardNotSupportedByRelease : TapSdkError(R.string.error_wrong_card_type)
class CardForDifferentApp : TapSdkError(R.string.alert_unsupported_card)
class CardNotSupportedByRelease : TapSdkError(R.string.error_wrong_card_type)
}
fun TapErrors.assembleErrors(): MutableList<Pair<Int, List<Any>?>> {

View file

@ -70,7 +70,7 @@ internal class DefaultResetCardUseCase(
null
}
type?.let {
if (type != null) {
tangemSdkManager.setUserCodeRequestPolicy(policy = UserCodeRequestPolicy.Always(type))
}
}

View file

@ -119,14 +119,14 @@ internal class LegacyScanProcessor @Inject constructor(
}
private fun sendAnalytics(analyticsEvent: AnalyticsEvent?, scanResponse: ScanResponse) {
analyticsEvent?.let {
analyticsEvent?.let { event ->
// this workaround needed to send CardWasScannedEvent without adding a context
val interceptor = CardContextInterceptor(scanResponse)
val params = it.params.toMutableMap()
val params = event.params.toMutableMap()
interceptor.intercept(params)
it.params = params.toMap()
event.params = params.toMap()
Analytics.send(it)
Analytics.send(event)
}
}

View file

@ -33,8 +33,8 @@ internal object UseCaseScanProcessor {
return scanCardUseCase(cardId, allowsRequestAccessCodeFromRepository)
.fold(
ifLeft = {
val error = scanCardExceptionConverter.convertBack(it)
ifLeft = { scanCardException ->
val error = scanCardExceptionConverter.convertBack(scanCardException)
Analytics.sendErrorEvent(TangemSdkErrorEvent(error))
CompletionResult.Failure(error)

View file

@ -8,10 +8,10 @@ sealed class ScanChainException : ScanCardException.ChainException() {
/**
* May be returned from [DisclaimerChain]
* */
data object DisclaimerWasCanceled : ScanChainException() {
class DisclaimerWasCanceled : ScanChainException() {
@Suppress("UnusedPrivateMember")
private fun readResolve(): Any = DisclaimerWasCanceled
private fun readResolve(): Any = DisclaimerWasCanceled()
}
/**

View file

@ -13,19 +13,19 @@ object MockProvider {
private var content: MockContent = getMockContent(ProductType.Wallet)
private var emulateError: Boolean = false
private var isEmulatingError: Boolean = false
private var emulatedError: TangemError = TangemSdkError.TagLost()
fun setEmulateError(error: TangemError? = null) {
emulateError = true
isEmulatingError = true
error?.let {
emulatedError = it
}
}
fun resetEmulateError() {
emulateError = false
isEmulatingError = false
}
fun setMocks(productType: ProductType) {
@ -74,7 +74,7 @@ object MockProvider {
}
private fun <T> CompletionResult.Success<T>.orFailure(): CompletionResult<T> {
return if (emulateError) {
return if (isEmulatingError) {
CompletionResult.Failure(emulatedError)
} else {
this

View file

@ -168,52 +168,52 @@ object BackupWalletMockContent : MockContent {
byteArrayOf(2, -109, 28, -27, -124, -58, -97, -61, 43, -84, 90, -9, -5, 4, 90, 17, 112, -125, -108, 44, 19, -79, -60, -23, 34, -20, -20, 61, 84, 113, 120, -90, -5),
)
to
ExtendedPublicKeysMap(
mapOf(
DerivationPath("m/44'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/84'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( // eth
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/145'/0'/0/0") to ExtendedPublicKey( // bch
publicKey = byteArrayOf(2, 38, -6, 92, -37, -91, -59, -108, -18, -119, -55, 41, 38, -33, 44, 59, 24, -79, -14, -38, -10, -123, 106, 56, 39, 8, 112, 29, -41, 99, 70, -104, -121),
chainCode = byteArrayOf(105, -21, -61, -50, 68, -89, 119, 53, -96, -40, 119, 77, -122, 121, 16, 40, -50, -48, -105, -101, -74, -7, -94, -59, -90, 96, 59, 99, 43, -91, 115, -29),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/3'/0'/0/0") to ExtendedPublicKey( // doge
publicKey = byteArrayOf(3, -25, -24, -97, -124, 24, -89, 44, 75, 123, 92, -86, -73, -93, 25, -90, -89, -95, 88, 3, 107, 37, -1, -85, -32, -57, -123, -41, 108, -9, -96, 77, -124),
chainCode = byteArrayOf(119, 3, 41, 112, 71, 54, 72, 30, 39, 25, 25, -104, 92, 46, -109, 63, 93, 67, 43, -102, -87, 39, -95, 106, 45, 67, 109, -29, -35, 10, -107, 104),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/195'/0'/0/0") to ExtendedPublicKey(
publicKey = byteArrayOf(2, -40, 115, -15, 80, 104, 100, -29, 80, 29, 112, -35, -54, 64, -98, 45, 115, 108, 93, 113, -71, 89, 17, 72, 98, 21, 126, 82, -50, 50, -12, -87, -62),
chainCode = byteArrayOf(-27, 56, 57, 54, 27, -40, 65, 109, 119, -54, -94, 88, -29, -115, -45, -112, -31, 57, 53, 56, 118, 87, 34, -16, -64, -45, 105, 77, 91, -106, -92, 41),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
ExtendedPublicKeysMap(
mapOf(
DerivationPath("m/44'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/84'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( // eth
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/145'/0'/0/0") to ExtendedPublicKey( // bch
publicKey = byteArrayOf(2, 38, -6, 92, -37, -91, -59, -108, -18, -119, -55, 41, 38, -33, 44, 59, 24, -79, -14, -38, -10, -123, 106, 56, 39, 8, 112, 29, -41, 99, 70, -104, -121),
chainCode = byteArrayOf(105, -21, -61, -50, 68, -89, 119, 53, -96, -40, 119, 77, -122, 121, 16, 40, -50, -48, -105, -101, -74, -7, -94, -59, -90, 96, 59, 99, 43, -91, 115, -29),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/3'/0'/0/0") to ExtendedPublicKey( // doge
publicKey = byteArrayOf(3, -25, -24, -97, -124, 24, -89, 44, 75, 123, 92, -86, -73, -93, 25, -90, -89, -95, 88, 3, 107, 37, -1, -85, -32, -57, -123, -41, 108, -9, -96, 77, -124),
chainCode = byteArrayOf(119, 3, 41, 112, 71, 54, 72, 30, 39, 25, 25, -104, 92, 46, -109, 63, 93, 67, 43, -102, -87, 39, -95, 106, 45, 67, 109, -29, -35, 10, -107, 104),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/195'/0'/0/0") to ExtendedPublicKey(
publicKey = byteArrayOf(2, -40, 115, -15, 80, 104, 100, -29, 80, 29, 112, -35, -54, 64, -98, 45, 115, 108, 93, 113, -71, 89, 17, 72, 98, 21, 126, 82, -50, 50, -12, -87, -62),
chainCode = byteArrayOf(-27, 56, 57, 54, 27, -40, 65, 109, 119, -54, -94, 88, -29, -115, -45, -112, -31, 57, 53, 56, 118, 87, 34, -16, -64, -45, 105, 77, 91, -106, -92, 41),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
),
),
),
)
@ -234,24 +234,24 @@ object BackupWalletMockContent : MockContent {
byteArrayOf(2, -109, 28, -27, -124, -58, -97, -61, 43, -84, 90, -9, -5, 4, 90, 17, 112, -125, -108, 44, 19, -79, -60, -23, 34, -20, -20, 61, 84, 113, 120, -90, -5),
)
to
ExtendedPublicKeysMap(
mapOf(
DerivationPath("m/44'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( // eth
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
ExtendedPublicKeysMap(
mapOf(
DerivationPath("m/44'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( // eth
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
),
),
),
primaryCard = primaryCard,
)

View file

@ -168,52 +168,52 @@ object DevWalletMockContent : MockContent {
byteArrayOf(2, -109, 28, -27, -124, -58, -97, -61, 43, -84, 90, -9, -5, 4, 90, 17, 112, -125, -108, 44, 19, -79, -60, -23, 34, -20, -20, 61, 84, 113, 120, -90, -5),
)
to
ExtendedPublicKeysMap(
mapOf(
DerivationPath("m/44'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/84'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( // eth
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/145'/0'/0/0") to ExtendedPublicKey( // bch
publicKey = byteArrayOf(2, 38, -6, 92, -37, -91, -59, -108, -18, -119, -55, 41, 38, -33, 44, 59, 24, -79, -14, -38, -10, -123, 106, 56, 39, 8, 112, 29, -41, 99, 70, -104, -121),
chainCode = byteArrayOf(105, -21, -61, -50, 68, -89, 119, 53, -96, -40, 119, 77, -122, 121, 16, 40, -50, -48, -105, -101, -74, -7, -94, -59, -90, 96, 59, 99, 43, -91, 115, -29),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/3'/0'/0/0") to ExtendedPublicKey( // doge
publicKey = byteArrayOf(3, -25, -24, -97, -124, 24, -89, 44, 75, 123, 92, -86, -73, -93, 25, -90, -89, -95, 88, 3, 107, 37, -1, -85, -32, -57, -123, -41, 108, -9, -96, 77, -124),
chainCode = byteArrayOf(119, 3, 41, 112, 71, 54, 72, 30, 39, 25, 25, -104, 92, 46, -109, 63, 93, 67, 43, -102, -87, 39, -95, 106, 45, 67, 109, -29, -35, 10, -107, 104),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/195'/0'/0/0") to ExtendedPublicKey(
publicKey = byteArrayOf(2, -40, 115, -15, 80, 104, 100, -29, 80, 29, 112, -35, -54, 64, -98, 45, 115, 108, 93, 113, -71, 89, 17, 72, 98, 21, 126, 82, -50, 50, -12, -87, -62),
chainCode = byteArrayOf(-27, 56, 57, 54, 27, -40, 65, 109, 119, -54, -94, 88, -29, -115, -45, -112, -31, 57, 53, 56, 118, 87, 34, -16, -64, -45, 105, 77, 91, -106, -92, 41),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
ExtendedPublicKeysMap(
mapOf(
DerivationPath("m/44'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/84'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( // eth
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/145'/0'/0/0") to ExtendedPublicKey( // bch
publicKey = byteArrayOf(2, 38, -6, 92, -37, -91, -59, -108, -18, -119, -55, 41, 38, -33, 44, 59, 24, -79, -14, -38, -10, -123, 106, 56, 39, 8, 112, 29, -41, 99, 70, -104, -121),
chainCode = byteArrayOf(105, -21, -61, -50, 68, -89, 119, 53, -96, -40, 119, 77, -122, 121, 16, 40, -50, -48, -105, -101, -74, -7, -94, -59, -90, 96, 59, 99, 43, -91, 115, -29),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/3'/0'/0/0") to ExtendedPublicKey( // doge
publicKey = byteArrayOf(3, -25, -24, -97, -124, 24, -89, 44, 75, 123, 92, -86, -73, -93, 25, -90, -89, -95, 88, 3, 107, 37, -1, -85, -32, -57, -123, -41, 108, -9, -96, 77, -124),
chainCode = byteArrayOf(119, 3, 41, 112, 71, 54, 72, 30, 39, 25, 25, -104, 92, 46, -109, 63, 93, 67, 43, -102, -87, 39, -95, 106, 45, 67, 109, -29, -35, 10, -107, 104),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/195'/0'/0/0") to ExtendedPublicKey(
publicKey = byteArrayOf(2, -40, 115, -15, 80, 104, 100, -29, 80, 29, 112, -35, -54, 64, -98, 45, 115, 108, 93, 113, -71, 89, 17, 72, 98, 21, 126, 82, -50, 50, -12, -87, -62),
chainCode = byteArrayOf(-27, 56, 57, 54, 27, -40, 65, 109, 119, -54, -94, 88, -29, -115, -45, -112, -31, 57, 53, 56, 118, 87, 34, -16, -64, -45, 105, 77, 91, -106, -92, 41),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
),
),
),
)
@ -234,24 +234,24 @@ object DevWalletMockContent : MockContent {
byteArrayOf(2, -109, 28, -27, -124, -58, -97, -61, 43, -84, 90, -9, -5, 4, 90, 17, 112, -125, -108, 44, 19, -79, -60, -23, 34, -20, -20, 61, 84, 113, 120, -90, -5),
)
to
ExtendedPublicKeysMap(
mapOf(
DerivationPath("m/44'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( // eth
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
ExtendedPublicKeysMap(
mapOf(
DerivationPath("m/44'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( // eth
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
),
),
),
primaryCard = primaryCard,
)

View file

@ -219,38 +219,38 @@ object Wallet2MockContent : MockContent {
byteArrayOf(2, -109, 28, -27, -124, -58, -97, -61, 43, -84, 90, -9, -5, 4, 90, 17, 112, -125, -108, 44, 19, -79, -60, -23, 34, -20, -20, 61, 84, 113, 120, -90, -5),
)
to
ExtendedPublicKeysMap(
mapOf(
DerivationPath("m/44'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( // eth
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/145'/0'/0/0") to ExtendedPublicKey( // bch
publicKey = byteArrayOf(2, 38, -6, 92, -37, -91, -59, -108, -18, -119, -55, 41, 38, -33, 44, 59, 24, -79, -14, -38, -10, -123, 106, 56, 39, 8, 112, 29, -41, 99, 70, -104, -121),
chainCode = byteArrayOf(105, -21, -61, -50, 68, -89, 119, 53, -96, -40, 119, 77, -122, 121, 16, 40, -50, -48, -105, -101, -74, -7, -94, -59, -90, 96, 59, 99, 43, -91, 115, -29),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/3'/0'/0/0") to ExtendedPublicKey( // doge
publicKey = byteArrayOf(3, -25, -24, -97, -124, 24, -89, 44, 75, 123, 92, -86, -73, -93, 25, -90, -89, -95, 88, 3, 107, 37, -1, -85, -32, -57, -123, -41, 108, -9, -96, 77, -124),
chainCode = byteArrayOf(119, 3, 41, 112, 71, 54, 72, 30, 39, 25, 25, -104, 92, 46, -109, 63, 93, 67, 43, -102, -87, 39, -95, 106, 45, 67, 109, -29, -35, 10, -107, 104),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
ExtendedPublicKeysMap(
mapOf(
DerivationPath("m/44'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( // eth
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/145'/0'/0/0") to ExtendedPublicKey( // bch
publicKey = byteArrayOf(2, 38, -6, 92, -37, -91, -59, -108, -18, -119, -55, 41, 38, -33, 44, 59, 24, -79, -14, -38, -10, -123, 106, 56, 39, 8, 112, 29, -41, 99, 70, -104, -121),
chainCode = byteArrayOf(105, -21, -61, -50, 68, -89, 119, 53, -96, -40, 119, 77, -122, 121, 16, 40, -50, -48, -105, -101, -74, -7, -94, -59, -90, 96, 59, 99, 43, -91, 115, -29),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/3'/0'/0/0") to ExtendedPublicKey( // doge
publicKey = byteArrayOf(3, -25, -24, -97, -124, 24, -89, 44, 75, 123, 92, -86, -73, -93, 25, -90, -89, -95, 88, 3, 107, 37, -1, -85, -32, -57, -123, -41, 108, -9, -96, 77, -124),
chainCode = byteArrayOf(119, 3, 41, 112, 71, 54, 72, 30, 39, 25, 25, -104, 92, 46, -109, 63, 93, 67, 43, -102, -87, 39, -95, 106, 45, 67, 109, -29, -35, 10, -107, 104),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
),
),
),
)
@ -271,24 +271,24 @@ object Wallet2MockContent : MockContent {
byteArrayOf(2, -109, 28, -27, -124, -58, -97, -61, 43, -84, 90, -9, -5, 4, 90, 17, 112, -125, -108, 44, 19, -79, -60, -23, 34, -20, -20, 61, 84, 113, 120, -90, -5),
)
to
ExtendedPublicKeysMap(
mapOf(
DerivationPath("m/44'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( // eth
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
ExtendedPublicKeysMap(
mapOf(
DerivationPath("m/44'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( // eth
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
),
),
),
primaryCard = primaryCard,
)

View file

@ -219,38 +219,38 @@ object Wallet2WithSeedPhraseMockContent : MockContent {
byteArrayOf(2, -109, 28, -27, -124, -58, -97, -61, 43, -84, 90, -9, -5, 4, 90, 17, 112, -125, -108, 44, 19, -79, -60, -23, 34, -20, -20, 61, 84, 113, 120, -90, -5),
)
to
ExtendedPublicKeysMap(
mapOf(
DerivationPath("m/44'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( // eth
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/145'/0'/0/0") to ExtendedPublicKey( // bch
publicKey = byteArrayOf(2, 38, -6, 92, -37, -91, -59, -108, -18, -119, -55, 41, 38, -33, 44, 59, 24, -79, -14, -38, -10, -123, 106, 56, 39, 8, 112, 29, -41, 99, 70, -104, -121),
chainCode = byteArrayOf(105, -21, -61, -50, 68, -89, 119, 53, -96, -40, 119, 77, -122, 121, 16, 40, -50, -48, -105, -101, -74, -7, -94, -59, -90, 96, 59, 99, 43, -91, 115, -29),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/3'/0'/0/0") to ExtendedPublicKey( // doge
publicKey = byteArrayOf(3, -25, -24, -97, -124, 24, -89, 44, 75, 123, 92, -86, -73, -93, 25, -90, -89, -95, 88, 3, 107, 37, -1, -85, -32, -57, -123, -41, 108, -9, -96, 77, -124),
chainCode = byteArrayOf(119, 3, 41, 112, 71, 54, 72, 30, 39, 25, 25, -104, 92, 46, -109, 63, 93, 67, 43, -102, -87, 39, -95, 106, 45, 67, 109, -29, -35, 10, -107, 104),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
ExtendedPublicKeysMap(
mapOf(
DerivationPath("m/44'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( // eth
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/145'/0'/0/0") to ExtendedPublicKey( // bch
publicKey = byteArrayOf(2, 38, -6, 92, -37, -91, -59, -108, -18, -119, -55, 41, 38, -33, 44, 59, 24, -79, -14, -38, -10, -123, 106, 56, 39, 8, 112, 29, -41, 99, 70, -104, -121),
chainCode = byteArrayOf(105, -21, -61, -50, 68, -89, 119, 53, -96, -40, 119, 77, -122, 121, 16, 40, -50, -48, -105, -101, -74, -7, -94, -59, -90, 96, 59, 99, 43, -91, 115, -29),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/3'/0'/0/0") to ExtendedPublicKey( // doge
publicKey = byteArrayOf(3, -25, -24, -97, -124, 24, -89, 44, 75, 123, 92, -86, -73, -93, 25, -90, -89, -95, 88, 3, 107, 37, -1, -85, -32, -57, -123, -41, 108, -9, -96, 77, -124),
chainCode = byteArrayOf(119, 3, 41, 112, 71, 54, 72, 30, 39, 25, 25, -104, 92, 46, -109, 63, 93, 67, 43, -102, -87, 39, -95, 106, 45, 67, 109, -29, -35, 10, -107, 104),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
),
),
),
)
@ -271,24 +271,24 @@ object Wallet2WithSeedPhraseMockContent : MockContent {
byteArrayOf(3, 23, -112, -57, 109, 60, -82, -36, 45, -14, -34, -12, 10, -89, 14, 37, 38, 36, -102, 37, 93, 90, 69, -113, -117, 120, -29, 12, -125, 43, -40, -31, 5),
)
to
ExtendedPublicKeysMap(
mapOf(
DerivationPath("m/44'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( // eth
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
ExtendedPublicKeysMap(
mapOf(
DerivationPath("m/44'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( // eth
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
),
),
),
primaryCard = primaryCard,
)

View file

@ -168,59 +168,59 @@ object WalletMockContent : MockContent {
byteArrayOf(2, -109, 28, -27, -124, -58, -97, -61, 43, -84, 90, -9, -5, 4, 90, 17, 112, -125, -108, 44, 19, -79, -60, -23, 34, -20, -20, 61, 84, 113, 120, -90, -5),
)
to
ExtendedPublicKeysMap(
mapOf(
DerivationPath("m/44'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/84'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( // eth
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/145'/0'/0/0") to ExtendedPublicKey( // bch
publicKey = byteArrayOf(2, 38, -6, 92, -37, -91, -59, -108, -18, -119, -55, 41, 38, -33, 44, 59, 24, -79, -14, -38, -10, -123, 106, 56, 39, 8, 112, 29, -41, 99, 70, -104, -121),
chainCode = byteArrayOf(105, -21, -61, -50, 68, -89, 119, 53, -96, -40, 119, 77, -122, 121, 16, 40, -50, -48, -105, -101, -74, -7, -94, -59, -90, 96, 59, 99, 43, -91, 115, -29),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/144'/0'/0/0") to ExtendedPublicKey( // xrp
publicKey = byteArrayOf(2, 38, -6, 92, -37, -91, -59, -108, -18, -119, -55, 41, 38, -33, 44, 59, 24, -79, -14, -38, -10, -123, 106, 56, 39, 8, 112, 29, -41, 99, 70, -104, -121),
chainCode = byteArrayOf(105, -21, -61, -50, 68, -89, 119, 53, -96, -40, 119, 77, -122, 121, 16, 40, -50, -48, -105, -101, -74, -7, -94, -59, -90, 96, 59, 99, 43, -91, 115, -29),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/3'/0'/0/0") to ExtendedPublicKey( // doge
publicKey = byteArrayOf(3, -25, -24, -97, -124, 24, -89, 44, 75, 123, 92, -86, -73, -93, 25, -90, -89, -95, 88, 3, 107, 37, -1, -85, -32, -57, -123, -41, 108, -9, -96, 77, -124),
chainCode = byteArrayOf(119, 3, 41, 112, 71, 54, 72, 30, 39, 25, 25, -104, 92, 46, -109, 63, 93, 67, 43, -102, -87, 39, -95, 106, 45, 67, 109, -29, -35, 10, -107, 104),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/195'/0'/0/0") to ExtendedPublicKey(
publicKey = byteArrayOf(2, -40, 115, -15, 80, 104, 100, -29, 80, 29, 112, -35, -54, 64, -98, 45, 115, 108, 93, 113, -71, 89, 17, 72, 98, 21, 126, 82, -50, 50, -12, -87, -62),
chainCode = byteArrayOf(-27, 56, 57, 54, 27, -40, 65, 109, 119, -54, -94, 88, -29, -115, -45, -112, -31, 57, 53, 56, 118, 87, 34, -16, -64, -45, 105, 77, 91, -106, -92, 41),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
ExtendedPublicKeysMap(
mapOf(
DerivationPath("m/44'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/84'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( // eth
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/145'/0'/0/0") to ExtendedPublicKey( // bch
publicKey = byteArrayOf(2, 38, -6, 92, -37, -91, -59, -108, -18, -119, -55, 41, 38, -33, 44, 59, 24, -79, -14, -38, -10, -123, 106, 56, 39, 8, 112, 29, -41, 99, 70, -104, -121),
chainCode = byteArrayOf(105, -21, -61, -50, 68, -89, 119, 53, -96, -40, 119, 77, -122, 121, 16, 40, -50, -48, -105, -101, -74, -7, -94, -59, -90, 96, 59, 99, 43, -91, 115, -29),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/144'/0'/0/0") to ExtendedPublicKey( // xrp
publicKey = byteArrayOf(2, 38, -6, 92, -37, -91, -59, -108, -18, -119, -55, 41, 38, -33, 44, 59, 24, -79, -14, -38, -10, -123, 106, 56, 39, 8, 112, 29, -41, 99, 70, -104, -121),
chainCode = byteArrayOf(105, -21, -61, -50, 68, -89, 119, 53, -96, -40, 119, 77, -122, 121, 16, 40, -50, -48, -105, -101, -74, -7, -94, -59, -90, 96, 59, 99, 43, -91, 115, -29),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/3'/0'/0/0") to ExtendedPublicKey( // doge
publicKey = byteArrayOf(3, -25, -24, -97, -124, 24, -89, 44, 75, 123, 92, -86, -73, -93, 25, -90, -89, -95, 88, 3, 107, 37, -1, -85, -32, -57, -123, -41, 108, -9, -96, 77, -124),
chainCode = byteArrayOf(119, 3, 41, 112, 71, 54, 72, 30, 39, 25, 25, -104, 92, 46, -109, 63, 93, 67, 43, -102, -87, 39, -95, 106, 45, 67, 109, -29, -35, 10, -107, 104),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/195'/0'/0/0") to ExtendedPublicKey(
publicKey = byteArrayOf(2, -40, 115, -15, 80, 104, 100, -29, 80, 29, 112, -35, -54, 64, -98, 45, 115, 108, 93, 113, -71, 89, 17, 72, 98, 21, 126, 82, -50, 50, -12, -87, -62),
chainCode = byteArrayOf(-27, 56, 57, 54, 27, -40, 65, 109, 119, -54, -94, 88, -29, -115, -45, -112, -31, 57, 53, 56, 118, 87, 34, -16, -64, -45, 105, 77, 91, -106, -92, 41),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
),
),
),
)
@ -241,24 +241,24 @@ object WalletMockContent : MockContent {
byteArrayOf(2, -109, 28, -27, -124, -58, -97, -61, 43, -84, 90, -9, -5, 4, 90, 17, 112, -125, -108, 44, 19, -79, -60, -23, 34, -20, -20, 61, 84, 113, 120, -90, -5),
)
to
ExtendedPublicKeysMap(
mapOf(
DerivationPath("m/44'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( // eth
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
ExtendedPublicKeysMap(
mapOf(
DerivationPath("m/44'/0'/0'/0/0") to ExtendedPublicKey( // btc
publicKey = byteArrayOf(3, 45, 58, -110, -52, -51, -83, -4, -45, -118, 119, 37, 123, -17, 66, -83, 61, -106, 115, 47, 121, 66, 84, -122, -57, -45, 7, -79, 70, -13, 28, -125, -52),
chainCode = byteArrayOf(93, 51, 52, -66, -39, -38, 34, -84, 50, 1, -127, -20, 80, -20, -30, -72, 2, 1, -78, -81, -17, 51, -52, -25, 12, 108, 50, 89, -66, 18, 65, 70),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey( // eth
publicKey = byteArrayOf(2, 34, 6, 119, -106, 5, -119, 111, -22, 8, 23, -108, -72, -56, 6, 77, -17, -61, -101, -85, 16, 28, 18, 3, -3, -89, -81, -108, 48, -7, -86, -82, -67),
chainCode = byteArrayOf(-75, 55, 107, -106, -37, -81, -15, 72, -102, 94, 55, -39, 9, -112, 1, 90, -50, 103, 53, 120, -92, -36, -85, -39, -65, 1, 88, 46, 92, 104, -13, -109),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
),
),
),
),
primaryCard = primaryCard,
)

View file

@ -42,7 +42,12 @@ class SignHashesTask(
is CompletionResult.Failure -> {
when {
response.error is TangemSdkError.WalletNotFound && pairWalletPublicKey != null -> {
sign(session, pairWalletPublicKey, publicKey.derivationPath, callback)
sign(
session = session,
publicKey = pairWalletPublicKey,
derivationPath = publicKey.derivationPath,
callback = callback,
)
}
else -> callback(CompletionResult.Failure(response.error))
}

View file

@ -64,22 +64,28 @@ class CreateProductWalletTask(
cardTypesResolver.isTangemTwins() ->
throw UnsupportedOperationException("Use the TwinCardsManager to create a wallet")
else -> CreateWalletTangemWallet(mnemonic, passphrase, shouldReset, derivationStyleProvider, cardDto)
else -> CreateWalletTangemWallet(
mnemonic = mnemonic,
passphrase = passphrase,
shouldReset = shouldReset,
derivationStyleProvider = derivationStyleProvider,
cardDTO = cardDto,
)
}
commandProcessor.proceed(cardDto, session) {
when (it) {
commandProcessor.proceed(cardDto, session) { result ->
when (result) {
is CompletionResult.Success -> {
val result = when (commandProcessor) {
val createProductWalletTaskResponse = when (commandProcessor) {
is CreateWalletTangemWallet -> {
it.data as CreateProductWalletTaskResponse
result.data as CreateProductWalletTaskResponse
}
else -> CreateProductWalletTaskResponse(card = session.environment.card!!)
else -> CreateProductWalletTaskResponse(card = requireNotNull(session.environment.card))
}
callback(CompletionResult.Success(result))
callback(CompletionResult.Success(createProductWalletTaskResponse))
}
is CompletionResult.Failure -> callback(CompletionResult.Failure(it.error))
is CompletionResult.Failure -> callback(CompletionResult.Failure(result.error))
}
}
}
@ -156,7 +162,12 @@ private class CreateWalletTangemWallet(
CreateWalletsTask(cardConfig.mandatoryCurves, mnemonic, passphrase).run(session) { result ->
when (result) {
is CompletionResult.Success -> {
checkIfAllWalletsCreated(card, session, result.data, callback)
checkIfAllWalletsCreated(
card = card,
session = session,
createResponse = result.data,
callback = callback,
)
}
is CompletionResult.Failure -> {
callback(CompletionResult.Failure(result.error))
@ -210,12 +221,16 @@ private class CreateWalletTangemWallet(
callback: (result: CompletionResult<CreateProductWalletTaskResponse>) -> Unit,
) {
val resetCommand = ResetToFactorySettingsTask(allowsRequestAccessCodeFromRepository = false)
resetCommand.run(session) {
when (it) {
resetCommand.run(session) { result ->
when (result) {
is CompletionResult.Success -> {
createMultiWallet(card, session, callback)
createMultiWallet(
card = card,
session = session,
callback = callback,
)
}
is CompletionResult.Failure -> callback(CompletionResult.Failure(it.error))
is CompletionResult.Failure -> callback(CompletionResult.Failure(result.error))
}
}
}
@ -228,17 +243,27 @@ private class CreateWalletTangemWallet(
) {
when {
card.settings.isBackupAllowed -> {
linkPrimaryCard(card, createWalletResponses, session, callback)
linkPrimaryCard(
card = card,
createWalletResponses = createWalletResponses,
session = session,
callback = callback,
)
}
card.settings.isHDWalletAllowed -> {
deriveKeys(card, createWalletResponses, session, callback)
deriveKeys(
card = card,
createWalletResponses = createWalletResponses,
session = session,
callback = callback,
)
}
else -> {
callback(
CompletionResult.Success(
CreateProductWalletTaskResponse(card = session.environment.card!!),
CreateProductWalletTaskResponse(card = requireNotNull(session.environment.card)),
),
)
}
@ -247,7 +272,7 @@ private class CreateWalletTangemWallet(
private fun linkPrimaryCard(
card: CardDTO,
createWalletResponse: List<CreateWalletResponse>,
createWalletResponses: List<CreateWalletResponse>,
session: CardSession,
callback: (result: CompletionResult<CreateProductWalletTaskResponse>) -> Unit,
) {
@ -257,14 +282,19 @@ private class CreateWalletTangemWallet(
primaryCard = result.data
when {
card.settings.isHDWalletAllowed -> {
deriveKeys(card, createWalletResponse, session, callback)
deriveKeys(
card = card,
createWalletResponses = createWalletResponses,
session = session,
callback = callback,
)
}
else -> {
callback(
CompletionResult.Success(
CreateProductWalletTaskResponse(
card = session.environment.card!!,
card = requireNotNull(session.environment.card),
primaryCard = primaryCard,
),
),
@ -282,13 +312,13 @@ private class CreateWalletTangemWallet(
private fun deriveKeys(
card: CardDTO,
createWalletResponse: List<CreateWalletResponse>,
createWalletResponses: List<CreateWalletResponse>,
session: CardSession,
callback: (result: CompletionResult<CreateProductWalletTaskResponse>) -> Unit,
) {
val map = mutableMapOf<ByteArrayKey, List<DerivationPath>>()
var isBlockchainsForCurvesExist = false
createWalletResponse.forEach { response ->
createWalletResponses.forEach { response ->
val blockchainsForCurve = getBlockchains(response.cardId, card).filter {
it.getSupportedCurves().contains(response.wallet.curve)
}

View file

@ -42,7 +42,7 @@ class CreateWalletsTask(
callback: (result: CompletionResult<CreateWalletsResponse>) -> Unit,
) {
val extendedPrivateKey = mnemonic?.let {
AnyMasterKeyFactory(mnemonic = it, passphrase = passphrase ?: "").makeMasterKey(curve)
AnyMasterKeyFactory(mnemonic = it, passphrase = passphrase.orEmpty()).makeMasterKey(curve)
}
CreateWalletTask(curve, extendedPrivateKey).run(session) { result ->
when (result) {

View file

@ -34,12 +34,10 @@ internal class DerivationsFinder(
val userWalletId = UserWalletIdBuilder.card(card).build() ?: return emptySet()
val derivationStyle = derivationStyleProvider.getDerivationStyle()
var blockchains = withContext(dispatchers.io) {
val blockchains = withContext(dispatchers.io) {
getBlockchains(userWalletId)
}
if (blockchains.isEmpty()) {
blockchains = if (DemoHelper.isDemoCardId(card.cardId)) {
}.ifEmpty {
if (DemoHelper.isDemoCardId(card.cardId)) {
getDemoBlockchains(derivationStyle)
} else {
getDefaultBlockchains(derivationStyle)

View file

@ -19,10 +19,15 @@ class ResetToFactorySettingsTask(
}
private fun deleteWallets(session: CardSession, callback: (result: CompletionResult<Boolean>) -> Unit) {
val wallet = session.environment.card?.wallets?.lastOrNull().guard {
resetBackup(session, callback)
return
}
val wallet = session
.environment
.card
?.wallets
?.lastOrNull()
.guard {
resetBackup(session, callback)
return
}
PurgeWalletCommand(wallet.publicKey).run(session) { result ->
when (result) {

View file

@ -111,13 +111,13 @@ internal class ScanProductTask(
}
private fun getErrorIfExcludedCard(cardDto: CardDTO, card: Card): TangemError? {
if (cardDto.isExcluded) return TapSdkError.CardForDifferentApp
if (cardDto.isNotSupportedInThatRelease) return TapSdkError.CardNotSupportedByRelease
if (cardDto.isExcluded) return TapSdkError.CardForDifferentApp()
if (cardDto.isNotSupportedInThatRelease) return TapSdkError.CardNotSupportedByRelease()
// according ios decline card lower Ed25519Slip0010Available version and contains imported wallets
if (card.firmwareVersion < FirmwareVersion.Ed25519Slip0010Available &&
card.wallets.any { it.isImported }
) {
return TapSdkError.CardNotSupportedByRelease
return TapSdkError.CardNotSupportedByRelease()
}
return null
}
@ -253,12 +253,13 @@ private class ScanWalletProcessor(
callback: (result: CompletionResult<ScanResponse>) -> Unit,
) {
mainScope.launch {
val activationInProgress = store.inject(DaggerGraphState::cardRepository)
val isActivationInProgress = store.inject(DaggerGraphState::cardRepository)
.isActivationInProgress(card.cardId)
@Suppress("ComplexCondition")
if (card.backupStatus == CardDTO.BackupStatus.NoBackup && card.wallets.isNotEmpty() &&
activationInProgress
if (card.backupStatus == CardDTO.BackupStatus.NoBackup &&
card.wallets.isNotEmpty() &&
isActivationInProgress
) {
StartPrimaryCardLinkingTask().run(session) { linkingResult ->
when (linkingResult) {
@ -372,8 +373,8 @@ private class ScanTwinProcessor : ProductCommandProcessor<ScanResponse> {
return@run
}
val verified = TwinsHelper.verifyTwinPublicKey(readDataResult.data.issuerData, publicKey)
val response = if (verified) {
val isVerified = TwinsHelper.verifyTwinPublicKey(readDataResult.data.issuerData, publicKey)
val response = if (isVerified) {
val twinPublicKey = readDataResult.data.issuerData.sliceArray(0 until 65)
val walletData = session.environment.walletData
ScanResponse(

View file

@ -153,9 +153,9 @@ class VisaCardActivationTask @AssistedInject constructor(
val otpTaskDeferred = async { createOTP() }
val dataToSign = dataToSignDeferred.await()
.getOrElse {
.getOrElse { error ->
otpTaskDeferred.cancel()
return@coroutineScope CompletionResult.Failure(it)
return@coroutineScope CompletionResult.Failure(error)
}
otpTaskDeferred.await()

View file

@ -115,8 +115,8 @@ class VisaCustomerWalletApproveTask(
extendedPublicKey = extendedPublicKey,
)
validationResult.onLeft {
callback(CompletionResult.Failure(it.tangemError))
validationResult.onLeft { error ->
callback(CompletionResult.Failure(error.tangemError))
return
}
@ -137,8 +137,8 @@ class VisaCustomerWalletApproveTask(
val publicKey = findKeyWithoutDerivation(
targetAddress = visaDataForApprove.targetAddress,
card = CardDTO(card),
).getOrElse {
callback(CompletionResult.Failure(it.tangemError))
).getOrElse { error ->
callback(CompletionResult.Failure(error.tangemError))
return
}

View file

@ -37,7 +37,7 @@ class CreateSecondTwinWalletTask(
}
if (!TwinsHelper.isTwinsCompatible(firstCardId, card.cardId)) {
callback(CompletionResult.Failure(IncompatibleTwinCard))
callback(CompletionResult.Failure(IncompatibleTwinCard()))
return
}

View file

@ -24,7 +24,7 @@ class FinalizeTwinTask(
when (readResult) {
is CompletionResult.Success ->
ScanProductTask(
readResult.data,
card = readResult.data,
derivationsFinder = null,
visaCardScanHandler = null,
visaCoroutineScope = null,

View file

@ -4,7 +4,7 @@ import com.tangem.common.core.TangemError
import com.tangem.tap.tangemSdkManager
import com.tangem.wallet.R
object IncompatibleTwinCard : TangemError(code = 50005) {
class IncompatibleTwinCard : TangemError(code = 50005) {
override var customMessage: String = tangemSdkManager.getString(
R.string.twin_error_wrong_twin,
)

View file

@ -41,7 +41,7 @@ class TwinCardsManager(card: CardDTO) {
creatingWalletMessage: Message,
): CompletionResult<CreateWalletResponse> {
val response = tangemSdkManager.createSecondTwinWallet(
firstPublicKey = currentCardPublicKey!!,
firstPublicKey = requireNotNull(currentCardPublicKey),
firstCardId = firstCardId,
issuerKeys = getIssuerKeys(),
preparingMessage = preparingMessage,
@ -58,7 +58,7 @@ class TwinCardsManager(card: CardDTO) {
suspend fun complete(message: Message): CompletionResult<ScanResponse> {
val response = tangemSdkManager.finalizeTwin(
secondCardPublicKey = secondCardPublicKey!!.hexToBytes(),
secondCardPublicKey = requireNotNull(secondCardPublicKey).hexToBytes(),
issuerKeyPair = getIssuerKeys(),
cardId = firstCardId,
initialMessage = message,

View file

@ -21,8 +21,9 @@ class WriteProtectedIssuerDataTask(
override fun run(session: CardSession, callback: (result: CompletionResult<SuccessResponse>) -> Unit) {
SignHashCommand(
twinPublicKey.calculateSha256(),
session.environment.card!!.wallets.first().publicKey,
hash = twinPublicKey.calculateSha256(),
walletPublicKey = requireNotNull(session.environment.card)
.wallets.first().publicKey,
)
.run(session) { signResult ->
when (signResult) {
@ -31,12 +32,12 @@ class WriteProtectedIssuerDataTask(
when (readResult) {
is CompletionResult.Success -> {
writeIssuerData(
twinPublicKey,
issuerKeys,
signResult.data.signature,
readResult.data,
session,
callback,
twinPublicKey = twinPublicKey,
issuerKeys = issuerKeys,
cardSignature = signResult.data.signature,
readResponse = readResult.data,
session = session,
callback = callback,
)
}
is CompletionResult.Failure -> callback(
@ -78,7 +79,7 @@ class WriteProtectedIssuerDataTask(
)
WriteIssuerDataCommand(
issuerData = data,
issuerDataSignature = signedByIssuer.finalizingSignature!!,
issuerDataSignature = requireNotNull(signedByIssuer.finalizingSignature),
issuerDataCounter = counter,
issuerPublicKey = issuerKeys.publicKey,
).run(session, callback)

View file

@ -57,12 +57,12 @@ internal class BiometricUserWalletsListManager(
override val selectedUserWalletSync: UserWallet?
get() = findSelectedUserWallet()
override val isLocked: Flow<Boolean>
override val lockedState: Flow<Boolean>
get() = state
.mapLatest { it.isLocked }
.distinctUntilChanged()
override val isLockedSync: Boolean
override val isLocked: Boolean
get() = state.value.isLocked
override val hasUserWallets: Boolean
@ -103,7 +103,9 @@ internal class BiometricUserWalletsListManager(
override suspend fun select(userWalletId: UserWalletId): CompletionResult<UserWallet> = catching {
if (state.value.selectedUserWalletId == userWalletId) {
return@catching findSelectedUserWallet()!!
return@catching requireNotNull(findSelectedUserWallet()) {
"Wallet is not found"
}
}
selectedUserWalletRepository.set(userWalletId)

View file

@ -93,23 +93,23 @@ internal class GeneralUserWalletsListManager(
override val walletsCount: Int
get() = requireImplementation.walletsCount
override val isLocked: Flow<Boolean>
override val lockedState: Flow<Boolean>
get() = implementation.transformLatest { impl ->
if (impl == null) return@transformLatest
if (impl is UserWalletsListManager.Lockable) {
emitAll(impl.isLocked)
emitAll(impl.lockedState)
} else {
error("RuntimeUserWalletsListManager is not lockable")
}
}
override val isLockedSync: Boolean
override val isLocked: Boolean
get() {
val impl = requireImplementation
return if (impl is UserWalletsListManager.Lockable) {
impl.isLockedSync
impl.isLocked
} else {
error("RuntimeUserWalletsListManager is not lockable")
}
@ -173,10 +173,10 @@ internal class GeneralUserWalletsListManager(
}
if (possibleManager == implementation.value) {
Timber.e("Switch to the same manager ${possibleManager::class.simpleName}")
Timber.e("Switch to the same manager ${possibleManager::class.simpleName.orEmpty()}")
}
Timber.i("Switch to ${possibleManager::class.simpleName}")
Timber.i("Switch to ${possibleManager::class.simpleName.orEmpty()}")
val previousManager = implementation.value
implementation.value = copySelectedUserWallet(

View file

@ -74,11 +74,13 @@ internal class RuntimeUserWalletsListManager : UserWalletsListManager {
?.takeIf { it.walletId == userWalletId }
?: walletNotFound()
state.updateAndGet { prevState ->
prevState.copy(
userWallet = update(wallet),
)
}.userWallet!!
requireNotNull(
state.updateAndGet { prevState ->
prevState.copy(
userWallet = update(wallet),
)
}.userWallet,
) { "User wallet is null after update" }
}
override suspend fun delete(userWalletIds: List<UserWalletId>): CompletionResult<Unit> = clear()

View file

@ -21,6 +21,7 @@ internal data class UserWalletSensitiveInformation(
val mobileWallets: List<MobileWallet>? = null,
)
@Suppress("BooleanPropertyNaming")
@JsonClass(generateAdapter = true)
internal data class UserWalletPublicInformation(
// Common

View file

@ -125,7 +125,7 @@ internal class DefaultUserWalletsListRepository(
// update the userWallets state and add if it doesn't exist
updateWallets { currentWallets ->
val wallets = currentWallets ?: emptyList()
val wallets = currentWallets.orEmpty()
if (wallets.any { it.walletId == userWallet.walletId }) {
wallets.map { if (it.walletId == userWallet.walletId) userWallet else it }
} else {
@ -332,12 +332,12 @@ internal class DefaultUserWalletsListRepository(
raise(LockWalletsError.NothingToLock)
}
updateWallets {
it?.map {
if (it.walletId !in unsecuredWalletIds) {
it.lock()
updateWallets { wallets ->
wallets?.map { wallet ->
if (wallet.walletId !in unsecuredWalletIds) {
wallet.lock()
} else {
it
wallet
}
}
}
@ -395,17 +395,17 @@ internal class DefaultUserWalletsListRepository(
}
private suspend fun hasBiometry(): Boolean {
val useBiometricAuthentication = appPreferencesStore.getSyncOrDefault(
val isBiometricAuthenticationUsed = appPreferencesStore.getSyncOrDefault(
key = PreferencesKeys.USE_BIOMETRIC_AUTHENTICATION_KEY,
default = false,
)
return tangemSdkManagerProvider.invoke().canUseBiometry && useBiometricAuthentication
return tangemSdkManagerProvider.invoke().canUseBiometry && isBiometricAuthenticationUsed
}
private fun updateWallets(block: (List<UserWallet>?) -> List<UserWallet>?) {
userWallets.update {
val updated = block(it)
userWallets.update { wallets ->
val updated = block(wallets)
selectedUserWallet.update { currentSelected ->
if (currentSelected == null) return@update null
updated?.find { it.walletId == currentSelected.walletId }

View file

@ -137,8 +137,7 @@ internal class UserWalletEncryptionKeysRepository(
private suspend fun UserWalletEncryptionKey.encode(): ByteArray {
return withContext(dispatchers.default) {
this@encode
.let(encryptionKeyAdapter::toJson)
encryptionKeyAdapter.toJson(this@encode)
.encodeToByteArray(throwOnInvalidSequence = true)
}
}
@ -153,8 +152,7 @@ internal class UserWalletEncryptionKeysRepository(
private suspend fun List<UserWalletId>.encode(): ByteArray {
return withContext(dispatchers.default) {
this@encode
.let(userWalletsIdsListAdapter::toJson)
userWalletsIdsListAdapter.toJson(this@encode)
.encodeToByteArray(throwOnInvalidSequence = true)
}
}

View file

@ -164,8 +164,7 @@ internal class BiometricUserWalletsKeysRepository(
private suspend fun UserWalletEncryptionKey.encode(): ByteArray {
return withContext(Dispatchers.Default) {
this@encode
.let(encryptionKeyAdapter::toJson)
encryptionKeyAdapter.toJson(this@encode)
.encodeToByteArray(throwOnInvalidSequence = true)
}
}
@ -180,8 +179,7 @@ internal class BiometricUserWalletsKeysRepository(
private suspend fun List<UserWalletId>.encode(): ByteArray {
return withContext(Dispatchers.Default) {
this@encode
.let(userWalletsIdsListAdapter::toJson)
userWalletsIdsListAdapter.toJson(this@encode)
.encodeToByteArray(throwOnInvalidSequence = true)
}
}

View file

@ -80,8 +80,7 @@ internal class DefaultUserWalletsPublicInformationRepository(
@JvmName("saveWithPublicInformation")
private suspend fun save(publicInformation: List<UserWalletPublicInformation>): CompletionResult<Unit> = catching {
withContext(Dispatchers.IO) {
publicInformation
.let(publicInformationAdapter::toJson)
publicInformationAdapter.toJson(publicInformation)
.encodeToByteArray(throwOnInvalidSequence = true)
.also { secureStorage.store(it, StorageKey.UserWalletPublicInformation.name) }
}

View file

@ -110,18 +110,18 @@ internal class DefaultUserWalletsSensitiveInformationRepository(
private suspend fun ByteArray.decodeToEncryptedSensitiveInformation(): Map<String, ByteArray>? {
return withContext(Dispatchers.Default) {
this@decodeToEncryptedSensitiveInformation
.decodeToString(throwOnInvalidSequence = true)
.let(encryptedSensitiveInformationMapAdapter::fromJson)
encryptedSensitiveInformationMapAdapter.fromJson(
this@decodeToEncryptedSensitiveInformation.decodeToString(throwOnInvalidSequence = true),
)
}
}
private suspend fun ByteArray.decodeToSensitiveInformation(): UserWalletSensitiveInformation? {
return withContext(Dispatchers.Default) {
try {
this@decodeToSensitiveInformation
.decodeToString(throwOnInvalidSequence = true)
.let(sensitiveInformationAdapter::fromJson)
sensitiveInformationAdapter.fromJson(
this@decodeToSensitiveInformation.decodeToString(throwOnInvalidSequence = true),
)
} catch (e: CharacterCodingException) {
Timber.e(e, "Unable to decode sensitive information")
@ -132,16 +132,14 @@ internal class DefaultUserWalletsSensitiveInformationRepository(
private suspend fun UserWalletSensitiveInformation.encode(): ByteArray {
return withContext(Dispatchers.Default) {
this@encode
.let(sensitiveInformationAdapter::toJson)
sensitiveInformationAdapter.toJson(this@encode)
.encodeToByteArray(throwOnInvalidSequence = true)
}
}
private suspend fun Map<String, ByteArray>.encode(): ByteArray {
return withContext(Dispatchers.Default) {
this@encode
.let(encryptedSensitiveInformationMapAdapter::toJson)
encryptedSensitiveInformationMapAdapter.toJson(this@encode)
.encodeToByteArray(throwOnInvalidSequence = true)
}
}

View file

@ -54,14 +54,14 @@ internal fun UserWalletPublicInformation.toUserWallet(): UserWallet {
walletId = walletId,
hotWalletId = hotWalletId,
wallets = null,
backedUp = backedUp!!,
backedUp = requireNotNull(backedUp),
)
} else {
UserWallet.Cold(
name = name,
walletId = walletId,
cardsInWallet = cardsInWallet,
scanResponse = scanResponse!!,
scanResponse = requireNotNull(scanResponse),
isMultiCurrency = isMultiCurrency,
hasBackupError = hasBackupError,
)
@ -78,7 +78,7 @@ internal fun UserWallet.updateWith(sensitiveInformation: UserWalletSensitiveInfo
copy(
scanResponse = scanResponse.copy(
card = scanResponse.card.copy(
wallets = sensitiveInformation.wallets!!,
wallets = requireNotNull(sensitiveInformation.wallets),
),
visaCardActivationStatus = sensitiveInformation.visaCardActivationStatus,
),

View file

@ -87,9 +87,9 @@ internal class VisaCardScanHandler @Inject constructor(
cardId = card.cardId,
// This is the wallet public key, not the address and it's alright, as the API expects it in this format
cardWalletAddress = wallet.publicKey.toHexString(),
).getOrElse {
).getOrElse { error ->
Timber.i("Failed to get Access token for Wallet public key authorization")
return CompletionResult.Failure(it.tangemError)
return CompletionResult.Failure(error.tangemError)
}
val signChallengeResult = signChallengeWithWallet(
@ -123,16 +123,16 @@ internal class VisaCardScanHandler @Inject constructor(
signedChallenge: VisaAuthSignedChallenge,
): CompletionResult<VisaCardActivationStatus> {
val authorizationTokensResponse = visaAuthRemoteDataSource.getAccessTokens(signedChallenge = signedChallenge)
.getOrElse {
.getOrElse { error ->
Timber.i("Failed to get Access token for Wallet public key authorization.")
return if (
it is VisaApiError.ProductInstanceIsNotActivated ||
it is VisaApiError.ProductInstanceNotFoundActivationRequired
error is VisaApiError.ProductInstanceIsNotActivated ||
error is VisaApiError.ProductInstanceNotFoundActivationRequired
) {
Timber.i("Proceeding with card authorization.")
handleCardAuthorization(cardWalletAddress = cardWalletAddress)
} else {
CompletionResult.Failure(it.tangemError)
CompletionResult.Failure(error.tangemError)
}
}
@ -152,9 +152,9 @@ internal class VisaCardScanHandler @Inject constructor(
val challengeResponse = visaAuthRemoteDataSource.getCardAuthChallenge(
cardId = card.cardId,
cardPublicKey = card.cardPublicKey.toHexString(),
).getOrElse {
Timber.e("Failed to get challenge for Card authorization. Plain error: ${it.errorCode}")
return CompletionResult.Failure(it.tangemError)
).getOrElse { error ->
Timber.e("Failed to get challenge for Card authorization. Plain error: ${error.errorCode}")
return CompletionResult.Failure(error.tangemError)
}
Timber.i("Received challenge to sign: ${challengeResponse.challenge}")
@ -179,9 +179,9 @@ internal class VisaCardScanHandler @Inject constructor(
signedChallenge = attestCardKeyResponse.cardSignature.toHexString(),
salt = attestCardKeyResponse.salt.toHexString(),
),
).getOrElse {
Timber.e("Failed to sign challenge with Card public key. Plain error: ${it.errorCode}")
return CompletionResult.Failure(it.tangemError)
).getOrElse { error ->
Timber.e("Failed to sign challenge with Card public key. Plain error: ${error.errorCode}")
return CompletionResult.Failure(error.tangemError)
}
visaAuthTokenStorage.store(
@ -189,9 +189,9 @@ internal class VisaCardScanHandler @Inject constructor(
tokens = authorizationTokensResponse,
)
val activationRemoteState = visaActivationRepository.getActivationRemoteState().getOrElse {
Timber.e("Failed to sign challenge with Card public key. Plain error: ${it.errorCode}")
return CompletionResult.Failure(it.tangemError)
val activationRemoteState = visaActivationRepository.getActivationRemoteState().getOrElse { error ->
Timber.e("Failed to sign challenge with Card public key. Plain error: ${error.errorCode}")
return CompletionResult.Failure(error.tangemError)
}
val error = when (activationRemoteState) {

View file

@ -6,6 +6,7 @@ import com.tangem.domain.models.scan.ScanResponse
import kotlinx.coroutines.CoroutineScope
import org.rekotlin.Action
@Suppress("BooleanPropertyNaming")
sealed class DetailsAction : Action {
data class PrepareScreen(
@ -32,7 +33,7 @@ sealed class DetailsAction : Action {
data object EnrollBiometrics : AppSettings()
data class BiometricsStatusChanged(
val needEnrollBiometrics: Boolean,
val isEnrollBiometricsNeeded: Boolean,
) : AppSettings()
data class ChangeAppThemeMode(
@ -40,7 +41,7 @@ sealed class DetailsAction : Action {
) : AppSettings()
data class ChangeBalanceHiding(
val hideBalance: Boolean,
val shouldHideBalance: Boolean,
) : AppSettings()
data class ChangeAppCurrency(

View file

@ -86,7 +86,7 @@ class DetailsMiddleware {
changeAppThemeMode(action.appThemeMode)
}
is DetailsAction.AppSettings.ChangeBalanceHiding -> {
changeBalanceHiding(action.hideBalance)
changeBalanceHiding(action.shouldHideBalance)
}
is DetailsAction.AppSettings.ChangeAppCurrency -> {
store.dispatch(GlobalAction.ChangeAppCurrency(action.currency))
@ -153,9 +153,9 @@ class DetailsMiddleware {
private suspend fun setBiometricLockForAllWallets() {
val userWalletsListRepository = store.inject(DaggerGraphState::userWalletsListRepository)
val userWallets = userWalletsListRepository.userWalletsSync()
userWallets.forEach {
userWallets.forEach { wallet ->
userWalletsListRepository.setLock(
userWalletId = it.walletId,
userWalletId = wallet.walletId,
lockMethod = LockMethod.Biometric,
changeUnsecured = false,
)
@ -174,11 +174,11 @@ class DetailsMiddleware {
deleteSavedAccessCodes()
val userWalletsListRepository = store.inject(DaggerGraphState::userWalletsListRepository)
val tangemHotSdk = store.inject(DaggerGraphState::tangemHotSdk)
userWalletsListRepository.userWalletsSync().forEach {
if (it is UserWallet.Hot) {
userWalletsListRepository.userWalletsSync().forEach { wallet ->
if (wallet is UserWallet.Hot) {
userWalletsListRepository.saveWithoutLock(
userWallet = it.copy(
hotWalletId = tangemHotSdk.removeBiometryAuthIfPresented(it.hotWalletId),
userWallet = wallet.copy(
hotWalletId = tangemHotSdk.removeBiometryAuthIfPresented(wallet.hotWalletId),
),
)
}
@ -188,10 +188,10 @@ class DetailsMiddleware {
private fun observeBiometricsStatusChanges(scope: CoroutineScope) {
val needEnrollBiometricsFlow = flow {
do {
val needEnrollBiometrics = runCatching(tangemSdkManager::needEnrollBiometrics).getOrNull()
val isEnrollBiometricsNeeded = runCatching(tangemSdkManager::needEnrollBiometrics).getOrNull()
if (needEnrollBiometrics != null) {
emit(needEnrollBiometrics)
if (isEnrollBiometricsNeeded != null) {
emit(isEnrollBiometricsNeeded)
}
delay(timeMillis = 200)

View file

@ -84,7 +84,7 @@ private fun handlePrivacyAction(action: DetailsAction.AppSettings, state: Detail
)
is DetailsAction.AppSettings.BiometricsStatusChanged -> state.copy(
appSettingsState = state.appSettingsState.copy(
needEnrollBiometrics = action.needEnrollBiometrics,
needEnrollBiometrics = action.isEnrollBiometricsNeeded,
),
)
is DetailsAction.AppSettings.ChangeAppThemeMode -> state.copy(
@ -99,7 +99,7 @@ private fun handlePrivacyAction(action: DetailsAction.AppSettings, state: Detail
)
is DetailsAction.AppSettings.ChangeBalanceHiding -> state.copy(
appSettingsState = state.appSettingsState.copy(
isHidingEnabled = action.hideBalance,
isHidingEnabled = action.shouldHideBalance,
),
)
// state should be copied to avoid concurrent modifications from different sources

View file

@ -11,6 +11,7 @@ data class DetailsState(
val appSettingsState: AppSettingsState = AppSettingsState(),
) : StateType
@Suppress("BooleanPropertyNaming")
data class AppSettingsState(
@Deprecated("Delete after hot wallet release")
val saveWallets: Boolean = false,

View file

@ -341,16 +341,16 @@ private class AppCurrencySelectorStateProvider : CollectionPreviewParameterProvi
.mapIndexed { index, s -> Currency(index.toString(), s) }
.toPersistentList()
AppCurrencySelectorState.Loading(onBackClick = {}).let(::add)
AppCurrencySelectorState.Default(
add(AppCurrencySelectorState.Loading(onBackClick = {}))
add(AppCurrencySelectorState.Default(
selectedId = "0",
items = items,
scrollToSelected = consumedEvent(),
onCurrencyClick = {},
onBackClick = {},
onTopBarActionClick = {},
).let(::add)
AppCurrencySelectorState.Search(
))
add(AppCurrencySelectorState.Search(
selectedId = "0",
items = items,
scrollToSelected = consumedEvent(),
@ -358,7 +358,7 @@ private class AppCurrencySelectorStateProvider : CollectionPreviewParameterProvi
onBackClick = {},
onSearchInputChange = {},
onTopBarActionClick = {},
).let(::add)
))
},
)
// endregion Preview

View file

@ -27,16 +27,16 @@ import kotlinx.collections.immutable.persistentListOf
@Composable
internal fun AppSettingsScreen(state: AppSettingsScreenState, onBackClick: () -> Unit, modifier: Modifier = Modifier) {
SettingsScreensScaffold(
onBackClick = onBackClick,
modifier = modifier,
titleRes = R.string.app_settings_title,
addBottomInsets = false,
content = {
when (state) {
is AppSettingsScreenState.Content -> AppSettings(state = state)
is AppSettingsScreenState.Loading -> Unit
}
},
titleRes = R.string.app_settings_title,
onBackClick = onBackClick,
addBottomInsets = false,
)
}
@ -103,10 +103,10 @@ private class AppSettingsScreenStateProvider : CollectionPreviewParameterProvide
itemsFactory.createSelectThemeModeButton(AppThemeMode.DEFAULT, {}),
)
AppSettingsScreenState.Content(
add(AppSettingsScreenState.Content(
items = items,
dialog = null,
).let(::add)
))
},
)
// endregion Preview

View file

@ -47,8 +47,8 @@ private class AlertDialogProvider : CollectionPreviewParameterProvider<Dialog.Al
collection = buildList {
val dialogsFactory = AppSettingsDialogsFactory()
dialogsFactory.createDeleteSavedAccessCodesAlert({}, {}).let(::add)
dialogsFactory.createDeleteSavedWalletsAlert({}, {}).let(::add)
add(dialogsFactory.createDeleteSavedAccessCodesAlert({}, {}))
add(dialogsFactory.createDeleteSavedWalletsAlert({}, {}))
},
)
// endregion Preview

View file

@ -64,10 +64,10 @@ private class ButtonItemProvider : CollectionPreviewParameterProvider<Item.Butto
collection = buildList {
val itemsFactory = AppSettingsItemsFactory()
itemsFactory.createSelectAppCurrencyButton(
add(itemsFactory.createSelectAppCurrencyButton(
currentAppCurrencyName = "US Dollar",
onClick = { /* no-op */ },
).let(::add)
))
},
)
// endregion Preview

View file

@ -71,9 +71,9 @@ private class CardItemProvider : CollectionPreviewParameterProvider<Item.Card>(
collection = buildList {
val itemsFactory = AppSettingsItemsFactory()
itemsFactory.createEnrollBiometricsCard(
add(itemsFactory.createEnrollBiometricsCard(
onClick = { /* no-op */ },
).let(::add)
))
},
)
// endregion Preview

View file

@ -85,26 +85,26 @@ private class SwitchItemProvider : CollectionPreviewParameterProvider<Item.Switc
collection = buildList {
val itemsFactory = AppSettingsItemsFactory()
itemsFactory.createSaveAccessCodeSwitch(
add(itemsFactory.createSaveAccessCodeSwitch(
isChecked = true,
isEnabled = true,
onCheckedChange = { /* no-op */ },
).let(::add)
itemsFactory.createSaveAccessCodeSwitch(
))
add(itemsFactory.createSaveAccessCodeSwitch(
isChecked = false,
isEnabled = true,
onCheckedChange = { /* no-op */ },
).let(::add)
itemsFactory.createSaveAccessCodeSwitch(
))
add(itemsFactory.createSaveAccessCodeSwitch(
isChecked = true,
isEnabled = false,
onCheckedChange = { /* no-op */ },
).let(::add)
itemsFactory.createSaveAccessCodeSwitch(
))
add(itemsFactory.createSaveAccessCodeSwitch(
isChecked = false,
isEnabled = false,
onCheckedChange = { /* no-op */ },
).let(::add)
))
},
)
// endregion Preview

View file

@ -99,60 +99,76 @@ internal class AppSettingsModel @Inject constructor(
}
private fun buildItems(state: AppSettingsState): ImmutableList<AppSettingsScreenState.Item> {
val items = buildList {
val items = buildList<AppSettingsScreenState.Item> {
if (state.needEnrollBiometrics) {
itemsFactory.createEnrollBiometricsCard(
onClick = ::enrollBiometrics,
).let(::add)
add(
itemsFactory.createEnrollBiometricsCard(
onClick = ::enrollBiometrics,
),
)
}
itemsFactory.createSelectAppCurrencyButton(
currentAppCurrencyName = state.selectedAppCurrency.name,
onClick = ::showAppCurrencySelector,
).let(::add)
add(
itemsFactory.createSelectAppCurrencyButton(
currentAppCurrencyName = state.selectedAppCurrency.name,
onClick = ::showAppCurrencySelector,
),
)
if (hotWalletFeatureToggles.isHotWalletEnabled) {
val canUseBiometrics = !state.needEnrollBiometrics && !state.isInProgress
itemsFactory.createUseBiometricsSwitch(
isChecked = state.useBiometricAuthentication,
isEnabled = canUseBiometrics,
onCheckedChange = ::onBiometricAuthenticationToggled,
).let(::add)
add(
itemsFactory.createUseBiometricsSwitch(
isChecked = state.useBiometricAuthentication,
isEnabled = canUseBiometrics,
onCheckedChange = ::onBiometricAuthenticationToggled,
),
)
itemsFactory.createRequireAccessCodeSwitch(
isChecked = state.requireAccessCode,
isEnabled = canUseBiometrics && state.useBiometricAuthentication,
onCheckedChange = ::onRequireAccessCodeToggled,
).let(::add)
add(
itemsFactory.createRequireAccessCodeSwitch(
isChecked = state.requireAccessCode,
isEnabled = canUseBiometrics && state.useBiometricAuthentication,
onCheckedChange = ::onRequireAccessCodeToggled,
),
)
} else {
if (state.isBiometricsAvailable) {
val canUseBiometrics = !state.needEnrollBiometrics && !state.isInProgress
itemsFactory.createSaveWalletsSwitch(
isChecked = state.saveWallets,
isEnabled = canUseBiometrics,
onCheckedChange = ::onSaveWalletsToggled,
).let(::add)
add(
itemsFactory.createSaveWalletsSwitch(
isChecked = state.saveWallets,
isEnabled = canUseBiometrics,
onCheckedChange = ::onSaveWalletsToggled,
),
)
itemsFactory.createSaveAccessCodeSwitch(
isChecked = state.saveAccessCodes,
isEnabled = canUseBiometrics,
onCheckedChange = ::onSaveAccessCodesToggled,
).let(::add)
add(
itemsFactory.createSaveAccessCodeSwitch(
isChecked = state.saveAccessCodes,
isEnabled = canUseBiometrics,
onCheckedChange = ::onSaveAccessCodesToggled,
),
)
}
}
itemsFactory.createFlipToHideBalanceSwitch(
isChecked = state.isHidingEnabled,
isEnabled = true,
onCheckedChange = ::onFlipToHideBalanceToggled,
).let(::add)
add(
itemsFactory.createFlipToHideBalanceSwitch(
isChecked = state.isHidingEnabled,
isEnabled = true,
onCheckedChange = ::onFlipToHideBalanceToggled,
),
)
itemsFactory.createSelectThemeModeButton(
currentThemeMode = state.selectedThemeMode,
onClick = { showThemeModeSelector(state.selectedThemeMode) },
).let(::add)
add(
itemsFactory.createSelectThemeModeButton(
currentThemeMode = state.selectedThemeMode,
onClick = { showThemeModeSelector(state.selectedThemeMode) },
),
)
}
return items.toImmutableList()
@ -280,7 +296,7 @@ internal class AppSettingsModel @Inject constructor(
val param = AnalyticsParam.OnOffState(enable)
analyticsEventHandler.send(Settings.AppSettings.HideBalanceChanged(param))
store.dispatch(DetailsAction.AppSettings.ChangeBalanceHiding(hideBalance = enable))
store.dispatch(DetailsAction.AppSettings.ChangeBalanceHiding(shouldHideBalance = enable))
}
private fun dismissDialog() {
@ -290,10 +306,10 @@ internal class AppSettingsModel @Inject constructor(
private fun bootstrapAppCurrencyUpdates() {
appCurrencyRepository
.getSelectedAppCurrency()
.onEach {
if (it.code == store.state.globalState.appCurrency.code) return@onEach
.onEach { appCurrency ->
if (appCurrency.code == store.state.globalState.appCurrency.code) return@onEach
store.dispatchWithMain(DetailsAction.AppSettings.ChangeAppCurrency(it))
store.dispatchWithMain(DetailsAction.AppSettings.ChangeAppCurrency(appCurrency))
}
.launchIn(scope)
.saveIn(appCurrencyUpdatesJobHolder)

View file

@ -26,19 +26,19 @@ import com.tangem.wallet.R
@Composable
internal fun CardSettingsScreen(state: CardSettingsScreenState, modifier: Modifier = Modifier) {
val needReadCard = state.cardDetails == null
val isCardReadingNeeded = state.cardDetails == null
SettingsScreensScaffold(
onBackClick = state.onBackClick,
modifier = modifier,
titleRes = R.string.card_settings_title,
content = {
if (needReadCard) {
if (isCardReadingNeeded) {
CardSettingsReadCard(state.onScanCardClick)
} else {
CardSettings(state = state)
}
},
titleRes = R.string.card_settings_title,
onBackClick = state.onBackClick,
)
}
@ -123,8 +123,8 @@ private fun CardSettings(state: CardSettingsScreenState) {
.fillMaxWidth()
.testTag(DeviceSettingsScreenTestTags.LAZY_LIST),
) {
items(state.cardDetails) {
val paddingBottom = when (it) {
items(state.cardDetails) { cardInfo ->
val paddingBottom = when (cardInfo) {
is CardInfo.CardId, is CardInfo.Issuer -> TangemTheme.dimens.spacing12
is CardInfo.SignedHashes -> TangemTheme.dimens.spacing14
is CardInfo.SecurityMode -> TangemTheme.dimens.spacing16
@ -132,7 +132,7 @@ private fun CardSettings(state: CardSettingsScreenState) {
is CardInfo.AccessCodeRecovery -> TangemTheme.dimens.spacing16
is CardInfo.ResetToFactorySettings -> TangemTheme.dimens.spacing28
}
val paddingTop = when (it) {
val paddingTop = when (cardInfo) {
is CardInfo.CardId -> TangemTheme.dimens.spacing0
is CardInfo.Issuer -> TangemTheme.dimens.spacing12
is CardInfo.SignedHashes -> TangemTheme.dimens.spacing12
@ -145,8 +145,8 @@ private fun CardSettings(state: CardSettingsScreenState) {
modifier = Modifier
.fillMaxWidth()
.clickable(
enabled = it.clickable,
onClick = { state.onElementClick(it) },
enabled = cardInfo.isClickable,
onClick = { state.onElementClick(cardInfo) },
)
.padding(
start = TangemTheme.dimens.spacing20,
@ -155,25 +155,25 @@ private fun CardSettings(state: CardSettingsScreenState) {
top = paddingTop,
),
) {
val titleColor = if (it.clickable) {
val titleColor = if (cardInfo.isClickable) {
TangemTheme.colors.text.primary1
} else {
TangemTheme.colors.text.tertiary
}
val subtitleColor = if (it.clickable) {
val subtitleColor = if (cardInfo.isClickable) {
TangemTheme.colors.text.secondary
} else {
TangemTheme.colors.text.tertiary
}
Text(
text = it.titleRes.resolveReference(),
text = cardInfo.titleRes.resolveReference(),
color = titleColor,
style = TangemTheme.typography.subtitle1,
modifier = Modifier.testTag(DeviceSettingsScreenTestTags.ITEM_TITLE),
)
Spacer(modifier = Modifier.size(TangemTheme.dimens.size4))
Text(
text = it.subtitle.resolveReference(),
text = cardInfo.subtitle.resolveReference(),
color = subtitleColor,
style = TangemTheme.typography.body2,
modifier = Modifier.testTag(DeviceSettingsScreenTestTags.ITEM_SUBTITLE),

View file

@ -18,7 +18,7 @@ internal data class CardSettingsScreenState(
internal sealed class CardInfo(
val titleRes: TextReference,
val subtitle: TextReference,
val clickable: Boolean = false,
val isClickable: Boolean = false,
) {
class CardId(subtitle: String) : CardInfo(
titleRes = TextReference.Res(R.string.details_row_title_cid),
@ -38,29 +38,29 @@ internal sealed class CardInfo(
class SecurityMode(securityOption: SecurityOption, clickable: Boolean) : CardInfo(
titleRes = TextReference.Res(R.string.card_settings_security_mode),
subtitle = TextReference.Res(securityOption.toTitleRes()),
clickable = clickable,
isClickable = clickable,
)
data object ChangeAccessCode : CardInfo(
titleRes = TextReference.Res(R.string.card_settings_change_access_code),
subtitle = TextReference.Res(R.string.card_settings_change_access_code_footer),
clickable = true,
isClickable = true,
)
class AccessCodeRecovery(val enabled: Boolean) : CardInfo(
class AccessCodeRecovery(val isEnabled: Boolean) : CardInfo(
titleRes = TextReference.Res(R.string.card_settings_access_code_recovery_title),
subtitle = if (enabled) {
subtitle = if (isEnabled) {
TextReference.Res(R.string.common_enabled)
} else {
TextReference.Res(R.string.common_disabled)
},
clickable = true,
isClickable = true,
)
class ResetToFactorySettings(description: TextReference) : CardInfo(
titleRes = TextReference.Res(R.string.card_settings_reset_card_to_factory),
subtitle = description,
clickable = true,
isClickable = true,
)
}

View file

@ -16,8 +16,8 @@ import com.tangem.wallet.R
@Composable
fun AccessCodeRecoveryScreen(state: AccessCodeRecoveryScreenState, onBackClick: () -> Unit) {
SettingsScreensScaffold(
content = { AccessCodeRecoveryOptions(state = state) },
onBackClick = onBackClick,
content = { AccessCodeRecoveryOptions(state = state) },
)
}
@ -38,13 +38,13 @@ fun AccessCodeRecoveryOptions(state: AccessCodeRecoveryScreenState) {
DetailsRadioButtonElement(
title = stringResourceSafe(id = R.string.common_enabled),
subtitle = stringResourceSafe(id = R.string.card_settings_access_code_recovery_enabled_description),
selected = state.enabledSelection,
isSelected = state.isEnabledSelection,
onClick = { state.onOptionClick(true) },
)
DetailsRadioButtonElement(
title = stringResourceSafe(id = R.string.common_disabled),
subtitle = stringResourceSafe(id = R.string.card_settings_access_code_recovery_disabled_description),
selected = !state.enabledSelection,
isSelected = !state.isEnabledSelection,
onClick = { state.onOptionClick(false) },
)

View file

@ -1,15 +1,15 @@
package com.tangem.tap.features.details.ui.cardsettings.coderecovery
/**
* @property enabledOnCard Indicates whether access code recovery is enabled on the card
* @property enabledSelection Represents the currently selected option in the app (not yet saved on the card)
* @property isEnabledOnCard Indicates whether access code recovery is enabled on the card
* @property isEnabledSelection Represents the currently selected option in the app (not yet saved on the card)
* @property isSaveChangesEnabled Determines if the user is allowed to save their selection to the card
* @property onSaveChangesClick Callback function called when the user wants to apply the selected option
* @property onOptionClick Callback function called when the user selects an option
* */
data class AccessCodeRecoveryScreenState(
val enabledOnCard: Boolean,
val enabledSelection: Boolean,
val isEnabledOnCard: Boolean,
val isEnabledSelection: Boolean,
val isSaveChangesEnabled: Boolean,
val onSaveChangesClick: () -> Unit,
val onOptionClick: (Boolean) -> Unit,

View file

@ -43,8 +43,8 @@ internal class AccessCodeRecoveryModel @Inject constructor(
)
return AccessCodeRecoveryScreenState(
enabledOnCard = isEnabled,
enabledSelection = isEnabled,
isEnabledOnCard = isEnabled,
isEnabledSelection = isEnabled,
isSaveChangesEnabled = false,
onSaveChangesClick = ::saveChanges,
onOptionClick = ::selectOption,
@ -52,7 +52,7 @@ internal class AccessCodeRecoveryModel @Inject constructor(
}
private fun saveChanges() = modelScope.launch {
val isEnabled = screenState.value.enabledSelection
val isEnabled = screenState.value.isEnabledSelection
tangemSdkManager
.setAccessCodeRecoveryEnabled(scannedScanResponse.card.cardId, isEnabled)
@ -78,10 +78,10 @@ internal class AccessCodeRecoveryModel @Inject constructor(
}
private fun selectOption(isEnabled: Boolean) {
screenState.update {
it.copy(
enabledSelection = isEnabled,
isSaveChangesEnabled = isEnabled != it.enabledOnCard,
screenState.update { state ->
state.copy(
isEnabledSelection = isEnabled,
isSaveChangesEnabled = isEnabled != state.isEnabledOnCard,
)
}
}

View file

@ -23,9 +23,9 @@ internal class CardSettingsInteractor @Inject constructor() {
}
fun update(transform: (ScanResponse) -> ScanResponse) {
_scannedScanResponse.update {
requireNotNull(it)
transform(it)
_scannedScanResponse.update { scanResponse ->
requireNotNull(scanResponse)
transform(scanResponse)
}
}

View file

@ -57,7 +57,7 @@ internal class CardSettingsModel @Inject constructor(
private val params = paramsContainer.require<CardSettingsComponent.Params>()
private var previousBiometricsRequestPolicy: Boolean = false
private var isBiometricsRequestPolicyPrevious: Boolean = false
private val userWalletId = params.userWalletId
@ -77,13 +77,13 @@ internal class CardSettingsModel @Inject constructor(
// Reset card scanned data
cardSettingsInteractor.clear()
// Restore the previous value of access code request policy
cardSdkConfigRepository.isBiometricsRequestPolicy = previousBiometricsRequestPolicy
cardSdkConfigRepository.isBiometricsRequestPolicy = isBiometricsRequestPolicyPrevious
}
private fun updateAccessCodeRequestPolicy() {
runBlocking {
// !!!IMPORTANT!!!: Do not forget to restore the previous value in onCleared() method
previousBiometricsRequestPolicy = cardSdkConfigRepository.isBiometricsRequestPolicy
isBiometricsRequestPolicyPrevious = cardSdkConfigRepository.isBiometricsRequestPolicy
val userWallet = getUserWalletUseCase(userWalletId)
.getOrElse { error("User wallet $userWalletId not found") }
@ -135,34 +135,38 @@ internal class CardSettingsModel @Inject constructor(
)
val isResetCardAllowed = isResetToFactoryAllowedByCard(card, cardTypesResolver)
val cardDetails = buildList {
CardInfo.CardId(cardId).let(::add)
CardInfo.Issuer(card.issuer.name).let(::add)
val cardDetails = buildList<CardInfo> {
add(CardInfo.CardId(cardId))
add(CardInfo.Issuer(card.issuer.name))
if (!cardTypesResolver.isTangemTwins()) {
CardInfo.SignedHashes(card.signedHashesCount().toString()).let(::add)
add(CardInfo.SignedHashes(card.signedHashesCount().toString()))
}
CardInfo.SecurityMode(
currentSecurityOption,
clickable = allowedSecurityOptions.size > 1,
).let(::add)
add(
CardInfo.SecurityMode(
currentSecurityOption,
clickable = allowedSecurityOptions.size > 1,
),
)
if (card.backupStatus?.isActive == true && card.isAccessCodeSet) {
CardInfo.ChangeAccessCode.let(::add)
add(CardInfo.ChangeAccessCode)
}
if (isAccessCodeRecoveryAllowed(cardTypesResolver)) {
CardInfo.AccessCodeRecovery(isAccessCodeRecoveryEnabled(cardTypesResolver, card)).let(::add)
add(CardInfo.AccessCodeRecovery(isAccessCodeRecoveryEnabled(cardTypesResolver, card)))
}
if (isResetCardAllowed) {
CardInfo.ResetToFactorySettings(
description = getResetToFactoryDescription(
isActiveBackupStatus = card.backupStatus?.isActive == true,
typesResolver = cardTypesResolver,
add(
CardInfo.ResetToFactorySettings(
description = getResetToFactoryDescription(
isActiveBackupStatus = card.backupStatus?.isActive == true,
typesResolver = cardTypesResolver,
),
),
).let(::add)
)
}
}

View file

@ -19,11 +19,11 @@ import com.tangem.wallet.R
@Composable
internal fun SettingsScreensScaffold(
onBackClick: () -> Unit,
content: @Composable () -> Unit,
modifier: Modifier = Modifier,
@StringRes titleRes: Int? = null,
snackbarHostState: SnackbarHostState = remember { SnackbarHostState() },
addBottomInsets: Boolean = true,
snackbarHostState: SnackbarHostState = remember { SnackbarHostState() },
content: @Composable () -> Unit,
fab: @Composable () -> Unit = {},
) {
val backgroundColor = TangemTheme.colors.background.secondary
@ -129,18 +129,18 @@ internal fun DetailsMainButton(
}
@Composable
internal fun DetailsRadioButtonElement(title: String, subtitle: String, selected: Boolean, onClick: () -> Unit) {
internal fun DetailsRadioButtonElement(title: String, subtitle: String, isSelected: Boolean, onClick: () -> Unit) {
Row(
modifier = Modifier
.fillMaxWidth()
.selectable(
selected = selected,
selected = isSelected,
onClick = { onClick() },
)
.padding(start = 20.dp, end = 20.dp, top = 16.dp, bottom = 16.dp),
) {
RadioButton(
selected = selected,
selected = isSelected,
onClick = null,
modifier = Modifier.padding(end = 20.dp),
colors = RadioButtonDefaults.colors(

View file

@ -7,7 +7,7 @@ internal fun isAccessCodeRecoveryAllowed(typeResolver: CardTypesResolver): Boole
internal fun isAccessCodeRecoveryEnabled(typeResolver: CardTypesResolver, card: CardDTO): Boolean =
if (typeResolver.isWallet2()) {
card.userSettings?.isUserCodeRecoveryAllowed ?: false
card.userSettings?.isUserCodeRecoveryAllowed == true
} else {
false
}

View file

@ -27,11 +27,11 @@ import com.tangem.tap.features.details.ui.resetcard.ResetCardScreenState.Dialog
@Composable
internal fun ResetCardScreen(state: ResetCardScreenState, onBackClick: () -> Unit, modifier: Modifier = Modifier) {
SettingsScreensScaffold(
onBackClick = onBackClick,
modifier = modifier,
content = {
ResetCardView(state = state)
},
onBackClick = onBackClick,
)
when (val dialog = state.dialog) {
@ -65,7 +65,7 @@ private fun ResetCardView(state: ResetCardScreenState) {
Conditions(state)
DynamicSpacer(scrollState = scrollState)
SpacerH16()
ResetButton(enabled = state.resetButtonEnabled, onResetButtonClick = state.onResetButtonClick)
ResetButton(enabled = state.isResetButtonEnabled, onResetButtonClick = state.onResetButtonClick)
SpacerH16()
}
}
@ -113,18 +113,18 @@ private fun Description(text: TextReference) {
@Composable
private fun Conditions(state: ResetCardScreenState) {
state.warningsToShow.forEach {
when (it) {
state.warningsToShow.forEach { warning ->
when (warning) {
ResetCardScreenState.WarningsToReset.LOST_WALLET_ACCESS -> {
ConditionCheckBox(
checkedState = state.acceptCondition1Checked,
checkedState = state.isAcceptCondition1Checked,
onCheckedChange = state.onAcceptCondition1ToggleClick,
description = TextReference.Res(R.string.reset_card_to_factory_condition_1),
)
}
ResetCardScreenState.WarningsToReset.LOST_PASSWORD_RESTORE -> {
ConditionCheckBox(
checkedState = state.acceptCondition2Checked,
checkedState = state.isAcceptCondition2Checked,
onCheckedChange = state.onAcceptCondition2ToggleClick,
description = TextReference.Res(R.string.reset_card_to_factory_condition_2),
)
@ -238,12 +238,12 @@ private fun ResetCardScreenSample(modifier: Modifier = Modifier) {
) {
ResetCardScreen(
state = ResetCardScreenState(
resetButtonEnabled = true,
showResetPasswordButton = false,
isResetButtonEnabled = true,
isResetPasswordButtonShown = false,
warningsToShow = listOf(ResetCardScreenState.WarningsToReset.LOST_WALLET_ACCESS),
descriptionText = TextReference.Res(R.string.reset_card_with_backup_to_factory_message),
acceptCondition1Checked = false,
acceptCondition2Checked = false,
isAcceptCondition1Checked = false,
isAcceptCondition2Checked = false,
onAcceptCondition1ToggleClick = {},
onAcceptCondition2ToggleClick = {},
onResetButtonClick = {},

View file

@ -5,12 +5,12 @@ import com.tangem.tap.features.details.ui.cardsettings.TextReference
import com.tangem.wallet.R
internal data class ResetCardScreenState(
val resetButtonEnabled: Boolean,
val isResetButtonEnabled: Boolean,
val descriptionText: TextReference,
val warningsToShow: List<WarningsToReset>,
val showResetPasswordButton: Boolean,
val acceptCondition1Checked: Boolean,
val acceptCondition2Checked: Boolean,
val isResetPasswordButtonShown: Boolean,
val isAcceptCondition1Checked: Boolean,
val isAcceptCondition2Checked: Boolean,
val onAcceptCondition1ToggleClick: (Boolean) -> Unit,
val onAcceptCondition2ToggleClick: (Boolean) -> Unit,
val onResetButtonClick: () -> Unit,

View file

@ -97,15 +97,15 @@ internal class ResetCardModel @Inject constructor(
}
return ResetCardScreenState(
resetButtonEnabled = false,
isResetButtonEnabled = false,
descriptionText = getResetToFactoryDescription(
isActiveBackupStatus = isActiveBackupPrimaryCard,
typesResolver = currentCardTypesResolver,
),
warningsToShow = warningsToShow,
showResetPasswordButton = shouldShowResetPasswordButton,
acceptCondition1Checked = false,
acceptCondition2Checked = false,
isResetPasswordButtonShown = shouldShowResetPasswordButton,
isAcceptCondition1Checked = false,
isAcceptCondition2Checked = false,
onAcceptCondition1ToggleClick = ::toggleFirstCondition,
onAcceptCondition2ToggleClick = ::toggleSecondCondition,
onResetButtonClick = { showDialog(ResetCardDialog.StartResetDialog) },
@ -121,26 +121,26 @@ internal class ResetCardModel @Inject constructor(
private fun toggleFirstCondition(isAccepted: Boolean) {
screenState.update { prevState ->
val resetButtonEnabled = if (prevState.showResetPasswordButton) {
isAccepted && prevState.acceptCondition2Checked
val isResetButtonEnabled = if (prevState.isResetPasswordButtonShown) {
isAccepted && prevState.isAcceptCondition2Checked
} else {
isAccepted
}
prevState.copy(
acceptCondition1Checked = isAccepted,
resetButtonEnabled = resetButtonEnabled,
isAcceptCondition1Checked = isAccepted,
isResetButtonEnabled = isResetButtonEnabled,
)
}
}
private fun toggleSecondCondition(isAccepted: Boolean) {
screenState.update { prevState ->
val resetButtonEnabled = prevState.acceptCondition1Checked && isAccepted
val isResetButtonEnabled = prevState.isAcceptCondition1Checked && isAccepted
prevState.copy(
acceptCondition2Checked = isAccepted,
resetButtonEnabled = resetButtonEnabled,
isAcceptCondition2Checked = isAccepted,
isResetButtonEnabled = isResetButtonEnabled,
)
}
}
@ -183,14 +183,14 @@ internal class ResetCardModel @Inject constructor(
modelScope.launch {
resetCardUseCase(cardId = primaryCardId, params = currentUserCodeParams).onRight {
deleteSavedAccessCodesUseCase(cardId = primaryCardId)
val hasUserWallets = deleteWalletUseCase(userWalletId = currentUserWalletId).getOrElse {
Timber.e("Unable to delete user wallet: $it")
val hasUserWallets = deleteWalletUseCase(userWalletId = currentUserWalletId).getOrElse { error ->
Timber.e("Unable to delete user wallet: $error")
return@launch
}
if (hasUserWallets) {
val newSelectedWallet = getSelectedWalletSyncUseCase().getOrElse {
error("Failed to get selected wallet: $it")
val newSelectedWallet = getSelectedWalletSyncUseCase().getOrElse { error ->
error("Failed to get selected wallet: $error")
}
store.onUserWalletSelected(newSelectedWallet)
@ -269,7 +269,7 @@ internal class ResetCardModel @Inject constructor(
if (hotWalletFeatureToggles.isHotWalletEnabled) {
store.dispatchNavigationAction { replaceAll(AppRoute.Home()) }
} else {
val isLocked = runCatching { userWalletsListManager.asLockable()?.isLockedSync }.isSuccess
val isLocked = runCatching { userWalletsListManager.asLockable()?.isLocked }.isSuccess
if (isLocked && userWalletsListManager.hasUserWallets) {
store.dispatchNavigationAction { popTo<AppRoute.Welcome>() }
} else {

View file

@ -22,10 +22,10 @@ internal fun SecurityModeScreen(
modifier: Modifier = Modifier,
) {
SettingsScreensScaffold(
onBackClick = onBackClick,
modifier = modifier,
content = { SecurityModeOptions(state = state) },
// titleRes = R.string.card_settings_security_mode,
onBackClick = onBackClick,
)
}
@ -57,7 +57,7 @@ private fun SecurityModeOptions(state: SecurityModeScreenState) {
@Composable
private fun SecurityOption(option: SecurityOption, state: SecurityModeScreenState) {
val selected = option == state.selectedSecurityMode
val isSelected = option == state.selectedSecurityMode
val title = option.toTitleRes()
@ -70,7 +70,7 @@ private fun SecurityOption(option: SecurityOption, state: SecurityModeScreenStat
DetailsRadioButtonElement(
title = stringResourceSafe(id = title),
subtitle = stringResourceSafe(id = subtitle),
selected = selected,
isSelected = isSelected,
onClick = { state.onNewModeSelected(option) },
)
}

View file

@ -77,9 +77,9 @@ internal class SecurityModeModel @Inject constructor(
SecurityOption.AccessCode -> tangemSdkManager.setAccessCode(cardId)
}
cardSettingsInteractor.update {
it.copy(
card = it.card.copy(
cardSettingsInteractor.update { scanResponse ->
scanResponse.copy(
card = scanResponse.card.copy(
isAccessCodeSet = selectedOption == SecurityOption.AccessCode,
isPasscodeSet = selectedOption == SecurityOption.PassCode,
),

View file

@ -150,7 +150,7 @@ internal class MainViewModel @Inject constructor(
prepareSelectedWalletFeedback()
// await while initial route stack is initialized
appRouterConfig.isInitialized.first { it }
appRouterConfig.initializedState.first { it }
isSplashScreenShown = false
}
@ -179,11 +179,9 @@ internal class MainViewModel @Inject constructor(
private fun prepareSelectedWalletFeedback() {
getSelectedWalletUseCase.invoke()
.mapLeft { emptyFlow<UserWallet>() }
.onRight {
it.distinctUntilChanged()
.onEach { userWallet ->
Analytics.setContext(userWallet)
}
.onRight { wallet ->
wallet.distinctUntilChanged()
.onEach { Analytics.setContext(it) }
.flowOn(dispatchers.io)
.launchIn(viewModelScope)
}
@ -208,7 +206,7 @@ internal class MainViewModel @Inject constructor(
return MoonPayService(
apiKey = environmentConfig.moonPayApiKey,
secretKey = environmentConfig.moonPayApiSecretKey,
logEnabled = LogConfig.network.moonPayService,
isLogEnabled = LogConfig.network.moonPayService,
userWalletProvider = { getSelectedWalletUseCase.sync().getOrNull() },
)
}
@ -224,8 +222,8 @@ internal class MainViewModel @Inject constructor(
.filter {
it.isBalanceHidingNotificationEnabled && it.isBalanceHidden
}
.onEach {
if (!it.isUpdateFromToast) {
.onEach { settings ->
if (!settings.isUpdateFromToast) {
listenToFlipsUseCase.changeUpdateEnabled(false)
val message = BottomSheetMessage.invoke(
@ -354,6 +352,7 @@ internal class MainViewModel @Inject constructor(
listenToFlipsUseCase.changeUpdateEnabled(isUpdateEnabled = true)
}
@Suppress("NullableToStringCall")
private fun sendKeyboardIdentifierEvent() {
viewModelScope.launch {
val keyboardId = keyboardValidator.getKeyboardId()

View file

@ -34,11 +34,11 @@ object OnboardingHelper {
}
response.cardTypesResolver.isWallet2() || response.cardTypesResolver.isShibaWallet() -> {
val emptyWallets = response.card.wallets.isEmpty()
val activationInProgress = cardRepository.isActivationInProgress(cardId)
val areWalletsEmpty = response.card.wallets.isEmpty()
val isActivationInProgress = cardRepository.isActivationInProgress(cardId)
val isNoBackup = response.card.backupStatus == CardDTO.BackupStatus.NoBackup &&
!DemoHelper.isDemoCard(response)
emptyWallets || activationInProgress || isNoBackup
areWalletsEmpty || isActivationInProgress || isNoBackup
}
response.card.wallets.isNotEmpty() -> cardRepository.isActivationInProgress(cardId)

View file

@ -50,8 +50,8 @@ object TradeCryptoMiddleware {
fiatCurrencyName = action.appCurrencyCode,
walletAddress = networkAddress,
isDarkTheme = MutableAppThemeModeHolder.isDarkThemeActive,
)?.let {
store.dispatchOpenUrl(it)
)?.let { url ->
store.dispatchOpenUrl(url)
Analytics.send(Token.Withdraw.ScreenOpened())
}
}

View file

@ -72,8 +72,8 @@ internal class WelcomeModel @Inject constructor(
this.state.update { prevState ->
prevState.copy(
showUnlockWithBiometricsProgress = state.isUnlockWithBiometricsInProgress,
showUnlockWithCardProgress = state.isUnlockWithCardInProgress,
isUnlockWithBiometricsProgressVisible = state.isUnlockWithBiometricsInProgress,
isUnlockWithCardProgressVisible = state.isUnlockWithCardInProgress,
warning = warning,
error = state.error
?.takeIf { !it.silent && warning == null }

View file

@ -13,7 +13,7 @@ internal sealed interface WelcomeAction : Action {
object ProceedWithCard : WelcomeAction {
object Success : WelcomeAction
data class Error(val error: TangemError) : WelcomeAction
data class ChangeProgress(val showProgress: Boolean) : WelcomeAction
data class ChangeProgress(val isProgress: Boolean) : WelcomeAction
}
object CloseError : WelcomeAction

View file

@ -141,13 +141,13 @@ internal class WelcomeMiddleware {
onSuccess = { scanResponse ->
scope.launch { onCardScanned(scanResponse) }
},
onFailure = {
when (it) {
onFailure = { error ->
when (error) {
is TangemSdkError.ExceptionError -> {
store.dispatchOnMain(WelcomeAction.ProceedWithCard.Success)
}
else -> {
store.dispatchOnMain(WelcomeAction.ProceedWithCard.Error(it))
store.dispatchOnMain(WelcomeAction.ProceedWithCard.Error(error))
}
}
},

View file

@ -25,7 +25,7 @@ internal object WelcomeReducer {
isUnlockWithCardInProgress = false,
)
is WelcomeAction.ProceedWithCard.ChangeProgress -> state.copy(
isUnlockWithCardInProgress = action.showProgress,
isUnlockWithCardInProgress = action.isProgress,
)
is WelcomeAction.ProceedWithBiometrics.Success -> state.copy(isUnlockWithBiometricsInProgress = false)
is WelcomeAction.ProceedWithCard.Success -> state.copy(isUnlockWithCardInProgress = false)

View file

@ -5,8 +5,8 @@ import com.tangem.tap.features.welcome.ui.model.WarningModel
internal data class WelcomeScreenState(
val onPopBack: () -> Unit = {},
val showUnlockWithBiometricsProgress: Boolean = false,
val showUnlockWithCardProgress: Boolean = false,
val isUnlockWithBiometricsProgressVisible: Boolean = false,
val isUnlockWithCardProgressVisible: Boolean = false,
val warning: WarningModel? = null,
val error: TextReference? = null,
val onUnlockClick: () -> Unit = {},

View file

@ -39,8 +39,8 @@ internal fun WelcomeScreen(state: WelcomeScreenState, modifier: Modifier = Modif
.systemBarsPadding(),
) {
WelcomeScreenContent(
showUnlockProgress = state.showUnlockWithBiometricsProgress,
showScanCardProgress = state.showUnlockWithCardProgress,
showUnlockProgress = state.isUnlockWithBiometricsProgressVisible,
showScanCardProgress = state.isUnlockWithCardProgressVisible,
onUnlockClick = state.onUnlockClick,
onScanCardClick = state.onScanCardClick,
)
@ -57,8 +57,8 @@ internal fun WelcomeScreen(state: WelcomeScreenState, modifier: Modifier = Modif
WarningDialog(warning)
LaunchedEffect(errorMessage, state.onCloseError) {
errorMessage?.let {
snackbarHostState.showSnackbar(it)
errorMessage?.let { message ->
snackbarHostState.showSnackbar(message)
state.onCloseError()
}
}
@ -82,8 +82,8 @@ private class WelcomeComponentPreviewProvider : PreviewParameterProvider<Welcome
PreviewWelcomeComponent(),
PreviewWelcomeComponent(
initialState = WelcomeScreenState(
showUnlockWithBiometricsProgress = true,
showUnlockWithCardProgress = true,
isUnlockWithBiometricsProgressVisible = true,
isUnlockWithCardProgressVisible = true,
),
),
PreviewWelcomeComponent(

View file

@ -9,7 +9,7 @@ import com.tangem.domain.core.wallets.UserWalletsListRepository
internal class DefaultAuthProvider(
private val userWalletsListManager: UserWalletsListManager,
private val userWalletsListRepository: UserWalletsListRepository,
private val useNewListRepository: Boolean = false,
private val shouldUseNewListRepository: Boolean = false,
) : AuthProvider {
override suspend fun getCardPublicKey(): String {
@ -39,7 +39,7 @@ internal class DefaultAuthProvider(
}
private suspend fun getWallets(): List<UserWallet> {
return if (useNewListRepository) {
return if (shouldUseNewListRepository) {
userWalletsListRepository.userWalletsSync()
} else {
userWalletsListManager.userWalletsSync
@ -47,7 +47,7 @@ internal class DefaultAuthProvider(
}
private suspend fun getSelectedWallet(): UserWallet? {
return if (useNewListRepository) {
return if (shouldUseNewListRepository) {
userWalletsListRepository.selectedUserWalletSync()
} else {
userWalletsListManager.selectedUserWalletSync

View file

@ -6,7 +6,7 @@ import java.util.concurrent.atomic.AtomicReference
internal class DefaultExpressAuthProvider : ExpressAuthProvider {
private var uuid = AtomicReference(UUID.randomUUID())
private val uuid = AtomicReference(UUID.randomUUID())
override fun getSessionId(): String {
return uuid.get().toString()

View file

@ -32,7 +32,7 @@ internal class AuthModule {
return DefaultAuthProvider(
userWalletsListManager = userWalletsListManager,
userWalletsListRepository = userWalletsListRepository,
useNewListRepository = hotWalletFeatureToggles.isHotWalletEnabled,
shouldUseNewListRepository = hotWalletFeatureToggles.isHotWalletEnabled,
)
}

View file

@ -54,7 +54,7 @@ internal class DefaultRampManager(
sendUnavailabilityReason: ScenarioUnavailabilityReason?,
): Either<ScenarioUnavailabilityReason, Unit> {
return either {
val sellSupportedByService = catch(
val isSellSupportedByService = catch(
block = {
val serviceCurrency = cryptoCurrencyConverter.convertBack(status.currency)
@ -78,7 +78,7 @@ internal class DefaultRampManager(
}
}
ensure(condition = sellSupportedByService) {
ensure(condition = isSellSupportedByService) {
ScenarioUnavailabilityReason.NotSupportedBySellService(status.currency.name)
}

View file

@ -34,6 +34,7 @@ data class MoonPayUserStatus(
val stateCode: String,
)
@Suppress("BooleanPropertyNaming")
@JsonClass(generateAdapter = true)
data class MoonPayCurrencies(
@Json(name = "type") val type: String,

View file

@ -26,7 +26,7 @@ import javax.crypto.spec.SecretKeySpec
class MoonPayService(
private val apiKey: String,
private val secretKey: String,
private val logEnabled: Boolean,
private val isLogEnabled: Boolean,
private val userWalletProvider: () -> UserWallet?,
) : ExchangeService {
@ -39,7 +39,7 @@ class MoonPayService(
private val api: MoonPayApi by lazy {
createRetrofitInstance(
baseUrl = MoonPayApi.MOOONPAY_BASE_URL,
logEnabled = logEnabled,
logEnabled = isLogEnabled,
).create(MoonPayApi::class.java)
}
@ -104,24 +104,35 @@ class MoonPayService(
override fun availableForSell(currency: Currency): Boolean {
val userWallet = userWalletProvider() ?: return false
val checkCardExchange = userWallet !is UserWallet.Cold || !userWallet.scanResponse.card.isStart2Coin
val isExchangeSupported = userWallet !is UserWallet.Cold || !userWallet.scanResponse.card.isStart2Coin
if (!checkCardExchange) return false
if (!isExchangeSupported) return false
if (!isSellAllowed()) return false
val availableForSell = status?.availableForSell ?: return false
val supportedCurrency = currency.blockchain.moonPaySupportedCurrency ?: return false
return availableForSell.any {
return availableForSell.any { availableCurrency ->
when (currency) {
is Currency.Blockchain -> {
it.networkCode.equals(other = supportedCurrency.networkCode, ignoreCase = true) &&
it.currencyCode.equals(other = supportedCurrency.currencyCode, ignoreCase = true)
availableCurrency.networkCode.equals(
other = supportedCurrency.networkCode,
ignoreCase = true,
) && availableCurrency.currencyCode.equals(
other = supportedCurrency.currencyCode,
ignoreCase = true,
)
}
is Currency.Token -> {
it.networkCode.equals(other = supportedCurrency.networkCode, ignoreCase = true) &&
it.contractAddress.equals(other = currency.token.contractAddress, ignoreCase = true)
availableCurrency.networkCode.equals(
other = supportedCurrency.networkCode,
ignoreCase = true,
) &&
availableCurrency.contractAddress.equals(
other = currency.token.contractAddress,
ignoreCase = true,
)
}
}
}
@ -137,15 +148,18 @@ class MoonPayService(
if (blockchain.isTestnet()) return blockchain.getTestnetTopUpUrl()
val supportedCurrency = blockchain.moonPaySupportedCurrency ?: return null
val moonpayCurrency = status?.availableForSell?.firstOrNull {
val moonpayCurrency = status?.availableForSell?.firstOrNull { availableCurrency ->
when (cryptoCurrency) {
is CryptoCurrency.Coin -> {
it.networkCode.equals(other = supportedCurrency.networkCode, ignoreCase = true) &&
it.currencyCode.equals(other = supportedCurrency.currencyCode, ignoreCase = true)
availableCurrency.networkCode.equals(other = supportedCurrency.networkCode, ignoreCase = true) &&
availableCurrency.currencyCode.equals(other = supportedCurrency.currencyCode, ignoreCase = true)
}
is CryptoCurrency.Token -> {
it.networkCode.equals(other = supportedCurrency.networkCode, ignoreCase = true) &&
it.contractAddress.equals(other = cryptoCurrency.contractAddress, ignoreCase = true)
availableCurrency.networkCode.equals(other = supportedCurrency.networkCode, ignoreCase = true) &&
availableCurrency.contractAddress.equals(
other = cryptoCurrency.contractAddress,
ignoreCase = true,
)
}
}
} ?: return null
@ -184,7 +198,7 @@ class MoonPayService(
}
private fun isSellAllowed(): Boolean {
return status?.responseUserStatus?.isSellAllowed ?: false
return status?.responseUserStatus?.isSellAllowed == true
}
private companion object {

View file

@ -48,13 +48,13 @@ class UserWalletManagerImpl(
override suspend fun getNativeTokenBalance(networkId: String, derivationPath: String?): ProxyAmount? {
val blockchain = requireNotNull(Blockchain.fromNetworkId(networkId)) { "blockchain not found" }
val walletManager = getActualWalletManager(blockchain, derivationPath)
return walletManager.wallet.amounts.firstNotNullOfOrNull {
it.takeIf { it.key is AmountType.Coin }
}?.value?.let {
return walletManager.wallet.amounts.firstNotNullOfOrNull { amountEntry ->
amountEntry.takeIf { amountEntry.key is AmountType.Coin }
}?.value?.let { amount ->
ProxyAmount(
it.currencySymbol,
it.value ?: BigDecimal.ZERO,
it.decimals,
amount.currencySymbol,
amount.value ?: BigDecimal.ZERO,
amount.decimals,
)
}
}

View file

@ -34,17 +34,17 @@ import com.tangem.core.ui.res.TangemTheme
import com.tangem.tap.routing.component.RoutingComponent
import com.tangem.tap.routing.transitions.RoutingTransitionAnimationFactory
@Suppress("LongParameterList")
@Suppress("LongParameterList", "ReusedModifierInstance")
@OptIn(ExperimentalDecomposeApi::class)
@Composable
internal fun RootContent(
stack: Value<ChildStack<AppRoute, RoutingComponent.Child>>,
backHandler: BackHandler,
uiDependencies: UiDependencies,
wcContent: @Composable (modifier: Modifier) -> Unit,
hotAccessCodeContent: @Composable (modifier: Modifier) -> Unit,
onBack: () -> Unit,
modifier: Modifier = Modifier,
wcContent: @Composable (modifier: Modifier) -> Unit,
hotAccessCodeContent: @Composable (modifier: Modifier) -> Unit,
) {
val context = LocalContext.current

View file

@ -133,7 +133,7 @@ internal class DefaultRoutingComponent @AssistedInject constructor(
AppRoute.Wallet
}
}.also {
appRouterConfig.isInitialized.value = true
appRouterConfig.initializedState.value = true
checkForUnfinishedBackup()
}
}
@ -141,13 +141,13 @@ internal class DefaultRoutingComponent @AssistedInject constructor(
@Composable
override fun Content(modifier: Modifier) {
RootContent(
modifier = modifier,
stack = stack,
backHandler = backHandler,
uiDependencies = uiDependencies,
onBack = router::pop,
modifier = modifier,
wcContent = { wcRoutingComponent.Content(it) },
hotAccessCodeContent = { hotAccessCodeRequestComponent.Content(it) },
backHandler = backHandler,
onBack = router::pop,
)
}

View file

@ -11,7 +11,7 @@ internal interface AppRouterConfig {
var routerScope: CoroutineScope?
var componentRouter: Router?
var stack: List<AppRoute>?
val isInitialized: MutableStateFlow<Boolean>
val initializedState: MutableStateFlow<Boolean>
// TODO: Replace with UI message handler: [REDACTED_JIRA]
var snackbarHandler: SnackbarHandler?

View file

@ -11,5 +11,5 @@ internal class MutableAppRouterConfig : AppRouterConfig {
override var componentRouter: Router? = null
override var stack: List<AppRoute>? = null
override var snackbarHandler: SnackbarHandler? = null
override val isInitialized: MutableStateFlow<Boolean> = MutableStateFlow(false)
override val initializedState: MutableStateFlow<Boolean> = MutableStateFlow(false)
}

View file

@ -4,13 +4,10 @@ import androidx.compose.animation.core.CubicBezierEasing
import androidx.compose.animation.core.FiniteAnimationSpec
import androidx.compose.animation.core.tween
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.layout
import com.arkivanov.decompose.extensions.compose.stack.animation.*
import com.tangem.common.routing.AppRoute
import kotlin.compareTo
import kotlin.times
object RoutingTransitionAnimationFactory {
@ -58,7 +55,7 @@ object RoutingTransitionAnimationFactory {
@Suppress("MagicNumber")
private fun slideAndFade(directions: Set<Direction>? = null): StackAnimator {
val easing = CubicBezierEasing(0.55f, 0.0f, 0.0f, 1f)
val easing = CubicBezierEasing(a = 0.55f, b = 0.0f, c = 0.0f, d = 1f)
return stackAnimator(
animationSpec = tween(durationMillis = 400, easing = easing),

View file

@ -183,10 +183,10 @@ internal class ChildFactory @Inject constructor(
token = route.token,
appCurrency = route.appCurrency,
showPortfolio = route.showPortfolio,
analyticsParams = route.analyticsParams?.let {
analyticsParams = route.analyticsParams?.let { params ->
MarketsTokenDetailsComponent.AnalyticsParams(
blockchain = it.blockchain,
source = it.source,
blockchain = params.blockchain,
source = params.source,
)
},
),

View file

@ -311,7 +311,6 @@ private fun MarketChartPreview(
}
val coroutineScope = rememberCoroutineScope()
val look by dataProducer.lookState.collectAsState()
TangemThemePreview {
val growingColor = TangemTheme.colors.icon.accent

Some files were not shown because too many files have changed in this diff Show more