Updated on 2026-08-14
This commit is contained in:
commit
d6f9f59866
1729 changed files with 67614 additions and 9361 deletions
|
|
@ -42,7 +42,6 @@ dependencies {
|
|||
implementation(projects.domain.notifications)
|
||||
api(projects.domain.networks)
|
||||
|
||||
testRuntimeOnly(deps.test.junit5.engine)
|
||||
testImplementation(projects.common.test)
|
||||
testImplementation(projects.test.core)
|
||||
testImplementation(projects.test.mock)
|
||||
|
|
|
|||
|
|
@ -4,10 +4,7 @@
|
|||
<CurrentIssues>
|
||||
<ID>BooleanPropertyNaming:SendTransactionUseCase.kt$SendTransactionUseCase$val linkedTerminal = cardSdkConfigRepository.isLinkedTerminal()</ID>
|
||||
<ID>BooleanPropertyNaming:ValidateWalletAddressUseCase.kt$ValidateWalletAddressUseCase$val current = isCurrentAddress(addressToValidate)</ID>
|
||||
<ID>MultilineLambdaItParameter:AssociateAssetUseCase.kt$AssociateAssetUseCase${ val network = currency.network it.network.id == network.id && it.network.derivationPath == network.derivationPath }</ID>
|
||||
<ID>NamedArguments:SendTransactionUseCase.kt$SendTransactionUseCase$invoke(listOf(txData), userWallet, network, TransactionSender.MultipleTransactionSendMode.DEFAULT)</ID>
|
||||
<ID>NamedArguments:ValidateWalletAddressUseCase.kt$ValidateWalletAddressUseCase$validateAddressInternal( userWalletId, network, address, isCurrentAddress = { toValidate -> currencyAddresses?.any { it.value == toValidate } ?: true }, )</ID>
|
||||
<ID>NamedArguments:ValidateWalletAddressUseCase.kt$ValidateWalletAddressUseCase$validateAddressInternal( userWalletId, network, address, isCurrentAddress = { toValidate -> senderAddresses.any { it.address == toValidate } }, )</ID>
|
||||
<ID>NullableBooleanCheck:ValidateWalletAddressUseCase.kt$ValidateWalletAddressUseCase$currencyAddresses?.any { it.value == toValidate } ?: true</ID>
|
||||
<ID>UnnecessaryLet:RetryIncompleteTransactionUseCase.kt$RetryIncompleteTransactionUseCase$let { raise(IncompleteTransactionError.SendError(it)) }</ID>
|
||||
</CurrentIssues>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<?xml version="1.0" ?>
|
||||
<SmellBaseline>
|
||||
<ManuallySuppressedIssues/>
|
||||
<CurrentIssues>
|
||||
<ID>NullableToStringCall:SendTransactionError.kt$SendTransactionError$$code</ID>
|
||||
</CurrentIssues>
|
||||
<CurrentIssues/>
|
||||
</SmellBaseline>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ sealed class GetFeeError {
|
|||
data object TronActivationError : BlockchainErrors()
|
||||
data object KaspaZeroUtxo : BlockchainErrors()
|
||||
data object SuiOneCoinRequired : BlockchainErrors()
|
||||
data object TooLargeSolanaTransactionError : BlockchainErrors()
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -19,4 +20,15 @@ sealed class GetFeeError {
|
|||
data object NotEnoughFunds : GaslessError()
|
||||
data class DataError(val cause: Throwable?) : GaslessError()
|
||||
}
|
||||
|
||||
/**
|
||||
* Error for gas estimation with state override for ethereum like networks.
|
||||
* Specifically overriding approval slot.
|
||||
*/
|
||||
data class EstimateOverrideError(
|
||||
val blockchain: String,
|
||||
val tokenSymbol: String,
|
||||
val rpcProvider: String,
|
||||
val error: String,
|
||||
) : GetFeeError()
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ import com.tangem.domain.transaction.error.SendTransactionError.Companion.USER_C
|
|||
import com.tangem.sdk.extensions.localizedDescriptionRes
|
||||
|
||||
fun Result.Failure.mapToFeeError(): GetFeeError {
|
||||
return when (this.error) {
|
||||
return when (val gasError = error) {
|
||||
is BlockchainSdkError.Tron.AccountActivationError -> {
|
||||
GetFeeError.BlockchainErrors.TronActivationError
|
||||
}
|
||||
|
|
@ -19,7 +19,15 @@ fun Result.Failure.mapToFeeError(): GetFeeError {
|
|||
is BlockchainSdkError.Sui.OneSuiRequired -> {
|
||||
GetFeeError.BlockchainErrors.SuiOneCoinRequired
|
||||
}
|
||||
else -> GetFeeError.DataError(this.error)
|
||||
is BlockchainSdkError.Ethereum.EstimateOverrideError -> {
|
||||
GetFeeError.EstimateOverrideError(
|
||||
blockchain = gasError.blockchain,
|
||||
tokenSymbol = gasError.tokenSymbol,
|
||||
rpcProvider = gasError.rpcProvider,
|
||||
error = gasError.underlyingError,
|
||||
)
|
||||
}
|
||||
else -> GetFeeError.DataError(error)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ class GetEthSpecificFeeUseCase(
|
|||
val minimalFee = getEthLegacyFee(
|
||||
gasPrice = gasPriceResult,
|
||||
gasLimit = gasLimit,
|
||||
decimals = cryptoCurrency.decimals,
|
||||
decimals = blockchain.decimals(),
|
||||
blockchain = blockchain,
|
||||
)
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ class GetEthSpecificFeeUseCase(
|
|||
val normalFee = getEthLegacyFee(
|
||||
gasPrice = normalGasPrice,
|
||||
gasLimit = gasLimit,
|
||||
decimals = cryptoCurrency.decimals,
|
||||
decimals = blockchain.decimals(),
|
||||
blockchain = blockchain,
|
||||
)
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ class GetEthSpecificFeeUseCase(
|
|||
val priorityFee = getEthLegacyFee(
|
||||
gasPrice = priorityGasPrice,
|
||||
gasLimit = gasLimit,
|
||||
decimals = cryptoCurrency.decimals,
|
||||
decimals = blockchain.decimals(),
|
||||
blockchain = blockchain,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.domain.transaction.usecase
|
|||
|
||||
import arrow.core.raise.catch
|
||||
import arrow.core.raise.either
|
||||
import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager
|
||||
import com.tangem.blockchain.blockchains.ethereum.EthereumTransactionExtras
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.AmountType
|
||||
|
|
@ -35,7 +36,13 @@ class GetFeeUseCase(
|
|||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val demoConfig: DemoConfig,
|
||||
) {
|
||||
suspend operator fun invoke(userWallet: UserWallet, network: Network, transactionData: TransactionData) = either {
|
||||
suspend operator fun invoke(
|
||||
userWallet: UserWallet,
|
||||
network: Network,
|
||||
transactionData: TransactionData,
|
||||
spenderAddress: String? = null,
|
||||
isSimulateEstimation: Boolean = false,
|
||||
) = either {
|
||||
catch(
|
||||
block = {
|
||||
val transactionSender = if (userWallet is UserWallet.Cold &&
|
||||
|
|
@ -48,8 +55,17 @@ class GetFeeUseCase(
|
|||
network = network,
|
||||
)
|
||||
}
|
||||
val result = transactionSender?.getFee(transactionData = transactionData)
|
||||
?: error("Fee is null")
|
||||
val isEthereumWalletManager = transactionSender is EthereumWalletManager
|
||||
val result = if (isSimulateEstimation && spenderAddress != null && isEthereumWalletManager) {
|
||||
transactionSender.estimateFeeWithOverride(
|
||||
transactionData = transactionData,
|
||||
spenderAddress = spenderAddress,
|
||||
isSimulate = true,
|
||||
)
|
||||
} else {
|
||||
transactionSender?.getFee(transactionData = transactionData)
|
||||
?: error("Fee is null")
|
||||
}
|
||||
|
||||
val maybeFee = when (result) {
|
||||
is Result.Success -> result.data
|
||||
|
|
|
|||
|
|
@ -199,7 +199,6 @@ class CreateAndSendGaslessTransactionUseCase(
|
|||
(context.walletManager as? PendingTransactionHandler)?.addPendingGaslessTransaction(
|
||||
transactionData = transactionData,
|
||||
txHash = txHash,
|
||||
contractAddress = transactionData.contractAddress,
|
||||
)
|
||||
|
||||
return txHash
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
package com.tangem.domain.transaction.error
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.tangem.blockchain.common.BlockchainSdkError
|
||||
import com.tangem.blockchain.extensions.Result
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
* Tests for [mapToFeeError] — the [Result.Failure] -> [GetFeeError] mapper. Focuses on the
|
||||
* [REDACTED_TASK_KEY] addition: [BlockchainSdkError.Ethereum.EstimateOverrideError] must be mapped to
|
||||
* [GetFeeError.EstimateOverrideError] field-by-field; all other errors fall through to
|
||||
* [GetFeeError.DataError].
|
||||
*/
|
||||
internal class ErrorsMapperTest {
|
||||
|
||||
@Test
|
||||
fun `GIVEN EstimateOverrideError THEN maps to GetFeeError EstimateOverrideError field by field`() {
|
||||
val sdkError = BlockchainSdkError.Ethereum.EstimateOverrideError(
|
||||
blockchain = "ethereum",
|
||||
tokenSymbol = "USDT",
|
||||
rpcProvider = "infura",
|
||||
underlyingError = "execution reverted",
|
||||
)
|
||||
|
||||
val result = Result.Failure(sdkError).mapToFeeError()
|
||||
|
||||
assertThat(result).isInstanceOf(GetFeeError.EstimateOverrideError::class.java)
|
||||
val mapped = result as GetFeeError.EstimateOverrideError
|
||||
assertThat(mapped.blockchain).isEqualTo("ethereum")
|
||||
assertThat(mapped.tokenSymbol).isEqualTo("USDT")
|
||||
assertThat(mapped.rpcProvider).isEqualTo("infura")
|
||||
assertThat(mapped.error).isEqualTo("execution reverted")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN TronActivationError THEN maps to TronActivationError`() {
|
||||
// AccountActivationError is a class taking an int code, not an object.
|
||||
val result = Result.Failure(BlockchainSdkError.Tron.AccountActivationError(code = 0)).mapToFeeError()
|
||||
|
||||
assertThat(result).isEqualTo(GetFeeError.BlockchainErrors.TronActivationError)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN KaspaZeroUtxoError THEN maps to KaspaZeroUtxo`() {
|
||||
val result = Result.Failure(BlockchainSdkError.Kaspa.ZeroUtxoError).mapToFeeError()
|
||||
|
||||
assertThat(result).isEqualTo(GetFeeError.BlockchainErrors.KaspaZeroUtxo)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN SuiOneSuiRequired THEN maps to SuiOneCoinRequired`() {
|
||||
val result = Result.Failure(BlockchainSdkError.Sui.OneSuiRequired).mapToFeeError()
|
||||
|
||||
assertThat(result).isEqualTo(GetFeeError.BlockchainErrors.SuiOneCoinRequired)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN unknown error THEN maps to DataError`() {
|
||||
val sdkError = BlockchainSdkError.CustomError("boom")
|
||||
|
||||
val result = Result.Failure(sdkError).mapToFeeError()
|
||||
|
||||
assertThat(result).isInstanceOf(GetFeeError.DataError::class.java)
|
||||
assertThat((result as GetFeeError.DataError).cause).isEqualTo(sdkError)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
package com.tangem.domain.transaction.usecase
|
||||
|
||||
import arrow.core.right
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.tangem.blockchain.blockchains.ethereum.EthereumTransactionExtras
|
||||
import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager
|
||||
import com.tangem.blockchain.common.*
|
||||
import com.tangem.blockchain.common.smartcontract.SmartContractCallData
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
|
|
@ -17,48 +19,185 @@ import com.tangem.domain.transaction.error.GetFeeError
|
|||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import io.mockk.*
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.math.BigDecimal
|
||||
import java.math.BigInteger
|
||||
|
||||
/**
|
||||
* Unit tests for [GetFeeUseCase].
|
||||
*
|
||||
* Focus is the Yield Mode gas-limit logic introduced on this branch
|
||||
* (uncompiled Ethereum transactions whose call data is [EthereumYieldSupplySendCallData]
|
||||
* get their gas limit increased by 40%), plus error mapping, null/exception handling,
|
||||
* demo card routing, and crypto-currency-to-amount conversion in the second overload.
|
||||
* Covers two orthogonal pieces of the compiled-transaction overload:
|
||||
* - The fee-source selection that chooses between the simulated `estimateFeeWithOverride` path and the legacy
|
||||
* `getFee` path. The simulated estimation is selected only when ALL of these hold:
|
||||
* - [GetFeeUseCase.invoke] is called with `isSimulateEstimation = true`
|
||||
* - `spenderAddress != null`
|
||||
* - the resolved transaction sender is an [EthereumWalletManager]
|
||||
* - The Yield Mode gas-limit logic: uncompiled Ethereum transactions whose call data is
|
||||
* [EthereumYieldSupplySendCallData] get their gas limit increased by 40%.
|
||||
*
|
||||
* Plus error mapping, null/exception handling, demo card routing, and crypto-currency-to-amount conversion in the
|
||||
* second overload.
|
||||
*/
|
||||
class GetFeeUseCaseTest {
|
||||
internal class GetFeeUseCaseTest {
|
||||
|
||||
private lateinit var walletManagersFacade: WalletManagersFacade
|
||||
private lateinit var demoConfig: DemoConfig
|
||||
private lateinit var useCase: GetFeeUseCase
|
||||
private val walletManagersFacade: WalletManagersFacade = mockk()
|
||||
private val demoConfig: DemoConfig = mockk()
|
||||
|
||||
private lateinit var walletManager: WalletManager
|
||||
private lateinit var network: Network
|
||||
private lateinit var userWallet: UserWallet.Hot
|
||||
private lateinit var userWalletId: UserWalletId
|
||||
private val useCase = GetFeeUseCase(
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
demoConfig = demoConfig,
|
||||
)
|
||||
|
||||
@Before
|
||||
private val network: Network = mockk(relaxed = true)
|
||||
private val userWalletId = UserWalletId(stringValue = "deadbeef")
|
||||
private val userWallet: UserWallet.Hot = mockk(relaxed = true) {
|
||||
every { walletId } returns userWalletId
|
||||
}
|
||||
|
||||
private val walletManager: WalletManager = mockk()
|
||||
private val ethereumWalletManager: EthereumWalletManager = mockk()
|
||||
private val plainWalletManager: WalletManager = mockk()
|
||||
|
||||
private val transactionData: TransactionData = mockk(relaxed = true)
|
||||
private val expectedFee: TransactionFee = mockk(relaxed = true)
|
||||
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
walletManagersFacade = mockk()
|
||||
demoConfig = mockk()
|
||||
useCase = GetFeeUseCase(walletManagersFacade, demoConfig)
|
||||
|
||||
walletManager = mockk()
|
||||
network = mockk()
|
||||
userWalletId = mockk()
|
||||
userWallet = mockk<UserWallet.Hot>()
|
||||
|
||||
every { demoConfig.isDemoCardId(any()) } returns false
|
||||
every { userWallet.walletId } returns userWalletId
|
||||
coEvery {
|
||||
walletManagersFacade.getOrCreateWalletManager(userWalletId, network)
|
||||
} returns walletManager
|
||||
}
|
||||
|
||||
// region invoke(userWallet, network, transactionData, spenderAddress, isSimulateEstimation) — fee-source selection
|
||||
|
||||
@Test
|
||||
fun `GIVEN simulate + spender + ethereum manager THEN estimateFee is used`() = runTest {
|
||||
coEvery {
|
||||
walletManagersFacade.getOrCreateWalletManager(userWalletId, network)
|
||||
} returns ethereumWalletManager
|
||||
coEvery {
|
||||
ethereumWalletManager.estimateFeeWithOverride(
|
||||
transactionData = transactionData,
|
||||
spenderAddress = SPENDER,
|
||||
isSimulate = true,
|
||||
)
|
||||
} returns Result.Success(expectedFee)
|
||||
|
||||
val result = useCase(
|
||||
userWallet = userWallet,
|
||||
network = network,
|
||||
transactionData = transactionData,
|
||||
spenderAddress = SPENDER,
|
||||
isSimulateEstimation = true,
|
||||
)
|
||||
|
||||
assertThat(result).isEqualTo(expectedFee.right())
|
||||
coVerify(exactly = 1) {
|
||||
ethereumWalletManager.estimateFeeWithOverride(
|
||||
transactionData = transactionData,
|
||||
spenderAddress = SPENDER,
|
||||
isSimulate = true,
|
||||
)
|
||||
}
|
||||
coVerify(exactly = 0) { ethereumWalletManager.getFee(transactionData = transactionData) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN simulate false THEN legacy getFee is used even for ethereum manager`() = runTest {
|
||||
coEvery {
|
||||
walletManagersFacade.getOrCreateWalletManager(userWalletId, network)
|
||||
} returns ethereumWalletManager
|
||||
coEvery { ethereumWalletManager.getFee(transactionData = transactionData) } returns
|
||||
Result.Success(expectedFee)
|
||||
|
||||
val result = useCase(
|
||||
userWallet = userWallet,
|
||||
network = network,
|
||||
transactionData = transactionData,
|
||||
spenderAddress = SPENDER,
|
||||
isSimulateEstimation = false,
|
||||
)
|
||||
|
||||
assertThat(result).isEqualTo(expectedFee.right())
|
||||
coVerify(exactly = 1) { ethereumWalletManager.getFee(transactionData = transactionData) }
|
||||
coVerify(exactly = 0) {
|
||||
ethereumWalletManager.estimateFeeWithOverride(
|
||||
transactionData = any(),
|
||||
spenderAddress = any(),
|
||||
isSimulate = any(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN null spender THEN legacy getFee is used even when simulate true`() = runTest {
|
||||
coEvery {
|
||||
walletManagersFacade.getOrCreateWalletManager(userWalletId, network)
|
||||
} returns ethereumWalletManager
|
||||
coEvery { ethereumWalletManager.getFee(transactionData = transactionData) } returns
|
||||
Result.Success(expectedFee)
|
||||
|
||||
val result = useCase(
|
||||
userWallet = userWallet,
|
||||
network = network,
|
||||
transactionData = transactionData,
|
||||
spenderAddress = null,
|
||||
isSimulateEstimation = true,
|
||||
)
|
||||
|
||||
assertThat(result).isEqualTo(expectedFee.right())
|
||||
coVerify(exactly = 1) { ethereumWalletManager.getFee(transactionData = transactionData) }
|
||||
coVerify(exactly = 0) {
|
||||
ethereumWalletManager.estimateFeeWithOverride(
|
||||
transactionData = any(),
|
||||
spenderAddress = any(),
|
||||
isSimulate = any(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN non-ethereum manager THEN legacy getFee is used even when simulate plus spender`() = runTest {
|
||||
coEvery {
|
||||
walletManagersFacade.getOrCreateWalletManager(userWalletId, network)
|
||||
} returns plainWalletManager
|
||||
coEvery { plainWalletManager.getFee(transactionData = transactionData) } returns
|
||||
Result.Success(expectedFee)
|
||||
|
||||
val result = useCase(
|
||||
userWallet = userWallet,
|
||||
network = network,
|
||||
transactionData = transactionData,
|
||||
spenderAddress = SPENDER,
|
||||
isSimulateEstimation = true,
|
||||
)
|
||||
|
||||
assertThat(result).isEqualTo(expectedFee.right())
|
||||
coVerify(exactly = 1) { plainWalletManager.getFee(transactionData = transactionData) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `GIVEN getFee returns failure THEN error is mapped to GetFeeError`() = runTest {
|
||||
val failure = Result.Failure(BlockchainSdkError.CustomError("boom"))
|
||||
coEvery {
|
||||
walletManagersFacade.getOrCreateWalletManager(userWalletId, network)
|
||||
} returns plainWalletManager
|
||||
coEvery { plainWalletManager.getFee(transactionData = transactionData) } returns failure
|
||||
|
||||
val result = useCase(
|
||||
userWallet = userWallet,
|
||||
network = network,
|
||||
transactionData = transactionData,
|
||||
)
|
||||
|
||||
assertThat(result.isLeft()).isTrue()
|
||||
assertThat(result.leftOrNull()).isInstanceOf(GetFeeError.DataError::class.java)
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region invoke(userWallet, network, transactionData) — Yield Mode gas-limit logic
|
||||
|
||||
@Test
|
||||
|
|
@ -475,4 +614,8 @@ class GetFeeUseCaseTest {
|
|||
}
|
||||
|
||||
// endregion
|
||||
|
||||
private companion object {
|
||||
const val SPENDER = "0xSpender"
|
||||
}
|
||||
}
|
||||
|
|
@ -18,9 +18,9 @@ import io.mockk.mockk
|
|||
import io.mockk.mockkObject
|
||||
import io.mockk.unmockkObject
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
internal class ValidateWalletAddressUseCaseTest {
|
||||
|
||||
|
|
@ -34,14 +34,14 @@ internal class ValidateWalletAddressUseCaseTest {
|
|||
private val userWalletId: UserWalletId = mockk()
|
||||
private val network: Network = mockk()
|
||||
|
||||
@Before
|
||||
@BeforeEach
|
||||
fun setUp() {
|
||||
mockkObject(BlockchainUtils)
|
||||
every { BlockchainUtils.decodeRippleXAddress(any(), any()) } returns null
|
||||
every { network.rawId } returns "ethereum"
|
||||
}
|
||||
|
||||
@After
|
||||
@AfterEach
|
||||
fun tearDown() {
|
||||
unmockkObject(BlockchainUtils)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,9 +22,9 @@ import io.mockk.coVerify
|
|||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.jupiter.api.Assertions.*
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.math.BigDecimal
|
||||
import java.math.BigInteger
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ class TokenFeeCalculatorTest {
|
|||
private lateinit var mockUserWalletId: UserWalletId
|
||||
private lateinit var mockTransactionData: TransactionData
|
||||
|
||||
@Before
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
walletManagersFacade = mockk()
|
||||
gaslessTransactionRepository = mockk()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue