Updated on 2026-08-14

This commit is contained in:
Tangem 2023-10-19 12:42:05 +03:00
parent 21f33b6e1a
commit 4590cb4d7f
18 changed files with 111 additions and 12 deletions

View file

@ -46,6 +46,7 @@ class CardContextInterceptor(
ProductType.Twins -> "Twin"
ProductType.Wallet -> "Wallet"
ProductType.Wallet2 -> "Wallet 2.0"
ProductType.Ring -> "Ring"
ProductType.Start2Coin -> "Start2Coin"
else -> if (DemoHelper.isDemoCard(scanResponse)) {
if (DemoHelper.isTestDemoCard(scanResponse)) {

View file

@ -1,6 +1,7 @@
package com.tangem.tap.domain
import android.content.res.Resources
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import com.tangem.Message
import com.tangem.TangemSdk
@ -81,12 +82,13 @@ class TangemSdkManager(private val cardSdkConfigRepository: CardSdkConfigReposit
suspend fun createProductWallet(scanResponse: ScanResponse): CompletionResult<CreateProductWalletTaskResponse> {
return runTaskAsync(
CreateProductWalletTask(
runnable = CreateProductWalletTask(
cardTypesResolver = scanResponse.cardTypesResolver,
derivationStyleProvider = scanResponse.derivationStyleProvider,
),
scanResponse.card.cardId,
Message(resources.getString(R.string.initial_message_create_wallet_body)),
cardId = scanResponse.card.cardId,
initialMessage = Message(resources.getString(R.string.initial_message_create_wallet_body)),
iconScanRes = if (scanResponse.cardTypesResolver.isRing()) R.drawable.img_hand_scan_ring else null,
)
}
@ -94,7 +96,7 @@ class TangemSdkManager(private val cardSdkConfigRepository: CardSdkConfigReposit
scanResponse: ScanResponse,
mnemonic: String,
): CompletionResult<CreateProductWalletTaskResponse> {
val mnemonic = try {
val defaultMnemonic = try {
DefaultMnemonic(mnemonic, tangemSdk.wordlist)
} catch (e: TangemSdkError.MnemonicException) {
return CompletionResult.Failure(e)
@ -103,7 +105,7 @@ class TangemSdkManager(private val cardSdkConfigRepository: CardSdkConfigReposit
CreateProductWalletTask(
scanResponse.cardTypesResolver,
derivationStyleProvider = scanResponse.derivationStyleProvider,
mnemonic,
defaultMnemonic,
),
scanResponse.card.cardId,
Message(resources.getString(R.string.initial_message_create_wallet_body)),
@ -213,9 +215,10 @@ class TangemSdkManager(private val cardSdkConfigRepository: CardSdkConfigReposit
cardId: String? = null,
initialMessage: Message? = null,
accessCode: String? = null,
@DrawableRes iconScanRes: Int? = null,
): CompletionResult<T> = withContext(Dispatchers.Main) {
suspendCancellableCoroutine { continuation ->
tangemSdk.startSessionWithRunnable(runnable, cardId, initialMessage, accessCode) { result ->
tangemSdk.startSessionWithRunnable(runnable, cardId, initialMessage, accessCode, iconScanRes) { result ->
if (continuation.isActive) continuation.resume(result)
}
}

View file

@ -281,6 +281,9 @@ private class ScanWalletProcessor(
}
private fun getWalletProductType(card: CardDTO): ProductType {
if (card.batchId == CardDTO.RING_BATCH_ID) {
return ProductType.Ring
}
return if (card.firmwareVersion >= FirmwareVersion.Ed25519Slip0010Available) {
ProductType.Wallet2
} else {

View file

@ -54,6 +54,7 @@ object OnboardingHelper {
ProductType.Note -> AppScreen.OnboardingNote
ProductType.Wallet,
ProductType.Wallet2,
ProductType.Ring,
-> if (scanResponse.card.settings.isBackupAllowed) {
AppScreen.OnboardingWallet
} else {

View file

@ -33,6 +33,7 @@ import com.tangem.tap.features.onboarding.OnboardingDialog
import com.tangem.tap.features.onboarding.OnboardingHelper
import com.tangem.tap.features.wallet.models.toCurrencies
import com.tangem.tap.proxy.redux.DaggerGraphState
import com.tangem.wallet.R
import kotlinx.coroutines.launch
import org.rekotlin.Action
import org.rekotlin.Middleware
@ -325,7 +326,12 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
}
}
is BackupAction.ScanPrimaryCard -> {
backupService.readPrimaryCard(cardId = card?.cardId) { result ->
val iconScanRes = if (scanResponse?.cardTypesResolver?.isRing() == true) {
R.drawable.img_hand_scan_ring
} else {
null
}
backupService.readPrimaryCard(iconScanRes = iconScanRes, cardId = card?.cardId) { result ->
when (result) {
is CompletionResult.Success -> {
store.dispatchOnMain(BackupAction.StartAddingBackupCards)
@ -392,7 +398,12 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
}
}
is BackupAction.WritePrimaryCard -> {
backupService.proceedBackup { result ->
val iconScanRes = if (scanResponse?.cardTypesResolver?.isRing() == true) {
R.drawable.img_hand_scan_ring
} else {
null
}
backupService.proceedBackup(iconScanRes = iconScanRes) { result ->
when (result) {
is CompletionResult.Success -> {
store.dispatchOnMain(BackupAction.PrepareToWriteBackupCard(1))

View file

@ -1,5 +1,6 @@
package com.tangem.tap.features.onboarding.products.wallet.redux
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.tap.backupService
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.global.GlobalAction
@ -40,6 +41,7 @@ private object ReducerForGlobalAction {
maxBackupCards = MAX_BACKUP_CARDS,
canSkipBackup = action.canSkipBackup,
),
isRingOnboarding = action.scanResponse.cardTypesResolver.isRing(),
)
}
is GlobalAction.Onboarding.StartForUnfinishedBackup -> {

View file

@ -14,6 +14,7 @@ data class OnboardingWalletState(
val backupState: BackupState = BackupState(),
val cardArtworkUri: Uri? = null,
val showConfetti: Boolean = false,
val isRingOnboarding: Boolean = false,
) : StateType {
@Suppress("MagicNumber")

View file

@ -179,13 +179,21 @@ class OnboardingWalletFragment :
seedPhraseStateHandler.newState(this, state, seedPhraseViewModel)
state.cardArtworkUri?.let {
seedPhraseViewModel.setCardArtworkUri(it.toString())
loadImageIntoImageView(it, binding.imvFrontCard)
if (state.isRingOnboarding) {
binding.imvFrontCard.load(R.drawable.img_ring_placeholder)
} else {
loadImageIntoImageView(state.cardArtworkUri, binding.imvFrontCard)
}
loadImageIntoImageView(it, binding.imvFirstBackupCard)
loadImageIntoImageView(it, binding.imvSecondBackupCard)
}
}
else -> {
loadImageIntoImageView(state.cardArtworkUri, binding.imvFrontCard)
if (state.isRingOnboarding) {
binding.imvFrontCard.load(R.drawable.img_ring_placeholder)
} else {
loadImageIntoImageView(state.cardArtworkUri, binding.imvFrontCard)
}
loadImageIntoImageView(state.cardArtworkUri, binding.imvFirstBackupCard)
loadImageIntoImageView(state.cardArtworkUri, binding.imvSecondBackupCard)
handleOnboardingStep(state)

View file

@ -0,0 +1,54 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="165dp"
android:height="305dp"
android:viewportWidth="165"
android:viewportHeight="305">
<path
android:pathData="M-95.51,314V148.5C-83.06,137.7 -4.53,72.86 -1.65,69.26C1.95,64.76 36.15,30.1 38.4,27.4C40.65,24.7 42.9,24.7 45.15,23.35C46.95,22.27 53.7,18.1 56.85,16.15C59.4,13.75 65.67,8.32 70.35,5.8C76.21,2.65 87.01,2.2 92.86,1.3C97.54,0.58 108.61,1 113.56,1.3C116.86,1.75 125.62,2.56 134.26,2.2C142.9,1.84 150.16,6.55 152.71,8.95L157.49,12L155.99,18.5L152.71,20.5L144.99,21.5H135.99L136.49,25L145.99,26L153.49,27L160.49,28.5L162.99,34.5L160.49,41.5L152.71,43H139.49L127.06,44L136.49,46.5L150.49,48.5L155.99,51L157.49,58L149.99,62.5H142.99L119.49,61L110.49,63.5L132.49,65.5L143.99,68L145.99,73C146.74,74.2 143.99,75.5 141.99,77.5C138.97,80.52 128.41,79.05 127.06,79.5C125.98,79.86 113.14,78.71 105.49,80.51C101.89,81.71 91.15,90.77 87.91,94.01C83.86,98.06 71.25,106.16 69,108.86C66.75,111.56 38.4,122.81 35.7,122.81C33,122.81 20.4,129.56 18.6,132.26C17.16,134.42 -76.16,283.85 -95.51,314Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M147.01,6.18C141.37,4.09 129.82,3.51 123.17,3.18C116.41,2.69 109.62,2.59 102.84,2.63C89.42,2.69 74.37,2.57 63.43,11.54C60.38,14.04 57.81,17.06 54.46,19.21C51.1,21.36 47.46,22.77 44.2,24.91C37.58,29.24 32.35,35.31 27,41C15.39,53.38 3.44,65.45 -8.84,77.22C-21.12,88.99 -81.75,137.82 -94.71,149C-93.09,147.62 -96.32,150.39 -94.71,149C-95.99,150.08 -97.85,148.25 -96.57,147.16C-83.41,135.97 -27.39,91.22 -14.86,79.34C-2.32,67.47 9.88,55.27 21.75,42.75C27.33,36.84 32.58,30.52 38.96,25.48C42.03,23.1 45.34,21.04 48.83,19.33C50.65,18.45 52.4,17.44 54.07,16.31C55.72,15.06 57.28,13.69 58.73,12.22C61.36,9.64 64.35,7.43 67.6,5.69C70.85,4.03 74.3,2.77 77.86,1.95C84.7,0.32 91.69,0.09 98.69,0.03C112.1,-0.1 129.96,0.14 143.23,2.47C147.49,3.22 154.23,9.24 154.23,9.24L147.01,6.18Z"
android:fillColor="#2C2C2E"/>
<path
android:pathData="M96.99,87C93.49,91.5 89.59,93.25 85.93,96.39C82.03,99.71 78.45,103.34 74.31,106.39C66.19,112.37 56.91,116.57 47.45,119.95C37.99,123.34 28.48,124.26 21.3,131.87C20.17,133.07 17.92,132.16 19.05,130.97C25.24,124.41 33.29,122.25 41.64,119.31C50.73,116.1 59.7,112.72 67.93,107.63C72.14,104.98 76.09,101.94 79.73,98.55C83.3,95.28 86.85,91.99 91.1,89.61C93.42,88.31 94.49,87 95.99,85.5C95.99,85.14 96.99,86.43 96.99,87Z"
android:fillColor="#2C2C2E"/>
<path
android:pathData="M90.99,91C94.49,88.5 102.19,80.9 106.99,80.5C112.99,80 131.99,79.5 137.49,79.5C142.99,79.5 146.49,74 146.49,72"
android:strokeWidth="2.4"
android:fillColor="#00000000"
android:strokeColor="#2C2C2E"/>
<path
android:pathData="M21.3,131.87C12.89,141.6 5.75,152.32 -0.17,163.74C-1.85,166.99 -85.33,299.94 -86.79,303.29C-87.46,304.81 -89.67,303.5 -89.01,302C-83.01,292 4.76,149.07 12.64,138.66C14.87,135.71 16.63,133.77 19.05,130.97C20.14,129.72 22.4,130.58 21.33,131.83L21.3,131.87Z"
android:fillColor="#2C2C2E"/>
<path
android:pathData="M96.67,57.73L99.23,61.8C100,63.05 100.75,64.16 100.48,65.69C100.12,67.16 99.61,68.6 98.95,69.97L97.24,74.44C96.8,75.59 94.93,75.09 95.39,73.93C96.4,71.31 97.57,68.7 98.44,66.03C98.56,65.75 98.62,65.45 98.62,65.14C98.62,64.84 98.56,64.53 98.44,64.25C98.13,63.66 97.78,63.09 97.4,62.54L95.04,58.74C94.38,57.69 96.05,56.72 96.7,57.78L96.67,57.73Z"
android:fillColor="#2C2C2E"/>
<path
android:pathData="M104.29,19.39C104.29,18.28 103.43,17.38 102.83,16.49C102.13,15.39 101.67,14.16 101.49,12.88C101.44,12.71 101.47,12.54 101.55,12.4C101.63,12.25 101.77,12.14 101.93,12.09C102.01,12.07 102.1,12.06 102.18,12.07C102.26,12.08 102.34,12.11 102.42,12.15C102.49,12.2 102.55,12.25 102.61,12.32C102.66,12.39 102.69,12.46 102.72,12.54C102.91,13.82 103.39,15.04 104.11,16.1C104.91,17.03 105.42,18.17 105.57,19.39C105.57,19.56 105.51,19.72 105.39,19.84C105.26,19.96 105.1,20.03 104.93,20.03C104.76,20.03 104.6,19.96 104.48,19.84C104.36,19.72 104.29,19.56 104.29,19.39Z"
android:fillColor="#2C2C2E"/>
<path
android:pathData="M86.43,27.14C85.04,26.45 83.83,25.45 82.89,24.22C81.79,22.89 80.79,21.48 79.77,20.11C79.69,19.97 79.67,19.8 79.71,19.64C79.76,19.48 79.86,19.35 80,19.26C80.14,19.18 80.31,19.17 80.47,19.21C80.63,19.25 80.76,19.35 80.85,19.49C81.81,20.77 82.74,22.1 83.77,23.34C84.64,24.49 85.77,25.42 87.05,26.07C87.2,26.15 87.3,26.29 87.34,26.45C87.38,26.61 87.36,26.78 87.29,26.92C87.2,27.06 87.06,27.16 86.9,27.2C86.74,27.25 86.58,27.23 86.43,27.15V27.14Z"
android:fillColor="#2C2C2E"/>
<path
android:pathData="M88.04,63.09C88.13,69.57 87.88,76.06 87.29,82.52C86.83,88 85.83,93.59 82.64,98.19C82.17,98.86 81.06,98.19 81.53,97.54C84.74,92.92 85.64,87.28 86.07,81.81C86.55,75.59 86.88,69.32 86.75,63.09C86.75,62.92 86.82,62.75 86.94,62.63C87.06,62.51 87.23,62.45 87.4,62.45C87.57,62.45 87.73,62.51 87.85,62.63C87.97,62.75 88.04,62.92 88.04,63.09Z"
android:fillColor="#2C2C2E"/>
<path
android:pathData="M143.99,4C150.49,6 157.49,10 157.49,14.5C157.49,24.22 139.4,21.5 133.99,21.5L127.49,24.5L144.99,26C148.82,26.5 157.09,27.8 159.49,29C161.89,30.2 162.99,33 162.99,36C162.49,40 160.69,42.2 157.49,43C153.49,44 137.99,43 133.49,43C128.99,43 127.99,43 123.49,43C119.89,43 118.82,43 116.49,43L129.49,45.5L137.49,46.5L146.99,48C152.04,48.36 157.49,49.85 157.49,56C157.49,60 151.99,63 147.99,63C143.46,63 134.49,62 132.99,61.5C131.79,61.1 122.49,62 119.49,61L99.49,64.5M99.49,65.5L116.49,64.5C120.16,64.33 135.02,65.45 137.49,66C141.99,67 146.49,67 146.49,72"
android:strokeWidth="2.4"
android:fillColor="#00000000"
android:strokeColor="#2C2C2E"/>
<path
android:pathData="M142.49,24m-13.5,0a13.5,13.5 0,1 1,27 0a13.5,13.5 0,1 1,-27 0"
android:strokeWidth="5"
android:fillColor="#00000000"
android:strokeColor="#2C2C2E"/>
<path
android:pathData="M131.57,18.26C130.91,17.96 129.09,17.24 124.63,18.26C122.23,18.87 124.22,18.42 122,19.52V40.38C127.77,40.22 124.13,40.38 122,40.38C127.11,37.71 130.55,35.91 133.97,31.27C134.13,31.04 136.8,25.43 135.03,21.68C134.3,20.18 133.08,18.98 131.57,18.26Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M55.83,29.45C63.11,30.01 70.51,30.21 77.73,28.94C81.28,28.34 84.74,27.33 88.05,25.91C91.39,24.43 94.46,22.29 98,21.27C105.24,19.17 112.97,21.69 120.13,19.08C123.36,17.9 126.54,16.19 130.09,16.52C131.59,16.6 133.03,17.14 134.21,18.06C135.4,18.97 136.29,20.22 136.75,21.65C139.01,28.38 134.46,34.62 129.64,38.23C126.82,40.37 123.68,42.06 120.35,43.24C116.7,44.5 112.86,44.95 109.09,45.76C101.34,47.33 94.37,51.13 87.3,54.54C83.81,56.25 80.2,57.79 76.85,59.78C73.77,61.65 71.09,64.1 68.96,67.01C64.43,73.08 60.83,79.84 56.58,86.09C54.69,88.87 52.48,91.58 49.46,93.19C46.39,94.66 43.01,95.34 39.61,95.18C37.9,95.18 36.19,95.02 34.42,94.88C32.66,94.73 32.77,92.17 32.88,91.7C36.17,91.97 41.11,92.89 44.38,92.25C47.58,91.61 50.44,89.87 52.48,87.33C54.63,84.54 56.6,81.61 58.37,78.56C60.4,75.37 62.4,72.16 64.47,69C66.25,66.14 68.36,63.49 70.75,61.13C73.42,58.78 76.42,56.85 79.66,55.4C83.08,53.68 86.56,52.06 90.02,50.39C93.47,48.72 96.67,47.12 100.11,45.76C103.55,44.43 107.12,43.45 110.76,42.83C114.36,42.16 118.02,41.55 121.41,40.1C124.56,38.71 127.48,36.86 130.09,34.61C132.5,32.58 133.54,29.57 134.38,26.42C135.06,23.85 134.38,20.68 131.82,19.57C128.76,18.2 125.27,19.83 122.41,20.98C119.12,22.3 115.61,22.98 112.07,22.99C108.55,23.05 105.01,22.74 101.51,23.2C97.84,23.68 94.8,25.45 91.56,27.11C88.48,28.69 85.23,29.9 81.87,30.73C75.05,32.27 68.04,32.82 61.06,32.38C59.35,32.31 57.56,32.19 55.82,32.06C54.07,31.93 54.17,29.37 55.82,29.49L55.83,29.45Z"
android:fillColor="#2C2C2E"/>
<path
android:pathData="M135.38,23.82C133.54,24.77 131.7,25.73 129.85,26.66C128.21,27.59 126.34,28.06 124.45,28.01C120.63,27.73 117.61,25.27 115.04,22.58C114.48,21.98 115.39,21.08 115.95,21.68C118.3,24.17 121.19,26.63 124.79,26.74C126.57,26.68 128.3,26.16 129.82,25.24L134.74,22.72C135.47,22.34 136.12,23.45 135.38,23.82Z"
android:fillColor="#1C1C1E"/>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View file

@ -51,6 +51,7 @@ internal class DefaultCardSdkConfigRepository(
ProductType.Wallet,
ProductType.Wallet2,
ProductType.Start2Coin,
ProductType.Ring,
-> CardIdDisplayFormat.Full
}
}

View file

@ -3,6 +3,7 @@ package com.tangem.domain.common
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.Token
@Suppress("TooManyFunctions")
interface CardTypesResolver {
fun isTangemNote(): Boolean
@ -13,6 +14,8 @@ interface CardTypesResolver {
fun isWallet2(): Boolean
fun isRing(): Boolean
fun isTangemTwins(): Boolean
fun isStart2Coin(): Boolean

View file

@ -12,6 +12,7 @@ import com.tangem.domain.models.scan.CardDTO
import com.tangem.domain.models.scan.ProductType
import com.tangem.operations.attestation.Attestation
@Suppress("TooManyFunctions")
internal class TangemCardTypesResolver(
private val card: CardDTO,
private val productType: ProductType,
@ -33,6 +34,10 @@ internal class TangemCardTypesResolver(
return card.firmwareVersion >= FirmwareVersion.Ed25519Slip0010Available && card.settings.isKeysImportAllowed
}
override fun isRing(): Boolean {
return productType == ProductType.Ring
}
override fun isTangemTwins(): Boolean = productType == ProductType.Twins
override fun isStart2Coin(): Boolean = card.isStart2Coin

View file

@ -22,6 +22,7 @@ class UserWalletBuilder(
ProductType.Start2Coin -> "Start2Coin"
ProductType.Wallet,
ProductType.Wallet2,
ProductType.Ring,
-> when {
card.isBackupNotAllowed -> "Tangem card"
cardTypesResolver.isStart2Coin() -> "Start2Coin"

View file

@ -61,6 +61,7 @@ class UserWalletIdBuilder private constructor(
ProductType.Note,
ProductType.Wallet,
ProductType.Wallet2,
ProductType.Ring,
ProductType.Start2Coin,
-> null
},

View file

@ -318,4 +318,8 @@ data class CardDTO(
}
}
}
companion object {
const val RING_BATCH_ID = "AC17"
}
}

View file

@ -21,5 +21,5 @@ data class ScanResponse(
typealias KeyWalletPublicKey = ByteArrayKey
enum class ProductType {
Note, Twins, Wallet, Start2Coin, Wallet2
Note, Twins, Wallet, Start2Coin, Wallet2, Ring
}

View file

@ -84,7 +84,7 @@ spr-client = "3.6.2"
# region Tangem
tangemBlockchainSdk = "release-app_4.11-360"
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
tangemCardSdk = "release-app_4.11-295"
tangemCardSdk = "release-app_4.11-305"
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds
# endregion Tangem