Updated on 2026-08-14
This commit is contained in:
parent
8c8e00e7b4
commit
95b6933a14
15 changed files with 205 additions and 9 deletions
|
|
@ -1,13 +1,9 @@
|
|||
package com.tangem.tap.domain.tokens
|
||||
|
||||
import com.tangem.core.configtoggle.FeatureToggles
|
||||
import com.tangem.core.configtoggle.feature.FeatureTogglesManager
|
||||
import com.tangem.domain.tokens.TokensFeatureToggles
|
||||
|
||||
@Suppress("UnusedPrivateProperty")
|
||||
internal class DefaultTokensFeatureToggles(
|
||||
private val featureTogglesManager: FeatureTogglesManager,
|
||||
) : TokensFeatureToggles {
|
||||
|
||||
override val isDynamicAddressesEnabled: Boolean
|
||||
get() = featureTogglesManager.isFeatureEnabled(FeatureToggles.DYNAMIC_ADDRESSES_ENABLED)
|
||||
}
|
||||
) : TokensFeatureToggles
|
||||
20
domain/dynamic-addresses/build.gradle.kts
Normal file
20
domain/dynamic-addresses/build.gradle.kts
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
plugins {
|
||||
alias(deps.plugins.android.library)
|
||||
alias(deps.plugins.kotlin.android)
|
||||
id("configuration")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.tangem.domain.dynamicaddresses"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(projects.domain.core)
|
||||
api(projects.domain.dynamicAddresses.models)
|
||||
|
||||
implementation(projects.domain.models)
|
||||
|
||||
implementation(tangemDeps.blockchain) {
|
||||
exclude(module = "joda-time")
|
||||
}
|
||||
}
|
||||
7
domain/dynamic-addresses/models/build.gradle.kts
Normal file
7
domain/dynamic-addresses/models/build.gradle.kts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
plugins {
|
||||
alias(deps.plugins.kotlin.jvm)
|
||||
id("configuration")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package com.tangem.domain.dynamicaddresses.model
|
||||
|
||||
import java.math.BigDecimal
|
||||
|
||||
data class ConsolidationInfo(
|
||||
val fee: BigDecimal,
|
||||
val inputCount: Int,
|
||||
val canCoverFee: Boolean,
|
||||
)
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.tangem.domain.dynamicaddresses.model
|
||||
|
||||
import java.math.BigDecimal
|
||||
|
||||
enum class DynamicAddressesStatus {
|
||||
ENABLED,
|
||||
|
||||
DISABLED,
|
||||
|
||||
/** Enabled on backend, but local XPUB setup required (cross-device sync) */
|
||||
ENABLED_REQUIRES_SETUP,
|
||||
}
|
||||
|
||||
data class UsedAddress(
|
||||
val address: String,
|
||||
val path: String,
|
||||
val balance: BigDecimal,
|
||||
)
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package com.tangem.domain.dynamicaddresses
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.getOrElse
|
||||
import arrow.core.raise.either
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.dynamicaddresses.model.ConsolidationInfo
|
||||
import com.tangem.domain.dynamicaddresses.repository.ConsolidationRepository
|
||||
import com.tangem.domain.dynamicaddresses.repository.DynamicAddressesRepository
|
||||
|
||||
class DisableDynamicAddressesUseCase(
|
||||
private val dynamicAddressesRepository: DynamicAddressesRepository,
|
||||
private val consolidationRepository: ConsolidationRepository,
|
||||
) {
|
||||
|
||||
/**
|
||||
* Returns [ConsolidationInfo] when consolidation is required before disabling,
|
||||
* or null when DA can be disabled immediately (no non-base balances).
|
||||
*/
|
||||
suspend operator fun invoke(userWalletId: UserWalletId, network: Network): Either<Throwable, ConsolidationInfo?> =
|
||||
either {
|
||||
val hasNonBaseBalances = dynamicAddressesRepository.hasNonBaseBalances(userWalletId, network)
|
||||
|
||||
if (!hasNonBaseBalances) {
|
||||
dynamicAddressesRepository.disable(userWalletId, network)
|
||||
return@either null
|
||||
}
|
||||
|
||||
consolidationRepository.getConsolidationInfo(userWalletId, network)
|
||||
.getOrElse { raise(it) }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package com.tangem.domain.dynamicaddresses
|
||||
|
||||
interface DynamicAddressesFeatureToggles {
|
||||
|
||||
val isDynamicAddressesEnabled: Boolean
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.tangem.domain.dynamicaddresses
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.dynamicaddresses.repository.DynamicAddressesRepository
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
|
||||
class EnableDynamicAddressesUseCase(
|
||||
private val dynamicAddressesRepository: DynamicAddressesRepository,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(userWalletId: UserWalletId, network: Network, xpub: String): Either<Throwable, Unit> =
|
||||
Either.catch {
|
||||
dynamicAddressesRepository.enable(userWalletId, network, xpub)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.tangem.domain.dynamicaddresses
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.dynamicaddresses.model.ConsolidationInfo
|
||||
import com.tangem.domain.dynamicaddresses.repository.ConsolidationRepository
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
|
||||
class GetConsolidationInfoUseCase(
|
||||
private val consolidationRepository: ConsolidationRepository,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(userWalletId: UserWalletId, network: Network): Either<Throwable, ConsolidationInfo> {
|
||||
return consolidationRepository.getConsolidationInfo(userWalletId, network)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.tangem.domain.dynamicaddresses
|
||||
|
||||
import com.tangem.domain.dynamicaddresses.model.DynamicAddressesStatus
|
||||
import com.tangem.domain.dynamicaddresses.repository.DynamicAddressesRepository
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class GetDynamicAddressesStatusUseCase(
|
||||
private val dynamicAddressesRepository: DynamicAddressesRepository,
|
||||
) {
|
||||
|
||||
operator fun invoke(userWalletId: UserWalletId, network: Network): Flow<DynamicAddressesStatus> {
|
||||
return dynamicAddressesRepository.getStatus(userWalletId, network)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.tangem.domain.dynamicaddresses
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.dynamicaddresses.repository.DynamicAddressesRepository
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
|
||||
class GetDynamicReceiveAddressUseCase(
|
||||
private val dynamicAddressesRepository: DynamicAddressesRepository,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(userWalletId: UserWalletId, network: Network): Either<Throwable, String> =
|
||||
Either.catch {
|
||||
dynamicAddressesRepository.getReceiveAddress(userWalletId, network)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package com.tangem.domain.dynamicaddresses.repository
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.blockchain.common.TransactionSigner
|
||||
import com.tangem.domain.dynamicaddresses.model.ConsolidationInfo
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
|
||||
interface ConsolidationRepository {
|
||||
|
||||
suspend fun getConsolidationInfo(
|
||||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
): Either<Throwable, ConsolidationInfo>
|
||||
|
||||
suspend fun sendConsolidationTransaction(
|
||||
userWalletId: UserWalletId,
|
||||
network: Network,
|
||||
signer: TransactionSigner,
|
||||
): Either<Throwable, String>
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package com.tangem.domain.dynamicaddresses.repository
|
||||
|
||||
import com.tangem.domain.dynamicaddresses.model.DynamicAddressesStatus
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface DynamicAddressesRepository {
|
||||
|
||||
fun getStatus(userWalletId: UserWalletId, network: Network): Flow<DynamicAddressesStatus>
|
||||
|
||||
suspend fun enable(userWalletId: UserWalletId, network: Network, xpub: String)
|
||||
|
||||
suspend fun disable(userWalletId: UserWalletId, network: Network)
|
||||
|
||||
suspend fun getReceiveAddress(userWalletId: UserWalletId, network: Network): String
|
||||
|
||||
// for explorer url
|
||||
suspend fun getLastUsedReceiveAddress(userWalletId: UserWalletId, network: Network): String?
|
||||
|
||||
suspend fun hasNonBaseBalances(userWalletId: UserWalletId, network: Network): Boolean
|
||||
}
|
||||
|
|
@ -5,6 +5,4 @@ package com.tangem.domain.tokens
|
|||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface TokensFeatureToggles {
|
||||
val isDynamicAddressesEnabled: Boolean
|
||||
}
|
||||
interface TokensFeatureToggles
|
||||
|
|
@ -335,6 +335,8 @@ include(":domain:common")
|
|||
include(":domain:core")
|
||||
include(":domain:demo")
|
||||
include(":domain:demo:models")
|
||||
include(":domain:dynamic-addresses")
|
||||
include(":domain:dynamic-addresses:models")
|
||||
include(":domain:settings")
|
||||
include(":domain:tokens")
|
||||
include(":domain:tokens:models")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue