Updated on 2026-08-14
This commit is contained in:
parent
439fb00fb2
commit
416e401d5b
18 changed files with 134 additions and 28 deletions
|
|
@ -2,7 +2,7 @@ package com.tangem.tap
|
|||
|
||||
import com.tangem.TangemSdkLogger
|
||||
import com.tangem.blockchainsdk.BlockchainSDKFactory
|
||||
import com.tangem.blockchainsdk.signer.TransactionSignerFactory
|
||||
import com.tangem.data.card.TransactionSignerFactory
|
||||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||
import com.tangem.common.routing.AppRouter
|
||||
import com.tangem.core.analytics.filter.OneTimeEventFilter
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import com.tangem.Log
|
|||
import com.tangem.TangemSdkLogger
|
||||
import com.tangem.blockchain.network.BlockchainSdkRetrofitBuilder
|
||||
import com.tangem.blockchainsdk.BlockchainSDKFactory
|
||||
import com.tangem.blockchainsdk.signer.TransactionSignerFactory
|
||||
import com.tangem.data.card.TransactionSignerFactory
|
||||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||
import com.tangem.common.routing.AppRouter
|
||||
import com.tangem.core.analytics.Analytics
|
||||
|
|
|
|||
|
|
@ -3,18 +3,20 @@ package com.tangem.tap.common.libs.blockchainsdk
|
|||
import com.tangem.Message
|
||||
import com.tangem.TangemSdk
|
||||
import com.tangem.blockchain.common.TransactionSigner
|
||||
import com.tangem.blockchainsdk.signer.TransactionSignerFactory
|
||||
import com.tangem.data.card.TransactionSignerFactory
|
||||
import com.tangem.domain.card.models.TwinKey
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.domain.TangemSigner
|
||||
import com.tangem.tap.store
|
||||
|
||||
internal class DefaultTransactionSignerFactory : TransactionSignerFactory {
|
||||
|
||||
override fun createTransactionSigner(cardId: String?, sdk: TangemSdk): TransactionSigner {
|
||||
override fun createTransactionSigner(cardId: String?, sdk: TangemSdk, twinKey: TwinKey?): TransactionSigner {
|
||||
return TangemSigner(
|
||||
cardId = cardId,
|
||||
tangemSdk = sdk,
|
||||
initialMessage = Message(),
|
||||
twinKey = twinKey,
|
||||
) { signResponse ->
|
||||
store.dispatch(action = GlobalAction.IsSignWithRing(signResponse.isRing))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.tap.di.libs.blockchainsdk
|
||||
|
||||
import com.tangem.blockchainsdk.signer.TransactionSignerFactory
|
||||
import com.tangem.data.card.TransactionSignerFactory
|
||||
import com.tangem.tap.common.libs.blockchainsdk.DefaultTransactionSignerFactory
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.tangem.TangemSdk
|
|||
import com.tangem.blockchain.common.TransactionSigner
|
||||
import com.tangem.blockchain.common.Wallet
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.domain.card.models.TwinKey
|
||||
import com.tangem.domain.models.scan.isRing
|
||||
import com.tangem.tap.domain.tasks.SignHashesTask
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
|
|
@ -14,6 +15,7 @@ class TangemSigner(
|
|||
private val cardId: String?,
|
||||
private val tangemSdk: TangemSdk,
|
||||
private val initialMessage: Message,
|
||||
private val twinKey: TwinKey?,
|
||||
private val signerCallback: (TangemSignerResponse) -> Unit,
|
||||
) : TransactionSigner {
|
||||
|
||||
|
|
@ -22,7 +24,7 @@ class TangemSigner(
|
|||
publicKey: Wallet.PublicKey,
|
||||
): CompletionResult<List<ByteArray>> {
|
||||
return suspendCancellableCoroutine { continuation ->
|
||||
val task = SignHashesTask(hashes, publicKey)
|
||||
val task = SignHashesTask(hashes, publicKey, twinKey?.getPairKey(publicKey.seedKey))
|
||||
|
||||
tangemSdk.startSessionWithRunnable(
|
||||
runnable = task,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import com.tangem.common.CompletionResult
|
|||
import com.tangem.common.core.CardSession
|
||||
import com.tangem.common.core.CardSessionRunnable
|
||||
import com.tangem.common.core.CompletionCallback
|
||||
import com.tangem.common.core.TangemSdkError
|
||||
import com.tangem.crypto.hdWallet.DerivationPath
|
||||
import com.tangem.operations.CommandResponse
|
||||
import com.tangem.operations.sign.SignHashesCommand
|
||||
|
||||
|
|
@ -18,7 +20,9 @@ class TangemSignHashesResponse(
|
|||
class SignHashesTask(
|
||||
private val hashes: Collection<ByteArray>,
|
||||
private val publicKey: Wallet.PublicKey,
|
||||
private val pairWalletPublicKey: ByteArray?,
|
||||
) : CardSessionRunnable<TangemSignHashesResponse> {
|
||||
|
||||
override fun run(session: CardSession, callback: CompletionCallback<TangemSignHashesResponse>) {
|
||||
SignHashesCommand(hashes.toTypedArray(), publicKey.seedKey, publicKey.derivationPath).run(session) { response ->
|
||||
when (response) {
|
||||
|
|
@ -35,8 +39,42 @@ class SignHashesTask(
|
|||
),
|
||||
)
|
||||
}
|
||||
is CompletionResult.Failure ->
|
||||
is CompletionResult.Failure -> {
|
||||
when {
|
||||
response.error is TangemSdkError.WalletNotFound && pairWalletPublicKey != null -> {
|
||||
sign(session, pairWalletPublicKey, publicKey.derivationPath, callback)
|
||||
}
|
||||
else -> callback(CompletionResult.Failure(response.error))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun sign(
|
||||
session: CardSession,
|
||||
publicKey: ByteArray,
|
||||
derivationPath: DerivationPath?,
|
||||
callback: CompletionCallback<TangemSignHashesResponse>,
|
||||
) {
|
||||
SignHashesCommand(hashes.toTypedArray(), publicKey, derivationPath).run(session) { response ->
|
||||
when (response) {
|
||||
is CompletionResult.Success -> {
|
||||
val card = session.environment.card
|
||||
callback(
|
||||
CompletionResult.Success(
|
||||
TangemSignHashesResponse(
|
||||
signatures = response.data.signatures,
|
||||
totalSignedHashes = response.data.totalSignedHashes,
|
||||
remainingSignatures = card?.wallet(publicKey)?.remainingSignatures,
|
||||
batchId = card?.batchId,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
is CompletionResult.Failure -> {
|
||||
callback(CompletionResult.Failure(response.error))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -218,6 +218,7 @@ class WalletConnectSdkHelper {
|
|||
signer = store.inject(DaggerGraphState::transactionSignerFactory).createTransactionSigner(
|
||||
cardId = cardId,
|
||||
sdk = sdk,
|
||||
twinKey = null, // use null here because twin doesn't support WC
|
||||
),
|
||||
)
|
||||
return when (result) {
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ class CurrencyExchangeManager(
|
|||
}
|
||||
}
|
||||
|
||||
@Deprecated("Useless")
|
||||
suspend fun buyErc20TestnetTokens(card: CardDTO, walletManager: EthereumWalletManager, destinationAddress: String) {
|
||||
walletManager.safeUpdate(card.isDemoCard())
|
||||
|
||||
|
|
@ -123,6 +124,7 @@ suspend fun buyErc20TestnetTokens(card: CardDTO, walletManager: EthereumWalletMa
|
|||
cardId = card.cardId.takeIf { isCardNotBackedUp },
|
||||
tangemSdk = store.inject(DaggerGraphState::cardSdkConfigRepository).sdk,
|
||||
initialMessage = Message(),
|
||||
twinKey = null,
|
||||
) { signResponse ->
|
||||
store.dispatch(
|
||||
GlobalAction.UpdateWalletSignedHashes(
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.tangem.tap.proxy.redux
|
||||
|
||||
import com.tangem.blockchainsdk.BlockchainSDKFactory
|
||||
import com.tangem.blockchainsdk.signer.TransactionSignerFactory
|
||||
import com.tangem.data.card.TransactionSignerFactory
|
||||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||
import com.tangem.common.routing.AppRouter
|
||||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@ package com.tangem.data.card
|
|||
|
||||
import com.tangem.TangemSdk
|
||||
import com.tangem.blockchain.common.TransactionSigner
|
||||
import com.tangem.blockchainsdk.signer.TransactionSignerFactory
|
||||
import com.tangem.common.UserCodeType
|
||||
import com.tangem.common.core.CardIdDisplayFormat
|
||||
import com.tangem.common.core.UserCodeRequestPolicy
|
||||
import com.tangem.data.card.sdk.CardSdkProvider
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.card.models.TwinKey
|
||||
import com.tangem.domain.models.scan.ProductType
|
||||
|
||||
/**
|
||||
|
|
@ -61,8 +61,8 @@ internal class DefaultCardSdkConfigRepository(
|
|||
}
|
||||
}
|
||||
|
||||
override fun getCommonSigner(cardId: String?): TransactionSigner {
|
||||
return transactionSignerFactory.createTransactionSigner(cardId = cardId, sdk = sdk)
|
||||
override fun getCommonSigner(cardId: String?, twinKey: TwinKey?): TransactionSigner {
|
||||
return transactionSignerFactory.createTransactionSigner(cardId = cardId, sdk = sdk, twinKey = twinKey)
|
||||
}
|
||||
|
||||
override fun isLinkedTerminal() = sdk.config.linkedTerminal
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
package com.tangem.data.card
|
||||
|
||||
import com.tangem.TangemSdk
|
||||
import com.tangem.blockchain.common.TransactionSigner
|
||||
import com.tangem.domain.card.models.TwinKey
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface TransactionSignerFactory {
|
||||
|
||||
fun createTransactionSigner(cardId: String?, sdk: TangemSdk, twinKey: TwinKey?): TransactionSigner
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.data.card.di
|
||||
|
||||
import com.tangem.blockchainsdk.signer.TransactionSignerFactory
|
||||
import com.tangem.data.card.TransactionSignerFactory
|
||||
import com.tangem.data.card.DefaultCardRepository
|
||||
import com.tangem.data.card.DefaultCardSdkConfigRepository
|
||||
import com.tangem.data.card.sdk.CardSdkProvider
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
package com.tangem.domain.card.models
|
||||
|
||||
import com.tangem.common.extensions.hexToBytes
|
||||
import com.tangem.domain.models.scan.ProductType
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
|
||||
data class TwinKey(
|
||||
val key1: ByteArray,
|
||||
val key2: ByteArray,
|
||||
) {
|
||||
fun getPairKey(walletPublicKey: ByteArray): ByteArray? {
|
||||
return when {
|
||||
walletPublicKey.contentEquals(key1) -> key2
|
||||
walletPublicKey.contentEquals(key2) -> key1
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as TwinKey
|
||||
|
||||
if (!key1.contentEquals(other.key1)) return false
|
||||
if (!key2.contentEquals(other.key2)) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = key1.contentHashCode()
|
||||
result = 31 * result + key2.contentHashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun getOrNull(scanResponse: ScanResponse): TwinKey? {
|
||||
return if (scanResponse.productType == ProductType.Twins) {
|
||||
val key1 = scanResponse.card.wallets.firstOrNull()?.publicKey ?: return null
|
||||
val key2 = scanResponse.secondTwinPublicKey?.hexToBytes() ?: return null
|
||||
TwinKey(key1 = key1, key2 = key2)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.tangem.domain.card.repository
|
|||
|
||||
import com.tangem.TangemSdk
|
||||
import com.tangem.blockchain.common.TransactionSigner
|
||||
import com.tangem.domain.card.models.TwinKey
|
||||
import com.tangem.domain.models.scan.ProductType
|
||||
|
||||
/**
|
||||
|
|
@ -28,7 +29,7 @@ interface CardSdkConfigRepository {
|
|||
fun updateCardIdDisplayFormat(productType: ProductType)
|
||||
|
||||
/** Get common signer by [cardId] */
|
||||
fun getCommonSigner(cardId: String?): TransactionSigner
|
||||
fun getCommonSigner(cardId: String?, twinKey: TwinKey?): TransactionSigner
|
||||
|
||||
/** Check if linked terminal is enabled */
|
||||
fun isLinkedTerminal(): Boolean?
|
||||
|
|
|
|||
|
|
@ -35,7 +35,10 @@ class AssociateAssetUseCase(
|
|||
if (isBalanceZero(userWalletId, networkCoin)) {
|
||||
raise(AssociateAssetError.NotEnoughBalance(networkCoin))
|
||||
}
|
||||
val signer = cardSdkConfigRepository.getCommonSigner(cardId = null)
|
||||
val signer = cardSdkConfigRepository.getCommonSigner(
|
||||
cardId = null,
|
||||
twinKey = null, // use null here because no assets support for Twin cards
|
||||
)
|
||||
|
||||
catch(
|
||||
block = {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,10 @@ class RetryIncompleteTransactionUseCase(
|
|||
currency: CryptoCurrency,
|
||||
): Either<IncompleteTransactionError, Unit> {
|
||||
return either {
|
||||
val signer = cardSdkConfigRepository.getCommonSigner(cardId = null)
|
||||
val signer = cardSdkConfigRepository.getCommonSigner(
|
||||
cardId = null,
|
||||
twinKey = null, // use null here because no assets support for Twin cards
|
||||
)
|
||||
|
||||
catch(
|
||||
block = {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import com.tangem.domain.common.TapWorkarounds.isStart2Coin
|
|||
import com.tangem.domain.common.TapWorkarounds.isTangemTwins
|
||||
import com.tangem.domain.demo.DemoConfig
|
||||
import com.tangem.domain.demo.DemoTransactionSender
|
||||
import com.tangem.domain.card.models.TwinKey
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.transaction.TransactionRepository
|
||||
import com.tangem.domain.transaction.error.SendTransactionError
|
||||
|
|
@ -37,7 +38,10 @@ class SendTransactionUseCase(
|
|||
val card = userWallet.scanResponse.card
|
||||
val isCardNotBackedUp = card.backupStatus?.isActive != true && !card.isTangemTwins
|
||||
|
||||
val signer = cardSdkConfigRepository.getCommonSigner(cardId = card.cardId.takeIf { isCardNotBackedUp })
|
||||
val signer = cardSdkConfigRepository.getCommonSigner(
|
||||
cardId = card.cardId.takeIf { isCardNotBackedUp },
|
||||
twinKey = TwinKey.getOrNull(scanResponse = userWallet.scanResponse),
|
||||
)
|
||||
|
||||
val linkedTerminal = cardSdkConfigRepository.isLinkedTerminal()
|
||||
if (userWallet.scanResponse.card.isStart2Coin) {
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
package com.tangem.blockchainsdk.signer
|
||||
|
||||
import com.tangem.TangemSdk
|
||||
import com.tangem.blockchain.common.TransactionSigner
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface TransactionSignerFactory {
|
||||
|
||||
fun createTransactionSigner(cardId: String?, sdk: TangemSdk): TransactionSigner
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue