Updated on 2026-08-14
This commit is contained in:
commit
ff24b00af4
404 changed files with 12634 additions and 3818 deletions
|
|
@ -14,6 +14,8 @@ import com.kaspersky.kaspresso.kaspresso.Kaspresso
|
|||
import com.kaspersky.kaspresso.testcases.api.testcase.TestCase
|
||||
import com.tangem.common.allure.FailedStepScreenshotInterceptor
|
||||
import com.tangem.common.rules.ApiEnvironmentRule
|
||||
import com.tangem.core.configtoggle.feature.FeatureTogglesManager
|
||||
import com.tangem.core.configtoggle.feature.MutableFeatureTogglesManager
|
||||
import com.tangem.datasource.api.common.config.managers.ApiConfigsManager
|
||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||
import com.tangem.datasource.local.preferences.PreferencesKeys
|
||||
|
|
@ -46,6 +48,9 @@ abstract class BaseTestCase : TestCase(
|
|||
@Inject
|
||||
lateinit var appPreferencesStore: AppPreferencesStore
|
||||
|
||||
@Inject
|
||||
lateinit var featureTogglesManager: FeatureTogglesManager
|
||||
|
||||
private val hiltRule = HiltAndroidRule(this)
|
||||
private val apiEnvironmentRule = ApiEnvironmentRule()
|
||||
private val permissionRule = GrantPermissionRule.grant(
|
||||
|
|
@ -90,6 +95,7 @@ abstract class BaseTestCase : TestCase(
|
|||
apiEnvironmentRule.setup(apiConfigsManager)
|
||||
ActivityScenario.launch(MainActivity::class.java)
|
||||
Intents.init()
|
||||
setFeatureToggles()
|
||||
additionalBeforeSection()
|
||||
}.after {
|
||||
additionalAfterSection()
|
||||
|
|
@ -113,4 +119,18 @@ abstract class BaseTestCase : TestCase(
|
|||
{
|
||||
composeTestRule.onRoot(useUnmergedTree = useUnmergedTree).printToLog(tag, maxDepth)
|
||||
}
|
||||
|
||||
|
||||
private fun setFeatureToggles() {
|
||||
runBlocking {
|
||||
with(featureTogglesManager as MutableFeatureTogglesManager) {
|
||||
changeToggle("WALLET_CONNECT_REDESIGN_ENABLED", true)
|
||||
changeToggle("WALLET_BALANCE_FETCHER_ENABLED", true)
|
||||
changeToggle("SEND_VIA_SWAP_ENABLED", true)
|
||||
changeToggle("SWAP_REDESIGN_ENABLED", true)
|
||||
changeToggle("SEND_REDESIGN_ENABLED", true)
|
||||
changeToggle("NEW_ONRAMP_MAIN_ENABLED", true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
package com.tangem.common.utils
|
||||
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.json.JSONObject
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
fun getWcUri(
|
||||
network: String = "ethereum",
|
||||
baseUrl: String = "[REDACTED_ENV_URL]"
|
||||
): String? {
|
||||
Timber.i("Getting WC URI for network: $network")
|
||||
|
||||
val client = OkHttpClient.Builder()
|
||||
.connectTimeout(30, TimeUnit.SECONDS) // Таймаут подключения
|
||||
.readTimeout(60, TimeUnit.SECONDS) // Таймаут чтения ответа
|
||||
.writeTimeout(30, TimeUnit.SECONDS) // Таймаут записи
|
||||
.callTimeout(90, TimeUnit.SECONDS) // Общий таймаут запроса
|
||||
.build()
|
||||
|
||||
val request = Request.Builder()
|
||||
.url("$baseUrl/wc_uri?network=$network")
|
||||
.get()
|
||||
.build()
|
||||
|
||||
return try {
|
||||
client.newCall(request).execute().use { response ->
|
||||
Timber.i("Response code: ${response.code}")
|
||||
|
||||
if (response.isSuccessful) {
|
||||
val body = response.body?.string() ?: ""
|
||||
Timber.i("Response body: $body")
|
||||
|
||||
val jsonObject = JSONObject(body)
|
||||
|
||||
if (jsonObject.getBoolean("success")) {
|
||||
val wcUri = jsonObject.getString("wcUri")
|
||||
Timber.i("Got WC URI successfully: $wcUri")
|
||||
|
||||
wcUri
|
||||
} else {
|
||||
Timber.e("API returned error: ${jsonObject.optString("error", "Unknown")}")
|
||||
null
|
||||
}
|
||||
} else {
|
||||
val errorBody = response.body?.string() ?: "No error body"
|
||||
Timber.e("Request failed: ${response.code}, body: $errorBody")
|
||||
null
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Error getting WC URI")
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun checkServiceHealth(
|
||||
baseUrl: String = "[REDACTED_ENV_URL]"
|
||||
): String? {
|
||||
Timber.i("Checking service health")
|
||||
|
||||
val client = OkHttpClient()
|
||||
val request = Request.Builder()
|
||||
.url("$baseUrl/health")
|
||||
.get()
|
||||
.build()
|
||||
|
||||
return try {
|
||||
client.newCall(request).execute().use { response ->
|
||||
Timber.i("Response code: ${response.code}")
|
||||
|
||||
if (response.isSuccessful) {
|
||||
val body = response.body?.string() ?: ""
|
||||
Timber.i("Response body: $body")
|
||||
|
||||
if (body.isEmpty()) {
|
||||
Timber.e("Response body is empty")
|
||||
return null
|
||||
}
|
||||
|
||||
val jsonObject = JSONObject(body)
|
||||
val status = jsonObject.optString("status", "")
|
||||
|
||||
if (status.isNotEmpty()) {
|
||||
Timber.i("Got status successfully: $status")
|
||||
status
|
||||
} else {
|
||||
Timber.e("Status field is missing or empty")
|
||||
null
|
||||
}
|
||||
} else {
|
||||
val errorBody = response.body?.string() ?: "No error body"
|
||||
Timber.e("Request failed: ${response.code}, body: $errorBody")
|
||||
null
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Error checking health")
|
||||
null
|
||||
}
|
||||
}
|
||||
|
|
@ -35,6 +35,10 @@ class MainScreenPageObject(semanticsProvider: SemanticsNodeInteractionsProvider)
|
|||
}
|
||||
)
|
||||
|
||||
val screenContainer: KNode = child {
|
||||
hasTestTag(MainScreenTestTags.SCREEN_CONTAINER)
|
||||
}
|
||||
|
||||
val synchronizeAddressesButton: KNode = child {
|
||||
hasText(getResourceString(R.string.common_generate_addresses))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
package com.tangem.screens
|
||||
|
||||
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
|
||||
import com.tangem.common.BaseTestCase
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.test.BaseButtonTestTags
|
||||
import com.tangem.core.ui.test.WalletConnectBottomSheetTestTags
|
||||
import io.github.kakaocup.compose.node.element.ComposeScreen
|
||||
import io.github.kakaocup.compose.node.element.ComposeScreen.Companion.onComposeScreen
|
||||
import io.github.kakaocup.compose.node.element.KNode
|
||||
import io.github.kakaocup.kakao.common.utilities.getResourceString
|
||||
import com.tangem.features.walletconnect.impl.R as WalletConnectImplR
|
||||
|
||||
class WalletConnectBottomSheetPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
|
||||
ComposeScreen<WalletConnectBottomSheetPageObject>(semanticsProvider = semanticsProvider) {
|
||||
|
||||
val title: KNode = child {
|
||||
hasText(getResourceString(WalletConnectImplR.string.wc_wallet_connect))
|
||||
hasTestTag(WalletConnectBottomSheetTestTags.TITLE)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val appIcon: KNode = child {
|
||||
hasTestTag(WalletConnectBottomSheetTestTags.APP_ICON)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val appName: KNode = child {
|
||||
hasTestTag(WalletConnectBottomSheetTestTags.APP_NAME)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val approveIcon: KNode = child {
|
||||
hasTestTag(WalletConnectBottomSheetTestTags.APPROVE_ICON)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val appUrl: KNode = child {
|
||||
hasTestTag(WalletConnectBottomSheetTestTags.APP_URL)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val connectionRequestIcon: KNode = child {
|
||||
hasTestTag(WalletConnectBottomSheetTestTags.CONNECTION_REQUEST_ICON)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val connectionRequestText: KNode = child {
|
||||
hasTestTag(WalletConnectBottomSheetTestTags.CONNECTION_REQUEST_TEXT)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val connectionRequestChevron: KNode = child {
|
||||
hasTestTag(WalletConnectBottomSheetTestTags.CONNECTION_REQUEST_CHEVRON)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val walletIcon: KNode = child {
|
||||
hasTestTag(WalletConnectBottomSheetTestTags.WALLET_ICON)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val walletNameTitle: KNode = child {
|
||||
hasTestTag(WalletConnectBottomSheetTestTags.WALLET_NAME_TITLE)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val walletName: KNode = child {
|
||||
hasTestTag(WalletConnectBottomSheetTestTags.WALLET_NAME)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val networksIcon: KNode = child {
|
||||
hasTestTag(WalletConnectBottomSheetTestTags.NETWORKS_ICON)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val networksTitle: KNode = child {
|
||||
hasTestTag(WalletConnectBottomSheetTestTags.NETWORKS_TITLE)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val networksIcons: KNode = child {
|
||||
hasTestTag(WalletConnectBottomSheetTestTags.NETWORKS_ICONS)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val networksSelectorIcon: KNode = child {
|
||||
hasTestTag(WalletConnectBottomSheetTestTags.NETWORKS_SELECTOR_ICON)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val cancelButton: KNode = child {
|
||||
hasText(getResourceString(R.string.common_cancel))
|
||||
hasTestTag(BaseButtonTestTags.TEXT)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val connectButton: KNode = child {
|
||||
hasText(getResourceString(R.string.wc_common_connect))
|
||||
hasTestTag(BaseButtonTestTags.TEXT)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal fun BaseTestCase.onWalletConnectBottomSheet(function: WalletConnectBottomSheetPageObject.() -> Unit) =
|
||||
onComposeScreen(composeTestRule, function)
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
package com.tangem.screens
|
||||
|
||||
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
|
||||
import com.tangem.common.BaseTestCase
|
||||
import com.tangem.core.ui.test.BaseButtonTestTags
|
||||
import com.tangem.core.ui.test.WalletConnectBottomSheetTestTags
|
||||
import com.tangem.core.ui.test.WalletConnectDetailsBottomSheetTestTags
|
||||
import io.github.kakaocup.compose.node.element.ComposeScreen
|
||||
import io.github.kakaocup.compose.node.element.ComposeScreen.Companion.onComposeScreen
|
||||
import io.github.kakaocup.compose.node.element.KNode
|
||||
import io.github.kakaocup.kakao.common.utilities.getResourceString
|
||||
import com.tangem.features.walletconnect.impl.R as WalletConnectImplR
|
||||
|
||||
class WalletConnectDetailsBottomSheetPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
|
||||
ComposeScreen<WalletConnectDetailsBottomSheetPageObject>(semanticsProvider = semanticsProvider) {
|
||||
|
||||
val title: KNode = child {
|
||||
hasTestTag(WalletConnectDetailsBottomSheetTestTags.TITLE)
|
||||
hasText(getResourceString(WalletConnectImplR.string.wc_connected_app_title))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val date: KNode = child {
|
||||
hasTestTag(WalletConnectDetailsBottomSheetTestTags.DATE)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val closeButton: KNode = child {
|
||||
hasTestTag(WalletConnectDetailsBottomSheetTestTags.CLOSE_BUTTON)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val networksBlockTitle: KNode = child {
|
||||
hasText(getResourceString(WalletConnectImplR.string.wc_connected_networks))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val appIcon: KNode = child {
|
||||
hasTestTag(WalletConnectBottomSheetTestTags.APP_ICON)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val approveIcon: KNode = child {
|
||||
hasTestTag(WalletConnectBottomSheetTestTags.APPROVE_ICON)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val appName: KNode = child {
|
||||
hasTestTag(WalletConnectBottomSheetTestTags.APP_NAME)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val appUrl: KNode = child {
|
||||
hasTestTag(WalletConnectBottomSheetTestTags.APP_URL)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val walletIcon: KNode = child {
|
||||
hasTestTag(WalletConnectDetailsBottomSheetTestTags.WALLET_ICON)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val walletTitle: KNode = child {
|
||||
hasTestTag(WalletConnectDetailsBottomSheetTestTags.WALLET_TITLE)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val walletName: KNode = child {
|
||||
hasTestTag(WalletConnectDetailsBottomSheetTestTags.WALLET_NAME)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val connectedNetworksTitle: KNode = child {
|
||||
hasTestTag(WalletConnectDetailsBottomSheetTestTags.NETWORKS_TITLE)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val connectedNetworkItem: KNode = child {
|
||||
hasTestTag(WalletConnectDetailsBottomSheetTestTags.NETWORK_ITEM)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val connectedNetworkIcon: KNode = child {
|
||||
hasTestTag(WalletConnectDetailsBottomSheetTestTags.NETWORK_ICON)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val connectedNetworkName: KNode = child {
|
||||
hasTestTag(WalletConnectDetailsBottomSheetTestTags.NETWORK_NAME)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val connectedNetworkSymbol: KNode = child {
|
||||
hasTestTag(WalletConnectDetailsBottomSheetTestTags.NETWORK_SYMBOL)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val disconnectButton: KNode = child {
|
||||
hasText(getResourceString(WalletConnectImplR.string.common_disconnect))
|
||||
hasTestTag(BaseButtonTestTags.TEXT)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal fun BaseTestCase.onWalletConnectDetailsBottomSheet(function: WalletConnectDetailsBottomSheetPageObject.() -> Unit) =
|
||||
onComposeScreen(composeTestRule, function)
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package com.tangem.screens
|
||||
|
||||
import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
|
||||
import com.tangem.common.BaseTestCase
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.test.BaseButtonTestTags
|
||||
import com.tangem.core.ui.test.WalletConnectScreenTestTags
|
||||
import io.github.kakaocup.compose.node.element.ComposeScreen
|
||||
import io.github.kakaocup.compose.node.element.ComposeScreen.Companion.onComposeScreen
|
||||
import io.github.kakaocup.compose.node.element.KNode
|
||||
import io.github.kakaocup.kakao.common.utilities.getResourceString
|
||||
|
||||
class WalletConnectPageObject(semanticsProvider: SemanticsNodeInteractionsProvider) :
|
||||
ComposeScreen<WalletConnectPageObject>(semanticsProvider = semanticsProvider) {
|
||||
|
||||
val title: KNode = child {
|
||||
hasText(getResourceString(R.string.wc_connections))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val moreButton: KNode = child {
|
||||
hasTestTag(WalletConnectScreenTestTags.MORE_BUTTON)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val walletName: KNode = child {
|
||||
hasTestTag(WalletConnectScreenTestTags.WALLET_NAME)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val appIcon: KNode = child {
|
||||
hasTestTag(WalletConnectScreenTestTags.APP_ICON)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val appName: KNode = child {
|
||||
hasTestTag(WalletConnectScreenTestTags.APP_NAME)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val approveIcon: KNode = child {
|
||||
hasTestTag(WalletConnectScreenTestTags.APPROVE_ICON)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val appUrl: KNode = child {
|
||||
hasTestTag(WalletConnectScreenTestTags.APP_URL)
|
||||
useUnmergedTree = true
|
||||
}
|
||||
|
||||
val newConnectionButton: KNode = child {
|
||||
hasTestTag(BaseButtonTestTags.TEXT)
|
||||
hasText(getResourceString(R.string.wc_new_connection))
|
||||
useUnmergedTree = true
|
||||
}
|
||||
}
|
||||
|
||||
internal fun BaseTestCase.onWalletConnectScreen(function: WalletConnectPageObject.() -> Unit) =
|
||||
onComposeScreen(composeTestRule, function)
|
||||
38
app/src/androidTest/kotlin/com/tangem/steps/BaseScenarios.kt
Normal file
38
app/src/androidTest/kotlin/com/tangem/steps/BaseScenarios.kt
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
package com.tangem.steps
|
||||
|
||||
import com.tangem.common.BaseTestCase
|
||||
import com.tangem.common.extensions.clickWithAssertion
|
||||
import com.tangem.domain.models.scan.ProductType
|
||||
import com.tangem.screens.onDisclaimerScreen
|
||||
import com.tangem.screens.onMainScreen
|
||||
import com.tangem.screens.onMarketsTooltipScreen
|
||||
import com.tangem.screens.onStoriesScreen
|
||||
import com.tangem.tap.domain.sdk.mocks.MockProvider
|
||||
import io.qameta.allure.kotlin.Allure.step
|
||||
|
||||
fun BaseTestCase.openMainScreen(productType: ProductType? = null) {
|
||||
if (productType != null) {
|
||||
MockProvider.setMocks(productType)
|
||||
}
|
||||
step("Click on 'Accept' button") {
|
||||
onDisclaimerScreen { acceptButton.clickWithAssertion() }
|
||||
}
|
||||
step("Click on 'Accept' button") {
|
||||
onStoriesScreen { scanButton.clickWithAssertion() }
|
||||
}
|
||||
step("Assert main screen is displayed") {
|
||||
onMainScreen { screenContainer.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert main screen is displayed") {
|
||||
onMarketsTooltipScreen { contentContainer.clickWithAssertion() }
|
||||
}
|
||||
}
|
||||
|
||||
fun BaseTestCase.synchronizeAddresses(balance: String) {
|
||||
step("Click on 'Synchronize addresses' button") {
|
||||
onMainScreen { synchronizeAddressesButton.clickWithAssertion() }
|
||||
}
|
||||
step("Assert wallet balance = '$balance'") {
|
||||
onMainScreen { walletBalance().assertTextContains(balance) }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package com.tangem.steps
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
|
||||
fun openAppByDeepLink(deepLinkUri: String?) {
|
||||
val deeplinkScheme = "tangem://wc?uri="
|
||||
val context = ApplicationProvider.getApplicationContext<android.content.Context>()
|
||||
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(deeplinkScheme + deepLinkUri)).apply {
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
package com.tangem.steps
|
||||
|
||||
import com.tangem.common.BaseTestCase
|
||||
import com.tangem.screens.onWalletConnectBottomSheet
|
||||
import com.tangem.screens.onWalletConnectDetailsBottomSheet
|
||||
import com.tangem.screens.onWalletConnectScreen
|
||||
import io.qameta.allure.kotlin.Allure.step
|
||||
|
||||
fun BaseTestCase.checkWalletConnectBottomSheet() {
|
||||
step("Assert 'Wallet Connect' bottom sheet title is displayed") {
|
||||
onWalletConnectBottomSheet { title.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'Wallet Connect' bottom sheet app icon is displayed") {
|
||||
onWalletConnectBottomSheet { appIcon.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'Wallet Connect' bottom sheet app name is displayed") {
|
||||
onWalletConnectBottomSheet { appName.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'Wallet Connect' bottom sheet approve icon is displayed") {
|
||||
onWalletConnectBottomSheet { approveIcon.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'Wallet Connect' bottom sheet app URL is displayed") {
|
||||
onWalletConnectBottomSheet { appUrl.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'Wallet Connect' bottom sheet connection request icon is displayed") {
|
||||
onWalletConnectBottomSheet { connectionRequestIcon.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'Wallet Connect' bottom sheet connection request text is displayed") {
|
||||
onWalletConnectBottomSheet { connectionRequestText.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'Wallet Connect' bottom sheet connection request chevron is displayed") {
|
||||
onWalletConnectBottomSheet { connectionRequestChevron.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'Wallet Connect' bottom sheet wallet icon is displayed") {
|
||||
onWalletConnectBottomSheet { walletIcon.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'Wallet Connect' bottom sheet wallet title is displayed") {
|
||||
onWalletConnectBottomSheet { walletNameTitle.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'Wallet Connect' bottom sheet wallet name is displayed") {
|
||||
onWalletConnectBottomSheet { walletName.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'Wallet Connect' bottom sheet networks icon is displayed") {
|
||||
onWalletConnectBottomSheet { networksIcon.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'Wallet Connect' bottom sheet networks title is displayed") {
|
||||
onWalletConnectBottomSheet { networksTitle.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'Wallet Connect' bottom sheet right networks icons is displayed") {
|
||||
onWalletConnectBottomSheet { networksIcons.assertIsDisplayed() }
|
||||
}
|
||||
step("'Wallet Connect' bottom sheet networks selector icon is displayed") {
|
||||
onWalletConnectBottomSheet { networksSelectorIcon.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'Wallet Connect' bottom sheet 'Cancel' button is displayed") {
|
||||
onWalletConnectBottomSheet { cancelButton.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'Wallet Connect' bottom sheet 'Connect' button is displayed") {
|
||||
onWalletConnectBottomSheet { connectButton.assertIsDisplayed() }
|
||||
}
|
||||
}
|
||||
|
||||
fun BaseTestCase.checkWalletConnectScreen() {
|
||||
step("Assert 'Wallet Connect' title is displayed") {
|
||||
onWalletConnectScreen { title.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'More' button is displayed") {
|
||||
onWalletConnectScreen { moreButton.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert wallet name is displayed") {
|
||||
onWalletConnectScreen { walletName.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert app icon is displayed") {
|
||||
onWalletConnectScreen { appIcon.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert app name is displayed") {
|
||||
onWalletConnectScreen { appName.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert approve icon is displayed") {
|
||||
onWalletConnectScreen { approveIcon.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert app URL is displayed") {
|
||||
onWalletConnectScreen { appUrl.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'New Connection' button is displayed") {
|
||||
onWalletConnectScreen { newConnectionButton.assertIsDisplayed() }
|
||||
}
|
||||
}
|
||||
|
||||
fun BaseTestCase.checkWalletConnectDetailsBottomSheet(dAppName: String) {
|
||||
step("Assert connection details title is displayed") {
|
||||
onWalletConnectDetailsBottomSheet { title.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert date is displayed") {
|
||||
onWalletConnectDetailsBottomSheet { date.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'Close' button is displayed") {
|
||||
onWalletConnectDetailsBottomSheet { closeButton.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert app icon is displayed") {
|
||||
onWalletConnectDetailsBottomSheet { appIcon.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert app name is displayed") {
|
||||
onWalletConnectDetailsBottomSheet { appName.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert approve icon is displayed") {
|
||||
onWalletConnectDetailsBottomSheet { approveIcon.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert app URL is displayed") {
|
||||
onWalletConnectDetailsBottomSheet { appUrl.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert wallet icon is displayed") {
|
||||
onWalletConnectDetailsBottomSheet { walletIcon.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert wallet title is displayed") {
|
||||
onWalletConnectDetailsBottomSheet { walletTitle.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert wallet name is displayed") {
|
||||
onWalletConnectDetailsBottomSheet { walletName.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'Connected networks' title is displayed") {
|
||||
onWalletConnectDetailsBottomSheet { connectedNetworksTitle.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert connected network item is displayed") {
|
||||
onWalletConnectDetailsBottomSheet { connectedNetworkItem.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert connected network icon is displayed") {
|
||||
onWalletConnectDetailsBottomSheet { connectedNetworkIcon.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert connected dApp name: '$dAppName'") {
|
||||
onWalletConnectDetailsBottomSheet { connectedNetworkName.assertTextContains(dAppName) }
|
||||
}
|
||||
step("Assert connected network symbol is displayed") {
|
||||
onWalletConnectDetailsBottomSheet { connectedNetworkSymbol.assertIsDisplayed() }
|
||||
}
|
||||
step("Assert 'Disconnect button' is displayed") {
|
||||
onWalletConnectDetailsBottomSheet { disconnectButton.assertIsDisplayed() }
|
||||
}
|
||||
}
|
||||
181
app/src/androidTest/kotlin/com/tangem/tests/WalletConnectTest.kt
Normal file
181
app/src/androidTest/kotlin/com/tangem/tests/WalletConnectTest.kt
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
package com.tangem.tests
|
||||
|
||||
import com.tangem.common.BaseTestCase
|
||||
import com.tangem.common.constants.TestConstants.TOTAL_BALANCE
|
||||
import com.tangem.common.extensions.clickWithAssertion
|
||||
import com.tangem.common.extensions.swipeUp
|
||||
import com.tangem.common.utils.getWcUri
|
||||
import com.tangem.scenarios.OpenMainScreenScenario
|
||||
import com.tangem.screens.*
|
||||
import com.tangem.steps.*
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import io.qameta.allure.kotlin.AllureId
|
||||
import io.qameta.allure.kotlin.junit4.DisplayName
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
|
||||
@HiltAndroidTest
|
||||
class WalletConnectTest : BaseTestCase() {
|
||||
|
||||
@AllureId("3833")
|
||||
@DisplayName("WC (React App): open session from deeplink on main screen")
|
||||
@Ignore("TODO [REDACTED_JIRA] React app deeplink doesn't work")
|
||||
@Test
|
||||
fun openWalletConnectSessionOnMainScreen() {
|
||||
val balance = TOTAL_BALANCE
|
||||
val dAppName = "React App"
|
||||
val deepLinkUri = getWcUri()
|
||||
|
||||
setupHooks().run {
|
||||
step("Open 'Main Screen'") {
|
||||
openMainScreen()
|
||||
}
|
||||
step("Synchronize addresses") {
|
||||
synchronizeAddresses(balance)
|
||||
}
|
||||
step("Create WC session buy deeplink") {
|
||||
openAppByDeepLink(deepLinkUri)
|
||||
}
|
||||
step("Check 'Wallet Connect' bottom sheet") {
|
||||
checkWalletConnectBottomSheet()
|
||||
}
|
||||
step("Click on 'Connect' button") {
|
||||
onWalletConnectBottomSheet { connectButton.performClick() }
|
||||
}
|
||||
step("Click 'More' button on TopBar") {
|
||||
onTopBar { moreButton.clickWithAssertion() }
|
||||
}
|
||||
step("Click on 'Wallet Connect' button") {
|
||||
onDetailsScreen { walletConnectButton.clickWithAssertion() }
|
||||
}
|
||||
step("Check 'Wallet Connect' screen") {
|
||||
checkWalletConnectScreen()
|
||||
}
|
||||
step("Click on app icon") {
|
||||
onWalletConnectScreen { appIcon.performClick() }
|
||||
}
|
||||
step("Check 'Wallet Connect' details bottom sheet") {
|
||||
checkWalletConnectDetailsBottomSheet(dAppName)
|
||||
}
|
||||
step("Click on 'Disconnect button' is displayed") {
|
||||
onWalletConnectDetailsBottomSheet { disconnectButton.performClick() }
|
||||
}
|
||||
step("Assert connection is not displayed") {
|
||||
onWalletConnectScreen { appName.assertIsNotDisplayed() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AllureId("3834")
|
||||
@DisplayName("WC (React App): open session from deeplink not on main screen")
|
||||
@Ignore("TODO [REDACTED_JIRA] React app deeplink doesn't work")
|
||||
@Test
|
||||
fun openWalletConnectSessionNotOnMainScreen() {
|
||||
val balance = TOTAL_BALANCE
|
||||
val dAppName = "React App"
|
||||
val deepLinkUri = getWcUri()
|
||||
|
||||
setupHooks().run {
|
||||
step("Open 'Main Screen'") {
|
||||
openMainScreen()
|
||||
}
|
||||
step("Synchronize addresses") {
|
||||
synchronizeAddresses(balance)
|
||||
}
|
||||
step("Click on 'Buy' button") {
|
||||
onMainScreen { buyButton.clickWithAssertion() }
|
||||
}
|
||||
step("Create WC session buy deeplink") {
|
||||
openAppByDeepLink(deepLinkUri)
|
||||
}
|
||||
step("Check 'Wallet Connect' bottom sheet") {
|
||||
checkWalletConnectBottomSheet()
|
||||
}
|
||||
step("Click on 'Connect' button") {
|
||||
onWalletConnectBottomSheet { connectButton.performClick() }
|
||||
}
|
||||
step("Click 'More' button on TopBar") {
|
||||
onTopBar { moreButton.clickWithAssertion() }
|
||||
}
|
||||
step("Click on 'Wallet Connect' button") {
|
||||
onDetailsScreen { walletConnectButton.clickWithAssertion() }
|
||||
}
|
||||
step("Assert 'Wallet Connect' bottom sheet is displayed") {
|
||||
onWalletConnectBottomSheet { connectButton.clickWithAssertion() }
|
||||
}
|
||||
step("Check 'Wallet Connect' screen") {
|
||||
checkWalletConnectScreen()
|
||||
}
|
||||
step("Click on app icon") {
|
||||
onWalletConnectScreen { appIcon.performClick() }
|
||||
}
|
||||
step("Check 'Wallet Connect' details bottom sheet") {
|
||||
checkWalletConnectDetailsBottomSheet(dAppName)
|
||||
}
|
||||
step("Click on 'Disconnect button' is displayed") {
|
||||
onWalletConnectDetailsBottomSheet { disconnectButton.performClick() }
|
||||
}
|
||||
step("Assert connection is not displayed") {
|
||||
onWalletConnectScreen { appName.assertIsNotDisplayed() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AllureId("886")
|
||||
@DisplayName("WC (React App): open session from deeplink ")
|
||||
@Ignore("TODO [REDACTED_JIRA] React app deeplink doesn't work")
|
||||
@Test
|
||||
fun openWalletConnectSession() {
|
||||
val balance = TOTAL_BALANCE
|
||||
val dAppName = "React App"
|
||||
val deepLinkUri = getWcUri()
|
||||
|
||||
setupHooks().run {
|
||||
step("Open 'Main Screen'") {
|
||||
openMainScreen()
|
||||
}
|
||||
step("Synchronize addresses") {
|
||||
synchronizeAddresses(balance)
|
||||
}
|
||||
step("Open recent apps") {
|
||||
device.uiDevice.pressRecentApps()
|
||||
}
|
||||
step("Stop app by swipe") {
|
||||
swipeUp(startHeightRatio = 0.8f)
|
||||
}
|
||||
step("Create WC session buy deeplink") {
|
||||
openAppByDeepLink(deepLinkUri)
|
||||
}
|
||||
step("Open 'Main Screen'") {
|
||||
scenario(OpenMainScreenScenario(composeTestRule))
|
||||
}
|
||||
step("Check 'Wallet Connect' bottom sheet") {
|
||||
checkWalletConnectBottomSheet()
|
||||
}
|
||||
step("Click on 'Connect' button") {
|
||||
onWalletConnectBottomSheet { connectButton.performClick() }
|
||||
}
|
||||
step("Click 'More' button on TopBar") {
|
||||
onTopBar { moreButton.clickWithAssertion() }
|
||||
}
|
||||
step("Click on 'Wallet Connect' button") {
|
||||
onDetailsScreen { walletConnectButton.clickWithAssertion() }
|
||||
}
|
||||
step("Check 'Wallet Connect' screen") {
|
||||
checkWalletConnectScreen()
|
||||
}
|
||||
step("Click on app icon") {
|
||||
onWalletConnectScreen { appIcon.performClick() }
|
||||
}
|
||||
step("Check 'Wallet Connect' details bottom sheet") {
|
||||
checkWalletConnectDetailsBottomSheet(dAppName)
|
||||
}
|
||||
step("Click on 'Disconnect button' is displayed") {
|
||||
onWalletConnectDetailsBottomSheet { disconnectButton.performClick() }
|
||||
}
|
||||
step("Assert connection is not displayed") {
|
||||
onWalletConnectScreen { appName.assertIsNotDisplayed() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.tap.data
|
||||
package com.tangem.tap
|
||||
|
||||
import com.google.firebase.messaging.FirebaseMessaging
|
||||
import com.tangem.utils.notifications.PushNotificationsTokenProvider
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.tap.di.data
|
||||
package com.tangem.tap.di
|
||||
|
||||
import com.tangem.tap.data.FirebasePushNotificationsTokenProvider
|
||||
import com.tangem.tap.FirebasePushNotificationsTokenProvider
|
||||
import com.tangem.utils.notifications.PushNotificationsTokenProvider
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
|
|
@ -10,7 +10,7 @@ import javax.inject.Singleton
|
|||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal interface PushNotificationsModule {
|
||||
internal interface GooglePushModule {
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
17
app/src/huawei/AndroidManifest.xml
Normal file
17
app/src/huawei/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<application>
|
||||
<service
|
||||
android:name="com.tangem.tap.HuaweiPushService"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="com.huawei.push.action.MESSAGING_EVENT" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<meta-data
|
||||
android:name="push_kit_auto_init_enabled"
|
||||
android:value="true" />
|
||||
</application>
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package com.tangem.tap
|
||||
|
||||
import android.content.Context
|
||||
import com.google.firebase.messaging.FirebaseMessaging
|
||||
import com.huawei.agconnect.AGConnectOptionsBuilder
|
||||
import com.huawei.hms.aaid.HmsInstanceId
|
||||
import com.huawei.hms.common.ApiException
|
||||
import com.tangem.google.GoogleServicesHelper
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.notifications.PushNotificationsTokenProvider
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.tasks.await
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class HuaweiPushNotificationsTokenProvider @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val coroutineDispatcherProvider: CoroutineDispatcherProvider,
|
||||
) : PushNotificationsTokenProvider {
|
||||
|
||||
override suspend fun getToken(): String {
|
||||
val isGoogleServicesAvailable = GoogleServicesHelper.checkGoogleServicesAvailability(context)
|
||||
return if (isGoogleServicesAvailable) {
|
||||
try {
|
||||
FirebaseMessaging.getInstance().token.await()
|
||||
} catch (ex: Exception) {
|
||||
Timber.e(ex)
|
||||
""
|
||||
}
|
||||
} else {
|
||||
withContext(coroutineDispatcherProvider.io) {
|
||||
try {
|
||||
val appId = AGConnectOptionsBuilder().build(context).getString(APP_ID_KEY)
|
||||
val token = HmsInstanceId.getInstance(context).getToken(appId, TOKEN_REQUEST_MODE)
|
||||
Timber.i("Requested token from HuaweiService: $token")
|
||||
token
|
||||
} catch (e: ApiException) {
|
||||
Timber.i("Fetching token from HuaweiService failed cause: ${e.message}")
|
||||
""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val APP_ID_KEY = "client/app_id"
|
||||
private const val TOKEN_REQUEST_MODE = "HCM"
|
||||
}
|
||||
}
|
||||
47
app/src/huawei/java/com/tangem/tap/HuaweiPushService.kt
Normal file
47
app/src/huawei/java/com/tangem/tap/HuaweiPushService.kt
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
package com.tangem.tap
|
||||
|
||||
import android.os.Bundle
|
||||
import com.huawei.hms.push.HmsMessageService
|
||||
import com.huawei.hms.push.RemoteMessage
|
||||
import com.tangem.google.GoogleServicesHelper
|
||||
import com.tangem.tap.common.pushes.PushNotificationDelegate
|
||||
import timber.log.Timber
|
||||
|
||||
class HuaweiPushService : HmsMessageService() {
|
||||
|
||||
private val pushNotificationDelegate: PushNotificationDelegate by lazy {
|
||||
PushNotificationDelegate(applicationContext)
|
||||
}
|
||||
|
||||
override fun onNewToken(token: String?, bundle: Bundle?) {
|
||||
super.onNewToken(token, bundle)
|
||||
Timber.i("HuaweiPushService: On new token from HuaweiService: $token")
|
||||
}
|
||||
|
||||
override fun onTokenError(e: Exception?, bundle: Bundle?) {
|
||||
super.onTokenError(e, bundle)
|
||||
Timber.i("HuaweiPushService: Fetching token from HuaweiService failed cause: ${e?.message}")
|
||||
}
|
||||
|
||||
override fun onMessageReceived(message: RemoteMessage?) {
|
||||
super.onMessageReceived(message)
|
||||
val isGoogleServicesAvailable = GoogleServicesHelper.checkGoogleServicesAvailability(this)
|
||||
if (isGoogleServicesAvailable) return
|
||||
val notification = message?.notification ?: return
|
||||
val channelId = notification.channelId ?: TANGEM_CHANNEL_ID
|
||||
|
||||
pushNotificationDelegate.showNotification(
|
||||
dataMap = message.dataOfMap,
|
||||
title = notification.title,
|
||||
body = notification.body,
|
||||
channelId = channelId,
|
||||
priority = message.urgency,
|
||||
imageUrl = notification.imageUrl,
|
||||
vibratePattern = notification.vibrateConfig,
|
||||
)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val TANGEM_CHANNEL_ID = "Tangem General" // General channel for notifications
|
||||
}
|
||||
}
|
||||
18
app/src/huawei/java/com/tangem/tap/di/HuaweiPushModule.kt
Normal file
18
app/src/huawei/java/com/tangem/tap/di/HuaweiPushModule.kt
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
package com.tangem.tap.di
|
||||
|
||||
import com.tangem.tap.HuaweiPushNotificationsTokenProvider
|
||||
import com.tangem.utils.notifications.PushNotificationsTokenProvider
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal interface HuaweiPushModule {
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindPushNotificationsTokenProvider(impl: HuaweiPushNotificationsTokenProvider): PushNotificationsTokenProvider
|
||||
}
|
||||
|
|
@ -1,160 +1,165 @@
|
|||
{
|
||||
"coins" : [
|
||||
"coins": [
|
||||
{
|
||||
"id" : "matic-token",
|
||||
"symbol" : "MATIC",
|
||||
"name" : "Polygon",
|
||||
"networks" : [
|
||||
"id": "matic-token",
|
||||
"symbol": "MATIC",
|
||||
"name": "Polygon",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "polygon-pos/test",
|
||||
"contractAddress" : "0x0000000000000000000000000000000000001010",
|
||||
"decimalCount" : 18
|
||||
"networkId": "polygon-pos/test",
|
||||
"contractAddress": "0x0000000000000000000000000000000000001010",
|
||||
"decimalCount": 18
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "kaspa",
|
||||
"symbol" : "KAS",
|
||||
"name" : "Kaspa",
|
||||
"networks" : [
|
||||
"id": "kaspa",
|
||||
"symbol": "KAS",
|
||||
"name": "Kaspa",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "kaspa/test"
|
||||
"networkId": "kaspa/test"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "Dai Stablecoin-DAI",
|
||||
"symbol" : "DAI",
|
||||
"name" : "Dai Stablecoin",
|
||||
"networks" : [
|
||||
"id": "Dai Stablecoin-DAI",
|
||||
"symbol": "DAI",
|
||||
"name": "Dai Stablecoin",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "polygon-pos/test",
|
||||
"contractAddress" : "0xcB1e72786A6eb3b44C2a2429e317c8a2462CFeb1",
|
||||
"decimalCount" : 18
|
||||
"networkId": "polygon-pos/test",
|
||||
"contractAddress": "0xcB1e72786A6eb3b44C2a2429e317c8a2462CFeb1",
|
||||
"decimalCount": 18
|
||||
},
|
||||
{
|
||||
"networkId" : "binance-smart-chain/test",
|
||||
"contractAddress" : "0xec5dcb5dbf4b114c9d0f65bccab49ec54f6a0867",
|
||||
"decimalCount" : 18
|
||||
"networkId": "binance-smart-chain/test",
|
||||
"contractAddress": "0xec5dcb5dbf4b114c9d0f65bccab49ec54f6a0867",
|
||||
"decimalCount": 18
|
||||
},
|
||||
{
|
||||
"networkId" : "binance-smart-chain/test",
|
||||
"contractAddress" : "0x8a9424745056eb399fd19a0ec26a14316684e274",
|
||||
"decimalCount" : 18
|
||||
"networkId": "binance-smart-chain/test",
|
||||
"contractAddress": "0x8a9424745056eb399fd19a0ec26a14316684e274",
|
||||
"decimalCount": 18
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "Dummy ERC20-DERC20",
|
||||
"symbol" : "DERC20",
|
||||
"name" : "Dummy ERC20",
|
||||
"networks" : [
|
||||
"id": "Dummy ERC20-DERC20",
|
||||
"symbol": "DERC20",
|
||||
"name": "Dummy ERC20",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "polygon-pos/test",
|
||||
"contractAddress" : "0xfe4F5145f6e09952a5ba9e956ED0C25e3Fa4c7F1",
|
||||
"decimalCount" : 18
|
||||
"networkId": "polygon-pos/test",
|
||||
"contractAddress": "0xfe4F5145f6e09952a5ba9e956ED0C25e3Fa4c7F1",
|
||||
"decimalCount": 18
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "Ether-ETH",
|
||||
"symbol" : "ETH",
|
||||
"name" : "Ether",
|
||||
"networks" : [
|
||||
"id": "Ether-ETH",
|
||||
"symbol": "ETH",
|
||||
"name": "Ether",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "polygon-pos/test",
|
||||
"contractAddress" : "0x714550C2C1Ea08688607D86ed8EeF4f5E4F22323",
|
||||
"decimalCount" : 18
|
||||
"networkId": "polygon-pos/test",
|
||||
"contractAddress": "0x714550C2C1Ea08688607D86ed8EeF4f5E4F22323",
|
||||
"decimalCount": 18
|
||||
},
|
||||
{
|
||||
"networkId" : "binance-smart-chain/test",
|
||||
"contractAddress" : "0xd66c6b4f0be8ce5b39d52e0fd1344c389929b378",
|
||||
"decimalCount" : 18
|
||||
"networkId": "binance-smart-chain/test",
|
||||
"contractAddress": "0xd66c6b4f0be8ce5b39d52e0fd1344c389929b378",
|
||||
"decimalCount": 18
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "Test Token-TST",
|
||||
"symbol" : "TST",
|
||||
"name" : "Test Token",
|
||||
"networks" : [
|
||||
"id": "Test Token-TST",
|
||||
"symbol": "TST",
|
||||
"name": "Test Token",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "polygon-pos/test",
|
||||
"contractAddress" : "0x2d7882bedcbfddce29ba99965dd3cdf7fcb10a1e",
|
||||
"decimalCount" : 18
|
||||
"networkId": "polygon-pos/test",
|
||||
"contractAddress": "0x2d7882bedcbfddce29ba99965dd3cdf7fcb10a1e",
|
||||
"decimalCount": 18
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "tether",
|
||||
"symbol" : "USDT",
|
||||
"name" : "Tether USD",
|
||||
"networks" : [
|
||||
"id": "tether",
|
||||
"symbol": "USDT",
|
||||
"name": "Tether USD",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "polygon-pos/test",
|
||||
"contractAddress" : "0x3813e82e6f7098b9583FC0F33a962D02018B6803",
|
||||
"decimalCount" : 6
|
||||
"networkId": "ethereum/test",
|
||||
"contractAddress": "0xaA8E23Fb1079EA71e0a56F48a2aA51851D8433D0",
|
||||
"decimalCount": 18
|
||||
},
|
||||
{
|
||||
"networkId" : "binance-smart-chain/test",
|
||||
"contractAddress" : "0x337610d27c682e347c9cd60bd4b3b107c9d34ddd",
|
||||
"decimalCount" : 18
|
||||
"networkId": "polygon-pos/test",
|
||||
"contractAddress": "0x3813e82e6f7098b9583FC0F33a962D02018B6803",
|
||||
"decimalCount": 6
|
||||
},
|
||||
{
|
||||
"networkId" : "tron/test",
|
||||
"contractAddress" : "TXLAQ63Xg1NAzckPwKHvzw7CSEmLMEqcdj",
|
||||
"decimalCount" : 6
|
||||
"networkId": "binance-smart-chain/test",
|
||||
"contractAddress": "0x337610d27c682e347c9cd60bd4b3b107c9d34ddd",
|
||||
"decimalCount": 18
|
||||
},
|
||||
{
|
||||
"networkId" : "binance-smart-chain/test",
|
||||
"contractAddress" : "0x7ef95a0fee0dd31b22626fa2e10ee6a223f8a684",
|
||||
"decimalCount" : 18
|
||||
"networkId": "tron/test",
|
||||
"contractAddress": "TXLAQ63Xg1NAzckPwKHvzw7CSEmLMEqcdj",
|
||||
"decimalCount": 6
|
||||
},
|
||||
{
|
||||
"networkId": "binance-smart-chain/test",
|
||||
"contractAddress": "0x7ef95a0fee0dd31b22626fa2e10ee6a223f8a684",
|
||||
"decimalCount": 18
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "just-gov",
|
||||
"symbol" : "JST",
|
||||
"name" : "JUST GOV",
|
||||
"networks" : [
|
||||
"id": "just-gov",
|
||||
"symbol": "JST",
|
||||
"name": "JUST GOV",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "tron/test",
|
||||
"contractAddress" : "TF17BgPaZYbz8oxbjhriubPDsA7ArKoLX3",
|
||||
"decimalCount" : 18
|
||||
"networkId": "tron/test",
|
||||
"contractAddress": "TF17BgPaZYbz8oxbjhriubPDsA7ArKoLX3",
|
||||
"decimalCount": 18
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "Wrapped Ether-WETH",
|
||||
"symbol" : "WETH",
|
||||
"name" : "Wrapped Ether",
|
||||
"networks" : [
|
||||
"id": "Wrapped Ether-WETH",
|
||||
"symbol": "WETH",
|
||||
"name": "Wrapped Ether",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "polygon-pos/test",
|
||||
"contractAddress" : "0xA6FA4fB5f76172d178d61B04b0ecd319C5d1C0aa",
|
||||
"decimalCount" : 18
|
||||
"networkId": "polygon-pos/test",
|
||||
"contractAddress": "0xA6FA4fB5f76172d178d61B04b0ecd319C5d1C0aa",
|
||||
"decimalCount": 18
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "Wrapped Matic-WMATIC",
|
||||
"symbol" : "WMATIC",
|
||||
"name" : "Wrapped Matic",
|
||||
"networks" : [
|
||||
"id": "Wrapped Matic-WMATIC",
|
||||
"symbol": "WMATIC",
|
||||
"name": "Wrapped Matic",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "polygon-pos/test",
|
||||
"contractAddress" : "0xd0A1E359811322d97991E03f863a0C30C2cF029C",
|
||||
"decimalCount" : 18
|
||||
"networkId": "polygon-pos/test",
|
||||
"contractAddress": "0xd0A1E359811322d97991E03f863a0C30C2cF029C",
|
||||
"decimalCount": 18
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "solana",
|
||||
"symbol" : "SOL",
|
||||
"name" : "Solana",
|
||||
"networks" : [
|
||||
"id": "solana",
|
||||
"symbol": "SOL",
|
||||
"name": "Solana",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "solana/test"
|
||||
"networkId": "solana/test"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -162,263 +167,262 @@
|
|||
"id": "the-open-network",
|
||||
"symbol": "TON",
|
||||
"name": "Toncoin",
|
||||
"networks":
|
||||
[
|
||||
"networks": [
|
||||
{
|
||||
"networkId": "the-open-network/test"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "Tangem Coin A-TCA",
|
||||
"symbol" : "TCA",
|
||||
"name" : "Tangem Coin A",
|
||||
"networks" : [
|
||||
"id": "Tangem Coin A-TCA",
|
||||
"symbol": "TCA",
|
||||
"name": "Tangem Coin A",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "solana/test",
|
||||
"contractAddress" : "22PTNbX31Zuztd6nD82fC8nQdT2hUfWv9XWXKuDkrFqR",
|
||||
"decimalCount" : 9
|
||||
"networkId": "solana/test",
|
||||
"contractAddress": "22PTNbX31Zuztd6nD82fC8nQdT2hUfWv9XWXKuDkrFqR",
|
||||
"decimalCount": 9
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "Tangem Coin B-TCB",
|
||||
"symbol" : "TCB",
|
||||
"name" : "Tangem Coin B",
|
||||
"networks" : [
|
||||
"id": "Tangem Coin B-TCB",
|
||||
"symbol": "TCB",
|
||||
"name": "Tangem Coin B",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "solana/test",
|
||||
"contractAddress" : "HmSghNPg6KCk711YJA92aPejt8auyFkvmaED6jbHfUs4",
|
||||
"decimalCount" : 9
|
||||
"networkId": "solana/test",
|
||||
"contractAddress": "HmSghNPg6KCk711YJA92aPejt8auyFkvmaED6jbHfUs4",
|
||||
"decimalCount": 9
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "binancecoin",
|
||||
"symbol" : "BNB",
|
||||
"name" : "Binance",
|
||||
"networks" : [
|
||||
"id": "binancecoin",
|
||||
"symbol": "BNB",
|
||||
"name": "Binance",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "binancecoin/test"
|
||||
"networkId": "binancecoin/test"
|
||||
},
|
||||
{
|
||||
"networkId" : "binance-smart-chain/test"
|
||||
"networkId": "binance-smart-chain/test"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "Hemster - 452-HEM",
|
||||
"symbol" : "HEM",
|
||||
"name" : "Hemster - 452",
|
||||
"networks" : [
|
||||
"id": "Hemster - 452-HEM",
|
||||
"symbol": "HEM",
|
||||
"name": "Hemster - 452",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "binancecoin/test",
|
||||
"contractAddress" : "HEM-452",
|
||||
"decimalCount" : 8
|
||||
"networkId": "binancecoin/test",
|
||||
"contractAddress": "HEM-452",
|
||||
"decimalCount": 8
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "Binance-Peg BTCB Token-BTCB",
|
||||
"symbol" : "BTCB",
|
||||
"name" : "Binance-Peg BTCB Token",
|
||||
"networks" : [
|
||||
"id": "Binance-Peg BTCB Token-BTCB",
|
||||
"symbol": "BTCB",
|
||||
"name": "Binance-Peg BTCB Token",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "binance-smart-chain/test",
|
||||
"contractAddress" : "0x6ce8da28e2f864420840cf74474eff5fd80e65b8",
|
||||
"decimalCount" : 18
|
||||
"networkId": "binance-smart-chain/test",
|
||||
"contractAddress": "0x6ce8da28e2f864420840cf74474eff5fd80e65b8",
|
||||
"decimalCount": 18
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "Binance-Peg BUSD Token-BUSD",
|
||||
"symbol" : "BUSD",
|
||||
"name" : "Binance-Peg BUSD Token",
|
||||
"networks" : [
|
||||
"id": "Binance-Peg BUSD Token-BUSD",
|
||||
"symbol": "BUSD",
|
||||
"name": "Binance-Peg BUSD Token",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "binance-smart-chain/test",
|
||||
"contractAddress" : "0xed24fc36d5ee211ea25a80239fb8c4cfd80f12ee",
|
||||
"decimalCount" : 18
|
||||
"networkId": "binance-smart-chain/test",
|
||||
"contractAddress": "0xed24fc36d5ee211ea25a80239fb8c4cfd80f12ee",
|
||||
"decimalCount": 18
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "Binance-Peg USDC Token-USDC",
|
||||
"symbol" : "USDC",
|
||||
"name" : "Binance-Peg USDC Token",
|
||||
"networks" : [
|
||||
"id": "Binance-Peg USDC Token-USDC",
|
||||
"symbol": "USDC",
|
||||
"name": "Binance-Peg USDC Token",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "binance-smart-chain/test",
|
||||
"contractAddress" : "0x64544969ed7ebf5f083679233325356ebe738930",
|
||||
"decimalCount" : 18
|
||||
"networkId": "binance-smart-chain/test",
|
||||
"contractAddress": "0x64544969ed7ebf5f083679233325356ebe738930",
|
||||
"decimalCount": 18
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "Binance-Peg XRP-XRP",
|
||||
"symbol" : "XRP",
|
||||
"name" : "Binance-Peg XRP",
|
||||
"networks" : [
|
||||
"id": "Binance-Peg XRP-XRP",
|
||||
"symbol": "XRP",
|
||||
"name": "Binance-Peg XRP",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "binance-smart-chain/test",
|
||||
"contractAddress" : "0xa83575490d7df4e2f47b7d38ef351a2722ca45b9",
|
||||
"decimalCount" : 18
|
||||
"networkId": "binance-smart-chain/test",
|
||||
"contractAddress": "0xa83575490d7df4e2f47b7d38ef351a2722ca45b9",
|
||||
"decimalCount": 18
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "ethereum",
|
||||
"symbol" : "ETH",
|
||||
"name" : "Ethereum",
|
||||
"networks" : [
|
||||
"id": "ethereum",
|
||||
"symbol": "ETH",
|
||||
"name": "Ethereum",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "ethereum/test"
|
||||
"networkId": "ethereum/test"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "ethereum-classic",
|
||||
"symbol" : "ETC",
|
||||
"name" : "Ethereum Classic",
|
||||
"networks" : [
|
||||
"id": "ethereum-classic",
|
||||
"symbol": "ETC",
|
||||
"name": "Ethereum Classic",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "ethereum-classic/test"
|
||||
"networkId": "ethereum-classic/test"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "Weenus-WEENUS",
|
||||
"symbol" : "WEENUS",
|
||||
"name" : "Weenus",
|
||||
"networks" : [
|
||||
"id": "Weenus-WEENUS",
|
||||
"symbol": "WEENUS",
|
||||
"name": "Weenus",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "ethereum/test",
|
||||
"contractAddress" : "0xaFF4481D10270F50f203E0763e2597776068CBc5",
|
||||
"decimalCount" : 18
|
||||
"networkId": "ethereum/test",
|
||||
"contractAddress": "0xaFF4481D10270F50f203E0763e2597776068CBc5",
|
||||
"decimalCount": 18
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "Xeenus-XEENUS",
|
||||
"symbol" : "XEENUS",
|
||||
"name" : "Xeenus",
|
||||
"networks" : [
|
||||
"id": "Xeenus-XEENUS",
|
||||
"symbol": "XEENUS",
|
||||
"name": "Xeenus",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "ethereum/test",
|
||||
"contractAddress" : "0x022E292b44B5a146F2e8ee36Ff44D3dd863C915c",
|
||||
"decimalCount" : 18
|
||||
"networkId": "ethereum/test",
|
||||
"contractAddress": "0x022E292b44B5a146F2e8ee36Ff44D3dd863C915c",
|
||||
"decimalCount": 18
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "Yeenus-YEENUS",
|
||||
"symbol" : "YEENUS",
|
||||
"name" : "Yeenus",
|
||||
"networks" : [
|
||||
"id": "Yeenus-YEENUS",
|
||||
"symbol": "YEENUS",
|
||||
"name": "Yeenus",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "ethereum/test",
|
||||
"contractAddress" : "0xc6fDe3FD2Cc2b173aEC24cc3f267cb3Cd78a26B7",
|
||||
"decimalCount" : 8
|
||||
"networkId": "ethereum/test",
|
||||
"contractAddress": "0xc6fDe3FD2Cc2b173aEC24cc3f267cb3Cd78a26B7",
|
||||
"decimalCount": 8
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "Zeenus-ZEENUS",
|
||||
"symbol" : "ZEENUS",
|
||||
"name" : "Zeenus",
|
||||
"networks" : [
|
||||
"id": "Zeenus-ZEENUS",
|
||||
"symbol": "ZEENUS",
|
||||
"name": "Zeenus",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "ethereum/test",
|
||||
"contractAddress" : "0x1f9061B953bBa0E36BF50F21876132DcF276fC6e",
|
||||
"decimalCount" : 0
|
||||
"networkId": "ethereum/test",
|
||||
"contractAddress": "0x1f9061B953bBa0E36BF50F21876132DcF276fC6e",
|
||||
"decimalCount": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "avalanche-2",
|
||||
"symbol" : "AVAX",
|
||||
"name" : "Avalanche",
|
||||
"networks" : [
|
||||
"id": "avalanche-2",
|
||||
"symbol": "AVAX",
|
||||
"name": "Avalanche",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "avalanche/test"
|
||||
"networkId": "avalanche/test"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "The Fuji stablecoin-FUJISTABLE",
|
||||
"symbol" : "FUJISTABLE",
|
||||
"name" : "The Fuji stablecoin",
|
||||
"networks" : [
|
||||
"id": "The Fuji stablecoin-FUJISTABLE",
|
||||
"symbol": "FUJISTABLE",
|
||||
"name": "The Fuji stablecoin",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "avalanche/test",
|
||||
"contractAddress" : "0x2058ec2791dD28b6f67DB836ddf87534F4Bbdf22",
|
||||
"decimalCount" : 6
|
||||
"networkId": "avalanche/test",
|
||||
"contractAddress": "0x2058ec2791dD28b6f67DB836ddf87534F4Bbdf22",
|
||||
"decimalCount": 6
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "To the Moon-FUJIMOON",
|
||||
"symbol" : "FUJIMOON",
|
||||
"name" : "To the Moon",
|
||||
"networks" : [
|
||||
"id": "To the Moon-FUJIMOON",
|
||||
"symbol": "FUJIMOON",
|
||||
"name": "To the Moon",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "avalanche/test",
|
||||
"contractAddress" : "0x97132C109c6816525F7f338DCb7435E1412A7668",
|
||||
"decimalCount" : 9
|
||||
"networkId": "avalanche/test",
|
||||
"contractAddress": "0x97132C109c6816525F7f338DCb7435E1412A7668",
|
||||
"decimalCount": 9
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "fantom",
|
||||
"symbol" : "FTM",
|
||||
"name" : "Fantom",
|
||||
"networks" : [
|
||||
"id": "fantom",
|
||||
"symbol": "FTM",
|
||||
"name": "Fantom",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "fantom/test"
|
||||
"networkId": "fantom/test"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "Fantom USD-FUSD",
|
||||
"symbol" : "FUSD",
|
||||
"name" : "Fantom USD",
|
||||
"networks" : [
|
||||
"id": "Fantom USD-FUSD",
|
||||
"symbol": "FUSD",
|
||||
"name": "Fantom USD",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "fantom/test",
|
||||
"contractAddress" : "0x91ea991bd52EE3C40EdA2509701d905e1Ee54074",
|
||||
"decimalCount" : 18
|
||||
"networkId": "fantom/test",
|
||||
"contractAddress": "0x91ea991bd52EE3C40EdA2509701d905e1Ee54074",
|
||||
"decimalCount": 18
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "Wrapped Fantom-WFTM",
|
||||
"symbol" : "WFTM",
|
||||
"name" : "Wrapped Fantom",
|
||||
"networks" : [
|
||||
"id": "Wrapped Fantom-WFTM",
|
||||
"symbol": "WFTM",
|
||||
"name": "Wrapped Fantom",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "fantom/test",
|
||||
"contractAddress" : "0xf1277d1Ed8AD466beddF92ef448A132661956621",
|
||||
"decimalCount" : 18
|
||||
"networkId": "fantom/test",
|
||||
"contractAddress": "0xf1277d1Ed8AD466beddF92ef448A132661956621",
|
||||
"decimalCount": 18
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "bitcoin",
|
||||
"symbol" : "BTC",
|
||||
"name" : "Bitcoin",
|
||||
"networks" : [
|
||||
"id": "bitcoin",
|
||||
"symbol": "BTC",
|
||||
"name": "Bitcoin",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "bitcoin/test"
|
||||
"networkId": "bitcoin/test"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "vechain",
|
||||
"symbol" : "VET",
|
||||
"name" : "VeChain",
|
||||
"networks" : [
|
||||
"id": "vechain",
|
||||
"symbol": "VET",
|
||||
"name": "VeChain",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "vechain/test"
|
||||
"networkId": "vechain/test"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -435,34 +439,34 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"id" : "tron",
|
||||
"symbol" : "TRX",
|
||||
"name" : "Tron",
|
||||
"networks" : [
|
||||
{
|
||||
"networkId" : "tron/test"
|
||||
}
|
||||
]
|
||||
"id": "tron",
|
||||
"symbol": "TRX",
|
||||
"name": "Tron",
|
||||
"networks": [
|
||||
{
|
||||
"networkId": "tron/test"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "algorand",
|
||||
"symbol" : "ALGO",
|
||||
"name" : "Algorand",
|
||||
"networks" : [
|
||||
{
|
||||
"networkId" : "algorand/test"
|
||||
}
|
||||
]
|
||||
"id": "algorand",
|
||||
"symbol": "ALGO",
|
||||
"name": "Algorand",
|
||||
"networks": [
|
||||
{
|
||||
"networkId": "algorand/test"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id" : "arbitrum-one",
|
||||
"symbol" : "ETH",
|
||||
"name" : "Arbitrum",
|
||||
"networks" : [
|
||||
{
|
||||
"networkId" : "arbitrum-one/test"
|
||||
}
|
||||
]
|
||||
"id": "arbitrum-one",
|
||||
"symbol": "ETH",
|
||||
"name": "Arbitrum",
|
||||
"networks": [
|
||||
{
|
||||
"networkId": "arbitrum-one/test"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "stellar",
|
||||
|
|
@ -485,12 +489,12 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"id" : "polkadot",
|
||||
"symbol" : "DOT",
|
||||
"name" : "Polkadot",
|
||||
"networks" : [
|
||||
"id": "polkadot",
|
||||
"symbol": "DOT",
|
||||
"name": "Polkadot",
|
||||
"networks": [
|
||||
{
|
||||
"networkId" : "polkadot/test"
|
||||
"networkId": "polkadot/test"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -509,8 +513,7 @@
|
|||
"id": "kava",
|
||||
"symbol": "KAVA",
|
||||
"name": "Kava EVM",
|
||||
"networks":
|
||||
[
|
||||
"networks": [
|
||||
{
|
||||
"networkId": "kava/test"
|
||||
}
|
||||
|
|
@ -520,8 +523,7 @@
|
|||
"id": "telos",
|
||||
"symbol": "TLOS",
|
||||
"name": "Telos EVM",
|
||||
"networks":
|
||||
[
|
||||
"networks": [
|
||||
{
|
||||
"networkId": "telos/test"
|
||||
}
|
||||
|
|
@ -531,8 +533,7 @@
|
|||
"id": "ravencoin",
|
||||
"symbol": "RVN",
|
||||
"name": "Ravencoin",
|
||||
"networks":
|
||||
[
|
||||
"networks": [
|
||||
{
|
||||
"networkId": "ravencoin/test"
|
||||
}
|
||||
|
|
@ -542,8 +543,7 @@
|
|||
"id": "cosmos",
|
||||
"symbol": "ATOM",
|
||||
"name": "Cosmos Hub",
|
||||
"networks":
|
||||
[
|
||||
"networks": [
|
||||
{
|
||||
"networkId": "cosmos/test"
|
||||
}
|
||||
|
|
@ -798,6 +798,30 @@
|
|||
"networkId": "alephium/test"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "chainlink",
|
||||
"name": "Chainlink",
|
||||
"symbol": "LINK",
|
||||
"networks": [
|
||||
{
|
||||
"networkId": "ethereum/test",
|
||||
"contractAddress": "0xf8Fb3713D459D7C1018BD0A49D19b4C44290EBE5",
|
||||
"decimalCount": 18
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "gho",
|
||||
"name": "GHO",
|
||||
"symbol": "GHO",
|
||||
"networks": [
|
||||
{
|
||||
"networkId": "ethereum/test",
|
||||
"contractAddress": "0xc4bF5CbDaBE595361438F8c6a187bDc330539c60",
|
||||
"decimalCount": 18
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository
|
|||
import com.tangem.domain.card.ScanCardProcessor
|
||||
import com.tangem.domain.card.repository.CardRepository
|
||||
import com.tangem.domain.core.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.feedback.GetCardInfoUseCase
|
||||
import com.tangem.domain.feedback.GetWalletMetaInfoUseCase
|
||||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||
import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase
|
||||
import com.tangem.domain.onboarding.WasTwinsOnboardingShownUseCase
|
||||
|
|
@ -107,7 +107,7 @@ interface ApplicationEntryPoint {
|
|||
|
||||
fun getSendFeedbackEmailUseCase(): SendFeedbackEmailUseCase
|
||||
|
||||
fun getGetCardInfoUseCase(): GetCardInfoUseCase
|
||||
fun getWalletMetaInfoUseCase(): GetWalletMetaInfoUseCase
|
||||
|
||||
fun getUrlOpener(): UrlOpener
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository
|
|||
import com.tangem.domain.card.ScanCardProcessor
|
||||
import com.tangem.domain.card.repository.CardRepository
|
||||
import com.tangem.domain.common.LogConfig
|
||||
import com.tangem.domain.feedback.GetCardInfoUseCase
|
||||
import com.tangem.domain.feedback.GetWalletMetaInfoUseCase
|
||||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||
import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase
|
||||
import com.tangem.domain.onboarding.WasTwinsOnboardingShownUseCase
|
||||
|
|
@ -77,6 +77,7 @@ import com.tangem.wallet.BuildConfig
|
|||
import dagger.hilt.EntryPoints
|
||||
import kotlinx.coroutines.*
|
||||
import org.rekotlin.Store
|
||||
import timber.log.Timber
|
||||
import com.tangem.tap.domain.walletconnect2.domain.LegacyWalletConnectRepository as WalletConnect2Repository
|
||||
|
||||
lateinit var store: Store<AppState>
|
||||
|
|
@ -165,8 +166,8 @@ abstract class TangemApplication : Application(), ImageLoaderFactory, Configurat
|
|||
private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase
|
||||
get() = entryPoint.getSendFeedbackEmailUseCase()
|
||||
|
||||
private val getCardInfoUseCase: GetCardInfoUseCase
|
||||
get() = entryPoint.getGetCardInfoUseCase()
|
||||
private val getWalletMetaInfoUseCase: GetWalletMetaInfoUseCase
|
||||
get() = entryPoint.getWalletMetaInfoUseCase()
|
||||
|
||||
private val urlOpener
|
||||
get() = entryPoint.getUrlOpener()
|
||||
|
|
@ -289,15 +290,16 @@ abstract class TangemApplication : Application(), ImageLoaderFactory, Configurat
|
|||
|
||||
tangemAppLoggerInitializer.initialize()
|
||||
|
||||
Timber.i("APP STARTED")
|
||||
if (BuildConfig.TESTER_MENU_ENABLED) {
|
||||
Timber.i(featureTogglesManager.toString())
|
||||
Timber.i(excludedBlockchainsManager.toString())
|
||||
}
|
||||
|
||||
foregroundActivityObserver = ForegroundActivityObserver()
|
||||
registerActivityLifecycleCallbacks(foregroundActivityObserver.callbacks)
|
||||
|
||||
// We need to initialize the toggles and excludedBlockchainsManager before the MainActivity starts using them.
|
||||
runBlocking {
|
||||
awaitAll(
|
||||
async { featureTogglesManager.init() },
|
||||
async { excludedBlockchainsManager.init() },
|
||||
)
|
||||
initWithConfigDependency(environmentConfig = environmentConfigStorage.initialize())
|
||||
}
|
||||
|
||||
|
|
@ -357,7 +359,7 @@ abstract class TangemApplication : Application(), ImageLoaderFactory, Configurat
|
|||
settingsRepository = settingsRepository,
|
||||
blockchainSDKFactory = blockchainSDKFactory,
|
||||
sendFeedbackEmailUseCase = sendFeedbackEmailUseCase,
|
||||
getCardInfoUseCase = getCardInfoUseCase,
|
||||
getWalletMetaInfoUseCase = getWalletMetaInfoUseCase,
|
||||
issuersConfigStorage = issuersConfigStorage,
|
||||
urlOpener = urlOpener,
|
||||
shareManager = shareManager,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
package com.tangem.tap.common.buildconfig
|
||||
|
||||
import com.tangem.utils.buildConfig.AppConfigurationProvider
|
||||
import com.tangem.wallet.BuildConfig
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
internal class AppConfigurationProviderImpl @Inject constructor() : AppConfigurationProvider {
|
||||
|
||||
override fun isDebug(): Boolean = BuildConfig.BUILD_TYPE == "debug"
|
||||
override fun isHuawei(): Boolean = BuildConfig.FLAVOR_NAME == "huawei"
|
||||
}
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
package com.tangem.tap.common.pushes
|
||||
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import coil.executeBlocking
|
||||
import coil.request.ImageRequest
|
||||
import com.tangem.domain.common.LogConfig
|
||||
import com.tangem.tap.MainActivity
|
||||
import com.tangem.tap.common.images.createCoilImageLoader
|
||||
import com.tangem.tap.features.intentHandler.handlers.OnPushClickedIntentHandler
|
||||
import com.tangem.wallet.R
|
||||
|
||||
class PushNotificationDelegate(private val context: Context) {
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
fun showNotification(
|
||||
dataMap: Map<String, String>,
|
||||
title: String?,
|
||||
body: String?,
|
||||
channelId: String,
|
||||
priority: Int,
|
||||
imageUrl: Uri? = null,
|
||||
vibratePattern: LongArray?,
|
||||
) {
|
||||
val intent = Intent(context, MainActivity::class.java).apply {
|
||||
dataMap.forEach { (key, value) ->
|
||||
putExtra(key, value)
|
||||
}
|
||||
putExtra(OnPushClickedIntentHandler.OPENED_FROM_GCM_PUSH, true)
|
||||
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
}
|
||||
|
||||
val pendingIntent = PendingIntent.getActivity(
|
||||
/* context = */ context,
|
||||
/* requestCode = */ PUSH_NOTIFICATION_REQUEST_CODE,
|
||||
/* intent = */ intent,
|
||||
/* flags = */ PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE,
|
||||
)
|
||||
|
||||
val notificationBuilder = NotificationCompat.Builder(context, channelId)
|
||||
.setSmallIcon(R.drawable.ic_tangem_24)
|
||||
.setContentTitle(title)
|
||||
.setContentText(body)
|
||||
.setPriority(priority)
|
||||
.setAutoCancel(true)
|
||||
.setContentIntent(pendingIntent)
|
||||
.setVibrate(vibratePattern)
|
||||
.apply {
|
||||
imageUrl?.let { uri ->
|
||||
val bitmap = getBitmapImageFromUrl(uri)
|
||||
setStyle(
|
||||
NotificationCompat
|
||||
.BigPictureStyle()
|
||||
.bigPicture(bitmap),
|
||||
).setLargeIcon(bitmap)
|
||||
}
|
||||
}
|
||||
|
||||
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val notificationChannel = NotificationChannel(
|
||||
channelId,
|
||||
ContextCompat.getString(context, R.string.tangem_app_name),
|
||||
NotificationManager.IMPORTANCE_HIGH,
|
||||
)
|
||||
notificationManager.createNotificationChannel(notificationChannel)
|
||||
}
|
||||
|
||||
// Generating unique notification id
|
||||
val uniqueId = (System.currentTimeMillis() % Integer.MAX_VALUE).toInt()
|
||||
|
||||
notificationManager.notify(
|
||||
/* id = */ uniqueId,
|
||||
/* notification = */ notificationBuilder.build(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun getBitmapImageFromUrl(url: Uri): Bitmap? {
|
||||
return createCoilImageLoader(
|
||||
context,
|
||||
logEnabled = LogConfig.imageLoader,
|
||||
).executeBlocking(
|
||||
ImageRequest.Builder(context)
|
||||
.data(url)
|
||||
.build(),
|
||||
).drawable?.toBitmap()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val PUSH_NOTIFICATION_REQUEST_CODE = 123
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +1,17 @@
|
|||
package com.tangem.tap.common.pushes
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import coil.executeBlocking
|
||||
import coil.request.ImageRequest
|
||||
import com.google.firebase.messaging.FirebaseMessagingService
|
||||
import com.google.firebase.messaging.RemoteMessage
|
||||
import com.tangem.domain.common.LogConfig
|
||||
import com.tangem.tap.MainActivity
|
||||
import com.tangem.tap.common.images.createCoilImageLoader
|
||||
import com.tangem.tap.features.intentHandler.handlers.OnPushClickedIntentHandler
|
||||
import com.tangem.wallet.R
|
||||
import timber.log.Timber
|
||||
|
||||
@SuppressLint("MissingFirebaseInstanceTokenRefresh")
|
||||
internal class TangemPushNotificationService : FirebaseMessagingService() {
|
||||
|
||||
private val pushNotificationDelegate: PushNotificationDelegate by lazy {
|
||||
PushNotificationDelegate(applicationContext)
|
||||
}
|
||||
|
||||
override fun onNewToken(token: String) {
|
||||
super.onNewToken(token)
|
||||
Timber.d("New FCM token received: $token")
|
||||
|
|
@ -36,73 +23,18 @@ internal class TangemPushNotificationService : FirebaseMessagingService() {
|
|||
val notification = message.notification ?: return
|
||||
val channelId = notification.channelId ?: TANGEM_CHANNEL_ID
|
||||
|
||||
val intent = Intent(applicationContext, MainActivity::class.java).apply {
|
||||
message.data.forEach {
|
||||
putExtra(it.key, it.value)
|
||||
}
|
||||
putExtra(OnPushClickedIntentHandler.OPENED_FROM_GCM_PUSH, true)
|
||||
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
}
|
||||
val pendingIntent = PendingIntent.getActivity(
|
||||
/* context = */ this,
|
||||
/* requestCode = */ PUSH_NOTIFICATION_REQUEST_CODE,
|
||||
/* intent = */ intent,
|
||||
/* flags = */ PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE,
|
||||
pushNotificationDelegate.showNotification(
|
||||
dataMap = message.data,
|
||||
title = notification.title,
|
||||
body = notification.body,
|
||||
channelId = channelId,
|
||||
priority = message.priority,
|
||||
imageUrl = notification.imageUrl,
|
||||
vibratePattern = notification.vibrateTimings,
|
||||
)
|
||||
|
||||
val notificationBuilder =
|
||||
NotificationCompat.Builder(applicationContext, channelId)
|
||||
.setSmallIcon(R.drawable.ic_tangem_24)
|
||||
.setContentTitle(notification.title)
|
||||
.setContentText(notification.body)
|
||||
.setPriority(message.priority)
|
||||
.setAutoCancel(true)
|
||||
.setContentIntent(pendingIntent)
|
||||
.setVibrate(notification.vibrateTimings)
|
||||
.apply {
|
||||
notification.imageUrl?.let { uri ->
|
||||
val bitmap = getBitmapImageFromUrl(uri)
|
||||
setStyle(
|
||||
NotificationCompat
|
||||
.BigPictureStyle()
|
||||
.bigPicture(bitmap),
|
||||
).setLargeIcon(bitmap)
|
||||
}
|
||||
}
|
||||
|
||||
val notificationManager = applicationContext.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val notificationChannel = NotificationChannel(
|
||||
channelId,
|
||||
ContextCompat.getString(applicationContext, R.string.tangem_app_name),
|
||||
NotificationManager.IMPORTANCE_HIGH,
|
||||
)
|
||||
notificationManager.createNotificationChannel(notificationChannel)
|
||||
}
|
||||
|
||||
// Generating unique notification id
|
||||
val uniqueId = (System.currentTimeMillis() % Integer.MAX_VALUE).toInt()
|
||||
|
||||
notificationManager.notify(
|
||||
/* id = */ uniqueId,
|
||||
/* notification = */ notificationBuilder.build(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun getBitmapImageFromUrl(url: Uri): Bitmap? {
|
||||
return createCoilImageLoader(
|
||||
applicationContext,
|
||||
logEnabled = LogConfig.imageLoader,
|
||||
).executeBlocking(
|
||||
ImageRequest.Builder(applicationContext)
|
||||
.data(url)
|
||||
.build(),
|
||||
).drawable?.toBitmap()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val TANGEM_CHANNEL_ID = "Tangem General" // General channel for notifications
|
||||
const val PUSH_NOTIFICATION_REQUEST_CODE = 123
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package com.tangem.tap.data
|
||||
|
||||
import android.content.Context
|
||||
import com.tangem.datasource.local.visa.TangemPayStorage
|
||||
import com.tangem.sdk.storage.AndroidSecureStorageV2
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
private const val DEFAULT_KEY = "tangem_pay_default_key"
|
||||
|
||||
@Singleton
|
||||
internal class DefaultTangemPayStorage @Inject constructor(
|
||||
@ApplicationContext applicationContext: Context,
|
||||
private val dispatcherProvider: CoroutineDispatcherProvider,
|
||||
) : TangemPayStorage {
|
||||
|
||||
private val secureStorage by lazy {
|
||||
AndroidSecureStorageV2(
|
||||
appContext = applicationContext,
|
||||
useStrongBox = false,
|
||||
name = "tangem_pay_storage",
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun store(authHeader: String) = withContext(dispatcherProvider.io) {
|
||||
secureStorage.store(authHeader.encodeToByteArray(throwOnInvalidSequence = true), DEFAULT_KEY)
|
||||
}
|
||||
|
||||
override suspend fun get(): String? = withContext(dispatcherProvider.io) {
|
||||
secureStorage.get(DEFAULT_KEY)?.decodeToString(throwOnInvalidSequence = true)
|
||||
}
|
||||
|
||||
override suspend fun clear() = withContext(dispatcherProvider.io) {
|
||||
secureStorage.delete(DEFAULT_KEY)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.tangem.tap.di
|
||||
|
||||
import com.tangem.tap.common.buildconfig.AppConfigurationProviderImpl
|
||||
import com.tangem.utils.buildConfig.AppConfigurationProvider
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal interface AppConfigurationModule {
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindAppConfigurationProvider(impl: AppConfigurationProviderImpl): AppConfigurationProvider
|
||||
}
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
package com.tangem.tap.di.data
|
||||
|
||||
import com.tangem.datasource.local.visa.TangemPayStorage
|
||||
import com.tangem.datasource.local.visa.VisaAuthTokenStorage
|
||||
import com.tangem.datasource.local.visa.VisaOTPStorage
|
||||
import com.tangem.tap.data.DefaultTangemPayStorage
|
||||
import com.tangem.tap.data.DefaultVisaAuthTokenStorage
|
||||
import com.tangem.tap.data.DefaultVisaOTPStorage
|
||||
import dagger.Binds
|
||||
|
|
@ -21,4 +23,8 @@ internal interface VisaStorageModule {
|
|||
@Binds
|
||||
@Singleton
|
||||
fun bindVisaOTPStorage(impl: DefaultVisaOTPStorage): VisaOTPStorage
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindTangemPayStorage(impl: DefaultTangemPayStorage): TangemPayStorage
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package com.tangem.tap.di.domain
|
||||
|
||||
import android.content.Context
|
||||
import com.tangem.domain.feedback.GetCardInfoUseCase
|
||||
import com.tangem.domain.feedback.GetWalletMetaInfoUseCase
|
||||
import com.tangem.domain.feedback.SaveBlockchainErrorUseCase
|
||||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||
import com.tangem.domain.feedback.repository.FeedbackRepository
|
||||
|
|
@ -18,8 +18,8 @@ internal object FeedbackDomainModule {
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideGetCardInfoUseCase(feedbackRepository: FeedbackRepository): GetCardInfoUseCase {
|
||||
return GetCardInfoUseCase(feedbackRepository = feedbackRepository)
|
||||
fun provideGetCardInfoUseCase(feedbackRepository: FeedbackRepository): GetWalletMetaInfoUseCase {
|
||||
return GetWalletMetaInfoUseCase(feedbackRepository = feedbackRepository)
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import com.tangem.domain.nft.repository.NFTRepository
|
|||
import com.tangem.domain.quotes.single.SingleQuoteStatusFetcher
|
||||
import com.tangem.domain.quotes.single.SingleQuoteStatusSupplier
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
|
||||
import com.tangem.domain.tokens.TokensFeatureToggles
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
|
|
@ -33,29 +32,21 @@ internal object NFTDomainModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
fun providesFetchNFTCollectionsUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
nftRepository: NFTRepository,
|
||||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles: TokensFeatureToggles,
|
||||
): FetchNFTCollectionsUseCase = FetchNFTCollectionsUseCase(
|
||||
currenciesRepository = currenciesRepository,
|
||||
nftRepository = nftRepository,
|
||||
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles = tokensFeatureToggles,
|
||||
)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesRefreshAllNFTUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
nftRepository: NFTRepository,
|
||||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles: TokensFeatureToggles,
|
||||
): RefreshAllNFTUseCase = RefreshAllNFTUseCase(
|
||||
currenciesRepository = currenciesRepository,
|
||||
nftRepository = nftRepository,
|
||||
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles = tokensFeatureToggles,
|
||||
)
|
||||
|
||||
@Provides
|
||||
|
|
@ -127,16 +118,12 @@ internal object NFTDomainModule {
|
|||
fun provideDisableWalletNFTUseCase(
|
||||
walletsRepository: WalletsRepository,
|
||||
nftRepository: NFTRepository,
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles: TokensFeatureToggles,
|
||||
): DisableWalletNFTUseCase {
|
||||
return DisableWalletNFTUseCase(
|
||||
walletsRepository = walletsRepository,
|
||||
nftRepository = nftRepository,
|
||||
currenciesRepository = currenciesRepository,
|
||||
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles = tokensFeatureToggles,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -120,6 +120,12 @@ internal object OnrampDomainModule {
|
|||
return OnrampSaveTransactionUseCase(onrampTransactionRepository, onrampErrorResolver)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideOnrampSepaAvailableUseCase(onrampRepository: OnrampRepository): OnrampSepaAvailableUseCase {
|
||||
return OnrampSepaAvailableUseCase(onrampRepository)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideOnrampUpdateTransactionStatusUseCase(
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@ internal object TokensDomainModule {
|
|||
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
singleYieldBalanceFetcher: SingleYieldBalanceFetcher,
|
||||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles: TokensFeatureToggles,
|
||||
stakingIdFactory: StakingIdFactory,
|
||||
): AddCryptoCurrenciesUseCase {
|
||||
return AddCryptoCurrenciesUseCase(
|
||||
|
|
@ -56,7 +55,6 @@ internal object TokensDomainModule {
|
|||
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
|
||||
singleYieldBalanceFetcher = singleYieldBalanceFetcher,
|
||||
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles = tokensFeatureToggles,
|
||||
stakingIdFactory = stakingIdFactory,
|
||||
)
|
||||
}
|
||||
|
|
@ -111,13 +109,11 @@ internal object TokensDomainModule {
|
|||
currenciesRepository: CurrenciesRepository,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles: TokensFeatureToggles,
|
||||
): RemoveCurrencyUseCase {
|
||||
return RemoveCurrencyUseCase(
|
||||
currenciesRepository = currenciesRepository,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles = tokensFeatureToggles,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -156,7 +152,6 @@ internal object TokensDomainModule {
|
|||
dispatchers: CoroutineDispatcherProvider,
|
||||
baseCurrencyStatusOperations: BaseCurrencyStatusOperations,
|
||||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles: TokensFeatureToggles,
|
||||
): GetCurrencyWarningsUseCase {
|
||||
return GetCurrencyWarningsUseCase(
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
|
|
@ -165,7 +160,6 @@ internal object TokensDomainModule {
|
|||
currencyChecksRepository = currencyChecksRepository,
|
||||
currencyStatusOperations = baseCurrencyStatusOperations,
|
||||
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles = tokensFeatureToggles,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -177,7 +171,6 @@ internal object TokensDomainModule {
|
|||
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
singleYieldBalanceFetcher: SingleYieldBalanceFetcher,
|
||||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles: TokensFeatureToggles,
|
||||
stakingIdFactory: StakingIdFactory,
|
||||
): FetchCurrencyStatusUseCase {
|
||||
return FetchCurrencyStatusUseCase(
|
||||
|
|
@ -186,7 +179,6 @@ internal object TokensDomainModule {
|
|||
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
|
||||
singleYieldBalanceFetcher = singleYieldBalanceFetcher,
|
||||
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles = tokensFeatureToggles,
|
||||
stakingIdFactory = stakingIdFactory,
|
||||
)
|
||||
}
|
||||
|
|
@ -214,9 +206,8 @@ internal object TokensDomainModule {
|
|||
fun provideGetCryptoCurrencyUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles: TokensFeatureToggles,
|
||||
): GetCryptoCurrencyUseCase {
|
||||
return GetCryptoCurrencyUseCase(currenciesRepository, multiWalletCryptoCurrenciesSupplier, tokensFeatureToggles)
|
||||
return GetCryptoCurrencyUseCase(currenciesRepository, multiWalletCryptoCurrenciesSupplier)
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
|
@ -238,13 +229,11 @@ internal object TokensDomainModule {
|
|||
fun provideApplyTokenListSortingUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles: TokensFeatureToggles,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): ApplyTokenListSortingUseCase {
|
||||
return ApplyTokenListSortingUseCase(
|
||||
currenciesRepository = currenciesRepository,
|
||||
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles = tokensFeatureToggles,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
|
|
@ -304,14 +293,10 @@ internal object TokensDomainModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
fun provideIsCryptoCurrencyCoinCouldHideUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles: TokensFeatureToggles,
|
||||
): IsCryptoCurrencyCoinCouldHideUseCase {
|
||||
return IsCryptoCurrencyCoinCouldHideUseCase(
|
||||
currenciesRepository = currenciesRepository,
|
||||
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles = tokensFeatureToggles,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -330,13 +315,11 @@ internal object TokensDomainModule {
|
|||
fun provideGetBalanceNotEnoughForFeeWarningUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles: TokensFeatureToggles,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): GetBalanceNotEnoughForFeeWarningUseCase {
|
||||
return GetBalanceNotEnoughForFeeWarningUseCase(
|
||||
currenciesRepository = currenciesRepository,
|
||||
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles = tokensFeatureToggles,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
|
|
@ -377,16 +360,12 @@ internal object TokensDomainModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
fun provideRefreshMultiCurrencyWalletQuotesUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles: TokensFeatureToggles,
|
||||
): RefreshMultiCurrencyWalletQuotesUseCase {
|
||||
return RefreshMultiCurrencyWalletQuotesUseCase(
|
||||
currenciesRepository = currenciesRepository,
|
||||
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
|
||||
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles = tokensFeatureToggles,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -402,18 +381,13 @@ internal object TokensDomainModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
fun provideBaseCurrencyStatusOperations(
|
||||
tokensFeatureToggles: TokensFeatureToggles,
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
quotesRepository: QuotesRepository,
|
||||
singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
|
||||
multiNetworkStatusSupplier: MultiNetworkStatusSupplier,
|
||||
multiNetworkStatusFetcher: MultiNetworkStatusFetcher,
|
||||
singleNetworkStatusFetcher: SingleNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher: MultiQuoteStatusFetcher,
|
||||
singleQuoteStatusSupplier: SingleQuoteStatusSupplier,
|
||||
singleYieldBalanceSupplier: SingleYieldBalanceSupplier,
|
||||
multiYieldBalanceSupplier: MultiYieldBalanceSupplier,
|
||||
multiYieldBalanceFetcher: MultiYieldBalanceFetcher,
|
||||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
stakingIdFactory: StakingIdFactory,
|
||||
): BaseCurrencyStatusOperations {
|
||||
|
|
@ -422,15 +396,10 @@ internal object TokensDomainModule {
|
|||
quotesRepository = quotesRepository,
|
||||
singleNetworkStatusSupplier = singleNetworkStatusSupplier,
|
||||
multiNetworkStatusSupplier = multiNetworkStatusSupplier,
|
||||
multiNetworkStatusFetcher = multiNetworkStatusFetcher,
|
||||
singleNetworkStatusFetcher = singleNetworkStatusFetcher,
|
||||
multiQuoteStatusFetcher = multiQuoteStatusFetcher,
|
||||
singleQuoteStatusSupplier = singleQuoteStatusSupplier,
|
||||
singleYieldBalanceSupplier = singleYieldBalanceSupplier,
|
||||
multiYieldBalanceSupplier = multiYieldBalanceSupplier,
|
||||
multiYieldBalanceFetcher = multiYieldBalanceFetcher,
|
||||
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles = tokensFeatureToggles,
|
||||
stakingIdFactory = stakingIdFactory,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ import com.tangem.domain.demo.models.DemoConfig
|
|||
import com.tangem.domain.networks.single.SingleNetworkStatusFetcher
|
||||
import com.tangem.domain.networks.single.SingleNetworkStatusSupplier
|
||||
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
|
||||
import com.tangem.domain.tokens.TokensFeatureToggles
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.transaction.FeeRepository
|
||||
import com.tangem.domain.transaction.TransactionRepository
|
||||
import com.tangem.domain.transaction.WalletAddressServiceRepository
|
||||
|
|
@ -63,18 +61,14 @@ internal object TransactionDomainModule {
|
|||
fun provideAssociateAssetUseCase(
|
||||
cardSdkConfigRepository: CardSdkConfigRepository,
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
singleNetworkStatusSupplier: SingleNetworkStatusSupplier,
|
||||
multiWalletCryptoCurrenciesSupplier: MultiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles: TokensFeatureToggles,
|
||||
): AssociateAssetUseCase {
|
||||
return AssociateAssetUseCase(
|
||||
cardSdkConfigRepository = cardSdkConfigRepository,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
currenciesRepository = currenciesRepository,
|
||||
singleNetworkStatusSupplier = singleNetworkStatusSupplier,
|
||||
multiWalletCryptoCurrenciesSupplier = multiWalletCryptoCurrenciesSupplier,
|
||||
tokensFeatureToggles = tokensFeatureToggles,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import dagger.hilt.InstallIn
|
|||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Suppress("TooManyFunctions")
|
||||
@Suppress("TooManyFunctions", "LargeClass")
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal object WalletsDomainModule {
|
||||
|
|
@ -352,4 +352,24 @@ internal object WalletsDomainModule {
|
|||
walletsRepository = walletsRepository,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesIsUpgradeWalletNotificationEnabledUseCase(
|
||||
walletsRepository: WalletsRepository,
|
||||
): IsUpgradeWalletNotificationEnabledUseCase {
|
||||
return IsUpgradeWalletNotificationEnabledUseCase(
|
||||
walletsRepository = walletsRepository,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesDismissUpgradeWalletNotificationUseCase(
|
||||
walletsRepository: WalletsRepository,
|
||||
): DismissUpgradeWalletNotificationUseCase {
|
||||
return DismissUpgradeWalletNotificationUseCase(
|
||||
walletsRepository = walletsRepository,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.tap.di.hot
|
||||
|
||||
import com.tangem.data.wallets.hot.DefaultHotWalletAccessor
|
||||
import com.tangem.domain.wallets.hot.HotWalletAccessor
|
||||
import com.tangem.hot.sdk.TangemHotSdk
|
||||
import com.tangem.tap.features.hot.TangemHotSDKProxy
|
||||
import dagger.Binds
|
||||
|
|
@ -15,4 +17,8 @@ internal interface TangemHotSdkModule {
|
|||
@Binds
|
||||
@Singleton
|
||||
fun bindTangemHotSdk(proxy: TangemHotSDKProxy): TangemHotSdk
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindHotWalletAccessor(default: DefaultHotWalletAccessor): HotWalletAccessor
|
||||
}
|
||||
|
|
@ -265,7 +265,7 @@ internal class LegacyScanProcessor @Inject constructor(
|
|||
onOk = { mainScope.launch { onSuccess() } },
|
||||
onSupportClick = {
|
||||
val cardInfo =
|
||||
store.inject(DaggerGraphState::getCardInfoUseCase).invoke(scanResponse).getOrNull()
|
||||
store.inject(DaggerGraphState::getWalletMetaInfoUseCase).invoke(scanResponse).getOrNull()
|
||||
?: error("CardInfo must be not null")
|
||||
|
||||
scope.launch {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import com.tangem.domain.models.scan.CardDTO
|
|||
import com.tangem.domain.visa.error.VisaActivationError
|
||||
import com.tangem.domain.visa.model.*
|
||||
import com.tangem.domain.visa.repository.VisaActivationRepository
|
||||
import com.tangem.domain.visa.repository.VisaAuthRepository
|
||||
import com.tangem.domain.visa.datasource.VisaAuthRemoteDataSource
|
||||
import com.tangem.operations.GenerateOTPCommand
|
||||
import com.tangem.operations.attestation.AttestCardKeyCommand
|
||||
import com.tangem.operations.pins.SetUserCodeCommand
|
||||
|
|
@ -46,7 +46,7 @@ class VisaCardActivationTask @AssistedInject constructor(
|
|||
@Assisted private val coroutineScope: CoroutineScope,
|
||||
private val otpStorage: VisaOTPStorage,
|
||||
private val visaAuthTokenStorage: VisaAuthTokenStorage,
|
||||
private val visaAuthRepository: VisaAuthRepository,
|
||||
private val visaAuthRemoteDataSource: VisaAuthRemoteDataSource,
|
||||
private val visaActivationRepositoryFactory: VisaActivationRepository.Factory,
|
||||
) : CardSessionRunnable<VisaCardActivationResponse> {
|
||||
|
||||
|
|
@ -168,7 +168,7 @@ class VisaCardActivationTask @AssistedInject constructor(
|
|||
signedChallenge: VisaAuthSignedChallenge,
|
||||
cardWalletAddress: String,
|
||||
): Either<TangemError, VisaDataToSignByCardWallet> = either {
|
||||
val tokens = visaAuthRepository.getAccessTokens(signedChallenge)
|
||||
val tokens = visaAuthRemoteDataSource.getAccessTokens(signedChallenge)
|
||||
.getOrElse { raise(it.tangemError) }
|
||||
|
||||
visaAuthTokenStorage.store(cardId, tokens)
|
||||
|
|
|
|||
|
|
@ -4,9 +4,5 @@ import com.tangem.core.configtoggle.feature.FeatureTogglesManager
|
|||
import com.tangem.domain.tokens.TokensFeatureToggles
|
||||
|
||||
internal class DefaultTokensFeatureToggles(
|
||||
private val featureTogglesManager: FeatureTogglesManager,
|
||||
) : TokensFeatureToggles {
|
||||
|
||||
override val isWalletBalanceFetcherEnabled: Boolean
|
||||
get() = featureTogglesManager.isFeatureEnabled(name = "WALLET_BALANCE_FETCHER_ENABLED")
|
||||
}
|
||||
@Suppress("UnusedPrivateMember") private val featureTogglesManager: FeatureTogglesManager,
|
||||
) : TokensFeatureToggles
|
||||
|
|
@ -62,7 +62,7 @@ internal class DefaultUserWalletsListRepository(
|
|||
// If we don't save persistent information, we don't need to load user wallets
|
||||
// and we should clear any existing data
|
||||
clearPersistentData()
|
||||
userWallets.value = emptyList()
|
||||
updateWallets { emptyList() }
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -118,7 +118,7 @@ internal class DefaultUserWalletsListRepository(
|
|||
}
|
||||
|
||||
// update the userWallets state and add if it doesn't exist
|
||||
userWallets.update { currentWallets ->
|
||||
updateWallets { currentWallets ->
|
||||
val wallets = currentWallets ?: emptyList()
|
||||
if (wallets.any { it.walletId == userWallet.walletId }) {
|
||||
wallets.map { if (it.walletId == userWallet.walletId) userWallet else it }
|
||||
|
|
@ -248,7 +248,7 @@ internal class DefaultUserWalletsListRepository(
|
|||
removePasswordAttempts(userWallet)
|
||||
|
||||
sensitiveInformationRepository.getAll(listOf(encryptionKey))
|
||||
.doOnSuccess { sensitiveInfo -> userWallets.update { it?.updateWith(sensitiveInfo) } }
|
||||
.doOnSuccess { sensitiveInfo -> updateWallets { it?.updateWith(sensitiveInfo) } }
|
||||
.doOnFailure { error ->
|
||||
raise(UnlockWalletError.UnableToUnlock)
|
||||
}
|
||||
|
|
@ -306,7 +306,7 @@ internal class DefaultUserWalletsListRepository(
|
|||
|
||||
sensitiveInformationRepository.getAll(allKeys)
|
||||
.doOnSuccess { sensitiveInfo ->
|
||||
userWallets.update { it?.updateWith(sensitiveInfo) }
|
||||
updateWallets { it?.updateWith(sensitiveInfo) }
|
||||
}
|
||||
.doOnFailure { raise(UnlockWalletError.UnableToUnlock) }
|
||||
}
|
||||
|
|
@ -318,7 +318,7 @@ internal class DefaultUserWalletsListRepository(
|
|||
raise(LockWalletsError.NothingToLock)
|
||||
}
|
||||
|
||||
userWallets.update {
|
||||
updateWallets {
|
||||
it?.map {
|
||||
if (it.walletId !in unsecuredWalletIds) {
|
||||
it.lock()
|
||||
|
|
@ -389,6 +389,15 @@ internal class DefaultUserWalletsListRepository(
|
|||
return tangemSdkManagerProvider.invoke().canUseBiometry && useBiometricAuthentication
|
||||
}
|
||||
|
||||
private fun updateWallets(block: (List<UserWallet>?) -> List<UserWallet>?) {
|
||||
userWallets.update(block)
|
||||
|
||||
selectedUserWallet.update { currentSelected ->
|
||||
if (currentSelected == null) return@update null
|
||||
userWallets.value?.find { it.walletId == currentSelected.walletId }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the nearest available wallet that can be selected
|
||||
*
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import com.tangem.domain.visa.error.VisaApiError
|
|||
import com.tangem.domain.visa.error.VisaCardScanError
|
||||
import com.tangem.domain.visa.model.*
|
||||
import com.tangem.domain.visa.repository.VisaActivationRepository
|
||||
import com.tangem.domain.visa.repository.VisaAuthRepository
|
||||
import com.tangem.domain.visa.datasource.VisaAuthRemoteDataSource
|
||||
import com.tangem.operations.attestation.AttestCardKeyCommand
|
||||
import com.tangem.operations.attestation.AttestCardKeyResponse
|
||||
import com.tangem.operations.attestation.AttestWalletKeyResponse
|
||||
|
|
@ -26,7 +26,7 @@ import javax.inject.Inject
|
|||
import kotlin.coroutines.resume
|
||||
|
||||
internal class VisaCardScanHandler @Inject constructor(
|
||||
private val visaAuthRepository: VisaAuthRepository,
|
||||
private val visaAuthRemoteDataSource: VisaAuthRemoteDataSource,
|
||||
private val visaActivationRepositoryFactory: VisaActivationRepository.Factory,
|
||||
private val visaAuthTokenStorage: VisaAuthTokenStorage,
|
||||
) {
|
||||
|
|
@ -83,7 +83,7 @@ internal class VisaCardScanHandler @Inject constructor(
|
|||
|
||||
Timber.i("Requesting challenge for wallet authorization")
|
||||
|
||||
val challengeResponse = visaAuthRepository.getCardWalletAuthChallenge(
|
||||
val challengeResponse = visaAuthRemoteDataSource.getCardWalletAuthChallenge(
|
||||
cardId = card.cardId,
|
||||
// This is the wallet public key, not the address and it's alright, as the API expects it in this format
|
||||
cardWalletAddress = wallet.publicKey.toHexString(),
|
||||
|
|
@ -122,7 +122,7 @@ internal class VisaCardScanHandler @Inject constructor(
|
|||
cardWalletAddress: String,
|
||||
signedChallenge: VisaAuthSignedChallenge,
|
||||
): CompletionResult<VisaCardActivationStatus> {
|
||||
val authorizationTokensResponse = visaAuthRepository.getAccessTokens(signedChallenge = signedChallenge)
|
||||
val authorizationTokensResponse = visaAuthRemoteDataSource.getAccessTokens(signedChallenge = signedChallenge)
|
||||
.getOrElse {
|
||||
Timber.i("Failed to get Access token for Wallet public key authorization.")
|
||||
return if (
|
||||
|
|
@ -149,7 +149,7 @@ internal class VisaCardScanHandler @Inject constructor(
|
|||
|
||||
Timber.i("Requesting authorization challenge to sign")
|
||||
|
||||
val challengeResponse = visaAuthRepository.getCardAuthChallenge(
|
||||
val challengeResponse = visaAuthRemoteDataSource.getCardAuthChallenge(
|
||||
cardId = card.cardId,
|
||||
cardPublicKey = card.cardPublicKey.toHexString(),
|
||||
).getOrElse {
|
||||
|
|
@ -174,7 +174,7 @@ internal class VisaCardScanHandler @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
val authorizationTokensResponse = visaAuthRepository.getAccessTokens(
|
||||
val authorizationTokensResponse = visaAuthRemoteDataSource.getAccessTokens(
|
||||
signedChallenge = challengeResponse.toSignedChallenge(
|
||||
signedChallenge = attestCardKeyResponse.cardSignature.toHexString(),
|
||||
salt = attestCardKeyResponse.salt.toHexString(),
|
||||
|
|
|
|||
|
|
@ -47,6 +47,14 @@ class WalletConnectSdkHelper {
|
|||
store.inject(DaggerGraphState::generalUserWalletsListManager)
|
||||
}
|
||||
|
||||
private val userWalletsListRepository by lazy {
|
||||
store.inject(DaggerGraphState::userWalletsListRepository)
|
||||
}
|
||||
|
||||
private val hotWalletFeatureToggles by lazy {
|
||||
store.inject(DaggerGraphState::hotWalletFeatureToggles)
|
||||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
suspend fun prepareTransactionData(data: EthTransactionData): WcTransactionData {
|
||||
val transaction = data.transaction
|
||||
|
|
@ -128,13 +136,13 @@ class WalletConnectSdkHelper {
|
|||
)
|
||||
}
|
||||
|
||||
fun isDemoCard(): Boolean {
|
||||
val userWallet = userWalletsListManager.selectedUserWalletSync ?: return false
|
||||
suspend fun isDemoCard(): Boolean {
|
||||
val userWallet = getSelectedWallet() ?: return false
|
||||
return userWallet is UserWallet.Cold && userWallet.scanResponse.isDemoCard()
|
||||
}
|
||||
|
||||
private suspend fun getWalletManager(blockchain: Blockchain, derivationPath: String?): WalletManager? {
|
||||
val userWallet = userWalletsListManager.selectedUserWalletSync ?: return null
|
||||
val userWallet = getSelectedWallet() ?: return null
|
||||
val walletManagerFacade = store.inject(DaggerGraphState::walletManagersFacade)
|
||||
return walletManagerFacade.getOrCreateWalletManager(
|
||||
userWalletId = userWallet.walletId,
|
||||
|
|
@ -481,6 +489,14 @@ class WalletConnectSdkHelper {
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun getSelectedWallet(): UserWallet? {
|
||||
return if (hotWalletFeatureToggles.isHotWalletEnabled) {
|
||||
userWalletsListRepository.selectedUserWalletSync()
|
||||
} else {
|
||||
userWalletsListManager.selectedUserWalletSync
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSolanaResultString(signedHash: ByteArray) = "{ signature: \"${signedHash.encodeBase58()}\" }"
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.tap.features.details.redux.walletconnect
|
|||
import com.tangem.blockchain.common.WalletManager
|
||||
import com.tangem.blockchainsdk.utils.toNetworkId
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.tap.common.extensions.dispatchNavigationAction
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
|
|
@ -183,9 +184,19 @@ class WalletConnectMiddleware {
|
|||
|
||||
private suspend fun getWalletManagers(): List<WalletManager> {
|
||||
val walletManagerFacade = store.inject(DaggerGraphState::walletManagersFacade)
|
||||
val userWalletsListManager = store.inject(DaggerGraphState::generalUserWalletsListManager)
|
||||
val userWallet = userWalletsListManager.selectedUserWalletSync ?: return emptyList()
|
||||
|
||||
val userWallet = getSelectedWallet() ?: return emptyList()
|
||||
return walletManagerFacade.getStoredWalletManagers(userWallet.walletId)
|
||||
}
|
||||
|
||||
private suspend fun getSelectedWallet(): UserWallet? {
|
||||
val userWalletsListManager = store.inject(DaggerGraphState::generalUserWalletsListManager)
|
||||
val userWalletsListRepository = store.inject(DaggerGraphState::userWalletsListRepository)
|
||||
val hotWalletFeatureToggles = store.inject(DaggerGraphState::hotWalletFeatureToggles)
|
||||
|
||||
return if (hotWalletFeatureToggles.isHotWalletEnabled) {
|
||||
userWalletsListRepository.selectedUserWalletSync()
|
||||
} else {
|
||||
userWalletsListManager.selectedUserWalletSync
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,6 +18,7 @@ import com.tangem.domain.wallets.legacy.asLockable
|
|||
import com.tangem.domain.wallets.usecase.DeleteWalletUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.features.hotwallet.HotWalletFeatureToggles
|
||||
import com.tangem.tap.common.analytics.events.Settings
|
||||
import com.tangem.tap.common.extensions.dispatchNavigationAction
|
||||
import com.tangem.tap.common.extensions.onUserWalletSelected
|
||||
|
|
@ -50,6 +51,7 @@ internal class ResetCardModel @Inject constructor(
|
|||
private val userWalletsListManager: UserWalletsListManager,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val cardSettingsInteractor: CardSettingsInteractor,
|
||||
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
) : Model() {
|
||||
|
||||
private val params = paramsContainer.require<ResetCardComponent.Params>()
|
||||
|
|
@ -259,16 +261,20 @@ internal class ResetCardModel @Inject constructor(
|
|||
private fun finishFullReset() {
|
||||
cardSettingsInteractor.clear()
|
||||
|
||||
val newSelectedWallet = userWalletsListManager.selectedUserWalletSync
|
||||
val newSelectedWallet = getSelectedWalletSyncUseCase.invoke().getOrNull()
|
||||
|
||||
if (newSelectedWallet != null) {
|
||||
store.dispatchNavigationAction { popTo<AppRoute.Wallet>() }
|
||||
} else {
|
||||
val isLocked = runCatching { userWalletsListManager.asLockable()?.isLockedSync }.isSuccess
|
||||
if (isLocked && userWalletsListManager.hasUserWallets) {
|
||||
store.dispatchNavigationAction { popTo<AppRoute.Welcome>() }
|
||||
} else {
|
||||
if (hotWalletFeatureToggles.isHotWalletEnabled) {
|
||||
store.dispatchNavigationAction { replaceAll(AppRoute.Home()) }
|
||||
} else {
|
||||
val isLocked = runCatching { userWalletsListManager.asLockable()?.isLockedSync }.isSuccess
|
||||
if (isLocked && userWalletsListManager.hasUserWallets) {
|
||||
store.dispatchNavigationAction { popTo<AppRoute.Welcome>() }
|
||||
} else {
|
||||
store.dispatchNavigationAction { replaceAll(AppRoute.Home()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
|||
import com.tangem.domain.balancehiding.ListenToFlipsUseCase
|
||||
import com.tangem.domain.balancehiding.UpdateBalanceHidingSettingsUseCase
|
||||
import com.tangem.domain.common.LogConfig
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.notifications.GetApplicationIdUseCase
|
||||
import com.tangem.domain.notifications.SendPushTokenUseCase
|
||||
import com.tangem.domain.notifications.models.ApplicationId
|
||||
|
|
@ -37,9 +38,9 @@ import com.tangem.domain.settings.DeleteDeprecatedLogsUseCase
|
|||
import com.tangem.domain.settings.IncrementAppLaunchCounterUseCase
|
||||
import com.tangem.domain.settings.usercountry.FetchUserCountryUseCase
|
||||
import com.tangem.domain.staking.FetchStakingTokensUseCase
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.usecase.AssociateWalletsWithApplicationIdUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetSavedWalletsCountUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase
|
||||
import com.tangem.domain.wallets.usecase.UpdateRemoteWalletsInfoUseCase
|
||||
import com.tangem.feature.swap.analytics.StoriesEvents
|
||||
import com.tangem.tap.common.extensions.setContext
|
||||
|
|
@ -69,7 +70,6 @@ internal class MainViewModel @Inject constructor(
|
|||
deleteDeprecatedLogsUseCase: DeleteDeprecatedLogsUseCase,
|
||||
private val incrementAppLaunchCounterUseCase: IncrementAppLaunchCounterUseCase,
|
||||
private val blockchainSDKFactory: BlockchainSDKFactory,
|
||||
private val userWalletsListManager: UserWalletsListManager,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val fetchStakingTokensUseCase: FetchStakingTokensUseCase,
|
||||
private val fetchUserCountryUseCase: FetchUserCountryUseCase,
|
||||
|
|
@ -90,6 +90,7 @@ internal class MainViewModel @Inject constructor(
|
|||
private val multiQuoteUpdater: MultiQuoteUpdater,
|
||||
private val appStateHolder: AppStateHolder,
|
||||
private val environmentConfigStorage: EnvironmentConfigStorage,
|
||||
private val getSelectedWalletUseCase: GetSelectedWalletUseCase,
|
||||
getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
||||
) : ViewModel() {
|
||||
|
||||
|
|
@ -185,13 +186,16 @@ internal class MainViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun prepareSelectedWalletFeedback() {
|
||||
userWalletsListManager.selectedUserWallet
|
||||
.distinctUntilChanged()
|
||||
.onEach { userWallet ->
|
||||
Analytics.setContext(userWallet)
|
||||
getSelectedWalletUseCase.invoke()
|
||||
.mapLeft { emptyFlow<UserWallet>() }
|
||||
.onRight {
|
||||
it.distinctUntilChanged()
|
||||
.onEach { userWallet ->
|
||||
Analytics.setContext(userWallet)
|
||||
}
|
||||
.flowOn(dispatchers.io)
|
||||
.launchIn(viewModelScope)
|
||||
}
|
||||
.flowOn(dispatchers.io)
|
||||
.launchIn(viewModelScope)
|
||||
}
|
||||
|
||||
private suspend fun fetchStakingTokens() {
|
||||
|
|
@ -214,7 +218,7 @@ internal class MainViewModel @Inject constructor(
|
|||
apiKey = environmentConfig.moonPayApiKey,
|
||||
secretKey = environmentConfig.moonPayApiSecretKey,
|
||||
logEnabled = LogConfig.network.moonPayService,
|
||||
userWalletProvider = { userWalletsListManager.selectedUserWalletSync },
|
||||
userWalletProvider = { getSelectedWalletUseCase.sync().getOrNull() },
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ object WalletActivationErrorDialog {
|
|||
val scanResponse = store.state.globalState.scanResponse
|
||||
?: error("ScanResponse must be not null")
|
||||
|
||||
val cardInfo = store.inject(DaggerGraphState::getCardInfoUseCase).invoke(scanResponse).getOrNull()
|
||||
val cardInfo = store.inject(DaggerGraphState::getWalletMetaInfoUseCase).invoke(scanResponse).getOrNull()
|
||||
?: error("CardInfo must be not null")
|
||||
|
||||
scope.launch {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
|||
import com.tangem.blockchainsdk.utils.toBlockchain
|
||||
import com.tangem.data.common.currency.CryptoCurrencyFactory
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.tap.common.extensions.inject
|
||||
import com.tangem.tap.domain.model.Currency
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
|
|
@ -24,9 +25,7 @@ internal class CryptoCurrencyConverter(
|
|||
cryptoCurrencyFactory.createCoin(
|
||||
blockchain = value.blockchain,
|
||||
extraDerivationPath = value.derivationPath,
|
||||
userWallet = requireNotNull(
|
||||
store.inject(DaggerGraphState::generalUserWalletsListManager).selectedUserWalletSync,
|
||||
),
|
||||
userWallet = getSelectedWallet(),
|
||||
),
|
||||
)
|
||||
is Currency.Token -> requireNotNull(
|
||||
|
|
@ -34,9 +33,7 @@ internal class CryptoCurrencyConverter(
|
|||
sdkToken = value.token,
|
||||
blockchain = value.blockchain,
|
||||
extraDerivationPath = value.derivationPath,
|
||||
userWallet = requireNotNull(
|
||||
store.inject(DaggerGraphState::generalUserWalletsListManager).selectedUserWalletSync,
|
||||
),
|
||||
userWallet = getSelectedWallet(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -63,4 +60,15 @@ internal class CryptoCurrencyConverter(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun getSelectedWallet(): UserWallet {
|
||||
val userWalletListManager = store.inject(DaggerGraphState::generalUserWalletsListManager)
|
||||
val userWalletsListRepository = store.inject(DaggerGraphState::userWalletsListRepository)
|
||||
val hotWalletFeatureToggles = store.inject(DaggerGraphState::hotWalletFeatureToggles)
|
||||
return if (hotWalletFeatureToggles.isHotWalletEnabled) {
|
||||
requireNotNull(userWalletsListRepository.selectedUserWallet.value)
|
||||
} else {
|
||||
requireNotNull(userWalletListManager.selectedUserWalletSync)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ import com.tangem.blockchain.common.Blockchain
|
|||
import com.tangem.blockchain.common.WalletManager
|
||||
import com.tangem.blockchainsdk.utils.fromNetworkId
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase
|
||||
import com.tangem.lib.crypto.UserWalletManager
|
||||
import com.tangem.lib.crypto.models.ProxyAmount
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
|
|
@ -15,13 +15,13 @@ import java.math.BigDecimal
|
|||
|
||||
class UserWalletManagerImpl(
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val userWalletsListManager: UserWalletsListManager,
|
||||
private val getSelectedWalletUseCase: GetSelectedWalletUseCase,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : UserWalletManager {
|
||||
|
||||
override fun getWalletId(): String {
|
||||
val selectedUserWallet = requireNotNull(
|
||||
userWalletsListManager.selectedUserWalletSync,
|
||||
getSelectedWalletUseCase.sync().getOrNull(),
|
||||
) { "selectedUserWallet shouldn't be null" }
|
||||
return selectedUserWallet.walletId.stringValue
|
||||
}
|
||||
|
|
@ -62,7 +62,7 @@ class UserWalletManagerImpl(
|
|||
@Throws(IllegalArgumentException::class)
|
||||
private suspend fun getActualWalletManager(blockchain: Blockchain, derivationPath: String?): WalletManager {
|
||||
val selectedUserWallet = requireNotNull(
|
||||
userWalletsListManager.selectedUserWalletSync,
|
||||
getSelectedWalletUseCase.sync().getOrNull(),
|
||||
) { "userWallet or userWalletsListManager is null" }
|
||||
val walletManager = withContext(dispatchers.io) {
|
||||
walletManagersFacade.getOrCreateWalletManager(
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.tangem.tap.proxy.di
|
||||
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase
|
||||
import com.tangem.lib.crypto.UserWalletManager
|
||||
import com.tangem.tap.proxy.AppStateHolder
|
||||
import com.tangem.tap.proxy.UserWalletManagerImpl
|
||||
|
|
@ -26,12 +26,12 @@ internal object ProxyModule {
|
|||
@Singleton
|
||||
fun provideUserWalletManager(
|
||||
walletManagersFacade: WalletManagersFacade,
|
||||
userWalletsListManager: UserWalletsListManager,
|
||||
getSelectedWalletUseCase: GetSelectedWalletUseCase,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): UserWalletManager {
|
||||
return UserWalletManagerImpl(
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
userWalletsListManager = userWalletsListManager,
|
||||
getSelectedWalletUseCase = getSelectedWalletUseCase,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import com.tangem.domain.card.ScanCardUseCase
|
|||
import com.tangem.domain.card.repository.CardRepository
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.core.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.feedback.GetCardInfoUseCase
|
||||
import com.tangem.domain.feedback.GetWalletMetaInfoUseCase
|
||||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||
import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase
|
||||
import com.tangem.domain.onboarding.WasTwinsOnboardingShownUseCase
|
||||
|
|
@ -63,7 +63,7 @@ data class DaggerGraphState(
|
|||
val settingsRepository: SettingsRepository? = null,
|
||||
val blockchainSDKFactory: BlockchainSDKFactory? = null,
|
||||
val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase? = null,
|
||||
val getCardInfoUseCase: GetCardInfoUseCase? = null,
|
||||
val getWalletMetaInfoUseCase: GetWalletMetaInfoUseCase? = null,
|
||||
val issuersConfigStorage: IssuersConfigStorage? = null,
|
||||
val urlOpener: UrlOpener? = null,
|
||||
val shareManager: ShareManager? = null,
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import com.tangem.features.disclaimer.api.components.DisclaimerComponent
|
|||
import com.tangem.features.home.api.HomeComponent
|
||||
import com.tangem.features.hotwallet.AddExistingWalletComponent
|
||||
import com.tangem.features.hotwallet.CreateMobileWalletComponent
|
||||
import com.tangem.features.hotwallet.UpgradeWalletComponent
|
||||
import com.tangem.features.hotwallet.WalletActivationComponent
|
||||
import com.tangem.features.hotwallet.CreateWalletBackupComponent
|
||||
import com.tangem.features.hotwallet.UpdateAccessCodeComponent
|
||||
|
|
@ -103,6 +104,7 @@ internal class ChildFactory @Inject constructor(
|
|||
private val chooseManagedTokensComponentFactory: ChooseManagedTokensComponent.Factory,
|
||||
private val createWalletSelectionComponentFactory: CreateWalletSelectionComponent.Factory,
|
||||
private val createMobileWalletComponentFactory: CreateMobileWalletComponent.Factory,
|
||||
private val upgradeWalletComponentFactory: UpgradeWalletComponent.Factory,
|
||||
private val addExistingWalletComponentFactory: AddExistingWalletComponent.Factory,
|
||||
private val walletActivationComponentFactory: WalletActivationComponent.Factory,
|
||||
private val createWalletBackupComponentFactory: CreateWalletBackupComponent.Factory,
|
||||
|
|
@ -205,6 +207,7 @@ internal class ChildFactory @Inject constructor(
|
|||
userWalletId = route.userWalletId,
|
||||
cryptoCurrency = route.currency,
|
||||
source = route.source,
|
||||
launchSepa = route.launchSepa,
|
||||
),
|
||||
componentFactory = onrampComponentFactory,
|
||||
)
|
||||
|
|
@ -486,6 +489,15 @@ internal class ChildFactory @Inject constructor(
|
|||
componentFactory = createMobileWalletComponentFactory,
|
||||
)
|
||||
}
|
||||
is AppRoute.UpgradeWallet -> {
|
||||
createComponentChild(
|
||||
context = context,
|
||||
params = UpgradeWalletComponent.Params(
|
||||
userWalletId = route.userWalletId,
|
||||
),
|
||||
componentFactory = upgradeWalletComponentFactory,
|
||||
)
|
||||
}
|
||||
is AppRoute.AddExistingWallet -> {
|
||||
createComponentChild(
|
||||
context = context,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<inset xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:drawable="@drawable/splash_logo"
|
||||
android:insetLeft="48dp"
|
||||
android:insetRight="48dp"
|
||||
android:insetTop="48dp"
|
||||
android:insetBottom="48dp"/>
|
||||
android:insetLeft="55dp"
|
||||
android:insetRight="55dp"
|
||||
android:insetTop="55dp"
|
||||
android:insetBottom="55dp"/>
|
||||
|
||||
<!-- image should fit exactly in square 192x192 dp-->
|
||||
<!-- (192 - splash_logo_side)/2 = 48dp -->
|
||||
<!-- (192 - splash_logo_side)/2 = 55dp -->
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="96dp"
|
||||
android:height="96dp"
|
||||
android:viewportWidth="450"
|
||||
android:viewportHeight="450">
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="M284.96,82H165.04C146.12,82 136.67,82 129.44,85.68C123.08,88.93 117.91,94.08 114.68,100.44C111,107.67 111,117.12 111,136.04V156.1H339V136.04C339,117.12 339,107.67 335.32,100.44C332.07,94.08 326.92,88.91 320.56,85.68C313.33,82 303.88,82 284.96,82Z" />
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="M262.99,218.8H338.99V312.96C338.99,331.88 338.99,341.33 335.31,348.56C332.07,354.92 326.91,360.09 320.56,363.32C313.32,367 303.87,367 284.95,367H263.01L262.99,218.8Z" />
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="M111,218.8H186.99V367H165.04C146.12,367 136.67,367 129.44,363.32C123.08,360.09 117.93,354.92 114.68,348.56C111,341.33 111,331.88 111,312.96V218.8Z" />
|
||||
</vector>
|
||||
|
|
@ -26,6 +26,4 @@
|
|||
<color name="text_primary_1">#1E1E1E</color>
|
||||
<color name="text_secondary">#656565</color>
|
||||
|
||||
<color name="background_splash">#000000</color>
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
</style>
|
||||
|
||||
<style name="SplashTheme" parent="Theme.SplashScreen">
|
||||
<item name="windowSplashScreenBackground">@color/background_splash</item>
|
||||
<item name="windowSplashScreenBackground">@color/background_primary</item>
|
||||
<item name="windowSplashScreenAnimatedIcon">@drawable/inset_splash</item>
|
||||
<item name="postSplashScreenTheme">@style/AppTheme</item>
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue