Skip to content

Commit

Permalink
Merge pull request #345 from tangem/feature/AND-4852_external_link_pr…
Browse files Browse the repository at this point in the history
…ovider

AND-4852 Added ExternalLinkProvider's
  • Loading branch information
Yoggam1 authored Oct 27, 2023
2 parents 7255c69 + 20d74b6 commit 241d16c
Show file tree
Hide file tree
Showing 43 changed files with 829 additions and 129 deletions.
136 changes: 7 additions & 129 deletions blockchain/src/main/java/com/tangem/blockchain/common/Blockchain.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import com.tangem.blockchain.common.address.AddressService
import com.tangem.blockchain.common.address.MultisigAddressProvider
import com.tangem.blockchain.common.address.TrustWalletAddressService
import com.tangem.blockchain.common.derivation.DerivationStyle
import com.tangem.blockchain.externallinkprovider.ExternalLinkProvider
import com.tangem.blockchain.externallinkprovider.ExternalLinkProviderFactory
import com.tangem.common.card.EllipticCurve
import com.tangem.crypto.hdWallet.DerivationPath

Expand Down Expand Up @@ -96,6 +98,8 @@ enum class Blockchain(
ChiaTestnet("chia/test", "TXCH", "Chia Network Testnet"),
;

private val externalLinkProvider: ExternalLinkProvider by lazy { ExternalLinkProviderFactory.makeProvider(this) }

fun decimals(): Int = when (this) {
Unknown -> 0
Near, NearTestnet,
Expand Down Expand Up @@ -224,142 +228,16 @@ enum class Blockchain(
return scheme == getShareScheme()
}

private fun getBaseExploreUrl(): String = when (this) {
Arbitrum -> "https://arbiscan.io/"
ArbitrumTestnet -> "https://goerli-rollup-explorer.arbitrum.io/"
Avalanche -> "https://snowtrace.io/"
AvalancheTestnet -> "https://testnet.snowtrace.io/"
Binance -> "https://explorer.binance.org/"
BinanceTestnet -> "https://testnet-explorer.binance.org/"
Bitcoin -> "https://www.blockchair.com/bitcoin/"
BitcoinTestnet -> "https://www.blockchair.com/bitcoin/testnet/"
BitcoinCash -> "https://www.blockchair.com/bitcoin-cash/"
BitcoinCashTestnet -> "https://www.blockchain.com/bch-testnet/"
BSC -> "https://bscscan.com/"
BSCTestnet -> "https://testnet.bscscan.com/"
Cardano -> "https://www.blockchair.com/cardano/"
Dogecoin -> "https://blockchair.com/dogecoin/"
Ducatus -> "https://insight.ducatus.io/#/DUC/mainnet/"
Ethereum -> "https://etherscan.io/"
EthereumTestnet -> "https://goerli.etherscan.io/"
EthereumClassic -> "https://blockscout.com/etc/mainnet/"
EthereumClassicTestnet -> "https://blockscout.com/etc/kotti/"
Fantom -> "https://ftmscan.com/"
FantomTestnet -> "https://testnet.ftmscan.com/"
Litecoin -> "https://blockchair.com/litecoin/"
Near -> "https://explorer.near.org/"
NearTestnet -> "https://explorer.testnet.near.org/"
Polkadot -> "https://polkadot.subscan.io/"
PolkadotTestnet -> "https://westend.subscan.io/"
Kusama -> "https://kusama.subscan.io/"
Polygon -> "https://polygonscan.com/"
PolygonTestnet -> "https://explorer-mumbai.maticvigil.com/"
RSK -> "https://explorer.rsk.co/"
Stellar -> "https://stellar.expert/explorer/public/"
StellarTestnet -> "https://stellar.expert/explorer/testnet/"
Solana -> "https://explorer.solana.com/"
SolanaTestnet -> "https://explorer.solana.com/"
Tezos -> "https://tzkt.io/"
Telos -> "https://teloscan.io/"
TelosTestnet -> "https://testnet.teloscan.io/"
TON -> "https://tonscan.org/"
TONTestnet -> "https://testnet.tonscan.org/"
Tron -> "https://tronscan.org/#/"
TronTestnet -> "https://nile.tronscan.org/#/"
XRP -> "https://xrpscan.com/"
Gnosis -> "https://blockscout.com/xdai/mainnet/"
Dash -> "https://blockexplorer.one/dash/mainnet/"
Optimism -> "https://optimistic.etherscan.io/"
OptimismTestnet -> "https://blockscout.com/optimism/goerli/"
EthereumFair -> "https://explorer.etherfair.org/"
EthereumPow -> "https://mainnet.ethwscan.com/"
EthereumPowTestnet -> "https://iceberg.ethwscan.com/"
Kaspa -> "https://explorer.kaspa.org/"
Kava -> "https://explorer.kava.io/"
KavaTestnet -> "https://explorer.testnet.kava.io/"
Ravencoin -> "https://api.ravencoin.org/"
RavencoinTestnet -> "https://testnet.ravencoin.network/"
CosmosTestnet -> "https://explorer.theta-testnet.polypore.xyz/accounts/"
Cosmos -> "https://www.mintscan.io/cosmos/account/"
TerraV1 -> "https://atomscan.com/terra/accounts/"
TerraV2 -> "https://terrasco.pe/mainnet/"
Cronos -> "https://cronoscan.com/"
AlephZero -> "https://alephzero.subscan.io/"
AlephZeroTestnet -> throw Exception("unsupported blockchain")
OctaSpace -> "https://explorer.octa.space/"
OctaSpaceTestnet -> throw Exception("unsupported blockchain")
Chia -> "https://xchscan.com/"
ChiaTestnet -> "https://testnet10.spacescan.io/"
Unknown -> throw Exception("unsupported blockchain")
}

fun getExploreUrl(address: String, tokenContractAddress: String? = null): String {
val path = "address/$address"
val baseUrl = getBaseExploreUrl()
val fullUrl = baseUrl + path
return when (this) {
Ethereum, EthereumTestnet -> if (tokenContractAddress == null) {
fullUrl
} else {
"$baseUrl$tokenContractAddress?a=$address"
}

EthereumClassic, EthereumClassicTestnet,
Kava, KavaTestnet,
-> "$fullUrl/transactions"

RSK -> if (tokenContractAddress != null) {
"$fullUrl?__tab=tokens"
} else {
fullUrl
}

SolanaTestnet -> "$fullUrl/?cluster=devnet"
XRP, Stellar, StellarTestnet -> "${baseUrl}account/$address"
Tezos -> "$baseUrl$address"
Kaspa -> "${baseUrl}addresses/$address"
Cosmos -> "${baseUrl}$address"
TerraV1 -> "${baseUrl}$address"
CosmosTestnet -> "${baseUrl}$address"
Near, NearTestnet -> "${baseUrl}accounts/$address"
else -> fullUrl
}
return externalLinkProvider.explorerUrl(walletAddress = address, contractAddress = tokenContractAddress)
}

fun getExploreTxUrl(transactionHash: String): String {
val url = getBaseExploreUrl() + "tx/$transactionHash"
return when (this) {
Bitcoin, BitcoinTestnet -> "${getBaseExploreUrl()}transaction/$transactionHash"
SolanaTestnet -> "$url/?cluster=devnet"
else -> url
}
return externalLinkProvider.explorerTransactionUrl(transactionHash)
}

fun getTestnetTopUpUrl(): String? {
return when (this) {
AvalancheTestnet -> "https://faucet.avax-test.network/"
BitcoinTestnet -> "https://coinfaucet.eu/en/btc-testnet/"
EthereumTestnet -> "https://goerlifaucet.com/"
EthereumClassicTestnet -> "https://kottifaucet.me"
BitcoinCashTestnet -> "https://coinfaucet.eu/en/bch-testnet/"
BinanceTestnet -> "https://docs.binance.org/smart-chain/wallet/binance.html"
BSCTestnet -> "https://testnet.binance.org/faucet-smart"
FantomTestnet -> "https://faucet.fantom.network"
PolygonTestnet -> "https://faucet.matic.network"
PolkadotTestnet -> "https://app.element.io/#/room/#westend_faucet:matrix.org"
StellarTestnet -> "https://laboratory.stellar.org/#account-creator?network=test"
SolanaTestnet -> "https://solfaucet.com/"
TronTestnet -> "https://nileex.io/join/getJoinPage"
OptimismTestnet -> "https://optimismfaucet.xyz" //another one https://faucet.paradigm.xyz
EthereumPowTestnet -> "https://faucet.ethwscan.com"
KavaTestnet -> "https://faucet.kava.io"
TelosTestnet -> "https://app.telos.net/testnet/developers"
CosmosTestnet -> "https://discord.com/channels/669268347736686612/953697793476821092"
AlephZeroTestnet -> "https://faucet.test.azero.dev/"
ChiaTestnet -> "https://xchdev.com/#!faucet.md"
NearTestnet -> "https://near-faucet.io/"
else -> null
}
return externalLinkProvider.testNetTopUpUrl
}

fun isTestnet(): Boolean = this == getTestnetVersion()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.tangem.blockchain.externallinkprovider

interface ExternalLinkProvider {

val explorerBaseUrl: String
val testNetTopUpUrl: String? get() = null

fun explorerUrl(walletAddress: String, contractAddress: String?): String

fun explorerTransactionUrl(transactionHash: String): String
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.tangem.blockchain.externallinkprovider

import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.externallinkprovider.providers.*

internal object ExternalLinkProviderFactory {

fun makeProvider(blockchain: Blockchain): ExternalLinkProvider {
val isTestnet = blockchain.isTestnet()
return when (blockchain) {
Blockchain.Unknown -> error("There is no ExternalLinkProvider for Blockchain.Unknown")
Blockchain.Arbitrum, Blockchain.ArbitrumTestnet -> ArbitrumExternalLinkProvider(isTestnet)
Blockchain.Avalanche, Blockchain.AvalancheTestnet -> AvalancheExternalLinkProvider(isTestnet)
Blockchain.Binance, Blockchain.BinanceTestnet -> BinanceExternalLinkProvider(isTestnet)
Blockchain.BSC, Blockchain.BSCTestnet -> BSCExternalLinkProvider(isTestnet)
Blockchain.Bitcoin, Blockchain.BitcoinTestnet -> BitcoinExternalLinkProvider(isTestnet)
Blockchain.BitcoinCash, Blockchain.BitcoinCashTestnet -> BitcoinCashExternalLinkProvider(isTestnet)
Blockchain.Cardano -> CardanoExternalLinkProvider()
Blockchain.Cosmos, Blockchain.CosmosTestnet -> CosmosExternalLinkProvider(isTestnet)
Blockchain.Dogecoin -> DogecoinExternalLinkProvider()
Blockchain.Ducatus -> DucatusExternalLinkProvider()
Blockchain.Ethereum, Blockchain.EthereumTestnet -> EthereumExternalLinkProvider(isTestnet)
Blockchain.EthereumClassic, Blockchain.EthereumClassicTestnet -> EthereumClassicExternalLinkProvider(isTestnet)
Blockchain.Fantom, Blockchain.FantomTestnet -> FantomExternalLinkProvider(isTestnet)
Blockchain.Litecoin -> LitecoinExternalLinkProvider()
Blockchain.Near, Blockchain.NearTestnet -> NearExternalLinkProvider(isTestnet)
Blockchain.Polkadot, Blockchain.PolkadotTestnet -> PolkadotExternalLinkProvider(isTestnet)
Blockchain.Kava, Blockchain.KavaTestnet -> KavaExternalLinkProvider(isTestnet)
Blockchain.Kusama -> KusamaExternalLinkProvider()
Blockchain.Polygon, Blockchain.PolygonTestnet -> PolygonExternalLinkProvider(isTestnet)
Blockchain.RSK -> RSKExternalLinkProvider()
Blockchain.Stellar, Blockchain.StellarTestnet -> StellarExternalLinkProvider(isTestnet)
Blockchain.Solana, Blockchain.SolanaTestnet -> SolanaExternalLinkProvider(isTestnet)
Blockchain.Tezos -> TezosExternalLinkProvider()
Blockchain.Tron, Blockchain.TronTestnet -> TronExternalLinkProvider(isTestnet)
Blockchain.XRP -> XRPExternalLinkProvider()
Blockchain.Gnosis -> GnosisExternalLinkProvider()
Blockchain.Dash -> DashExternalLinkProvider()
Blockchain.Optimism, Blockchain.OptimismTestnet -> OptimismExternalLinkProvider(isTestnet)
Blockchain.EthereumFair -> EthereumFairExternalLinkProvider()
Blockchain.EthereumPow, Blockchain.EthereumPowTestnet -> EthereumPowExternalLinkProvider(isTestnet)
Blockchain.Kaspa -> KaspaExternalLinkProvider()
Blockchain.Telos, Blockchain.TelosTestnet -> TelosExternalLinkProvider(isTestnet)
Blockchain.TON, Blockchain.TONTestnet -> TONExternalLinkProvider(isTestnet)
Blockchain.Ravencoin, Blockchain.RavencoinTestnet -> RavencoinExternalLinkProvider(isTestnet)
Blockchain.TerraV1 -> TerraV1ExternalLinkProvider()
Blockchain.TerraV2 -> TerraV2ExternalLinkProvider()
Blockchain.Cronos -> CronosExternalLinkProvider()
Blockchain.AlephZero -> AlephZeroExternalLinkProvider()
Blockchain.AlephZeroTestnet -> throw Exception("unsupported blockchain")
Blockchain.OctaSpace -> OctaSpaceExternalLinkProvider()
Blockchain.OctaSpaceTestnet -> throw Exception("unsupported blockchain")
Blockchain.Chia, Blockchain.ChiaTestnet -> ChiaExternalLinkProvider(isTestnet)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.tangem.blockchain.externallinkprovider.providers

import com.tangem.blockchain.externallinkprovider.ExternalLinkProvider

internal class AlephZeroExternalLinkProvider : ExternalLinkProvider {

override val explorerBaseUrl: String = "https://alephzero.subscan.io/"

override fun explorerUrl(walletAddress: String, contractAddress: String?): String {
return explorerBaseUrl + "account/$walletAddress"
}

override fun explorerTransactionUrl(transactionHash: String): String {
return explorerBaseUrl + "extrinsic/$transactionHash"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.tangem.blockchain.externallinkprovider.providers

import com.tangem.blockchain.externallinkprovider.ExternalLinkProvider

internal class ArbitrumExternalLinkProvider(isTestnet: Boolean) : ExternalLinkProvider {

override val explorerBaseUrl: String = if (isTestnet) "https://testnet.arbiscan.io/" else "https://arbiscan.io/"

override val testNetTopUpUrl: String? = if (isTestnet) "https://nileex.io/join/getJoinPage" else null

override fun explorerUrl(walletAddress: String, contractAddress: String?): String {
return if (contractAddress != null) {
explorerBaseUrl + "token/$contractAddress?a=$walletAddress"
} else {
explorerBaseUrl + "address/$walletAddress"
}
}

override fun explorerTransactionUrl(transactionHash: String): String {
return explorerBaseUrl + "tx/$transactionHash"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.tangem.blockchain.externallinkprovider.providers

import com.tangem.blockchain.externallinkprovider.ExternalLinkProvider

internal class AvalancheExternalLinkProvider(isTestnet: Boolean) : ExternalLinkProvider {

override val explorerBaseUrl: String = if (isTestnet) "https://testnet.snowtrace.io/" else "https://snowtrace.io/"

override val testNetTopUpUrl: String? = if (isTestnet) "https://faucet.avax-test.network/" else null

override fun explorerUrl(walletAddress: String, contractAddress: String?): String {
return if (contractAddress != null) {
explorerBaseUrl + "token/$contractAddress?a=$walletAddress"
} else {
explorerBaseUrl + "address/$walletAddress"
}
}

override fun explorerTransactionUrl(transactionHash: String): String {
return explorerBaseUrl + "tx/$transactionHash"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.tangem.blockchain.externallinkprovider.providers

import com.tangem.blockchain.externallinkprovider.ExternalLinkProvider

internal class BSCExternalLinkProvider(isTestnet: Boolean) : ExternalLinkProvider {

override val explorerBaseUrl: String = if (isTestnet) "https://testnet.bscscan.com/" else "https://bscscan.com/"

override val testNetTopUpUrl: String? = if (isTestnet) "https://testnet.binance.org/faucet-smart" else null

override fun explorerUrl(walletAddress: String, contractAddress: String?): String {
return if (contractAddress != null) {
explorerBaseUrl + "token/$contractAddress?a=$walletAddress"
} else {
explorerBaseUrl + "address/$walletAddress"
}
}

override fun explorerTransactionUrl(transactionHash: String): String {
return explorerBaseUrl + "tx/$transactionHash"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.tangem.blockchain.externallinkprovider.providers

import com.tangem.blockchain.externallinkprovider.ExternalLinkProvider

internal class BinanceExternalLinkProvider(isTestnet: Boolean) : ExternalLinkProvider {

override val explorerBaseUrl: String =
if (isTestnet) "https://testnet-explorer.binance.org/" else "https://explorer.binance.org/"

override val testNetTopUpUrl: String? =
if (isTestnet) "https://docs.binance.org/smart-chain/wallet/binance.html" else null

override fun explorerUrl(walletAddress: String, contractAddress: String?): String {
return explorerBaseUrl + "address/$walletAddress"
}

override fun explorerTransactionUrl(transactionHash: String): String {
return explorerBaseUrl + "tx/$transactionHash"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.tangem.blockchain.externallinkprovider.providers

import com.tangem.blockchain.externallinkprovider.ExternalLinkProvider

internal class BitcoinCashExternalLinkProvider(private val isTestnet: Boolean) : ExternalLinkProvider {

override val explorerBaseUrl: String =
if (isTestnet) "https://blockexplorer.one/bitcoin-cash/testnet/" else "https://www.blockchair.com/bitcoin-cash/"

override val testNetTopUpUrl: String? = if (isTestnet) "https://coinfaucet.eu/en/bch-testnet/" else null

override fun explorerUrl(walletAddress: String, contractAddress: String?): String {
return explorerBaseUrl + "address/$walletAddress"
}

override fun explorerTransactionUrl(transactionHash: String): String {
return if (isTestnet) {
explorerBaseUrl + "tx/$transactionHash"
} else {
explorerBaseUrl + "transaction/$transactionHash"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.tangem.blockchain.externallinkprovider.providers

import com.tangem.blockchain.externallinkprovider.ExternalLinkProvider

internal class BitcoinExternalLinkProvider(isTestnet: Boolean) : ExternalLinkProvider {

override val explorerBaseUrl: String =
if (isTestnet) "https://www.blockchair.com/bitcoin/" else "https://www.blockchair.com/bitcoin/testnet/"

override val testNetTopUpUrl: String? = if (isTestnet) "https://coinfaucet.eu/en/btc-testnet/" else null

override fun explorerUrl(walletAddress: String, contractAddress: String?): String {
return explorerBaseUrl + "address/$walletAddress"
}

override fun explorerTransactionUrl(transactionHash: String): String {
return explorerBaseUrl + "transaction/$transactionHash"
}
}
Loading

0 comments on commit 241d16c

Please sign in to comment.