Updated on 2026-08-14
This commit is contained in:
parent
7c92156d19
commit
680794d447
12 changed files with 357 additions and 5 deletions
|
|
@ -4,11 +4,16 @@ import com.tangem.blockchain.common.Blockchain
|
|||
import com.tangem.blockchain.common.Token
|
||||
import com.tangem.blockchainsdk.utils.fromNetworkId
|
||||
import com.tangem.data.common.currency.ResponseCryptoCurrenciesFactory
|
||||
import com.tangem.data.transaction.convertes.GaslessSignedTransactionResultConverter
|
||||
import com.tangem.data.transaction.convertes.GaslessTransactionRequestBuilder
|
||||
import com.tangem.datasource.api.common.response.getOrThrow
|
||||
import com.tangem.datasource.api.gasless.GaslessTxServiceApi
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.transaction.GaslessTransactionRepository
|
||||
import com.tangem.domain.transaction.models.Eip7702Authorization
|
||||
import com.tangem.domain.transaction.models.GaslessSignedTransactionResult
|
||||
import com.tangem.domain.transaction.models.GaslessTransactionData
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
|
|
@ -22,6 +27,8 @@ class DefaultGaslessTransactionRepository(
|
|||
) : GaslessTransactionRepository {
|
||||
|
||||
private val supportedTokensState = MutableStateFlow<Set<CryptoCurrency>?>(null)
|
||||
private val gaslessTransactionRequestBuilder = GaslessTransactionRequestBuilder()
|
||||
private val signedTransactionResultConverter = GaslessSignedTransactionResultConverter()
|
||||
|
||||
override fun isNetworkSupported(network: Network): Boolean {
|
||||
val blockchain = Blockchain.fromNetworkId(network.backendId) ?: return false
|
||||
|
|
@ -63,6 +70,34 @@ class DefaultGaslessTransactionRepository(
|
|||
return TOKEN_RECEIVER_ADDRESS
|
||||
}
|
||||
|
||||
override suspend fun sendGaslessTransaction(
|
||||
gaslessTransactionData: GaslessTransactionData,
|
||||
signature: String,
|
||||
userAddress: String,
|
||||
network: Network,
|
||||
eip7702Auth: Eip7702Authorization?,
|
||||
): GaslessSignedTransactionResult = withContext(coroutineDispatcherProvider.io) {
|
||||
val blockchain = Blockchain.fromNetworkId(network.backendId)
|
||||
?: error("Cannot determine blockchain for network id: ${network.backendId}")
|
||||
|
||||
val transactionRequest = gaslessTransactionRequestBuilder.build(
|
||||
gaslessTransaction = gaslessTransactionData,
|
||||
signature = signature,
|
||||
userAddress = userAddress,
|
||||
chainId = blockchain.getChainId() ?: error("ChainId is null for blockchain: $blockchain"),
|
||||
eip7702Auth = eip7702Auth,
|
||||
)
|
||||
|
||||
val response = gaslessTxServiceApi.signGaslessTransaction(transactionRequest).getOrThrow()
|
||||
|
||||
if (!response.isSuccess) {
|
||||
error("Gasless service returned unsuccessful response")
|
||||
}
|
||||
|
||||
// Convert DTO to domain model
|
||||
signedTransactionResultConverter.convert(response.result)
|
||||
}
|
||||
|
||||
override fun getBaseGasForTransaction(): BigInteger {
|
||||
return BASE_GAS_FOR_TRANSACTION
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
package com.tangem.data.transaction.convertes
|
||||
|
||||
import com.tangem.datasource.api.gasless.models.GaslessSignedTransactionResultDTO as GaslessSignedTransactionResultDTO
|
||||
import com.tangem.domain.transaction.models.GaslessSignedTransactionResult
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
/**
|
||||
* Converts DTO GaslessSignedTransactionResult from API to domain model.
|
||||
* Transforms string representations of gas parameters to BigInteger for type safety.
|
||||
*/
|
||||
class GaslessSignedTransactionResultConverter :
|
||||
Converter<GaslessSignedTransactionResultDTO, GaslessSignedTransactionResult> {
|
||||
|
||||
override fun convert(value: GaslessSignedTransactionResultDTO): GaslessSignedTransactionResult {
|
||||
return GaslessSignedTransactionResult(
|
||||
signedTransaction = value.signedTransaction,
|
||||
gasLimit = value.gasLimit.toBigInteger(),
|
||||
maxFeePerGas = value.maxFeePerGas.toBigInteger(),
|
||||
maxPriorityFeePerGas = value.maxPriorityFeePerGas.toBigInteger(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package com.tangem.data.transaction.convertes
|
||||
|
||||
import com.tangem.datasource.api.gasless.models.GaslessTransactionRequest
|
||||
import com.tangem.domain.transaction.models.Eip7702Authorization
|
||||
import com.tangem.domain.transaction.models.GaslessTransactionData
|
||||
import com.tangem.datasource.api.gasless.models.Eip7702AuthorizationDTO
|
||||
|
||||
/**
|
||||
* Builder for creating complete GaslessTransactionRequest from domain model.
|
||||
* Combines transaction data with signature and user information.
|
||||
*/
|
||||
class GaslessTransactionRequestBuilder(
|
||||
private val converter: GaslessTxDataToGaslessRequestConverter = GaslessTxDataToGaslessRequestConverter(),
|
||||
) {
|
||||
|
||||
/**
|
||||
* Creates complete gasless transaction request.
|
||||
*
|
||||
* @param gaslessTransaction domain model of transaction
|
||||
* @param signature transaction signature in hex format (with 0x prefix)
|
||||
* @param userAddress user's Ethereum address
|
||||
* @param chainId blockchain network chain ID
|
||||
* @param eip7702Auth optional EIP-7702 authorization for account abstraction
|
||||
* @return complete request ready for API submission
|
||||
*/
|
||||
fun build(
|
||||
gaslessTransaction: GaslessTransactionData,
|
||||
signature: String,
|
||||
userAddress: String,
|
||||
chainId: Int,
|
||||
eip7702Auth: Eip7702Authorization? = null,
|
||||
): GaslessTransactionRequest {
|
||||
return GaslessTransactionRequest(
|
||||
gaslessTransaction = converter.convert(gaslessTransaction),
|
||||
signature = signature,
|
||||
userAddress = userAddress,
|
||||
chainId = chainId,
|
||||
eip7702Auth = eip7702Auth?.toDTO(),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts domain Eip7702Authorization to DTO.
|
||||
*/
|
||||
private fun Eip7702Authorization.toDTO(): Eip7702AuthorizationDTO {
|
||||
return Eip7702AuthorizationDTO(
|
||||
chainId = chainId,
|
||||
address = address,
|
||||
nonce = nonce.toString(),
|
||||
yParity = yParity,
|
||||
r = r,
|
||||
s = s,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package com.tangem.data.transaction.convertes
|
||||
|
||||
import com.tangem.datasource.api.gasless.models.FeeData
|
||||
import com.tangem.datasource.api.gasless.models.TransactionData
|
||||
import com.tangem.domain.transaction.models.GaslessTransactionData
|
||||
import com.tangem.utils.converter.Converter
|
||||
import com.tangem.utils.extensions.toHexString
|
||||
import com.tangem.datasource.api.gasless.models.GaslessTransactionData as GaslessTransactionDataDTO
|
||||
|
||||
/**
|
||||
* Converts domain GaslessTransactionData to DTO for API requests.
|
||||
* Note: This converter only handles the transaction data conversion.
|
||||
* Additional fields (signature, userAddress, chainId) must be added separately
|
||||
* to create complete GaslessTransactionRequest.
|
||||
*/
|
||||
class GaslessTxDataToGaslessRequestConverter : Converter<GaslessTransactionData, GaslessTransactionDataDTO> {
|
||||
|
||||
override fun convert(value: GaslessTransactionData): GaslessTransactionDataDTO {
|
||||
return GaslessTransactionDataDTO(
|
||||
transaction = convertTransaction(value.transaction),
|
||||
fee = convertFee(value.fee),
|
||||
nonce = value.nonce.toString(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun convertTransaction(transaction: com.tangem.domain.transaction.models.Transaction): TransactionData {
|
||||
return TransactionData(
|
||||
to = transaction.to,
|
||||
value = transaction.value.toString(),
|
||||
data = transaction.data.toHexString(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun convertFee(fee: com.tangem.domain.transaction.models.Fee): FeeData {
|
||||
return FeeData(
|
||||
feeToken = fee.feeToken,
|
||||
maxTokenFee = fee.maxTokenFee.toString(),
|
||||
coinPriceInToken = fee.coinPriceInToken.toString(),
|
||||
feeTransferGasLimit = fee.feeTransferGasLimit.toString(),
|
||||
baseGas = fee.baseGas.toString(),
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue