Updated on 2026-08-14
This commit is contained in:
commit
31e6ed6bb2
13 changed files with 108 additions and 64 deletions
|
|
@ -8,7 +8,7 @@ import com.tangem.tap.common.TestActions
|
|||
import com.tangem.tap.domain.TapError
|
||||
import com.tangem.tap.domain.extensions.amountToCreateAccount
|
||||
import com.tangem.tap.domain.getFirstToken
|
||||
import com.tangem.tap.features.demo.isDemoWallet
|
||||
import com.tangem.tap.features.demo.isDemoCard
|
||||
import com.tangem.tap.features.wallet.redux.AddressData
|
||||
import com.tangem.tap.features.wallet.redux.reducers.createAddressesData
|
||||
import com.tangem.tap.network.NetworkConnectivity
|
||||
|
|
@ -21,7 +21,10 @@ import timber.log.Timber
|
|||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
suspend fun WalletManager.safeUpdate(): Result<Wallet> = try {
|
||||
if (isDemoWallet() || TestActions.testAmountInjectionForWalletManagerEnabled) {
|
||||
val scanResponse = store.state.globalState.scanResponse
|
||||
?: error("Scan response must not be null")
|
||||
|
||||
if (scanResponse.isDemoCard() || TestActions.testAmountInjectionForWalletManagerEnabled) {
|
||||
delay(500)
|
||||
TestActions.testAmountInjectionForWalletManagerEnabled = false
|
||||
Result.Success(wallet)
|
||||
|
|
|
|||
|
|
@ -5,44 +5,25 @@ import com.tangem.TangemSdk
|
|||
import com.tangem.blockchain.common.TransactionSigner
|
||||
import com.tangem.blockchain.common.Wallet
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.tap.domain.tasks.SignHashTask
|
||||
import com.tangem.common.card.Card
|
||||
import com.tangem.tap.domain.tasks.SignHashesTask
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
|
||||
class TangemSigner(
|
||||
private val card: Card,
|
||||
private val tangemSdk: TangemSdk,
|
||||
private val initialMessage: Message,
|
||||
private val signerCallback: (TangemSignerResponse) -> Unit,
|
||||
) : TransactionSigner {
|
||||
|
||||
override suspend fun sign(hash: ByteArray, cardId: String, publicKey: Wallet.PublicKey): CompletionResult<ByteArray> {
|
||||
override suspend fun sign(
|
||||
hashes: List<ByteArray>,
|
||||
publicKey: Wallet.PublicKey
|
||||
): CompletionResult<List<ByteArray>> {
|
||||
return suspendCoroutine { continuation ->
|
||||
val command = SignHashTask(hash, publicKey)
|
||||
tangemSdk.startSessionWithRunnable(
|
||||
runnable = command,
|
||||
cardId = cardId,
|
||||
initialMessage = initialMessage,
|
||||
) { result ->
|
||||
when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
signerCallback(
|
||||
TangemSignerResponse(
|
||||
result.data.totalSignedHashes,
|
||||
result.data.remainingSignatures
|
||||
)
|
||||
)
|
||||
continuation.resume(CompletionResult.Success(result.data.signature))
|
||||
}
|
||||
is CompletionResult.Failure ->
|
||||
continuation.resume(CompletionResult.Failure(result.error))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val cardId = if (card.backupStatus?.isActive == true) null else card.cardId
|
||||
|
||||
override suspend fun sign(hashes: List<ByteArray>, cardId: String, publicKey: Wallet.PublicKey): CompletionResult<List<ByteArray>> {
|
||||
return suspendCoroutine { continuation ->
|
||||
val task = SignHashesTask(hashes, publicKey)
|
||||
tangemSdk.startSessionWithRunnable(
|
||||
runnable = task,
|
||||
|
|
@ -65,6 +46,21 @@ class TangemSigner(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun sign(
|
||||
hash: ByteArray,
|
||||
publicKey: Wallet.PublicKey
|
||||
): CompletionResult<ByteArray> {
|
||||
val result = sign(
|
||||
hashes = listOf(hash),
|
||||
publicKey = publicKey
|
||||
)
|
||||
|
||||
return when (result) {
|
||||
is CompletionResult.Success -> CompletionResult.Success(result.data.first())
|
||||
is CompletionResult.Failure -> CompletionResult.Failure(result.error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class TangemSignerResponse(
|
||||
|
|
|
|||
|
|
@ -32,9 +32,10 @@ fun WalletManagerFactory.makeWalletManagerForApp(
|
|||
return when {
|
||||
scanResponse.isTangemTwins() && scanResponse.secondTwinPublicKey != null -> {
|
||||
makeTwinWalletManager(
|
||||
card.cardId,
|
||||
wallet.publicKey, scanResponse.secondTwinPublicKey!!.hexToBytes(),
|
||||
environmentBlockchain, wallet.curve
|
||||
walletPublicKey = wallet.publicKey,
|
||||
pairPublicKey = scanResponse.secondTwinPublicKey!!.hexToBytes(),
|
||||
blockchain = environmentBlockchain,
|
||||
curve = wallet.curve
|
||||
)
|
||||
}
|
||||
seedKey != null && derivationParams != null -> {
|
||||
|
|
@ -47,7 +48,6 @@ fun WalletManagerFactory.makeWalletManagerForApp(
|
|||
?: return null
|
||||
|
||||
makeWalletManager(
|
||||
cardId = card.cardId,
|
||||
blockchain = environmentBlockchain,
|
||||
seedKey = wallet.publicKey,
|
||||
derivedKey = derivedKey,
|
||||
|
|
@ -56,7 +56,6 @@ fun WalletManagerFactory.makeWalletManagerForApp(
|
|||
}
|
||||
else -> {
|
||||
makeWalletManager(
|
||||
cardId = card.cardId,
|
||||
blockchain = environmentBlockchain,
|
||||
walletPublicKey = wallet.publicKey,
|
||||
curve = wallet.curve
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@ class WalletStateConverter : StringStateConverter<AppState> {
|
|||
walletMap["publicKey"] = publicKeyMap
|
||||
walletMap["amounts"] = amounts
|
||||
walletMap["addresses"] = wallet.addresses.toString()
|
||||
walletMap["cardId"] = wallet.cardId
|
||||
|
||||
return walletMap
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,17 @@ import com.tangem.blockchain.blockchains.ethereum.EthereumGasLoader
|
|||
import com.tangem.blockchain.blockchains.ethereum.EthereumTransactionExtras
|
||||
import com.tangem.blockchain.blockchains.ethereum.EthereumUtils
|
||||
import com.tangem.blockchain.blockchains.ethereum.EthereumUtils.Companion.toKeccak
|
||||
import com.tangem.blockchain.common.*
|
||||
import com.tangem.blockchain.extensions.*
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.AmountType
|
||||
import com.tangem.blockchain.common.CommonSigner
|
||||
import com.tangem.blockchain.common.TransactionData
|
||||
import com.tangem.blockchain.common.TransactionSender
|
||||
import com.tangem.blockchain.common.Wallet
|
||||
import com.tangem.blockchain.common.WalletManager
|
||||
import com.tangem.blockchain.extensions.Result
|
||||
import com.tangem.blockchain.extensions.SimpleResult
|
||||
import com.tangem.blockchain.extensions.hexToBigDecimal
|
||||
import com.tangem.blockchain.extensions.isAscii
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.core.TangemSdkError
|
||||
import com.tangem.common.extensions.hexToBytes
|
||||
|
|
@ -17,7 +26,11 @@ import com.tangem.operations.sign.SignHashCommand
|
|||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.extensions.safeUpdate
|
||||
import com.tangem.tap.common.extensions.toFormattedString
|
||||
import com.tangem.tap.features.details.redux.walletconnect.*
|
||||
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectSession
|
||||
import com.tangem.tap.features.details.redux.walletconnect.WalletForSession
|
||||
import com.tangem.tap.features.details.redux.walletconnect.WcPersonalSignData
|
||||
import com.tangem.tap.features.details.redux.walletconnect.WcTransactionData
|
||||
import com.tangem.tap.features.details.redux.walletconnect.WcTransactionType
|
||||
import com.tangem.tap.features.details.ui.walletconnect.dialogs.PersonalSignDialogData
|
||||
import com.tangem.tap.features.details.ui.walletconnect.dialogs.TransactionRequestDialogData
|
||||
import com.tangem.tap.store
|
||||
|
|
@ -25,8 +38,8 @@ import com.tangem.tap.tangemSdk
|
|||
import com.tangem.tap.tangemSdkManager
|
||||
import com.trustwallet.walletconnect.models.ethereum.WCEthereumSignMessage
|
||||
import com.trustwallet.walletconnect.models.ethereum.WCEthereumTransaction
|
||||
import timber.log.Timber
|
||||
import java.math.BigDecimal
|
||||
import timber.log.Timber
|
||||
|
||||
class WalletConnectSdkHelper {
|
||||
|
||||
|
|
@ -108,9 +121,8 @@ class WalletConnectSdkHelper {
|
|||
)
|
||||
val blockchain = session.wallet.getBlockchainForSession()
|
||||
return factory.makeWalletManager(
|
||||
session.wallet.cardId,
|
||||
blockchain,
|
||||
publicKey
|
||||
blockchain = blockchain,
|
||||
publicKey = publicKey
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -124,7 +136,7 @@ class WalletConnectSdkHelper {
|
|||
private suspend fun sendTransaction(data: WcTransactionData): String? {
|
||||
val result = (data.walletManager as TransactionSender).send(
|
||||
transactionData = data.transaction,
|
||||
signer = Signer(tangemSdk)
|
||||
signer = CommonSigner(tangemSdk)
|
||||
)
|
||||
return when (result) {
|
||||
SimpleResult.Success -> {
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ class DemoConfig {
|
|||
testDemoCardIds).distinct()
|
||||
}
|
||||
|
||||
private val releaseDemoCardIds = mutableListOf<String>(
|
||||
private val releaseDemoCardIds = mutableListOf(
|
||||
// Tangem Wallet:
|
||||
"AC01000000041100",
|
||||
"AC01000000042462",
|
||||
|
|
@ -284,7 +284,10 @@ class DemoTransactionSender(
|
|||
|
||||
override suspend fun send(transactionData: TransactionData, signer: TransactionSigner): SimpleResult {
|
||||
val dataToSign = randomString(32).toByteArray()
|
||||
val signerResponse = signer.sign(dataToSign, walletManager.wallet.cardId, walletManager.wallet.publicKey)
|
||||
val signerResponse = signer.sign(
|
||||
hash = dataToSign,
|
||||
publicKey = walletManager.wallet.publicKey
|
||||
)
|
||||
return when (signerResponse) {
|
||||
is CompletionResult.Success -> SimpleResult.Failure(Exception(ID))
|
||||
is CompletionResult.Failure -> SimpleResult.fromTangemSdkError(signerResponse.error)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
package com.tangem.tap.features.demo
|
||||
|
||||
import com.tangem.blockchain.common.WalletManager
|
||||
import com.tangem.common.card.Card
|
||||
import com.tangem.domain.common.ScanResponse
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
fun ScanResponse.isDemoCard(): Boolean = DemoHelper.isDemoCardId(card.cardId)
|
||||
fun WalletManager.isDemoWallet(): Boolean = DemoHelper.isDemoCardId(wallet.cardId)
|
||||
fun Card.isDemoCard(): Boolean = DemoHelper.isDemoCardId(cardId)
|
||||
|
|
@ -7,7 +7,7 @@ import com.tangem.blockchain.extensions.Result
|
|||
import com.tangem.common.extensions.isZero
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.features.demo.DemoTransactionSender
|
||||
import com.tangem.tap.features.demo.isDemoWallet
|
||||
import com.tangem.tap.features.demo.isDemoCard
|
||||
import com.tangem.tap.features.send.redux.AmountActionUi
|
||||
import com.tangem.tap.features.send.redux.FeeAction
|
||||
import com.tangem.tap.features.send.redux.ReceiptAction
|
||||
|
|
@ -28,6 +28,7 @@ class RequestFeeMiddleware {
|
|||
fun handle(appState: AppState?, dispatch: DispatchFunction) {
|
||||
val sendState = appState?.sendState ?: return
|
||||
val walletManager = sendState.walletManager ?: return
|
||||
val scanResponse = appState.globalState.scanResponse ?: return
|
||||
|
||||
if (!SendState.isReadyToRequestFee()) {
|
||||
dispatch(FeeAction.FeeCalculation.SetFeeError(FeeAction.Error.ADDRESS_OR_AMOUNT_IS_EMPTY))
|
||||
|
|
@ -40,7 +41,7 @@ class RequestFeeMiddleware {
|
|||
|
||||
val destinationAddress = sendState.addressPayIdState.destinationWalletAddress!!
|
||||
val destinationAmount = Amount(typedAmount, sendState.amountState.amountToSendCrypto)
|
||||
val txSender = if (walletManager.isDemoWallet()) {
|
||||
val txSender = if (scanResponse.isDemoCard()) {
|
||||
DemoTransactionSender(walletManager)
|
||||
} else {
|
||||
walletManager as TransactionSender
|
||||
|
|
|
|||
|
|
@ -4,7 +4,11 @@ import com.google.firebase.crashlytics.FirebaseCrashlytics
|
|||
import com.tangem.blockchain.blockchains.binance.BinanceTransactionExtras
|
||||
import com.tangem.blockchain.blockchains.stellar.StellarTransactionExtras
|
||||
import com.tangem.blockchain.blockchains.xrp.XrpTransactionBuilder
|
||||
import com.tangem.blockchain.common.*
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.BlockchainSdkError
|
||||
import com.tangem.blockchain.common.TransactionError
|
||||
import com.tangem.blockchain.common.TransactionSender
|
||||
import com.tangem.blockchain.common.WalletManager
|
||||
import com.tangem.blockchain.extensions.SimpleResult
|
||||
import com.tangem.common.card.Card
|
||||
import com.tangem.common.core.TangemSdkError
|
||||
|
|
@ -15,7 +19,11 @@ import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE
|
|||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.AnalyticsEvent
|
||||
import com.tangem.tap.common.analytics.AnalyticsParam
|
||||
import com.tangem.tap.common.extensions.*
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
import com.tangem.tap.common.extensions.dispatchErrorNotification
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.safeUpdate
|
||||
import com.tangem.tap.common.extensions.stripZeroPlainString
|
||||
import com.tangem.tap.common.redux.AppDialog
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
|
|
@ -26,9 +34,15 @@ import com.tangem.tap.domain.configurable.warningMessage.WarningMessage
|
|||
import com.tangem.tap.domain.extensions.minimalAmount
|
||||
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
|
||||
import com.tangem.tap.features.demo.DemoTransactionSender
|
||||
import com.tangem.tap.features.demo.isDemoWallet
|
||||
import com.tangem.tap.features.send.redux.*
|
||||
import com.tangem.tap.features.demo.isDemoCard
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdActionUi
|
||||
import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction
|
||||
import com.tangem.tap.features.send.redux.AmountAction
|
||||
import com.tangem.tap.features.send.redux.AmountActionUi
|
||||
import com.tangem.tap.features.send.redux.FeeAction.RequestFee
|
||||
import com.tangem.tap.features.send.redux.PrepareSendScreen
|
||||
import com.tangem.tap.features.send.redux.SendAction
|
||||
import com.tangem.tap.features.send.redux.SendActionUi
|
||||
import com.tangem.tap.features.send.redux.states.ButtonState
|
||||
import com.tangem.tap.features.send.redux.states.ExternalTransactionData
|
||||
import com.tangem.tap.features.send.redux.states.MainCurrencyType
|
||||
|
|
@ -38,6 +52,7 @@ import com.tangem.tap.scope
|
|||
import com.tangem.tap.store
|
||||
import com.tangem.tap.tangemSdk
|
||||
import com.tangem.wallet.R
|
||||
import java.util.EnumSet
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -45,7 +60,6 @@ import kotlinx.coroutines.withContext
|
|||
import org.rekotlin.Action
|
||||
import org.rekotlin.Middleware
|
||||
import timber.log.Timber
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
@ -161,7 +175,11 @@ private fun sendTransaction(
|
|||
tangemSdk.config.linkedTerminal = false
|
||||
}
|
||||
|
||||
val signer = TangemSigner(tangemSdk, action.messageForSigner) { signResponse ->
|
||||
val signer = TangemSigner(
|
||||
card = card,
|
||||
tangemSdk = tangemSdk,
|
||||
initialMessage = action.messageForSigner
|
||||
) { signResponse ->
|
||||
store.dispatch(
|
||||
GlobalAction.UpdateWalletSignedHashes(
|
||||
walletSignedHashes = signResponse.totalSignedHashes,
|
||||
|
|
@ -171,7 +189,7 @@ private fun sendTransaction(
|
|||
)
|
||||
}
|
||||
val sendResult = try {
|
||||
if (walletManager.isDemoWallet()) {
|
||||
if (card.isDemoCard()) {
|
||||
DemoTransactionSender(walletManager).send(txData, signer)
|
||||
} else {
|
||||
(walletManager as TransactionSender).send(txData, signer)
|
||||
|
|
@ -340,5 +358,4 @@ private fun updateWarnings(dispatch: (Action) -> Unit) {
|
|||
|
||||
val warnings = warningsManager.getWarnings(WarningMessage.Location.SendScreen, listOf(blockchain))
|
||||
dispatch(SendAction.Warnings.Set(warnings))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -45,6 +45,7 @@ class TradeCryptoMiddleware {
|
|||
|
||||
val selectedWalletData = store.state.walletState.getSelectedWalletData() ?: return
|
||||
val exchangeManager = store.state.globalState.exchangeManager ?: return
|
||||
val card = store.state.globalState.scanResponse?.card ?: return
|
||||
val appCurrency = store.state.globalState.appCurrency
|
||||
|
||||
val addresses = selectedWalletData.walletAddresses?.list.orEmpty()
|
||||
|
|
@ -59,7 +60,13 @@ class TradeCryptoMiddleware {
|
|||
return
|
||||
}
|
||||
|
||||
scope.launch { exchangeManager.buyErc20TestnetTokens(walletManager, currency.token) }
|
||||
scope.launch {
|
||||
exchangeManager.buyErc20TestnetTokens(
|
||||
card = card,
|
||||
walletManager = walletManager,
|
||||
token = currency.token
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import com.tangem.blockchain.common.AmountType
|
|||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.Token
|
||||
import com.tangem.blockchain.extensions.Result
|
||||
import com.tangem.common.card.Card
|
||||
import com.tangem.tap.common.extensions.safeUpdate
|
||||
import com.tangem.tap.common.redux.global.CryptoCurrencyName
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
|
|
@ -68,7 +69,11 @@ class CurrencyExchangeManager(
|
|||
enum class Action { Buy, Sell }
|
||||
}
|
||||
|
||||
suspend fun CurrencyExchangeManager.buyErc20TestnetTokens(walletManager: EthereumWalletManager, token: Token) {
|
||||
suspend fun CurrencyExchangeManager.buyErc20TestnetTokens(
|
||||
card: Card,
|
||||
walletManager: EthereumWalletManager,
|
||||
token: Token,
|
||||
) {
|
||||
walletManager.safeUpdate()
|
||||
|
||||
val amountToSend = Amount(walletManager.wallet.blockchain)
|
||||
|
|
@ -85,7 +90,9 @@ suspend fun CurrencyExchangeManager.buyErc20TestnetTokens(walletManager: Ethereu
|
|||
val transaction = walletManager.createTransaction(amountToSend, fee, destinationAddress)
|
||||
|
||||
val signer = TangemSigner(
|
||||
tangemSdk = tangemSdk, Message()
|
||||
card = card,
|
||||
tangemSdk = tangemSdk,
|
||||
initialMessage = Message(),
|
||||
) { signResponse ->
|
||||
store.dispatch(
|
||||
GlobalAction.UpdateWalletSignedHashes(
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
ext.versions = [
|
||||
kotlin : '1.6.10',
|
||||
build_gradle : '7.1.3',
|
||||
tamgem_card_sdk : 'develop-154',
|
||||
tamgem_blockchain_sdk: 'develop-93',
|
||||
tamgem_card_sdk : 'develop-156',
|
||||
tamgem_blockchain_sdk: 'develop-96',
|
||||
]
|
||||
|
||||
ext.environmentConfig = [
|
||||
environment : "ENVIRONMENT",
|
||||
testActionEnabled: "TEST_ACTION_ENABLED",
|
||||
logEnabled : "LOG_ENABLED",
|
||||
]
|
||||
]
|
||||
|
|
|
|||
|
|
@ -85,4 +85,4 @@ dependencies {
|
|||
testImplementation "com.google.truth:truth:1.1.3"
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue