From 816facfb2732ccf70c8fddfc2645db650d0e2525 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 1 May 2020 18:47:42 +0300 Subject: [PATCH 1/2] Updated on 2026-08-14 --- .../ethereum/EthereumTransactionBuilder.kt | 15 ++++++++------- .../ethereum/network/EthereumNetworkManager.kt | 2 ++ .../com/tangem/blockchain/common/Blockchain.kt | 10 ++++------ .../blockchain/common/WalletManagerFactory.kt | 3 +-- .../tangem/blockchain/network/RetrofitBuilder.kt | 2 +- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/EthereumTransactionBuilder.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/EthereumTransactionBuilder.kt index 8ab1dcc1ad..ead68d974b 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/EthereumTransactionBuilder.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/EthereumTransactionBuilder.kt @@ -5,7 +5,6 @@ import com.tangem.blockchain.common.AmountType import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.TransactionData import com.tangem.common.extensions.hexToBytes -import org.kethereum.DEFAULT_GAS_LIMIT import org.kethereum.crypto.api.ec.ECDSASignature import org.kethereum.crypto.determineRecId import org.kethereum.crypto.impl.ec.canonicalise @@ -22,6 +21,7 @@ class EthereumTransactionBuilder(private val walletPublicKey: ByteArray, blockch private val chainId = when (blockchain) { Blockchain.Ethereum -> Chain.Mainnet.id + Blockchain.RSK -> Chain.RskMainnet.id else -> throw Exception("${blockchain.fullName} blockchain is not supported by EthereumTransactionBuilder") } @@ -36,14 +36,15 @@ class EthereumTransactionBuilder(private val walletPublicKey: ByteArray, blockch val to: Address val value: BigInteger - val input: ByteArray//data for smart contract + val input: ByteArray //data for smart contract - if (transactionData.amount.type == AmountType.Coin) { //ETH transfer + if (transactionData.amount.type == AmountType.Coin) { //coin transfer to = Address(transactionData.destinationAddress) value = bigIntegerAmount input = ByteArray(0) - } else { //Token transfer - to = Address(transactionData.contractAddress ?: throw Exception("Contract address is not specified!")) + } else { //token transfer + to = Address(transactionData.contractAddress + ?: throw Exception("Contract address is not specified!")) value = BigInteger.ZERO input = createErc20TransferData(transactionData.destinationAddress, bigIntegerAmount) } @@ -104,8 +105,8 @@ enum class Chain(val id: Int) { Morden(2), Ropsten(3), Rinkeby(4), - RootstockMainnet(30), - RootstockTestnet(31), + RskMainnet(30), + RskTestnet(31), Kovan(42), EthereumClassicMainnet(61), EthereumClassicTestnet(62), diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/EthereumNetworkManager.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/EthereumNetworkManager.kt index 757d6a5a56..f71e5c093b 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/EthereumNetworkManager.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/EthereumNetworkManager.kt @@ -5,6 +5,7 @@ import com.tangem.blockchain.extensions.Result import com.tangem.blockchain.extensions.SimpleResult import com.tangem.blockchain.extensions.retryIO import com.tangem.blockchain.network.API_INFURA +import com.tangem.blockchain.network.API_RSK import com.tangem.blockchain.network.createRetrofitInstance import kotlinx.coroutines.Deferred import kotlinx.coroutines.async @@ -20,6 +21,7 @@ class EthereumNetworkManager(blockchain: Blockchain) { private val api: InfuraApi by lazy { val baseUrl = when (blockchain) { Blockchain.Ethereum -> API_INFURA + Blockchain.RSK -> API_RSK else -> throw Exception("${blockchain.fullName} blockchain is not supported by EthereumNetworkManager") } createRetrofitInstance(baseUrl).create(InfuraApi::class.java) diff --git a/blockchain/src/main/java/com/tangem/blockchain/common/Blockchain.kt b/blockchain/src/main/java/com/tangem/blockchain/common/Blockchain.kt index 540e8c71d4..dc133669e3 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/common/Blockchain.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/common/Blockchain.kt @@ -8,8 +8,6 @@ import com.tangem.blockchain.blockchains.ethereum.EthereumAddressService import com.tangem.blockchain.blockchains.stellar.StellarAddressService import com.tangem.blockchain.blockchains.xrp.XrpAddressService -import java.math.BigDecimal - enum class Blockchain( val id: String, val currency: String, @@ -20,7 +18,7 @@ enum class Blockchain( BitcoinTestnet("BTC/test", "BTCt", "Bitcoin Testnet"), BitcoinCash("BCH", "BCH", "Bitcoin Cash"), Ethereum("ETH", "ETH", "Ethereum"), - Rootstock("", "", ""), + RSK("RSK", "RBTC", "RSK"), Cardano("CARDANO", "ADA", "Cardano"), XRP("XRP", "XRP", "XRP Ledger"), Binance("BINANCE", "BNB", "Binance"), @@ -30,7 +28,7 @@ enum class Blockchain( fun decimals(): Int = when (this) { Bitcoin, BitcoinTestnet, BitcoinCash, Binance, BinanceTestnet -> 8 Cardano, XRP -> 6 - Ethereum, Rootstock -> 18 + Ethereum, RSK -> 18 Stellar -> 7 Unknown -> 0 } @@ -49,7 +47,7 @@ enum class Blockchain( BitcoinTestnet -> BitcoinAddressService(true) BitcoinCash -> BitcoinCashAddressService() Ethereum -> EthereumAddressService() - Rootstock -> throw Exception("unsupported blockchain") + RSK -> throw Exception("unsupported blockchain") Cardano -> CardanoAddressService() XRP -> XrpAddressService() Binance -> BinanceAddressService() @@ -75,7 +73,7 @@ enum class Blockchain( } else { "https://etherscan.io/token/${token.contractAddress}?a=$address" } - Rootstock -> { + RSK -> { var url = "https://explorer.rsk.co/address/$address" if (token != null) { url += "?__tab=tokens" diff --git a/blockchain/src/main/java/com/tangem/blockchain/common/WalletManagerFactory.kt b/blockchain/src/main/java/com/tangem/blockchain/common/WalletManagerFactory.kt index 20d0c1883e..621ed2f129 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/common/WalletManagerFactory.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/common/WalletManagerFactory.kt @@ -12,7 +12,6 @@ import com.tangem.blockchain.blockchains.bitcoincash.BitcoinCashWalletManager import com.tangem.blockchain.blockchains.cardano.CardanoTransactionBuilder import com.tangem.blockchain.blockchains.cardano.CardanoWalletManager import com.tangem.blockchain.blockchains.cardano.network.CardanoNetworkManager -import com.tangem.blockchain.blockchains.ethereum.Chain import com.tangem.blockchain.blockchains.ethereum.EthereumTransactionBuilder import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager import com.tangem.blockchain.blockchains.ethereum.network.EthereumNetworkManager @@ -61,7 +60,7 @@ object WalletManagerFactory { BitcoinCashNetworkManager() ) } - Blockchain.Ethereum -> { + Blockchain.Ethereum, Blockchain.RSK -> { return EthereumWalletManager( cardId, wallet, EthereumTransactionBuilder(walletPublicKey, blockchain), diff --git a/blockchain/src/main/java/com/tangem/blockchain/network/RetrofitBuilder.kt b/blockchain/src/main/java/com/tangem/blockchain/network/RetrofitBuilder.kt index bdd4eca666..94d89c0531 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/network/RetrofitBuilder.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/network/RetrofitBuilder.kt @@ -40,7 +40,7 @@ const val API_INFURA = "https://mainnet.infura.io/" const val API_SOCHAIN_V2 = "https://chain.so/" const val API_ESTIMATEFEE = "https://estimatefee.com/" const val API_UPDATE_VERSION = "https://raw.githubusercontent.com/" -const val API_ROOTSTOCK = "https://public-node.rsk.co/" +const val API_RSK = "https://public-node.rsk.co/" const val API_BLOCKCYPHER = "https://api.blockcypher.com/" const val API_BINANCE = "https://dex.binance.org/" const val API_BINANCE_TESTNET = "https://testnet-dex.binance.org/" From d8c8d805ec19c334563c23c1b02a2774016da01f Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 6 May 2020 18:02:15 +0300 Subject: [PATCH 2/2] Updated on 2026-08-14 --- .../ethereum/EthereumWalletManager.kt | 12 +----- .../network/{InfuraApi.kt => EthereumApi.kt} | 11 +++--- .../network/EthereumNetworkManager.kt | 27 ++++++++----- .../ethereum/network/EthereumProvider.kt | 39 +++++++++++++++++++ ...{InfuraResponse.kt => EthereumResponse.kt} | 6 +-- .../ethereum/network/InfuraProvider.kt | 39 ------------------- .../tangem/blockchain/common/Blockchain.kt | 3 +- 7 files changed, 69 insertions(+), 68 deletions(-) rename blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/{InfuraApi.kt => EthereumApi.kt} (74%) create mode 100644 blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/EthereumProvider.kt rename blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/{InfuraResponse.kt => EthereumResponse.kt} (85%) delete mode 100644 blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/InfuraProvider.kt diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/EthereumWalletManager.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/EthereumWalletManager.kt index 76d48f8ba8..5ac19d6370 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/EthereumWalletManager.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/EthereumWalletManager.kt @@ -2,21 +2,13 @@ package com.tangem.blockchain.blockchains.ethereum import android.util.Log import com.tangem.blockchain.blockchains.ethereum.network.EthereumNetworkManager -import com.tangem.blockchain.blockchains.ethereum.network.EthereumResponse +import com.tangem.blockchain.blockchains.ethereum.network.EthereumInfoResponse import com.tangem.blockchain.common.* import com.tangem.blockchain.extensions.Result import com.tangem.blockchain.extensions.SimpleResult import com.tangem.common.CompletionResult import com.tangem.common.extensions.toHexString -import org.kethereum.DEFAULT_GAS_LIMIT -import org.kethereum.crypto.api.ec.ECDSASignature -import org.kethereum.crypto.determineRecId -import org.kethereum.crypto.impl.ec.canonicalise -import org.kethereum.extensions.transactions.encodeRLP -import org.kethereum.keccakshortcut.keccak -import org.kethereum.model.* import java.math.BigDecimal -import java.math.BigInteger class EthereumWalletManager( cardId: String, @@ -39,7 +31,7 @@ class EthereumWalletManager( } } - private fun updateWallet(data: EthereumResponse) { + private fun updateWallet(data: EthereumInfoResponse) { wallet.amounts[AmountType.Coin]?.value = data.balance wallet.amounts[AmountType.Token]?.value = data.tokenBalance txCount = data.txCount diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/InfuraApi.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/EthereumApi.kt similarity index 74% rename from blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/InfuraApi.kt rename to blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/EthereumApi.kt index ec6845b1d0..0b0030a779 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/InfuraApi.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/EthereumApi.kt @@ -4,15 +4,16 @@ import com.squareup.moshi.JsonClass import retrofit2.http.Body import retrofit2.http.Headers import retrofit2.http.POST +import retrofit2.http.Path -interface InfuraApi { +interface EthereumApi { @Headers("Content-Type: application/json") - @POST("v3/613a0b14833145968b1f656240c7d245") - suspend fun postToInfura(@Body body: InfuraBody?): InfuraResponse + @POST("{apiKey}") + suspend fun post(@Body body: EthereumBody?, @Path("apiKey") apiKey: String): EthereumResponse } @JsonClass(generateAdapter = true) -data class InfuraBody( +data class EthereumBody( val jsonrpc: String = "2.0", val id: Int = 67, val method: String? = null, @@ -21,7 +22,7 @@ data class InfuraBody( data class EthCallParams(private val data: String, private val to: String) -enum class InfuraMethod(val value: String) { +enum class EthereumMethod(val value: String) { GET_BALANCE("eth_getBalance"), GET_TRANSACTION_COUNT("eth_getTransactionCount"), GET_PENDING_COUNT("eth_getPendingCount"), diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/EthereumNetworkManager.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/EthereumNetworkManager.kt index f71e5c093b..0fd3078d40 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/EthereumNetworkManager.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/EthereumNetworkManager.kt @@ -17,17 +17,24 @@ import java.math.RoundingMode class EthereumNetworkManager(blockchain: Blockchain) { + private val infuraPath = "v3/" - private val api: InfuraApi by lazy { + private val api: EthereumApi by lazy { val baseUrl = when (blockchain) { - Blockchain.Ethereum -> API_INFURA + Blockchain.Ethereum -> API_INFURA + infuraPath Blockchain.RSK -> API_RSK else -> throw Exception("${blockchain.fullName} blockchain is not supported by EthereumNetworkManager") } - createRetrofitInstance(baseUrl).create(InfuraApi::class.java) + createRetrofitInstance(baseUrl).create(EthereumApi::class.java) } - private val provider: InfuraProvider by lazy { InfuraProvider(api) } + private val apiKey = when (blockchain) { + Blockchain.Ethereum -> INFURA_API_KEY + Blockchain.RSK -> "" + else -> throw Exception("${blockchain.fullName} blockchain is not supported by EthereumNetworkManager") + } + + private val provider: EthereumProvider by lazy { EthereumProvider(api, apiKey) } suspend fun sendTransaction(transaction: String): SimpleResult { return try { @@ -52,17 +59,17 @@ class EthereumNetworkManager(blockchain: Blockchain) { } } - suspend fun getInfo(address: String, contractAddress: String? = null): Result { + suspend fun getInfo(address: String, contractAddress: String? = null): Result { return try { coroutineScope { val balanceResponse = retryIO { async { provider.getBalance(address) } } val txCountResponse = retryIO { async { provider.getTxCount(address) } } val pendingTxCountResponse = retryIO { async { provider.getPendingTxCount(address) } } - var tokenBalanceResponse: Deferred? = null + var tokenBalanceResponse: Deferred? = null if (contractAddress != null) { tokenBalanceResponse = retryIO { async { provider.getTokenBalance(address, contractAddress) } } } - Result.Success(EthereumResponse( + Result.Success(EthereumInfoResponse( balanceResponse.await().result!!.parseAmount(), tokenBalanceResponse?.await()?.result?.parseAmount(), txCountResponse.await().result?.responseToNumber()?.toLong() ?: 0, @@ -98,9 +105,11 @@ class EthereumNetworkManager(blockchain: Blockchain) { } -data class EthereumResponse( +data class EthereumInfoResponse( val balance: BigDecimal, val tokenBalance: BigDecimal?, val txCount: Long, val pendingTxCount: Long -) \ No newline at end of file +) + +private const val INFURA_API_KEY = "613a0b14833145968b1f656240c7d245" \ No newline at end of file diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/EthereumProvider.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/EthereumProvider.kt new file mode 100644 index 0000000000..c320f566b6 --- /dev/null +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/EthereumProvider.kt @@ -0,0 +1,39 @@ +package com.tangem.blockchain.blockchains.ethereum.network + +class EthereumProvider(private val api: EthereumApi, private val apiKey: String) { + suspend fun getBalance(address: String) = api.post(createEthereumBody(EthereumMethod.GET_BALANCE, address), apiKey) + suspend fun getTokenBalance(address: String, contractAddress: String) = api.post(createEthereumBody(EthereumMethod.CALL, address, contractAddress), apiKey) + suspend fun getTxCount(address: String) = api.post(createEthereumBody(EthereumMethod.GET_TRANSACTION_COUNT, address), apiKey) + suspend fun getPendingTxCount(address: String) = api.post(createEthereumBody(EthereumMethod.GET_PENDING_COUNT, address), apiKey) + suspend fun getGasPrice() = api.post(createEthereumBody(EthereumMethod.GAS_PRICE), apiKey) + suspend fun sendTransaction(transaction: String) = api.post(createEthereumBody(EthereumMethod.SEND_RAW_TRANSACTION, transaction = transaction), apiKey) +} + +private fun createEthereumBody( + method: EthereumMethod, + address: String? = null, + contractAddress: String? = null, + transaction: String? = null): EthereumBody { + + return when (method) { + EthereumMethod.GET_BALANCE -> + EthereumBody(method = EthereumMethod.GET_BALANCE.value, params = listOf(address ?: "", "latest")) + EthereumMethod.GET_TRANSACTION_COUNT -> + EthereumBody(method = EthereumMethod.GET_TRANSACTION_COUNT.value, params = listOf(address ?: "", "latest")) + EthereumMethod.GET_PENDING_COUNT -> + EthereumBody(method = EthereumMethod.GET_TRANSACTION_COUNT.value, params = listOf(address ?: "", "pending")) + EthereumMethod.GAS_PRICE -> + EthereumBody(method = EthereumMethod.GAS_PRICE.value) + EthereumMethod.SEND_RAW_TRANSACTION -> + EthereumBody(method = EthereumMethod.SEND_RAW_TRANSACTION.value, params = listOf(transaction ?: "")) + EthereumMethod.CALL -> { + EthereumBody( + method = EthereumMethod.CALL.value, + params = listOf(EthCallParams( + "0x70a08231000000000000000000000000" + address?.substring(2), contractAddress + ?: ""), + "latest" + )) + } + } +} \ No newline at end of file diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/InfuraResponse.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/EthereumResponse.kt similarity index 85% rename from blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/InfuraResponse.kt rename to blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/EthereumResponse.kt index 7f8c2c088e..3e8da36c84 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/InfuraResponse.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/EthereumResponse.kt @@ -4,7 +4,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) -data class InfuraResponse( +data class EthereumResponse( @Json(name = "jsonrpc") val jsonrpc: String = "", @@ -15,11 +15,11 @@ data class InfuraResponse( val result: String? = null, @Json(name = "error") - val error: InfuraError? = null + val error: EthereumError? = null ) @JsonClass(generateAdapter = true) -data class InfuraError( +data class EthereumError( @Json(name = "code") val code: Int? = null, diff --git a/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/InfuraProvider.kt b/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/InfuraProvider.kt deleted file mode 100644 index ec29d6ec6c..0000000000 --- a/blockchain/src/main/java/com/tangem/blockchain/blockchains/ethereum/network/InfuraProvider.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.tangem.blockchain.blockchains.ethereum.network - -class InfuraProvider(private val api: InfuraApi) { - suspend fun getBalance(address: String) = api.postToInfura(createInfuraBody(InfuraMethod.GET_BALANCE, address)) - suspend fun getTokenBalance(address: String, contractAddress: String) = api.postToInfura(createInfuraBody(InfuraMethod.CALL, address, contractAddress)) - suspend fun getTxCount(address: String) = api.postToInfura(createInfuraBody(InfuraMethod.GET_TRANSACTION_COUNT, address)) - suspend fun getPendingTxCount(address: String) = api.postToInfura(createInfuraBody(InfuraMethod.GET_PENDING_COUNT, address)) - suspend fun getGasPrice() = api.postToInfura(createInfuraBody(InfuraMethod.GAS_PRICE)) - suspend fun sendTransaction(transaction: String) = api.postToInfura(createInfuraBody(InfuraMethod.SEND_RAW_TRANSACTION, transaction = transaction)) -} - -private fun createInfuraBody( - method: InfuraMethod, - address: String? = null, - contractAddress: String? = null, - transaction: String? = null): InfuraBody { - - return when (method) { - InfuraMethod.GET_BALANCE -> - InfuraBody(method = InfuraMethod.GET_BALANCE.value, params = listOf(address ?: "", "latest")) - InfuraMethod.GET_TRANSACTION_COUNT -> - InfuraBody(method = InfuraMethod.GET_TRANSACTION_COUNT.value, params = listOf(address ?: "", "latest")) - InfuraMethod.GET_PENDING_COUNT -> - InfuraBody(method = InfuraMethod.GET_TRANSACTION_COUNT.value, params = listOf(address ?: "", "pending")) - InfuraMethod.GAS_PRICE -> - InfuraBody(method = InfuraMethod.GAS_PRICE.value) - InfuraMethod.SEND_RAW_TRANSACTION -> - InfuraBody(method = InfuraMethod.SEND_RAW_TRANSACTION.value, params = listOf(transaction ?: "")) - InfuraMethod.CALL -> { - InfuraBody( - method = InfuraMethod.CALL.value, - params = listOf(EthCallParams( - "0x70a08231000000000000000000000000" + address?.substring(2), contractAddress - ?: ""), - "latest" - )) - } - } -} \ No newline at end of file diff --git a/blockchain/src/main/java/com/tangem/blockchain/common/Blockchain.kt b/blockchain/src/main/java/com/tangem/blockchain/common/Blockchain.kt index dc133669e3..c579c2d3db 100644 --- a/blockchain/src/main/java/com/tangem/blockchain/common/Blockchain.kt +++ b/blockchain/src/main/java/com/tangem/blockchain/common/Blockchain.kt @@ -46,8 +46,7 @@ enum class Blockchain( Bitcoin -> BitcoinAddressService() BitcoinTestnet -> BitcoinAddressService(true) BitcoinCash -> BitcoinCashAddressService() - Ethereum -> EthereumAddressService() - RSK -> throw Exception("unsupported blockchain") + Ethereum, RSK -> EthereumAddressService() Cardano -> CardanoAddressService() XRP -> XrpAddressService() Binance -> BinanceAddressService()