Updated on 2026-08-14

This commit is contained in:
Tangem 2026-02-25 18:06:51 +03:00
commit 642da93f97
15 changed files with 116 additions and 0 deletions

View file

@ -164,4 +164,6 @@ internal val Blockchain.moonPaySupportedCurrency: MoonPaySupportedCurrency?
ArbitrumNova -> null
Plasma, PlasmaTestnet -> null
Monad, MonadTestnet -> null
Berachain -> MoonPaySupportedCurrency(networkCode = "berachain", currencyCode = "bera_bera")
BerachainTestnet -> null
}

View file

@ -34,6 +34,14 @@ internal object BlockchainSDKConfigConverter : Converter<EnvironmentConfigModel,
apiKey = value.quiknodeMonadApiKey,
subdomain = value.quiknodeMonadSubdomain,
),
quickNodeBerachainCredentials = QuickNodeCredentials(
apiKey = value.quiknodeBerachainApiKey,
subdomain = value.quiknodeBerachainSubdomain,
),
quickNodeStellarCredentials = QuickNodeCredentials(
apiKey = value.quiknodeStellarApiKey,
subdomain = value.quiknodeStellarSubdomain,
),
infuraProjectId = value.infuraProjectId,
tronGridApiKey = value.tronGridApiKey,
nowNodeCredentials = NowNodeCredentials(value.nowNodesApiKey),
@ -116,6 +124,7 @@ internal object BlockchainSDKConfigConverter : Converter<EnvironmentConfigModel,
tezos = GetBlockAccessToken(rest = accessTokens.tezos?.rest),
monad = GetBlockAccessToken(rest = accessTokens.monad?.rest),
stellar = GetBlockAccessToken(rest = accessTokens.stellar?.rest),
berachain = GetBlockAccessToken(jsonRpc = accessTokens.berachain?.jsonRPC),
)
}
}

View file

@ -72,6 +72,14 @@ internal object GeneratedEnvironmentConfigConverter {
}
}
private fun createQuickNodeCredentials(apiKey: String?, subdomain: String?): QuickNodeCredentials? {
return if (!apiKey.isNullOrEmpty() && !subdomain.isNullOrEmpty()) {
QuickNodeCredentials(apiKey = apiKey, subdomain = subdomain)
} else {
null
}
}
private fun createBlockchainSdkConfig(): BlockchainSdkConfig {
return BlockchainSdkConfig(
blockchairCredentials = BlockchairCredentials(
@ -95,6 +103,14 @@ internal object GeneratedEnvironmentConfigConverter {
apiKey = GeneratedEnvironmentConfig.quiknodeMonadApiKey,
subdomain = GeneratedEnvironmentConfig.quiknodeMonadSubdomain,
),
quickNodeBerachainCredentials = createQuickNodeCredentials(
apiKey = GeneratedEnvironmentConfig.quiknodeBerachainApiKey,
subdomain = GeneratedEnvironmentConfig.quiknodeBerachainSubdomain,
),
quickNodeStellarCredentials = QuickNodeCredentials(
apiKey = GeneratedEnvironmentConfig.quiknodeStellarApiKey,
subdomain = GeneratedEnvironmentConfig.quiknodeStellarSubdomain,
),
infuraProjectId = GeneratedEnvironmentConfig.infuraProjectId,
tronGridApiKey = GeneratedEnvironmentConfig.tronGridApiKey,
nowNodeCredentials = NowNodeCredentials(apiKey = GeneratedEnvironmentConfig.nowNodesApiKey),
@ -176,6 +192,7 @@ internal object GeneratedEnvironmentConfigConverter {
tezos = GetBlockAccessToken(rest = GetBlockAccessTokens.Tezos.rest),
monad = GetBlockAccessToken(rest = GetBlockAccessTokens.Monad.rest),
stellar = GetBlockAccessToken(rest = GetBlockAccessTokens.Stellar.rest),
berachain = GetBlockAccessToken(rest = GetBlockAccessTokens.Berachain.rest),
)
}
}

View file

@ -20,6 +20,10 @@ class EnvironmentConfigModel(
@Json(name = "quiknodePlasmaApiKey") val quiknodePlasmaApiKey: String,
@Json(name = "quiknodeMonadSubdomain") val quiknodeMonadSubdomain: String,
@Json(name = "quiknodeMonadApiKey") val quiknodeMonadApiKey: String,
@Json(name = "quiknodeBerachainSubdomain") val quiknodeBerachainSubdomain: String,
@Json(name = "quiknodeBerachainApiKey") val quiknodeBerachainApiKey: String,
@Json(name = "quiknodeStellarSubdomain") val quiknodeStellarSubdomain: String,
@Json(name = "quiknodeStellarApiKey") val quiknodeStellarApiKey: String,
@Json(name = "nowNodesApiKey") val nowNodesApiKey: String,
@Json(name = "getBlockAccessTokens") val getBlockAccessTokens: GetBlockAccessTokens?,
@Json(name = "tonCenterApiKey") val tonCenterKeys: TonCenterKeys,
@ -101,6 +105,7 @@ data class GetBlockAccessTokens(
@Json(name = "tezos") val tezos: GetBlockToken?,
@Json(name = "monad") val monad: GetBlockToken?,
@Json(name = "stellar") val stellar: GetBlockToken?,
@Json(name = "berachain") val berachain: GetBlockToken?,
)
@JsonClass(generateAdapter = true)

View file

@ -100,6 +100,7 @@ fun getActiveIconRes(blockchainId: String): Int {
"arbitrum-nova" -> R.drawable.img_arbitrum_nova_22
"plasma", "plasma/test" -> R.drawable.img_plasma_22
"monad", "monad/test" -> R.drawable.img_monad_22
"berachain", "berachain/test" -> R.drawable.img_berachain_22
else -> R.drawable.ic_alert_24
}
}
@ -198,6 +199,7 @@ fun getActiveIconResByCoinId(coinId: String): Int {
"arbitrum-nova" -> R.drawable.img_arbitrum_nova_22
"plasma", "plasma/test" -> R.drawable.img_plasma_22
"monad", "monad/test" -> R.drawable.img_monad_22
"berachain-bera" -> R.drawable.img_berachain_22
else -> R.drawable.ic_alert_24
}
}
@ -299,6 +301,7 @@ fun getGreyedOutIconRes(blockchainId: String): Int {
"arbitrum-nova" -> R.drawable.ic_arbitrum_nova_22
"plasma", "plasma/test" -> R.drawable.ic_plasma_22
"monad", "monad/test" -> R.drawable.ic_monad_22
"berachain", "berachain/test" -> R.drawable.ic_berachain_22
else -> R.drawable.ic_alert_24
}
}

View file

@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="22dp"
android:height="22dp"
android:viewportWidth="22"
android:viewportHeight="22">
<path
android:pathData="M14.1523,13.2142V12.3734C14.6582,12.1959 15.0266,11.6448 15.0266,10.9924C15.0266,10.34 14.6582,9.7873 14.1523,9.6113V8.7705C14.6287,8.6039 14.984,8.1041 15.0233,7.5H14.4438V7.7569C14.4438,7.9547 14.3259,8.129 14.1523,8.2162V8.0963C14.1523,7.9204 14.0017,7.7772 13.8167,7.7772H13.7873C13.6023,7.7772 13.4516,7.9204 13.4516,8.0963V8.2162C13.2781,8.129 13.1602,7.9562 13.1602,7.7569V7.5H12.5807C12.62,8.1041 12.9752,8.6039 13.4516,8.7705V9.6113C12.9474,9.7873 12.5774,10.3384 12.5774,10.9924C12.5774,11.6463 12.9457,12.1975 13.4516,12.3734V13.2142C12.9752,13.3808 12.62,13.8807 12.5807,14.4847H13.1602V14.2278C13.1602,14.0301 13.2781,13.8557 13.4516,13.7685V13.8884C13.4516,14.0644 13.6023,14.2076 13.7873,14.2076H13.8167C14.0017,14.2076 14.1523,14.0644 14.1523,13.8884V13.7685C14.3259,13.8557 14.4438,14.0285 14.4438,14.2278V14.4847H15.0233C14.984,13.8807 14.6287,13.3808 14.1523,13.2142ZM13.1602,11.3598V10.6234C13.1602,10.4256 13.2781,10.2512 13.4516,10.164V10.2839C13.4516,10.4599 13.6023,10.6031 13.7873,10.6031H13.8167C14.0017,10.6031 14.1523,10.4599 14.1523,10.2839V10.164C14.3259,10.2512 14.4438,10.4241 14.4438,10.6234V11.3598C14.4438,11.5576 14.3259,11.732 14.1523,11.8191V11.6993C14.1523,11.5233 14.0017,11.3801 13.8167,11.3801H13.7873C13.6023,11.3801 13.4516,11.5233 13.4516,11.6993V11.8191C13.2797,11.732 13.1602,11.5591 13.1602,11.3598Z"
android:fillColor="#000000"/>
<path
android:pathData="M17.7083,11.4392V10.544C18.2142,10.3665 18.5826,9.8153 18.5826,9.1629C18.5826,8.5105 18.2142,7.9578 17.7083,7.7818V7.5H17.0092V7.7818C16.5033,7.9593 16.135,8.5105 16.135,9.1629C16.135,9.8153 16.5033,10.368 17.0092,10.544V11.4392C16.5033,11.6167 16.135,12.1679 16.135,12.8203C16.135,13.4727 16.5033,14.0254 17.0092,14.2014V14.4832H17.7083V14.2014C18.2142,14.0239 18.5826,13.4727 18.5826,12.8203C18.5826,12.1679 18.2142,11.6167 17.7083,11.4392ZM16.7162,9.5303V8.7939C16.7162,8.5961 16.8341,8.4218 17.0076,8.3346V8.4545C17.0076,8.6304 17.1583,8.7736 17.3432,8.7736H17.3711C17.5561,8.7736 17.7067,8.6304 17.7067,8.4545V8.3346C17.8802,8.4218 17.9981,8.5946 17.9981,8.7939V9.5303C17.9981,9.7281 17.8802,9.9025 17.7067,9.9897V9.8698C17.7067,9.6938 17.5561,9.5506 17.3711,9.5506H17.3416C17.1566,9.5506 17.006,9.6938 17.006,9.8698V9.9897C16.8357,9.9025 16.7162,9.7296 16.7162,9.5303ZM17.9997,13.1893C17.9997,13.3871 17.8819,13.5615 17.7083,13.6486V13.4727C17.7083,13.2968 17.5577,13.1535 17.3727,13.1535H17.3449C17.1599,13.1535 17.0092,13.2968 17.0092,13.4727V13.6486C16.8357,13.5615 16.7178,13.3886 16.7178,13.1893V12.4529C16.7178,12.2551 16.8357,12.0807 17.0092,11.9935V12.0574C17.0092,12.2333 17.1599,12.3766 17.3449,12.3766H17.3744C17.5593,12.3766 17.7099,12.2333 17.7099,12.0574V11.9935C17.8835,12.0807 18.0014,12.2536 18.0014,12.4529V13.1893H17.9997Z"
android:fillColor="#000000"/>
<path
android:pathData="M10.1463,10.2798C10.1397,10.244 10.1316,10.2098 10.1185,10.1771C10.1234,10.1693 11.2104,8.729 10.2036,7.8384C9.1984,6.9478 8.0245,8.1094 8.018,8.1156C7.8313,8.0595 7.643,8.0253 7.4564,8.0097C7.4564,8.0097 7.4564,8.0097 7.4548,8.0097C7.0717,7.949 6.5347,8.0097 6.5347,8.0097C6.3497,8.0253 6.163,8.0595 5.978,8.114C5.9715,8.1078 4.7976,6.9463 3.7924,7.8369C2.7872,8.7275 3.8726,10.1693 3.8775,10.1755C3.8661,10.2098 3.8562,10.244 3.8497,10.2783C3.7416,10.8948 3,11.0848 3,12.1591C3,13.2537 3.7744,14.1163 5.3559,14.1163H6.0042C6.0075,14.1194 6.258,14.4589 6.7753,14.4791C6.7753,14.4791 6.8949,14.4915 7.1699,14.4822C7.7183,14.4822 7.9852,14.1225 7.9868,14.1178H8.6352C10.2166,14.1178 10.991,13.2553 10.991,12.1607C10.996,11.0879 10.2543,10.8964 10.1463,10.2798Z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,22 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="22dp"
android:height="22dp"
android:viewportWidth="22"
android:viewportHeight="22">
<group>
<clip-path
android:pathData="M11,0L11,0A11,11 0,0 1,22 11L22,11A11,11 0,0 1,11 22L11,22A11,11 0,0 1,0 11L0,11A11,11 0,0 1,11 0z"/>
<path
android:pathData="M11,0L11,0A11,11 0,0 1,22 11L22,11A11,11 0,0 1,11 22L11,22A11,11 0,0 1,0 11L0,11A11,11 0,0 1,11 0z"
android:fillColor="#814626"/>
<path
android:pathData="M14.1523,13.2142V12.3734C14.6582,12.1959 15.0266,11.6448 15.0266,10.9924C15.0266,10.34 14.6582,9.7873 14.1523,9.6113V8.7705C14.6287,8.6039 14.984,8.1041 15.0233,7.5H14.4438V7.7569C14.4438,7.9547 14.3259,8.129 14.1523,8.2162V8.0963C14.1523,7.9204 14.0017,7.7772 13.8167,7.7772H13.7873C13.6023,7.7772 13.4516,7.9204 13.4516,8.0963V8.2162C13.2781,8.129 13.1602,7.9562 13.1602,7.7569V7.5H12.5807C12.62,8.1041 12.9752,8.6039 13.4516,8.7705V9.6113C12.9474,9.7873 12.5774,10.3384 12.5774,10.9924C12.5774,11.6463 12.9457,12.1975 13.4516,12.3734V13.2142C12.9752,13.3808 12.62,13.8807 12.5807,14.4847H13.1602V14.2278C13.1602,14.0301 13.2781,13.8557 13.4516,13.7685V13.8884C13.4516,14.0644 13.6023,14.2076 13.7873,14.2076H13.8167C14.0017,14.2076 14.1523,14.0644 14.1523,13.8884V13.7685C14.3259,13.8557 14.4438,14.0285 14.4438,14.2278V14.4847H15.0233C14.984,13.8807 14.6287,13.3808 14.1523,13.2142ZM13.1602,11.3598V10.6234C13.1602,10.4256 13.2781,10.2512 13.4516,10.164V10.2839C13.4516,10.4599 13.6023,10.6031 13.7873,10.6031H13.8167C14.0017,10.6031 14.1523,10.4599 14.1523,10.2839V10.164C14.3259,10.2512 14.4438,10.4241 14.4438,10.6234V11.3598C14.4438,11.5576 14.3259,11.732 14.1523,11.8191V11.6993C14.1523,11.5233 14.0017,11.3801 13.8167,11.3801H13.7873C13.6023,11.3801 13.4516,11.5233 13.4516,11.6993V11.8191C13.2797,11.732 13.1602,11.5591 13.1602,11.3598Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M17.7083,11.4392V10.544C18.2142,10.3665 18.5826,9.8153 18.5826,9.1629C18.5826,8.5105 18.2142,7.9578 17.7083,7.7818V7.5H17.0092V7.7818C16.5033,7.9593 16.135,8.5105 16.135,9.1629C16.135,9.8153 16.5033,10.368 17.0092,10.544V11.4392C16.5033,11.6167 16.135,12.1679 16.135,12.8203C16.135,13.4727 16.5033,14.0254 17.0092,14.2014V14.4832H17.7083V14.2014C18.2142,14.0239 18.5826,13.4727 18.5826,12.8203C18.5826,12.1679 18.2142,11.6167 17.7083,11.4392ZM16.7162,9.5303V8.7939C16.7162,8.5961 16.8341,8.4218 17.0076,8.3346V8.4545C17.0076,8.6304 17.1583,8.7736 17.3432,8.7736H17.3711C17.5561,8.7736 17.7067,8.6304 17.7067,8.4545V8.3346C17.8802,8.4218 17.9981,8.5946 17.9981,8.7939V9.5303C17.9981,9.7281 17.8802,9.9025 17.7067,9.9897V9.8698C17.7067,9.6938 17.5561,9.5506 17.3711,9.5506H17.3416C17.1566,9.5506 17.006,9.6938 17.006,9.8698V9.9897C16.8357,9.9025 16.7162,9.7296 16.7162,9.5303ZM17.9997,13.1893C17.9997,13.3871 17.8819,13.5615 17.7083,13.6486V13.4727C17.7083,13.2968 17.5577,13.1535 17.3727,13.1535H17.3449C17.1599,13.1535 17.0092,13.2968 17.0092,13.4727V13.6486C16.8357,13.5615 16.7178,13.3886 16.7178,13.1893V12.4529C16.7178,12.2551 16.8357,12.0807 17.0092,11.9935V12.0574C17.0092,12.2333 17.1599,12.3766 17.3449,12.3766H17.3744C17.5593,12.3766 17.7099,12.2333 17.7099,12.0574V11.9935C17.8835,12.0807 18.0014,12.2536 18.0014,12.4529V13.1893H17.9997Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M10.1463,10.2798C10.1397,10.244 10.1316,10.2098 10.1185,10.1771C10.1234,10.1693 11.2104,8.729 10.2036,7.8384C9.1984,6.9478 8.0245,8.1094 8.018,8.1156C7.8313,8.0595 7.643,8.0253 7.4564,8.0097C7.4564,8.0097 7.4564,8.0097 7.4548,8.0097C7.0717,7.949 6.5347,8.0097 6.5347,8.0097C6.3497,8.0253 6.163,8.0595 5.978,8.114C5.9715,8.1078 4.7976,6.9463 3.7924,7.8369C2.7872,8.7275 3.8726,10.1693 3.8775,10.1755C3.8661,10.2098 3.8562,10.244 3.8497,10.2783C3.7416,10.8948 3,11.0848 3,12.1591C3,13.2537 3.7744,14.1163 5.3559,14.1163H6.0042C6.0075,14.1194 6.258,14.4589 6.7753,14.4791C6.7753,14.4791 6.8949,14.4915 7.1699,14.4822C7.7183,14.4822 7.9852,14.1225 7.9868,14.1178H8.6352C10.2166,14.1178 10.991,13.2553 10.991,12.1607C10.996,11.0879 10.2543,10.8964 10.1463,10.2798Z"
android:fillColor="#ffffff"/>
</group>
</vector>

