Updated on 2026-08-14
This commit is contained in:
parent
f748b8539d
commit
f1238f5ef8
20 changed files with 528 additions and 88 deletions
|
|
@ -3,7 +3,11 @@ package com.tangem.data.staking
|
|||
import android.util.Base64
|
||||
import arrow.core.raise.catch
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.TransactionData
|
||||
import com.tangem.blockchain.common.TransactionStatus
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.blockchainsdk.utils.toCoinId
|
||||
import com.tangem.common.extensions.hexToBytes
|
||||
import com.tangem.common.extensions.toCompressedPublicKey
|
||||
import com.tangem.data.common.cache.CacheRegistry
|
||||
import com.tangem.data.staking.converters.*
|
||||
|
|
@ -25,6 +29,7 @@ import com.tangem.datasource.local.token.StakingBalanceStore
|
|||
import com.tangem.datasource.local.token.StakingYieldsStore
|
||||
import com.tangem.domain.core.lce.LceFlow
|
||||
import com.tangem.domain.core.lce.lceFlow
|
||||
import com.tangem.domain.staking.model.StakingApproval
|
||||
import com.tangem.domain.staking.model.StakingAvailability
|
||||
import com.tangem.domain.staking.model.StakingEntryInfo
|
||||
import com.tangem.domain.staking.model.UnsubmittedTransactionMetadata
|
||||
|
|
@ -231,14 +236,26 @@ internal class DefaultStakingRepository(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun constructTransaction(transactionId: String): StakingTransaction {
|
||||
override suspend fun constructTransaction(
|
||||
networkId: String,
|
||||
fee: Fee,
|
||||
transactionId: String,
|
||||
): Pair<StakingTransaction, TransactionData.Compiled> {
|
||||
return withContext(dispatchers.io) {
|
||||
val transactionResponse = stakeKitApi.constructTransaction(
|
||||
transactionId = transactionId,
|
||||
body = ConstructTransactionRequestBody(),
|
||||
)
|
||||
|
||||
transactionConverter.convert(transactionResponse.getOrThrow())
|
||||
val transaction = transactionConverter.convert(transactionResponse.getOrThrow())
|
||||
val unsignedTransaction = transaction.unsignedTransaction ?: error("No unsigned transaction available")
|
||||
val transactionData = TransactionData.Compiled(
|
||||
value = getTransactionDataType(networkId, unsignedTransaction),
|
||||
fee = fee,
|
||||
status = TransactionStatus.Unconfirmed,
|
||||
)
|
||||
|
||||
transaction to transactionData
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -530,10 +547,24 @@ internal class DefaultStakingRepository(
|
|||
}
|
||||
}
|
||||
|
||||
override fun isApproveNeeded(cryptoCurrency: CryptoCurrency): Boolean {
|
||||
override fun getStakingApproval(cryptoCurrency: CryptoCurrency): StakingApproval {
|
||||
return when (cryptoCurrency.id.getIntegrationKey()) {
|
||||
Blockchain.Ethereum.id.plus(Blockchain.Polygon.toCoinId()) -> true
|
||||
else -> false
|
||||
Blockchain.Ethereum.id + Blockchain.Polygon.toCoinId() -> {
|
||||
StakingApproval.Needed(ETHEREUM_POLYGON_APPROVE_SPENDER)
|
||||
}
|
||||
else -> StakingApproval.Empty
|
||||
}
|
||||
}
|
||||
|
||||
private fun getTransactionDataType(networkId: String, unsignedTransaction: String): TransactionData.Compiled.Data {
|
||||
val blockchain = Blockchain.fromId(networkId)
|
||||
return when (blockchain) {
|
||||
Blockchain.Solana,
|
||||
Blockchain.Cosmos,
|
||||
-> TransactionData.Compiled.Data.Bytes(unsignedTransaction.hexToBytes())
|
||||
Blockchain.Ethereum,
|
||||
-> TransactionData.Compiled.Data.RawString(unsignedTransaction)
|
||||
else -> error("Unsupported blockchain")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -579,6 +610,8 @@ internal class DefaultStakingRepository(
|
|||
const val NEAR_INTEGRATION_ID = "near-near-native-staking"
|
||||
const val TEZOS_INTEGRATION_ID = "tezos-xtz-native-staking"
|
||||
|
||||
const val ETHEREUM_POLYGON_APPROVE_SPENDER = "0x5e3Ef299fDDf15eAa0432E6e66473ace8c13D908"
|
||||
|
||||
// uncomment items as implementation is ready
|
||||
val integrationIdMap = mapOf(
|
||||
Blockchain.Solana.run { id + toCoinId() } to SOLANA_INTEGRATION_ID,
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import com.tangem.blockchain.common.transaction.Fee
|
|||
import com.tangem.blockchainsdk.utils.fromNetworkId
|
||||
import com.tangem.common.extensions.hexToBytes
|
||||
import com.tangem.datasource.local.walletmanager.WalletManagersStore
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.transaction.TransactionRepository
|
||||
import com.tangem.domain.transaction.models.TransactionType
|
||||
|
|
@ -24,6 +25,7 @@ import com.tangem.domain.wallets.models.UserWalletId
|
|||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.math.BigDecimal
|
||||
import java.math.BigInteger
|
||||
import com.tangem.blockchain.blockchains.tron.TransactionType as SdkTransactionType
|
||||
|
||||
|
|
@ -42,15 +44,15 @@ internal class DefaultTransactionRepository(
|
|||
network: Network,
|
||||
txExtras: TransactionExtras?,
|
||||
hash: String?,
|
||||
): TransactionData.Uncompiled? = withContext(coroutineDispatcherProvider.io) {
|
||||
): TransactionData.Uncompiled = withContext(coroutineDispatcherProvider.io) {
|
||||
val blockchain = Blockchain.fromId(network.id.value)
|
||||
val walletManager = walletManagersFacade.getOrCreateWalletManager(
|
||||
userWalletId = userWalletId,
|
||||
blockchain = blockchain,
|
||||
derivationPath = network.derivationPath.value,
|
||||
)
|
||||
) ?: error("Wallet manager not found")
|
||||
|
||||
return@withContext walletManager?.createTransactionDataInternal(
|
||||
return@withContext walletManager.createTransactionDataInternal(
|
||||
amount = amount,
|
||||
fee = fee,
|
||||
memo = memo,
|
||||
|
|
@ -61,6 +63,48 @@ internal class DefaultTransactionRepository(
|
|||
)
|
||||
}
|
||||
|
||||
override suspend fun createApprovalTransaction(
|
||||
amount: Amount,
|
||||
fee: Fee,
|
||||
contractAddress: String,
|
||||
spenderAddress: String,
|
||||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
hash: String?,
|
||||
): TransactionData.Uncompiled = withContext(coroutineDispatcherProvider.io) {
|
||||
val blockchain = Blockchain.fromId(network.id.value)
|
||||
val walletManager = walletManagersFacade.getOrCreateWalletManager(
|
||||
userWalletId = userWalletId,
|
||||
blockchain = blockchain,
|
||||
derivationPath = network.derivationPath.value,
|
||||
) ?: error("Wallet manager not found")
|
||||
val approver = walletManager as? Approver ?: error("Cannot cast to Approver")
|
||||
|
||||
val approvalData = approver.getApproveData(
|
||||
spenderAddress = spenderAddress,
|
||||
value = amount,
|
||||
)
|
||||
|
||||
val extras = createTransactionDataExtras(
|
||||
data = approvalData,
|
||||
network = network,
|
||||
transactionType = TransactionType.APPROVE,
|
||||
nonce = null,
|
||||
gasLimit = null,
|
||||
)
|
||||
|
||||
return@withContext createTransaction(
|
||||
amount = amount,
|
||||
fee = fee,
|
||||
memo = null,
|
||||
destination = contractAddress,
|
||||
userWalletId = userWalletId,
|
||||
network = network,
|
||||
txExtras = extras,
|
||||
hash = hash,
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun validateTransaction(
|
||||
amount: Amount,
|
||||
fee: Fee?,
|
||||
|
|
@ -141,6 +185,28 @@ internal class DefaultTransactionRepository(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun getAllowance(
|
||||
userWalletId: UserWalletId,
|
||||
cryptoCurrency: CryptoCurrency.Token,
|
||||
spenderAddress: String,
|
||||
): BigDecimal {
|
||||
val walletManager = walletManagersFacade.getOrCreateWalletManager(userWalletId, cryptoCurrency.network)
|
||||
val blockchain = Blockchain.fromId(cryptoCurrency.network.id.value)
|
||||
val allowanceResult = (walletManager as? Approver)?.getAllowance(
|
||||
spenderAddress,
|
||||
Token(
|
||||
symbol = blockchain.currency,
|
||||
contractAddress = cryptoCurrency.contractAddress,
|
||||
decimals = cryptoCurrency.decimals,
|
||||
),
|
||||
) ?: error("Cannot cast to Approver")
|
||||
|
||||
return allowanceResult.fold(
|
||||
onSuccess = { it },
|
||||
onFailure = { error(it) },
|
||||
)
|
||||
}
|
||||
|
||||
private fun convertToSdkTransactionType(transactionType: TransactionType): SdkTransactionType {
|
||||
return when (transactionType) {
|
||||
TransactionType.APPROVE -> SdkTransactionType.APPROVE
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue