Updated on 2026-08-14

This commit is contained in:
Tangem 2025-09-22 17:20:18 +03:00
commit 7db00540c5
351 changed files with 6478 additions and 1691 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

@ -9,7 +9,7 @@ import com.tangem.tap.domain.sdk.mocks.MockContent
import com.tangem.tap.domain.sdk.mocks.MockProvider
import io.qameta.allure.kotlin.Allure.step
fun BaseTestCase.openMainScreen(
fun BaseTestCase.scanCard(
productType: ProductType? = null,
mockContent: MockContent? = null,
alreadyActivatedDialogIsShown : Boolean = false
@ -32,6 +32,20 @@ fun BaseTestCase.openMainScreen(
AlreadyUsedWalletDialogPageObject { thisIsMyWalletButton.click() }
}
}
}
fun BaseTestCase.openMainScreen(
productType: ProductType? = null,
mockContent: MockContent? = null,
alreadyActivatedDialogIsShown: Boolean = false
) {
step("Scan card") {
scanCard(
productType = productType,
mockContent = mockContent,
alreadyActivatedDialogIsShown = alreadyActivatedDialogIsShown
)
}
step("Assert 'Main' screen is displayed") {
onMainScreen { screenContainer.assertIsDisplayed() }
}

View file

@ -0,0 +1,112 @@
package com.tangem.scenarios
import com.tangem.common.BaseTestCase
import com.tangem.screens.onOnboardingScreen
import io.qameta.allure.kotlin.Allure.step
fun BaseTestCase.checkBackupScreen() {
step("Assert 'Creating a backup' top bar title is displayed") {
onOnboardingScreen { creatingBackupTobBarTitle.assertIsDisplayed() }
}
step("Assert 'Prepare your scan or ring' title is displayed") {
onOnboardingScreen { prepareYouCardOrRingTitle.assertIsDisplayed() }
}
step("Assert 'Start backup' text is displayed") {
onOnboardingScreen { startBackupText.assertIsDisplayed() }
}
step("Assert 'Scan card' button is displayed") {
onOnboardingScreen { scanCardButton.assertIsDisplayed() }
}
step("Assert 'Skip for later' button is not displayed") {
onOnboardingScreen { skipForLaterButton.assertIsNotDisplayed() }
}
}
fun BaseTestCase.checkCreateWalletScreenForWalletNoWallets() {
step("Assert 'Create wallet' tob bar title is displayed") {
onOnboardingScreen { createWalletTopBarTitle.assertIsDisplayed() }
}
step("Assert top bar 'Back' button is displayed") {
onOnboardingScreen { topBarBackButton.assertIsDisplayed() }
}
step("Assert top bar 'More' button is displayed") {
onOnboardingScreen { topBarMoreButton.assertIsDisplayed() }
}
step("Assert 'Create wallet' title is displayed") {
onOnboardingScreen { createWalletTitle.assertIsDisplayed() }
}
step("Assert 'Create wallet' text is displayed") {
onOnboardingScreen { createWalletText.assertIsDisplayed() }
}
step("Assert 'Create wallet' button is displayed") {
onOnboardingScreen { createWalletButton.assertIsDisplayed() }
}
}
fun BaseTestCase.openAndCheckBackupScreenForWalletNoWallets() {
step("Click on 'Create wallet' button") {
onOnboardingScreen { createWalletButton.performClick() }
}
step("Assert 'Getting started' top bar title is displayed") {
onOnboardingScreen { gettingStartedTobBarTitle.assertIsDisplayed() }
}
step("Assert 'Backup wallet' title is displayed") {
onOnboardingScreen { backupWalletTitle.assertIsDisplayed() }
}
step("Assert 'Backup wallet' text is displayed") {
onOnboardingScreen { backupWalletText.assertIsDisplayed() }
}
step("Assert 'Backup now' button is displayed") {
onOnboardingScreen { backupWalletButton.assertIsDisplayed() }
}
step("Assert 'Skip for later' button is not displayed") {
onOnboardingScreen { skipForLaterButton.assertIsNotDisplayed() }
}
}
fun BaseTestCase.checkCreateWalletScreenForWallet2NoWallets() {
step("Assert 'Create a wallet' top bar title is displayed") {
onOnboardingScreen { createWalletTopBarTitle.assertIsDisplayed() }
}
step("Assert top bar 'Back' button is displayed") {
onOnboardingScreen { topBarBackButton.assertIsDisplayed() }
}
step("Assert top bar 'More' button is displayed") {
onOnboardingScreen { topBarMoreButton.assertIsDisplayed() }
}
step("Assert 'Generate keys privately' title is displayed") {
onOnboardingScreen { generateKeysPrivatelyTitle.assertIsDisplayed() }
}
step("Assert 'Generate keys privately' text is displayed") {
onOnboardingScreen { generateKeysPrivatelyText.assertIsDisplayed() }
}
step("Assert 'Create wallet' button is displayed") {
onOnboardingScreen { createWalletButton.assertIsDisplayed() }
}
step("Assert 'Other options' button is displayed") {
onOnboardingScreen { otherOptionsButton.assertIsDisplayed() }
}
}
fun BaseTestCase.openAndCheckBackupScreenForWallet2NoWallets() {
step("Click on 'Create wallet' button") {
onOnboardingScreen { createWalletButton.performClick() }
}
step("Assert 'Creating a backup' top bar title is displayed") {
onOnboardingScreen { creatingBackupTobBarTitle.assertIsDisplayed() }
}
step("Assert 'No backup devices' title is displayed") {
onOnboardingScreen { noBackupDevicesTitle.assertIsDisplayed() }
}
step("Assert 'No backup devices' text is displayed") {
onOnboardingScreen { noBackupDevicesText.assertIsDisplayed() }
}
step("Assert 'Add card or ring' button is displayed") {
onOnboardingScreen { addCardOrRingButton.assertIsDisplayed() }
}
step("Assert 'Finalize backup' button is displayed") {
onOnboardingScreen { finalizeBackupButton.assertIsDisplayed() }
}
step("Assert 'Skip for later' button is not displayed") {
onOnboardingScreen { skipForLaterButton.assertIsNotDisplayed() }
}
}

View file

@ -0,0 +1,151 @@
package com.tangem.screens
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
import com.tangem.common.BaseTestCase
import com.tangem.core.ui.test.BaseButtonTestTags
import com.tangem.core.ui.test.StoriesScreenTestTags
import com.tangem.core.ui.test.TopAppBarTestTags
import com.tangem.wallet.R
import io.github.kakaocup.compose.node.element.ComposeScreen
import io.github.kakaocup.compose.node.element.ComposeScreen.Companion.onComposeScreen
import io.github.kakaocup.compose.node.element.KNode
import io.github.kakaocup.kakao.common.utilities.getResourceString
import io.github.kakaocup.kakao.common.views.KView
import io.github.kakaocup.kakao.text.KButton
import com.tangem.features.onboarding.v2.impl.R as OnboardingImplR
class OnboardingPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<OnboardingPageObject>(semanticsProvider = semanticsProvider) {
val topBarBackButton: KNode = child {
hasTestTag(TopAppBarTestTags.CLOSE_BUTTON)
useUnmergedTree = true
}
val createWalletTopBarTitle: KNode = child {
hasTestTag(TopAppBarTestTags.TITLE)
hasText(getResourceString(OnboardingImplR.string.onboarding_create_wallet_header))
useUnmergedTree = true
}
val createWalletTitle: KNode = child {
hasTestTag(StoriesScreenTestTags.TITLE)
hasText(getResourceString(OnboardingImplR.string.onboarding_create_wallet_header))
useUnmergedTree = true
}
val createWalletText: KNode = child {
hasTestTag(StoriesScreenTestTags.TEXT)
hasText(getResourceString(OnboardingImplR.string.onboarding_create_wallet_body))
useUnmergedTree = true
}
val gettingStartedTobBarTitle: KNode = child {
hasTestTag(TopAppBarTestTags.TITLE)
hasText(getResourceString(OnboardingImplR.string.onboarding_getting_started))
useUnmergedTree = true
}
val creatingBackupTobBarTitle: KNode = child {
hasTestTag(TopAppBarTestTags.TITLE)
hasText(getResourceString(OnboardingImplR.string.onboarding_navbar_title_creating_backup))
useUnmergedTree = true
}
val prepareYouCardOrRingTitle: KNode = child {
hasText(getResourceString(OnboardingImplR.string.onboarding_title_scan_origin_card))
useUnmergedTree = true
}
val startBackupText: KNode = child {
hasText(getResourceString(OnboardingImplR.string.onboarding_subtitle_scan_primary))
useUnmergedTree = true
}
val topBarMoreButton: KNode = child {
hasTestTag(TopAppBarTestTags.MORE_BUTTON)
}
val backupWalletTitle: KNode = child {
hasText(getResourceString(OnboardingImplR.string.onboarding_wallet_info_title_first))
useUnmergedTree = true
}
val backupWalletText: KNode = child {
hasText(getResourceString(OnboardingImplR.string.onboarding_wallet_info_subtitle_first))
useUnmergedTree = true
}
val generateKeysPrivatelyTitle: KNode = child {
hasText(getResourceString(OnboardingImplR.string.onboarding_create_wallet_options_title))
useUnmergedTree = true
}
val generateKeysPrivatelyText: KNode = child {
hasText(getResourceString(OnboardingImplR.string.onboarding_create_wallet_options_message))
useUnmergedTree = true
}
val noBackupDevicesTitle: KNode = child {
hasText(getResourceString(OnboardingImplR.string.onboarding_subtitle_no_backup_cards))
useUnmergedTree = true
}
val noBackupDevicesText: KNode = child {
hasText(getResourceString(OnboardingImplR.string.onboarding_title_no_backup_cards))
useUnmergedTree = true
}
val createWalletButton: KNode = child {
hasTestTag(BaseButtonTestTags.TEXT)
hasText(getResourceString(OnboardingImplR.string.onboarding_create_wallet_button_create_wallet))
useUnmergedTree = true
}
val backupWalletButton: KNode = child {
hasTestTag(BaseButtonTestTags.TEXT)
hasText(getResourceString(OnboardingImplR.string.onboarding_button_backup_now))
useUnmergedTree = true
}
val scanCardButton: KNode = child {
hasTestTag(BaseButtonTestTags.TEXT)
hasText(getResourceString(OnboardingImplR.string.onboarding_button_backup_card))
useUnmergedTree = true
}
val otherOptionsButton: KNode = child {
hasTestTag(BaseButtonTestTags.TEXT)
hasText(getResourceString(OnboardingImplR.string.onboarding_create_wallet_options_button_options))
useUnmergedTree = true
}
val addCardOrRingButton: KNode = child {
hasTestTag(BaseButtonTestTags.TEXT)
hasText(getResourceString(OnboardingImplR.string.onboarding_button_add_backup_card))
useUnmergedTree = true
}
val finalizeBackupButton: KNode = child {
hasTestTag(BaseButtonTestTags.TEXT)
hasText(getResourceString(OnboardingImplR.string.onboarding_button_finalize_backup))
useUnmergedTree = true
}
val skipForLaterButton: KNode = child {
hasTestTag(BaseButtonTestTags.TEXT)
hasText(getResourceString(OnboardingImplR.string.onboarding_button_skip_backup))
useUnmergedTree = true
}
val enableNFCAlert: KView = KView {
withId(R.id.alertTitle)
}
val cancelButton: KButton = KButton {
withId(android.R.id.button2)
}
}
internal fun BaseTestCase.onOnboardingScreen(function: OnboardingPageObject.() -> Unit) =
onComposeScreen(composeTestRule, function)

View file

@ -3,18 +3,12 @@ package com.tangem.screens
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
import com.tangem.common.BaseTestCase
import com.tangem.core.ui.test.StoriesScreenTestTags
import com.tangem.wallet.R
import io.github.kakaocup.compose.node.element.ComposeScreen
import io.github.kakaocup.compose.node.element.ComposeScreen.Companion.onComposeScreen
import io.github.kakaocup.compose.node.element.KNode
import io.github.kakaocup.kakao.common.views.KView
import io.github.kakaocup.kakao.text.KButton
class StoriesPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
ComposeScreen<StoriesPageObject>(
semanticsProvider = semanticsProvider,
viewBuilderAction = { hasTestTag(StoriesScreenTestTags.SCREEN_CONTAINER) }
) {
ComposeScreen<StoriesPageObject>(semanticsProvider = semanticsProvider) {
val scanButton: KNode = child {
hasTestTag(StoriesScreenTestTags.SCAN_BUTTON)
@ -23,14 +17,6 @@ class StoriesPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
val orderButton: KNode = child {
hasTestTag(StoriesScreenTestTags.ORDER_BUTTON)
}
val enableNFCAlert: KView = KView {
withId(R.id.alertTitle)
}
val cancelButton: KButton = KButton {
withId(android.R.id.button2)
}
}
internal fun BaseTestCase.onStoriesScreen(function: StoriesPageObject.() -> Unit) =

View file

@ -0,0 +1,64 @@
package com.tangem.tests
import com.tangem.common.BaseTestCase
import com.tangem.scenarios.*
import com.tangem.tap.domain.sdk.mocks.content.ShibaNoBackupMockContent
import com.tangem.tap.domain.sdk.mocks.content.ShibaNoBackupNoWalletsMockContent
import com.tangem.tap.domain.sdk.mocks.content.Wallet2NoBackupMockContent
import com.tangem.tap.domain.sdk.mocks.content.Wallet2NoBackupNoWalletsMockContent
import dagger.hilt.android.testing.HiltAndroidTest
import io.qameta.allure.kotlin.AllureId
import io.qameta.allure.kotlin.junit4.DisplayName
import org.junit.Test
@HiltAndroidTest
class OnboardingTest : BaseTestCase() {
@AllureId("248")
@DisplayName("Onboarding: 'Shiba' no wallets backup screen test")
@Test
fun shibaNoWalletsBackupScreenTest() {
setupHooks().run {
scanCard(mockContent = ShibaNoBackupNoWalletsMockContent)
checkCreateWalletScreenForWalletNoWallets()
openAndCheckBackupScreenForWalletNoWallets()
}
}
@AllureId("3989")
@DisplayName("Onboarding: 'Shiba' with wallets backup screen test")
@Test
fun shibaBackupScreenTest() {
setupHooks().run {
scanCard(
mockContent = ShibaNoBackupMockContent,
alreadyActivatedDialogIsShown = true
)
checkBackupScreen()
}
}
@AllureId("246")
@DisplayName("Onboarding: 'Wallet 2' no wallets backup screen test")
@Test
fun wallet2NoWalletsBackupScreenTest() {
setupHooks().run {
scanCard(mockContent = Wallet2NoBackupNoWalletsMockContent)
checkCreateWalletScreenForWallet2NoWallets()
openAndCheckBackupScreenForWallet2NoWallets()
}
}
@AllureId("3990")
@DisplayName("Onboarding: 'Wallet 2' with wallets backup screen test")
@Test
fun wallet2BackupScreenTest() {
setupHooks().run {
scanCard(
mockContent = Wallet2NoBackupMockContent,
alreadyActivatedDialogIsShown = true
)
checkBackupScreen()
}
}
}

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

@ -0,0 +1,270 @@
package com.tangem.tap.domain.sdk.mocks.content
import com.tangem.common.SuccessResponse
import com.tangem.common.card.*
import com.tangem.common.extensions.ByteArrayKey
import com.tangem.crypto.hdWallet.DerivationPath
import com.tangem.crypto.hdWallet.bip32.ExtendedPublicKey
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.models.scan.ProductType
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.operations.attestation.Attestation
import com.tangem.operations.backup.PrimaryCard
import com.tangem.operations.derivation.DerivationTaskResponse
import com.tangem.operations.derivation.ExtendedPublicKeysMap
import com.tangem.operations.wallet.CreateWalletResponse
import com.tangem.sdk.api.CreateProductWalletTaskResponse
import com.tangem.tap.domain.sdk.mocks.MockContent
import java.util.Date
object ShibaNoBackupMockContent : MockContent {
private val primaryCard = PrimaryCard(
cardId = "AF02010000000002",
batchId = "AF02",
cardPublicKey = byteArrayOf(2, 48, 4, 54, -34, -33, 22, 53, -92, 8, 72, 50, 69, 1, 105, -53, 9, -126, -23, -61, -62, -85, -24, -112, -32, 76, -88, -66, -25, -83, -70, -95, 90),
linkingKey = byteArrayOf(
2, 121, 98, 127, -70, 14, 5, -23, -76, 115, -30, -26, 111, 17, 110, 34, -100, -121,
-57, -123, 74, 3, -91, 56, -20, 56, 50, -40, -101, 96, 82, 70, -91,
),
existingWalletsCount = 3, isHDWalletAllowed = true,
issuer = Card.Issuer(
name = "TANGEM SDK",
publicKey = byteArrayOf(2, 95, 22, -67, 29, 46, -81, -28, 99, -26, 42, 51, 90, 9, -26, -78, -69, -53, -48, 68, 82, 82, 104, -123, -53, 103, -97, -60, -46, 122, -15, -67, 34),
),
manufacturer = Card.Manufacturer(
name = "TANGEM",
manufactureDate = Date(1743759687),
signature = byteArrayOf(44, 8, 116, 111, -57, 20, -93, 101, -104, 97, -104, -15, 58, -8, 41, -53, 95, 99, 107, 47, -29, -118, 41, 64, 22, 94, 33, -81, 114, -47, 10, -16, 97, 14, 94, -36, -82, -108, 74, -9, 35, -38, 66, 67, -116, -55, 65, -30, -58, -33, 31, 120, -45, 42, -3, -120, -74, -97, 97, -102, -13, -28, 29, -41),
),
walletCurves = listOf(EllipticCurve.Secp256k1, EllipticCurve.Ed25519, EllipticCurve.Bls12381G2Aug),
firmwareVersion = FirmwareVersion(
major = 6,
minor = 21,
patch = 0,
type = FirmwareVersion.FirmwareType.Release,
),
isKeysImportAllowed = false,
certificate = null,
)
override val cardDto = CardDTO(
cardId = "AF02010000000002",
batchId = "AF02",
cardPublicKey = byteArrayOf(2, 48, 4, 54, -34, -33, 22, 53, -92, 8, 72, 50, 69, 1, 105, -53, 9, -126, -23, -61, -62, -85, -24, -112, -32, 76, -88, -66, -25, -83, -70, -95, 90),
firmwareVersion = CardDTO.FirmwareVersion(
major = 6,
minor = 21,
patch = 0,
type = FirmwareVersion.FirmwareType.Release,
),
manufacturer = CardDTO.Manufacturer(
name = "TANGEM SDK",
manufactureDate = Date(1649635200000),
signature = byteArrayOf(-20, 98, -101, 94, -23, 73, 122, -21, 74, 76, 79, -55, -102, -62, -30, 44, -38, 118, 75, 121, -36, 118, -62, 60, -38, -63, 33, -14, -98, -69, 112, 22, 48, -43, 47, 65, -61, -56, 38, -94, -45, 44, 95, -22, 6, -31, -40, -25, 42, 38, 94, -99, 71, 98, -33, 27, -102, 30, 52, -7, 51, -27, 84, 66),
),
issuer = CardDTO.Issuer(
name = "TANGEM",
publicKey = byteArrayOf(3, 86, -25, -61, 55, 99, 41, -33, -82, 115, -120, -33, 22, -107, 103, 3, -122, 16, 60, -110, 72, 106, -121, 100, 79, -87, -27, 18, -55, -49, 78, -110, -2),
),
settings = CardDTO.Settings(
securityDelay = 15000,
maxWalletsCount = 20,
isSettingAccessCodeAllowed = true,
isSettingPasscodeAllowed = false,
isResettingUserCodesAllowed = true,
isLinkedTerminalEnabled = true,
isBackupAllowed = true,
supportedEncryptionModes = listOf(EncryptionMode.Strong, EncryptionMode.Fast, EncryptionMode.None),
isFilesAllowed = true,
isHDWalletAllowed = true,
isKeysImportAllowed = true,
),
userSettings = CardDTO.UserSettings(isUserCodeRecoveryAllowed = true),
linkedTerminalStatus = CardDTO.LinkedTerminalStatus.None,
isAccessCodeSet = true,
isPasscodeSet = false,
supportedCurves = listOf(
EllipticCurve.Secp256k1,
EllipticCurve.Ed25519,
EllipticCurve.Secp256r1,
EllipticCurve.Bls12381G2,
EllipticCurve.Bls12381G2Aug,
EllipticCurve.Bls12381G2Pop,
EllipticCurve.Bip0340,
),
wallets = listOf(
CardDTO.Wallet(
publicKey = byteArrayOf(2, -74, 50, 45, -105, 119, 115, 87, -7, -110, 33, 10, -41, -9, -41, 1, 63, -73, 31, -77, 86, 66, -47, -31, 16, 32, 63, 122, 87, 94, 41, 68, 125),
chainCode = byteArrayOf(74, -90, -85, -117, -116, -78, 98, 63, 83, 12, 43, -69, 43, -54, -119, -62, 80, 107, -127, 53, 73, 108, 114, -102, 81, -123, 68, 92, 65, -25, 107, 86),
curve = EllipticCurve.Secp256k1,
settings = CardWallet.Settings(isPermanent = false),
totalSignedHashes = 0,
remainingSignatures = null,
index = 0,
hasBackup = false,
derivedKeys = mapOf(
DerivationPath("m/44'/0'/0'/0/0") to ExtendedPublicKey(
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),
),
DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey(
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),
),
DerivationPath("m/44'/1'/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),
),
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),
),
),
extendedPublicKey = ExtendedPublicKey(
publicKey = byteArrayOf(2, -74, 50, 45, -105, 119, 115, 87, -7, -110, 33, 10, -41, -9, -41, 1, 63, -73, 31, -77, 86, 66, -47, -31, 16, 32, 63, 122, 87, 94, 41, 68, 125),
chainCode = byteArrayOf(80, 13, -8, -108, -35, 116, -92, 125, -65, -28, 85, 72, -113, 59, 83, 13, 5, -83, -102, 123, 124, -22, 94, 108, -71, 95, 65, -2, 38, 38, -108, 14),
),
isImported = false,
),
CardDTO.Wallet(
publicKey = byteArrayOf(-123, -48, -77, -113, -63, -124, -18, 36, -14, -127, 104, 89, 48, 103, 69, -12, 107, -103, 64, -2, 97, 126, -78, -99, -9, -72, 94, -68, 30, 43, 38, 42),
chainCode = byteArrayOf(104, 109, 56, -52, 125, -119, -49, -51, -46, -122, -111, 75, 51, 103, 15, 25, -101, 72, -101, 101, -128, -2, -51, 3, 74, 62, -49, -6, -95, 91, -104, -58),
curve = EllipticCurve.Ed25519,
settings = CardWallet.Settings(isPermanent = false),
totalSignedHashes = 0,
remainingSignatures = null,
index = 1,
hasBackup = false,
derivedKeys = emptyMap(),
extendedPublicKey = ExtendedPublicKey(
publicKey = byteArrayOf(-65, -53, -62, -12, -57, -32, -38, -9, -128, -52, -83, -61, 73, 39, 41, 15, -74, -97, 38, 52, -101, 63, 74, -56, -20, 15, 57, -127, 114, -93, -17, -109),
chainCode = byteArrayOf(-81, 15, 125, 28, -115, -22, 87, 81, 87, -123, -25, -74, 86, 2, 1, 110, -115, 65, -110, 63, -64, 83, -93, -97, -104, 123, 12, -26, 94, 27, 84, -6),
),
isImported = false,
),
),
attestation = Attestation(
cardKeyAttestation = Attestation.Status.Verified,
walletKeysAttestation = Attestation.Status.Skipped,
firmwareAttestation = Attestation.Status.Skipped,
cardUniquenessAttestation = Attestation.Status.Skipped,
),
backupStatus = CardDTO.BackupStatus.NoBackup,
)
override val scanResponse = ScanResponse(
card = cardDto,
productType = ProductType.Wallet,
walletData = null,
secondTwinPublicKey = null,
derivedKeys = emptyMap(),
primaryCard = null,
)
override val derivationTaskResponse = DerivationTaskResponse(
entries = mapOf(
ByteArrayKey(
byteArrayOf(2, -74, 50, 45, -105, 119, 115, 87, -7, -110, 33, 10, -41, -9, -41, 1, 63, -73, 31, -77, 86, 66, -47, -31, 16, 32, 63, 122, 87, 94, 41, 68, 125),
)
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,
),
),
),
),
)
override val extendedPublicKey = ExtendedPublicKey(
publicKey = byteArrayOf(3, 2, 95, 53, 40, -87, -60, 11, -8, -47, 41, 37, 100, 15, -69, 1, -122, 127, -20, -81, -32, -20, -24, 5, -28, 113, 106, -90, -59, -30, -27, -110, -110),
chainCode = byteArrayOf(-95, -87, -95, -25, 27, 96, -57, -92, -69, -106, -45, 10, 85, 4, -92, -68, 49, -24, -28, -50, -49, -77, -20, 118, -50, -27, 104, -93, 115, -50, -46, -34),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
)
override val successResponse = SuccessResponse(cardId = "AF02010000000002")
override val createProductWalletTaskResponse = CreateProductWalletTaskResponse(
card = cardDto,
derivedKeys = mapOf(
ByteArrayKey(
byteArrayOf(2, -74, 50, 45, -105, 119, 115, 87, -7, -110, 33, 10, -41, -9, -41, 1, 63, -73, 31, -77, 86, 66, -47, -31, 16, 32, 63, 122, 87, 94, 41, 68, 125),
)
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,
),
),
),
),
primaryCard = primaryCard,
)
override val importWalletResponse: CreateProductWalletTaskResponse
get() = error("Available only for Wallet 2")
override val createFirstTwinResponse: CreateWalletResponse
get() = error("Available only for Twin")
override val createSecondTwinResponse: CreateWalletResponse
get() = error("Available only for Twin")
override val finalizeTwinResponse: ScanResponse
get() = error("Available only for Twin")
}

View file

@ -0,0 +1,223 @@
package com.tangem.tap.domain.sdk.mocks.content
import com.tangem.common.SuccessResponse
import com.tangem.common.card.Card
import com.tangem.common.card.EllipticCurve
import com.tangem.common.card.EncryptionMode
import com.tangem.common.card.FirmwareVersion
import com.tangem.common.extensions.ByteArrayKey
import com.tangem.crypto.hdWallet.DerivationPath
import com.tangem.crypto.hdWallet.bip32.ExtendedPublicKey
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.models.scan.ProductType
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.operations.attestation.Attestation
import com.tangem.operations.backup.PrimaryCard
import com.tangem.operations.derivation.DerivationTaskResponse
import com.tangem.operations.derivation.ExtendedPublicKeysMap
import com.tangem.operations.wallet.CreateWalletResponse
import com.tangem.sdk.api.CreateProductWalletTaskResponse
import com.tangem.tap.domain.sdk.mocks.MockContent
import java.util.Date
object ShibaNoBackupNoWalletsMockContent : MockContent {
private val primaryCard = PrimaryCard(
cardId = "AF02010000000002",
batchId = "AF02",
cardPublicKey = byteArrayOf(2, 48, 4, 54, -34, -33, 22, 53, -92, 8, 72, 50, 69, 1, 105, -53, 9, -126, -23, -61, -62, -85, -24, -112, -32, 76, -88, -66, -25, -83, -70, -95, 90),
linkingKey = byteArrayOf(
2, 121, 98, 127, -70, 14, 5, -23, -76, 115, -30, -26, 111, 17, 110, 34, -100, -121,
-57, -123, 74, 3, -91, 56, -20, 56, 50, -40, -101, 96, 82, 70, -91,
),
existingWalletsCount = 3, isHDWalletAllowed = true,
issuer = Card.Issuer(
name = "TANGEM SDK",
publicKey = byteArrayOf(2, 95, 22, -67, 29, 46, -81, -28, 99, -26, 42, 51, 90, 9, -26, -78, -69, -53, -48, 68, 82, 82, 104, -123, -53, 103, -97, -60, -46, 122, -15, -67, 34),
),
manufacturer = Card.Manufacturer(
name = "TANGEM",
manufactureDate = Date(1743759687),
signature = byteArrayOf(44, 8, 116, 111, -57, 20, -93, 101, -104, 97, -104, -15, 58, -8, 41, -53, 95, 99, 107, 47, -29, -118, 41, 64, 22, 94, 33, -81, 114, -47, 10, -16, 97, 14, 94, -36, -82, -108, 74, -9, 35, -38, 66, 67, -116, -55, 65, -30, -58, -33, 31, 120, -45, 42, -3, -120, -74, -97, 97, -102, -13, -28, 29, -41),
),
walletCurves = listOf(EllipticCurve.Secp256k1, EllipticCurve.Ed25519, EllipticCurve.Bls12381G2Aug),
firmwareVersion = FirmwareVersion(
major = 6,
minor = 21,
patch = 0,
type = FirmwareVersion.FirmwareType.Release,
),
isKeysImportAllowed = false,
certificate = null,
)
override val cardDto = CardDTO(
cardId = "AF02010000000002",
batchId = "AF02",
cardPublicKey = byteArrayOf(2, 48, 4, 54, -34, -33, 22, 53, -92, 8, 72, 50, 69, 1, 105, -53, 9, -126, -23, -61, -62, -85, -24, -112, -32, 76, -88, -66, -25, -83, -70, -95, 90),
firmwareVersion = CardDTO.FirmwareVersion(
major = 6,
minor = 21,
patch = 0,
type = FirmwareVersion.FirmwareType.Release,
),
manufacturer = CardDTO.Manufacturer(
name = "TANGEM SDK",
manufactureDate = Date(1649635200000),
signature = byteArrayOf(-20, 98, -101, 94, -23, 73, 122, -21, 74, 76, 79, -55, -102, -62, -30, 44, -38, 118, 75, 121, -36, 118, -62, 60, -38, -63, 33, -14, -98, -69, 112, 22, 48, -43, 47, 65, -61, -56, 38, -94, -45, 44, 95, -22, 6, -31, -40, -25, 42, 38, 94, -99, 71, 98, -33, 27, -102, 30, 52, -7, 51, -27, 84, 66),
),
issuer = CardDTO.Issuer(
name = "TANGEM",
publicKey = byteArrayOf(3, 86, -25, -61, 55, 99, 41, -33, -82, 115, -120, -33, 22, -107, 103, 3, -122, 16, 60, -110, 72, 106, -121, 100, 79, -87, -27, 18, -55, -49, 78, -110, -2),
),
settings = CardDTO.Settings(
securityDelay = 15000,
maxWalletsCount = 20,
isSettingAccessCodeAllowed = true,
isSettingPasscodeAllowed = false,
isResettingUserCodesAllowed = true,
isLinkedTerminalEnabled = true,
isBackupAllowed = true,
supportedEncryptionModes = listOf(EncryptionMode.Strong, EncryptionMode.Fast, EncryptionMode.None),
isFilesAllowed = true,
isHDWalletAllowed = true,
isKeysImportAllowed = true,
),
userSettings = CardDTO.UserSettings(isUserCodeRecoveryAllowed = true),
linkedTerminalStatus = CardDTO.LinkedTerminalStatus.None,
isAccessCodeSet = true,
isPasscodeSet = false,
supportedCurves = listOf(
EllipticCurve.Secp256k1,
EllipticCurve.Ed25519,
EllipticCurve.Secp256r1,
EllipticCurve.Bls12381G2,
EllipticCurve.Bls12381G2Aug,
EllipticCurve.Bls12381G2Pop,
EllipticCurve.Bip0340,
),
wallets = emptyList(),
attestation = Attestation(
cardKeyAttestation = Attestation.Status.Verified,
walletKeysAttestation = Attestation.Status.Skipped,
firmwareAttestation = Attestation.Status.Skipped,
cardUniquenessAttestation = Attestation.Status.Skipped,
),
backupStatus = CardDTO.BackupStatus.NoBackup,
)
override val scanResponse = ScanResponse(
card = cardDto,
productType = ProductType.Wallet,
walletData = null,
secondTwinPublicKey = null,
derivedKeys = emptyMap(),
primaryCard = null,
)
override val derivationTaskResponse = DerivationTaskResponse(
entries = mapOf(
ByteArrayKey(
byteArrayOf(2, -74, 50, 45, -105, 119, 115, 87, -7, -110, 33, 10, -41, -9, -41, 1, 63, -73, 31, -77, 86, 66, -47, -31, 16, 32, 63, 122, 87, 94, 41, 68, 125),
)
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,
),
),
),
),
)
override val extendedPublicKey = ExtendedPublicKey(
publicKey = byteArrayOf(3, 2, 95, 53, 40, -87, -60, 11, -8, -47, 41, 37, 100, 15, -69, 1, -122, 127, -20, -81, -32, -20, -24, 5, -28, 113, 106, -90, -59, -30, -27, -110, -110),
chainCode = byteArrayOf(-95, -87, -95, -25, 27, 96, -57, -92, -69, -106, -45, 10, 85, 4, -92, -68, 49, -24, -28, -50, -49, -77, -20, 118, -50, -27, 104, -93, 115, -50, -46, -34),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
)
override val successResponse = SuccessResponse(cardId = "AF02010000000002")
override val createProductWalletTaskResponse = CreateProductWalletTaskResponse(
card = cardDto,
derivedKeys = mapOf(
ByteArrayKey(
byteArrayOf(2, -74, 50, 45, -105, 119, 115, 87, -7, -110, 33, 10, -41, -9, -41, 1, 63, -73, 31, -77, 86, 66, -47, -31, 16, 32, 63, 122, 87, 94, 41, 68, 125),
)
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,
),
),
),
),
primaryCard = primaryCard,
)
override val importWalletResponse: CreateProductWalletTaskResponse
get() = error("Available only for Wallet 2")
override val createFirstTwinResponse: CreateWalletResponse
get() = error("Available only for Twin")
override val createSecondTwinResponse: CreateWalletResponse
get() = error("Available only for Twin")
override val finalizeTwinResponse: ScanResponse
get() = error("Available only for Twin")
}

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

@ -0,0 +1,307 @@
package com.tangem.tap.domain.sdk.mocks.content
import com.tangem.common.SuccessResponse
import com.tangem.common.card.*
import com.tangem.common.extensions.ByteArrayKey
import com.tangem.crypto.hdWallet.DerivationPath
import com.tangem.crypto.hdWallet.bip32.ExtendedPublicKey
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.models.scan.ProductType
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.operations.attestation.Attestation
import com.tangem.operations.backup.PrimaryCard
import com.tangem.operations.derivation.DerivationTaskResponse
import com.tangem.operations.derivation.ExtendedPublicKeysMap
import com.tangem.operations.wallet.CreateWalletResponse
import com.tangem.sdk.api.CreateProductWalletTaskResponse
import com.tangem.tap.domain.sdk.mocks.MockContent
import java.util.Date
object Wallet2NoBackupMockContent : MockContent {
private val primaryCard = PrimaryCard(
cardId = "AF05888888880018",
batchId = "AF05",
cardPublicKey = 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),
linkingKey = byteArrayOf( //
2, 121, 98, 127, -70, 14, 5, -23, -76, 115, -30, -26, 111, 17, 110, 34, -100, -121,
-57, -123, 74, 3, -91, 56, -20, 56, 50, -40, -101, 96, 82, 70, -91,
),
existingWalletsCount = 5, isHDWalletAllowed = true,
issuer = Card.Issuer(
name = "TANGEM SDK",
publicKey = byteArrayOf(2, 95, 22, -67, 29, 46, -81, -28, 99, -26, 42, 51, 90, 9, -26, -78, -69, -53, -48, 68, 82, 82, 104, -123, -53, 103, -97, -60, -46, 122, -15, -67, 34),
),
manufacturer = Card.Manufacturer(
name = "TANGEM",
manufactureDate = Date(1743759687),
signature = byteArrayOf(),
),
walletCurves = listOf(
EllipticCurve.Secp256k1,
EllipticCurve.Ed25519,
EllipticCurve.Bls12381G2Aug,
EllipticCurve.Secp256r1,
EllipticCurve.Ed25519Slip0010,
EllipticCurve.Bls12381G2,
EllipticCurve.Bls12381G2Pop,
EllipticCurve.Bip0340,
),
firmwareVersion = FirmwareVersion(
major = 6,
minor = 33,
patch = 0,
type = FirmwareVersion.FirmwareType.Release,
),
isKeysImportAllowed = false,
certificate = null,
)
override val cardDto = CardDTO(
cardId = "AF05888888880018",
batchId = "AF05",
cardPublicKey = 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),
firmwareVersion = CardDTO.FirmwareVersion(
major = 6,
minor = 33,
patch = 0,
type = FirmwareVersion.FirmwareType.Release,
),
manufacturer = CardDTO.Manufacturer(
name = "TANGEM",
manufactureDate = Date(1698094800000),
signature = byteArrayOf(51, -12, 14, -56, 7, -39, 5, 63, 59, 24, 102, 99, -126, 124, -127, -108, -118, 71, -19, -71, 4, -47, -121, -46, 49, -51, -31, 100, -56, -15, 96, -37, 25, 82, 94, -88, 48, 98, -105, -97, -40, 41, 27, 116, 65, 26, 78, -85, 66, -94, -92, 15, 50, -2, 7, -69, 41, 56, -75, 59, 86, 68, -38, -3),
),
issuer = CardDTO.Issuer(
name = "TANGEM SDK",
publicKey = byteArrayOf(2, 95, 22, -67, 29, 46, -81, -28, 99, -26, 42, 51, 90, 9, -26, -78, -69, -53, -48, 68, 82, 82, 104, -123, -53, 103, -97, -60, -46, 122, -15, -67, 34),
),
settings = CardDTO.Settings(
securityDelay = 15000,
maxWalletsCount = 20,
isSettingAccessCodeAllowed = true,
isSettingPasscodeAllowed = true,
isResettingUserCodesAllowed = false,
isLinkedTerminalEnabled = true,
isBackupAllowed = true,
supportedEncryptionModes = listOf(EncryptionMode.Strong, EncryptionMode.Fast, EncryptionMode.None),
isFilesAllowed = true,
isHDWalletAllowed = true,
isKeysImportAllowed = true,
),
userSettings = CardDTO.UserSettings(isUserCodeRecoveryAllowed = true),
linkedTerminalStatus = CardDTO.LinkedTerminalStatus.None,
isAccessCodeSet = true,
isPasscodeSet = false,
supportedCurves = listOf(
EllipticCurve.Secp256k1,
EllipticCurve.Ed25519,
EllipticCurve.Bls12381G2Aug,
EllipticCurve.Secp256r1,
EllipticCurve.Ed25519Slip0010,
EllipticCurve.Bls12381G2,
EllipticCurve.Bls12381G2Pop,
EllipticCurve.Bip0340,
),
wallets = listOf(
CardDTO.Wallet(
publicKey = byteArrayOf(3, 17, 59, -102, -56, 66, 10, 36, 97, -106, -92, -117, -105, -88, -2, -3, -95, -75, -54, -2, 57, 27, -90, -19, 82, 103, -12, -52, -126, -105, -120, -55, -2),
chainCode = byteArrayOf(-34, -28, -28, -12, 80, -109, -90, -31, -74, 36, -78, -21, 39, -125, -39, -91, 63, 40, -26, 3, 66, 27, -62, -55, -97, 52, -65, -11, 26, -80, 33, -45),
curve = EllipticCurve.Secp256k1,
settings = CardWallet.Settings(isPermanent = false),
totalSignedHashes = 0,
remainingSignatures = null,
index = 0,
hasBackup = false,
derivedKeys = mapOf(
DerivationPath("m/44'/60'/0'/0/0") to ExtendedPublicKey(
publicKey = byteArrayOf(2, 55, -114, -94, -73, -61, -50, 51, -115, 55, -79, 63, -96, -44, -64, -24, -36, -122, -123, -38, 81, -15, -127, -97, -42, 72, -85, -62, -98, 46, 119, 16, -55),
chainCode = byteArrayOf(31, 17, 71, -28, -29, 17, 72, -29, -98, 112, 31, -8, 72, -75, 4, -11, 60, -100, 9, 35, 58, -42, -38, 96, -71, -68, 24, -119, -43, -18, -122, 72),
),
DerivationPath("m/84'/0'/0'/0/0") to ExtendedPublicKey(
publicKey = byteArrayOf(2, -26, 103, 96, 112, 127, -125, 0, 7, 53, 30, -12, -82, 45, 14, 107, -9, 126, 75, 104, -67, -49, 35, -12, -82, -90, 101, -101, 125, -76, 88, -54, 99),
chainCode = byteArrayOf(-42, 36, 97, 65, -64, -113, 76, -91, -9, 11, 89, 123, -9, -3, 21, 103, -113, -60, 48, -31, -34, 108, 111, -38, -110, -80, 109, 17, -29, 2, 45, -71),
),
DerivationPath("m/44'/1'/0'/0/0") to ExtendedPublicKey(
publicKey = byteArrayOf(2, -96, -3, -83, 101, 63, -25, -125, -4, -65, -42, -56, 24, -52, 118, -11, -104, -105, 40, -59, 20, -109, -97, 29, -95, -6, -80, 2, 67, 103, -80, -22, -94),
chainCode = byteArrayOf(-125, 27, -91, 38, -66, 109, -92, 16, -37, 93, 107, -29, -128, -1, 115, -64, 108, -63, 17, 27, 58, 78, -2, 39, 88, -39, 44, 89, 32, -38, -16, -38),
),
),
extendedPublicKey = ExtendedPublicKey(
publicKey = byteArrayOf(-109, 42, -80, -115, -12, 44, 48, -118, -89, 10, 21, 59, 98, -110, -86, -14, 123, 105, -30, -49, -40, -4, -7, 32, 60, 67, -88, -52, -96, -10, -14, 123),
chainCode = byteArrayOf(-101, -10, -92, 72, 19, 121, -38, 105, -55, -82, -68, 13, -6, 17, 66, -10, -75, 58, 119, -127, 74, 68, 82, 25, 45, -110, 3, 3, 108, -97, -51, -127),
),
isImported = false,
),
CardDTO.Wallet(
publicKey = byteArrayOf(-109, 42, -80, -115, -12, 44, 48, -118, -89, 10, 21, 59, 98, -110, -86, -14, 123, 105, -30, -49, -40, -4, -7, 32, 60, 67, -88, -52, -96, -10, -14, 123),
chainCode = byteArrayOf(-101, -10, -92, 72, 19, 121, -38, 105, -55, -82, -68, 13, -6, 17, 66, -10, -75, 58, 119, -127, 74, 68, 82, 25, 45, -110, 3, 3, 108, -97, -51, -127),
curve = EllipticCurve.Ed25519,
settings = CardWallet.Settings(isPermanent = false),
totalSignedHashes = 0,
remainingSignatures = null,
index = 1,
hasBackup = false,
derivedKeys = emptyMap(),
extendedPublicKey = ExtendedPublicKey(
publicKey = byteArrayOf(-64, 18, -128, 121, -89, -37, -99, 44, -125, -72, -111, -79, 7, 85, 40, 67, -39, 117, 123, 11, 105, -6, -5, -79, 19, -10, -29, 20, -14, -40, 5, 90),
chainCode = byteArrayOf(33, -97, 53, -112, 61, 112, -24, 74, -87, -85, -124, -4, 103, -94, -97, 76, -41, -27, 118, 33, 55, 121, -17, -52, 60, 122, 27, 25, 29, -76, 78, 11),
),
isImported = false,
),
CardDTO.Wallet(
publicKey = byteArrayOf(-118, -77, -109, 8, -119, 101, -91, 46, -44, 15, 52, -64, -92, 5, -102, 126, 52, 121, 63, -76, -54, 80, -82, -5, 31, -35, 105, -119, -96, -54, 38, 2, -6, 109, 117, -26, -47, -20, 108, 106, -69, 72, -37, -117, -30, -9, 104, -123),
chainCode = null,
curve = EllipticCurve.Bls12381G2Aug,
settings = CardWallet.Settings(isPermanent = false),
totalSignedHashes = 1,
remainingSignatures = null,
index = 2,
hasBackup = false,
derivedKeys = emptyMap(),
extendedPublicKey = null,
isImported = false,
),
CardDTO.Wallet(
publicKey = byteArrayOf(17, -78, 53, 101, 96, -110, -10, -48, -84, 88, -64, 58, -26, -13, -2, -6, -25, 23, -79, -45, 58, 77, 52, -75, -123, 121, 32, 92, 84, -74, -111, -8),
chainCode = byteArrayOf(-110, 73, -124, -65, -1, -70, 64, -89, 95, -74, 15, 46, -110, 87, 15, -61, 120, -51, 111, 111, -45, 37, 123, -114, 65, -116, 21, 39, -77, 86, -3, -26),
curve = EllipticCurve.Bip0340,
settings = CardWallet.Settings(isPermanent = false),
totalSignedHashes = 0,
remainingSignatures = null,
index = 3,
hasBackup = false,
derivedKeys = emptyMap(),
extendedPublicKey = ExtendedPublicKey(
publicKey = byteArrayOf(115, 14, 11, 0, -93, 81, -103, -95, -75, -84, 18, -120, -31, 76, -83, -81, 91, 25, -75, 36, -99, -53, -25, -15, -1, -57, 14, -39, 98, -116, -63, -123),
chainCode = byteArrayOf(23, 5, 38, -48, 67, -42, -31, -21, 89, 11, 22, -28, 44, -19, -115, -78, 123, -27, 57, 57, -24, -86, 55, 15, 104, 114, -36, 80, 81, -108, -41, 112),
),
isImported = false,
),
CardDTO.Wallet(
publicKey = byteArrayOf(-52, -92, 64, 108, -8, -100, 87, -86, -60, 18, -18, -81, 114, -84, 76, -24, 84, 52, -34, 79, -30, -66, -112, -55, -35, -119, 127, -109, 35, 18, -29, -25),
chainCode = byteArrayOf(94, -33, -94, -63, 40, -20, -26, 71, 111, 9, 87, -36, -42, -33, 40, -53, 85, 31, -36, -29, 65, -121, 2, -23, -119, -51, 114, -17, -39, -74, 23, -97),
curve = EllipticCurve.Ed25519Slip0010,
settings = CardWallet.Settings(isPermanent = false),
totalSignedHashes = 0,
remainingSignatures = null,
index = 4,
hasBackup = false,
derivedKeys = emptyMap(),
extendedPublicKey = ExtendedPublicKey(
publicKey = byteArrayOf(-43, 1, -81, -47, -8, -103, -66, 42, 37, -7, 65, 54, 57, -24, 127, -89, 69, -112, 42, -46, -128, 36, -117, -28, 30, -48, 37, 52, 93, -47, 92, -47),
chainCode = byteArrayOf(4, -97, 81, -37, 76, -67, -87, -4, -82, -36, -45, -28, -117, -59, -62, 93, -73, 50, 65, -91, -83, 25, -95, 89, -64, -40, 113, 28, 59, 113, -99, 89),
),
isImported = false,
),
),
attestation = Attestation(
cardKeyAttestation = Attestation.Status.Verified,
walletKeysAttestation = Attestation.Status.Skipped,
firmwareAttestation = Attestation.Status.Skipped,
cardUniquenessAttestation = Attestation.Status.Skipped,
),
backupStatus = CardDTO.BackupStatus.NoBackup,
)
override val scanResponse = ScanResponse(
card = cardDto,
productType = ProductType.Wallet2,
walletData = null,
secondTwinPublicKey = null,
derivedKeys = emptyMap(),
primaryCard = null,
)
override val derivationTaskResponse = DerivationTaskResponse(
entries = mapOf(
ByteArrayKey(
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,
),
),
),
),
)
override val extendedPublicKey = ExtendedPublicKey(
publicKey = byteArrayOf(2, -93, -36, -105, 121, -52, -30, -43, -67, -7, -31, -26, -35, 25, 99, 25, -20, 118, -20, -125, -89, 12, -101, -86, 74, -91, 23, -24, 93, -86, 20, -53, -8),
chainCode = byteArrayOf(32, 60, 63, -96, 97, 58, 121, 108, 75, 59, 63, -113, 60, -49, 47, 33, 15, -65, -69, 45, -7, -26, 65, -5, -91, -55, -42, -102, -127, -104, -111, 96),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
)
override val successResponse = SuccessResponse(cardId = "AF05888888880018")
override val createProductWalletTaskResponse = CreateProductWalletTaskResponse(
card = cardDto,
derivedKeys = mapOf(
ByteArrayKey(
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,
),
),
),
),
primaryCard = primaryCard,
)
override val importWalletResponse: CreateProductWalletTaskResponse
get() = TODO("Not yet implemented")
override val createFirstTwinResponse: CreateWalletResponse
get() = error("Available only for Twin")
override val createSecondTwinResponse: CreateWalletResponse
get() = error("Available only for Twin")
override val finalizeTwinResponse: ScanResponse
get() = error("Available only for Twin")
}

View file

@ -0,0 +1,219 @@
package com.tangem.tap.domain.sdk.mocks.content
import com.tangem.common.SuccessResponse
import com.tangem.common.card.Card
import com.tangem.common.card.EllipticCurve
import com.tangem.common.card.EncryptionMode
import com.tangem.common.card.FirmwareVersion
import com.tangem.common.extensions.ByteArrayKey
import com.tangem.crypto.hdWallet.DerivationPath
import com.tangem.crypto.hdWallet.bip32.ExtendedPublicKey
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.models.scan.ProductType
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.operations.attestation.Attestation
import com.tangem.operations.backup.PrimaryCard
import com.tangem.operations.derivation.DerivationTaskResponse
import com.tangem.operations.derivation.ExtendedPublicKeysMap
import com.tangem.operations.wallet.CreateWalletResponse
import com.tangem.sdk.api.CreateProductWalletTaskResponse
import com.tangem.tap.domain.sdk.mocks.MockContent
import java.util.Date
object Wallet2NoBackupNoWalletsMockContent : MockContent {
private val primaryCard = PrimaryCard(
cardId = "AF05888888880018",
batchId = "AF05",
cardPublicKey = 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),
linkingKey = byteArrayOf( //
2, 121, 98, 127, -70, 14, 5, -23, -76, 115, -30, -26, 111, 17, 110, 34, -100, -121,
-57, -123, 74, 3, -91, 56, -20, 56, 50, -40, -101, 96, 82, 70, -91,
),
existingWalletsCount = 5, isHDWalletAllowed = true,
issuer = Card.Issuer(
name = "TANGEM SDK",
publicKey = byteArrayOf(2, 95, 22, -67, 29, 46, -81, -28, 99, -26, 42, 51, 90, 9, -26, -78, -69, -53, -48, 68, 82, 82, 104, -123, -53, 103, -97, -60, -46, 122, -15, -67, 34),
),
manufacturer = Card.Manufacturer(
name = "TANGEM",
manufactureDate = Date(1743759687),
signature = byteArrayOf(),
),
walletCurves = listOf(
EllipticCurve.Secp256k1,
EllipticCurve.Ed25519,
EllipticCurve.Bls12381G2Aug,
EllipticCurve.Secp256r1,
EllipticCurve.Ed25519Slip0010,
EllipticCurve.Bls12381G2,
EllipticCurve.Bls12381G2Pop,
EllipticCurve.Bip0340,
),
firmwareVersion = FirmwareVersion(
major = 6,
minor = 33,
patch = 0,
type = FirmwareVersion.FirmwareType.Release,
),
isKeysImportAllowed = false,
certificate = null,
)
override val cardDto = CardDTO(
cardId = "AF05888888880018",
batchId = "AF05",
cardPublicKey = 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),
firmwareVersion = CardDTO.FirmwareVersion(
major = 6,
minor = 33,
patch = 0,
type = FirmwareVersion.FirmwareType.Release,
),
manufacturer = CardDTO.Manufacturer(
name = "TANGEM",
manufactureDate = Date(1698094800000),
signature = byteArrayOf(51, -12, 14, -56, 7, -39, 5, 63, 59, 24, 102, 99, -126, 124, -127, -108, -118, 71, -19, -71, 4, -47, -121, -46, 49, -51, -31, 100, -56, -15, 96, -37, 25, 82, 94, -88, 48, 98, -105, -97, -40, 41, 27, 116, 65, 26, 78, -85, 66, -94, -92, 15, 50, -2, 7, -69, 41, 56, -75, 59, 86, 68, -38, -3),
),
issuer = CardDTO.Issuer(
name = "TANGEM SDK",
publicKey = byteArrayOf(2, 95, 22, -67, 29, 46, -81, -28, 99, -26, 42, 51, 90, 9, -26, -78, -69, -53, -48, 68, 82, 82, 104, -123, -53, 103, -97, -60, -46, 122, -15, -67, 34),
),
settings = CardDTO.Settings(
securityDelay = 15000,
maxWalletsCount = 20,
isSettingAccessCodeAllowed = true,
isSettingPasscodeAllowed = true,
isResettingUserCodesAllowed = false,
isLinkedTerminalEnabled = true,
isBackupAllowed = true,
supportedEncryptionModes = listOf(EncryptionMode.Strong, EncryptionMode.Fast, EncryptionMode.None),
isFilesAllowed = true,
isHDWalletAllowed = true,
isKeysImportAllowed = true,
),
userSettings = CardDTO.UserSettings(isUserCodeRecoveryAllowed = true),
linkedTerminalStatus = CardDTO.LinkedTerminalStatus.None,
isAccessCodeSet = true,
isPasscodeSet = false,
supportedCurves = listOf(
EllipticCurve.Secp256k1,
EllipticCurve.Ed25519,
EllipticCurve.Bls12381G2Aug,
EllipticCurve.Secp256r1,
EllipticCurve.Ed25519Slip0010,
EllipticCurve.Bls12381G2,
EllipticCurve.Bls12381G2Pop,
EllipticCurve.Bip0340,
),
wallets = emptyList(),
attestation = Attestation(
cardKeyAttestation = Attestation.Status.Verified,
walletKeysAttestation = Attestation.Status.Skipped,
firmwareAttestation = Attestation.Status.Skipped,
cardUniquenessAttestation = Attestation.Status.Skipped,
),
backupStatus = CardDTO.BackupStatus.NoBackup,
)
override val scanResponse = ScanResponse(
card = cardDto,
productType = ProductType.Wallet2,
walletData = null,
secondTwinPublicKey = null,
derivedKeys = emptyMap(),
primaryCard = null,
)
override val derivationTaskResponse = DerivationTaskResponse(
entries = mapOf(
ByteArrayKey(
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,
),
),
),
),
)
override val extendedPublicKey = ExtendedPublicKey(
publicKey = byteArrayOf(2, -93, -36, -105, 121, -52, -30, -43, -67, -7, -31, -26, -35, 25, 99, 25, -20, 118, -20, -125, -89, 12, -101, -86, 74, -91, 23, -24, 93, -86, 20, -53, -8),
chainCode = byteArrayOf(32, 60, 63, -96, 97, 58, 121, 108, 75, 59, 63, -113, 60, -49, 47, 33, 15, -65, -69, 45, -7, -26, 65, -5, -91, -55, -42, -102, -127, -104, -111, 96),
depth = 0,
parentFingerprint = byteArrayOf(0, 0, 0, 0),
childNumber = 0,
)
override val successResponse = SuccessResponse(cardId = "AF05888888880018")
override val createProductWalletTaskResponse = CreateProductWalletTaskResponse(
card = cardDto,
derivedKeys = mapOf(
ByteArrayKey(
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,
),
),
),
),
primaryCard = primaryCard,
)
override val importWalletResponse: CreateProductWalletTaskResponse
get() = TODO("Not yet implemented")
override val createFirstTwinResponse: CreateWalletResponse
get() = error("Available only for Twin")
override val createSecondTwinResponse: CreateWalletResponse
get() = error("Available only for Twin")
override val finalizeTwinResponse: ScanResponse
get() = error("Available only for Twin")
}

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

View file

@ -15,8 +15,8 @@ import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.domain.apptheme.model.AppThemeMode
import com.tangem.tap.features.details.ui.appsettings.AppSettingsScreenState.Item
import com.tangem.tap.features.details.ui.appsettings.components.*
@ -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(
this + 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

@ -14,8 +14,8 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.tap.features.details.ui.appsettings.AppSettingsItemsFactory
import com.tangem.tap.features.details.ui.appsettings.AppSettingsScreenState.Item
@ -64,10 +64,10 @@ private class ButtonItemProvider : CollectionPreviewParameterProvider<Item.Butto
collection = buildList {
val itemsFactory = AppSettingsItemsFactory()
itemsFactory.createSelectAppCurrencyButton(
this + itemsFactory.createSelectAppCurrencyButton(
currentAppCurrencyName = "US Dollar",
onClick = { /* no-op */ },
).let(::add)
)
},
)
// endregion Preview

View file

@ -16,8 +16,8 @@ import androidx.compose.ui.unit.dp
import com.tangem.core.ui.components.SpacerH4
import com.tangem.core.ui.components.SpacerW16
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.tap.features.details.ui.appsettings.AppSettingsItemsFactory
import com.tangem.tap.features.details.ui.appsettings.AppSettingsScreenState.Item
@ -71,9 +71,7 @@ private class CardItemProvider : CollectionPreviewParameterProvider<Item.Card>(
collection = buildList {
val itemsFactory = AppSettingsItemsFactory()
itemsFactory.createEnrollBiometricsCard(
onClick = { /* no-op */ },
).let(::add)
this + itemsFactory.createEnrollBiometricsCard(onClick = { /* no-op */ })
},
)
// endregion Preview

View file

@ -17,8 +17,8 @@ import com.tangem.core.ui.components.SpacerH4
import com.tangem.core.ui.components.SpacerW32
import com.tangem.core.ui.components.TangemSwitch
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.tap.features.details.ui.appsettings.AppSettingsItemsFactory
import com.tangem.tap.features.details.ui.appsettings.AppSettingsScreenState.Item
@ -85,26 +85,29 @@ private class SwitchItemProvider : CollectionPreviewParameterProvider<Item.Switc
collection = buildList {
val itemsFactory = AppSettingsItemsFactory()
itemsFactory.createSaveAccessCodeSwitch(
this + itemsFactory.createSaveAccessCodeSwitch(
isChecked = true,
isEnabled = true,
onCheckedChange = { /* no-op */ },
).let(::add)
itemsFactory.createSaveAccessCodeSwitch(
)
this + itemsFactory.createSaveAccessCodeSwitch(
isChecked = false,
isEnabled = true,
onCheckedChange = { /* no-op */ },
).let(::add)
itemsFactory.createSaveAccessCodeSwitch(
)
this + itemsFactory.createSaveAccessCodeSwitch(
isChecked = true,
isEnabled = false,
onCheckedChange = { /* no-op */ },
).let(::add)
itemsFactory.createSaveAccessCodeSwitch(
)
this + itemsFactory.createSaveAccessCodeSwitch(
isChecked = false,
isEnabled = false,
onCheckedChange = { /* no-op */ },
).let(::add)
)
},
)
// endregion Preview

View file

@ -32,6 +32,7 @@ import com.tangem.tap.store
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.coroutines.JobHolder
import com.tangem.utils.coroutines.saveIn
import com.tangem.utils.extensions.addIf
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.*
@ -99,60 +100,59 @@ internal class AppSettingsModel @Inject constructor(
}
private fun buildItems(state: AppSettingsState): ImmutableList<AppSettingsScreenState.Item> {
val items = buildList {
if (state.needEnrollBiometrics) {
itemsFactory.createEnrollBiometricsCard(
onClick = ::enrollBiometrics,
).let(::add)
}
val items = buildList<AppSettingsScreenState.Item> {
addIf(
condition = state.needEnrollBiometrics,
element = itemsFactory.createEnrollBiometricsCard(onClick = ::enrollBiometrics),
)
itemsFactory.createSelectAppCurrencyButton(
this + itemsFactory.createSelectAppCurrencyButton(
currentAppCurrencyName = state.selectedAppCurrency.name,
onClick = ::showAppCurrencySelector,
).let(::add)
)
if (hotWalletFeatureToggles.isHotWalletEnabled) {
val canUseBiometrics = !state.needEnrollBiometrics && !state.isInProgress
itemsFactory.createUseBiometricsSwitch(
this + itemsFactory.createUseBiometricsSwitch(
isChecked = state.useBiometricAuthentication,
isEnabled = canUseBiometrics,
onCheckedChange = ::onBiometricAuthenticationToggled,
).let(::add)
)
itemsFactory.createRequireAccessCodeSwitch(
this + itemsFactory.createRequireAccessCodeSwitch(
isChecked = state.requireAccessCode,
isEnabled = canUseBiometrics && state.useBiometricAuthentication,
onCheckedChange = ::onRequireAccessCodeToggled,
).let(::add)
)
} else {
if (state.isBiometricsAvailable) {
val canUseBiometrics = !state.needEnrollBiometrics && !state.isInProgress
itemsFactory.createSaveWalletsSwitch(
this + itemsFactory.createSaveWalletsSwitch(
isChecked = state.saveWallets,
isEnabled = canUseBiometrics,
onCheckedChange = ::onSaveWalletsToggled,
).let(::add)
)
itemsFactory.createSaveAccessCodeSwitch(
this + itemsFactory.createSaveAccessCodeSwitch(
isChecked = state.saveAccessCodes,
isEnabled = canUseBiometrics,
onCheckedChange = ::onSaveAccessCodesToggled,
).let(::add)
)
}
}
itemsFactory.createFlipToHideBalanceSwitch(
this + itemsFactory.createFlipToHideBalanceSwitch(
isChecked = state.isHidingEnabled,
isEnabled = true,
onCheckedChange = ::onFlipToHideBalanceToggled,
).let(::add)
)
itemsFactory.createSelectThemeModeButton(
this + itemsFactory.createSelectThemeModeButton(
currentThemeMode = state.selectedThemeMode,
onClick = { showThemeModeSelector(state.selectedThemeMode) },
).let(::add)
)
}
return items.toImmutableList()
@ -280,7 +280,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 +290,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

@ -12,9 +12,9 @@ import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.domain.card.CardTypesResolver
import com.tangem.domain.card.ScanCardProcessor
import com.tangem.domain.card.repository.CardSdkConfigRepository
import com.tangem.domain.card.common.util.cardTypesResolver
import com.tangem.domain.card.common.util.getBackupCardsCount
import com.tangem.domain.card.repository.CardSdkConfigRepository
import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.models.scan.ScanResponse
import com.tangem.domain.models.wallet.requireColdWallet
@ -34,6 +34,7 @@ import com.tangem.tap.features.details.ui.cardsettings.domain.CardSettingsIntera
import com.tangem.tap.features.details.ui.common.utils.*
import com.tangem.tap.store
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.extensions.addIf
import com.tangem.wallet.R
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
@ -57,7 +58,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,20 +78,19 @@ 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") }
.requireColdWallet()
cardSdkConfigRepository.isBiometricsRequestPolicy =
userWallet.scanResponse.card.isAccessCodeSet &&
cardSdkConfigRepository.isBiometricsRequestPolicy = userWallet.scanResponse.card.isAccessCodeSet &&
settingsRepository.shouldSaveAccessCodes()
}
}
@ -135,34 +135,39 @@ 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: List<CardInfo> = buildList {
add(CardInfo.CardId(cardId))
add(CardInfo.Issuer(card.issuer.name))
if (!cardTypesResolver.isTangemTwins()) {
CardInfo.SignedHashes(card.signedHashesCount().toString()).let(::add)
}
addIf(
condition = !cardTypesResolver.isTangemTwins(),
element = CardInfo.SignedHashes(card.signedHashesCount().toString()),
)
CardInfo.SecurityMode(
currentSecurityOption,
clickable = allowedSecurityOptions.size > 1,
).let(::add)
add(
CardInfo.SecurityMode(
securityOption = currentSecurityOption,
clickable = allowedSecurityOptions.size > 1,
),
)
if (card.backupStatus?.isActive == true && card.isAccessCodeSet) {
CardInfo.ChangeAccessCode.let(::add)
}
addIf(
condition = card.backupStatus?.isActive == true && card.isAccessCodeSet,
element = CardInfo.ChangeAccessCode,
)
if (isAccessCodeRecoveryAllowed(cardTypesResolver)) {
CardInfo.AccessCodeRecovery(isAccessCodeRecoveryEnabled(cardTypesResolver, card)).let(::add)
}
addIf(
condition = isAccessCodeRecoveryAllowed(cardTypesResolver),
element = CardInfo.AccessCodeRecovery(isAccessCodeRecoveryEnabled(cardTypesResolver, card)),
)
if (isResetCardAllowed) {
addIf(isResetCardAllowed) {
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,

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