View file

@ -377,6 +377,7 @@ class NetworkFactory @Inject constructor(
Blockchain.ArbitrumNova,
Blockchain.Plasma, Blockchain.PlasmaTestnet,
Blockchain.Monad, Blockchain.MonadTestnet,
Blockchain.Berachain, Blockchain.BerachainTestnet,
-> Network.TransactionExtrasType.NONE
// endregion
}

View file

@ -461,6 +461,13 @@ class NetworkFactoryTest {
Blockchain.Scroll, Blockchain.ScrollTestnet,
Blockchain.ZkLinkNova, Blockchain.ZkLinkNovaTestnet,
Blockchain.Pepecoin, Blockchain.PepecoinTestnet,
Blockchain.Hyperliquid, Blockchain.HyperliquidTestnet,
Blockchain.Quai, Blockchain.QuaiTestnet,
Blockchain.Linea, Blockchain.LineaTestnet,
Blockchain.ArbitrumNova,
Blockchain.Plasma, Blockchain.PlasmaTestnet,
Blockchain.Monad, Blockchain.MonadTestnet,
Blockchain.Berachain, Blockchain.BerachainTestnet,
),
expected = Network.TransactionExtrasType.NONE,
),

View file

@ -164,5 +164,6 @@ public val Blockchain.mercuryoNetwork: String?
Blockchain.ArbitrumNova -> null
Blockchain.Plasma, Blockchain.PlasmaTestnet -> null
Blockchain.Monad, Blockchain.MonadTestnet -> null
Blockchain.Berachain, Blockchain.BerachainTestnet -> null
}
}

View file

@ -219,6 +219,8 @@ data object Wallet2CardConfig : CardConfig {
Blockchain.PlasmaTestnet -> EllipticCurve.Secp256k1
Blockchain.Monad -> EllipticCurve.Secp256k1
Blockchain.MonadTestnet -> EllipticCurve.Secp256k1
Blockchain.Berachain -> EllipticCurve.Secp256k1
Blockchain.BerachainTestnet -> EllipticCurve.Secp256k1
}
}
}

View file

@ -175,6 +175,8 @@ class Wallet2CardConfigTest {
Blockchain.PlasmaTestnet to EllipticCurve.Secp256k1,
Blockchain.Monad to EllipticCurve.Secp256k1,
Blockchain.MonadTestnet to EllipticCurve.Secp256k1,
Blockchain.Berachain to EllipticCurve.Secp256k1,
Blockchain.BerachainTestnet to EllipticCurve.Secp256k1,
)
@Test

View file

@ -176,6 +176,8 @@ fun Blockchain.Companion.fromNetworkId(networkId: String): Blockchain? {
"plasma/test" -> Blockchain.PlasmaTestnet
"monad" -> Blockchain.Monad
"monad/test" -> Blockchain.MonadTestnet
"berachain" -> Blockchain.Berachain
"berachain/test" -> Blockchain.BerachainTestnet
else -> null
}
}
@ -349,6 +351,8 @@ fun Blockchain.toNetworkId(): String {
Blockchain.PlasmaTestnet -> "plasma/test"
Blockchain.Monad -> "monad"
Blockchain.MonadTestnet -> "monad/test"
Blockchain.Berachain -> "berachain"
Blockchain.BerachainTestnet -> "berachain/test"
}
}
@ -458,6 +462,7 @@ fun Blockchain.toCoinId(): String {
Blockchain.ArbitrumNova -> "arbitrum-nova-ethereum"
Blockchain.Plasma, Blockchain.PlasmaTestnet -> "plasma"
Blockchain.Monad, Blockchain.MonadTestnet -> "monad"
Blockchain.Berachain, Blockchain.BerachainTestnet -> "berachain-bera"
}
}

View file

@ -178,6 +178,7 @@ class AccountNodeRecognizer(private val blockchain: Blockchain) {
Blockchain.Quai,
Blockchain.Plasma,
Blockchain.Monad,
Blockchain.Berachain,
-> true
Blockchain.Nexa, // unsupported network
Blockchain.Chia,
@ -254,6 +255,7 @@ class AccountNodeRecognizer(private val blockchain: Blockchain) {
Blockchain.LineaTestnet,
Blockchain.PlasmaTestnet,
Blockchain.MonadTestnet,
Blockchain.BerachainTestnet,
-> false
// endregion
}

View file

@ -103,6 +103,29 @@ internal class AccountNodeRecognizerTest {
expected = null,
),
// endregion
// region Berachain blockchain (EVM-like)
TestModel(
blockchain = Blockchain.Berachain,
derivationPath = "m/44'/60'/0'/0/1",
expected = 1,
),
TestModel(
blockchain = Blockchain.Berachain,
derivationPath = "m/44'/60'/0'/0/0",
expected = 0,
),
TestModel(
blockchain = Blockchain.Berachain,
derivationPath = "m/44'/60'/0'/0",
expected = null,
),
TestModel(
blockchain = Blockchain.Berachain,
derivationPath = "m/44'/60'",
expected = null,
),
// endregion
)
private fun provideUTXOTestModels() = listOf(