From 68c7028380c4c1c2bcf46f7a526311f5684d8960 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 22 May 2025 15:49:27 +0400 Subject: [PATCH] Updated on 2026-08-14 --- .../data/common/network/NetworkFactory.kt | 339 +++++++++++++ .../data/common/network/NetworkFactoryTest.kt | 468 ++++++++++++++++++ 2 files changed, 807 insertions(+) create mode 100644 data/common/src/main/kotlin/com/tangem/data/common/network/NetworkFactory.kt create mode 100644 data/common/src/test/kotlin/com/tangem/data/common/network/NetworkFactoryTest.kt diff --git a/data/common/src/main/kotlin/com/tangem/data/common/network/NetworkFactory.kt b/data/common/src/main/kotlin/com/tangem/data/common/network/NetworkFactory.kt new file mode 100644 index 0000000000..5f57691f92 --- /dev/null +++ b/data/common/src/main/kotlin/com/tangem/data/common/network/NetworkFactory.kt @@ -0,0 +1,339 @@ +package com.tangem.data.common.network + +import androidx.annotation.VisibleForTesting +import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchain.common.FeePaidCurrency +import com.tangem.blockchainsdk.utils.ExcludedBlockchains +import com.tangem.blockchainsdk.utils.toNetworkId +import com.tangem.data.common.currency.getBlockchain +import com.tangem.domain.common.DerivationStyleProvider +import com.tangem.domain.common.extensions.canHandleToken +import com.tangem.domain.common.util.cardTypesResolver +import com.tangem.domain.common.util.derivationStyleProvider +import com.tangem.domain.models.network.Network +import com.tangem.domain.models.scan.ScanResponse +import timber.log.Timber +import javax.inject.Inject + +/** + * Factory for creating [Network] + * + * @property excludedBlockchains excluded blockchains + * +[REDACTED_AUTHOR] + */ +class NetworkFactory @Inject constructor( + private val excludedBlockchains: ExcludedBlockchains, +) { + + /** + * Create + * + * @param blockchain blockchain + * @param extraDerivationPath extra derivation path + * @param scanResponse scan response + */ + fun create(blockchain: Blockchain, extraDerivationPath: String?, scanResponse: ScanResponse): Network? { + return create( + blockchain = blockchain, + derivationPath = createDerivationPath( + blockchain = blockchain, + extraDerivationPath = extraDerivationPath, + cardDerivationStyleProvider = scanResponse.derivationStyleProvider, + ), + canHandleTokens = scanResponse.card.canHandleToken( + blockchain = blockchain, + cardTypesResolver = scanResponse.cardTypesResolver, + excludedBlockchains = excludedBlockchains, + ), + ) + } + + /** + * Create + * + * @param networkId network id + * @param derivationPath derivation path + * @param scanResponse scan response + */ + fun create(networkId: Network.ID, derivationPath: Network.DerivationPath, scanResponse: ScanResponse): Network? { + val blockchain = getBlockchain(networkId) + + return create( + blockchain = blockchain, + derivationPath = derivationPath, + canHandleTokens = scanResponse.card.canHandleToken( + blockchain = blockchain, + cardTypesResolver = scanResponse.cardTypesResolver, + excludedBlockchains = excludedBlockchains, + ), + ) + } + + /** + * Create + * + * @param blockchain blockchain + * @param extraDerivationPath extra derivation path + * @param derivationStyleProvider derivation style provider + * @param canHandleTokens flag that indicates whether the network can handle tokens + */ + fun create( + blockchain: Blockchain, + extraDerivationPath: String?, + derivationStyleProvider: DerivationStyleProvider?, + canHandleTokens: Boolean, + ): Network? { + return create( + blockchain = blockchain, + derivationPath = createDerivationPath( + blockchain = blockchain, + extraDerivationPath = extraDerivationPath, + cardDerivationStyleProvider = derivationStyleProvider, + ), + canHandleTokens = canHandleTokens, + ) + } + + private fun create( + blockchain: Blockchain, + derivationPath: Network.DerivationPath, + canHandleTokens: Boolean, + ): Network? { + if (!blockchain.isBlockchainSupported()) return null + + return runCatching { + Network( + id = Network.ID(value = blockchain.id, derivationPath = derivationPath), + backendId = blockchain.toNetworkId(), + name = blockchain.fullName, + isTestnet = blockchain.isTestnet(), + derivationPath = derivationPath, + currencySymbol = blockchain.currency, + standardType = getNetworkStandardType(blockchain), + hasFiatFeeRate = blockchain.feePaidCurrency() !is FeePaidCurrency.FeeResource, + canHandleTokens = canHandleTokens, + transactionExtrasType = blockchain.getSupportedTransactionExtras(), + ) + } + .getOrNull() + } + + private fun Blockchain.isBlockchainSupported(): Boolean { + if (this == Blockchain.Unknown) { + Timber.w("Unable to convert Unknown blockchain to the domain network model") + return false + } + if (this in excludedBlockchains) { + Timber.w("Unable to convert excluded blockchain to the domain network model") + return false + } + + return true + } + + private fun createDerivationPath( + blockchain: Blockchain, + extraDerivationPath: String?, + cardDerivationStyleProvider: DerivationStyleProvider?, + ): Network.DerivationPath { + if (cardDerivationStyleProvider == null) return Network.DerivationPath.None + + val defaultDerivationPath = getDefaultDerivationPath(blockchain, cardDerivationStyleProvider) + + return if (extraDerivationPath.isNullOrBlank()) { + if (defaultDerivationPath.isNullOrBlank()) { + Network.DerivationPath.None + } else { + Network.DerivationPath.Card(defaultDerivationPath) + } + } else { + if (extraDerivationPath == defaultDerivationPath) { + Network.DerivationPath.Card(defaultDerivationPath) + } else { + Network.DerivationPath.Custom(extraDerivationPath) + } + } + } + + private fun getDefaultDerivationPath( + blockchain: Blockchain, + derivationStyleProvider: DerivationStyleProvider, + ): String? { + return blockchain.derivationPath(derivationStyleProvider.getDerivationStyle())?.rawPath + } + + private fun getNetworkStandardType(blockchain: Blockchain): Network.StandardType { + return when (blockchain) { + Blockchain.Ethereum, Blockchain.EthereumTestnet -> Network.StandardType.ERC20 + Blockchain.BSC, Blockchain.BSCTestnet -> Network.StandardType.BEP20 + Blockchain.Binance, Blockchain.BinanceTestnet -> Network.StandardType.BEP2 + Blockchain.Tron, Blockchain.TronTestnet -> Network.StandardType.TRC20 + else -> Network.StandardType.Unspecified(blockchain.name) + } + } + + @Suppress("LongMethod") + private fun Blockchain.getSupportedTransactionExtras(): Network.TransactionExtrasType { + return when (this) { + Blockchain.XRP -> Network.TransactionExtrasType.DESTINATION_TAG + Blockchain.Binance, + Blockchain.TON, + Blockchain.Cosmos, + Blockchain.TerraV1, + Blockchain.TerraV2, + Blockchain.Stellar, + Blockchain.Hedera, + Blockchain.Algorand, + Blockchain.Sei, + Blockchain.InternetComputer, + Blockchain.Casper, + -> Network.TransactionExtrasType.MEMO + // region Other blockchains + Blockchain.Unknown, + Blockchain.Alephium, + Blockchain.AlephiumTestnet, + Blockchain.Arbitrum, + Blockchain.ArbitrumTestnet, + Blockchain.Avalanche, + Blockchain.AvalancheTestnet, + Blockchain.BinanceTestnet, + Blockchain.BSC, + Blockchain.BSCTestnet, + Blockchain.Bitcoin, + Blockchain.BitcoinTestnet, + Blockchain.BitcoinCash, + Blockchain.BitcoinCashTestnet, + Blockchain.Cardano, + Blockchain.CosmosTestnet, + Blockchain.Dogecoin, + Blockchain.Ducatus, + Blockchain.Ethereum, + Blockchain.EthereumTestnet, + Blockchain.EthereumClassic, + Blockchain.EthereumClassicTestnet, + Blockchain.Fantom, + Blockchain.FantomTestnet, + Blockchain.Litecoin, + Blockchain.Near, + Blockchain.NearTestnet, + Blockchain.Polkadot, + Blockchain.PolkadotTestnet, + Blockchain.Kava, + Blockchain.KavaTestnet, + Blockchain.Kusama, + Blockchain.Polygon, + Blockchain.PolygonTestnet, + Blockchain.RSK, + Blockchain.SeiTestnet, + Blockchain.StellarTestnet, + Blockchain.Solana, + Blockchain.SolanaTestnet, + Blockchain.Tezos, + Blockchain.Tron, + Blockchain.TronTestnet, + Blockchain.Gnosis, + Blockchain.Dash, + Blockchain.Optimism, + Blockchain.OptimismTestnet, + Blockchain.Dischain, + Blockchain.EthereumPow, + Blockchain.EthereumPowTestnet, + Blockchain.Kaspa, + Blockchain.KaspaTestnet, + Blockchain.Telos, + Blockchain.TelosTestnet, + Blockchain.TONTestnet, + Blockchain.Ravencoin, + Blockchain.Clore, + Blockchain.RavencoinTestnet, + Blockchain.Cronos, + Blockchain.AlephZero, + Blockchain.AlephZeroTestnet, + Blockchain.OctaSpace, + Blockchain.OctaSpaceTestnet, + Blockchain.Chia, + Blockchain.ChiaTestnet, + Blockchain.Decimal, + Blockchain.DecimalTestnet, + Blockchain.XDC, + Blockchain.XDCTestnet, + Blockchain.VeChain, + Blockchain.VeChainTestnet, + Blockchain.Aptos, + Blockchain.AptosTestnet, + Blockchain.Playa3ull, + Blockchain.Shibarium, + Blockchain.ShibariumTestnet, + Blockchain.AlgorandTestnet, + Blockchain.HederaTestnet, + Blockchain.Aurora, + Blockchain.AuroraTestnet, + Blockchain.Areon, + Blockchain.AreonTestnet, + Blockchain.PulseChain, + Blockchain.PulseChainTestnet, + Blockchain.ZkSyncEra, + Blockchain.ZkSyncEraTestnet, + Blockchain.Nexa, + Blockchain.NexaTestnet, + Blockchain.Moonbeam, + Blockchain.MoonbeamTestnet, + Blockchain.Manta, + Blockchain.MantaTestnet, + Blockchain.PolygonZkEVM, + Blockchain.PolygonZkEVMTestnet, + Blockchain.Radiant, + Blockchain.Fact0rn, + Blockchain.Base, + Blockchain.BaseTestnet, + Blockchain.Moonriver, + Blockchain.MoonriverTestnet, + Blockchain.Mantle, + Blockchain.MantleTestnet, + Blockchain.Flare, + Blockchain.FlareTestnet, + Blockchain.Taraxa, + Blockchain.TaraxaTestnet, + Blockchain.Koinos, + Blockchain.KoinosTestnet, + Blockchain.Joystream, + Blockchain.Bittensor, + Blockchain.Filecoin, + Blockchain.Blast, + Blockchain.BlastTestnet, + Blockchain.Cyber, + Blockchain.CyberTestnet, + Blockchain.Sui, + Blockchain.SuiTestnet, + Blockchain.EnergyWebChain, + Blockchain.EnergyWebChainTestnet, + Blockchain.EnergyWebX, + Blockchain.EnergyWebXTestnet, + Blockchain.CasperTestnet, + Blockchain.Core, + Blockchain.CoreTestnet, + Blockchain.Xodex, + Blockchain.Canxium, + Blockchain.Chiliz, + Blockchain.ChilizTestnet, + Blockchain.VanarChain, + Blockchain.VanarChainTestnet, + Blockchain.OdysseyChain, Blockchain.OdysseyChainTestnet, + Blockchain.Bitrock, Blockchain.BitrockTestnet, + Blockchain.Sonic, Blockchain.SonicTestnet, + Blockchain.ApeChain, Blockchain.ApeChainTestnet, + Blockchain.Scroll, Blockchain.ScrollTestnet, + Blockchain.ZkLinkNova, Blockchain.ZkLinkNovaTestnet, + Blockchain.Pepecoin, Blockchain.PepecoinTestnet, + -> Network.TransactionExtrasType.NONE + // endregion + } + } + + @VisibleForTesting(otherwise = VisibleForTesting.NONE) + fun createNetworkStandardType(blockchain: Blockchain) = getNetworkStandardType(blockchain) + + @VisibleForTesting(otherwise = VisibleForTesting.NONE) + fun createSupportedTransactionExtras(blockchain: Blockchain) = blockchain.getSupportedTransactionExtras() +} \ No newline at end of file diff --git a/data/common/src/test/kotlin/com/tangem/data/common/network/NetworkFactoryTest.kt b/data/common/src/test/kotlin/com/tangem/data/common/network/NetworkFactoryTest.kt new file mode 100644 index 0000000000..12de89dfc7 --- /dev/null +++ b/data/common/src/test/kotlin/com/tangem/data/common/network/NetworkFactoryTest.kt @@ -0,0 +1,468 @@ +package com.tangem.data.common.network + +import com.google.common.truth.Truth +import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchainsdk.utils.ExcludedBlockchains +import com.tangem.common.test.domain.card.MockScanResponseFactory +import com.tangem.common.test.domain.token.MockCryptoCurrencyFactory +import com.tangem.common.test.utils.ProvideTestModels +import com.tangem.domain.common.DerivationStyleProvider +import com.tangem.domain.common.configs.GenericCardConfig +import com.tangem.domain.common.configs.MultiWalletCardConfig +import com.tangem.domain.common.util.derivationStyleProvider +import com.tangem.domain.models.network.Network +import com.tangem.domain.models.scan.ScanResponse +import io.mockk.every +import io.mockk.mockk +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import org.junit.jupiter.params.ParameterizedTest + +/** +[REDACTED_AUTHOR] + */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class NetworkFactoryTest { + + private val networkFactory = NetworkFactory(excludedBlockchains = ExcludedBlockchains()) + + @Nested + @TestInstance(TestInstance.Lifecycle.PER_CLASS) + inner class Create { + + @Test + fun `create if blockchain is excluded`() { + // Arrange + val excludedBlockchains = mockk() + val networkFactory = NetworkFactory(excludedBlockchains = excludedBlockchains) + + every { any() in excludedBlockchains } returns true + + // Act + val actual = networkFactory.create( + blockchain = Blockchain.Ethereum, + extraDerivationPath = null, + scanResponse = createMultiWalletScanResponse(), + ) + + // Assert + Truth.assertThat(actual).isNull() + } + + @ParameterizedTest + @ProvideTestModels + fun create(model: CreateTestModel) { + // Act + val actual = when (model) { + is CreateTestModel.First -> { + networkFactory.create( + blockchain = model.blockchain, + extraDerivationPath = model.extraDerivationPath, + scanResponse = model.scanResponse, + ) + } + is CreateTestModel.Second -> { + networkFactory.create( + networkId = model.networkId, + derivationPath = model.derivationPath, + scanResponse = model.scanResponse, + ) + } + is CreateTestModel.Third -> { + networkFactory.create( + blockchain = model.blockchain, + extraDerivationPath = model.extraDerivationPath, + derivationStyleProvider = model.derivationStyleProvider, + canHandleTokens = model.canHandleTokens, + ) + } + } + + // Assert + Truth.assertThat(actual).isEqualTo(model.expected) + } + + @Suppress("unused") + private fun provideTestModels() = listOf( + // region create(blockchain: Blockchain, extraDerivationPath: String?, scanResponse: ScanResponse) + CreateTestModel.First( + blockchain = Blockchain.Unknown, + extraDerivationPath = null, // never-mind + scanResponse = createMultiWalletScanResponse(), // never-mind + expected = null, + ), + createFirst( + extraDerivationPath = null, + scanResponse = createGenericScanResponse(), // default derivation path is null + expectedDerivationPath = Network.DerivationPath.None, + ), + createFirst( + extraDerivationPath = null, + scanResponse = createMultiWalletScanResponse(), + expectedDerivationPath = Network.DerivationPath.Card(value = "m/44'/60'/0'/0/0"), // use default + ), + createFirst( + extraDerivationPath = "m/44'/60'/0'/0/0", // as default + scanResponse = createMultiWalletScanResponse(), + expectedDerivationPath = Network.DerivationPath.Card(value = "m/44'/60'/0'/0/0"), + ), + createFirst( + extraDerivationPath = "m/84'/0'/0'/0/0", + scanResponse = createMultiWalletScanResponse(), + expectedDerivationPath = Network.DerivationPath.Custom(value = "m/84'/0'/0'/0/0"), + ), + // endregion + + // region create(networkId: Network.ID, derivationPath: Network.DerivationPath, scanResponse: ScanResponse) + CreateTestModel.Second( + networkId = Network.ID(value = "1", derivationPath = Network.DerivationPath.None), + derivationPath = Network.DerivationPath.None, // never-mind + scanResponse = createMultiWalletScanResponse(), // never-mind + expected = null, + ), + createSecond( + scanResponse = createGenericScanResponse(), // default derivation path is null + derivationPath = Network.DerivationPath.None, + ), + createSecond( + scanResponse = createMultiWalletScanResponse(), + derivationPath = Network.DerivationPath.None, + ), + createSecond( + scanResponse = createMultiWalletScanResponse(), + derivationPath = Network.DerivationPath.Card(value = "m/44'/60'/0'/0/0"), + ), + createSecond( + scanResponse = createMultiWalletScanResponse(), + derivationPath = Network.DerivationPath.Custom(value = "m/84'/0'/0'/0/0"), + ), + // endregion + + // region fun create(blockchain: Blockchain, extraDerivationPath: String?, derivationStyleProvider: DerivationStyleProvider?, canHandleTokens: Boolean) + CreateTestModel.Third( + blockchain = Blockchain.Unknown, + extraDerivationPath = null, // never-mind + derivationStyleProvider = createMultiWalletScanResponse().derivationStyleProvider, // never-mind + canHandleTokens = true, // never-mind + expected = null, + ), + createThird( + extraDerivationPath = null, + derivationStyleProvider = createGenericScanResponse().derivationStyleProvider, // default derivation path is null + canHandleTokens = true, + expectedDerivationPath = Network.DerivationPath.None, + ), + createThird( + extraDerivationPath = null, + derivationStyleProvider = createMultiWalletScanResponse().derivationStyleProvider, + canHandleTokens = true, + expectedDerivationPath = Network.DerivationPath.Card(value = "m/44'/60'/0'/0/0"), // use default + ), + createThird( + extraDerivationPath = "m/44'/60'/0'/0/0", // as default + derivationStyleProvider = createMultiWalletScanResponse().derivationStyleProvider, + canHandleTokens = false, + expectedDerivationPath = Network.DerivationPath.Card(value = "m/44'/60'/0'/0/0"), + ), + createThird( + extraDerivationPath = "m/84'/0'/0'/0/0", + derivationStyleProvider = createMultiWalletScanResponse().derivationStyleProvider, + canHandleTokens = false, + expectedDerivationPath = Network.DerivationPath.Custom(value = "m/84'/0'/0'/0/0"), + ), + // endregion + ) + + private fun createFirst( + extraDerivationPath: String?, + scanResponse: ScanResponse, + expectedDerivationPath: Network.DerivationPath, + ): CreateTestModel.First { + return CreateTestModel.First( + blockchain = Blockchain.Ethereum, + extraDerivationPath = extraDerivationPath, + scanResponse = scanResponse, + expected = MockCryptoCurrencyFactory().ethereum.network.copy( + id = Network.ID( + value = Blockchain.Ethereum.id, + derivationPath = expectedDerivationPath, + ), + derivationPath = expectedDerivationPath, + canHandleTokens = true, + ), + ) + } + + private fun createSecond( + scanResponse: ScanResponse, + derivationPath: Network.DerivationPath, + ): CreateTestModel.Second { + return CreateTestModel.Second( + networkId = Network.ID(value = Blockchain.Ethereum.id, derivationPath = derivationPath), + derivationPath = derivationPath, + scanResponse = scanResponse, + expected = MockCryptoCurrencyFactory().ethereum.network.copy( + id = Network.ID( + value = Blockchain.Ethereum.id, + derivationPath = derivationPath, + ), + derivationPath = derivationPath, + canHandleTokens = true, + ), + ) + } + + private fun createThird( + extraDerivationPath: String?, + derivationStyleProvider: DerivationStyleProvider?, + canHandleTokens: Boolean, + expectedDerivationPath: Network.DerivationPath, + ): CreateTestModel.Third { + return CreateTestModel.Third( + blockchain = Blockchain.Ethereum, + extraDerivationPath = extraDerivationPath, + derivationStyleProvider = derivationStyleProvider, + canHandleTokens = canHandleTokens, + expected = MockCryptoCurrencyFactory().ethereum.network.copy( + id = Network.ID(value = Blockchain.Ethereum.id, derivationPath = expectedDerivationPath), + derivationPath = expectedDerivationPath, + canHandleTokens = canHandleTokens, + ), + ) + } + + private fun createMultiWalletScanResponse(): ScanResponse { + return MockScanResponseFactory.create( + cardConfig = MultiWalletCardConfig, + derivedKeys = emptyMap(), + ) + } + + private fun createGenericScanResponse(): ScanResponse { + return MockScanResponseFactory.create( + cardConfig = GenericCardConfig(maxWalletCount = 1), + derivedKeys = emptyMap(), + ) + } + } + + sealed interface CreateTestModel { + + val expected: Network? + + data class First( + val blockchain: Blockchain, + val extraDerivationPath: String?, + val scanResponse: ScanResponse, + override val expected: Network?, + ) : CreateTestModel + + data class Second( + val networkId: Network.ID, + val derivationPath: Network.DerivationPath, + val scanResponse: ScanResponse, + override val expected: Network?, + ) : CreateTestModel + + data class Third( + val blockchain: Blockchain, + val extraDerivationPath: String?, + val derivationStyleProvider: DerivationStyleProvider?, + val canHandleTokens: Boolean, + override val expected: Network?, + ) : CreateTestModel + } + + @Nested + @TestInstance(TestInstance.Lifecycle.PER_CLASS) + inner class GetNetworkStandardType { + + @ParameterizedTest + @ProvideTestModels + fun getNetworkStandardType(model: GetNetworkStandardTypeModel) { + // Act + val actual = model.blockchains.map(networkFactory::createNetworkStandardType) + + // Assert + val expected = model.blockchains.map(model.expected) + Truth.assertThat(actual).isEqualTo(expected) + } + + @Suppress("unused") + private fun provideTestModels() = listOf( + GetNetworkStandardTypeModel( + blockchains = listOf(Blockchain.Ethereum, Blockchain.EthereumTestnet), + expected = { Network.StandardType.ERC20 }, + ), + GetNetworkStandardTypeModel( + blockchains = listOf(Blockchain.BSC, Blockchain.BSCTestnet), + expected = { Network.StandardType.BEP20 }, + ), + GetNetworkStandardTypeModel( + blockchains = listOf(Blockchain.Binance, Blockchain.BinanceTestnet), + expected = { Network.StandardType.BEP2 }, + ), + GetNetworkStandardTypeModel( + blockchains = listOf(Blockchain.Tron, Blockchain.TronTestnet), + expected = { Network.StandardType.TRC20 }, + ), + GetNetworkStandardTypeModel( + blockchains = Blockchain.entries - listOf( + Blockchain.Ethereum, + Blockchain.EthereumTestnet, + Blockchain.BSC, + Blockchain.BSCTestnet, + Blockchain.Binance, + Blockchain.BinanceTestnet, + Blockchain.Tron, + Blockchain.TronTestnet, + ), + expected = { Network.StandardType.Unspecified(it.name) }, + ), + ) + } + + data class GetNetworkStandardTypeModel( + val blockchains: List, + val expected: (Blockchain) -> Network.StandardType, + ) + + @Nested + @TestInstance(TestInstance.Lifecycle.PER_CLASS) + inner class GetSupportedTransactionExtras { + + @ParameterizedTest + @ProvideTestModels + fun getSupportedTransactionExtras(model: GetSupportedTransactionExtrasModel) { + // Act + val actual = model.blockchains.map(networkFactory::createSupportedTransactionExtras) + + // Assert + val expected = List(size = model.blockchains.size) { model.expected } + + Truth.assertThat(actual).isEqualTo(expected) + } + + @Suppress("unused") + private fun provideTestModels() = listOf( + GetSupportedTransactionExtrasModel( + blockchains = listOf(Blockchain.XRP), + expected = Network.TransactionExtrasType.DESTINATION_TAG, + ), + GetSupportedTransactionExtrasModel( + blockchains = listOf( + Blockchain.Binance, + Blockchain.TON, + Blockchain.Cosmos, + Blockchain.TerraV1, + Blockchain.TerraV2, + Blockchain.Stellar, + Blockchain.Hedera, + Blockchain.Algorand, + Blockchain.Sei, + Blockchain.InternetComputer, + Blockchain.Casper, + ), + expected = Network.TransactionExtrasType.MEMO, + ), + GetSupportedTransactionExtrasModel( + blockchains = listOf( + Blockchain.Unknown, + Blockchain.Alephium, Blockchain.AlephiumTestnet, + Blockchain.Arbitrum, Blockchain.ArbitrumTestnet, + Blockchain.Avalanche, Blockchain.AvalancheTestnet, + Blockchain.BinanceTestnet, + Blockchain.BSC, Blockchain.BSCTestnet, + Blockchain.Bitcoin, Blockchain.BitcoinTestnet, + Blockchain.BitcoinCash, Blockchain.BitcoinCashTestnet, + Blockchain.Cardano, + Blockchain.CosmosTestnet, + Blockchain.Dogecoin, + Blockchain.Ducatus, + Blockchain.Ethereum, Blockchain.EthereumTestnet, + Blockchain.EthereumClassic, Blockchain.EthereumClassicTestnet, + Blockchain.Fantom, Blockchain.FantomTestnet, + Blockchain.Litecoin, + Blockchain.Near, Blockchain.NearTestnet, + Blockchain.Polkadot, Blockchain.PolkadotTestnet, + Blockchain.Kava, Blockchain.KavaTestnet, + Blockchain.Kusama, + Blockchain.Polygon, Blockchain.PolygonTestnet, + Blockchain.RSK, + Blockchain.SeiTestnet, + Blockchain.StellarTestnet, + Blockchain.Solana, Blockchain.SolanaTestnet, + Blockchain.Tezos, + Blockchain.Tron, Blockchain.TronTestnet, + Blockchain.Gnosis, + Blockchain.Dash, + Blockchain.Optimism, Blockchain.OptimismTestnet, + Blockchain.Dischain, + Blockchain.EthereumPow, Blockchain.EthereumPowTestnet, + Blockchain.Kaspa, Blockchain.KaspaTestnet, + Blockchain.Telos, Blockchain.TelosTestnet, + Blockchain.TONTestnet, + Blockchain.Ravencoin, + Blockchain.Clore, + Blockchain.RavencoinTestnet, + Blockchain.Cronos, + Blockchain.AlephZero, Blockchain.AlephZeroTestnet, + Blockchain.OctaSpace, Blockchain.OctaSpaceTestnet, + Blockchain.Chia, Blockchain.ChiaTestnet, + Blockchain.Decimal, Blockchain.DecimalTestnet, + Blockchain.XDC, Blockchain.XDCTestnet, + Blockchain.VeChain, Blockchain.VeChainTestnet, + Blockchain.Aptos, Blockchain.AptosTestnet, + Blockchain.Playa3ull, + Blockchain.Shibarium, Blockchain.ShibariumTestnet, + Blockchain.AlgorandTestnet, + Blockchain.HederaTestnet, + Blockchain.Aurora, Blockchain.AuroraTestnet, + Blockchain.Areon, Blockchain.AreonTestnet, + Blockchain.PulseChain, Blockchain.PulseChainTestnet, + Blockchain.ZkSyncEra, Blockchain.ZkSyncEraTestnet, + Blockchain.Nexa, Blockchain.NexaTestnet, + Blockchain.Moonbeam, Blockchain.MoonbeamTestnet, + Blockchain.Manta, Blockchain.MantaTestnet, + Blockchain.PolygonZkEVM, Blockchain.PolygonZkEVMTestnet, + Blockchain.Radiant, + Blockchain.Fact0rn, + Blockchain.Base, Blockchain.BaseTestnet, + Blockchain.Moonriver, Blockchain.MoonriverTestnet, + Blockchain.Mantle, Blockchain.MantleTestnet, + Blockchain.Flare, Blockchain.FlareTestnet, + Blockchain.Taraxa, Blockchain.TaraxaTestnet, + Blockchain.Koinos, Blockchain.KoinosTestnet, + Blockchain.Joystream, + Blockchain.Bittensor, + Blockchain.Filecoin, + Blockchain.Blast, Blockchain.BlastTestnet, + Blockchain.Cyber, Blockchain.CyberTestnet, + Blockchain.Sui, Blockchain.SuiTestnet, + Blockchain.EnergyWebChain, Blockchain.EnergyWebChainTestnet, + Blockchain.EnergyWebX, Blockchain.EnergyWebXTestnet, + Blockchain.CasperTestnet, + Blockchain.Core, Blockchain.CoreTestnet, + Blockchain.Xodex, + Blockchain.Canxium, + Blockchain.Chiliz, Blockchain.ChilizTestnet, + Blockchain.VanarChain, Blockchain.VanarChainTestnet, + Blockchain.OdysseyChain, Blockchain.OdysseyChainTestnet, + Blockchain.Bitrock, Blockchain.BitrockTestnet, + Blockchain.Sonic, Blockchain.SonicTestnet, + Blockchain.ApeChain, Blockchain.ApeChainTestnet, + Blockchain.Scroll, Blockchain.ScrollTestnet, + Blockchain.ZkLinkNova, Blockchain.ZkLinkNovaTestnet, + Blockchain.Pepecoin, Blockchain.PepecoinTestnet, + ), + expected = Network.TransactionExtrasType.NONE, + ), + ) + } + + data class GetSupportedTransactionExtrasModel( + val blockchains: List, + val expected: Network.TransactionExtrasType, + ) +} \ No newline at end of file