diff --git a/.editorconfig b/.editorconfig
deleted file mode 100644
index 0ab5ea61ec..0000000000
--- a/.editorconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-[*.{kt,kts}]
-
-indent_size = 4
-indent_style = space
-insert_final_newline = true
-
-ij_kotlin_allow_trailing_comma = true
-ij_kotlin_allow_trailing_comma_on_call_site = true
-
-ij_kotlin_imports_layout = *, java.**, javax.**, kotlin.**, ^
-ij_kotlin_packages_to_use_import_on_demand = java.util.*, kotlinx.android.synthetic.**
-
-max_line_length = 120
diff --git a/.gitignore b/.gitignore
index dcdbe5fc57..3e96fb9767 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
# Built application files
/build
+/buildSrc
# Local configuration file (sdk path, etc)
local.properties
@@ -32,4 +33,3 @@ local.properties
**/fastlane/Preview.html
**/fastlane/screenshots
**/fastlane/test_output
-/buildSrc/build/
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index 6527894333..8f2af51f2d 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -2,6 +2,10 @@
+
+
+
+
-
-
+
+
+
+
@@ -19,6 +25,9 @@
+
+
+
@@ -178,9 +187,6 @@
-
-
-
@@ -200,4 +206,4 @@
-
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index ce1b62532a..5647ad7cfc 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -4,8 +4,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -15,6 +43,14 @@
+
+
+
+
+
+
+
+
@@ -85,8 +121,6 @@
-
-
\ No newline at end of file
diff --git a/Gemfile.lock b/Gemfile.lock
index b4221a320d..535cdb9a32 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -217,4 +217,4 @@ DEPENDENCIES
fastlane-plugin-firebase_app_distribution
BUNDLED WITH
- 1.17.2
+ 2.5.23
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 1c44bd0851..f3177619a4 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,212 +1,314 @@
+import java.util.Properties
+import com.tangem.plugin.configuration.configurations.extension.kaptForObfuscatingVariants
+
plugins {
- id("com.android.application")
- kotlin("android")
- kotlin("kapt")
- kotlin("plugin.serialization")
- id("com.google.gms.google-services")
- id("com.google.firebase.crashlytics")
- id("com.google.dagger.hilt.android")
+ alias(deps.plugins.android.application)
+ alias(deps.plugins.kotlin.android)
+ alias(deps.plugins.kotlin.kapt)
+ alias(deps.plugins.kotlin.serialization)
+ alias(deps.plugins.google.services)
+ alias(deps.plugins.hilt.android)
+ alias(deps.plugins.firebase.crashlytics)
+ alias(deps.plugins.firebase.perf)
+ id("configuration")
}
android {
- compileSdk = AppConfig.compileSdkVersion
-
- defaultConfig {
- applicationId = AppConfig.packageName
- minSdk = AppConfig.minSdkVersion
- targetSdk = AppConfig.targetSdkVersion
-
- versionCode = if (project.hasProperty("versionCode")) {
- (project.property("versionCode") as String).toInt()
- } else {
- AppConfig.versionCode
- }
-
- versionName = if (project.hasProperty("versionName")) {
- project.property("versionName") as String
- } else {
- AppConfig.versionName
- }
-
- testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+ namespace = "com.tangem.wallet"
+ testOptions {
+ animationsDisabled = true
}
-
- buildFeatures {
- compose = true
- viewBinding = true
+ packaging {
+ jniLibs {
+ useLegacyPackaging = true
+ }
+ resources.excludes.add("META-INF/DEPENDENCIES")
+ resources.excludes.add("META-INF/LICENSE.md")
+ resources.excludes.add("META-INF/NOTICE.md")
}
+ androidResources {
+ generateLocaleConfig = true
+ }
+ signingConfigs {
+ getByName("debug") {
+ val keystorePath = "src/main/assets/tangem-app-config/android/keystore/debug_keystore"
+ val propertiesPath = "src/main/assets/tangem-app-config/android/keystore/debug_keystore.properties"
- buildTypes {
- release {
- isDebuggable = false
- isMinifyEnabled = false
- proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
+ val keystoreProperties = Properties()
+ file(propertiesPath)
+ .inputStream()
+ .use { keystoreProperties.load(it) }
- BuildConfigFieldFactory(
- fields = listOf(
- Field.Environment("prod"),
- Field.TestActionEnabled(false),
- Field.LogEnabled(false),
- ),
- builder = ::buildConfigField,
- ).create()
- }
-
- debug {
- isDebuggable = true
- isMinifyEnabled = false
- applicationIdSuffix = ".dev"
-
- configure {
- // disable mapping file uploads (default=true if minifying)
- mappingFileUploadEnabled = false
- }
-
- BuildConfigFieldFactory(
- fields = listOf(
- Field.Environment("dev"),
- Field.TestActionEnabled(true),
- Field.LogEnabled(true),
- ),
- builder = ::buildConfigField,
- ).create()
- }
-
- create("debug_beta") {
- initWith(getByName("release"))
- versionNameSuffix = "-beta"
- applicationIdSuffix = ".debug"
- signingConfig = signingConfigs.getByName("debug")
+ storeFile = file(keystorePath)
+ storePassword = keystoreProperties["store_password"] as String
+ keyAlias = keystoreProperties["key_alias"] as String
+ keyPassword = keystoreProperties["key_password"] as String
}
}
- kotlinOptions {
- jvmTarget = JavaVersion.VERSION_1_8.toString()
- }
+}
- compileOptions {
- sourceCompatibility = JavaVersion.VERSION_1_8
- targetCompatibility = JavaVersion.VERSION_1_8
- isCoreLibraryDesugaringEnabled = false
- }
+configurations.all {
+ exclude(group = "org.bouncycastle", module = "bcprov-jdk15to18")
+ exclude(group = "com.github.komputing.kethereum")
- composeOptions {
- kotlinCompilerExtensionVersion = Versions.compose
- }
+ resolutionStrategy {
+ dependencySubstitution {
+ substitute(module("org.bouncycastle:bcprov-jdk15on"))
+ .using(module("org.bouncycastle:bcprov-jdk18on:1.73"))
+ }
- packagingOptions {
- resources.excludes += "lib/x86_64/darwin/libscrypt.dylib"
- resources.excludes += "lib/x86_64/freebsd/libscrypt.so"
- resources.excludes += "lib/x86_64/linux/libscrypt.so"
- resources.excludes += "META-INF/gradle/incremental.annotation.processors"
+ force(
+ "org.bouncycastle:bcpkix-jdk15on:1.70",
+ )
}
}
-repositories {
- mavenCentral()
- maven(url = "https://jitpack.io")
-}
dependencies {
- implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.aar"))))
- implementation(project(":domain"))
- implementation(project(":common"))
- implementation(project(":core:analytics"))
- implementation(project(":core:res"))
- implementation(project(":core:ui"))
- implementation(project(":core:datasource"))
- implementation(project(":core:utils"))
- implementation(project(":libs:crypto"))
- implementation(project(":libs:auth"))
+ implementation(projects.domain.legacy)
+ implementation(projects.libs.blockchainSdk)
+ implementation(projects.domain.models)
+ implementation(projects.domain.core)
+ implementation(projects.domain.card)
+ implementation(projects.domain.demo)
+ implementation(projects.domain.wallets)
+ implementation(projects.domain.wallets.models)
+ implementation(projects.domain.settings)
+ implementation(projects.domain.tokens)
+ implementation(projects.domain.tokens.models)
+ implementation(projects.domain.txhistory)
+ implementation(projects.domain.appCurrency)
+ implementation(projects.domain.appCurrency.models)
+ implementation(projects.domain.appTheme)
+ implementation(projects.domain.appTheme.models)
+ implementation(projects.domain.balanceHiding)
+ implementation(projects.domain.balanceHiding.models)
+ implementation(projects.domain.transaction)
+ implementation(projects.domain.analytics)
+ implementation(projects.domain.visa)
+ implementation(projects.domain.onboarding)
+ implementation(projects.domain.feedback)
+ implementation(projects.domain.qrScanning)
+ implementation(projects.domain.qrScanning.models)
+ implementation(projects.domain.staking)
+ implementation(projects.domain.walletConnect)
+ implementation(projects.domain.markets)
+ implementation(projects.domain.manageTokens)
+ implementation(projects.domain.onramp)
+ implementation(projects.domain.promo)
+ implementation(projects.domain.promo.models)
+
+ implementation(projects.common)
+ implementation(projects.common.routing)
+ implementation(projects.common.google)
+ implementation(projects.core.analytics)
+ implementation(projects.core.analytics.models)
+ implementation(projects.core.navigation)
+ implementation(projects.core.configToggles)
+ implementation(projects.core.res)
+ implementation(projects.core.ui)
+ implementation(projects.core.datasource)
+ implementation(projects.core.utils)
+ implementation(projects.core.decompose)
+ implementation(projects.core.deepLinks)
+ implementation(projects.libs.crypto)
+ implementation(projects.libs.auth)
+ implementation(projects.libs.blockchainSdk)
+ implementation(projects.libs.tangemSdkApi)
+
+ implementation(projects.data.appCurrency)
+ implementation(projects.data.appTheme)
+ implementation(projects.data.balanceHiding)
+ implementation(projects.data.card)
+ implementation(projects.data.common)
+ implementation(projects.data.settings)
+ implementation(projects.data.tokens)
+ implementation(projects.data.txhistory)
+ implementation(projects.data.wallets)
+ implementation(projects.data.analytics)
+ implementation(projects.data.transaction)
+ implementation(projects.data.visa)
+ implementation(projects.data.promo)
+ implementation(projects.data.onboarding)
+ implementation(projects.data.feedback)
+ implementation(projects.data.qrScanning)
+ implementation(projects.data.staking)
+ implementation(projects.data.walletConnect)
+ implementation(projects.data.markets)
+ implementation(projects.data.manageTokens)
+ implementation(projects.data.onramp)
/** Features */
- implementation(project(":features:referral:presentation"))
- implementation(project(":features:referral:domain"))
- implementation(project(":features:referral:data"))
- implementation(project(":features:swap:presentation"))
- implementation(project(":features:swap:domain"))
- implementation(project(":features:swap:data"))
+ implementation(projects.features.onboarding)
+ implementation(projects.features.referral.presentation)
+ implementation(projects.features.referral.domain)
+ implementation(projects.features.referral.data)
+ implementation(projects.features.swap.api)
+ implementation(projects.features.swap.impl)
+ implementation(projects.features.swap.domain)
+ implementation(projects.features.swap.domain.api)
+ implementation(projects.features.swap.data)
+ implementation(projects.features.tester.api)
+ implementation(projects.features.tester.impl)
+ implementation(projects.features.wallet.api)
+ implementation(projects.features.wallet.impl)
+ implementation(projects.features.tokendetails.api)
+ implementation(projects.features.tokendetails.impl)
+ implementation(projects.features.manageTokens.api)
+ implementation(projects.features.manageTokens.impl)
+ implementation(projects.features.send.api)
+ implementation(projects.features.send.impl)
+ implementation(projects.features.qrScanning.api)
+ implementation(projects.features.qrScanning.impl)
+ implementation(projects.features.staking.api)
+ implementation(projects.features.staking.impl)
+ implementation(projects.features.details.api)
+ implementation(projects.features.details.impl)
+ implementation(projects.features.disclaimer.api)
+ implementation(projects.features.disclaimer.impl)
+ implementation(projects.features.pushNotifications.api)
+ implementation(projects.features.pushNotifications.impl)
+ implementation(projects.features.walletSettings.api)
+ implementation(projects.features.walletSettings.impl)
+ implementation(projects.features.markets.api)
+ implementation(projects.features.markets.impl)
+ implementation(projects.features.onramp.api)
+ implementation(projects.features.onramp.impl)
+ implementation(projects.features.onboardingV2.api)
+ implementation(projects.features.onboardingV2.impl)
+ implementation(projects.features.stories.api)
+ implementation(projects.features.stories.impl)
/** AndroidX libraries */
- implementation(AndroidX.coreKtx)
- implementation(AndroidX.appCompat)
- implementation(AndroidX.fragmentKtx)
- implementation(AndroidX.constraintLayout)
- implementation(AndroidX.browser)
- implementation(AndroidX.lifecycleRuntimeKtx)
- implementation(AndroidX.lifecycleCommonJava8)
- implementation(AndroidX.lifecycleViewModelKtx)
- implementation(AndroidX.lifecycleLiveDataKtx)
- implementation(AndroidX.activityCompose)
+ implementation(deps.androidx.core.ktx)
+ implementation(deps.androidx.core.splashScreen)
+ implementation(deps.androidx.appCompat)
+ implementation(deps.androidx.datastore)
+ implementation(deps.androidx.fragment.ktx)
+ implementation(deps.androidx.constraintLayout)
+ implementation(deps.androidx.activity.compose)
+ implementation(deps.androidx.browser)
+ implementation(deps.androidx.paging.runtime)
+ implementation(deps.androidx.swipeRefreshLayout)
+ implementation(deps.androidx.fragment.compose)
+ implementation(deps.lifecycle.runtime.ktx)
+ implementation(deps.lifecycle.common.java8)
+ implementation(deps.lifecycle.viewModel.ktx)
+ implementation(deps.lifecycle.compose)
/** Compose libraries */
- implementation(Compose.material)
- implementation(Compose.animation)
- implementation(Compose.foundation)
- implementation(Compose.ui)
- implementation(Compose.uiTooling)
- implementation(Compose.coil)
+ implementation(deps.compose.constraintLayout)
+ implementation(deps.compose.material)
+ implementation(deps.compose.material3)
+ implementation(deps.compose.animation)
+ implementation(deps.compose.coil)
+ implementation(deps.compose.constraintLayout)
+ implementation(deps.compose.foundation)
+ implementation(deps.compose.material)
+ implementation(deps.compose.navigation.hilt)
+ implementation(deps.compose.shimmer)
+ implementation(deps.compose.ui)
+ implementation(deps.compose.ui.tooling)
+ implementation(deps.compose.paging)
/** Firebase libraries */
- implementation(platform(Firebase.bom))
- implementation(Firebase.firebaseAnalytics)
- implementation(Firebase.firebaseCrashlytics)
-
+ implementation(platform(deps.firebase.bom))
+ implementation(deps.firebase.analytics)
+ implementation(deps.firebase.crashlytics)
+ implementation(deps.firebase.messaging)
+ implementation(deps.firebase.perf) {
+ exclude(group = "com.google.firebase", module = "protolite-well-known-types")
+ exclude(group = "com.google.protobuf", module = "protobuf-javalite")
+ }
/** Tangem libraries */
- implementation(Tangem.blockchain) {
+ implementation(tangemDeps.blockchain) {
exclude(module = "joda-time")
}
- implementation(Tangem.cardCore)
- implementation(Tangem.cardAndroid) {
+ implementation(tangemDeps.card.core)
+ implementation(tangemDeps.card.android) {
exclude(module = "joda-time")
}
/** DI */
- implementation(Library.hilt)
- kapt(Library.hiltKapt)
+ implementation(deps.hilt.android)
+
+ kapt(deps.hilt.kapt)
/** Other libraries */
- implementation(Library.materialComponent)
- implementation(Library.googlePlayCore)
- implementation(Library.googlePlayCoreKtx)
- coreLibraryDesugaring(Library.desugarJdkLibs)
- implementation(Library.timber)
- implementation(Library.reKotlin)
- implementation(Library.zxingQrCore)
- implementation(Library.zxingQrBarcodeScanner)
- implementation(Library.otaliastudiosCameraView)
- implementation(Library.coil)
- implementation(Library.appsflyer)
- implementation(Library.amplitude)
- implementation(Library.kotsonGsonExt)
- //TODO: refactoring: remove it when all network services moved to the datasource module
- implementation(Library.retrofit)
- implementation(Library.retrofitMoshiConverter)
- implementation(Library.moshi)
- implementation(Library.moshiKotlin)
- implementation(Library.okHttp)
- implementation(Library.okHttpLogging)
- implementation(Library.zendeskChat)
- implementation(Library.zendeskMessaging)
- implementation(Library.spongecastleCryptoCore)
- implementation(Library.lottie)
- implementation(Library.shopifyBuySdk) {
- exclude(group = "com.shopify.graphql.support")
- exclude(module = "joda-time")
- }
- implementation(Library.accompanistAppCompatTheme)
- implementation(Library.accompanistSystemUiController)
- implementation(Library.xmlShimmer)
- implementation(Library.viewBindingDelegate)
- implementation(Library.armadillo)
- implementation(Library.googlePlayServicesWallet)
- implementation(Library.composeShimmer)
- implementation(Library.mviCoreWatcher)
- implementation(Library.kotlinSerialization)
+ implementation(deps.kotlin.immutable.collections)
+ implementation(deps.material)
+ implementation(deps.googlePlay.review)
+ implementation(deps.googlePlay.review.ktx)
+ implementation(deps.googlePlay.services.wallet)
+ coreLibraryDesugaring(deps.desugar)
+ implementation(deps.timber)
+ implementation(deps.reKotlin)
+ implementation(deps.zxing.qrCore)
+ implementation(deps.coil)
+ implementation(deps.amplitude)
+ implementation(deps.kotsonGson)
+ implementation(deps.spongecastle.core)
+ implementation(deps.lottie)
+ implementation(deps.compose.accompanist.appCompatTheme)
+ implementation(deps.compose.accompanist.systemUiController)
+ implementation(deps.xmlShimmer)
+ implementation(deps.viewBindingDelegate)
+ implementation(deps.armadillo)
+ implementation(deps.kotlin.serialization)
+ implementation(deps.reownCore)
+ implementation(deps.reownWeb3)
+ implementation(deps.prettyLogger)
+ implementation(deps.decompose.ext.compose)
+ implementation(deps.moshi.adapters)
+
+ implementation(deps.moshi.kotlin)
+ kaptForObfuscatingVariants(deps.moshi.kotlin.codegen)
+ kaptForObfuscatingVariants(deps.retrofit.response.type.keeper)
/** Testing libraries */
- testImplementation(Test.junit)
- testImplementation(Test.truth)
- androidTestImplementation(Test.junitAndroidExt)
- androidTestImplementation(Test.espresso)
+ testImplementation(deps.test.coroutine)
+ testImplementation(deps.test.junit)
+ testImplementation(deps.test.mockk)
+ testImplementation(deps.test.truth)
+ androidTestImplementation(deps.test.junit.android)
+ androidTestImplementation(deps.test.espresso){
+ exclude(group = "com.google.protobuf", module = "protobuf-lite") //conflicting with firebasePerf
+ }
+ androidTestImplementation(deps.test.espresso.intents)
+ {
+ exclude(group = "com.google.protobuf", module = "protobuf-lite") //conflicting with firebasePerf
+ }
+ androidTestImplementation(deps.test.compose.junit)
+ androidTestImplementation(deps.test.hamcrest)
+ androidTestImplementation(deps.test.hilt)
+ androidTestImplementation(deps.test.ultron.android)
+ androidTestImplementation(deps.test.ultron.compose)
+ androidTestImplementation(deps.test.ultron.allure)
+ kaptAndroidTest(deps.test.hilt.compiler)
+
+ /** Chucker */
+ debugImplementation(deps.chucker)
+ debugPGImplementation(deps.chucker)
+ mockedImplementation(deps.chuckerStub)
+ externalImplementation(deps.chuckerStub)
+ internalImplementation(deps.chuckerStub)
+ releaseImplementation(deps.chuckerStub)
+
+ /** Camera */
+ implementation(deps.camera.camera2)
+ implementation(deps.camera.lifecycle)
+ implementation(deps.camera.view)
+
+ implementation(deps.listenableFuture)
+ implementation(deps.mlKit.barcodeScanning)
+
+ /** Leakcanary */
+ debugImplementation(deps.leakcanary)
+
+ /** Excluded dependencies */
+ implementation("com.google.guava:guava:30.0-android") {
+ // excludes version 9999.0-empty-to-avoid-conflict-with-guava
+ exclude(group = "com.google.guava", module = "listenablefuture")
+ }
}
\ No newline at end of file
diff --git a/app/libs/rekotlin-1.0.4.jar b/app/libs/rekotlin-1.0.4.jar
new file mode 100644
index 0000000000..3221e554be
Binary files /dev/null and b/app/libs/rekotlin-1.0.4.jar differ
diff --git a/app/libs/ripple-core-0.0.1.jar b/app/libs/ripple-core-0.0.1.jar
deleted file mode 100644
index 617db52b2d..0000000000
Binary files a/app/libs/ripple-core-0.0.1.jar and /dev/null differ
diff --git a/app/libs/walletconnect-1.5.6.aar b/app/libs/walletconnect-1.5.6.aar
deleted file mode 100644
index 30c576fb89..0000000000
Binary files a/app/libs/walletconnect-1.5.6.aar and /dev/null differ
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
index 2f9dc5a47e..2a7b205c9d 100644
--- a/app/proguard-rules.pro
+++ b/app/proguard-rules.pro
@@ -1,21 +1,208 @@
-# Add project specific ProGuard rules here.
-# You can control the set of applied configuration files using the
-# proguardFiles setting in build.gradle.kts.
-#
-# For more details, see
-# http://developer.android.com/guide/developing/tools/proguard.html
+-dontusemixedcaseclassnames
+-flattenpackagehierarchy
+-adaptclassstrings
-# If your project uses WebView with JS, uncomment the following
-# and specify the fully qualified class name to the JavaScript interface
-# class:
-#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
-# public *;
-#}
+# firebase
+-keep public class com.google.firebase.** { *; }
+-keep class com.google.android.gms.internal.** { *; }
+-keepclasseswithmembers class com.google.firebase.FirebaseException
-# Uncomment this to preserve the line number information for
-# debugging stack traces.
-#-keepattributes SourceFile,LineNumberTable
+# hedera sdk
+-keep class com.hedera.hashgraph.sdk.** { *; }
+-keep interface com.hedera.hashgraph.sdk.** { *; }
+-dontwarn com.esaulpaugh.headlong.**
+-dontwarn edu.umd.cs.findbugs.annotations.SuppressFBWarnings
+-dontwarn io.grpc.stub.**
-# If you keep the line number information, uncomment this to
-# hide the original source file name.
-#-renamesourcefileattribute SourceFile
+# trustwallet sdk
+-keep class wallet.core.jni.** { *; }
+
+# solana
+-keep class org.p2p.solanaj.** { *; }
+-keep class com.tangem.blockchain.blockchains.solana.solanaj.model.** { *; }
+
+# binance
+-keep class com.tangem.blockchain.blockchains.binance.client.** { *; }
+
+# shadow gson
+-keep,allowobfuscation,allowshrinking class shadow.com.google.gson.reflect.TypeToken
+-keep,allowobfuscation,allowshrinking class * extends shadow.com.google.gson.reflect.TypeToken
+
+# polkadot
+-keep class io.emeraldpay.polkaj.api.RpcRequest { *; }
+-keep class io.emeraldpay.polkaj.api.RpcResponse { *; }
+-keep class io.emeraldpay.polkaj.api.RpcResponseError { *; }
+
+# kethereum
+-keep class org.kethereum.bip32.model.ExtendedKey**
+-keepclassmembers class org.kethereum.bip32.model.ExtendedKey** { *; }
+
+# some crypto
+-dontwarn net.i2p.crypto.**
+-dontwarn java.net.http.**
+-dontwarn lombok.**
+
+-keep class org.spongycastle.** { *; }
+
+-dontwarn org.apache.hc.core5.**
+-dontwarn org.apache.hc.client5.**
+-dontwarn org.apache.log4j.config.**
+
+-dontwarn javax.naming.**
+-dontwarn javax.xml.stream.**
+-dontwarn javax.script.**
+
+-dontwarn org.java_websocket.client.WebSocketClient
+-dontwarn org.java_websocket.handshake.ServerHandshake
+
+-dontwarn aQute.bnd.annotation.spi.ServiceProvider
+
+-dontwarn org.threeten.bp.**
+-keep class org.threeten.bp.*
+-keepclassmembers class org.threeten.bp.** { *; }
+
+# joda time
+# These aren't necessary if including joda-convert
+-dontwarn org.joda.convert.FromString
+-dontwarn org.joda.convert.ToString
+
+-keepnames class org.joda.** implements java.io.Serializable
+-keepclassmembers class org.joda.** implements java.io.Serializable {
+ static final long serialVersionUID;
+ private static final java.io.ObjectStreamField[] serialPersistentFields;
+ !static !transient ;
+ private void writeObject(java.io.ObjectOutputStream);
+ private void readObject(java.io.ObjectInputStream);
+ java.lang.Object writeReplace();
+ java.lang.Object readResolve();
+}
+# joda time
+
+# The name of @JsonClass types is used to look up the generated adapter.
+-keepnames @com.squareup.moshi.JsonClass class *
+
+-keepclassmembers class * {
+ @com.squareup.moshi.FromJson ;
+ @com.squareup.moshi.ToJson ;
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class kotlin.Metadata { *; }
+-keepclassmembers class kotlin.Metadata {
+ public ;
+}
+
+# Proguard configuration for Jackson 2.x
+-keep class com.fasterxml.** { *; }
+-keep class com.fasterxml.jackson.databind.ObjectMapper {
+ public ;
+ protected ;
+}
+-keep class com.fasterxml.jackson.databind.ObjectWriter {
+ public ** writeValueAsString(**);
+}
+-keepnames class com.fasterxml.jackson.** { *; }
+-dontwarn com.fasterxml.jackson.databind.**
+-keep class * implements com.fasterxml.jackson.core.type.TypeReference
+
+-keep class kotlin.reflect.**
+-keep public class kotlin.reflect.jvm.internal.impl.** { public *; }
+
+# Kotlin serialization looks up the generated serializer classes through a function on companion
+# objects. The companions are looked up reflectively so we need to explicitly keep these functions.
+-keepclasseswithmembers class **.*$Companion {
+ kotlinx.serialization.KSerializer serializer(...);
+}
+# If a companion has the serializer function, keep the companion field on the original type so that
+# the reflective lookup succeeds.
+-if class **.*$Companion {
+ kotlinx.serialization.KSerializer serializer(...);
+}
+-keepclassmembers class <1>.<2> {
+ <1>.<2>$Companion Companion;
+}
+
+-keepnames class * implements android.os.Parcelable {
+ public static final ** CREATOR;
+}
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
+
+-dontwarn okhttp3.**
+-dontwarn okio.**
+
+# Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and
+# EnclosingMethod is required to use InnerClasses.
+-keepattributes Signature, InnerClasses, EnclosingMethod, *Annotation*, Exceptions
+
+# Retrofit does reflection on method and parameter annotations.
+-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations
+
+# Keep annotation default values (e.g., retrofit2.http.Field.encoded).
+-keepattributes AnnotationDefault
+
+# Retain service method parameters when optimizing.
+-keepclassmembers,allowshrinking,allowobfuscation interface * {
+ @retrofit2.http.* ;
+}
+
+-keepclasseswithmembers class * {
+ @retrofit2.http.* ;
+}
+-keepclassmembernames interface * {
+ @retrofit.http.* ;
+}
+
+# Ignore annotation used for build tooling.
+-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
+
+# Ignore JSR 305 annotations for embedding nullability information.
+-dontwarn javax.annotation.**
+
+# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath.
+-dontwarn kotlin.Unit
+
+# Top-level functions that can only be used by Kotlin.
+-dontwarn retrofit2.KotlinExtensions
+-dontwarn retrofit2.KotlinExtensions.*
+
+# With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy
+# and replaces all potential values with null. Explicitly keeping the interfaces prevents this.
+-if interface * { @retrofit2.http.* ; }
+-keep,allowobfuscation interface <1>
+
+# Keep generic signature of Call, Response (R8 full mode strips signatures from non-kept items).
+-keep,allowobfuscation,allowshrinking interface retrofit2.Call
+-keep,allowobfuscation,allowshrinking class retrofit2.Response
+
+# With R8 full mode generic signatures are stripped for classes that are not
+# kept. Suspend functions are wrapped in continuations where the type argument
+# is used.
+-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
+
+# public tangem android sdk
+-keep class com.tangem.operations.** { *; }
+-keep class com.tangem.crypto.** { *; }
+-keep class com.tangem.common.card.** { *; }
+
+# TODO remove (easy to fix in sdk)
+-keep class com.tangem.common.json.** { *; }
+-keep class com.tangem.common.SuccessResponse { *; }
+-keep class com.tangem.common.UserCode { *; }
+-keep class com.tangem.common.UserCodeType { *; }
+
+# non-sensitive enums
+-keep enum com.tangem.domain.apptheme.model.AppThemeMode { *; }
+
+-keep class com.reown.walletkit.client.Wallet$Model { *; }
+-keep class com.reown.walletkit.client.Wallet { *; }
+
+-keep class **.R
+-keep class **.R$* {
+ ;
+}
diff --git a/app/src/androidTest/kotlin/com/tangem/common/ApplicationInjectionExecutionRule.kt b/app/src/androidTest/kotlin/com/tangem/common/ApplicationInjectionExecutionRule.kt
new file mode 100644
index 0000000000..e1c23e8e9b
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/tangem/common/ApplicationInjectionExecutionRule.kt
@@ -0,0 +1,28 @@
+package com.tangem.common
+
+import androidx.test.core.app.ApplicationProvider
+import com.tangem.tap.ApplicationEntryPoint
+import com.tangem.tap.TangemApplication
+import dagger.hilt.android.testing.OnComponentReadyRunner
+import org.junit.rules.TestRule
+import org.junit.runner.Description
+import org.junit.runners.model.Statement
+
+class ApplicationInjectionExecutionRule : TestRule {
+
+ private val tangemApplication: TangemApplication
+ get() = ApplicationProvider.getApplicationContext()
+
+ override fun apply(base: Statement, description: Description): Statement {
+ return object : Statement() {
+ override fun evaluate() {
+ OnComponentReadyRunner.addListener(
+ tangemApplication, ApplicationEntryPoint::class.java
+ ) { _: ApplicationEntryPoint ->
+ tangemApplication.init()
+ }
+ base.evaluate()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/androidTest/kotlin/com/tangem/common/BaseTestCase.kt b/app/src/androidTest/kotlin/com/tangem/common/BaseTestCase.kt
new file mode 100644
index 0000000000..b028458c9b
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/tangem/common/BaseTestCase.kt
@@ -0,0 +1,66 @@
+package com.tangem.common
+
+import android.Manifest
+import androidx.test.rule.GrantPermissionRule
+import com.atiurin.ultron.core.compose.config.UltronComposeConfig
+import com.atiurin.ultron.core.compose.createUltronComposeRule
+import com.atiurin.ultron.core.compose.listeners.ComposDebugListener
+import com.atiurin.ultron.core.config.UltronCommonConfig
+import com.atiurin.ultron.core.config.UltronConfig
+import com.atiurin.ultron.core.test.UltronTest
+import com.tangem.datasource.local.preferences.AppPreferencesStore
+import com.tangem.sdk.api.TangemSdkManager
+import com.tangem.tap.MainActivity
+import dagger.hilt.android.testing.HiltAndroidRule
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.runBlocking
+import org.junit.BeforeClass
+import org.junit.Rule
+import javax.inject.Inject
+
+abstract class BaseTestCase : UltronTest() {
+ @Inject
+ lateinit var tangemSdkManager: TangemSdkManager
+
+ @Inject
+ lateinit var appPreferencesStore: AppPreferencesStore
+
+ @get:Rule(order = 0)
+ val grantPermissionRule: GrantPermissionRule = GrantPermissionRule.grant(
+ Manifest.permission.POST_NOTIFICATIONS,
+ Manifest.permission.CAMERA
+ )
+ @get:Rule(order = 1)
+ val hiltRule = HiltAndroidRule(this)
+
+ @get:Rule (order = 2)
+ val injectionRule = ApplicationInjectionExecutionRule()
+
+ @get:Rule(order = 3)
+ val composeRule = createUltronComposeRule()
+
+ override val beforeTest: () -> Unit = {
+ hiltRule.inject()
+ runBlocking {
+ delay(INIT_DELAY)
+ }
+ }
+
+ override val afterTest: () -> Unit = {
+ runBlocking {
+ appPreferencesStore.editData { prefs -> prefs.clear() }
+ }
+ }
+
+ companion object {
+ @BeforeClass
+ @JvmStatic
+ fun config() {
+ UltronConfig.applyRecommended()
+ UltronComposeConfig.applyRecommended()
+ UltronCommonConfig.addListener(ComposDebugListener())
+ }
+
+ private const val INIT_DELAY = 2000L
+ }
+}
\ No newline at end of file
diff --git a/app/src/androidTest/kotlin/com/tangem/common/HiltTestRunner.kt b/app/src/androidTest/kotlin/com/tangem/common/HiltTestRunner.kt
new file mode 100644
index 0000000000..3f5c02d5a5
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/tangem/common/HiltTestRunner.kt
@@ -0,0 +1,17 @@
+package com.tangem.common
+
+import android.app.Application
+import android.content.Context
+import androidx.test.runner.AndroidJUnitRunner
+import com.tangem.common.di.TangemMockedApplication_Application
+
+class HiltTestRunner : AndroidJUnitRunner() {
+
+ override fun newApplication(
+ cl: ClassLoader?,
+ className: String?,
+ context: Context?
+ ): Application {
+ return super.newApplication(cl, TangemMockedApplication_Application::class.java.name, context)
+ }
+}
\ No newline at end of file
diff --git a/app/src/androidTest/kotlin/com/tangem/common/TangemEmptyApplication.kt b/app/src/androidTest/kotlin/com/tangem/common/TangemEmptyApplication.kt
new file mode 100644
index 0000000000..2c1cb02a42
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/tangem/common/TangemEmptyApplication.kt
@@ -0,0 +1,11 @@
+package com.tangem.common
+
+import com.tangem.tap.TangemApplication
+
+open class TangemEmptyApplication : TangemApplication() {
+
+ override fun onCreate() {
+ // super.onCreate() is not called intentionally
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/androidTest/kotlin/com/tangem/common/di/TangemMockedApplication.kt b/app/src/androidTest/kotlin/com/tangem/common/di/TangemMockedApplication.kt
new file mode 100644
index 0000000000..06698555e9
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/tangem/common/di/TangemMockedApplication.kt
@@ -0,0 +1,7 @@
+package com.tangem.common.di
+
+import com.tangem.common.TangemEmptyApplication
+import dagger.hilt.android.testing.CustomTestApplication
+
+@CustomTestApplication(TangemEmptyApplication::class)
+internal class TangemMockedApplication
\ No newline at end of file
diff --git a/app/src/androidTest/kotlin/com/tangem/common/di/TestModule.kt b/app/src/androidTest/kotlin/com/tangem/common/di/TestModule.kt
new file mode 100644
index 0000000000..9ac4e38e62
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/tangem/common/di/TestModule.kt
@@ -0,0 +1,28 @@
+package com.tangem.common.di
+
+import android.content.Context
+import com.tangem.sdk.api.TangemSdkManager
+import com.tangem.tap.di.TangemSdkManagerModule
+import com.tangem.tap.domain.sdk.impl.MockTangemSdkManager
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.components.SingletonComponent
+import dagger.hilt.testing.TestInstallIn
+import javax.inject.Singleton
+
+@Module
+@TestInstallIn(
+ components = [SingletonComponent::class],
+ replaces = [TangemSdkManagerModule::class]
+)
+object TestModule {
+
+ @Provides
+ @Singleton
+ fun provideTangemSdkManager(
+ @ApplicationContext context: Context
+ ): TangemSdkManager {
+ return MockTangemSdkManager(resources = context.resources)
+ }
+}
\ No newline at end of file
diff --git a/app/src/androidTest/kotlin/com/tangem/common/extensions/TestDataUtils.kt b/app/src/androidTest/kotlin/com/tangem/common/extensions/TestDataUtils.kt
new file mode 100644
index 0000000000..671c7e4c60
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/tangem/common/extensions/TestDataUtils.kt
@@ -0,0 +1,9 @@
+package com.tangem.common.extensions
+
+import androidx.test.platform.app.InstrumentationRegistry
+
+object TestDataUtils {
+ fun getResourceString(resourceId: Int): String {
+ return InstrumentationRegistry.getInstrumentation().targetContext.resources.getString(resourceId)
+ }
+}
\ No newline at end of file
diff --git a/app/src/androidTest/kotlin/com/tangem/scenarios/MainPageScenario.kt b/app/src/androidTest/kotlin/com/tangem/scenarios/MainPageScenario.kt
new file mode 100644
index 0000000000..2513c160b0
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/tangem/scenarios/MainPageScenario.kt
@@ -0,0 +1,27 @@
+package com.tangem.scenarios
+
+import com.atiurin.ultron.allure.step.step
+import com.atiurin.ultron.extensions.assertIsDisplayed
+import com.atiurin.ultron.extensions.click
+import com.tangem.domain.models.scan.ProductType
+import com.tangem.screens.DisclaimerPage
+import com.tangem.screens.MainPage
+import com.tangem.screens.StoriesPage
+import com.tangem.tap.domain.sdk.mocks.MockProvider
+
+object MainPageScenario {
+ fun open(productType: ProductType? = null) {
+ if (productType != null) {
+ MockProvider.setMocks(productType)
+ }
+ step("Click on \"Accept\" button") {
+ DisclaimerPage.acceptButton.click()
+ }
+ step("Click on \"Scan\" button emulating scan error") {
+ StoriesPage.scanButton.click()
+ }
+ step("Assert: main is displayed") {
+ MainPage.container.assertIsDisplayed()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/androidTest/kotlin/com/tangem/screens/DetailsPage.kt b/app/src/androidTest/kotlin/com/tangem/screens/DetailsPage.kt
new file mode 100644
index 0000000000..990f09205c
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/tangem/screens/DetailsPage.kt
@@ -0,0 +1,16 @@
+package com.tangem.screens
+
+import androidx.compose.ui.test.hasText
+import com.atiurin.ultron.page.Page
+import com.tangem.common.extensions.TestDataUtils.getResourceString
+import com.tangem.wallet.R
+
+object DetailsPage : Page() {
+ val walletConnectButton = hasText(getResourceString(R.string.wallet_connect_title))
+ val walletNameButton = hasText(getResourceString(R.string.manage_tokens_network_selector_wallet))
+ val scanCardButton = hasText(getResourceString(R.string.scan_card_settings_button))
+ val buyTangemButton = hasText(getResourceString(R.string.details_buy_wallet))
+ val appSettingsButton = hasText(getResourceString(R.string.app_settings_title))
+ val contactSupportButton = hasText(getResourceString(R.string.details_row_title_contact_to_support))
+ val toSButton = hasText(getResourceString(R.string.disclaimer_title))
+}
\ No newline at end of file
diff --git a/app/src/androidTest/kotlin/com/tangem/screens/DisclaimerPage.kt b/app/src/androidTest/kotlin/com/tangem/screens/DisclaimerPage.kt
new file mode 100644
index 0000000000..b8dbd41150
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/tangem/screens/DisclaimerPage.kt
@@ -0,0 +1,9 @@
+package com.tangem.screens
+
+import androidx.compose.ui.test.hasTestTag
+import com.atiurin.ultron.page.Page
+import com.tangem.core.ui.test.TestTags
+
+object DisclaimerPage : Page() {
+ val acceptButton = hasTestTag(TestTags.DISCLAIMER_SCREEN_ACCEPT_BUTTON)
+}
\ No newline at end of file
diff --git a/app/src/androidTest/kotlin/com/tangem/screens/MainPage.kt b/app/src/androidTest/kotlin/com/tangem/screens/MainPage.kt
new file mode 100644
index 0000000000..f9016b3f69
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/tangem/screens/MainPage.kt
@@ -0,0 +1,9 @@
+package com.tangem.screens
+
+import androidx.compose.ui.test.hasTestTag
+import com.atiurin.ultron.page.Page
+import com.tangem.core.ui.test.TestTags
+
+object MainPage : Page() {
+ val container = hasTestTag(TestTags.MAIN_SCREEN)
+}
\ No newline at end of file
diff --git a/app/src/androidTest/kotlin/com/tangem/screens/StoriesPage.kt b/app/src/androidTest/kotlin/com/tangem/screens/StoriesPage.kt
new file mode 100644
index 0000000000..51f472521a
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/tangem/screens/StoriesPage.kt
@@ -0,0 +1,10 @@
+package com.tangem.screens
+
+import androidx.compose.ui.test.hasTestTag
+import com.atiurin.ultron.page.Page
+import com.tangem.core.ui.test.TestTags
+
+object StoriesPage : Page() {
+ val scanButton = hasTestTag(TestTags.STORIES_SCREEN_SCAN_BUTTON)
+ val orderButton = hasTestTag(TestTags.STORIES_SCREEN_ORDER_BUTTON)
+}
\ No newline at end of file
diff --git a/app/src/androidTest/kotlin/com/tangem/screens/TopBarPage.kt b/app/src/androidTest/kotlin/com/tangem/screens/TopBarPage.kt
new file mode 100644
index 0000000000..2505ffae8b
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/tangem/screens/TopBarPage.kt
@@ -0,0 +1,9 @@
+package com.tangem.screens
+
+import androidx.compose.ui.test.hasTestTag
+import com.atiurin.ultron.page.Page
+import com.tangem.core.ui.test.TestTags
+
+object TopBarPage : Page() {
+ val moreButton = hasTestTag(TestTags.MAIN_SCREEN_MORE_BUTTON)
+}
\ No newline at end of file
diff --git a/app/src/androidTest/kotlin/com/tangem/screens/WalletSettingsPage.kt b/app/src/androidTest/kotlin/com/tangem/screens/WalletSettingsPage.kt
new file mode 100644
index 0000000000..a38559a523
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/tangem/screens/WalletSettingsPage.kt
@@ -0,0 +1,13 @@
+package com.tangem.screens
+
+import androidx.compose.ui.test.hasText
+import com.atiurin.ultron.page.Page
+import com.tangem.common.extensions.TestDataUtils.getResourceString
+import com.tangem.wallet.R
+
+object WalletSettingsPage : Page() {
+ val linkMoreCardsButton = hasText(getResourceString(R.string.details_row_title_create_backup))
+ val cardSettingsButton = hasText(getResourceString(R.string.card_settings_title))
+ val referralProgramButton = hasText(getResourceString(R.string.details_referral_title))
+ val forgetWalletButton = hasText(getResourceString(R.string.settings_forget_wallet))
+}
\ No newline at end of file
diff --git a/app/src/androidTest/kotlin/com/tangem/tests/DetailsScreenTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/DetailsScreenTest.kt
new file mode 100644
index 0000000000..1951caf4d7
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/tangem/tests/DetailsScreenTest.kt
@@ -0,0 +1,138 @@
+package com.tangem.tests
+
+import com.atiurin.ultron.allure.step.step
+import com.atiurin.ultron.extensions.assertIsDisplayed
+import com.atiurin.ultron.extensions.assertIsNotDisplayed
+import com.atiurin.ultron.extensions.click
+import com.tangem.common.BaseTestCase
+import com.tangem.domain.models.scan.ProductType
+import com.tangem.scenarios.MainPageScenario
+import com.tangem.screens.DetailsPage
+import com.tangem.screens.TopBarPage
+import com.tangem.screens.WalletSettingsPage
+import dagger.hilt.android.testing.HiltAndroidTest
+import org.junit.Test
+
+@HiltAndroidTest
+class DetailsScreenTest : BaseTestCase() {
+
+ @Test
+ fun walletWithoutBackupDetails() {
+ MainPageScenario.open()
+ step("Open wallet details") {
+ TopBarPage.moreButton.click()
+ }
+ step("Assert wallet connect button is visible") {
+ DetailsPage.walletConnectButton.assertIsDisplayed()
+ }
+ step("Assert scan card button is visible") {
+ DetailsPage.scanCardButton.assertIsDisplayed()
+ }
+ step("Assert buy Tangem card button is visible") {
+ DetailsPage.buyTangemButton.assertIsDisplayed()
+ }
+ step("Assert app settings button is visible") {
+ DetailsPage.appSettingsButton.assertIsDisplayed()
+ }
+ step("Assert contact support button is visible") {
+ DetailsPage.contactSupportButton.assertIsDisplayed()
+ }
+ step("Assert terms or service button is visible") {
+ DetailsPage.toSButton.assertIsDisplayed()
+ }
+ step("Open wallet settings screen") {
+ DetailsPage.walletNameButton.click()
+ }
+ step("Assert Link more cards button is visible") {
+ WalletSettingsPage.linkMoreCardsButton.assertIsDisplayed()
+ }
+ step("Assert Card Settings button is visible") {
+ WalletSettingsPage.cardSettingsButton.assertIsDisplayed()
+ }
+ step("Assert Referral program button is visible") {
+ WalletSettingsPage.referralProgramButton.assertIsDisplayed()
+ }
+ step("Assert Forget wallet button is visible") {
+ WalletSettingsPage.forgetWalletButton.assertIsDisplayed()
+ }
+ }
+
+ @Test
+ fun wallet2Details() {
+ MainPageScenario.open(ProductType.Wallet2)
+ step("Open wallet details") {
+ TopBarPage.moreButton.click()
+ }
+ step("Assert wallet connect button is visible") {
+ DetailsPage.walletConnectButton.assertIsDisplayed()
+ }
+ step("Assert scan card button is visible") {
+ DetailsPage.scanCardButton.assertIsDisplayed()
+ }
+ step("Assert buy Tangem card button is visible") {
+ DetailsPage.buyTangemButton.assertIsDisplayed()
+ }
+ step("Assert app settings button is visible") {
+ DetailsPage.appSettingsButton.assertIsDisplayed()
+ }
+ step("Assert contact support button is visible") {
+ DetailsPage.contactSupportButton.assertIsDisplayed()
+ }
+ step("Assert terms or service button is visible") {
+ DetailsPage.toSButton.assertIsDisplayed()
+ }
+ step("Open wallet settings screen") {
+ DetailsPage.walletNameButton.click()
+ }
+ step("Assert Link more cards button does not exist") {
+ WalletSettingsPage.linkMoreCardsButton.assertIsNotDisplayed()
+ }
+ step("Assert Card Settings button is visible") {
+ WalletSettingsPage.cardSettingsButton.assertIsDisplayed()
+ }
+ step("Assert Referral program button is visible") {
+ WalletSettingsPage.referralProgramButton.assertIsDisplayed()
+ }
+ step("Assert Forget wallet button is visible") {
+ WalletSettingsPage.forgetWalletButton.assertIsDisplayed()
+ }
+ }
+
+ @Test
+ fun noteDetails() {
+ MainPageScenario.open(ProductType.Note)
+ step("Open wallet details") {
+ TopBarPage.moreButton.click()
+ }
+ step("Assert wallet connect button does not exist") {
+ DetailsPage.walletConnectButton.assertIsNotDisplayed()
+ }
+ step("Assert scan card button is visible") {
+ DetailsPage.scanCardButton.assertIsDisplayed()
+ }
+ step("Assert buy Tangem card button is visible") {
+ DetailsPage.buyTangemButton.assertIsDisplayed()
+ }
+ step("Assert app settings button is visible") {
+ DetailsPage.appSettingsButton.assertIsDisplayed()
+ }
+ step("Assert contact support button is visible") {
+ DetailsPage.contactSupportButton.assertIsDisplayed()
+ }
+ step("Assert terms or service button is visible") {
+ DetailsPage.toSButton.assertIsDisplayed()
+ }
+ step("Open wallet settings screen") {
+ DetailsPage.walletNameButton.click()
+ }
+ step("Assert Card Settings button is visible") {
+ WalletSettingsPage.cardSettingsButton.assertIsDisplayed()
+ }
+ step("Assert Referral program button does not exist") {
+ WalletSettingsPage.referralProgramButton.assertIsNotDisplayed()
+ }
+ step("Assert Forget wallet button is visible") {
+ WalletSettingsPage.forgetWalletButton.assertIsDisplayed()
+ }
+ }
+}
diff --git a/app/src/androidTest/kotlin/com/tangem/tests/ScanErrorTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/ScanErrorTest.kt
new file mode 100644
index 0000000000..de198088d3
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/tangem/tests/ScanErrorTest.kt
@@ -0,0 +1,42 @@
+package com.tangem.tests
+
+import com.atiurin.ultron.allure.step.step
+import com.atiurin.ultron.extensions.assertIsDisplayed
+import com.atiurin.ultron.extensions.assertIsNotDisplayed
+import com.atiurin.ultron.extensions.click
+import com.tangem.common.BaseTestCase
+import com.tangem.screens.DisclaimerPage
+import com.tangem.screens.MainPage
+import com.tangem.screens.StoriesPage
+import com.tangem.tap.domain.sdk.mocks.MockProvider
+import dagger.hilt.android.testing.HiltAndroidTest
+import org.junit.Test
+
+@HiltAndroidTest
+class ScanErrorTest : BaseTestCase() {
+
+ @Test
+ fun goToMain() {
+ step("Click on \"Accept\" button") {
+ DisclaimerPage.acceptButton.click()
+ }
+ step("Emulate scan error") {
+ MockProvider.setEmulateError()
+ }
+ step("Click on \"Scan\" button emulating scan error") {
+ StoriesPage.scanButton.click()
+ }
+ step("Assert: Error is displayed") {
+ MainPage.container.assertIsNotDisplayed()
+ }
+ step("Emulate success scan") {
+ MockProvider.resetEmulateError()
+ }
+ step("Click on \"Scan\" button") {
+ StoriesPage.scanButton.click()
+ }
+ step("Assert: wallet screen is displayed") {
+ MainPage.container.assertIsDisplayed()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/androidTest/kotlin/com/tangem/tests/StoriesTest.kt b/app/src/androidTest/kotlin/com/tangem/tests/StoriesTest.kt
new file mode 100644
index 0000000000..5adaaeada1
--- /dev/null
+++ b/app/src/androidTest/kotlin/com/tangem/tests/StoriesTest.kt
@@ -0,0 +1,36 @@
+package com.tangem.tests
+
+import android.content.Intent.ACTION_VIEW
+import androidx.test.espresso.intent.Intents
+import androidx.test.espresso.intent.matcher.IntentMatchers.hasAction
+import androidx.test.espresso.intent.matcher.IntentMatchers.hasData
+import com.atiurin.ultron.allure.step.step
+import com.atiurin.ultron.core.config.UltronConfig.UiAutomator.Companion.uiDevice
+import com.atiurin.ultron.extensions.click
+import com.tangem.common.BaseTestCase
+import com.tangem.screens.DisclaimerPage
+import com.tangem.screens.StoriesPage
+import com.tangem.tap.features.home.redux.HomeMiddleware.NEW_BUY_WALLET_URL
+import dagger.hilt.android.testing.HiltAndroidTest
+import org.hamcrest.core.AllOf.allOf
+import org.junit.Test
+
+@HiltAndroidTest
+class StoriesTest : BaseTestCase() {
+
+ @Test
+ fun checkOrderButton() {
+ Intents.init()
+ step("Click Accept on ToS") {
+ DisclaimerPage.acceptButton.click()
+ }
+ step("Click order button ") {
+ StoriesPage.orderButton.click()
+ }
+ step("Assert: browser is opened ") {
+ Intents.intended(allOf(hasAction(ACTION_VIEW), hasData(NEW_BUY_WALLET_URL)))
+ uiDevice.pressBack()
+ Intents.release()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/debug/AndroidManifest.xml b/app/src/debug/AndroidManifest.xml
deleted file mode 100644
index 2784e858d0..0000000000
--- a/app/src/debug/AndroidManifest.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/debug/res/values-ru/strings.xml b/app/src/debug/res/values-ru/strings.xml
deleted file mode 100644
index 682b552975..0000000000
--- a/app/src/debug/res/values-ru/strings.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
- DebugTangem
-
-
\ No newline at end of file
diff --git a/app/src/debug/res/values/strings.xml b/app/src/debug/res/values/strings.xml
index 764dd201cc..0911a552b7 100644
--- a/app/src/debug/res/values/strings.xml
+++ b/app/src/debug/res/values/strings.xml
@@ -1,6 +1,6 @@
- DebugTangem
+ Debug Tangem
-
\ No newline at end of file
+
diff --git a/app/src/debug/res/values/values.xml b/app/src/debug/res/values/values.xml
new file mode 100644
index 0000000000..8cc3a85358
--- /dev/null
+++ b/app/src/debug/res/values/values.xml
@@ -0,0 +1,4 @@
+
+
+ true
+
\ No newline at end of file
diff --git a/app/src/debug/res/xml/network_security_config.xml b/app/src/debug/res/xml/network_security_config.xml
new file mode 100644
index 0000000000..52c44ac992
--- /dev/null
+++ b/app/src/debug/res/xml/network_security_config.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/src/debug_beta/AndroidManifest.xml b/app/src/debug_beta/AndroidManifest.xml
deleted file mode 100644
index 2784e858d0..0000000000
--- a/app/src/debug_beta/AndroidManifest.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/debug_beta/res/values-ru/strings.xml b/app/src/debug_beta/res/values-ru/strings.xml
deleted file mode 100644
index 3ae149049f..0000000000
--- a/app/src/debug_beta/res/values-ru/strings.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
- BetaTangem
-
-
\ No newline at end of file
diff --git a/app/src/debug_beta/res/values/strings.xml b/app/src/debug_beta/res/values/strings.xml
deleted file mode 100644
index 3ae149049f..0000000000
--- a/app/src/debug_beta/res/values/strings.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
- BetaTangem
-
-
\ No newline at end of file
diff --git a/app/src/external/res/values/strings.xml b/app/src/external/res/values/strings.xml
new file mode 100644
index 0000000000..1e2d2f4d56
--- /dev/null
+++ b/app/src/external/res/values/strings.xml
@@ -0,0 +1,6 @@
+
+
+
+ External Tangem
+
+
diff --git a/app/src/external/res/values/values.xml b/app/src/external/res/values/values.xml
new file mode 100644
index 0000000000..8cc3a85358
--- /dev/null
+++ b/app/src/external/res/values/values.xml
@@ -0,0 +1,4 @@
+
+
+ true
+
\ No newline at end of file
diff --git a/app/src/external/res/xml/network_security_config.xml b/app/src/external/res/xml/network_security_config.xml
new file mode 100644
index 0000000000..d49c0f70ba
--- /dev/null
+++ b/app/src/external/res/xml/network_security_config.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/internal/res/values/strings.xml b/app/src/internal/res/values/strings.xml
new file mode 100644
index 0000000000..4ba0d6fad8
--- /dev/null
+++ b/app/src/internal/res/values/strings.xml
@@ -0,0 +1,6 @@
+
+
+
+ Internal Tangem
+
+
diff --git a/app/src/internal/res/values/values.xml b/app/src/internal/res/values/values.xml
new file mode 100644
index 0000000000..8cc3a85358
--- /dev/null
+++ b/app/src/internal/res/values/values.xml
@@ -0,0 +1,4 @@
+
+
+ true
+
\ No newline at end of file
diff --git a/app/src/internal/res/xml/network_security_config.xml b/app/src/internal/res/xml/network_security_config.xml
new file mode 100644
index 0000000000..52c44ac992
--- /dev/null
+++ b/app/src/internal/res/xml/network_security_config.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5fa1e04d9d..1ebb3c801a 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,8 +1,8 @@
+ xmlns:tools="http://schemas.android.com/tools">
+
@@ -10,8 +10,7 @@
-
-
+
@@ -26,28 +25,41 @@
+
+
+
+
+
+
+ tools:replace="android:allowBackup, android:fullBackupContent, android:label">
+
@@ -57,40 +69,25 @@
-
-
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
+
+
+
-
-
-
+
+
+
+
+
+
+
@@ -120,7 +117,7 @@
@@ -131,17 +128,23 @@
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/app/src/main/assets/features_dev.json b/app/src/main/assets/features_dev.json
deleted file mode 100644
index 82e46b21bf..0000000000
--- a/app/src/main/assets/features_dev.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "isWalletPayIdEnabled": true,
- "isSendingToPayIdEnabled": true,
- "isTopUpEnabled": true,
- "isCreatingTwinCardsAllowed": true
-}
\ No newline at end of file
diff --git a/app/src/main/assets/features_prod.json b/app/src/main/assets/features_prod.json
deleted file mode 100644
index d3b1375fae..0000000000
--- a/app/src/main/assets/features_prod.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "isWalletPayIdEnabled": false,
- "isSendingToPayIdEnabled": true,
- "isTopUpEnabled": true,
- "isCreatingTwinCardsAllowed": true
-}
\ No newline at end of file
diff --git a/app/src/main/assets/fw_hashes.json b/app/src/main/assets/fw_hashes.json
deleted file mode 100644
index 9c86b3a1db..0000000000
--- a/app/src/main/assets/fw_hashes.json
+++ /dev/null
@@ -1,138 +0,0 @@
-[
- {
- "fw":"1.24r",
- "challenge":"00000000000000000000000000000001",
- "sha-256":[
- {"block":0,"count":1,"digest":"9B091DF443FE951D27AA8843517096DC421433F5603EBC566B11891F867E3D18"},
- {"block":1,"count":1,"digest":"B4F723EE79075C8C00FA17D037BF10528BB0C7CF421539EE15F4A397204C87AF"},
- {"block":2,"count":1,"digest":"1258585B438B6BC8F41FC22AFF383C86690E984E84E96AA752C9A54954DF731A"},
- {"block":3,"count":1,"digest":"14082C75D6AA533A06E9B764642F97B5783FED91BD1173EFADC3CF57D8769AAE"},
- {"block":4,"count":1,"digest":"A8F6CB02D56933361127072BB0D89999020CE196AE9718E9CF019DCCC9437E85"},
- {"block":5,"count":1,"digest":"491604BA2A2F6EE03A2B4812958F0356D745678FB0ABABF0109A9E8F59099D9D"},
- {"block":6,"count":1,"digest":"B2F057FF8B83343BC40058CA459F3C63B9670ABCD059730BE70223AEBDC88D77"},
- {"block":7,"count":1,"digest":"73F4391010345E27745A1AFEC93C02B2CA460D9EAB437605F82A18281DF17DCE"},
- {"block":8,"count":1,"digest":"74588EBB6704DD3DB9ECDFE6B85EC2872BD6A1F7C73E080E57697D3FF8DDD470"},
- {"block":9,"count":1,"digest":"3B382C35ADBBF206B0A6B216EE95AF2321EE34148E93BBFECCF275AB13ED08A2"},
- {"block":11500,"count":1,"digest":"21DDEC9788E3EA04663297AD0208F2714F139434E3540EBB7C96150EE1D320C9"},
- {"block":11501,"count":1,"digest":"C545C5D092D1EBC4BA266C139CE0F2A399E4D23E74EB4EBD0E53019AB58CB486"},
- {"block":0,"count":0,"digest":"C689C50352E9F6E41BF2E6EC852D8466814A51018F40BE32BAADEE9C2A9E6B6D"}
- ],
- "crc-16":[
- {"block":0,"count":1,"digest":"1BFC"},
- {"block":1,"count":1,"digest":"D58D"},
- {"block":2,"count":1,"digest":"7E3E"},
- {"block":3,"count":1,"digest":"14EA"},
- {"block":4,"count":1,"digest":"014F"},
- {"block":5,"count":1,"digest":"5FF0"},
- {"block":6,"count":1,"digest":"7D3A"},
- {"block":7,"count":1,"digest":"702C"},
- {"block":8,"count":1,"digest":"CC22"},
- {"block":9,"count":1,"digest":"392C"},
- {"block":11500,"count":1,"digest":"5FCB"},
- {"block":11501,"count":1,"digest":"FF77"},
- {"block":0,"count":0,"digest":"D07B"}
- ]
- },
- {
- "fw":"1.24d SDK",
- "challenge":"00000000000000000000000000000001",
- "sha-256":[
- {"block":0,"count":1,"digest":"6B360B47FFB16641EF9CC778746FE6B1010AB60C69281CE431A46ECC29A72304"},
- {"block":1,"count":1,"digest":"648F50D44E9A31CB4C2682EAD7B8E2E570E5F252035849CD9B08BD4F9106B432"},
- {"block":2,"count":1,"digest":"BAA31588F599E2DBC8AC06CFBF4E710B9B0E3FEA0201AE67E5A9E605DB50D1ED"},
- {"block":3,"count":1,"digest":"48CFA13758F0B8018A97831C11BB1668A39CC76B141C90038551D950F83A43BA"},
- {"block":4,"count":1,"digest":"8932B8E9D93A28EEEAC8FD3477F38A8A384AC895B06E09B8396A7806C3DCFC09"},
- {"block":5,"count":1,"digest":"A3E7F2911AB380B366E47EB9E7DCC0C3D8667EEE3CF355FCCD5B113918873EFC"},
- {"block":6,"count":1,"digest":"32CFCDC12C3AAA6C8FE4935C76B795A81206141AE7C7AB941A4B5F74EB02D844"},
- {"block":7,"count":1,"digest":"1BA7B6ED5F28A0744E177843F2A960CB757B27FF6052C17F9E57B266AEC4F564"},
- {"block":8,"count":1,"digest":"7C1A2C88529DA038C3A124CC049B9A5CD73089C2CD9C66B15DF91020E981B94B"},
- {"block":9,"count":1,"digest":"5F14E10CBE14230EEF9B8896C84998197E56738952A1ECF22202801B9AE64340"},
- {"block":10,"count":1,"digest":"8FF4F496E7C68A654E574F13517EFA4F2058FDFC9E949421DA5ACC855C876F63"},
- {"block":11491,"count":1,"digest":"E45CFEA35B1C4C217A55B78B0D78C841978F1008C3C1917D228EECB0324A0942"},
- {"block":0,"count":0,"digest":"F4199A74F2D4BAF2E282A670989A50B9186665D8EC453D1CED02F4E4019E1C0F"}
- ],
- "crc-16":[
- {"block":0,"count":1,"digest":"22C3"},
- {"block":1,"count":1,"digest":"ECB2"},
- {"block":2,"count":1,"digest":"4701"},
- {"block":3,"count":1,"digest":"2DD5"},
- {"block":4,"count":1,"digest":"3870"},
- {"block":5,"count":1,"digest":"66CF"},
- {"block":6,"count":1,"digest":"4405"},
- {"block":7,"count":1,"digest":"4913"},
- {"block":8,"count":1,"digest":"F51D"},
- {"block":9,"count":1,"digest":"0013"},
- {"block":10,"count":1,"digest":"5E68"},
- {"block":11491,"count":1,"digest":"4078"},
- {"block":0,"count":0,"digest":"75C3"}
- ]
- },
- {
- "fw":"1.28r",
- "challenge":"00000000000000000000000000000001",
- "sha-256":[
- {"block":0,"count":1,"digest":"A52D552A4CCA2979122300C7C8686031FBB216C187971C739305D493284DD262"},
- {"block":1,"count":1,"digest":"AF8D5DDC8FD0BA9B58707BC66940A50298AAB6FFE74D243874BAA25CCD53C7C3"},
- {"block":2,"count":1,"digest":"03612CB50531C2A2B7825B6A72C14528522A926A781391E8FE17027943543387"},
- {"block":3,"count":1,"digest":"88A984179C97654B7833824DF43A13133BC6E627C17C9A65BEEDFB671CD78D2A"},
- {"block":4,"count":1,"digest":"A3DB1DD3F876ED972287FEC903C2112F6B99A09BCF686E2B65A6E19EA9CD9ECB"},
- {"block":5,"count":1,"digest":"CA7685FCD6BE9D8310BBD58AA7DED1390925BADA47B6611DB010625CA6BA7542"},
- {"block":6,"count":1,"digest":"192E10BF1D4AA426676918AAC7312FF4914A4781A2E6372986356AC26917078B"},
- {"block":7,"count":1,"digest":"00B657206A8120DE159F3C16B4F036B7D2D292603067FCB6B33E3753421D9D15"},
- {"block":8,"count":1,"digest":"2F875EE18AD37A3A4666810E7E0942F7370CAD365C510B7952280EC43BE12ADE"},
- {"block":9,"count":1,"digest":"1CFAF013B43CAF9F6627DAC871335B09279375A9DE8644AEB2FBBA105C73C05A"},
- {"block":10,"count":1,"digest":"AD33E62400EFE078EB9256C3A6F9B9299A4B56F4A7E63E78C9BC34F7DCA2FE10"},
- {"block":11497,"count":1,"digest":"FBB56C858CF485012A08343B73C46CDA7423500D52FBE5E4F28326F2515C7150"},
- {"block":0,"count":0,"digest":"7582258B2AF9FDCD83BCDEA05FA0310216F7CFF4FB27C699461397EF4D189567"}
- ],
- "crc-16":[
- {"block":0,"count":1,"digest":"B42D"},
- {"block":1,"count":1,"digest":"7A5C"},
- {"block":2,"count":1,"digest":"D1EF"},
- {"block":3,"count":1,"digest":"BB3B"},
- {"block":4,"count":1,"digest":"AE9E"},
- {"block":5,"count":1,"digest":"F021"},
- {"block":6,"count":1,"digest":"D2EB"},
- {"block":7,"count":1,"digest":"DFFD"},
- {"block":8,"count":1,"digest":"63F3"},
- {"block":9,"count":1,"digest":"96FD"},
- {"block":10,"count":1,"digest":"C886"},
- {"block":11497,"count":1,"digest":"E4B0"},
- {"block":0,"count":0,"digest":"0143"}
- ]
- },
- {
- "fw":"1.28d SDK",
- "challenge":"00000000000000000000000000000001",
- "sha-256":[
- {"block":0,"count":1,"digest":"2F9DB9B70A20E28A97A6A58919E71ABF757BA73E693D9DC9CEEE1B0BCA8DAB8E"},
- {"block":1,"count":1,"digest":"6B6F75ECF7E9CB76E570C290E7BEEAEF44E4B24C46BA4AA115D5BBAE3209869F"},
- {"block":2,"count":1,"digest":"4D584DDC73B940C7E508456BF0C52BC6BE018CD448A5886B54BEBF1D26D31AD5"},
- {"block":3,"count":1,"digest":"A9D5929A34793F5BCC623234AE34DEE246A95ED34D75D51508B9DC2694F28CD6"},
- {"block":4,"count":1,"digest":"094D5F3E03262B6D07E58F795E17FFF2D83D39ABCF86B3B04A856A37BB076AD0"},
- {"block":5,"count":1,"digest":"40F5586223406B2BD790629AB5D8D1AB97B6EA9151B69BF4D55C4A1EF5E2A1BB"},
- {"block":6,"count":1,"digest":"B56C71A3E6DFE98B1666825825844372EEE5811EEA743A40760FA7AE2D66CADD"},
- {"block":7,"count":1,"digest":"4331EB4B7415883536DDBA03D75F0408BE1F23F3DEE4459227755C12CBF98A8D"},
- {"block":8,"count":1,"digest":"7383EDD57D266591760CD74E50073D28973CB2DAFD1410E45030B33588768DEE"},
- {"block":9,"count":1,"digest":"893F5CF5E368E82CABE7F48D5DAA54AFAFA740B28496F303E845E680B7C1436C"},
- {"block":10,"count":1,"digest":"8DEEB29CD6C764FB7AB53A056BC3C860DBD8E121AB7C1E6E4DF3C273A503C405"},
- {"block":11497,"count":1,"digest":"6F6166E13672B12BD947CDFEC3158064A14C5A259AD0B3550738E30E90BC20C5"},
- {"block":0,"count":0,"digest":"E475661F4D0948ACBDF104EAD718260A73FB99448691F0EB68AED85D189B6F3C"}
- ],
- "crc-16":[
- {"block":0,"count":1,"digest":"3506"},
- {"block":1,"count":1,"digest":"FB77"},
- {"block":2,"count":1,"digest":"50C4"},
- {"block":3,"count":1,"digest":"3A10"},
- {"block":4,"count":1,"digest":"2FB5"},
- {"block":5,"count":1,"digest":"710A"},
- {"block":6,"count":1,"digest":"53C0"},
- {"block":7,"count":1,"digest":"5ED6"},
- {"block":8,"count":1,"digest":"E2D8"},
- {"block":9,"count":1,"digest":"17D6"},
- {"block":10,"count":1,"digest":"49AD"},
- {"block":11497,"count":1,"digest":"659B"},
- {"block":0,"count":0,"digest":"1893"}
- ]
- }
-]
\ No newline at end of file
diff --git a/app/src/main/assets/tangem-app-config b/app/src/main/assets/tangem-app-config
index 93150ef69d..89dac3cd1e 160000
--- a/app/src/main/assets/tangem-app-config
+++ b/app/src/main/assets/tangem-app-config
@@ -1 +1 @@
-Subproject commit 93150ef69daf244a92266d7cdfbc9294b745b4e2
+Subproject commit 89dac3cd1e171d5801596ad151aa3af3fbc6c140
diff --git a/app/src/main/assets/testnet_tokens.json b/app/src/main/assets/testnet_tokens.json
index 4053d99fcb..ad10260b6b 100644
--- a/app/src/main/assets/testnet_tokens.json
+++ b/app/src/main/assets/testnet_tokens.json
@@ -12,6 +12,16 @@
}
]
},
+ {
+ "id" : "kaspa",
+ "symbol" : "KAS",
+ "name" : "Kaspa",
+ "networks" : [
+ {
+ "networkId" : "kaspa/test"
+ }
+ ]
+ },
{
"id" : "Dai Stablecoin-DAI",
"symbol" : "DAI",
@@ -148,6 +158,17 @@
}
]
},
+ {
+ "id": "the-open-network",
+ "symbol": "TON",
+ "name": "Toncoin",
+ "networks":
+ [
+ {
+ "networkId": "the-open-network/test"
+ }
+ ]
+ },
{
"id" : "Tangem Coin A-TCA",
"symbol" : "TCA",
@@ -391,6 +412,28 @@
}
]
},
+ {
+ "id" : "vechain",
+ "symbol" : "VET",
+ "name" : "VeChain",
+ "networks" : [
+ {
+ "networkId" : "vechain/test"
+ }
+ ]
+ },
+ {
+ "id": "vethor-token",
+ "symbol": "VTHO",
+ "name": "VeThor",
+ "networks": [
+ {
+ "networkId": "vechain/test",
+ "contractAddress": "0x0000000000000000000000000000456e65726779",
+ "decimalCount": 18
+ }
+ ]
+ },
{
"id" : "tron",
"symbol" : "TRX",
@@ -401,6 +444,16 @@
}
]
},
+ {
+ "id" : "algorand",
+ "symbol" : "ALGO",
+ "name" : "Algorand",
+ "networks" : [
+ {
+ "networkId" : "algorand/test"
+ }
+ ]
+ },
{
"id" : "arbitrum-one",
"symbol" : "ETH",
@@ -451,9 +504,300 @@
"networkId": "optimistic-ethereum/test"
}
]
+ },
+ {
+ "id": "kava",
+ "symbol": "KAVA",
+ "name": "Kava EVM",
+ "networks":
+ [
+ {
+ "networkId": "kava/test"
+ }
+ ]
+ },
+ {
+ "id": "telos",
+ "symbol": "TLOS",
+ "name": "Telos EVM",
+ "networks":
+ [
+ {
+ "networkId": "telos/test"
+ }
+ ]
+ },
+ {
+ "id": "ravencoin",
+ "symbol": "RVN",
+ "name": "Ravencoin",
+ "networks":
+ [
+ {
+ "networkId": "ravencoin/test"
+ }
+ ]
+ },
+ {
+ "id": "cosmos",
+ "symbol": "ATOM",
+ "name": "Cosmos Hub",
+ "networks":
+ [
+ {
+ "networkId": "cosmos/test"
+ }
+ ]
+ },
+ {
+ "id": "aleph-zero",
+ "symbol": "AZERO",
+ "name": "Aleph Zero",
+ "networks": [
+ {
+ "networkId": "aleph-zero/test"
+ }
+ ]
+ },
+ {
+ "id": "near",
+ "symbol": "NEAR",
+ "name": "NEAR",
+ "networks": [
+ {
+ "networkId": "near-protocol/test"
+ }
+ ]
+ },
+ {
+ "id": "decimal",
+ "name": "Decimal",
+ "symbol": "tDEL",
+ "networks": [
+ {
+ "networkId": "decimal/test"
+ }
+ ]
+ },
+ {
+ "id": "xdce-crowd-sale",
+ "name": "XDC",
+ "symbol": "XDC",
+ "networks": [
+ {
+ "networkId": "xdc-network/test"
+ }
+ ]
+ },
+ {
+ "id": "shibarium",
+ "name": "Shibarium",
+ "symbol": "BONE",
+ "networks": [
+ {
+ "networkId": "shibarium/test"
+ }
+ ]
+ },
+ {
+ "id": "aptos",
+ "name": "Aptos",
+ "symbol": "APT",
+ "networks": [
+ {
+ "networkId": "aptos/test"
+ }
+ ]
+ },
+ {
+ "id": "hedera-hashgraph",
+ "name": "Hedera",
+ "symbol": "HBAR",
+ "networks": [
+ {
+ "networkId": "hedera-hashgraph/test"
+ }
+ ]
+ },
+ {
+ "id": "aurora-ethereum",
+ "name": "Aurora Testnet",
+ "symbol": "ETH",
+ "networks": [
+ {
+ "networkId": "aurora/test"
+ }
+ ]
+ },
+ {
+ "id": "areon-network",
+ "name": "Areon Network Testnet",
+ "symbol": "TAREA",
+ "networks": [
+ {
+ "networkId": "areon-network/test"
+ }
+ ]
+ },
+ {
+ "id": "pulsechain",
+ "name": "PulseChain Testnet v4",
+ "symbol": "tPLS",
+ "networks": [
+ {
+ "networkId": "pulsechain/test"
+ }
+ ]
+ },
+ {
+ "id": "zksync-ethereum",
+ "name": "zkSync",
+ "symbol": "ETH",
+ "networks": [
+ {
+ "networkId": "zksync/test"
+ }
+ ]
+ },
+ {
+ "id": "moonbeam",
+ "name": "Moonbeam",
+ "symbol": "GLMR",
+ "networks": [
+ {
+ "networkId": "moonbeam/test"
+ }
+ ]
+ },
+ {
+ "id": "manta-pacific",
+ "name": "Manta Testnet",
+ "symbol": "ETH",
+ "networks": [
+ {
+ "networkId": "manta-pacific/test"
+ }
+ ]
+ },
+ {
+ "id": "polygon-zkevm-ethereum",
+ "name": "Polygon zkEvm Testnet",
+ "symbol": "ETH",
+ "networks": [
+ {
+ "networkId": "polygon-zkevm/test"
+ }
+ ]
+ },
+ {
+ "id": "base-ethereum",
+ "name": "Base",
+ "symbol": "ETH",
+ "networks": [
+ {
+ "networkId": "base/test"
+ }
+ ]
+ },
+ {
+ "id": "blast-ethereum",
+ "name": "Blast",
+ "symbol": "ETH",
+ "networks": [
+ {
+ "networkId": "blast/test"
+ }
+ ]
+ },
+ {
+ "id": "cyberconnect",
+ "name": "Cyber",
+ "symbol": "ETH",
+ "networks": [
+ {
+ "networkId": "cyber/test"
+ }
+ ]
+ },
+ {
+ "id": "sei-network",
+ "name": "Sei Network",
+ "symbol": "SEI",
+ "networks": [
+ {
+ "networkId": "sei-network/test"
+ }
+ ]
+ },
+ {
+ "id": "energy-web-chain",
+ "name": "Energy Web Chain",
+ "symbol": "EWT",
+ "networks": [
+ {
+ "networkId": "energy-web-chain/test"
+ }
+ ]
+ },
+ {
+ "id": "energy-web-x",
+ "name": "Energy Web X",
+ "symbol": "EWT",
+ "networks": [
+ {
+ "networkId": "energy-web-x/test"
+ }
+ ]
+ },
+ {
+ "id": "core",
+ "name": "Core",
+ "symbol": "CORE",
+ "networks": [
+ {
+ "networkId": "core/test"
+ }
+ ]
+ },
+ {
+ "id": "chiliz",
+ "name": "Chiliz",
+ "symbol": "CHZ",
+ "networks": [
+ {
+ "networkId": "chiliz/test"
+ }
+ ]
+ },
+ {
+ "id": "vanar-chain",
+ "name": "Vanar Chain",
+ "symbol": "VANRY",
+ "networks": [
+ {
+ "networkId": "vanar-chain/test"
+ }
+ ]
+ },
+ {
+ "id": "casper-network",
+ "name": "Casper",
+ "symbol": "CSPR",
+ "networks": [
+ {
+ "networkId": "casper-network/test"
+ }
+ ]
+ },
+ {
+ "id": "alephium",
+ "name": "Alephium",
+ "symbol": "ALPH",
+ "networks": [
+ {
+ "networkId": "alephium/test"
+ }
+ ]
}
- ],
-
- "total" : 0,
- "imageHost" : "https://s3.eu-central-1.amazonaws.com/tangem.api/coins/"
+ ]
}
diff --git a/app/src/main/assets/tokens.json b/app/src/main/assets/tokens.json
deleted file mode 100644
index 00457a63f6..0000000000
--- a/app/src/main/assets/tokens.json
+++ /dev/null
@@ -1 +0,0 @@
-{"imageHost":"https://s3.eu-central-1.amazonaws.com/tangem.api/coins/","ts":1652764975956,"coins":[{"id" : "arbitrum-one","symbol" : "ETH","name" : "Arbitrum", "active":true,"networks" : [{"networkId" : "arbitrum-one"}]},{"id" : "ethereum-classic","symbol" : "ETC","name" : "Ethereum Classic","networks" : [{"networkId" : "ethereum-classic"}]},{"id":"bitcoin","name":"Bitcoin","symbol":"BTC","active":true,"networks":[{"networkId":"bitcoin"}]},{"id":"ethereum","name":"Ethereum","symbol":"ETH","active":true,"networks":[{"networkId":"ethereum"}]},{"id":"tether","name":"Tether","symbol":"USDT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdac17f958d2ee523a2206206994597c13d831ec7","decimalCount":6},{"networkId":"binance-smart-chain","contractAddress":"0x55d398326f99059ff775485246999027b3197955","decimalCount":18},{"networkId":"solana","contractAddress":"Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB","decimalCount":6},{"networkId":"avalanche","contractAddress":"0xc7198437980c041c805a1edcba50c1ce5db95118","decimalCount":6},{"networkId":"polygon-pos","contractAddress":"0xc2132d05d31c914a87c6611c10748aeb04b58e8f","decimalCount":6},{"networkId":"fantom","contractAddress":"0x049d68029688eabf473097a2fc38ef61633a3c7a","decimalCount":6},{"networkId":"arbitrum-one","contractAddress":"0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9","decimalCount":6}]},{"id":"usd-coin","name":"USD Coin","symbol":"USDC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48","decimalCount":6},{"networkId":"binance-smart-chain","contractAddress":"0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d","decimalCount":18},{"networkId":"solana","contractAddress":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v","decimalCount":6},{"networkId":"avalanche","contractAddress":"0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e","decimalCount":6},{"networkId":"polygon-pos","contractAddress":"0x2791bca1f2de4661ed88a30c99a7a9449aa84174","decimalCount":6},{"networkId":"fantom","contractAddress":"0x04068da6c83afcfa0e13ba15a6696662335d5b75","decimalCount":6},{"networkId":"arbitrum-one","contractAddress":"0xff970a61a04b1ca14834a43f5de4533ebddb5cc8","decimalCount":6}]},{"id":"binancecoin","name":"BNB","symbol":"BNB","active":true,"networks":[{"networkId":"binancecoin"},{"networkId":"binance-smart-chain"}]},{"id":"ripple","name":"XRP","symbol":"XRP","active":true,"networks":[{"networkId":"xrp"}]},{"id":"cardano","name":"Cardano","symbol":"ADA","active":true,"networks":[{"networkId":"cardano"}]},{"id":"solana","name":"Solana","symbol":"SOL","active":true,"networks":[{"networkId":"solana"}]},{"id":"binance-usd","name":"Binance USD","symbol":"BUSD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4fabb145d64652a948d72533023f6e7a623c7c53","decimalCount":18},{"networkId":"binancecoin","contractAddress":"BUSD-BD1","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0xe9e7cea3dedca5984780bafc599bd69add087d56","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x19860ccb0a68fd4213ab9d8266f7bbf05a8dde98","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xdab529f40e671a1d4bf91361c21bf9f0c9712ab7","decimalCount":18}]},{"id":"dogecoin","name":"Dogecoin","symbol":"DOGE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4206931337dc273a630d328da6441786bfad668f","decimalCount":8},{"networkId":"dogecoin"}]},{"id":"avalanche-2","name":"Avalanche","symbol":"AVAX","active":true,"networks":[{"networkId":"avalanche"},{"networkId":"polygon-pos","contractAddress":"0x2c89bbc92bd86f8075d1decc58c7f4e0107f286b","decimalCount":18}]},{"id":"wrapped-bitcoin","name":"Wrapped Bitcoin","symbol":"WBTC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2260fac5e5542a773aa44fbcfedf7c193bc2c599","decimalCount":8},{"networkId":"avalanche","contractAddress":"0x50b7545627a5162f82a992c33b87adc75187b218","decimalCount":8},{"networkId":"polygon-pos","contractAddress":"0x1bfd67037b42cf73acf2047067bd4f2c47d9bfd6","decimalCount":8},{"networkId":"fantom","contractAddress":"0x321162cd933e2be498cd2267a90534a804051b11","decimalCount":8},{"networkId":"arbitrum-one","contractAddress":"0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f","decimalCount":8}]},{"id":"staked-ether","name":"Lido Staked Ether","symbol":"STETH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xae7ab96520de3a18e5e111b5eaab095312d7fe84","decimalCount":18}]},{"id":"tron","name":"TRON","symbol":"TRX","active":true,"networks":[{"networkId":"tron"}]},{"id":"shiba-inu","name":"Shiba Inu","symbol":"SHIB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce","decimalCount":18}]},{"id":"dai","name":"Dai","symbol":"DAI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6b175474e89094c44da98b954eedeac495271d0f","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x1af3f329e8be154074d8769d1ffa4ee058b1dbc3","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xd586e7f844cea2f87f50152665bcbc2c279d8d70","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x8f3cf7ad23cd3cadbd9735aff958023239c6a063","decimalCount":18},{"networkId":"fantom","contractAddress":"0x8d11ec38a3eb5e956b052f67da8bdc9bef8abf3e","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xda10009cbd5d07dd0cecc66161fc93d7c9000da1","decimalCount":18}]},{"id":"crypto-com-chain","name":"Cronos","symbol":"CRO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa0b73e1ff0b80914ab6fe0444e65848c4c34450b","decimalCount":8}]},{"id":"litecoin","name":"Litecoin","symbol":"LTC","active":true,"networks":[{"networkId":"litecoin"}]},{"id":"matic-network","name":"Polygon","symbol":"MATIC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xcc42724c6683b7e57334c4e856f4c9965ed682bd","decimalCount":18},{"networkId":"polygon-pos"}]},{"id":"leo-token","name":"LEO Token","symbol":"LEO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2af5d2ad76741191d15dfe7bf6ac92d4bd912ca3","decimalCount":18}]},{"id":"ftx-token","name":"FTX Token","symbol":"FTT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x50d1c9771902476076ecfc8b2a83ad6b9355a4c9","decimalCount":18},{"networkId":"solana","contractAddress":"AGFEad2et2ZJif9jaGpdMixQqvW5i81aBdvKe7PHNfz3","decimalCount":6}]},{"id":"bitcoin-cash","name":"Bitcoin Cash","symbol":"BCH","active":true,"networks":[{"networkId":"bitcoin-cash"}]},{"id":"chainlink","name":"Chainlink","symbol":"LINK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x514910771af9ca656af840dff83e8264ecf986ca","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf8a0bf9cf54bb92f17374d9e9a321e6a111a51bd","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x5947bb275c521040051d82396192181b413227a3","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x53e0bca35ec356bd5dddfebbd1fc0fd03fabad39","decimalCount":18},{"networkId":"fantom","contractAddress":"0xb3654dc3d10ea7645f8319668e8f54d2574fbdc8","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xf97f4df75117a78c1a5a0dbb814af92458539fb4","decimalCount":18}]},{"id":"stellar","name":"Stellar","symbol":"XLM","active":true,"networks":[{"networkId":"stellar"}]},{"id":"cosmos","name":"Cosmos Hub","symbol":"ATOM","active":false,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x0eb3a705fc54725037cc9e008bdede697f62f335","decimalCount":18}]},{"id":"okb","name":"OKB","symbol":"OKB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x75231f58b43240c9718dd58b4967c5114342a86c","decimalCount":18}]},{"id":"apecoin","name":"ApeCoin","symbol":"APE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4d224452801aced8b2f0aebe155379bb5d594381","decimalCount":18}]},{"id":"uniswap","name":"Uniswap","symbol":"UNI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1f9840a85d5af5bf1d1762f925bdaddc4201f984","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xbf5140a22578168fd562dccf235e5d43a02ce9b1","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x8ebaf22b6f053dffeaf46f4dd9efa95d89ba8580","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xb33eaad8d922b1083446dc23f610c2567fb5180f","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xfa7f8980b0f1e64a2062791cc3b0871572f1f7f0","decimalCount":18}]},{"id":"magic-internet-money","name":"Magic Internet Money","symbol":"MIM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x99d8a9c45b2eca8864373a26d1459e3dff1e17f3","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x130966628846bfd36ff31a822705796e8cb8c18d","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x49a0400587a7f65072c87c4910449fdcc5c47242","decimalCount":18},{"networkId":"fantom","contractAddress":"0x82f0b8b456c1a451378467398982d4834b6829c1","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xfea7a6a0b346362bf88a9e4a88416b77a57d6c2a","decimalCount":18}]},{"id":"decentraland","name":"Decentraland","symbol":"MANA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0f5d2fb29fb7d3cfee444a200298f468908cc942","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xa1c57f48f0deb89f569dfbe6e2b7f46d33606fd4","decimalCount":18}]},{"id":"the-sandbox","name":"The Sandbox","symbol":"SAND","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3845badade8e6dff049820680d1f14bd3903a5d0","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xbbba073c31bf03b8acf7c28ef0738decf3695683","decimalCount":18}]},{"id":"compound-ether","name":"cETH","symbol":"CETH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4ddc2d193948926d02f9b1fe9e1daa0718270ed5","decimalCount":8}]},{"id":"chain-2","name":"Chain","symbol":"XCN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa2cd3d43c775978a96bdbf12d733d5a1ed94fb18","decimalCount":18}]},{"id":"tezos","name":"Tezos","symbol":"XTZ","active":true,"networks":[{"networkId":"tezos"}]},{"id":"axie-infinity","name":"Axie Infinity","symbol":"AXS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbb0e17ef65f82ab018d8edd776e8dd940327b28b","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x715d400f88c167884bbcc41c5fea407ed4d2f8a0","decimalCount":18}]},{"id":"maker","name":"Maker","symbol":"MKR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x88128fd4b259552a9a1d457f435a6527aab72d42","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x2e9a6df78e42a30712c10a9dc4b1c8656f8f2879","decimalCount":18}]},{"id":"frax","name":"Frax","symbol":"FRAX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x853d955acef822db058eb8505911ed77f175b99e","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x90c97f71e18723b0cf0dfa30ee176ab653e89f40","decimalCount":18},{"networkId":"solana","contractAddress":"FR87nWEUxVgerFGhZM8Y4AggKGLnaXswr1Pd8wZ4kZcp","decimalCount":8},{"networkId":"avalanche","contractAddress":"0xd24c2ad096400b6fbcd2ad8b24e7acbc21a1da64","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x45c32fa6df82ead1e2ef74d17b76547eddfaff89","decimalCount":18},{"networkId":"fantom","contractAddress":"0xdc301622e621166bd8e82f2ca0a26c13ad0be355","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x17fc002b466eec40dae837fc4be5c67993ddbd6f","decimalCount":18}]},{"id":"pancakeswap-token","name":"PancakeSwap","symbol":"CAKE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x0e09fabb73bd3ade0a17ecc321fd13a19e81ce82","decimalCount":18}]},{"id":"the-graph","name":"The Graph","symbol":"GRT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc944e90c64b2c07662a292be6244bdf05cda44a7","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x8a0cac13c7da965a312f08ea4229c37869e85cb9","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x5fe2b58c013d7601147dcdd68c143a77499f5531","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x23a941036ae778ac51ab04cea08ed6e2fe103614","decimalCount":18}]},{"id":"aave","name":"Aave","symbol":"AAVE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x63a72806098bd3d9520cc43356dd78afe5d386d9","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xd6df932a45c0f255f85145f286ea0b292b21c90b","decimalCount":18},{"networkId":"fantom","contractAddress":"0x6a07a792ab2965c72a5b8088d3a069a7ac3a993b","decimalCount":18}]},{"id":"true-usd","name":"TrueUSD","symbol":"TUSD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0000000000085d4780b73119b644ae5ecd22b376","decimalCount":18},{"networkId":"binancecoin","contractAddress":"TUSDB-888","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0x14016e85a25aeb13065688cafb43044c2ef86784","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x1c20e891bab6b1727d14da358fae2984ed9b59eb","decimalCount":18},{"networkId":"tron","contractAddress":"TUpMhErZL2fhh4sVNULAbNKLokS4GjC1F4","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x2e1ad108ff1d8c782fcbbb89aad783ac49586756","decimalCount":18},{"networkId":"fantom","contractAddress":"0x9879abdea01a879644185341f7af7d8343556b7a","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x4d15a3a2286d883af0aa1b3f21367843fac63e07","decimalCount":18}]},{"id":"huobi-btc","name":"Huobi BTC","symbol":"HBTC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0316eb71485b0ab14103307bf65a021042c6d380","decimalCount":18}]},{"id":"terra-luna","name":"Terra","symbol":"LUNA","active":true,"networks":[{"networkId":"fantom","contractAddress":"0x95dd59343a893637be1c3228060ee6afbf6f0730","decimalCount":6}]},{"id":"compound-usd-coin","name":"cUSDC","symbol":"CUSDC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x39aa39c021dfbae8fac545936693ac917d5e7563","decimalCount":8}]},{"id":"huobi-token","name":"Huobi Token","symbol":"HT","active":false,"networks":[{"networkId":"ethereum","contractAddress":"0x6f259637dcd74c767781e37bc6133cd6a68aa161","decimalCount":18}]},{"id":"bittorrent","name":"BitTorrent","symbol":"BTT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc669928185dbce49d2230cc9b0979be6dc797957","decimalCount":18},{"networkId":"tron","contractAddress":"TAFjULxiVgT4qWk6UZwjqwZXTSaGaqnVp4","decimalCount":18}]},{"id":"thorchain","name":"THORChain","symbol":"RUNE","active":false,"networks":[{"networkId":"binancecoin","contractAddress":"RUNE-B1A","decimalCount":8}]},{"id":"quant-network","name":"Quant","symbol":"QNT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4a220e6096b25eadb88358cb44068a3248254675","decimalCount":18}]},{"id":"paxos-standard","name":"Pax Dollar","symbol":"USDP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8e870d67f660d95d5be530380d0ec0bd388289e1","decimalCount":18}]},{"id":"fantom","name":"Fantom","symbol":"FTM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4e15361fd6b4bb609fa63c81a2be19d873717870","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xad29abb318791d579433d831ed122afeaf29dcfe","decimalCount":18},{"networkId":"fantom"}]},{"id":"stepn","name":"STEPN","symbol":"GMT","active":true,"networks":[{"networkId":"solana","contractAddress":"7i5KKsX2weiTkry7jA4ZwSuXGhs5eJBEjY8vVxR4pfRx","decimalCount":9}]},{"id":"neutrino","name":"Neutrino USD","symbol":"USDN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x674c6ad92fd080e4004b2312b45f796a192d27a0","decimalCount":18}]},{"id":"cdai","name":"cDAI","symbol":"CDAI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5d3a536e4d6dbd6114cc1ead35777bab948e3643","decimalCount":8}]},{"id":"gatechain-token","name":"GateToken","symbol":"GT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe66747a101bff2dba3697199dcce5b743b454759","decimalCount":18}]},{"id":"bitdao","name":"BitDAO","symbol":"BIT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1a4b46696b2bb4794eb3d4c26f1c55f9170fa4c5","decimalCount":18}]},{"id":"nexo","name":"NEXO","symbol":"NEXO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb62132e35a6c13ee1ee0f84dc5d40bad8d815206","decimalCount":18},{"networkId":"fantom","contractAddress":"0x7c598c96d02398d89fbcb9d41eab3df0c16f227d","decimalCount":18}]},{"id":"zilliqa","name":"Zilliqa","symbol":"ZIL","active":false,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xb86abcb37c3a4b64f74f59301aff131a1becc787","decimalCount":12}]},{"id":"convex-finance","name":"Convex Finance","symbol":"CVX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4e3fbd56cd56c3e72c1403e103b45db9da5b9d2b","decimalCount":18}]},{"id":"enjincoin","name":"Enjin Coin","symbol":"ENJ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf629cbd94d3791c9250152bd8dfbdf380e2a3b9c","decimalCount":18}]},{"id":"gala","name":"Gala","symbol":"GALA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x15d4c048f83bd7e37d49ea4c83a07267ec4203da","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0x7ddee176f665cd201f93eede625770e2fd911990","decimalCount":18}]},{"id":"amp-token","name":"Amp","symbol":"AMP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xff20817765cb7f73d4bde2e66e067e58d11095c2","decimalCount":18}]},{"id":"waves","name":"Waves","symbol":"WAVES","active":false,"networks":[{"networkId":"ethereum","contractAddress":"0x1cf4592ebffd730c7dc92c1bdffdfc3b9efcf29a","decimalCount":18}]},{"id":"havven","name":"Synthetix Network Token","symbol":"SNX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xbec243c995409e6520d7c41e404da5deba4b209b","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x50b728d8d964fd00c2d0aad81718b71311fef68a","decimalCount":18},{"networkId":"fantom","contractAddress":"0x56ee926bd8c72b2d5fa1af4d9e4cbb515a1e3adc","decimalCount":18}]},{"id":"chiliz","name":"Chiliz","symbol":"CHZ","active":false,"networks":[{"networkId":"ethereum","contractAddress":"0x3506424f91fd33084466f402d5d97f05f8e3b4af","decimalCount":18}]},{"id":"basic-attention-token","name":"Basic Attention Token","symbol":"BAT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0d8775f648430679a709e98d2b0cb6250d2887ef","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x98443b96ea4b0858fdf3219cd13e98c7a4690588","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x3cef98bb43d732e2f285ee605a8158cde967d219","decimalCount":18}]},{"id":"loopring","name":"Loopring","symbol":"LRC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbbbbca6a901c926f240b89eacb641d8aec7aeafd","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x46d0ce7de6247b0a95f67b43b589b4041bae7fbe","decimalCount":18}]},{"id":"pax-gold","name":"PAX Gold","symbol":"PAXG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x45804880de22913dafe09f4980848ece6ecbaf78","decimalCount":18}]},{"id":"gnosis","name":"Gnosis","symbol":"GNO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6810e776880c02933d47db1b9fc05908e5386b96","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xa0b862f60edef4452f25b4160f177db44deb6cf1","decimalCount":18}]},{"id":"compound-usdt","name":"cUSDT","symbol":"CUSDT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf650c3d88d12db855b8bf7d11be6c55a4e07dcc9","decimalCount":8}]},{"id":"curve-dao-token","name":"Curve DAO Token","symbol":"CRV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd533a949740bb3306d119cc777fa900ba034cd52","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x172370d5cd63279efa6d502dab29171933a610af","decimalCount":18},{"networkId":"fantom","contractAddress":"0x1e4f97b9f9f913c46f1632781732927b9019c68b","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x11cdb42b0eb46d95f990bedd4695a6e3fa034978","decimalCount":18}]},{"id":"fei-usd","name":"Fei USD","symbol":"FEI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x956f47f50a910163d8bf957cf5846d573e7f87ca","decimalCount":18}]},{"id":"lido-dao","name":"Lido DAO","symbol":"LDO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5a98fcbea516cf06857215779fd812ca3bef1b32","decimalCount":18}]},{"id":"frax-share","name":"Frax Share","symbol":"FXS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3432b6a60d23ca0dfca7761b7ab56459d9c964d0","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xe48a3d7d0bc88d552f730b62c006bc925eadb9ee","decimalCount":18},{"networkId":"solana","contractAddress":"6LX8BhMQ4Sy2otmAWj7Y5sKd9YTVVUgfMsBzT6B9W7ct","decimalCount":8},{"networkId":"avalanche","contractAddress":"0x214db107654ff987ad859f34125307783fc8e387","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x1a3acf6d19267e2d3e7f898f42803e90c9219062","decimalCount":18},{"networkId":"fantom","contractAddress":"0x7d016eec9c25232b01f23ef992d98ca97fc2af5a","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x9d2f299715d94d8a7e6f5eaa8e654e8c74a988a7","decimalCount":18}]},{"id":"compound-governance-token","name":"Compound","symbol":"COMP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc00e94cb662c3520282e6f5717214004a7f26888","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x52ce071bd9b1c4b00a0b92d298c512478cad67e8","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xc3048e19e76cb9a3aa9d77d8c03c29fc906e2437","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x8505b9d2254a7ae468c0e9dd10ccea3a837aef5c","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x354a6da3fcde098f8389cad84b0182725c6c91de","decimalCount":18}]},{"id":"nxm","name":"Nexus Mutual","symbol":"NXM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd7c49cee7e9188cca6ad8ff264c1da2e69d4cf3b","decimalCount":18}]},{"id":"holotoken","name":"Holo","symbol":"HOT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6c6ee5e31d828de241282b9606c8e98ea48526e2","decimalCount":18}]},{"id":"tether-gold","name":"Tether Gold","symbol":"XAUT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x68749665ff8d2d112fa859aa293f07a622782f38","decimalCount":6}]},{"id":"tokenize-xchange","name":"Tokenize Xchange","symbol":"TKX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x667102bd3413bfeaa3dffb48fa8288819e480a88","decimalCount":8}]},{"id":"ecomi","name":"ECOMI","symbol":"OMI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xed35af169af46a02ee13b9d79eb57d6d68c1749e","decimalCount":18}]},{"id":"bancor","name":"Bancor Network Token","symbol":"BNT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1f573d6fb3f13d689ff844b4ce37794d79a7ff1c","decimalCount":18}]},{"id":"1inch","name":"1inch","symbol":"1INCH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x111111111117dc0aa78b770fa6a738034120c302","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x111111111117dc0aa78b770fa6a738034120c302","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xd501281565bf7789224523144fe5d98e8b28f267","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x9c2c5fd7b07e95ee044ddeba0e97a665f142394f","decimalCount":18}]},{"id":"serum","name":"Serum","symbol":"SRM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x476c5e26a75bd202a9683ffd34359c0cc15be0ff","decimalCount":6},{"networkId":"solana","contractAddress":"SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt","decimalCount":6}]},{"id":"livepeer","name":"Livepeer","symbol":"LPT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x58b6a8a3302369daec383334672404ee733ab239","decimalCount":18}]},{"id":"flex-coin","name":"FLEX Coin","symbol":"FLEX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfcf8eda095e37a41e002e266daad7efc1579bc0a","decimalCount":18}]},{"id":"yearn-finance","name":"yearn.finance","symbol":"YFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0bc529c00c6401aef6d220be8c6ea1667f6ad93e","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x9eaac1b23d935365bd7b542fe22ceee2922f52dc","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xda537104d6a5edd53c6fbba9a898708e465260b6","decimalCount":18},{"networkId":"fantom","contractAddress":"0x29b0da86e484e1c0029b56e817912d778ac0ec69","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x82e3a8f066a6989666b031d916c43672085b1582","decimalCount":18}]},{"id":"msol","name":"Marinade staked SOL","symbol":"MSOL","active":true,"networks":[{"networkId":"solana","contractAddress":"mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So","decimalCount":9}]},{"id":"omisego","name":"OMG Network","symbol":"OMG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd26114cd6ee289accf82350c8d8487fedb8a0c07","decimalCount":18}]},{"id":"celsius-degree-token","name":"Celsius Network","symbol":"CEL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaaaebe6fe48e54f431b0c390cfaf0b017d09d42d","decimalCount":4},{"networkId":"polygon-pos","contractAddress":"0xd85d1e945766fea5eda9103f918bd915fbca63e6","decimalCount":4},{"networkId":"fantom","contractAddress":"0x2c78f1b70ccf63cdee49f9233e9faa99d43aa07e","decimalCount":4}]},{"id":"0x","name":"0x","symbol":"ZRX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe41d2489571d322189246dafa5ebde1f4699f498","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x596fa47043f99a4e0f122243b841e55375cde0d2","decimalCount":18}]},{"id":"gemini-dollar","name":"Gemini Dollar","symbol":"GUSD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x056fd409e1d7a124bd7017459dfea2f387b6d5cd","decimalCount":2}]},{"id":"liquity-usd","name":"Liquity USD","symbol":"LUSD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5f98805a4e8be255a32880fdec7f6728c6568ba0","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x23001f892c0c82b79303edc9b9033cd190bb21c7","decimalCount":18}]},{"id":"rocket-pool","name":"Rocket Pool","symbol":"RPL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd33526068d116ce69f19a9ee46f0bd304f21a51f","decimalCount":18}]},{"id":"audius","name":"Audius","symbol":"AUDIO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x18aaa7115705e8be94bffebde57af9bfc265b998","decimalCount":18}]},{"id":"xido-finance","name":"Xido Finance","symbol":"XIDO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf6650117017ffd48b725b4ec5a00b414097108a7","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x3764bc0de9b6a68c67929130aaec16b6060cab8c","decimalCount":18}]},{"id":"ankr","name":"Ankr","symbol":"ANKR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8290333cef9e6d528dd5618fb97a76f268f3edd4","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf307910a4c7bbc79691fd374889b36d8531b08e3","decimalCount":18}]},{"id":"olympus","name":"Olympus","symbol":"OHM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x64aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5","decimalCount":9}]},{"id":"convex-crv","name":"Convex CRV","symbol":"CVXCRV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x62b9c7356a2dc64a1969e19c23e4f579f9810aa7","decimalCount":18}]},{"id":"skale","name":"SKALE","symbol":"SKL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x00c83aecc790e8a4453e5dd3b0b4b3680501a7a7","decimalCount":18}]},{"id":"everdome","name":"Everdome","symbol":"DOME","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x475bfaa1848591ae0e6ab69600f48d828f61a80e","decimalCount":18}]},{"id":"just","name":"JUST","symbol":"JST","active":true,"networks":[{"networkId":"tron","contractAddress":"TCFLL5dx5ZJdKnWuesXxi1VPwjLVmWZZy9","decimalCount":18}]},{"id":"husd","name":"HUSD","symbol":"HUSD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdf574c24545e5ffecb9a659c229253d4111d87e1","decimalCount":8}]},{"id":"swissborg","name":"SwissBorg","symbol":"CHSB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xba9d4199fab4f26efe3551d490e3821486f135ba","decimalCount":8}]},{"id":"iotex","name":"IoTeX","symbol":"IOTX","active":false,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x9678e42cebeb63f23197d726b29b1cb20d0064e5","decimalCount":18}]},{"id":"everscale","name":"Everscale","symbol":"EVER","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x29d578cec46b50fa5c88a99c6a4b70184c062953","decimalCount":9}]},{"id":"dogelon-mars","name":"Dogelon Mars","symbol":"ELON","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x761d38e5ddf6ccf6cf7c55759d5210750b5d60f3","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xe0339c80ffde91f3e20494df88d4206d86024cdf","decimalCount":18}]},{"id":"ethereum-name-service","name":"Ethereum Name Service","symbol":"ENS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc18360217d8f7ab5e7c516566761ea12ce7f9d72","decimalCount":18}]},{"id":"titanswap","name":"TitanSwap","symbol":"TITAN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3a8cccb969a61532d1e6005e2ce12c200caece87","decimalCount":18}]},{"id":"safemoon","name":"SafeMoon [OLD]","symbol":"SAFEMOON","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x8076c74c5e3f5852037f31ff0093eeb8c8add8d3","decimalCount":9}]},{"id":"render-token","name":"Render Token","symbol":"RNDR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6de037ef9ad2725eb40118bb1702ebb27e4aeb24","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x61299774020da444af134c82fa83e3810b309991","decimalCount":18}]},{"id":"mimatic","name":"MAI","symbol":"MIMATIC","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x3b55e45fd6bd7d4724f5c47e0d1bcaedd059263e","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xa3fa99a148fa48d14ed51d610c367c61876997f1","decimalCount":18},{"networkId":"fantom","contractAddress":"0xfb98b335551a418cd0737375a2ea0ded62ea213b","decimalCount":18}]},{"id":"synapse-2","name":"Synapse","symbol":"SYN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0f2d719407fdbeff09d87557abb7232601fd9f29","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xa4080f1778e69467e905b8d6f72f6e441f9e9484","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x1f1e7c893855525b303f99bdf5c3c05be09ca251","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xf8f9efc0db77d8881500bb06ff5d6abc3070e695","decimalCount":18},{"networkId":"fantom","contractAddress":"0xe55e19fb4f2d85af758950957714292dac1e25b2","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x080f6aed32fc474dd5717105dba5ea57268f46eb","decimalCount":18}]},{"id":"golem","name":"Golem","symbol":"GLM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7dd9c5cba05e151c895fde1cf355c9a1d5da6429","decimalCount":18}]},{"id":"sushi","name":"Sushi","symbol":"SUSHI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6b3595068778dd592e39a122f4f5a5cf09c90fe2","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x947950bcc74888a40ffa2593c5798f11fc9124c4","decimalCount":18},{"networkId":"solana","contractAddress":"ChVzxWRmrTeSgwd3Ui3UumcN8KX7VK3WaD4KGeSKpypj","decimalCount":8},{"networkId":"avalanche","contractAddress":"0x37b608519f91f70f2eeb0e5ed9af4061722e4f76","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x0b3f868e0be5597d5db7feb59e1cadbb0fdda50a","decimalCount":18},{"networkId":"fantom","contractAddress":"0xae75a438b2e0cb8bb01ec1e1e376de11d44477cc","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xd4d42f0b6def4ce0383636770ef773390d85c61a","decimalCount":18}]},{"id":"safemoon-2","name":"SafeMoon","symbol":"SFM","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x42981d0bfbaf196529376ee702f2a9eb9092fcb5","decimalCount":9}]},{"id":"ethos","name":"Voyager Token","symbol":"VGX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3c4b6e6e1ea3d4863700d7f76b36b7f3d3f13e3d","decimalCount":8}]},{"id":"trust-wallet-token","name":"Trust Wallet Token","symbol":"TWT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4b0f1812e5df2a09796481ff14017e6005508003","decimalCount":18}]},{"id":"swipe","name":"SXP","symbol":"SXP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8ce9137d39326ad0cd6491fb5cc0cba0e089b6a9","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x47bead2563dcbf3bf2c9407fea4dc236faba485a","decimalCount":18}]},{"id":"escoin-token","name":"Escoin Token","symbol":"ELG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa2085073878152ac3090ea13d1e41bd69e60dc99","decimalCount":18}]},{"id":"immutable-x","name":"Immutable X","symbol":"IMX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf57e7e7c23978c3caec3c3548e3d615c346e79ff","decimalCount":18}]},{"id":"woo-network","name":"WOO Network","symbol":"WOO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4691937a7508860f876c9c0a2a617e7d9e945d4b","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x4691937a7508860f876c9c0a2a617e7d9e945d4b","decimalCount":18},{"networkId":"solana","contractAddress":"E5rk3nmgLUuKUiS94gg4bpWwWwyjCMtddsAXkTFLtHEy","decimalCount":6},{"networkId":"avalanche","contractAddress":"0xabc9547b534519ff73921b1fba6e672b5f58d083","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x1b815d120b3ef02039ee11dc2d33de7aa4a8c603","decimalCount":18},{"networkId":"fantom","contractAddress":"0x6626c47c00f1d87902fc13eecfac3ed06d5e8d8a","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xcafcd85d8ca7ad1e1c6f82f651fa15e33aefd07b","decimalCount":18}]},{"id":"tether-eurt","name":"Euro Tether","symbol":"EURT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc581b735a1688071a1746c968e0798d642ede491","decimalCount":6}]},{"id":"tenset","name":"Tenset","symbol":"10SET","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7ff4169a6b5122b664c51c95727d87750ec07c84","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x1f64fdad335ed784898effb5ce22d54d8f432523","decimalCount":18}]},{"id":"uma","name":"UMA","symbol":"UMA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x04fa0d235c4abf4bcf4787af4cf447de572ef828","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x3bd2b1c7ed8d396dbb98ded3aebb41350a5b2339","decimalCount":18}]},{"id":"playdapp","name":"PlayDapp","symbol":"PLA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3a4f40631a4f906c2bad353ed06de7a5d3fcb430","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x8765f05adce126d70bcdf1b0a48db573316662eb","decimalCount":18}]},{"id":"nucypher","name":"NuCypher","symbol":"NU","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4fe83213d56308330ec302a8bd641f1d0113a4cc","decimalCount":18}]},{"id":"apenft","name":"APENFT","symbol":"NFT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x198d14f2ad9ce69e76ea330b374de4957c3f850a","decimalCount":6},{"networkId":"binance-smart-chain","contractAddress":"0x20ee7b720f4e4c4ffcb00c4065cdae55271aecca","decimalCount":6},{"networkId":"tron","contractAddress":"TFczxzPhnThNSqr5by8tvxsdCFRRz6cPNq","decimalCount":6}]},{"id":"renbtc","name":"renBTC","symbol":"RENBTC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xeb4c2781e4eba804ce9a9803c67d0893436bb27d","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0xfce146bf3146100cfe5db4129cf6c82b0ef4ad8c","decimalCount":8},{"networkId":"polygon-pos","contractAddress":"0xdbf31df14b66535af65aac99c32e9ea844e14501","decimalCount":8}]},{"id":"illuvium","name":"Illuvium","symbol":"ILV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x767fe9edc9e0df98e07454847909b5e959d7ca0e","decimalCount":18}]},{"id":"polymath","name":"Polymath","symbol":"POLY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9992ec3cf6a55b00978cddf2b27bc6882d88d1ec","decimalCount":18}]},{"id":"rally-2","name":"Rally","symbol":"RLY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf1f955016ecbcd7321c7266bccfb96c68ea5e49b","decimalCount":18}]},{"id":"dydx","name":"dYdX","symbol":"DYDX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x92d6c1e31e14520e676a687f0a93788b716beff5","decimalCount":18}]},{"id":"mxc","name":"MXC","symbol":"MXC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5ca381bbfb58f0092df149bd3d243b08b9a8386e","decimalCount":18}]},{"id":"velas","name":"Velas","symbol":"VLX","active":false,"networks":[{"networkId":"ethereum","contractAddress":"0x8c543aed163909142695f2d2acd0d55791a9edb9","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xe9c803f48dffe50180bd5b01dc04da939e3445fc","decimalCount":18}]},{"id":"dao-maker","name":"DAO Maker","symbol":"DAO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0f51bb10119727a7e5ea3538074fb341f56b09ad","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x22f3997a5df5a80e29871fed24fe3e85741f5e82","decimalCount":18}]},{"id":"radio-caca","name":"Radio Caca","symbol":"RACA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x12bb890508c125661e03b09ec06e404bc9289040","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x12bb890508c125661e03b09ec06e404bc9289040","decimalCount":18}]},{"id":"alchemix-usd","name":"Alchemix USD","symbol":"ALUSD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbc6da0fe9ad5f3b0d58160288917aa56653660e9","decimalCount":18}]},{"id":"kyber-network-crystal","name":"Kyber Network Crystal","symbol":"KNC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdefa4e8a7bcba345f687a2f1456f5edd9ce97202","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xfe56d5892bdffc7bf58f2e84be1b2c32d21c308b","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x39fc9e94caeacb435842fadedecb783589f50f5f","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x1c954e8fe737f99f68fa1ccda3e51ebdb291948c","decimalCount":18},{"networkId":"fantom","contractAddress":"0x1e1085efaa63edfe74aad7c05a28eae4ef917c3f","decimalCount":18}]},{"id":"cratos","name":"Cratos","symbol":"CRTS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x678e840c640f619e17848045d23072844224dd37","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x678e840c640f619e17848045d23072844224dd37","decimalCount":18}]},{"id":"e-radix","name":"e-Radix","symbol":"EXRD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6468e79a80c0eab0f9a2b574c8d5bc374af59414","decimalCount":18}]},{"id":"telcoin","name":"Telcoin","symbol":"TEL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x467bccd9d29f223bce8043b84e8c8b282827790f","decimalCount":2},{"networkId":"polygon-pos","contractAddress":"0xdf7837de1f2fa4631d716cf2502f8b230f1dcc32","decimalCount":2}]},{"id":"zipmex-token","name":"Zipmex Token","symbol":"ZMT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaa602de53347579f86b996d2add74bb6f79462b2","decimalCount":18}]},{"id":"looksrare","name":"LooksRare","symbol":"LOOKS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf4d2888d29d722226fafa5d9b24f9164c092421e","decimalCount":18}]},{"id":"coinex-token","name":"CoinEx Token","symbol":"CET","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x081f67afa0ccf8c7b17540767bbe95df2ba8d97f","decimalCount":18}]},{"id":"gmx","name":"GMX","symbol":"GMX","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x62edc0692bd897d2295872a9ffcac5425011c661","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xfc5a1a6eb076a2c7ad06ed22c90d7e710e35ad0a","decimalCount":18}]},{"id":"mx-token","name":"MX Token","symbol":"MX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x11eef04c884e24d9b7b4760e7476d06ddf797f36","decimalCount":18}]},{"id":"lido-staked-sol","name":"Lido Staked SOL","symbol":"STSOL","active":true,"networks":[{"networkId":"solana","contractAddress":"7dHbWXmci3dT8UFYWYZweBLXgycu7Y3iL6trKn1Y7ARj","decimalCount":9}]},{"id":"republic-protocol","name":"REN","symbol":"REN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x408e41876cccdc0f92210600ef50372656052a38","decimalCount":18}]},{"id":"xsgd","name":"XSGD","symbol":"XSGD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x70e8de73ce538da2beed35d14187f6959a8eca96","decimalCount":6}]},{"id":"ceek","name":"CEEK Smart VR Token","symbol":"CEEK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb056c38f6b7dc4064367403e26424cd2c60655e1","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xe0f94ac5462997d2bc57287ac3a3ae4c31345d66","decimalCount":18}]},{"id":"baby-doge-coin","name":"Baby Doge Coin","symbol":"BABYDOGE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xac57de9c1a09fec648e93eb98875b212db0d460b","decimalCount":9},{"networkId":"binance-smart-chain","contractAddress":"0xc748673057861a797275cd8a068abb95a902e8de","decimalCount":9}]},{"id":"multichain","name":"Multichain","symbol":"MULTI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x65ef703f5594d2573eb71aaf55bc0cb548492df4","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x9fb9a33956351cf4fa040f65a13b835a3c8764e3","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x9fb9a33956351cf4fa040f65a13b835a3c8764e3","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x9fb9a33956351cf4fa040f65a13b835a3c8764e3","decimalCount":18},{"networkId":"fantom","contractAddress":"0x9fb9a33956351cf4fa040f65a13b835a3c8764e3","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x9fb9a33956351cf4fa040f65a13b835a3c8764e3","decimalCount":18}]},{"id":"biswap","name":"Biswap","symbol":"BSW","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x965f527d9159dce6288a2219db51fc6eef120dd1","decimalCount":18}]},{"id":"mobox","name":"Mobox","symbol":"MBOX","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x3203c9e46ca618c8c1ce5dc67e7e9d75f5da2377","decimalCount":18}]},{"id":"flex-usd","name":"flexUSD","symbol":"FLEXUSD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa774ffb4af6b0a91331c084e1aebae6ad535e6f3","decimalCount":18}]},{"id":"status","name":"Status","symbol":"SNT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x744d70fdbe2ba4cf95131626614a1763df805b9e","decimalCount":18}]},{"id":"maple","name":"Maple","symbol":"MPL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x33349b282065b0284d756f0577fb39c158f935e6","decimalCount":18}]},{"id":"raydium","name":"Raydium","symbol":"RAY","active":true,"networks":[{"networkId":"solana","contractAddress":"4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R","decimalCount":6}]},{"id":"orbs","name":"Orbs","symbol":"ORBS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xff56cc6b1e6ded347aa0b7676c85ab0b3d08b0fa","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xebd49b26169e1b52c04cfd19fcf289405df55f80","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x614389eaae0a6821dc49062d56bda3d9d45fa2ff","decimalCount":18}]},{"id":"wink","name":"WINkLink","symbol":"WIN","active":true,"networks":[{"networkId":"tron","contractAddress":"TLa2f6VPqDgRE67v1736s7bJ8Ray5wYjU7","decimalCount":6}]},{"id":"aurora-near","name":"Aurora","symbol":"AURORA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaaaaaa20d9e0e2461697782ef11675f668207961","decimalCount":18}]},{"id":"pundi-x-2","name":"Pundi X","symbol":"PUNDIX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0fd10b9899882a6f2fcb5c371e17e70fdee00c38","decimalCount":18}]},{"id":"chromaway","name":"Chromia","symbol":"CHR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8a2279d4a90b6fe1c4b30fa660cc9f926797baa2","decimalCount":6},{"networkId":"binance-smart-chain","contractAddress":"0xf9cec8d50f6c8ad3fb6dccec577e05aa32b224fe","decimalCount":6}]},{"id":"xyo-network","name":"XYO Network","symbol":"XYO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x55296f69f40ea6d20e478533c15a6b08b654e758","decimalCount":18}]},{"id":"keep-network","name":"Keep Network","symbol":"KEEP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x85eee30c52b0b379b046fb0f85f4f3dc3009afec","decimalCount":18}]},{"id":"fetch-ai","name":"Fetch.ai","symbol":"FET","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaea46a60368a7bd060eec7df8cba43b7ef41ad85","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x031b41e504677879370e9dbcf937283a8691fa7f","decimalCount":18}]},{"id":"btse-token","name":"BTSE Token","symbol":"BTSE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x666d875c600aa06ac1cf15641361dec3b00432ef","decimalCount":8}]},{"id":"stasis-eurs","name":"STASIS EURO","symbol":"EURS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdb25f211ab05b1c97d595516f45794528a807ad8","decimalCount":2},{"networkId":"polygon-pos","contractAddress":"0xe111178a87a3bff0c8d18decba5798827539ae99","decimalCount":2}]},{"id":"vulcan-forged","name":"Vulcan Forged","symbol":"PYR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x430ef9263e76dae63c84292c3409d61c598e9682","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x430ef9263e76dae63c84292c3409d61c598e9682","decimalCount":18}]},{"id":"benqi-liquid-staked-avax","name":"BENQI Liquid Staked AVAX","symbol":"SAVAX","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x2b2c81e08f1af8835a78bb2a90ae924ace0ea4be","decimalCount":18}]},{"id":"spell-token","name":"Spell","symbol":"SPELL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x090185f2135308bad17527004364ebcc2d37e5f6","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xce1bffbd5374dac86a2893119683f4911a2f7814","decimalCount":18},{"networkId":"fantom","contractAddress":"0x468003b688943977e6130f4f68f23aad939a1040","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x3e6648c5a70a150a88bce65f4ad4d506fe15d2af","decimalCount":18}]},{"id":"iron-bank-euro","name":"Iron Bank EURO","symbol":"IBEUR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x96e61422b6a9ba0e068b6c5add4ffabc6a4aae27","decimalCount":18}]},{"id":"seth2","name":"sETH2","symbol":"SETH2","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfe2e637202056d30016725477c5da089ab0a043a","decimalCount":18}]},{"id":"wazirx","name":"WazirX","symbol":"WRX","active":true,"networks":[{"networkId":"binancecoin","contractAddress":"WRX-ED1","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0x8e17ed70334c87ece574c9d537bc153d8609e2a3","decimalCount":8},{"networkId":"polygon-pos","contractAddress":"0x72d6066f486bd0052eefb9114b66ae40e0a6031a","decimalCount":8}]},{"id":"tribe-2","name":"Tribe","symbol":"TRIBE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc7283b66eb1eb5fb86327f08e1b5816b0720212b","decimalCount":18}]},{"id":"coti","name":"COTI","symbol":"COTI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xddb3422497e61e13543bea06989c0789117555c5","decimalCount":18}]},{"id":"liquity","name":"Liquity","symbol":"LQTY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6dea81c8171d0ba574754ef6f8b412f2ed88c54d","decimalCount":18}]},{"id":"insure","name":"inSure DeFi","symbol":"SURE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcb86c6a22cb56b6cf40cafedb06ba0df188a416e","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x9b17baadf0f21f03e35249e0e59723f34994f806","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x5fc17416925789e0852fbfcd81c490ca4abc51f9","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xf88332547c680f755481bf489d890426248bb275","decimalCount":18}]},{"id":"fx-coin","name":"Function X","symbol":"FX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8c15ef5b4b21951d50e53e4fbda8298ffad25057","decimalCount":18}]},{"id":"injective-protocol","name":"Injective","symbol":"INJ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe28b3b32b6c345a34ff64674606124dd5aceca30","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xa2b726b1145a4773f68593cf171187d8ebe4d495","decimalCount":18}]},{"id":"kirobo","name":"Kirobo","symbol":"KIRO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb1191f691a355b43542bea9b8847bc73e7abb137","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf83c0f6d3a5665bd7cfdd5831a856d85942bc060","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xb382c1cfa622795a534e5bd56fac93d59bac8b0d","decimalCount":18}]},{"id":"civic","name":"Civic","symbol":"CVC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x41e5560054824ea6b0732e656e3ad64e20e94e45","decimalCount":8}]},{"id":"asd","name":"AscendEx Token","symbol":"ASD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xff742d05420b6aca4481f635ad8341f81a6300c2","decimalCount":18}]},{"id":"joe","name":"JOE","symbol":"JOE","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x6e84a6216ea6dacc71ee8e6b0a5b7322eebc0fdd","decimalCount":18}]},{"id":"merit-circle","name":"Merit Circle","symbol":"MC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x949d48eca67b17269629c7194f4b727d4ef9e5d6","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x949d48eca67b17269629c7194f4b727d4ef9e5d6","decimalCount":18}]},{"id":"cartesi","name":"Cartesi","symbol":"CTSI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x491604c0fdf08347dd1fa4ee062a822a5dd06b5d","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x8da443f84fea710266c8eb6bc34b71702d033ef2","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x6b289cceaa8639e3831095d75a3e43520fabf552","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x2727ab1c2d22170abc9b595177b2d5c6e1ab7b7b","decimalCount":18}]},{"id":"origin-protocol","name":"Origin Protocol","symbol":"OGN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8207c1ffc5b6804f6024322ccf34f29c3541ae26","decimalCount":18}]},{"id":"origintrail","name":"OriginTrail","symbol":"TRAC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaa7a9ca87d3694b5755f213b5d04094b8d0f0a6f","decimalCount":18}]},{"id":"power-ledger","name":"Power Ledger","symbol":"POWR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x595832f8fc6bf59c85c527fec3740a1b7a361269","decimalCount":6}]},{"id":"klever","name":"Klever","symbol":"KLV","active":true,"networks":[{"networkId":"tron","contractAddress":"TVj7RNVHy6thbM7BWdSe9G6gXwKhjhdNZS","decimalCount":6}]},{"id":"api3","name":"API3","symbol":"API3","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0b38210ea11411557c13457d4da7dc6ea731b88a","decimalCount":18}]},{"id":"hxro","name":"Hxro","symbol":"HXRO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4bd70556ae3f8a6ec6c4080a0c327b24325438f3","decimalCount":18}]},{"id":"dent","name":"Dent","symbol":"DENT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3597bfd533a99c9aa083587b074434e61eb0a258","decimalCount":8}]},{"id":"ankreth","name":"Ankr Reward-Bearing Staked ETH","symbol":"AETHC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe95a203b1a91a908f9b9ce46459d101078c2c3cb","decimalCount":18}]},{"id":"metis-token","name":"Metis Token","symbol":"METIS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9e32b13ce7f2e80a01932b42553652e053d6ed8e","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xe552fb52a4f19e44ef5a967632dbc320b0820639","decimalCount":18}]},{"id":"celer-network","name":"Celer Network","symbol":"CELR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4f9254c83eb525f9fcf346490bbb3ed28a81c667","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x3a8b787f78d775aecfeea15706d4221b40f345ab","decimalCount":18}]},{"id":"ultra","name":"Ultra","symbol":"UOS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd13c7342e1ef687c5ad21b27c2b65d772cab5c8c","decimalCount":4}]},{"id":"ellipsis","name":"Ellipsis [OLD]","symbol":"EPS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xa7f552078dcc247c2684336020c03648500c6d9f","decimalCount":18}]},{"id":"ocean-protocol","name":"Ocean Protocol","symbol":"OCEAN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x967da4048cd07ab37855c090aaf366e4ce1b9f48","decimalCount":18}]},{"id":"digitalbits","name":"DigitalBits","symbol":"XDB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb9eefc4b0d472a44be93970254df4f4016569d27","decimalCount":7}]},{"id":"creditcoin-2","name":"Creditcoin","symbol":"CTC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa3ee21c306a700e682abcdfe9baa6a08f3820419","decimalCount":18}]},{"id":"balancer","name":"Balancer","symbol":"BAL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xba100000625a3754423978a60c9317c58a424e3d","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x9a71012b13ca4d3d0cdc72a177df3ef03b0e76a3","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x040d1edc9569d4bab2d15287dc5a4f10f56a56b8","decimalCount":18}]},{"id":"funfair","name":"FUNToken","symbol":"FUN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x419d0d8bdd9af5e606ae2232ed285aff190e711b","decimalCount":8}]},{"id":"tokamak-network","name":"Tokamak Network","symbol":"TON","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2be5e8c109e2197d077d13a82daead6a9b3433c5","decimalCount":18}]},{"id":"gpex","name":"GPEX","symbol":"GPX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3e7804c51a70ba26e904c2e0ab440c5623a8a83f","decimalCount":8}]},{"id":"coin98","name":"Coin98","symbol":"C98","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xae12c5930881c53715b369cec7606b70d8eb229f","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xaec945e04baf28b135fa7c640f624f8d90f1c3a6","decimalCount":18}]},{"id":"gensokishis-metaverse","name":"GensoKishi Metaverse","symbol":"MV","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0xa3c322ad15218fbfaed26ba7f616249f7705d945","decimalCount":18}]},{"id":"metal","name":"Metal","symbol":"MTL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf433089366899d83a9f26a773d59ec7ecf30355e","decimalCount":8}]},{"id":"sun-token","name":"Sun Token","symbol":"SUN","active":true,"networks":[{"networkId":"tron","contractAddress":"TSSMHYeV2uE9qYH95DqyoCuNCzEL1NvU3S","decimalCount":18}]},{"id":"storm","name":"StormX","symbol":"STMX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbe9375c6a420d2eeb258962efb95551a5b722803","decimalCount":18}]},{"id":"lukso-token","name":"LUKSO Token","symbol":"LYXE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa8b919680258d369114910511cc87595aec0be6d","decimalCount":18}]},{"id":"weway","name":"WeWay","symbol":"WWY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9ab70e92319f0b9127df78868fd3655fb9f1e322","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x9ab70e92319f0b9127df78868fd3655fb9f1e322","decimalCount":18}]},{"id":"nusd","name":"sUSD","symbol":"SUSD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x57ab1ec28d129707052df4df418d58a2d46d5f51","decimalCount":18},{"networkId":"fantom","contractAddress":"0x0e1694483ebb3b74d3054e383840c6cf011e518e","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xa970af1a584579b618be4d69ad6f73459d112f95","decimalCount":18}]},{"id":"railgun","name":"Railgun","symbol":"RAIL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe76c6c83af64e4c60245d8c7de953df673a7a33d","decimalCount":18}]},{"id":"rari-governance-token","name":"Rari Governance Token","symbol":"RGT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd291e7a03283640fdc51b121ac401383a46cc623","decimalCount":18},{"networkId":"fantom","contractAddress":"0xcf726a06f3dcec8ef2b033336d138caa0eae5af2","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xef888bca6ab6b1d26dbec977c455388ecd794794","decimalCount":18}]},{"id":"reef-finance","name":"Reef Finance","symbol":"REEF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfe3e6a25e6b192a42a44ecddcd13796471735acf","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf21768ccbc73ea5b6fd3c687208a7c2def2d966e","decimalCount":18}]},{"id":"mdex","name":"Mdex","symbol":"MDX","active":false,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x9c65ab58d8d978db963e63f2bfb7121627e3a739","decimalCount":18}]},{"id":"tokemak","name":"Tokemak","symbol":"TOKE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2e9d63788249371f1dfc918a52f8d799f4a38c94","decimalCount":18}]},{"id":"hoo-token","name":"Hoo Token","symbol":"HOO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd241d7b5cb0ef9fc79d9e4eb9e21f5e209f52f7d","decimalCount":8}]},{"id":"request-network","name":"Request","symbol":"REQ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8f8221afbb33998d8584a2b05749ba73c37a938a","decimalCount":18}]},{"id":"poollotto-finance","name":"Poollotto.finance","symbol":"PLT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x631c2f0edabac799f07550aee4ff0bf7fd35212b","decimalCount":18}]},{"id":"perpetual-protocol","name":"Perpetual Protocol","symbol":"PERP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbc396689893d065f41bc2c6ecbee5e0085233447","decimalCount":18}]},{"id":"xsushi","name":"xSUSHI","symbol":"XSUSHI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8798249c2e607446efb7ad49ec89dd1865ff4272","decimalCount":18}]},{"id":"compound-basic-attention-token","name":"cBAT","symbol":"CBAT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6c8c6b02e7b2be14d4fa6022dfd6d75921d90e4e","decimalCount":8}]},{"id":"kyber-network","name":"Kyber Network Crystal Legacy","symbol":"KNCL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdd974d5c2e2928dea5f71b9825b8b646686bd200","decimalCount":18},{"networkId":"fantom","contractAddress":"0x765277eebeca2e31912c9946eae1021199b39c61","decimalCount":18}]},{"id":"metadium","name":"Metadium","symbol":"META","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xde2f7766c8bf14ca67193128535e5c7454f8387c","decimalCount":18}]},{"id":"mask-network","name":"Mask Network","symbol":"MASK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x69af81e73a73b40adf4f3d4223cd9b1ece623074","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x2ed9a5c8c13b93955103b9a7c167b67ef4d568a3","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x2b9e7ccdf0f4e5b24757c1e1a80e311e34cb10c7","decimalCount":18}]},{"id":"orchid-protocol","name":"Orchid Protocol","symbol":"OXT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4575f41308ec1483f3d399aa9a2826d74da13deb","decimalCount":18}]},{"id":"aavegotchi","name":"Aavegotchi","symbol":"GHST","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3f382dbd960e3a9bbceae22651e88158d2791550","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x385eeac5cb85a38a9a07a70c73e0a3271cfb54a7","decimalCount":18}]},{"id":"reserve-rights-token","name":"Reserve Rights Token","symbol":"RSR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x320623b8e4ff03373931769a31fc52a4e78b5d70","decimalCount":18}]},{"id":"radicle","name":"Radicle","symbol":"RAD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x31c8eacbffdd875c74b94b077895bd78cf1e64a3","decimalCount":18}]},{"id":"metahero","name":"Metahero","symbol":"HERO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd40bedb44c081d2935eeba6ef5a3c8a31a1bbe13","decimalCount":18}]},{"id":"constitutiondao","name":"ConstitutionDAO","symbol":"PEOPLE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7a58c0be72be218b41c608b7fe7c5bb630736c71","decimalCount":18}]},{"id":"quark-chain","name":"QuarkChain","symbol":"QKC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xea26c4ac16d4a5a106820bc8aee85fd0b7b2b664","decimalCount":18}]},{"id":"nest","name":"Nest Protocol","symbol":"NEST","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x04abeda201850ac0124161f037efd70c74ddc74c","decimalCount":18}]},{"id":"biconomy","name":"Biconomy","symbol":"BICO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf17e65822b568b3903685a7c9f496cf7656cc6c2","decimalCount":18}]},{"id":"dopex","name":"Dopex","symbol":"DPX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xeec2be5c91ae7f8a338e1e5f3b5de49d07afdc81","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x6c2c06790b3e3e3c38e12ee22f8183b37a13ee55","decimalCount":18}]},{"id":"prometeus","name":"Prometeus","symbol":"PROM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfc82bb4ba86045af6f327323a46e80412b91b27d","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xaf53d56ff99f1322515e54fdde93ff8b3b7dafd5","decimalCount":18}]},{"id":"stratis","name":"Stratis","symbol":"STRAX","active":false,"networks":[{"networkId":"ethereum","contractAddress":"0xa3c22370de5f9544f0c4de126b1e46ceadf0a51b","decimalCount":18}]},{"id":"numeraire","name":"Numeraire","symbol":"NMR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1776e1f26f98b1a5df9cd347953a26dd3cb46671","decimalCount":18}]},{"id":"storj","name":"Storj","symbol":"STORJ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb64ef51c888972c908cfacf59b47c1afbc0ab8ac","decimalCount":8}]},{"id":"strike","name":"Strike","symbol":"STRK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x74232704659ef37c08995e386a2e26cc27a8d7b1","decimalCount":18}]},{"id":"adshares","name":"Adshares","symbol":"ADS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcfcecfe2bd2fed07a9145222e8a7ad9cf1ccd22a","decimalCount":11},{"networkId":"binance-smart-chain","contractAddress":"0xcfcecfe2bd2fed07a9145222e8a7ad9cf1ccd22a","decimalCount":11},{"networkId":"polygon-pos","contractAddress":"0x598e49f01befeb1753737934a5b11fea9119c796","decimalCount":11}]},{"id":"dawn-protocol","name":"Dawn Protocol","symbol":"DAWN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x580c8520deda0a441522aeae0f9f7a5f29629afa","decimalCount":18}]},{"id":"nerve-finance","name":"Nerve Finance","symbol":"NRV","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x42f6f551ae042cbe50c739158b4f0cac0edb9096","decimalCount":18}]},{"id":"bifrost","name":"Bifrost","symbol":"BFC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0c7d5ae016f806603cb1782bea29ac69471cab9c","decimalCount":18},{"networkId":"fantom","contractAddress":"0x84c882a4d8eb448ce086ea19418ca0f32f106117","decimalCount":18}]},{"id":"floki-inu","name":"Floki Inu","symbol":"FLOKI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcf0c122c6b73ff809c693db761e7baebe62b6a2e","decimalCount":9},{"networkId":"binance-smart-chain","contractAddress":"0xfb5b838b6cfeedc2873ab27866079ac55363d37e","decimalCount":9}]},{"id":"stp-network","name":"STP Network","symbol":"STPT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xde7d85157d9714eadf595045cc12ca4a5f3e2adb","decimalCount":18}]},{"id":"hermez-network-token","name":"Hermez Network","symbol":"HEZ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xeef9f339514298c6a857efcfc1a762af84438dee","decimalCount":18}]},{"id":"mango-markets","name":"Mango","symbol":"MNGO","active":true,"networks":[{"networkId":"solana","contractAddress":"MangoCzJ36AjZyKwVj3VnYU4GTonjfVEnJmvvWaxLac","decimalCount":6}]},{"id":"aelf","name":"aelf","symbol":"ELF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbf2179859fc6d5bee9bf9158632dc51678a4100e","decimalCount":18}]},{"id":"uquid-coin","name":"Uquid Coin","symbol":"UQC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8806926ab68eb5a7b909dcaf6fdbe5d93271d6e2","decimalCount":18}]},{"id":"boba-network","name":"Boba Network","symbol":"BOBA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x42bbfa2e77757c645eeaad1655e0911a7553efbc","decimalCount":18}]},{"id":"efinity","name":"Efinity","symbol":"EFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x656c00e1bcd96f256f224ad9112ff426ef053733","decimalCount":18}]},{"id":"veritaseum","name":"Veritaseum","symbol":"VERI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8f3470a7388c05ee4e7af3d01d8c722b0ff52374","decimalCount":18}]},{"id":"coinmetro","name":"Coinmetro","symbol":"XCM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x36ac219f90f5a6a3c77f2a7b660e3cc701f68e25","decimalCount":18}]},{"id":"sifchain","name":"Sifchain","symbol":"EROWAN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x07bac35846e5ed502aa91adf6a9e7aa210f2dcbe","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xa7051c5a22d963b81d71c2ba64d46a877fbc1821","decimalCount":18}]},{"id":"bezoge-earth","name":"Bezoge Earth","symbol":"BEZOGE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdc349913d53b446485e98b76800b6254f43df695","decimalCount":9}]},{"id":"sai","name":"Sai","symbol":"SAI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359","decimalCount":18}]},{"id":"ampleforth","name":"Ampleforth","symbol":"AMPL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd46ba6d942050d489dbd938a2c909a5d5039a161","decimalCount":9},{"networkId":"binance-smart-chain","contractAddress":"0xdb021b1b247fe2f1fa57e0a87c748cc1e321f07f","decimalCount":9},{"networkId":"avalanche","contractAddress":"0x027dbca046ca156de9622cd1e2d907d375e53aa7","decimalCount":9}]},{"id":"alpha-finance","name":"Alpha Venture DAO","symbol":"ALPHA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa1faa113cbe53436df28ff0aee54275c13b40975","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xa1faa113cbe53436df28ff0aee54275c13b40975","decimalCount":18}]},{"id":"band-protocol","name":"Band Protocol","symbol":"BAND","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xba11d00c5f74255f56a5e366f4f77f5a186d7f55","decimalCount":18},{"networkId":"fantom","contractAddress":"0x46e7628e8b4350b2716ab470ee0ba1fa9e76c6c5","decimalCount":18}]},{"id":"alchemy-pay","name":"Alchemy Pay","symbol":"ACH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xed04915c23f00a313a544955524eb7dbd823143d","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0xbc7d6b50616989655afd682fb42743507003056d","decimalCount":8}]},{"id":"sharering","name":"ShareToken","symbol":"SHR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd98f75b1a3261dab9eed4956c93f33749027a964","decimalCount":2}]},{"id":"jasmycoin","name":"JasmyCoin","symbol":"JASMY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7420b4b9a0110cdc71fb720908340c03f9bc03ec","decimalCount":18}]},{"id":"ufo-gaming","name":"UFO Gaming","symbol":"UFO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x249e38ea4102d0cf8264d3701f1a0e39c4f2dc3b","decimalCount":18}]},{"id":"wrapped-centrifuge","name":"Wrapped Centrifuge","symbol":"WCFG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc221b7e65ffc80de234bbb6667abdd46593d34f0","decimalCount":18}]},{"id":"singularitynet","name":"SingularityNET","symbol":"AGIX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5b7533812759b45c2b44c19e320ba2cd2681b542","decimalCount":8}]},{"id":"propy","name":"Propy","symbol":"PRO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x226bb599a12c826476e3a771454697ea52e9e220","decimalCount":8}]},{"id":"platoncoin","name":"PlatonCoin","symbol":"PLTC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x429d83bb0dcb8cdd5311e34680adc8b12070a07f","decimalCount":18}]},{"id":"utrust","name":"Utrust","symbol":"UTK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdc9ac3c20d1ed0b540df9b1fedc10039df13f99c","decimalCount":18}]},{"id":"ageur","name":"agEUR","symbol":"AGEUR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1a7e4e63778b4f12a199c062f3efdd288afcbce8","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xe0b52e49357fd4daf2c15e02058dce6bc0057db4","decimalCount":18}]},{"id":"dola-usd","name":"Dola","symbol":"DOLA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x865377367054516e17014ccded1e7d814edc9ce4","decimalCount":18}]},{"id":"truefi","name":"TrueFi","symbol":"TRU","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4c19596f5aaff459fa38b0f7ed92f11ae6543784","decimalCount":8}]},{"id":"temple","name":"TempleDAO","symbol":"TEMPLE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x470ebf5f030ed85fc1ed4c2d36b9dd02e77cf1b7","decimalCount":18}]},{"id":"tomb","name":"Tomb","symbol":"TOMB","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0xb84527d59b6ecb96f433029ecc890d4492c5dce1","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x0e98c977b943f06075b2d795794238fbfb9b9a34","decimalCount":18},{"networkId":"fantom","contractAddress":"0x6c021ae822bea943b2e66552bde1d2696a53fbb7","decimalCount":18}]},{"id":"shapeshift-fox-token","name":"ShapeShift FOX Token","symbol":"FOX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc770eefad204b5180df6a14ee197d99d808ee52d","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x65a05db8322701724c197af82c9cae41195b0aa8","decimalCount":18}]},{"id":"victoria-vr","name":"Victoria VR","symbol":"VR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7d5121505149065b562c789a0145ed750e6e8cdd","decimalCount":18}]},{"id":"origin-dollar","name":"Origin Dollar","symbol":"OUSD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2a8e1e676ec238d8a992307b495b45b3feaa5e86","decimalCount":18}]},{"id":"cvault-finance","name":"cVault.finance","symbol":"CORE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x62359ed7505efc61ff1d56fef82158ccaffa23d7","decimalCount":18}]},{"id":"iexec-rlc","name":"iExec RLC","symbol":"RLC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x607f4c5bb672230e8672085532f7e901544a7375","decimalCount":9}]},{"id":"aragon","name":"Aragon","symbol":"ANT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa117000000f279d81a1d3cc75430faa017fa5a2e","decimalCount":18}]},{"id":"everipedia","name":"Everipedia","symbol":"IQ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x579cea1889991f68acc35ff5c3dd0621ff29b0c9","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x0e37d70b51ffa2b98b4d34a5712c5291115464e3","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xb9638272ad6998708de56bbc0a290a1de534a578","decimalCount":18}]},{"id":"nkn","name":"NKN","symbol":"NKN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5cf04716ba20127f1e2297addcf4b5035000c9eb","decimalCount":18}]},{"id":"proton","name":"Proton","symbol":"XPR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd7efb00d12c2c13131fd319336fdf952525da2af","decimalCount":4},{"networkId":"binance-smart-chain","contractAddress":"0x5de3939b2f811a61d830e6f52d13b066881412ab","decimalCount":4}]},{"id":"venus","name":"Venus","symbol":"XVS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xcf6bb5389c92bdda8a3747ddb454cb7a64626c63","decimalCount":18}]},{"id":"yoshi-exchange","name":"Yoshi.exchange","symbol":"YOSHI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4374f26f0148a6331905edf4cd33b89d8eed78d1","decimalCount":18},{"networkId":"fantom","contractAddress":"0x3dc57b391262e3aae37a08d91241f9ba9d58b570","decimalCount":18}]},{"id":"dusk-network","name":"DUSK Network","symbol":"DUSK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x940a2db1b7008b6c776d4faaca729d6d4a4aa551","decimalCount":18}]},{"id":"beefy-finance","name":"Beefy.Finance","symbol":"BIFI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xca3f508b8e4dd382ee878a314789373d80a5190a","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xd6070ae98b8069de6b494332d1a1a81b6179d960","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xfbdd194376de19a88118e84e279b977f165d01b8","decimalCount":18},{"networkId":"fantom","contractAddress":"0xd6070ae98b8069de6b494332d1a1a81b6179d960","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x99c409e5f62e4bd2ac142f17cafb6810b8f0baae","decimalCount":18}]},{"id":"polkastarter","name":"Polkastarter","symbol":"POLS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x83e6f1e41cdd28eaceb20cb649155049fac3d5aa","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x7e624fa0e1c4abfd309cc15719b7e2580887f570","decimalCount":18}]},{"id":"neutrino-system-base-token","name":"Neutrino System Base Token","symbol":"NSBT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9d79d5b61de59d882ce90125b18f74af650acb93","decimalCount":6}]},{"id":"sperax","name":"Sperax","symbol":"SPA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb4a3b0faf0ab53df58001804dda5bfc6a3d59008","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x5575552988a3a80504bbaeb1311674fcfd40ad4b","decimalCount":18}]},{"id":"kishu-inu","name":"Kishu Inu","symbol":"KISHU","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa2b4c0af19cc16a6cfacce81f192b024d625817d","decimalCount":9}]},{"id":"superfarm","name":"SuperFarm","symbol":"SUPER","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe53ec727dbdeb9e2d5456c3be40cff031ab40a55","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x51ba0b044d96c3abfca52b64d733603ccc4f0d4d","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xa1428174f516f527fafdd146b883bb4428682737","decimalCount":18}]},{"id":"unibright","name":"Unibright","symbol":"UBT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8400d94a5cb0fa0d041a3788e395285d61c9ee5e","decimalCount":8},{"networkId":"polygon-pos","contractAddress":"0x7fbc10850cae055b27039af31bd258430e714c62","decimalCount":8}]},{"id":"deapcoin","name":"DEAPCOIN","symbol":"DEP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1a3496c18d558bd9c6c8f609e1b129f67ab08163","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xcaf5191fc480f43e4df80106c7695eca56e48b18","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xd4d026322c88c2d49942a75dff920fcfbc5614c1","decimalCount":18}]},{"id":"blox","name":"Blox","symbol":"CDT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x177d39ac676ed1c67a2b268ad7f1e58826e5b0af","decimalCount":18}]},{"id":"wonderland","name":"Wonderland","symbol":"TIME","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0xb54f16fb19478766a268f172c9480f8da1a7c9c3","decimalCount":9}]},{"id":"tornado-cash","name":"Tornado Cash","symbol":"TORN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x77777feddddffc19ff86db637967013e6c6a116c","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x1ba8d3c4c219b124d351f603060663bd1bcd9bbf","decimalCount":18}]},{"id":"yield-guild-games","name":"Yield Guild Games","symbol":"YGG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x25f8087ead173b73d6e8b84329989a8eea16cf73","decimalCount":18}]},{"id":"carry","name":"Carry","symbol":"CRE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x115ec79f1de567ec68b7ae7eda501b406626478e","decimalCount":18}]},{"id":"reflexer-ungovernance-token","name":"Reflexer Ungovernance Token","symbol":"FLX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6243d8cea23066d098a15582d81a598b4e8391f4","decimalCount":18}]},{"id":"bakerytoken","name":"BakerySwap","symbol":"BAKE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xe02df9e3e622debdd69fb838bb799e3f168902c5","decimalCount":18}]},{"id":"kardiachain","name":"KardiaChain","symbol":"KAI","active":false,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x39ae8eefb05138f418bb27659c21632dc1ddab10","decimalCount":18}]},{"id":"dei-token","name":"DEI","symbol":"DEI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xde12c7959e1a72bbe8a5f7a1dc8f8eef9ab011b3","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xde12c7959e1a72bbe8a5f7a1dc8f8eef9ab011b3","decimalCount":18},{"networkId":"fantom","contractAddress":"0xde12c7959e1a72bbe8a5f7a1dc8f8eef9ab011b3","decimalCount":18}]},{"id":"btc-standard-hashrate-token","name":"BTC Standard Hashrate Token","symbol":"BTCST","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x78650b139471520656b9e7aa7a5e9276814a38e9","decimalCount":17}]},{"id":"boringdao-[old]","name":"BoringDAO [OLD]","symbol":"BOR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3c9d6c1c73b31c837832c72e04d3152f051fc1a9","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x92d7756c60dcfd4c689290e8a9f4d263b3b32241","decimalCount":18}]},{"id":"aergo","name":"Aergo","symbol":"AERGO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x91af0fbb28aba7e31403cb457106ce79397fd4e6","decimalCount":18}]},{"id":"wozx","name":"Efforce","symbol":"WOZX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x34950ff2b487d9e5282c5ab342d08a2f712eb79f","decimalCount":18}]},{"id":"wrapped-nxm","name":"Wrapped NXM","symbol":"WNXM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0d438f3b5175bebc262bf23753c1e53d03432bde","decimalCount":18}]},{"id":"hunt-token","name":"HUNT","symbol":"HUNT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9aab071b4129b083b01cb5a0cb513ce7eca26fa5","decimalCount":18}]},{"id":"luffy-inu","name":"Luffy","symbol":"LUFFY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7121d00b4fa18f13da6c2e30d19c04844e6afdc8","decimalCount":9}]},{"id":"augur","name":"Augur","symbol":"REP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x221657776846890989a759ba2973e427dff5c9bb","decimalCount":18}]},{"id":"xcad-network","name":"XCAD Network","symbol":"XCAD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7659ce147d0e714454073a5dd7003544234b6aa0","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x431e0cd023a32532bf3969cddfc002c00e98429d","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xa55870278d6389ec5b524553d03c04f5677c061e","decimalCount":18}]},{"id":"musd","name":"mStable USD","symbol":"MUSD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe2f2a5c287993345a840db3b0845fbc70f5935a5","decimalCount":18}]},{"id":"aleph","name":"Aleph.im","symbol":"ALEPH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x27702a26126e0b3702af63ee09ac4d1a084ef628","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x82d2f8e02afb160dd5a480a617692e62de9038c4","decimalCount":18}]},{"id":"e-money","name":"e-Money","symbol":"NGM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xed0d5747a9ab03a75fbfec3228cd55848245b75d","decimalCount":6}]},{"id":"avinoc","name":"AVINOC","symbol":"AVINOC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf1ca9cb74685755965c7458528a36934df52a3ef","decimalCount":18}]},{"id":"orion-protocol","name":"Orion Protocol","symbol":"ORN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0258f474786ddfd37abce6df6bbb1dd5dfc4434a","decimalCount":8}]},{"id":"unifty","name":"Unifty","symbol":"NIF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7e291890b01e5181f7ecc98d79ffbe12ad23df9e","decimalCount":18}]},{"id":"green-satoshi-token","name":"Green Satoshi Token","symbol":"GST","active":true,"networks":[{"networkId":"solana","contractAddress":"AFbX8oGjGpmVFywbVouvhQSRmiW2aR1mohfahi4Y2AdB","decimalCount":9}]},{"id":"rainbow-token-2","name":"Crypto Unicorns Rainbow","symbol":"RBW","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x431cd3c9ac9fc73644bf68bf5691f4b83f9e104f","decimalCount":18}]},{"id":"cocos-bcx","name":"COCOS BCX","symbol":"COCOS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc4c7ea4fab34bd9fb9a5e1b1a98df76e26e6407c","decimalCount":18}]},{"id":"cult-dao","name":"Cult DAO","symbol":"CULT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf0f9d895aca5c8678f706fb8216fa22957685a13","decimalCount":18}]},{"id":"badger-dao","name":"Badger DAO","symbol":"BADGER","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3472a5a71965499acd81997a54bba8d852c6e53d","decimalCount":18},{"networkId":"fantom","contractAddress":"0x753fbc5800a8c8e3fb6dc6415810d627a387dfc9","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xbfa641051ba0a0ad1b0acf549a89536a0d76472e","decimalCount":18}]},{"id":"dodo","name":"DODO","symbol":"DODO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x43dfc4159d86f3a37a5a4b3d4580b888ad7d4ddd","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x67ee3cb086f8a16f34bee3ca72fad36f7db929e2","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xe4bf2864ebec7b7fdf6eeca9bacae7cdfdaffe78","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x69eb4fa4a2fbd498c257c57ea8b7655a2559a581","decimalCount":18}]},{"id":"seth","name":"sETH","symbol":"SETH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5e74c9036fb86bd7ecdcb084a0673efc32ea31cb","decimalCount":18}]},{"id":"my-neighbor-alice","name":"My Neighbor Alice","symbol":"ALICE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xac51066d7bec65dc4589368da368b212745d63e8","decimalCount":6},{"networkId":"binance-smart-chain","contractAddress":"0xac51066d7bec65dc4589368da368b212745d63e8","decimalCount":6}]},{"id":"covalent","name":"Covalent","symbol":"CQT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd417144312dbf50465b1c641d016962017ef6240","decimalCount":18}]},{"id":"bitrue-token","name":"Bitrue Coin","symbol":"BTR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd433138d12beb9929ff6fd583dc83663eea6aaa5","decimalCount":18}]},{"id":"toucan-protocol-base-carbon-tonne","name":"Toucan Protocol: Base Carbon Tonne","symbol":"BCT","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x2f800db0fdb5223b3c3f354886d907a671414a7f","decimalCount":18}]},{"id":"koda-finance","name":"Koda Cryptocurrency","symbol":"KODA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x8094e772fa4a60bdeb1dfec56ab040e17dd608d5","decimalCount":9}]},{"id":"seedify-fund","name":"Seedify.fund","symbol":"SFUND","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x477bc8d23c634c154061869478bce96be6045d12","decimalCount":18}]},{"id":"nominex","name":"Nominex","symbol":"NMX","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd32d01a43c869edcd1117c640fbdcfcfd97d9d65","decimalCount":18}]},{"id":"yfii-finance","name":"DFI.money","symbol":"YFII","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa1d0e215a23d7030842fc67ce582a6afa3ccab83","decimalCount":18}]},{"id":"rook","name":"Rook","symbol":"ROOK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfa5047c9c78b8877af97bdcb85db743fd7313d4a","decimalCount":18}]},{"id":"defipulse-index","name":"DeFi Pulse Index","symbol":"DPI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1494ca1f11d487c2bbe4543e90080aeba4ba3c2b","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x85955046df4668e1dd369d2de9f3aeb98dd2a369","decimalCount":18}]},{"id":"alpaca-finance","name":"Alpaca Finance","symbol":"ALPACA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x8f0528ce5ef7b51152a59745befdd91d97091d2f","decimalCount":18},{"networkId":"fantom","contractAddress":"0xad996a45fd2373ed0b10efa4a8ecb9de445a4302","decimalCount":18}]},{"id":"beta-finance","name":"Beta Finance","symbol":"BETA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbe1a001fe942f96eea22ba08783140b9dcc09d28","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xbe1a001fe942f96eea22ba08783140b9dcc09d28","decimalCount":18}]},{"id":"mainframe","name":"Hifi Finance","symbol":"MFT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdf2c7238198ad8b389666574f2d8bc411a4b7428","decimalCount":18}]},{"id":"dopex-rebate-token","name":"Dopex Rebate","symbol":"RDPX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0ff5a8451a839f5f0bb3562689d9a44089738d11","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x32eb7902d4134bf98a28b963d26de779af92a212","decimalCount":18}]},{"id":"aurory","name":"Aurory","symbol":"AURY","active":true,"networks":[{"networkId":"solana","contractAddress":"AURYydfxJib1ZkTir1Jn1J9ECYUtjb6rKQVmtYaixWPP","decimalCount":9}]},{"id":"keep3rv1","name":"Keep3rV1","symbol":"KP3R","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1ceb5cb57c4d4e2b2433641b95dd330a33185a44","decimalCount":18},{"networkId":"fantom","contractAddress":"0x2a5062d22adcfaafbd5c541d4da82e4b450d4212","decimalCount":18}]},{"id":"auction","name":"Bounce","symbol":"AUCTION","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa9b1eb5908cfc3cdf91f9b8b3a74108598009096","decimalCount":18}]},{"id":"alien-worlds","name":"Alien Worlds","symbol":"TLM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x888888848b652b3e3a0f34c96e00eec0f3a23f72","decimalCount":4}]},{"id":"anchor-protocol","name":"Anchor Protocol","symbol":"ANC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0f3adc247e91c3c50bc08721355a41037e89bc20","decimalCount":18}]},{"id":"spookyswap","name":"Spookyswap","symbol":"BOO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x55af5865807b196bd0197e0902746f31fbccfa58","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xbd83010eb60f12112908774998f65761cf9f6f9a","decimalCount":18},{"networkId":"fantom","contractAddress":"0x841fad6eae12c286d1fd18d1d525dffa75c7effe","decimalCount":18}]},{"id":"ethlend","name":"Aave [OLD]","symbol":"LEND","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x80fb784b7ed66730e8b1dbd9820afd29931aab03","decimalCount":18}]},{"id":"compound-0x","name":"c0x","symbol":"CZRX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb3319f5d18bc0d84dd1b4825dcde5d5f7266d407","decimalCount":8}]},{"id":"melon","name":"Enzyme","symbol":"MLN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xec67005c4e498ec7f55e092bd1d35cbc47c91892","decimalCount":18}]},{"id":"compound-uniswap","name":"cUNI","symbol":"CUNI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x35a18000230da775cac24873d00ff85bccded550","decimalCount":8}]},{"id":"alchemix","name":"Alchemix","symbol":"ALCX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdbdb4d16eda451d0503b854cf79d55697f90c8df","decimalCount":18}]},{"id":"presearch","name":"Presearch","symbol":"PRE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xec213f83defb583af3a000b1c0ada660b1902a0f","decimalCount":18}]},{"id":"phantasma","name":"Phantasma","symbol":"SOUL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x75858677e27c930fb622759feaffee2b754af07f","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0x298eff8af1ecebbb2c034eaa3b9a5d0cc56c59cd","decimalCount":8}]},{"id":"umee","name":"Umee","symbol":"UMEE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc0a4df35568f116c370e6a6a6022ceb908eeddac","decimalCount":6}]},{"id":"clover-finance","name":"Clover Finance","symbol":"CLV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x80c62fe4487e1351b47ba49809ebd60ed085bf52","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x09e889bb4d5b474f561db0491c38702f367a4e4d","decimalCount":18}]},{"id":"everrise","name":"EverRise","symbol":"RISE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc17c30e98541188614df99239cabd40280810ca3","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xc17c30e98541188614df99239cabd40280810ca3","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xc17c30e98541188614df99239cabd40280810ca3","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xc17c30e98541188614df99239cabd40280810ca3","decimalCount":18},{"networkId":"fantom","contractAddress":"0xc17c30e98541188614df99239cabd40280810ca3","decimalCount":18}]},{"id":"klima-dao","name":"Klima DAO","symbol":"KLIMA","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x4e78011ce80ee02d2c3e649fb657e45898257815","decimalCount":9}]},{"id":"decentral-games","name":"Decentral Games","symbol":"DG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4b520c812e8430659fc9f12f6d0c39026c83588d","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xef938b6da8576a896f6e0321ef80996f4890f9c4","decimalCount":18}]},{"id":"axion","name":"Axion","symbol":"AXN","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x839f1a22a59eaaf26c85958712ab32f80fea23d9","decimalCount":18}]},{"id":"dvision-network","name":"Dvision Network","symbol":"DVI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x10633216e7e8281e33c86f02bf8e565a635d9770","decimalCount":18}]},{"id":"splinterlands","name":"Splinterlands","symbol":"SPS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x1633b7157e7638c4d6593436111bf125ee74703f","decimalCount":18}]},{"id":"elastos","name":"Elastos","symbol":"ELA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe6fd75ff38adca4b97fbcd938c86b98772431867","decimalCount":18}]},{"id":"mirror-protocol","name":"Mirror Protocol","symbol":"MIR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x09a3ecafa817268f77be1283176b946c4ff2e608","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x5b6dcf557e2abe2323c48445e8cc948910d8c2c9","decimalCount":18}]},{"id":"usdk","name":"USDK","symbol":"USDK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1c48f86ae57291f7686349f12601910bd8d470bb","decimalCount":18}]},{"id":"aioz-network","name":"AIOZ Network","symbol":"AIOZ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x626e8036deb333b408be468f951bdb42433cbf18","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x33d08d8c7a168333a85285a68c0042b39fc3741d","decimalCount":18}]},{"id":"loom-network","name":"Loom Network (OLD)","symbol":"LOOMOLD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa4e8c3ec456107ea67d3075bf9e3df3a75823db0","decimalCount":18}]},{"id":"zignaly","name":"Zignaly","symbol":"ZIG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb2617246d0c6c0087f18703d576831899ca94f01","decimalCount":18}]},{"id":"district0x","name":"district0x","symbol":"DNT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0abdace70d3790235af448c88547603b945604ea","decimalCount":18}]},{"id":"starlink","name":"StarLink","symbol":"STARL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8e6cd950ad6ba651f6dd608dc70e5886b1aa6b24","decimalCount":18}]},{"id":"gyen","name":"GYEN","symbol":"GYEN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc08512927d12348f6620a698105e1baac6ecd911","decimalCount":6}]},{"id":"lto-network","name":"LTO Network","symbol":"LTO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd01409314acb3b245cea9500ece3f6fd4d70ea30","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0x857b222fc79e1cbbf8ca5f78cb133d1b7cf34bbd","decimalCount":18}]},{"id":"handshake","name":"Handshake","symbol":"HNS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa771b49064da011df051052848477f18dba1d2ac","decimalCount":6}]},{"id":"doge-army-token","name":"Doge Army","symbol":"DGAT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x96e3bd1915483ed6e6569e908a0f6f49434557ed","decimalCount":18}]},{"id":"qanplatform","name":"QANplatform","symbol":"QANX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaaa7a10a8ee237ea61e8ac46c50a8db8bcc1baaa","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xaaa7a10a8ee237ea61e8ac46c50a8db8bcc1baaa","decimalCount":18}]},{"id":"qredo","name":"Qredo","symbol":"QRDO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4123a133ae3c521fd134d7b13a2dec35b56c2463","decimalCount":8}]},{"id":"qash","name":"QASH","symbol":"QASH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x618e75ac90b12c6049ba3b27f5d5f8651b0037f6","decimalCount":6}]},{"id":"verasity","name":"Verasity","symbol":"VRA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf411903cbc70a74d22900a5de66a2dda66507255","decimalCount":18}]},{"id":"xmon","name":"XMON","symbol":"XMON","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3aada3e213abf8529606924d8d1c55cbdc70bf74","decimalCount":18}]},{"id":"vectorspace","name":"Vectorspace AI","symbol":"VXV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7d29a64504629172a429e64183d6673b9dacbfce","decimalCount":18}]},{"id":"butterflydao","name":"Redacted Cartel","symbol":"BTRFLY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc0d4ceb216b3ba9c3701b291766fdcba977cec3a","decimalCount":9}]},{"id":"alpha-quark-token","name":"Alpha Quark Token","symbol":"AQT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2a9bdcff37ab68b95a53435adfd8892e86084f93","decimalCount":18}]},{"id":"cudos","name":"Cudos","symbol":"CUDOS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x817bbdbc3e8a1204f3691d14bb44992841e3db35","decimalCount":18}]},{"id":"adventure-gold","name":"Adventure Gold","symbol":"AGLD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x32353a6c91143bfd6c7d363b546e62a9a2489a20","decimalCount":18}]},{"id":"allianceblock","name":"AllianceBlock","symbol":"ALBT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x00a8b738e453ffd858a7edf03bccfe20412f0eb0","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x9e037de681cafa6e661e6108ed9c2bd1aa567ecd","decimalCount":18}]},{"id":"aurora-dao","name":"IDEX","symbol":"IDEX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb705268213d593b8fd88d3fdeff93aff5cbdcfae","decimalCount":18}]},{"id":"bzx-protocol","name":"bZx Protocol","symbol":"BZRX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x56d811088235f11c8920698a204a5010a788f4b3","decimalCount":18}]},{"id":"superrare","name":"SuperRare","symbol":"RARE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xba5bde662c17e2adff1075610382b9b691296350","decimalCount":18}]},{"id":"lcx","name":"LCX","symbol":"LCX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x037a54aab062628c9bbae1fdb1583c195585fe41","decimalCount":18}]},{"id":"safepal","name":"SafePal","symbol":"SFP","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd41fdb03ba84762dd66a0af1a6c8540ff1ba5dfb","decimalCount":18}]},{"id":"concierge-io","name":"Travala.com","symbol":"AVA","active":true,"networks":[{"networkId":"binancecoin","contractAddress":"AVA-645","decimalCount":8}]},{"id":"gains-farm","name":"Gains Farm","symbol":"GFARM2","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x831091da075665168e01898c6dac004a867f1e1b","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x7075cab6bcca06613e2d071bd918d1a0241379e2","decimalCount":18}]},{"id":"quick","name":"Quickswap [OLD]","symbol":"QUICK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6c28aef8977c9b773996d0e8376d2ee379446f2f","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x831753dd7087cac61ab5644b308642cc1c33dc13","decimalCount":18}]},{"id":"sbtc","name":"sBTC","symbol":"SBTC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfe18be6b3bd88a2d2a7f928d00292e7a9963cfc6","decimalCount":18}]},{"id":"singularitydao","name":"SingularityDAO","symbol":"SDAO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x993864e43caa7f7f12953ad6feb1d1ca635b875f","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x90ed8f1dc86388f14b64ba8fb4bbd23099f18240","decimalCount":18}]},{"id":"shiba-predator","name":"Shiba Predator","symbol":"QOM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa71d0588eaf47f12b13cf8ec750430d21df04974","decimalCount":18}]},{"id":"jet","name":"JET","symbol":"JET","active":true,"networks":[{"networkId":"solana","contractAddress":"JET6zMJWkCN9tpRT2v2jfAmm5VnQFDpUBCyaKojmGtz","decimalCount":9}]},{"id":"automata","name":"Automata","symbol":"ATA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa2120b9e674d3fc3875f415a7df52e382f141225","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xa2120b9e674d3fc3875f415a7df52e382f141225","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x0df0f72ee0e5c9b7ca761ecec42754992b2da5bf","decimalCount":18}]},{"id":"marketpeak","name":"PEAKDEFI","symbol":"PEAK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x630d98424efe0ea27fb1b3ab7741907dffeaad78","decimalCount":8}]},{"id":"boson-protocol","name":"Boson Protocol","symbol":"BOSON","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc477d038d5420c6a9e0b031712f61c5120090de9","decimalCount":18}]},{"id":"market-making-pro","name":"Market Making Pro","symbol":"MMPRO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x6067490d05f3cf2fdffc0e353b1f5fd6e5ccdf70","decimalCount":18}]},{"id":"bonfida","name":"Bonfida","symbol":"FIDA","active":true,"networks":[{"networkId":"solana","contractAddress":"EchesyfXePKdLtoiZSL8pBe8Myagyy8ZRqsACNCFGnvp","decimalCount":6}]},{"id":"interest-bearing-bitcoin","name":"Interest Bearing Bitcoin","symbol":"IBBTC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc4e15973e6ff2a35cc804c2cf9d2a1b817a8b40f","decimalCount":18}]},{"id":"maps","name":"MAPS","symbol":"MAPS","active":true,"networks":[{"networkId":"solana","contractAddress":"MAPS41MDahZ9QdKXhVa4dWB9RuyfV4XqhyAZ8XcYepb","decimalCount":6}]},{"id":"snowbank","name":"Snowbank","symbol":"SB","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x7d1232b90d3f809a54eeaeebc639c62df8a8942f","decimalCount":9}]},{"id":"feg-token-bsc","name":"FEG Token BSC","symbol":"FEG","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xacfc95585d80ab62f67a14c566c1b7a49fe91167","decimalCount":9}]},{"id":"jpeg-d","name":"JPEG'd","symbol":"JPEG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe80c0cd204d654cebe8dd64a4857cab6be8345a3","decimalCount":18}]},{"id":"refereum","name":"Refereum","symbol":"RFR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd0929d411954c47438dc1d871dd6081f5c5e149c","decimalCount":4}]},{"id":"gitcoin","name":"Gitcoin","symbol":"GTC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xde30da39c46104798bb5aa3fe8b9e0e1f348163f","decimalCount":18}]},{"id":"noia-network","name":"Syntropy","symbol":"NOIA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa8c8cfb141a3bb59fea1e2ea6b79b5ecbcd7b6ca","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x957d1ad5214468332c5e6c00305a25116f9a46bb","decimalCount":18}]},{"id":"arpa-chain","name":"ARPA Chain","symbol":"ARPA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xba50933c268f567bdc86e1ac131be072c6b0b71a","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xee800b277a96b0f490a1a732e1d6395fad960a26","decimalCount":18}]},{"id":"ribbon-finance","name":"Ribbon Finance","symbol":"RBN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6123b0049f904d730db3c36a31167d9d4121fa6b","decimalCount":18}]},{"id":"genopets","name":"Genopets","symbol":"GENE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x9df465460938f9ebdf51c38cc87d72184471f8f0","decimalCount":18},{"networkId":"solana","contractAddress":"GENEtH5amGSi8kHAtQoezp1XEXwZJ8vcuePYnXdKrMYz","decimalCount":9}]},{"id":"marlin","name":"Marlin","symbol":"POND","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x57b946008913b82e4df85f501cbaed910e58d26c","decimalCount":18}]},{"id":"bitmart-token","name":"BitMart Token","symbol":"BMX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x986ee2b944c42d017f52af21c4c69b84dbea35d8","decimalCount":18}]},{"id":"harvest-finance","name":"Harvest Finance","symbol":"FARM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa0246c9032bc3a600820415ae600c6388619a14d","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x4b5c23cac08a567ecf0c1ffca8372a45a5d33743","decimalCount":18}]},{"id":"rootkit","name":"Rootkit","symbol":"ROOT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcb5f72d37685c3d5ad0bb5f982443bc8fcdf570e","decimalCount":18}]},{"id":"eth-2x-flexible-leverage-index","name":"Index Coop - ETH 2x Flexible Leverage Index","symbol":"ETH2X-FLI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaa6e8127831c9de45ae56bb1b0d4d4da6e5665bd","decimalCount":18}]},{"id":"derivadao","name":"DerivaDAO","symbol":"DDX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3a880652f47bfaa771908c07dd8673a787daed3a","decimalCount":18}]},{"id":"refinable","name":"Refinable","symbol":"FINE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4e6415a5727ea08aae4580057187923aec331227","decimalCount":18}]},{"id":"rai","name":"Rai Reflex Index","symbol":"RAI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x03ab458634910aad20ef5f1c8ee96f1d6ac54919","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x97cd1cfe2ed5712660bb6c14053c0ecb031bff7d","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x00e5646f60ac6fb446f621d146b6e1886f002905","decimalCount":18}]},{"id":"adex","name":"Ambire AdEx","symbol":"ADX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xade00c28244d5ce17d72e40330b1c318cd12b7c3","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x6bff4fb161347ad7de4a625ae5aa3a1ca7077819","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xc8e36f0a44fbeca89fdd5970439cbe62eb4b5d03","decimalCount":18}]},{"id":"magic","name":"Magic","symbol":"MAGIC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb0c7a3ba49c7a6eaba6cd4a96c55a1391070ac9a","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x539bde0d7dbd336b79148aa742883198bbf60342","decimalCount":18}]},{"id":"sovryn","name":"Sovryn","symbol":"SOV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbdab72602e9ad40fc6a6852caf43258113b8f7a5","decimalCount":18}]},{"id":"token-pocket","name":"Token Pocket","symbol":"TPT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4161725d019690a3e0de50f6be67b07a86a9fae1","decimalCount":4},{"networkId":"binance-smart-chain","contractAddress":"0xeca41281c24451168a37211f0bc2b8645af45092","decimalCount":4}]},{"id":"koinos","name":"Koinos","symbol":"KOIN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x66d28cb58487a7609877550e1a34691810a6b9fc","decimalCount":8}]},{"id":"linear","name":"Linear","symbol":"LINA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3e9bc21c9b189c09df3ef1b824798658d5011937","decimalCount":18}]},{"id":"feg-token","name":"FEG Token","symbol":"FEG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x389999216860ab8e0175387a0c90e5c52522c945","decimalCount":9}]},{"id":"circuits-of-value","name":"Circuits of Value","symbol":"COVAL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3d658390460295fb963f54dc0899cfb1c30776df","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0xd15cee1deafbad6c0b3fd7489677cc102b141464","decimalCount":8},{"networkId":"polygon-pos","contractAddress":"0x4597c8a59ab28b36840b82b3a674994a279593d0","decimalCount":8},{"networkId":"fantom","contractAddress":"0x8b8407c6184f1f0fd1082e83d6a3b8349caced12","decimalCount":8}]},{"id":"box-token","name":"BOX Token","symbol":"BOX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe1a178b681bd05964d3e3ed33ae731577d9d96dd","decimalCount":18}]},{"id":"x2y2","name":"X2Y2","symbol":"X2Y2","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1e4ede388cbc9f4b5c79681b7f94d36a11abebc9","decimalCount":18}]},{"id":"swarm-bzz","name":"Swarm","symbol":"BZZ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x19062190b1925b5b6689d7073fdfc8c2976ef8cb","decimalCount":16}]},{"id":"bnb48-club-token","name":"BNB48 Club Token","symbol":"KOGE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xe6df05ce8c8301223373cf5b969afcb1498c5528","decimalCount":18}]},{"id":"kin","name":"Kin","symbol":"KIN","active":false,"networks":[{"networkId":"solana","contractAddress":"kinXdEcpDQeHPEuQnqmUgtYykqKGVFq6CeVX5iAHJq6","decimalCount":5}]},{"id":"ampleforth-governance-token","name":"Ampleforth Governance Token","symbol":"FORTH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x77fba179c79de5b7653f68b5039af940ada60ce0","decimalCount":18}]},{"id":"woonkly-power","name":"Woonkly Power","symbol":"WOOP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaad483f97f13c6a20b9d05d07c397ce85c42c393","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x8b303d5bbfbbf46f1a4d9741e491e06986894e18","decimalCount":18}]},{"id":"alpine-f1-team-fan-token","name":"Alpine F1 Team Fan Token","symbol":"ALPINE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x287880ea252b52b63cc5f40a2d3e5a44aa665a76","decimalCount":8}]},{"id":"velo","name":"Velo","symbol":"VELO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xf486ad071f3bee968384d2e39e2d8af0fcf6fd46","decimalCount":18}]},{"id":"dvf","name":"DeversiFi","symbol":"DVF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdddddd4301a082e62e84e43f474f044423921918","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xa7aa2921618e3d63da433829d448b58c9445a4c3","decimalCount":18}]},{"id":"redfox-labs-2","name":"RFOX","symbol":"RFOX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa1d6df714f91debf4e0802a542e13067f31b8262","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x0a3a21356793b49154fd3bbe91cbc2a16c0457f5","decimalCount":18}]},{"id":"wilder-world","name":"Wilder World","symbol":"WILD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2a3bff78b79a009976eea096a51a948a3dc00e34","decimalCount":18}]},{"id":"saito","name":"Saito","symbol":"SAITO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfa14fa6958401314851a17d6c5360ca29f74b57b","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x3c6dad0475d3a1696b359dc04c99fd401be134da","decimalCount":18}]},{"id":"marcopolo","name":"MAP Protocol","symbol":"MAP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9e976f211daea0d652912ab99b0dc21a7fd728e4","decimalCount":18}]},{"id":"ethernity-chain","name":"Ethernity Chain","symbol":"ERN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbbc2ae13b23d715c30720f079fcd9b4a74093505","decimalCount":18}]},{"id":"ovr","name":"Ovr","symbol":"OVR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x21bfbda47a0b4b5b1248c767ee49f7caa9b23697","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x7e35d0e9180bf3a1fc47b0d110be7a21a10b41fe","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x1631244689ec1fecbdd22fb5916e920dfc9b8d30","decimalCount":18}]},{"id":"mossland","name":"Mossland","symbol":"MOC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x865ec58b06bf6305b886793aa20a2da31d034e68","decimalCount":18}]},{"id":"tomb-shares","name":"Tomb Shares","symbol":"TSHARE","active":true,"networks":[{"networkId":"fantom","contractAddress":"0x4cdf39285d7ca8eb3f090fda0c069ba5f4145b37","decimalCount":18}]},{"id":"aeternity","name":"Aeternity","symbol":"AE","active":false,"networks":[{"networkId":"ethereum","contractAddress":"0x5ca9a71b1d01849c0a95490cc00559717fcf0d1d","decimalCount":18}]},{"id":"pundi-x","name":"Pundi X [OLD]","symbol":"NPXS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa15c7ebe1f07caf6bff097d8a589fb8ac49ae5b3","decimalCount":18}]},{"id":"rupiah-token","name":"Rupiah Token","symbol":"IDRT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x998ffe1e43facffb941dc337dd0468d52ba5b48a","decimalCount":2}]},{"id":"trustswap","name":"Trustswap","symbol":"SWAP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcc4304a31d09258b0029ea7fe63d032f52e44efe","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x82443a77684a7da92fdcb639c8d2bd068a596245","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xc7b5d72c836e718cda8888eaf03707faef675079","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x3809dcdd5dde24b37abe64a5a339784c3323c44f","decimalCount":18}]},{"id":"hi-dollar","name":"hi Dollar","symbol":"HI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc4f6e93aeddc11dc22268488465babcaf09399ac","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x77087ab5df23cfb52449a188e80e9096201c2097","decimalCount":18}]},{"id":"rai-finance","name":"RAI Finance","symbol":"SOFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb49fa25978abf9a248b8212ab4b87277682301c0","decimalCount":18}]},{"id":"decentral-games-governance","name":"Decentral Games Governance","symbol":"XDG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4f81c790581b240a5c948afd173620ecc8c71c8d","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xc6480da81151b2277761024599e8db2ad4c388c8","decimalCount":18}]},{"id":"richquack","name":"Rich Quack","symbol":"QUACK","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd74b782e05aa25c50e7330af541d46e18f36661c","decimalCount":9}]},{"id":"alethea-artificial-liquid-intelligence-token","name":"Alethea Artificial Liquid Intelligence","symbol":"ALI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6b0b3a982b4634ac68dd83a4dbf02311ce324181","decimalCount":18}]},{"id":"pha","name":"Phala Network","symbol":"PHA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6c5ba91642f10282b576d91922ae6448c9d52f4e","decimalCount":18}]},{"id":"reserve","name":"Reserve","symbol":"RSV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x196f4727526ea7fb1e17b2071b3d8eaa38486988","decimalCount":18}]},{"id":"hopr","name":"HOPR","symbol":"HOPR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf5581dfefd8fb0e4aec526be659cfab1f8c781da","decimalCount":18}]},{"id":"dia-data","name":"DIA","symbol":"DIA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x84ca8bc7997272c7cfb4d0cd3d55cd942b3c9419","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x99956d38059cf7beda96ec91aa7bb2477e0901dd","decimalCount":18}]},{"id":"polyswarm","name":"PolySwarm","symbol":"NCT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9e46a38f5daabe8683e10793b06749eef7d733d1","decimalCount":18}]},{"id":"morpheus-network","name":"Morpheus Network","symbol":"MNW","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd3e4ba569045546d09cf021ecc5dfe42b1d7f6e4","decimalCount":18}]},{"id":"zenon","name":"Zenon","symbol":"ZNN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x84b174628911896a3b87fa6980d05dbc2ee74836","decimalCount":8}]},{"id":"civilization","name":"Civilization","symbol":"CIV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x37fe0f067fa808ffbdd12891c0858532cfe7361d","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x42f6bdcfd82547e89f1069bf375aa60e6c6c063d","decimalCount":18}]},{"id":"apollox-2","name":"ApolloX","symbol":"APX","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x78f5d389f5cdccfc41594abab4b0ed02f31398b3","decimalCount":18}]},{"id":"hedpay","name":"HEdpAY","symbol":"HDP.Ф","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc4d5545392f5fc57eba3af8981815669bb7e2a48","decimalCount":4}]},{"id":"pstake-finance","name":"pSTAKE Finance","symbol":"PSTAKE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfb5c6815ca3ac72ce9f5006869ae67f18bf77006","decimalCount":18}]},{"id":"somnium-space-cubes","name":"Somnium Space CUBEs","symbol":"CUBE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdf801468a808a32656d2ed2d2d80b72a129739f4","decimalCount":8}]},{"id":"coin-of-the-champions","name":"Coin of the champions","symbol":"COC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc4bb7277a74678f053259cb1f96140347efbfd46","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xbdc3b3639f7aa19e623a4d603a3fb7ab20115a91","decimalCount":18}]},{"id":"yield-app","name":"YIELD App","symbol":"YLD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf94b5c5651c888d928439ab6514b93944eee6f48","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x4cebdbcb286101a17d3ea1f7fe7bbded2b2053dd","decimalCount":18}]},{"id":"meter","name":"Meter Governance","symbol":"MTRG","active":false,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xbd2949f67dcdc549c6ebe98696449fa79d988a9f","decimalCount":18}]},{"id":"sentinel-protocol","name":"Sentinel Protocol","symbol":"UPP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc86d054809623432210c107af2e3f619dcfbf652","decimalCount":18}]},{"id":"gains-network","name":"Gains Network","symbol":"GNS","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0xe5417af564e4bfda1c483642db72007871397896","decimalCount":18}]},{"id":"popcorn","name":"Popcorn","symbol":"POP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd0cd466b34a24fcb2f87676278af2005ca8a78c4","decimalCount":18}]},{"id":"mixmarvel","name":"MixMarvel","symbol":"MIX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5d285f735998f36631f678ff41fb56a10a4d0429","decimalCount":18}]},{"id":"contentos","name":"Contentos","symbol":"COS","active":true,"networks":[{"networkId":"binancecoin","contractAddress":"COS-2E4","decimalCount":8}]},{"id":"quantstamp","name":"Quantstamp","symbol":"QSP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x99ea4db9ee77acd40b119bd1dc4e33e1c070b80d","decimalCount":18}]},{"id":"tranchess","name":"Tranchess","symbol":"CHESS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x20de22029ab63cf9a7cf5feb2b737ca1ee4c82a6","decimalCount":18}]},{"id":"vega-protocol","name":"Vega Protocol","symbol":"VEGA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcb84d72e61e383767c4dfeb2d8ff7f4fb89abc6e","decimalCount":18}]},{"id":"benqi","name":"BENQI","symbol":"QI","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x8729438eb15e2c8b576fcc6aecda6a148776c0f5","decimalCount":18}]},{"id":"cargox","name":"CargoX","symbol":"CXO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb6ee9668771a79be7967ee29a63d4184f8097143","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xf2ae0038696774d65e67892c9d301c5f2cbbda58","decimalCount":18}]},{"id":"shibadoge","name":"ShibaDoge","symbol":"SHIBDOGE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6adb2e268de2aa1abf6578e4a8119b960e02928f","decimalCount":9}]},{"id":"tokocrypto","name":"Tokocrypto","symbol":"TKO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x9f589e3eabe42ebc94a44727b3f3531c0c877809","decimalCount":18}]},{"id":"panther","name":"Panther Protocol","symbol":"ZKP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x909e34d3f6124c324ac83dcca84b74398a6fa173","decimalCount":18}]},{"id":"bone-shibaswap","name":"Bone ShibaSwap","symbol":"BONE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9813037ee2218799597d83d4a5b6f3b6778218d9","decimalCount":18}]},{"id":"dxdao","name":"DXdao","symbol":"DXD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa1d65e8fb6e87b60feccbc582f7f97804b725521","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xc3ae0333f0f34aa734d5493276223d95b8f9cb37","decimalCount":18}]},{"id":"whale","name":"WHALE","symbol":"WHALE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9355372396e3f6daf13359b7b607a3374cc638e0","decimalCount":4}]},{"id":"sipher","name":"Sipher","symbol":"SIPHER","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9f52c8ecbee10e00d9faaac5ee9ba0ff6550f511","decimalCount":18}]},{"id":"mcontent","name":"MContent","symbol":"MCONTENT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd3c51de3e6dd9b53d7f37699afb3ee3bf9b9b3f4","decimalCount":6},{"networkId":"binance-smart-chain","contractAddress":"0x799e1cf88a236e42b4a87c544a22a94ae95a6910","decimalCount":6}]},{"id":"rarible","name":"Rarible","symbol":"RARI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfca59cd816ab1ead66534d82bc21e7515ce441cf","decimalCount":18}]},{"id":"wirex","name":"Wirex","symbol":"WXT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa02120696c7b8fe16c09c749e4598819b2b0e915","decimalCount":18}]},{"id":"naga","name":"NAGA","symbol":"NGC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x72dd4b6bd852a3aa172be4d6c5a6dbec588cf131","decimalCount":18}]},{"id":"gamezone","name":"GameZone","symbol":"GZONE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xb6adb74efb5801160ff749b1985fd3bd5000e938","decimalCount":18}]},{"id":"content-value-network","name":"Conscious Value Network","symbol":"CVNT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6400b5522f8d448c0803e6245436dd1c81df09ce","decimalCount":8}]},{"id":"thorchain-erc20","name":"THORChain (ERC20)","symbol":"RUNE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3155ba85d5f96b2d030a4966af206230e46849cb","decimalCount":18}]},{"id":"lattice-token","name":"Lattice Token","symbol":"LTX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa393473d64d2f9f026b60b6df7859a689715d092","decimalCount":8}]},{"id":"vai","name":"Vai","symbol":"VAI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4bd17003473389a42daf6a0a729f6fdb328bbbd7","decimalCount":18}]},{"id":"bluzelle","name":"Bluzelle","symbol":"BLZ","active":false,"networks":[{"networkId":"ethereum","contractAddress":"0x5732046a883704404f284ce41ffadd5b007fd668","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x935a544bf5816e3a7c13db2efe3009ffda0acda2","decimalCount":18}]},{"id":"barnbridge","name":"BarnBridge","symbol":"BOND","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0391d2021f89dc339f60fff84546ea23e337750f","decimalCount":18}]},{"id":"idia","name":"Impossible Finance Launchpad","symbol":"IDIA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x0b15ddf19d47e6a86a56148fb4afffc6929bcb89","decimalCount":18}]},{"id":"get-token","name":"GET Protocol","symbol":"GET","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8a854288a5976036a725879164ca3e91d30c6a1b","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xdb725f82818de83e99f1dac22a9b5b51d3d04dd4","decimalCount":18}]},{"id":"qi-dao","name":"Qi Dao","symbol":"QI","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0xa56f9a54880afbc30cf29bb66d2d9adcdcaeadd6","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x580a84c73811e1839f75d86d75d88cca0c241ff4","decimalCount":18}]},{"id":"yieldly","name":"Yieldly","symbol":"YLDY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x88cb253d4c8cab8cdf7948a9251db85a13669e23","decimalCount":18}]},{"id":"fuse-network-token","name":"Fuse","symbol":"FUSE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x970b9bb2c0444f5e81e9d0efb84c8ccdcdcaf84d","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x5857c96dae9cf8511b08cb07f85753c472d36ea3","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xf915fdda4c882731c0456a4214548cd13a822886","decimalCount":18}]},{"id":"tellor","name":"Tellor","symbol":"TRB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x88df592f8eb5d7bd38bfef7deb0fbc02cf3778a0","decimalCount":18}]},{"id":"tbtc","name":"tBTC","symbol":"TBTC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8daebade922df735c38c80c7ebd708af50815faa","decimalCount":18}]},{"id":"tokenlon","name":"Tokenlon","symbol":"LON","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0000000000095413afc295d19edeb1ad7b71c952","decimalCount":18}]},{"id":"nftx","name":"NFTX","symbol":"NFTX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x87d73e916d7057945c9bcd8cdd94e42a6f47f776","decimalCount":18}]},{"id":"sx-network","name":"SX Network","symbol":"SX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x99fe3b1391503a1bc1788051347a1324bff41452","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x840195888db4d6a99ed9f73fcd3b225bb3cb1a79","decimalCount":18}]},{"id":"fodl-finance","name":"Fodl Finance","symbol":"FODL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4c2e59d098df7b6cbae0848d66de2f8a4889b9c3","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x5314ba045a459f63906aa7c76d9f337dcb7d6995","decimalCount":18}]},{"id":"bscpad","name":"BSCPAD","symbol":"BSCPAD","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x5a3010d4d8d3b5fb49f8b6e57fb9e48063f16700","decimalCount":18}]},{"id":"phonon-dao","name":"Phonon DAO","symbol":"PHONON","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x758b4684be769e92eefea93f60dda0181ea303ec","decimalCount":18}]},{"id":"boringdao","name":"BoringDAO","symbol":"BORING","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbc19712feb3a26080ebf6f2f7849b417fdd792ca","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xffeecbf8d7267757c2dc3d13d730e97e15bfdf7f","decimalCount":18}]},{"id":"pinksale","name":"PinkSale","symbol":"PINKSALE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x602ba546a7b06e0fc7f58fd27eb6996ecc824689","decimalCount":18}]},{"id":"lockchain","name":"LockTrip","symbol":"LOC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5e3346444010135322268a4630d2ed5f8d09446c","decimalCount":18}]},{"id":"avalaunch","name":"Avalaunch","symbol":"XAVA","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0xd1c3f94de7e5b45fa4edbba472491a9f4b166fc4","decimalCount":18}]},{"id":"streamr-xdata","name":"Streamr XDATA","symbol":"XDATA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0cf0ee63788a0849fe5297f3407f701e122cc023","decimalCount":18}]},{"id":"hotbit-token","name":"Hotbit Token","symbol":"HTB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6be61833fc4381990e82d7d4a9f4c9b3f67ea941","decimalCount":18}]},{"id":"mantra-dao","name":"MANTRA DAO","symbol":"OM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3593d125a4f7849a1b059e64f4517a86dd60c95d","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf78d2e7936f5fe18308a3b2951a93b6c4a41f5e2","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xc3ec80343d2bae2f8e680fdadde7c17e71e114ea","decimalCount":18}]},{"id":"kleros","name":"Kleros","symbol":"PNK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x93ed3fbe21207ec2e8f2d3c3de6e058cb73bc04d","decimalCount":18}]},{"id":"chronobank","name":"chrono.tech","symbol":"TIME","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x485d17a6f1b8780392d53d64751824253011a260","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0x3b198e26e473b8fab2085b37978e36c9de5d7f68","decimalCount":8}]},{"id":"guildfi","name":"GuildFi","symbol":"GF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaaef88cea01475125522e117bfe45cf32044e238","decimalCount":18}]},{"id":"mimo-parallel-governance-token","name":"Mimo Governance","symbol":"MIMO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x90b831fa3bebf58e9744a14d638e25b4ee06f9bc","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xadac33f543267c4d59a8c299cf804c303bc3e4ac","decimalCount":18},{"networkId":"fantom","contractAddress":"0x1d1764f04de29da6b90ffbef372d1a45596c4855","decimalCount":18}]},{"id":"vitadao","name":"VitaDAO","symbol":"VITA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x81f8f0bb1cb2a06649e51913a151f0e7ef6fa321","decimalCount":18}]},{"id":"grid","name":"GridPlus [OLD]","symbol":"GRID","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x12b19d3e2ccc14da04fae33e63652ce469b3f2fd","decimalCount":12}]},{"id":"revolution-populi","name":"Revolution Populi","symbol":"RVP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x17ef75aa22dd5f6c2763b8304ab24f40ee54d48a","decimalCount":18}]},{"id":"hector-dao","name":"Hector Finance","symbol":"HEC","active":true,"networks":[{"networkId":"fantom","contractAddress":"0x5c4fdfc5233f935f20d2adba572f770c2e377ab0","decimalCount":9}]},{"id":"peculium-2","name":"Peculium","symbol":"PCL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x1dbdf52915875f749cbaeaaf515252455b623f6e","decimalCount":10}]},{"id":"frontier-token","name":"Frontier","symbol":"FRONT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf8c3527cc04340b208c854e985240c02f7b7793f","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x928e55dab735aa8260af3cedada18b5f70c72f1b","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xa3ed22eee92a3872709823a6970069e12a4540eb","decimalCount":18}]},{"id":"blockport","name":"BUX Token","symbol":"BUX","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x211ffbe424b90e25a15531ca322adf1559779e45","decimalCount":18}]},{"id":"treeb","name":"Retreeb","symbol":"TREEB","active":true,"networks":[{"networkId":"fantom","contractAddress":"0xc60d7067dfbc6f2caf30523a064f416a5af52963","decimalCount":18}]},{"id":"spartacus","name":"Spartacus","symbol":"SPA","active":true,"networks":[{"networkId":"fantom","contractAddress":"0x5602df4a94eb6c680190accfa2a475621e0ddbdc","decimalCount":9}]},{"id":"star-atlas","name":"Star Atlas","symbol":"ATLAS","active":true,"networks":[{"networkId":"solana","contractAddress":"ATLASXmbPQxBUYbxPsV97usA3fPQYEqzQBUHgiFCUsXx","decimalCount":8}]},{"id":"paraswap","name":"ParaSwap","symbol":"PSP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcafe001067cdef266afb7eb5a286dcfd277f3de5","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xcafe001067cdef266afb7eb5a286dcfd277f3de5","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x42d61d766b85431666b39b89c43011f24451bff6","decimalCount":18}]},{"id":"bilira","name":"BiLira","symbol":"TRYB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2c537e5624e4af88a7ae4060c022609376c8d0eb","decimalCount":6},{"networkId":"binance-smart-chain","contractAddress":"0xc1fdbed7dac39cae2ccc0748f7a80dc446f6a594","decimalCount":6},{"networkId":"avalanche","contractAddress":"0x564a341df6c126f90cf3ecb92120fd7190acb401","decimalCount":6}]},{"id":"metronome","name":"Metronome","symbol":"MET","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa3d58c4e56fedcae3a7c43a725aee9a71f0ece4e","decimalCount":18}]},{"id":"unizen","name":"Unizen","symbol":"ZCX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc52c326331e9ce41f04484d3b5e5648158028804","decimalCount":18}]},{"id":"voxies","name":"Voxies","symbol":"VOXEL","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0xd0258a3fd00f38aa8090dfee343f10a9d4d30d3f","decimalCount":18}]},{"id":"fsn","name":"FUSION","symbol":"FSN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x979aca85ba37c675e78322ed5d97fa980b9bdf00","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xfa4fa764f15d0f6e20aaec8e0d696870e5b77c6e","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x2bf9b864cdc97b08b6d79ad4663e71b8ab65c45c","decimalCount":18},{"networkId":"fantom","contractAddress":"0x50eb82cc284e3d35936827023b048106aaecfc5f","decimalCount":18}]},{"id":"freeway-token","name":"Freeway Token","symbol":"FWT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4a7397b0b86bb0f9482a3f4f16de942f04e88702","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x893169619461d3aba810a40b5403c62f27e703f9","decimalCount":18}]},{"id":"ultiledger","name":"Ultiledger","symbol":"ULT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe884cc2795b9c45beeac0607da9539fd571ccf85","decimalCount":18}]},{"id":"selfkey","name":"SelfKey","symbol":"KEY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4cc19356f2d37338b9802aa8e8fc58b0373296e7","decimalCount":18}]},{"id":"litentry","name":"Litentry","symbol":"LIT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb59490ab09a0f526cc7305822ac65f2ab12f9723","decimalCount":18}]},{"id":"dexe","name":"DeXe","symbol":"DEXE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xde4ee8057785a7e8e800db58f9784845a5c2cbd6","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x039cb485212f996a9dbb85a9a75d898f94d38da6","decimalCount":18}]},{"id":"oxygen","name":"Oxygen","symbol":"OXY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x965697b4ef02f0de01384d0d4f9f782b1670c163","decimalCount":6},{"networkId":"solana","contractAddress":"z3dn17yLaGMKffVogeFHQ9zWVcXgqgf3PQnDsNs2g6M","decimalCount":6}]},{"id":"tracer-dao","name":"Tracer DAO","symbol":"TCR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9c4a4204b79dd291d6b6571c5be8bbcd0622f050","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xa72159fc390f0e3c6d415e658264c7c4051e9b87","decimalCount":18}]},{"id":"kryll","name":"KRYLL","symbol":"KRL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x464ebe77c293e473b48cfe96ddcf88fcf7bfdac0","decimalCount":18}]},{"id":"ooki","name":"Ooki","symbol":"OOKI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0de05f6447ab4d22c8827449ee4ba2d5c288379b","decimalCount":18}]},{"id":"math","name":"MATH","symbol":"MATH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x08d967bb0134f2d07f7cfb6e246680c53927dd30","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf218184af829cf2b0019f8e6f0b2423498a36983","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x99f40b01ba9c469193b360f72740e416b17ac332","decimalCount":18}]},{"id":"measurable-data-token","name":"Measurable Data Token","symbol":"MDT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x814e0908b12a99fecf5bc101bb5d0b8b5cdf7d26","decimalCount":18}]},{"id":"apeswap-finance","name":"ApeSwap","symbol":"BANANA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x603c7f932ed1fc6575303d8fb018fdcbb0f39a95","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x5d47baba0d66083c52009271faf3f50dcc01023c","decimalCount":18}]},{"id":"position-token","name":"Position","symbol":"POSI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x5ca42204cdaa70d5c773946e69de942b85ca6706","decimalCount":18}]},{"id":"stafi","name":"Stafi","symbol":"FIS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xef3a930e1ffffacd2fc13434ac81bd278b0ecc8d","decimalCount":18}]},{"id":"moviebloc","name":"MovieBloc","symbol":"MBL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb879da8b24c9b8685de8526cf492e954f165d74b","decimalCount":18}]},{"id":"jade-protocol","name":"Jade Protocol","symbol":"JADE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x7ad7242a99f21aa543f9650a56d141c57e4f6081","decimalCount":9}]},{"id":"parsiq","name":"PARSIQ","symbol":"PRQ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x362bc847a3a9637d3af6624eec853618a43ed7d2","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xd21d29b38374528675c34936bf7d5dd693d2a577","decimalCount":18}]},{"id":"vite","name":"Vite","symbol":"VITE","active":false,"networks":[{"networkId":"ethereum","contractAddress":"0xadd5e881984783dd432f80381fb52f45b53f3e70","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x2794dad4077602ed25a88d03781528d1637898b4","decimalCount":18}]},{"id":"deus-finance-2","name":"DEUS Finance","symbol":"DEUS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xde5ed76e7c05ec5e4572cfc88d1acea165109e44","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xde5ed76e7c05ec5e4572cfc88d1acea165109e44","decimalCount":18},{"networkId":"fantom","contractAddress":"0xde5ed76e7c05ec5e4572cfc88d1acea165109e44","decimalCount":18}]},{"id":"bella-protocol","name":"Bella Protocol","symbol":"BEL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa91ac63d040deb1b7a5e4d4134ad23eb0ba07e14","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x8443f091997f06a61670b735ed92734f5628692f","decimalCount":18}]},{"id":"cow-protocol","name":"CoW Protocol","symbol":"COW","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdef1ca1fb7fbcdc777520aa7f396b4e015f497ab","decimalCount":18}]},{"id":"orca","name":"Orca","symbol":"ORCA","active":true,"networks":[{"networkId":"solana","contractAddress":"orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE","decimalCount":6}]},{"id":"vader-protocol","name":"Vader Protocol","symbol":"VADER","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2602278ee1882889b946eb11dc0e810075650983","decimalCount":18}]},{"id":"solve-care","name":"SOLVE","symbol":"SOLVE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x446c9033e7516d820cc9a2ce2d0b7328b579406f","decimalCount":8}]},{"id":"anj","name":"Aragon Court","symbol":"ANJ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcd62b1c403fa761baadfc74c525ce2b51780b184","decimalCount":18}]},{"id":"global-coin-research","name":"Global Coin Research","symbol":"GCR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6307b25a665efc992ec1c1bc403c38f3ddd7c661","decimalCount":4},{"networkId":"polygon-pos","contractAddress":"0xa69d14d6369e414a32a5c7e729b7afbafd285965","decimalCount":4}]},{"id":"annex","name":"Annex Finance","symbol":"ANN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x98936bde1cf1bff1e7a8012cee5e2583851f2067","decimalCount":18}]},{"id":"bigshortbets","name":"BigShortBets","symbol":"BIGSB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x131157c6760f78f7ddf877c0019eba175ba4b6f6","decimalCount":18}]},{"id":"silo-finance","name":"Silo Finance","symbol":"SILO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6f80310ca7f2c654691d1383149fa1a57d8ab1f8","decimalCount":18}]},{"id":"crabada","name":"Crabada","symbol":"CRA","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0xa32608e873f9ddef944b24798db69d80bbb4d1ed","decimalCount":18}]},{"id":"talken","name":"Talken","symbol":"TALK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcaabcaa4ca42e1d86de1a201c818639def0ba7a7","decimalCount":18}]},{"id":"dextools","name":"DexTools","symbol":"DEXT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfb7b4564402e5500db5bb6d63ae671302777c75a","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xe91a8d2c584ca93c7405f15c22cdfe53c29896e3","decimalCount":18}]},{"id":"catecoin","name":"CateCoin","symbol":"CATE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xe4fae3faa8300810c835970b9187c268f55d998f","decimalCount":9}]},{"id":"yuan-chain-coin","name":"Yuan Chain Coin","symbol":"YCC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x37e1160184f7dd29f00b78c050bf13224780b0b0","decimalCount":8}]},{"id":"netvrk","name":"Netvrk","symbol":"NTVRK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfc0d6cf33e38bce7ca7d89c0e292274031b7157a","decimalCount":18}]},{"id":"btu-protocol","name":"BTU Protocol","symbol":"BTU","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb683d83a532e2cb7dfa5275eed3698436371cc9f","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xfdc26cda2d2440d0e83cd1dee8e8be48405806dc","decimalCount":18}]},{"id":"tor","name":"TOR","symbol":"TOR","active":true,"networks":[{"networkId":"fantom","contractAddress":"0x74e23df9110aa9ea0b6ff2faee01e740ca1c642e","decimalCount":18}]},{"id":"gemma-extending-tech","name":"Gemma Extending Tech","symbol":"GXT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4674672bcddda2ea5300f5207e1158185c944bc0","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x3107c0a1126268ca303f8d99c712392fa596e6d7","decimalCount":18}]},{"id":"seur","name":"sEUR","symbol":"SEUR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd71ecff9342a5ced620049e616c5035f1db98620","decimalCount":18}]},{"id":"polkadex","name":"Polkadex","symbol":"PDEX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf59ae934f6fe444afc309586cc60a84a0f89aaea","decimalCount":18}]},{"id":"terra-virtua-kolect","name":"Terra Virtua Kolect","symbol":"TVK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd084b83c305dafd76ae3e1b4e1f1fe2ecccb3988","decimalCount":18}]},{"id":"xdefi","name":"XDEFI","symbol":"XDEFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x72b886d09c117654ab7da13a14d603001de0b777","decimalCount":18}]},{"id":"compound-chainlink-token","name":"cLINK","symbol":"CLINK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xface851a4921ce59e912d19329929ce6da6eb0c7","decimalCount":8}]},{"id":"pluton","name":"Pluton","symbol":"PLU","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd8912c10681d8b21fd3742244f44658dba12264e","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x7dc0cb65ec6019330a6841e9c274f2ee57a6ca6c","decimalCount":18}]},{"id":"sperax-usd","name":"Sperax USD","symbol":"USDS","active":true,"networks":[{"networkId":"arbitrum-one","contractAddress":"0xd74f5255d557944cf7dd0e45ff521520002d5748","decimalCount":18}]},{"id":"chain-games","name":"Chain Games","symbol":"CHAIN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc4c2614e694cf534d407ee49f8e44d125e4681c4","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x35de111558f691f77f791fb0c08b2d6b931a9d47","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xd55fce7cdab84d84f2ef3f99816d765a2a94a509","decimalCount":18}]},{"id":"derace","name":"DeRace","symbol":"DERC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9fa69536d1cda4a04cfb50688294de75b505a9ae","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x373e768f79c820aa441540d254dca6d045c6d25b","decimalCount":18}]},{"id":"crypterium","name":"Crypterium","symbol":"CRPT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x08389495d7456e1951ddf7c3a1314a4bfb646d8b","decimalCount":18}]},{"id":"banana","name":"Banana","symbol":"BANANA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x94e496474f1725f1c1824cb5bdb92d7691a4f03a","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xbc91347e80886453f3f8bbd6d7ac07c122d87735","decimalCount":18}]},{"id":"revv","name":"REVV","symbol":"REVV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x557b933a7c2c45672b610f8954a3deb39a51a8ca","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x833f307ac507d47309fd8cdd1f835bef8d702a93","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x70c006878a5a50ed185ac4c87d837633923de296","decimalCount":18}]},{"id":"bosagora","name":"BOSAGORA","symbol":"BOA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x746dda2ea243400d5a63e0700f190ab79f06489e","decimalCount":7}]},{"id":"eden","name":"EDEN","symbol":"EDEN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1559fa1b8f28238fd5d76d9f434ad86fd20d1559","decimalCount":18}]},{"id":"airswap","name":"AirSwap","symbol":"AST","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x27054b13b1b798b345b591a4d22e6562d47ea75a","decimalCount":4}]},{"id":"insurace","name":"InsurAce","symbol":"INSUR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x544c42fbb96b39b21df61cf322b5edc285ee7429","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x3192ccddf1cdce4ff055ebc80f3f0231b86a7e30","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x544c42fbb96b39b21df61cf322b5edc285ee7429","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x8a0e8b4b0903929f47c3ea30973940d4a9702067","decimalCount":18}]},{"id":"givingtoservices-svs","name":"GivingToServices SVS","symbol":"SVS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7ca62545a380e7d71f8f5cfa14b9211002075930","decimalCount":18}]},{"id":"alkimi","name":"Alkimi","symbol":"$ADS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3106a0a076bedae847652f42ef07fd58589e001f","decimalCount":18}]},{"id":"platypus-finance","name":"Platypus Finance","symbol":"PTP","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x22d4002028f537599be9f666d1c4fa138522f9c8","decimalCount":18}]},{"id":"cream-2","name":"Cream","symbol":"CREAM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2ba592f78db6436527729929aaf6c908497cb200","decimalCount":18},{"networkId":"fantom","contractAddress":"0x657a1861c15a3ded9af0b6799a195a249ebdcbc6","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xf4d48ce3ee1ac3651998971541badbb9a14d7234","decimalCount":18}]},{"id":"newscrypto-coin","name":"Newscrypto Coin","symbol":"NWC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x968f6f898a6df937fc1859b323ac2f14643e3fed","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x968f6f898a6df937fc1859b323ac2f14643e3fed","decimalCount":18}]},{"id":"step-finance","name":"Step Finance","symbol":"STEP","active":true,"networks":[{"networkId":"solana","contractAddress":"StepAscQoEioFxxWGnh2sLBDFp9d8rvKz2Yp39iDpyT","decimalCount":9}]},{"id":"manifold-finance","name":"Manifold Finance","symbol":"FOLD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd084944d3c05cd115c09d072b9f44ba3e0e45921","decimalCount":18}]},{"id":"bepro-network","name":"BEPRO Network","symbol":"BEPRO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcf3c8be2e2c42331da80ef210e9b1b307c03d36a","decimalCount":18}]},{"id":"star-atlas-dao","name":"Star Atlas DAO","symbol":"POLIS","active":true,"networks":[{"networkId":"solana","contractAddress":"poLisWXnNRwC6oBu1vHiuKQzFjGL4XDSu4g9qjz9qVk","decimalCount":8}]},{"id":"stake-dao","name":"Stake DAO","symbol":"SDT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x73968b9a57c6e53d41345fd57a6e6ae27d6cdb2f","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x361a5a4993493ce00f61c32d4ecca5512b82ce90","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x7ba4a00d54a07461d9db2aef539e91409943adc9","decimalCount":18}]},{"id":"dfx-finance","name":"DFX Finance","symbol":"DFX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x888888435fde8e7d4c54cab67f206e4199454c60","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xe7804d91dfcde7f776c90043e03eaa6df87e6395","decimalCount":18}]},{"id":"the-doge-nft","name":"The Doge NFT","symbol":"DOG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbaac2b4491727d78d2b78815144570b9f2fe8899","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xaa88c603d142c371ea0eac8756123c5805edee03","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xeee3371b89fc43ea970e908536fcddd975135d8a","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x4425742f1ec8d98779690b5a3a6276db85ddc01a","decimalCount":18}]},{"id":"route","name":"Router Protocol","symbol":"ROUTE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x16eccfdbb4ee1a85a33f3a9b21175cd7ae753db4","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x16eccfdbb4ee1a85a33f3a9b21175cd7ae753db4","decimalCount":18}]},{"id":"index-cooperative","name":"Index Cooperative","symbol":"INDEX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0954906da0bf32d5479e25f46056d22f08464cab","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xfbd8a3b908e764dbcd51e27992464b4432a1132b","decimalCount":18}]},{"id":"adappter-token","name":"Adappter Token","symbol":"ADP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc314b0e758d5ff74f63e307a86ebfe183c95767b","decimalCount":18}]},{"id":"ariva","name":"Ariva","symbol":"ARV","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x6679eb24f59dfe111864aec72b443d1da666b360","decimalCount":8}]},{"id":"ramp","name":"RAMP","symbol":"RAMP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x33d0568941c0c64ff7e0fb4fba0b11bd37deed9f","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x8519ea49c997f50ceffa444d240fb655e89248aa","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xaecebfcf604ad245eaf0d5bd68459c3a7a6399c2","decimalCount":18}]},{"id":"dforce-token","name":"dForce Token","symbol":"DF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x431ad2ff6a9c365805ebad47ee021148d6f7dbe0","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xae6aab43c4f3e0cea4ab83752c278f8debaba689","decimalCount":18}]},{"id":"interest-compounding-eth-index","name":"Interest Compounding ETH Index","symbol":"ICETH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7c07f7abe10ce8e33dc6c5ad68fe033085256a84","decimalCount":18}]},{"id":"opendao","name":"OpenDAO","symbol":"SOS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3b484b82567a09e2588a13d54d032153f0c0aee0","decimalCount":18}]},{"id":"urus-token","name":"Aurox Token","symbol":"URUS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc6dddb5bc6e61e0841c54f3e723ae1f3a807260b","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xc6dddb5bc6e61e0841c54f3e723ae1f3a807260b","decimalCount":18}]},{"id":"santiment-network-token","name":"Santiment Network Token","symbol":"SAN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7c5a0ce9267ed19b22f8cae653f198e3e8daf098","decimalCount":18}]},{"id":"marinade","name":"Marinade","symbol":"MNDE","active":true,"networks":[{"networkId":"solana","contractAddress":"MNDEFzGvMt87ueuHvVU9VcTqsAP5b3fTGPsHuuPA5ey","decimalCount":9}]},{"id":"suku","name":"SUKU","symbol":"SUKU","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0763fdccf1ae541a5961815c0872a8c5bc6de4d7","decimalCount":18}]},{"id":"ichi-farm","name":"ICHI","symbol":"ICHI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x903bef1736cddf2a537176cf3c64579c3867a881","decimalCount":9}]},{"id":"0chain","name":"0chain","symbol":"ZCN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb9ef770b6a5e12e45983c5d80545258aa38f3b78","decimalCount":10},{"networkId":"polygon-pos","contractAddress":"0x8bb30e0e67b11b978a5040144c410e1ccddcba30","decimalCount":10}]},{"id":"solanium","name":"Solanium","symbol":"SLIM","active":true,"networks":[{"networkId":"solana","contractAddress":"xxxxa1sKNGwFtw2kFn8XauW9xq8hBZ5kVtcSesTT9fW","decimalCount":6}]},{"id":"numbers-protocol","name":"Numbers Protocol","symbol":"NUM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3496b523e5c00a4b4150d6721320cddb234c3079","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xeceb87cf00dcbf2d4e2880223743ff087a995ad9","decimalCount":18}]},{"id":"delta-exchange-token","name":"Delta Exchange Token","symbol":"DETO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xab93df617f51e1e415b5b4f8111f122d6b48e55c","decimalCount":18}]},{"id":"cryptex-finance","name":"Cryptex Finance","symbol":"CTX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x321c2fe4446c7c963dc41dd58879af648838f98d","decimalCount":18}]},{"id":"lunr-token","name":"Lunr","symbol":"LUNR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa87135285ae208e22068acdbff64b11ec73eaa5a","decimalCount":4},{"networkId":"binance-smart-chain","contractAddress":"0x37807d4fbeb84124347b8899dd99616090d3e304","decimalCount":4}]},{"id":"loot","name":"Lootex","symbol":"LOOT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x721a1b990699ee9d90b6327faad0a3e840ae8335","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x14a9a94e555fdd54c21d7f7e328e61d7ebece54b","decimalCount":18}]},{"id":"xels","name":"XELS","symbol":"XELS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x397deb686c72384fad502a81f4d7fdb89e1f1280","decimalCount":8}]},{"id":"xdai-stake","name":"STAKE","symbol":"STAKE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0ae055097c6d159879521c384f1d2123d1f195e6","decimalCount":18}]},{"id":"angle-protocol","name":"ANGLE","symbol":"ANGLE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x31429d1856ad1377a8a0079410b297e1a9e214c2","decimalCount":18}]},{"id":"stratos","name":"Stratos","symbol":"STOS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x08c32b0726c5684024ea6e141c50ade9690bbdcc","decimalCount":18}]},{"id":"vecrv-dao-yvault","name":"veCRV-DAO yVault","symbol":"YVE-CRVDAO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc5bddf9843308380375a611c18b50fb9341f502a","decimalCount":18}]},{"id":"stackos","name":"StackOS","symbol":"STACK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x56a86d648c435dc707c8405b78e2ae8eb4e60ba4","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x6855f7bb6287f94ddcc8915e37e73a3c9fee5cf3","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x980111ae1b84e50222c8843e3a7a038f36fecd2b","decimalCount":18}]},{"id":"elysia","name":"ELYSIA","symbol":"EL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2781246fe707bb15cee3e5ea354e2154a2877b16","decimalCount":18}]},{"id":"nectar-token","name":"Nectar","symbol":"NEC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcc80c051057b774cd75067dc48f8987c4eb97a5e","decimalCount":18}]},{"id":"gods-unchained","name":"Gods Unchained","symbol":"GODS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xccc8cb5229b0ac8069c51fd58367fd1e622afd97","decimalCount":18}]},{"id":"sportium","name":"Sportium","symbol":"SPRT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x56156fb7860d7eb0b4b1a5356c5354b295194a45","decimalCount":18}]},{"id":"pnetwork","name":"pNetwork","symbol":"PNT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x89ab32156e46f46d02ade3fecbe5fc4243b9aaed","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xdaacb0ab6fb34d24e8a67bfa14bf4d95d4c7af92","decimalCount":18}]},{"id":"vvsp","name":"vVSP","symbol":"VVSP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xba4cfe5741b357fa371b506e5db0774abfecf8fc","decimalCount":18}]},{"id":"altura","name":"Altura","symbol":"ALU","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x8263cd1601fe73c066bf49cc09841f35348e3be0","decimalCount":18}]},{"id":"coin-capsule","name":"Ternoa","symbol":"CAPS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x03be5c903c727ee2c8c4e9bc0acc860cca4715e2","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xffba7529ac181c2ee1844548e6d7061c9a597df4","decimalCount":18}]},{"id":"time-new-bank","name":"Time New Bank","symbol":"TNB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf7920b0768ecb20a123fac32311d07d193381d6f","decimalCount":18}]},{"id":"3x-long-ethereum-token","name":"3X Long Ethereum Token","symbol":"ETHBULL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x871baed4088b863fd6407159f3672d70cd34837d","decimalCount":18}]},{"id":"nfty-token","name":"NFTY Labs","symbol":"NFTY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe1d7c7a4596b038ced2a84bf65b8647271c53208","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x5774b2fc3e91af89f89141eacf76545e74265982","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xcc081220542a60a8ea7963c4f53d522b503272c1","decimalCount":18}]},{"id":"lyra-finance","name":"Lyra Finance","symbol":"LYRA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x01ba67aac7f75f647d94220cc98fb30fcc5105bf","decimalCount":18}]},{"id":"dotmoovs","name":"dotmoovs","symbol":"MOOV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x24ec2ca132abf8f6f8a6e24a1b97943e31f256a7","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x0ebd9537a25f56713e34c45b38f421a1e7191469","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xe46f5128b933e5a6f907fe73ece80059c222db0a","decimalCount":18}]},{"id":"velaspad","name":"VelasPad","symbol":"VLXPAD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb8e3bb633f7276cc17735d86154e0ad5ec9928c0","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xb8e3bb633f7276cc17735d86154e0ad5ec9928c0","decimalCount":18}]},{"id":"unicrypt-2","name":"UniCrypt","symbol":"UNCX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xadb2437e6f65682b85f814fbc12fec0508a7b1d0","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x09a6c44c3947b69e2b45f4d51b67e6a39acfb506","decimalCount":18}]},{"id":"era-swap-token","name":"Era Swap Token","symbol":"ES","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x72108a8cc3254813c6be2f1b77be53e185abfdd9","decimalCount":18}]},{"id":"arianee","name":"Arianee","symbol":"ARIA20","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xedf6568618a00c6f0908bf7758a16f76b6e04af9","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x46f48fbdedaa6f5500993bede9539ef85f4bee8e","decimalCount":18}]},{"id":"everid","name":"Everest","symbol":"ID","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xebd9d99a3982d547c5bb4db7e3b1f9f14b67eb83","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x8ea2526c2373ba3fe1d0987f5db8ac770a42dd51","decimalCount":18}]},{"id":"shabu-shabu","name":"Shabu Shabu","symbol":"KOBE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcb4e8cafeda995da5cedfda5205bd5664a12b848","decimalCount":18}]},{"id":"bridge","name":"Bridge$","symbol":"BRG.X","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x0e2114955023b736fa97d9e2fcde2836d10b7a5c","decimalCount":18}]},{"id":"futureswap","name":"Futureswap","symbol":"FST","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0e192d382a36de7011f795acc4391cd302003606","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x488cc08935458403a0458e45e20c0159c8ab2c92","decimalCount":18}]},{"id":"rss3","name":"RSS3","symbol":"RSS3","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc98d64da73a6616c42117b582e832812e7b8d57f","decimalCount":18}]},{"id":"thorswap","name":"THORSwap","symbol":"THOR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa5f2211b9b8170f694421f2046281775e8468044","decimalCount":18}]},{"id":"neos-credits","name":"Neos Credits","symbol":"NCR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdb5c3c46e28b53a39c255aa39a411dd64e5fed9c","decimalCount":18}]},{"id":"lunar","name":"Lunar","symbol":"LNR","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x9d4451151a8de5b545a1bc6c8fdeb9d94a2868e1","decimalCount":9}]},{"id":"erc20","name":"ERC20","symbol":"ERC20","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc3761eb917cd790b30dad99f6cc5b4ff93c4f9ea","decimalCount":18}]},{"id":"qmall","name":"Qmall","symbol":"QMALL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2217e5921b7edfb4bb193a6228459974010d2198","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x07e551e31a793e20dc18494ff6b03095a8f8ee36","decimalCount":18}]},{"id":"unlend-finance","name":"UniLend Finance","symbol":"UFT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0202be363b8a4820f3f4de7faf5224ff05943ab1","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x2645d5f59d952ef2317c8e0aaa5a61c392ccd44d","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x5b4cf2c120a9702225814e18543ee658c5f8631e","decimalCount":18}]},{"id":"unifi-protocol-dao","name":"Unifi Protocol DAO","symbol":"UNFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x441761326490cacf7af299725b6292597ee822c2","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x728c5bac3c3e370e372fc4671f9ef6916b814d8b","decimalCount":18}]},{"id":"rainicorn","name":"Rainicorn","symbol":"RAINI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xeb953eda0dc65e3246f43dc8fa13f35623bdd5ed","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xeb953eda0dc65e3246f43dc8fa13f35623bdd5ed","decimalCount":18},{"networkId":"fantom","contractAddress":"0xe83dfaaafd3310474d917583ae9633b4f68fb036","decimalCount":18}]},{"id":"paragonsdao","name":"ParagonsDAO","symbol":"PDT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x375abb85c329753b1ba849a601438ae77eec9893","decimalCount":18}]},{"id":"occamfi","name":"OccamFi","symbol":"OCC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2f109021afe75b949429fe30523ee7c0d5b27207","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x2a4dffa1fa0f86ce7f0982f88aecc199fb3476bc","decimalCount":18}]},{"id":"defi-land","name":"DeFi Land","symbol":"DFL","active":true,"networks":[{"networkId":"solana","contractAddress":"DFL1zNkaGPWm1BqAVqRjCZvHmwTFrEaJtbzJWgseoNJh","decimalCount":9}]},{"id":"hackenai","name":"Hacken Token","symbol":"HAI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x05fb86775fd5c16290f1e838f5caaa7342bd9a63","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0xaa9e582e5751d703f85912903bacaddfed26484c","decimalCount":8}]},{"id":"peardao","name":"PearDAO","symbol":"PEX","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x6a0b66710567b6beb81a71f7e9466450a91a384b","decimalCount":18}]},{"id":"inverse-finance","name":"Inverse Finance","symbol":"INV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x41d5d79431a913c4ae7d69a668ecdfe5ff9dfb68","decimalCount":18}]},{"id":"zkspace","name":"ZKSpace","symbol":"ZKS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe4815ae53b124e7263f08dcdbbb757d41ed658c6","decimalCount":18}]},{"id":"trustpad","name":"TrustPad","symbol":"TPAD","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xadcfc6bf853a0a8ad7f9ff4244140d10cf01363c","decimalCount":9}]},{"id":"gifto","name":"Gifto","symbol":"GTO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc5bbae50781be1669306b9e001eff57a2957b09d","decimalCount":5}]},{"id":"hoge-finance","name":"Hoge Finance","symbol":"HOGE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfad45e47083e4607302aa43c65fb3106f1cd7607","decimalCount":9},{"networkId":"binance-smart-chain","contractAddress":"0xa4fffc757e8c4f24e7b209c033c123d20983ad40","decimalCount":9}]},{"id":"trias-token","name":"Trias Token","symbol":"TRIAS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3a856d4effa670c54585a5d523e96513e148e95d","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xa4838122c683f732289805fc3c207febd55babdd","decimalCount":18}]},{"id":"dora-factory","name":"Dora Factory","symbol":"DORA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbc4171f45ef0ef66e76f979df021a34b46dcc81d","decimalCount":18}]},{"id":"tower","name":"Tower","symbol":"TOWER","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1c9922314ed1415c95b9fd453c3818fd41867d0b","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xe7c9c6bc87b86f9e5b57072f907ee6460b593924","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x2bc07124d8dac638e290f401046ad584546bc47b","decimalCount":18}]},{"id":"banano","name":"Banano","symbol":"BAN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xe20b9e246db5a0d21bf9209e4858bc9a3ff7a034","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xe20b9e246db5a0d21bf9209e4858bc9a3ff7a034","decimalCount":18},{"networkId":"fantom","contractAddress":"0xe20b9e246db5a0d21bf9209e4858bc9a3ff7a034","decimalCount":18}]},{"id":"instadapp","name":"Instadapp","symbol":"INST","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6f40d4a6237c257fff2db00fa0510deeecd303eb","decimalCount":18}]},{"id":"veraone","name":"VeraOne","symbol":"VRO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x10bc518c32fbae5e38ecb50a612160571bd81e44","decimalCount":8}]},{"id":"mcdex","name":"MCDEX","symbol":"MCB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4e352cf164e64adcbad318c3a1e222e9eba4ce42","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x5fe80d2cd054645b9419657d3d10d26391780a7b","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x4e352cf164e64adcbad318c3a1e222e9eba4ce42","decimalCount":18}]},{"id":"videocoin","name":"Vivid Labs","symbol":"VID","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2c9023bbc572ff8dc1228c7858a280046ea8c9e5","decimalCount":18},{"networkId":"fantom","contractAddress":"0x922d641a426dcffaef11680e5358f34d97d112e1","decimalCount":18}]},{"id":"town-star","name":"Town Star","symbol":"TOWN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3dd98c8a089dbcff7e8fc8d4f532bd493501ab7f","decimalCount":8}]},{"id":"paid-network","name":"PAID Network","symbol":"PAID","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1614f18fc94f47967a3fbe5ffcd46d4e7da3d787","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xad86d0e9764ba90ddd68747d64bffbd79879a238","decimalCount":18}]},{"id":"gamercoin","name":"GamerCoin","symbol":"GHX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x728f30fa2f100742c7949d1961804fa8e0b1387d","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xbd7b8e4de08d9b01938f7ff2058f110ee1e0e8d4","decimalCount":18}]},{"id":"stakewise","name":"StakeWise","symbol":"SWISE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x48c3399719b582dd63eb5aadf12a40b4c3f52fa2","decimalCount":18}]},{"id":"friends-with-benefits-pro","name":"Friends With Benefits Pro","symbol":"FWB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x35bd01fc9d6d5d81ca9e055db88dc49aa2c699a8","decimalCount":18}]},{"id":"block-ape-scissors","name":"Block Ape Scissors","symbol":"BAS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x8ddeec6b677c7c552c9f3563b99e4ff90b862ebc","decimalCount":18}]},{"id":"switcheo","name":"Carbon Protocol","symbol":"SWTH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb4371da53140417cbb3362055374b10d97e420bb","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0xc0ecb8499d8da2771abcbf4091db7f65158f1468","decimalCount":8}]},{"id":"spool-dao-token","name":"Spool DAO","symbol":"SPOOL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x40803cea2b2a32bda1be61d3604af6a814e70976","decimalCount":18}]},{"id":"beethoven-x","name":"Beethoven X","symbol":"BEETS","active":true,"networks":[{"networkId":"fantom","contractAddress":"0xf24bcf4d1e507740041c9cfd2dddb29585adce1e","decimalCount":18}]},{"id":"refi","name":"Reimagined Finance","symbol":"REFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa808b22ffd2c472ad1278088f16d4010e6a54d5f","decimalCount":18}]},{"id":"swapxi-token","name":"SwapXI","symbol":"SWAPXI","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x312ee43df66d1fd1ea28e5b28f355da84dca13c2","decimalCount":12}]},{"id":"scrooge","name":"Scrooge","symbol":"SCROOGE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xfa1ba18067ac6884fb26e329e60273488a247fc3","decimalCount":18}]},{"id":"one-ledger","name":"OneLedger","symbol":"OLT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x64a60493d888728cf42616e034a0dfeae38efcf0","decimalCount":18}]},{"id":"label-foundation","name":"LABEL Foundation","symbol":"LBL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2162f572b25f7358db9376ab58a947a4e45cede1","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x77edfae59a7948d66e9911a30cc787d2172343d4","decimalCount":18}]},{"id":"shyft-network-2","name":"Shyft Network","symbol":"SHFT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb17c88bda07d28b3838e0c1de6a30eafbcf52d85","decimalCount":18}]},{"id":"goldfinch","name":"Goldfinch","symbol":"GFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdab396ccf3d84cf2d07c4454e10c8a6f5b008d2b","decimalCount":18}]},{"id":"concentrated-voting-power","name":"PowerPool Concentrated Voting Power","symbol":"CVP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x38e4adb44ef08f22f5b5b76a8f0c2d0dcbe7dca1","decimalCount":18}]},{"id":"pbtc35a","name":"pBTC35A","symbol":"PBTC35A","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa8b12cc90abf65191532a12bb5394a714a46d358","decimalCount":18}]},{"id":"coinweb","name":"Coinweb","symbol":"CWEB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x505b5eda5e25a67e1c24a2bf1a527ed9eb88bf04","decimalCount":18}]},{"id":"cellframe","name":"Cellframe","symbol":"CELL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x26c8afbbfe1ebaca03c2bb082e69d0476bffe099","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf3e1449ddb6b218da2c9463d4594ceccc8934346","decimalCount":18}]},{"id":"wasder","name":"Wasder","symbol":"WAS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0c572544a4ee47904d54aaa6a970af96b6f00e1b","decimalCount":18}]},{"id":"byteball","name":"Obyte","symbol":"GBYTE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x31f69de127c8a0ff10819c0955490a4ae46fcc2a","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xeb34de0c4b2955ce0ff1526cdf735c9e6d249d09","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xab5f7a0e20b0d056aed4aa4528c78da45be7308b","decimalCount":18}]},{"id":"enreachdao","name":"EnreachDAO","symbol":"NRCH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x69fa8e7f6bf1ca1fb0de61e1366f7412b827cc51","decimalCount":9},{"networkId":"binance-smart-chain","contractAddress":"0x69fa8e7f6bf1ca1fb0de61e1366f7412b827cc51","decimalCount":9}]},{"id":"lossless","name":"Lossless","symbol":"LSS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3b9be07d622accaed78f479bc0edabfd6397e320","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf7686f43591302cd9b4b9c4fe1291473fae7d9c9","decimalCount":18}]},{"id":"affyn","name":"Affyn","symbol":"FYN","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x3b56a704c01d650147ade2b8cee594066b3f9421","decimalCount":18}]},{"id":"blockchainspace","name":"BlockchainSpace","symbol":"GUILD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x83e9f223e1edb3486f876ee888d76bfba26c475a","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x0565805ca3a4105faee51983b0bd8ffb5ce1455c","decimalCount":18}]},{"id":"metaverse-index","name":"Metaverse Index","symbol":"MVI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x72e364f2abdc788b7e918bc238b21f109cd634d7","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xfe712251173a2cd5f5be2b46bb528328ea3565e1","decimalCount":18}]},{"id":"opulous","name":"Opulous","symbol":"OPUL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x80d55c03180349fff4a229102f62328220a96444","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x686318000d982bc8dcc1cdcf8ffd22322f0960ed","decimalCount":18}]},{"id":"aag-ventures","name":"AAG Ventures","symbol":"AAG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5ba19d656b65f1684cfea4af428c23b9f3628f97","decimalCount":18}]},{"id":"force-protocol","name":"ForTube","symbol":"FOR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1fcdce58959f536621d76f5b7ffb955baa5a672f","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x658a109c5900bc6d2357c87549b651670e5b0539","decimalCount":18}]},{"id":"lazio-fan-token","name":"Lazio Fan Token","symbol":"LAZIO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x77d547256a2cd95f32f67ae0313e450ac200648d","decimalCount":8}]},{"id":"lgcy-network","name":"LGCY Network","symbol":"LGCY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xae697f994fc5ebc000f8e22ebffee04612f98a0d","decimalCount":18}]},{"id":"rich","name":"Rich","symbol":"RCH","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x041e714aa0dce7d4189441896486d361e98bad5f","decimalCount":9}]},{"id":"glitch-protocol","name":"Glitch Protocol","symbol":"GLCH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x038a68ff68c393373ec894015816e33ad41bd564","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf0902eb0049a4003793bab33f3566a22d2834442","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xbe5cf150e1ff59ca7f2499eaa13bfc40aae70e78","decimalCount":18}]},{"id":"bao-finance","name":"Bao Finance","symbol":"BAO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x374cb8c27130e2c9e04f44303f3c8351b9de61c1","decimalCount":18}]},{"id":"sylo","name":"Sylo","symbol":"SYLO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf293d23bf2cdc05411ca0eddd588eb1977e8dcd4","decimalCount":18}]},{"id":"taboo-token","name":"Taboo Token","symbol":"TABOO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x9abdba20edfba06b782126b4d8d72a5853918fd0","decimalCount":9}]},{"id":"foam-protocol","name":"FOAM","symbol":"FOAM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4946fcea7c692606e8908002e55a582af44ac121","decimalCount":18}]},{"id":"outer-ring","name":"Outer Ring","symbol":"GQ","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xf700d4c708c2be1463e355f337603183d20e0808","decimalCount":18}]},{"id":"akropolis","name":"Akropolis","symbol":"AKRO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8ab7404063ec4dbcfd4598215992dc3f8ec853d7","decimalCount":18}]},{"id":"sentivate","name":"Sentivate","symbol":"SNTVT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7865af71cf0b288b4e7f654f4f7851eb46a2b7f8","decimalCount":18}]},{"id":"mithril","name":"Mithril","symbol":"MITH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3893b9422cd5d70a81edeffe3d5a1c6a978310bb","decimalCount":18}]},{"id":"gamestarter","name":"Gamestarter","symbol":"GAME","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd567b5f02b9073ad3a982a099a23bf019ff11d1c","decimalCount":5},{"networkId":"binance-smart-chain","contractAddress":"0x66109633715d2110dda791e64a7b2afadb517abb","decimalCount":5}]},{"id":"sandclock","name":"Sandclock","symbol":"QUARTZ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xba8a621b4a54e61c442f5ec623687e2a942225ef","decimalCount":18}]},{"id":"marketmove","name":"MarketMove","symbol":"MOVE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x231cf6f78620e42fe00d0c5c3088b427f355d01c","decimalCount":9}]},{"id":"aventus","name":"Aventus","symbol":"AVT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0d88ed6e74bbfd96b831231638b66c05571e824f","decimalCount":18}]},{"id":"pallapay","name":"Pallapay","symbol":"PALLA","active":true,"networks":[{"networkId":"tron","contractAddress":"TCfLxS9xHxH8auBL3T8pf3NFTZhsxy4Ncg","decimalCount":8}]},{"id":"sideshift-token","name":"SideShift Token","symbol":"XAI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x35e78b3982e87ecfd5b3f3265b601c046cdbe232","decimalCount":18}]},{"id":"unisocks","name":"Unisocks","symbol":"SOCKS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x23b608675a2b2fb1890d3abbd85c5775c51691d5","decimalCount":18}]},{"id":"alchemist","name":"Alchemist","symbol":"MIST","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x88acdd2a6425c3faae4bc9650fd7e27e0bebb7ab","decimalCount":18}]},{"id":"dragonchain","name":"Dragonchain","symbol":"DRGN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x419c4db4b9e25d6db2ad9691ccb832c8d9fda05e","decimalCount":18}]},{"id":"antimatter","name":"AntiMatter","symbol":"MATTER","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9b99cca871be05119b2012fd4474731dd653febe","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xaaa62d9584cbe8e4d68a43ec91bff4ff1fadb202","decimalCount":18}]},{"id":"bitnautic","name":"BitNautic","symbol":"BTNT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc45dbdf28844fdb1482c502897d433ac08d6ccd0","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xb9c7099d2fbbf82314de08045745daf951cdda85","decimalCount":18}]},{"id":"advertise-coin","name":"Advertise Coin","symbol":"ADCO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb6c3dc857845a713d3531cea5ac546f6767992f4","decimalCount":6}]},{"id":"stader","name":"Stader","symbol":"SD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x30d20208d987713f46dfd34ef128bb16c404d10f","decimalCount":18}]},{"id":"scallop","name":"Scallop","symbol":"SCLP","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xf2c96e402c9199682d5ded26d3771c6b192c01af","decimalCount":18}]},{"id":"paribus","name":"Paribus","symbol":"PBX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd528cf2e081f72908e086f8800977df826b5a483","decimalCount":18}]},{"id":"wliti","name":"wLITI","symbol":"WLITI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0b63128c40737b13647552e0c926bcfeccc35f93","decimalCount":18}]},{"id":"adapad","name":"ADAPad","symbol":"ADAPAD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdb0170e2d0c1cc1b2e7a90313d9b9afa4f250289","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xdb0170e2d0c1cc1b2e7a90313d9b9afa4f250289","decimalCount":18}]},{"id":"ekta-2","name":"Ekta","symbol":"EKTA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2f75113b13d136f861d212fa9b572f2c79ac81c4","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x45808ce43eb2d7685ff0242631f0feb6f3d8701a","decimalCount":18}]},{"id":"rubic","name":"Rubic","symbol":"RBC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa4eed63db85311e22df4473f87ccfc3dadcfa3e3","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x8e3bcc334657560253b83f08331d85267316e08a","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xc3cffdaf8f3fdf07da6d5e3a89b8723d5e385ff8","decimalCount":18}]},{"id":"lit","name":"LIT","symbol":"LIT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc5b3d3231001a776123194cf1290068e8b0c783b","decimalCount":18}]},{"id":"flux-token","name":"FluxProtocol","symbol":"FLX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3ea8ea4237344c9931214796d9417af1a1180770","decimalCount":18}]},{"id":"premia","name":"Premia","symbol":"PREMIA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6399c842dd2be3de30bf99bc7d1bbf6fa3650e70","decimalCount":18},{"networkId":"fantom","contractAddress":"0x3028b4395f98777123c7da327010c40f3c7cc4ef","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x51fc0f6660482ea73330e414efd7808811a57fa2","decimalCount":18}]},{"id":"pawtocol","name":"Pawtocol","symbol":"UPI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x70d2b7c19352bb76e4409858ff5746e500f2b67c","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x0d35a2b85c5a63188d566d104bebf7c694334ee4","decimalCount":18}]},{"id":"v-id-blockchain","name":"VIDT Datalink","symbol":"VIDT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfef4185594457050cc9c23980d301908fe057bb1","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x3f515f0a8e93f2e2f891ceeb3db4e62e202d7110","decimalCount":18}]},{"id":"wpp-token","name":"WPP Token","symbol":"WPP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1955d744f9435522be508d1ba60e3c12d0690b6a","decimalCount":18}]},{"id":"notional-finance","name":"Notional Finance","symbol":"NOTE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcfeaead4947f0705a14ec42ac3d44129e1ef3ed5","decimalCount":8}]},{"id":"electra-protocol","name":"Electra Protocol","symbol":"XEP","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xb897d0a0f68800f8be7d69ffdd1c24b69f57bf3e","decimalCount":8}]},{"id":"gelato","name":"Gelato","symbol":"GEL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x15b7c0c907e4c6b9adaaaabc300c08991d6cea05","decimalCount":18}]},{"id":"oraichain-token","name":"Oraichain Token","symbol":"ORAI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4c11249814f11b9346808179cf06e71ac328c1b5","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xa325ad6d9c92b55a3fc5ad7e412b1518f96441c0","decimalCount":18}]},{"id":"mute","name":"Mute","symbol":"MUTE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa49d7499271ae71cd8ab9ac515e6694c755d400c","decimalCount":18}]},{"id":"kylin-network","name":"Kylin Network","symbol":"KYL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x67b6d479c7bb412c54e03dca8e1bc6740ce6b99c","decimalCount":18}]},{"id":"cake-monster","name":"Cake Monster","symbol":"MONSTA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x8a5d7fcd4c90421d21d30fcc4435948ac3618b2f","decimalCount":18}]},{"id":"opacity","name":"Opacity","symbol":"OPCT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdb05ea0877a2622883941b939f0bb11d1ac7c400","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xce6bf09e5c7a3e65b84f88dcc6475c88d38ba5ef","decimalCount":18}]},{"id":"pangolin","name":"Pangolin","symbol":"PNG","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x60781c2586d68229fde47564546784ab3faca982","decimalCount":18}]},{"id":"proximax","name":"ProximaX","symbol":"XPX","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x6f3aaf802f57d045efdd2ac9c06d8879305542af","decimalCount":6}]},{"id":"mogul-productions","name":"Mogul Productions","symbol":"STARS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc55c2175e90a46602fd42e931f62b3acc1a013ca","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xbd83010eb60f12112908774998f65761cf9f6f9a","decimalCount":18}]},{"id":"magnet-dao","name":"Magnet DAO","symbol":"MAG","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x1d60109178c48e4a937d8ab71699d8ebb6f7c5de","decimalCount":9}]},{"id":"dollars","name":"Dollars","symbol":"USDX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2f6081e3552b1c86ce4479b80062a1dda8ef23e3","decimalCount":9}]},{"id":"straitsx-indonesia-rupiah","name":"XIDR","symbol":"XIDR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xebf2096e01455108badcbaf86ce30b6e5a72aa52","decimalCount":6}]},{"id":"bytz","name":"BYTZ","symbol":"BYTZ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2aad9dbc82611485a52325923e1187734e951b78","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0x586fc153cf7e9c029d8c30842c4cb6a86f03b816","decimalCount":8}]},{"id":"arc","name":"Arc","symbol":"ARC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc82e3db60a52cf7529253b4ec688f631aad9e7c2","decimalCount":18}]},{"id":"compound-wrapped-btc","name":"cWBTC","symbol":"CWBTC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xccf4429db6322d5c611ee964527d42e5d685dd6a","decimalCount":8}]},{"id":"babylon-finance","name":"Babylon Finance","symbol":"BABL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf4dc48d260c93ad6a96c5ce563e70ca578987c74","decimalCount":18}]},{"id":"mint-club","name":"Mint Club","symbol":"MINT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x1f3af095cda17d63cad238358837321e95fc5915","decimalCount":18}]},{"id":"universe-xyz","name":"Universe.XYZ","symbol":"XYZ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x618679df9efcd19694bb1daa8d00718eacfa2883","decimalCount":18}]},{"id":"ethereum-push-notification-service","name":"Ethereum Push Notification Service - EPNS","symbol":"PUSH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf418588522d5dd018b425e472991e52ebbeeeeee","decimalCount":18}]},{"id":"dacxi","name":"Dacxi","symbol":"DACXI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xefab7248d36585e2340e5d25f8a8d243e6e3193f","decimalCount":18}]},{"id":"arcblock","name":"Arcblock","symbol":"ABT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb98d4c97425d9908e66e53a6fdf673acca0be986","decimalCount":18}]},{"id":"apm-coin","name":"apM Coin","symbol":"APM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc8c424b91d8ce0137bab4b832b7f7d154156ba6c","decimalCount":18}]},{"id":"gamium","name":"Gamium","symbol":"GMM","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x5b6bf0c7f989de824677cfbd507d9635965e9cd3","decimalCount":18}]},{"id":"buying","name":"Buying.com","symbol":"BUY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x396ec402b42066864c406d1ac3bc86b575003ed8","decimalCount":2},{"networkId":"binance-smart-chain","contractAddress":"0x40225c6277b29bf9056b4acb7ee1512cbff11671","decimalCount":18}]},{"id":"unicly-cryptopunks-collection","name":"Unicly CryptoPunks Collection","symbol":"UPUNK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8d2bffcbb19ff14a698c424fbcdcfd17aab9b905","decimalCount":18}]},{"id":"sora","name":"Sora","symbol":"XOR","active":false,"networks":[{"networkId":"ethereum","contractAddress":"0x40fd72257597aa14c7231a7b1aaa29fce868f677","decimalCount":18}]},{"id":"88mph","name":"88mph","symbol":"MPH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8888801af4d980682e47f1a9036e589479e835c5","decimalCount":18}]},{"id":"rae-token","name":"Receive Access Ecosystem","symbol":"RAE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe5a3229ccb22b6484594973a03a3851dcd948756","decimalCount":18}]},{"id":"polkafoundry","name":"PolkaFoundry","symbol":"PKF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8b39b70e39aa811b69365398e0aace9bee238aeb","decimalCount":18}]},{"id":"zb-token","name":"ZB Token","symbol":"ZB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbd0793332e9fb844a52a205a233ef27a5b34b927","decimalCount":18}]},{"id":"media-network","name":"Media Network","symbol":"MEDIA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdb726152680ece3c9291f1016f1d36f3995f6941","decimalCount":6},{"networkId":"solana","contractAddress":"ETAtLmCmsoiEEKfNrHKJ2kYy3MoABhU6NQvpSfij5tDs","decimalCount":6}]},{"id":"hollaex-token","name":"HollaEx","symbol":"XHT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd3c625f54dec647db8780dbbe0e880ef21ba4329","decimalCount":18}]},{"id":"o3-swap","name":"O3 Swap","symbol":"O3","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xee9801669c6138e84bd50deb500827b776777d28","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xee9801669c6138e84bd50deb500827b776777d28","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xee9801669c6138e84bd50deb500827b776777d28","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xee9801669c6138e84bd50deb500827b776777d28","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xee9801669c6138e84bd50deb500827b776777d28","decimalCount":18}]},{"id":"tronpad","name":"TRONPAD","symbol":"TRONPAD","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x1bf7aedec439d6bfe38f8f9b20cf3dc99e3571c4","decimalCount":18}]},{"id":"zombie-inu","name":"Zombie Inu","symbol":"ZINU","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc50ef449171a51fbeafd7c562b064b6471c36caa","decimalCount":9},{"networkId":"binance-smart-chain","contractAddress":"0x21f9b5b2626603e3f40bfc13d01afb8c431d382f","decimalCount":9}]},{"id":"signum","name":"Signum","symbol":"SIGNA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x7b0e7e40ee4672599f7095d1ddd730b0805195ba","decimalCount":8}]},{"id":"jupiter","name":"Jupiter","symbol":"JUP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4b1e80cac91e2216eeb63e29b957eb91ae9c2be8","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x0231f91e02debd20345ae8ab7d71a41f8e140ce7","decimalCount":18}]},{"id":"nunet","name":"NuNet","symbol":"NTX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf0d33beda4d734c72684b5f9abbebf715d0a7935","decimalCount":6}]},{"id":"exeedme","name":"Exeedme","symbol":"XED","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xee573a945b01b788b9287ce062a0cfc15be9fd86","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x5621b5a3f4a8008c4ccdd1b942b121c8b1944f1f","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x2fe8733dcb25bfbba79292294347415417510067","decimalCount":18}]},{"id":"pibble","name":"Pibble","symbol":"PIB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1864ce27e9f7517047933caae530674e8c70b8a7","decimalCount":18}]},{"id":"april","name":"April","symbol":"APRIL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xbfea674ce7d16e26e39e3c088810367a708ef94c","decimalCount":18}]},{"id":"neon-exchange","name":"Nash","symbol":"NEX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe2dc070524a6e305ddb64d8513dc444b6a1ec845","decimalCount":8}]},{"id":"ice-token","name":"Popsicle Finance","symbol":"ICE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf16e81dce15b08f326220742020379b855b87df9","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf16e81dce15b08f326220742020379b855b87df9","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x4e1581f01046efdd7a1a2cdb0f82cdd7f71f2e59","decimalCount":18},{"networkId":"fantom","contractAddress":"0xf16e81dce15b08f326220742020379b855b87df9","decimalCount":18}]},{"id":"jones-dao","name":"Jones DAO","symbol":"JONES","active":true,"networks":[{"networkId":"arbitrum-one","contractAddress":"0x10393c20975cf177a3513071bc110f7962cd67da","decimalCount":18}]},{"id":"doge-dash","name":"Doge Dash","symbol":"DOGEDASH","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x7ae5709c585ccfb3e61ff312ec632c21a5f03f70","decimalCount":18}]},{"id":"epik-prime","name":"Epik Prime","symbol":"EPIK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4da0c48376c277cdbd7fc6fdc6936dee3e4adf75","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x368ce786ea190f32439074e8d22e12ecb718b44c","decimalCount":18}]},{"id":"shardus","name":"Shardus","symbol":"ULT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x09617f6fd6cf8a71278ec86e23bbab29c04353a7","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xf0059cc2b3e980065a906940fbce5f9db7ae40a7","decimalCount":18}]},{"id":"werewolf-coin","name":"Werewolf Coin","symbol":"WWC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x38118bdb3b480f570837a4c2e88fac6e83be6689","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x7f13dbb949c48f2a377fa4db4f2d5221ecbf3df9","decimalCount":18}]},{"id":"vector-finance","name":"Vector Finance","symbol":"VTX","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x5817d4f0b62a59b17f75207da1848c2ce75e7af4","decimalCount":18}]},{"id":"blackpool-token","name":"BlackPool","symbol":"BPT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0ec9f76202a7061eb9b3a7d6b59d36215a7e37da","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x6863bd30c9e313b264657b107352ba246f8af8e0","decimalCount":18}]},{"id":"dope-wars-paper","name":"Dope Wars Paper","symbol":"PAPER","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7ae1d57b58fa6411f32948314badd83583ee0e8c","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xc28ea768221f67b6a1fd33e6aa903d4e42f6b177","decimalCount":18}]},{"id":"steam-exchange","name":"Steam Exchange","symbol":"STEAMX","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xc0924edefb2c0c303de2d0c21bff07ab763163b5","decimalCount":9}]},{"id":"stakeborg-dao","name":"Stakeborg DAO","symbol":"STANDARD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xda0c94c73d127ee191955fb46bacd7ff999b2bcd","decimalCount":18}]},{"id":"swftcoin","name":"SWFTCOIN","symbol":"SWFTC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0bb217e40f8a5cb79adf04e1aab60e5abd0dfc1e","decimalCount":8}]},{"id":"kan","name":"BitKan","symbol":"KAN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1410434b0346f5be678d0fb554e5c7ab620f8f4a","decimalCount":18}]},{"id":"kunci-coin","name":"Kunci Coin","symbol":"KUNCI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x6cf271270662be1c4fc1b7bb7d7d7fc60cc19125","decimalCount":6}]},{"id":"ston","name":"Ston","symbol":"STON","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdc47f2ba852669b178699449e50682d6ceaf8c07","decimalCount":18}]},{"id":"vesper-finance","name":"Vesper Finance","symbol":"VSP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1b40183efb4dd766f11bda7a7c3ad8982e998421","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x09c5a4bca808bd1ba2b8e6b3aaf7442046b4ca5b","decimalCount":18},{"networkId":"fantom","contractAddress":"0x461d52769884ca6235b685ef2040f47d30c94eb5","decimalCount":18}]},{"id":"dego-finance","name":"Dego Finance","symbol":"DEGO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x88ef27e69108b2633f8e1c184cc37940a075cc02","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x3fda9383a84c05ec8f7630fe10adf1fac13241cc","decimalCount":18}]},{"id":"floordao","name":"FloorDAO","symbol":"FLOOR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf59257e961883636290411c11ec5ae622d19455e","decimalCount":9}]},{"id":"yearn-lazy-ape","name":"Yearn Lazy Ape","symbol":"YLA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9ba60ba98413a60db4c651d4afe5c937bbd8044b","decimalCount":18}]},{"id":"auto","name":"Auto","symbol":"AUTO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xa184088a740c695e156f91f5cc086a06bb78b827","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x7f426f6dc648e50464a0392e60e1bb465a67e9cf","decimalCount":18}]},{"id":"dose-token","name":"DOSE","symbol":"DOSE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb31ef9e52d94d4120eb44fe1ddfde5b4654a6515","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x7837fd820ba38f95c54d6dac4ca3751b81511357","decimalCount":18}]},{"id":"evolution-finance","name":"Evolution Finance","symbol":"EVN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9af15d7b8776fa296019979e70a5be53c714a7ec","decimalCount":18}]},{"id":"hot-cross","name":"Hot Cross","symbol":"HOTCROSS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4297394c20800e8a38a619a243e9bbe7681ff24e","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x4fa7163e153419e0e1064e418dd7a99314ed27b6","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x2f86508f41310d8d974b76deb3d246c0caa71cf5","decimalCount":18}]},{"id":"lords","name":"LORDS","symbol":"LORDS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x686f2404e77ab0d9070a46cdfb0b7fecdd2318b0","decimalCount":18}]},{"id":"chain-guardians","name":"Chain Guardians","symbol":"CGG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1fe24f25b1cf609b9c4e7e12d802e3640dfa5e43","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x1613957159e9b0ac6c80e824f7eea748a32a0ae2","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x2ab4f9ac80f33071211729e45cfc346c1f8446d5","decimalCount":18}]},{"id":"polkamarkets","name":"Polkamarkets","symbol":"POLK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd478161c952357f05f0292b56012cd8457f1cfbf","decimalCount":18}]},{"id":"splyt","name":"SHOPX","symbol":"SHOPX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7bef710a5759d197ec0bf621c3df802c2d60d848","decimalCount":18}]},{"id":"mork","name":"MORK","symbol":"MORK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf552b656022c218c26dad43ad88881fc04116f76","decimalCount":4}]},{"id":"metasoccer","name":"MetaSoccer","symbol":"MSU","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0xe8377a076adabb3f9838afb77bee96eac101ffb1","decimalCount":18}]},{"id":"vempire-ddao","name":"vEmpire DDAO","symbol":"VEMP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcfeb09c3c5f0f78ad72166d55f9e6e9a60e96eec","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xedf3ce4dd6725650a8e9398e5c6398d061fa7955","decimalCount":18}]},{"id":"media-licensing-token","name":"Media Licensing Token","symbol":"MLT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9506d37f70eb4c3d79c398d326c871abbf10521d","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x4518231a8fdf6ac553b9bbd51bbb86825b583263","decimalCount":18}]},{"id":"openocean","name":"OpenOcean","symbol":"OOE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7778360f035c589fce2f4ea5786cbd8b36e5396b","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x9029fdfae9a03135846381c7ce16595c3554e10a","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x0ebd9537a25f56713e34c45b38f421a1e7191469","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x9d5565da88e596730522cbc5a918d2a89dbc16d9","decimalCount":18},{"networkId":"fantom","contractAddress":"0x9d8f97a3c2f9f397b6d46cbe2d39cc1d8cf19010","decimalCount":18}]},{"id":"blockbank","name":"BlockBank","symbol":"BBANK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf4b5470523ccd314c6b9da041076e7d79e0df267","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf4b5470523ccd314c6b9da041076e7d79e0df267","decimalCount":18}]},{"id":"aladdin-dao","name":"Aladdin DAO","symbol":"ALD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb26c4b3ca601136daf98593feaeff9e0ca702a8d","decimalCount":18}]},{"id":"bomb-money","name":"Bomb Money","symbol":"BOMB","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x522348779dcb2911539e76a1042aa922f9c47ee3","decimalCount":18}]},{"id":"chimaera","name":"XAYA","symbol":"CHI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6dc02164d75651758ac74435806093e421b64605","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0x22648c12acd87912ea1710357b1302c6a4154ebc","decimalCount":8},{"networkId":"polygon-pos","contractAddress":"0xe79feaaa457ad7899357e8e2065a3267ac9ee601","decimalCount":8}]},{"id":"troy","name":"Troy","symbol":"TROY","active":true,"networks":[{"networkId":"binancecoin","contractAddress":"TROY-9B8","decimalCount":8}]},{"id":"saffron-finance","name":"saffron.finance","symbol":"SFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb753428af26e81097e7fd17f40c88aaa3e04902c","decimalCount":18}]},{"id":"blockchain-monster-hunt","name":"Blockchain Monster Hunt","symbol":"BCMC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2ba8349123de45e931a8c8264c332e6e9cf593f9","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xc10358f062663448a3489fc258139944534592ac","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xc10358f062663448a3489fc258139944534592ac","decimalCount":18}]},{"id":"smart-valor","name":"Smart Valor","symbol":"VALOR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x297e4e5e59ad72b1b0a2fd446929e76117be0e0a","decimalCount":18}]},{"id":"radar","name":"Radar","symbol":"RADAR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf9fbe825bfb2bf3e387af0dc18cac8d87f29dea8","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf03a2dc374d494fbe894563fe22ee544d826aa50","decimalCount":18}]},{"id":"blockv","name":"BLOCKv","symbol":"VEE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x340d2bde5eb28c1eed91b2f790723e3b160613b7","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xf1c1a3c2481a3a8a3f173a9ab5ade275292a6fa3","decimalCount":18}]},{"id":"santos-fc-fan-token","name":"Santos FC Fan Token","symbol":"SANTOS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xa64455a4553c9034236734faddaddbb64ace4cc7","decimalCount":8}]},{"id":"poolz-finance","name":"Poolz Finance","symbol":"POOLZ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x69a95185ee2a045cdc4bcd1b1df10710395e4e23","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x77018282fd033daf370337a5367e62d8811bc885","decimalCount":18}]},{"id":"te-food","name":"TE-FOOD","symbol":"TONE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2ab6bb8408ca3199b8fa6c92d5b455f820af03c4","decimalCount":18}]},{"id":"zano","name":"Zano","symbol":"ZANO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdb85f6685950e285b1e611037bebe5b34e2b7d78","decimalCount":18}]},{"id":"hegic","name":"Hegic","symbol":"HEGIC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x584bc13c7d411c00c01a62e8019472de68768430","decimalCount":18},{"networkId":"fantom","contractAddress":"0x44b26e839eb3572c5e959f994804a5de66600349","decimalCount":18}]},{"id":"calo-app","name":"Calo","symbol":"CALO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xb6b91269413b6b99242b1c0bc611031529999999","decimalCount":18}]},{"id":"empire-capital-token","name":"Empire Capital","symbol":"ECC","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xc84d8d03aa41ef941721a4d77b24bb44d7c7ac55","decimalCount":9}]},{"id":"ridotto","name":"Ridotto","symbol":"RDT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4740735aa98dc8aa232bd049f8f0210458e7fca3","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xe9c64384deb0c2bf06d991a8d708c77eb545e3d5","decimalCount":18}]},{"id":"polar-sync","name":"Polar Sync","symbol":"POLAR","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xc64c9b30c981fc2ee4e13d0ca3f08258e725fd24","decimalCount":18}]},{"id":"guild-of-guardians","name":"Guild of Guardians","symbol":"GOG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9ab7bb7fdc60f4357ecfef43986818a2a3569c62","decimalCount":18}]},{"id":"vedao","name":"veDAO","symbol":"WEVE","active":true,"networks":[{"networkId":"fantom","contractAddress":"0x911da02c1232a3c3e1418b834a311921143b04d7","decimalCount":18}]},{"id":"bogged-finance","name":"Bogged Finance","symbol":"BOG","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xb09fe1613fe03e7361319d2a43edc17422f36b09","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xb09fe1613fe03e7361319d2a43edc17422f36b09","decimalCount":18}]},{"id":"raiden-network","name":"Raiden Network Token","symbol":"RDN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x255aa6df07540cb5d3d297f0d0d4d84cb52bc8e6","decimalCount":18}]},{"id":"k21","name":"K21","symbol":"K21","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb9d99c33ea2d86ec5ec6b8a4dd816ebba64404af","decimalCount":18}]},{"id":"strikecoin","name":"StrikeX","symbol":"STRX","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd6fdde76b8c1c45b33790cc8751d5b88984c44ec","decimalCount":18}]},{"id":"fantohm","name":"Fantohm","symbol":"FHM","active":true,"networks":[{"networkId":"fantom","contractAddress":"0xfa1fbb8ef55a4855e5688c0ee13ac3f202486286","decimalCount":9}]},{"id":"pendle","name":"Pendle","symbol":"PENDLE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x808507121b80c02388fad14726482e061b8da827","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xfb98b335551a418cd0737375a2ea0ded62ea213b","decimalCount":18}]},{"id":"polkaswap","name":"Polkaswap","symbol":"PSWAP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x519c1001d550c0a1dae7d1fc220f7d14c2a521bb","decimalCount":18}]},{"id":"mysterium","name":"Mysterium","symbol":"MYST","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4cf89ca06ad997bc732dc876ed2a7f26a9e7f361","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x2ff0b946a6782190c4fe5d4971cfe79f0b6e4df2","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x1379e8886a944d2d9d440b3d88df536aea08d9f3","decimalCount":18}]},{"id":"bread","name":"Bread","symbol":"BRD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x558ec3152e2eb2174905cd19aea4e34a23de9ad6","decimalCount":18}]},{"id":"multivac","name":"MultiVAC","symbol":"MTV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6226e00bcac68b0fe55583b90a1d727c14fab77f","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x8aa688ab789d1848d131c65d98ceaa8875d97ef1","decimalCount":18}]},{"id":"daohaus","name":"DAOhaus","symbol":"HAUS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf2051511b9b121394fa75b8f7d4e7424337af687","decimalCount":18}]},{"id":"usdp","name":"USDP Stablecoin","symbol":"USDP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1456688345527be1f37e9e627da0837d6f08c925","decimalCount":18}]},{"id":"cirus","name":"Cirus","symbol":"CIRUS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa01199c61841fce3b3dafb83fefc1899715c8756","decimalCount":18}]},{"id":"govi","name":"CVI","symbol":"GOVI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xeeaa40b28a2d1b0b08f6f97bb1dd4b75316c6107","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x43df9c0a1156c96cea98737b511ac89d0e2a1f46","decimalCount":18}]},{"id":"moon-nation-game","name":"Moon Nation Game","symbol":"MNG","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x5941f87eb62737ec5ebbecab3e373c40fe40566b","decimalCount":9}]},{"id":"probit-exchange","name":"Probit Token","symbol":"PROB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfb559ce67ff522ec0b9ba7f5dc9dc7ef6c139803","decimalCount":18}]},{"id":"bankless-dao","name":"Bankless DAO","symbol":"BANK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2d94aa3e47d9d5024503ca8491fce9a2fb4da198","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xdb7cb471dd0b49b29cab4a1c14d070f27216a0ab","decimalCount":18}]},{"id":"nftrade","name":"NFTrade","symbol":"NFTD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8e0fe2947752be0d5acf73aae77362daf79cb379","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xac83271abb4ec95386f08ad2b904a46c61777cef","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x9e3ca00f2d4a9e5d4f0add0900de5f15050812cf","decimalCount":18}]},{"id":"cardstack","name":"Cardstack","symbol":"CARD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x954b890704693af242613edef1b603825afcd708","decimalCount":18}]},{"id":"fractal","name":"Fractal","symbol":"FCL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf4d861575ecc9493420a3f5a14f85b13f0b50eb3","decimalCount":18}]},{"id":"polychain-monsters","name":"Polychain Monsters","symbol":"PMON","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1796ae0b0fa4862485106a0de9b654efe301d0b2","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x1796ae0b0fa4862485106a0de9b654efe301d0b2","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x1796ae0b0fa4862485106a0de9b654efe301d0b2","decimalCount":18}]},{"id":"kalmar","name":"Kalmar","symbol":"KALM","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4ba0057f784858a48fe351445c672ff2a3d43515","decimalCount":18}]},{"id":"zmine","name":"ZMINE","symbol":"ZMN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xfcb8a4b1a0b645e08064e05b98e9cc6f48d2aa57","decimalCount":18}]},{"id":"polka-city","name":"Polkacity","symbol":"POLC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaa8330fb2b4d5d07abfe7a72262752a8505c6b37","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x6ae9701b9c423f40d54556c9a443409d79ce170a","decimalCount":18}]},{"id":"vent-finance","name":"Vent Finance","symbol":"VENT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5f0bc16d50f72d10b719dbf6845de2e599eb5624","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x872d068c25511be88c1f5990c53eeffcdf46c9b4","decimalCount":18}]},{"id":"thales","name":"Thales","symbol":"THALES","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8947da500eb47f82df21143d0c01a29862a8c3c5","decimalCount":18}]},{"id":"umbrella-network","name":"Umbrella Network","symbol":"UMB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6fc13eace26590b80cccab1ba5d51890577d83b2","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x846f52020749715f02aef25b5d1d65e48945649d","decimalCount":18}]},{"id":"liquiddriver","name":"LiquidDriver","symbol":"LQDR","active":true,"networks":[{"networkId":"fantom","contractAddress":"0x10b620b2dbac4faa7d7ffd71da486f5d44cd86f9","decimalCount":18}]},{"id":"friesdao","name":"friesDAO","symbol":"FRIES","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfa57f00d948bb6a28072f5416fcbf7836c3d62dd","decimalCount":18}]},{"id":"gold-fever-native-gold","name":"Gold Fever Native Gold","symbol":"NGL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2653891204f463fb2a2f4f412564b19e955166ae","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x0f5d8cd195a4539bcf2ec6118c6da50287c6d5f5","decimalCount":18}]},{"id":"satt","name":"SaTT","symbol":"SATT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdf49c9f599a0a9049d97cff34d0c30e468987389","decimalCount":18}]},{"id":"mobiecoin","name":"MobieCoin","symbol":"MBX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x71ba91dc68c6a206db0a6a92b4b1de3f9271432d","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x064c8e55aa484adbd58ca2d43343ef50137473b7","decimalCount":18}]},{"id":"stacktical","name":"DSLA Protocol","symbol":"DSLA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3affcca64c2a6f4e3b6bd9c64cd2c969efd1ecbe","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x1861c9058577c3b48e73d91d6f25c18b17fbffe0","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xd7c295e399ca928a3a14b01d760e794f1adf8990","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xa0e390e9cea0d0e8cd40048ced9fa9ea10d71639","decimalCount":18},{"networkId":"fantom","contractAddress":"0x25a528af62e56512a19ce8c3cab427807c28cc19","decimalCount":18}]},{"id":"wegro","name":"WeGro","symbol":"WEGRO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd7c5d2a3b7868e6dd539e145c98a565f29ef3fa4","decimalCount":18}]},{"id":"babb","name":"BABB","symbol":"BAX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9a0242b7a33dacbe40edb927834f96eb39f8fbcb","decimalCount":18}]},{"id":"infinity-pad","name":"Infinity Pad","symbol":"IPAD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x36ed7baad9a571b5dad55d096c0ed902188d6d3c","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf07dfc2ad28ab5b09e8602418d2873fcb95e1744","decimalCount":18}]},{"id":"mahadao","name":"MahaDAO","symbol":"MAHA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb4d930279552397bba2ee473229f89ec245bc365","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xedd6ca8a4202d4a36611e2fff109648c4863ae19","decimalCount":18}]},{"id":"anchorswap","name":"AnchorSwap","symbol":"ANCHOR","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4aac18de824ec1b553dbf342829834e4ff3f7a9f","decimalCount":18}]},{"id":"gamee","name":"GAMEE","symbol":"GMEE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd9016a907dc0ecfa3ca425ab20b6b785b42f2373","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x84e9a6f9d240fdd33801f7135908bfa16866939a","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xcf32822ff397ef82425153a9dcb726e5ff61dca7","decimalCount":18}]},{"id":"wom-token","name":"WOM Protocol","symbol":"WOM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbd356a39bff2cada8e9248532dd879147221cf76","decimalCount":18}]},{"id":"ambire-wallet","name":"Ambire Wallet","symbol":"WALLET","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x88800092ff476844f74dc2fc427974bbee2794ae","decimalCount":18}]},{"id":"morpheus-labs","name":"Morpheus Labs","symbol":"MITX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4a527d8fc13c5203ab24ba0944f4cb14658d1db6","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x31042a4e66eda0d12143ffc8cc1552d611da4cba","decimalCount":18}]},{"id":"aldrin","name":"Aldrin","symbol":"RIN","active":true,"networks":[{"networkId":"solana","contractAddress":"E5ndSkaB17Dm7CsD22dvcjfrYSDLCxFcMd6z8ddCk5wp","decimalCount":9}]},{"id":"betu","name":"Betu","symbol":"BETU","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x0df1b3f30865c5b324797f8db9d339514cac4e94","decimalCount":18}]},{"id":"hapi","name":"HAPI","symbol":"HAPI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd9c2d319cd7e6177336b0a9c93c21cb48d84fb54","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xd9c2d319cd7e6177336b0a9c93c21cb48d84fb54","decimalCount":18}]},{"id":"bitcoin-pro","name":"Bitcoin Pro","symbol":"BTCP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x723cbfc05e2cfcc71d3d89e770d32801a5eef5ab","decimalCount":8}]},{"id":"populous","name":"Populous","symbol":"PPT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd4fa1460f537bb9085d22c7bccb5dd450ef28e3a","decimalCount":8}]},{"id":"vfox","name":"VFOX","symbol":"VFOX","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4d61577d8fd2208a0afb814ea089fdeae19ed202","decimalCount":18}]},{"id":"filecoin-standard-full-hashrate","name":"Filecoin Standard Full Hashrate","symbol":"SFIL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x965b85d4674f64422c4898c8f8083187f02b32c0","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0x965b85d4674f64422c4898c8f8083187f02b32c0","decimalCount":8}]},{"id":"credmark","name":"Credmark","symbol":"CMK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x68cfb82eacb9f198d508b514d898a403c449533e","decimalCount":18}]},{"id":"symbiosis-finance","name":"Symbiosis Finance","symbol":"SIS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd38bb40815d2b0c2d2c866e0c72c5728ffc76dd9","decimalCount":18}]},{"id":"ptokens-btc","name":"pTokens BTC","symbol":"PBTC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5228a22e72ccc52d415ecfd199f99d0665e7733b","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xed28a457a5a76596ac48d87c0f577020f6ea1c4c","decimalCount":18}]},{"id":"usd-balance","name":"USD Balance","symbol":"USDB","active":true,"networks":[{"networkId":"fantom","contractAddress":"0x6fc9383486c163fa48becdec79d6058f984f62ca","decimalCount":18}]},{"id":"safemars","name":"Safemars","symbol":"SAFEMARS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x3ad9594151886ce8538c1ff615efa2385a8c3a88","decimalCount":9}]},{"id":"babydoge-coin-eth","name":"BabyDoge ETH","symbol":"BABYDOGE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xac8e13ecc30da7ff04b842f21a62a1fb0f10ebd5","decimalCount":9}]},{"id":"shirtum","name":"Shirtum","symbol":"SHI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x7269d98af4aa705e0b1a5d8512fadb4d45817d5a","decimalCount":18}]},{"id":"ztcoin","name":"ZBG Token","symbol":"ZT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfe39e6a32acd2af7955cb3d406ba2b55c901f247","decimalCount":18}]},{"id":"spiritswap","name":"SpiritSwap","symbol":"SPIRIT","active":true,"networks":[{"networkId":"fantom","contractAddress":"0x5cc61a78f164885776aa610fb0fe1257df78e59b","decimalCount":18}]},{"id":"treasure-under-sea","name":"Treasure Under Sea","symbol":"TUS","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0xf693248f96fe03422fea95ac0afbbbc4a8fdd172","decimalCount":18}]},{"id":"etherisc","name":"Etherisc DIP Token","symbol":"DIP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc719d010b63e5bbf2c0551872cd5316ed26acd83","decimalCount":18}]},{"id":"new-order","name":"New Order","symbol":"NEWO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x98585dfc8d9e7d48f0b1ae47ce33332cf4237d96","decimalCount":18}]},{"id":"the-husl","name":"The HUSL","symbol":"HUSL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa2881f7f441267042f9778ffa0d4f834693426be","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x284ac5af363bde6ef5296036af8fb0e9cc347b41","decimalCount":18}]},{"id":"waltonchain","name":"Waltonchain","symbol":"WTC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb7cb1c96db6b22b0d3d9536e0108d062bd488f74","decimalCount":18}]},{"id":"cache-gold","name":"CACHE Gold","symbol":"CGT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf5238462e7235c7b62811567e63dd17d12c2eaa0","decimalCount":8}]},{"id":"acent","name":"Acent","symbol":"ACE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xec5483804e637d45cde22fa0869656b64b5ab1ab","decimalCount":18}]},{"id":"tokenclub","name":"TokenClub","symbol":"TCT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4824a7b64e3966b0133f4f4ffb1b9d6beb75fff7","decimalCount":18}]},{"id":"darwinia-network-native-token","name":"Darwinia Network Native Token","symbol":"RING","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9469d013805bffb7d3debe5e7839237e535ec483","decimalCount":18}]},{"id":"beekan","name":"BeeKan / Beenews","symbol":"BKBT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6a27348483d59150ae76ef4c0f3622a78b0ca698","decimalCount":18}]},{"id":"kccpad","name":"KCCPad","symbol":"KCCPAD","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x11582ef4642b1e7f0a023804b497656e2663bc9b","decimalCount":18}]},{"id":"acet-token","name":"Acet","symbol":"ACT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x9f3bcbe48e8b754f331dfc694a894e8e686ac31d","decimalCount":18}]},{"id":"realfevr","name":"RealFevr","symbol":"FEVR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9fb83c0635de2e815fd1c21b3a292277540c2e8d","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x82030cdbd9e4b7c5bb0b811a61da6360d69449cc","decimalCount":18}]},{"id":"the-abyss","name":"Abyss","symbol":"ABYSS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0e8d6b471e332f140e7d9dbb99e5e3822f728da6","decimalCount":18}]},{"id":"shill-token","name":"Project SEED SHILL","symbol":"SHILL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xfb9c339b4bace4fe63ccc1dd9a3c3c531441d5fe","decimalCount":18},{"networkId":"solana","contractAddress":"6cVgJUqo4nmvQpbgrDZwyfd6RwWw5bfnCamS3M9N1fd","decimalCount":6}]},{"id":"bifi","name":"BiFi","symbol":"BIFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2791bfd60d232150bff86b39b7146c0eaaa2ba81","decimalCount":18},{"networkId":"fantom","contractAddress":"0xad260f380c9a30b1d60e4548a75010ede630b665","decimalCount":18}]},{"id":"ferrum-network","name":"Ferrum Network","symbol":"FRM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe5caef4af8780e59df925470b050fb23c43ca68c","decimalCount":6},{"networkId":"binance-smart-chain","contractAddress":"0xa719b8ab7ea7af0ddb4358719a34631bb79d15dc","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xe5caef4af8780e59df925470b050fb23c43ca68c","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xd99bafe5031cc8b345cb2e8c80135991f12d7130","decimalCount":18}]},{"id":"vcgamers","name":"VCGamers","symbol":"VCG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1f36fb2d91d9951cf58ae4c1956c0b77e224f1e9","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x1f36fb2d91d9951cf58ae4c1956c0b77e224f1e9","decimalCount":18}]},{"id":"tempus","name":"Tempus","symbol":"TEMP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa36fdbbae3c9d55a1d67ee5821d53b50b63a1ab9","decimalCount":18},{"networkId":"fantom","contractAddress":"0x1c174f6ab0753162befbb916c69def2cc1bfdec1","decimalCount":18}]},{"id":"torum","name":"Torum","symbol":"XTM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcd1faff6e578fa5cac469d2418c95671ba1a62fe","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xcd1faff6e578fa5cac469d2418c95671ba1a62fe","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xe1c42be9699ff4e11674819c1885d43bd92e9d15","decimalCount":18}]},{"id":"metavpad","name":"MetaVPad","symbol":"METAV","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x62858686119135cc00c4a3102b436a0eb314d402","decimalCount":18}]},{"id":"tigercash","name":"TigerCash","symbol":"TCH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9b39a0b97319a9bd5fed217c1db7b030453bac91","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x5ecc4b299e23f526980c33fe35eff531a54aedb1","decimalCount":18}]},{"id":"btc-2x-flexible-leverage-index","name":"BTC 2x Flexible Leverage Index","symbol":"BTC2X-FLI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0b498ff89709d3838a063f1dfa463091f9801c2b","decimalCount":18}]},{"id":"crypto-raiders","name":"Crypto Raiders","symbol":"RAIDER","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0xcd7361ac3307d1c5a46b63086a90742ff44c63b3","decimalCount":18}]},{"id":"julswap","name":"JulSwap","symbol":"JULD","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x5a41f637c3f7553dba6ddc2d3ca92641096577ea","decimalCount":18}]},{"id":"trubadger","name":"TruBadger","symbol":"TRUBGR","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xc003f5193cabe3a6cbb56948dfeaae2276a6aa5e","decimalCount":18}]},{"id":"ethereans","name":"Ethereans","symbol":"OS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6100dd79fcaa88420750dcee3f735d168abcb771","decimalCount":18}]},{"id":"robot","name":"Robot","symbol":"ROBOT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfb5453340c03db5ade474b27e68b6a9c6b2823eb","decimalCount":18}]},{"id":"modefi","name":"Modefi","symbol":"MOD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xea1ea0972fa092dd463f2968f9bb51cc4c981d71","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xd4fbc57b6233f268e7fba3b66e62719d74deecbc","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x8346ab8d5ea7a9db0209aed2d1806afa0e2c4c21","decimalCount":18},{"networkId":"fantom","contractAddress":"0xe64b9fd040d1f9d4715c645e0d567ef69958d3d9","decimalCount":18}]},{"id":"rangers-protocol-gas","name":"Rangers Protocol","symbol":"RPG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0e5c8c387c5eba2ecbc137ad012aed5fe729e251","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xc2098a8938119a52b1f7661893c0153a6cb116d5","decimalCount":18}]},{"id":"databroker-dao","name":"DaTa eXchange Token","symbol":"DTX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x765f0c16d1ddc279295c1a7c24b0883f62d33f75","decimalCount":18}]},{"id":"tontoken","name":"TONToken","symbol":"TON","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6a6c2ada3ce053561c2fbc3ee211f23d9b8c520a","decimalCount":18}]},{"id":"cope","name":"Cope","symbol":"COPE","active":true,"networks":[{"networkId":"solana","contractAddress":"8HGyAAB1yoM1ttS7pXjHMa3dukTFGQggnFFH3hJZgzQh","decimalCount":6}]},{"id":"blocto-token","name":"Blocto","symbol":"BLT","active":true,"networks":[{"networkId":"solana","contractAddress":"BLT1noyNr3GttckEVrtcfC6oyK6yV1DpPgSyXbncMwef","decimalCount":8}]},{"id":"iqeon","name":"IQeon","symbol":"IQN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0db8d8b76bc361bacbb72e2c491e06085a97ab31","decimalCount":18}]},{"id":"realm","name":"Realm","symbol":"REALM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x464fdb8affc9bac185a7393fd4298137866dcfb8","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x464fdb8affc9bac185a7393fd4298137866dcfb8","decimalCount":18}]},{"id":"eqifi","name":"EQIFi","symbol":"EQX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbd3de9a069648c84d27d74d701c9fa3253098b15","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x436c52a8cee41d5e9c5e6f4cb146e66d552fb700","decimalCount":18}]},{"id":"cardstarter","name":"Cardstarter","symbol":"CARDS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3d6f0dea3ac3c607b3998e6ce14b6350721752d9","decimalCount":18}]},{"id":"robonomics-network","name":"Robonomics Network","symbol":"XRT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7de91b204c1c737bcee6f000aaa6569cf7061cb7","decimalCount":9}]},{"id":"bscex","name":"BSCEX","symbol":"BSCX","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x5ac52ee5b2a633895292ff6d8a89bb9190451587","decimalCount":18}]},{"id":"swash","name":"Swash","symbol":"SWASH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa130e3a33a4d84b04c3918c4e5762223ae252f80","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xba3cb8329d442e6f9eb70fafe1e214251df3d275","decimalCount":18}]},{"id":"adora-token","name":"Adora","symbol":"ARA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9ac5c63ddcb93612e316ab31dfc8192bc8961988","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xa9243aeb1e1038273d479436d4f4dece656c62f3","decimalCount":18}]},{"id":"vidya","name":"Vidya","symbol":"VIDYA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3d3d35bb9bec23b06ca00fe472b50e7a4c692c30","decimalCount":18}]},{"id":"cola-token","name":"Cola","symbol":"COLA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x19e98c4921aab7e3f5fd2adca36cfb669c63e926","decimalCount":18}]},{"id":"blockasset","name":"Blockasset","symbol":"BLOCK","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xbc7a566b85ef73f935e640a06b5a8b031cd975df","decimalCount":6}]},{"id":"onston","name":"Onston","symbol":"ONSTON","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x47b9f01b16e9c9cb99191dca68c9cc5bf6403957","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x72bc9d71dd9ad563f52270c6ce5fb30f617c7a1d","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xa4ce4a467e51aefec683a649c3f14427f104667f","decimalCount":18}]},{"id":"internxt","name":"Internxt","symbol":"INXT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4a8f5f96d5436e43112c2fbc6a9f70da9e4e16d4","decimalCount":8}]},{"id":"woofy","name":"Woofy","symbol":"WOOFY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd0660cd418a64a1d44e9214ad8e459324d8157f1","decimalCount":12},{"networkId":"polygon-pos","contractAddress":"0xd0660cd418a64a1d44e9214ad8e459324d8157f1","decimalCount":12},{"networkId":"fantom","contractAddress":"0xd0660cd418a64a1d44e9214ad8e459324d8157f1","decimalCount":12}]},{"id":"crypto-carbon-energy","name":"Crypto Carbon Energy","symbol":"CYCE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xeadd9b69f96140283f9ff75da5fd33bcf54e6296","decimalCount":6}]},{"id":"spartan-protocol-token","name":"Spartan Protocol Token","symbol":"SPARTA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x3910db0600ea925f63c36ddb1351ab6e2c6eb102","decimalCount":18}]},{"id":"ix-swap","name":"IX Swap","symbol":"IXS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x73d7c860998ca3c01ce8c808f5577d94d545d1b4","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x1ba17c639bdaecd8dc4aac37df062d17ee43a1b8","decimalCount":18}]},{"id":"apy-finance","name":"APY.Finance","symbol":"APY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x95a4492f028aa1fd432ea71146b433e7b4446611","decimalCount":18}]},{"id":"connect-financial","name":"Connect Financial","symbol":"CNFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xeabb8996ea1662cad2f7fb715127852cd3262ae9","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x6f5401c53e2769c858665621d22ddbf53d8d27c5","decimalCount":18}]},{"id":"mars4","name":"MARS4","symbol":"MARS4","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x16cda4028e9e872a38acb903176719299beaed87","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x9cd9c5a44cb8fab39b2ee3556f5c439e65e4fddd","decimalCount":18}]},{"id":"sin-city","name":"Sinverse","symbol":"SIN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x6397de0f9aedc0f7a8fa8b438dde883b9c201010","decimalCount":18}]},{"id":"sidus","name":"Sidus","symbol":"SIDUS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x549020a9cb845220d66d3e9c6d9f9ef61c981102","decimalCount":18}]},{"id":"muse-2","name":"Muse DAO","symbol":"MUSE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb6ca7399b4f9ca56fc27cbff44f4d2e4eef1fc81","decimalCount":18}]},{"id":"green-climate-world","name":"Green Climate World","symbol":"WGC","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x1e4ffa373d94c95717fb83ec026b2e0e2f443bb0","decimalCount":16}]},{"id":"uno-re","name":"Uno Re","symbol":"UNO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x474021845c4643113458ea4414bdb7fb74a01a77","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x474021845c4643113458ea4414bdb7fb74a01a77","decimalCount":18}]},{"id":"dify-finance","name":"Dify.Finance","symbol":"YFIII","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4be40bc9681d0a7c24a99b4c92f85b9053fc2a45","decimalCount":18}]},{"id":"spankchain","name":"SpankChain","symbol":"SPANK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x42d6622dece394b54999fbd73d108123806f6a18","decimalCount":18}]},{"id":"unicly-bored-ape-yacht-club-collection","name":"Unicly Bored Ape Yacht Club Collection","symbol":"UAPE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x17e347aad89b30b96557bcbfbff8a14e75cc88a1","decimalCount":18}]},{"id":"ioi-token","name":"IOI","symbol":"IOI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8b3870df408ff4d7c3a26df852d41034eda11d81","decimalCount":6},{"networkId":"binance-smart-chain","contractAddress":"0x959229d94c9060552daea25ac17193bca65d7884","decimalCount":6},{"networkId":"polygon-pos","contractAddress":"0xaf24765f631c8830b5528b57002241ee7eef1c14","decimalCount":6}]},{"id":"wrapped-ampleforth","name":"Wrapped Ampleforth","symbol":"WAMPL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xedb171c18ce90b633db442f2a6f72874093b49ef","decimalCount":18}]},{"id":"dovu","name":"Dovu","symbol":"DOV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xac3211a5025414af2866ff09c23fc18bc97e79b1","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xc9457161320210d22f0d0d5fc1309acb383d4609","decimalCount":18}]},{"id":"boringdao-btc","name":"BoringDAO BTC","symbol":"OBTC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8064d9ae6cdf087b1bcd5bdf3531bd5d8c537a68","decimalCount":18}]},{"id":"creampye","name":"Creampye [OLD]","symbol":"PYE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xaad87f47cdea777faf87e7602e91e3a6afbe4d57","decimalCount":18}]},{"id":"meta","name":"mStable Governance Token: Meta","symbol":"MTA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa3bed4e1c75d00fa6f4e5e6922db7261b5e9acd2","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xf501dd45a1198c2e1b5aef5314a68b9006d842e0","decimalCount":18}]},{"id":"plotx","name":"PlotX","symbol":"PLOT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x72f020f8f3e8fd9382705723cd26380f8d0c66bb","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xe82808eaa78339b06a691fd92e1be79671cad8d3","decimalCount":18}]},{"id":"fibo-token","name":"FibSwap DEX","symbol":"FIBO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x5067c6e9e6c443372f2e62946273abbf3cc2f2b3","decimalCount":9}]},{"id":"planet-finance","name":"Planet Finance","symbol":"AQUA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x72b7d61e8fc8cf971960dd9cfa59b8c829d91991","decimalCount":18}]},{"id":"tokpie","name":"TOKPIE","symbol":"TKP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd31695a1d35e489252ce57b129fd4b1b05e6acac","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x7849ed1447250d0b896f89b58f3075b127ca29b3","decimalCount":18}]},{"id":"gains","name":"Gains","symbol":"GAINS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd9b312d77bc7bed9b9cecb56636300bed4fe5ce9","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xd9ea58350bf120e2169a35fa1afc31975b07de01","decimalCount":18}]},{"id":"dappradar","name":"DappRadar","symbol":"RADAR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x44709a920fccf795fbc57baa433cc3dd53c44dbe","decimalCount":18}]},{"id":"kromatika","name":"Kromatika","symbol":"KROM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3af33bef05c2dcb3c7288b77fe1c8d2aeba4d789","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x14af1f2f02dccb1e43402339099a05a5e363b83c","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x55ff62567f09906a85183b866df84bf599a4bf70","decimalCount":18}]},{"id":"reth2","name":"rETH2","symbol":"RETH2","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x20bc832ca081b91433ff6c17f85701b6e92486c5","decimalCount":18}]},{"id":"gamer","name":"GAMER","symbol":"GMR","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xadca52302e0a6c2d5d68edcdb4ac75deb5466884","decimalCount":18}]},{"id":"dafi-protocol","name":"Dafi Protocol","symbol":"DAFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfc979087305a826c2b2a0056cfaba50aad3e6439","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x4e0fe270b856eebb91fb4b4364312be59f499a3f","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x638df98ad8069a15569da5a6b01181804c47e34c","decimalCount":18}]},{"id":"genre","name":"GENRE","symbol":"GENRE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa392c35ec6900346adec720abe50413f48ee5143","decimalCount":4}]},{"id":"gamma-strategies","name":"Gamma Strategies","symbol":"GAMMA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6bea7cfef803d1e3d5f7c0103f7ded065644e197","decimalCount":18}]},{"id":"charli3","name":"Charli3","symbol":"C3","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf1a91c7d44768070f711c68f33a7ca25c8d30268","decimalCount":18}]},{"id":"oiler","name":"Oiler","symbol":"OIL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0275e1001e293c46cfe158b3702aade0b99f88a5","decimalCount":18}]},{"id":"gyro","name":"Gyro","symbol":"GYRO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x1b239abe619e74232c827fbe5e49a4c072bd869d","decimalCount":9}]},{"id":"dhedge-dao","name":"dHEDGE DAO","symbol":"DHT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xca1207647ff814039530d7d35df0e1dd2e91fa84","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x8c92e38eca8210f4fcbf17f0951b198dd7668292","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x8038f3c971414fd1fc220ba727f2d4a0fc98cb65","decimalCount":18}]},{"id":"cerby-token","name":"Cerby Token","symbol":"CERBY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdef1fac7bf08f173d286bbbdcbeeade695129840","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xdef1fac7bf08f173d286bbbdcbeeade695129840","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xdef1fac7bf08f173d286bbbdcbeeade695129840","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xdef1fac7bf08f173d286bbbdcbeeade695129840","decimalCount":18},{"networkId":"fantom","contractAddress":"0xdef1fac7bf08f173d286bbbdcbeeade695129840","decimalCount":18}]},{"id":"digits-dao","name":"Digits DAO","symbol":"DIGITS","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x18e2269f98db2eda3cfc06e6cca384b291e553d9","decimalCount":18}]},{"id":"revomon","name":"Revomon","symbol":"REVO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x155040625d7ae3e9cada9a73e3e44f76d3ed1409","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x155040625d7ae3e9cada9a73e3e44f76d3ed1409","decimalCount":18}]},{"id":"shopping-io","name":"Shopping.io","symbol":"SPI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9b02dd390a603add5c07f9fd9175b7dabe8d63b7","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x78a18db278f9c7c9657f61da519e6ef43794dd5d","decimalCount":18}]},{"id":"unidex","name":"UniDex","symbol":"UNIDX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x95b3497bbcccc46a8f45f5cf54b0878b39f8d96c","decimalCount":18},{"networkId":"fantom","contractAddress":"0x2130d2a1e51112d349ccf78d2a1ee65843ba36e0","decimalCount":18}]},{"id":"tendieswap","name":"TendieSwap","symbol":"TENDIE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x9853a30c69474bed37595f9b149ad634b5c323d9","decimalCount":18}]},{"id":"phoenix-global","name":"Phoenix Global","symbol":"PHB","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x0409633a72d846fc5bbe2f98d88564d35987904d","decimalCount":18}]},{"id":"salt","name":"SALT","symbol":"SALT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4156d3342d5c385a87d264f90653733592000581","decimalCount":8}]},{"id":"polkabridge","name":"PolkaBridge","symbol":"PBR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x298d492e8c1d909d3f63bc4a36c66c64acb3d695","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x0d6ae2a429df13e44a07cd2969e085e4833f64a0","decimalCount":18}]},{"id":"nebulas","name":"Nebulas","symbol":"NAS","active":false,"networks":[{"networkId":"ethereum","contractAddress":"0x5d65d971895edc438f465c17db6992698a52318d","decimalCount":18}]},{"id":"uncl","name":"UNCL","symbol":"UNCL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2f4eb47a1b1f4488c71fc10e39a4aa56af33dd49","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x0e8d5504bf54d9e44260f8d153ecd5412130cabb","decimalCount":18}]},{"id":"deri-protocol","name":"Deri Protocol","symbol":"DERI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa487bf43cf3b10dffc97a9a744cbb7036965d3b9","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xe60eaf5a997dfae83739e035b005a33afdcc6df5","decimalCount":18}]},{"id":"juggernaut","name":"Juggernaut","symbol":"JGN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x73374ea518de7addd4c2b624c0e8b113955ee041","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xc13b7a43223bb9bf4b69bd68ab20ca1b79d81c75","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x4e3642603a75528489c2d94f86e9507260d3c5a1","decimalCount":18}]},{"id":"gameswap-org","name":"Gameswap","symbol":"GSWAP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaac41ec512808d64625576eddd580e7ea40ef8b2","decimalCount":18}]},{"id":"strong","name":"Strong","symbol":"STRONG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x990f341946a3fdb507ae7e52d17851b87168017c","decimalCount":18}]},{"id":"onooks","name":"Onooks","symbol":"OOKS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x69d9905b2e5f6f5433212b7f3c954433f23c1572","decimalCount":18}]},{"id":"geeq","name":"GEEQ","symbol":"GEEQ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6b9f031d718dded0d681c20cb754f97b3bb81b78","decimalCount":18}]},{"id":"oneswap-dao-token","name":"OneSwap DAO Token","symbol":"ONES","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0b342c51d1592c41068d5d4b4da4a68c0a04d5a4","decimalCount":18}]},{"id":"kira-network","name":"KIRA Network","symbol":"KEX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x16980b3b4a3f9d89e33311b5aa8f80303e5ca4f8","decimalCount":6},{"networkId":"binance-smart-chain","contractAddress":"0x8d11ec38a3eb5e956b052f67da8bdc9bef8abf3e","decimalCount":6}]},{"id":"secret-finance","name":"Secret Finance","symbol":"SEFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x773258b03c730f84af10dfcb1bfaa7487558b8ac","decimalCount":6},{"networkId":"binance-smart-chain","contractAddress":"0xcd95350c69f229e72e57a44e8c05c436e65e4beb","decimalCount":6}]},{"id":"eco-value-coin","name":"Eco Value Coin","symbol":"EVC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaa843f65872a25d6e9552ea0b360fb1d5e333124","decimalCount":18}]},{"id":"tranche-finance","name":"Tranche Finance","symbol":"SLICE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0aee8703d34dd9ae107386d3eff22ae75dd616d1","decimalCount":18}]},{"id":"cumrocket","name":"CumRocket","symbol":"CUMMIES","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x27ae27110350b98d564b9a3eed31baebc82d878d","decimalCount":18}]},{"id":"pinknode","name":"Pinknode","symbol":"PNODE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaf691508ba57d416f895e32a1616da1024e882d2","decimalCount":18}]},{"id":"cap","name":"Cap","symbol":"CAP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x43044f861ec040db59a7e324c40507addb673142","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x031d35296154279dc1984dcd93e392b1f946737b","decimalCount":18}]},{"id":"xfund","name":"xFund","symbol":"XFUND","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x892a6f9df0147e5f079b0993f486f9aca3c87881","decimalCount":9}]},{"id":"tokenomy","name":"Tokenomy","symbol":"TEN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdd16ec0f66e54d453e6756713e533355989040e4","decimalCount":18}]},{"id":"allbridge","name":"Allbridge","symbol":"ABR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa11bd36801d8fa4448f0ac4ea7a62e3634ce8c7c","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x68784ffaa6ff05e3e04575df77960dc1d9f42b4a","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xafc43610c7840b20b90caaf93759be5b54b291c9","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x04429fbb948bbd09327763214b45e505a5293346","decimalCount":18},{"networkId":"fantom","contractAddress":"0x543acd673960041eee1305500893260f1887b679","decimalCount":18}]},{"id":"nft-art-finance","name":"NFT Art Finance","symbol":"NFTART","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xf7844cb890f4c339c497aeab599abdc3c874b67a","decimalCount":9}]},{"id":"deepspace","name":"DEEPSPACE","symbol":"DPS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xf275e1ac303a4c9d987a2c48b8e555a77fec3f1c","decimalCount":9}]},{"id":"jarvis-reward-token","name":"Jarvis Reward Token","symbol":"JRT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8a9c67fee641579deba04928c4bc45f66e26343a","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x596ebe76e2db4470966ea395b0d063ac6197a8c5","decimalCount":18}]},{"id":"unicly","name":"Unicly","symbol":"UNIC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x94e0bab2f6ab1f19f4750e42d7349f2740513ad5","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x21ce5251d47aa72d2d1dc849b1bcce14d2467d1b","decimalCount":18}]},{"id":"drops-ownership-power","name":"Drops Ownership Power","symbol":"DOP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6bb61215298f296c55b19ad842d3df69021da2ef","decimalCount":18}]},{"id":"lamden","name":"Lamden","symbol":"TAU","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x70d7109d3afe13ee8f9015566272838519578c6b","decimalCount":18}]},{"id":"yield-yak","name":"Yield Yak","symbol":"YAK","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x59414b3089ce2af0010e7523dea7e2b35d776ec7","decimalCount":18}]},{"id":"pooltogether","name":"PoolTogether","symbol":"POOL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0cec1a9154ff802e7934fc916ed7ca50bde6844e","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x25788a1a171ec66da6502f9975a15b609ff54cf6","decimalCount":18}]},{"id":"serey-coin","name":"Serey Coin","symbol":"SRY","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x2b618835a1eefcbf41e33497451ca1f3aa62f2d8","decimalCount":18}]},{"id":"xtblock-token","name":"XTblock","symbol":"XTT-B20","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x70b6c6a555507ee4ac91c15e5c80b7dc8ff3b489","decimalCount":18}]},{"id":"hara-token","name":"Hara Token","symbol":"HART","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x52928c95c4c7e934e0efcfab08853a0e4558861d","decimalCount":18}]},{"id":"saveplanetearth","name":"SavePlanetEarth","symbol":"SPE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4ac81e3631dcda62109e3117c4cae7bf70bbbbd2","decimalCount":9}]},{"id":"oxbitcoin","name":"0xBitcoin","symbol":"0XBTC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb6ed7644c69416d67b522e20bc294a9a9b405b31","decimalCount":8},{"networkId":"polygon-pos","contractAddress":"0x71b821aa52a49f32eed535fca6eb5aa130085978","decimalCount":8},{"networkId":"arbitrum-one","contractAddress":"0x7cb16cb78ea464ad35c8a50abf95dff3c9e09d5d","decimalCount":8}]},{"id":"dogebonk","name":"DogeBonk","symbol":"DOBO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xae2df9f730c54400934c06a17462c41c08a06ed8","decimalCount":9}]},{"id":"charg-coin","name":"Charg Coin","symbol":"CHG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc4a86561cb0b7ea1214904f26e6d50fd357c7986","decimalCount":18}]},{"id":"sparkpoint","name":"SparkPoint","symbol":"SRK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0488401c3f535193fa8df029d9ffe615a06e74e6","decimalCount":18}]},{"id":"smart-mfg","name":"Smart MFG","symbol":"MFG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6710c63432a2de02954fc0f851db07146a6c0312","decimalCount":18}]},{"id":"thorstarter","name":"Thorstarter","symbol":"XRUNE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x69fa0fee221ad11012bab0fdb45d444d3d2ce71c","decimalCount":18},{"networkId":"fantom","contractAddress":"0xe1e6b01ae86ad82b1f1b4eb413b219ac32e17bf6","decimalCount":18}]},{"id":"tetu","name":"TETU","symbol":"TETU","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x255707b70bf90aa112006e1b07b9aea6de021424","decimalCount":18},{"networkId":"fantom","contractAddress":"0x65c9d9d080714cda7b5d58989dc27f897f165179","decimalCount":18}]},{"id":"blank","name":"BlockWallet","symbol":"BLANK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x41a3dba3d677e573636ba691a70ff2d606c29666","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xf4c83080e80ae530d6f8180572cbbf1ac9d5d435","decimalCount":18}]},{"id":"cropbytes","name":"CropBytes","symbol":"CBX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x37fc4b48ce93469dbea9918468993c735049642a","decimalCount":18}]},{"id":"sport-and-leisure","name":"Sport and Leisure","symbol":"SNL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa806b3fed6891136940cf81c4085661500aa2709","decimalCount":6}]},{"id":"b-protocol","name":"B.Protocol","symbol":"BPRO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbbbbbbb5aa847a2003fbc6b5c16df0bd1e725f61","decimalCount":18}]},{"id":"pikachu","name":"Pika","symbol":"PIKA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x60f5672a271c7e39e787427a18353ba59a4a3578","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xffb89d7637cf4860884ed48b57ae5562bf64e10f","decimalCount":18}]},{"id":"siren","name":"Siren","symbol":"SI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd23ac27148af6a2f339bd82d0e3cff380b5093de","decimalCount":18}]},{"id":"kine-protocol","name":"Kine Protocol","symbol":"KINE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcbfef8fdd706cde6f208460f2bf39aa9c785f05d","decimalCount":18}]},{"id":"quadrant-protocol","name":"Quadrant Protocol","symbol":"EQUAD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc28e931814725bbeb9e670676fabbcb694fe7df2","decimalCount":18}]},{"id":"duckdaodime","name":"DuckDaoDime","symbol":"DDIM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfbeea1c75e4c4465cb2fccc9c6d6afe984558e20","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xc9132c76060f6b319764ea075973a650a1a53bc9","decimalCount":18}]},{"id":"bedrock","name":"Bedrock","symbol":"ROCK","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xc3387e4285e9f80a7cfdf02b4ac6cdf2476a528a","decimalCount":18}]},{"id":"polydoge","name":"PolyDoge","symbol":"POLYDOGE","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x8a953cfe442c5e8855cc6c61b1293fa648bae472","decimalCount":18}]},{"id":"dogsofelon","name":"Dogs Of Elon","symbol":"DOE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf8e9f10c22840b613cda05a0c5fdb59a4d6cd7ef","decimalCount":18}]},{"id":"wagerr","name":"Wagerr","symbol":"WGR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc237868a9c5729bdf3173dddacaa336a0a5bb6e0","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0xdbf8265b1d5244a13424f13977723acf5395eab2","decimalCount":18}]},{"id":"shibaverse","name":"Shibaverse","symbol":"VERSE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7ae0d42f23c33338de15bfa89c7405c068d9dc0a","decimalCount":18}]},{"id":"jenny-metaverse-dao-token","name":"Jenny Metaverse DAO Token","symbol":"UJENNY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa499648fd0e80fd911972bbeb069e4c20e68bf22","decimalCount":18}]},{"id":"geist-finance","name":"Geist Finance","symbol":"GEIST","active":true,"networks":[{"networkId":"fantom","contractAddress":"0xd8321aa83fb0a4ecd6348d4577431310a6e0814d","decimalCount":18}]},{"id":"bomber-coin","name":"Bomber Coin","symbol":"BCOIN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x00e1656e45f18ec6747f5a8496fd39b50b38396d","decimalCount":18}]},{"id":"arable-protocol","name":"Arable Protocol","symbol":"ACRE","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x00ee200df31b869a321b10400da10b561f3ee60d","decimalCount":18}]},{"id":"gton-capital","name":"GTON CAPITAL","symbol":"GTON","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x01e0e2e61f554ecaaec0cc933e739ad90f24a86d","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x64d5baf5ac030e2b7c435add967f787ae94d0205","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x4e720dd3ac5cfe1e1fbde4935f386bb1c66f4642","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xf480f38c366daac4305dc484b2ad7a496ff00cea","decimalCount":18},{"networkId":"fantom","contractAddress":"0xc1be9a4d5d45beeacae296a7bd5fadbfc14602c4","decimalCount":18}]},{"id":"upbots","name":"UpBots","symbol":"UBXT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8564653879a18c560e7c0ea0e084c516c62f5653","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xbbeb90cfb6fafa1f69aa130b7341089abeef5811","decimalCount":18}]},{"id":"dehub","name":"DeHub","symbol":"DEHUB","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xfc206f429d55c71cb7294eff40c6adb20dc21508","decimalCount":5}]},{"id":"1art","name":"OneArt","symbol":"1ART","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd3c325848d7c6e29b574cb0789998b2ff901f17e","decimalCount":18},{"networkId":"fantom","contractAddress":"0xd3c325848d7c6e29b574cb0789998b2ff901f17e","decimalCount":18}]},{"id":"latoken","name":"LATOKEN","symbol":"LA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe50365f5d679cb98a1dd62d6f6e58e59321bcddf","decimalCount":18}]},{"id":"unix","name":"UniX","symbol":"UNIX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xddd6a0ecc3c6f6c102e5ea3d8af7b801d1a77ac8","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x8c4476dfec8e7eedf2de3e9e9461b7c14c828d46","decimalCount":18}]},{"id":"saud","name":"sAUD","symbol":"SAUD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf48e200eaf9906362bb1442fca31e0835773b8b4","decimalCount":18}]},{"id":"exnetwork-token","name":"ExNetwork Token","symbol":"EXNT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd6c67b93a7b248df608a653d82a100556144c5da","decimalCount":16}]},{"id":"decentral-games-old","name":"Decentral Games (Old)","symbol":"DG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xee06a81a695750e71a662b51066f2c74cf4478a0","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x9fdc3ae5c814b79dca2556564047c5e7e5449c19","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x2a93172c8dccbfbc60a39d56183b7279a2f647b4","decimalCount":18}]},{"id":"unmarshal","name":"Unmarshal","symbol":"MARSH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5a666c7d92e5fa7edcb6390e4efd6d0cdd69cf37","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x2fa5daf6fe0708fbd63b1a7d1592577284f52256","decimalCount":18}]},{"id":"xwin-finance","name":"xWIN Finance","symbol":"XWIN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd88ca08d8eec1e9e09562213ae83a7853ebb5d28","decimalCount":18}]},{"id":"tidal-finance","name":"Tidal Finance","symbol":"TIDAL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x29cbd0510eec0327992cd6006e63f9fa8e7f33b7","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xb41ec2c036f8a42da384dde6ada79884f8b84b26","decimalCount":18}]},{"id":"spheroid-universe","name":"Spheroid Universe","symbol":"SPH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa0cf46eb152656c7090e769916eb44a138aaa406","decimalCount":18}]},{"id":"crust-network","name":"Crust Network","symbol":"CRU","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x32a7c02e79c4ea1008dd6564b35f131428673c41","decimalCount":18}]},{"id":"ispolink","name":"Ispolink","symbol":"ISP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc8807f0f5ba3fa45ffbdc66928d71c5289249014","decimalCount":18}]},{"id":"public-mint","name":"Public Mint","symbol":"MINT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0cdf9acd87e940837ff21bb40c9fd55f68bba059","decimalCount":18}]},{"id":"cashaa","name":"Cashaa","symbol":"CAS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x780207b8c0fdc32cf60e957415bfa1f2d4d9718c","decimalCount":18}]},{"id":"wam","name":"Wam","symbol":"WAM","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xebbaeff6217d22e7744394061d874015709b8141","decimalCount":18}]},{"id":"million","name":"Million","symbol":"MM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6b4c7a5e3f0b99fcd83e9c089bddd6c7fce5c611","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xbf05279f9bf1ce69bbfed670813b7e431142afa4","decimalCount":18}]},{"id":"offshift","name":"Offshift","symbol":"XFT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xabe580e7ee158da464b51ee1a83ac0289622e6be","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xe138c66982fd5c890c60b94fdba1747faf092c20","decimalCount":18}]},{"id":"safemoon-inu","name":"SafeMoon Inu","symbol":"SMI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcd7492db29e2ab436e819b249452ee1bbdf52214","decimalCount":8}]},{"id":"suterusu","name":"Suterusu","symbol":"SUTER","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaa2ce7ae64066175e0b90497ce7d9c190c315db4","decimalCount":18}]},{"id":"nftb","name":"NFTb","symbol":"NFTB","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xde3dbbe30cfa9f437b293294d1fd64b26045c71a","decimalCount":18}]},{"id":"smartmesh","name":"SmartMesh","symbol":"SMT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x21f15966e07a10554c364b988e91dab01d32794a","decimalCount":18}]},{"id":"vulkania","name":"Vulkania [OLD]","symbol":"VLK","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x0921d788e7f7498f80adb0a0a62b8a9476f2db92","decimalCount":8}]},{"id":"bent-finance","name":"Bent Finance","symbol":"BENT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x01597e397605bf280674bf292623460b4204c375","decimalCount":18}]},{"id":"signata","name":"Signata","symbol":"SATA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3ebb4a4e91ad83be51f8d596533818b246f4bee1","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x6b1c8765c7eff0b60706b0ae489eb9bb9667465a","decimalCount":18}]},{"id":"rocket-vault-rocketx","name":"RocketX exchange","symbol":"RVF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdc8af07a7861bedd104b8093ae3e9376fc8596d2","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x872a34ebb2d54af86827810eebc7b9dc6b2144aa","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x2ce13e4199443fdfff531abb30c9b6594446bbc7","decimalCount":18}]},{"id":"rebel-bots","name":"Rebel Bots","symbol":"RBLS","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0xe26cda27c13f4f87cffc2f437c5900b27ebb5bbb","decimalCount":8}]},{"id":"bbs-network","name":"BBS Network","symbol":"BBS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfe459828c90c0ba4bc8b42f5c5d44f316700b430","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xa477a79a118a84a0d371a53c8f46f8ce883ec1dd","decimalCount":18}]},{"id":"fortknoxter","name":"FortKnoxster","symbol":"FKX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x16484d73ac08d2355f466d448d2b79d2039f6ebb","decimalCount":18}]},{"id":"fear","name":"Fear","symbol":"FEAR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x88a9a52f944315d5b4e917b9689e65445c401e83","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x9ba6a67a6f3b21705a46b380a1b97373a33da311","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xa2ca40dbe72028d3ac78b5250a8cb8c404e7fb8c","decimalCount":18}]},{"id":"skey-network","name":"Skey Network","symbol":"SKEY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x06a01a4d579479dd5d884ebf61a31727a3d8d442","decimalCount":8}]},{"id":"bnpl-pay","name":"BNPL Pay","symbol":"BNPL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x84d821f7fbdd595c4c4a50842913e6b1e07d7a53","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x1263fea931b86f3e8ce8afbf29f66631b7be9347","decimalCount":18}]},{"id":"shopperoo","name":"Shopperoo","symbol":"SRO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x8d98a4e36ca048b8e4616564e5a8ebb78895ddff","decimalCount":18}]},{"id":"nifty-league","name":"Nifty League","symbol":"NFTL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3c8d2fce49906e11e71cb16fa0ffeb2b16c29638","decimalCount":18}]},{"id":"gather","name":"Gather","symbol":"GTH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xeb986da994e4a118d5956b02d8b7c3c7ce373674","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xeb986da994e4a118d5956b02d8b7c3c7ce373674","decimalCount":18}]},{"id":"imperium-empires","name":"Imperium Empires","symbol":"IME","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0xf891214fdcf9cdaa5fdc42369ee4f27f226adad6","decimalCount":18}]},{"id":"fiat-dao-token","name":"Fiat DAO","symbol":"FDT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xed1480d12be41d92f36f5f7bdd88212e381a3677","decimalCount":18}]},{"id":"elk-finance","name":"Elk Finance","symbol":"ELK","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0xeeeeeb57642040be42185f49c52f7e9b38f8eeee","decimalCount":18},{"networkId":"fantom","contractAddress":"0xeeeeeb57642040be42185f49c52f7e9b38f8eeee","decimalCount":18}]},{"id":"feisty-doge-nft","name":"Feisty Doge NFT","symbol":"NFD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdfdb7f72c1f195c5951a234e8db9806eb0635346","decimalCount":18}]},{"id":"pacoca","name":"Pacoca","symbol":"PACOCA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x55671114d774ee99d653d6c12460c780a67f1d18","decimalCount":18}]},{"id":"galaxy-fight-club","name":"Galaxy Fight Club","symbol":"GCOIN","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x071ac29d569a47ebffb9e57517f855cb577dcc4c","decimalCount":18}]},{"id":"fancy-games","name":"Fancy Games","symbol":"FNC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7f280dac515121dcda3eac69eb4c13a52392cace","decimalCount":18}]},{"id":"gm","name":"GM","symbol":"GM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbc7250c8c3eca1dfc1728620af835fca489bfdf3","decimalCount":9}]},{"id":"fringe-finance","name":"Fringe Finance","symbol":"FRIN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc9fe6e1c76210be83dc1b5b20ec7fd010b0b1d15","decimalCount":18}]},{"id":"degenerator","name":"Meme","symbol":"MEME","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd5525d397898e5502075ea5e830d8914f6f0affe","decimalCount":8}]},{"id":"decentral-games-ice","name":"Decentral Games ICE","symbol":"ICE","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0xc6c855ad634dcdad23e64da71ba85b8c51e5ad7c","decimalCount":18}]},{"id":"digg","name":"DIGG","symbol":"DIGG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x798d1be841a82a273720ce31c822c61a67a601c3","decimalCount":9}]},{"id":"giveth","name":"Giveth","symbol":"GIV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x900db999074d9277c5da2a43f252d74366230da0","decimalCount":18}]},{"id":"froyo-games","name":"Froyo Games","symbol":"FROYO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xe369fec23380f9f14ffd07a1dc4b7c1a9fdd81c9","decimalCount":18}]},{"id":"trueflip","name":"TrueFlip","symbol":"TFL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa7f976c360ebbed4465c2855684d1aae5271efa9","decimalCount":8}]},{"id":"belt","name":"Belt","symbol":"BELT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xe0e514c71282b6f4e823703a39374cf58dc3ea4f","decimalCount":18}]},{"id":"micropets","name":"MicroPets","symbol":"PETS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xa77346760341460b42c230ca6d21d4c8e743fa9c","decimalCount":18}]},{"id":"shroom-finance","name":"Niftyx Protocol","symbol":"SHROOM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xed0439eacf4c4965ae4613d77a5c2efe10e5f183","decimalCount":18}]},{"id":"divergence-protocol","name":"Divergence Protocol","symbol":"DIVER","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfb782396c9b20e564a64896181c7ac8d8979d5f4","decimalCount":18}]},{"id":"clearpool","name":"Clearpool","symbol":"CPOOL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x66761fa41377003622aee3c7675fc7b5c1c2fac5","decimalCount":18}]},{"id":"solchicks-token","name":"SolChicks","symbol":"CHICKS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xa91c7bc1e07996a188c1a5b1cfdff450389d8acf","decimalCount":8},{"networkId":"solana","contractAddress":"cxxShYRVcepDudXhe7U62QHvw8uBJoKFifmzggGKVC2","decimalCount":9}]},{"id":"strips-finance","name":"Strips Finance","symbol":"STRP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x97872eafd79940c7b24f7bcc1eadb1457347adc9","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x326c33fd1113c1f29b35b4407f3d6312a8518431","decimalCount":18}]},{"id":"gerowallet","name":"GeroWallet","symbol":"GERO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3431f91b3a388115f00c5ba9fdb899851d005fb5","decimalCount":18}]},{"id":"defit","name":"Digital Fitness","symbol":"DEFIT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x84cffa78b2fbbeec8c37391d2b12a04d2030845e","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x428360b02c1269bc1c79fbc399ad31d58c1e8fda","decimalCount":18}]},{"id":"jumptoken","name":"Jump","symbol":"JMPT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x88d7e9b65dc24cf54f5edef929225fc3e1580c25","decimalCount":18}]},{"id":"sonar","name":"Sonar","symbol":"PING","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x5546600f77eda1dcf2e8817ef4d617382e7f71f5","decimalCount":9}]},{"id":"e1337","name":"1337","symbol":"1337","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x35872fea6a4843facbcdbce99e3b69596a3680b8","decimalCount":4}]},{"id":"waves-ducks","name":"Waves Ducks","symbol":"EGG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc2708a3a4ba7f64bddc1a49f92f941bc77cad23a","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x889efce29fa0bb9b26be9fda17a8003f4e8da4de","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x51de72b17c7bd12e9e6d69eb506a669eb6b5249e","decimalCount":18}]},{"id":"suncontract","name":"SunContract","symbol":"SNC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf4134146af2d511dd5ea8cdb1c4ac88c57d60404","decimalCount":18}]},{"id":"naos-finance","name":"NAOS Finance","symbol":"NAOS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4a615bb7166210cce20e6642a6f8fb5d4d044496","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x758d08864fb6cce3062667225ca10b8f00496cc2","decimalCount":18}]},{"id":"etherrock-72","name":"Etherrock #72","symbol":"PEBBLE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdc98c5543f3004debfaad8966ec403093d0aa4a8","decimalCount":18}]},{"id":"lith-token","name":"Lith","symbol":"LITH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf8a4a419c2d7140e49ef952a7e7ae1bd4a8b6b9c","decimalCount":18}]},{"id":"tarot","name":"Tarot","symbol":"TAROT","active":true,"networks":[{"networkId":"fantom","contractAddress":"0xc5e2b037d30a390e62180970b3aa4e91868764cd","decimalCount":18}]},{"id":"biconomy-exchange-token","name":"Biconomy Exchange","symbol":"BIT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xc864019047b864b6ab609a968ae2725dfaee808a","decimalCount":9}]},{"id":"viberate","name":"Viberate","symbol":"VIB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2c974b2d0ba1716e644c1fc59982a89ddd2ff724","decimalCount":18}]},{"id":"faraland","name":"FaraLand","symbol":"FARA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xf4ed363144981d3a65f42e7d0dc54ff9eef559a1","decimalCount":18}]},{"id":"vabble","name":"Vabble","symbol":"VAB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe7ae6d0c56cacaf007b7e4d312f9af686a9e9a04","decimalCount":18}]},{"id":"dexioprotocol","name":"Dexioprotocol","symbol":"DEXI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x29b1e39a529d3b3cacea55989594f71813e998bb","decimalCount":18}]},{"id":"starship","name":"StarShip","symbol":"STARSHIP","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x52419258e3fa44deac7e670eadd4c892b480a805","decimalCount":9}]},{"id":"crowns","name":"Seascape Crowns","symbol":"CWS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xac0104cca91d167873b8601d2e71eb3d4d8c33e0","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xbcf39f0edda668c58371e519af37ca705f2bfcbd","decimalCount":18}]},{"id":"fndz-token","name":"FNDZ","symbol":"FNDZ","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x7754c0584372d29510c019136220f91e25a8f706","decimalCount":18}]},{"id":"dfyn-network","name":"Dfyn Network","symbol":"DFYN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9695e0114e12c0d3a3636fab5a18e6b737529023","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xc168e40227e4ebd8c1cae80f7a55a4f0e6d66c97","decimalCount":18}]},{"id":"lithium-finance","name":"Lithium Finance","symbol":"LITH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x188e817b02e635d482ae4d81e25dda98a97c4a42","decimalCount":18}]},{"id":"xend-finance","name":"Xend Finance","symbol":"XEND","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe4cfe9eaa8cdb0942a80b7bc68fd8ab0f6d44903","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x4a080377f83d669d7bb83b3184a8a5e61b500608","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x86775d0b80b3df266af5377db34ba8f318d715ec","decimalCount":18}]},{"id":"clucoin","name":"CluCoin","symbol":"CLU","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x1162e2efce13f99ed259ffc24d99108aaa0ce935","decimalCount":9}]},{"id":"thorwallet","name":"THORWallet DEX","symbol":"TGT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x108a850856db3f85d0269a2693d896b394c80325","decimalCount":18}]},{"id":"bibox-token","name":"Bibox Token","symbol":"BIX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x009c43b42aefac590c719e971020575974122803","decimalCount":18}]},{"id":"cashbet-coin","name":"CBC.network","symbol":"CBC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x26db5439f651caf491a87d48799da81f191bdb6b","decimalCount":8}]},{"id":"kleekai","name":"KleeKai","symbol":"KLEE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa67e9f021b9d208f7e3365b2a155e3c55b27de71","decimalCount":9}]},{"id":"dinger-token","name":"Dinger","symbol":"DINGER","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9e5bd9d9fad182ff0a93ba8085b664bcab00fa68","decimalCount":9},{"networkId":"binance-smart-chain","contractAddress":"0x0d3843f92d622468ba67df5a6a4149b484a75af3","decimalCount":9}]},{"id":"labs-group","name":"LABS Group","symbol":"LABS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8b0e42f366ba502d787bb134478adfae966c8798","decimalCount":18}]},{"id":"growth-defi","name":"GROWTH DeFi","symbol":"GRO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x336ed56d8615271b38ecee6f4786b55d0ee91b96","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x72699ba15cc734f8db874fa9652c8de12093f187","decimalCount":18},{"networkId":"fantom","contractAddress":"0x91f1430833879272643658f8ed07d60257ddf321","decimalCount":18}]},{"id":"auruscoin","name":"AurusDeFi","symbol":"AWX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa51fc71422a30fa7ffa605b360c3b283501b5bf6","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x56a0efefc9f1fbb54fbd25629ac2aa764f1b56f7","decimalCount":18}]},{"id":"avaocado-dao","name":"Avocado DAO","symbol":"AVG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa41f142b6eb2b164f8164cae0716892ce02f311f","decimalCount":18}]},{"id":"oddz","name":"Oddz","symbol":"ODDZ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcd2828fc4d8e8a0ede91bb38cf64b1a81de65bf6","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xcd40f2670cf58720b694968698a5514e924f742d","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xb0a6e056b587d0a85640b39b1cb44086f7a26a1e","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x4e830f67ec499e69930867f9017aeb5b3f629c73","decimalCount":18}]},{"id":"orclands-metaverse","name":"Orclands Metaverse","symbol":"ORC","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x968f9c44879f67a29b1bfccf93ea82d46a72881f","decimalCount":9}]},{"id":"convergence","name":"Convergence","symbol":"CONV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc834fa996fa3bec7aad3693af486ae53d8aa8b50","decimalCount":18}]},{"id":"freedom-coin","name":"FREEdom coin","symbol":"FREE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2f141ce366a2462f02cea3d12cf93e4dca49e4fd","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x12e34cdf6a031a10fe241864c32fb03a4fdad739","decimalCount":18}]},{"id":"fuel-token","name":"Jetfuel Finance","symbol":"FUEL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x2090c8295769791ab7a3cf1cc6e0aa19f35e441a","decimalCount":18}]},{"id":"minds","name":"Minds","symbol":"MINDS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb26631c6dda06ad89b93c71400d25692de89c068","decimalCount":18}]},{"id":"dragon-crypto-aurum","name":"Dragon Crypto Aurum","symbol":"DCAU","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x100cc3a819dd3e8573fd2e46d1e66ee866068f30","decimalCount":18}]},{"id":"uniwhales","name":"UniWhales","symbol":"UWL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdbdd6f355a37b94e6c7d32fef548e98a280b8df5","decimalCount":18}]},{"id":"apwine","name":"APWine","symbol":"APW","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4104b135dbc9609fc1a9490e61369036497660c8","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x6c0ab120dbd11ba701aff6748568311668f63fe0","decimalCount":18}]},{"id":"lua-token","name":"LuaSwap","symbol":"LUA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb1f66997a5760428d3a87d68b90bfe0ae64121cc","decimalCount":18}]},{"id":"niob","name":"NIOB","symbol":"NIOB","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x5ac5e6af46ef285b3536833e65d245c49b608d9b","decimalCount":18}]},{"id":"oxbull-tech","name":"Oxbull Tech","symbol":"OXB","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x3fd5b5746315e3f8d43a46b09c826a001ebb977d","decimalCount":9}]},{"id":"league-of-ancients","name":"League of Ancients","symbol":"LOA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x94b69263fca20119ae817b6f783fc0f13b02ad50","decimalCount":18}]},{"id":"armor","name":"ARMOR","symbol":"ARMOR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1337def16f9b486faed0293eb623dc8395dfe46a","decimalCount":18}]},{"id":"tokencard","name":"Monolith","symbol":"TKN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaaaf91d9b90df800df4f55c205fd6989c977e73a","decimalCount":8}]},{"id":"waterfall-governance-token","name":"Waterfall Governance","symbol":"WTF","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd73f32833b6d5d9c8070c23e599e283a3039823c","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x873801ae2ff12d816db9a7b082f5796bec64c82c","decimalCount":18}]},{"id":"autobahn-network","name":"Autobahn Network","symbol":"TXL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8eef5a82e6aa222a60f009ac18c24ee12dbf4b41","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x1ffd0b47127fdd4097e54521c9e2c7f0d66aafc5","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x8eef5a82e6aa222a60f009ac18c24ee12dbf4b41","decimalCount":18}]},{"id":"opium","name":"Opium","symbol":"OPIUM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x888888888889c00c67689029d7856aac1065ec11","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x566cedd201f67e542a6851a2959c1a449a041945","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xe8f157e041df3b28151b667364e9c90789da7923","decimalCount":18}]},{"id":"zodium","name":"Zodium","symbol":"ZODI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x0cca2f5561bb0fca88e5b9b48b7fbf000349c357","decimalCount":18}]},{"id":"curate","name":"Curate","symbol":"XCUR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe1c7e30c42c24582888c758984f6e382096786bd","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0xd52669712f253cd6b2fe8a8638f66ed726cb770c","decimalCount":8}]},{"id":"wall-street-bets-dapp","name":"WallStreetBets DApp","symbol":"WSB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe1590a6fa0cff9c960181cb77d8a873601772f64","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x22168882276e5d5e1da694343b41dd7726eeb288","decimalCount":18}]},{"id":"launchpool","name":"Launchpool","symbol":"LPOOL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6149c26cd2f7b5ccdb32029af817123f6e37df5b","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xcfb24d3c3767364391340a2e6d99c64f1cbd7a3d","decimalCount":18}]},{"id":"equos-origin","name":"EQO","symbol":"EQO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x46e9fe43470fafd690100c86037f9e566e24d480","decimalCount":18}]},{"id":"maximizer","name":"Maximizer","symbol":"MAXI","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x7c08413cbf02202a1c13643db173f2694e0f73f0","decimalCount":9}]},{"id":"covesting","name":"Covesting","symbol":"COV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xada86b1b313d1d5267e3fc0bb303f0a2b66d0ea7","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x0f237db17aa4e6de062e6f052bd9c805789b01c3","decimalCount":18}]},{"id":"kommunitas","name":"Kommunitas","symbol":"KOM","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x471ea49dd8e60e697f4cac262b5fafcc307506e4","decimalCount":8},{"networkId":"polygon-pos","contractAddress":"0xc004e2318722ea2b15499d6375905d75ee5390b8","decimalCount":8}]},{"id":"blocksquare","name":"Blocksquare","symbol":"BST","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x509a38b7a1cc0dcd83aa9d06214663d9ec7c7f4a","decimalCount":18}]},{"id":"vera","name":"Vera","symbol":"VERA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd7f0cc50ad69408ae58be033f4f85d2367c2e468","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x4a0a3902e091cdb3aec4279a6bfac50297f0a79e","decimalCount":18}]},{"id":"dogegf","name":"DogeGF","symbol":"DOGEGF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfb130d93e49dca13264344966a611dc79a456bc5","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x0e7252706393470ffb0629da2caa39fc9340f2d4","decimalCount":18}]},{"id":"zeroswap","name":"ZeroSwap","symbol":"ZEE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2edf094db69d6dcd487f1b3db9febe2eec0dd4c5","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x44754455564474a89358b2c2265883df993b12f0","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xfd4959c06fbcc02250952daebf8e0fb38cf9fd8c","decimalCount":18}]},{"id":"moeda-loyalty-points","name":"Moeda Loyalty Points","symbol":"MDA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x51db5ad35c671a87207d88fc11d593ac0c8415bd","decimalCount":18}]},{"id":"locgame","name":"LOCGame","symbol":"LOCG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x60eb57d085c59932d5faa6c6026268a4386927d0","decimalCount":18}]},{"id":"pointpay","name":"PointPay","symbol":"PXP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x95aa5d2dbd3c16ee3fdea82d5c6ec3e38ce3314f","decimalCount":18}]},{"id":"monsta-infinite","name":"Monsta Infinite","symbol":"MONI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x9573c88ae3e37508f87649f87c4dd5373c9f31e0","decimalCount":18}]},{"id":"warden","name":"Warden","symbol":"WAD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0b6f3c17e1626a7cbfa4302ce4e3c45522d23a83","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x0feadcc3824e7f3c12f40e324a60c23ca51627fc","decimalCount":18}]},{"id":"burency","name":"Burency","symbol":"BUY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x31fdd1c6607f47c14a2821f599211c67ac20fa96","decimalCount":18}]},{"id":"idavoll-network","name":"Idavoll DAO","symbol":"IDV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x92ec47df1aa167806dfa4916d9cfb99da6953b8f","decimalCount":18}]},{"id":"gro-dao-token","name":"Gro DAO","symbol":"GRO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3ec8798b81485a254928b70cda1cf0a2bb0b74d7","decimalCount":18}]},{"id":"wabi","name":"Wabi","symbol":"WABI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x286bda1413a2df81731d4930ce2f862a35a609fe","decimalCount":18}]},{"id":"euler-tools","name":"Euler Tools","symbol":"EULER","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x3920123482070c1a2dff73aad695c60e7c6f6862","decimalCount":18}]},{"id":"charged-particles","name":"Charged Particles","symbol":"IONX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x02d3a27ac3f55d5d91fb0f52759842696a864217","decimalCount":18}]},{"id":"bondly","name":"Bondly","symbol":"BONDLY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x91dfbee3965baaee32784c2d546b7a0c62f268c9","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x5d0158a5c3ddf47d4ea4517d8db0d76aa2e87563","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x64ca1571d1476b7a21c5aaf9f1a750a193a103c0","decimalCount":18}]},{"id":"spacechain-erc-20","name":"SpaceChain (ERC-20)","symbol":"SPC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x86ed939b500e121c0c5f493f399084db596dad20","decimalCount":18}]},{"id":"plastiks","name":"Plastiks","symbol":"PLASTIK","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x2764be4756fec8de911d8d37efe4ae8aff178254","decimalCount":9}]},{"id":"usechain","name":"Usechain","symbol":"USE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd9485499499d66b175cf5ed54c0a19f1a6bcb61a","decimalCount":18}]},{"id":"spendcoin","name":"Spendcoin","symbol":"SPND","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xddd460bbd9f79847ea08681563e8a9696867210c","decimalCount":18}]},{"id":"binamon","name":"Binamon","symbol":"BMON","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x08ba0619b1e7a582e0bce5bbe9843322c954c340","decimalCount":18}]},{"id":"acryptos","name":"ACryptoS","symbol":"ACS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4197c6ef3879a08cd51e5560da5064b773aa1d29","decimalCount":18}]},{"id":"lambda","name":"Lambda","symbol":"LAMB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8971f9fd7196e5cee2c1032b50f656855af7dd26","decimalCount":18}]},{"id":"all-sports","name":"All Sports","symbol":"SOC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2d0e95bd4795d7ace0da3c0ff7b706a5970eb9d3","decimalCount":18}]},{"id":"impossible-finance","name":"Impossible Finance","symbol":"IF","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xb0e1fc65c1a741b4662b813eb787d369b8614af1","decimalCount":18}]},{"id":"verisafe","name":"VeriSafe","symbol":"VSF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xac9ce326e95f51b5005e9fe1dd8085a01f18450c","decimalCount":18}]},{"id":"kattana","name":"Kattana","symbol":"KTN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x491e136ff7ff03e6ab097e54734697bb5802fc1c","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xdae6c2a48bfaa66b43815c5548b10800919c993e","decimalCount":18}]},{"id":"pegaxy-stone","name":"Pegaxy Stone","symbol":"PGX","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0xc1c93d475dc82fe72dbc7074d55f5a734f8ceeae","decimalCount":18}]},{"id":"dimitra","name":"Dimitra","symbol":"DMTR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x51cb253744189f11241becb29bedd3f1b5384fdb","decimalCount":18}]},{"id":"medical-token-currency","name":"Doc.com","symbol":"MTC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x905e337c6c8645263d3521205aa37bf4d034e745","decimalCount":18}]},{"id":"cleardao","name":"ClearDAO","symbol":"CLH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd7d8f3b8bc8bc48d3acc37879eaba7b85889fa52","decimalCount":18}]},{"id":"cybermiles","name":"CyberMiles","symbol":"CMT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf85feea2fdd81d51177f6b8f35f0e6734ce45f5f","decimalCount":18}]},{"id":"smartcredit-token","name":"SmartCredit Token","symbol":"SMARTCREDIT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x72e9d9038ce484ee986fea183f8d8df93f9ada13","decimalCount":18}]},{"id":"epik-protocol","name":"EpiK Protocol","symbol":"EPK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdaf88906ac1de12ba2b1d2f7bfc94e9638ac40c4","decimalCount":18}]},{"id":"pathdao","name":"PathDAO","symbol":"PATH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2a2550e0a75acec6d811ae3930732f7f3ad67588","decimalCount":18}]},{"id":"rio-defi","name":"RioDeFi","symbol":"RFUEL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaf9f549774ecedbd0966c52f250acc548d3f36e5","decimalCount":18}]},{"id":"gaia-everworld","name":"Gaia Everworld","symbol":"GAIA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x347e430b7cd1235e216be58ffa13394e5009e6e2","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x723b17718289a91af252d616de2c77944962d122","decimalCount":18}]},{"id":"unslashed-finance","name":"Unslashed Finance","symbol":"USF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe0e05c43c097b0982db6c9d626c4eb9e95c3b9ce","decimalCount":18}]},{"id":"hyve","name":"Hyve","symbol":"HYVE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd794dd1cada4cf79c9eebaab8327a1b0507ef7d4","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf6565a97dc832d93dc83b75ee9aa5c7e8ecb0f9d","decimalCount":18}]},{"id":"gunstar-metaverse","name":"Gunstar Metaverse","symbol":"GST","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x7edc0ec89f987ecd85617b891c44fe462a325869","decimalCount":18}]},{"id":"csp-dao-network","name":"CSP DAO Network","symbol":"NEBO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7f0c8b125040f707441cad9e5ed8a8408673b455","decimalCount":18}]},{"id":"openanx","name":"OAX","symbol":"OAX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x701c244b988a513c945973defa05de933b23fe1d","decimalCount":18}]},{"id":"dark-frontiers","name":"Dark Frontiers","symbol":"DARK","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x12fc07081fab7de60987cad8e8dc407b606fb2f8","decimalCount":8}]},{"id":"billionhappiness","name":"BillionHappiness","symbol":"BHC","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x6fd7c98458a943f469e1cf4ea85b173f5cd342f4","decimalCount":18}]},{"id":"revenue-coin","name":"Revenue Coin","symbol":"RVC","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xbcbdecf8e76a5c32dba69de16985882ace1678c6","decimalCount":18}]},{"id":"amepay","name":"AME Chain","symbol":"AME","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x12513335ffd5dafc2334e98625d27c1ca84bff86","decimalCount":18}]},{"id":"bitspawn","name":"Bitspawn","symbol":"SPWN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe516d78d784c77d479977be58905b3f2b1111126","decimalCount":18}]},{"id":"ripio-credit-network","name":"Ripio Credit Network","symbol":"RCN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf970b8e36e23f7fc3fd752eea86f8be8d83375a6","decimalCount":18}]},{"id":"botto","name":"Botto","symbol":"BOTTO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9dfad1b7102d46b1b197b90095b5c4e9f5845bba","decimalCount":18}]},{"id":"bnktothefuture","name":"BnkToTheFuture","symbol":"BFT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x01ff50f8b7f74e4f00580d9596cd3d0d6d6e326f","decimalCount":18}]},{"id":"par-stablecoin","name":"Parallel","symbol":"PAR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x68037790a0229e9ce6eaa8a99ea92964106c4703","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xe2aa7db6da1dae97c5f5c6914d285fbfcc32a128","decimalCount":18},{"networkId":"fantom","contractAddress":"0x13082681e8ce9bd0af505912d306403592490fc7","decimalCount":18}]},{"id":"honest-mining","name":"Honest","symbol":"HNST","active":true,"networks":[{"networkId":"binancecoin","contractAddress":"HNST-3C9","decimalCount":8}]},{"id":"enterdao","name":"EnterDAO","symbol":"ENTR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd779eea9936b4e323cddff2529eb6f13d0a4d66e","decimalCount":18}]},{"id":"lympo","name":"Lympo","symbol":"LYM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc690f7c7fcffa6a82b79fab7508c466fefdfc8c5","decimalCount":18}]},{"id":"inventoryclub","name":"InventoryClub","symbol":"VNT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe912b8ba2513d7e29b7b2e5b14398dbf77503fb4","decimalCount":18}]},{"id":"liquidus","name":"Liquidus","symbol":"LIQ","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xc7981767f644c7f8e483dabdc413e8a371b83079","decimalCount":18}]},{"id":"enjinstarter","name":"Enjinstarter","symbol":"EJS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x96610186f3ab8d73ebee1cf950c750f3b1fb79c2","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x09f423ac3c9babbff6f94d372b16e4206e71439f","decimalCount":18}]},{"id":"solace","name":"SOLACE","symbol":"SOLACE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x501ace9c35e60f03a2af4d484f49f9b1efde9f40","decimalCount":18}]},{"id":"xeta-reality","name":"Xeta Reality","symbol":"XETA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x179960442ece8de9f390011b7f7c9b56c74e4d0a","decimalCount":9}]},{"id":"emanate","name":"Emanate","symbol":"EMT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x893700a1a86ee68b92536bf6fd4d3200d7369f7d","decimalCount":18}]},{"id":"tap","name":"Tap","symbol":"XTP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6368e1e18c4c419ddfc608a0bed1ccb87b9250fc","decimalCount":18}]},{"id":"exponential-capital","name":"Exponential Capital","symbol":"EXPO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcfaf8edcea94ebaa080dc4983c3f9be5701d6613","decimalCount":18}]},{"id":"superbonds","name":"SuperBonds","symbol":"SB","active":true,"networks":[{"networkId":"solana","contractAddress":"SuperbZyz7TsSdSoFAZ6RYHfAWe9NmjXBLVQpS8hqdx","decimalCount":6}]},{"id":"garlicoin","name":"Garlicoin","symbol":"GRLC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x58f7345b5295e43aa454911571f13be186655be9","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0x7283dfa2d8d7e277b148cc263b5d8ae02f1076d3","decimalCount":8}]},{"id":"my-defi-pet","name":"My DeFi Pet","symbol":"DPET","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfb62ae373aca027177d1c18ee0862817f9080d08","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xfb62ae373aca027177d1c18ee0862817f9080d08","decimalCount":18}]},{"id":"unido-ep","name":"Unido","symbol":"UDO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xea3983fc6d0fbbc41fb6f6091f68f3e08894dc06","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x70802af0ba10dd5bb33276b5b37574b6451db3d9","decimalCount":18}]},{"id":"sheesha-finance-erc20","name":"Sheesha Finance (ERC20)","symbol":"SHEESHA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x232fb065d9d24c34708eedbf03724f2e95abe768","decimalCount":18}]},{"id":"apreum","name":"Apreum","symbol":"APU","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0xc155504787e9430180f33f35edd7c5ec06cd5761","decimalCount":18}]},{"id":"minidoge","name":"MiniDOGE","symbol":"MINIDOGE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xba07eed3d09055d60caef2bdfca1c05792f2dfad","decimalCount":9}]},{"id":"must","name":"Must","symbol":"MUST","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9c78ee466d6cb57a4d01fd887d2b5dfb2d46288f","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x9c78ee466d6cb57a4d01fd887d2b5dfb2d46288f","decimalCount":18}]},{"id":"stakehound-staked-ether","name":"StakeHound Staked Ether","symbol":"STETH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdfe66b14d37c77f4e9b180ceb433d1b164f0281d","decimalCount":18}]},{"id":"dappnode","name":"DAppNode","symbol":"NODE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xda007777d86ac6d989cc9f79a73261b3fc5e0da0","decimalCount":18}]},{"id":"b-cube-ai","name":"B-cube.ai","symbol":"BCUBE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x93c9175e26f57d2888c7df8b470c9eea5c0b0a93","decimalCount":18}]},{"id":"arc-governance","name":"ARC Governance","symbol":"ARCX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1321f1f1aa541a56c31682c57b80ecfccd9bb288","decimalCount":18}]},{"id":"lightcoin","name":"Lightcoin","symbol":"LHC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x320d31183100280ccdf69366cd56180ea442a3e8","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0x320d31183100280ccdf69366cd56180ea442a3e8","decimalCount":8}]},{"id":"unit-protocol-duck","name":"Unit Protocol New","symbol":"DUCK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x92e187a03b6cd19cb6af293ba17f2745fd2357d5","decimalCount":18},{"networkId":"fantom","contractAddress":"0x602a3ad311e66b6f5e567a13016b712aba0625c6","decimalCount":18}]},{"id":"varen","name":"Varen","symbol":"VRN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x72377f31e30a405282b522d588aebbea202b4f23","decimalCount":18}]},{"id":"vita-inu","name":"Vita Inu","symbol":"VINU","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xfebe8c1ed424dbf688551d4e2267e7a53698f0aa","decimalCount":18}]},{"id":"yam-2","name":"YAM","symbol":"YAM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0aacfbec6a24756c20d41914f2caba817c0d8521","decimalCount":18}]},{"id":"tierion","name":"Tierion","symbol":"TNT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x08f5a9235b08173b7569f83645d2c7fb55e8ccd8","decimalCount":8}]},{"id":"singularity","name":"Singularity","symbol":"SGLY","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x5f50411cde3eec27b0eac21691b4e500c69a5a2e","decimalCount":18}]},{"id":"boom-token","name":"Boom Token","symbol":"BOOM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdb7eab9ba6be88b869f738f6deeba96d49fe13fd","decimalCount":18}]},{"id":"xy-finance","name":"XY Finance","symbol":"XY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x77777777772cf0455fb38ee0e75f38034dfa50de","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x666666661f9b6d8c581602aaa2f76cbead06c401","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x55555555a687343c6ce28c8e1f6641dc71659fad","decimalCount":18},{"networkId":"fantom","contractAddress":"0x444444443b0fcb2733b93f23c910580fba52fffa","decimalCount":18}]},{"id":"innovaminex","name":"InnovaMinex","symbol":"MINX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xae353daeed8dcc7a9a12027f7e070c0a50b7b6a4","decimalCount":6}]},{"id":"sonm","name":"SONM","symbol":"SNM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x46d0dac0926fa16707042cadc23f1eb4141fe86b","decimalCount":18}]},{"id":"x-2","name":"X","symbol":"X","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7f3141c4d6b047fb930991b450f1ed996a51cb26","decimalCount":18}]},{"id":"king-shiba","name":"King Shiba","symbol":"KINGSHIB","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x84f4f7cdb4574c9556a494dab18ffc1d1d22316c","decimalCount":9}]},{"id":"idexo-token","name":"Idexo","symbol":"IDO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf9c53268e9de692ae1b2ea5216e24e1c3ad7cb1e","decimalCount":18}]},{"id":"mirrored-apple","name":"Mirrored Apple","symbol":"MAAPL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd36932143f6ebdedd872d5fb0651f4b72fd15a84","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x900aeb8c40b26a8f8dfaf283f884b03ee7abb3ec","decimalCount":18}]},{"id":"slink","name":"sLINK","symbol":"SLINK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbbc455cb4f1b9e4bfc4b73970d360c8f032efee6","decimalCount":18}]},{"id":"pog-coin","name":"PolygonumOnline","symbol":"POG","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xfcb0f2d2f83a32a847d8abb183b724c214cd7dd8","decimalCount":18}]},{"id":"degen-index","name":"DEGEN Index","symbol":"DEGEN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x126c121f99e1e211df2e5f8de2d96fa36647c855","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xae6e3540e97b0b9ea8797b157b510e133afb6282","decimalCount":18}]},{"id":"phantasia","name":"Phantasia","symbol":"FANT","active":true,"networks":[{"networkId":"solana","contractAddress":"FANTafPFBAt93BNJVpdu25pGPmca3RfwdsDsRrT3LX1r","decimalCount":6}]},{"id":"1-up","name":"1-UP","symbol":"1-UP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc86817249634ac209bc73fca1712bbd75e37407d","decimalCount":18}]},{"id":"blockchain-certified-data-token","name":"EvidenZ","symbol":"BCDT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xacfa209fb73bf3dd5bbfb1101b9bc999c49062a5","decimalCount":18},{"networkId":"binancecoin","contractAddress":"0x8683e604cdf911cd72652a04bf9d571697a86a60","decimalCount":8}]},{"id":"agave-token","name":"Agave Token","symbol":"AGVE","active":true,"networks":[{"networkId":"arbitrum-one","contractAddress":"0x848e0ba28b637e8490d88bae51fa99c87116409b","decimalCount":18}]},{"id":"paint-swap","name":"Paint Swap","symbol":"BRUSH","active":true,"networks":[{"networkId":"fantom","contractAddress":"0x85dec8c4b2680793661bca91a8f129607571863d","decimalCount":18}]},{"id":"perth-mint-gold-token","name":"Perth Mint Gold Token","symbol":"PMGT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaffcdd96531bcd66faed95fc61e443d08f79efef","decimalCount":5}]},{"id":"txa","name":"TXA","symbol":"TXA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4463e6a3ded0dbe3f6e15bc8420dfc55e5fea830","decimalCount":18}]},{"id":"dxsale-network","name":"DxSale Network","symbol":"SALE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf063fe1ab7a291c5d06a86e14730b00bf24cb589","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x04f73a09e2eb410205be256054794fb452f0d245","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x8f6196901a4a153d8ee8f3fa779a042f6092d908","decimalCount":18}]},{"id":"monavale","name":"Monavale","symbol":"MONA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x275f5ad03be0fa221b4c6649b8aee09a42d9412a","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x6968105460f67c3bf751be7c15f92f5286fd0ce5","decimalCount":18}]},{"id":"communifty","name":"Communifty","symbol":"CNFT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8e2b4badac15a4ec8c56020f4ce60faa7558c052","decimalCount":18}]},{"id":"ime-lab","name":"iMe Lab","symbol":"LIME","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9d0b65a76274645b29e4cc41b8f23081fa09f4a3","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x7bc75e291e656e8658d66be1cc8154a3769a35dd","decimalCount":18}]},{"id":"duel-network","name":"Duel Network","symbol":"DUEL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x297817ce1a8de777e7ddbed86c3b7f9dc9349f2c","decimalCount":18}]},{"id":"snook","name":"Snook","symbol":"SNK","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x689f8e5913c158ffb5ac5aeb83b3c875f5d20309","decimalCount":18}]},{"id":"arcona","name":"Arcona","symbol":"ARCONA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0f71b8de197a1c84d31de0f1fa7926c365f052b3","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x8fc4532be3003fb5a3a2f9afc7e95b3bfbd5faab","decimalCount":18}]},{"id":"wirtual","name":"Wirtual","symbol":"WIRTUAL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xa19d3f4219e2ed6dc1cb595db20f70b8b6866734","decimalCount":18}]},{"id":"indexed-finance","name":"Indexed Finance","symbol":"NDX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x86772b1409b61c639eaac9ba0acfbb6e238e5f83","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xb965029343d55189c25a7f3e0c9394dc0f5d41b1","decimalCount":18}]},{"id":"dfohub","name":"dfohub","symbol":"BUIDL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7b123f53421b1bf8533339bfbdc7c98aa94163db","decimalCount":18}]},{"id":"dingocoin","name":"Dingocoin","symbol":"DINGO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x9b208b117b2c4f76c1534b6f006b033220a681a4","decimalCount":8}]},{"id":"coinfirm-amlt","name":"AMLT Network","symbol":"AMLT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xca0e7269600d353f70b14ad118a49575455c0f2f","decimalCount":18}]},{"id":"you-chain","name":"YOU Chain","symbol":"YOU","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x34364bee11607b1963d66bca665fde93fca666a8","decimalCount":18}]},{"id":"pillar","name":"Pillar","symbol":"PLR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe3818504c1b32bf1557b16c238b2e01fd3149c17","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x790cfdc6ab2e0ee45a433aac5434f183be1f6a20","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xa6b37fc85d870711c56fbcb8afe2f8db049ae774","decimalCount":18}]},{"id":"qiibee","name":"qiibee","symbol":"QBX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2467aa6b5a2351416fd4c3def8462d841feeecec","decimalCount":18}]},{"id":"ok-lets-go","name":"ok.lets.go.","symbol":"OKLG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5dbb9f64cd96e2dbbca58d14863d615b67b42f2e","decimalCount":9},{"networkId":"binance-smart-chain","contractAddress":"0x55e8b37a3c43b049dedf56c77f462db095108651","decimalCount":9}]},{"id":"falcon-token","name":"Falcon Project","symbol":"FNT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdc5864ede28bd4405aa04d93e05a0531797d9d59","decimalCount":6}]},{"id":"roobee","name":"Roobee","symbol":"ROOBEE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa31b1767e09f842ecfd4bc471fe44f830e3891aa","decimalCount":18}]},{"id":"kick","name":"Kick","symbol":"KICK","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x824a50df33ac1b41afc52f4194e2e8356c17c3ac","decimalCount":10}]},{"id":"don-key","name":"Don-key","symbol":"DON","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x217ddead61a42369a266f1fb754eb5d3ebadc88a","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x86b3f23b6e90f5bbfac59b5b2661134ef8ffd255","decimalCount":18}]},{"id":"crosswallet","name":"CrossWallet","symbol":"CWT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x5a726a26edb0df8fd55f03cc30af8a7cea81e78d","decimalCount":18}]},{"id":"vesta-finance","name":"Vesta Finance","symbol":"VSTA","active":true,"networks":[{"networkId":"arbitrum-one","contractAddress":"0xa684cd057951541187f288294a1e1c2646aa2d24","decimalCount":18}]},{"id":"airbloc-protocol","name":"Airbloc","symbol":"ABL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf8b358b3397a8ea5464f8cc753645d42e14b79ea","decimalCount":18}]},{"id":"kainet","name":"KAINET","symbol":"KAINET","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x723b6795be37ad8a0376acfb50034fa21912b439","decimalCount":9}]},{"id":"dinox","name":"DinoX","symbol":"DNXC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x20a8cec5fffea65be7122bcab2ffe32ed4ebf03a","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x3c1748d647e6a56b37b66fcd2b5626d0461d3aa0","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xcaf5191fc480f43e4df80106c7695eca56e48b18","decimalCount":18}]},{"id":"kalao","name":"Kalao","symbol":"KLO","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0xb27c8941a7df8958a1778c0259f76d1f8b711c35","decimalCount":18}]},{"id":"hodl-finance","name":"Hodl Finance","symbol":"HFT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x186866858aef38c05829166a7711b37563e15994","decimalCount":9}]},{"id":"quidd","name":"Quidd","symbol":"QUIDD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xda9fdab21bc4a5811134a6e0ba6ca06624e67c07","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x7961ade0a767c0e5b67dd1a1f78ba44f727642ed","decimalCount":18}]},{"id":"nftlaunch","name":"NFTLaunch","symbol":"NFTL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe7f72bc0252ca7b16dbb72eeee1afcdb2429f2dd","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xe7f72bc0252ca7b16dbb72eeee1afcdb2429f2dd","decimalCount":18}]},{"id":"tenx","name":"TenX","symbol":"PAY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb97048628db6b661d4c2aa833e95dbe1a905b280","decimalCount":18}]},{"id":"ubiq","name":"Ubiq","symbol":"UBQ","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0xb1c5c9b97b35592777091cd34ffff141ae866abd","decimalCount":18}]},{"id":"monetha","name":"Monetha","symbol":"MTH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaf4dce16da2877f8c9e00544c93b62ac40631f16","decimalCount":5}]},{"id":"bird-money","name":"Bird.Money","symbol":"BIRD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x70401dfd142a16dc7031c56e862fc88cb9537ce0","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x8780fea4c6b242677d4a397fe1110ac09ce99ad2","decimalCount":18}]},{"id":"linka","name":"LINKA","symbol":"LINKA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x578b49c45961f98d8df92854b53f1641af0a5036","decimalCount":18}]},{"id":"goal-token","name":"Goal","symbol":"GOAL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x438fc473ba340d0734e2d05acdf5bee775d1b0a4","decimalCount":18}]},{"id":"scream","name":"Scream","symbol":"SCREAM","active":true,"networks":[{"networkId":"fantom","contractAddress":"0xe0654c8e6fd4d733349ac7e09f6f23da256bf475","decimalCount":18}]},{"id":"dlp-duck-token","name":"DLP Duck Token","symbol":"DUCK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc0ba369c8db6eb3924965e5c4fd0b4c1b91e305f","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x5d186e28934c6b0ff5fc2fece15d1f34f78cbd87","decimalCount":18}]},{"id":"wiva","name":"WIVA","symbol":"WIVA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa00055e6ee4d1f4169096ecb682f70caa8c29987","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x784641e51c300120a8d15bfdb3b45375d4352748","decimalCount":18}]},{"id":"archangel-token","name":"ArchAngel","symbol":"ARCHA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x36e43065e977bc72cb86dbd8405fae7057cdc7fd","decimalCount":9},{"networkId":"binance-smart-chain","contractAddress":"0xb0ff8188f374902bb180bd186d17967b5b1188f2","decimalCount":9},{"networkId":"fantom","contractAddress":"0x5e2e2d3ee4944d0e6c0b663625859cf8cc45ca88","decimalCount":9}]},{"id":"firestarter","name":"FireStarter","symbol":"FLAME","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x22e3f02f86bc8ea0d73718a2ae8851854e62adc5","decimalCount":18}]},{"id":"king-floki","name":"King Floki V2","symbol":"KING","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xb872057ee478b3eb77e74c9aa7b50fe4ed650e58","decimalCount":9}]},{"id":"deblox","name":"Deblox","symbol":"DGS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4ea636b489f51e2c332e2a6203bf3fcc0954a5f4","decimalCount":18}]},{"id":"nft-index","name":"NFT Index","symbol":"NFTI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe5feeac09d36b18b3fa757e5cf3f8da6b8e27f4c","decimalCount":18}]},{"id":"revolve-games","name":"Revolve Games","symbol":"RPG","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x01e0d17a533e5930a349c2bb71304f04f20ab12b","decimalCount":18}]},{"id":"decentr","name":"Decentr","symbol":"DEC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x30f271c9e86d2b7d00a6376cd96a1cfbd5f0b9b3","decimalCount":18}]},{"id":"woof-token","name":"WOOF","symbol":"WOOF","active":true,"networks":[{"networkId":"solana","contractAddress":"9nEqaUcb16sQ3Tn1psbkWqyhPdLmfHWjKGymREjsAgTE","decimalCount":6}]},{"id":"bloxmove-erc20","name":"bloXmove","symbol":"BLXM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x38d9eb07a7b8df7d86f440a4a5c4a4c1a27e1a08","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x40e51e0ec04283e300f12f6bb98da157bb22036e","decimalCount":18}]},{"id":"wall-street-games","name":"Wall Street Games","symbol":"WSG","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xa58950f05fea2277d2608748412bf9f802ea4901","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x3c1bb39bb696b443a1d80bb2b3a3d950ba9dee87","decimalCount":18}]},{"id":"brokoli","name":"Brokoli","symbol":"BRKL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4674a4f24c5f63d53f22490fb3a08eaaad739ff8","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x66cafcf6c32315623c7ffd3f2ff690aa36ebed38","decimalCount":18}]},{"id":"renzec","name":"renZEC","symbol":"RENZEC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1c5db575e2ff833e46a2e9864c22f4b22e0b37c2","decimalCount":8}]},{"id":"big-data-protocol","name":"Big Data Protocol","symbol":"BDP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf3dcbc6d72a4e1892f7917b7c43b74131df8480e","decimalCount":18}]},{"id":"unbound-finance","name":"Unbound Finance","symbol":"UNB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8db253a1943dddf1af9bcf8706ac9a0ce939d922","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x301af3eff0c904dc5ddd06faa808f653474f7fcc","decimalCount":18}]},{"id":"roco-finance","name":"Roco Finance","symbol":"ROCO","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0xb2a85c5ecea99187a977ac34303b80acbddfa208","decimalCount":18}]},{"id":"bridge-mutual","name":"Bridge Mutual","symbol":"BMI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x725c263e32c72ddc3a19bea12c5a0479a81ee688","decimalCount":18}]},{"id":"gazetv","name":"GazeTV","symbol":"GAZE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd1e06952708771f71e6dd18f06ee418f6e8fc564","decimalCount":18}]},{"id":"abitshadow-token","name":"Abitshadow Token","symbol":"ABST","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x7e46d5eb5b7ca573b367275fee94af1945f5b636","decimalCount":8}]},{"id":"relevant","name":"Relevant","symbol":"REL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb6c4267c4877bb0d6b1685cfd85b0fbe82f105ec","decimalCount":18}]},{"id":"holyheld-2","name":"Mover","symbol":"MOVE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3fa729b4548becbad4eab6ef18413470e6d5324c","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x521cddc0cba84f14c69c1e99249f781aa73ee0bc","decimalCount":18},{"networkId":"fantom","contractAddress":"0xc055c698f3793577707b3e6979b089f50c314d3a","decimalCount":18}]},{"id":"cyberfi","name":"CyberFi","symbol":"CFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x63b4f3e3fa4e438698ce330e365e831f7ccd1ef4","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x6a545f9c64d8f7b957d8d2e6410b52095a9e6c29","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xecf8f2fa183b1c4d2a269bf98a54fce86c812d3e","decimalCount":18},{"networkId":"fantom","contractAddress":"0x6a545f9c64d8f7b957d8d2e6410b52095a9e6c29","decimalCount":18}]},{"id":"kuma-inu","name":"Kuma Inu","symbol":"KUMA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x48c276e8d03813224bb1e55f953adb6d02fd3e02","decimalCount":18}]},{"id":"unilayer","name":"UniLayer","symbol":"LAYER","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0ff6ffcfda92c53f615a4a75d982f399c989366b","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xc2c23a86def9e9f5972a633b3d25f7ecbfa5e575","decimalCount":18}]},{"id":"elyfi","name":"ELYFI","symbol":"ELFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4da34f8264cb33a5c9f17081b9ef5ff6091116f4","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x6c619006043eab742355395690c7b42d3411e8c0","decimalCount":18}]},{"id":"launchzone","name":"LaunchZone","symbol":"LZ","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x3b78458981eb7260d1f781cb8be2caac7027dbe2","decimalCount":18}]},{"id":"julien","name":"JULIEN","symbol":"JULIEN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe6710e0cda178f3d921f456902707b0d4c4a332b","decimalCount":4}]},{"id":"swingby","name":"Swingby","symbol":"SWINGBY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8287c7b963b405b7b8d467db9d79eec40625b13a","decimalCount":18},{"networkId":"binancecoin","contractAddress":"SWINGBY-888","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0x71de20e0c4616e7fcbfdd3f875d568492cbe4739","decimalCount":18}]},{"id":"xio","name":"Blockzero Labs","symbol":"XIO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0f7f961648ae6db43c75663ac7e5414eb79b5704","decimalCount":18}]},{"id":"float-protocol-float","name":"Float Protocol: Float","symbol":"FLOAT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb05097849bca421a3f51b249ba6cca4af4b97cb9","decimalCount":18}]},{"id":"phuture","name":"Phuture","symbol":"PHTR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe1fc4455f62a6e89476f1072530c20cf1a0622da","decimalCount":18}]},{"id":"pickle-finance","name":"Pickle Finance","symbol":"PICKLE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x429881672b9ae42b8eba0e26cd9c73711b891ca5","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x2b88ad57897a8b496595925f43048301c37615da","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x965772e0e9c84b6f359c8597c891108dcf1c5b1a","decimalCount":18}]},{"id":"oni-token","name":"ONINO","symbol":"ONI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xea89199344a492853502a7a699cc4230854451b8","decimalCount":18},{"networkId":"fantom","contractAddress":"0x667c856f1a624baefe89fc4909c8701296c86c98","decimalCount":18}]},{"id":"transient","name":"Transient","symbol":"TSCT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x805ea9c07b49dd23ce11ec66dc6d8a2957385035","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xeeed90aa795c0e7d90fcec0fcfaa7bf6fc13c20a","decimalCount":18}]},{"id":"bitsong","name":"BitSong","symbol":"BTSG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x05079687d35b93538cbd59fe5596380cae9054a9","decimalCount":18}]},{"id":"piedao-dough-v2","name":"PieDAO DOUGH v2","symbol":"DOUGH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xad32a8e6220741182940c5abf610bde99e737b2d","decimalCount":18}]},{"id":"napoleon-x","name":"Napoleon X","symbol":"NPX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x28b5e12cce51f15594b0b91d5b5adaa70f684a02","decimalCount":2},{"networkId":"binance-smart-chain","contractAddress":"0xd8cb4c2369db13c94c90c7fd3bebc9757900ee6b","decimalCount":18}]},{"id":"reucoin","name":"REUCOIN","symbol":"REU","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa287fd349d80dfd2a8aee1c0d90f17281f24c061","decimalCount":18}]},{"id":"any-blocknet","name":"ANY Blocknet","symbol":"ABLOCK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe692c8d72bd4ac7764090d54842a305546dd1de5","decimalCount":8},{"networkId":"avalanche","contractAddress":"0xc931f61b1534eb21d8c11b24f3f5ab2471d4ab50","decimalCount":8}]},{"id":"blackdragon-token","name":"BlackDragon Token","symbol":"BDT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4efe8665e564bf454ccf5c90ee16817f7485d5cf","decimalCount":18}]},{"id":"ninneko","name":"Ninneko","symbol":"NINO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x6cad12b3618a3c7ef1feb6c91fdc3251f58c2a90","decimalCount":18}]},{"id":"wrapped-dgld","name":"Wrapped-DGLD","symbol":"WDGLD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x123151402076fc819b7564510989e475c9cd93ca","decimalCount":8}]},{"id":"jigstack","name":"Jigstack","symbol":"STAK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1f8a626883d7724dbd59ef51cbd4bf1cf2016d13","decimalCount":18}]},{"id":"cryptonovae","name":"Cryptonovae","symbol":"YAE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4ee438be38f8682abb089f2bfea48851c5e71eaf","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x4ee438be38f8682abb089f2bfea48851c5e71eaf","decimalCount":18}]},{"id":"shakita-inu","name":"Shakita Inu","symbol":"SHAK","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x76e08e1c693d42551dd6ba7c2a659f74ff5ba261","decimalCount":18}]},{"id":"nftfy","name":"Nftfy","symbol":"NFTFY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbf6ff49ffd3d104302ef0ab0f10f5a84324c091c","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xbf6ff49ffd3d104302ef0ab0f10f5a84324c091c","decimalCount":18}]},{"id":"hollygold","name":"HollyGold","symbol":"HGOLD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0c93b616933b0cd03b201b29cd8a22681dd9e0d9","decimalCount":8}]},{"id":"axpire","name":"aXpire","symbol":"AXPR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdd0020b1d5ba47a54e2eb16800d73beb6546f91a","decimalCount":18}]},{"id":"zyx","name":"ZYX","symbol":"ZYX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf974b5f9ac9c6632fee8b76c61b0242ce69c839d","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x377c6e37633e390aef9afb4f5e0b16689351eed4","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x377c6e37633e390aef9afb4f5e0b16689351eed4","decimalCount":18}]},{"id":"hundred-finance","name":"Hundred Finance","symbol":"HND","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x10010078a54396f62c96df8532dc2b4847d47ed3","decimalCount":18},{"networkId":"fantom","contractAddress":"0x10010078a54396f62c96df8532dc2b4847d47ed3","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x10010078a54396f62c96df8532dc2b4847d47ed3","decimalCount":18}]},{"id":"idle","name":"IDLE","symbol":"IDLE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x875773784af8135ea0ef43b5a374aad105c5d39e","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xc25351811983818c9fe6d8c580531819c8ade90f","decimalCount":18}]},{"id":"bankless-bed-index","name":"Bankless BED Index","symbol":"BED","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2af1df3ab0ab157e1e2ad8f88a7d04fbea0c7dc6","decimalCount":18}]},{"id":"konomi-network","name":"Konomi Network","symbol":"KONO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x850aab69f0e0171a9a49db8be3e71351c8247df4","decimalCount":18}]},{"id":"olyseum","name":"Olyseum","symbol":"OLY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6595b8fd9c920c81500dca94e53cdc712513fb1f","decimalCount":18}]},{"id":"yvault-lp-ycurve","name":"yUSD","symbol":"YVAULT-LP-YCURVE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5dbcf33d8c2e976c6b560249878e6f1491bca25c","decimalCount":18}]},{"id":"bloom","name":"Bloom","symbol":"BLT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x107c4504cd79c5d2696ea0030a8dd4e92601b82e","decimalCount":18}]},{"id":"gspi","name":"Shopping.io Governance","symbol":"GSPI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xb42e1c3902b85b410334f5fff79cdc51fbee6950","decimalCount":18}]},{"id":"nabox","name":"Nabox","symbol":"NABOX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x03d1e72765545729a035e909edd9371a405f77fb","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x755f34709e369d37c6fa52808ae84a32007d1155","decimalCount":18}]},{"id":"defi-yield-protocol","name":"DeFi Yield Protocol","symbol":"DYP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x961c8c0b1aad0c0b10a51fef6a867e3091bcef17","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x961c8c0b1aad0c0b10a51fef6a867e3091bcef17","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x961c8c0b1aad0c0b10a51fef6a867e3091bcef17","decimalCount":18}]},{"id":"slam-token","name":"Slam Token","symbol":"SLAM","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x000851476180bfc499ea68450a5327d21c9b050e","decimalCount":18}]},{"id":"musk-gold","name":"MUSK Gold","symbol":"MUSK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6069c9223e8a5da1ec49ac5525d4bb757af72cd8","decimalCount":18}]},{"id":"impermax","name":"Impermax","symbol":"IMX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7b35ce522cb72e4077baeb96cb923a5529764a00","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xea6887e4a9cda1b77e70129e5fba830cdb5cddef","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x60bb3d364b765c497c8ce50ae0ae3f0882c5bd05","decimalCount":18},{"networkId":"fantom","contractAddress":"0xea38f1ccf77bf43f352636241b05dd8f6f5f52b2","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x9c67ee39e3c4954396b9142010653f17257dd39c","decimalCount":18}]},{"id":"top-network","name":"TOP Network","symbol":"TOP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdcd85914b8ae28c1e62f1c488e1d968d5aaffe2b","decimalCount":18}]},{"id":"furucombo","name":"Furucombo","symbol":"COMBO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xffffffff2ba8f66d4e51811c5190992176930278","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x6ddb31002abc64e1479fc439692f7ea061e78165","decimalCount":18}]},{"id":"enigma","name":"Enigma","symbol":"ENG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf0ee6b27b759c9893ce4f094b49ad28fd15a23e4","decimalCount":8}]},{"id":"yin-finance","name":"YIN Finance","symbol":"YIN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x794baab6b878467f93ef17e2f2851ce04e3e34c8","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x794baab6b878467f93ef17e2f2851ce04e3e34c8","decimalCount":18}]},{"id":"nord-finance","name":"Nord Finance","symbol":"NORD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6e9730ecffbed43fd876a264c982e254ef05a0de","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x6e9730ecffbed43fd876a264c982e254ef05a0de","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xf6f85b3f9fd581c2ee717c404f7684486f057f95","decimalCount":18},{"networkId":"fantom","contractAddress":"0xeaf26191ac1d35ae30baa19a5ad5558dd8156aef","decimalCount":18}]},{"id":"bios","name":"0x_nodes","symbol":"BIOS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaaca86b876ca011844b5798eca7a67591a9743c8","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xcf87d3d50a98a7832f5cfdf99ae1b88c7cfba4a7","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xd7783a275e53fc6746dedfbad4a06059937502a4","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xe20d2df5041f8ed06976846470f727295cdd4d23","decimalCount":18},{"networkId":"fantom","contractAddress":"0x75e0eb8e6d92ab832bb11e46c041d06a89ac5f0d","decimalCount":18}]},{"id":"cogiverse","name":"9D NFT","symbol":"COGI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x6cb755c4b82e11e727c05f697c790fdbc4253957","decimalCount":18}]},{"id":"sdefi","name":"sDEFI","symbol":"SDEFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe1afe1fd76fd88f78cbf599ea1846231b8ba3b6b","decimalCount":18}]},{"id":"futurecoin","name":"FutureCoin","symbol":"FUTURE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x9fbff386a9405b4c98329824418ec02b5c20976b","decimalCount":18}]},{"id":"kineko","name":"Kineko","symbol":"KKO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x368c5290b13caa10284db58b4ad4f3e9ee8bf4c9","decimalCount":18},{"networkId":"solana","contractAddress":"kiNeKo77w1WBEzFFCXrTDRWGRWGP8yHvKC9rX6dqjQh","decimalCount":9}]},{"id":"bean","name":"Bean","symbol":"BEAN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdc59ac4fefa32293a95889dc396682858d52e5db","decimalCount":6}]},{"id":"elon-doge-token","name":"ElonDoge.io","symbol":"EDOGE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x163f182c32d24a09d91eb75820cde9fd5832b329","decimalCount":9}]},{"id":"yflink","name":"YF Link","symbol":"YFL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x28cb7e841ee97947a86b06fa4090c8451f64c0be","decimalCount":18}]},{"id":"yel-finance","name":"Yel.Finance","symbol":"YEL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7815bda662050d84718b988735218cffd32f75ea","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xd3b71117e6c1558c1553305b44988cd944e97300","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xd3b71117e6c1558c1553305b44988cd944e97300","decimalCount":18},{"networkId":"fantom","contractAddress":"0xd3b71117e6c1558c1553305b44988cd944e97300","decimalCount":18}]},{"id":"afin-coin","name":"Asian Fintech","symbol":"AFIN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xee9e5eff401ee921b138490d00ca8d1f13f67a72","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0xb955b4cab9aa3b49e23aeb5204ebc5ff6678e86d","decimalCount":18}]},{"id":"cryptowar-xblade","name":"OpenWorld","symbol":"OPEN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x27a339d9b59b21390d7209b78a839868e319301b","decimalCount":18}]},{"id":"tokenplace","name":"Tokenplace","symbol":"TOK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4fb721ef3bf99e0f2c193847afa296b9257d3c30","decimalCount":8},{"networkId":"avalanche","contractAddress":"0xae9d2385ff2e2951dd4fa061e74c4d3dedd24347","decimalCount":8}]},{"id":"devour","name":"Devour","symbol":"RESTAURANTS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdffc63f92c939deb112d88735ade3b4d21b6d491","decimalCount":18}]},{"id":"rac","name":"RAC","symbol":"RAC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc22b30e4cce6b78aaaadae91e44e73593929a3e9","decimalCount":18}]},{"id":"life-crypto","name":"Life Crypto","symbol":"LIFE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6c936d4ae98e6d2172db18c16c4b601c99918ee6","decimalCount":18}]},{"id":"finxflo","name":"FINXFLO","symbol":"FXF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8a40c222996f9f3431f63bf80244c36822060f12","decimalCount":18}]},{"id":"howdoo","name":"Hyprr","symbol":"UDOO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x12f649a9e821f90bb143089a6e56846945892ffb","decimalCount":18}]},{"id":"defi-for-you","name":"Defi For You","symbol":"DFY","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd98560689c6e748dc37bc410b4d3096b1aa3d8c2","decimalCount":18}]},{"id":"warp-finance","name":"Warp Finance","symbol":"WARP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xed40834a13129509a89be39a9be9c0e96a0ddd71","decimalCount":18}]},{"id":"tadpole-finance","name":"Tadpole","symbol":"TAD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9f7229af0c4b9740e207ea283b9094983f78ba04","decimalCount":18}]},{"id":"gas-dao","name":"Gas DAO","symbol":"GAS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6bba316c48b49bd1eac44573c5c871ff02958469","decimalCount":18}]},{"id":"hedget","name":"Hedget","symbol":"HGET","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7968bc6a03017ea2de509aaa816f163db0f35148","decimalCount":6}]},{"id":"alyattes","name":"Alyattes","symbol":"ALYA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x49a9f9a2271d8c5da44c57e7102aca79c222f4a9","decimalCount":9}]},{"id":"daex","name":"DAEX","symbol":"DAX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0b4bdc478791897274652dc15ef5c135cae61e60","decimalCount":18}]},{"id":"ethichub","name":"EthicHub","symbol":"ETHIX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfd09911130e6930bf87f2b0554c44f400bd80d3e","decimalCount":18}]},{"id":"resfinex-token","name":"Resfinex Token","symbol":"RES","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0a9f693fce6f00a51a8e0db4351b5a8078b4242e","decimalCount":5}]},{"id":"1world","name":"1World","symbol":"1WO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfdbc1adc26f0f8f8606a5d63b7d3a3cd21c22b23","decimalCount":8}]},{"id":"citadel-one","name":"Citadel.one","symbol":"XCT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xe8670901e86818745b28c8b30b17986958fce8cc","decimalCount":6}]},{"id":"zap","name":"Zap","symbol":"ZAP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6781a0f84c7e9e846dcb84a9a5bd49333067b104","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xc5326b32e8baef125acd68f8bc646fd646104f1c","decimalCount":18}]},{"id":"wanaka-farm","name":"Wanaka Farm","symbol":"WANA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x339c72829ab7dd45c3c52f965e7abe358dd8761e","decimalCount":18}]},{"id":"nft-protocol","name":"NFT Protocol","symbol":"NFT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcb8d1260f9c92a3a545d409466280ffdd7af7042","decimalCount":18}]},{"id":"swapr","name":"Swapr","symbol":"SWPR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6cacdb97e3fc8136805a9e7c342d866ab77d0957","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xde903e2712288a1da82942dddf2c20529565ac30","decimalCount":18}]},{"id":"ureeqa","name":"UREEQA","symbol":"URQA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1735db6ab5baa19ea55d0adceed7bcdc008b3136","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xbd3936ec8d83a5d4e73eca625ecfa006da8c8f52","decimalCount":18}]},{"id":"acryptosi","name":"ACryptoSI","symbol":"ACSI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x5b17b4d5e4009b5c43e3e3d63a5229f794cba389","decimalCount":18}]},{"id":"tycoon","name":"Tycoon","symbol":"TYC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3a82d3111ab5faf39d847d46023d9090261a658f","decimalCount":18}]},{"id":"equalizer","name":"Equalizer","symbol":"EQZ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1da87b114f35e1dc91f72bf57fc07a768ad40bb0","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x1da87b114f35e1dc91f72bf57fc07a768ad40bb0","decimalCount":18}]},{"id":"dogey-inu","name":"Dogey-Inu","symbol":"DINU","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbb1ee07d6c7baeb702949904080eb61f5d5e7732","decimalCount":18}]},{"id":"cryptopolis","name":"Cryptopolis","symbol":"CPO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xea395dfafed39924988b475f2ca7f4c72655203a","decimalCount":18}]},{"id":"unimex-network","name":"UniMex Network","symbol":"UMX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x10be9a8dae441d276a5027936c3aaded2d82bc15","decimalCount":18}]},{"id":"wagyuswap","name":"WagyuSwap","symbol":"WAG","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x7fa7df4996ac59f398476892cfb195ed38543520","decimalCount":18}]},{"id":"powertrade-fuel","name":"PowerTrade Fuel","symbol":"PTF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc57d533c50bc22247d49a368880fb49a1caa39f7","decimalCount":18}]},{"id":"astroswap","name":"AstroSwap","symbol":"ASTRO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x72eb7ca07399ec402c5b7aa6a65752b6a1dc0c27","decimalCount":18}]},{"id":"genaro-network","name":"Genaro Network","symbol":"GNX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6ec8a24cabdc339a06a172f8223ea557055adaa5","decimalCount":9}]},{"id":"edenchain","name":"Edenchain","symbol":"EDN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x89020f0d5c5af4f3407eb5fe185416c457b0e93e","decimalCount":18}]},{"id":"everlens","name":"Everlens","symbol":"ELEN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xca2483727292ba552aec12dfee4dc105cb1376b9","decimalCount":18}]},{"id":"aurora","name":"Aurora Chain","symbol":"AOA","active":false,"networks":[{"networkId":"ethereum","contractAddress":"0x9ab165d795019b6d8b3e971dda91071421305e5a","decimalCount":18}]},{"id":"algovest","name":"AlgoVest","symbol":"AVS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x94d916873b22c9c1b53695f1c002f78537b9b3b2","decimalCount":18}]},{"id":"sync-network","name":"Sync Network","symbol":"SYNC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb6ff96b8a8d214544ca0dbc9b33f7ad6503efd32","decimalCount":18}]},{"id":"aichain","name":"AICHAIN","symbol":"AIT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x79650799e7899a802cb96c0bc33a6a8d4ce4936c","decimalCount":18}]},{"id":"masq","name":"MASQ","symbol":"MASQ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x06f3c323f0238c72bf35011071f2b5b7f43a054c","decimalCount":18}]},{"id":"cpchain","name":"CPChain","symbol":"CPC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfae4ee59cdd86e3be9e8b90b53aa866327d7c090","decimalCount":18}]},{"id":"metagods","name":"MetaGods","symbol":"MGOD","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x10a12969cb08a8d88d4bfb5d1fa317d41e0fdab3","decimalCount":18}]},{"id":"ideaology","name":"Ideaology","symbol":"IDEA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5d3a4f62124498092ce665f865e0b38ff6f5fbea","decimalCount":18}]},{"id":"shopnext","name":"ShopNEXT","symbol":"NEXT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x9809e877192b510d767a94ba39a79429219a5afb","decimalCount":18}]},{"id":"game-ace-token","name":"Game Ace","symbol":"GAT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xf315cfc8550f6fca969d397ca8b807c5033fa122","decimalCount":18}]},{"id":"mist","name":"Mist","symbol":"MIST","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x68e374f856bf25468d365e539b700b648bf94b67","decimalCount":18}]},{"id":"senate","name":"SENATE","symbol":"SENATE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x34be5b8c30ee4fde069dc878989686abe9884470","decimalCount":18}]},{"id":"ether-1","name":"Etho Protocol","symbol":"ETHO","active":false,"networks":[{"networkId":"ethereum","contractAddress":"0x99676c9fa4c77848aeb2383fcfbd7e980dc25027","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x0e900aa6ed4244c43d597e6d2f8fb3994303ed99","decimalCount":18}]},{"id":"smoothy","name":"Smoothy","symbol":"SMTY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbf776e4fca664d791c4ee3a71e2722990e003283","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xbf776e4fca664d791c4ee3a71e2722990e003283","decimalCount":18}]},{"id":"sw-dao","name":"SW DAO","symbol":"SWD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1fd154b4d0e3753b714b511a53fe1fb72dc7ae1c","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xaee24d5296444c007a532696aada9de5ce6cafd0","decimalCount":18}]},{"id":"horizon-protocol","name":"Horizon Protocol","symbol":"HZN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xc0eff7749b125444953ef89682201fb8c6a917cd","decimalCount":18}]},{"id":"gami-world","name":"GAMI World","symbol":"GAMI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x1236a887ef31b4d32e1f0a2b5e4531f52cec7e75","decimalCount":6}]},{"id":"leaguedao-governance-token","name":"LeagueDAO Governance","symbol":"LEAG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7b39917f9562c8bc83c7a6c2950ff571375d505d","decimalCount":18}]},{"id":"angel-nodes","name":"Angel Nodes","symbol":"ANGEL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x623974fa31d79d12dc8a2ec8dfea9bcdf8938889","decimalCount":8}]},{"id":"polker","name":"Polker","symbol":"PKR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x001a8ffcb0f03e99141652ebcdecdb0384e3bd6c","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xc49dde62b4a0810074721faca54aab52369f486a","decimalCount":18}]},{"id":"chronicle","name":"Chronicle","symbol":"XNL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x06a00715e6f92210af9d7680b584931faf71a833","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x5f26fa0c2ee5d3c0323d861d0c503f31ac212662","decimalCount":18}]},{"id":"index-coop-eth-2x-flexible-leverage-index","name":"Index Coop - ETH 2x Flexible Leverage Index (Polygon)","symbol":"ETH2X-FLI-P","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x3ad707da309f3845cd602059901e39c4dcd66473","decimalCount":18}]},{"id":"polis","name":"Polis","symbol":"POLIS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xb5bea8a26d587cf665f2d78f077cca3c7f6341bd","decimalCount":18}]},{"id":"green-planet","name":"Green Planet","symbol":"GAMMA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xb3cb6d2f8f2fde203a022201c81a96c167607f15","decimalCount":18}]},{"id":"inpulse-x","name":"InpulseX","symbol":"IPX","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x1a3ee33da561642ba6be4671a06267ee0f36cedd","decimalCount":18}]},{"id":"heroes-empires","name":"Heroes & Empires","symbol":"HE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x20d39a5130f799b95b55a930e5b7ebc589ea9ed8","decimalCount":18}]},{"id":"hord","name":"Hord","symbol":"HORD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x43a96962254855f16b925556f9e97be436a43448","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x39d4549908e7adcee9b439429294eeb4c65c2c9e","decimalCount":18}]},{"id":"zusd","name":"ZUSD","symbol":"ZUSD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc56c2b7e71b54d38aab6d52e94a04cbfa8f604fa","decimalCount":6}]},{"id":"otterclam","name":"OtterClam","symbol":"CLAM","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0xc250e9987a032acac293d838726c511e6e1c029d","decimalCount":9}]},{"id":"kanpeki","name":"Kanpeki","symbol":"KAE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x65def5029a0e7591e46b38742bfedd1fb7b24436","decimalCount":18},{"networkId":"fantom","contractAddress":"0x65def5029a0e7591e46b38742bfedd1fb7b24436","decimalCount":18}]},{"id":"basketdao-defi-index","name":"BasketDAO DeFi Index","symbol":"BDI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0309c98b1bffa350bcb3f9fb9780970ca32a5060","decimalCount":18}]},{"id":"subx-finance","name":"SUBX FINANCE LAB","symbol":"SFX","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4cbda3d23c031cd403db2d24512ad920bf22f205","decimalCount":9}]},{"id":"rhythm","name":"Rhythm","symbol":"RHYTHM","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xe4318f2acf2b9c3f518a3a03b5412f4999970ddb","decimalCount":9}]},{"id":"razor-network","name":"Razor Network","symbol":"RAZOR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x50de6856358cc35f3a9a57eaaa34bd4cb707d2cd","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x50de6856358cc35f3a9a57eaaa34bd4cb707d2cd","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xc91c06db0f7bffba61e2a5645cc15686f0a8c828","decimalCount":18}]},{"id":"nix-bridge-token","name":"Voice Token","symbol":"VOICE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2e2364966267b5d7d2ce6cd9a9b5bd19d9c7c6a9","decimalCount":18}]},{"id":"ojamu","name":"Ojamu","symbol":"OJA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0aa7efe4945db24d95ca6e117bba65ed326e291a","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x26373ec913876c9e6d38494dde458cb8649cb30c","decimalCount":18}]},{"id":"xaurum","name":"Xaurum","symbol":"XAUR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4df812f6064def1e5e029f1ca858777cc98d2d81","decimalCount":8}]},{"id":"plasma-finance","name":"Plasma Finance","symbol":"PPAY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x054d64b73d3d8a21af3d764efd76bcaa774f3bb2","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xfb288d60d3b66f9c3e231a9a39ed3f158a4269aa","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x08158a6b5d4018340387d1a302f882e98a8bc5b4","decimalCount":18}]},{"id":"standard-protocol","name":"Standard Protocol","symbol":"STND","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9040e237c3bf18347bb00957dc22167d0f2b999d","decimalCount":18}]},{"id":"leon-token","name":"Leonicorn LEON","symbol":"LEON","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x27e873bee690c8e161813de3566e9e18a64b0381","decimalCount":18}]},{"id":"matrix-ai-network","name":"Matrix AI Network","symbol":"MAN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe25bcec5d3801ce3a794079bf94adf1b8ccd802d","decimalCount":18}]},{"id":"bundles","name":"Bundles","symbol":"BUND","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8d3e855f3f55109d473735ab76f753218400fe96","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x9c1a3e3a69f83bdf98a51e4a552bbc2e479d45e7","decimalCount":18}]},{"id":"artem","name":"Artem","symbol":"ARTEM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9b83f827928abdf18cf1f7e67053572b9bceff3a","decimalCount":18}]},{"id":"panda-girl","name":"Panda Girl","symbol":"PGIRL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4c4da68d45f23e38ec8407272ee4f38f280263c0","decimalCount":6}]},{"id":"swapz-app","name":"SWAPZ.app","symbol":"SWAPZ","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd522a1dce1ca4b138dda042a78672307eb124cc2","decimalCount":18}]},{"id":"projectx","name":"ProjectX","symbol":"XIL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xf3be1a4a47576208c1592cc027087ce154b00672","decimalCount":18}]},{"id":"kollect","name":"Kollect","symbol":"KOL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1cc30e2eac975416060ec6fe682041408420d414","decimalCount":18}]},{"id":"yield-optimization-platform","name":"Yield Optimization Platform & Protocol","symbol":"YOP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xae1eaae3f627aaca434127644371b67b18444051","decimalCount":8}]},{"id":"revest-finance","name":"Revest Finance","symbol":"RVST","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x120a3879da835a5af037bb2d1456bebd6b54d4ba","decimalCount":18}]},{"id":"perion","name":"Perion","symbol":"PERC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x60be1e1fe41c1370adaf5d8e66f07cf1c2df2268","decimalCount":18}]},{"id":"pawthereum","name":"Pawthereum","symbol":"PAWTH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaecc217a749c2405b5ebc9857a16d58bdc1c367f","decimalCount":9},{"networkId":"binance-smart-chain","contractAddress":"0x409e215738e31d8ab252016369c2dd9c2008fee0","decimalCount":9}]},{"id":"unipilot","name":"Unipilot","symbol":"PILOT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x37c997b35c619c21323f3518b9357914e8b99525","decimalCount":18}]},{"id":"unicly-mystic-axies-collection","name":"Unicly Mystic Axies Collection","symbol":"UAXIE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x68b1cadb8d5ab0c97fe9d9fbe0eb60acb329fe3f","decimalCount":18}]},{"id":"poodle","name":"Poodl Token","symbol":"POODL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4a68c250486a116dc8d6a0c5b0677de07cc09c5d","decimalCount":9}]},{"id":"dev-protocol","name":"Dev Protocol","symbol":"DEV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5caf454ba92e6f2c929df14667ee360ed9fd5b26","decimalCount":18}]},{"id":"kaiba-defi","name":"Kaiba Defi","symbol":"KAIBA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf2210f65235c2fb391ab8650520237e6378e5c5a","decimalCount":9}]},{"id":"disbalancer","name":"disBalancer","symbol":"DDOS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7fbec0bb6a7152e77c30d005b5d49cbc08a602c3","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x7fbec0bb6a7152e77c30d005b5d49cbc08a602c3","decimalCount":18}]},{"id":"orion-money","name":"Orion Money","symbol":"ORION","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x727f064a78dc734d33eec18d5370aef32ffd46e4","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x3dcb18569425930954feb191122e574b87f66abd","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x5e0294af1732498c77f8db015a2d52a76298542b","decimalCount":18}]},{"id":"plant-vs-undead-token","name":"Plant vs Undead","symbol":"PVU","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x31471e0791fcdbe82fbf4c44943255e923f1b794","decimalCount":18}]},{"id":"relay-token","name":"Relay Chain","symbol":"RELAY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5d843fa9495d23de997c394296ac7b4d721e841c","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xe338d4250a4d959f88ff8789eaae8c32700bd175","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x78c42324016cd91d1827924711563fb66e33a83a","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x904371845bc56dcbbcf0225ef84a669b2fd6bd0d","decimalCount":18}]},{"id":"hybrix","name":"Hybrix","symbol":"HY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9b53e429b0badd98ef7f01f03702986c516a5715","decimalCount":18}]},{"id":"sentinel-group","name":"Sentinel [OLD]","symbol":"DVPN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa44e5137293e855b1b7bc7e2c6f8cd796ffcb037","decimalCount":8}]},{"id":"shard","name":"Shard Coin","symbol":"SHARD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbebdab6da046bc49ffbb61fbd7b33157eb270d05","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xd8a1734945b9ba38eb19a291b475e31f49e59877","decimalCount":18}]},{"id":"pist-trust","name":"Pist Trust","symbol":"PIST","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x315dc1b524de57ae8e809a2e97699dbc895b8a21","decimalCount":9}]},{"id":"the-crypto-prophecies","name":"The Crypto Prophecies","symbol":"TCP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x06576eb3b212d605b797dc15523d9dc9f4f66db4","decimalCount":18}]},{"id":"cornichon","name":"Cornichon","symbol":"CORN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa456b515303b2ce344e9d2601f91270f8c2fea5e","decimalCount":18}]},{"id":"xtoken","name":"xToken","symbol":"XTK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7f3edcdd180dbe4819bd98fee8929b5cedb3adeb","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xf0a5717ec0883ee56438932b0fe4a20822735fba","decimalCount":18}]},{"id":"kondux","name":"Kondux","symbol":"KNDX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7ff7a55a7c637e3953ab25569c335e04b96c475b","decimalCount":9}]},{"id":"unit-protocol","name":"Unit Protocol","symbol":"COL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc76fb75950536d98fa62ea968e1d6b45ffea2a55","decimalCount":18}]},{"id":"meme-inu","name":"Meme Inu","symbol":"MEME","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x74b988156925937bd4e082f0ed7429da8eaea8db","decimalCount":18}]},{"id":"obortech","name":"Obortech","symbol":"OBOT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xedadeb5faa413e6c8623461849dfd0b7c3790c32","decimalCount":18}]},{"id":"tia","name":"TIA","symbol":"TIA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x824e35f7a75324f99300afac75ecf7354e17ea26","decimalCount":9}]},{"id":"uniqly","name":"Uniqly","symbol":"UNIQ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3758e00b100876c854636ef8db61988931bb8025","decimalCount":18}]},{"id":"degis","name":"Degis","symbol":"DEG","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x9f285507ea5b4f33822ca7abb5ec8953ce37a645","decimalCount":18}]},{"id":"unistake","name":"Unistake","symbol":"UNISTAKE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9ed8e7c9604790f7ec589f99b94361d8aab64e5e","decimalCount":18}]},{"id":"coinspaid","name":"CoinsPaid","symbol":"CPD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9b31bb425d8263fa1b8b9d090b83cf0c31665355","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x2406dce4da5ab125a18295f4fb9fd36a0f7879a2","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x1ce4a2c355f0dcc24e32a9af19f1836d6f4f98ae","decimalCount":18}]},{"id":"verox","name":"Verox","symbol":"VRX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x87de305311d5788e8da38d19bb427645b09cb4e5","decimalCount":18}]},{"id":"mars-ecosystem-token","name":"Mars Ecosystem","symbol":"XMS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x7859b01bbf675d67da8cd128a50d155cd881b576","decimalCount":18}]},{"id":"ruff","name":"Ruff","symbol":"RUFF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf278c1ca969095ffddded020290cf8b5c424ace2","decimalCount":18}]},{"id":"wowswap","name":"WOWswap","symbol":"WOW","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3405a1bd46b85c5c029483fbecf2f3e611026e45","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x4da996c5fe84755c80e108cf96fe705174c5e36a","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xa384bc7cdc0a93e686da9e7b8c0807cd040f4e0b","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x855d4248672a1fce482165e8dbe1207b94b1968a","decimalCount":18}]},{"id":"whiteheart","name":"Whiteheart","symbol":"WHITE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5f0e628b693018f639d10e4a4f59bd4d8b2b6b44","decimalCount":18}]},{"id":"asia-coin","name":"Asia Coin","symbol":"ASIA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf519381791c03dd7666c142d4e49fd94d3536011","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xebaffc2d2ea7c66fb848c48124b753f93a0a90ec","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x50bcbc40306230713239ae1bddd5eefeeaa273dc","decimalCount":18}]},{"id":"verso","name":"Verso","symbol":"VSO","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x846d50248baf8b7ceaa9d9b53bfd12d7d7fbb25a","decimalCount":18}]},{"id":"chronobase","name":"ChronoBase","symbol":"TIK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0922f1d808adc3a4444bed2f73fac53a1a2a5859","decimalCount":18}]},{"id":"wild-credit","name":"Wild Credit","symbol":"WILD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x403d512ab96103562dcafe4635545e8ee2753f6e","decimalCount":18}]},{"id":"rewards-bunny","name":"Rewards Bunny","symbol":"RBUNNY","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x68848e1d1ffd7b38d103106c74220c1ad3494afc","decimalCount":18}]},{"id":"dapp-com","name":"Dapp.com","symbol":"DAPPT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x96184d9c811ea0624fc30c80233b1d749b9e485b","decimalCount":18}]},{"id":"baanx","name":"Baanx","symbol":"BXX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6b1a8f210ec6b7b6643cea3583fb0c079f367898","decimalCount":18}]},{"id":"graphlinq-protocol","name":"GraphLinq Protocol","symbol":"GLQ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9f9c8ec3534c3ce16f928381372bfbfbfb9f4d24","decimalCount":18}]},{"id":"mettalex","name":"Mettalex","symbol":"MTLX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2e1e15c44ffe4df6a0cb7371cd00d5028e571d14","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x5921dee8556c4593eefcfad3ca5e2f618606483b","decimalCount":18}]},{"id":"flare-token","name":"Flare","symbol":"1FLR","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x5f0197ba06860dac7e31258bdf749f92b6a636d4","decimalCount":18}]},{"id":"pussy-financial","name":"Pussy Financial","symbol":"PUSSY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9196e18bc349b1f64bc08784eae259525329a1ad","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xd9e8d20bde081600fac0d94b88eafaddce55aa43","decimalCount":18}]},{"id":"nitro-league","name":"Nitro League","symbol":"NITRO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0335a7610d817aeca1bebbefbd392ecc2ed587b8","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x695fc8b80f344411f34bdbcb4e621aa69ada384b","decimalCount":18}]},{"id":"apy-vision","name":"APY.vision","symbol":"VISION","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf406f7a9046793267bc276908778b29563323996","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x034b2090b579228482520c589dbd397c53fc51cc","decimalCount":18}]},{"id":"decentraweb","name":"DecentraWeb","symbol":"DWEB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe7f58a92476056627f9fdb92286778abd83b285f","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x8839e639f210b80ffea73aedf51baed8dac04499","decimalCount":18}]},{"id":"unifarm","name":"UniFarm","symbol":"UFARM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x40986a85b4cfcdb054a6cbfb1210194fee51af88","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x0a356f512f6fce740111ee04ab1699017a908680","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xd60effed653f3f1b69047f2d2dc4e808a548767b","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xa7305ae84519ff8be02484cda45834c4e7d13dd6","decimalCount":18}]},{"id":"sekuritance","name":"Sekuritance","symbol":"SKRT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x887168120cb89fb06f3e74dc4af20d67df0977f6","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xe51e88dd08499762b8e4eb3a9f3da9b8e79608c3","decimalCount":18}]},{"id":"waultswap","name":"WaultSwap","symbol":"WEX","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xa9c41a46a6b3531d28d5c32f6633dd2ff05dfb90","decimalCount":18}]},{"id":"kambria","name":"Kambria","symbol":"KAT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x14da230d6726c50f759bc1838717f8ce6373509c","decimalCount":18}]},{"id":"newdex-token","name":"Newdex Token","symbol":"DEX","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x996f56299a5b7c4f825a44886e07dafc4660b794","decimalCount":8}]},{"id":"puli-inu","name":"Puli","symbol":"PULI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xaef0a177c8c329cbc8508292bb7e06c00786bbfc","decimalCount":9}]},{"id":"ucash","name":"U.CASH","symbol":"UCASH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x92e52a1a235d9a103d970901066ce910aacefd37","decimalCount":8}]},{"id":"kiwigo","name":"Kiwigo","symbol":"KGO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x5d3afba1924ad748776e4ca62213bf7acf39d773","decimalCount":5}]},{"id":"swarm-markets","name":"Swarm Markets","symbol":"SMT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb17548c7b510427baac4e267bea62e800b247173","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xe631dabef60c37a37d70d3b4f812871df663226f","decimalCount":18}]},{"id":"cindicator","name":"Cindicator","symbol":"CND","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd4c435f5b09f855c3317c8524cb1f586e42795fa","decimalCount":18}]},{"id":"coinmerge-bsc","name":"CoinMerge (BEP20)","symbol":"CMERGE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x8d3e3a57c5f140b5f9feb0d43d37a347ee01c851","decimalCount":9}]},{"id":"carvertical","name":"carVertical","symbol":"CV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x50bc2ecc0bfdf5666640048038c1aba7b7525683","decimalCount":18}]},{"id":"solape-token","name":"SOLAPE","symbol":"SOLAPE","active":true,"networks":[{"networkId":"solana","contractAddress":"GHvFFSZ9BctWsEc5nujR1MTmmJWY7tgQz2AXE6WVFtGN","decimalCount":9}]},{"id":"coinxpad","name":"CoinxPad","symbol":"CXPAD","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xe90d1567ecef9282cc1ab348d9e9e2ac95659b99","decimalCount":18}]},{"id":"egretia","name":"Egretia","symbol":"EGT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8e1b448ec7adfc7fa35fc2e885678bd323176e34","decimalCount":18}]},{"id":"gridzone","name":"GridZone.io","symbol":"ZONE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc1d9b5a0776d7c8b98b8a838e5a0dd1bc5fdd53c","decimalCount":18}]},{"id":"ulti-arena","name":"Ulti Arena","symbol":"ULTI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x42bfe4a3e023f2c90aebffbd9b667599fa38514f","decimalCount":18}]},{"id":"elvantis","name":"Elvantis","symbol":"ELV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4734baf528766ec4c420a6c13f8dba7bb1920181","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xe942c48044fb1c7f4c9eb456f6097fa4a1a17b8f","decimalCount":18}]},{"id":"ari10","name":"Ari10","symbol":"ARI10","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x80262f604acac839724f66846f290a2cc8b48662","decimalCount":18}]},{"id":"veriblock","name":"VeriBlock","symbol":"VBK","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd347deffbb2e750c752b2d4aa5c26fd57ab90d64","decimalCount":18}]},{"id":"dexkit","name":"DexKit","symbol":"KIT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7866e48c74cbfb8183cd1a929cd9b95a7a5cb4f4","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x314593fa9a2fa16432913dbccc96104541d32d11","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x4d0def42cf57d6f27cd4983042a55dce1c9f853c","decimalCount":18}]},{"id":"unitrade","name":"Unitrade","symbol":"TRADE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6f87d756daf0503d08eb8993686c7fc01dc44fb1","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x7af173f350d916358af3e218bdf2178494beb748","decimalCount":18}]},{"id":"chainium","name":"WeOwn","symbol":"CHX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1460a58096d80a50a2f1f956dda497611fa4f165","decimalCount":18}]},{"id":"prcy-coin","name":"PRivaCY Coin","symbol":"PRCY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdfc3829b127761a3218bfcee7fc92e1232c9d116","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0xdfc3829b127761a3218bfcee7fc92e1232c9d116","decimalCount":8},{"networkId":"polygon-pos","contractAddress":"0xdfc3829b127761a3218bfcee7fc92e1232c9d116","decimalCount":8}]},{"id":"swag-finance","name":"SWAG Finance","symbol":"SWAG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x87edffde3e14c7a66c9b9724747a1c5696b742e6","decimalCount":18}]},{"id":"oin-finance","name":"OIN Finance","symbol":"OIN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9aeb50f542050172359a0e1a25a9933bc8c01259","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0x658e64ffcf40d240a43d52ca9342140316ae44fa","decimalCount":8}]},{"id":"doubloon","name":"Doubloon","symbol":"DBL","active":true,"networks":[{"networkId":"arbitrum-one","contractAddress":"0xd3f1da62cafb7e7bc6531ff1cef6f414291f03d3","decimalCount":18}]},{"id":"statera","name":"Statera","symbol":"STA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa7de087329bfcda5639247f96140f9dabe3deed1","decimalCount":18},{"networkId":"fantom","contractAddress":"0x89d5e71e275b4be094df9551627bcf4e3b24ce22","decimalCount":18}]},{"id":"eve-exchange","name":"EVE","symbol":"EVE","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0xae29ac47a9e3b0a52840e547adf74b912999f7fc","decimalCount":18}]},{"id":"thx-network","name":"THX Network","symbol":"THX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe632ea2ef2cfd8fc4a2731c76f99078aef6a4b31","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x2934b36ca9a4b31e633c5be670c8c8b28b6aa015","decimalCount":18}]},{"id":"hiveterminal","name":"Hiveterminal token","symbol":"HVN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc0eb85285d83217cd7c891702bcbc0fc401e2d9d","decimalCount":8}]},{"id":"humandao","name":"humanDAO","symbol":"HDAO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdac657ffd44a3b9d8aba8749830bf14beb66ff2d","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x72928d5436ff65e57f72d5566dcd3baedc649a88","decimalCount":18}]},{"id":"b20","name":"B20","symbol":"B20","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc4de189abf94c57f396bd4c52ab13b954febefd8","decimalCount":18}]},{"id":"raven-protocol","name":"Raven Protocol","symbol":"RAVEN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xcd7c5025753a49f1881b31c48caa7c517bb46308","decimalCount":18},{"networkId":"binancecoin","contractAddress":"RAVEN-F66","decimalCount":8}]},{"id":"peri-finance","name":"PERI Finance","symbol":"PERI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5d30ad9c6374bf925d0a75454fa327aacf778492","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xb49b7e0742ecb4240ffe91661d2a580677460b6a","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xdc0e17eae3b9651875030244b971fa0223a1764f","decimalCount":18}]},{"id":"unfederalreserve","name":"unFederalReserve","symbol":"ERSDL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5218e472cfcfe0b64a064f055b43b4cdc9efd3a6","decimalCount":18}]},{"id":"cryptocart","name":"CryptoCart V2","symbol":"CCV2","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x612e1726435fe38dd49a0b35b4065b56f49c8f11","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x612e1726435fe38dd49a0b35b4065b56f49c8f11","decimalCount":18}]},{"id":"catapult","name":"Catapult","symbol":"ATD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8052327f1baf94a9dc8b26b9100f211ee3774f54","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x1ce440d1a64eea6aa1db2a5aa51c9b326930957c","decimalCount":18}]},{"id":"ubxs-token","name":"UBXS","symbol":"UBXS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4f1960e29b2ca581a38c5c474e123f420f8092db","decimalCount":6}]},{"id":"vibe","name":"VIBE","symbol":"VIBE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe8ff5c9c75deb346acac493c463c8950be03dfba","decimalCount":18}]},{"id":"nodeseeds","name":"Nodeseeds","symbol":"NDS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x747f564d258612ec5c4e24742c5fd4110bcbe46b","decimalCount":18}]},{"id":"autonio","name":"Autonio","symbol":"NIOX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc813ea5e3b48bebeedb796ab42a30c5599b01740","decimalCount":4},{"networkId":"polygon-pos","contractAddress":"0xad684e79ce4b6d464f2ff7c3fd51646892e24b96","decimalCount":4}]},{"id":"aircoins","name":"Aircoins","symbol":"AIRX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8cb1d155a5a1d5d667611b7710920fd9d1cd727f","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0x6fb05b156788e88c8ad1e057e729362ff8c39d93","decimalCount":8}]},{"id":"mirrored-ishares-silver-trust","name":"Mirrored iShares Silver Trust","symbol":"MSLV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9d1555d8cb3c846bb4f7d5b1b1080872c3166676","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x211e763d0b9311c08ec92d72ddc20ab024b6572a","decimalCount":18}]},{"id":"the-parallel","name":"The Parallel","symbol":"PRL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd07e82440a395f3f3551b42da9210cd1ef4f8b24","decimalCount":18}]},{"id":"paypolitan-token","name":"Paypolitan Token","symbol":"EPAN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x72630b1e3b42874bf335020ba0249e3e9e47bafc","decimalCount":18}]},{"id":"cryptoids-admin-coin","name":"Cryptoids Admin Coin","symbol":"CAC","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x5b7d8a53e63f1817b68d40dc997cb7394db0ff1a","decimalCount":18}]},{"id":"mch-coin","name":"MCH Coin","symbol":"MCHC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd69f306549e9d96f183b1aeca30b8f4353c2ecc3","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xee7666aacaefaa6efeef62ea40176d3eb21953b9","decimalCount":18}]},{"id":"swapfolio","name":"Swapfolio","symbol":"SWFL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xba21ef4c9f433ede00badefcc2754b8e74bd538a","decimalCount":18}]},{"id":"herocoin","name":"HEROcoin","symbol":"PLAY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe477292f1b3268687a29376116b0ed27a9c76170","decimalCount":18}]},{"id":"scalara-nft-index","name":"Scalara NFT Index","symbol":"NFTI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x525ef76138bf76118d786dbedeae5f87aabf4a81","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xc75ea0c71023c14952f3c7b9101ecbbaa14aa27a","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xcfe3fbc98d80f7eca0bc76cd1f406a19dd425896","decimalCount":18}]},{"id":"polylastic","name":"Polylastic","symbol":"POLX","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x187ae45f2d361cbce37c6a8622119c91148f261b","decimalCount":18}]},{"id":"unicly-fewocious-collection","name":"Unicly Fewocious Collection","symbol":"UFEWO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcccf837f40d334f8602f031e64b52ad4cd2b6601","decimalCount":18}]},{"id":"soldex","name":"Soldex","symbol":"SOLX","active":true,"networks":[{"networkId":"solana","contractAddress":"CH74tuRLTYcxG7qNJCsV9rghfLXJCQJbsu7i52a8F1Gn","decimalCount":9}]},{"id":"somee-social-old","name":"SoMee.Social [OLD]","symbol":"ONG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd341d1680eeee3255b8c4c75bcce7eb57f144dae","decimalCount":18}]},{"id":"moonstarter","name":"MoonStarter","symbol":"MNST","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x6a6ccf15b38da4b5b0ef4c8fe9fefcb472a893f9","decimalCount":18}]},{"id":"fastswap-bsc","name":"Fastswap (BSC)","symbol":"FAST","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x2322afaac81697e770c19a58df587d8739777536","decimalCount":18}]},{"id":"wasabix","name":"WasabiX","symbol":"WASABI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x896e145568624a498c5a909187363ae947631503","decimalCount":18}]},{"id":"piedao-balanced-crypto-pie","name":"PieDAO Balanced Crypto Pie","symbol":"BCP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe4f726adc8e89c6a6017f01eada77865db22da14","decimalCount":18},{"networkId":"fantom","contractAddress":"0x9611579c926294b0e29e5371a81a3e463650be17","decimalCount":18}]},{"id":"savage","name":"SAVAGE","symbol":"SAVG","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x981aecc6eb4d382b96a02b75e931900705e95a31","decimalCount":18}]},{"id":"hakka-finance","name":"Hakka Finance","symbol":"HAKKA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0e29e5abbb5fd88e28b2d355774e73bd47de3bcd","decimalCount":18}]},{"id":"ethermon","name":"Ethermon","symbol":"EMON","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd6a5ab46ead26f49b03bbb1f9eb1ad5c1767974a","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xd6a5ab46ead26f49b03bbb1f9eb1ad5c1767974a","decimalCount":18}]},{"id":"treatdao-v2","name":"TreatDAO","symbol":"TREAT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x01bd7acb6ff3b6dd5aefa05cf085f2104f3fc53f","decimalCount":18}]},{"id":"roge","name":"Rogue Doge","symbol":"ROGE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x45734927fa2f616fbe19e65f42a0ef3d37d1c80a","decimalCount":9}]},{"id":"coinmerge","name":"CoinMerge (ERC20)","symbol":"CMERGE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc48b4814faed1ccc885dd6fde62a6474aecbb19a","decimalCount":9}]},{"id":"moonedge","name":"MoonEdge","symbol":"MOONED","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x7e4c577ca35913af564ee2a24d882a4946ec492b","decimalCount":18}]},{"id":"beholder","name":"Behodler","symbol":"EYE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x155ff1a85f440ee0a382ea949f24ce4e0b751c65","decimalCount":18}]},{"id":"sheesha-finance-polygon","name":"Sheesha Finance Polygon","symbol":"MSHEESHA","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x88c949b4eb85a90071f2c0bef861bddee1a7479d","decimalCount":18}]},{"id":"neumark","name":"Neumark","symbol":"NEU","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa823e6722006afe99e91c30ff5295052fe6b8e32","decimalCount":18}]},{"id":"defi-warrior","name":"Defi Warrior","symbol":"FIWA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x633237c6fa30fae46cc5bb22014da30e50a718cc","decimalCount":18}]},{"id":"bankless-defi-innovation-index","name":"Bankless DeFi Innovation Index","symbol":"GMI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x47110d43175f7f2c2425e7d15792acc5817eb44f","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x7fb27ee135db455de5ab1ccec66a24cbc82e712d","decimalCount":18}]},{"id":"gogocoin","name":"GOGOcoin","symbol":"GOGO","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0xdd2af2e723547088d3846841fbdcc6a8093313d6","decimalCount":18}]},{"id":"ethpad","name":"ETHPad","symbol":"ETHPAD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8db1d28ee0d822367af8d220c0dc7cb6fe9dc442","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x8db1d28ee0d822367af8d220c0dc7cb6fe9dc442","decimalCount":18}]},{"id":"en-tan-mo","name":"En-Tan-Mo","symbol":"ETM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6020da0f7c1857dbe4431ec92a15cc318d933eaa","decimalCount":18}]},{"id":"geyser","name":"Geyser","symbol":"GYSR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbea98c05eeae2f3bc8c3565db7551eb738c8ccab","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xc48f61a288a08f1b80c2edd74652e1276b6a168c","decimalCount":18}]},{"id":"ionchain-token","name":"IONChain","symbol":"IONC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbc647aad10114b89564c0a7aabe542bd0cf2c5af","decimalCount":18}]},{"id":"chads-vc","name":"CHADS VC","symbol":"CHADS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x69692d3345010a207b759a7d1af6fc7f38b35c5e","decimalCount":18}]},{"id":"metastrike","name":"Metastrike","symbol":"MTS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x496cc0b4ee12aa2ac4c42e93067484e7ff50294b","decimalCount":18}]},{"id":"unicly-aavegotchi-astronauts-collection","name":"Unicly Aavegotchi Astronauts Collection","symbol":"UGOTCHI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x30c2a84aed6db30e31cf4d7059b1836c12c68068","decimalCount":18}]},{"id":"nearpad","name":"NearPad","symbol":"PAD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xea7cc765ebc94c4805e3bff28d7e4ae48d06468a","decimalCount":18}]},{"id":"katana-inu","name":"Katana Inu","symbol":"KATA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2e85ae1c47602f7927bcabc2ff99c40aa222ae15","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x6d6ba21e4c4b29ca7bfa1c344ba1e35b8dae7205","decimalCount":18}]},{"id":"bsc-station","name":"BSC Station","symbol":"BSCS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xbcb24afb019be7e93ea9c43b7e22bb55d5b7f45d","decimalCount":18}]},{"id":"humaniq","name":"Humaniq","symbol":"HMQ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcbcc0f036ed4788f63fc0fee32873d6a7487b908","decimalCount":8}]},{"id":"meme-lordz","name":"Meme Lordz","symbol":"$LORDZ","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x2541be91fe0d220ffcbe65f11d88217a87a43bda","decimalCount":9}]},{"id":"zenfuse","name":"Zenfuse","symbol":"ZEFU","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb1e9157c2fdcc5a856c8da8b2d89b6c32b3c1229","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x23ec58e45ac5313bcb6681f4f7827b8a8453ac45","decimalCount":18}]},{"id":"ftribe-fighters","name":"Ftribe Fighters","symbol":"F2C","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x657b632714e08ac66b79444ad3f3875526ee6689","decimalCount":18}]},{"id":"freerossdao","name":"FreeRossDAO","symbol":"FREE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4cd0c43b0d53bc318cc5342b77eb6f124e47f526","decimalCount":18}]},{"id":"pulsepad","name":"PulsePad","symbol":"PLSPAD","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x8a74bc8c372bc7f0e9ca3f6ac0df51be15aec47a","decimalCount":18}]},{"id":"portion","name":"Portion","symbol":"PRT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6d0f5149c502faf215c89ab306ec3e50b15e2892","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xaf00aac2431b04ef6afd904d19b08d5146e3a9a0","decimalCount":18}]},{"id":"silva-token","name":"Silva","symbol":"SILVA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x68b5edb385b59e30a7a7db1e681a449e94df0213","decimalCount":9}]},{"id":"museum-of-crypto-art","name":"Museum of Crypto Art","symbol":"MOCA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9ac07635ddbde5db18648c360defb00f5f22537e","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xce899f26928a2b21c6a2fddd393ef37c61dba918","decimalCount":18}]},{"id":"pontoon","name":"Pontoon","symbol":"TOON","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaee433adebe0fbb88daa47ef0c1a513caa52ef02","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xaee433adebe0fbb88daa47ef0c1a513caa52ef02","decimalCount":18}]},{"id":"dogecola","name":"DogeCola","symbol":"DOGECOLA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xe320df552e78d57e95cf1182b6960746d5016561","decimalCount":9}]},{"id":"odyssey","name":"Odyssey","symbol":"OCN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4092678e4e78230f46a1534c0fbc8fa39780892b","decimalCount":18}]},{"id":"polytrade","name":"Polytrade","symbol":"TRADE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6e5970dbd6fc7eb1f29c6d2edf2bc4c36124c0c1","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x6ba7a8f9063c712c1c8cabc776b1da7126805f3b","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x692ac1e363ae34b6b489148152b12e2785a3d8d6","decimalCount":18}]},{"id":"terablock","name":"TeraBlock","symbol":"TBC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9798df2f5d213a872c787bd03b2b91f54d0d04a1","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x9798df2f5d213a872c787bd03b2b91f54d0d04a1","decimalCount":18}]},{"id":"formation-fi","name":"Formation FI","symbol":"FORM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x21381e026ad6d8266244f2a583b35f9e4413fa2a","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x25a528af62e56512a19ce8c3cab427807c28cc19","decimalCount":18}]},{"id":"rendoge","name":"renDOGE","symbol":"RENDOGE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3832d2f059e55934220881f831be501d180671a7","decimalCount":8},{"networkId":"polygon-pos","contractAddress":"0xce829a89d4a55a63418bcc43f00145adef0edb8e","decimalCount":8}]},{"id":"utu-coin","name":"UTU Coin","symbol":"UTU","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa58a4f5c4bb043d2cc1e170613b74e767c94189b","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xed4bb33f20f32e989af975196e86019773a7cff0","decimalCount":18}]},{"id":"prosper","name":"Prosper","symbol":"PROS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8642a849d0dcb7a15a974794668adcfbe4794b56","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xed8c8aa8299c10f067496bb66f8cc7fb338a3405","decimalCount":18}]},{"id":"eddaswap","name":"EDDASwap","symbol":"EDDA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfbbe9b1142c699512545f47937ee6fae0e4b0aa9","decimalCount":18}]},{"id":"sirin-labs-token","name":"Sirin Labs Token","symbol":"SRN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x68d57c9a1c35f63e2c83ee8e49a64e9d70528d25","decimalCount":18}]},{"id":"dragon-kart-token","name":"Dragon Kart","symbol":"KART","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x8bdd8dbcbdf0c066ca5f3286d33673aa7a553c10","decimalCount":18}]},{"id":"anrkey-x","name":"AnRKey X","symbol":"$ANRX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcae72a7a0fd9046cf6b165ca54c9e3a3872109e0","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xe2e7329499e8ddb1f2b04ee4b35a8d7f6881e4ea","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x554f074d9ccda8f483d1812d4874cbebd682644e","decimalCount":18}]},{"id":"impactmarket","name":"impactMarket","symbol":"PACT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xee9d08840554c9f8d30d0e3833d4906d3f39a49e","decimalCount":18}]},{"id":"coin","name":"Coin","symbol":"COIN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe61fdaf474fac07063f2234fb9e60c1163cfa850","decimalCount":18}]},{"id":"potentiam","name":"Potentiam","symbol":"PTM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7c32db0645a259fae61353c1f891151a2e7f8c1e","decimalCount":18}]},{"id":"total-crypto-market-cap-token","name":"Total Crypto Market Cap","symbol":"TCAP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x16c52ceece2ed57dad87319d91b5e3637d50afa4","decimalCount":18}]},{"id":"vegawallet-token","name":"VegaWallet Token","symbol":"VGW","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x94236591125e935f5ac128bb3d5062944c24958c","decimalCount":5}]},{"id":"kampay","name":"Kampay","symbol":"KAMPAY","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x8e984e03ab35795c60242c902ece2450242c90e9","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x39fc9e94caeacb435842fadedecb783589f50f5f","decimalCount":18}]},{"id":"velhalla","name":"Velhalla","symbol":"SCAR","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x8d9fb713587174ee97e91866050c383b5cee6209","decimalCount":18}]},{"id":"bitlocus","name":"Bitlocus","symbol":"BTL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x93e32efafd24973d45f363a76d73ccb9edf59986","decimalCount":6},{"networkId":"binance-smart-chain","contractAddress":"0x51e7b598c9155b9dccb04eb42519f6eec9c841e9","decimalCount":6}]},{"id":"somee-social","name":"SoMee.Social","symbol":"SOMEE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x65f9a292f1aeed5d755aa2fd2fb17ab2e9431447","decimalCount":18}]},{"id":"xp-network","name":"XP Network","symbol":"XPNET","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x8cf8238abf7b933bf8bb5ea2c7e4be101c11de2a","decimalCount":18}]},{"id":"unique-utility-token","name":"Unique Utility","symbol":"UNQT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa80f2c8f61c56546001f5fc2eb8d6e4e72c45d4c","decimalCount":18}]},{"id":"shuey-rhon-inu","name":"Shuey Rhon Inu","symbol":"SHUEY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcdca1b81dbb543baa92c97b701396cd3ba315e5d","decimalCount":18}]},{"id":"wepower","name":"WePower","symbol":"WPR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4cf488387f035ff08c371515562cba712f9015d4","decimalCount":18}]},{"id":"legolas-exchange","name":"LGO Token","symbol":"LGO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0a50c93c762fdd6e56d86215c24aaad43ab629aa","decimalCount":8}]},{"id":"topbidder","name":"TopBidder","symbol":"BID","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x00000000000045166c45af0fc6e4cf31d9e14b9a","decimalCount":18}]},{"id":"lendingblock","name":"Lendingblock","symbol":"LND","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0947b0e6d821378805c9598291385ce7c791a6b2","decimalCount":18}]},{"id":"cofix","name":"CoFiX","symbol":"COFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1a23a6bfbadb59fa563008c0fb7cf96dfcf34ea1","decimalCount":18}]},{"id":"unifi","name":"Covenants","symbol":"UNIFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9e78b8274e1d6a76a0dbbf90418894df27cbceb5","decimalCount":18}]},{"id":"golden-doge","name":"Golden Doge","symbol":"GDOGE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xa53e61578ff54f1ad70186be99332a6e20b6ffa9","decimalCount":9}]},{"id":"moonscape","name":"Moonscape","symbol":"MSCP","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x27d72484f1910f5d0226afa4e03742c9cd2b297a","decimalCount":18}]},{"id":"treatdao","name":"TreatDAO [OLD]","symbol":"TREAT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xac0c7d9b063ed2c0946982ddb378e03886c064e6","decimalCount":18}]},{"id":"coreto","name":"Coreto","symbol":"COR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9c2dc0c3cc2badde84b0025cf4df1c5af288d835","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xa4b6573c9ae09d81e4d1360e6402b81f52557098","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x4fdce518fe527439fe76883e6b51a1c522b61b7c","decimalCount":18}]},{"id":"anji","name":"Anji","symbol":"ANJI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xfc619ffcc0e0f30427bf938f9a1b2bfae15bdf84","decimalCount":9}]},{"id":"nanobyte","name":"NanoByte","symbol":"NBT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x1d3437e570e93581bd94b2fd8fbf202d4a65654a","decimalCount":18}]},{"id":"etna-network","name":"ETNA Network","symbol":"ETNA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x51f35073ff7cf54c9e86b7042e59a8cc9709fc46","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x015c425f6dfabc31e1464cc4339954339f096061","decimalCount":18}]},{"id":"sarcophagus","name":"Sarcophagus","symbol":"SARCO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7697b462a7c4ff5f8b55bdbc2f4076c2af9cf51a","decimalCount":18}]},{"id":"footballstars","name":"FootballStars","symbol":"FTS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x6507458bb53aec6be863161641ec28739c41cc97","decimalCount":18}]},{"id":"milk","name":"Cool Cats Milk","symbol":"MILK","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x1599fe55cda767b1f631ee7d414b41f5d6de393d","decimalCount":18}]},{"id":"polkawar","name":"PolkaWar","symbol":"PWAR","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x16153214e683018d5aa318864c8e692b66e16778","decimalCount":18}]},{"id":"husky-avax","name":"Husky AVAX","symbol":"HUSKY","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x52d88a9a2a20a840d7a336d21e427e9ad093deea","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x65378b697853568da9ff8eab60c13e1ee9f4a654","decimalCount":18}]},{"id":"digix-gold","name":"Digix Gold","symbol":"DGX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4f3afec4e5a3f2a6a1a411def7d7dfe50ee057bf","decimalCount":9}]},{"id":"hydro-protocol","name":"Hydro Protocol","symbol":"HOT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9af839687f6c94542ac5ece2e317daae355493a1","decimalCount":18}]},{"id":"invest-like-stakeborg-index","name":"Invest Like Stakeborg Index","symbol":"ILSI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0acc0fee1d86d2cd5af372615bf59b298d50cd69","decimalCount":18}]},{"id":"potcoin","name":"Potcoin","symbol":"POT","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0xd7c8469c7ec40f853da5f651de81b45aed47e5ab","decimalCount":18}]},{"id":"shih-tzu","name":"Shih Tzu","symbol":"SHIH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x841fb148863454a3b3570f515414759be9091465","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x1e8150ea46e2a7fbb795459198fbb4b35715196c","decimalCount":18}]},{"id":"onx-finance","name":"OnX Finance","symbol":"ONX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe0ad1806fd3e7edf6ff52fdb822432e847411033","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x3d8f74620857dd8ed6d0da02ceb13fd0ed8ba678","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xeb94a5e2c643403e29fa1d7197e7e0708b09ad84","decimalCount":18},{"networkId":"fantom","contractAddress":"0x27749e79ad796c4251e0a0564aef45235493a0b6","decimalCount":18}]},{"id":"ally-direct","name":"Ally Direct","symbol":"DRCT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9d561d63375672abd02119b9bc4fb90eb9e307ca","decimalCount":18}]},{"id":"stream-protocol","name":"Stream Protocol","symbol":"STPL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9b5c2be869a19e84bdbcb1386dad83a2ec8dae82","decimalCount":18}]},{"id":"skull","name":"Skull","symbol":"SKULL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbcc66ed2ab491e9ae7bf8386541fb17421fa9d35","decimalCount":4}]},{"id":"energyfi","name":"Energyfi","symbol":"EFT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xae98e63db1c4646bf5b40b29c664bc922f71bc65","decimalCount":18}]},{"id":"bullieverse","name":"Bullieverse","symbol":"BULL","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x9f95e17b2668afe01f8fbd157068b0a4405cc08d","decimalCount":18}]},{"id":"beach-token-bsc","name":"Beach BSC","symbol":"BEACH","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x1a57dc4e3bc63b06c2b263774859f227b99ab031","decimalCount":9}]},{"id":"fairgame","name":"FairGame","symbol":"FAIR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9b20dabcec77f6289113e61893f7beefaeb1990a","decimalCount":18}]},{"id":"zuki-moba","name":"Zuki Moba","symbol":"ZUKI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xe81257d932280ae440b17afc5f07c8a110d21432","decimalCount":18}]},{"id":"arth","name":"ARTH","symbol":"ARTH","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0xe52509181feb30eb4979e29ec70d50fd5c44d590","decimalCount":18}]},{"id":"swerve-dao","name":"Swerve","symbol":"SWRV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb8baa0e4287890a5f79863ab62b7f175cecbd433","decimalCount":18}]},{"id":"dav","name":"DAV Network","symbol":"DAV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd82df0abd3f51425eb15ef7580fda55727875f14","decimalCount":18}]},{"id":"cover-protocol","name":"Cover Protocol","symbol":"COVER","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4688a8b1f292fdab17e9a90c8bc379dc1dbd8713","decimalCount":18},{"networkId":"fantom","contractAddress":"0xb01e8419d842beebf1b70a7b5f7142abbaf7159d","decimalCount":18}]},{"id":"superlauncher-dao","name":"SuperLauncher DAO","symbol":"LAUNCH","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xb5389a679151c4b8621b1098c6e0961a3cfee8d4","decimalCount":18}]},{"id":"leonicorn-swap","name":"Leonicorn Swap","symbol":"LEOS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x2c8368f8f474ed9af49b87eac77061beb986c2f1","decimalCount":8}]},{"id":"carbon","name":"Carbon","symbol":"CRBN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcdeee767bed58c5325f68500115d4b722b3724ee","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x5a4fb10e7c4cbb9a2b9d9a942f9a875ebd3489ea","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x89ef0900b0a6b5548ab2ff58ef588f9433b5fcf5","decimalCount":18}]},{"id":"spaceswap-milk2","name":"Spaceswap MILK2","symbol":"MILK2","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x80c8c3dcfb854f9542567c8dac3f44d709ebc1de","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x4a5a34212404f30c5ab7eb61b078fa4a55adc5a5","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x721c299e6bf7d6a430d9bea3364ea197314bce09","decimalCount":18}]},{"id":"purefi","name":"PureFi","symbol":"UFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcda4e840411c00a614ad9205caec807c7458a0e3","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xe2a59d5e33c6540e18aaa46bf98917ac3158db0d","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x3c205c8b3e02421da82064646788c82f7bd753b9","decimalCount":18}]},{"id":"spice-finance","name":"SPICE","symbol":"SPICE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1fdab294eda5112b7d066ed8f2e4e562d5bcc664","decimalCount":18}]},{"id":"helmet-insure","name":"Helmet Insure","symbol":"HELMET","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x948d2a81086a075b3130bac19e4c6dee1d2e3fe8","decimalCount":18}]},{"id":"luxfi","name":"LuxFi","symbol":"LXF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa799c4adcf62e025ce4d8abe6a77cebc487d772a","decimalCount":18}]},{"id":"clintex-cti","name":"ClinTex CTi","symbol":"CTI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8c18d6a985ef69744b9d57248a45c0861874f244","decimalCount":18}]},{"id":"atn","name":"ATN","symbol":"ATN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x461733c17b0755ca5649b6db08b3e213fcf22546","decimalCount":18}]},{"id":"fsw-token","name":"Falconswap","symbol":"FSW","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfffffffff15abf397da76f1dcc1a1604f45126db","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xad5dc12e88c6534eea8cfe2265851d9d4a1472ad","decimalCount":18}]},{"id":"inmediate","name":"Direct Insurance Token","symbol":"DIT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf14922001a2fb8541a433905437ae954419c2439","decimalCount":8}]},{"id":"quiverx","name":"QuiverX","symbol":"QRX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6e0dade58d2d89ebbe7afc384e3e4f15b70b14d8","decimalCount":18}]},{"id":"dinoswap","name":"DinoSwap","symbol":"DINO","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0xaa9654becca45b5bdfa5ac646c939c62b527d394","decimalCount":18}]},{"id":"stone-token","name":"Stone Token","symbol":"STN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe63d6b308bce0f6193aec6b7e6eba005f41e36ab","decimalCount":18},{"networkId":"fantom","contractAddress":"0xfa9343c3897324496a05fc75abed6bac29f8a40f","decimalCount":18}]},{"id":"tryhards","name":"TryHards","symbol":"TRY","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x75d107de2217ffe2cd574a1b3297c70c8fafd159","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xefee2de82343be622dcb4e545f75a3b9f50c272d","decimalCount":18}]},{"id":"penguin-finance","name":"Penguin Finance","symbol":"PEFI","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0xe896cdeaac9615145c0ca09c8cd5c25bced6384c","decimalCount":18}]},{"id":"bright-union","name":"Bright Union","symbol":"BRIGHT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbeab712832112bd7664226db7cd025b153d3af55","decimalCount":18}]},{"id":"fortressdao","name":"Fortress","symbol":"FORT","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0xf6d46849db378ae01d93732585bec2c4480d1fd5","decimalCount":9}]},{"id":"genesis-vision","name":"Genesis Vision","symbol":"GVT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x103c3a209da59d3e7c4a89307e66521e081cfdf0","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf25868b9e9c62f12192650ac668a2aa69f965f44","decimalCount":18}]},{"id":"tastenft","name":"TasteNFT","symbol":"TASTE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xdb238123939637d65a03e4b2b485650b4f9d91cb","decimalCount":9}]},{"id":"tripcandy","name":"TripCandy","symbol":"CANDY","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x639ad7c49ec616a64e074c21a58608c0d843a8a3","decimalCount":18}]},{"id":"swarm","name":"Swarm Network","symbol":"SWM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3505f494c3f0fed0b594e01fa41dd3967645ca39","decimalCount":18}]},{"id":"raze-network","name":"Raze Network","symbol":"RAZE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5eaa69b29f99c84fe5de8200340b4e9b4ab38eac","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x65e66a61d0a8f1e686c2d6083ad611a10d84d97a","decimalCount":18}]},{"id":"nextexchange","name":"NEXT","symbol":"NEXT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x377d552914e7a104bc22b4f3b6268ddc69615be7","decimalCount":18}]},{"id":"portify","name":"Portify","symbol":"PFY","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x69083b64988933e8b4783e8302b9bbf90163280e","decimalCount":9}]},{"id":"pocket-arena","name":"Pocket Arena","symbol":"POC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x095cf7f3e82a1dcadbf0fbc59023f419883ea296","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x1b6609830c695f1c0692123bd2fd6d01f6794b98","decimalCount":18}]},{"id":"seen","name":"SEEN","symbol":"SEEN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xca3fe04c7ee111f0bbb02c328c699226acf9fd33","decimalCount":18}]},{"id":"playnity","name":"PlayNity","symbol":"PLY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x20d60c6eb195868d4643f2c9b0809e4de6cc003d","decimalCount":6},{"networkId":"binance-smart-chain","contractAddress":"0x5f39dd1bb6db20f3e792c4489f514794cac6392c","decimalCount":6}]},{"id":"night-life-crypto","name":"Night Life Crypto","symbol":"NLIFE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1951ab088141e69a3713a351b0d55ba3acda192c","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0x86cbbedca621ae78a421a40365081caafda24296","decimalCount":8}]},{"id":"eurocoinpay","name":"EurocoinToken","symbol":"ECTE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe9fa21e671bcfb04e6868784b89c19d5aa2424ea","decimalCount":18}]},{"id":"paypie","name":"PayPie","symbol":"PPP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc42209accc14029c1012fb5680d95fbd6036e2a0","decimalCount":18}]},{"id":"quasacoin","name":"Quasacoin","symbol":"QUA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4daeb4a06f70f4b1a5c329115731fe4b89c0b227","decimalCount":18}]},{"id":"ceres","name":"Ceres","symbol":"CERES","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2e7b0d4f9b2eaf782ed3d160e3a0a4b1a7930ada","decimalCount":18}]},{"id":"tanks","name":"Tanks","symbol":"TANKS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd20738760aededa73f6cd91a3d357746e0283a0e","decimalCount":18}]},{"id":"xfinance","name":"Xfinance","symbol":"XFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5befbb272290dd5b8521d4a938f6c4757742c430","decimalCount":18}]},{"id":"revault-network","name":"Revault Network","symbol":"REVA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4fdd92bd67acf0676bfc45ab7168b3996f7b4a3b","decimalCount":18}]},{"id":"dogewhale","name":"Dogewhale","symbol":"DOGEWHALE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x43adc41cf63666ebb1938b11256f0ea3f16e6932","decimalCount":18}]},{"id":"float-protocol","name":"Float Protocol","symbol":"BANK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x24a6a37576377f63f194caa5f518a60f45b42921","decimalCount":18}]},{"id":"citizen-finance-old","name":"Citizen Finance (OLD)","symbol":"CIFI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x89f2a5463ef4e4176e57eef2b2fdd256bf4bc2bd","decimalCount":18}]},{"id":"elpis-battle","name":"Elpis Battle","symbol":"EBA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x3944ac66b9b9b40a6474022d6962b6caa001b5e3","decimalCount":18}]},{"id":"bitball","name":"Bitball","symbol":"BTB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x06e0feb0d74106c7ada8497754074d222ec6bcdf","decimalCount":18}]},{"id":"vynk-chain","name":"VYNK Chain","symbol":"VYNC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xee1ae38be4ce0074c4a4a8dc821cc784778f378c","decimalCount":4},{"networkId":"binance-smart-chain","contractAddress":"0xee1ae38be4ce0074c4a4a8dc821cc784778f378c","decimalCount":4}]},{"id":"metafabric","name":"MetaFabric","symbol":"FABRIC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8c6fa66c21ae3fc435790e451946a9ea82e6e523","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x73ff5dd853cb87c144f463a555dce0e43954220d","decimalCount":18}]},{"id":"crd-network","name":"CRD Network","symbol":"CRD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcaaa93712bdac37f736c323c93d4d5fdefcc31cc","decimalCount":18}]},{"id":"ara-token","name":"Ara Token","symbol":"ARA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa92e7c82b11d10716ab534051b271d2f6aef7df5","decimalCount":18}]},{"id":"askobar-network","name":"Asko","symbol":"ASKO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xeeee2a622330e6d2036691e983dee87330588603","decimalCount":18}]},{"id":"mu-continent","name":"Mu Continent","symbol":"MU","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xce262761df57c72999146b7a6a752da03835db4a","decimalCount":9}]},{"id":"ixicash","name":"IxiCash","symbol":"IXI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x179cd91631d96e8fafee6a744eac6ffdbb923520","decimalCount":8}]},{"id":"coinary-token","name":"Coinary","symbol":"CYT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd9025e25bb6cf39f8c926a704039d2dd51088063","decimalCount":18}]},{"id":"demole","name":"Demole","symbol":"DMLG","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x1c796c140de269e255372ea687ef7644bab87935","decimalCount":18}]},{"id":"8pay","name":"8Pay","symbol":"8PAY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfeea0bdd3d07eb6fe305938878c0cadbfa169042","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xfeea0bdd3d07eb6fe305938878c0cadbfa169042","decimalCount":18}]},{"id":"metabrands","name":"MetaBrands","symbol":"MAGE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd52aae39a2b5cc7812f7b9450ebb61dfef702b15","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x921f99719eb6c01b4b8f0ba7973a7c24891e740a","decimalCount":18}]},{"id":"defidollar","name":"DefiDollar","symbol":"DUSD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5bc25f649fc4e26069ddf4cf4010f9f706c23831","decimalCount":18}]},{"id":"nidhi-dao","name":"Nidhi Dao","symbol":"GURU","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x057e0bd9b797f9eeeb8307b35dbc8c12e534c41e","decimalCount":9}]},{"id":"openalexa-protocol","name":"OpenAlexa Protocol","symbol":"OAP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1788430620960f9a70e3dc14202a3a35dde1a316","decimalCount":18}]},{"id":"integral","name":"Integral","symbol":"ITGR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd502f487e1841fdc805130e13eae80c61186bc98","decimalCount":18}]},{"id":"metaverse-nft-index","name":"Metaverse NFT Index","symbol":"PLAY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x33e18a092a93ff21ad04746c7da12e35d34dc7c4","decimalCount":18}]},{"id":"dogemon-go","name":"DogemonGo","symbol":"DOGO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x9e6b3e35c8f563b45d864f9ff697a144ad28a371","decimalCount":18},{"networkId":"solana","contractAddress":"5LSFpvLDkcdV2a3Kiyzmg5YmJsj2XDLySaXvnfP1cgLT","decimalCount":6}]},{"id":"domraider","name":"DomRaider","symbol":"DRT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9af4f26941677c706cfecf6d3379ff01bb85d5ab","decimalCount":8}]},{"id":"flypme","name":"FlypMe","symbol":"FYP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8f0921f30555624143d427b340b1156914882c10","decimalCount":18}]},{"id":"zeptagram","name":"Zeptacoin","symbol":"ZPTC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x39ae6d231d831756079ec23589d2d37a739f2e89","decimalCount":4},{"networkId":"binance-smart-chain","contractAddress":"0x39ae6d231d831756079ec23589d2d37a739f2e89","decimalCount":4}]},{"id":"reward-hunters-token","name":"Reward Hunters","symbol":"RHT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xf1018c71eebe32dd85012ad413bab6b940d0d51e","decimalCount":18}]},{"id":"parex","name":"Parex","symbol":"PRX","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x90e3414e00e231b962666bd94adb811d5bcd0c2a","decimalCount":8}]},{"id":"data-economy-index","name":"Data Economy Index","symbol":"DATA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x33d63ba1e57e54779f7ddaeaa7109349344cf5f1","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x1d607faa0a51518a7728580c238d912747e71f7a","decimalCount":18}]},{"id":"libra-credit","name":"LibraToken","symbol":"LBA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfe5f141bf94fe84bc28ded0ab966c16b17490657","decimalCount":18}]},{"id":"the-three-kingdoms","name":"The Three Kingdoms","symbol":"TTK","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x39703a67bac0e39f9244d97f4c842d15fbad9c1f","decimalCount":18}]},{"id":"centric-cash","name":"Centric Swap","symbol":"CNS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xf6cb4ad242bab681effc5de40f7c8ff921a12d63","decimalCount":8}]},{"id":"fabwelt","name":"Fabwelt","symbol":"WELT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x1785113910847770290f5f840b4c74fc46451201","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x23e8b6a3f6891254988b84da3738d2bfe5e703b9","decimalCount":18}]},{"id":"happycoin","name":"HappyCoin","symbol":"HAPPY","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xb0b924c4a31b7d4581a7f78f57cee1e65736be1d","decimalCount":9}]},{"id":"cat-token","name":"Cat Token","symbol":"CAT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x56015bbe3c01fe05bc30a8a9a9fd9a88917e7db3","decimalCount":18}]},{"id":"snovio","name":"Snovian.Space","symbol":"SNOV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbdc5bac39dbe132b1e030e898ae3830017d7d969","decimalCount":18}]},{"id":"pumapay","name":"PumaPay","symbol":"PMA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x846c66cf71c43f80403b51fe3906b3599d63336f","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x43a167b15a6f24913a8b4d35488b36ac15d39200","decimalCount":18}]},{"id":"surf-finance","name":"Surf.Finance","symbol":"SURF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xea319e87cf06203dae107dd8e5672175e3ee976c","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x1e42edbe5376e717c1b22904c59e406426e8173f","decimalCount":18}]},{"id":"decubate","name":"Decubate","symbol":"DCB","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xeac9873291ddaca754ea5642114151f3035c67a2","decimalCount":18}]},{"id":"cryptozoon","name":"CryptoZoon","symbol":"ZOON","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x9d173e6c594f479b4d47001f8e6a95a7adda42bc","decimalCount":18}]},{"id":"beach-token","name":"Beach","symbol":"BEACH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbd15c4c8cd28a08e43846e3155c01a1f648d8d42","decimalCount":9}]},{"id":"polyient-games-governance-token","name":"Polyient Games Governance Token","symbol":"PGT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xeaccb6e0f24d66cf4aa6cbda33971b9231d332a1","decimalCount":18}]},{"id":"genesis-worlds","name":"Genesis Worlds","symbol":"GENESIS","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x51869836681bce74a514625c856afb697a013797","decimalCount":18}]},{"id":"octofi","name":"OctoFi","symbol":"OCTO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7240ac91f01233baaf8b064248e80feaa5912ba3","decimalCount":18},{"networkId":"fantom","contractAddress":"0x639a647fbe20b6c8ac19e48e2de44ea792c62c5c","decimalCount":18}]},{"id":"subme","name":"Subme","symbol":"SUB","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xfd290c590866f8282d89671a85ac9964b165d682","decimalCount":4}]},{"id":"shoot","name":"SHOOT","symbol":"SHOO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x0fcc11f873360450a1afd8cb7cfe0a9d787cc25e","decimalCount":18}]},{"id":"redpanda-earth","name":"RedPanda Earth","symbol":"REDPANDA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x514cdb9cd8a2fb2bdcf7a3b8ddd098caf466e548","decimalCount":9}]},{"id":"momento","name":"Momento","symbol":"MOMENTO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0ae8b74cd2d566853715800c9927f879d6b76a37","decimalCount":9},{"networkId":"binance-smart-chain","contractAddress":"0x1b9a8c4f2df5dc7b8744b1a170d8d727360c67ee","decimalCount":9}]},{"id":"snetwork","name":"Snetwork","symbol":"SNET","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xff19138b039d938db46bdda0067dc4ba132ec71c","decimalCount":8}]},{"id":"debitum-network","name":"Debitum Network","symbol":"DEB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x151202c9c18e495656f372281f493eb7698961d5","decimalCount":18}]},{"id":"seba","name":"Seba","symbol":"SEBA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd15d3baf3f40988810c5f9da54394ffb5246ded6","decimalCount":18}]},{"id":"gsenetwork","name":"GSENetwork","symbol":"GSE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe530441f4f73bdb6dc2fa5af7c3fc5fd551ec838","decimalCount":4}]},{"id":"empty-set-dollar","name":"Empty Set Dollar","symbol":"ESD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x36f3fd68e7325a35eb768f1aedaae9ea0689d723","decimalCount":18}]},{"id":"my-master-war","name":"My Master War","symbol":"MAT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xf3147987a00d35eecc10c731269003ca093740ca","decimalCount":18}]},{"id":"battle-pets","name":"Battle Pets","symbol":"PET","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4d4e595d643dc61ea7fcbf12e4b1aaa39f9975b8","decimalCount":18}]},{"id":"tribeone","name":"TribeOne","symbol":"HAKA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd85ad783cc94bd04196a13dc042a3054a9b52210","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xd85ad783cc94bd04196a13dc042a3054a9b52210","decimalCount":18}]},{"id":"templardao","name":"Templar DAO","symbol":"TEM","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x19e6bfc1a6e4b042fb20531244d47e252445df01","decimalCount":9}]},{"id":"linkeye","name":"Linkeye","symbol":"LET","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfa3118b34522580c35ae27f6cf52da1dbb756288","decimalCount":6}]},{"id":"fantom-maker","name":"Fantom Maker","symbol":"FAME","active":true,"networks":[{"networkId":"fantom","contractAddress":"0x904f51a2e7eeaf76aaf0418cbaf0b71149686f4a","decimalCount":18}]},{"id":"aircoin-2","name":"AirCoin","symbol":"AIR","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd8a2ae43fd061d24acd538e3866ffc2c05151b53","decimalCount":18}]},{"id":"handle-fi","name":"handle.fi","symbol":"FOREX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdb298285fe4c5410b05390ca80e8fbe9de1f259b","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xdb298285fe4c5410b05390ca80e8fbe9de1f259b","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xdb298285fe4c5410b05390ca80e8fbe9de1f259b","decimalCount":18}]},{"id":"thorus","name":"Thorus","symbol":"THO","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0xae4aa155d2987b454c29450ef4f862cf00907b61","decimalCount":18}]},{"id":"babylons","name":"Babylons","symbol":"BABI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xec15a508a187e8ddfe572a5423faa82bbdd65120","decimalCount":18}]},{"id":"power-index-pool-token","name":"Power Index Pool Token","symbol":"PIPT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x26607ac599266b21d13c7acf7942c7701a8b699c","decimalCount":18}]},{"id":"face","name":"Faceter","symbol":"FACE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1ccaa0f2a7210d76e1fdec740d5f323e2e1b1672","decimalCount":18}]},{"id":"market-ledger","name":"Market Ledger","symbol":"ML","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xc4fb957e3f1c04c8dc4000525e55920861f25bfc","decimalCount":18}]},{"id":"milkshakeswap","name":"Milkshake Swap","symbol":"MILK","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xc9bcf3f71e37579a4a42591b09c9dd93dfe27965","decimalCount":18}]},{"id":"rise-of-defenders","name":"Rise of Defenders","symbol":"RDR","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x92da433da84d58dfe2aade1943349e491cbd6820","decimalCount":18}]},{"id":"pop-chest-token","name":"POP Network","symbol":"POP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5d858bcd53e085920620549214a8b27ce2f04670","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x1bb76a939d6b7f5be6b95c4f9f822b02b4d62ced","decimalCount":18}]},{"id":"evedo","name":"Evedo","symbol":"EVED","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5aaefe84e0fb3dd1f0fcff6fa7468124986b91bd","decimalCount":18}]},{"id":"overlord","name":"Overlord","symbol":"LORD","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x2daf1a83aa348afbcbc73f63bb5ee3154d9f5776","decimalCount":18}]},{"id":"talecraft","name":"TaleCraft","symbol":"CRAFT","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x8ae8be25c23833e0a01aa200403e826f611f9cd2","decimalCount":18}]},{"id":"synchrolife","name":"SynchroLife","symbol":"SYC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe49214e4c92dc9bcb3b56c1309afe0d626dd730e","decimalCount":18}]},{"id":"golff","name":"Golff","symbol":"GOF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x488e0369f9bc5c40c002ea7c1fe4fd01a198801c","decimalCount":18}]},{"id":"wallstreetninja","name":"WallStreetNinja","symbol":"WSN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x7fa4cd8aeedcb8d36dbc5d856e3a1bee490d7b36","decimalCount":18}]},{"id":"gny","name":"GNY","symbol":"GNY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb1f871ae9462f1b2c6826e88a7827e76f86751d4","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xe4a4ad6e0b773f47d28f548742a23efd73798332","decimalCount":18}]},{"id":"exmo-coin","name":"EXMO Coin","symbol":"EXM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x83869de76b9ad8125e22b857f519f001588c0f62","decimalCount":8}]},{"id":"luna-rush","name":"Luna Rush","symbol":"LUS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xde301d6a2569aefcfe271b9d98f318baee1d30a4","decimalCount":18}]},{"id":"polylauncher","name":"Polylauncher","symbol":"ANGEL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6c7b97c7e09e790d161769a52f155125fac6d5a1","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x0b6afe834dab840335f87d99b45c2a4bd81a93c7","decimalCount":18}]},{"id":"bondappetite-usd","name":"BondAppetite USD","symbol":"USDAP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9a1997c130f4b2997166975d9aff92797d5134c2","decimalCount":18}]},{"id":"nuco-cloud","name":"Nuco.Cloud","symbol":"NCDT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe0c8b298db4cffe05d1bea0bb1ba414522b33c1b","decimalCount":18}]},{"id":"ideas","name":"IDEAS","symbol":"IDS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x1c61a220a0f1dfc750d28188a97a6c7bf14e9851","decimalCount":18}]},{"id":"archer-dao-governance-token","name":"Archer DAO Governance Token","symbol":"ARCH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1f3f9d3068568f8040775be2e8c03c103c61f3af","decimalCount":18}]},{"id":"sav3","name":"SAV3","symbol":"SAV3","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6e10aacb89a28d6fa0fe68790777fec7e7f01890","decimalCount":18}]},{"id":"polinate","name":"Polinate","symbol":"POLI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa1a36d3537bbe375cc9694795f663ddc8d516db9","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x6fb54ffe60386ac33b722be13d2549dd87bf63af","decimalCount":18}]},{"id":"omni-real-estate-token","name":"Omni Real Estate Token","symbol":"ORT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x1d64327c74d6519afef54e58730ad6fc797f05ba","decimalCount":18}]},{"id":"dmm-governance","name":"DMM: Governance","symbol":"DMG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xed91879919b71bb6905f23af0a68d231ecf87b14","decimalCount":18}]},{"id":"iot-chain","name":"IoT Chain","symbol":"ITC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5e6b6d9abad9093fdc861ea1600eba1b355cd940","decimalCount":18}]},{"id":"finance-vote","name":"Finance Vote","symbol":"FVT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x45080a6531d671ddff20db42f93792a489685e32","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x0a232cb2005bda62d3de7ab5deb3ffe4c456165a","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x72a5a58f79ffc2102227b92faeba93b169a3a3f1","decimalCount":18}]},{"id":"mirrored-invesco-qqq-trust","name":"Mirrored Invesco QQQ Trust","symbol":"MQQQ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x13b02c8de71680e71f0820c996e4be43c2f57d15","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x1cb4183ac708e07511ac57a2e45a835f048d7c56","decimalCount":18}]},{"id":"yieldwatch","name":"Yieldwatch","symbol":"WATCH","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x7a9f28eb62c791422aa23ceae1da9c847cbec9b0","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x09211dc67f9fe98fb7bbb91be0ef05f4a12fa2b2","decimalCount":18}]},{"id":"roseon-finance","name":"Roseon Finance","symbol":"ROSN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x651cd665bd558175a956fb3d72206ea08eb3df5b","decimalCount":18}]},{"id":"piedao-defi-large-cap","name":"PieDAO DEFI Large Cap","symbol":"DEFI+L","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x78f225869c08d478c34e5f645d07a87d3fe8eb78","decimalCount":18}]},{"id":"infinito","name":"Infinito","symbol":"INFT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x83d60e7aed59c6829fb251229061a55f35432c4d","decimalCount":6}]},{"id":"nafter","name":"Nafter","symbol":"NAFT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd7730681b1dc8f6f969166b29d8a5ea8568616a3","decimalCount":18}]},{"id":"daostack","name":"DAOstack","symbol":"GEN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x543ff227f64aa17ea132bf9886cab5db55dcaddf","decimalCount":18}]},{"id":"mobifi","name":"MobiFi","symbol":"MOFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb2dbf14d0b47ed3ba02bdb7c954e05a72deb7544","decimalCount":18}]},{"id":"oikos","name":"Oikos","symbol":"OKS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x18acf236eb40c0d4824fb8f2582ebbecd325ef6a","decimalCount":18}]},{"id":"megacryptopolis","name":"MegaCryptoPolis","symbol":"MEGA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3218a02f8f8b5c3894ce30eb255f10bcba13e654","decimalCount":18}]},{"id":"cook","name":"Cook","symbol":"COOK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xff75ced57419bcaebe5f05254983b013b0646ef5","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x965b0df5bda0e7a0649324d78f03d5f7f2de086a","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x637afeff75ca669ff92e4570b14d6399a658902f","decimalCount":18}]},{"id":"defire","name":"DeFIRE","symbol":"CWAP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe74dc43867e0cbeb208f1a012fc60dcbbf0e3044","decimalCount":18}]},{"id":"hoqu","name":"HOQU","symbol":"HQX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1b957dc4aefeed3b4a2351a6a6d5cbfbba0cecfa","decimalCount":18}]},{"id":"zippie","name":"Zippie","symbol":"ZIPT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xedd7c94fd7b4971b916d15067bc454b9e1bad980","decimalCount":18}]},{"id":"verve","name":"Verve","symbol":"VERVE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x32561fa6d2d3e2191bf50f813df2c34fb3c89b62","decimalCount":18}]},{"id":"vault-hill-city","name":"Vault Hill City","symbol":"VHC","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x51b5619f5180e333d18b6310c8d540aea43a0371","decimalCount":18}]},{"id":"fintrux","name":"FintruX","symbol":"FTX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd559f20296ff4895da39b5bd9add54b442596a61","decimalCount":18}]},{"id":"wicrypt","name":"Wicrypt","symbol":"WNT","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x82a0e6c02b91ec9f6ff943c0a933c03dbaa19689","decimalCount":18}]},{"id":"cub-finance","name":"Cub Finance","symbol":"CUB","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x50d809c74e0b8e49e7b4c65bb3109abe3ff4c1c1","decimalCount":18}]},{"id":"onering","name":"OneRing","symbol":"RING","active":true,"networks":[{"networkId":"fantom","contractAddress":"0x582423c10c9e83387a96d00a69ba3d11ee47b7b5","decimalCount":18}]},{"id":"origin-sport","name":"Origin Sport","symbol":"ORS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xeb9a4b185816c354db92db09cc3b50be60b901b6","decimalCount":18}]},{"id":"ghostmarket","name":"GhostMarket","symbol":"GM","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x0b53b5da7d0f275c31a6a182622bdf02474af253","decimalCount":8},{"networkId":"polygon-pos","contractAddress":"0x6a335ac6a3cdf444967fe03e7b6b273c86043990","decimalCount":8}]},{"id":"acestarter","name":"AceStarter","symbol":"ASTAR","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x9eeddb9da3bcbfdcfbf075441a9e14c6a8899999","decimalCount":18}]},{"id":"komet","name":"Komet","symbol":"KOMET","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6cfb6df56bbdb00226aeffcdb2cd1fe8da1abda7","decimalCount":18}]},{"id":"cave","name":"Crypto Cavemen","symbol":"CAVE","active":true,"networks":[{"networkId":"solana","contractAddress":"4SZjjNABoqhbd4hnapbvoEPEqT8mnNkfbEoAwALf1V8t","decimalCount":6}]},{"id":"ultralpha","name":"UltrAlpha","symbol":"UAT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x01c0987e88f778df6640787226bc96354e1a9766","decimalCount":18}]},{"id":"crypto-phoenix","name":"Crypto Phoenix","symbol":"CPHX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8689d850cdf3b74a1f6a5eb60302c785b71c2fc7","decimalCount":18}]},{"id":"dprating","name":"DPRating","symbol":"RATING","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe8663a64a96169ff4d95b4299e7ae9a76b905b31","decimalCount":8}]},{"id":"bobs_repair","name":"Bob's Repair","symbol":"BOB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdf347911910b6c9a4286ba8e2ee5ea4a39eb2134","decimalCount":18}]},{"id":"openswap","name":"OpenSwap","symbol":"OSWAP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb32ac3c79a94ac1eb258f3c830bbdbc676483c93","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xb32ac3c79a94ac1eb258f3c830bbdbc676483c93","decimalCount":18}]},{"id":"fire-lotto","name":"Fire Lotto","symbol":"FLOT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x049399a6b048d52971f7d122ae21a1532722285f","decimalCount":18}]},{"id":"release-ico-project","name":"RELEASE","symbol":"REL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x61bfc979ea8160ede9b862798b7833a97bafa02a","decimalCount":18}]},{"id":"value-liquidity","name":"Value DeFi","symbol":"VALUE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x49e833337ece7afe375e44f4e3e8481029218e5c","decimalCount":18}]},{"id":"waultswap-polygon","name":"WaultSwap Polygon","symbol":"WEXPOLY","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x4c4bf319237d98a30a929a96112effa8da3510eb","decimalCount":18}]},{"id":"butterfly-protocol-2","name":"Butterfly Protocol","symbol":"BFLY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf680429328caaacabee69b7a9fdb21a71419c063","decimalCount":18}]},{"id":"indahash","name":"indaHash","symbol":"IDH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5136c98a80811c3f46bdda8b5c4555cfd9f812f0","decimalCount":6}]},{"id":"spherium","name":"Spherium","symbol":"SPHRI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8a0cdfab62ed35b836dc0633482798421c81b3ec","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x8ea93d00cc6252e2bd02a34782487eed65738152","decimalCount":18}]},{"id":"revain","name":"Revain","symbol":"REV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2ef52ed7de8c5ce03a4ef0efbe9b7450f2d7edc9","decimalCount":6}]},{"id":"moneytoken","name":"MoneyToken","symbol":"IMT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x13119e34e140097a507b07a5564bde1bc375d9e6","decimalCount":18}]},{"id":"zero-exchange","name":"0.exchange","symbol":"ZERO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf0939011a9bb95c3b791f0cb546377ed2693a574","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x1f534d2b1ee2933f1fdf8e4b63a44b2249d77eaf","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x008e26068b3eb40b443d3ea88c1ff99b789c10f7","decimalCount":18}]},{"id":"privapp-network","name":"Privapp Network","symbol":"BPRIVA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd0f4afa85a667d27837e9c07c81169869c16dd16","decimalCount":8}]},{"id":"xmooney","name":"xMooney","symbol":"XM","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x98631c69602083d04f83934576a53e2a133d482f","decimalCount":9}]},{"id":"paint","name":"MurAll","symbol":"PAINT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4c6ec08cf3fc987c6c4beb03184d335a2dfc4042","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x7c28f627ea3aec8b882b51eb1935f66e5b875714","decimalCount":18}]},{"id":"niftify","name":"Niftify","symbol":"NIFT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4a1d542b52a95ad01ddc70c2e7df0c7bbaadc56f","decimalCount":18}]},{"id":"pancake-hunny","name":"Hunny Finance","symbol":"HUNNY","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x565b72163f17849832a692a3c5928cc502f46d69","decimalCount":18}]},{"id":"echidna","name":"Echidna","symbol":"ECD","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0xeb8343d5284caec921f035207ca94db6baaacbcd","decimalCount":18}]},{"id":"governor-dao","name":"Governor DAO","symbol":"GDAO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x515d7e9d75e2b76db60f8a051cd890eba23286bc","decimalCount":18}]},{"id":"metawars","name":"MetaWars","symbol":"WARS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x50e756a22ff5cee3559d18b9d9576bc38f09fa7c","decimalCount":18}]},{"id":"kaka-nft-world","name":"KAKA NFT World","symbol":"KAKA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x26a1bdfa3bb86b2744c4a42ebfdd205761d13a8a","decimalCount":18}]},{"id":"skrumble-network","name":"Skrumble Network","symbol":"SKM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x048fe49be32adfc9ed68c37d32b5ec9df17b3603","decimalCount":18}]},{"id":"public-index-network","name":"Public Index Network","symbol":"PIN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc1f976b91217e240885536af8b63bc8b5269a9be","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x3b79a28264fc52c7b4cea90558aa0b162f7faf57","decimalCount":18}]},{"id":"polkaparty","name":"PolkaParty","symbol":"POLP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x48592de8cded16f6bb56c896fe1affc37630889c","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x6e3bf2fff13e18413d3780f93753d6cff5aee3e1","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x2d72a97a31dc920db03330780d30074626e39c8a","decimalCount":18}]},{"id":"beatbind","name":"BeatBind","symbol":"BBND","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbc0d84fa6260e065f330d51621d682d2630f4aa2","decimalCount":18}]},{"id":"dexsport","name":"Dexsport","symbol":"DESU","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x32f1518baace69e85b9e5ff844ebd617c52573ac","decimalCount":18}]},{"id":"azuki","name":"Azuki","symbol":"AZUKI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x910524678c0b1b23ffb9285a81f99c29c11cbaed","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x7cdc0421469398e0f3aa8890693d86c840ac8931","decimalCount":18}]},{"id":"mirrored-microsoft","name":"Mirrored Microsoft","symbol":"MMSFT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x41bbedd7286daab5910a1f15d12cbda839852bd7","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x0ab06caa3ca5d6299925efaa752a2d2154ece929","decimalCount":18}]},{"id":"x8-project","name":"X8X Token","symbol":"X8X","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x910dfc18d6ea3d6a7124a6f8b5458f281060fa4c","decimalCount":18}]},{"id":"trustfi-network-token","name":"TrustFi Network","symbol":"TFI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x7565ab68d3f9dadff127f864103c8c706cf28235","decimalCount":18}]},{"id":"abcc-token","name":"ABCC Token","symbol":"AT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbf8fb919a8bbf28e590852aef2d284494ebc0657","decimalCount":18}]},{"id":"evereth","name":"EverETH","symbol":"EVERETH","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x16dcc0ec78e91e868dca64be86aec62bf7c61037","decimalCount":9}]},{"id":"exrt-network","name":"EXRT Network","symbol":"EXRT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb20043f149817bff5322f1b928e89abfc65a9925","decimalCount":8}]},{"id":"the-fire-token","name":"The Fire","symbol":"XFR","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x11c3f759c0aae61078ec923af15f2f6fa2d326ce","decimalCount":18}]},{"id":"sapien","name":"Sapien","symbol":"SPN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x20f7a3ddf244dc9299975b4da1c39f8d5d75f05a","decimalCount":6}]},{"id":"graphene","name":"Graphene","symbol":"GFN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xf209ce1960fb7e750ff30ba7794ea11c6acdc1f3","decimalCount":18}]},{"id":"trava-finance","name":"Trava Finance","symbol":"TRAVA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x0391be54e72f7e001f6bbc331777710b4f2999ef","decimalCount":18},{"networkId":"fantom","contractAddress":"0x477a9d5df9beda06f6b021136a2efe7be242fcc9","decimalCount":18}]},{"id":"denarius","name":"Denarius","symbol":"D","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xf6b53b4c982b9b7e87af9dc5c66c85117a5df303","decimalCount":8}]},{"id":"essentia","name":"Essentia","symbol":"ESS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfc05987bd2be489accf0f509e44b0145d68240f7","decimalCount":18}]},{"id":"centaur","name":"Centaur","symbol":"CNTR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x03042482d64577a7bdb282260e2ea4c8a89c064b","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xdae89da41a96956e9e70320ac9c0dd077070d3a5","decimalCount":18}]},{"id":"darwinia-commitment-token","name":"Darwinia Commitment Token","symbol":"KTON","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9f284e1337a815fe77d2ff4ae46544645b20c5ff","decimalCount":18}]},{"id":"nsure-network","name":"Nsure Network","symbol":"NSURE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x20945ca1df56d237fd40036d47e866c7dccd2114","decimalCount":18}]},{"id":"defidollar-dao","name":"DefiDollar DAO","symbol":"DFD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x20c36f062a31865bed8a5b1e512d9a1a20aa333a","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x9899a98b222fcb2f3dbee7df45d943093a4ff9ff","decimalCount":18}]},{"id":"mirrored-alibaba","name":"Mirrored Alibaba","symbol":"MBABA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x56aa298a19c93c6801fdde870fa63ef75cc0af72","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xca2f75930912b85d8b2914ad06166483c0992945","decimalCount":18}]},{"id":"ten","name":"TEN","symbol":"TENFI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd15c444f1199ae72795eba15e8c1db44e47abf62","decimalCount":18}]},{"id":"kingdom-game-4-0","name":"Kingdom Game 4.0","symbol":"KDG","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x87a2d9a9a6b2d61b2a57798f1b4b2ddd19458fb6","decimalCount":18}]},{"id":"widiland","name":"WidiLand","symbol":"WIDI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xa361c79783833524dc7838399a4862b5f47038b8","decimalCount":18}]},{"id":"soakmont","name":"Soakmont","symbol":"SOAK","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x841dc7a49e0825bdf3ee585cfb6e553495915ace","decimalCount":18}]},{"id":"darleygo-essence","name":"DarleyGo Essence","symbol":"DGE","active":true,"networks":[{"networkId":"solana","contractAddress":"AAXng5czWLNtTXHdWEn9Ef7kXMXEaraHj2JQKo7ZoLux","decimalCount":9}]},{"id":"dark-magic","name":"Dark Magic","symbol":"DMAGIC","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x61daecab65ee2a1d5b6032df030f3faa3d116aa7","decimalCount":18}]},{"id":"pixl-coin-2","name":"Pixl Coin","symbol":"PXLC","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x72d2946094e6e57c2fade4964777a9af2b7a51f9","decimalCount":9}]},{"id":"simple-token","name":"OST","symbol":"OST","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2c4e8f2d746113d0696ce89b35f0d8bf88e0aeca","decimalCount":18}]},{"id":"safemooncash","name":"SafeMoonCash","symbol":"SAFEMOONCASH","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xf017e2773e4ee0590c81d79ccbcf1b2de1d22877","decimalCount":9}]},{"id":"spores-network","name":"Spores Network","symbol":"SPO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcbe771323587ea16dacb6016e269d7f08a7acc4e","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x8357c604c5533fa0053beaaa1494da552cea38f7","decimalCount":18}]},{"id":"defactor","name":"Defactor","symbol":"FACTR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdefac16715671b7b6aeefe012125f1e19ee4b7d7","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xdefac16715671b7b6aeefe012125f1e19ee4b7d7","decimalCount":18}]},{"id":"project-oasis","name":"ProjectOasis","symbol":"OASIS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xb19289b436b2f7a92891ac391d8f52580d3087e4","decimalCount":18}]},{"id":"mrweb-finance","name":"MrWeb Finance","symbol":"AMA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xfc3da4a1b6fadab364039525dd2ab7c0c16521cd","decimalCount":18},{"networkId":"tron","contractAddress":"TVocZFCRZ6tg8MqKCKXzZ9H2qSg29T75tK","decimalCount":6}]},{"id":"sether","name":"Sether","symbol":"SETH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x78b039921e84e726eb72e7b1212bb35504c645ca","decimalCount":18}]},{"id":"kawakami","name":"Kawakami","symbol":"KAWA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5552e5a89a70cb2ef5adbbc45a6be442fe7160ec","decimalCount":18}]},{"id":"rocki","name":"Rocki","symbol":"ROCKI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xff44b937788215eca197baaf9af69dbdc214aa04","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xa01000c52b234a92563ba61e5649b7c76e1ba0f3","decimalCount":18}]},{"id":"piedao-defi","name":"PieDAO DEFI++","symbol":"DEFI++","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8d1ce361eb68e9e05573443c407d4a3bed23b033","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x5b6ab5078bd2bbf1a215fffba16a94b7df7f639d","decimalCount":18}]},{"id":"blizz-finance","name":"Blizz Finance","symbol":"BLZZ","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x0f34919404a290e71fc6a510cb4a6acb8d764b24","decimalCount":18}]},{"id":"nanjcoin","name":"NANJCOIN","symbol":"NANJ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xffe02ee4c69edf1b340fcad64fbd6b37a7b9e265","decimalCount":8}]},{"id":"multiplier","name":"Multiplier","symbol":"MXX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8a6f3bf52a26a21531514e23016eeae8ba7e7018","decimalCount":8}]},{"id":"franklin","name":"Franklin","symbol":"FLY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x85f6eb2bd5a062f5f8560be93fb7147e16c81472","decimalCount":4},{"networkId":"binance-smart-chain","contractAddress":"0x681fd3e49a6188fc526784ee70aa1c269ee2b887","decimalCount":4}]},{"id":"2key","name":"2key.network","symbol":"2KEY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe48972fcd82a274411c01834e2f031d4377fa2c0","decimalCount":18}]},{"id":"matrix-2","name":"Matrix","symbol":"MTIX","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x33b783a4833f7613ccb6569a9f39a261b311afbb","decimalCount":9}]},{"id":"spore","name":"Spore","symbol":"SPORE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x33a3d962955a3862c8093d1273344719f03ca17c","decimalCount":9},{"networkId":"avalanche","contractAddress":"0x6e7f5c0b9f4432716bdd0a77a3601291b9d9e985","decimalCount":9}]},{"id":"calicoin","name":"CaliCoin","symbol":"CALI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb8fa12f8409da31a4fc43d15c4c78c33d8213b9b","decimalCount":18}]},{"id":"coldstack","name":"Coldstack","symbol":"CLS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x675bbc7514013e2073db7a919f6e4cbef576de37","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x668048e70284107a6afab1711f28d88df3e72948","decimalCount":18}]},{"id":"iron-bank","name":"Iron Bank","symbol":"IB","active":true,"networks":[{"networkId":"fantom","contractAddress":"0x00a35fd824c717879bf370e70ac6868b95870dfb","decimalCount":18}]},{"id":"hitchain","name":"HitChain","symbol":"HIT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7995ab36bb307afa6a683c24a25d90dc1ea83566","decimalCount":6}]},{"id":"wings","name":"Wings","symbol":"WINGS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x667088b212ce3d06a1b553a7221e1fd19000d9af","decimalCount":18}]},{"id":"crystl-finance","name":"Crystl Finance","symbol":"CRYSTL","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x76bf0c28e604cc3fe9967c83b3c3f31c213cfe64","decimalCount":18}]},{"id":"menlo-one","name":"Menlo One","symbol":"ONE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4d807509aece24c0fa5a102b6a3b059ec6e14392","decimalCount":18}]},{"id":"play-it-forward-dao","name":"Play It Forward DAO","symbol":"PIF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb30f5d11b94efbbfdeaa4de38edffceec0be6513","decimalCount":18}]},{"id":"landshare","name":"Landshare","symbol":"LAND","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x9d986a3f147212327dd658f712d5264a73a1fdb0","decimalCount":18}]},{"id":"bgogo","name":"Bgogo Token","symbol":"BGG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xea54c81fe0f72de8e86b6dc78a9271aa3925e3b5","decimalCount":18}]},{"id":"dehive","name":"DeHive","symbol":"DHV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x62dc4817588d53a056cbbd18231d91ffccd34b2a","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x58759dd469ae5631c42cf8a473992335575b58d7","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x5fcb9de282af6122ce3518cde28b7089c9f97b26","decimalCount":18}]},{"id":"marginswap","name":"Marginswap","symbol":"MFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaa4e3edb11afa93c41db59842b29de64b72e355b","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x9fda7ceec4c18008096c2fe2b85f05dc300f94d0","decimalCount":18}]},{"id":"forefront","name":"Forefront","symbol":"FF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7e9d8f07a64e363e97a648904a89fb4cd5fb94cd","decimalCount":18}]},{"id":"bittoken","name":"BITToken","symbol":"BITT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9f9913853f749b3fe6d6d4e16a1cc3c1656b6d51","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x518445f0db93863e5e93a7f70617c05afa8048f1","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xfd0cbddec28a93bb86b9db4a62258f5ef25fefde","decimalCount":18}]},{"id":"dos-network","name":"DOS Network","symbol":"DOS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0a913bead80f321e7ac35285ee10d9d922659cb7","decimalCount":18}]},{"id":"arcs","name":"ARCS","symbol":"ARX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7d8daff6d70cead12c6f077048552cf89130a2b1","decimalCount":18}]},{"id":"complifi","name":"CompliFi","symbol":"COMFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x752efadc0a7e05ad1bcccda22c141d01a75ef1e4","decimalCount":18}]},{"id":"flixxo","name":"Flixxo","symbol":"FLIXX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf04a8ac553fcedb5ba99a64799155826c136b0be","decimalCount":18}]},{"id":"food-farmer-finance","name":"Food Farmer Finance","symbol":"FFF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc16b2419494ae0604432297d40cdf0e8d68de8d6","decimalCount":18},{"networkId":"fantom","contractAddress":"0xc16b2419494ae0604432297d40cdf0e8d68de8d6","decimalCount":18}]},{"id":"solanax","name":"Solanax","symbol":"SOLD","active":true,"networks":[{"networkId":"solana","contractAddress":"5v6tZ1SiAi7G8Qg4rBF1ZdAn4cn6aeQtefewMr1NLy61","decimalCount":9}]},{"id":"hummingbot","name":"Hummingbot","symbol":"HBOT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe5097d9baeafb89f9bcb78c9290d545db5f9e9cb","decimalCount":18}]},{"id":"goose-finance","name":"Goose Finance","symbol":"EGG","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xf952fc3ca7325cc27d15885d37117676d25bfda6","decimalCount":18}]},{"id":"delta-theta","name":"delta.theta","symbol":"DLTA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0000000de40dfa9b17854cbc7869d80f9f98d823","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x3a06212763caf64bf101daa4b0cebb0cd393fa1a","decimalCount":18}]},{"id":"superbid","name":"SuperBid","symbol":"SUPERBID","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0563dce613d559a47877ffd1593549fb9d3510d6","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xee9762352f63f4387af40d58291612067727457d","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xa3860f969075045d82de85b06bb665f93c4bae32","decimalCount":18}]},{"id":"aga-token","name":"AGA Token","symbol":"AGA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2d80f5f5328fdcb6eceb7cacf5dd8aedaec94e20","decimalCount":4},{"networkId":"binance-smart-chain","contractAddress":"0x976e33b07565b0c05b08b2e13affd3113e3d178d","decimalCount":4},{"networkId":"polygon-pos","contractAddress":"0x033d942a6b495c4071083f4cde1f17e986fe856c","decimalCount":4}]},{"id":"mywish","name":"MyWish","symbol":"WISH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd123575d94a7ad9bff3ad037ae9d4d52f41a7518","decimalCount":8},{"networkId":"binancecoin","contractAddress":"WISH-2D5","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0x8aed24bf6e0247be51c57d68ad32a176bf86f4d9","decimalCount":8}]},{"id":"starbots","name":"Starbots","symbol":"BOT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xdbccd9131405dd1fe7320090af337952b9845dfa","decimalCount":8}]},{"id":"cotrader","name":"CoTrader","symbol":"COT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5c872500c00565505f3624ab435c222e558e9ff8","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x304fc73e86601a61a6c6db5b0eafea587622acdc","decimalCount":18}]},{"id":"crypto-fight-club","name":"Crypto Fight Club","symbol":"FIGHT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4f39c3319188a723003670c3f9b9e7ef991e52f3","decimalCount":18}]},{"id":"berry-data","name":"Berry Data","symbol":"BRY","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xf859bf77cbe8699013d6dbc7c2b926aaf307f830","decimalCount":18}]},{"id":"definity","name":"DeFinity","symbol":"DEFX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5f474906637bdcda05f29c74653f6962bb0f8eda","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xbe4cb2c354480042a39350a0c6c26bf54786539f","decimalCount":18}]},{"id":"yield-protocol","name":"Yield Protocol","symbol":"YIELD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa8b61cff52564758a204f841e636265bebc8db9b","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf9d906a8dd25c4a4966bc075cdc946702219e62c","decimalCount":18}]},{"id":"shibavax","name":"Shibavax","symbol":"SHIBX","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x440abbf18c54b2782a4917b80a1746d3a2c2cce1","decimalCount":18}]},{"id":"merkle-network","name":"Merkle Network","symbol":"MERKLE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x000000000ca5171087c18fb271ca844a2370fc0a","decimalCount":18}]},{"id":"base-protocol","name":"Base Protocol","symbol":"BASE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x07150e919b4de5fd6a63de1f9384828396f25fdc","decimalCount":9}]},{"id":"nolimitcoin","name":"NoLimitCoin","symbol":"NLC","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x6519cb1f694ccbcc72417570b364f2d051eefb9d","decimalCount":8}]},{"id":"warena","name":"Warena","symbol":"RENA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xa9d75cc3405f0450955050c520843f99aff8749d","decimalCount":18}]},{"id":"rabbit-finance","name":"Rabbit Finance","symbol":"RABBIT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x95a1199eba84ac5f19546519e287d43d2f0e1b41","decimalCount":18}]},{"id":"minersdefi","name":"MinersDefi","symbol":"MINERS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xeb6b00f8c7e1da78fb919c810c30dde95475bdde","decimalCount":18}]},{"id":"nucleus-vision","name":"Nucleus Vision","symbol":"NCASH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x809826cceab68c387726af962713b64cb5cb3cca","decimalCount":18}]},{"id":"rainbowtoken","name":"RainbowToken","symbol":"RAINBOWTOKEN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x673da443da2f6ae7c5c660a9f0d3dd24d1643d36","decimalCount":9}]},{"id":"katalyo","name":"Katalyo","symbol":"KTLYO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x24e3794605c84e580eea4972738d633e8a7127c8","decimalCount":18}]},{"id":"polkally","name":"Kally","symbol":"KALLY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfd30c9bea1a952feeed2ef2c6b2ff8a8fc4aad07","decimalCount":18}]},{"id":"cockapoo","name":"Cockapoo","symbol":"CPOO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x71809c4ff017ceade03038a8b597ecabb6519918","decimalCount":18}]},{"id":"medicalchain","name":"Medicalchain","symbol":"MTN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x41dbecc1cdc5517c6f76f6a6e836adbee2754de3","decimalCount":18}]},{"id":"yee","name":"Yee","symbol":"YEE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x922105fad8153f516bcfb829f56dc097a0e1d705","decimalCount":18}]},{"id":"herofi","name":"HeroFi","symbol":"HEROEGG","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xcfbb1bfa710cb2eba070cc3bec0c35226fea4baf","decimalCount":18}]},{"id":"solidex","name":"Solidex","symbol":"SEX","active":true,"networks":[{"networkId":"fantom","contractAddress":"0xd31fcd1f7ba190dbc75354046f6024a9b86014d7","decimalCount":18}]},{"id":"definer","name":"DeFiner","symbol":"FIN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x054f76beed60ab6dbeb23502178c52d6c5debe40","decimalCount":18}]},{"id":"golden-ball","name":"Golden Ball","symbol":"GLB","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x52eb6c887a4691f10bee396778603927c23be1fc","decimalCount":9}]},{"id":"mobilego","name":"MobileGo","symbol":"MGO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x40395044ac3c0c57051906da938b54bd6557f212","decimalCount":8}]},{"id":"defiato","name":"DeFiato","symbol":"DFIAT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1045f5ccb01daea4f8eab055f5fcbb7c0e7c89f0","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf64ed9ad397a1ae657f31131d4b189220a7f1cc7","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xafe3d2a31231230875dee1fa1eef14a412443d22","decimalCount":18}]},{"id":"genesis-pool","name":"Genesis Pool","symbol":"GPOOL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x797de1dc0b9faf5e25c1f7efe8df9599138fa09d","decimalCount":18}]},{"id":"scifi-index","name":"SCIFI Index","symbol":"SCIFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfdc4a3fc36df16a78edcaf1b837d3acaaedb2cb4","decimalCount":18}]},{"id":"ukrainedao-flag-nft","name":"UkraineDAO Flag NFT","symbol":"LOVE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5380442d3c4ec4f5777f551f5edd2fa0f691a27c","decimalCount":18}]},{"id":"mercor-finance","name":"Mercor Finance","symbol":"MRCR","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x155dab50f1dded25c099e209e7b375456a70e504","decimalCount":18}]},{"id":"sportsicon","name":"SportsIcon","symbol":"$ICONS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3f68e7b44e9bcb486c2feadb7a2289d9cdfc9088","decimalCount":18}]},{"id":"zoracles","name":"Zoracles","symbol":"ZORA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd8e3fb3b08eba982f2754988d70d57edc0055ae6","decimalCount":9}]},{"id":"sekuya","name":"Sekuya","symbol":"SKUY","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xe327ce757cd206721e100812e744fc56e4e0a969","decimalCount":9}]},{"id":"true-pnl","name":"True PNL","symbol":"PNL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9fc8f0ca1668e87294941b7f627e9c15ea06b459","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xb346c52874c7023df183068c39478c3b7b2515bc","decimalCount":18}]},{"id":"props","name":"Props Token","symbol":"PROPS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6fe56c0bcdd471359019fcbc48863d6c3e9d4f41","decimalCount":18}]},{"id":"eosdac","name":"eosDAC","symbol":"EOSDAC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7e9e431a0b8c4d532c745b1043c7fa29a48d4fba","decimalCount":18}]},{"id":"ptokens-ore","name":"ORE Network","symbol":"ORE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4f640f2529ee0cf119a2881485845fa8e61a782a","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x4ef285c8cbe52267c022c39da98b97ca4b7e2ff9","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xd52f6ca48882be8fbaa98ce390db18e1dbe1062d","decimalCount":18}]},{"id":"throne","name":"Throne","symbol":"THN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2e95cea14dd384429eb3c4331b776c4cfbb6fcd9","decimalCount":18}]},{"id":"data","name":"DATA","symbol":"DTA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x69b148395ce0015c13e36bffbad63f49ef874e03","decimalCount":18}]},{"id":"etherland","name":"Etherland","symbol":"ELAND","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x33e07f5055173cf8febede8b21b12d1e2b523205","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x708cb02ad77e1b245b1640cee51b3cc844bcaef4","decimalCount":18}]},{"id":"feeder-finance","name":"Feeder Finance","symbol":"FEED","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x67d66e8ec1fd25d98b3ccd3b19b7dc4b4b7fc493","decimalCount":18},{"networkId":"fantom","contractAddress":"0x5d5530eb3147152fe78d5c4bfeede054c8d1442a","decimalCount":18}]},{"id":"ring","name":"Ring","symbol":"RING","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x021988d2c89b1a9ff56641b2f247942358ff05c9","decimalCount":5}]},{"id":"metavault","name":"Metavault","symbol":"MVD","active":true,"networks":[{"networkId":"fantom","contractAddress":"0x27746007e821aeec6f9c65cbfda04870c236346c","decimalCount":9}]},{"id":"playermon","name":"Playermon","symbol":"PYM","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x0bd49815ea8e2682220bcb41524c0dd10ba71d41","decimalCount":18}]},{"id":"rigoblock","name":"RigoBlock","symbol":"GRG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4fbb350052bca5417566f188eb2ebce5b19bc964","decimalCount":18}]},{"id":"ubex","name":"Ubex","symbol":"UBEX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6704b673c70de9bf74c8fba4b4bd748f0e2190e1","decimalCount":18}]},{"id":"traxia","name":"Traxia","symbol":"TMT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3209f98bebf0149b769ce26d71f7aea8e435efea","decimalCount":18}]},{"id":"amon","name":"Amon","symbol":"AMN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x737f98ac8ca59f2c68ad658e3c3d8c8963e40a4c","decimalCount":18}]},{"id":"lepasa","name":"Lepasa","symbol":"LEPA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbba6c7c7d673c48d90069ad2e9d2fe587fcb6bc3","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xa4050aa9b76ccdae1a6a8b2f3e8627cdc1546d86","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xf9a4bbaa7fa1dd2352f1a47d6d3fcff259a6d05f","decimalCount":18}]},{"id":"rage-fan","name":"Rage.Fan","symbol":"RAGE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x94804dc4948184ffd7355f62ccbb221c9765886f","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xd38c1b7b95d359978996e01b8a85286f65b3c011","decimalCount":18}]},{"id":"neurotoken","name":"Neurotoken","symbol":"NTK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x69beab403438253f13b6e92db91f7fb849258263","decimalCount":18}]},{"id":"plethori","name":"Plethori","symbol":"PLE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3873965e73d9a21f88e645ce40b7db187fde4931","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x47aa3650cff9930f277d4670db138da818e1a3ca","decimalCount":18}]},{"id":"islander","name":"Islander","symbol":"ISA","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x3eefb18003d033661f84e48360ebecd181a84709","decimalCount":18}]},{"id":"union-protocol-governance-token","name":"UNION Protocol Governance Token","symbol":"UNN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x226f7b842e0f0120b7e194d05432b3fd14773a9d","decimalCount":18}]},{"id":"ysl","name":"YSL","symbol":"YSL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x95e7c70b58790a1cbd377bc403cd7e9be7e0afb1","decimalCount":18}]},{"id":"merculet","name":"Merculet","symbol":"MVP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x432a2c54de2dde941a36d2eb8c424ed666f74aef","decimalCount":18}]},{"id":"triall","name":"Triall","symbol":"TRL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x58f9102bf53cf186682bd9a281d3cd3c616eec41","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xe2eb47954e821dc94e19013677004cd59be0b17f","decimalCount":18}]},{"id":"alphatoken","name":".Alpha","symbol":".ALPHA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x48af7b1c9dac8871c064f62fcec0d9d6f7c269f5","decimalCount":18}]},{"id":"kangal","name":"Kangal","symbol":"KANGAL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6e765d26388a17a6e86c49a8e41df3f58abcd337","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xd632bd021a07af70592ce1e18717ab9aa126decb","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x34f380a4e3389e99c0369264453523bbe5af7fab","decimalCount":18}]},{"id":"substratum","name":"Substratum","symbol":"SUB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8d75959f1e61ec2571aa72798237101f084de63a","decimalCount":18}]},{"id":"polkarare","name":"Polkarare","symbol":"PRARE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2c2f7e7c5604d162d75641256b80f1bf6f4dc796","decimalCount":18}]},{"id":"rentible","name":"Rentible","symbol":"RNB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2a039b1d9bbdccbb91be28691b730ca893e5e743","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xadec335a2e3881303a9b0203eb99de12202280df","decimalCount":18}]},{"id":"aimedis-2","name":"Aimedis","symbol":"AIMX","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd376f64bb7db90e11e78c91cbd58b756e1b8e7a1","decimalCount":18}]},{"id":"spiderdao","name":"SpiderDAO","symbol":"SPDR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbcd4b7de6fde81025f74426d43165a5b0d790fdd","decimalCount":18}]},{"id":"shadows","name":"Shadows","symbol":"DOWS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x661ab0ed68000491d98c796146bcf28c20d7c559","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xfb7400707df3d76084fbeae0109f41b178f71c02","decimalCount":18}]},{"id":"benzene","name":"Benzene","symbol":"BZN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6524b87960c2d573ae514fd4181777e7842435d4","decimalCount":18}]},{"id":"palletone","name":"PalletOneToken","symbol":"PTN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfe76be9cec465ed3219a9972c21655d57d21aec6","decimalCount":18}]},{"id":"lotto","name":"Lotto","symbol":"LOTTO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb0dfd28d3cf7a5897c694904ace292539242f858","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf301c8435d4dfa51641f71b0615add794b52c8e9","decimalCount":18}]},{"id":"accel-defi","name":"Accel Defi","symbol":"ACCEL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7475c42f8bf2c19f4eaf12feaababa859fdc8914","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x2cace984dab08bd192a7fd044276060cb955dd9c","decimalCount":18}]},{"id":"bnsd-finance","name":"BNSD Finance","symbol":"BNSD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x668dbf100635f593a3847c0bdaf21f0a09380188","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xc1165227519ffd22fdc77ceb1037b9b284eef068","decimalCount":18}]},{"id":"xmax","name":"XMax","symbol":"XMX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0f8c45b896784a1e408526b9300519ef8660209c","decimalCount":8}]},{"id":"solana-ecosystem-index","name":"Solana Ecosystem Index","symbol":"SOLI","active":true,"networks":[{"networkId":"solana","contractAddress":"8JnNWJ46yfdq8sKgT1Lk4G7VWkAA8Rhh7LhqgJ6WY41G","decimalCount":6}]},{"id":"shield-finance","name":"Coliquidity","symbol":"COLI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd49efa7bc0d339d74f487959c573d518ba3f8437","decimalCount":18}]},{"id":"axioms","name":"Axioms","symbol":"AXI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x73ee6d7e6b203125add89320e9f343d65ec7c39a","decimalCount":18}]},{"id":"bitto-exchange","name":"BITTO","symbol":"BITTO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x55a290f08bb4cae8dcf1ea5635a3fcfd4da60456","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x816e9e589f8c07149da4e2496c547952338b27e2","decimalCount":18}]},{"id":"niobium-coin","name":"Niobium Coin","symbol":"NBC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9f195617fa8fbad9540c5d113a99a0a0172aaedc","decimalCount":18}]},{"id":"scry-info","name":"Scry.info","symbol":"DDD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9f5f3cfd7a32700c93f971637407ff17b91c7342","decimalCount":18}]},{"id":"sak3","name":"SAKE","symbol":"SAK3","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe9f84de264e91529af07fa2c746e934397810334","decimalCount":18}]},{"id":"zasset-zusd","name":"Zasset zUSD","symbol":"ZUSD","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xf0186490b18cb74619816cfc7feb51cdbe4ae7b9","decimalCount":18}]},{"id":"basis-cash","name":"Basis Cash","symbol":"BAC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3449fc1cd036255ba1eb19d65ff4ba2b8903a69a","decimalCount":18}]},{"id":"imo","name":"IMO","symbol":"IMO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x94d79c325268c898d2902050730f27a478c56cc1","decimalCount":18}]},{"id":"tripio","name":"Tripio","symbol":"TRIO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8b40761142b9aa6dc8964e61d0585995425c3d94","decimalCount":18}]},{"id":"cryptokek","name":"Cryptokek","symbol":"KEK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3fa400483487a489ec9b1db29c4129063eec4654","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x627524d78b4fc840c887ffec90563c7a42b671fd","decimalCount":18},{"networkId":"fantom","contractAddress":"0x627524d78b4fc840c887ffec90563c7a42b671fd","decimalCount":18}]},{"id":"sashimi","name":"Sashimi","symbol":"SASHIMI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc28e27870558cf22add83540d2126da2e4b464c2","decimalCount":18}]},{"id":"travel-care-2","name":"Travel Care","symbol":"TRAVEL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x826e5ec70dbc5607ff9218011fbb97f9a8d97953","decimalCount":18}]},{"id":"unlimitedip","name":"UnlimitedIP","symbol":"UIP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4290563c2d7c255b5eec87f2d3bd10389f991d68","decimalCount":18}]},{"id":"cnns","name":"CNNS","symbol":"CNNS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6c3be406174349cfa4501654313d97e6a31072e1","decimalCount":18}]},{"id":"tolar","name":"Tolar","symbol":"TOL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd07d9fe2d2cc067015e2b4917d24933804f42cfa","decimalCount":18}]},{"id":"corgicoin","name":"CorgiCoin","symbol":"CORGI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x450dcf93160a30be156a4600802c91bf64dffd2e","decimalCount":18}]},{"id":"peachfolio","name":"Peachfolio","symbol":"PCHF","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xc1cbfb96a1d5361590b8df04ef78de2fa3178390","decimalCount":18}]},{"id":"smaugs-nft","name":"Smaugs NFT","symbol":"SMG","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x6bfd576220e8444ca4cc5f89efbd7f02a4c94c16","decimalCount":8}]},{"id":"rainbow-token","name":"HaloDAO","symbol":"RNBW","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe94b97b6b43639e238c851a7e693f50033efd75c","decimalCount":18}]},{"id":"avaxlauncher","name":"Avaxlauncher","symbol":"AVXL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xbd29490383edfd560426c3b63d01534408bc2da6","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xbee994ad257dcc84672c0c6e6168a4701041f39f","decimalCount":18}]},{"id":"litex","name":"LITEX","symbol":"LXT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbc46d9961a3932f7d6b64abfdec80c1816c4b835","decimalCount":18}]},{"id":"defhold","name":"DefHold","symbol":"DEFO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe481f2311c774564d517d015e678c2736a25ddd3","decimalCount":18}]},{"id":"wrapped-gen-0-cryptokitties","name":"Wrapped Gen-0 CryptoKitties","symbol":"WG0","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa10740ff9ff6852eac84cdcff9184e1d6d27c057","decimalCount":18}]},{"id":"exzocoin","name":"ExzoCoin 2.0","symbol":"EXZO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xf8fc63200e181439823251020d691312fdcf5090","decimalCount":9}]},{"id":"change","name":"Change","symbol":"CAG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7d4b8cce0591c9044a22ee543533b72e976e36c3","decimalCount":18}]},{"id":"centaurify","name":"Centaurify","symbol":"CENT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x08ba718f288c3b12b01146816bef9fa03cc635bc","decimalCount":18}]},{"id":"oh-finance","name":"Oh! Finance","symbol":"OH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x16ba8efe847ebdfef99d399902ec29397d403c30","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x937e077abaea52d3abf879c9b9d3f2ebd15baa21","decimalCount":18}]},{"id":"carbon-gems","name":"Carbon GEMS","symbol":"GEMS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe74ac81b14021d0cfb835f269f48f25918c5cae6","decimalCount":18}]},{"id":"social-good-project","name":"SocialGood","symbol":"SG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xddf7fd345d54ff4b40079579d4c4670415dbfd0a","decimalCount":18}]},{"id":"canyacoin","name":"CanYaCoin","symbol":"CAN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x007ea5c0ea75a8df45d288a4debdd5bb633f9e56","decimalCount":18}]},{"id":"ultrain","name":"Ultrain","symbol":"UGAS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8716fc5da009d3a208f0178b637a50f4ef42400f","decimalCount":18}]},{"id":"aluna","name":"Aluna","symbol":"ALN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8185bc4757572da2a610f887561c32298f1a5748","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf44fb887334fa17d2c5c0f970b5d320ab53ed557","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xa8fcee762642f156b5d757b6fabc36e06b6d4a1a","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x9b3fa2a7c3eb36d048a5d38d81e7fafc6bc47b25","decimalCount":18}]},{"id":"dough","name":"Dough","symbol":"DOUGH","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xede5020492be8e265db6141cb0a1d2df9dbae9bb","decimalCount":18}]},{"id":"airight","name":"aiRight","symbol":"AIRI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x7e2a35c746f2f7c240b664f1da4dd100141ae71f","decimalCount":18}]},{"id":"piedao-btc","name":"PieDAO BTC++","symbol":"BTC++","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0327112423f3a68efdf1fcf402f6c5cb9f7c33fd","decimalCount":18}]},{"id":"fanstime","name":"FansTime","symbol":"FTI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x943ed852dadb5c3938ecdc6883718df8142de4c8","decimalCount":18}]},{"id":"lepricon","name":"Lepricon","symbol":"L3P","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdef1da03061ddd2a5ef6c59220c135dec623116d","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xdef1da03061ddd2a5ef6c59220c135dec623116d","decimalCount":18}]},{"id":"baked-token","name":"Baked","symbol":"BAKED","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa4cb0dce4849bdcad2d553e9e68644cf40e26cce","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x32515ffdc3a84cfbf9ad4db14ef8f0a535c7afd6","decimalCount":18}]},{"id":"machix","name":"Machi X","symbol":"MCX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd15ecdcf5ea68e3995b2d0527a0ae0a3258302f8","decimalCount":18}]},{"id":"tradestars","name":"TradeStars","symbol":"TSX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x734c90044a0ba31b3f2e640c10dc5d3540499bfd","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x270388e0ca29cfd7c7e73903d9d933a23d1bab39","decimalCount":18}]},{"id":"kittenfinance","name":"KittenFinance","symbol":"KIF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x177ba0cac51bfc7ea24bad39d81dcefd59d74faa","decimalCount":18}]},{"id":"phoenixdao","name":"PhoenixDAO","symbol":"PHNX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x38a2fdc11f526ddd5a607c1f251c065f40fbf2f7","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x92c59f1cc9a322670cca29594e4d994d48bdfd36","decimalCount":18}]},{"id":"mirrored-tesla","name":"Mirrored Tesla","symbol":"MTSLA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x21ca39943e91d704678f5d00b6616650f066fd63","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf215a127a196e3988c09d052e16bcfd365cd7aa3","decimalCount":18}]},{"id":"iteration-syndicate","name":"Iteration Syndicate","symbol":"ITS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc32cc5b70bee4bd54aa62b9aefb91346d18821c4","decimalCount":18}]},{"id":"royale","name":"Royale","symbol":"ROYA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7eaf9c89037e4814dc0d9952ac7f888c784548db","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x99415856b37be9e75c0153615c7954f9ddb97a6e","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x0bd820ad2d7ab7305b5c9538ba824c9b9beb0561","decimalCount":18}]},{"id":"unitedcrowd","name":"UnitedCrowd","symbol":"UCT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6d1dc3928604b00180bb570bdae94b9698d33b79","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x6d1dc3928604b00180bb570bdae94b9698d33b79","decimalCount":18}]},{"id":"playcent","name":"Playcent","symbol":"PCNT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x657b83a0336561c8f64389a6f5ade675c04b0c3b","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xe9b9c1c38dab5eab3b7e2ad295425e89bd8db066","decimalCount":18}]},{"id":"the-bitcoin-family","name":"The Bitcoin Family","symbol":"FAMILY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x833e4c02c47b7e38f5b9a80b26eb07d23d1961f4","decimalCount":4}]},{"id":"ticoex-token","name":"TICOEX Token","symbol":"TICO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x36b60a425b82483004487abc7adcb0002918fc56","decimalCount":8}]},{"id":"follow-token","name":"Alpha Impact","symbol":"FOLO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb2a63a5dd36c91ec2da59b188ff047f66fac122a","decimalCount":18}]},{"id":"gg-token","name":"GG Token","symbol":"GGTK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfa99a87b14b02e2240c79240c5a20f945ca5ef76","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x49b1be61a8ca3f9a9f178d6550e41e00d9162159","decimalCount":18}]},{"id":"payrue","name":"Propel","symbol":"PROPEL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x9b44df3318972be845d83f961735609137c4c23c","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xe0ce60af0850bf54072635e66e79df17082a1109","decimalCount":18}]},{"id":"lunachow","name":"LunaChow","symbol":"LUCHOW","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa5ef74068d04ba0809b7379dd76af5ce34ab7c57","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xe4e8e6878718bfe533702d4a6571eb74d79b0915","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xc4bb7277a74678f053259cb1f96140347efbfd46","decimalCount":18}]},{"id":"oneroot-network","name":"OneRoot Network","symbol":"RNT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xff603f43946a3a28df5e6a73172555d8c8b02386","decimalCount":18}]},{"id":"snowswap","name":"Snowswap","symbol":"SNOW","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xfe9a29ab92522d14fc65880d817214261d8479ae","decimalCount":18}]},{"id":"localtrade","name":"LocalTrade","symbol":"LTT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x1dc84fc11e48ae640d48044f22a603bbe914a612","decimalCount":9}]},{"id":"localcoinswap","name":"LocalCoinSwap","symbol":"LCS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaa19961b6b858d9f18a115f25aa1d98abc1fdba8","decimalCount":18}]},{"id":"nami-corporation-token","name":"Nami Corporation Token","symbol":"NAMI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2f7b618993cc3848d6c7ed9cdd5e835e4fe22b98","decimalCount":18}]},{"id":"b21","name":"B21","symbol":"B21","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6faa826af0568d1866fca570da79b318ef114dab","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x70512c7f3d3009be997559d279b991461c451d70","decimalCount":18}]},{"id":"coin-artist","name":"Coin Artist","symbol":"COIN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x87b008e57f640d94ee44fd893f0323af933f9195","decimalCount":18}]},{"id":"robotina","name":"Robotina","symbol":"ROX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x574f84108a98c575794f75483d801d1d5dc861a5","decimalCount":18}]},{"id":"infomatix","name":"Infomatix","symbol":"INFO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xdf727040d3997b5d95dee8c661fa96e3c13ee0c9","decimalCount":18}]},{"id":"lunaland","name":"LunaLand","symbol":"LLN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x2a354f59ed1dd485129891e718865eb55ebdb8b3","decimalCount":18}]},{"id":"contentbox","name":"ContentBox","symbol":"BOX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x63f584fa56e60e4d0fe8802b27c7e6e3b33e007f","decimalCount":18}]},{"id":"multiverse-capital","name":"Multiverse Capital","symbol":"MVC","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x80d04e44955aa9c3f24041b2a824a20a88e735a8","decimalCount":18}]},{"id":"alpaca","name":"Alpaca City","symbol":"ALPA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7ca4408137eb639570f8e647d9bd7b7e8717514a","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xc5e6689c9c8b02be7c49912ef19e79cf24977f03","decimalCount":18}]},{"id":"joincoin","name":"JoinCoin","symbol":"JOIN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x003771227d08ac9961b9160b1219fef136546e90","decimalCount":18}]},{"id":"cryptomeda","name":"Cryptomeda","symbol":"TECH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6286a9e6f7e745a6d884561d88f94542d6715698","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x6286a9e6f7e745a6d884561d88f94542d6715698","decimalCount":18}]},{"id":"qchi","name":"QChi","symbol":"QCH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x687bfc3e73f6af55f0ccca8450114d107e781a0e","decimalCount":18}]},{"id":"crossswap","name":"CrossSwap","symbol":"CSWAP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe0b0c16038845bed3fcf70304d3e167df81ce225","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xe0b0c16038845bed3fcf70304d3e167df81ce225","decimalCount":18}]},{"id":"peanut","name":"Peanut","symbol":"NUX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x89bd2e7e388fab44ae88bef4e1ad12b4f1e0911c","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x6d8734002fbffe1c86495e32c95f732fc77f6f2a","decimalCount":18}]},{"id":"block-commerce-protocol","name":"Block Commerce Protocol","symbol":"BCP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4612021c75809160be60db21fbc9d6add0b32def","decimalCount":18}]},{"id":"polkadomain","name":"PolkaDomain","symbol":"NAME","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe1a4c5bbb704a92599fedb191f451e0d3a1ed842","decimalCount":18}]},{"id":"piedao-defi-small-cap","name":"PieDAO DEFI Small Cap","symbol":"DEFI+S","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xad6a626ae2b43dcb1b39430ce496d2fa0365ba9c","decimalCount":18}]},{"id":"dracula","name":"Dracula","symbol":"DRC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb78b3320493a4efaa1028130c5ba26f0b6085ef8","decimalCount":18}]},{"id":"decentralized-nations","name":"Decentralized Nations","symbol":"DENA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x15f0eedf9ce24fc4b6826e590a8292ce5524a1da","decimalCount":18}]},{"id":"stacker-ventures","name":"Stacker Ventures","symbol":"STACK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe0955f26515d22e347b17669993fcefcc73c3a0a","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xccbe9b810d6574701d324fd6dbe0a1b68f9d5bf7","decimalCount":18}]},{"id":"primas","name":"Primas","symbol":"PST","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe3fedaecd47aa8eab6b23227b0ee56f092c967a9","decimalCount":18}]},{"id":"racex","name":"RaceX","symbol":"RACEX","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x7086e045b78e1e72f741f25231c08d238812cf8a","decimalCount":18}]},{"id":"papel","name":"Papel Token","symbol":"PAPEL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x557dd6700e66818af340cce17fd4508ced81fbc1","decimalCount":9}]},{"id":"merge","name":"Merge","symbol":"MERGE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x2d5c9167fdd5c068c8fcb8992e6af639b42fbf70","decimalCount":18}]},{"id":"toshi-token","name":"Toshimon","symbol":"TOSHI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf136d7b0b7ae5b86d21e7b78dfa95375a7360f19","decimalCount":18}]},{"id":"ethereum-yield","name":"Ethereum Yield","symbol":"ETHY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd1afbccc9a2c2187ea544363b986ea0ab6ef08b5","decimalCount":18}]},{"id":"lovelace-world","name":"Lovelace World","symbol":"LACE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xa3499dd7dbbbd93cb0f8303f8a8ace8d02508e73","decimalCount":18}]},{"id":"alchemy-dao","name":"AlchemyDAO","symbol":"ALCH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0000a1c00009a619684135b824ba02f7fbf3a572","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x87b078cf94b188efb9d2208cae47a66ea7fea09a","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0x0e15258734300290a651fdbae8deb039a8e7a2fa","decimalCount":18}]},{"id":"meta-doge","name":"Meta Doge","symbol":"METADOGE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8530b66ca3ddf50e0447eae8ad7ea7d5e62762ed","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x8530b66ca3ddf50e0447eae8ad7ea7d5e62762ed","decimalCount":18}]},{"id":"rasko","name":"rASKO","symbol":"RASKO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd118f42edbc839f7e1e85d5269a25288792c141b","decimalCount":18}]},{"id":"nft-platform-index","name":"NFT Platform Index","symbol":"NFTP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x68bb81b3f67f7aab5fd1390ecb0b8e1a806f2465","decimalCount":18}]},{"id":"atlantis-loans","name":"Atlantis Loans","symbol":"ATL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x1fd991fb6c3102873ba68a4e6e6a87b3a5c10271","decimalCount":18}]},{"id":"cougar-token","name":"CougarSwap","symbol":"CGS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x26d88b1e61e22da3f1a1ba95a1ba278f6fcef00b","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x047fd3b3d2366f9babe105ade4598e263d6c699c","decimalCount":18},{"networkId":"fantom","contractAddress":"0x5a2e451fb1b46fde7718315661013ae1ae68e28c","decimalCount":18}]},{"id":"omnitude","name":"Omnitude","symbol":"ECOM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x171d750d42d661b62c277a6b486adb82348c3eca","decimalCount":18}]},{"id":"netcoincapital","name":"Netcoincapital","symbol":"NCC","active":true,"networks":[{"networkId":"tron","contractAddress":"TCDgp5bwtixaShPifUm7HpZ71C1pe6zif1","decimalCount":6}]},{"id":"squid-moon","name":"Squid Moon","symbol":"SQM","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x2766cc2537538ac68816b6b5a393fa978a4a8931","decimalCount":18}]},{"id":"ties-network","name":"Ties.DB","symbol":"TIE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x999967e2ec8a74b7c8e9db19e039d920b31d39d0","decimalCount":18}]},{"id":"soul-swap","name":"Soul Swap","symbol":"SOUL","active":true,"networks":[{"networkId":"fantom","contractAddress":"0xe2fb177009ff39f52c0134e8007fa0e4baacbd07","decimalCount":18}]},{"id":"lead-token","name":"Lead Token","symbol":"LEAD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1dd80016e3d4ae146ee2ebb484e8edd92dacc4ce","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x2ed9e96edd11a1ff5163599a66fb6f1c77fa9c66","decimalCount":18}]},{"id":"kerman","name":"KERMAN","symbol":"KERMAN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7841b2a48d1f6e78acec359fed6d874eb8a0f63c","decimalCount":4}]},{"id":"parachute","name":"Parachute","symbol":"PAR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1beef31946fbbb40b877a72e4ae04a8d1a5cee06","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x19c91764a976ac6c1e2c2e4c5856f2939342a814","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xf521d590fb1e0b432fd0e020cdbd6c6397d652c2","decimalCount":18}]},{"id":"banca","name":"Banca","symbol":"BANCA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x998b3b82bc9dba173990be7afb772788b5acb8bd","decimalCount":18}]},{"id":"dyor","name":"DYOR","symbol":"DYOR","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x10051147418c42218986cedd0adc266441f8a14f","decimalCount":9}]},{"id":"moonienft","name":"MoonieNFT","symbol":"MNY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa6f7645ed967faf708a614a2fca8d4790138586f","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xa6f7645ed967faf708a614a2fca8d4790138586f","decimalCount":18}]},{"id":"chainswap","name":"Chainswap","symbol":"ASAP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcc665390b03c5d324d8faf81c15ecee29a73bcb4","decimalCount":18}]},{"id":"aetherv2","name":"AetherV2","symbol":"ATH","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x6d3a0fb0070ea61f901ebc0b675c30450acac737","decimalCount":9}]},{"id":"medishares","name":"MediShares","symbol":"MDS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x66186008c1050627f979d464eabb258860563dbe","decimalCount":18}]},{"id":"liquidifty","name":"Liquidifty","symbol":"LQT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xbd2c43da85d007b0b3cd856fd55c299578d832bc","decimalCount":18}]},{"id":"ledgerscore","name":"LedgerScore","symbol":"LED","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x72de803b67b6ab05b61efab2efdcd414d16ebf6d","decimalCount":18}]},{"id":"community-metaverse","name":"Community Metaverse","symbol":"COMT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x45b239cc0a760d1afd276b749141c7e404844ee6","decimalCount":18}]},{"id":"blockspace-token","name":"Blocks Space","symbol":"BLS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x34aa9099d924f3fb2377ff20d81b235311c15346","decimalCount":18}]},{"id":"upfiring","name":"Upfiring","symbol":"UFR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xea097a2b1db00627b2fa17460ad260c016016977","decimalCount":18}]},{"id":"polygon-ecosystem-index","name":"Amun Polygon Ecosystem Index","symbol":"PECO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9d3ee6b64e69ebe12a4bf0b01d031cb80f556ee4","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xa9536b9c75a9e0fae3b56a96ac8edf76abc91978","decimalCount":18}]},{"id":"red","name":"Red","symbol":"RED","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x76960dccd5a1fe799f7c29be9f19ceb4627aeb2f","decimalCount":18}]},{"id":"spacecowboy","name":"SpaceCowBoy","symbol":"SCB","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x0d36cc179019db9a65aa3b85db59e4bb52df0b12","decimalCount":18}]},{"id":"argo","name":"ArGoApp","symbol":"ARGO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x28cca76f6e8ec81e4550ecd761f899110b060e97","decimalCount":18}]},{"id":"apyswap","name":"APYSwap","symbol":"APYS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf7413489c474ca4399eee604716c72879eea3615","decimalCount":18}]},{"id":"quai-dao","name":"Quai Dao","symbol":"QUAI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x40821cd074dfecb1524286923bc69315075b5c89","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x3dc2d7434bdbb4ca1a8a6bcc8a8075aeae2d2179","decimalCount":18}]},{"id":"foresight","name":"Foresight","symbol":"FORS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb1ec548f296270bc96b8a1b3b3c8f3f04b494215","decimalCount":18}]},{"id":"wenlambo","name":"Wenlambo","symbol":"WENLAMBO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd8a31016cd7da048ca21ffe04256c6d08c3a2251","decimalCount":18}]},{"id":"ares-protocol","name":"Ares Protocol","symbol":"ARES","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x358aa737e033f34df7c54306960a38d09aabd523","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf9752a6e8a5e5f5e6eb3ab4e7d8492460fb319f0","decimalCount":18}]},{"id":"ebox","name":"Ebox","symbol":"EBOX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x33840024177a7daca3468912363bed8b425015c5","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xb41c43fabd22a6c6ea135e975769e9051f9ee8ad","decimalCount":18}]},{"id":"lendefi","name":"Lendefi","symbol":"LDFI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x8f1e60d84182db487ac235acc65825e50b5477a1","decimalCount":18}]},{"id":"gamerse","name":"Gamerse","symbol":"LFG","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xf93f6b686f4a6557151455189a9173735d668154","decimalCount":18}]},{"id":"inheritance-art","name":"inheritance Art","symbol":"IAI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xe495b7155fbd040065491092b02893c8e17629ed","decimalCount":18}]},{"id":"blockster","name":"Blockster","symbol":"BXR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x97a3bd8a445cc187c6a751f392e15c3b2134d695","decimalCount":18}]},{"id":"unvest","name":"Unvest","symbol":"UNV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf009f5531de69067435e32c4b9d36077f4c4a673","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf915fdda4c882731c0456a4214548cd13a822886","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x64ee4f41a15d6c431ab6607d4e95462169d50f6c","decimalCount":18}]},{"id":"starbase","name":"Starbase","symbol":"STAR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf70a642bd387f94380ffb90451c2c81d4eb82cbc","decimalCount":18}]},{"id":"electrify-asia","name":"Electrify.Asia","symbol":"ELEC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd49ff13661451313ca1553fd6954bd1d9b6e02b9","decimalCount":18}]},{"id":"cryptex","name":"CryptEx","symbol":"CRX","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x97a30c692ece9c317235d48287d23d358170fc40","decimalCount":18}]},{"id":"matrixswap","name":"Matrix Labs","symbol":"MATRIX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc8d3dcb63c38607cb0c9d3f55e8ecce628a01c36","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xc32bb619966b9a56cf2472528a36fd099ce979e0","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x211f4e76fcb811ed2b310a232a24b3445d95e3bc","decimalCount":18}]},{"id":"happyfans","name":"HappyFans","symbol":"HAPPY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3079f61704e9efa2bcf1db412f735d8d4cfa26f4","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf5d8a096cccb31b9d7bce5afe812be23e3d4690d","decimalCount":18}]},{"id":"friendz","name":"Friendz","symbol":"FDZ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x23352036e911a22cfc692b5e2e196692658aded9","decimalCount":18}]},{"id":"typerium","name":"Typerium","symbol":"TYPE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xeaf61fc150cd5c3bea75744e830d916e60ea5a9f","decimalCount":4}]},{"id":"hashcoin","name":"HashCoin","symbol":"HSC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2bba3cf6de6058cc1b4457ce00deb359e2703d7f","decimalCount":18}]},{"id":"zeedex","name":"Zeedex","symbol":"ZDEX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5150956e082c748ca837a5dfa0a7c10ca4697f9c","decimalCount":18}]},{"id":"robust-token","name":"Robust","symbol":"RBT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x891e4554227385c5c740f9b483e935e3cbc29f01","decimalCount":18}]},{"id":"the-4th-pillar","name":"4thpillar technologies","symbol":"FOUR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4730fb1463a6f1f44aeb45f6c5c422427f37f4d0","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xd882739fca9cbae00f3821c4c65189e2d7e26147","decimalCount":18},{"networkId":"solana","contractAddress":"DAtU322C23YpoZyWBm8szk12QyqHa9rUQe1EYXzbm1JE","decimalCount":9},{"networkId":"polygon-pos","contractAddress":"0x48cbc913de09317df2365e6827df50da083701d5","decimalCount":18}]},{"id":"bitorbit","name":"BitOrbit","symbol":"BITORB","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xed0c1c9c64ff7c7cc37c3af0dfcf5b02efe0bb5f","decimalCount":18}]},{"id":"gamyfi-token","name":"GamyFi Token","symbol":"GFX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x65ad6a2288b2dd23e466226397c8f5d1794e58fc","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x65ad6a2288b2dd23e466226397c8f5d1794e58fc","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x65ad6a2288b2dd23e466226397c8f5d1794e58fc","decimalCount":18}]},{"id":"dether","name":"Dether","symbol":"DTH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5adc961d6ac3f7062d2ea45fefb8d8167d44b190","decimalCount":18}]},{"id":"nftify","name":"NFTify","symbol":"N1","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xacbd826394189cf2623c6df98a18b41fc8ffc16d","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x5989d72a559eb0192f2d20170a43a4bd28a1b174","decimalCount":18}]},{"id":"lympo-market-token","name":"Lympo Market Token","symbol":"LMT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x327673ae6b33bd3d90f0096870059994f30dc8af","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x9617857e191354dbea0b714d78bc59e57c411087","decimalCount":18}]},{"id":"recharge-finance","name":"Recharge Finance","symbol":"R3FI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x13572851103bed49ff743af4c4bb5ace88b22e2f","decimalCount":9},{"networkId":"binance-smart-chain","contractAddress":"0x4f55ab914ce8a633c7eb5d8b4d190a96e9ed7f90","decimalCount":9}]},{"id":"tapmydata","name":"TapX","symbol":"TAP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7f1f2d3dfa99678675ece1c243d3f7bc3746db5d","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x10635bf5c17f5e4c0ed9012aef7c12f96a57a4dd","decimalCount":18}]},{"id":"token-tkx","name":"Xixo TKX","symbol":"TKX","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4d864e4f542b4b40acb3151c9dad2e2c9236a88f","decimalCount":6}]},{"id":"robonomics-web-services","name":"Robonomics Web Services","symbol":"RWS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x08ad83d779bdf2bbe1ad9cc0f78aa0d24ab97802","decimalCount":18}]},{"id":"teneo","name":"Teneo","symbol":"TEN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x25b9d4b9535920194c359d2879db6a1382c2ff26","decimalCount":18}]},{"id":"nyan-v2","name":"Nyan V2","symbol":"NYAN-2","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbf4a9a37ecfc21825011285222c36ab35de51f14","decimalCount":18}]},{"id":"cardence","name":"Cardence","symbol":"$CRDN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xfa17b330bcc4e7f3e2456996d89a5a54ab044831","decimalCount":18}]},{"id":"pinkmoon","name":"PinkMoon","symbol":"PINKM","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xb6090a50f66046e3c6afb9311846a6432e45060a","decimalCount":9}]},{"id":"patientory","name":"Patientory","symbol":"PTOY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8ae4bf2c33a8e667de34b54938b0ccd03eb8cc06","decimalCount":8}]},{"id":"media-eye","name":"MeDIA eYe","symbol":"EYE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9a257c90fa239fba07771ef7da2d554d148c2e89","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x9a257c90fa239fba07771ef7da2d554d148c2e89","decimalCount":18}]},{"id":"black-phoenix","name":"Black Phoenix","symbol":"BPX","active":true,"networks":[{"networkId":"tron","contractAddress":"TXBcx59eDVndV5upFQnTR2xdvqFd5reXET","decimalCount":18}]},{"id":"chain-wars-essence","name":"Chain Wars","symbol":"CWE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x9c6b7221cdda3b8136fbf9d27ac07aeecc1087b5","decimalCount":18}]},{"id":"mirrored-amazon","name":"Mirrored Amazon","symbol":"MAMZN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0cae9e4d663793c2a2a0b211c1cf4bbca2b9caa7","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x3947b992dc0147d2d89df0392213781b04b25075","decimalCount":18}]},{"id":"aga-rewards-2","name":"AGA Rewards","symbol":"AGAR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb453f1f2ee776daf2586501361c457db70e1ca0f","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0x4ec16da4c9007462de151c0da9f5426c69978a7b","decimalCount":8},{"networkId":"polygon-pos","contractAddress":"0xf84bd51eab957c2e7b7d646a3427c5a50848281d","decimalCount":8}]},{"id":"minikishu","name":"MINIKISHU","symbol":"MINIKISHU","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x47fd00664661058546fddada3eecc9f2cd41020e","decimalCount":9}]},{"id":"yfdai-finance","name":"YfDAI.finance","symbol":"YF-DAI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf4cd3d3fda8d7fd6c5a500203e38640a70bf9577","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x7e7ff932fab08a0af569f93ce65e7b8b23698ad8","decimalCount":18}]},{"id":"dextf","name":"Domani Protocol","symbol":"DEXTF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x5f64ab1544d28732f0a24f4713c2c8ec0da089f0","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x03e8d118a1864c7dc53bf91e007ab7d91f5a06fa","decimalCount":18}]},{"id":"hyperchain-x","name":"HyperChain X","symbol":"HYPER","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x0469f8ca65ce318888cc0d6459d0c7cbe5912c98","decimalCount":7}]},{"id":"cerberusdao","name":"CerberusDAO","symbol":"3DOG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8a14897ea5f668f36671678593fae44ae23b39fb","decimalCount":9}]},{"id":"kittycoin","name":"Kitty Coin","symbol":"KITTY","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0xb4228798ff437ecd8fa43429664e9992256fe6ac","decimalCount":18}]},{"id":"kuramainu","name":"KuramaInu","symbol":"KUNU","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe49cb97091b5bde1e8b7043e3d5717e64fde825e","decimalCount":9}]},{"id":"bottos","name":"Bottos","symbol":"BTO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x36905fc93280f52362a1cbab151f25dc46742fb5","decimalCount":18}]},{"id":"tosdis","name":"TosDis","symbol":"DIS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x220b71671b649c03714da9c621285943f3cbcdc6","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x57effde2759b68d86c544e88f7977e3314144859","decimalCount":18},{"networkId":"fantom","contractAddress":"0x0e121961dd741c9d49c9a04379da944a9d2fac7a","decimalCount":18}]},{"id":"santa-coin-2","name":"Santa Coin","symbol":"SANTA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4f1a6fc6a7b65dc7ebc4eb692dc3641be997c2f2","decimalCount":9}]},{"id":"meta-bsc","name":"Meta BSC","symbol":"META","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x26165a5a3dd21fa528becf3ff7f114d00a517344","decimalCount":9}]},{"id":"bull-coin","name":"Bull Coin","symbol":"BULL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xf483af09917ba63f1e274056978036d266eb56e6","decimalCount":18}]},{"id":"polygen","name":"Polygen","symbol":"PGEN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf6719e1a8fcbb1b9c290019e37e004966a8916c9","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x01d35cbc2070a3b76693ce2b6364eae24eb88591","decimalCount":18}]},{"id":"swarm-city","name":"Swarm City","symbol":"SWT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb9e7f8568e08d5659f5d29c4997173d84cdf2607","decimalCount":18}]},{"id":"snowball-token","name":"Snowball","symbol":"SNOB","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0xc38f41a296a4493ff429f1238e030924a1542e50","decimalCount":18}]},{"id":"avaware","name":"Avaware","symbol":"AVE","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x78ea17559b3d2cf85a7f9c2c704eda119db5e6de","decimalCount":18}]},{"id":"phoenix-token","name":"Phoenix Finance","symbol":"PHX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaec65404ddc3af3c897ad89571d5772c1a695f22","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xac86e5f9ba48d680516df50c72928c2ec50f3025","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x9c6bfedc14b5c23e3900889436edca7805170f01","decimalCount":18}]},{"id":"option-room","name":"OptionRoom","symbol":"ROOM","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x3c45a24d36ab6fc1925533c1f57bc7e1b6fba8a4","decimalCount":18}]},{"id":"auctus","name":"Auctus","symbol":"AUC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc12d099be31567add4e4e4d0d45691c3f58f5663","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x3028b4395f98777123c7da327010c40f3c7cc4ef","decimalCount":18},{"networkId":"arbitrum-one","contractAddress":"0xea986d33ef8a20a96120ecc44dbdd49830192043","decimalCount":18}]},{"id":"delphy","name":"Delphy","symbol":"DPY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6c2adc2073994fb2ccc5032cc2906fa221e9b391","decimalCount":18}]},{"id":"credefi","name":"Credefi","symbol":"CREDI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xae6e307c3fe9e922e5674dbd7f830ed49c014c6b","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x2235e79086dd23135119366da45851c741874e5b","decimalCount":18}]},{"id":"blue","name":"Blue Protocol","symbol":"BLUE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x539efe69bcdd21a83efd9122571a64cc25e0282b","decimalCount":8}]},{"id":"reverse","name":"Reverse","symbol":"RVRS","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x5dd175a4242afe19e5c1051d8cd13fc8979f2329","decimalCount":9}]},{"id":"koromaru","name":"KOROMARU","symbol":"KOROMARU","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd0d42005e7b3c0812b1268f0e5faf97ff2423651","decimalCount":9}]},{"id":"channels","name":"Channels","symbol":"CAN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xde9a73272bc2f28189ce3c243e36fafda2485212","decimalCount":18}]},{"id":"nftlootbox","name":"LootBox.io","symbol":"LOOT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7b3d36eb606f873a75a6ab68f8c999848b04f935","decimalCount":18}]},{"id":"adbank","name":"adbank","symbol":"ADB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2baac9330cf9ac479d819195794d79ad0c7616e3","decimalCount":18}]},{"id":"keyfi","name":"KeyFi","symbol":"KEYFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb8647e90c0645152fccf4d9abb6b59eb4aa99052","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x4b6000f9163de2e3f0a01ec37e06e1469dbbce9d","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xd1a5f2a049343fc4d5f8d478f734eba51b22375e","decimalCount":18}]},{"id":"sator","name":"Sator","symbol":"SAO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3ef389f264e07fff3106a3926f2a166d1393086f","decimalCount":9}]},{"id":"geodb","name":"GeoDB","symbol":"GEO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x147faf8de9d8d8daae129b187f0d02d819126750","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xc342774492b54ce5f8ac662113ed702fc1b34972","decimalCount":18}]},{"id":"potent-coin","name":"Potent Coin","symbol":"PTT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x057aff3e314e1ca15bed75510df81a20098ce456","decimalCount":18}]},{"id":"project-inverse","name":"Planet Inverse","symbol":"XIV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x44f262622248027f8e2a8fb1090c4cf85072392c","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x00518f36d2e0e514e8eb94d34124fc18ee756f10","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xde799636af0d8d65a17aaa83b66cbbe9b185eb01","decimalCount":18}]},{"id":"moonpoly","name":"Moonpoly","symbol":"CMP","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xcfd947b1ad06c39522fb67fb00b21a3fda906e34","decimalCount":9}]},{"id":"add-xyz-new","name":"Add.xyz (NEW)","symbol":"ADD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x635d081fd8f6670135d8a3640e2cf78220787d56","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xcd7e445175ff67475f0079b13aa6bed8a4e01809","decimalCount":18}]},{"id":"relite-finance","name":"Relite Finance","symbol":"RELI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0e58ed58e150dba5fd8e5d4a49f54c7e1e880124","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x7015a4b6ec17b64e09252a99f9f6e7feee6c37eb","decimalCount":18}]},{"id":"sake-token","name":"SakeToken","symbol":"SAKE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x066798d9ef0833ccc719076dab77199ecbd178b0","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x8bd778b12b15416359a227f0533ce2d91844e1ed","decimalCount":18}]},{"id":"ibuffer-token","name":"iBuffer","symbol":"IBFR","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xa296ad1c47fe6bdc133f39555c1d1177bd51fbc5","decimalCount":18}]},{"id":"arcane-token","name":"Arcane Token","symbol":"ARCANE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x477565b356b3973d16e8cd837c6970613f13e24a","decimalCount":9}]},{"id":"unicake","name":"UniCAKE","symbol":"UCT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x802fc33f170aedeca12e4f04a959bec9c16bc836","decimalCount":18}]},{"id":"tacos","name":"Tacos","symbol":"TACO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x00d1793d7c3aae506257ba985b34c76aaf642557","decimalCount":18}]},{"id":"bscstarter","name":"Starter.xyz","symbol":"START","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1d7ca62f6af49ec66f6680b8606e634e55ef22c1","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x31d0a7ada4d4c131eb612db48861211f63e57610","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xf44fb887334fa17d2c5c0f970b5d320ab53ed557","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x6ccf12b480a99c54b23647c995f4525d544a7e72","decimalCount":18}]},{"id":"depocket","name":"DePocket","symbol":"DEPO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x7d99eda556388ad7743a1b658b9c4fc67d7a9d74","decimalCount":18}]},{"id":"zlot","name":"zLOT","symbol":"ZLOT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa8e7ad77c60ee6f30bac54e2e7c0617bd7b5a03e","decimalCount":18},{"networkId":"fantom","contractAddress":"0x2f60c28fb2fdc90a2a5644442d0f6d8998101e76","decimalCount":18}]},{"id":"smartofgiving","name":"smARTOFGIVING","symbol":"AOG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8578530205cecbe5db83f7f29ecfeec860c297c2","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xb32d4817908f001c2a53c15bff8c14d8813109be","decimalCount":18}]},{"id":"deficliq","name":"DefiCliq","symbol":"CLIQ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0def8d8adde14c9ef7c2a986df3ea4bd65826767","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xe795347731bc547f4e4643f7945738ce2bc18529","decimalCount":18}]},{"id":"hyperion","name":"Hyperion","symbol":"HYN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe99a894a69d7c2e3c92e61b64c505a6a57d2bc07","decimalCount":18}]},{"id":"covercompared","name":"CoverCompared","symbol":"CVR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3c03b4ec9477809072ff9cc9292c9b25d4a8e6c6","decimalCount":18}]},{"id":"crabada-amulet","name":"Crabada Amulet","symbol":"CRAM","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0xd2cd7a59aa8f8fdc68d01b1e8a95747730b927d3","decimalCount":18}]},{"id":"unclemine","name":"UncleMine","symbol":"UM","active":true,"networks":[{"networkId":"solana","contractAddress":"DMCUFm2ZAnSU7UgsdVq23gRogMU3MEBjPgQF1gK53rEn","decimalCount":6}]},{"id":"legend-of-fantasy-war","name":"Legend of Fantasy War","symbol":"LFW","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd71239a33c8542bd42130c1b4aca0673b4e4f48b","decimalCount":18}]},{"id":"ladz","name":"LADZ","symbol":"LADZ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1287c0509df9a475ef178471ab2132b9dfd312b3","decimalCount":4}]},{"id":"donut","name":"Donut","symbol":"DONUT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc0f9bd5fa5698b6505f643900ffa515ea5df54a9","decimalCount":18}]},{"id":"cardwallet","name":"CardWallet","symbol":"CW","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd55236d48606c295adebf129dad04fc74bfaa708","decimalCount":18}]},{"id":"work-quest","name":"Work Quest","symbol":"WQT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x06677dc4fe12d3ba3c7ccfd0df8cd45e4d4095bf","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xe89508d74579a06a65b907c91f697cf4f8d9fac7","decimalCount":18}]},{"id":"zip","name":"Zipper Network","symbol":"ZIP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa9d2927d3a04309e008b6af6e2e282ae2952e7fd","decimalCount":18}]},{"id":"moonfarm-finance","name":"MoonFarm Finance","symbol":"MFO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xb46049c79d77ff1d555a67835fba6978536581af","decimalCount":18}]},{"id":"genomesdao","name":"GenomesDAO","symbol":"$GENE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x21413c119b0c11c5d96ae1bd328917bc5c8ed67e","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x34667ed7c36cbbbf2d5d5c5c8d6eb76a094edb9f","decimalCount":18}]},{"id":"appcoins","name":"AppCoins","symbol":"APPC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1a7a8bd9106f2b8d977e08582dc7d24c723ab0db","decimalCount":18}]},{"id":"bountymarketcap","name":"BountyMarketCap","symbol":"BMC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd945d2031b4c63c0e363304fb771f709b502dc0a","decimalCount":18}]},{"id":"metagamehub-dao","name":"MetaGameHub DAO","symbol":"MGH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8765b1a0eb57ca49be7eacd35b24a574d0203656","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xc3c604f1943b8c619c5d65cd11a876e9c8edcf10","decimalCount":18}]},{"id":"metarun","name":"Metarun","symbol":"MRUN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xca0d640a401406f3405b4c252a5d0c4d17f38ebb","decimalCount":18}]},{"id":"dfsocial-gaming-2","name":"DFSocial Gaming","symbol":"DFSG","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x612c49b95c9121107be3a2fe1fcf1efc1c4730ad","decimalCount":18}]},{"id":"world-token","name":"World Token","symbol":"WORLD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbf494f02ee3fde1f20bee6242bce2d1ed0c15e47","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x31ffbe9bf84b4d9d02cd40eccab4af1e2877bbc6","decimalCount":18}]},{"id":"libre-defi","name":"Libre DeFi","symbol":"LIBRE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x63db060697b01c6f4a26561b1494685dcbbd998c","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x8afa62fa8dde8888405c899d7da077a61a87eed3","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xf52d69bc301be21cbed7d3ca652d1708ff8a1162","decimalCount":18}]},{"id":"axial-token","name":"Axial Token","symbol":"AXIAL","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0xcf8419a615c57511807236751c0af38db4ba3351","decimalCount":18}]},{"id":"sugarbounce","name":"SugarBounce","symbol":"TIP","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x40f906e19b14100d5247686e08053c4873c66192","decimalCount":18}]},{"id":"defrost-finance","name":"Defrost Finance","symbol":"MELT","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x47eb6f7525c1aa999fbc9ee92715f5231eb1241d","decimalCount":18}]},{"id":"kurobi","name":"Kurobi","symbol":"KURO","active":true,"networks":[{"networkId":"solana","contractAddress":"2Kc38rfQ49DFaKHQaWbijkE7fcymUMLY5guUiUsDmFfn","decimalCount":6}]},{"id":"avme","name":"AVME","symbol":"AVME","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x1ecd47ff4d9598f89721a2866bfeb99505a413ed","decimalCount":18}]},{"id":"lavax-labs","name":"LavaX Labs","symbol":"LAVAX","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xa9be3cd803fa19f2af24412ff0a2a4a67a29de88","decimalCount":18}]},{"id":"silverstonks","name":"Silver Stonks","symbol":"SSTX","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x5396734569e26101677eb39c89413f7fa7d8006f","decimalCount":7}]},{"id":"ethernaal","name":"Ethernaal","symbol":"NAAL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc133529e57681b2999708f9458be5634e293995e","decimalCount":18}]},{"id":"aca-token","name":"ACA","symbol":"ACA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x9eb6935aea6afb5bc6d1a74be0c2f78280ab6448","decimalCount":9}]},{"id":"dynamix","name":"Dynamix","symbol":"DYNA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xc41689a727469c1573009757200371edf36d540e","decimalCount":9}]},{"id":"bobo-cash","name":"Bobo Cash","symbol":"BOBO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf53c24f7729c88c110265929c7124e6259efccab","decimalCount":9}]},{"id":"tardigrades-finance","name":"Tardigrades Finance","symbol":"TRDG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x92a42db88ed0f02c71d439e55962ca7cab0168b5","decimalCount":9},{"networkId":"binance-smart-chain","contractAddress":"0x92a42db88ed0f02c71d439e55962ca7cab0168b5","decimalCount":9}]},{"id":"kingspeed","name":"KingSpeed","symbol":"KSC","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x3ac0f8cecc1fb0ee6c2017a072d52e85b00c6694","decimalCount":18}]},{"id":"spindle","name":"SPINDLE","symbol":"SPD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1dea979ae76f26071870f824088da78979eb91c8","decimalCount":18}]},{"id":"blockmason-credit-protocol","name":"Blockmason Credit Protocol","symbol":"BCPT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1c4481750daa5ff521a2a7490d9981ed46465dbd","decimalCount":18}]},{"id":"coinfi","name":"CoinFi","symbol":"COFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3136ef851592acf49ca4c825131e364170fa32b3","decimalCount":18}]},{"id":"vether","name":"Vether","symbol":"VETH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4ba6ddd7b89ed838fed25d208d4f644106e34279","decimalCount":18}]},{"id":"nemesis-dao","name":"Nemesis DAO","symbol":"NMS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x8ac9dc3358a2db19fdd57f433ff45d1fc357afb3","decimalCount":9}]},{"id":"etherparty","name":"Etherparty","symbol":"FUEL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xea38eaa3c86c8f9b751533ba2e562deb9acded40","decimalCount":18}]},{"id":"krown","name":"KROWN","symbol":"KRW","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x499568c250ab2a42292261d6121525d70691894b","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x1446f3cedf4d86a9399e49f7937766e6de2a3aab","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xa5acfeca5270bc9768633fbc86caa959b85ec8b7","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x6c3b2f402cd7d22ae2c319b9d2f16f57927a4a17","decimalCount":18}]},{"id":"aidcoin","name":"AidCoin","symbol":"AID","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x37e8789bb9996cac9156cd5f5fd32599e6b91289","decimalCount":18}]},{"id":"meliora","name":"Meliora","symbol":"MORA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xeb633ec737889eba802478aea7eb0f5203eb8deb","decimalCount":18}]},{"id":"argon","name":"Argon","symbol":"ARGON","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x851f7a700c5d67db59612b871338a85526752c25","decimalCount":18}]},{"id":"adaboy","name":"ADABoy","symbol":"ADABOY","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x1e653794a6849bc8a78be50c4d48981afad6359d","decimalCount":18}]},{"id":"ethereum-stake","name":"Ethereum Stake","symbol":"ETHYS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd0d3ebcad6a20ce69bc3bc0e1ec964075425e533","decimalCount":18}]},{"id":"bartertrade","name":"BarterTrade","symbol":"BART","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x54c9ea2e9c9e8ed865db4a4ce6711c2a0d5063ba","decimalCount":18}]},{"id":"daoventures","name":"DAOventures","symbol":"DVD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x77dce26c03a9b833fc2d7c31c22da4f42e9d9582","decimalCount":18}]},{"id":"ghospers-game","name":"Ghospers Game","symbol":"GHSP","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4a0cc0876ec16428a4fa4a7c4c300de2db73b75b","decimalCount":18}]},{"id":"macaronswap","name":"MacaronSwap","symbol":"MCRN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xacb2d47827c9813ae26de80965845d80935afd0b","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xba25b552c8a098afdf276324c32c71fe28e0ad40","decimalCount":18}]},{"id":"goldmint","name":"Goldmint","symbol":"MNTP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x83cee9e086a77e492ee0bb93c2b0437ad6fdeccc","decimalCount":18}]},{"id":"totemfi","name":"TotemFi","symbol":"TOTM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6ff1bfa14a57594a5874b37ff6ac5efbd9f9599a","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x6ff1bfa14a57594a5874b37ff6ac5efbd9f9599a","decimalCount":18}]},{"id":"hugo-finance","name":"Hugo Game","symbol":"HUGO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xce195c777e1ce96c30ebec54c91d20417a068706","decimalCount":9}]},{"id":"investdex","name":"InvestDex","symbol":"INVEST","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x853a8ab1c365ea54719eb13a54d6b22f1fbe7feb","decimalCount":18}]},{"id":"defipie","name":"DeFiPie","symbol":"PIE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x607c794cda77efb21f8848b7910ecf27451ae842","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xc4b35d3a24e3e8941c5d87fd21d0725642f50308","decimalCount":18}]},{"id":"blitzpredict","name":"BlitzPick","symbol":"XBP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x28dee01d53fed0edf5f6e310bf8ef9311513ae40","decimalCount":18}]},{"id":"yup","name":"Yup","symbol":"YUP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x69bbc3f8787d573f1bbdd0a5f40c7ba0aee9bcc9","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x086373fad3447f7f86252fb59d56107e9e0faafa","decimalCount":18}]},{"id":"iht-real-estate-protocol","name":"IHT Real Estate Protocol","symbol":"IHT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xeda8b016efa8b1161208cf041cd86972eee0f31e","decimalCount":18}]},{"id":"mmaon","name":"MMAON","symbol":"MMAON","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8315472bae77f9a2b856a67eb0796480aafcd51c","decimalCount":18}]},{"id":"metaverse-exchange","name":"Metaverse Exchange","symbol":"METACEX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd796b8eff23d5c4c71f43c99ffd7d8a3119f7475","decimalCount":18}]},{"id":"remme","name":"Remme","symbol":"REM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x83984d6142934bb535793a82adb0a46ef0f66b6d","decimalCount":4}]},{"id":"spaceswap-shake","name":"Spaceswap SHAKE","symbol":"SHAKE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6006fc2a849fedaba8330ce36f5133de01f96189","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xba8a6ef5f15ed18e7184f44a775060a6bf91d8d0","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xc1d02e488a9ce2481bfdcd797d5373dd2e70a9c2","decimalCount":18}]},{"id":"cashcow","name":"CashCow","symbol":"COW","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x8b6fa031c7d2e60fbfe4e663ec1b8f37df1ba483","decimalCount":9}]},{"id":"vodi-x","name":"Vodi X","symbol":"VDX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x91e64f39c1fe14492e8fdf5a8b0f305bd218c8a1","decimalCount":18}]},{"id":"dmarket","name":"DMarket","symbol":"DMT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2ccbff3a042c68716ed2a2cb0c544a9f1d1935e1","decimalCount":8}]},{"id":"otcbtc-token","name":"OTCBTC Token","symbol":"OTB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa86a0da9d05d0771955df05b44ca120661af16de","decimalCount":18}]},{"id":"indorse","name":"Indorse","symbol":"IND","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf8e386eda857484f5a12e4b5daa9984e06e73705","decimalCount":18}]},{"id":"blind-boxes","name":"Blind Boxes","symbol":"BLES","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe796d6ca1ceb1b022ece5296226bf784110031cd","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x393d87e44c7b1f5ba521b351532c24ece253b849","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x1b599beb7b1f50807dd58fd7e8ffcf073b435e71","decimalCount":18}]},{"id":"tiki-token","name":"Tiki","symbol":"TIKI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x9b76d1b12ff738c113200eb043350022ebf12ff0","decimalCount":18}]},{"id":"stobox-token","name":"Stobox","symbol":"STBU","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa6422e3e219ee6d4c1b18895275fe43556fd50ed","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xb0c4080a8fa7afa11a09473f3be14d44af3f8743","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xcf403036bc139d30080d2cf0f5b48066f98191bb","decimalCount":18}]},{"id":"crypto-inu","name":"Crypto Inu","symbol":"ABCD","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xa0cc3a881aef241d6cb3b7db3168bd26094560be","decimalCount":9}]},{"id":"privateum","name":"Privateum","symbol":"PVM","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x71aff23750db1f4edbe32c942157a478349035b2","decimalCount":18}]},{"id":"decentbet","name":"DecentBet","symbol":"DBET","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9b68bfae21df5a510931a262cecf63f41338f264","decimalCount":18}]},{"id":"dogeswap","name":"Dogeswap","symbol":"DOGES","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb4fbed161bebcb37afb1cb4a6f7ca18b977ccb25","decimalCount":18}]},{"id":"deathroad","name":"DeathRoad","symbol":"DRACE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xa6c897caaca3db7fd6e2d2ce1a00744f40ab87bb","decimalCount":18}]},{"id":"mirrored-united-states-oil-fund","name":"Mirrored United States Oil Fund","symbol":"MUSO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x31c63146a635eb7465e5853020b39713ac356991","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x9cddf33466ce007676c827c76e799f5109f1843c","decimalCount":18}]},{"id":"umi-digital","name":"Umi Digital","symbol":"UMI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x61107a409fffe1965126aa456af679719695c69c","decimalCount":18}]},{"id":"graviton-zero","name":"Graviton Zero","symbol":"GRAV","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xa6168c7e5eb7c5c379f3a1d7cf1073e09b2f031e","decimalCount":18}]},{"id":"mars","name":"Mars","symbol":"MARS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x66c0dded8433c9ea86c8cf91237b14e10b4d70b7","decimalCount":18}]},{"id":"unipower","name":"UniPower","symbol":"POWER","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf2f9a7e93f845b3ce154efbeb64fb9346fcce509","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x00d5149cdf7cec8725bf50073c51c4fa58ecca12","decimalCount":18}]},{"id":"dopewarz","name":"DopeWarz","symbol":"DRUG","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x27e2a0e643c7f17959f84c345d2123b77bbd412c","decimalCount":18}]},{"id":"kawaii-islands","name":"Kawaii Islands","symbol":"KWT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x257a8d1e03d17b8535a182301f15290f11674b53","decimalCount":18}]},{"id":"benchmark-protocol","name":"Benchmark Protocol","symbol":"MARK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x67c597624b17b16fb77959217360b7cd18284253","decimalCount":9}]},{"id":"xsigma","name":"xSigma","symbol":"SIG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7777777777697cfeecf846a76326da79cc606517","decimalCount":18}]},{"id":"liquidity-dividends-protocol","name":"Liquidity Dividends Protocol","symbol":"LID","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0417912b3a7af768051765040a55bb0925d4ddcf","decimalCount":18}]},{"id":"hakuswap","name":"HakuSwap","symbol":"HAKU","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x695fa794d59106cebd40ab5f5ca19f458c723829","decimalCount":18}]},{"id":"adamant-coin","name":"Adamant Coin","symbol":"ADMC","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xa55ef2fb2b7b6a60371fd3def9b806e74a48be69","decimalCount":9}]},{"id":"name-changing-token","name":"Name Change Token","symbol":"NCT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8a9c4dfe8b9d8962b31e4e16f8321c44d48e246e","decimalCount":18}]},{"id":"xion-finance","name":"Xion Finance","symbol":"XGT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xc25af3123d2420054c8fcd144c21113aa2853f39","decimalCount":18}]},{"id":"bondappetit-gov-token","name":"BondAppetit Governance Token","symbol":"BAG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x28a06c02287e657ec3f8e151a13c36a1d43814b0","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x1ad0132d8b5ef3cebda1a9692f36ac30be871b6b","decimalCount":18}]},{"id":"doki-doki-finance","name":"Doki Doki","symbol":"DOKI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9ceb84f92a0561fa3cc4132ab9c0b76a59787544","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x5c7f7fe4766fe8f0fa9b41e2e4194d939488ff1c","decimalCount":18}]},{"id":"balpha","name":"bAlpha","symbol":"BALPHA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7a5ce6abd131ea6b148a022cb76fc180ae3315a6","decimalCount":18}]},{"id":"wrapped-cryptokitties","name":"Wrapped CryptoKitties","symbol":"WCK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x09fe5f0236f0ea5d930197dce254d77b04128075","decimalCount":18}]},{"id":"bintex-futures","name":"Bintex Futures","symbol":"BNTX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x86d1d12523b65203851c571fcc029bf90903fb6d","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x0ec04ece89609e545b8768e303986421ffc32eaf","decimalCount":18}]},{"id":"non-fungible-toke","name":"Non-Fungible TOKE","symbol":"TOKE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x98ddc72bd02d448f68c4226f26122c66c5bd711e","decimalCount":18}]},{"id":"astrotools","name":"AstroTools","symbol":"ASTRO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcbd55d4ffc43467142761a764763652b48b969ff","decimalCount":18}]},{"id":"xiasi-inu","name":"Xiasi Inu","symbol":"XIASI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x0e20e3216ea172fcf9eaa19723b119e090fd353f","decimalCount":9}]},{"id":"united-emirate-decentralized-coin","name":"United Emirate Decentralized Coin","symbol":"UEDC","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xf0b6e29c429bbb8e1448340f0776be933805344e","decimalCount":18}]},{"id":"pinkslip-finance","name":"Pinkslip Finance","symbol":"PSLIP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x36ce7a52cda404b8fa87a98d0d17ec7dd0b144ed","decimalCount":18}]},{"id":"wault-usd","name":"Wault USD","symbol":"WUSD","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x3ff997eaea488a082fb7efc8e6b9951990d0c3ab","decimalCount":18}]},{"id":"gameflip","name":"Gameflip","symbol":"FLP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3a1bda28adb5b0a812a7cf10a1950c920f79bcd3","decimalCount":18}]},{"id":"keytango","name":"keyTango","symbol":"TANGO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x182f4c4c97cd1c24e1df8fc4c053e5c47bf53bef","decimalCount":18}]},{"id":"ttcoin","name":"TTcoin","symbol":"TC","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x659049786cb66e4486b8c0e0ccc90a5929a21162","decimalCount":4},{"networkId":"tron","contractAddress":"TCMwzYUUCxLkTNpXjkYSBgXgqXwt7KJ82y","decimalCount":4}]},{"id":"sacks","name":"Sacks","symbol":"SACKS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa6610ed604047e7b76c1da288172d15bcda57596","decimalCount":18}]},{"id":"endor","name":"Endor Protocol Token","symbol":"EDR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc528c28fec0a90c083328bc45f587ee215760a0f","decimalCount":18}]},{"id":"nil-dao","name":"Nil DAO","symbol":"NIL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x47252a63c723889814aebcac0683e615624cec64","decimalCount":18}]},{"id":"moontools","name":"MoonTools","symbol":"MOONS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x260e63d91fccc499606bae3fe945c4ed1cf56a56","decimalCount":18}]},{"id":"dogedi","name":"DOGEDI","symbol":"DOGEDI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xdc49d53330317cbc6924fa53042e0c9bca0a8d63","decimalCount":12}]},{"id":"yoyow","name":"YOYOW","symbol":"YOYOW","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcbeaec699431857fdb4d37addbbdc20e132d4903","decimalCount":18}]},{"id":"dogeville","name":"DogeVille","symbol":"DVILLE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd3b6bfd18b34ae0e3165738bf66ebc64cad1b944","decimalCount":18}]},{"id":"satopay","name":"SatoPay","symbol":"STOP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8c3ee4f778e282b59d42d693a97b80b1ed80f4ee","decimalCount":18}]},{"id":"open-governance-token","name":"OPEN Governance Token","symbol":"OPEN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x69e8b9528cabda89fe846c67675b5d73d463a916","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf35262a9d427f96d2437379ef090db986eae5d42","decimalCount":18}]},{"id":"golden-ratio-token","name":"Golden Ratio Token","symbol":"GRT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb83cd8d39462b761bb0092437d38b37812dd80a2","decimalCount":18}]},{"id":"myra-ai","name":"Myra AI","symbol":"MYRA","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x5cd7d317d9cb4d46ff0b4f6a20d9547069fe0f27","decimalCount":18}]},{"id":"structure-finance","name":"Structure Finance","symbol":"STF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1f4cb968b76931c494ff92ed80ccb169ad641cb1","decimalCount":18}]},{"id":"gaj","name":"Gaj Finance","symbol":"GAJ","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9fda7ceec4c18008096c2fe2b85f05dc300f94d0","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x595c8481c48894771ce8fade54ac6bf59093f9e8","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xf4b0903774532aee5ee567c02aab681a81539e92","decimalCount":18}]},{"id":"keep4r","name":"Keep4r","symbol":"KP4R","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa89ac6e529acf391cfbbd377f3ac9d93eae9664e","decimalCount":18}]},{"id":"alex","name":"Alex","symbol":"ALEX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8ba6dcc667d3ff64c1a2123ce72ff5f0199e5315","decimalCount":4}]},{"id":"plutos-network","name":"Plutos Network","symbol":"PLUT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x2984f825bfe72e55e1725d5c020258e81ff97450","decimalCount":18}]},{"id":"yetiswap","name":"YetiSwap","symbol":"YTS","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x488f73cddda1de3664775ffd91623637383d6404","decimalCount":18}]},{"id":"squid","name":"SquidDao","symbol":"SQUID","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x21ad647b8f4fe333212e735bfc1f36b4941e6ad2","decimalCount":9}]},{"id":"gowithmi","name":"GoWithMi","symbol":"GMAT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb13de094cc5cee6c4cc0a3737bf0290166d9ca5d","decimalCount":18}]},{"id":"wrapped-virgin-gen-0-cryptokitties","name":"Wrapped Virgin Gen-0 CryptoKittties","symbol":"WVG0","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x25c7b64a93eb1261e130ec21a3e9918caa38b611","decimalCount":18}]},{"id":"cnn","name":"Content Neutrality Network","symbol":"CNN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8713d26637cf49e1b6b4a7ce57106aabc9325343","decimalCount":18}]},{"id":"basis-share","name":"Basis Share","symbol":"BAS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x106538cc16f938776c7c180186975bca23875287","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x83a6da342099835bcaa9c219dd76a5033c837de5","decimalCount":18}]},{"id":"wetrust","name":"WeTrust","symbol":"TRST","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcb94be6f13a1182e4a4b6140cb7bf2025d28e41b","decimalCount":6}]},{"id":"nftmall","name":"NFTmall","symbol":"GEM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9b17baadf0f21f03e35249e0e59723f34994f806","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xbac1df744df160877cdc45e13d0394c06bc388ff","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xdebb1d6a2196f2335ad51fbde7ca587205889360","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x4a7b9a4589a88a06ca29f99556db08234078d727","decimalCount":18}]},{"id":"tradao","name":"TraDAO","symbol":"TOD","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x21d5fa5ecf2605c0e835ae054af9bba0468e5951","decimalCount":9}]},{"id":"dragonbite","name":"DragonBite","symbol":"BITE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4eed0fa8de12d5a86517f214c2f11586ba2ed88d","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xde69c05e8121ef0db29c3d9ceceda6ef6b606d0c","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x280724409b288de06c6d66c05965d3d456e2283a","decimalCount":18}]},{"id":"shar-pei","name":"Shar Pei","symbol":"SHARPEI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xfe3af7376e412a377358d5894c790bb3e00d0dc1","decimalCount":18}]},{"id":"givly-coin","name":"GIV Token","symbol":"GIV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf6537fe0df7f0cc0985cf00792cc98249e73efa0","decimalCount":8}]},{"id":"yam-v2","name":"YAM v2","symbol":"YAMV2","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xaba8cac6866b83ae4eec97dd07ed254282f6ad8a","decimalCount":24}]},{"id":"catbread","name":"CatBread","symbol":"CATBREAD","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x74a6e371f95073005b3a5faf4a9e25ae30290f94","decimalCount":9}]},{"id":"stox","name":"Stox","symbol":"STX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x006bea43baa3f7a6f765f14f10a1a1b08334ef45","decimalCount":18}]},{"id":"nfx-coin","name":"NFX Coin","symbol":"NFXC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2d39ec4da54329d28d230b4973f5aa27886c3aee","decimalCount":18}]},{"id":"seigniorage-shares","name":"Seigniorage Shares","symbol":"SHARE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x39795344cbcc76cc3fb94b9d1b15c23c2070c66d","decimalCount":9}]},{"id":"chartex","name":"ChartEx","symbol":"CHART","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1d37986f252d0e349522ea6c3b98cb935495e63e","decimalCount":18}]},{"id":"cream-eth2","name":"Cream ETH 2","symbol":"CRETH2","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xcbc1065255cbc3ab41a6868c22d1f1c573ab89fd","decimalCount":18}]},{"id":"bscwin-bulls","name":"BSCWIN Bulls","symbol":"BSCWIN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x73b01a9c8379a9d3009f2351f22583f8b75cc1ba","decimalCount":9}]},{"id":"u-network","name":"U Network","symbol":"UUU","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3543638ed4a9006e4840b105944271bcea15605d","decimalCount":18}]},{"id":"mytoken","name":"MyToken","symbol":"MT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9b4e2b4b13d125238aa0480dd42b4f6fc71b37cc","decimalCount":18}]},{"id":"wallfair","name":"Wallfair","symbol":"WFAIR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc6065b9fc8171ad3d29bad510709249681758972","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xb6b5cdf74606181a1b05bfc0b9f17fc2a64b0cd5","decimalCount":18}]},{"id":"zerogoki","name":"Zerogoki","symbol":"REI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x011864d37035439e078d64630777ec518138af05","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x765b85839717ebfc84378b83381a4814897a0506","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xb9f9e37c2cdbaff928c3da730b02f06fe09ae70e","decimalCount":18}]},{"id":"avaxtars","name":"Avaxtars","symbol":"AVXT","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0x397bbd6a0e41bdf4c3f971731e180db8ad06ebc1","decimalCount":6}]},{"id":"rare","name":"Rare","symbol":"RARE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x81b1bfd6cb9ad42db395c2a27f73d4dcf5777e2d","decimalCount":4}]},{"id":"dark-matter","name":"Dark Matter","symbol":"DMT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x79126d32a86e6663f3aaac4527732d0701c1ae6c","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xd28449bb9bb659725accad52947677cce3719fd7","decimalCount":18}]},{"id":"xiotri","name":"Xiotri","symbol":"XIOT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x31024a4c3e9aeeb256b825790f5cb7ac645e7cd5","decimalCount":3}]},{"id":"mochi-market","name":"Mochi Market","symbol":"MOMA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbd1848e1491d4308ad18287a745dd4db2a4bd55b","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xb72842d6f5fedf91d22d56202802bb9a79c6322e","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xe3ab61371ecc88534c522922a026f2296116c109","decimalCount":18}]},{"id":"node-squared","name":"Node Squared","symbol":"N2","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6110c64219621ce5b02fb8e8e57b54c01b83bf85","decimalCount":9}]},{"id":"metafluence","name":"Metafluence","symbol":"METO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xa78775bba7a542f291e5ef7f13c6204e704a90ba","decimalCount":18}]},{"id":"hydro","name":"Hydro","symbol":"HYDRO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x946112efab61c3636cbd52de2e1392d7a75a6f01","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xf3dbb49999b25c9d6641a9423c7ad84168d00071","decimalCount":18}]},{"id":"flurry","name":"Flurry Finance","symbol":"FLURRY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x60f63b76e2fc1649e57a3489162732a90acf59fe","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x47c9bcef4fe2dbcdf3abf508f147f1bbe8d4fef2","decimalCount":18}]},{"id":"dexfolio","name":"Dexfolio","symbol":"DEXF","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xb9844a9cb6abd9f86bb0b3ad159e37eecce08987","decimalCount":18}]},{"id":"sharder-protocol","name":"Sharder protocol","symbol":"SS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbbff862d906e348e9946bfb2132ecb157da3d4b4","decimalCount":18}]},{"id":"dfund","name":"dFund","symbol":"DFND","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd2adc1c84443ad06f0017adca346bd9b6fc52cab","decimalCount":18}]},{"id":"acoconut","name":"ACoconut","symbol":"AC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9a0aba393aac4dfbff4333b06c407458002c6183","decimalCount":18}]},{"id":"reflect-finance","name":"reflect.finance","symbol":"RFI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa1afffe3f4d611d252010e3eaf6f4d77088b0cd7","decimalCount":9}]},{"id":"maincoin","name":"MainCoin","symbol":"MNC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9f0f1be08591ab7d990faf910b38ed5d60e4d5bf","decimalCount":18}]},{"id":"odem","name":"ODEM","symbol":"ODE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbf52f2ab39e26e0951d2a02b49b7702abe30406a","decimalCount":18}]},{"id":"catex-token","name":"Catex Token","symbol":"CATT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6e605c269e0c92e70beeb85486f1fc550f9380bd","decimalCount":18}]},{"id":"lys-capital","name":"LYS Capital","symbol":"LYS","active":true,"networks":[{"networkId":"arbitrum-one","contractAddress":"0xa4f595ba35161c9ffe3db8c03991b9c2cbb26c6b","decimalCount":18}]},{"id":"bonfi","name":"BonFi","symbol":"BNF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1de5e000c41c8d35b9f1f4985c23988f05831057","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xca14caf9e8dd2793e7010fc48dfe6c6af8445136","decimalCount":18}]},{"id":"cryptotask-2","name":"CryptoTask","symbol":"CTASK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x196c81385bc536467433014042788eb707703934","decimalCount":18}]},{"id":"jade-currency","name":"Jade Currency","symbol":"JADE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x330f4fe5ef44b4d0742fe8bed8ca5e29359870df","decimalCount":18}]},{"id":"fufu","name":"Fufu","symbol":"FUFU","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x509a51394cc4d6bb474fefb2994b8975a55a6e79","decimalCount":18}]},{"id":"stater","name":"Stater","symbol":"STR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x84bb947fcedba6b9c7dcead42df07e113bb03007","decimalCount":18}]},{"id":"alt-estate","name":"AltEstate Token","symbol":"ALT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x419b8ed155180a8c9c64145e76dad49c0a4efb97","decimalCount":18}]},{"id":"crdt","name":"CRDT","symbol":"CRDT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xdaab5e695bb0e8ce8384ee56ba38fa8290618e52","decimalCount":18}]},{"id":"knit-finance","name":"Knit Finance","symbol":"KFT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xef53462838000184f35f7d991452e5f25110b207","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x1b41a1ba7722e6431b1a782327dbe466fe1ee9f9","decimalCount":18}]},{"id":"keysians-network","name":"Keysians Network","symbol":"KEN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6a7ef4998eb9d0f706238756949f311a59e05745","decimalCount":18}]},{"id":"yearn-secure","name":"Yearn Secure","symbol":"YSEC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xeea9ae787f3a620072d13b2cdc8cabffb9c0ab96","decimalCount":18}]},{"id":"leverj-gluon","name":"Leverj Gluon","symbol":"L2","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbbff34e47e559ef680067a6b1c980639eeb64d24","decimalCount":18}]},{"id":"twinci","name":"Twinci","symbol":"TWIN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xaf83f292fced83032f52ced45ef7dbddb586441a","decimalCount":18}]},{"id":"ydragon","name":"YDragon","symbol":"YDR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x3757232b55e60da4a8793183ac030cfce4c3865d","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x3757232b55e60da4a8793183ac030cfce4c3865d","decimalCount":18},{"networkId":"avalanche","contractAddress":"0xf03dccaec9a28200a6708c686cf0b8bf26ddc356","decimalCount":18}]},{"id":"everex","name":"Everex","symbol":"EVX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf3db5fa2c66b7af3eb0c0b782510816cbe4813b8","decimalCount":4}]},{"id":"checkdot","name":"CheckDot","symbol":"CDT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x0cbd6fadcf8096cc9a43d90b45f65826102e3ece","decimalCount":18}]},{"id":"vicewrld","name":"Vicewrld","symbol":"VICE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xeea06fc74182b195f679f31d735d95ee502f03f3","decimalCount":18}]},{"id":"hackspace-capital","name":"Hackspace Capital","symbol":"HAC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x43567eb78638a55bbe51e9f9fb5b2d7ad1f125aa","decimalCount":4}]},{"id":"somee-advertising-token","name":"SoMee Advertising","symbol":"SAT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc9f1016d336ef77aee75fc11ad64c5ecf9121332","decimalCount":18}]},{"id":"safewhale","name":"SafeWhale","symbol":"SWHAL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4048a31e0a4fa577d343290835b34ebb4e3dbb1b","decimalCount":18}]},{"id":"riskmoon","name":"Riskmoon","symbol":"RISKMOON","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xa96f3414334f5a0a529ff5d9d8ea95f42147b8c9","decimalCount":9}]},{"id":"proton-token","name":"Proton Token","symbol":"PTT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4689a4e169eb39cc9078c0940e21ff1aa8a39b9c","decimalCount":18}]},{"id":"ethereum-gold-project","name":"Ethereum Gold Project","symbol":"ETGP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa96f31f1c187c28980176c3a27ba7069f48abde4","decimalCount":8}]},{"id":"solchicks-shards","name":"SolChicks Shards","symbol":"SHARDS","active":true,"networks":[{"networkId":"solana","contractAddress":"8j3hXRK5rdoZ2vSpGLRmXtWmW6iYaRUw5xVk4Kzmc9Hp","decimalCount":9}]},{"id":"diamond-coin","name":"Diamond Coin","symbol":"DIAMOND","active":true,"networks":[{"networkId":"fantom","contractAddress":"0xdda0f0e1081b8d64ab1d64621eb2679f93086705","decimalCount":18}]},{"id":"gambit","name":"Gambit","symbol":"GMT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x99e92123eb77bc8f999316f622e5222498438784","decimalCount":18}]},{"id":"lever-network","name":"Lever Network","symbol":"LEV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbc194e6f748a222754c3e8b9946922c09e7d4e91","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xbc194e6f748a222754c3e8b9946922c09e7d4e91","decimalCount":18}]},{"id":"hanu-yokia","name":"Hanu Yokia","symbol":"HANU","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x72e5390edb7727e3d4e3436451dadaff675dbcc0","decimalCount":12},{"networkId":"binance-smart-chain","contractAddress":"0xdae4f1dca49408288b55250022f67195eff2445a","decimalCount":12},{"networkId":"polygon-pos","contractAddress":"0x709a4b6217584188ddb93c82f5d716d969acce1c","decimalCount":12}]},{"id":"cryptotycoon","name":"CryptoTycoon","symbol":"CTT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x464863745ed3af8b9f8871f1082211c55f8f884d","decimalCount":18}]},{"id":"bethereum","name":"Bethereum","symbol":"BETHER","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x14c926f2290044b647e1bf2072e67b495eff1905","decimalCount":18}]},{"id":"smartshare","name":"Smartshare","symbol":"SSP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x624d520bab2e4ad83935fa503fb130614374e850","decimalCount":4}]},{"id":"curio-governance","name":"Curio Governance","symbol":"CGT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf56b164efd3cfc02ba739b719b6526a6fa1ca32a","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x3d04edc843e74935c09f54cc4b2fe1870e347ac9","decimalCount":18}]},{"id":"merchdao","name":"MerchDAO","symbol":"MRCH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbed4ab0019ff361d83ddeb74883dac8a70f5ea1e","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x4df071fb2d145be595b767f997c91818694a6ce1","decimalCount":18}]},{"id":"fantomstarter","name":"FantomStarter","symbol":"FS","active":true,"networks":[{"networkId":"fantom","contractAddress":"0xc758295cd1a564cdb020a78a681a838cf8e0627d","decimalCount":18}]},{"id":"more-token","name":"More","symbol":"MORE","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0xd9d90f882cddd6063959a9d837b05cb748718a05","decimalCount":18}]},{"id":"obtoken","name":"OB","symbol":"OBT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x8da6113655309f84127e0837fcf5c389892578b3","decimalCount":18}]},{"id":"afen-blockchain","name":"AFEN Blockchain","symbol":"AFEN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xd0840d5f67206f865aee7cce075bd4484cd3cc81","decimalCount":18}]},{"id":"flux","name":"Datamine FLUX","symbol":"FLUX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x469eda64aed3a3ad6f868c44564291aa415cb1d9","decimalCount":18}]},{"id":"kassandra","name":"Kassandra","symbol":"KACY","active":true,"networks":[{"networkId":"avalanche","contractAddress":"0xf32398dae246c5f672b52a54e9b413dffcae1a44","decimalCount":18}]},{"id":"mirrored-netflix","name":"Mirrored Netflix","symbol":"MNFLX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc8d674114bac90148d11d3c1d33c61835a0f9dcd","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xa04f060077d90fe2647b61e4da4ad1f97d6649dc","decimalCount":18}]},{"id":"stronghands-finance","name":"StrongHands Finance","symbol":"ISHND","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x1cc1aca0dae2d6c4a0e8ae7b4f2d01eabbc435ee","decimalCount":18}]},{"id":"mirrored-google","name":"Mirrored Google","symbol":"MGOOGL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x59a921db27dd6d4d974745b7ffc5c33932653442","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x62d71b23bf15218c7d2d7e48dbbd9e9c650b173f","decimalCount":18}]},{"id":"moonbear-finance","name":"MoonBear.Finance","symbol":"MBF","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xe2997ae926c7a76af782923a7fef89f36d86c98f","decimalCount":9}]},{"id":"coinsbit-token","name":"Coinsbit Token","symbol":"CNB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc538143202f3b11382d8606aae90a96b042a19db","decimalCount":18}]},{"id":"cryption-network","name":"Cryption Network","symbol":"CNT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x429876c4a6f89fb470e92456b8313879df98b63c","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xd1e6354fb05bf72a8909266203dab80947dceccf","decimalCount":18}]},{"id":"0xcert","name":"0xcert","symbol":"ZXC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x83e2be8d114f9661221384b3a50d24b96a5653f5","decimalCount":18}]},{"id":"hero-inu","name":"Heros","symbol":"HEROS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xb622400807765e73107b7196f444866d7edf6f62","decimalCount":9},{"networkId":"binance-smart-chain","contractAddress":"0xd1673c00ac7010bf2c376ebea43633dd61a81016","decimalCount":9}]},{"id":"srcoin","name":"SRH","symbol":"SRH","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc350e846e2c57f9eece90febc253d14c8080871b","decimalCount":18}]},{"id":"0xmonero","name":"0xMonero","symbol":"0XMR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x035df12e0f3ac6671126525f1015e47d79dfeddf","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x22a213852cee93eb6d41601133414d180c5684c2","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x52ede6bba83b7b4ba1d738df0df713d6a2036b71","decimalCount":18},{"networkId":"fantom","contractAddress":"0xab41861399eb56896b24fbaabaa8bce45e4a626b","decimalCount":18}]},{"id":"index-coop-matic-2x-flexible-leverage-index","name":"Index Coop - MATIC 2x Flexible Leverage Index","symbol":"MATIC2X-FLI-P","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0xf287d97b6345bad3d88856b26fb7c0ab3f2c7976","decimalCount":18}]},{"id":"noderunners","name":"Node Runners","symbol":"NDR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x739763a258640919981f9ba610ae65492455be53","decimalCount":18}]},{"id":"degenvc","name":"DegenVC","symbol":"DGVC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x26e43759551333e57f073bb0772f50329a957b30","decimalCount":18}]},{"id":"krypto-kitty","name":"Krypto Kitty","symbol":"KTY","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x86296279c147bd40cbe5b353f83cea9e9cc9b7bb","decimalCount":9}]},{"id":"lien","name":"Lien","symbol":"LIEN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xab37e1358b639fd877f015027bb62d3ddaa7557e","decimalCount":8},{"networkId":"binance-smart-chain","contractAddress":"0x5d684adaf3fcfe9cfb5cede3abf02f0cdd1012e3","decimalCount":8}]},{"id":"value-finance","name":"Value Finance","symbol":"VFT","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x14e8bcd053e68a22f239b9e9bead87932465d245","decimalCount":18}]},{"id":"yeld-finance","name":"Yeld Finance","symbol":"YELD","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x468ab3b1f63a1c14b361bc367c3cc92277588da1","decimalCount":18}]},{"id":"infinitypad","name":"InfinityPad","symbol":"INFP","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xfe82eff54a58c21ffc9523c4998d5dad84dcbd50","decimalCount":18}]},{"id":"wtf-token","name":"Fees.wtf","symbol":"WTF","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa68dd8cb83097765263adad881af6eed479c4a33","decimalCount":18}]},{"id":"defiville-island","name":"DefiVille Island","symbol":"ISLA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x20a68f9e34076b2dc15ce726d7eebb83b694702d","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xfe6a2342f7c5d234e8496df12c468be17e0c181f","decimalCount":18}]},{"id":"mirrored-ishares-gold-trust","name":"Mirrored iShares Gold Trust","symbol":"MIAU","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1d350417d9787e000cc1b95d70e9536dcd91f373","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x1658aed6c7dbab2ddbd8f5d898b0e9eab0305813","decimalCount":18}]},{"id":"one-cash","name":"One Cash","symbol":"ONC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd90e69f67203ebe02c917b5128629e77b4cd92dc","decimalCount":18}]},{"id":"medi-token","name":"Medi","symbol":"MEDI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x24b20da7a2fa0d1d5afcd693e1c8afff20507efd","decimalCount":9}]},{"id":"sechain","name":"SeChain","symbol":"SNN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf5717f5df41ea67ef67dfd3c1d02f9940bcf5d08","decimalCount":3},{"networkId":"binance-smart-chain","contractAddress":"0xa997e5aaae60987eb0b59a336dce6b158b113100","decimalCount":3}]},{"id":"skyrim-finance","name":"Skyrim Finance","symbol":"SKYRIM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2610f0bfc21ef389fe4d03cfb7de9ac1e6c99d6e","decimalCount":18}]},{"id":"melalie","name":"MELX","symbol":"MEL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xed0889f7e1c7c7267407222be277e1f1ef4d4892","decimalCount":18}]},{"id":"etha-lend","name":"ETHA Lend","symbol":"ETHA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x59e9261255644c411afdd00bd89162d09d862e38","decimalCount":18}]},{"id":"crusaders-of-crypto","name":"Crusaders of Crypto","symbol":"CRUSADER","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x6289812163af9421e566b3d74774074fac2a0441","decimalCount":9}]},{"id":"cryptobonusmiles","name":"CryptoBonusMiles","symbol":"CBM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x95efd1fe6099f65a7ed524def487483221094947","decimalCount":18},{"networkId":"binancecoin","contractAddress":"CBM-4B2","decimalCount":8}]},{"id":"buymainstreet","name":"BuyMainStreet","symbol":"$MAINST","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x8fc1a944c149762b6b578a06c0de2abd6b7d2b89","decimalCount":9}]},{"id":"tendies","name":"Tendies","symbol":"TEND","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1453dbb8a29551ade11d89825ca812e05317eaeb","decimalCount":18}]},{"id":"nasdex-token","name":"NASDEX","symbol":"NSDX","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0xe8d17b127ba8b9899a160d9a07b69bca8e08bfc6","decimalCount":18}]},{"id":"morphie","name":"Morphie","symbol":"MRFI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xaf1167b1f90e4f27d9f520a4cd3a1e452e011cea","decimalCount":18},{"networkId":"avalanche","contractAddress":"0x05e481b19129b560e921e487adb281e70bdba463","decimalCount":18}]},{"id":"safeswap-token","name":"Safeswap SSGTX","symbol":"SSGTX","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0xd0cfd20e8bbdb7621b705a4fd61de2e80c2cd02f","decimalCount":18}]},{"id":"wault","name":"Wault","symbol":"WAULTX","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xb64e638e60d154b43f660a6bf8fd8a3b249a6a21","decimalCount":18}]},{"id":"lucha","name":"Lucha","symbol":"LUCHA","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x6749441fdc8650b5b5a854ed255c82ef361f1596","decimalCount":18}]},{"id":"datamine","name":"Datamine","symbol":"DAM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf80d589b3dbe130c270a69f1a69d050f268786df","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0xb75bbd79985a8092b05224f62d7fed25924b075d","decimalCount":18}]},{"id":"polkacipher","name":"PolkaCipher","symbol":"CPHR","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x7428be82fd79d4c98650a7c67de9682a64fcab71","decimalCount":18}]},{"id":"updog","name":"UpDog","symbol":"UPDOG","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x400613f184d1207f5c07a67d67040a4e23e92feb","decimalCount":9}]},{"id":"catbonk","name":"Catbonk","symbol":"CABO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xdfaabaa57dec10c049335bdaa2e949b4ce2ead30","decimalCount":9}]},{"id":"app-alliance-association","name":"AAAchain","symbol":"AAA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6aba1623ea906d1164cbb007e764ebde2514a2ba","decimalCount":10}]},{"id":"ownly","name":"Ownly","symbol":"OWN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x7665cb7b0d01df1c9f9b9cc66019f00abd6959ba","decimalCount":18}]},{"id":"mib-coin","name":"MIB Coin","symbol":"MIB","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x146d8d942048ad517479c9bab1788712af180fde","decimalCount":18}]},{"id":"collateral-pay","name":"Collateral Pay","symbol":"COLL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x957891c11616d3e0b0a76a76fb42724c382e0ef3","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xa4cb040b85e94f5c0c32ea1151b20d3ab40b3493","decimalCount":18}]},{"id":"unity-network","name":"Unity Network","symbol":"UNT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8d610e20481f4c4f3acb87bba9c46bef7795fdfe","decimalCount":18}]},{"id":"piplcoin","name":"PiplCoin","symbol":"PIPL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe64509f0bf07ce2d29a7ef19a8a9bc065477c1b4","decimalCount":8}]},{"id":"fuzex","name":"FuzeX","symbol":"FXT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1829aa045e21e0d59580024a951db48096e01782","decimalCount":18}]},{"id":"jetcoin","name":"Jetcoin","symbol":"JET","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8727c112c712c4a03371ac87a74dd6ab104af768","decimalCount":18}]},{"id":"2gether-2","name":"2gether","symbol":"2GT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc96c1609a1a45ccc667b2b7fa6508e29617f7b69","decimalCount":18}]},{"id":"bcv","name":"BitCapitalVendor","symbol":"BCV","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1014613e2b3cbc4d575054d4982e580d9b99d7b1","decimalCount":8}]},{"id":"1million-token","name":"1Million Token","symbol":"1MT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xf0bc1ae4ef7ffb126a8347d06ac6f8add770e1ce","decimalCount":7},{"networkId":"binance-smart-chain","contractAddress":"0x8d67448d4f6231abc070a42a8905084b79e09136","decimalCount":7}]},{"id":"insula","name":"Insula","symbol":"ISLA","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x697ef32b4a3f5a4c39de1cb7563f24ca7bfc5947","decimalCount":18}]},{"id":"typhoon-network","name":"Typhoon Network","symbol":"TYPH","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4090e535f2e251f5f88518998b18b54d26b3b07c","decimalCount":18}]},{"id":"zeusshield","name":"Zeusshield","symbol":"ZSC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7a41e0517a5eca4fdbc7fbeba4d4c47b9ff6dc63","decimalCount":18}]},{"id":"x-consoles","name":"X-Consoles","symbol":"GAME","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x882e5b370d595e50c24b2a0e7a94e87cc32adda1","decimalCount":18}]},{"id":"impulseven","name":"ImpulseVen","symbol":"I7","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x560cc7de81b2a594f6518713cbe122bcf297a6e8","decimalCount":18}]},{"id":"hellogold","name":"HelloGold","symbol":"HGT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xba2184520a1cc49a6159c57e61e1844e085615b6","decimalCount":8}]},{"id":"avaluse","name":"Avaluse","symbol":"AVAL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbcf9dbf8b14ed096b2ba08b7269356197fdd1b5d","decimalCount":18}]},{"id":"dust-token","name":"DUST Token","symbol":"DUST","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xbca3c97837a39099ec3082df97e28ce91be14472","decimalCount":8},{"networkId":"polygon-pos","contractAddress":"0x556f501cf8a43216df5bc9cc57eb04d4ffaa9e6d","decimalCount":8}]},{"id":"bitdegree","name":"BitDegree","symbol":"BDG","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1961b3331969ed52770751fc718ef530838b6dee","decimalCount":18}]},{"id":"hnk-orijent-1919-token","name":"HNK Orijent 1919","symbol":"ORI","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x54cc4db6f878a1cde6bdd0c8befcf70f5dabf206","decimalCount":5}]},{"id":"dios-finance","name":"Dios Finance","symbol":"DIOS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x08eecf5d03bda3df2467f6af46b160c24d931de7","decimalCount":9}]},{"id":"gamex","name":"GameX","symbol":"GMX","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xc62ef0d8e137499833abb05dee47007d2b334ba6","decimalCount":9}]},{"id":"sentinel-chain","name":"Sentinel Chain","symbol":"SENC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa13f0743951b4f6e3e3aa039f682e17279f52bc3","decimalCount":18}]},{"id":"rentberry","name":"Rentberry","symbol":"BERRY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6aeb95f06cda84ca345c2de0f3b7f96923a44f4c","decimalCount":14}]},{"id":"oro","name":"ORO","symbol":"ORO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc3eb2622190c57429aac3901808994443b64b466","decimalCount":18}]},{"id":"better-money","name":"Better Money","symbol":"BETTER","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa7925aa2a6e4575ab0c74d169f3bc3e03d4c319a","decimalCount":4}]},{"id":"nft-stars","name":"NFT Stars","symbol":"NFTS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x08037036451c768465369431da5c671ad9b37dbc","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x08037036451c768465369431da5c671ad9b37dbc","decimalCount":18}]},{"id":"midas-protocol","name":"Midas Protocol","symbol":"MAS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x23ccc43365d9dd3882eab88f43d515208f832430","decimalCount":18}]},{"id":"blocsport-one","name":"blocsport.one","symbol":"BLS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x708739980021a0b0b2e555383fe1283697e140e9","decimalCount":18}]},{"id":"micromoney","name":"MicroMoney","symbol":"AMM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8b1f49491477e0fb46a29fef53f1ea320d13c349","decimalCount":6}]},{"id":"pancakepoll","name":"PancakePoll","symbol":"PPOLL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xc29000a4b1ecd326b6dafae17bda636475fea1e7","decimalCount":9}]},{"id":"jetoken","name":"JeToken","symbol":"JETS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x0f005dfe97c5041e538b7075915b2ee706677c26","decimalCount":9}]},{"id":"fortress","name":"Fortress Loans","symbol":"FTS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4437743ac02957068995c48e08465e0ee1769fbe","decimalCount":18}]},{"id":"blockcdn","name":"BlockCDN","symbol":"BCDN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1e797ce986c3cff4472f7d38d5c4aba55dfefe40","decimalCount":15}]},{"id":"bounty0x","name":"Bounty0x","symbol":"BNTY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd2d6158683aee4cc838067727209a0aaf4359de3","decimalCount":18}]},{"id":"owndata","name":"OWNDATA","symbol":"OWN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x170b275ced089fffaebfe927f445a350ed9160dc","decimalCount":8}]},{"id":"battle-saga","name":"Battle Saga","symbol":"BTL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x708955db0d4c52ffbf9aa34af7f3ca8bf07390a8","decimalCount":18}]},{"id":"unicly-doki-doki-collection","name":"Unicly Doki Doki Collection","symbol":"UDOKI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7e6c38d007740931e4b419bf15a68c79a0fb0c66","decimalCount":18}]},{"id":"non-fungible-yearn","name":"Non-Fungible Yearn","symbol":"NFY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1cbb83ebcd552d5ebf8131ef8c9cd9d9bab342bc","decimalCount":18}]},{"id":"trendering","name":"Trendering","symbol":"TRND","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc3dd23a0a854b4f9ae80670f528094e9eb607ccb","decimalCount":18}]},{"id":"latiumx","name":"LatiumX","symbol":"LATX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x2f85e502a988af76f7ee6d83b7db8d6c0a823bf9","decimalCount":8}]},{"id":"facts","name":"FACTS","symbol":"BKC","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x34bdf48a8f753de4822a6cfb1fee275f9b4d662e","decimalCount":18}]},{"id":"pivot-token","name":"Pivot Token","symbol":"PVT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x7869c4a1a3f6f8684fbcc422a21ad7abe3167834","decimalCount":18}]},{"id":"babyswap","name":"BabySwap","symbol":"BABY","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x53e562b9b7e5e94b81f10e96ee70ad06df3d2657","decimalCount":18}]},{"id":"pink-panther","name":"PINK PANTHER","symbol":"PINK","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xa113b79c09f0794568b8864a24197e0b817041ea","decimalCount":18}]},{"id":"gencoin-capital","name":"GenCoin Capital","symbol":"GENCAP","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x0b569fa433faa7f01f3ea880193de38044b41de0","decimalCount":9}]},{"id":"greeneum-network","name":"Greeneum Network","symbol":"GREEN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe0a16435df493bd17a58cb2ee58675f5ea069517","decimalCount":18}]},{"id":"kickpad","name":"KickPad","symbol":"KPAD","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xcfefa64b0ddd611b125157c41cd3827f2e8e8615","decimalCount":18}]},{"id":"mirrored-twitter","name":"Mirrored Twitter","symbol":"MTWTR","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xedb0414627e6f1e3f082de65cd4f9c693d78cca9","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0x7426ab52a0e057691e2544fae9c8222e958b2cfb","decimalCount":18}]},{"id":"polkainsure-finance","name":"Polkainsure Finance","symbol":"PIS","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x834ce7ad163ab3be0c5fd4e0a81e67ac8f51e00c","decimalCount":18}]},{"id":"sparkpoint-fuel","name":"SparkPoint Fuel","symbol":"SFUEL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x37ac4d6140e54304d77437a5c11924f61a2d976f","decimalCount":18}]},{"id":"omni-consumer-protocol","name":"Omni Consumer Protocol","symbol":"OCP","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x3c70260eee0a2bfc4b375feb810325801f289fbd","decimalCount":18}]},{"id":"parkgene","name":"Parkgene","symbol":"GENE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x6dd4e4aad29a40edd6a409b9c1625186c9855b4d","decimalCount":8}]},{"id":"protector-roge","name":"Protector Roge","symbol":"PROGE","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x282d0ad1fa03dfbdb88243b958e77349c73737d1","decimalCount":9}]},{"id":"ailink-token","name":"AiLink Token","symbol":"ALI","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x4289c043a12392f1027307fb58272d8ebd853912","decimalCount":18}]},{"id":"porta","name":"Porta","symbol":"KIAN","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x5ece3f1542c4e1a06767457e4d8286bea772fc41","decimalCount":18}]},{"id":"auric-network","name":"Auric Network","symbol":"AUSCM","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x1c7bbadc81e18f7177a95eb1593e5f5f35861b10","decimalCount":18}]},{"id":"vox-finance","name":"Vox.Finance","symbol":"VOX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x12d102f06da35cc0111eb58017fd2cd28537d0e1","decimalCount":18},{"networkId":"binance-smart-chain","contractAddress":"0xc227f8eecc481a8e8baa30a4754b109b81c4dfa4","decimalCount":18}]},{"id":"bigbom-eco","name":"Bigbom","symbol":"BBO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x84f7c44b6fed1080f647e354d552595be2cc602f","decimalCount":18}]},{"id":"firdaos","name":"Firdaos","symbol":"FDO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x361887c1d1b73557018c47c8001711168128cf69","decimalCount":18}]},{"id":"staysafu","name":"StaySAFU","symbol":"SAFU","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x890cc7d14948478c98a6cd7f511e1f7f7f99f397","decimalCount":9}]},{"id":"marsx","name":"MarsX","symbol":"MX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xe0df31d06d72b2f5231489af0edc422b372f49f1","decimalCount":18}]},{"id":"ark-of-the-universe","name":"Ark Of The Universe","symbol":"ARKS","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4c3d5af5c43dbecee525327e93d51eb4d6ddabec","decimalCount":18}]},{"id":"flokibonk","name":"FlokiBonk","symbol":"FLOBO","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x9d3e14b607b2f569cfafe29af71e811d7e575cfe","decimalCount":9}]},{"id":"pinkelon","name":"PinkElon","symbol":"PINKE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x8da0f18e4deb7ba81dbd061df57325a894014b5a","decimalCount":9}]},{"id":"rune","name":"Rune","symbol":"RUNE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xa9776b590bfc2f956711b3419910a5ec1f63153e","decimalCount":18}]},{"id":"bepay","name":"bePAY Finance","symbol":"BECOIN","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x8f081eb884fd47b79536d28e2dd9d4886773f783","decimalCount":6},{"networkId":"binance-smart-chain","contractAddress":"0x8f081eb884fd47b79536d28e2dd9d4886773f783","decimalCount":6}]},{"id":"revival","name":"REVIVAL","symbol":"RVL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x7eaee60040135f20f508a393ca400ded339d654e","decimalCount":9}]},{"id":"dogeyield","name":"DogeYield","symbol":"DOGY","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x9c405acf8688afb61b3197421cdeec1a266c6839","decimalCount":18}]},{"id":"verify","name":"Verify","symbol":"CRED","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x672a1ad4f667fb18a333af13667aa0af1f5b5bdd","decimalCount":18}]},{"id":"origo","name":"Origo","symbol":"OGO","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xff0e5e014cf97e0615cb50f6f39da6388e2fae6e","decimalCount":18}]},{"id":"richochet","name":"Ricochet","symbol":"RIC","active":true,"networks":[{"networkId":"polygon-pos","contractAddress":"0x263026e7e53dbfdce5ae55ade22493f828922965","decimalCount":18}]},{"id":"akropolis-delphi","name":"Delphi","symbol":"ADEL","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x94d863173ee77439e4292284ff13fad54b3ba182","decimalCount":18}]},{"id":"adtoken","name":"adToken","symbol":"ADT","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xd0d6d6c5fe4a677d343cc433536bb717bae167dd","decimalCount":9}]},{"id":"savix","name":"Savix","symbol":"SVX","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0xc434b27736a6882d33094d34792999702860a13c","decimalCount":9}]},{"id":"colligo","name":"Colligo","symbol":"COTK","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0xea738b6f1c888b2eced0fad66918defefe7c4494","decimalCount":18}]},{"id":"brick-token","name":"Brick","symbol":"BRICK","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x4e5ab517719a2bdbafefc22c712d7b5bc5f5544e","decimalCount":18}]},{"id":"pancaketools","name":"PancakeTools","symbol":"TCAKE","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x3b831d36ed418e893f42d46ff308c326c239429f","decimalCount":18}]},{"id":"axia","name":"Axia","symbol":"AXIAV3","active":true,"networks":[{"networkId":"ethereum","contractAddress":"0x793786e2dd4cc492ed366a94b88a3ff9ba5e7546","decimalCount":18},{"networkId":"polygon-pos","contractAddress":"0x49690541e3f6e933a9aa3cffee6010a7bb5b72d7","decimalCount":18}]},{"id":"token-kennel","name":"Token Kennel","symbol":"KENNEL","active":true,"networks":[{"networkId":"binance-smart-chain","contractAddress":"0x2c319cde4e46f85f7a1004b9a81d4a52d896e208","decimalCount":18}]}],"total":2498}
\ No newline at end of file
diff --git a/app/src/main/ic_fp-web.png b/app/src/main/ic_fp-web.png
deleted file mode 100644
index 85a16951a6..0000000000
Binary files a/app/src/main/ic_fp-web.png and /dev/null differ
diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png
index 8e9c7d9162..5e8563dc00 100644
Binary files a/app/src/main/ic_launcher-playstore.png and b/app/src/main/ic_launcher-playstore.png differ
diff --git a/app/src/main/ic_launcher-web.png b/app/src/main/ic_launcher-web.png
deleted file mode 100644
index 11e69a8089..0000000000
Binary files a/app/src/main/ic_launcher-web.png and /dev/null differ
diff --git a/app/src/main/ic_launcher_2-web.png b/app/src/main/ic_launcher_2-web.png
deleted file mode 100644
index 8639ebe991..0000000000
Binary files a/app/src/main/ic_launcher_2-web.png and /dev/null differ
diff --git a/app/src/main/ic_launcher_round-web.png b/app/src/main/ic_launcher_round-web.png
deleted file mode 100644
index 026a409e86..0000000000
Binary files a/app/src/main/ic_launcher_round-web.png and /dev/null differ
diff --git a/app/src/main/ic_logo_small-web.png b/app/src/main/ic_logo_small-web.png
deleted file mode 100644
index 76a713ee01..0000000000
Binary files a/app/src/main/ic_logo_small-web.png and /dev/null differ
diff --git a/app/src/main/java/com/tangem/tap/ActivityResultCaller.kt b/app/src/main/java/com/tangem/tap/ActivityResultCaller.kt
deleted file mode 100644
index 16a05117ac..0000000000
--- a/app/src/main/java/com/tangem/tap/ActivityResultCaller.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.tangem.tap
-
-import android.content.Intent
-import androidx.activity.result.ActivityResultLauncher
-
-interface ActivityResultCaller {
- val activityResultLauncher: ActivityResultLauncher?
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt b/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt
new file mode 100644
index 0000000000..f39b16e9d7
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt
@@ -0,0 +1,142 @@
+package com.tangem.tap
+
+import com.tangem.TangemSdkLogger
+import com.tangem.blockchainsdk.BlockchainSDKFactory
+import com.tangem.data.card.TransactionSignerFactory
+import com.tangem.blockchainsdk.utils.ExcludedBlockchains
+import com.tangem.common.routing.AppRouter
+import com.tangem.core.analytics.filter.OneTimeEventFilter
+import com.tangem.core.configtoggle.blockchain.ExcludedBlockchainsManager
+import com.tangem.core.configtoggle.feature.FeatureTogglesManager
+import com.tangem.core.decompose.di.GlobalUiMessageSender
+import com.tangem.core.decompose.ui.UiMessageSender
+import com.tangem.core.navigation.settings.SettingsManager
+import com.tangem.core.navigation.share.ShareManager
+import com.tangem.core.navigation.url.UrlOpener
+import com.tangem.core.ui.clipboard.ClipboardManager
+import com.tangem.datasource.connection.NetworkConnectionManager
+import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage
+import com.tangem.datasource.local.config.issuers.IssuersConfigStorage
+import com.tangem.datasource.local.logs.AppLogsStore
+import com.tangem.datasource.local.preferences.AppPreferencesStore
+import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
+import com.tangem.domain.apptheme.GetAppThemeModeUseCase
+import com.tangem.domain.apptheme.repository.AppThemeModeRepository
+import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository
+import com.tangem.domain.card.ScanCardProcessor
+import com.tangem.domain.card.repository.CardRepository
+import com.tangem.domain.feedback.GetCardInfoUseCase
+import com.tangem.domain.feedback.SendFeedbackEmailUseCase
+import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase
+import com.tangem.domain.onboarding.WasTwinsOnboardingShownUseCase
+import com.tangem.domain.onboarding.repository.OnboardingRepository
+import com.tangem.domain.settings.repositories.SettingsRepository
+import com.tangem.domain.settings.usercountry.GetUserCountryUseCase
+import com.tangem.domain.walletmanager.WalletManagersFacade
+import com.tangem.domain.wallets.legacy.UserWalletsListManager
+import com.tangem.domain.wallets.repository.WalletsRepository
+import com.tangem.domain.wallets.usecase.GenerateWalletNameUseCase
+import com.tangem.features.onboarding.v2.OnboardingV2FeatureToggles
+import com.tangem.features.onramp.OnrampFeatureToggles
+import com.tangem.tap.common.analytics.handlers.BlockchainExceptionHandler
+import com.tangem.tap.common.log.TangemAppLoggerInitializer
+import com.tangem.tap.domain.scanCard.CardScanningFeatureToggles
+import com.tangem.tap.proxy.AppStateHolder
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
+import dagger.hilt.EntryPoint
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import com.tangem.tap.domain.walletconnect2.domain.LegacyWalletConnectRepository as WalletConnect2Repository
+
+@EntryPoint
+@InstallIn(SingletonComponent::class)
+@Suppress("TooManyFunctions")
+interface ApplicationEntryPoint {
+
+ fun getEnvironmentConfigStorage(): EnvironmentConfigStorage
+
+ fun getAppStateHolder(): AppStateHolder
+
+ fun getIssuersConfigStorage(): IssuersConfigStorage
+
+ fun getFeatureTogglesManager(): FeatureTogglesManager
+
+ fun getExcludedBlockchainsManager(): ExcludedBlockchainsManager
+
+ fun getNetworkConnectionManager(): NetworkConnectionManager
+
+ fun getCardScanningFeatureToggles(): CardScanningFeatureToggles
+
+ fun getWalletConnect2Repository(): WalletConnect2Repository
+
+ fun getScanCardProcessor(): ScanCardProcessor
+
+ fun getAppCurrencyRepository(): AppCurrencyRepository
+
+ fun getWalletManagersFacade(): WalletManagersFacade
+
+ fun getAppThemeModeRepository(): AppThemeModeRepository
+
+ fun getBalanceHidingRepository(): BalanceHidingRepository
+
+ fun getAppPreferencesStore(): AppPreferencesStore
+
+ fun getGetAppThemeModeUseCase(): GetAppThemeModeUseCase
+
+ fun getWalletsRepository(): WalletsRepository
+
+ fun getOneTimeEventFilter(): OneTimeEventFilter
+
+ fun getGeneralUserWalletsListManager(): UserWalletsListManager
+
+ fun getWasTwinsOnboardingShownUseCase(): WasTwinsOnboardingShownUseCase
+
+ fun getSaveTwinsOnboardingShownUseCase(): SaveTwinsOnboardingShownUseCase
+
+ fun getWalletNameGenerateUseCase(): GenerateWalletNameUseCase
+
+ fun getCardRepository(): CardRepository
+
+ fun getTangemSdkLogger(): TangemSdkLogger
+
+ fun getSettingsRepository(): SettingsRepository
+
+ fun getBlockchainSDKFactory(): BlockchainSDKFactory
+
+ fun getSendFeedbackEmailUseCase(): SendFeedbackEmailUseCase
+
+ fun getGetCardInfoUseCase(): GetCardInfoUseCase
+
+ fun getUrlOpener(): UrlOpener
+
+ fun getShareManager(): ShareManager
+
+ fun getAppRouter(): AppRouter
+
+ fun getTangemAppLogger(): TangemAppLoggerInitializer
+
+ fun getTransactionSignerFactory(): TransactionSignerFactory
+
+ fun getGetUserCountryCodeUseCase(): GetUserCountryUseCase
+
+ fun getOnrampFeatureToggles(): OnrampFeatureToggles
+
+ fun getOnboardingV2FeatureToggles(): OnboardingV2FeatureToggles
+
+ fun getOnboardingRepository(): OnboardingRepository
+
+ fun getCoroutineDispatcherProvider(): CoroutineDispatcherProvider
+
+ fun getExcludedBlockchains(): ExcludedBlockchains
+
+ fun getAppLogsStore(): AppLogsStore
+
+ fun getClipboardManager(): ClipboardManager
+
+ fun getSettingsManager(): SettingsManager
+
+ fun getBlockchainExceptionHandler(): BlockchainExceptionHandler
+
+ @GlobalUiMessageSender
+ fun getUiMessageSender(): UiMessageSender
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/DecomposeFragment.kt b/app/src/main/java/com/tangem/tap/DecomposeFragment.kt
new file mode 100644
index 0000000000..b4ac28e100
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/DecomposeFragment.kt
@@ -0,0 +1,70 @@
+package com.tangem.tap
+
+import android.os.Bundle
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.core.os.bundleOf
+import androidx.fragment.app.Fragment
+import com.tangem.core.decompose.context.AppComponentContext
+import com.tangem.core.decompose.factory.ComponentFactory
+import com.tangem.core.ui.UiDependencies
+import com.tangem.core.ui.decompose.ComposableContentComponent
+import com.tangem.core.ui.screen.ComposeFragment
+import com.tangem.utils.Provider
+import dagger.hilt.android.AndroidEntryPoint
+import java.util.WeakHashMap
+import javax.inject.Inject
+
+@AndroidEntryPoint
+internal class DecomposeFragment : ComposeFragment() {
+
+ @Inject
+ override lateinit var uiDependencies: UiDependencies
+
+ private lateinit var component: ComposableContentComponent
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ val tag = requireArguments().getString(TAG_KEY)
+ val builder = componentsBuilders[tag]
+
+ component = requireNotNull(builder?.build()) {
+ "Component builder is not set, call newInstance() for DecomposeFragment creation first."
+ }
+ }
+
+ @Composable
+ override fun ScreenContent(modifier: Modifier) {
+ component.Content(modifier)
+ }
+
+ private class ComponentBuilder>(
+ private val contextProvider: Provider,
+ private val params: P,
+ private val componentFactory: F,
+ ) {
+
+ fun build(): C = componentFactory.create(contextProvider(), params)
+ }
+
+ companion object {
+
+ private const val TAG_KEY = "tag"
+
+ private val componentsBuilders = WeakHashMap>()
+
+ fun > newInstance(
+ tag: String,
+ contextProvider: Provider,
+ params: P,
+ componentFactory: F,
+ ): Fragment {
+ this@Companion.componentsBuilders[tag] = ComponentBuilder(contextProvider, params, componentFactory)
+
+ return DecomposeFragment().apply {
+ this.arguments = bundleOf(TAG_KEY to tag)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/ForegroundActivityObserver.kt b/app/src/main/java/com/tangem/tap/ForegroundActivityObserver.kt
index 9664f38966..cb7805793c 100644
--- a/app/src/main/java/com/tangem/tap/ForegroundActivityObserver.kt
+++ b/app/src/main/java/com/tangem/tap/ForegroundActivityObserver.kt
@@ -2,24 +2,18 @@ package com.tangem.tap
import android.app.Activity
import android.app.Application.ActivityLifecycleCallbacks
-import android.content.Intent
import android.os.Bundle
-import androidx.activity.result.ActivityResultLauncher
-import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
-import java.util.*
+import java.util.WeakHashMap
import kotlin.reflect.KClass
-class ForegroundActivityObserver : ActivityResultCaller {
- override var activityResultLauncher: ActivityResultLauncher? = null
- private set
+class ForegroundActivityObserver {
- private val activities = WeakHashMap, Activity>()
+ private val activities = WeakHashMap, AppCompatActivity>()
- val foregroundActivity: Activity?
+ val foregroundActivity: AppCompatActivity?
get() = activities.entries
- .filterNot { it.value.isDestroyed }
- .firstOrNull()
+ .firstOrNull { it.value?.isDestroyed == false }
?.value
internal val callbacks: ActivityLifecycleCallbacks
@@ -27,22 +21,14 @@ class ForegroundActivityObserver : ActivityResultCaller {
internal inner class Callbacks : ActivityLifecycleCallbacks {
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
- activityResultLauncher = (activity as? AppCompatActivity)?.registerForActivityResult(
- ActivityResultContracts.StartActivityForResult(),
- ) {
- /* no-op */
- }
}
override fun onActivityResumed(activity: Activity) {
- activities[activity::class] = activity
+ activities[activity::class] = activity as? AppCompatActivity
}
override fun onActivityDestroyed(activity: Activity) {
activities.remove(activity::class)
- if (activities.isEmpty()) {
- activityResultLauncher = null
- }
}
override fun onActivityStarted(activity: Activity) {
@@ -59,8 +45,6 @@ class ForegroundActivityObserver : ActivityResultCaller {
}
}
-fun ForegroundActivityObserver.withForegroundActivity(
- block: (Activity) -> Unit
-) {
+fun ForegroundActivityObserver.withForegroundActivity(block: (AppCompatActivity) -> Unit) {
foregroundActivity?.let { block(it) }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/LockUserWalletsTimer.kt b/app/src/main/java/com/tangem/tap/LockUserWalletsTimer.kt
index 426f49ca25..c1ac40b684 100644
--- a/app/src/main/java/com/tangem/tap/LockUserWalletsTimer.kt
+++ b/app/src/main/java/com/tangem/tap/LockUserWalletsTimer.kt
@@ -2,21 +2,21 @@ package com.tangem.tap
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
-import androidx.lifecycle.lifecycleScope
-import com.tangem.tap.common.extensions.dispatchOnMain
-import com.tangem.tap.common.redux.navigation.AppScreen
-import com.tangem.tap.common.redux.navigation.NavigationAction
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.isActive
-import kotlinx.coroutines.launch
+import com.tangem.common.routing.AppRoute
+import com.tangem.domain.settings.repositories.SettingsRepository
+import com.tangem.domain.wallets.legacy.UserWalletsListManager
+import com.tangem.domain.wallets.legacy.asLockable
+import com.tangem.tap.common.extensions.dispatchNavigationAction
+import kotlinx.coroutines.*
import timber.log.Timber
import kotlin.time.Duration
internal class LockUserWalletsTimer(
owner: LifecycleOwner,
+ private val settingsRepository: SettingsRepository,
private val duration: Duration = with(Duration) { 10.minutes },
+ private val userWalletsListManager: UserWalletsListManager,
+ private val coroutineScope: CoroutineScope,
) : LifecycleOwner by owner,
DefaultLifecycleObserver {
@@ -30,35 +30,43 @@ internal class LockUserWalletsTimer(
lifecycle.addObserver(this)
}
- override fun onResume(owner: LifecycleOwner) {
- Timber.d(
- """
+ override fun onStart(owner: LifecycleOwner) {
+ coroutineScope.launch {
+ val wasApplicationStopped = settingsRepository.wasApplicationStopped()
+ val shouldOpenWelcomeScreenOnResume = settingsRepository.shouldOpenWelcomeScreenOnResume()
+
+ Timber.i(
+ """
Owner resumed
- |- Was stopped: ${preferencesStorage.wasApplicationStopped}
- |- Need to open welcome screen: ${preferencesStorage.shouldOpenWelcomeScreenOnResume}
- """.trimIndent(),
- )
- preferencesStorage.wasApplicationStopped = false
- start()
- if (preferencesStorage.shouldOpenWelcomeScreenOnResume) {
- store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Welcome))
- preferencesStorage.shouldOpenWelcomeScreenOnResume = false
+ |- Was stopped: $wasApplicationStopped
+ |- Need to open welcome screen: $shouldOpenWelcomeScreenOnResume
+ """.trimIndent(),
+ )
+
+ settingsRepository.setWasApplicationStopped(value = false)
+
+ if (shouldOpenWelcomeScreenOnResume) {
+ store.dispatchNavigationAction { replaceAll(AppRoute.Welcome()) }
+ settingsRepository.setShouldOpenWelcomeScreenOnResume(value = false)
+ }
}
}
- override fun onStop(owner: LifecycleOwner) {
- Timber.d("Owner stopped")
- preferencesStorage.wasApplicationStopped = true
+ override fun onResume(owner: LifecycleOwner) {
+ start()
}
- override fun onDestroy(owner: LifecycleOwner) {
- Timber.d("Owner destroyed")
- stop()
+ override fun onStop(owner: LifecycleOwner) {
+ Timber.i("Owner stopped")
+
+ coroutineScope.launch {
+ settingsRepository.setWasApplicationStopped(value = true)
+ }
}
fun restart() {
if (delayJob == null) return
- Timber.d(
+ Timber.i(
"""
Timer restart
|- Duration millis: ${duration.inWholeMilliseconds}
@@ -69,7 +77,7 @@ internal class LockUserWalletsTimer(
private fun start(log: Boolean = true) {
if (log) {
- Timber.d(
+ Timber.i(
"""
Timer start
|- Duration millis: ${duration.inWholeMilliseconds}
@@ -79,38 +87,30 @@ internal class LockUserWalletsTimer(
delayJob = createDelayJob()
}
- private fun stop(log: Boolean = true) {
- if (log) {
- Timber.d(
+ private fun createDelayJob(): Job = coroutineScope.launch {
+ val startTime = System.currentTimeMillis()
+
+ delay(duration)
+
+ val userWalletsListManager = userWalletsListManager.asLockable() ?: return@launch
+
+ if (userWalletsListManager.hasUserWallets) {
+ val currentTime = System.currentTimeMillis()
+ val wasApplicationStopped = settingsRepository.wasApplicationStopped()
+
+ Timber.i(
"""
- Timer stop
- |- Was started: ${delayJob?.isActive ?: false}
+ Finished
+ |- App is stopped: $wasApplicationStopped
+ |- Millis passed: ${currentTime - startTime}
""".trimIndent(),
)
- }
- delayJob = null
- }
- private fun createDelayJob(): Job = lifecycleScope.launch(Dispatchers.Default) {
- val startTime = System.currentTimeMillis()
- delay(duration)
- if (isActive) {
- val userWalletsListManager = userWalletsListManagerSafe ?: return@launch
- if (userWalletsListManager.hasSavedUserWallets) {
- val currentTime = System.currentTimeMillis()
- Timber.d(
- """
- Finished
- |- App is stopped: ${preferencesStorage.wasApplicationStopped}
- |- Millis passed: ${currentTime - startTime}
- """.trimIndent(),
- )
- userWalletsListManager.lock()
- if (preferencesStorage.wasApplicationStopped) {
- preferencesStorage.shouldOpenWelcomeScreenOnResume = true
- } else {
- store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Welcome))
- }
+ userWalletsListManager.lock()
+ if (wasApplicationStopped) {
+ settingsRepository.setShouldOpenWelcomeScreenOnResume(value = true)
+ } else {
+ store.dispatchNavigationAction { replaceAll(AppRoute.Welcome()) }
}
}
}
diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt
index 6b5d0bd175..ed2a3f63b6 100644
--- a/app/src/main/java/com/tangem/tap/MainActivity.kt
+++ b/app/src/main/java/com/tangem/tap/MainActivity.kt
@@ -1,55 +1,113 @@
package com.tangem.tap
+import android.annotation.SuppressLint
import android.content.Intent
import android.content.pm.ActivityInfo
+import android.content.res.Configuration
+import android.os.Build
import android.os.Bundle
-import android.view.View
+import android.view.MotionEvent
+import android.view.WindowManager
+import androidx.activity.SystemBarStyle
+import androidx.activity.compose.setContent
+import androidx.activity.enableEdgeToEdge
+import androidx.activity.viewModels
+import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity
-import androidx.core.view.WindowCompat
-import androidx.core.view.WindowInsetsControllerCompat
+import androidx.appcompat.app.AppCompatDelegate
+import androidx.appcompat.app.AppCompatDelegate.setDefaultNightMode
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.toArgb
+import androidx.compose.ui.platform.ViewCompositionStrategy
+import androidx.coordinatorlayout.widget.CoordinatorLayout
+import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.flowWithLifecycle
+import androidx.lifecycle.lifecycleScope
+import arrow.core.getOrElse
import by.kirich1409.viewbindingdelegate.viewBinding
+import com.arkivanov.decompose.value.observe
+import com.arkivanov.essenty.lifecycle.asEssentyLifecycle
+import com.google.android.material.snackbar.BaseTransientBottomBar
import com.google.android.material.snackbar.Snackbar
-import com.tangem.TangemSdk
+import com.tangem.common.routing.AppRoute
+import com.tangem.common.routing.entity.SerializableIntent
+import com.tangem.core.analytics.api.AnalyticsEventHandler
+import com.tangem.core.decompose.context.AppComponentContext
+import com.tangem.core.decompose.di.RootAppComponentContext
+import com.tangem.core.deeplink.DeepLinksRegistry
+import com.tangem.core.navigation.email.EmailSender
+import com.tangem.core.ui.UiDependencies
+import com.tangem.core.ui.extensions.TextReference
+import com.tangem.core.ui.extensions.resolveReference
+import com.tangem.core.ui.message.EventMessageEffect
+import com.tangem.core.ui.message.SnackbarMessage
+import com.tangem.core.ui.res.TangemColorPalette
+import com.tangem.core.ui.res.TangemTheme
+import com.tangem.data.card.sdk.CardSdkOwner
+import com.tangem.domain.apptheme.model.AppThemeMode
+import com.tangem.domain.card.ScanCardUseCase
+import com.tangem.domain.card.repository.CardRepository
+import com.tangem.domain.card.repository.CardSdkConfigRepository
+import com.tangem.domain.settings.SetGooglePayAvailabilityUseCase
+import com.tangem.domain.settings.SetGoogleServicesAvailabilityUseCase
+import com.tangem.domain.settings.ShouldInitiallyAskPermissionUseCase
+import com.tangem.domain.settings.repositories.SettingsRepository
+import com.tangem.domain.staking.SendUnsubmittedHashesUseCase
+import com.tangem.domain.tokens.GetPolkadotCheckHasImmortalUseCase
+import com.tangem.domain.tokens.GetPolkadotCheckHasResetUseCase
+import com.tangem.domain.wallets.legacy.UserWalletsListManager
+import com.tangem.feature.qrscanning.QrScanningRouter
+import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
+import com.tangem.features.onboarding.v2.OnboardingV2FeatureToggles
+import com.tangem.features.pushnotifications.api.navigation.PushNotificationsRouter
+import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION
+import com.tangem.features.send.api.navigation.SendRouter
+import com.tangem.features.tokendetails.navigation.TokenDetailsRouter
+import com.tangem.features.wallet.navigation.WalletRouter
+import com.tangem.google.GoogleServicesHelper
import com.tangem.operations.backup.BackupService
-import com.tangem.tangem_sdk_new.extensions.init
-import com.tangem.tangem_sdk_new.extensions.initWithBiometrics
+import com.tangem.sdk.api.BackupServiceHolder
+import com.tangem.sdk.api.TangemSdkManager
+import com.tangem.sdk.extensions.init
import com.tangem.tap.common.ActivityResultCallbackHolder
import com.tangem.tap.common.DialogManager
import com.tangem.tap.common.OnActivityResultCallback
import com.tangem.tap.common.SnackbarHandler
-import com.tangem.tap.common.extensions.dispatchOnMain
+import com.tangem.tap.common.apptheme.MutableAppThemeModeHolder
+import com.tangem.tap.common.extensions.dispatchNavigationAction
+import com.tangem.tap.common.extensions.showFragmentAllowingStateLoss
import com.tangem.tap.common.redux.NotificationsHandler
-import com.tangem.tap.common.redux.navigation.AppScreen
-import com.tangem.tap.common.redux.navigation.NavigationAction
-import com.tangem.tap.common.shop.googlepay.GooglePayService
-import com.tangem.tap.common.shop.googlepay.GooglePayService.Companion.LOAD_PAYMENT_DATA_REQUEST_CODE
-import com.tangem.tap.common.shop.googlepay.GooglePayUtil.createPaymentsClient
-import com.tangem.tap.domain.TangemSdkManager
-import com.tangem.tap.domain.userWalletList.UserWalletsListManager
-import com.tangem.tap.domain.userWalletList.di.provideBiometricImplementation
+import com.tangem.tap.domain.walletconnect2.domain.WalletConnectInteractor
+import com.tangem.tap.features.intentHandler.IntentProcessor
+import com.tangem.tap.features.intentHandler.handlers.BackgroundScanIntentHandler
+import com.tangem.tap.features.intentHandler.handlers.OnPushClickedIntentHandler
+import com.tangem.tap.features.intentHandler.handlers.WalletConnectLinkIntentHandler
+import com.tangem.tap.features.main.MainViewModel
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupAction
-import com.tangem.tap.features.shop.redux.ShopAction
-import com.tangem.tap.features.welcome.redux.WelcomeAction
import com.tangem.tap.proxy.AppStateHolder
+import com.tangem.tap.proxy.redux.DaggerGraphAction
+import com.tangem.tap.routing.component.RoutingComponent
+import com.tangem.tap.routing.configurator.AppRouterConfig
+import com.tangem.tap.routing.toggle.RoutingFeatureToggles
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.coroutines.FeatureCoroutineExceptionHandler
import com.tangem.wallet.R
import com.tangem.wallet.databinding.ActivityMainBinding
import dagger.hilt.android.AndroidEntryPoint
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.Job
-import java.lang.ref.WeakReference
+import kotlinx.coroutines.*
+import kotlinx.coroutines.flow.*
+import timber.log.Timber
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
+import kotlin.time.Duration.Companion.seconds
-lateinit var tangemSdk: TangemSdk
lateinit var tangemSdkManager: TangemSdkManager
lateinit var backupService: BackupService
-lateinit var userWalletsListManager: UserWalletsListManager
internal var lockUserWalletsTimer: LockUserWalletsTimer? = null
private set
-var userWalletsListManagerSafe: UserWalletsListManager? = null
- private set
var notificationsHandler: NotificationsHandler? = null
private val coroutineContext: CoroutineContext
@@ -60,12 +118,112 @@ private val mainCoroutineContext: CoroutineContext
get() = Job() + Dispatchers.Main + FeatureCoroutineExceptionHandler.create("mainScope")
val mainScope = CoroutineScope(mainCoroutineContext)
+@Suppress("LargeClass")
@AndroidEntryPoint
class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbackHolder {
@Inject
lateinit var appStateHolder: AppStateHolder
+ /** Router for opening tester menu */
+ @Inject
+ lateinit var cardSdkOwner: CardSdkOwner
+
+ @Inject
+ lateinit var cardSdkConfigRepository: CardSdkConfigRepository
+
+ @Inject
+ lateinit var injectedTangemSdkManager: TangemSdkManager
+
+ @Inject
+ lateinit var scanCardUseCase: ScanCardUseCase
+
+ @Inject
+ lateinit var walletRouter: WalletRouter
+
+ @Inject
+ lateinit var tokenDetailsRouter: TokenDetailsRouter
+
+ @Inject
+ lateinit var walletConnectInteractor: WalletConnectInteractor
+
+ @Inject
+ lateinit var sendRouter: SendRouter
+
+ @Inject
+ lateinit var qrScanningRouter: QrScanningRouter
+
+ @Inject
+ lateinit var deepLinksRegistry: DeepLinksRegistry
+
+ @Inject
+ lateinit var settingsRepository: SettingsRepository
+
+ @Inject
+ lateinit var sendUnsubmittedHashesUseCase: SendUnsubmittedHashesUseCase
+
+ @Inject
+ lateinit var getPolkadotCheckHasResetUseCase: GetPolkadotCheckHasResetUseCase
+
+ @Inject
+ lateinit var getPolkadotCheckHasImmortalUseCase: GetPolkadotCheckHasImmortalUseCase
+
+ @Inject
+ lateinit var analyticsEventsHandler: AnalyticsEventHandler
+
+ @Inject
+ lateinit var userWalletsListManager: UserWalletsListManager
+
+ @Inject
+ lateinit var emailSender: EmailSender
+
+ @Inject
+ @RootAppComponentContext
+ internal lateinit var rootComponentContext: AppComponentContext
+
+ @Inject
+ internal lateinit var appRouterConfig: AppRouterConfig
+
+ @Inject
+ internal lateinit var routingComponentFactory: RoutingComponent.Factory
+
+ @Inject
+ lateinit var pushNotificationsRouter: PushNotificationsRouter
+
+ @Inject
+ lateinit var cardRepository: CardRepository
+
+ @Inject
+ lateinit var shouldInitiallyAskPermissionUseCase: ShouldInitiallyAskPermissionUseCase
+
+ @Inject
+ lateinit var backupServiceHolder: BackupServiceHolder
+
+ @Inject
+ lateinit var onboardingV2FeatureToggles: OnboardingV2FeatureToggles
+
+ @Inject
+ lateinit var setGoogleServicesAvailabilityUseCase: SetGoogleServicesAvailabilityUseCase
+
+ @Inject
+ lateinit var setGooglePayAvailabilityUseCase: SetGooglePayAvailabilityUseCase
+
+ @Inject
+ lateinit var dispatchers: CoroutineDispatcherProvider
+
+ @Inject
+ internal lateinit var routingFeatureToggles: RoutingFeatureToggles
+
+ @Inject
+ internal lateinit var uiDependencies: UiDependencies
+
+ internal val viewModel: MainViewModel by viewModels()
+
+ private lateinit var appThemeModeFlow: SharedFlow
+
+ // TODO: fixme: inject through DI
+ private val intentProcessor: IntentProcessor = IntentProcessor()
+
private var snackbar: Snackbar? = null
private val dialogManager = DialogManager()
private val binding: ActivityMainBinding by viewBinding(ActivityMainBinding::bind)
@@ -73,38 +231,182 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
private val onActivityResultCallbacks = mutableListOf()
override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
- systemActions()
- store.dispatch(NavigationAction.ActivityCreated(WeakReference(this)))
+ // We need to call it before onCreate to prevent unnecessary activity recreation
+ installAppTheme()
- tangemSdk = TangemSdk.initWithBiometrics(this, TangemSdkManager.config)
- tangemSdkManager = TangemSdkManager(tangemSdk, this)
- appStateHolder.tangemSdkManager = tangemSdkManager
- appStateHolder.tangemSdk = tangemSdk
- backupService = BackupService.init(tangemSdk, this)
- userWalletsListManager = UserWalletsListManager.provideBiometricImplementation(
- context = applicationContext,
- tangemSdkManager = tangemSdkManager,
+ val splashScreen = installSplashScreen()
+
+ enableEdgeToEdge(
+ navigationBarStyle = SystemBarStyle.auto(
+ Color.Transparent.toArgb(),
+ Color.Transparent.toArgb(),
+ ),
)
- appStateHolder.userWalletsListManager = userWalletsListManager
- userWalletsListManagerSafe = userWalletsListManager
- lockUserWalletsTimer = LockUserWalletsTimer(owner = this)
+
+ super.onCreate(savedInstanceState)
+
+ // We have to allow adjust_resize (can only be specified in the manifest) for Android <=10,
+ // in order for imePadding to work correctly
+ // for Android 11+ we set SOFT_INPUT_ADJUST_NOTHING to prevent resizing the layout
+ // so that we don't have any distortions in the layout when displaying the keyboard
+ // https://issuetracker.google.com/issues/266331465
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
+ window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING)
+ }
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+ window.setHideOverlayWindows(true)
+ }
+
+ splashScreen.setKeepOnScreenCondition { viewModel.isSplashScreenShown }
+
+ installActivityDependencies()
+ observeAppThemeModeUpdates()
+
+ if (routingFeatureToggles.isNavigationRefactoringEnabled) {
+ setRootContent()
+ } else {
+ setContentView(R.layout.activity_main)
+ installRouting()
+ installEventMessageEffect()
+ }
+
+ initContent()
+
+ observePolkadotAccountHealthCheck()
+ sendStakingUnsubmittedHashes()
+ checkGoogleServicesAvailability()
+
+ if (intent != null && savedInstanceState == null) {
+ // handle intent only on start, not on recreate
+ deepLinksRegistry.launch(intent)
+ }
+
+ lifecycle.addObserver(WindowObscurationObserver)
+ }
+
+ private fun installEventMessageEffect() {
+ binding.composeView.setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
+ binding.composeView.setContent {
+ TangemTheme(
+ activity = this,
+ uiDependencies = uiDependencies,
+ overrideSystemBarColors = false,
+ ) {
+ EventMessageEffect(
+ onShowSnackbar = { message, _ ->
+ showSnackbar(
+ text = message.message.resolveReference(resources),
+ length = when (message.duration) {
+ SnackbarMessage.Duration.Short -> Snackbar.LENGTH_SHORT
+ SnackbarMessage.Duration.Long -> Snackbar.LENGTH_LONG
+ SnackbarMessage.Duration.Indefinite -> Snackbar.LENGTH_INDEFINITE
+ },
+ buttonTitle = message.actionLabel?.resolveReference(resources),
+ action = message.action,
+ onDismiss = message.onDismissRequest,
+ )
+ },
+ )
+ }
+ }
+ }
+
+ private fun setRootContent() {
+ val routingComponent = routingComponentFactory.create(
+ context = rootComponentContext,
+ initialStack = null,
+ )
+
+ setContent {
+ routingComponent.Content(Modifier.fillMaxSize())
+ }
+ }
+
+ private fun installRouting() {
+ // for now activity is singleTop and after going to ChromeCustomTab it calls onCreate but onDestroy
+ // doesn't calls. It lead to issue that decompose nav stack is not saved in bundle and to restore it
+ // we try to init component with previous stack
+ val routingComponent = routingComponentFactory.create(
+ context = rootComponentContext,
+ initialStack = appRouterConfig.stack,
+ )
+
+ appRouterConfig.routerScope = mainScope
+ appRouterConfig.componentRouter = routingComponent.router
+ appRouterConfig.snackbarHandler = this
+
+ routingComponent.stack.observe(lifecycle.asEssentyLifecycle()) { childStack ->
+ val stack = childStack.backStack
+ .plus(childStack.active)
+ .map { it.configuration }
+
+ if (stack == appRouterConfig.stack) return@observe
+
+ appRouterConfig.stack = stack
+
+ when (val child = childStack.active.instance) {
+ is RoutingComponent.Child.Initial -> Unit
+ is RoutingComponent.Child.LegacyFragment -> {
+ supportFragmentManager.showFragmentAllowingStateLoss(child.name, child.fragmentProvider)
+ }
+ is RoutingComponent.Child.LegacyIntent -> {
+ startActivity(child.intent)
+ }
+ is RoutingComponent.Child.ComposableComponent -> error("Unsupported child: $child")
+ }
+ }
+ }
+
+ private fun installActivityDependencies() {
+ cardSdkOwner.register(activity = this)
+ tangemSdkManager = injectedTangemSdkManager
+
+ if (onboardingV2FeatureToggles.isOnboardingV2Enabled) {
+ backupServiceHolder.createAndSetService(cardSdkConfigRepository.sdk, this)
+ backupService = backupServiceHolder.backupService.get()!! // will be deleted eventually
+ } else {
+ backupService = BackupService.init(cardSdkConfigRepository.sdk, this)
+ }
+
+ lockUserWalletsTimer = LockUserWalletsTimer(
+ owner = this,
+ settingsRepository = settingsRepository,
+ userWalletsListManager = userWalletsListManager,
+ coroutineScope = mainScope,
+ )
+
+ initIntentHandlers()
store.dispatch(
- ShopAction.CheckIfGooglePayAvailable(
- GooglePayService(createPaymentsClient(this), this),
+ DaggerGraphAction.SetActivityDependencies(
+ scanCardUseCase = scanCardUseCase,
+ walletConnectInteractor = walletConnectInteractor,
+ cardSdkConfigRepository = cardSdkConfigRepository,
),
)
}
- private fun systemActions() {
- WindowCompat.setDecorFitsSystemWindows(window, false)
+ private fun installAppTheme() {
+ appThemeModeFlow = createAppThemeModeFlow()
+ val mode = runBlocking {
+ withTimeoutOrNull(APP_THEME_LOAD_TIMEOUT.seconds) {
+ appThemeModeFlow.first()
+ } ?: AppThemeMode.DEFAULT
+ }
- val windowInsetsController = WindowInsetsControllerCompat(window, binding.root)
- windowInsetsController.isAppearanceLightStatusBars = true
- windowInsetsController.isAppearanceLightNavigationBars = true
+ updateAppTheme(mode)
+ }
+ private fun observeAppThemeModeUpdates() {
+ appThemeModeFlow
+ .flowWithLifecycle(lifecycle)
+ .onEach(::updateAppTheme)
+ .launchIn(lifecycleScope)
+ }
+
+ @SuppressLint("SourceLockedOrientationActivity")
+ private fun initContent() {
supportFragmentManager.registerFragmentLifecycleCallbacks(
NavBarInsetsFragmentLifecycleCallback(),
true,
@@ -113,16 +415,19 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
}
- override fun onResume() {
- super.onResume()
- notificationsHandler = NotificationsHandler(binding.fragmentContainer)
+ private fun createAppThemeModeFlow(): SharedFlow {
+ val tangemApplication = application as TangemApplication
- navigateToInitialScreenIfNeeded(intent)
- }
-
- override fun onNewIntent(intent: Intent?) {
- super.onNewIntent(intent)
- intentHandler.handleIntent(intent, userWalletsListManager.hasSavedUserWallets)
+ return tangemApplication.getAppThemeModeUseCase()
+ .filterNotNull()
+ .distinctUntilChanged()
+ .map { maybeMode ->
+ maybeMode.getOrElse { AppThemeMode.DEFAULT }
+ }
+ .shareIn(
+ scope = lifecycleScope,
+ started = SharingStarted.WhileSubscribed(stopTimeoutMillis = 5_000),
+ )
}
override fun onStart() {
@@ -130,6 +435,17 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
dialogManager.onStart(this)
}
+ override fun onResume() {
+ super.onResume()
+
+ if (!routingFeatureToggles.isNavigationRefactoringEnabled) {
+ // TODO: RESEARCH! NotificationsHandler is created in onResume and destroyed in onStop
+ notificationsHandler = NotificationsHandler(binding.fragmentContainer)
+ }
+
+ navigateToInitialScreenIfNeeded(intent)
+ }
+
override fun onStop() {
notificationsHandler = null
dialogManager.onStop()
@@ -137,22 +453,93 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
}
override fun onDestroy() {
- store.dispatch(NavigationAction.ActivityDestroyed(WeakReference(this)))
+ intentProcessor.removeAll()
+ // workaround: kill process when activity destroy to avoid state when lock() wallets
+ // and navigation to unlock screen was skipped because system kills activity but not process
+ android.os.Process.killProcess(android.os.Process.myPid())
super.onDestroy()
}
- override fun showSnackbar(text: Int, buttonTitle: Int?, action: View.OnClickListener?) {
- if (snackbar != null) return
+ private fun initIntentHandlers() {
+ val hasSavedWalletsProvider = { userWalletsListManager.hasUserWallets }
+ intentProcessor.addHandler(OnPushClickedIntentHandler(analyticsEventsHandler))
+ intentProcessor.addHandler(BackgroundScanIntentHandler(hasSavedWalletsProvider, lifecycleScope))
+ intentProcessor.addHandler(WalletConnectLinkIntentHandler())
+ }
- snackbar = Snackbar.make(
- binding.fragmentContainer,
- getString(text),
- Snackbar.LENGTH_INDEFINITE,
- )
- if (buttonTitle != null && action != null) {
- snackbar?.setAction(getString(buttonTitle), action)
+ private fun updateAppTheme(appThemeMode: AppThemeMode) {
+ val mode = when (appThemeMode) {
+ AppThemeMode.FORCE_DARK -> AppCompatDelegate.MODE_NIGHT_YES
+ AppThemeMode.FORCE_LIGHT -> AppCompatDelegate.MODE_NIGHT_NO
+ AppThemeMode.FOLLOW_SYSTEM -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
}
- snackbar?.show()
+
+ setDefaultNightMode(mode)
+
+ MutableAppThemeModeHolder.value = appThemeMode
+ MutableAppThemeModeHolder.isDarkThemeActive = isDarkTheme()
+ }
+
+ override fun onConfigurationChanged(newConfig: Configuration) {
+ super.onConfigurationChanged(newConfig)
+
+ /*
+ * We need to manually change the background color of the activity when the UI mode changes to prevent
+ * flickering when navigating between fragments.
+ *
+
+ * `android:configChanges="uiMode"` is set in the manifest.
+ * */
+ updateAppBackground()
+ }
+
+ private fun updateAppBackground() {
+ val backgroundColor = if (isDarkTheme()) {
+ TangemColorPalette.Dark6
+ } else {
+ TangemColorPalette.White
+ }
+
+ findViewById(R.id.fragment_container).setBackgroundColor(backgroundColor.toArgb())
+ }
+
+ private fun isDarkTheme(): Boolean {
+ return when (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
+ Configuration.UI_MODE_NIGHT_YES -> true
+ Configuration.UI_MODE_NIGHT_NO -> false
+ Configuration.UI_MODE_NIGHT_UNDEFINED -> false
+ else -> false
+ }
+ }
+
+ override fun onNewIntent(intent: Intent?) {
+ super.onNewIntent(intent)
+
+ lifecycleScope.launch {
+ intentProcessor.handleIntent(intent = intent, isFromForeground = true)
+ }
+
+ if (intent != null) {
+ deepLinksRegistry.launch(intent)
+ }
+ }
+
+ override fun showSnackbar(@StringRes text: Int, length: Int, @StringRes buttonTitle: Int?, action: (() -> Unit)?) {
+ showSnackbar(
+ getString(text),
+ length,
+ buttonTitle?.let(::getString),
+ action = { action?.invoke() },
+ )
+ }
+
+ override fun showSnackbar(text: TextReference, length: Int, buttonTitle: TextReference?, action: (() -> Unit)?) {
+ showSnackbar(
+ text = text.resolveReference(resources),
+ length = length,
+ buttonTitle = buttonTitle?.resolveReference(resources),
+ action = { action?.invoke() },
+ )
}
override fun dismissSnackbar() {
@@ -164,13 +551,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
super.onActivityResult(requestCode, resultCode, data)
onActivityResultCallbacks.forEach { it(requestCode, resultCode, data) }
- when (requestCode) {
- LOAD_PAYMENT_DATA_REQUEST_CODE -> {
- store.dispatch(
- ShopAction.BuyWithGooglePay.HandleGooglePayResponse(resultCode, data),
- )
- }
- }
}
override fun addOnActivityResultCallback(callback: OnActivityResultCallback) {
@@ -188,29 +568,145 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
lockUserWalletsTimer?.restart()
}
- private fun navigateToInitialScreenIfNeeded(intent: Intent?) {
- val backStackIsEmpty = supportFragmentManager.backStackEntryCount == 0
- val isNotScannedBefore = store.state.globalState.scanResponse == null
- val isOnboardingServiceNotActive = store.state.globalState.onboardingState.onboardingStarted
- val isShopNotOpened = store.state.shopState.total != null
- when {
- !backStackIsEmpty && isNotScannedBefore && isOnboardingServiceNotActive && isShopNotOpened -> {
- navigateToInitialScreen(intent)
+ override fun dispatchTouchEvent(event: MotionEvent): Boolean {
+ val result = WindowObscurationObserver.dispatchTouchEvent(event, analyticsEventsHandler)
+
+ return if (result) super.dispatchTouchEvent(event) else false
+ }
+
+ private fun showSnackbar(
+ text: String,
+ length: Int,
+ buttonTitle: String?,
+ action: (() -> Unit)? = null,
+ onDismiss: () -> Unit = {},
+ ) {
+ if (snackbar != null) return
+
+ snackbar = Snackbar.make(binding.fragmentContainer, text, length).apply {
+ val textColor = getColor(R.color.text_primary_2)
+
+ setBackgroundTint(getColor(R.color.button_primary))
+ setActionTextColor(textColor)
+ setTextColor(textColor)
+
+ if (buttonTitle != null && action != null) {
+ setAction(buttonTitle, { action() })
}
- backStackIsEmpty -> {
- navigateToInitialScreen(intent)
+
+ addCallback(
+ object : BaseTransientBottomBar.BaseCallback() {
+ override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {
+ onDismiss()
+ snackbar = null
+ removeCallback(this)
+ }
+ },
+ )
+ }
+
+ snackbar?.show()
+ }
+
+ private fun navigateToInitialScreenIfNeeded(intentWhichStartedActivity: Intent?) {
+ val backStack = appRouterConfig.stack ?: emptyList()
+ // TODO move inital navigation to navigation component ([REDACTED_JIRA])
+ val isOnlyInitialRoute = backStack.all { it is AppRoute.Initial }
+ val isOnInitialScreen = backStack.all { it is AppRoute.Welcome || it is AppRoute.Home }
+ val isNotScannedBefore = store.state.globalState.scanResponse == null
+ val isOnboardingServiceNotActive = !store.state.globalState.onboardingState.onboardingStarted
+
+ when {
+ !isOnInitialScreen && isNotScannedBefore && isOnboardingServiceNotActive -> {
+ navigateToInitialScreen(intentWhichStartedActivity)
+ }
+ backStack.isEmpty() -> {
+ navigateToInitialScreen(intentWhichStartedActivity)
+ }
+ isOnlyInitialRoute -> navigateToInitialScreen(intentWhichStartedActivity)
+ else -> Unit
+ }
+ }
+
+ private fun navigateToInitialScreen(intentWhichStartedActivity: Intent?) {
+ if (userWalletsListManager.isLockable && userWalletsListManager.hasUserWallets) {
+ store.dispatchNavigationAction {
+ replaceAll(AppRoute.Welcome(intentWhichStartedActivity?.let(::SerializableIntent)))
+ }
+ intentProcessor.handleIntent(
+ intent = intentWhichStartedActivity,
+ isFromForeground = false,
+ skipNavigationHandlers = true,
+ )
+ } else {
+ lifecycleScope.launch {
+ val shouldShowTos = !cardRepository.isTangemTOSAccepted()
+ val shouldShowInitialPush = shouldInitiallyAskPermissionUseCase(PUSH_PERMISSION).getOrElse { false }
+
+ val route = when {
+ shouldShowTos -> AppRoute.Disclaimer(isTosAccepted = false)
+ shouldShowInitialPush -> AppRoute.PushNotification
+ else -> AppRoute.Home
+ }
+
+ store.dispatchNavigationAction { replaceAll(route) }
+ intentProcessor.handleIntent(
+ intent = intentWhichStartedActivity,
+ isFromForeground = false,
+ skipNavigationHandlers = false,
+ )
+ }
+ }
+
+ store.dispatch(BackupAction.CheckForUnfinishedBackup)
+ }
+
+ private fun observePolkadotAccountHealthCheck() {
+ lifecycleScope.launch {
+ getPolkadotCheckHasResetUseCase()
+ .flowWithLifecycle(lifecycle, minActiveState = Lifecycle.State.CREATED)
+ .distinctUntilChanged()
+ .collect {
+ analyticsEventsHandler.send(WalletScreenAnalyticsEvent.Token.PolkadotAccountReset(it.second))
+ }
+ }
+ lifecycleScope.launch {
+ getPolkadotCheckHasImmortalUseCase()
+ .flowWithLifecycle(lifecycle, minActiveState = Lifecycle.State.CREATED)
+ .distinctUntilChanged()
+ .collect {
+ analyticsEventsHandler.send(
+ WalletScreenAnalyticsEvent.Token.PolkadotImmortalTransactions(it.second),
+ )
+ }
+ }
+ }
+
+ private fun sendStakingUnsubmittedHashes() {
+ lifecycleScope.launch {
+ sendUnsubmittedHashesUseCase.invoke()
+ .onLeft { Timber.e(it.toString()) }
+ .onRight { Timber.d("Submitting hashes succeeded") }
+ }
+ }
+
+ private fun checkGoogleServicesAvailability() {
+ val isGoogleServicesAvailable = GoogleServicesHelper.checkGoogleServicesAvailability(this)
+
+ lifecycleScope.launch {
+ setGoogleServicesAvailabilityUseCase(isGoogleServicesAvailable)
+
+ if (isGoogleServicesAvailable) {
+ val paymentsClient = GoogleServicesHelper.createPaymentsClient(this@MainActivity)
+ val isGooglePayAvailable = GoogleServicesHelper.checkGooglePayAvailability(paymentsClient)
+ setGooglePayAvailabilityUseCase(isGooglePayAvailable)
+ } else {
+ setGooglePayAvailabilityUseCase(false)
}
}
}
- private fun navigateToInitialScreen(intent: Intent?) {
- if (userWalletsListManager.hasSavedUserWallets) {
- store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.Welcome))
- store.dispatchOnMain(WelcomeAction.HandleIntentIfNeeded(intent))
- } else {
- store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.Home))
- intentHandler.handleIntent(intent, hasSavedUserWallets = false)
- }
- store.dispatch(BackupAction.CheckForUnfinishedBackup)
+ companion object {
+ private const val APP_THEME_LOAD_TIMEOUT = 2
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/NavBarInsetsFragmentLifecycleCallback.kt b/app/src/main/java/com/tangem/tap/NavBarInsetsFragmentLifecycleCallback.kt
index 6e620bd0bc..fefb785d4c 100644
--- a/app/src/main/java/com/tangem/tap/NavBarInsetsFragmentLifecycleCallback.kt
+++ b/app/src/main/java/com/tangem/tap/NavBarInsetsFragmentLifecycleCallback.kt
@@ -11,12 +11,8 @@ import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks
class NavBarInsetsFragmentLifecycleCallback : FragmentLifecycleCallbacks() {
- override fun onFragmentViewCreated(
- fm: FragmentManager,
- f: Fragment,
- v: View,
- savedInstanceState: Bundle?,
- ) {
+
+ override fun onFragmentViewCreated(fm: FragmentManager, f: Fragment, v: View, savedInstanceState: Bundle?) {
if (v is ComposeView) return
ViewCompat.setOnApplyWindowInsetsListener(v) { view, windowInsets ->
diff --git a/app/src/main/java/com/tangem/tap/TangemApplication.kt b/app/src/main/java/com/tangem/tap/TangemApplication.kt
new file mode 100644
index 0000000000..540e44d667
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/TangemApplication.kt
@@ -0,0 +1,371 @@
+package com.tangem.tap
+
+import android.app.Application
+import coil.ImageLoader
+import coil.ImageLoaderFactory
+import com.chuckerteam.chucker.api.ChuckerInterceptor
+import com.tangem.Log
+import com.tangem.TangemSdkLogger
+import com.tangem.blockchain.network.BlockchainSdkRetrofitBuilder
+import com.tangem.blockchainsdk.BlockchainSDKFactory
+import com.tangem.blockchainsdk.utils.ExcludedBlockchains
+import com.tangem.common.routing.AppRouter
+import com.tangem.core.analytics.Analytics
+import com.tangem.core.analytics.api.ParamsInterceptor
+import com.tangem.core.analytics.filter.OneTimeEventFilter
+import com.tangem.core.analytics.models.AnalyticsEvent
+import com.tangem.core.analytics.models.AnalyticsParam
+import com.tangem.core.analytics.models.Basic
+import com.tangem.core.analytics.models.Basic.TransactionSent.WalletForm
+import com.tangem.core.configtoggle.blockchain.ExcludedBlockchainsManager
+import com.tangem.core.configtoggle.feature.FeatureTogglesManager
+import com.tangem.core.decompose.ui.UiMessageSender
+import com.tangem.core.navigation.settings.SettingsManager
+import com.tangem.core.ui.clipboard.ClipboardManager
+import com.tangem.data.card.TransactionSignerFactory
+import com.tangem.datasource.api.common.MoshiConverter
+import com.tangem.datasource.api.common.createNetworkLoggingInterceptor
+import com.tangem.datasource.connection.NetworkConnectionManager
+import com.tangem.datasource.local.config.environment.EnvironmentConfig
+import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage
+import com.tangem.datasource.local.config.issuers.IssuersConfigStorage
+import com.tangem.datasource.local.logs.AppLogsStore
+import com.tangem.datasource.local.preferences.AppPreferencesStore
+import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
+import com.tangem.domain.apptheme.GetAppThemeModeUseCase
+import com.tangem.domain.apptheme.repository.AppThemeModeRepository
+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.SendFeedbackEmailUseCase
+import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase
+import com.tangem.domain.onboarding.WasTwinsOnboardingShownUseCase
+import com.tangem.domain.onboarding.repository.OnboardingRepository
+import com.tangem.domain.settings.repositories.SettingsRepository
+import com.tangem.domain.settings.usercountry.GetUserCountryUseCase
+import com.tangem.domain.walletmanager.WalletManagersFacade
+import com.tangem.domain.wallets.legacy.UserWalletsListManager
+import com.tangem.domain.wallets.repository.WalletsRepository
+import com.tangem.domain.wallets.usecase.GenerateWalletNameUseCase
+import com.tangem.features.onboarding.v2.OnboardingV2FeatureToggles
+import com.tangem.features.onramp.OnrampFeatureToggles
+import com.tangem.tap.common.analytics.AnalyticsFactory
+import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
+import com.tangem.tap.common.analytics.handlers.amplitude.AmplitudeAnalyticsHandler
+import com.tangem.tap.common.analytics.handlers.firebase.FirebaseAnalyticsHandler
+import com.tangem.tap.common.images.createCoilImageLoader
+import com.tangem.tap.common.log.TangemAppLoggerInitializer
+import com.tangem.tap.common.redux.AppState
+import com.tangem.tap.common.redux.appReducer
+import com.tangem.tap.domain.scanCard.CardScanningFeatureToggles
+import com.tangem.tap.domain.tasks.product.DerivationsFinder
+import com.tangem.tap.proxy.AppStateHolder
+import com.tangem.tap.proxy.redux.DaggerGraphState
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
+import com.tangem.wallet.BuildConfig
+import dagger.hilt.EntryPoints
+import kotlinx.coroutines.async
+import kotlinx.coroutines.awaitAll
+import kotlinx.coroutines.runBlocking
+import org.rekotlin.Store
+import kotlin.collections.set
+import com.tangem.tap.domain.walletconnect2.domain.LegacyWalletConnectRepository as WalletConnect2Repository
+
+lateinit var store: Store
+
+lateinit var foregroundActivityObserver: ForegroundActivityObserver
+internal lateinit var derivationsFinder: DerivationsFinder
+
+abstract class TangemApplication : Application(), ImageLoaderFactory {
+
+ // region DI
+ private val entryPoint: ApplicationEntryPoint
+ get() = EntryPoints.get(this, ApplicationEntryPoint::class.java)
+
+ private val appStateHolder: AppStateHolder
+ get() = entryPoint.getAppStateHolder()
+
+ private val environmentConfigStorage: EnvironmentConfigStorage
+ get() = entryPoint.getEnvironmentConfigStorage()
+
+ private val issuersConfigStorage: IssuersConfigStorage
+ get() = entryPoint.getIssuersConfigStorage()
+
+ private val featureTogglesManager: FeatureTogglesManager
+ get() = entryPoint.getFeatureTogglesManager()
+
+ private val excludedBlockchainsManager: ExcludedBlockchainsManager
+ get() = entryPoint.getExcludedBlockchainsManager()
+
+ private val networkConnectionManager: NetworkConnectionManager
+ get() = entryPoint.getNetworkConnectionManager()
+
+ private val cardScanningFeatureToggles: CardScanningFeatureToggles
+ get() = entryPoint.getCardScanningFeatureToggles()
+
+ private val walletConnect2Repository: WalletConnect2Repository
+ get() = entryPoint.getWalletConnect2Repository()
+
+ private val scanCardProcessor: ScanCardProcessor
+ get() = entryPoint.getScanCardProcessor()
+
+ private val appCurrencyRepository: AppCurrencyRepository
+ get() = entryPoint.getAppCurrencyRepository()
+
+ private val walletManagersFacade: WalletManagersFacade
+ get() = entryPoint.getWalletManagersFacade()
+
+ private val appThemeModeRepository: AppThemeModeRepository
+ get() = entryPoint.getAppThemeModeRepository()
+
+ private val balanceHidingRepository: BalanceHidingRepository
+ get() = entryPoint.getBalanceHidingRepository()
+
+ private val appPreferencesStore: AppPreferencesStore
+ get() = entryPoint.getAppPreferencesStore()
+
+ val getAppThemeModeUseCase: GetAppThemeModeUseCase
+ get() = entryPoint.getGetAppThemeModeUseCase()
+
+ private val walletsRepository: WalletsRepository
+ get() = entryPoint.getWalletsRepository()
+
+ private val oneTimeEventFilter: OneTimeEventFilter
+ get() = entryPoint.getOneTimeEventFilter()
+
+ private val generalUserWalletsListManager: UserWalletsListManager
+ get() = entryPoint.getGeneralUserWalletsListManager()
+
+ private val wasTwinsOnboardingShownUseCase: WasTwinsOnboardingShownUseCase
+ get() = entryPoint.getWasTwinsOnboardingShownUseCase()
+
+ private val saveTwinsOnboardingShownUseCase: SaveTwinsOnboardingShownUseCase
+ get() = entryPoint.getSaveTwinsOnboardingShownUseCase()
+
+ private val generateWalletNameUseCase: GenerateWalletNameUseCase
+ get() = entryPoint.getWalletNameGenerateUseCase()
+
+ private val cardRepository: CardRepository
+ get() = entryPoint.getCardRepository()
+
+ private val tangemSdkLogger: TangemSdkLogger
+ get() = entryPoint.getTangemSdkLogger()
+
+ private val settingsRepository: SettingsRepository
+ get() = entryPoint.getSettingsRepository()
+
+ private val blockchainSDKFactory: BlockchainSDKFactory
+ get() = entryPoint.getBlockchainSDKFactory()
+
+ private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase
+ get() = entryPoint.getSendFeedbackEmailUseCase()
+
+ private val getCardInfoUseCase: GetCardInfoUseCase
+ get() = entryPoint.getGetCardInfoUseCase()
+
+ private val urlOpener
+ get() = entryPoint.getUrlOpener()
+
+ private val shareManager
+ get() = entryPoint.getShareManager()
+
+ private val appRouter: AppRouter
+ get() = entryPoint.getAppRouter()
+
+ private val tangemAppLoggerInitializer: TangemAppLoggerInitializer
+ get() = entryPoint.getTangemAppLogger()
+
+ private val transactionSignerFactory: TransactionSignerFactory
+ get() = entryPoint.getTransactionSignerFactory()
+
+ private val getUserCountryUseCase: GetUserCountryUseCase
+ get() = entryPoint.getGetUserCountryCodeUseCase()
+
+ private val onrampFeatureToggles: OnrampFeatureToggles
+ get() = entryPoint.getOnrampFeatureToggles()
+
+ private val onboardingV2FeatureToggles: OnboardingV2FeatureToggles
+ get() = entryPoint.getOnboardingV2FeatureToggles()
+
+ private val onboardingRepository: OnboardingRepository
+ get() = entryPoint.getOnboardingRepository()
+
+ private val dispatchers: CoroutineDispatcherProvider
+ get() = entryPoint.getCoroutineDispatcherProvider()
+
+ private val excludedBlockchains: ExcludedBlockchains
+ get() = entryPoint.getExcludedBlockchains()
+
+ private val appLogsStore: AppLogsStore
+ get() = entryPoint.getAppLogsStore()
+
+ private val clipboardManager: ClipboardManager
+ get() = entryPoint.getClipboardManager()
+
+ private val settingsManager: SettingsManager
+ get() = entryPoint.getSettingsManager()
+
+ private val uiMessageSender: UiMessageSender
+ get() = entryPoint.getUiMessageSender()
+
+ // endregion
+
+ override fun onCreate() {
+ super.onCreate()
+
+ init()
+
+ updateLogFiles()
+ }
+
+ private fun updateLogFiles() {
+ appLogsStore.deleteOldLogsFile()
+
+ if (!BuildConfig.TESTER_MENU_ENABLED) {
+ appLogsStore.deleteLastLogFile()
+ }
+
+ // Temporally logs are not saved
+ // scope.launch {
+ // if (!appPreferencesStore.getSyncOrDefault(WAS_LOG_FILE_CLEARED, false)) {
+ // appLogsStore.deleteLastLogFile()
+ // appPreferencesStore.store(WAS_LOG_FILE_CLEARED, true)
+ // }
+ // }
+ }
+
+ fun init() {
+ store = createReduxStore()
+
+ tangemAppLoggerInitializer.initialize()
+
+ foregroundActivityObserver = ForegroundActivityObserver()
+ registerActivityLifecycleCallbacks(foregroundActivityObserver.callbacks)
+
+ // TODO: Try to performance and user experience.
+ // [REDACTED_JIRA]
+ runBlocking {
+ awaitAll(
+ async { featureTogglesManager.init() },
+ async { excludedBlockchainsManager.init() },
+ async { initWithConfigDependency(environmentConfig = environmentConfigStorage.initialize()) },
+ )
+ }
+
+ loadNativeLibraries()
+ // ExceptionHandler.append(blockchainExceptionHandler) // TODO [REDACTED_TASK_KEY] Send only to Firebase
+ if (LogConfig.network.blockchainSdkNetwork) {
+ BlockchainSdkRetrofitBuilder.interceptors = listOf(
+ createNetworkLoggingInterceptor(),
+ ChuckerInterceptor(this),
+ )
+ }
+
+ derivationsFinder = DerivationsFinder(
+ appPreferencesStore = appPreferencesStore,
+ dispatchers = dispatchers,
+ )
+ appStateHolder.mainStore = store
+
+ walletConnect2Repository.init(projectId = environmentConfigStorage.getConfigSync().walletConnectProjectId)
+ }
+
+ private fun createReduxStore(): Store {
+ return Store(
+ reducer = { action, state -> appReducer(action, state) },
+ middleware = AppState.getMiddleware(),
+ state = AppState(
+ daggerGraphState = DaggerGraphState(
+ networkConnectionManager = networkConnectionManager,
+ cardScanningFeatureToggles = cardScanningFeatureToggles,
+ walletConnectRepository = walletConnect2Repository,
+ scanCardProcessor = scanCardProcessor,
+ appCurrencyRepository = appCurrencyRepository,
+ walletManagersFacade = walletManagersFacade,
+ appStateHolder = appStateHolder,
+ appThemeModeRepository = appThemeModeRepository,
+ balanceHidingRepository = balanceHidingRepository,
+ walletsRepository = walletsRepository,
+ generalUserWalletsListManager = generalUserWalletsListManager,
+ wasTwinsOnboardingShownUseCase = wasTwinsOnboardingShownUseCase,
+ saveTwinsOnboardingShownUseCase = saveTwinsOnboardingShownUseCase,
+ generateWalletNameUseCase = generateWalletNameUseCase,
+ cardRepository = cardRepository,
+ settingsRepository = settingsRepository,
+ blockchainSDKFactory = blockchainSDKFactory,
+ sendFeedbackEmailUseCase = sendFeedbackEmailUseCase,
+ getCardInfoUseCase = getCardInfoUseCase,
+ issuersConfigStorage = issuersConfigStorage,
+ urlOpener = urlOpener,
+ shareManager = shareManager,
+ appRouter = appRouter,
+ transactionSignerFactory = transactionSignerFactory,
+ getUserCountryUseCase = getUserCountryUseCase,
+ onrampFeatureToggles = onrampFeatureToggles,
+ environmentConfigStorage = environmentConfigStorage,
+ onboardingV2FeatureToggles = onboardingV2FeatureToggles,
+ onboardingRepository = onboardingRepository,
+ excludedBlockchains = excludedBlockchains,
+ appPreferencesStore = appPreferencesStore,
+ clipboardManager = clipboardManager,
+ settingsManager = settingsManager,
+ uiMessageSender = uiMessageSender,
+ ),
+ ),
+ )
+ }
+
+ override fun newImageLoader(): ImageLoader {
+ return createCoilImageLoader(
+ context = this,
+ logEnabled = LogConfig.imageLoader,
+ )
+ }
+
+ private fun loadNativeLibraries() {
+ System.loadLibrary("TrustWalletCore")
+ }
+
+ private fun initWithConfigDependency(environmentConfig: EnvironmentConfig) {
+ initAnalytics(this, environmentConfig)
+ Log.addLogger(logger = tangemSdkLogger)
+ }
+
+ private fun initAnalytics(application: Application, environmentConfig: EnvironmentConfig) {
+ val factory = AnalyticsFactory()
+ factory.addHandlerBuilder(AmplitudeAnalyticsHandler.Builder())
+ factory.addHandlerBuilder(FirebaseAnalyticsHandler.Builder())
+
+ factory.addFilter(oneTimeEventFilter)
+
+ val buildData = AnalyticsHandlerBuilder.Data(
+ application = application,
+ config = environmentConfig,
+ isDebug = BuildConfig.DEBUG,
+ logConfig = LogConfig.analyticsHandlers,
+ jsonConverter = MoshiConverter.sdkMoshiConverter,
+ )
+
+ Analytics.addParamsInterceptor(
+ interceptor = object : ParamsInterceptor {
+ override fun id(): String = "SendTransactionSignerInfoInterceptor"
+
+ override fun canBeAppliedTo(event: AnalyticsEvent): Boolean = event is Basic.TransactionSent
+
+ override fun intercept(params: MutableMap) {
+ val isLastSignWithRing = store.state.globalState.isLastSignWithRing
+
+ params[AnalyticsParam.WALLET_FORM] = if (isLastSignWithRing) {
+ WalletForm.Ring.name
+ } else {
+ WalletForm.Card.name
+ }
+ }
+ },
+ )
+
+ factory.build(Analytics, buildData)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/TangemHiltApplication.kt b/app/src/main/java/com/tangem/tap/TangemHiltApplication.kt
new file mode 100644
index 0000000000..a818249392
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/TangemHiltApplication.kt
@@ -0,0 +1,6 @@
+package com.tangem.tap
+
+import dagger.hilt.android.HiltAndroidApp
+
+@HiltAndroidApp
+class TangemHiltApplication : TangemApplication()
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/TapApplication.kt b/app/src/main/java/com/tangem/tap/TapApplication.kt
deleted file mode 100644
index 0c8ba92c53..0000000000
--- a/app/src/main/java/com/tangem/tap/TapApplication.kt
+++ /dev/null
@@ -1,242 +0,0 @@
-package com.tangem.tap
-
-import android.app.Application
-import android.content.Context
-import android.content.pm.PackageManager
-import coil.ImageLoader
-import coil.ImageLoaderFactory
-import com.tangem.Log
-import com.tangem.LogFormat
-import com.tangem.blockchain.common.BlockchainSdkConfig
-import com.tangem.blockchain.common.WalletManagerFactory
-import com.tangem.blockchain.network.BlockchainSdkRetrofitBuilder
-import com.tangem.core.analytics.Analytics
-import com.tangem.datasource.api.common.MoshiConverter
-import com.tangem.domain.DomainLayer
-import com.tangem.domain.common.LogConfig
-import com.tangem.tap.common.AndroidAssetReader
-import com.tangem.tap.common.AssetReader
-import com.tangem.tap.common.IntentHandler
-import com.tangem.tap.common.analytics.AnalyticsFactory
-import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
-import com.tangem.tap.common.analytics.filters.BasicSignInFilter
-import com.tangem.tap.common.analytics.filters.BasicTopUpFilter
-import com.tangem.tap.common.analytics.handlers.amplitude.AmplitudeAnalyticsHandler
-import com.tangem.tap.common.analytics.handlers.appsFlyer.AppsFlyerAnalyticsHandler
-import com.tangem.tap.common.analytics.handlers.firebase.FirebaseAnalyticsHandler
-import com.tangem.tap.common.feedback.AdditionalFeedbackInfo
-import com.tangem.tap.common.feedback.FeedbackManager
-import com.tangem.tap.common.images.createCoilImageLoader
-import com.tangem.tap.common.log.TangemLogCollector
-import com.tangem.tap.common.redux.AppState
-import com.tangem.tap.common.redux.appReducer
-import com.tangem.tap.common.redux.global.GlobalAction
-import com.tangem.tap.common.shop.TangemShopService
-import com.tangem.tap.domain.configurable.config.Config
-import com.tangem.tap.domain.configurable.config.ConfigManager
-import com.tangem.tap.domain.configurable.config.FeaturesLocalLoader
-import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager
-import com.tangem.tap.domain.tokens.UserTokensRepository
-import com.tangem.tap.domain.totalBalance.TotalFiatBalanceCalculator
-import com.tangem.tap.domain.totalBalance.di.provideDefaultImplementation
-import com.tangem.tap.domain.walletCurrencies.WalletCurrenciesManager
-import com.tangem.tap.domain.walletCurrencies.di.provideDefaultImplementation
-import com.tangem.tap.domain.walletStores.WalletStoresManager
-import com.tangem.tap.domain.walletStores.di.provideDefaultImplementation
-import com.tangem.tap.domain.walletStores.repository.WalletAmountsRepository
-import com.tangem.tap.domain.walletStores.repository.WalletManagersRepository
-import com.tangem.tap.domain.walletStores.repository.WalletStoresRepository
-import com.tangem.tap.domain.walletStores.repository.di.provideDefaultImplementation
-import com.tangem.tap.domain.walletconnect.WalletConnectRepository
-import com.tangem.tap.network.NetworkConnectivity
-import com.tangem.tap.persistence.PreferencesStorage
-import com.tangem.tap.proxy.AppStateHolder
-import com.tangem.wallet.BuildConfig
-import com.zendesk.logger.Logger
-import dagger.hilt.android.HiltAndroidApp
-import org.rekotlin.Store
-import timber.log.Timber
-import zendesk.chat.Chat
-import javax.inject.Inject
-
-lateinit var store: Store
-
-lateinit var foregroundActivityObserver: ForegroundActivityObserver
-lateinit var activityResultCaller: ActivityResultCaller
-lateinit var preferencesStorage: PreferencesStorage
-lateinit var walletConnectRepository: WalletConnectRepository
-lateinit var shopService: TangemShopService
-lateinit var assetReader: AssetReader
-lateinit var userTokensRepository: UserTokensRepository
-
-private val walletStoresRepository by lazy { WalletStoresRepository.provideDefaultImplementation() }
-private val walletManagersRepository by lazy {
- WalletManagersRepository.provideDefaultImplementation(
- walletManagerFactory = WalletManagerFactory(
- blockchainSdkConfig = store.state.globalState.configManager
- ?.config
- ?.blockchainSdkConfig
- ?: BlockchainSdkConfig(),
- ),
- )
-}
-private val walletAmountsRepository by lazy {
- WalletAmountsRepository.provideDefaultImplementation(
- tangemTechService = store.state.domainNetworks.tangemTechService,
- )
-}
-val walletStoresManager by lazy {
- WalletStoresManager.provideDefaultImplementation(
- userTokensRepository = userTokensRepository,
- walletStoresRepository = walletStoresRepository,
- walletManagersRepository = walletManagersRepository,
- walletAmountsRepository = walletAmountsRepository,
- appCurrencyProvider = { store.state.globalState.appCurrency },
- )
-}
-val walletCurrenciesManager by lazy {
- WalletCurrenciesManager.provideDefaultImplementation(
- userTokensRepository = userTokensRepository,
- walletStoresRepository = walletStoresRepository,
- walletManagersRepository = walletManagersRepository,
- walletAmountsRepository = walletAmountsRepository,
- appCurrencyProvider = { store.state.globalState.appCurrency },
- )
-}
-val totalFiatBalanceCalculator by lazy {
- TotalFiatBalanceCalculator.provideDefaultImplementation()
-}
-val intentHandler by lazy { IntentHandler() }
-
-@HiltAndroidApp
-class TapApplication : Application(), ImageLoaderFactory {
-
- @Inject
- lateinit var appStateHolder: AppStateHolder
-
- override fun onCreate() {
- super.onCreate()
-
- store = Store(
- reducer = { action, state ->
- appReducer(action, state, appStateHolder)
- },
- middleware = AppState.getMiddleware(),
- state = AppState(),
- )
-
- if (BuildConfig.DEBUG) {
- Timber.plant(Timber.DebugTree())
- }
-
- foregroundActivityObserver = ForegroundActivityObserver()
- activityResultCaller = foregroundActivityObserver
- registerActivityLifecycleCallbacks(foregroundActivityObserver.callbacks)
-
- DomainLayer.init()
- NetworkConnectivity.createInstance(store, this)
- preferencesStorage = PreferencesStorage(this)
- walletConnectRepository = WalletConnectRepository(this)
-
- assetReader = AndroidAssetReader(this)
- val configLoader = FeaturesLocalLoader(assetReader, MoshiConverter.sdkMoshi)
- initConfigManager(configLoader, ::initWithConfigDependency)
- initWarningMessagesManager()
-
- BlockchainSdkRetrofitBuilder.enableNetworkLogging = LogConfig.network.blockchainSdkNetwork
-
- userTokensRepository = UserTokensRepository.init(
- context = this,
- tangemTechService = store.state.domainNetworks.tangemTechService,
- )
- appStateHolder.mainStore = store
- appStateHolder.userTokensRepository = userTokensRepository
- appStateHolder.walletStoresManager = walletStoresManager
- }
-
- override fun newImageLoader(): ImageLoader {
- return createCoilImageLoader(
- context = this,
- logEnabled = LogConfig.imageLoader,
- )
- }
-
- private fun initConfigManager(loader: FeaturesLocalLoader, onComplete: (Config) -> Unit) {
- val configManager = ConfigManager()
- configManager.load(loader) { config ->
- store.dispatch(GlobalAction.SetConfigManager(configManager))
- onComplete(config)
- }
- }
-
- private fun initWithConfigDependency(config: Config) {
- shopService = TangemShopService(this, config.shopify!!)
- initAnalytics(this, config)
- initFeedbackManager(this, preferencesStorage)
- }
-
- private fun initAnalytics(application: Application, config: Config) {
- val factory = AnalyticsFactory()
- factory.addHandlerBuilder(AmplitudeAnalyticsHandler.Builder())
- factory.addHandlerBuilder(AppsFlyerAnalyticsHandler.Builder())
- factory.addHandlerBuilder(FirebaseAnalyticsHandler.Builder())
-
- factory.addFilter(BasicSignInFilter())
- factory.addFilter(BasicTopUpFilter(preferencesStorage.toppedUpWalletStorage))
-
- val buildData = AnalyticsHandlerBuilder.Data(
- application = application,
- config = config,
- isDebug = BuildConfig.DEBUG,
- logConfig = LogConfig.analyticsHandlers,
- jsonConverter = MoshiConverter.sdkMoshiConverter,
- )
- factory.build(Analytics, buildData)
- }
-
- private fun initFeedbackManager(context: Context, preferencesStorage: PreferencesStorage) {
- fun initAdditionalFeedbackInfo(context: Context): AdditionalFeedbackInfo = AdditionalFeedbackInfo().apply {
- appVersion = try {
- val pInfo = context.packageManager.getPackageInfo(context.packageName, 0)
- pInfo.versionName
- } catch (e: PackageManager.NameNotFoundException) {
- e.printStackTrace()
- "x.y.z"
- }
- }
-
- fun initTangemLogCollector(): TangemLogCollector {
- val logLevels = listOf(
- Log.Level.ApduCommand,
- Log.Level.Apdu,
- Log.Level.Tlv,
- Log.Level.Nfc,
- Log.Level.Command,
- Log.Level.Session,
- Log.Level.View,
- Log.Level.Network,
- Log.Level.Error,
- )
- return TangemLogCollector(logLevels, LogFormat.StairsFormatter())
- }
-
- val additionalFeedbackInfo = initAdditionalFeedbackInfo(context)
- val tangemLogCollector = initTangemLogCollector()
- Log.addLogger(tangemLogCollector)
-
- val feedbackManager = FeedbackManager(
- infoHolder = additionalFeedbackInfo,
- logCollector = tangemLogCollector,
- preferencesStorage = preferencesStorage,
- )
- feedbackManager.chatInitializer = { zendeskConfig ->
- Chat.INSTANCE.init(context, zendeskConfig.accountKey, zendeskConfig.appId)
- Logger.setLoggable(LogConfig.zendesk)
- }
- store.dispatch(GlobalAction.SetFeedbackManager(feedbackManager))
- }
-
- private fun initWarningMessagesManager() {
- store.dispatch(GlobalAction.SetWarningManager(WarningMessagesManager()))
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/WaitForMigration.kt b/app/src/main/java/com/tangem/tap/WaitForMigration.kt
deleted file mode 100644
index 59c14fb064..0000000000
--- a/app/src/main/java/com/tangem/tap/WaitForMigration.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.tangem.tap
-
-/**
-[REDACTED_AUTHOR]
- */
-
-const val DELAY_SDK_DIALOG_CLOSE = 1400L
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/WindowObscurationObserver.kt b/app/src/main/java/com/tangem/tap/WindowObscurationObserver.kt
new file mode 100644
index 0000000000..57f5a3fdec
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/WindowObscurationObserver.kt
@@ -0,0 +1,68 @@
+package com.tangem.tap
+
+import android.os.Build
+import android.view.MotionEvent
+import androidx.lifecycle.DefaultLifecycleObserver
+import androidx.lifecycle.LifecycleOwner
+import com.tangem.core.analytics.api.AnalyticsEventHandler
+import com.tangem.core.analytics.models.event.TechAnalyticsEvent
+import com.tangem.core.analytics.models.event.TechAnalyticsEvent.WindowObscured.ObscuredState
+import timber.log.Timber
+
+internal object WindowObscurationObserver : DefaultLifecycleObserver {
+
+ private var isWindowPartiallyObscuredAlreadySent: Boolean = false
+ private var isWindowFullyObscuredAlreadySent: Boolean = false
+
+ private var isReadyToProxy = false
+
+ override fun onResume(owner: LifecycleOwner) {
+ super.onResume(owner)
+ isReadyToProxy = true
+ }
+
+ override fun onPause(owner: LifecycleOwner) {
+ super.onPause(owner)
+ isReadyToProxy = false
+ }
+
+ fun dispatchTouchEvent(event: MotionEvent, analyticsEventHandler: AnalyticsEventHandler): Boolean {
+ if (!isReadyToProxy) return true
+
+ val isPartiallyObscured = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ event.flags and MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED != 0
+ } else {
+ false
+ }
+
+ if (isPartiallyObscured) {
+ Timber.d("Window is partially obscured")
+
+ if (!isWindowPartiallyObscuredAlreadySent) {
+ analyticsEventHandler.send(
+ event = TechAnalyticsEvent.WindowObscured(state = ObscuredState.PARTIALLY),
+ )
+
+ isWindowPartiallyObscuredAlreadySent = true
+ }
+ }
+
+ val isFullyObscured = event.flags and MotionEvent.FLAG_WINDOW_IS_OBSCURED != 0
+
+ if (isFullyObscured) {
+ Timber.d("Window is partially or fully obscured")
+
+ if (!isWindowFullyObscuredAlreadySent) {
+ analyticsEventHandler.send(
+ event = TechAnalyticsEvent.WindowObscured(state = ObscuredState.FULLY),
+ )
+
+ isWindowFullyObscuredAlreadySent = true
+ }
+
+ return false
+ }
+
+ return true
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/AssetReader.kt b/app/src/main/java/com/tangem/tap/common/AssetReader.kt
deleted file mode 100644
index 3f5eb10dd9..0000000000
--- a/app/src/main/java/com/tangem/tap/common/AssetReader.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.tangem.tap.common
-
-import android.content.Context
-import com.tangem.tap.common.extensions.readAssetAsString
-
-/**
-[REDACTED_AUTHOR]
- */
-interface AssetReader {
- fun readAssetAsString(name: String): String
-}
-
-class AndroidAssetReader(
- private val context: Context,
-) : AssetReader {
-
- override fun readAssetAsString(name: String): String {
- return context.readAssetAsString(name)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/CompositionCounter.kt b/app/src/main/java/com/tangem/tap/common/CompositionCounter.kt
deleted file mode 100644
index 4e80061209..0000000000
--- a/app/src/main/java/com/tangem/tap/common/CompositionCounter.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.tangem.tap.common
-
-import timber.log.Timber
-
-class CompositionCounter(
- val id: String,
- count: Int = 0
-) {
- var count: Int = count
- private set
-
- fun increase(id: String): CompositionCounter {
- if (this.id != id) return this
-
- count += 1
- return CompositionCounter(id, count)
- }
-}
-
-class CompositionLogger(
- private val recomposeViewId: String,
- private val tag: String = recomposeViewId,
- private var turnOnForIds: List = listOf(recomposeViewId)
-) {
- val count: Int
- get() = compositionCounter.count
-
- private var compositionCounter: CompositionCounter = CompositionCounter(recomposeViewId)
-
- fun nextComposition() {
- compositionCounter = compositionCounter.increase(recomposeViewId)
- log("")
- }
-
- fun log(message: String) {
- if (!turnOnForIds.contains(recomposeViewId)) return
-
- Timber.d("$tag[$recomposeViewId]:[${compositionCounter.count}]: $message")
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/CurrencyConverter.kt b/app/src/main/java/com/tangem/tap/common/CurrencyConverter.kt
deleted file mode 100644
index 2f3e688532..0000000000
--- a/app/src/main/java/com/tangem/tap/common/CurrencyConverter.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.tangem.tap.common
-
-import com.tangem.common.extensions.isZero
-import com.tangem.tap.common.extensions.scaleToFiat
-import java.math.BigDecimal
-import java.math.RoundingMode
-
-/**
-[REDACTED_AUTHOR]
- */
-class CurrencyConverter(
- private val rateValue: BigDecimal,
- private val decimals: Int
-) {
- private val roundingMode = RoundingMode.HALF_UP
-
- fun toFiat(crypto: BigDecimal, fiatDecimals: Int = 2): BigDecimal {
- return toFiatUnscaled(crypto).setScale(fiatDecimals, roundingMode)
- }
-
- fun toFiatUnscaled(crypto: BigDecimal): BigDecimal {
- return rateValue.multiply(crypto).setScale(decimals, roundingMode)
- }
-
- fun toFiatWithPrecision(crypto: BigDecimal): BigDecimal {
- return toFiatUnscaled(crypto).scaleToFiat(true)
- }
-
- fun toCrypto(fiat: BigDecimal): BigDecimal {
- if (fiat.isZero()) return fiat
-
- val scaledRateValue = rateValue.setScale(decimals, roundingMode)
- val scaledFiat = fiat.setScale(decimals, roundingMode)
- return scaledFiat.divide(scaledRateValue, RoundingMode.UP)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/CustomTabsManager.kt b/app/src/main/java/com/tangem/tap/common/CustomTabsManager.kt
deleted file mode 100644
index a30af0f5d6..0000000000
--- a/app/src/main/java/com/tangem/tap/common/CustomTabsManager.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.tangem.tap.common
-
-import android.content.Context
-import android.net.Uri
-import androidx.browser.customtabs.CustomTabColorSchemeParams
-import androidx.browser.customtabs.CustomTabsIntent
-import com.tangem.tap.common.extensions.getColorCompat
-import com.tangem.wallet.R
-
-class CustomTabsManager {
- fun openUrl(url: String, context: Context) {
- val customTabsIntent = CustomTabsIntent.Builder()
- .setDefaultColorSchemeParams(
- CustomTabColorSchemeParams.Builder()
- .setNavigationBarColor(context.getColorCompat(R.color.toolbarColor))
- .build()
- )
- .build()
- customTabsIntent.launchUrl(context, Uri.parse(url))
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/DialogManager.kt b/app/src/main/java/com/tangem/tap/common/DialogManager.kt
index 93c54eeefa..c69530d3be 100644
--- a/app/src/main/java/com/tangem/tap/common/DialogManager.kt
+++ b/app/src/main/java/com/tangem/tap/common/DialogManager.kt
@@ -2,38 +2,16 @@ package com.tangem.tap.common
import android.app.Dialog
import android.content.Context
+import com.tangem.domain.redux.StateDialog
import com.tangem.tap.common.redux.AppDialog
import com.tangem.tap.common.redux.global.GlobalState
-import com.tangem.tap.common.ui.SimpleAlertDialog
-import com.tangem.tap.common.ui.SimpleCancelableAlertDialog
+import com.tangem.tap.common.ui.*
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectDialog
-import com.tangem.tap.features.details.ui.walletconnect.dialogs.ApproveWcSessionDialog
-import com.tangem.tap.features.details.ui.walletconnect.dialogs.BnbTransactionDialog
-import com.tangem.tap.features.details.ui.walletconnect.dialogs.ChooseNetworkDialog
-import com.tangem.tap.features.details.ui.walletconnect.dialogs.ClipboardOrScanQrDialog
-import com.tangem.tap.features.details.ui.walletconnect.dialogs.PersonalSignDialog
-import com.tangem.tap.features.details.ui.walletconnect.dialogs.TransactionDialog
-import com.tangem.tap.features.onboarding.AddressInfoBottomSheetDialog
+import com.tangem.tap.features.details.ui.walletconnect.dialogs.*
import com.tangem.tap.features.onboarding.OnboardingDialog
import com.tangem.tap.features.onboarding.products.twins.ui.dialog.TwinningProcessNotCompletedDialog
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupDialog
-import com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog.InterruptOnboardingDialog
-import com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog.NoFundsForActivationDialog
-import com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog.PutVisaCardDialog
-import com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog.RegistrationErrorDialog
-import com.tangem.tap.features.onboarding.products.wallet.saltPay.dialog.SaltPayDialog
-import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.AddMoreBackupCardsDialog
-import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.BackupInProgressDialog
-import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.ConfirmDiscardingBackupDialog
-import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.UnfinishedBackupFoundDialog
-import com.tangem.tap.features.wallet.redux.models.WalletDialog
-import com.tangem.tap.features.wallet.ui.dialogs.AmountToSendBottomSheetDialog
-import com.tangem.tap.features.wallet.ui.dialogs.ChooseTradeActionBottomSheetDialog
-import com.tangem.tap.features.wallet.ui.dialogs.RussianCardholdersWarningBottomSheetDialog
-import com.tangem.tap.features.wallet.ui.dialogs.ScanFailsDialog
-import com.tangem.tap.features.wallet.ui.dialogs.SignedHashesWarningDialog
-import com.tangem.tap.features.wallet.ui.dialogs.SimpleOkDialog
-import com.tangem.tap.features.wallet.ui.wallet.CurrencySelectionDialog
+import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.*
import com.tangem.tap.store
import com.tangem.wallet.R
import org.rekotlin.StoreSubscriber
@@ -67,30 +45,38 @@ class DialogManager : StoreSubscriber {
if (dialog != null) return
dialog = when (state.dialog) {
- is AppDialog.SimpleOkDialog -> SimpleOkDialog.create(state.dialog, context)
is AppDialog.SimpleOkDialogRes -> SimpleOkDialog.create(state.dialog, context)
- is AppDialog.SimpleOkErrorDialog -> SimpleOkDialog.create(state.dialog, context)
- is AppDialog.SimpleOkWarningDialog -> SimpleOkDialog.create(state.dialog, context)
- is AppDialog.ScanFailsDialog -> ScanFailsDialog.create(context)
+ is StateDialog.ScanFailsDialog -> ScanFailsDialog.create(
+ context = context,
+ source = state.dialog.source,
+ onTryAgain = state.dialog.onTryAgain,
+ )
+ is StateDialog.NfcFeatureIsUnavailable -> SimpleAlertDialog.create(
+ titleRes = R.string.common_error,
+ messageRes = R.string.nfc_error_unavailable,
+ context = context,
+ )
is AppDialog.AddressInfoDialog -> AddressInfoBottomSheetDialog(state.dialog, context)
is AppDialog.TestActionsDialog -> TestActionsBottomSheetDialog(state.dialog, context)
is OnboardingDialog.TwinningProcessNotCompleted -> TwinningProcessNotCompletedDialog.create(context)
is OnboardingDialog.InterruptOnboarding -> InterruptOnboardingDialog.create(context, state.dialog)
+ is OnboardingDialog.WalletActivationError -> WalletActivationErrorDialog.create(context, state.dialog)
is WalletConnectDialog.UnsupportedCard ->
SimpleAlertDialog.create(
titleRes = R.string.wallet_connect_title,
messageRes = R.string.wallet_connect_scanner_error_not_valid_card,
context = context,
)
- is WalletConnectDialog.AddNetwork ->
+ is WalletConnectDialog.AddNetwork -> {
+ val message = context.getString(
+ R.string.wallet_connect_error_missing_blockchains,
+ ) + state.dialog.networks.joinToString()
SimpleAlertDialog.create(
titleRes = R.string.wallet_connect_title,
- message = context.getString(
- R.string.wallet_connect_network_not_found_format,
- state.dialog.network,
- ),
+ message = message,
context = context,
)
+ }
is WalletConnectDialog.OpeningSessionRejected -> {
SimpleAlertDialog.create(
titleRes = R.string.wallet_connect_title,
@@ -105,57 +91,98 @@ class DialogManager : StoreSubscriber {
context = context,
)
}
- is WalletConnectDialog.ApproveWcSession ->
- ApproveWcSessionDialog.create(state.dialog.session, state.dialog.networks, context)
- is WalletConnectDialog.ChooseNetwork ->
- ChooseNetworkDialog.create(state.dialog.session, state.dialog.networks, context)
is WalletConnectDialog.ClipboardOrScanQr ->
ClipboardOrScanQrDialog.create(state.dialog.clipboardUri, context)
- is WalletConnectDialog.RequestTransaction -> TransactionDialog.create(state.dialog.dialogData, context)
+ is WalletConnectDialog.RequestTransaction -> TransactionDialog.create(state.dialog.data, context)
is WalletConnectDialog.PersonalSign -> PersonalSignDialog.create(state.dialog.data, context)
is WalletConnectDialog.BnbTransactionDialog ->
BnbTransactionDialog.create(
- data = state.dialog.data,
- session = state.dialog.session,
- sessionId = state.dialog.sessionId,
- dAppName = state.dialog.dAppName,
+ preparedData = state.dialog.data,
context = context,
)
- is WalletConnectDialog.UnsupportedNetwork ->
+ is WalletConnectDialog.UnsupportedNetwork -> {
+ val warning = if (state.dialog.networks.isNullOrEmpty()) {
+ context.getString(R.string.wallet_connect_scanner_error_unsupported_network)
+ } else {
+ context.getString(R.string.wallet_connect_error_unsupported_blockchains) +
+ state.dialog.networks.joinToString()
+ }
SimpleAlertDialog.create(
titleRes = R.string.wallet_connect_title,
- messageRes = R.string.wallet_connect_scanner_error_unsupported_network,
+ message = warning,
context = context,
)
+ }
+ is WalletConnectDialog.UnsupportedDapp -> SimpleAlertDialog.create(
+ titleRes = R.string.wallet_connect_title,
+ messageRes = R.string.wallet_connect_error_unsupported_dapp,
+ context = context,
+ )
+ is WalletConnectDialog.SessionProposalDialog -> {
+ SessionProposalDialog.create(
+ sessionProposal = state.dialog.sessionProposal,
+ networks = state.dialog.networks,
+ context = context,
+ onApprove = state.dialog.onApprove,
+ onReject = state.dialog.onReject,
+ )
+ }
+ is WalletConnectDialog.SignTransactionDialog -> SignTransactionDialog.create(
+ preparedData = state.dialog.data,
+ context = context,
+ )
+ is WalletConnectDialog.SignTransactionsDialog -> SignTransactionsDialog.create(
+ preparedData = state.dialog.data,
+ context = context,
+ )
+ is WalletConnectDialog.PairConnectErrorDialog -> SimpleAlertDialog.create(
+ titleRes = R.string.wallet_connect_title,
+ message = state.dialog.error.message,
+ context = context,
+ )
+ is WalletConnectDialog.UnsupportedWcVersion -> SimpleAlertDialog.create(
+ titleRes = R.string.common_error,
+ messageRes = R.string.unsupported_wc_version,
+ context = context,
+ )
+ is BackupDialog.AttestationFailed -> AttestationFailedDialog.create(context)
is BackupDialog.AddMoreBackupCards -> AddMoreBackupCardsDialog.create(context)
is BackupDialog.BackupInProgress -> BackupInProgressDialog.create(context)
- is BackupDialog.UnfinishedBackupFound -> UnfinishedBackupFoundDialog.create(context)
- is BackupDialog.ConfirmDiscardingBackup -> ConfirmDiscardingBackupDialog.create(context)
- is SaltPayDialog.Activation.NoGas -> NoFundsForActivationDialog.create(context)
- is SaltPayDialog.Activation.PutVisaCard -> PutVisaCardDialog.create(context)
- is SaltPayDialog.Activation.OnError -> RegistrationErrorDialog.create(context, state.dialog)
- is WalletDialog.CurrencySelectionDialog -> CurrencySelectionDialog.create(state.dialog, context)
- is WalletDialog.ChooseTradeActionDialog -> ChooseTradeActionBottomSheetDialog(context, state.dialog)
- is WalletDialog.SelectAmountToSendDialog -> AmountToSendBottomSheetDialog(context, state.dialog)
- is WalletDialog.SignedHashesMultiWalletDialog -> SignedHashesWarningDialog.create(context)
- is WalletDialog.TokensAreLinkedDialog -> SimpleAlertDialog.create(
+ is BackupDialog.UnfinishedBackupFound -> UnfinishedBackupFoundDialog.create(
+ context = context,
+ scanResponse = state.dialog.scanResponse,
+ )
+ is BackupDialog.ConfirmDiscardingBackup -> ConfirmDiscardingBackupDialog.create(
+ context = context,
+ unfinishedBackupScanResponse = state.dialog.scanResponse,
+ )
+ is BackupDialog.ResetBackupCard -> ResetBackupCardDialog.create(
+ context = context,
+ cardId = state.dialog.cardId,
+ )
+ is AppDialog.TokensAreLinkedDialog -> SimpleAlertDialog.create(
title = context.getString(state.dialog.titleRes, state.dialog.currencySymbol),
message = context.getString(
state.dialog.messageRes,
- state.dialog.currencySymbol,
state.dialog.currencyTitle,
+ state.dialog.currencySymbol,
+ state.dialog.networkName,
),
context = context,
)
- is WalletDialog.RemoveWalletDialog -> SimpleCancelableAlertDialog.create(
+ is AppDialog.WalletAlreadyWasUsedDialog -> WalletAlreadyWasUsedDialog.create(
+ context = context,
+ onOk = state.dialog.onOk,
+ onSupport = state.dialog.onSupportClick,
+ onCancel = state.dialog.onCancel,
+ )
+ is AppDialog.RemoveWalletDialog -> SimpleCancelableAlertDialog.create(
title = context.getString(state.dialog.titleRes, state.dialog.currencyTitle),
messageRes = state.dialog.messageRes,
context = context,
primaryButtonRes = state.dialog.primaryButtonRes,
primaryButtonAction = state.dialog.onOk,
)
- is WalletDialog.RussianCardholdersWarningDialog ->
- RussianCardholdersWarningBottomSheetDialog(context, state.dialog.data)
else -> null
}
dialog?.show()
diff --git a/app/src/main/java/com/tangem/tap/common/FileReader.kt b/app/src/main/java/com/tangem/tap/common/FileReader.kt
deleted file mode 100644
index 49e08b5bcb..0000000000
--- a/app/src/main/java/com/tangem/tap/common/FileReader.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.tangem.tap.common
-
-import android.content.Context
-import com.tangem.tap.common.extensions.readFile
-import com.tangem.tap.common.extensions.rewriteFile
-
-interface FileReader {
- fun readFile(fileName: String): String
- fun rewriteFile(content: String, fileName: String)
-}
-
-class AndroidFileReader(private val context: Context) : FileReader {
- override fun readFile(fileName: String): String {
- return context.readFile(fileName)
- }
-
- override fun rewriteFile(content: String, fileName: String) {
- context.rewriteFile(content, fileName)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/GlobalLayoutStateHandler.kt b/app/src/main/java/com/tangem/tap/common/GlobalLayoutStateHandler.kt
deleted file mode 100644
index a716d772fe..0000000000
--- a/app/src/main/java/com/tangem/tap/common/GlobalLayoutStateHandler.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.tangem.tap.common
-
-import android.view.View
-import android.view.ViewTreeObserver
-import timber.log.Timber
-
-/**
-[REDACTED_AUTHOR]
- */
-class GlobalLayoutStateHandler(
- private val view: T,
- attachImmediately: Boolean = true
-) : ViewTreeObserver.OnGlobalLayoutListener {
-
- var onStateChanged: ((T) -> Unit)? = null
-
- private var isAttached: Boolean = false
-
- init {
- if (attachImmediately) attach()
- }
-
- fun attach() {
- if (isAttached) {
- Timber.d("Already attached")
- return
- }
-
- isAttached = true
- view.viewTreeObserver.addOnGlobalLayoutListener(this)
- }
-
- fun detach() {
- view.viewTreeObserver.removeOnGlobalLayoutListener(this)
- isAttached = false
- }
-
- override fun onGlobalLayout() {
- onStateChanged?.invoke(view)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/Handler.kt b/app/src/main/java/com/tangem/tap/common/Handler.kt
index 37b39734cb..7842da9fbf 100644
--- a/app/src/main/java/com/tangem/tap/common/Handler.kt
+++ b/app/src/main/java/com/tangem/tap/common/Handler.kt
@@ -11,20 +11,6 @@ fun postUi(ms: Long = 0, func: Runnable) {
if (ms == 0L) uiHandler.post { func.run() } else uiHandler.postDelayed(func, ms)
}
-fun postBackground(ms: Long = 0, func: Runnable) {
- if (ms == 0L) backgroundHandler.post { func.run() } else backgroundHandler.postDelayed(func, ms)
-}
-
fun postUiDelayBg(ms: Long, func: Runnable) {
backgroundHandler.postDelayed({ uiHandler.post(func) }, ms)
-}
-
-fun post(ms: Long = 0, func: Runnable) {
- if (ms == 0L) {
- func.run()
- } else {
- val currentLooper = Looper.myLooper() ?: return
-
- Handler(currentLooper).postDelayed(func, ms)
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/IntentHandler.kt b/app/src/main/java/com/tangem/tap/common/IntentHandler.kt
deleted file mode 100644
index f1cd3b1027..0000000000
--- a/app/src/main/java/com/tangem/tap/common/IntentHandler.kt
+++ /dev/null
@@ -1,110 +0,0 @@
-package com.tangem.tap.common
-
-import android.content.Intent
-import android.nfc.NfcAdapter
-import android.nfc.Tag
-import android.os.Build
-import com.tangem.tap.common.extensions.removePrefixOrNull
-import com.tangem.tap.domain.walletconnect.WalletConnectManager
-import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction
-import com.tangem.tap.features.home.redux.HomeAction
-import com.tangem.tap.features.wallet.redux.WalletAction
-import com.tangem.tap.features.welcome.redux.WelcomeAction
-import com.tangem.tap.scope
-import com.tangem.tap.store
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.launch
-import timber.log.Timber
-
-class IntentHandler {
-
- private val nfcActions = arrayOf(
- NfcAdapter.ACTION_NDEF_DISCOVERED,
- NfcAdapter.ACTION_TECH_DISCOVERED,
- NfcAdapter.ACTION_TAG_DISCOVERED,
- )
-
- fun handleIntent(intent: Intent?, hasSavedUserWallets: Boolean) {
- handleBackgroundScan(intent, hasSavedUserWallets)
- handleWalletConnectLink(intent)
- handleSellCurrencyCallback(intent)
- }
-
- fun handleWalletConnectLink(intent: Intent?) {
- val wcUri = when (intent?.scheme) {
- WalletConnectManager.WC_SCHEME -> {
- intent.data?.toString()
- }
- TANGEM_SCHEME -> {
- intent.data?.toString()?.removePrefixOrNull(TANGEM_WC_PREFIX)
- }
- else -> {
- null
- }
- }
- if (wcUri != null) {
- store.dispatch(WalletConnectAction.HandleDeepLink(wcUri))
- }
- }
-
- fun handleBackgroundScan(intent: Intent?, hasSavedUserWallets: Boolean): Boolean {
- if (intent == null || intent.action !in nfcActions) return false
-
- val tag: Tag? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
- intent.getParcelableExtra(NfcAdapter.EXTRA_TAG, Tag::class.java)
- } else {
- @Suppress("DEPRECATION")
- intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
- }
- if (tag == null) return false
-
- intent.action = null
- if (hasSavedUserWallets) {
- // TODO: Remove delay after [REDACTED_JIRA]
- scope.launch {
- delay(timeMillis = 200)
- store.dispatch(WelcomeAction.ProceedWithCard)
- }
- } else {
- store.dispatch(HomeAction.ReadCard())
- }
-
- return true
- }
-
- fun handleSellCurrencyCallback(intent: Intent?) {
- try {
- val transactionID =
- intent?.data?.getQueryParameter(TRANSACTION_ID_PARAM) ?: return
- val currency =
- intent.data?.getQueryParameter(CURRENCY_CODE_PARAM) ?: return
- val amount =
- intent.data?.getQueryParameter(CURRENCY_AMOUNT_PARAM) ?: return
- val destinationAddress =
- intent.data?.getQueryParameter(DEPOSIT_WALLET_ADDRESS_PARAM)
- ?: return
-
- Timber.d("MoonPay Sell: $amount $currency to $destinationAddress")
-
- store.dispatch(
- WalletAction.TradeCryptoAction.SendCrypto(
- currencyId = currency,
- amount = amount,
- destinationAddress = destinationAddress,
- transactionId = transactionID,
- ),
- )
- } catch (exception: Exception) {
- Timber.d("Not MoonPay URL")
- }
- }
-
- companion object {
- private const val TRANSACTION_ID_PARAM = "transactionId"
- private const val CURRENCY_CODE_PARAM = "baseCurrencyCode"
- private const val CURRENCY_AMOUNT_PARAM = "baseCurrencyAmount"
- private const val DEPOSIT_WALLET_ADDRESS_PARAM = "depositWalletAddress"
- private const val TANGEM_SCHEME = "tangem"
- private const val TANGEM_WC_PREFIX = "tangem://wc?uri="
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/KeyboardObserver.kt b/app/src/main/java/com/tangem/tap/common/KeyboardObserver.kt
deleted file mode 100644
index 47f579ca1b..0000000000
--- a/app/src/main/java/com/tangem/tap/common/KeyboardObserver.kt
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.tangem.tap.common
-
-import android.app.Activity
-import android.graphics.Rect
-import android.util.DisplayMetrics
-import android.view.ViewTreeObserver.OnGlobalLayoutListener
-import kotlin.math.absoluteValue
-
-class KeyboardObserver(activity: Activity) {
-
- private val decorView = activity.window.decorView
- private val windowManager = activity.windowManager
- private val originalWindowHeight: Int = getWindowHeight()
- private val onGlobalLayoutListener: OnGlobalLayoutListener = OnGlobalLayoutListener { onGlobalLayout() }
-
- private var onKeyboardListener: ((Boolean) -> Unit)? = null
- private var lastIsShow = false
- private var lastWindowHeight = getWindowHeight()
-
- fun registerListener(listener: (Boolean) -> Unit) {
- decorView.viewTreeObserver.addOnGlobalLayoutListener(onGlobalLayoutListener)
- onKeyboardListener = listener
- }
-
- fun unregisterListener() {
- decorView.viewTreeObserver.removeOnGlobalLayoutListener(onGlobalLayoutListener)
- onKeyboardListener = null
- }
-
- private fun getWindowHeight() = Rect().apply { decorView.getWindowVisibleDisplayFrame(this) }.bottom
-
- private fun onGlobalLayout() {
- val currentWindowHeight = getWindowHeight()
- if (isSoftKeyChanged()) {
- lastWindowHeight = currentWindowHeight
- return
- }
-
- lastWindowHeight = currentWindowHeight
- val isShow = originalWindowHeight != currentWindowHeight
- if (lastIsShow == isShow) return
-
- lastIsShow = isShow
- onKeyboardListener?.invoke(isShow)
- }
-
- private fun isSoftKeyChanged() = (lastWindowHeight - getWindowHeight()).absoluteValue == getSoftKeyButtonHeight()
-
- private fun getSoftKeyButtonHeight(): Int {
- val applicationDisplayHeight = DisplayMetrics().apply {
- windowManager.defaultDisplay.getMetrics(this)
- }.heightPixels
-
- val realDisplayHeight = DisplayMetrics().apply {
- windowManager.defaultDisplay.getRealMetrics(this)
- }.heightPixels
-
- return realDisplayHeight - applicationDisplayHeight
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/SnackbarHandler.kt b/app/src/main/java/com/tangem/tap/common/SnackbarHandler.kt
index c10b8e6f37..2d8f270f89 100644
--- a/app/src/main/java/com/tangem/tap/common/SnackbarHandler.kt
+++ b/app/src/main/java/com/tangem/tap/common/SnackbarHandler.kt
@@ -1,8 +1,24 @@
package com.tangem.tap.common
-import android.view.View
+import androidx.annotation.StringRes
+import com.google.android.material.snackbar.Snackbar
+import com.tangem.core.ui.extensions.TextReference
interface SnackbarHandler {
- fun showSnackbar(text: Int, buttonTitle: Int? = null, action: View.OnClickListener? = null)
+
+ fun showSnackbar(
+ @StringRes text: Int,
+ length: Int = Snackbar.LENGTH_INDEFINITE,
+ @StringRes buttonTitle: Int? = null,
+ action: (() -> Unit)? = null,
+ )
+
+ fun showSnackbar(
+ text: TextReference,
+ length: Int = Snackbar.LENGTH_INDEFINITE,
+ buttonTitle: TextReference? = null,
+ action: (() -> Unit)? = null,
+ )
+
fun dismissSnackbar()
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/TestActions.kt b/app/src/main/java/com/tangem/tap/common/TestActions.kt
index b787e7a1b3..955b89e867 100644
--- a/app/src/main/java/com/tangem/tap/common/TestActions.kt
+++ b/app/src/main/java/com/tangem/tap/common/TestActions.kt
@@ -8,11 +8,8 @@ import androidx.appcompat.widget.LinearLayoutCompat
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.tangem.tap.common.extensions.dispatchDialogHide
-import com.tangem.tap.common.extensions.dispatchDialogShow
-import com.tangem.tap.common.extensions.show
import com.tangem.tap.common.redux.AppDialog
import com.tangem.tap.store
-import com.tangem.wallet.BuildConfig
/**
[REDACTED_AUTHOR]
@@ -22,18 +19,6 @@ object TestActions {
// It used only for the test actions in debug or debug_beta builds
var testAmountInjectionForWalletManagerEnabled = false
-
- /**
- * @param isTestView - true must be used if you want to show or hide your view depends on BuildConfig
- */
- fun initFor(view: View, actions: List, isTestView: Boolean = false) {
- if (!BuildConfig.TEST_ACTION_ENABLED) return
- if (isTestView) view.show(BuildConfig.TEST_ACTION_ENABLED)
-
- view.setOnClickListener {
- store.dispatchDialogShow(AppDialog.TestActionsDialog(actions))
- }
- }
}
typealias TestAction = Pair Unit>
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/AnalyticsFactory.kt b/app/src/main/java/com/tangem/tap/common/analytics/AnalyticsFactory.kt
index ed2e3868b5..e6383007c0 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/AnalyticsFactory.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/AnalyticsFactory.kt
@@ -22,10 +22,6 @@ class AnalyticsFactory {
filters.add(filter)
}
- fun addParamsInterceptor(interceptor: ParamsInterceptor) {
- interceptors.add(interceptor)
- }
-
fun build(analytics: Analytics, data: AnalyticsHandlerBuilder.Data) {
builders.mapNotNull { it.build(data) }.forEach { analytics.addHandler(it.id(), it) }
filters.forEach { analytics.addFilter(it) }
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/DefaultAnalyticsContextProxy.kt b/app/src/main/java/com/tangem/tap/common/analytics/DefaultAnalyticsContextProxy.kt
new file mode 100644
index 0000000000..d1aecc29d0
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/analytics/DefaultAnalyticsContextProxy.kt
@@ -0,0 +1,31 @@
+package com.tangem.tap.common.analytics
+
+import com.tangem.core.analytics.Analytics
+import com.tangem.core.analytics.utils.AnalyticsContextProxy
+import com.tangem.domain.models.scan.ScanResponse
+import com.tangem.tap.common.extensions.addContext
+import com.tangem.tap.common.extensions.eraseContext
+import com.tangem.tap.common.extensions.removeContext
+import com.tangem.tap.common.extensions.setContext
+
+/**
+[REDACTED_AUTHOR]
+ */
+internal class DefaultAnalyticsContextProxy : AnalyticsContextProxy {
+
+ override fun setContext(scanResponse: ScanResponse) {
+ Analytics.setContext(scanResponse)
+ }
+
+ override fun eraseContext() {
+ Analytics.eraseContext()
+ }
+
+ override fun addContext(scanResponse: ScanResponse) {
+ Analytics.addContext(scanResponse)
+ }
+
+ override fun removeContext() {
+ Analytics.removeContext()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/DefaultChangeCardAnalyticsContextUseCase.kt b/app/src/main/java/com/tangem/tap/common/analytics/DefaultChangeCardAnalyticsContextUseCase.kt
new file mode 100644
index 0000000000..27f55538da
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/analytics/DefaultChangeCardAnalyticsContextUseCase.kt
@@ -0,0 +1,13 @@
+package com.tangem.tap.common.analytics
+
+import com.tangem.core.analytics.Analytics
+import com.tangem.domain.analytics.ChangeCardAnalyticsContextUseCase
+import com.tangem.domain.models.scan.ScanResponse
+import com.tangem.tap.common.extensions.setContext
+
+internal class DefaultChangeCardAnalyticsContextUseCase : ChangeCardAnalyticsContextUseCase {
+
+ override fun invoke(scanResponse: ScanResponse) {
+ Analytics.setContext(scanResponse)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/TangemSdkErrorMapper.kt b/app/src/main/java/com/tangem/tap/common/analytics/TangemSdkErrorMapper.kt
deleted file mode 100644
index 2f9552c1ae..0000000000
--- a/app/src/main/java/com/tangem/tap/common/analytics/TangemSdkErrorMapper.kt
+++ /dev/null
@@ -1,119 +0,0 @@
-package com.tangem.tap.common.analytics
-
-import com.tangem.common.core.TangemSdkError
-
-object TangemSdkErrorMapper {
-
- // This mapping is performed to group errors in FirebaseCrashlytics.
- // At the moment, the errors in Crashlytics can only be grouped by their place of creation (class and line).
- @Suppress("LongMethod", "ComplexMethod")
- fun map(error: TangemSdkError): TangemSdkError {
- return when (error) {
- is TangemSdkError.TagLost -> TangemSdkError.TagLost()
- is TangemSdkError.ExtendedLengthNotSupported -> TangemSdkError.ExtendedLengthNotSupported()
- is TangemSdkError.SerializeCommandError -> TangemSdkError.SerializeCommandError()
- is TangemSdkError.DeserializeApduFailed -> TangemSdkError.DeserializeApduFailed()
- is TangemSdkError.EncodingFailedTypeMismatch -> TangemSdkError.EncodingFailedTypeMismatch(
- error.customMessage
- )
- is TangemSdkError.EncodingFailed -> TangemSdkError.EncodingFailed(error.customMessage)
- is TangemSdkError.DecodingFailedMissingTag -> TangemSdkError.DecodingFailedMissingTag(
- error.customMessage
- )
- is TangemSdkError.DecodingFailedTypeMismatch -> TangemSdkError.DecodingFailedTypeMismatch(
- error.customMessage
- )
- is TangemSdkError.DecodingFailed -> TangemSdkError.DecodingFailed(error.customMessage)
- is TangemSdkError.InvalidResponse -> TangemSdkError.InvalidResponse()
- is TangemSdkError.UnknownStatus -> TangemSdkError.UnknownStatus(error.statusWord)
- is TangemSdkError.ErrorProcessingCommand -> TangemSdkError.ErrorProcessingCommand()
- is TangemSdkError.InvalidState -> TangemSdkError.InvalidState()
- is TangemSdkError.InsNotSupported -> TangemSdkError.InsNotSupported()
- is TangemSdkError.InvalidParams -> TangemSdkError.InvalidParams()
- is TangemSdkError.NeedEncryption -> TangemSdkError.NeedEncryption()
- is TangemSdkError.FileNotFound -> TangemSdkError.FileNotFound()
- is TangemSdkError.WalletNotFound -> TangemSdkError.WalletNotFound()
- is TangemSdkError.AlreadyPersonalized -> TangemSdkError.AlreadyPersonalized()
- is TangemSdkError.CannotBeDepersonalized -> TangemSdkError.CannotBeDepersonalized()
- is TangemSdkError.AccessCodeRequired -> TangemSdkError.AccessCodeRequired()
- is TangemSdkError.CardReadWrongWallet -> TangemSdkError.CardReadWrongWallet()
- is TangemSdkError.CardWithMaxZeroWallets -> TangemSdkError.CardWithMaxZeroWallets()
- is TangemSdkError.AlreadyCreated -> TangemSdkError.AlreadyCreated()
- is TangemSdkError.MaxNumberOfWalletsCreated -> TangemSdkError.MaxNumberOfWalletsCreated()
- is TangemSdkError.PurgeWalletProhibited -> TangemSdkError.PurgeWalletProhibited()
- is TangemSdkError.AccessCodeCannotBeChanged -> TangemSdkError.AccessCodeCannotBeChanged()
- is TangemSdkError.PasscodeCannotBeChanged -> TangemSdkError.PasscodeCannotBeChanged()
- is TangemSdkError.AccessCodeCannotBeDefault -> TangemSdkError.AccessCodeCannotBeDefault()
- is TangemSdkError.NoRemainingSignatures -> TangemSdkError.NoRemainingSignatures()
- is TangemSdkError.EmptyHashes -> TangemSdkError.EmptyHashes()
- is TangemSdkError.HashSizeMustBeEqual -> TangemSdkError.HashSizeMustBeEqual()
- is TangemSdkError.WalletIsNotCreated -> TangemSdkError.WalletIsNotCreated()
- is TangemSdkError.SignHashesNotAvailable -> TangemSdkError.SignHashesNotAvailable()
- is TangemSdkError.TooManyHashesInOneTransaction -> TangemSdkError.TooManyHashesInOneTransaction()
- is TangemSdkError.ExtendedDataSizeTooLarge -> TangemSdkError.ExtendedDataSizeTooLarge()
- is TangemSdkError.NotPersonalized -> TangemSdkError.NotPersonalized()
- is TangemSdkError.NotActivated -> TangemSdkError.NotActivated()
- is TangemSdkError.WalletIsPurged -> TangemSdkError.WalletIsPurged()
- is TangemSdkError.PasscodeRequired -> TangemSdkError.PasscodeRequired()
- is TangemSdkError.VerificationFailed -> TangemSdkError.VerificationFailed()
- is TangemSdkError.DataSizeTooLarge -> TangemSdkError.DataSizeTooLarge()
- is TangemSdkError.MissingCounter -> TangemSdkError.MissingCounter()
- is TangemSdkError.OverwritingDataIsProhibited -> TangemSdkError.OverwritingDataIsProhibited()
- is TangemSdkError.DataCannotBeWritten -> TangemSdkError.DataCannotBeWritten()
- is TangemSdkError.MissingIssuerPubicKey -> TangemSdkError.MissingIssuerPubicKey()
- is TangemSdkError.CardVerificationFailed -> TangemSdkError.CardVerificationFailed()
- is TangemSdkError.WrongAccessCode -> TangemSdkError.WrongAccessCode()
- is TangemSdkError.WrongPasscode -> TangemSdkError.WrongPasscode()
- is TangemSdkError.UnknownError -> TangemSdkError.UnknownError()
- is TangemSdkError.UserCancelled -> TangemSdkError.UserCancelled()
- is TangemSdkError.Busy -> TangemSdkError.Busy()
- is TangemSdkError.MissingPreflightRead -> TangemSdkError.MissingPreflightRead()
- is TangemSdkError.WrongCardNumber -> TangemSdkError.WrongCardNumber()
- is TangemSdkError.WrongCardType -> TangemSdkError.WrongCardType(null)
- is TangemSdkError.CardError -> TangemSdkError.CardError()
- is TangemSdkError.NotSupportedFirmwareVersion -> TangemSdkError.NotSupportedFirmwareVersion()
- is TangemSdkError.WalletError -> TangemSdkError.WalletError()
- is TangemSdkError.WalletCannotBeCreated -> TangemSdkError.WalletCannotBeCreated()
- is TangemSdkError.UnsupportedCurve -> TangemSdkError.UnsupportedCurve()
- is TangemSdkError.UnsupportedWalletConfig -> TangemSdkError.UnsupportedWalletConfig()
- is TangemSdkError.CryptoUtilsError -> TangemSdkError.CryptoUtilsError(error.customMessage)
- is TangemSdkError.NetworkError -> TangemSdkError.NetworkError(error.customMessage)
- is TangemSdkError.ExceptionError -> TangemSdkError.ExceptionError(error.cause)
- is TangemSdkError.TooMuchBackupCards -> TangemSdkError.TooMuchBackupCards()
- is TangemSdkError.BackupCardRequired -> TangemSdkError.BackupCardRequired()
- is TangemSdkError.CertificateSignatureRequired -> TangemSdkError.CertificateSignatureRequired()
- is TangemSdkError.AccessCodeOrPasscodeRequired -> TangemSdkError.AccessCodeOrPasscodeRequired()
- is TangemSdkError.ResetPinNoCardsToReset -> TangemSdkError.ResetPinNoCardsToReset()
- is TangemSdkError.ResetPinWrongCard -> TangemSdkError.ResetPinWrongCard()
- is TangemSdkError.BackupFailedCardNotLinked -> TangemSdkError.BackupFailedCardNotLinked()
- is TangemSdkError.BackupNotAllowed -> TangemSdkError.BackupNotAllowed()
- is TangemSdkError.BackupCardAlreadyAdded -> TangemSdkError.BackupCardAlreadyAdded()
- is TangemSdkError.MissingPrimaryCard -> TangemSdkError.MissingPrimaryCard()
- is TangemSdkError.MissingPrimaryAttestSignature -> TangemSdkError.MissingPrimaryAttestSignature()
- is TangemSdkError.NoBackupDataForCard -> TangemSdkError.NoBackupDataForCard()
- is TangemSdkError.BackupFailedEmptyWallets -> TangemSdkError.BackupFailedEmptyWallets()
- is TangemSdkError.BackupFailedNotEmptyWallets -> TangemSdkError.BackupFailedNotEmptyWallets()
- is TangemSdkError.NoActiveBackup -> TangemSdkError.NoActiveBackup()
- is TangemSdkError.ResetBackupFailedHasBackupedWallets ->
- TangemSdkError.ResetBackupFailedHasBackupedWallets()
- is TangemSdkError.BackupServiceInvalidState -> TangemSdkError.BackupServiceInvalidState()
- is TangemSdkError.NoBackupCardForIndex -> TangemSdkError.NoBackupCardForIndex()
- is TangemSdkError.EmptyBackupCards -> TangemSdkError.EmptyBackupCards()
- is TangemSdkError.BackupFailedWrongIssuer -> TangemSdkError.BackupFailedWrongIssuer()
- is TangemSdkError.BackupFailedHDWalletSettings -> TangemSdkError.BackupFailedHDWalletSettings()
- is TangemSdkError.BackupFailedNotEnoughCurves -> TangemSdkError.BackupFailedNotEnoughCurves()
- is TangemSdkError.BackupFailedNotEnoughWallets -> TangemSdkError.BackupFailedNotEnoughWallets()
- is TangemSdkError.FileSettingsUnsupported -> TangemSdkError.FileSettingsUnsupported()
- is TangemSdkError.FilesIsEmpty -> TangemSdkError.FilesIsEmpty()
- is TangemSdkError.FilesDisabled -> TangemSdkError.FilesDisabled()
- is TangemSdkError.HDWalletDisabled -> TangemSdkError.HDWalletDisabled()
- is TangemSdkError.WrongInteractionMode -> TangemSdkError.WrongInteractionMode()
- is TangemSdkError.IssuerSignatureLoadingFailed -> TangemSdkError.IssuerSignatureLoadingFailed()
- is TangemSdkError.BackupFailedFirmware -> TangemSdkError.BackupFailedFirmware()
- is TangemSdkError.UserForgotTheCode -> TangemSdkError.UserForgotTheCode()
- is TangemSdkError.BackupFailedIncompatibleBatch -> TangemSdkError.BackupFailedIncompatibleBatch()
- is TangemSdkError.BiometricsUnavailable -> error
- is TangemSdkError.BiometricsAuthenticationFailed -> error
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/api/AnalyticsHandlerBuilder.kt b/app/src/main/java/com/tangem/tap/common/analytics/api/AnalyticsHandlerBuilder.kt
index 6d23925143..742a2178bc 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/api/AnalyticsHandlerBuilder.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/api/AnalyticsHandlerBuilder.kt
@@ -3,15 +3,15 @@ package com.tangem.tap.common.analytics.api
import android.app.Application
import com.tangem.common.json.MoshiJsonConverter
import com.tangem.core.analytics.api.AnalyticsHandler
+import com.tangem.datasource.local.config.environment.EnvironmentConfig
import com.tangem.domain.common.AnalyticsHandlersLogConfig
-import com.tangem.tap.domain.configurable.config.Config
interface AnalyticsHandlerBuilder {
fun build(data: Data): AnalyticsHandler?
data class Data(
val application: Application,
- val config: Config,
+ val config: EnvironmentConfig,
val isDebug: Boolean,
val logConfig: AnalyticsHandlersLogConfig,
val jsonConverter: MoshiJsonConverter,
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/converters/AnalyticsErrorConverter.kt b/app/src/main/java/com/tangem/tap/common/analytics/converters/AnalyticsErrorConverter.kt
index b6fab47d07..4f32eee854 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/converters/AnalyticsErrorConverter.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/converters/AnalyticsErrorConverter.kt
@@ -1,10 +1,10 @@
package com.tangem.tap.common.analytics.converters
import com.tangem.blockchain.common.BlockchainSdkError
-import com.tangem.common.Converter
import com.tangem.common.core.TangemSdkError
+import com.tangem.domain.demo.DemoTransactionSender
import com.tangem.tap.common.analytics.events.AnalyticsParam
-import com.tangem.tap.features.demo.DemoTransactionSender
+import com.tangem.utils.converter.Converter
/**
[REDACTED_AUTHOR]
@@ -31,8 +31,8 @@ private class ThrowableErrorConverter : Converter
override fun convert(value: Throwable): Map {
val unknown = "unknown"
return mapOf(
- AnalyticsParam.ErrorKey to AnalyticsParam.Error.App.value,
- AnalyticsParam.ErrorDescription to (value.message ?: value.cause?.message ?: unknown),
+ AnalyticsParam.ERROR_KEY to AnalyticsParam.Error.App.value,
+ AnalyticsParam.ERROR_DESCRIPTION to (value.message ?: value.cause?.message ?: unknown),
)
}
}
@@ -43,9 +43,9 @@ class CardSdkErrorConverter : Converter> {
if (value is TangemSdkError.UserCancelled) return emptyMap()
return mapOf(
- AnalyticsParam.ErrorKey to AnalyticsParam.Error.CardSdk.value,
- AnalyticsParam.ErrorCode to value.code.toString(),
- AnalyticsParam.ErrorDescription to value.toString(),
+ AnalyticsParam.ERROR_KEY to AnalyticsParam.Error.CardSdk.value,
+ AnalyticsParam.ERROR_CODE to value.code.toString(),
+ AnalyticsParam.ERROR_DESCRIPTION to value.toString(),
)
}
}
@@ -62,9 +62,9 @@ private class BlockchainSdkErrorConverter(
}
return mapOf(
- AnalyticsParam.ErrorKey to AnalyticsParam.Error.BlockchainSdk.value,
- AnalyticsParam.ErrorCode to value.code.toString(),
- AnalyticsParam.ErrorDescription to "${value.javaClass.simpleName}: ${value.customMessage}",
+ AnalyticsParam.ERROR_KEY to AnalyticsParam.Error.BlockchainSdk.value,
+ AnalyticsParam.ERROR_CODE to value.code.toString(),
+ AnalyticsParam.ERROR_DESCRIPTION to "${value.javaClass.simpleName}: ${value.customMessage}",
)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/converters/BasicEventConverter.kt b/app/src/main/java/com/tangem/tap/common/analytics/converters/BasicEventConverter.kt
deleted file mode 100644
index 1f227fc391..0000000000
--- a/app/src/main/java/com/tangem/tap/common/analytics/converters/BasicEventConverter.kt
+++ /dev/null
@@ -1,160 +0,0 @@
-package com.tangem.tap.common.analytics.converters
-
-import com.tangem.common.Converter
-import com.tangem.common.extensions.isZero
-import com.tangem.core.analytics.Analytics
-import com.tangem.domain.common.ScanResponse
-import com.tangem.tap.common.analytics.events.AnalyticsParam
-import com.tangem.tap.common.analytics.events.Basic
-import com.tangem.tap.common.analytics.filters.BasicTopUpFilter
-import com.tangem.tap.domain.model.WalletDataModel
-import com.tangem.tap.domain.model.builders.UserWalletIdBuilder
-import com.tangem.tap.features.wallet.redux.ProgressState
-import com.tangem.tap.features.wallet.redux.WalletState
-import com.tangem.tap.features.wallet.redux.reducers.calculateTotalCryptoAmount
-import timber.log.Timber
-import java.math.BigDecimal
-
-/**
-[REDACTED_AUTHOR]
- */
-class BasicEventsPreChecker {
-
- fun tryToSend(converterData: BasicEventsSourceData) {
- if (!isReadyToSend(converterData)) return
-
- BasicSignInEventConverter().convert(converterData)?.let { Analytics.send(it) }
- BasicTopUpEventConverter().convert(converterData)?.let { Analytics.send(it) }
- }
-
- @Suppress("ComplexMethod")
- private fun isReadyToSend(data: BasicEventsSourceData): Boolean {
- val (scanResponse, walletState, biometricsWalletDataModels) = data
- if (walletState.derivationsCheckIsScheduled) {
- Timber.d("FAILED: derivationsCheckIsScheduled")
- return false
- }
- if (scanResponse.cardTypesResolver.isMultiwalletAllowed() && walletState.missingDerivations.isNotEmpty()) {
- Timber.d("FAILED: isMultiwalletAllowed || missingDerivations.isNotEmpty")
- return false
- }
-
- if (biometricsWalletDataModels == null) {
- Timber.d("SWITCH: OLD")
- val walletsDataFromStores = data.walletState.walletsDataFromStores
- if (walletsDataFromStores.isEmpty()) {
- Timber.d("FAILED: walletsDataFromStores.isEmpty")
- return false
- }
-
- val totalBalanceState = data.walletState.totalBalance?.state
- if (totalBalanceState == null || totalBalanceState == ProgressState.Loading ||
- totalBalanceState == ProgressState.Refreshing
- ) {
- Timber.d("FAILED: totalBalanceState: ${totalBalanceState?.name}")
- return false
- }
-
- val balancesCount = walletsDataFromStores
- .map { if (it.currencyData.amount == null) 0 else 1 }
- .reduce { acc, i -> acc + i }
-
- if (balancesCount != walletsDataFromStores.size) {
- Timber.d("FAILED: balancesCount != walletsDataFromStores.size")
- return false
- }
- } else {
- Timber.d("SWITCH: BIOMETRICS")
- if (biometricsWalletDataModels.isEmpty()) {
- Timber.d("FAILED: biometricsWalletDataModels.isEmpty")
- return false
- }
-
- val isCorrectStatus = biometricsWalletDataModels.any {
- it.status is WalletDataModel.Loading ||
- it.status is WalletDataModel.NoAccount ||
- it.status is WalletDataModel.Unreachable ||
- it.status is WalletDataModel.MissedDerivation ||
- it.status.isErrorStatus
- }
- if (isCorrectStatus) {
- Timber.d("FAILED: by status")
- return false
- }
- }
-
- Timber.d("SUCCESS")
- return true
- }
-}
-
-/**
- * With biometrics enabled, we should check its storage instead of "WalletState.walletsDataFromStores"
- * because the latter is updated after some time.
- * @property biometricsWalletDataModels - wallet data models from the 'WalletStoresManager'. If null, then
- * the "WalletState.walletsDataFromStores" will be used to determine appropriate state
- */
-data class BasicEventsSourceData(
- val scanResponse: ScanResponse,
- val walletState: WalletState,
- val biometricsWalletDataModels: List?,
-) {
- val batchId: String by lazy { scanResponse.card.batchId }
-
- val userWalletIdStringValue: String? by lazy {
- UserWalletIdBuilder.scanResponse(scanResponse)
- .build()
- ?.stringValue
- }
-
- val paramCardCurrency: AnalyticsParam.CardCurrency? by lazy {
- ParamCardCurrencyConverter().convert(scanResponse.cardTypesResolver)
- }
-
- val paramCardBalanceState: AnalyticsParam.CardBalanceState by lazy { calculateAmount().toCardBalanceState() }
-
- private fun calculateAmount(): BigDecimal {
- return biometricsWalletDataModels?.calculateTotalCryptoAmount()
- ?: walletState.walletsDataFromStores.calculateTotalCryptoAmount()
- }
-
- private fun BigDecimal.toCardBalanceState(): AnalyticsParam.CardBalanceState = when {
- isZero() -> AnalyticsParam.CardBalanceState.Empty
- else -> AnalyticsParam.CardBalanceState.Full
- }
-
- private fun List.calculateTotalCryptoAmount(): BigDecimal {
- return this
- .map { it.status.amount }
- .reduce(BigDecimal::plus)
- }
-}
-
-class BasicSignInEventConverter : Converter {
-
- override fun convert(value: BasicEventsSourceData): Basic.SignedIn? {
- if (value.paramCardCurrency == null || value.userWalletIdStringValue == null) return null
-
- return Basic.SignedIn(
- state = value.paramCardBalanceState,
- currency = value.paramCardCurrency!!,
- batch = value.batchId,
- ).apply {
- filterData = value.userWalletIdStringValue
- }
- }
-}
-
-class BasicTopUpEventConverter : Converter {
-
- override fun convert(value: BasicEventsSourceData): Basic.ToppedUp? {
- if (value.paramCardCurrency == null || value.userWalletIdStringValue == null) return null
-
- val data = BasicTopUpFilter.Data(
- walletId = value.userWalletIdStringValue!!,
- cardBalanceState = value.paramCardBalanceState,
- )
-
- return Basic.ToppedUp(value.paramCardCurrency!!).apply { filterData = data }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/converters/ParamCardCurrencyConverter.kt b/app/src/main/java/com/tangem/tap/common/analytics/converters/ParamCardCurrencyConverter.kt
index 61d71c5a14..303dcf3b25 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/converters/ParamCardCurrencyConverter.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/converters/ParamCardCurrencyConverter.kt
@@ -1,28 +1,27 @@
package com.tangem.tap.common.analytics.converters
import com.tangem.blockchain.common.Blockchain
-import com.tangem.common.Converter
import com.tangem.domain.common.CardTypesResolver
-import com.tangem.domain.common.SaltPayWorkaround
import com.tangem.tap.common.analytics.events.AnalyticsParam
+import com.tangem.utils.converter.Converter
+import com.tangem.core.analytics.models.AnalyticsParam as CoreAnalyticsParam
/**
[REDACTED_AUTHOR]
*/
-class ParamCardCurrencyConverter : Converter {
+class ParamCardCurrencyConverter : Converter {
- override fun convert(value: CardTypesResolver): AnalyticsParam.CardCurrency? {
- if (value.isMultiwalletAllowed()) return AnalyticsParam.CardCurrency.MultiCurrency
+ override fun convert(value: CardTypesResolver): CoreAnalyticsParam.WalletType? {
+ if (value.isMultiwalletAllowed()) return CoreAnalyticsParam.WalletType.MultiCurrency
val type = when {
value.isTangemNote() -> AnalyticsParam.CurrencyType.Blockchain(value.getBlockchain())
value.isTangemTwins() -> AnalyticsParam.CurrencyType.Blockchain(Blockchain.Bitcoin)
- value.isSaltPay() -> AnalyticsParam.CurrencyType.Token(SaltPayWorkaround.tokenFrom(Blockchain.SaltPay))
value.getBlockchain() != Blockchain.Unknown -> AnalyticsParam.CurrencyType.Blockchain(value.getBlockchain())
value.getPrimaryToken() != null -> AnalyticsParam.CurrencyType.Token(value.getPrimaryToken()!!)
else -> null
} ?: return null
- return AnalyticsParam.CardCurrency.SingleCurrency(type)
+ return CoreAnalyticsParam.WalletType.SingleCurrency(type.value)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/converters/ShopOrderToEventConverter.kt b/app/src/main/java/com/tangem/tap/common/analytics/converters/ShopOrderToEventConverter.kt
deleted file mode 100644
index 5d779e661f..0000000000
--- a/app/src/main/java/com/tangem/tap/common/analytics/converters/ShopOrderToEventConverter.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.tangem.tap.common.analytics.converters
-
-import com.shopify.buy3.Storefront
-import com.tangem.common.Converter
-import com.tangem.tap.common.analytics.events.Shop
-import com.tangem.tap.common.shop.data.ProductType
-
-/**
-[REDACTED_AUTHOR]
- */
-class ShopOrderToEventConverter : Converter, Shop.Purchased> {
-
- override fun convert(value: Pair): Shop.Purchased {
- val checkout = value.first
- val productType = value.second
-
- val sku = checkout.lineItems?.edges?.firstOrNull()?.node?.variant?.sku ?: productType.sku
- val count = when (productType) {
- ProductType.WALLET_2_CARDS -> "2"
- ProductType.WALLET_3_CARDS -> "3"
- }
- val amount = "${checkout.totalPriceV2.amount} ${checkout.totalPriceV2.currencyCode.name}"
- val code = (checkout.discountApplications.edges.firstOrNull()?.node as? Storefront.DiscountCodeApplication)
- ?.code
-
- return Shop.Purchased(sku, count, amount, code)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/AnalyticsParam.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/AnalyticsParam.kt
index 2e5a925560..8cfba8dd64 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/events/AnalyticsParam.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/events/AnalyticsParam.kt
@@ -1,52 +1,47 @@
package com.tangem.tap.common.analytics.events
+import com.tangem.domain.apptheme.model.AppThemeMode
import com.tangem.tap.features.details.redux.SecurityOption
sealed class AnalyticsParam {
sealed class CurrencyType(val value: String) {
- class Currency(currency: com.tangem.tap.features.wallet.models.Currency) : CurrencyType(currency.currencySymbol)
+ class Currency(currency: com.tangem.tap.domain.model.Currency) : CurrencyType(currency.currencySymbol)
class Blockchain(blockchain: com.tangem.blockchain.common.Blockchain) : CurrencyType(blockchain.currency)
class Token(token: com.tangem.blockchain.common.Token) : CurrencyType(token.symbol)
- class FiatCurrency(
- fiatCurrency: com.tangem.tap.common.entities.FiatCurrency,
- ) : CurrencyType(fiatCurrency.symbol)
-
class Amount(amount: com.tangem.blockchain.common.Amount) : CurrencyType(amount.currencySymbol)
}
- // MultiCurrency or CurrencyType
- sealed class CardCurrency(val value: String) {
- object MultiCurrency : CardCurrency("Multicurrency")
- class SingleCurrency(type: CurrencyType) : CardCurrency(type.value)
- }
-
sealed class CardBalanceState(val value: String) {
- object Empty : CardBalanceState("Empty")
- object Full : CardBalanceState("Full")
+ data object Empty : CardBalanceState("Empty")
+ data object Full : CardBalanceState("Full")
companion object
}
sealed class RateApp(val value: String) {
- object Liked : RateApp("Liked")
- object Disliked : RateApp("Disliked")
- object Closed : RateApp("Close")
+ data object Liked : RateApp("Liked")
+ data object Closed : RateApp("Close")
}
sealed class OnOffState(val value: String) {
- object On : OnOffState("On")
- object Off : OnOffState("Off")
+
+ data object On : OnOffState("On")
+ data object Off : OnOffState("Off")
+
+ companion object {
+
+ operator fun invoke(value: Boolean): OnOffState = if (value) On else Off
+ }
}
sealed class UserCode(val value: String) {
- object AccessCode : UserCode("Access Code")
- object Passcode : UserCode("Passcode")
+ data object AccessCode : UserCode("Access Code")
}
sealed class SecurityMode(val value: String) {
- object AccessCode : SecurityMode("Access Code")
- object Passcode : SecurityMode("Passcode")
- object LongTap : SecurityMode("Long Tap")
+ data object AccessCode : SecurityMode("Access Code")
+ data object Passcode : SecurityMode("Passcode")
+ data object LongTap : SecurityMode("Long Tap")
companion object {
fun from(option: SecurityOption): SecurityMode = when (option) {
@@ -57,16 +52,70 @@ sealed class AnalyticsParam {
}
}
+ sealed class AccessCodeRecoveryStatus(val value: String) {
+
+ val key: String = "Status"
+
+ data object Enabled : AccessCodeRecoveryStatus("Enabled")
+ data object Disabled : AccessCodeRecoveryStatus("Disabled")
+
+ companion object {
+ fun from(enabled: Boolean): AccessCodeRecoveryStatus {
+ return if (enabled) Enabled else Disabled
+ }
+ }
+ }
+
sealed class Error(val value: String) {
- object App : Error("App Error")
- object CardSdk : Error("Card Sdk Error")
- object BlockchainSdk : Error("Blockchain Sdk Error")
+ data object App : Error("App Error")
+ data object CardSdk : Error("Card Sdk Error")
+ data object BlockchainSdk : Error("Blockchain Sdk Error")
+ }
+
+ sealed class WalletCreationType(val value: String) {
+ data object PrivateKey : WalletCreationType(value = "Private Key")
+ data object NewSeed : WalletCreationType(value = "New Seed")
+ data object SeedImport : WalletCreationType(value = "Seed Import")
+ }
+
+ sealed class AppTheme(val value: String) {
+ data object System : AppTheme("System")
+ data object Dark : AppTheme("Dark")
+ data object Light : AppTheme("Light")
+
+ companion object {
+ fun fromAppThemeMode(mode: AppThemeMode): AppTheme {
+ return when (mode) {
+ AppThemeMode.FORCE_DARK -> Dark
+ AppThemeMode.FORCE_LIGHT -> Light
+ AppThemeMode.FOLLOW_SYSTEM -> System
+ }
+ }
+ }
}
companion object Key {
- const val BatchId = "Batch"
- const val ErrorDescription = "Error Description"
- const val ErrorCode = "Error Code"
- const val ErrorKey = "Error Key"
+ const val BLOCKCHAIN = "blockchain"
+ const val TOKEN = "Token"
+ const val SOURCE = "Source"
+ const val BALANCE = "Balance"
+ const val BATCH = "Batch"
+ const val FEE_TYPE = "Fee Type"
+ const val PERMISSION_TYPE = "Permission Type"
+ const val PRODUCT_TYPE = "Product Type"
+ const val FIRMWARE = "Firmware"
+ const val USER_WALLET_ID = "User Wallet ID"
+ const val CURRENCY = "Currency"
+ const val ERROR_DESCRIPTION = "Error Description"
+ const val ERROR_CODE = "Error Code"
+ const val ERROR_KEY = "Error Key"
+ const val CREATION_TYPE = "Creation Type"
+ const val SEED_PHRASE_LENGTH = "Seed Phrase Length"
+ const val DAPP_NAME = "DApp Name"
+ const val DAPP_URL = "DApp Url"
+ const val METHOD_NAME = "Method Name"
+ const val VALIDATION = "Validation"
+ const val BLOCKCHAIN_EXCEPTION_HOST = "exception_host"
+ const val BLOCKCHAIN_SELECTED_HOST = "selected_host"
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/Basic.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/Basic.kt
deleted file mode 100644
index 0d9a529469..0000000000
--- a/app/src/main/java/com/tangem/tap/common/analytics/events/Basic.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.tangem.tap.common.analytics.events
-
-import com.tangem.core.analytics.AnalyticsEvent
-
-/**
-[REDACTED_AUTHOR]
- */
-sealed class Basic(
- event: String,
- params: Map = mapOf(),
- error: Throwable? = null,
-) : AnalyticsEvent("Basic", event, params, error) {
-
- class SignedIn(
- state: AnalyticsParam.CardBalanceState,
- currency: AnalyticsParam.CardCurrency,
- batch: String,
- ) : Basic(
- event = "Signed in",
- params = mapOf(
- "State" to state.value,
- "Currency" to currency.value,
- AnalyticsParam.BatchId to batch,
- ),
- )
-
- class ToppedUp(currency: AnalyticsParam.CardCurrency) : Basic(
- event = "Topped up",
- params = mapOf("Currency" to currency.value),
- )
-
- class ScanError(error: Throwable) : Basic(
- event = "Scan",
- error = error,
- )
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/BlockchainExceptionEvent.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/BlockchainExceptionEvent.kt
new file mode 100644
index 0000000000..385ab3e517
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/analytics/events/BlockchainExceptionEvent.kt
@@ -0,0 +1,17 @@
+package com.tangem.tap.common.analytics.events
+
+import com.tangem.core.analytics.models.AnalyticsEvent
+
+class BlockchainExceptionEvent(
+ selectedHost: String,
+ exceptionHost: String,
+ error: String,
+) : AnalyticsEvent(
+ category = "BlockchainSdk",
+ event = "Exception",
+ params = mapOf(
+ AnalyticsParam.BLOCKCHAIN_SELECTED_HOST to selectedHost,
+ AnalyticsParam.BLOCKCHAIN_EXCEPTION_HOST to exceptionHost,
+ AnalyticsParam.ERROR_DESCRIPTION to error,
+ ),
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/Chat.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/Chat.kt
index 96fa307105..f4b9dbc61f 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/events/Chat.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/events/Chat.kt
@@ -1,6 +1,6 @@
package com.tangem.tap.common.analytics.events
-import com.tangem.core.analytics.AnalyticsEvent
+import com.tangem.core.analytics.models.AnalyticsEvent
/**
[REDACTED_AUTHOR]
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/DetailsScreen.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/DetailsScreen.kt
index a0d34306c9..775f44a0d8 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/events/DetailsScreen.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/events/DetailsScreen.kt
@@ -1,6 +1,6 @@
package com.tangem.tap.common.analytics.events
-import com.tangem.core.analytics.AnalyticsEvent
+import com.tangem.core.analytics.models.AnalyticsEvent
/**
[REDACTED_AUTHOR]
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/IntroductionProcess.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/IntroductionProcess.kt
index 0d799d379f..b5ce0042ae 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/events/IntroductionProcess.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/events/IntroductionProcess.kt
@@ -1,6 +1,6 @@
package com.tangem.tap.common.analytics.events
-import com.tangem.core.analytics.AnalyticsEvent
+import com.tangem.core.analytics.models.AnalyticsEvent
/**
[REDACTED_AUTHOR]
@@ -14,6 +14,5 @@ sealed class IntroductionProcess(
class ButtonTokensList : IntroductionProcess("Button - Tokens List")
class ButtonBuyCards : IntroductionProcess("Button - Buy Cards")
class ButtonScanCard : IntroductionProcess("Button - Scan Card")
- class CardWasScanned : IntroductionProcess("Card Was Scanned")
class ButtonRequestSupport : IntroductionProcess("Button - Request Support")
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/MainScreen.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/MainScreen.kt
deleted file mode 100644
index 6f718755f0..0000000000
--- a/app/src/main/java/com/tangem/tap/common/analytics/events/MainScreen.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.tangem.tap.common.analytics.events
-
-import com.tangem.core.analytics.AnalyticsEvent
-
-/**
-[REDACTED_AUTHOR]
- */
-sealed class MainScreen(
- event: String,
- params: Map = mapOf(),
-) : AnalyticsEvent("Main Screen", event, params) {
-
- class ScreenOpened : MainScreen("Screen opened")
-
- class ButtonScanCard : MainScreen("Button - Scan Card")
- class CardWasScanned : MainScreen("Card Was Scanned")
- class ButtonMyWallets : MainScreen("Button - My Wallets")
-
- class EnableBiometrics(state: AnalyticsParam.OnOffState) : MainScreen(
- event = "Enable Biometric",
- params = mapOf("State" to state.value),
- )
-
- class MainCurrencyChanged(currencyType: AnalyticsParam.CurrencyType) : MainScreen(
- event = "Main Currency Changed",
- params = mapOf("Currency Type" to currencyType.value),
- )
-
- class NoticeRateAppButton(result: AnalyticsParam.RateApp) : MainScreen(
- event = "Notice - Rate The App Button Tapped",
- params = mapOf("Result" to result.value),
- )
-
- class NoticeBackupYourWalletTapped : MainScreen("Notice - Backup Your Wallet Tapped")
- class NoticeScanYourCardTapped : MainScreen("Notice - Scan Your Card Tapped")
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/ManageTokens.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/ManageTokens.kt
deleted file mode 100644
index 55ed5f97b9..0000000000
--- a/app/src/main/java/com/tangem/tap/common/analytics/events/ManageTokens.kt
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.tangem.tap.common.analytics.events
-
-import com.tangem.core.analytics.AnalyticsEvent
-import com.tangem.domain.common.extensions.toNetworkId
-import com.tangem.domain.features.addCustomToken.CustomCurrency
-import com.tangem.tap.common.extensions.filterNotNull
-
-/**
-[REDACTED_AUTHOR]
- */
-sealed class ManageTokens(
- event: String,
- params: Map = mapOf(),
-) : AnalyticsEvent("Manage Tokens", event, params) {
-
- class ScreenOpened : ManageTokens("Manage Tokens Screen Opened")
- class TokenSearched : ManageTokens("Token Searched")
-
- class TokenSwitcherChanged(
- type: AnalyticsParam.CurrencyType,
- state: AnalyticsParam.OnOffState,
- ) : ManageTokens(
- "Token Switcher Changed",
- params = mapOf(
- "Token" to type.value,
- "State" to state.value,
- ),
- )
-
- class ButtonSaveChanges : ManageTokens("Button - Save Changes")
- class ButtonCustomToken : ManageTokens("Button - Custom Token")
-
- sealed class CustomToken(
- event: String,
- params: Map = mapOf(),
- ) : ManageTokens(event, params) {
-
- class ScreenOpened : ManageTokens("Custom Token Screen Opened")
-
- class TokenWasAdded(customCurrency: CustomCurrency) : ManageTokens(
- event = "Custom Token Was Added",
- params = convertToParam(customCurrency),
- ) {
- companion object {
- private fun convertToParam(customCurrency: CustomCurrency): Map = with(customCurrency) {
- return when (this) {
- is CustomCurrency.CustomBlockchain -> mapOf(
- "Token" to network.currency,
- "Derivation Path" to derivationPath?.rawPath,
- ).filterNotNull()
- is CustomCurrency.CustomToken -> mapOf(
- "Token" to token.symbol,
- "Derivation Path" to derivationPath?.rawPath,
- "Network Id" to network.toNetworkId(),
- "Contract Address" to token.contractAddress,
- ).filterNotNull()
- }
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/MyWallets.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/MyWallets.kt
deleted file mode 100644
index 4db0526ad2..0000000000
--- a/app/src/main/java/com/tangem/tap/common/analytics/events/MyWallets.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.tangem.tap.common.analytics.events
-
-import com.tangem.core.analytics.AnalyticsEvent
-
-sealed class MyWallets(
- event: String,
- params: Map = mapOf(),
-) : AnalyticsEvent("My Wallets", event, params) {
-
- class MyWalletsScreenOpened : MyWallets(event = "My Wallets Screen Opened")
- class CardWasScanned : MyWallets(event = "Card Was Scanned")
-
- sealed class Button {
- class ScanNewCard : MyWallets(event = "Button - Scan New Card")
- class UnlockWithBiometrics : MyWallets(event = "Button - Unlock all with Face ID")
- class EditWalletTapped : MyWallets(event = "Button - Edit Wallet Tapped")
- class DeleteWalletTapped : MyWallets(event = "Button - Delete Wallet Tapped")
- class WalletUnlockTapped : MyWallets(event = "Button - Wallet Unlock Tapped")
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/Onboarding.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/Onboarding.kt
index 4ec37c4806..f35a636601 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/events/Onboarding.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/events/Onboarding.kt
@@ -1,6 +1,6 @@
package com.tangem.tap.common.analytics.events
-import com.tangem.core.analytics.AnalyticsEvent
+import com.tangem.core.analytics.models.AnalyticsEvent
/**
[REDACTED_AUTHOR]
@@ -21,7 +21,17 @@ sealed class Onboarding(
class ScreenOpened : CreateWallet("Create Wallet Screen Opened")
class ButtonCreateWallet : CreateWallet("Button - Create Wallet")
- class WalletCreatedSuccessfully : CreateWallet("Wallet Created Successfully")
+ class WalletCreatedSuccessfully(
+ creationType: AnalyticsParam.WalletCreationType = AnalyticsParam.WalletCreationType.PrivateKey,
+ seedPhraseLength: Int? = null,
+ ) : CreateWallet(
+ event = "Wallet Created Successfully",
+ params = buildMap {
+ put(AnalyticsParam.CREATION_TYPE, creationType.value)
+
+ if (seedPhraseLength != null) put(AnalyticsParam.SEED_PHRASE_LENGTH, seedPhraseLength.toString())
+ },
+ )
}
sealed class Backup(
@@ -40,6 +50,16 @@ sealed class Onboarding(
event = "Backup Finished",
params = mapOf("Cards count" to "$cardsCount"),
)
+
+ object ResetCancelEvent : Backup(
+ event = "Reset Card Notification",
+ params = mapOf("Option" to "Cancel"),
+ )
+
+ object ResetPerformEvent : Backup(
+ event = "Reset Card Notification",
+ params = mapOf("Option" to "Reset"),
+ )
}
sealed class Topup(
@@ -51,7 +71,7 @@ sealed class Onboarding(
class ButtonBuyCrypto(currency: AnalyticsParam.CurrencyType) : Topup(
event = "Button - Buy Crypto",
- params = mapOf("Currency" to currency.value),
+ params = mapOf(AnalyticsParam.CURRENCY to currency.value),
)
class ButtonShowWalletAddress : Topup("Button - Show the Wallet Address")
@@ -67,16 +87,6 @@ sealed class Onboarding(
class SetupFinished : Twins("Twin Setup Finished")
}
- class PinCodeSet : Onboarding("Onboarding", "PIN code set")
- class ButtonConnect : Onboarding("Onboarding", "Button - Connect")
- class KYCStarted : Onboarding("Onboarding", "KYC started")
- class KYCInProgress : Onboarding("Onboarding", "KYC in progress")
- class KYCRejected : Onboarding("Onboarding", "KYC rejected")
- class ClaimScreenOpened : Onboarding("Onboarding", "Claim screen opened")
- class ButtonClaim : Onboarding("Onboarding", "Button - Claim")
- class ClaimWasSuccessfully : Onboarding("Onboarding", "Claim was successfully")
- class ButtonChat : Onboarding("Onboarding", "Button - Chat")
-
class EnableBiometrics(state: AnalyticsParam.OnOffState) : Onboarding(
category = "Onboarding / Biometric",
event = "Enable Biometric",
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/Portfolio.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/Portfolio.kt
deleted file mode 100644
index 71383c9f9a..0000000000
--- a/app/src/main/java/com/tangem/tap/common/analytics/events/Portfolio.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.tangem.tap.common.analytics.events
-
-import com.tangem.core.analytics.AnalyticsEvent
-
-/**
-[REDACTED_AUTHOR]
- */
-
-sealed class Portfolio(
- event: String,
- params: Map = mapOf(),
-) : AnalyticsEvent("Portfolio", event, params) {
-
- class Refreshed : Portfolio("Refreshed")
- class ButtonManageTokens : Portfolio("Button - Manage Tokens")
- class TokenTapped : Portfolio("Token is Tapped")
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/Push.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/Push.kt
new file mode 100644
index 0000000000..46c647b06f
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/analytics/events/Push.kt
@@ -0,0 +1,13 @@
+package com.tangem.tap.common.analytics.events
+
+import com.tangem.core.analytics.models.AnalyticsEvent
+
+internal sealed class Push(event: String) : AnalyticsEvent(
+ category = "Push",
+ event = event,
+ params = emptyMap(),
+ error = null,
+) {
+
+ data object PushNotificationOpened : Push(event = "Push Notification Opened")
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/ScanFailsDialogAnalytics.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/ScanFailsDialogAnalytics.kt
new file mode 100644
index 0000000000..392f340405
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/analytics/events/ScanFailsDialogAnalytics.kt
@@ -0,0 +1,17 @@
+package com.tangem.tap.common.analytics.events
+
+import com.tangem.core.analytics.models.AnalyticsEvent
+import com.tangem.core.analytics.models.AnalyticsParam
+
+class ScanFailsDialogAnalytics(button: Buttons, source: AnalyticsParam.ScreensSources) : AnalyticsEvent(
+ category = "Cant Scan The Card",
+ event = button.event,
+ params = mapOf(
+ AnalyticsParam.SOURCE to source.value,
+ ),
+) {
+ enum class Buttons(val event: String) {
+ TRY_AGAIN("Try again button"),
+ HOW_TO_SCAN("Button blog"),
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/Settings.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/Settings.kt
index 03cbb88ac6..98b0289289 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/events/Settings.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/events/Settings.kt
@@ -1,7 +1,6 @@
package com.tangem.tap.common.analytics.events
-import com.tangem.core.analytics.AnalyticsEvent
-import com.tangem.tap.features.details.ui.details.SocialNetwork
+import com.tangem.core.analytics.models.AnalyticsEvent
/**
[REDACTED_AUTHOR]
@@ -14,19 +13,8 @@ sealed class Settings(
) : AnalyticsEvent(category, event, params, error) {
class ScreenOpened : Settings(event = "Settings Screen Opened")
- class ButtonChat : Settings(event = "Button - Chat")
- class ButtonSendFeedback : Settings(event = "Button - Send Feedback")
class ButtonStartWalletConnectSession : Settings(event = "Button - Start Wallet Connect Session")
class ButtonStopWalletConnectSession : Settings(event = "Button - Stop Wallet Connect Session")
- class ButtonCardSettings : Settings(event = "Button - Card Settings")
- class ButtonAppSettings : Settings(event = "Button - App Settings")
- class ButtonCreateBackup : Settings(event = "Button - Create Backup")
- class ButtonWalletConnect : Settings(event = "Button - Wallet Connect")
-
- class ButtonSocialNetwork(network: SocialNetwork) : Settings(
- event = "Button - Social Network",
- params = mapOf("Network" to network.id),
- )
sealed class CardSettings(
event: String,
@@ -35,11 +23,19 @@ sealed class Settings(
) : Settings("Settings / Card Settings", event, params, error) {
class ButtonFactoryReset : CardSettings("Button - Factory Reset")
- class FactoryResetFinished(error: Throwable? = null) : CardSettings(
+ class FactoryResetFinished(cardsCount: Int? = null, error: Throwable? = null) : CardSettings(
event = "Factory Reset Finished",
+ params = buildMap {
+ cardsCount?.let { put("Cards Count", "$it") }
+ },
error = error,
)
+ class FactoryResetCanceled(cardsCount: Int) : CardSettings(
+ event = "Factory Reset Canceled",
+ params = mapOf("Cards Count" to "$cardsCount"),
+ )
+
class UserCodeChanged : CardSettings("User Code Changed")
class ButtonChangeSecurityMode : CardSettings("Button - Change Security Mode")
@@ -53,23 +49,45 @@ sealed class Settings(
params = mapOf("Mode" to mode.value),
error = error,
)
+
+ class AccessCodeRecoveryChanged(status: AnalyticsParam.AccessCodeRecoveryStatus) : CardSettings(
+ event = "Access Code Recovery Changed",
+ params = mapOf(status.key to status.value),
+ )
}
sealed class AppSettings(
event: String,
params: Map = mapOf(),
- ) : Settings("Settings / App Settings", event, params) {
+ ) : Settings(category = "Settings / App Settings", event = event, params = params) {
- class SaveWalletSwitcherChanged(state: AnalyticsParam.OnOffState) : CardSettings(
+ class SaveWalletSwitcherChanged(state: AnalyticsParam.OnOffState) : AppSettings(
event = "Save Wallet Switcher Changed",
params = mapOf("State" to state.value),
)
- class SaveAccessCodeSwitcherChanged(state: AnalyticsParam.OnOffState) : CardSettings(
+ class SaveAccessCodeSwitcherChanged(state: AnalyticsParam.OnOffState) : AppSettings(
event = "Save Access Code Switcher Changed",
params = mapOf("State" to state.value),
)
- object ButtonEnableBiometricAuthentication : AppSettings("Button - Enable Biometric Authentication")
+ object ButtonEnableBiometricAuthentication : AppSettings(event = "Button - Enable Biometric Authentication")
+
+ class MainCurrencyChanged(currencyType: String) : AppSettings(
+ event = "Main Currency Changed",
+ params = mapOf("Currency Type" to currencyType),
+ )
+
+ class ThemeSwitched(theme: AnalyticsParam.AppTheme) : AppSettings(
+ event = "App Theme Switched",
+ params = mapOf("State" to theme.value),
+ )
+
+ object EnableBiometrics : AppSettings(event = "Notice - Enable Biometric")
+
+ class HideBalanceChanged(state: AnalyticsParam.OnOffState) : AppSettings(
+ event = "Hide Balance Changed",
+ params = mapOf("State" to state.value),
+ )
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/Shop.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/Shop.kt
index 0ab4dd9361..4076de8685 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/events/Shop.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/events/Shop.kt
@@ -1,6 +1,6 @@
package com.tangem.tap.common.analytics.events
-import com.tangem.core.analytics.AnalyticsEvent
+import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.tap.common.extensions.filterNotNull
/**
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/SignIn.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/SignIn.kt
index cad34430d9..212969481a 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/events/SignIn.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/events/SignIn.kt
@@ -1,6 +1,6 @@
package com.tangem.tap.common.analytics.events
-import com.tangem.core.analytics.AnalyticsEvent
+import com.tangem.core.analytics.models.AnalyticsEvent
/**
[REDACTED_AUTHOR]
@@ -11,8 +11,7 @@ sealed class SignIn(
error: Throwable? = null,
) : AnalyticsEvent("Sign In", event, params, error) {
- class ScreenOpened : SignIn(event = "Sing In Screen Opened")
- class CardWasScanned : SignIn(event = "Card Was Scanned")
+ class ScreenOpened : SignIn(event = "Sign In Screen Opened")
class ButtonBiometricSignIn : SignIn(event = "Button - Biometric Sign In")
class ButtonCardSignIn : SignIn(event = "Button - Card Sign In")
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/Token.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/Token.kt
index 0ad3ca514e..bf0bdc539a 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/events/Token.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/events/Token.kt
@@ -1,7 +1,7 @@
package com.tangem.tap.common.analytics.events
-import com.tangem.core.analytics.AnalyticsEvent
-import com.tangem.tap.common.analytics.events.AnalyticsParam.CurrencyType
+import com.tangem.core.analytics.models.AnalyticsEvent
+import com.tangem.core.analytics.models.AnalyticsParam.Key.TOKEN_PARAM
/**
[REDACTED_AUTHOR]
@@ -13,67 +13,21 @@ sealed class Token(
error: Throwable? = null,
) : AnalyticsEvent(category, event, params, error) {
- class Refreshed : Token("Token", "Refreshed")
- class ButtonExplore : Token("Token", "Button - Explore")
-
- class ButtonRemoveToken(type: CurrencyType) : Token(
- "Token",
- "Button - Remove Token",
- params = mapOf("Token" to type.value),
- )
-
- class ButtonBuy(type: CurrencyType) : Token(
- category = "Token",
- event = "Button - Buy",
- params = mapOf("Token" to type.value),
- )
-
- class ButtonSell(type: CurrencyType) : Token(
- category = "Token",
- event = "Button - Sell",
- params = mapOf("Token" to type.value),
- )
-
- class ButtonExchange(type: CurrencyType) : Token(
- category = "Token",
- event = "Button - Exchange",
- params = mapOf("Token" to type.value),
- )
-
- class ButtonSend(type: CurrencyType) : Token(
- category = "Token",
- event = "Button - Send",
- params = mapOf("Token" to type.value),
- )
-
sealed class Receive(
event: String,
params: Map = mapOf(),
) : Token("Token / Receive", event, params) {
- class ScreenOpened : Receive("Receive Screen Opened")
+ class ScreenOpened(
+ val token: String,
+ ) : Receive(
+ event = "Receive Screen Opened",
+ params = mapOf(TOKEN_PARAM to token),
+ )
class ButtonCopyAddress : Receive("Button - Copy Address")
class ButtonShareAddress : Receive("Button - Share Address")
}
- sealed class Send(
- event: String,
- params: Map = mapOf(),
- error: Throwable? = null,
- ) : Token("Token / Send", event, params, error) {
-
- class ScreenOpened : Send("Send Screen Opened")
- class ButtonPaste : Send("Button - Paste")
- class ButtonQRCode : Send("Button - QR Code")
- class ButtonSwapCurrency : Send("Button - Swap Currency")
-
- class TransactionSent(type: CurrencyType, error: Throwable? = null) : Send(
- event = "Transaction Sent",
- params = mapOf("Token" to type.value),
- error = error,
- )
- }
-
sealed class Topup(
event: String,
params: Map = mapOf(),
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/WalletConnect.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/WalletConnect.kt
index 9ce10213ac..d2870bbb6a 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/events/WalletConnect.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/events/WalletConnect.kt
@@ -1,21 +1,72 @@
package com.tangem.tap.common.analytics.events
-import com.tangem.core.analytics.AnalyticsEvent
+import com.tangem.core.analytics.models.AnalyticsEvent
/**
[REDACTED_AUTHOR]
*/
-sealed class WalletConnect(
+internal sealed class WalletConnect(
event: String,
params: Map = mapOf(),
error: Throwable? = null,
) : AnalyticsEvent("Wallet Connect", event, params, error) {
class ScreenOpened : WalletConnect(event = "WC Screen Opened")
- class NewSessionEstablished : WalletConnect("New Session Established")
- class SessionDisconnected : WalletConnect("Session Disconnected")
- class RequestSigned : WalletConnect("Request Signed")
+ class NewSessionEstablished(dAppName: String, dAppUrl: String, blockchainNames: List) : WalletConnect(
+ event = "New Session Established",
+ params = mapOf(
+ AnalyticsParam.DAPP_NAME to dAppName,
+ AnalyticsParam.DAPP_URL to dAppUrl,
+ AnalyticsParam.BLOCKCHAIN to blockchainNames.joinToString(","),
+ ),
+ )
- class SignError(error: Throwable) : WalletConnect("Sign", error = error)
- class TransactionError(error: Throwable) : WalletConnect("Transaction", error = error)
+ class SessionDisconnected(dAppName: String, dAppUrl: String) : WalletConnect(
+ event = "Session Disconnected",
+ params = mapOf(
+ AnalyticsParam.DAPP_NAME to dAppName,
+ AnalyticsParam.DAPP_URL to dAppUrl,
+ ),
+ )
+
+ class RequestHandled(
+ params: RequestHandledParams,
+ ) : WalletConnect(
+ event = "Request Handled",
+ params = params.toParamsMap(),
+ )
+
+ data class RequestHandledParams(
+ val dAppName: String,
+ val dAppUrl: String,
+ val methodName: String,
+ val blockchain: String,
+ val errorCode: String? = null,
+ val errorDescription: String? = null,
+ ) {
+ fun toParamsMap(): Map {
+ val validation = if (errorCode == null) Validation.SUCCESS.param else Validation.FAIL.param
+ val code = errorCode ?: SUCCESS_CODE
+ return buildMap {
+ put(AnalyticsParam.DAPP_NAME, dAppName)
+ put(AnalyticsParam.DAPP_URL, dAppUrl)
+ put(AnalyticsParam.METHOD_NAME, methodName)
+ put(AnalyticsParam.BLOCKCHAIN, blockchain)
+ put(AnalyticsParam.VALIDATION, validation)
+ put(AnalyticsParam.ERROR_CODE, code)
+ if (errorDescription != null) {
+ put(AnalyticsParam.ERROR_DESCRIPTION, errorDescription)
+ }
+ }
+ }
+ }
+
+ enum class Validation(val param: String) {
+ SUCCESS("Success"),
+ FAIL("Fail"),
+ }
+
+ private companion object {
+ const val SUCCESS_CODE = "0"
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/filters/BasicSignInFilter.kt b/app/src/main/java/com/tangem/tap/common/analytics/filters/BasicSignInFilter.kt
deleted file mode 100644
index 09c26d8d7d..0000000000
--- a/app/src/main/java/com/tangem/tap/common/analytics/filters/BasicSignInFilter.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.tangem.tap.common.analytics.filters
-
-import com.tangem.core.analytics.api.AnalyticsEventFilter
-import com.tangem.core.analytics.api.AnalyticsHandler
-import com.tangem.core.analytics.AnalyticsEvent
-import com.tangem.tap.common.analytics.events.Basic
-
-/**
-[REDACTED_AUTHOR]
- */
-class BasicSignInFilter : AnalyticsEventFilter {
-
- private val alreadySignedIn = mutableSetOf()
-
- override fun canBeAppliedTo(event: AnalyticsEvent): Boolean = event is Basic.SignedIn
-
- override fun canBeSent(event: AnalyticsEvent): Boolean {
- val userWalletId = event.filterData as? String ?: return false
-
- val canBeSent = !alreadySignedIn.contains(userWalletId)
- alreadySignedIn.add(userWalletId)
-
- return canBeSent
- }
-
- override fun canBeConsumedByHandler(handler: AnalyticsHandler, event: AnalyticsEvent): Boolean = true
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/filters/BasicTopUpFilter.kt b/app/src/main/java/com/tangem/tap/common/analytics/filters/BasicTopUpFilter.kt
deleted file mode 100644
index de89bf9e7e..0000000000
--- a/app/src/main/java/com/tangem/tap/common/analytics/filters/BasicTopUpFilter.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.tangem.tap.common.analytics.filters
-
-import com.tangem.common.extensions.guard
-import com.tangem.core.analytics.api.AnalyticsEventFilter
-import com.tangem.core.analytics.api.AnalyticsHandler
-import com.tangem.core.analytics.AnalyticsEvent
-import com.tangem.tap.common.analytics.events.AnalyticsParam
-import com.tangem.tap.common.analytics.events.Basic
-import com.tangem.tap.persistence.ToppedUpWalletStorage
-
-/**
-[REDACTED_AUTHOR]
- */
-class BasicTopUpFilter(
- private val topupWalletStorage: ToppedUpWalletStorage,
-) : AnalyticsEventFilter {
-
- override fun canBeAppliedTo(event: AnalyticsEvent): Boolean = event is Basic.ToppedUp
-
- override fun canBeSent(event: AnalyticsEvent): Boolean {
- val data = event.filterData as? Data ?: return false
-
- val walletInfo = topupWalletStorage.restore(data.walletId).guard {
- val newWalletInfo = Data(
- walletId = data.walletId,
- cardBalanceState = data.cardBalanceState,
- )
- topupWalletStorage.save(newWalletInfo)
- return false
- }
-
- if (walletInfo.isToppedUp) return false
-
- return if (!walletInfo.isToppedUp && data.isToppedUp) {
- topupWalletStorage.save(walletInfo.copy(cardBalanceState = AnalyticsParam.CardBalanceState.Full))
- true
- } else {
- false
- }
- }
-
- override fun canBeConsumedByHandler(handler: AnalyticsHandler, event: AnalyticsEvent): Boolean = true
-
- data class Data(
- val walletId: String,
- val cardBalanceState: AnalyticsParam.CardBalanceState,
- ) {
- val isToppedUp: Boolean = cardBalanceState == AnalyticsParam.CardBalanceState.Full
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/BlockchainExceptionHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/BlockchainExceptionHandler.kt
new file mode 100644
index 0000000000..b227a5f1f1
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/BlockchainExceptionHandler.kt
@@ -0,0 +1,20 @@
+package com.tangem.tap.common.analytics.handlers
+
+import com.tangem.blockchain.common.ExceptionHandlerOutput
+import com.tangem.core.analytics.api.AnalyticsEventHandler
+import com.tangem.tap.common.analytics.events.BlockchainExceptionEvent
+import javax.inject.Inject
+
+class BlockchainExceptionHandler @Inject constructor(
+ private val analyticsHandler: AnalyticsEventHandler,
+) : ExceptionHandlerOutput {
+ override fun handleApiSwitch(currentHost: String, nextHost: String, message: String) {
+ analyticsHandler.send(
+ BlockchainExceptionEvent(
+ selectedHost = nextHost,
+ exceptionHost = currentHost,
+ error = message,
+ ),
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeAnalyticsHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeAnalyticsHandler.kt
index a1daeb7ccf..2aa36c5413 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeAnalyticsHandler.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeAnalyticsHandler.kt
@@ -9,8 +9,8 @@ class AmplitudeAnalyticsHandler(
override fun id(): String = ID
- override fun send(event: String, params: Map) {
- client.logEvent(event, params)
+ override fun send(eventId: String, params: Map) {
+ client.logEvent(eventId, params)
}
companion object {
@@ -18,10 +18,14 @@ class AmplitudeAnalyticsHandler(
}
class Builder : AnalyticsHandlerBuilder {
- override fun build(data: AnalyticsHandlerBuilder.Data): AnalyticsHandler? = when {
- !data.isDebug -> AmplitudeClient(data.application, data.config.amplitudeApiKey)
- data.isDebug && data.logConfig.amplitude -> AmplitudeLogClient(data.jsonConverter)
- else -> null
- }?.let { AmplitudeAnalyticsHandler(it) }
+ override fun build(data: AnalyticsHandlerBuilder.Data): AnalyticsHandler {
+ return AmplitudeAnalyticsHandler(
+ client = if (data.logConfig.amplitude) {
+ AmplitudeLogClient(data.jsonConverter)
+ } else {
+ AmplitudeClient(data.application, data.config.amplitudeApiKey)
+ },
+ )
+ }
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeClient.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeClient.kt
index ddb27d18ff..74cec2eaf2 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeClient.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeClient.kt
@@ -3,8 +3,8 @@ package com.tangem.tap.common.analytics.handlers.amplitude
import android.app.Application
import com.amplitude.api.Amplitude
import com.amplitude.api.AmplitudeClient
-import com.tangem.common.Converter
import com.tangem.core.analytics.api.EventLogger
+import com.tangem.utils.converter.Converter
import org.json.JSONObject
/**
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerAnalyticsHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerAnalyticsHandler.kt
deleted file mode 100644
index d1b3189ab1..0000000000
--- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerAnalyticsHandler.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.tangem.tap.common.analytics.handlers.appsFlyer
-
-import com.appsflyer.AFInAppEventType
-import com.tangem.core.analytics.AnalyticsEvent
-import com.tangem.core.analytics.api.AnalyticsHandler
-import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
-import com.tangem.tap.common.analytics.events.Shop
-
-class AppsFlyerAnalyticsHandler(
- private val client: AppsFlyerAnalyticsClient,
-) : AnalyticsHandler {
-
- override fun id(): String = ID
-
- override fun send(event: String, params: Map) {
- client.logEvent(event, params)
- }
-
- override fun send(event: AnalyticsEvent) {
- if (event is Shop.Purchased) {
- send(AFInAppEventType.PURCHASE, event.params)
- } else {
- super.send(event)
- }
- }
-
- companion object {
- const val ID = "AppsFlyer"
- }
-
- class Builder : AnalyticsHandlerBuilder {
- override fun build(data: AnalyticsHandlerBuilder.Data): AnalyticsHandler? = when {
- !data.isDebug -> AppsFlyerClient(data.application, data.config.appsFlyerDevKey)
- data.isDebug && data.logConfig.appsFlyer -> AppsFlyerLogClient(data.jsonConverter)
- else -> null
- }?.let { AppsFlyerAnalyticsHandler(it) }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerClient.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerClient.kt
deleted file mode 100644
index 40cee4e698..0000000000
--- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerClient.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.tangem.tap.common.analytics.handlers.appsFlyer
-
-import android.content.Context
-import com.appsflyer.AppsFlyerLib
-import com.tangem.core.analytics.api.EventLogger
-
-/**
-[REDACTED_AUTHOR]
- */
-interface AppsFlyerAnalyticsClient : EventLogger
-
-internal class AppsFlyerClient(
- private val context: Context,
- key: String,
-) : AppsFlyerAnalyticsClient {
-
- private val appsFlyerLib: AppsFlyerLib = AppsFlyerLib.getInstance()
-
- init {
- appsFlyerLib.init(key, null, context)
- appsFlyerLib.start(context)
- }
-
- override fun logEvent(event: String, params: Map) {
- appsFlyerLib.logEvent(context, event, params)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerLogClient.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerLogClient.kt
deleted file mode 100644
index 8e87061b2c..0000000000
--- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerLogClient.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.tangem.tap.common.analytics.handlers.appsFlyer
-
-import com.tangem.common.json.MoshiJsonConverter
-import com.tangem.tap.common.analytics.AnalyticsEventsLogger
-
-/**
-[REDACTED_AUTHOR]
- */
-internal class AppsFlyerLogClient(
- jsonConverter: MoshiJsonConverter,
-) : AppsFlyerAnalyticsClient {
-
- private val logger = AnalyticsEventsLogger(AppsFlyerAnalyticsHandler.ID, jsonConverter)
-
- override fun logEvent(event: String, params: Map) {
- logger.logEvent(event, params)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAnalyticsEventConverter.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAnalyticsEventConverter.kt
new file mode 100644
index 0000000000..559fc3418b
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAnalyticsEventConverter.kt
@@ -0,0 +1,33 @@
+package com.tangem.tap.common.analytics.handlers.firebase
+
+internal class FirebaseAnalyticsEventConverter {
+
+ fun convertEventName(event: String): String {
+ return convertString(event, FIREBASE_EVENT_NAME_MAX_LENGTH)
+ }
+
+ fun convertEventParams(params: Map): Map {
+ return params.map { (key, value) ->
+ convertString(key, FIREBASE_EVENT_NAME_MAX_LENGTH) to convertString(value, FIREBASE_EVENT_VALUE_MAX_LENGTH)
+ }.toMap()
+ }
+
+ private fun convertString(string: String, maxLength: Int): String {
+ return string
+ .replace(REPLACING_PATTERN.toRegex(), WORD_SEPARATOR)
+ .trim { it in TRIMMING_CHARACTERS }
+ .trimToLength(maxLength)
+ }
+
+ private fun String.trimToLength(length: Int): String {
+ return if (this.length > length) this.substring(0, length) else this
+ }
+
+ private companion object {
+ const val REPLACING_PATTERN = "[^\\w]+"
+ const val WORD_SEPARATOR = "_"
+ const val TRIMMING_CHARACTERS = WORD_SEPARATOR
+ const val FIREBASE_EVENT_NAME_MAX_LENGTH = 40
+ const val FIREBASE_EVENT_VALUE_MAX_LENGTH = 100
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAnalyticsHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAnalyticsHandler.kt
index 7430fcc17f..10b399382c 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAnalyticsHandler.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAnalyticsHandler.kt
@@ -1,9 +1,9 @@
package com.tangem.tap.common.analytics.handlers.firebase
import com.google.firebase.analytics.FirebaseAnalytics
-import com.tangem.core.analytics.AnalyticsEvent
import com.tangem.core.analytics.api.AnalyticsHandler
import com.tangem.core.analytics.api.ErrorEventHandler
+import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
import com.tangem.tap.common.analytics.converters.AnalyticsErrorConverter
import com.tangem.tap.common.analytics.events.Shop
@@ -14,8 +14,8 @@ class FirebaseAnalyticsHandler(
override fun id(): String = ID
- override fun send(event: String, params: Map) {
- client.logEvent(event, params)
+ override fun send(eventId: String, params: Map) {
+ client.logEvent(eventId, params)
}
override fun send(event: AnalyticsEvent) {
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAppInstanceIdProvider.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAppInstanceIdProvider.kt
new file mode 100644
index 0000000000..5a8a85c072
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAppInstanceIdProvider.kt
@@ -0,0 +1,29 @@
+package com.tangem.tap.common.analytics.handlers.firebase
+
+import com.google.firebase.analytics.ktx.analytics
+import com.google.firebase.ktx.Firebase
+import com.tangem.core.analytics.AppInstanceIdProvider
+import kotlinx.coroutines.suspendCancellableCoroutine
+import timber.log.Timber
+import kotlin.coroutines.resume
+
+internal class FirebaseAppInstanceIdProvider : AppInstanceIdProvider {
+
+ override suspend fun getAppInstanceId(): String? = suspendCancellableCoroutine { continuation ->
+ Firebase.analytics.appInstanceId
+ .addOnSuccessListener { continuation.resume(it) }
+ .addOnFailureListener {
+ Timber.w("Fail to get appInstanceId")
+ continuation.resume(null)
+ }
+ }
+
+ override fun getAppInstanceIdSync(): String? {
+ return try {
+ Firebase.analytics.appInstanceId.result
+ } catch (e: IllegalStateException) {
+ Timber.e(e, "getAppInstanceIdSync")
+ null
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseClient.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseClient.kt
index 33751b5e0a..7e4e5085bc 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseClient.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseClient.kt
@@ -2,7 +2,6 @@ package com.tangem.tap.common.analytics.handlers.firebase
import android.os.Bundle
import androidx.core.os.bundleOf
-import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
@@ -19,18 +18,21 @@ internal class FirebaseClient : FirebaseAnalyticsClient {
private val fbAnalytics = Firebase.analytics
private val fbCrashlytics = Firebase.crashlytics
+ private val eventConverter = FirebaseAnalyticsEventConverter()
+
override fun logEvent(event: String, params: Map) {
- fbAnalytics.logEvent(event, params.toBundle())
+ fbAnalytics.logEvent(
+ eventConverter.convertEventName(event),
+ eventConverter.convertEventParams(params).toBundle(),
+ )
}
override fun logErrorEvent(error: Throwable, params: Map) {
- params.forEach { fbCrashlytics.setCustomKey(it.key, it.value) }
+ eventConverter.convertEventParams(params)
+ .forEach { fbCrashlytics.setCustomKey(it.key, it.value) }
+
fbCrashlytics.recordException(error)
}
private fun Map.toBundle(): Bundle = bundleOf(*this.toList().toTypedArray())
-
- companion object {
- const val ORDER_EVENT = FirebaseAnalytics.Event.PURCHASE
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/BatchIdParamsInterceptor.kt b/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/BatchIdParamsInterceptor.kt
deleted file mode 100644
index b7e7ec6fbf..0000000000
--- a/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/BatchIdParamsInterceptor.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.tangem.tap.common.analytics.paramsInterceptor
-
-import com.tangem.core.analytics.api.ParamsInterceptor
-import com.tangem.core.analytics.AnalyticsEvent
-import com.tangem.tap.common.analytics.events.AnalyticsParam
-
-/**
-[REDACTED_AUTHOR]
- */
-class BatchIdParamsInterceptor(
- val batchId: String,
-) : ParamsInterceptor {
-
- override fun id(): String = this::class.java.simpleName
-
- override fun canBeAppliedTo(event: AnalyticsEvent): Boolean = true
-
- override fun intercept(params: MutableMap) {
- params[AnalyticsParam.BatchId] = batchId
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/CardContextInterceptor.kt b/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/CardContextInterceptor.kt
new file mode 100644
index 0000000000..42a7f46c75
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/CardContextInterceptor.kt
@@ -0,0 +1,86 @@
+package com.tangem.tap.common.analytics.paramsInterceptor
+
+import com.tangem.core.analytics.api.ParamsInterceptor
+import com.tangem.core.analytics.models.AnalyticsEvent
+import com.tangem.domain.common.util.cardTypesResolver
+import com.tangem.domain.models.scan.ProductType
+import com.tangem.domain.models.scan.ScanResponse
+import com.tangem.domain.wallets.builder.UserWalletIdBuilder
+import com.tangem.tap.common.analytics.converters.ParamCardCurrencyConverter
+import com.tangem.tap.common.analytics.events.AnalyticsParam
+import com.tangem.tap.common.analytics.events.IntroductionProcess
+import com.tangem.tap.common.extensions.inject
+import com.tangem.tap.features.demo.DemoHelper
+import com.tangem.tap.proxy.redux.DaggerGraphState
+import com.tangem.tap.store
+import kotlinx.coroutines.runBlocking
+
+/**
+[REDACTED_AUTHOR]
+ */
+class CardContextInterceptor(
+ private val scanResponse: ScanResponse,
+) : ParamsInterceptor {
+
+ private val walletsRepository = store.inject(DaggerGraphState::walletsRepository)
+
+ private val userWalletId = UserWalletIdBuilder.scanResponse(scanResponse).build()
+
+ override fun id(): String = CardContextInterceptor.id()
+
+ override fun canBeAppliedTo(event: AnalyticsEvent): Boolean {
+ return when (event) {
+ is IntroductionProcess.ButtonScanCard -> false
+ else -> true
+ }
+ }
+
+ override fun intercept(params: MutableMap) {
+ val card = scanResponse.card
+ params[AnalyticsParam.BATCH] = card.batchId
+ params[AnalyticsParam.PRODUCT_TYPE] = getProductType()
+ params[AnalyticsParam.FIRMWARE] = card.firmwareVersion.stringValue
+ if (userWalletId != null) {
+ params[AnalyticsParam.USER_WALLET_ID] = userWalletId.stringValue
+ }
+
+ ParamCardCurrencyConverter().convert(scanResponse.cardTypesResolver)?.let {
+ params[AnalyticsParam.CURRENCY] = it.value
+ }
+ }
+
+ private fun getProductType(): String {
+ if (scanResponse.productType != ProductType.Ring && userWalletId != null) {
+ val isWalletWithRing = runBlocking { walletsRepository.isWalletWithRing(userWalletId) }
+
+ if (isWalletWithRing) return "Ring"
+ }
+
+ return when (scanResponse.productType) {
+ ProductType.Note -> "Note"
+ ProductType.Twins -> "Twin"
+ ProductType.Wallet -> "Wallet"
+ ProductType.Wallet2 -> "Wallet 2.0"
+ ProductType.Ring -> "Ring"
+ ProductType.Start2Coin -> "Start2Coin"
+ ProductType.Visa -> "VISA"
+ else -> if (DemoHelper.isDemoCard(scanResponse)) getDemoCardProductType() else "Other"
+ }
+ }
+
+ private fun getDemoCardProductType(): String {
+ return if (DemoHelper.isTestDemoCard(scanResponse)) {
+ "Demo Test"
+ } else {
+ when (scanResponse.card.cardId.substring(0..1)) {
+ "AC" -> "Demo Wallet"
+ "AB" -> "Demo Note"
+ else -> "Demo Other"
+ }
+ }
+ }
+
+ companion object {
+ fun id(): String = CardContextInterceptor::class.java.simpleName
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/LinkedCardContextInterceptor.kt b/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/LinkedCardContextInterceptor.kt
new file mode 100644
index 0000000000..25b67c3ee0
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/LinkedCardContextInterceptor.kt
@@ -0,0 +1,26 @@
+package com.tangem.tap.common.analytics.paramsInterceptor
+
+import com.tangem.core.analytics.api.ParamsInterceptor
+import com.tangem.core.analytics.models.AnalyticsEvent
+import com.tangem.domain.models.scan.ScanResponse
+
+/**
+[REDACTED_AUTHOR]
+ */
+class LinkedCardContextInterceptor(
+ scanResponse: ScanResponse,
+ val parent: LinkedCardContextInterceptor? = null,
+) : ParamsInterceptor {
+
+ private val contextInterceptor = CardContextInterceptor(scanResponse)
+
+ override fun id(): String = LinkedCardContextInterceptor.id()
+
+ override fun canBeAppliedTo(event: AnalyticsEvent): Boolean = contextInterceptor.canBeAppliedTo(event)
+
+ override fun intercept(params: MutableMap) = contextInterceptor.intercept(params)
+
+ companion object {
+ fun id(): String = LinkedCardContextInterceptor::class.java.simpleName
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/apptheme/MutableAppThemeModeHolder.kt b/app/src/main/java/com/tangem/tap/common/apptheme/MutableAppThemeModeHolder.kt
new file mode 100644
index 0000000000..9dec177e01
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/apptheme/MutableAppThemeModeHolder.kt
@@ -0,0 +1,19 @@
+package com.tangem.tap.common.apptheme
+
+import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.mutableStateOf
+import com.tangem.core.ui.theme.AppThemeModeHolder
+import com.tangem.domain.apptheme.model.AppThemeMode
+
+internal object MutableAppThemeModeHolder : AppThemeModeHolder {
+
+ override val appThemeMode: MutableState = mutableStateOf(AppThemeMode.DEFAULT)
+
+ var value: AppThemeMode
+ set(value) {
+ appThemeMode.value = value
+ }
+ get() = appThemeMode.value
+
+ var isDarkThemeActive: Boolean = false
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/clipboard/DefaultClipboardManager.kt b/app/src/main/java/com/tangem/tap/common/clipboard/DefaultClipboardManager.kt
new file mode 100644
index 0000000000..73f2ebd5ef
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/clipboard/DefaultClipboardManager.kt
@@ -0,0 +1,52 @@
+package com.tangem.tap.common.clipboard
+
+import android.content.ClipData
+import android.content.ClipDescription
+import android.content.ClipDescription.MIMETYPE_TEXT_PLAIN
+import android.os.Build
+import android.os.PersistableBundle
+import com.tangem.core.ui.clipboard.ClipboardManager
+import timber.log.Timber
+import android.content.ClipboardManager as AndroidClipboardManager
+
+internal class DefaultClipboardManager(private val clipboardManager: AndroidClipboardManager) : ClipboardManager {
+
+ override fun setText(text: String, isSensitive: Boolean, label: String) {
+ val clip = ClipData.newPlainText(label, text).apply {
+ if (isSensitive) description.setAsSensitive()
+ }
+
+ clipboardManager.setPrimaryClip(clip)
+ }
+
+ override fun getText(default: String?): String? {
+ val clip = clipboardManager.primaryClip
+
+ if (clip == null || clip.itemCount == 0) {
+ Timber.d("Clipboard is empty")
+ return default
+ }
+
+ val clipDescription = clipboardManager.primaryClipDescription
+ if (clipDescription?.hasMimeType(MIMETYPE_TEXT_PLAIN) == false) {
+ Timber.d("Clipboard doesn't contain text")
+ return default
+ }
+
+ return clip.getItemAt(0).text?.toString()
+ }
+
+ private fun ClipDescription.setAsSensitive() {
+ extras = PersistableBundle().apply {
+ putBoolean(getExtraIsSensitiveFlag(), true)
+ }
+ }
+
+ private fun getExtraIsSensitiveFlag(): String {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ ClipDescription.EXTRA_IS_SENSITIVE
+ } else {
+ "android.content.extra.IS_SENSITIVE"
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/clipboard/MockClipboardManager.kt b/app/src/main/java/com/tangem/tap/common/clipboard/MockClipboardManager.kt
new file mode 100644
index 0000000000..8013aa18f1
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/clipboard/MockClipboardManager.kt
@@ -0,0 +1,13 @@
+package com.tangem.tap.common.clipboard
+
+import com.tangem.core.ui.clipboard.ClipboardManager
+import timber.log.Timber
+
+internal object MockClipboardManager : ClipboardManager {
+
+ override fun setText(text: String, isSensitive: Boolean, label: String) {
+ Timber.w("Clipboard Manager not available")
+ }
+
+ override fun getText(default: String?): String? = null
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/AutoSizeText.kt b/app/src/main/java/com/tangem/tap/common/compose/AutoSizeText.kt
deleted file mode 100644
index 63d98b6269..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/AutoSizeText.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.tangem.tap.common.compose
-
-import androidx.compose.material.LocalTextStyle
-import androidx.compose.material.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.drawWithContent
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.unit.TextUnit
-import androidx.compose.ui.unit.sp
-
-@Suppress("MagicNumber")
-@Composable
-fun TextAutoSize(
- text: String,
- fontSizeRange: FontSizeRange,
- modifier: Modifier = Modifier,
- textStyle: TextStyle = LocalTextStyle.current,
-) {
- val fontSizeValue = remember { mutableStateOf(fontSizeRange.max.value) }
- val readyToDraw = remember { mutableStateOf(false) }
-
- val textState = remember { mutableStateOf(text) }
- if (textState.value != text) {
- readyToDraw.value = false
- fontSizeValue.value = fontSizeRange.max.value
- textState.value = text
- }
-
- Text(
- modifier = modifier.drawWithContent { if (readyToDraw.value) drawContent() },
- text = text,
- softWrap = false,
- style = textStyle,
- fontSize = fontSizeValue.value.sp,
- onTextLayout = {
- if (it.hasVisualOverflow) {
- val nextFontSizeValue = fontSizeValue.value - fontSizeRange.step.value
- if (nextFontSizeValue <= fontSizeRange.min.value) {
- fontSizeValue.value = fontSizeRange.min.value
- readyToDraw.value = true
- } else {
- fontSizeValue.value = nextFontSizeValue * 0.8f
- }
- } else {
- readyToDraw.value = true
- }
- },
- )
-}
-
-data class FontSizeRange(
- val min: TextUnit,
- val max: TextUnit,
- val step: TextUnit = DEFAULT_TEXT_STEP,
-) {
- init {
- require(min < max) { "min should be less than max, $this" }
- require(step.value > 0) { "step should be greater than 0, $this" }
- }
-
- companion object {
- private val DEFAULT_TEXT_STEP = 1.sp
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/BlockchainSpinner.kt b/app/src/main/java/com/tangem/tap/common/compose/BlockchainSpinner.kt
deleted file mode 100644
index 215fb7b312..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/BlockchainSpinner.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.tangem.tap.common.compose
-
-import androidx.annotation.StringRes
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.res.stringResource
-import com.tangem.blockchain.common.Blockchain
-import com.tangem.domain.common.form.Field
-
-@Composable
-fun BlockchainSpinner(
- @StringRes title: Int,
- itemList: List,
- selectedItem: Field.Data,
- isEnabled: Boolean = true,
- textFieldConverter: (Blockchain) -> String,
- dropdownItemView: @Composable ((Blockchain) -> Unit)? = null,
- closePopupTrigger: ClosePopupTrigger = ClosePopupTrigger(),
- onItemSelect: (Blockchain) -> Unit,
-) {
- OutlinedSpinner(
- modifier = Modifier.fillMaxWidth(),
- label = stringResource(id = title),
- itemList = itemList,
- selectedItem = selectedItem,
- textFieldConverter = textFieldConverter,
- dropdownItemView = dropdownItemView,
- isEnabled = isEnabled,
- onItemSelected = onItemSelect,
- closePopupTrigger = closePopupTrigger,
- )
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/Button.kt b/app/src/main/java/com/tangem/tap/common/compose/Button.kt
deleted file mode 100644
index c536af17bd..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/Button.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.tangem.tap.common.compose
-
-import androidx.compose.material.ripple.LocalRippleTheme
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
-
-/**
- * Used for disable ripple if button is enable = false
- */
-@Composable
-fun ToggledRippleTheme(
- isEnabled: Boolean,
- content: @Composable () -> Unit,
-) {
- val theme = LocalRippleTheme provides if (isEnabled) LocalRippleTheme.current else NoRippleTheme()
- CompositionLocalProvider(theme) { content() }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/ComposableValueDebouncer.kt b/app/src/main/java/com/tangem/tap/common/compose/ComposableValueDebouncer.kt
deleted file mode 100644
index 44395f9279..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/ComposableValueDebouncer.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.tangem.tap.common.compose
-
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-import com.tangem.domain.common.util.ValueDebouncer
-
-/**
-[REDACTED_AUTHOR]
- * This is an empty compose view. It just remember the ValueDebouncer inside of itself.
- */
-@Composable
-fun valueDebouncerAsState(
- initialValue: T,
- onValueChange: (T) -> Unit,
- debounce: Long = 600,
- onEmitValueReceive: (T) -> Unit = {},
-): ValueDebouncer {
- return remember {
- ValueDebouncer(
- initialValue = initialValue,
- debounceDuration = debounce,
- onEmitValueReceived = { emitValue ->
- emitValue?.let { onEmitValueReceive(it) }
- },
- onValueChanged = { changedValue ->
- changedValue?.let { onValueChange(it) }
- },
- )
- }
-}
-
-@Composable
-fun valueDebouncerNullableAsState(
- initialValue: T?,
- onValueChange: (T?) -> Unit,
- debounce: Long = 400,
- onEmitValueReceive: (T?) -> Unit = {},
-): ValueDebouncer {
- return remember {
- ValueDebouncer(
- initialValue = initialValue,
- debounceDuration = debounce,
- onEmitValueReceived = onEmitValueReceive,
- onValueChanged = onValueChange,
- )
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/ComposeDialogManager.kt b/app/src/main/java/com/tangem/tap/common/compose/ComposeDialogManager.kt
deleted file mode 100644
index 8d0de7df69..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/ComposeDialogManager.kt
+++ /dev/null
@@ -1,159 +0,0 @@
-package com.tangem.tap.common.compose
-
-import androidx.compose.foundation.clickable
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.lazy.LazyColumn
-import androidx.compose.foundation.lazy.items
-import androidx.compose.material.AlertDialog
-import androidx.compose.material.Button
-import androidx.compose.material.LocalTextStyle
-import androidx.compose.material.MaterialTheme
-import androidx.compose.material.Surface
-import androidx.compose.material.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.DisposableEffect
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.MutableState
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.unit.sp
-import androidx.compose.ui.window.Dialog
-import androidx.compose.ui.window.DialogProperties
-import com.tangem.core.ui.components.SpacerH16
-import com.tangem.domain.DomainDialog
-import com.tangem.domain.redux.domainStore
-import com.tangem.domain.redux.global.DomainGlobalAction
-import com.tangem.domain.redux.global.DomainGlobalState
-import com.tangem.tap.domain.moduleMessage.ModuleMessageConverter
-import com.tangem.tap.features.tokens.addCustomToken.compose.SelectTokenNetworkDialog
-import com.tangem.wallet.R
-import org.rekotlin.StoreSubscriber
-
-@Composable
-fun ComposeDialogManager() {
- val dialogSate = remember { mutableStateOf(null) }
- val subscriber = remember {
- object : StoreSubscriber {
- override fun newState(state: DomainGlobalState) {
- dialogSate.value = state.dialog
- }
- }
- }
-
- ShowTheDialog(dialogSate)
-
- LaunchedEffect(key1 = Unit, block = {
- domainStore.subscribe(subscriber) { state ->
- state.skipRepeats { oldState, newState ->
- oldState.globalState == newState.globalState
- }.select { it.globalState }
- }
- })
- DisposableEffect(key1 = Unit, effect = {
- onDispose { domainStore.unsubscribe(subscriber) }
- })
-}
-
-@Composable
-private fun ShowTheDialog(dialogState: MutableState) {
- if (dialogState.value == null) return
-
- val context = LocalContext.current
- val errorConverter = remember { ModuleMessageConverter(context) }
- val onDismissRequest = { domainStore.dispatch(DomainGlobalAction.ShowDialog(null)) }
-
- when (val dialog = dialogState.value) {
- is DomainDialog.DialogError -> ErrorDialog(
- title = stringResource(id = R.string.common_error),
- body = errorConverter.convert(dialog.error).message,
- onDismissRequest
- )
- is DomainDialog.SelectTokenDialog -> SelectTokenNetworkDialog(dialog, onDismissRequest)
- else -> {}
- }
-}
-
-/**
- * Dialog with single item selection
- */
-@Composable
-fun SimpleDialog(
- title: String,
- items: List,
- onSelect: (T) -> Unit,
- onDismissRequest: () -> Unit,
- itemContent: @Composable (T) -> Unit,
-) {
- Dialog(
- properties = DialogProperties(false, false),
- onDismissRequest = { }
- ) {
- Surface(
- modifier = Modifier.fillMaxWidth(),
- shape = MaterialTheme.shapes.medium
- ) {
- Column(
- modifier = Modifier.padding(22.dp)
- ) {
- DialogTitle(title = title)
- LazyColumn {
- items(items) { item ->
- Row(
- modifier = Modifier
- .fillMaxWidth()
- .height(56.dp)
- .clickable {
- onSelect(item)
- onDismissRequest()
- },
- verticalAlignment = Alignment.CenterVertically,
- ) { itemContent(item) }
- }
- }
- }
- }
- }
-}
-
-@Composable
-private fun DialogTitle(title: String) {
- Text(
- text = title,
- style = LocalTextStyle.provides(
- TextStyle(
- fontWeight = FontWeight.Bold,
- fontSize = 20.sp
- )
- ).value
- )
- SpacerH16()
-}
-
-@Composable
-fun ErrorDialog(
- title: String,
- body: String,
- onDismissRequest: () -> Unit,
-) {
- AlertDialog(
- title = { DialogTitle(title) },
- text = { Text(body) },
- onDismissRequest = onDismissRequest,
- confirmButton = {
- Button(onClick = onDismissRequest) {
- Text(text = stringResource(id = R.string.common_ok))
- }
- }
- )
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/ErrorViews.kt b/app/src/main/java/com/tangem/tap/common/compose/ErrorViews.kt
deleted file mode 100644
index c8d0701b2e..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/ErrorViews.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.tangem.tap.common.compose
-
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.padding
-import androidx.compose.material.LocalTextStyle
-import androidx.compose.material.MaterialTheme
-import androidx.compose.material.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.unit.dp
-
-/**
-[REDACTED_AUTHOR]
- */
-@Composable
-fun ErrorView(
- text: String,
- modifier: Modifier = Modifier,
- style: TextStyle = LocalTextStyle.current,
-) {
- Text(
- text,
- color = MaterialTheme.colors.error,
- modifier = modifier,
- style = style,
- )
-}
-
-@Preview
-@Composable
-private fun ErrorViewTest() {
- Box(Modifier.padding(16.dp)) {
- ErrorView(text = "Some error description")
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/NoRippleTheme.kt b/app/src/main/java/com/tangem/tap/common/compose/NoRippleTheme.kt
deleted file mode 100644
index f0afe076ba..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/NoRippleTheme.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.tangem.tap.common.compose
-
-import androidx.compose.material.ripple.RippleAlpha
-import androidx.compose.material.ripple.RippleTheme
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.graphics.Color
-
-/**
-[REDACTED_AUTHOR]
- */
-class NoRippleTheme : RippleTheme {
- @Composable
- override fun defaultColor() = Color.Unspecified
-
- @Composable
- override fun rippleAlpha(): RippleAlpha = RippleAlpha(0.0f, 0.0f, 0.0f, 0.0f)
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/OutlinedSpinner.kt b/app/src/main/java/com/tangem/tap/common/compose/OutlinedSpinner.kt
deleted file mode 100644
index 981e5e00e6..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/OutlinedSpinner.kt
+++ /dev/null
@@ -1,106 +0,0 @@
-package com.tangem.tap.common.compose
-
-import android.os.Handler
-import android.os.Looper
-import androidx.compose.material.*
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.tooling.preview.Preview
-import androidx.core.os.postDelayed
-import com.tangem.blockchain.common.Blockchain
-import com.tangem.common.extensions.VoidCallback
-import com.tangem.domain.common.form.Field
-import com.tangem.tap.common.extensions.ValueCallback
-
-/**
-[REDACTED_AUTHOR]
- */
-@Suppress("MagicNumber")
-@OptIn(ExperimentalMaterialApi::class)
-@Composable
-fun OutlinedSpinner(
- label: String,
- itemList: List,
- selectedItem: Field.Data,
- onItemSelected: ValueCallback,
- modifier: Modifier = Modifier,
- textFieldConverter: (T) -> String = { it.toString() },
- dropdownItemView: @Composable ((T) -> Unit)? = null,
- isEnabled: Boolean = true,
- onClose: VoidCallback = {},
- closePopupTrigger: ClosePopupTrigger = ClosePopupTrigger(),
-) {
- val rIsExpanded = remember { mutableStateOf(false) }
- val stateSelectedItem = remember { mutableStateOf(selectedItem.value) }
- if (!selectedItem.isUserInput) {
- stateSelectedItem.value = selectedItem.value
- }
-
- val onDropDownItemSelectedInternal: (T) -> Unit = {
- stateSelectedItem.value = it
- rIsExpanded.value = false
- onItemSelected(it)
- }
- val onDismissRequest = {
- rIsExpanded.value = false
- onClose()
- }
-
- closePopupTrigger.close = {
- onDismissRequest()
- Handler(Looper.getMainLooper()).postDelayed(100) {
- closePopupTrigger.onCloseComplete()
- }
- }
-
- ExposedDropdownMenuBox(
- expanded = rIsExpanded.value,
- onExpandedChange = { rIsExpanded.value = !rIsExpanded.value },
- ) {
- OutlinedTextField(
- modifier = modifier,
- readOnly = true,
- enabled = isEnabled,
- value = textFieldConverter(stateSelectedItem.value),
- onValueChange = {},
- label = { Text(label) },
- trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = rIsExpanded.value) },
- colors = TangemTextFieldsDefault.defaultTextFieldColors,
- )
-
- if (isEnabled) {
- ExposedDropdownMenu(
- expanded = rIsExpanded.value,
- onDismissRequest = onDismissRequest,
- ) {
- itemList.forEach { item ->
- DropdownMenuItem(onClick = { onDropDownItemSelectedInternal(item) }) {
- when (dropdownItemView) {
- null -> Text(textFieldConverter(item))
- else -> dropdownItemView(item)
- }
- }
- }
- }
- }
- }
-}
-
-class ClosePopupTrigger {
- var close: () -> Unit = {}
- var onCloseComplete: () -> Unit = {}
- var isTriggered = false
-}
-
-@Preview
-@Composable
-private fun TestSpinnerPreview() {
- OutlinedSpinner(
- label = "Blockchain name",
- itemList = listOf(Blockchain.values()),
- selectedItem = Field.Data(Blockchain.Avalanche, false),
- onItemSelected = {},
- )
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/OutlinedTextFieldWidget.kt b/app/src/main/java/com/tangem/tap/common/compose/OutlinedTextFieldWidget.kt
deleted file mode 100644
index 113dbfb809..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/OutlinedTextFieldWidget.kt
+++ /dev/null
@@ -1,280 +0,0 @@
-package com.tangem.tap.common.compose
-
-import androidx.compose.animation.AnimatedVisibility
-import androidx.compose.animation.animateContentSize
-import androidx.compose.animation.fadeIn
-import androidx.compose.animation.fadeOut
-import androidx.compose.animation.slideInVertically
-import androidx.compose.animation.slideOutVertically
-import androidx.compose.foundation.interaction.MutableInteractionSource
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.text.KeyboardOptions
-import androidx.compose.material.LinearProgressIndicator
-import androidx.compose.material.OutlinedTextField
-import androidx.compose.material.Text
-import androidx.compose.material.TextFieldColors
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.input.VisualTransformation
-import androidx.compose.ui.text.style.TextOverflow
-import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.unit.sp
-import com.tangem.common.module.ModuleError
-import com.tangem.core.ui.res.TangemTheme
-import com.tangem.domain.common.form.Field
-import com.tangem.tap.common.CompositionLogger
-import com.tangem.tap.common.compose.extensions.stringResourceDefault
-import com.tangem.tap.domain.moduleMessage.ModuleMessageConverter
-
-/**
-[REDACTED_AUTHOR]
- */
-@Composable
-fun OutlinedTextFieldWidget(
- fieldData: Field.Data,
- labelId: Int? = null,
- label: String = "",
- placeholderId: Int? = null,
- placeholder: String = "",
- trailingIcon: @Composable (() -> Unit)? = null,
- isEnabled: Boolean = true,
- isVisible: Boolean = true,
- isLoading: Boolean = false,
- error: ModuleError? = null,
- errorConverter: ModuleMessageConverter? = null,
- debounceTextChanges: Long = 400,
- visualTransformation: VisualTransformation = VisualTransformation.None,
- keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
- onTextChange: (String) -> Unit,
-) {
- if (!isVisible) return
-
- Column(modifier = Modifier.animateContentSize()) {
- OutlinedProgressTextField(
- fieldData = fieldData,
- label = stringResourceDefault(labelId, label),
- placeholder = stringResourceDefault(placeholderId, placeholder),
- trailingIcon = trailingIcon,
- isEnabled = isEnabled,
- isLoading = isLoading,
- error = error,
- debounce = debounceTextChanges,
- visualTransformation = visualTransformation,
- keyboardOptions = keyboardOptions,
- onTextChange = onTextChange,
- )
- errorConverter?.let { AnimatedErrorView(errorConverter = it, error = error) }
- }
-}
-
-@Suppress("LongMethod", "NestedBlockDepth", "MagicNumber", "MaxLineLength")
-@Composable
-private fun OutlinedProgressTextField(
- fieldData: Field.Data,
- label: String = "",
- placeholder: String = "",
- isEnabled: Boolean = true,
- isLoading: Boolean = false,
- error: ModuleError? = null,
- debounce: Long = 400,
- visualTransformation: VisualTransformation = VisualTransformation.None,
- keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
- colors: TextFieldColors = TangemTextFieldsDefault.defaultTextFieldColors,
- interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
- trailingIcon: @Composable (() -> Unit)? = null,
- onTextChange: (String) -> Unit,
-) {
- val logger = remember {
- CompositionLogger(label, "OutlinedProgressTextField", listOf("Символ токена"))
- }
- logger.nextComposition()
-
- val textValueState = remember { mutableStateOf(fieldData.value) }
- val textDebouncer = valueDebouncerAsState(
- initialValue = fieldData.value,
- debounce = debounce,
- onEmitValueReceive = {
- logger.log("DEBOUNCER: onEmitValueReceived: [$it]")
- logger.log("DEBOUNCER: start RECOMPOSE by new value for textValueState.value = [$it]")
- textValueState.value = it
- },
- onValueChange = {
- logger.log("DEBOUNCER: onValueChanged: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> dispatch.toStore([$it])")
- onTextChange(it)
- },
- )
-
- logger.log("RECOMPOSE ---------------------------------------------------------------START [${logger.count}]")
- logger.log("RECOMPOSE --data: fieldData.value: [$fieldData]")
- logger.log("RECOMPOSE --data: textValueState.value: [${textValueState.value}]")
- logger.log("RECOMPOSE --data: textDebouncer.emittedValue = [${textDebouncer.emittedValue}]")
- logger.log("RECOMPOSE --data: textDebouncer.debounced = [${textDebouncer.debounced}]")
-
- if (!fieldData.isUserInput) {
- // initial value is not from an user
- val isNotUserInput = "-- IS NOT USER INPUT"
- logger.log("recompose $isNotUserInput")
- if (textValueState.value == fieldData.value) {
- logger.log("$isNotUserInput: внешние данные ОДИНАКОВЫ с данными в поле")
- } else {
- logger.log("$isNotUserInput: внешние данные РАЗЛИЧАЮТСЯ с данными в поле")
- if (textDebouncer.emittedValue != textDebouncer.debounced || textDebouncer.emitsCountBeforeDebounce > 0) {
- logger.log("$isNotUserInput: пользователь ВВОДИТ данные -> внешние данные игнорируем, ждем RECOMPOSE")
- } else {
- logger.log("$isNotUserInput: пользователь НЕ вводит данные -> пытаемся обработать внешние данные")
- if (textValueState.value != textDebouncer.emittedValue ||
- textValueState.value != textDebouncer.debounced
- ) {
- logger.log("$isNotUserInput: даннные в поле не соответствуют данным из textDebouncer")
- if (textDebouncer.emittedValue.isEmpty() && textDebouncer.debounced.isEmpty()) {
- logger.log(
- "$isNotUserInput: даннные в textDebouncer ПУСТЫ -> start RECOMPOSE новые данные для " +
- "textValueState.value = [${fieldData.value}]",
- )
- textValueState.value = fieldData.value
- } else {
- logger.log(
- "$isNotUserInput: даннные в textDebouncer НЕ ПУСТЫ -> start RECOMPOSE новые данные для " +
- "textValueState.value = [${fieldData.value}]",
- )
- textValueState.value = fieldData.value
- }
- } else {
- logger.log(
- "$isNotUserInput: в пустое поле вставляются данные -> start RECOMPOSE новые данные для " +
- "textValueState.value = [${fieldData.value}]",
- )
- textValueState.value = fieldData.value
- }
- }
- }
- }
- logger.log("recompose --------------------------------------------------------------FINISH [${logger.count}]")
-
- Box {
- OutlinedTextField(
- modifier = Modifier
- .fillMaxWidth(),
- value = textValueState.value,
- onValueChange = {
- logger.log("WIDGET: textDebouncer.emmit([$it])")
- textDebouncer.emmit(it)
- },
- keyboardOptions = keyboardOptions,
- label = {
- Text(
- text = label,
- style = TangemTheme.typography.caption,
- color = colors.labelColor(
- enabled = isEnabled,
- error = error != null,
- interactionSource = interactionSource,
- ).value,
- )
- },
- placeholder = {
- Text(
- text = placeholder,
- style = TangemTheme.typography.body1,
- color = colors.placeholderColor(enabled = isEnabled).value,
- maxLines = 1,
- overflow = TextOverflow.Ellipsis,
- )
- },
- trailingIcon = trailingIcon,
- singleLine = true,
- enabled = isEnabled,
- isError = error != null,
- visualTransformation = visualTransformation,
- colors = colors,
- interactionSource = interactionSource,
- )
- AnimatedVisibility(
- modifier = Modifier
- .fillMaxWidth()
- .align(Alignment.BottomCenter)
- .padding(start = 6.dp, top = 0.dp, end = 6.dp, bottom = 6.dp),
- visible = isLoading,
- ) {
- LinearProgressIndicator(
- color = TangemTheme.colors.icon.primary1,
- )
- }
- }
-}
-
-@Composable
-private fun AnimatedErrorView(
- errorConverter: ModuleMessageConverter,
- error: ModuleError? = null,
-) {
- AnimatedVisibility(
- visible = error != null,
- enter = fadeIn() + slideInVertically(),
- exit = slideOutVertically() + fadeOut(),
- ) {
- error?.let {
- ErrorView(
- text = errorConverter.convert(it).message,
- style = TextStyle(fontSize = 14.sp),
- )
- }
- }
-}
-
-@Preview
-@Composable
-private fun OutlinedTextFieldWithErrorTest() {
- val context = LocalContext.current
- val converter = remember { ModuleMessageConverter(context) }
-
- class SimpleError(
- override val code: Int = 1,
- override val message: String = "Error message",
- override val data: Any? = null,
- ) : ModuleError()
-
- val modifier = Modifier
- .fillMaxWidth()
- .padding(16.dp)
- Column {
- OutlinedTextFieldWidget(
- fieldData = Field.Data("", false),
- label = "First label",
- placeholder = "1 placeholder",
- error = null,
- errorConverter = converter,
- ) {}
- OutlinedTextFieldWidget(
- fieldData = Field.Data("First", false),
- label = "First label",
- placeholder = "1 placeholder",
- error = null,
- errorConverter = converter,
- ) {}
- OutlinedTextFieldWidget(
- fieldData = Field.Data("First", false),
- label = "First label",
- placeholder = "1 placeholder",
- isLoading = true,
- error = null,
- errorConverter = converter,
- ) {}
- OutlinedTextFieldWidget(
- fieldData = Field.Data("First", false),
- label = "First label",
- placeholder = "1 placeholder",
- error = SimpleError(),
- errorConverter = converter,
- ) {}
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/PinCodeWidget.kt b/app/src/main/java/com/tangem/tap/common/compose/PinCodeWidget.kt
deleted file mode 100644
index f742bb5731..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/PinCodeWidget.kt
+++ /dev/null
@@ -1,168 +0,0 @@
-package com.tangem.tap.common.compose
-
-import androidx.compose.foundation.background
-import androidx.compose.foundation.gestures.detectTapGestures
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.layout.wrapContentSize
-import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.foundation.text.KeyboardActions
-import androidx.compose.foundation.text.KeyboardOptions
-import androidx.compose.material.LocalTextStyle
-import androidx.compose.material.MaterialTheme
-import androidx.compose.material.Surface
-import androidx.compose.material.Text
-import androidx.compose.material.TextField
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.ExperimentalComposeUiApi
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.alpha
-import androidx.compose.ui.draw.clip
-import androidx.compose.ui.focus.FocusRequester
-import androidx.compose.ui.focus.focusRequester
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.input.pointer.pointerInput
-import androidx.compose.ui.platform.LocalSoftwareKeyboardController
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.text.input.ImeAction
-import androidx.compose.ui.text.input.KeyboardType
-import androidx.compose.ui.text.input.TextFieldValue
-import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.unit.sp
-import androidx.core.text.isDigitsOnly
-
-/**
-[REDACTED_AUTHOR]
- */
-@OptIn(ExperimentalComposeUiApi::class)
-@Composable
-fun PinCodeWidget(
- config: PinViewConfig = tangemPinConfig,
- onPinChange: (String, Boolean) -> Unit = { pin, isLastSymbolEntered -> },
-) {
- val focusRequester = remember { FocusRequester() }
- val keyboardController = LocalSoftwareKeyboardController.current
-
- val rTextFieldValue = remember { mutableStateOf(TextFieldValue("")) }
- val indexedSymbols: List = createPinSymbolsList(config.pinsCount, rTextFieldValue.value.text)
-
- fun isLastSymbolEntered(): Boolean = rTextFieldValue.value.text.length == config.pinsCount
-
- fun handleOnTextFieldValueChanged(value: TextFieldValue) {
- if (!value.text.isDigitsOnly()) return
-
- if (value.text.length <= config.pinsCount) {
- rTextFieldValue.value = value
- onPinChange(value.text, isLastSymbolEntered())
- }
- }
-
- Box(
- modifier = config.modifier
- .pointerInput(Unit) {
- detectTapGestures {
- focusRequester.requestFocus()
- keyboardController?.show()
- }
- },
- ) {
- Row {
- for (index in 0 until config.pinsCount) {
- PinElement(
- config = config,
- pinSymbol = indexedSymbols[index] ?: "",
- )
- }
- }
- TextField(
- modifier = Modifier
- .alpha(0f)
- .size(1.dp)
- .align(Alignment.Center)
- .focusRequester(focusRequester),
- keyboardOptions = KeyboardOptions(
- keyboardType = KeyboardType.Decimal,
- imeAction = if (isLastSymbolEntered()) ImeAction.Done else ImeAction.Next,
- ),
- keyboardActions = KeyboardActions(
- onDone = { keyboardController?.hide() },
- ),
- value = rTextFieldValue.value,
- onValueChange = ::handleOnTextFieldValueChanged,
- )
- }
-
- LaunchedEffect(Unit) {
- focusRequester.requestFocus()
- }
-}
-
-@Composable
-private fun PinElement(
- config: PinViewConfig,
- pinSymbol: String,
-) {
- Box(Modifier.padding(config.pinBoxPadding)) {
- Box(config.pinBoxModifier) {
- Text(
- text = pinSymbol,
- modifier = config.pinTextModifier.align(Alignment.Center),
- style = config.pinsTextStyle ?: LocalTextStyle.current,
- )
- }
- }
-}
-
-private fun createPinSymbolsList(size: Int, text: String): List = List(size) {
- try {
- text[it].toString()
- } catch (ex: IndexOutOfBoundsException) {
- null
- }
-}
-
-data class PinViewConfig(
- val modifier: Modifier = Modifier,
- val pinBoxModifier: Modifier = Modifier,
- val pinBoxPadding: Dp = 0.dp,
- val pinTextModifier: Modifier = Modifier,
- val pinsCount: Int = 4,
- val pinsTextStyle: TextStyle? = null,
-)
-
-private val tangemPinConfig = PinViewConfig(
- modifier = Modifier
- .wrapContentSize(),
- pinBoxModifier = Modifier
- .width(42.dp)
- .height(56.dp)
- .clip(RoundedCornerShape(8.dp))
- .background(Color(0xFFF0F0F0)),
- pinBoxPadding = 6.dp,
- pinTextModifier = Modifier,
- pinsCount = 4,
- pinsTextStyle = TextStyle(
- fontWeight = FontWeight(500),
- fontSize = 24.sp,
- ),
-)
-
-@Preview
-@Composable
-private fun PinCodeWidgetPreview() {
- Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
- PinCodeWidget(tangemPinConfig)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/TangemTextFieldsDefault.kt b/app/src/main/java/com/tangem/tap/common/compose/TangemTextFieldsDefault.kt
index 694fd8c376..945ffc182f 100644
--- a/app/src/main/java/com/tangem/tap/common/compose/TangemTextFieldsDefault.kt
+++ b/app/src/main/java/com/tangem/tap/common/compose/TangemTextFieldsDefault.kt
@@ -128,11 +128,7 @@ internal data class TangemTextFieldColors(
}
@Composable
- override fun labelColor(
- enabled: Boolean,
- error: Boolean,
- interactionSource: InteractionSource,
- ): State {
+ override fun labelColor(enabled: Boolean, error: Boolean, interactionSource: InteractionSource): State {
val focused by interactionSource.collectIsFocusedAsState()
val targetValue = when {
diff --git a/app/src/main/java/com/tangem/tap/common/compose/TangemTypography.kt b/app/src/main/java/com/tangem/tap/common/compose/TangemTypography.kt
deleted file mode 100644
index 2013295f25..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/TangemTypography.kt
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.tangem.tap.common.compose
-
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.font.Font
-import androidx.compose.ui.text.font.FontFamily
-import androidx.compose.ui.unit.sp
-import com.tangem.wallet.R
-
-object TangemTypography {
-
- val body1 = TextStyle(
- fontFamily = FontFamily(Font(R.font.roboto_regular)),
- fontSize = 16.0.sp,
- letterSpacing = 0.5.sp,
- lineHeight = 24.0.sp,
- )
- val body2 = TextStyle(
- fontFamily = FontFamily(Font(R.font.roboto_regular)),
- fontSize = 14.0.sp,
- letterSpacing = 0.25.sp,
- lineHeight = 20.0.sp,
- )
- val button = TextStyle(
- fontFamily = FontFamily(Font(R.font.roboto_medium)),
- fontSize = 14.0.sp,
- letterSpacing = 0.10000000149011612.sp,
- lineHeight = 20.0.sp,
- )
- val caption = TextStyle(
- fontFamily = FontFamily(Font(R.font.roboto_regular)),
- fontSize = 12.0.sp,
- letterSpacing = 0.4000000059604645.sp,
- lineHeight = 16.0.sp,
- )
- val headline1 = TextStyle(
- fontFamily = FontFamily(Font(R.font.roboto_regular)),
- fontSize = 34.0.sp,
- letterSpacing = 0.0.sp,
- lineHeight = 44.0.sp,
- )
- val headline2 = TextStyle(
- fontFamily = FontFamily(Font(R.font.roboto_medium)),
- fontSize = 24.0.sp,
- letterSpacing = 0.18000000715255737.sp,
- lineHeight = 32.0.sp,
- )
- val headline3 = TextStyle(
- fontFamily = FontFamily(Font(R.font.roboto_medium)),
- fontSize = 20.0.sp,
- letterSpacing = 0.15000000596046448.sp,
- lineHeight = 24.0.sp,
- )
- val overline = TextStyle(
- fontFamily = FontFamily(Font(R.font.roboto_medium)),
- fontSize = 10.0.sp,
- letterSpacing = 1.5.sp,
- lineHeight = 16.0.sp,
- )
- val subtitle1 = TextStyle(
- fontFamily = FontFamily(Font(R.font.roboto_medium)),
- fontSize = 16.0.sp,
- letterSpacing = 0.15000000596046448.sp,
- lineHeight = 24.0.sp,
- )
- val subtitle2 = TextStyle(
- fontFamily = FontFamily(Font(R.font.roboto_medium)),
- fontSize = 14.0.sp,
- letterSpacing = 0.10000000149011612.sp,
- lineHeight = 24.0.sp,
- )
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/Undefined.kt b/app/src/main/java/com/tangem/tap/common/compose/Undefined.kt
deleted file mode 100644
index 10e2ec9956..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/Undefined.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.tangem.tap.common.compose
-
-import androidx.compose.foundation.layout.Column
-import androidx.compose.material.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.unit.sp
-
-/**
-[REDACTED_AUTHOR]
- * Compose views are not typically used as a main or base view.
- */
-
-@Composable
-fun TitleSubtitle(
- title: String,
- subtitle: String
-) {
- Column {
- Text(text = title)
- Text(
- text = subtitle,
- fontSize = 12.sp,
- color = Color.Gray
- )
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/Warning.kt b/app/src/main/java/com/tangem/tap/common/compose/Warning.kt
deleted file mode 100644
index ea4d150e51..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/Warning.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.tangem.tap.common.compose
-
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.padding
-import androidx.compose.material.MaterialTheme
-import androidx.compose.material.Surface
-import androidx.compose.material.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.res.colorResource
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.unit.sp
-import com.tangem.common.module.ModuleMessage
-import com.tangem.core.ui.components.SpacerH8
-import com.tangem.tap.domain.moduleMessage.ModuleMessageConverter
-import com.tangem.wallet.R
-
-/**
-[REDACTED_AUTHOR]
- */
-@Composable
-fun AddCustomTokenWarning(
- warning: ModuleMessage,
- converter: ModuleMessageConverter,
- modifier: Modifier = Modifier,
-) {
- Surface(
- modifier = modifier,
- shape = MaterialTheme.shapes.small,
- color = colorResource(id = R.color.warning_warning),
- elevation = 4.dp,
- ) {
- Column(
- modifier = Modifier.padding(16.dp),
- ) {
- Text(
- text = stringResource(id = R.string.common_warning),
- color = colorResource(id = R.color.white),
- fontSize = 14.sp,
- fontWeight = FontWeight.Bold
- )
- SpacerH8()
- Text(
- text = converter.convert(warning).message,
- color = colorResource(id = R.color.white),
- fontSize = 13.sp,
- lineHeight = 18.sp
- )
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/extensions/AnimatedValue.kt b/app/src/main/java/com/tangem/tap/common/compose/extensions/AnimatedValue.kt
index 1952c6a058..b21726c8e7 100644
--- a/app/src/main/java/com/tangem/tap/common/compose/extensions/AnimatedValue.kt
+++ b/app/src/main/java/com/tangem/tap/common/compose/extensions/AnimatedValue.kt
@@ -1,6 +1,10 @@
package com.tangem.tap.common.compose.extensions
-import androidx.compose.animation.core.*
+import androidx.compose.animation.core.Animatable
+import androidx.compose.animation.core.AnimationVector1D
+import androidx.compose.animation.core.Easing
+import androidx.compose.animation.core.LinearEasing
+import androidx.compose.animation.core.tween
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
@@ -41,8 +45,8 @@ fun animatable(
targetValue = values.second,
animationSpec = tween(
durationMillis = duration,
- easing = easing
- )
+ easing = easing,
+ ),
)
}
}
diff --git a/app/src/main/java/com/tangem/tap/common/compose/extensions/Context.kt b/app/src/main/java/com/tangem/tap/common/compose/extensions/Context.kt
deleted file mode 100644
index 719c80d0d4..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/extensions/Context.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.tangem.tap.common.compose.extensions
-
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.platform.LocalContext
-import com.tangem.tap.common.extensions.copyToClipboard
-import com.tangem.tap.common.extensions.getFromClipboard
-
-/**
-[REDACTED_AUTHOR]
- */
-@Suppress("ComposableFunctionName")
-@Composable
-fun copyToClipboard(value: Any, label: String = "") {
- LocalContext.current.copyToClipboard(value, label)
-}
-
-@Suppress("ComposableFunctionName")
-@Composable
-fun getFromClipboard(default: CharSequence? = null): CharSequence? {
- return LocalContext.current.getFromClipboard(default)
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/extensions/Dp.kt b/app/src/main/java/com/tangem/tap/common/compose/extensions/Dp.kt
index 42acdcf306..04240d7b55 100644
--- a/app/src/main/java/com/tangem/tap/common/compose/extensions/Dp.kt
+++ b/app/src/main/java/com/tangem/tap/common/compose/extensions/Dp.kt
@@ -14,6 +14,4 @@ fun Dp.toPx(): Float {
return with(LocalDensity.current) { currentDp.toPx() }
}
-fun DpSize.halfWidth(): Dp = this.width / 2
-
fun DpSize.halfHeight(): Dp = this.height / 2
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/extensions/LazyListState.kt b/app/src/main/java/com/tangem/tap/common/compose/extensions/LazyListState.kt
deleted file mode 100644
index dab9b8f654..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/extensions/LazyListState.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.tangem.tap.common.compose.extensions
-
-import androidx.compose.foundation.lazy.LazyListState
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.derivedStateOf
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.remember
-import androidx.compose.ui.platform.LocalView
-import com.tangem.tap.common.extensions.hideKeyboard
-
-@Composable
-fun LazyListState.OnBottomReached(loadMoreThreshold: Int, onLoadMore: () -> Unit) {
- require(loadMoreThreshold >= 0)
- val shouldLoadMore by remember {
- derivedStateOf {
- val lastVisibleItem = layoutInfo.visibleItemsInfo.lastOrNull()
- ?: return@derivedStateOf false
- lastVisibleItem.index >= layoutInfo.totalItemsCount - 1 - loadMoreThreshold
- }
- }
-
- LaunchedEffect(shouldLoadMore) {
- if (shouldLoadMore) onLoadMore()
- }
-}
-
-@Composable
-fun LazyListState.HideKeyboardOnScroll() {
- if (isScrollInProgress) {
- LocalView.current.hideKeyboard()
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/extensions/MutableState.kt b/app/src/main/java/com/tangem/tap/common/compose/extensions/MutableState.kt
deleted file mode 100644
index 459086b9c3..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/extensions/MutableState.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.tangem.tap.common.compose.extensions
-
-import androidx.compose.runtime.MutableState
-
-/**
-[REDACTED_AUTHOR]
- */
-fun MutableState>.addAndNotify(value: T) {
- this.value = this.value.toMutableList().apply { add(value) }
-}
-
-fun MutableState>.removeAndNotify(value: T) {
- this.value = this.value.toMutableList().apply { remove(value) }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/extensions/Painter.kt b/app/src/main/java/com/tangem/tap/common/compose/extensions/Painter.kt
index fa91934a30..dfabb2cddf 100644
--- a/app/src/main/java/com/tangem/tap/common/compose/extensions/Painter.kt
+++ b/app/src/main/java/com/tangem/tap/common/compose/extensions/Painter.kt
@@ -5,8 +5,7 @@ import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
-import com.tangem.tangem_sdk_new.extensions.dpToPx
-import com.tangem.tangem_sdk_new.extensions.pxToDp
+import com.tangem.sdk.extensions.pxToDp
/**
[REDACTED_AUTHOR]
@@ -17,8 +16,5 @@ fun Painter.dpSize(): DpSize = DpSize(
intrinsicSize.height.pxToDp().dp,
)
-@Composable
-private fun Float.dpToPx(): Float = LocalContext.current.dpToPx(this)
-
@Composable
private fun Float.pxToDp(): Float = LocalContext.current.pxToDp(this)
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/compose/extensions/Resources.kt b/app/src/main/java/com/tangem/tap/common/compose/extensions/Resources.kt
deleted file mode 100644
index 5b8da92e24..0000000000
--- a/app/src/main/java/com/tangem/tap/common/compose/extensions/Resources.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.tangem.tap.common.compose.extensions
-
-import android.content.res.Resources
-import androidx.annotation.StringRes
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.platform.LocalContext
-
-/**
-[REDACTED_AUTHOR]
- */
-@Composable
-fun stringResourceDefault(@StringRes id: Int?, default: String = ""): String {
- val resources = LocalContext.current.resources
- return try {
- resources.getString(requireNotNull(id))
- } catch (ex: Resources.NotFoundException) {
- default
- } catch (ex: IllegalArgumentException) {
- default
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/entities/Button.kt b/app/src/main/java/com/tangem/tap/common/entities/Button.kt
deleted file mode 100644
index d9ff2b27f8..0000000000
--- a/app/src/main/java/com/tangem/tap/common/entities/Button.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.tangem.tap.common.entities
-
-import com.tangem.tap.features.send.redux.states.ButtonState
-import com.tangem.tap.features.wallet.redux.ProgressState
-
-open class Button(val enabled: Boolean)
-
-open class IndeterminateProgressButton(
- val state: ButtonState
-) : Button(state != ButtonState.DISABLED) {
-
- val progressState: ProgressState
- get() = when (state) {
- ButtonState.PROGRESS -> ProgressState.Loading
- else -> ProgressState.Done
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/entities/FiatCurrency.kt b/app/src/main/java/com/tangem/tap/common/entities/FiatCurrency.kt
deleted file mode 100644
index c0df80eb2a..0000000000
--- a/app/src/main/java/com/tangem/tap/common/entities/FiatCurrency.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.tangem.tap.common.entities
-
-data class FiatCurrency(
- val code: String,
- val name: String,
- val symbol: String,
-) {
- val displayName: String
- get() = "${this.name} (${this.code}) - ${this.symbol}"
-
- companion object {
- val Default = FiatCurrency(
- symbol = "$",
- code = "USD",
- name = "US Dollar",
- )
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/entities/ProgressState.kt b/app/src/main/java/com/tangem/tap/common/entities/ProgressState.kt
new file mode 100644
index 0000000000..61adc5cd45
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/entities/ProgressState.kt
@@ -0,0 +1,5 @@
+package com.tangem.tap.common.entities
+
+import com.tangem.tap.common.toggleWidget.WidgetState
+
+enum class ProgressState : WidgetState { Loading, Done, Error }
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Activity.kt b/app/src/main/java/com/tangem/tap/common/extensions/Activity.kt
deleted file mode 100644
index 5f531a9bc8..0000000000
--- a/app/src/main/java/com/tangem/tap/common/extensions/Activity.kt
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.tangem.tap.common.extensions
-
-import android.app.Activity
-import android.content.Intent
-import android.net.Uri
-import androidx.core.app.ShareCompat
-import androidx.core.content.ContextCompat
-import androidx.core.content.FileProvider
-import java.io.File
-
-/**
- * required since targetAndroid=30
- *
- *
- *
- *
- *
- *
- */
-fun Activity.sendEmail(
- email: String,
- subject: String,
- message: String,
- file: File? = null,
- onFail: ((Exception) -> Unit)? = null
-) {
- fun createEmailShareIntent(recipient: String, subject: String, text: String, file: File? = null): Intent {
- val builder = ShareCompat.IntentBuilder.from(this)
- .setType("message/rfc822")
- .setEmailTo(arrayOf(recipient))
- .setSubject(subject)
- .setText(text)
- file?.let { builder.setStream(FileProvider.getUriForFile(this, "$packageName.provider", it)) }
- return builder.intent
- }
-
- val originalIntent = createEmailShareIntent(email, subject, message, file)
- val emailFilterIntent = Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:"))
-
- val originalIntentResults = packageManager.queryIntentActivities(originalIntent, 0)
- val emailFilterIntentResults = packageManager.queryIntentActivities(emailFilterIntent, 0)
-
- val targetedIntents = originalIntentResults
- .filter { originalResult ->
- emailFilterIntentResults.any {
- originalResult.activityInfo.packageName == it.activityInfo.packageName
- }
- }
- .map {
- createEmailShareIntent(email, subject, message, file).apply {
- setPackage(it.activityInfo.packageName)
- }
- }
- .toMutableList()
- try {
- val chooserIntent = Intent.createChooser(targetedIntents.removeAt(0), "Send mail...")
- chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedIntents.toTypedArray())
- chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- ContextCompat.startActivity(this, chooserIntent, null)
- } catch (ex: Exception) {
- onFail?.invoke(ex)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Analytics.kt b/app/src/main/java/com/tangem/tap/common/extensions/Analytics.kt
new file mode 100644
index 0000000000..8e79d07381
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/extensions/Analytics.kt
@@ -0,0 +1,43 @@
+package com.tangem.tap.common.extensions
+
+import com.tangem.core.analytics.Analytics
+import com.tangem.domain.models.scan.ScanResponse
+import com.tangem.tap.common.analytics.paramsInterceptor.LinkedCardContextInterceptor
+
+/**
+[REDACTED_AUTHOR]
+ */
+
+/**
+ * Sets the new context
+ */
+fun Analytics.setContext(scanResponse: ScanResponse) {
+ addParamsInterceptor(LinkedCardContextInterceptor(scanResponse))
+}
+
+/**
+ * Erases the context
+ */
+fun Analytics.eraseContext() {
+ removeParamsInterceptor(LinkedCardContextInterceptor.id())
+}
+
+/**
+ * Adds a new context and keeps a previous context as the parent of the new one
+ */
+fun Analytics.addContext(scanResponse: ScanResponse) {
+ val currentContext = removeParamsInterceptor(LinkedCardContextInterceptor.id()) as? LinkedCardContextInterceptor
+ val newContext = LinkedCardContextInterceptor(scanResponse, parent = currentContext)
+
+ addParamsInterceptor(newContext)
+}
+
+/**
+ * Removes the current context and restores the previous one if it was present.
+ */
+fun Analytics.removeContext() {
+ val currentContext = removeParamsInterceptor(LinkedCardContextInterceptor.id()) as? LinkedCardContextInterceptor
+ val previousContext = currentContext?.parent ?: return
+
+ addParamsInterceptor(previousContext)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/AssetManager.kt b/app/src/main/java/com/tangem/tap/common/extensions/AssetManager.kt
deleted file mode 100644
index 9130b6c91d..0000000000
--- a/app/src/main/java/com/tangem/tap/common/extensions/AssetManager.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.tangem.tap.common.extensions
-
-import android.content.res.AssetManager
-
-fun AssetManager.readJsonFileToString(fileName: String): String =
- this.open("$fileName.json").bufferedReader().readText()
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/BackupService.kt b/app/src/main/java/com/tangem/tap/common/extensions/BackupService.kt
deleted file mode 100644
index 140f0946b4..0000000000
--- a/app/src/main/java/com/tangem/tap/common/extensions/BackupService.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.tangem.tap.common.extensions
-
-import com.tangem.domain.common.SaltPayWorkaround
-import com.tangem.operations.backup.BackupService
-
-/**
-[REDACTED_AUTHOR]
- */
-@Suppress("MagicNumber")
-fun BackupService.primaryCardIsSaltPayVisa(): Boolean {
- return primaryCardId?.slice(0..3)?.let(SaltPayWorkaround::isVisaBatchId) ?: false
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Bitmap.kt b/app/src/main/java/com/tangem/tap/common/extensions/Bitmap.kt
deleted file mode 100644
index 80e756c21c..0000000000
--- a/app/src/main/java/com/tangem/tap/common/extensions/Bitmap.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.tangem.tap.common.extensions
-
-import android.graphics.Bitmap
-import android.graphics.BitmapFactory
-import java.io.ByteArrayOutputStream
-
-@Suppress("MagicNumber")
-fun Bitmap.toByteArray(): ByteArray {
- val stream = ByteArrayOutputStream()
- this.compress(Bitmap.CompressFormat.JPEG, 20, stream)
- return stream.toByteArray()
-}
-
-@Suppress("MagicNumber")
-fun ByteArray.toBitmap(): Bitmap {
- return BitmapFactory.decodeByteArray(this, 0, this.size)
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Blockchain.kt b/app/src/main/java/com/tangem/tap/common/extensions/Blockchain.kt
deleted file mode 100644
index 133869ee22..0000000000
--- a/app/src/main/java/com/tangem/tap/common/extensions/Blockchain.kt
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.tangem.tap.common.extensions
-
-import androidx.annotation.DrawableRes
-import com.tangem.blockchain.common.Blockchain
-import com.tangem.common.extensions.remove
-import com.tangem.wallet.R
-
-@Suppress("ComplexMethod")
-@DrawableRes
-fun Blockchain.getGreyedOutIconRes(): Int {
- return when (this) {
- Blockchain.Arbitrum, Blockchain.ArbitrumTestnet -> R.drawable.ic_arbitrum_no_color
-// Blockchain.Ducatus -> R.drawable.ic_ducatus
- Blockchain.Bitcoin, Blockchain.BitcoinTestnet -> R.drawable.ic_bitcoin_no_color
- Blockchain.BitcoinCash -> R.drawable.ic_bitcoin_cash_no_color
- Blockchain.Litecoin -> R.drawable.ic_litecoin_no_color
- Blockchain.Ethereum, Blockchain.EthereumTestnet -> R.drawable.ic_eth_no_color
- Blockchain.EthereumClassic, Blockchain.EthereumClassicTestnet -> R.drawable.ic_eth_no_color
- Blockchain.RSK -> R.drawable.ic_rsk_no_color
- Blockchain.Cardano, Blockchain.CardanoShelley -> R.drawable.ic_cardano_no_color
- Blockchain.Tezos -> R.drawable.ic_tezos_no_color
- Blockchain.XRP -> R.drawable.ic_xrp_no_color
- Blockchain.Stellar -> R.drawable.ic_stellar_no_color
- Blockchain.Avalanche, Blockchain.AvalancheTestnet -> R.drawable.ic_avalanche_no_color
- Blockchain.Polygon, Blockchain.PolygonTestnet -> R.drawable.ic_polygon_no_color
- Blockchain.Solana, Blockchain.SolanaTestnet -> R.drawable.ic_solana_no_color
- Blockchain.Fantom, Blockchain.FantomTestnet -> R.drawable.ic_fantom_no_color
- Blockchain.BSC, Blockchain.BSCTestnet, Blockchain.Binance, Blockchain.BinanceTestnet ->
- R.drawable.ic_bsc_no_color
- Blockchain.Dogecoin -> R.drawable.ic_dogecoin_no_color
- Blockchain.Tron, Blockchain.TronTestnet -> R.drawable.ic_tron_no_color
- Blockchain.Gnosis -> R.drawable.ic_gnosis_no_color
- Blockchain.EthereumPow, Blockchain.EthereumPowTestnet -> R.drawable.ic_ethereumpow_no_color
- Blockchain.EthereumFair -> R.drawable.ic_ethereumfair_no_color
- Blockchain.Polkadot, Blockchain.PolkadotTestnet -> R.drawable.ic_polkadot_no_color
- Blockchain.Kusama -> R.drawable.ic_kusama_no_color
- Blockchain.Optimism, Blockchain.OptimismTestnet -> R.drawable.ic_optimism_no_color
- Blockchain.Dash -> R.drawable.ic_dash_no_color
- else -> R.drawable.ic_tangem_logo
- }
-}
-
-fun Blockchain.getNetworkName(): String {
- return when (this) {
- Blockchain.Ethereum, Blockchain.EthereumTestnet -> "ERC20"
- Blockchain.BSC, Blockchain.BSCTestnet -> "BEP20"
- Blockchain.Binance, Blockchain.BinanceTestnet -> "BEP2"
- Blockchain.Tron, Blockchain.TronTestnet -> "TRC20"
- else -> ""
- }
-}
-
-val Blockchain.fullNameWithoutTestnet
- get() = this.fullName.remove(" Testnet")
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Collections.kt b/app/src/main/java/com/tangem/tap/common/extensions/Collections.kt
deleted file mode 100644
index 8492ae44f1..0000000000
--- a/app/src/main/java/com/tangem/tap/common/extensions/Collections.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.tangem.tap.common.extensions
-
-/**
-[REDACTED_AUTHOR]
- */
-fun List.containsAny(list: List): Boolean {
- this.forEach { mainItem ->
- list.forEach { if (it == mainItem) return true }
- }
- return false
-}
-
-fun MutableList.removeBy(predicate: (T) -> Boolean): Boolean {
- val toRemove = this.filter(predicate)
- this.removeAll(toRemove)
- return toRemove.isNotEmpty()
-}
-
-fun MutableList.replaceBy(item: T, predicate: (T) -> Boolean): Boolean {
- val toRemove = this.filter(predicate)
- if (toRemove.isEmpty()) return false
-
- val indexes = toRemove.map { indexOf(it) }
- this.removeAll(toRemove)
- indexes.forEach { this.add(it, item) }
- return true
-}
-
-fun MutableList.replaceByOrAdd(item: T, predicate: (T) -> Boolean) {
- if (!replaceBy(item, predicate)) add(item)
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Context.kt b/app/src/main/java/com/tangem/tap/common/extensions/Context.kt
index ee68830265..14f4cd0dbf 100644
--- a/app/src/main/java/com/tangem/tap/common/extensions/Context.kt
+++ b/app/src/main/java/com/tangem/tap/common/extensions/Context.kt
@@ -1,29 +1,11 @@
package com.tangem.tap.common.extensions
-import android.content.ContentResolver
-import android.content.Context
-import android.content.pm.PackageManager
-import android.content.res.Resources
-import android.net.Uri
-import androidx.annotation.AnyRes
-import androidx.core.content.ContextCompat
-
-fun Context.readFile(fileName: String): String =
- this.openFileInput(fileName).bufferedReader().readText()
-
-fun Context.rewriteFile(content: String, fileName: String) {
- this.openFileOutput(fileName, Context.MODE_PRIVATE).use {
- it.write(content.toByteArray(), 0, content.length)
- }
-}
-
-fun Context.readAssetAsString(fileName: String): String {
- return this.assets.open("$fileName.json").bufferedReader().readText()
-}
-
-fun Context.isPermissionGranted(permission: String): Boolean {
- return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
-}
+import android.content.*
+import android.content.pm.*
+import android.content.res.*
+import android.net.*
+import androidx.annotation.*
+import androidx.core.content.*
/**
* Get uri to any resource type via given Resource Instance
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/ImageView.kt b/app/src/main/java/com/tangem/tap/common/extensions/ImageView.kt
deleted file mode 100644
index 0c3a471d54..0000000000
--- a/app/src/main/java/com/tangem/tap/common/extensions/ImageView.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.tangem.tap.common.extensions
-
-import android.widget.ImageView
-import androidx.annotation.DrawableRes
-
-/**
-[REDACTED_AUTHOR]
- */
-fun ImageView.setDrawable(@DrawableRes resId: Int) {
- setImageDrawable(context.getDrawableCompat(resId))
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Map.kt b/app/src/main/java/com/tangem/tap/common/extensions/Map.kt
index e970306219..313c83ff03 100644
--- a/app/src/main/java/com/tangem/tap/common/extensions/Map.kt
+++ b/app/src/main/java/com/tangem/tap/common/extensions/Map.kt
@@ -1,4 +1,3 @@
package com.tangem.tap.common.extensions
-fun Map.filterNotNull(): Map =
- filter { it.key != null && it.value != null } as Map
\ No newline at end of file
+fun Map.filterNotNull(): Map = filter { it.key != null && it.value != null } as Map
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt b/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt
index 6cb707b071..243a2f8770 100644
--- a/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt
+++ b/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt
@@ -1,121 +1,60 @@
package com.tangem.tap.common.extensions
-import android.os.Bundle
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment
-import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentManager
-import com.tangem.feature.referral.ReferralFragment
-import com.tangem.feature.swap.presentation.SwapFragment
-import com.tangem.tap.common.redux.navigation.AppScreen
-import com.tangem.tap.common.redux.navigation.FragmentShareTransition
-import com.tangem.tap.features.details.ui.appsettings.AppSettingsFragment
-import com.tangem.tap.features.details.ui.cardsettings.CardSettingsFragment
-import com.tangem.tap.features.details.ui.details.DetailsFragment
-import com.tangem.tap.features.details.ui.resetcard.ResetCardFragment
-import com.tangem.tap.features.details.ui.securitymode.SecurityModeFragment
-import com.tangem.tap.features.details.ui.walletconnect.QrScanFragment
-import com.tangem.tap.features.details.ui.walletconnect.WalletConnectFragment
-import com.tangem.tap.features.disclaimer.ui.DisclaimerFragment
-import com.tangem.tap.features.home.HomeFragment
-import com.tangem.tap.features.onboarding.products.note.OnboardingNoteFragment
-import com.tangem.tap.features.onboarding.products.otherCards.OnboardingOtherCardsFragment
-import com.tangem.tap.features.onboarding.products.twins.ui.TwinsCardsFragment
-import com.tangem.tap.features.onboarding.products.wallet.ui.OnboardingWalletFragment
-import com.tangem.tap.features.saveWallet.ui.SaveWalletBottomSheetFragment
-import com.tangem.tap.features.send.ui.SendFragment
-import com.tangem.tap.features.shop.ui.ShopFragment
-import com.tangem.tap.features.tokens.addCustomToken.AddCustomTokenFragment
-import com.tangem.tap.features.tokens.ui.AddTokensFragment
-import com.tangem.tap.features.wallet.ui.WalletDetailsFragment
-import com.tangem.tap.features.wallet.ui.WalletFragment
-import com.tangem.tap.features.walletSelector.ui.WalletSelectorBottomSheetFragment
-import com.tangem.tap.features.welcome.ui.WelcomeFragment
+import com.tangem.utils.Provider
import com.tangem.wallet.R
import timber.log.Timber
-fun FragmentActivity.openFragment(
- screen: AppScreen,
- addToBackstack: Boolean,
- bundle: Bundle? = null,
- fgShareTransition: FragmentShareTransition? = null,
-) {
- val transaction = this.supportFragmentManager.beginTransaction()
- val fragment = fragmentFactory(screen)
- fragment.arguments = bundle
- fgShareTransition?.apply {
- fragment.sharedElementEnterTransition = enterTransitionSet
- fragment.sharedElementReturnTransition = exitTransitionSet
- transaction.setReorderingAllowed(true)
- shareElements.forEach { shareElement ->
- shareElement.wView.get()?.let { view ->
- transaction.addSharedElement(view, shareElement.elementName)
- }
+fun FragmentManager.showFragmentAllowingStateLoss(name: String, fragmentProvider: Provider) {
+ if (backStackEntryCount > 0) {
+ val currentFragmentName = getBackStackEntryAt(backStackEntryCount - 1).name
+
+ if (name == currentFragmentName) {
+ Timber.i("Fragment $name is already at the top of the stack")
+ return
}
}
- if (screen.isDialogFragment) {
- (fragment as DialogFragment).show(transaction, screen.name)
- if (addToBackstack) {
- transaction.addToBackStack(screen.name)
+
+ Timber.i("Showing $name route")
+
+ val isPoppedBack = popBackStackImmediate(name, 0)
+
+ if (!isPoppedBack) {
+ val fragment = fragmentProvider()
+
+ if (fragment is DialogFragment) {
+ fragment.showDialog(fragmentManager = this, name)
+ } else {
+ fragment.showFragment(fragmentManager = this, name)
}
+
+ Timber.i("Route $name is shown")
} else {
- transaction.replace(R.id.fragment_container, fragment, screen.name)
- if (addToBackstack) {
- transaction.addToBackStack(screen.name)
- }
+ Timber.i("Route $name is found in backstack and shown")
+ }
+}
+
+private fun DialogFragment.showDialog(fragmentManager: FragmentManager, name: String) {
+ val transaction = fragmentManager.beginTransaction()
+
+ try {
+ transaction.addToBackStack(name)
+ show(transaction, name)
+ } catch (e: IllegalStateException) {
+ transaction.add(this, name)
+ transaction.addToBackStack(name)
+
transaction.commitAllowingStateLoss()
}
}
-fun FragmentActivity.popBackTo(screen: AppScreen?, inclusive: Boolean = false) {
- val inclusiveFlag = if (inclusive) FragmentManager.POP_BACK_STACK_INCLUSIVE else 0
- try {
- this.supportFragmentManager.popBackStack(screen?.name, inclusiveFlag)
- } catch (e: IllegalStateException) {
- Timber.e(e)
- }
-}
+private fun Fragment.showFragment(fragmentManager: FragmentManager, name: String) {
+ val transaction = fragmentManager.beginTransaction()
-fun FragmentActivity.getPreviousScreen(): AppScreen? {
- val indexOfLastFragment = if (this.supportFragmentManager.backStackEntryCount > 0) {
- this.supportFragmentManager.backStackEntryCount - 1
- } else {
- 0
- }
- val tag = if (indexOfLastFragment < this.supportFragmentManager.backStackEntryCount) {
- this.supportFragmentManager.getBackStackEntryAt(indexOfLastFragment).name
- } else {
- null
- }
- return tag?.let { AppScreen.valueOf(tag) }
-}
+ transaction.replace(R.id.fragment_container, this, name)
+ transaction.addToBackStack(name)
-@Suppress("ComplexMethod")
-private fun fragmentFactory(screen: AppScreen): Fragment {
- return when (screen) {
- AppScreen.Home -> HomeFragment()
- AppScreen.Shop -> ShopFragment()
- AppScreen.OnboardingNote -> OnboardingNoteFragment()
- AppScreen.OnboardingWallet -> OnboardingWalletFragment()
- AppScreen.OnboardingTwins -> TwinsCardsFragment()
- AppScreen.OnboardingOther -> OnboardingOtherCardsFragment()
- AppScreen.Wallet -> WalletFragment()
- AppScreen.Send -> SendFragment()
- AppScreen.Details -> DetailsFragment()
- AppScreen.DetailsSecurity -> SecurityModeFragment()
- AppScreen.CardSettings -> CardSettingsFragment()
- AppScreen.AppSettings -> AppSettingsFragment()
- AppScreen.ResetToFactory -> ResetCardFragment()
- AppScreen.Disclaimer -> DisclaimerFragment()
- AppScreen.AddTokens -> AddTokensFragment()
- AppScreen.AddCustomToken -> AddCustomTokenFragment()
- AppScreen.WalletDetails -> WalletDetailsFragment()
- AppScreen.WalletConnectSessions -> WalletConnectFragment()
- AppScreen.QrScan -> QrScanFragment()
- AppScreen.ReferralProgram -> ReferralFragment()
- AppScreen.Swap -> SwapFragment()
- AppScreen.Welcome -> WelcomeFragment()
- AppScreen.SaveWallet -> SaveWalletBottomSheetFragment()
- AppScreen.WalletSelector -> WalletSelectorBottomSheetFragment()
- }
+ transaction.commitAllowingStateLoss()
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Specific.kt b/app/src/main/java/com/tangem/tap/common/extensions/Specific.kt
index ff4f898d8d..0dfce4b8c7 100644
--- a/app/src/main/java/com/tangem/tap/common/extensions/Specific.kt
+++ b/app/src/main/java/com/tangem/tap/common/extensions/Specific.kt
@@ -1,15 +1,10 @@
package com.tangem.tap.common.extensions
-import android.text.Spanned
-import android.text.SpannedString
-import android.text.style.RelativeSizeSpan
-import androidx.core.text.buildSpannedString
-import com.tangem.common.extensions.isZero
import java.math.BigDecimal
import java.math.RoundingMode
import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
-import java.util.*
+import java.util.Locale
// TODO: move extensions to utils
fun BigDecimal.toFormattedString(
@@ -22,144 +17,7 @@ fun BigDecimal.toFormattedString(
df.decimalFormatSymbols = symbols
df.maximumFractionDigits = decimals
df.minimumFractionDigits = 0
- df.isGroupingUsed = false
+ df.isGroupingUsed = true
df.roundingMode = roundingMode
return df.format(this)
-}
-
-@Suppress("MagicNumber")
-fun BigDecimal.toFormattedCurrencyString(
- decimals: Int,
- currency: String,
- roundingMode: RoundingMode = RoundingMode.DOWN,
- limitNumberOfDecimals: Boolean = true,
-): String {
- val decimalsForRounding = if (limitNumberOfDecimals) {
- if (decimals > 8) 8 else decimals
- } else {
- decimals
- }
- val formattedAmount = this.toFormattedString(
- decimals = decimalsForRounding,
- roundingMode = roundingMode,
- )
- return "$formattedAmount $currency"
-}
-
-fun BigDecimal.toFiatRateString(
- fiatCurrencyName: String,
-): String {
- val value = this
- .setScale(2, RoundingMode.HALF_UP)
- .formatWithSpaces()
- return "$value $fiatCurrencyName"
-}
-
-fun BigDecimal.toFiatString(
- rateValue: BigDecimal,
- fiatCurrencyName: String,
- formatWithSpaces: Boolean = false,
-): String {
- val fiatValue = rateValue.multiply(this)
- return fiatValue.toFormattedFiatValue(fiatCurrencyName, formatWithSpaces)
-}
-
-fun BigDecimal.toFiatValue(rateValue: BigDecimal): BigDecimal {
- val fiatValue = rateValue.multiply(this)
- return fiatValue.setScale(2, RoundingMode.HALF_UP)
-}
-
-fun BigDecimal.toFormattedFiatValue(
- fiatCurrencyName: String,
- formatWithSpaces: Boolean = false,
-): String {
- val fiatValue = this.setScale(2, RoundingMode.HALF_UP)
- .let { if (formatWithSpaces) it.formatWithSpaces() else it }
- return " $fiatValue $fiatCurrencyName"
-}
-
-fun BigDecimal.stripZeroPlainString(): String = this.stripTrailingZeros().toPlainString()
-
-// 0.00 -> 0.00
-// 0.00002345 -> 0.00002
-// 1.00002345 -> 1.00
-// 1.45002345 -> 1.45
-fun BigDecimal.scaleToFiat(applyPrecision: Boolean = false): BigDecimal {
- if (this.isZero()) return this
-
- val scaledFiat = this.setScale(2, RoundingMode.DOWN)
- return if (scaledFiat.isZero() && applyPrecision) this.setPrecision(1) else scaledFiat
-}
-
-fun BigDecimal.setPrecision(precision: Int, roundingMode: RoundingMode = RoundingMode.DOWN): BigDecimal {
- if (precision == precision() || scale() <= precision) return this
- return this.setScale(scale() - precision() + precision, roundingMode)
-}
-
-fun BigDecimal.isPositive(): Boolean = this.compareTo(BigDecimal.ZERO) == 1
-fun BigDecimal.isNegative(): Boolean = this.compareTo(BigDecimal.ZERO) == -1
-fun BigDecimal.isGreaterThan(value: BigDecimal): Boolean = this.compareTo(value) == 1
-fun BigDecimal.isLessThan(value: BigDecimal): Boolean = this.compareTo(value) == -1
-
-fun BigDecimal.isGreaterThanOrEqual(value: BigDecimal): Boolean {
- val compareResult = this.compareTo(value)
- return compareResult == 1 || compareResult == 0
-}
-
-fun BigDecimal.isLessThanOrEqual(value: BigDecimal): Boolean {
- val compareResult = this.compareTo(value)
- return compareResult == -1 || compareResult == 0
-}
-
-fun BigDecimal.formatAmountAsSpannedString(
- currencySymbol: String,
- reminderPartSizeProportion: Float = 0.7f,
-): SpannedString {
- val amount = this
- .setScale(2, RoundingMode.HALF_UP)
- .formatWithSpaces()
- val integer = amount.substringBefore('.')
- val reminder = amount.substringAfter('.')
-
- // test formatter log Log.e("TEST ", BigDecimal("1234567890987654321.1234567890987654321").formatWithSpaces())
-
- return buildSpannedString {
- append(integer)
- append('.')
- append(
- "$reminder $currencySymbol",
- RelativeSizeSpan(reminderPartSizeProportion),
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE,
- )
- }
-}
-
-@Suppress("MagicNumber")
-fun BigDecimal.formatWithSpaces(): String {
- val str = this.toString()
- var integerStr = str.substringBefore('.')
- val reminderStr = str.substringAfter('.')
- val packets = arrayListOf()
-
- var index: Int = integerStr.length
- while (0 < index) {
- if (index <= 3) {
- packets.add(integerStr)
- break
- }
- index -= 3
- packets.add(integerStr.substring(startIndex = index))
- integerStr = integerStr.substring(startIndex = 0, endIndex = index)
- }
-
- return buildString {
- packets.reversed().forEachIndexed { index, packet ->
- append(packet)
- if (index != packets.lastIndex) append(' ')
- }
- if (reminderStr.isNotBlank()) {
- append('.')
- append(reminderStr)
- }
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Store.kt b/app/src/main/java/com/tangem/tap/common/extensions/Store.kt
index 69c5f1c085..b86d13b6e9 100644
--- a/app/src/main/java/com/tangem/tap/common/extensions/Store.kt
+++ b/app/src/main/java/com/tangem/tap/common/extensions/Store.kt
@@ -1,12 +1,13 @@
package com.tangem.tap.common.extensions
-import com.tangem.domain.common.ScanResponse
+import com.tangem.common.routing.AppRouter
import com.tangem.domain.common.extensions.withMainContext
-import com.tangem.tap.common.redux.StateDialog
+import com.tangem.domain.redux.StateDialog
+import com.tangem.domain.wallets.models.UserWallet
+import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.global.GlobalAction
-import com.tangem.tap.common.redux.navigation.NavigationAction
import com.tangem.tap.domain.TapError
-import com.tangem.tap.domain.model.UserWallet
+import com.tangem.tap.proxy.redux.DaggerGraphState
import com.tangem.tap.scope
import com.tangem.tap.store
import kotlinx.coroutines.Dispatchers
@@ -16,10 +17,25 @@ import org.rekotlin.Store
/**
* Dispatch action with creating the new coroutine with the Main dispatcher
+ *
+ * @see dispatchWithMain
*/
fun Store<*>.dispatchOnMain(action: Action) {
scope.launch(Dispatchers.Main) {
- store.dispatch(action)
+ dispatch(action)
+ }
+}
+
+/**
+ * Dispatch action on the Main coroutine context
+ *
+ * @param action [Action] to be dispatched
+ *
+ * @see dispatchOnMain
+ * */
+suspend fun Store<*>.dispatchWithMain(action: Action) {
+ withMainContext {
+ dispatch(action)
}
}
@@ -27,13 +43,8 @@ fun Store<*>.dispatchNotification(resId: Int) {
dispatchOnMain(GlobalAction.ShowNotification(resId))
}
-@Suppress("UnusedReceiverParameter")
-suspend fun Store<*>.onUserWalletSelected(userWallet: UserWallet, refresh: Boolean = false) {
- store.state.globalState.tapWalletManager.onWalletSelected(userWallet, refresh)
-}
-
-fun Store<*>.dispatchToastNotification(resId: Int) {
- dispatchOnMain(GlobalAction.ShowToastNotification(resId))
+suspend fun Store.onUserWalletSelected(userWallet: UserWallet) {
+ state.globalState.tapWalletManager.onWalletSelected(userWallet)
}
fun Store<*>.dispatchErrorNotification(error: TapError) {
@@ -63,20 +74,28 @@ fun Store<*>.dispatchDialogHide() {
/**
* Dispatch action inside a coroutine with the Main dispatcher
*/
+@Deprecated(
+ message = "Use dispatchWithMain instead",
+ replaceWith = ReplaceWith(expression = "dispatchWithMain"),
+)
suspend fun dispatchOnMain(vararg actions: Action) {
withMainContext { actions.forEach { store.dispatch(it) } }
}
-/**
- * Dispatch action
- */
-suspend fun Store<*>.onCardScanned(scanResponse: ScanResponse) {
- store.state.globalState.tapWalletManager.onCardScanned(scanResponse)
+fun Store.dispatchOpenUrl(url: String) {
+ inject(DaggerGraphState::urlOpener).openUrl(url)
}
-fun Store<*>.dispatchOpenUrl(url: String) {
- store.dispatch(NavigationAction.OpenUrl(url))
+fun Store.dispatchShare(url: String) {
+ inject(DaggerGraphState::shareManager).shareText(url)
}
-fun Store<*>.dispatchShare(url: String) {
- store.dispatch(NavigationAction.Share(url))
+
+fun Store.dispatchNavigationAction(action: AppRouter.() -> Unit) {
+ inject(DaggerGraphState::appRouter).action()
+}
+
+inline fun Store.inject(getDependency: DaggerGraphState.() -> T?): T {
+ return requireNotNull(state.daggerGraphState.getDependency()) {
+ "${T::class.simpleName} isn't initialized "
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/String.kt b/app/src/main/java/com/tangem/tap/common/extensions/String.kt
index 3c4125d422..448ae3e36a 100644
--- a/app/src/main/java/com/tangem/tap/common/extensions/String.kt
+++ b/app/src/main/java/com/tangem/tap/common/extensions/String.kt
@@ -1,46 +1,12 @@
package com.tangem.tap.common.extensions
-import android.content.Context
import android.graphics.Bitmap
import android.graphics.Color
-import android.net.Uri
-import android.text.Spannable
-import android.text.style.ForegroundColorSpan
-import androidx.core.content.ContextCompat
-import androidx.core.text.toSpannable
import com.google.zxing.BarcodeFormat
import com.google.zxing.EncodeHintType
import com.google.zxing.qrcode.QRCodeWriter
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
-import java.util.*
-
-fun String?.ellipsizeBeforeSpace(allowedSize: Int): String {
- if (this.isNullOrBlank()) return ""
- val size = this.length
- val sizeDifference = size - allowedSize
- val endIndex = this.indexOf(" ")
- val startIndex = endIndex - sizeDifference
- val newString = this.removeRange(startIndex, endIndex)
- return newString.substring(0 until startIndex) + "..." +
- newString.substring(startIndex until newString.length)
-}
-
-fun String.colorSegment(
- context: Context,
- color: Int,
- startIndex: Int = 0,
- endIndex: Int = this.length,
-): Spannable {
- return this.toSpannable()
- .also { spannable ->
- spannable.setSpan(
- ForegroundColorSpan(ContextCompat.getColor(context, color)),
- startIndex,
- endIndex,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE,
- )
- }
-}
+import java.util.Hashtable
@Suppress("MagicNumber")
fun String.toQrCode(): Bitmap {
@@ -63,8 +29,6 @@ fun String.toQrCode(): Bitmap {
return bmp
}
-fun String.urlEncode(): String = Uri.encode(this)
-
fun String.removePrefixOrNull(prefix: String): String? = when {
startsWith(prefix) -> substring(prefix.length)
else -> null
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/StringBuilder.kt b/app/src/main/java/com/tangem/tap/common/extensions/StringBuilder.kt
deleted file mode 100644
index 961e77e8f7..0000000000
--- a/app/src/main/java/com/tangem/tap/common/extensions/StringBuilder.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.tangem.tap.common.extensions
-
-/**
-[REDACTED_AUTHOR]
- */
-fun StringBuilder.appendIf(value: String, predicate: (String) -> Boolean): StringBuilder {
- if (predicate(value)) this.append(value)
- return this
-}
-
-fun StringBuilder.appendIfNotNull(value: String?, prefix: String? = null, postfix: String? = null): StringBuilder {
- if (value == null) return this
-
- prefix?.let { append(it) }
- append(value)
- postfix?.let { append(it) }
- return this
-}
-
-fun String.appendIfNotNull(value: String?, prefix: String? = null, postfix: String? = null): String {
- return StringBuilder(this).apply { appendIfNotNull(value, prefix, postfix) }.toString()
-}
-
-fun StringBuilder.breakLine(count: Int = 1): StringBuilder = append("\n".repeat(count))
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Toast.kt b/app/src/main/java/com/tangem/tap/common/extensions/Toast.kt
deleted file mode 100644
index 23d969af40..0000000000
--- a/app/src/main/java/com/tangem/tap/common/extensions/Toast.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.tangem.tap.common.extensions
-
-import android.content.Context
-import android.view.View
-import android.widget.Toast
-import androidx.annotation.StringRes
-import androidx.fragment.app.Fragment
-
-fun Context.toast(message: String, length: Int = Toast.LENGTH_LONG) {
- Toast.makeText(this, message, length).show()
-}
-
-fun Context.toast(@StringRes messageRes: Int, length: Int = Toast.LENGTH_LONG) {
- Toast.makeText(this, this.getString(messageRes), length).show()
-}
-
-fun View.toast(message: String, length: Int = Toast.LENGTH_LONG) {
- context.toast(message, length)
-}
-
-fun View.toast(@StringRes messageRes: Int, length: Int = Toast.LENGTH_LONG) {
- context.toast(context.getString(messageRes), length)
-}
-
-fun Fragment.toast(message: String, length: Int = Toast.LENGTH_LONG) {
- context?.toast(message, length)
-}
-
-fun Fragment.toast(@StringRes messageRes: Int, length: Int = Toast.LENGTH_LONG) {
- context?.let { it.toast(it.getString(messageRes), length) }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Token.kt b/app/src/main/java/com/tangem/tap/common/extensions/Token.kt
deleted file mode 100644
index 7acbdfd9fb..0000000000
--- a/app/src/main/java/com/tangem/tap/common/extensions/Token.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.tangem.tap.common.extensions
-
-import android.graphics.Color
-import androidx.annotation.ColorInt
-import androidx.core.graphics.luminance
-import androidx.core.graphics.toColorInt
-import com.tangem.blockchain.common.Token
-
-@Suppress("MagicNumber")
-@ColorInt
-fun Token.getColor(isTestnet: Boolean = false): Int {
- val defaultColor = "#C7C7CC".toColorInt() // equivalent to R.color.lightGray4
-
- return if (isTestnet) {
- defaultColor
- } else {
- try {
- ("#" + this.contractAddress.subSequence(2..7).toString()).toColorInt()
- } catch (exception: Exception) {
- defaultColor
- }
- }
-}
-
-@Suppress("MagicNumber")
-@ColorInt
-fun Token.getTextColor(isTestnet: Boolean = false): Int = when {
- isTestnet -> Color.WHITE
- this.getColor().luminance > 0.5 -> Color.BLACK
- else -> Color.WHITE
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Transition.kt b/app/src/main/java/com/tangem/tap/common/extensions/Transition.kt
deleted file mode 100644
index 69fbba97b6..0000000000
--- a/app/src/main/java/com/tangem/tap/common/extensions/Transition.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.tangem.tap.common.extensions
-
-import androidx.transition.Transition
-
-/**
-[REDACTED_AUTHOR]
- */
-inline fun Transition.addListener(
- crossinline onStart: (animator: Transition) -> Unit = {},
- crossinline onEnd: (animator: Transition) -> Unit = {},
- crossinline onCancel: (animator: Transition) -> Unit = {},
- crossinline onPause: (animator: Transition) -> Unit = {},
- crossinline onRepeat: (animator: Transition) -> Unit = {}
-): Transition.TransitionListener {
- val listener = object : Transition.TransitionListener {
- override fun onTransitionStart(transition: Transition) = onStart(transition)
- override fun onTransitionEnd(transition: Transition) = onEnd(transition)
- override fun onTransitionCancel(transition: Transition) = onCancel(transition)
- override fun onTransitionPause(transition: Transition) = onPause(transition)
- override fun onTransitionResume(transition: Transition) = onRepeat(transition)
- }
- addListener(listener)
- return listener
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/UI.kt b/app/src/main/java/com/tangem/tap/common/extensions/UI.kt
index 28bfaad264..355da51669 100644
--- a/app/src/main/java/com/tangem/tap/common/extensions/UI.kt
+++ b/app/src/main/java/com/tangem/tap/common/extensions/UI.kt
@@ -2,37 +2,19 @@
package com.tangem.tap.common.extensions
-import android.app.Activity
-import android.content.ClipData
-import android.content.ClipboardManager
import android.content.Context
-import android.content.ContextWrapper
-import android.content.Intent
import android.graphics.drawable.Drawable
-import android.util.DisplayMetrics
-import android.util.TypedValue
import android.view.View
-import android.view.ViewGroup
-import android.view.inputmethod.InputMethodManager
import androidx.annotation.ColorInt
import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
-import androidx.annotation.PluralsRes
import androidx.annotation.StringRes
import androidx.core.content.ContextCompat
-import androidx.core.view.isVisible
-import androidx.fragment.app.Fragment
-import com.google.android.material.card.MaterialCardView
fun Context.getDrawableCompat(@DrawableRes drawableResId: Int): Drawable? {
return ContextCompat.getDrawable(this, drawableResId)
}
-@ColorInt
-fun Fragment.getColor(@ColorRes colorRes: Int): Int {
- return ContextCompat.getColor(requireContext(), colorRes)
-}
-
@ColorInt
fun Context.getColorCompat(@ColorRes colorRes: Int): Int {
return ContextCompat.getColor(this, colorRes)
@@ -51,10 +33,6 @@ fun View.getString(@StringRes id: Int, vararg formatArgs: String): String {
return context.getString(id, *formatArgs)
}
-fun View.getQuantityString(@PluralsRes id: Int, quantity: Int): String {
- return context.resources.getQuantityString(id, quantity, quantity)
-}
-
fun View.show(show: Boolean, invokeBeforeStateChanged: (() -> Unit)? = null) {
return if (show) this.show(invokeBeforeStateChanged) else this.hide(invokeBeforeStateChanged)
}
@@ -73,110 +51,6 @@ fun View.hide(invokeBeforeStateChanged: (() -> Unit)? = null) {
this.visibility = View.GONE
}
-fun View.invisible(invisible: Boolean = true, invokeBeforeStateChanged: (() -> Unit)? = null) {
- if (invisible) {
- if (this.visibility == View.INVISIBLE) return
-
- invokeBeforeStateChanged?.invoke()
- this.visibility = View.INVISIBLE
- } else {
- this.show(invokeBeforeStateChanged)
- }
-}
-
-fun Context.dpToPixels(dp: Int): Int =
- TypedValue.applyDimension(
- TypedValue.COMPLEX_UNIT_DIP,
- dp.toFloat(),
- this.resources.displayMetrics,
- ).toInt()
-
-fun Context.pixelsToDp(pixels: Int): Int {
- return (pixels.toFloat() /
- (resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT))
- .toInt()
-}
-
-tailrec fun Context?.getActivity(): Activity? = this as? Activity
- ?: (this as? ContextWrapper)?.baseContext?.getActivity()
-
-fun MaterialCardView.setMargins(
- marginLeftDp: Int = 16,
- marginTopDp: Int = 8,
- marginRightDp: Int = 16,
- marginBottomDp: Int = 8,
-) {
- val params = this.layoutParams
- (params as ViewGroup.MarginLayoutParams).setMargins(
- context.dpToPixels(marginLeftDp),
- context.dpToPixels(marginTopDp),
- context.dpToPixels(marginRightDp),
- context.dpToPixels(marginBottomDp),
- )
- this.layoutParams = params
-}
-
-fun View.hideKeyboard() {
- val inputMethodManager =
- context.getSystemService(android.content.Context.INPUT_METHOD_SERVICE) as? InputMethodManager
- inputMethodManager?.hideSoftInputFromWindow(this.windowToken, 0)
-}
-
-fun Context.copyToClipboard(value: Any, label: String = "") {
- val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager ?: return
-
- val clip: ClipData = ClipData.newPlainText(label, value.toString())
- clipboard.setPrimaryClip(clip)
-}
-
-fun Context.getFromClipboard(default: CharSequence? = null): CharSequence? {
- val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager
- ?: return default
- val clipData = clipboard.primaryClip ?: return default
- if (clipData.itemCount == 0) return default
-
- return clipData.getItemAt(0).text
-}
-
-fun Context.shareText(text: String) {
- val sendIntent: Intent = Intent().apply {
- action = Intent.ACTION_SEND
- putExtra(Intent.EXTRA_TEXT, text)
- type = "text/plain"
- }
- val shareIntent = Intent.createChooser(sendIntent, null)
- startActivity(shareIntent)
-}
-
-fun Fragment.shareText(text: String) {
- requireContext().shareText(text)
-}
-
fun View.getString(resId: Int, vararg formatArgs: Any?): String {
return context.getString(resId, *formatArgs)
-}
-
-fun View.animateVisibility(
- show: Boolean,
- durationMillis: Long = SHORT_ANIMATION_DURATION,
- hiddenVisibility: Int = View.GONE,
-) {
- if (show) {
- this.animate()
- .alpha(1f)
- .setDuration(durationMillis)
- .withStartAction {
- this.alpha = 0f
- this.isVisible = true
- }
- } else {
- this.animate()
- .alpha(0f)
- .setDuration(durationMillis)
- .withStartAction {
- this.visibility = hiddenVisibility
- }
- }
-}
-
-private const val SHORT_ANIMATION_DURATION = 80L
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/ValueCallback.kt b/app/src/main/java/com/tangem/tap/common/extensions/ValueCallback.kt
deleted file mode 100644
index 3dd4357bba..0000000000
--- a/app/src/main/java/com/tangem/tap/common/extensions/ValueCallback.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.tangem.tap.common.extensions
-
-/**
-[REDACTED_AUTHOR]
- */
-typealias ValueCallback = (T) -> Unit
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/ViewGroup.kt b/app/src/main/java/com/tangem/tap/common/extensions/ViewGroup.kt
index 50c90e1133..214138e5dc 100644
--- a/app/src/main/java/com/tangem/tap/common/extensions/ViewGroup.kt
+++ b/app/src/main/java/com/tangem/tap/common/extensions/ViewGroup.kt
@@ -3,15 +3,9 @@ package com.tangem.tap.common.extensions
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import android.view.ViewParent
-import androidx.core.view.forEach
import androidx.transition.AutoTransition
import androidx.transition.Transition
import androidx.transition.TransitionManager
-import com.google.android.material.chip.Chip
-import com.google.android.material.chip.ChipGroup
-import com.tangem.tap.common.GlobalLayoutStateHandler
-import timber.log.Timber
/**
[REDACTED_AUTHOR]
@@ -20,30 +14,6 @@ fun ViewGroup.inflate(viewToInflate: Int, attachToRoot: Boolean = false): View {
return LayoutInflater.from(context).inflate(viewToInflate, this, attachToRoot)
}
-fun ViewParent?.beginDelayedTransition(transition: Transition = AutoTransition()) {
- if (this == null) Timber.e("Can't invoke beginDelayedTransition, because parent is NULL")
- (this as? ViewGroup)?.beginDelayedTransition(transition)
-}
-
fun ViewGroup.beginDelayedTransition(transition: Transition = AutoTransition()) {
TransitionManager.beginDelayedTransition(this, transition)
-}
-
-fun View.beginDelayedTransition(transition: Transition = AutoTransition()) {
- (this as? ViewGroup)?.beginDelayedTransition(transition)
-}
-
-fun ChipGroup.fitChipsByGroupWidth() {
- val layoutStateHandler = GlobalLayoutStateHandler(this)
- layoutStateHandler.onStateChanged = stateHandler@{
- if (it.childCount < 2) {
- layoutStateHandler.detach()
- return@stateHandler
- }
-
- val spacingBetweenViews = it.chipSpacingHorizontal * (it.childCount - 1)
- val width = (it.width - spacingBetweenViews) / it.childCount
- it.forEach { chip -> (chip as? Chip)?.width = width }
- layoutStateHandler.detach()
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt b/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt
index 97997ba97f..d16033568b 100644
--- a/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt
+++ b/app/src/main/java/com/tangem/tap/common/extensions/WalletManager.kt
@@ -1,19 +1,19 @@
package com.tangem.tap.common.extensions
-import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.BlockchainSdkError
import com.tangem.blockchain.common.Wallet
import com.tangem.blockchain.common.WalletManager
+import com.tangem.blockchain.common.address.AddressType
+import com.tangem.blockchainsdk.utils.amountToCreateAccount
import com.tangem.common.services.Result
+import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.tap.common.TestActions
+import com.tangem.tap.common.apptheme.MutableAppThemeModeHolder
import com.tangem.tap.domain.TapError
-import com.tangem.tap.domain.extensions.amountToCreateAccount
import com.tangem.tap.domain.getFirstToken
-import com.tangem.tap.features.demo.isDemoCard
-import com.tangem.tap.features.wallet.redux.AddressData
-import com.tangem.tap.features.wallet.redux.reducers.createAddressesData
-import com.tangem.tap.network.NetworkConnectivity
+import com.tangem.tap.domain.model.WalletAddressData
import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager
+import com.tangem.tap.proxy.redux.DaggerGraphState
import com.tangem.tap.store
import kotlinx.coroutines.delay
import timber.log.Timber
@@ -21,11 +21,13 @@ import timber.log.Timber
/**
[REDACTED_AUTHOR]
*/
+@Deprecated(
+ message = "Use WalletStoresManager.fetch({userWalletId}, refresh = true) (to update all user wallet tokens)" +
+ "or WalletCurrenciesManager.update(...) (to update only one user wallet blockchain and its tokens) instead",
+)
@Suppress("MagicNumber")
-suspend fun WalletManager.safeUpdate(): Result = try {
- val scanResponse = store.state.globalState.scanResponse
-
- if (scanResponse?.isDemoCard() == true || TestActions.testAmountInjectionForWalletManagerEnabled) {
+suspend fun WalletManager.safeUpdate(isDemoCard: Boolean): Result = try {
+ if (isDemoCard || TestActions.testAmountInjectionForWalletManagerEnabled) {
delay(500)
TestActions.testAmountInjectionForWalletManagerEnabled = false
Result.Success(wallet)
@@ -36,11 +38,12 @@ suspend fun WalletManager.safeUpdate(): Result = try {
} catch (exception: Exception) {
Timber.e(exception)
- if (!NetworkConnectivity.getInstance().isOnlineOrConnecting()) {
+ val networkConnectionManager = store.inject(DaggerGraphState::networkConnectionManager)
+ if (!networkConnectionManager.isOnline) {
Result.Failure(TapError.NoInternetConnection)
} else {
val blockchain = wallet.blockchain
- val amountToCreateAccount = blockchain.amountToCreateAccount(wallet.getFirstToken())
+ val amountToCreateAccount = blockchain.amountToCreateAccount(this, wallet.getFirstToken())
if (exception is BlockchainSdkError.AccountNotFound && amountToCreateAccount != null) {
Result.Failure(TapError.WalletManager.NoAccountError(amountToCreateAccount.toString()))
@@ -56,30 +59,41 @@ suspend fun WalletManager.safeUpdate(): Result = try {
}
}
-fun WalletManager.getTopUpUrl(): String? {
+internal fun WalletManager.getTopUpUrl(cryptoCurrency: CryptoCurrency): String? {
val globalState = store.state.globalState
val defaultAddress = wallet.address
return globalState.exchangeManager.getUrl(
action = CurrencyExchangeManager.Action.Buy,
- blockchain = wallet.blockchain,
- cryptoCurrencyName = wallet.blockchain.currency,
+ cryptoCurrency = cryptoCurrency,
fiatCurrencyName = globalState.appCurrency.code,
walletAddress = defaultAddress,
+ isDarkTheme = MutableAppThemeModeHolder.isDarkThemeActive,
)
}
-fun WalletManager?.getAddressData(): AddressData? {
+internal fun WalletManager?.getAddressData(): WalletAddressData? {
val wallet = this?.wallet ?: return null
val addressDataList = wallet.createAddressesData()
return if (addressDataList.isEmpty()) null else addressDataList[0]
}
-fun WalletManager.Companion.stub(): T {
- val wallet = Wallet(Blockchain.Unknown, setOf(), Wallet.PublicKey(byteArrayOf(), null, null), setOf())
- return object : WalletManager(wallet) {
- override val currentHost: String = ""
- override suspend fun update() {}
- } as T
+private fun Wallet.createAddressesData(): List {
+ val listOfAddressData = mutableListOf()
+ // put a defaultAddress at the first place
+ addresses.forEach {
+ val addressData = WalletAddressData(
+ it.value,
+ it.type,
+ getShareUri(it.value),
+ getExploreUrl(it.value),
+ )
+ if (it.type == AddressType.Default) {
+ listOfAddressData.add(0, addressData)
+ } else {
+ listOfAddressData.add(addressData)
+ }
+ }
+ return listOfAddressData
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/WebView.kt b/app/src/main/java/com/tangem/tap/common/extensions/WebView.kt
deleted file mode 100644
index 7aa93b2bb1..0000000000
--- a/app/src/main/java/com/tangem/tap/common/extensions/WebView.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.tangem.tap.common.extensions
-
-import android.webkit.WebView
-
-/**
-[REDACTED_AUTHOR]
- */
-fun WebView.configureSettings() {
- resumeTimers()
- settings.apply {
- javaScriptEnabled = true
- domStorageEnabled = true
- }
-}
-
-fun WebView.stop() {
- stopLoading()
- pauseTimers()
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/feature/Feature.kt b/app/src/main/java/com/tangem/tap/common/feature/Feature.kt
deleted file mode 100644
index 1eb07546b4..0000000000
--- a/app/src/main/java/com/tangem/tap/common/feature/Feature.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.tangem.tap.common.feature
-
-/**
-[REDACTED_AUTHOR]
- */
-interface Feature {
- fun featureIsSwitchedOn(): Boolean
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/feedback/AdditionalFeedbackInfo.kt b/app/src/main/java/com/tangem/tap/common/feedback/AdditionalFeedbackInfo.kt
deleted file mode 100644
index c6f5bafd0a..0000000000
--- a/app/src/main/java/com/tangem/tap/common/feedback/AdditionalFeedbackInfo.kt
+++ /dev/null
@@ -1,124 +0,0 @@
-package com.tangem.tap.common.feedback
-
-import android.os.Build
-import com.tangem.blockchain.common.Amount
-import com.tangem.blockchain.common.AmountType
-import com.tangem.blockchain.common.Blockchain
-import com.tangem.blockchain.common.Token
-import com.tangem.blockchain.common.Wallet
-import com.tangem.blockchain.common.WalletManager
-import com.tangem.blockchain.common.address.Address
-import com.tangem.domain.common.CardDTO
-import com.tangem.domain.common.ScanResponse
-import com.tangem.tap.common.extensions.stripZeroPlainString
-import com.tangem.tap.domain.model.builders.UserWalletIdBuilder
-
-class AdditionalFeedbackInfo {
- class EmailWalletInfo(
- var blockchain: Blockchain = Blockchain.Unknown,
- var derivationPath: String = "",
- var outputsCount: String? = null,
- var host: String = "",
- var addresses: String = "",
- var explorerLink: String = "",
- )
-
- var appVersion: String = ""
-
- // card
- var cardId: String = ""
- var cardFirmwareVersion: String = ""
- var cardIssuer: String = ""
- var cardBlockchain: String = ""
- var userWalletId: String = ""
-
- // wallets
- internal val walletsInfo = mutableListOf()
- internal val tokens = mutableMapOf>()
- internal var onSendErrorWalletInfo: EmailWalletInfo? = null
- var signedHashesCount: String = ""
-
- // device
- var phoneModel: String = Build.MODEL
- var osVersion: String = Build.VERSION.SDK_INT.toString()
-
- // send error
- var destinationAddress: String = ""
- var amount: String = ""
- var fee: String = ""
- var token: String = ""
-
- private val Address.name: String
- get() = type.javaClass.simpleName
-
- fun setCardInfo(data: ScanResponse) {
- cardId = data.card.cardId
- cardBlockchain = data.walletData?.blockchain ?: ""
- cardFirmwareVersion = data.card.firmwareVersion.stringValue
- cardIssuer = data.card.issuer.name
- signedHashesCount = formatSignedHashes(data.card.wallets)
- userWalletId = UserWalletIdBuilder.scanResponse(data).build()?.stringValue ?: ""
- }
-
- fun setWalletsInfo(walletManagers: List) {
- walletsInfo.clear()
- tokens.clear()
- walletManagers.forEach { manager ->
- walletsInfo.add(createEmailWalletInfo(manager))
- if (manager.cardTokens.isNotEmpty()) {
- tokens[manager.wallet.blockchain] = manager.cardTokens
- }
- }
- }
-
- fun updateOnSendError(
- walletManager: WalletManager,
- amountToSend: Amount,
- feeAmount: Amount,
- destinationAddress: String,
- ) {
- onSendErrorWalletInfo = createEmailWalletInfo(walletManager)
- this.destinationAddress = destinationAddress
- amount = amountToSend.value?.stripZeroPlainString() ?: "0"
- fee = feeAmount.value?.stripZeroPlainString() ?: "0"
- token = if (amountToSend.type is AmountType.Token) amountToSend.currencySymbol else ""
- }
-
- private fun createEmailWalletInfo(walletManager: WalletManager): EmailWalletInfo {
- return EmailWalletInfo(
- blockchain = walletManager.wallet.blockchain,
- derivationPath = walletManager.wallet.publicKey.derivationPath?.rawPath ?: "",
- outputsCount = walletManager.outputsCount?.toString(),
- host = walletManager.currentHost,
- addresses = formatAddresses(walletManager.wallet),
- explorerLink = formatExploreUrls(walletManager.wallet),
- )
- }
-
- private fun formatSignedHashes(wallets: List): String {
- return wallets.joinToString("\n") { "Signed hashes: ${it.curve.curve} - ${it.totalSignedHashes}" }
- }
-
- private fun formatAddresses(wallet: Wallet): String {
- return wallet.formatAddressWith("Multiple address:") {
- "${it.name} - ${it.value}"
- }
- }
-
- private fun formatExploreUrls(wallet: Wallet): String {
- return wallet.formatAddressWith("Multiple explorers links:") {
- "${it.name} - ${wallet.getExploreUrl(it.value)}"
- }
- }
-
- @Suppress("MagicNumber")
- private fun Wallet.formatAddressWith(with: String, mapAddress: (Address) -> String): String {
- return if (addresses.size == 1) {
- getExploreUrl(address)
- } else {
- addresses.map { mapAddress(it) }.toMutableList()
- .apply { add(0, with) }
- .joinToString("\n")
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/feedback/FeedbackData.kt b/app/src/main/java/com/tangem/tap/common/feedback/FeedbackData.kt
deleted file mode 100644
index 452eb173aa..0000000000
--- a/app/src/main/java/com/tangem/tap/common/feedback/FeedbackData.kt
+++ /dev/null
@@ -1,111 +0,0 @@
-package com.tangem.tap.common.feedback
-
-import android.content.Context
-import com.tangem.domain.common.TapWorkarounds
-import com.tangem.tap.common.extensions.breakLine
-import com.tangem.wallet.R
-
-interface FeedbackData {
- val subjectResId: Int
- val mainMessageResId: Int
-
- fun getDataCollectionMessageResId(): Int = R.string.feedback_data_collection_message
-
- fun prepare(infoHolder: AdditionalFeedbackInfo) {}
-
- fun createOptionalMessage(infoHolder: AdditionalFeedbackInfo): String
-
- @Suppress("MagicNumber")
- fun joinTogether(context: Context, infoHolder: AdditionalFeedbackInfo): String {
- return StringBuilder().apply {
- append(context.getString(mainMessageResId))
- breakLine(3)
- append(context.getString(getDataCollectionMessageResId()))
- breakLine()
- append(createOptionalMessage(infoHolder))
- }.toString()
- }
-}
-
-class RateCanBeBetterEmail : FeedbackData {
- override val subjectResId: Int = R.string.feedback_subject_rate_negative
- override val mainMessageResId: Int = R.string.feedback_preface_rate_negative
-
- override fun createOptionalMessage(infoHolder: AdditionalFeedbackInfo): String = FeedbackDataBuilder(infoHolder)
- .appendCardInfo()
- .breakLine()
- .appendPhoneInfo()
- .build()
-}
-
-class ScanFailsEmail : FeedbackData {
-
- override val subjectResId: Int = R.string.feedback_subject_scan_failed
- override val mainMessageResId: Int = R.string.feedback_preface_scan_failed
-
- @Suppress("MagicNumber")
- override fun joinTogether(context: Context, infoHolder: AdditionalFeedbackInfo): String = StringBuilder().apply {
- append(context.getString(mainMessageResId))
- breakLine(4)
- append(createOptionalMessage(infoHolder))
- }.toString()
-
- override fun createOptionalMessage(infoHolder: AdditionalFeedbackInfo): String = FeedbackDataBuilder(infoHolder)
- .appendPhoneInfo()
- .build()
-}
-
-class SendTransactionFailedEmail(
- val error: String,
-) : FeedbackData {
-
- override val subjectResId: Int = R.string.feedback_subject_tx_failed
- override val mainMessageResId: Int = R.string.feedback_preface_tx_failed
-
- override fun createOptionalMessage(infoHolder: AdditionalFeedbackInfo): String = FeedbackDataBuilder(infoHolder)
- .appendCardInfo()
- .appendDelimiter()
- .appendTxFailedBlockchainInfo(error)
- .breakLine()
- .appendPhoneInfo()
- .build()
-}
-
-class FeedbackEmail : FeedbackData {
- override val subjectResId: Int
- get() = if (isS2CCard) s2cSubject else tangemSubject
- override val mainMessageResId: Int
- get() = if (isS2CCard) s2cMainMessage else tangemMainMessage
-
- private val tangemSubject: Int = R.string.feedback_subject_support_tangem
- private val tangemMainMessage: Int = R.string.feedback_preface_support
-
- private val s2cSubject: Int = R.string.feedback_subject_support
- private val s2cMainMessage: Int = R.string.feedback_preface_support
-
- private var isS2CCard = false
-
- override fun prepare(infoHolder: AdditionalFeedbackInfo) {
- isS2CCard = TapWorkarounds.isStart2CoinIssuer(infoHolder.cardIssuer)
- }
-
- override fun createOptionalMessage(infoHolder: AdditionalFeedbackInfo): String = FeedbackDataBuilder(infoHolder)
- .appendCardInfo()
- .appendWalletsInfo()
- .breakLine()
- .appendPhoneInfo()
- .build()
-}
-
-class SupportInfo : FeedbackData {
- override val subjectResId: Int = R.string.details_chat
- override val mainMessageResId: Int = R.string.details_chat
-
- override fun createOptionalMessage(infoHolder: AdditionalFeedbackInfo): String {
- return FeedbackDataBuilder(infoHolder)
- .appendCardInfo()
- .appendDelimiter()
- .appendPhoneInfo()
- .build()
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/feedback/FeedbackDataBuilder.kt b/app/src/main/java/com/tangem/tap/common/feedback/FeedbackDataBuilder.kt
deleted file mode 100644
index 4baf39c3e2..0000000000
--- a/app/src/main/java/com/tangem/tap/common/feedback/FeedbackDataBuilder.kt
+++ /dev/null
@@ -1,84 +0,0 @@
-package com.tangem.tap.common.feedback
-
-import com.tangem.tap.common.extensions.breakLine
-
-class FeedbackDataBuilder(
- private val infoHolder: AdditionalFeedbackInfo,
-) {
- val builder = StringBuilder()
-
- fun appendDelimiter(): FeedbackDataBuilder {
- builder.appendDelimiter()
- return this
- }
-
- fun breakLine(count: Int = 1): FeedbackDataBuilder {
- builder.breakLine(count)
- return this
- }
-
- fun appendCardInfo(): FeedbackDataBuilder {
- builder.appendKeyValue("Card ID", infoHolder.cardId)
- builder.appendKeyValue("Firmware version", infoHolder.cardFirmwareVersion)
- builder.appendKeyValue("Card Blockchain", infoHolder.cardBlockchain)
- builder.appendKeyValue("", infoHolder.signedHashesCount)
- builder.appendKeyValue("User Wallet ID", infoHolder.userWalletId)
- return this
- }
-
- fun appendWalletsInfo(): FeedbackDataBuilder {
- infoHolder.walletsInfo.forEach {
- builder.appendDelimiter()
- builder.appendKeyValue("Blockchain", it.blockchain.fullName)
- builder.appendKeyValue("Derivation path", it.derivationPath)
- builder.appendKeyValue("Outputs count", it.outputsCount)
-
- infoHolder.tokens[it.blockchain]?.let { tokens ->
- builder.append("Tokens:")
- breakLine()
- tokens.forEach { token ->
- builder.appendKeyValue("ID", token.id ?: "[custom token]")
- builder.appendKeyValue("Name", token.name)
- builder.appendKeyValue("Contract address", token.contractAddress)
- }
- }
-
- builder.appendKeyValue("Host", it.host)
- builder.appendKeyValue("Wallet address", it.addresses)
- builder.appendKeyValue("Explorer link", it.explorerLink)
- }
- return this
- }
-
- fun appendTxFailedBlockchainInfo(error: String): FeedbackDataBuilder {
- val walletInfo = infoHolder.onSendErrorWalletInfo ?: AdditionalFeedbackInfo.EmailWalletInfo()
- builder.appendKeyValue("Blockchain", walletInfo.blockchain.fullName)
- builder.appendKeyValue("Derivation path", walletInfo.derivationPath)
- builder.appendKeyValue("Host", walletInfo.host)
- builder.appendKeyValue("Token", infoHolder.token)
- builder.appendKeyValue("Error", error)
- builder.appendDelimiter()
- builder.appendKeyValue("Source address", walletInfo.addresses)
- builder.appendKeyValue("Destination address", infoHolder.destinationAddress)
- builder.appendKeyValue("Amount", infoHolder.amount)
- builder.appendKeyValue("Fee", infoHolder.fee)
- return this
- }
-
- fun appendPhoneInfo(): FeedbackDataBuilder {
- builder.appendKeyValue("Phone model", infoHolder.phoneModel)
- builder.appendKeyValue("OS version", infoHolder.osVersion)
- builder.appendKeyValue("App version", infoHolder.appVersion)
- return this
- }
-
- fun build(): String = builder.toString()
-}
-
-private fun StringBuilder.appendKeyValue(key: String, value: String?): StringBuilder = when {
- value.isNullOrBlank() -> this
- key.isBlank() -> this.append("$value\n")
- else -> this.append("$key: $value\n")
-}
-
-private fun StringBuilder.appendDelimiter(): StringBuilder = append("----------\n")
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/feedback/FeedbackManager.kt b/app/src/main/java/com/tangem/tap/common/feedback/FeedbackManager.kt
deleted file mode 100644
index b44db4004b..0000000000
--- a/app/src/main/java/com/tangem/tap/common/feedback/FeedbackManager.kt
+++ /dev/null
@@ -1,141 +0,0 @@
-package com.tangem.tap.common.feedback
-
-import android.content.Context
-import android.os.Build
-import com.tangem.core.analytics.Analytics
-import com.tangem.domain.common.TapWorkarounds
-import com.tangem.tap.common.extensions.sendEmail
-import com.tangem.tap.common.log.TangemLogCollector
-import com.tangem.tap.common.zendesk.ZendeskConfig
-import com.tangem.tap.foregroundActivityObserver
-import com.tangem.tap.persistence.PreferencesStorage
-import com.tangem.tap.withForegroundActivity
-import com.tangem.wallet.R
-import timber.log.Timber
-import zendesk.chat.Chat
-import zendesk.chat.ChatConfiguration
-import zendesk.chat.ChatEngine
-import zendesk.chat.ChatProvidersConfiguration
-import zendesk.chat.VisitorInfo
-import zendesk.configurations.Configuration
-import zendesk.messaging.MessagingActivity
-import java.io.File
-import java.io.FileWriter
-import java.io.StringWriter
-
-/**
-[REDACTED_AUTHOR]
- */
-class FeedbackManager(
- val infoHolder: AdditionalFeedbackInfo,
- private val logCollector: TangemLogCollector,
- private val preferencesStorage: PreferencesStorage,
-) {
- private var lastUsedConfigForInitialization: ZendeskConfig? = null
-
- var chatInitializer: ((ZendeskConfig) -> Unit)? = null
-
- fun initChat(zendeskConfig: ZendeskConfig) {
- // prevent double initialization with the same config
- if (lastUsedConfigForInitialization == zendeskConfig) return
-
- lastUsedConfigForInitialization = zendeskConfig
- chatInitializer?.invoke(zendeskConfig)
- }
-
- fun sendEmail(feedbackData: FeedbackData, onFail: ((Exception) -> Unit)? = null) {
- feedbackData.prepare(infoHolder)
- foregroundActivityObserver.withForegroundActivity { activity ->
- val fileLog = if (feedbackData is ScanFailsEmail) createLogFile(activity) else null
- activity.sendEmail(
- email = getSupportEmail(),
- subject = activity.getString(feedbackData.subjectResId),
- message = feedbackData.joinTogether(activity, infoHolder),
- file = fileLog,
- onFail = onFail,
- )
- }
- }
-
- fun openChat(feedbackData: FeedbackData) {
- feedbackData.prepare(infoHolder)
- foregroundActivityObserver.withForegroundActivity { activity ->
- setChatVisitorInfo()
- setChatVisitorNote(activity, feedbackData)
- showMessagingActivity(activity)
- }
- }
-
- private fun createLogFile(context: Context): File? {
- return try {
- val file = File(context.filesDir, "logs.txt")
- file.delete()
- file.createNewFile()
-
- val stringWriter = StringWriter()
- logCollector.getLogs().forEach { stringWriter.append(it) }
- val fileWriter = FileWriter(file)
- fileWriter.write(stringWriter.toString())
- fileWriter.close()
- logCollector.clearLogs()
- file
- } catch (ex: Exception) {
- Timber.e(ex, "Can't create the logs file")
- null
- }
- }
-
- private fun setChatVisitorInfo() {
- if (preferencesStorage.chatFirstLaunchTime == null) {
- preferencesStorage.chatFirstLaunchTime = System.currentTimeMillis()
- }
- val chatUserId = (preferencesStorage.chatFirstLaunchTime.toString() + Build.MODEL).hashCode()
- val visitorInfo = VisitorInfo.builder()
- .withName("User $chatUserId")
- .build()
-
- Chat.INSTANCE.chatProvidersConfiguration = ChatProvidersConfiguration.builder()
- .withVisitorInfo(visitorInfo)
- .build()
- }
-
- private fun setChatVisitorNote(
- context: Context,
- feedbackData: FeedbackData,
- ) {
- Chat.INSTANCE.providers()
- ?.profileProvider()
- ?.setVisitorNote(feedbackData.joinTogether(context, infoHolder))
- }
-
- private fun showMessagingActivity(context: Context) {
- Analytics.send(com.tangem.tap.common.analytics.events.Chat.ScreenOpened())
- MessagingActivity.builder()
- .withMultilineResponseOptionsEnabled(false)
- .withBotLabelStringRes(R.string.chat_bot_name)
- .withBotAvatarDrawable(R.mipmap.ic_launcher)
- .withEngines(ChatEngine.engine())
- .show(context, buildChatConfig())
- }
-
- private fun buildChatConfig(): Configuration {
- return ChatConfiguration.builder()
- .withOfflineFormEnabled(true)
- .withAgentAvailabilityEnabled(true)
- .withPreChatFormEnabled(false)
- .build()
- }
-
- private fun getSupportEmail(): String {
- return if (TapWorkarounds.isStart2CoinIssuer(infoHolder.cardIssuer)) {
- S2C_SUPPORT_EMAIL
- } else {
- DEFAULT_SUPPORT_EMAIL
- }
- }
-
- companion object {
- const val DEFAULT_SUPPORT_EMAIL = "support@tangem.com"
- const val S2C_SUPPORT_EMAIL = "cardsupport@start2coin.com"
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/finisher/AndroidAppFinisher.kt b/app/src/main/java/com/tangem/tap/common/finisher/AndroidAppFinisher.kt
new file mode 100644
index 0000000000..10299c8916
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/finisher/AndroidAppFinisher.kt
@@ -0,0 +1,27 @@
+package com.tangem.tap.common.finisher
+
+import android.content.Context
+import android.content.Intent
+import com.tangem.core.navigation.finisher.AppFinisher
+import com.tangem.tap.MainActivity
+import com.tangem.tap.foregroundActivityObserver
+import com.tangem.tap.withForegroundActivity
+
+internal class AndroidAppFinisher(
+ private val appContext: Context,
+) : AppFinisher {
+
+ override fun finish() {
+ foregroundActivityObserver.withForegroundActivity { activity ->
+ activity.finish()
+ }
+ }
+
+ override fun restart() {
+ val intent = Intent(appContext, MainActivity::class.java).apply {
+ flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
+ }
+ appContext.startActivity(intent)
+ Runtime.getRuntime().exit(0)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/haptic/DefaultVibratorHapticManager.kt b/app/src/main/java/com/tangem/tap/common/haptic/DefaultVibratorHapticManager.kt
new file mode 100644
index 0000000000..2bcae01131
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/haptic/DefaultVibratorHapticManager.kt
@@ -0,0 +1,38 @@
+package com.tangem.tap.common.haptic
+
+import android.os.Build
+import android.os.VibrationEffect
+import android.os.Vibrator
+import androidx.annotation.ChecksSdkIntAtLeast
+import com.tangem.core.ui.haptic.TangemHapticEffect
+import com.tangem.core.ui.haptic.VibratorHapticManager
+
+internal class DefaultVibratorHapticManager(
+ private val vibrator: Vibrator,
+) : VibratorHapticManager {
+
+ private val isHapticEnabled = deviceSupportsVibrationEffects()
+
+ @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.Q)
+ private fun deviceSupportsVibrationEffects(): Boolean = when {
+ !vibrator.hasVibrator() -> false
+
+ Build.VERSION.SDK_INT >= Build.VERSION_CODES.R ->
+ vibrator.areAllEffectsSupported(
+ TangemHapticEffect.OneTime.DoubleClick.code,
+ TangemHapticEffect.OneTime.HeavyClick.code,
+ TangemHapticEffect.OneTime.Tick.code,
+ TangemHapticEffect.OneTime.Click.code,
+ ) == Vibrator.VIBRATION_EFFECT_SUPPORT_YES
+
+ Build.VERSION.SDK_INT == Build.VERSION_CODES.Q -> true
+
+ else -> false
+ }
+
+ override fun performOneTime(effect: TangemHapticEffect.OneTime) {
+ if (!isHapticEnabled) return
+
+ vibrator.vibrate(VibrationEffect.createPredefined(effect.code))
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/images/Coil.kt b/app/src/main/java/com/tangem/tap/common/images/Coil.kt
index 4e5a88d6e0..4b269bdca4 100644
--- a/app/src/main/java/com/tangem/tap/common/images/Coil.kt
+++ b/app/src/main/java/com/tangem/tap/common/images/Coil.kt
@@ -3,17 +3,17 @@ package com.tangem.tap.common.images
import android.content.Context
import android.util.Log
import coil.ImageLoader
+import coil.memory.MemoryCache
+import coil.request.CachePolicy
import coil.util.Logger
+import com.tangem.datasource.api.common.createNetworkLoggingInterceptor
import okhttp3.OkHttpClient
-import okhttp3.logging.HttpLoggingInterceptor
import timber.log.Timber
private const val COIL_LOG_TAG = "COIL"
+private const val COIL_MEMORY_CACHE_SIZE = 0.25
-fun createCoilImageLoader(
- context: Context,
- logEnabled: Boolean = false,
-): ImageLoader {
+fun createCoilImageLoader(context: Context, logEnabled: Boolean = false): ImageLoader {
return ImageLoader.Builder(context)
.apply {
if (!logEnabled) return@apply
@@ -21,17 +21,16 @@ fun createCoilImageLoader(
logger(CoilTimberLogger())
okHttpClient {
OkHttpClient.Builder()
- .addNetworkInterceptor(
- HttpLoggingInterceptor { message ->
- Timber.tag(COIL_LOG_TAG).d(message)
- }
- .apply {
- level = HttpLoggingInterceptor.Level.BODY
- }
- )
+ .addNetworkInterceptor(createNetworkLoggingInterceptor())
.build()
}
}
+ .memoryCachePolicy(CachePolicy.ENABLED)
+ .memoryCache {
+ MemoryCache.Builder(context)
+ .maxSizePercent(COIL_MEMORY_CACHE_SIZE)
+ .build()
+ }
.build()
}
diff --git a/app/src/main/java/com/tangem/tap/common/images/DefaultImagePreloader.kt b/app/src/main/java/com/tangem/tap/common/images/DefaultImagePreloader.kt
new file mode 100644
index 0000000000..ab8c4410f8
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/images/DefaultImagePreloader.kt
@@ -0,0 +1,21 @@
+package com.tangem.tap.common.images
+
+import android.content.Context
+import coil.imageLoader
+import coil.request.CachePolicy
+import coil.request.ImageRequest
+import com.tangem.core.ui.coil.ImagePreloader
+
+internal class DefaultImagePreloader(
+ private val appContext: Context,
+) : ImagePreloader {
+ override fun preload(url: String) {
+ appContext.imageLoader.enqueue(
+ ImageRequest.Builder(appContext)
+ .data(url)
+ .memoryCacheKey(url)
+ .memoryCachePolicy(CachePolicy.ENABLED)
+ .build(),
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/leapfrogWidget/TestLeapfrogFragment.kt b/app/src/main/java/com/tangem/tap/common/leapfrogWidget/TestLeapfrogFragment.kt
deleted file mode 100644
index 98a06327bb..0000000000
--- a/app/src/main/java/com/tangem/tap/common/leapfrogWidget/TestLeapfrogFragment.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.tangem.tap.common.leapfrogWidget
-
-import android.os.Bundle
-import android.view.View
-import android.widget.FrameLayout
-import androidx.fragment.app.Fragment
-import androidx.transition.TransitionInflater
-import by.kirich1409.viewbindingdelegate.viewBinding
-import com.tangem.tangem_sdk_new.ui.widget.leapfrogWidget.LeapfrogWidget
-import com.tangem.tangem_sdk_new.ui.widget.leapfrogWidget.LeapfrogWidgetState
-import com.tangem.tap.domain.twins.TwinsCardWidget
-import com.tangem.wallet.R
-import com.tangem.wallet.databinding.TestLeapfrogFragmentBinding
-
-class TestLeapfrogFragment : Fragment(R.layout.test_leapfrog_fragment) {
-
- private lateinit var twinsCardWidget: TwinsCardWidget
- private val binding: TestLeapfrogFragmentBinding by viewBinding(TestLeapfrogFragmentBinding::bind)
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- val inflater = TransitionInflater.from(requireContext())
- exitTransition = inflater.inflateTransition(R.transition.fade)
- }
-
- @Suppress("MagicNumber")
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
-
- val leapfrogContainer: FrameLayout = view.findViewById(R.id.leapfrog_views_container)
- val leapfrog = LeapfrogWidget(leapfrogContainer)
- twinsCardWidget = TwinsCardWidget(leapfrog) { 200f }
-
- binding.btnTwinWelcome.setOnClickListener {
- twinsCardWidget.toWelcome()
- }
- binding.btnTwinToLeapfrog.setOnClickListener {
- twinsCardWidget.toLeapfrog()
- }
- binding.btnTwinActivate.setOnClickListener {
- twinsCardWidget.toActivate()
- }
-
- binding.btnLpInit.setOnClickListener {
- leapfrog.initViews()
- }
- binding.btnLpUnfold.setOnClickListener {
- leapfrog.unfold()
- }
- binding.btnLpFold.setOnClickListener {
- leapfrog.fold()
- }
- binding.btnLpLeap.setOnClickListener {
- leapfrog.leap()
- }
- binding.btnLpLeapBack.setOnClickListener {
- leapfrog.leapBack()
- }
- }
-
- override fun onStart() {
- super.onStart()
- leapfrogWidgetState?.let { twinsCardWidget.leapfrogWidget.applyState(it) }
- }
-
- override fun onStop() {
- super.onStop()
- leapfrogWidgetState = twinsCardWidget.leapfrogWidget.getState()
- }
-}
-
-private var leapfrogWidgetState: LeapfrogWidgetState? = null
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/libs/blockchainsdk/DefaultTransactionSignerFactory.kt b/app/src/main/java/com/tangem/tap/common/libs/blockchainsdk/DefaultTransactionSignerFactory.kt
new file mode 100644
index 0000000000..e31c519069
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/libs/blockchainsdk/DefaultTransactionSignerFactory.kt
@@ -0,0 +1,24 @@
+package com.tangem.tap.common.libs.blockchainsdk
+
+import com.tangem.Message
+import com.tangem.TangemSdk
+import com.tangem.blockchain.common.TransactionSigner
+import com.tangem.data.card.TransactionSignerFactory
+import com.tangem.domain.card.models.TwinKey
+import com.tangem.tap.common.redux.global.GlobalAction
+import com.tangem.tap.domain.TangemSigner
+import com.tangem.tap.store
+
+internal class DefaultTransactionSignerFactory : TransactionSignerFactory {
+
+ override fun createTransactionSigner(cardId: String?, sdk: TangemSdk, twinKey: TwinKey?): TransactionSigner {
+ return TangemSigner(
+ cardId = cardId,
+ tangemSdk = sdk,
+ initialMessage = Message(),
+ twinKey = twinKey,
+ ) { signResponse ->
+ store.dispatch(action = GlobalAction.IsSignWithRing(signResponse.isRing))
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/log/TangemAppLoggerInitializer.kt b/app/src/main/java/com/tangem/tap/common/log/TangemAppLoggerInitializer.kt
new file mode 100644
index 0000000000..a2011ff5e7
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/log/TangemAppLoggerInitializer.kt
@@ -0,0 +1,51 @@
+package com.tangem.tap.common.log
+
+import android.util.Log
+import com.orhanobut.logger.AndroidLogAdapter
+import com.orhanobut.logger.Logger
+import com.tangem.datasource.local.logs.AppLogsStore
+import com.tangem.wallet.BuildConfig
+import timber.log.Timber
+
+/**
+ * Tangem app logger
+ *
+ * @property appLogsStore app logs store
+ *
+[REDACTED_AUTHOR]
+ */
+class TangemAppLoggerInitializer(
+ private val appLogsStore: AppLogsStore,
+) {
+
+ /** Initialize */
+ fun initialize() {
+ if (IS_LOG_ENABLED) {
+ Logger.addLogAdapter(AndroidLogAdapter(TimberFormatStrategy()))
+ }
+
+ Timber.plant(tree = createTimberTree())
+ }
+
+ private fun createTimberTree(): Timber.Tree {
+ return object : Timber.DebugTree() {
+ override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
+ if (IS_LOG_ENABLED) {
+ Logger.log(priority, tag, message, t)
+ }
+
+ if (PERMITTED_PRIORITY.contains(priority)) {
+ appLogsStore.saveLogMessage(
+ tag = tag ?: "TangemAppLogger",
+ message = message,
+ )
+ }
+ }
+ }
+ }
+
+ private companion object {
+ val IS_LOG_ENABLED: Boolean = BuildConfig.LOG_ENABLED
+ val PERMITTED_PRIORITY = listOf(Log.ERROR, Log.INFO)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/log/TangemCardSDKLogger.kt b/app/src/main/java/com/tangem/tap/common/log/TangemCardSDKLogger.kt
new file mode 100644
index 0000000000..e9c1efdd96
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/log/TangemCardSDKLogger.kt
@@ -0,0 +1,30 @@
+package com.tangem.tap.common.log
+
+import com.tangem.Log
+import com.tangem.LogFormat
+import com.tangem.TangemSdkLogger
+import com.tangem.datasource.local.logs.AppLogsStore
+
+/**
+ * CardSDK logger implementation
+ *
+ * @property levels logging levels
+ * @property messageFormatter message formatter
+ * @property appLogsStore app logs store
+ *
+[REDACTED_AUTHOR]
+ */
+@Suppress("UnusedPrivateMember")
+internal class TangemCardSDKLogger(
+ private val levels: List,
+ private val messageFormatter: LogFormat,
+ private val appLogsStore: AppLogsStore,
+) : TangemSdkLogger {
+
+ override fun log(message: () -> String, level: Log.Level) {
+ // Disabled for now in [REDACTED_JIRA]
+ // if (!levels.contains(level)) return
+ //
+ // appLogsStore.saveLogMessage(message = messageFormatter.format(message, level))
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/log/TangemLogCollector.kt b/app/src/main/java/com/tangem/tap/common/log/TangemLogCollector.kt
deleted file mode 100644
index 54a56e17c3..0000000000
--- a/app/src/main/java/com/tangem/tap/common/log/TangemLogCollector.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.tangem.tap.common.log
-
-import com.tangem.Log
-import com.tangem.LogFormat
-import com.tangem.TangemSdkLogger
-import java.text.SimpleDateFormat
-import java.util.*
-
-class TangemLogCollector(
- private val levels: List,
- private val messageFormatter: LogFormat,
-) : TangemSdkLogger {
-
- private val dateFormatter = SimpleDateFormat("HH:mm:ss.SSS")
- private val logs = mutableListOf()
- private val mutex = Object()
-
- override fun log(message: () -> String, level: Log.Level) {
- if (!levels.contains(level)) return
-
- synchronized(mutex) {
- val formattedMessage = messageFormatter.format(message, level)
- val logMessage = "${dateFormatter.format(Date())}: $formattedMessage"
- logs.add("$logMessage\n")
- }
- }
-
- fun getLogs(): List = synchronized(mutex) { logs.toList() }
-
- fun clearLogs() = synchronized(mutex) { logs.clear() }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/log/TimberFormatStrategy.kt b/app/src/main/java/com/tangem/tap/common/log/TimberFormatStrategy.kt
new file mode 100644
index 0000000000..0a43f525d4
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/log/TimberFormatStrategy.kt
@@ -0,0 +1,63 @@
+package com.tangem.tap.common.log
+
+import com.orhanobut.logger.FormatStrategy
+import com.orhanobut.logger.LogStrategy
+import com.orhanobut.logger.LogcatLogStrategy
+
+class TimberFormatStrategy : FormatStrategy {
+
+ private val logStrategy: LogStrategy = LogcatLogStrategy()
+
+ override fun log(priority: Int, tag: String?, message: String) {
+ logTopBorder(priority, tag)
+ val bytes = message.toByteArray()
+ val length = bytes.size
+ if (length <= CHUNK_SIZE) {
+ logContent(priority, tag, message)
+ logBottomBorder(priority, tag)
+ return
+ }
+ var i = 0
+ while (i < length) {
+ val count = (length - i).coerceAtMost(CHUNK_SIZE)
+ // create a new String with system's default charset (which is UTF-8 for Android)
+ logContent(priority, tag, String(bytes, i, count))
+ i += CHUNK_SIZE
+ }
+ logBottomBorder(priority, tag)
+ }
+
+ private fun logTopBorder(logType: Int, tag: String?) {
+ logChunk(logType, tag, TOP_BORDER)
+ }
+
+ private fun logBottomBorder(logType: Int, tag: String?) {
+ logChunk(logType, tag, BOTTOM_BORDER)
+ }
+
+ private fun logContent(logType: Int, tag: String?, chunk: String) {
+ chunk.split(System.lineSeparator()).forEach { line ->
+ logChunk(logType, tag, "$HORIZONTAL_LINE $line")
+ }
+ }
+
+ private fun logChunk(priority: Int, tag: String?, chunk: String) {
+ logStrategy.log(priority, tag, chunk)
+ }
+
+ private companion object {
+ /**
+ * Android's max limit for a log entry is ~4076 bytes,
+ * so 4000 bytes is used as chunk size since default charset
+ * is UTF-8
+ */
+ private const val CHUNK_SIZE = 4000
+
+ const val TOP_LEFT_CORNER = "┌"
+ const val BOTTOM_LEFT_CORNER = "└"
+ const val HORIZONTAL_LINE = "│"
+ const val DOUBLE_DIVIDER = "────────────────────────────────────────────────────────"
+ const val TOP_BORDER = TOP_LEFT_CORNER + DOUBLE_DIVIDER + DOUBLE_DIVIDER
+ const val BOTTOM_BORDER = BOTTOM_LEFT_CORNER + DOUBLE_DIVIDER + DOUBLE_DIVIDER
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/pushes/TangemPushNotificationService.kt b/app/src/main/java/com/tangem/tap/common/pushes/TangemPushNotificationService.kt
new file mode 100644
index 0000000000..9bdca56b66
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/pushes/TangemPushNotificationService.kt
@@ -0,0 +1,105 @@
+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() {
+
+ override fun onNewToken(token: String) {
+ super.onNewToken(token)
+ Timber.d("New FCM token received: $token")
+ }
+
+ override fun onMessageReceived(message: RemoteMessage) {
+ super.onMessageReceived(message)
+
+ val notification = message.notification ?: return
+ val channelId = notification.channelId ?: TANGEM_CHANNEL_ID
+
+ // TODO refactoring: [REDACTED_JIRA]
+ val intent = Intent(applicationContext, MainActivity::class.java)
+ intent.putExtra(OnPushClickedIntentHandler.OPENED_FROM_GCM_PUSH, true)
+ intent.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,
+ )
+
+ 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
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/qrCodeScan/ScanQrCodeActivity.kt b/app/src/main/java/com/tangem/tap/common/qrCodeScan/ScanQrCodeActivity.kt
deleted file mode 100644
index 4a86caa20d..0000000000
--- a/app/src/main/java/com/tangem/tap/common/qrCodeScan/ScanQrCodeActivity.kt
+++ /dev/null
@@ -1,68 +0,0 @@
-package com.tangem.tap.common.qrCodeScan
-
-import android.Manifest
-import android.content.Intent
-import android.content.pm.PackageManager
-import android.os.Build
-import android.os.Bundle
-import androidx.appcompat.app.AppCompatActivity
-import androidx.core.app.ActivityCompat
-import androidx.core.content.ContextCompat
-import com.google.zxing.Result
-import com.otaliastudios.cameraview.CameraView.PERMISSION_REQUEST_CODE
-import me.dm7.barcodescanner.zxing.ZXingScannerView
-
-/**
-[REDACTED_AUTHOR]
- */
-class ScanQrCodeActivity : AppCompatActivity(), ZXingScannerView.ResultHandler {
- private lateinit var mScannerView: ZXingScannerView
-
- override fun onCreate(state: Bundle?) {
- super.onCreate(state)
- mScannerView = ZXingScannerView(this)
- setContentView(mScannerView)
-
- if (!permissionIsGranted()) requestPermission()
- }
-
- override fun onResume() {
- super.onResume()
- mScannerView.setResultHandler(this)
- mScannerView.startCamera()
- }
-
- override fun onPause() {
- super.onPause()
- mScannerView.stopCamera()
- }
-
- override fun handleResult(result: Result) {
- setResult(SCAN_QR_REQUEST_CODE, Intent().apply { putExtra(SCAN_RESULT, result.text) })
- finish()
- }
-
- override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
- if (requestCode != PERMISSION_REQUEST_CODE) return
-
- if (grantResults.isEmpty() || grantResults[0] != PackageManager.PERMISSION_GRANTED) {
- finish()
- }
- }
-
- private fun permissionIsGranted(): Boolean {
- return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- val cameraPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
- cameraPermission == PackageManager.PERMISSION_GRANTED
- } else true
- }
-
- private fun requestPermission() {
- ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), PERMISSION_REQUEST_CODE)
- }
-
- companion object {
- const val SCAN_QR_REQUEST_CODE = 1001
- const val SCAN_RESULT = "scanResult"
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/recyclerView/SpaceItemDecoration.kt b/app/src/main/java/com/tangem/tap/common/recyclerView/SpaceItemDecoration.kt
deleted file mode 100644
index b1d16fc3f6..0000000000
--- a/app/src/main/java/com/tangem/tap/common/recyclerView/SpaceItemDecoration.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.tangem.tap.common.recyclerView
-
-import android.graphics.Rect
-import android.view.View
-import androidx.recyclerview.widget.RecyclerView
-import com.tangem.tangem_sdk_new.extensions.dpToPx
-
-class SpaceItemDecoration(
- private val horizontalSpaceDp: Float,
- private val verticalSpaceDp: Float,
-) : RecyclerView.ItemDecoration() {
-
- private lateinit var space: Space
-
- override fun getItemOffsets(
- outRect: Rect,
- view: View,
- parent: RecyclerView,
- state: RecyclerView.State
- ) {
- if (state.itemCount == 0) return
- if (!::space.isInitialized) {
- space = Space(
- view.dpToPx(horizontalSpaceDp).toInt(),
- view.dpToPx(verticalSpaceDp).toInt()
- )
- }
-
- outRect.left = space.horizontal
- outRect.right = space.horizontal
-
- when (state.itemCount) {
- 1 -> {
- outRect.top = space.vertical
- outRect.bottom = space.vertical
- }
- else -> {
- val adapterPosition = parent.getChildAdapterPosition(view)
- if (adapterPosition == -1) return
-
- when (adapterPosition) {
- 0 -> {
- // first
- outRect.top = space.vertical
- outRect.bottom = space.vertical / 2
- }
- state.itemCount - 1 -> {
- // last
- outRect.top = space.vertical / 2
- outRect.bottom = space.vertical
- }
- else -> {
- // middle
- outRect.top = space.vertical / 2
- outRect.bottom = space.vertical / 2
- }
- }
- }
- }
- }
-
- private data class Space(
- val horizontal: Int,
- val vertical: Int,
- )
-
- companion object {
- fun all(dp: Float): SpaceItemDecoration = SpaceItemDecoration(dp, dp)
- fun vertical(dp: Float): SpaceItemDecoration = SpaceItemDecoration(0f, dp)
- fun horizontal(dp: Float): SpaceItemDecoration = SpaceItemDecoration(dp, 0f)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/redux/AccessCodeRequestPolicyMiddleware.kt b/app/src/main/java/com/tangem/tap/common/redux/AccessCodeRequestPolicyMiddleware.kt
index e9aaabfd70..57be8c6e21 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/AccessCodeRequestPolicyMiddleware.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/AccessCodeRequestPolicyMiddleware.kt
@@ -1,9 +1,12 @@
package com.tangem.tap.common.redux
-import com.tangem.domain.common.ScanResponse
+import com.tangem.domain.models.scan.ScanResponse
+import com.tangem.tap.common.extensions.inject
import com.tangem.tap.common.redux.global.GlobalAction
-import com.tangem.tap.preferencesStorage
-import com.tangem.tap.tangemSdkManager
+import com.tangem.tap.mainScope
+import com.tangem.tap.proxy.redux.DaggerGraphState
+import com.tangem.tap.store
+import kotlinx.coroutines.launch
import org.rekotlin.Middleware
class AccessCodeRequestPolicyMiddleware {
@@ -19,9 +22,12 @@ class AccessCodeRequestPolicyMiddleware {
}
private fun updateAccessCodeRequestPolicy(scanResponse: ScanResponse) {
- tangemSdkManager.setAccessCodeRequestPolicy(
- useBiometricsForAccessCode = preferencesStorage.shouldSaveAccessCodes &&
- scanResponse.card.isAccessCodeSet,
- )
+ mainScope.launch {
+ val shouldSaveAccessCodes = store.inject(DaggerGraphState::settingsRepository).shouldSaveAccessCodes()
+
+ store.inject(DaggerGraphState::cardSdkConfigRepository).setAccessCodeRequestPolicy(
+ isBiometricsRequestPolicy = shouldSaveAccessCodes && scanResponse.card.isAccessCodeSet,
+ )
+ }
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/redux/AppDialog.kt b/app/src/main/java/com/tangem/tap/common/redux/AppDialog.kt
new file mode 100644
index 0000000000..1188cd7d03
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/redux/AppDialog.kt
@@ -0,0 +1,53 @@
+package com.tangem.tap.common.redux
+
+import com.tangem.common.extensions.VoidCallback
+import com.tangem.domain.redux.StateDialog
+import com.tangem.tap.common.TestAction
+import com.tangem.tap.domain.model.Currency
+import com.tangem.tap.domain.model.WalletAddressData
+import com.tangem.wallet.R
+
+/**
+[REDACTED_AUTHOR]
+ */
+sealed class AppDialog : StateDialog {
+ data class SimpleOkDialogRes(
+ val headerId: Int,
+ val messageId: Int,
+ val args: List = emptyList(),
+ val onOk: VoidCallback? = null,
+ ) : AppDialog()
+
+ internal data class AddressInfoDialog(
+ val currency: Currency,
+ val addressData: WalletAddressData,
+ ) : AppDialog()
+
+ data class TestActionsDialog(
+ val actionsList: List,
+ ) : AppDialog()
+
+ data class RemoveWalletDialog(
+ val currencyTitle: String,
+ val onOk: () -> Unit,
+ ) : AppDialog() {
+ val messageRes: Int = R.string.token_details_hide_alert_message
+ val titleRes: Int = R.string.token_details_hide_alert_title
+ val primaryButtonRes: Int = R.string.token_details_hide_alert_hide
+ }
+
+ data class TokensAreLinkedDialog(
+ val currencyTitle: String,
+ val currencySymbol: String,
+ val networkName: String,
+ ) : AppDialog() {
+ val messageRes: Int = R.string.token_details_unable_hide_alert_message
+ val titleRes: Int = R.string.token_details_unable_hide_alert_title
+ }
+
+ data class WalletAlreadyWasUsedDialog(
+ val onOk: () -> Unit,
+ val onSupportClick: () -> Unit,
+ val onCancel: () -> Unit,
+ ) : AppDialog()
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt b/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt
index f03dfc70ca..80b48b4193 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt
@@ -1,47 +1,34 @@
package com.tangem.tap.common.redux
import com.tangem.tap.common.redux.global.globalReducer
-import com.tangem.tap.common.redux.navigation.NavigationReducer
import com.tangem.tap.features.details.redux.DetailsReducer
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectReducer
-import com.tangem.tap.features.disclaimer.redux.DisclaimerReducer
import com.tangem.tap.features.home.redux.HomeReducer
import com.tangem.tap.features.onboarding.products.note.redux.OnboardingNoteReducer
import com.tangem.tap.features.onboarding.products.otherCards.redux.OnboardingOtherCardsReducer
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsReducer
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletReducer
import com.tangem.tap.features.saveWallet.redux.SaveWalletReducer
-import com.tangem.tap.features.send.redux.reducers.SendScreenReducer
-import com.tangem.tap.features.shop.redux.ShopReducer
-import com.tangem.tap.features.tokens.redux.TokensReducer
-import com.tangem.tap.features.wallet.redux.reducers.WalletReducer
-import com.tangem.tap.proxy.AppStateHolder
-import com.tangem.tap.features.walletSelector.redux.WalletSelectorReducer
import com.tangem.tap.features.welcome.redux.WelcomeReducer
+import com.tangem.tap.proxy.redux.DaggerGraphReducer
import org.rekotlin.Action
-fun appReducer(action: Action, state: AppState?, appStateHolder: AppStateHolder): AppState {
+fun appReducer(action: Action, state: AppState?): AppState {
requireNotNull(state)
if (action is AppAction.RestoreState) return action.state
return AppState(
- navigationState = NavigationReducer.reduce(action, state),
- globalState = globalReducer(action, state, appStateHolder),
+ globalState = globalReducer(action, state),
homeState = HomeReducer.reduce(action, state),
onboardingNoteState = OnboardingNoteReducer.reduce(action, state),
onboardingWalletState = OnboardingWalletReducer.reduce(action, state),
onboardingOtherCardsState = OnboardingOtherCardsReducer.reduce(action, state),
- walletState = WalletReducer.reduce(action, state, appStateHolder),
twinCardsState = TwinCardsReducer.reduce(action, state),
- sendState = SendScreenReducer.reduce(action, state.sendState),
detailsState = DetailsReducer.reduce(action, state),
- disclaimerState = DisclaimerReducer.reduce(action, state),
- tokensState = TokensReducer.reduce(action, state),
walletConnectState = WalletConnectReducer.reduce(action, state.walletConnectState),
- shopState = ShopReducer.reduce(action, state.shopState),
welcomeState = WelcomeReducer.reduce(action, state),
saveWalletState = SaveWalletReducer.reduce(action, state),
- walletSelectorState = WalletSelectorReducer.reduce(action, state),
+ daggerGraphState = DaggerGraphReducer.reduce(action, state),
)
}
diff --git a/app/src/main/java/com/tangem/tap/common/redux/AppState.kt b/app/src/main/java/com/tangem/tap/common/redux/AppState.kt
index 820f5b3d3f..04d6fa4896 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/AppState.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/AppState.kt
@@ -1,18 +1,12 @@
package com.tangem.tap.common.redux
-import com.tangem.domain.redux.DomainState
-import com.tangem.domain.redux.domainStore
-import com.tangem.domain.redux.global.NetworkServices
import com.tangem.tap.common.redux.global.GlobalMiddleware
import com.tangem.tap.common.redux.global.GlobalState
-import com.tangem.tap.common.redux.navigation.NavigationState
-import com.tangem.tap.common.redux.navigation.navigationMiddleware
+import com.tangem.tap.common.redux.legacy.LegacyMiddleware
import com.tangem.tap.features.details.redux.DetailsMiddleware
import com.tangem.tap.features.details.redux.DetailsState
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectMiddleware
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectState
-import com.tangem.tap.features.disclaimer.redux.DisclaimerMiddleware
-import com.tangem.tap.features.disclaimer.redux.DisclaimerState
import com.tangem.tap.features.home.redux.HomeMiddleware
import com.tangem.tap.features.home.redux.HomeState
import com.tangem.tap.features.onboarding.products.note.redux.OnboardingNoteMiddleware
@@ -24,83 +18,51 @@ import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsState
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupMiddleware
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletMiddleware
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletState
-import com.tangem.tap.features.onboarding.products.wallet.saltPay.redux.OnboardingSaltPayMiddleware
import com.tangem.tap.features.saveWallet.redux.SaveWalletMiddleware
import com.tangem.tap.features.saveWallet.redux.SaveWalletState
-import com.tangem.tap.features.send.redux.middlewares.SendMiddleware
-import com.tangem.tap.features.send.redux.states.SendState
-import com.tangem.tap.features.shop.redux.ShopMiddleware
-import com.tangem.tap.features.shop.redux.ShopState
-import com.tangem.tap.features.tokens.redux.TokensMiddleware
-import com.tangem.tap.features.tokens.redux.TokensState
-import com.tangem.tap.features.wallet.redux.WalletState
-import com.tangem.tap.features.wallet.redux.middlewares.WalletMiddleware
-import com.tangem.tap.features.walletSelector.redux.WalletSelectorMiddleware
-import com.tangem.tap.features.walletSelector.redux.WalletSelectorState
+import com.tangem.tap.features.wallet.redux.middlewares.TradeCryptoMiddleware
import com.tangem.tap.features.welcome.redux.WelcomeMiddleware
import com.tangem.tap.features.welcome.redux.WelcomeState
-import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider
+import com.tangem.tap.proxy.redux.DaggerGraphMiddleware
+import com.tangem.tap.proxy.redux.DaggerGraphState
import org.rekotlin.Middleware
import org.rekotlin.StateType
data class AppState(
- val navigationState: NavigationState = NavigationState(),
val globalState: GlobalState = GlobalState(),
val homeState: HomeState = HomeState(),
val onboardingNoteState: OnboardingNoteState = OnboardingNoteState(),
val onboardingWalletState: OnboardingWalletState = OnboardingWalletState(),
val onboardingOtherCardsState: OnboardingOtherCardsState = OnboardingOtherCardsState(),
- val walletState: WalletState = WalletState(),
val twinCardsState: TwinCardsState = TwinCardsState(),
- val sendState: SendState = SendState(),
val detailsState: DetailsState = DetailsState(),
- val disclaimerState: DisclaimerState = DisclaimerState(),
- val tokensState: TokensState = TokensState(),
val walletConnectState: WalletConnectState = WalletConnectState(),
- val shopState: ShopState = ShopState(),
val welcomeState: WelcomeState = WelcomeState(),
val saveWalletState: SaveWalletState = SaveWalletState(),
- val walletSelectorState: WalletSelectorState = WalletSelectorState(),
+ val daggerGraphState: DaggerGraphState = DaggerGraphState(),
) : StateType {
- val domainState: DomainState
- get() = domainStore.state
-
- val domainNetworks: NetworkServices
- get() = domainState.globalState.networkServices
-
- val featureRepositoryProvider: FeatureRepositoryProvider
- get() = FeatureRepositoryProvider(
- tangemTechApi = domainNetworks.tangemTechService.api,
- dispatchers = AppCoroutineDispatcherProvider(),
- )
-
companion object {
fun getMiddleware(): List> {
return listOf(
logMiddleware,
- navigationMiddleware,
notificationsMiddleware,
GlobalMiddleware.handler,
HomeMiddleware.handler,
OnboardingNoteMiddleware.handler,
OnboardingWalletMiddleware.handler,
- OnboardingSaltPayMiddleware.handler,
OnboardingOtherCardsMiddleware.handler,
- WalletMiddleware().walletMiddleware,
TwinCardsMiddleware.handler,
- SendMiddleware().sendMiddleware,
DetailsMiddleware().detailsMiddleware,
- DisclaimerMiddleware().disclaimerMiddleware,
- TokensMiddleware().tokensMiddleware,
WalletConnectMiddleware().walletConnectMiddleware,
BackupMiddleware().backupMiddleware,
- ShopMiddleware().shopMiddleware,
WelcomeMiddleware().middleware,
SaveWalletMiddleware().middleware,
- WalletSelectorMiddleware().middleware,
LockUserWalletsTimerMiddleware().middleware,
AccessCodeRequestPolicyMiddleware().middleware,
+ DaggerGraphMiddleware.daggerGraphMiddleware,
+ LegacyMiddleware.legacyMiddleware,
+ TradeCryptoMiddleware.middleware,
)
}
}
diff --git a/app/src/main/java/com/tangem/tap/common/redux/FeatureRepositoryProvider.kt b/app/src/main/java/com/tangem/tap/common/redux/FeatureRepositoryProvider.kt
deleted file mode 100644
index 5794edffb9..0000000000
--- a/app/src/main/java/com/tangem/tap/common/redux/FeatureRepositoryProvider.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.tangem.tap.common.redux
-
-import com.tangem.datasource.api.tangemTech.TangemTechApi
-import com.tangem.tap.features.home.data.HomeRepositoryImpl
-import com.tangem.tap.features.home.domain.HomeRepository
-import com.tangem.tap.features.wallet.data.WalletRepositoryImpl
-import com.tangem.tap.features.wallet.domain.WalletRepository
-import com.tangem.utils.coroutines.CoroutineDispatcherProvider
-
-class FeatureRepositoryProvider(tangemTechApi: TangemTechApi, dispatchers: CoroutineDispatcherProvider) {
-
- val walletRepository: WalletRepository = WalletRepositoryImpl(tangemTechApi, dispatchers)
-
- val homeRepository: HomeRepository = HomeRepositoryImpl(tangemTechApi, dispatchers)
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/redux/LogMiddleware.kt b/app/src/main/java/com/tangem/tap/common/redux/LogMiddleware.kt
index 30b127fda1..a544190398 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/LogMiddleware.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/LogMiddleware.kt
@@ -1,19 +1,15 @@
package com.tangem.tap.common.redux
-import com.tangem.domain.common.LogConfig
import org.rekotlin.Middleware
import timber.log.Timber
/**
[REDACTED_AUTHOR]
*/
-val logMiddleware: Middleware = { dispatch, appState ->
+val logMiddleware: Middleware = { _, _ ->
{ nextDispatch ->
{ action ->
- if (LogConfig.storeAction) {
- Timber.d("Dispatch action: $action")
- // printOnboardingWalletState()
- }
+ Timber.i("Dispatch action: ${action::class.java.simpleName}")
nextDispatch(action)
}
}
diff --git a/app/src/main/java/com/tangem/tap/common/redux/NotificationsMiddleware.kt b/app/src/main/java/com/tangem/tap/common/redux/NotificationsMiddleware.kt
index 4a7cb7b8f8..1b862e7ed4 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/NotificationsMiddleware.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/NotificationsMiddleware.kt
@@ -20,22 +20,14 @@ class NotificationsHandler(coordinatorLayout: CoordinatorLayout) {
private val basicCoordinatorLayout = WeakReference(coordinatorLayout)
private var baseLayout = basicCoordinatorLayout
- fun replaceBaseLayout(coordinatorLayout: CoordinatorLayout) {
- baseLayout = WeakReference(coordinatorLayout)
- }
-
- fun returnBaseLayout() {
- baseLayout = basicCoordinatorLayout
- }
-
- fun showNotification(message: String) {
+ private fun showNotification(message: String) {
baseLayout.get()?.let { layout ->
Snackbar.make(layout, message, Snackbar.LENGTH_LONG)
.also { snackbar -> snackbar.show() }
}
}
- fun showDebugNotification(message: String) {
+ private fun showDebugNotification(message: String) {
baseLayout.get()?.let { layout ->
Snackbar.make(layout, message, Snackbar.LENGTH_LONG)
.also { snackbar ->
diff --git a/app/src/main/java/com/tangem/tap/common/redux/Request.kt b/app/src/main/java/com/tangem/tap/common/redux/Request.kt
deleted file mode 100644
index 4faae37c93..0000000000
--- a/app/src/main/java/com/tangem/tap/common/redux/Request.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.tangem.tap.common.redux
-
-import org.rekotlin.Action
-
-abstract class Request : Action {
- abstract suspend fun execute()
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/redux/StateDialog.kt b/app/src/main/java/com/tangem/tap/common/redux/StateDialog.kt
deleted file mode 100644
index e216493dd6..0000000000
--- a/app/src/main/java/com/tangem/tap/common/redux/StateDialog.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.tangem.tap.common.redux
-
-import com.tangem.common.extensions.VoidCallback
-import com.tangem.tap.common.TestAction
-import com.tangem.tap.features.wallet.models.Currency
-import com.tangem.tap.features.wallet.redux.AddressData
-
-/**
-[REDACTED_AUTHOR]
- */
-interface StateDialog
-
-sealed class AppDialog : StateDialog {
- data class SimpleOkDialog(val header: String, val message: String, val onOk: VoidCallback? = null) : AppDialog()
- data class SimpleOkErrorDialog(val message: String, val onOk: VoidCallback? = null) : AppDialog()
- data class SimpleOkWarningDialog(val message: String, val onOk: VoidCallback? = null) : AppDialog()
- data class SimpleOkDialogRes(
- val headerId: Int,
- val messageId: Int,
- val onOk: VoidCallback? = null,
- ) : AppDialog()
-
- object ScanFailsDialog : AppDialog()
-
- data class AddressInfoDialog(
- val currency: Currency,
- val addressData: AddressData,
- ) : AppDialog()
-
- data class TestActionsDialog(
- val actionsList: List,
- ) : AppDialog()
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt
index 1417d013d1..108d722975 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt
@@ -1,31 +1,21 @@
package com.tangem.tap.common.redux.global
-import com.tangem.blockchain.common.Blockchain
-import com.tangem.blockchain.common.WalletManager
import com.tangem.common.CompletionResult
-import com.tangem.common.core.TangemError
-import com.tangem.domain.common.ScanResponse
-import com.tangem.tap.common.entities.FiatCurrency
-import com.tangem.tap.common.feedback.FeedbackData
-import com.tangem.tap.common.feedback.FeedbackManager
+import com.tangem.core.analytics.models.AnalyticsParam
+import com.tangem.domain.appcurrency.model.AppCurrency
+import com.tangem.domain.models.scan.ScanResponse
+import com.tangem.domain.redux.StateDialog
import com.tangem.tap.common.redux.DebugErrorAction
import com.tangem.tap.common.redux.ErrorAction
import com.tangem.tap.common.redux.NotificationAction
-import com.tangem.tap.common.redux.StateDialog
-import com.tangem.tap.common.redux.ToastNotificationAction
-import com.tangem.tap.common.zendesk.ZendeskConfig
import com.tangem.tap.domain.TapError
-import com.tangem.tap.domain.configurable.config.ConfigManager
-import com.tangem.tap.domain.configurable.warningMessage.WarningMessage
-import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager
-import com.tangem.tap.features.details.redux.SecurityOption
+import com.tangem.tap.features.onboarding.products.wallet.redux.BackupStartedSource
import org.rekotlin.Action
sealed class GlobalAction : Action {
// notifications
data class ShowNotification(override val messageResource: Int) : GlobalAction(), NotificationAction
- data class ShowToastNotification(override val messageResource: Int) : GlobalAction(), ToastNotificationAction
data class ShowErrorNotification(override val error: TapError) : GlobalAction(), ErrorAction
data class DebugShowErrorNotification(override val error: TapError) : GlobalAction(), DebugErrorAction
@@ -36,41 +26,41 @@ sealed class GlobalAction : Action {
sealed class Onboarding : GlobalAction() {
/**
* Initiate an onboarding process.
- * For SaltPay cards it's additionally checks for unfinished backup.
- * For resuming unfinished backup for standard Wallet cards see CheckForUnfinishedBackup and
- * StartForUnfinishedBackup
+ * For resuming unfinished backup of standard Wallet see
+ * BackupAction.CheckForUnfinishedBackup, GlobalAction.Onboarding.StartForUnfinishedBackup
*/
- data class Start(val scanResponse: ScanResponse, val canSkipBackup: Boolean = true) : Onboarding()
+ data class Start(
+ val scanResponse: ScanResponse,
+ val source: BackupStartedSource,
+ val canSkipBackup: Boolean = true,
+ ) : Onboarding()
/**
- * Initiate resuming of unfinished backup only for standard Wallet cards.
- * For SaltPay cards unfinished backup resumed after scanning the card on HomeScreen through Onboarding.Start.
- * See more Onboarding.Start, CheckForUnfinishedBackup
+ * Initiate resuming of unfinished backup for standard Wallet.
+ * See more BackupAction.CheckForUnfinishedBackup
*/
data class StartForUnfinishedBackup(val addedBackupCardsCount: Int) : Onboarding()
+
object Stop : Onboarding()
+
+ data class ShouldResetCardOnCreate(val shouldReset: Boolean) : Onboarding()
}
- data class ScanCard(
- val additionalBlockchainsToDerive: Collection? = null,
- val onSuccess: ((ScanResponse) -> Unit)? = null,
- val onFailure: ((TangemError) -> Unit)? = null,
- val messageResId: Int? = null,
- ) : GlobalAction()
-
object ScanFailsCounter {
- data class ChooseBehavior(val result: CompletionResult) : GlobalAction()
+ data class ChooseBehavior(
+ val result: CompletionResult,
+ val analyticsSource: AnalyticsParam.ScreensSources,
+ ) : GlobalAction()
+
object Reset : GlobalAction()
object Increment : GlobalAction()
}
data class SaveScanResponse(val scanResponse: ScanResponse) : GlobalAction()
- data class SetIfCardVerifiedOnline(val verified: Boolean) : GlobalAction()
-
- data class ChangeAppCurrency(val appCurrency: FiatCurrency) : GlobalAction()
+ data class ChangeAppCurrency(val appCurrency: AppCurrency) : GlobalAction()
object RestoreAppCurrency : GlobalAction() {
- data class Success(val appCurrency: FiatCurrency) : GlobalAction()
+ data class Success(val appCurrency: AppCurrency) : GlobalAction()
}
data class UpdateWalletSignedHashes(
@@ -79,16 +69,7 @@ sealed class GlobalAction : Action {
val walletPublicKey: ByteArray,
) : GlobalAction()
- data class HideWarningMessage(val warning: WarningMessage) : GlobalAction()
- data class UpdateSecurityOptions(val securityOption: SecurityOption) : GlobalAction()
-
- data class SetConfigManager(val configManager: ConfigManager) : GlobalAction()
- data class SetWarningManager(val warningManager: WarningMessagesManager) : GlobalAction()
- data class SetFeedbackManager(val feedbackManager: FeedbackManager) : GlobalAction()
-
- data class SendEmail(val feedbackData: FeedbackData) : GlobalAction()
- data class OpenChat(val feedbackData: FeedbackData, val zendeskConfig: ZendeskConfig? = null) : GlobalAction()
- data class UpdateFeedbackInfo(val walletManagers: List) : GlobalAction()
+ data class IsSignWithRing(val isSignWithRing: Boolean) : GlobalAction()
object ExchangeManager : GlobalAction() {
object Init : GlobalAction() {
@@ -99,8 +80,4 @@ sealed class GlobalAction : Action {
object Update : GlobalAction()
}
-
- object FetchUserCountry : GlobalAction() {
- data class Success(val countryCode: String) : GlobalAction()
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt
index b880c71872..e7f1d6613d 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMiddleware.kt
@@ -3,32 +3,28 @@ package com.tangem.tap.common.redux.global
import com.tangem.common.CompletionResult
import com.tangem.common.core.TangemSdkError
import com.tangem.common.extensions.guard
-import com.tangem.common.extensions.ifNotNull
+import com.tangem.core.analytics.models.AnalyticsParam
+import com.tangem.datasource.local.config.environment.EnvironmentConfig
+import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.common.LogConfig
-import com.tangem.domain.common.extensions.withMainContext
-import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
-import com.tangem.tap.common.extensions.dispatchDialogShow
-import com.tangem.tap.common.extensions.dispatchOnMain
-import com.tangem.tap.common.redux.AppDialog
+import com.tangem.domain.models.scan.CardDTO
+import com.tangem.domain.models.scan.ScanResponse
+import com.tangem.domain.redux.StateDialog
+import com.tangem.tap.common.extensions.*
import com.tangem.tap.common.redux.AppState
-import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager
-import com.tangem.tap.features.send.redux.SendAction
-import com.tangem.tap.features.wallet.redux.WalletAction
import com.tangem.tap.network.exchangeServices.CardExchangeRules
import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager
-import com.tangem.tap.network.exchangeServices.mercuryo.MercuryoApi
+import com.tangem.tap.network.exchangeServices.ExchangeService
+import com.tangem.tap.network.exchangeServices.mercuryo.MercuryoEnvironment
import com.tangem.tap.network.exchangeServices.mercuryo.MercuryoService
import com.tangem.tap.network.exchangeServices.moonpay.MoonPayService
-import com.tangem.tap.preferencesStorage
+import com.tangem.tap.proxy.redux.DaggerGraphState
import com.tangem.tap.scope
import com.tangem.tap.store
-import com.tangem.tap.tangemSdkManager
-import com.tangem.tap.userTokensRepository
+import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.launch
import org.rekotlin.Action
-import org.rekotlin.DispatchFunction
import org.rekotlin.Middleware
-import java.util.*
object GlobalMiddleware {
val handler = globalMiddlewareHandler
@@ -37,120 +33,49 @@ object GlobalMiddleware {
private val globalMiddlewareHandler: Middleware = { dispatch, appState ->
{ nextDispatch ->
{ action ->
- handleAction(action, appState, dispatch)
+ handleAction(action, appState)
nextDispatch(action)
}
}
}
@Suppress("LongMethod", "ComplexMethod")
-private fun handleAction(action: Action, appState: () -> AppState?, dispatch: DispatchFunction) {
+private fun handleAction(action: Action, appState: () -> AppState?) {
when (action) {
is GlobalAction.ScanFailsCounter.ChooseBehavior -> {
when (action.result) {
is CompletionResult.Success -> store.dispatch(GlobalAction.ScanFailsCounter.Reset)
is CompletionResult.Failure -> {
- if (action.result.error is TangemSdkError.UserCancelled) {
- store.dispatch(GlobalAction.ScanFailsCounter.Increment)
- if (store.state.globalState.scanCardFailsCounter >= 2) {
- store.dispatchDialogShow(AppDialog.ScanFailsDialog)
- }
- } else {
- store.dispatch(GlobalAction.ScanFailsCounter.Reset)
- }
+ handleFailureChooseBehaviour(action.result, action.analyticsSource)
}
}
}
is GlobalAction.RestoreAppCurrency -> {
- store.dispatch(
- GlobalAction.RestoreAppCurrency.Success(
- preferencesStorage.fiatCurrenciesPrefStorage.getAppCurrency(),
- ),
- )
- }
- is GlobalAction.HideWarningMessage -> {
- store.state.globalState.warningManager?.let {
- if (it.hideWarning(action.warning)) {
- if (WarningMessagesManager.isAlreadySignedHashesWarning(action.warning)) {
- // TODO: No appropriate warningMessage identification. Make it better later
- store.dispatch(WalletAction.Warnings.CheckHashesCount.SaveCardId)
- }
-
- store.dispatch(WalletAction.Warnings.Update)
- store.dispatch(SendAction.Warnings.Update)
- }
- }
- }
- is GlobalAction.SendEmail -> {
- store.state.globalState.feedbackManager?.sendEmail(action.feedbackData)
- }
- is GlobalAction.OpenChat -> {
- val globalState = store.state.globalState
- val feedbackManager = globalState.feedbackManager.guard {
- store.dispatchDebugErrorNotification("FeedbackManager not initialized")
- return
- }
- val config = globalState.configManager?.config.guard {
- store.dispatchDebugErrorNotification("Config not initialized")
- return
- }
-
- val scanResponse = globalState.scanResponse ?: globalState.onboardingState.onboardingManager?.scanResponse
-
- // if config not set -> try to get it based on a scanResponse.productType
- val unsafeZendeskConfig = action.zendeskConfig ?: when {
- scanResponse?.cardTypesResolver?.isSaltPay() == true -> config.saltPayConfig?.zendesk
- else -> config.zendesk
- }
-
- val zendeskConfig = unsafeZendeskConfig.guard {
- store.dispatchDebugErrorNotification("ZendeskConfig not initialized")
- return
- }
- feedbackManager.initChat(zendeskConfig)
- feedbackManager.openChat(action.feedbackData)
- }
- is GlobalAction.UpdateWalletSignedHashes -> {
- store.dispatch(WalletAction.Warnings.CheckRemainingSignatures(action.remainingSignatures))
- }
- is GlobalAction.UpdateFeedbackInfo -> {
- store.state.globalState.feedbackManager?.infoHolder
- ?.setWalletsInfo(action.walletManagers)
+ restoreAppCurrency()
}
is GlobalAction.ExchangeManager.Init -> {
- val appStateSafe = appState() ?: return
- val config = appStateSafe.globalState.configManager?.config
- ifNotNull(
- config?.mercuryoWidgetId,
- config?.mercuryoSecret,
- config?.moonPayApiKey,
- config?.moonPayApiSecretKey,
- ) { mercuryoWidgetId, mercuryoSecret, moonPayKey, moonPaySecretKey ->
- scope.launch {
- val buyService = MercuryoService(
- apiVersion = MercuryoApi.API_VERSION,
- mercuryoWidgetId = mercuryoWidgetId,
- secret = mercuryoSecret,
- logEnabled = LogConfig.network.mercuryoService,
- )
- val sellService = MoonPayService(
- apiKey = moonPayKey,
- secretKey = moonPaySecretKey,
- logEnabled = LogConfig.network.moonPayService,
- )
- val cardProvider = {
- store.state.globalState.scanResponse?.card
- ?: store.state.globalState.onboardingState.onboardingManager?.scanResponse?.card
- }
+ val config = store.inject(DaggerGraphState::environmentConfigStorage).getConfigSync()
- val exchangeManager = CurrencyExchangeManager(
- buyService = buyService,
- sellService = sellService,
- primaryRules = CardExchangeRules(cardProvider),
- )
- store.dispatchOnMain(GlobalAction.ExchangeManager.Init.Success(exchangeManager))
- store.dispatchOnMain(GlobalAction.ExchangeManager.Update)
+ scope.launch {
+ val scanResponseProvider: () -> ScanResponse? = {
+ val userWalletsListManager = store.inject(DaggerGraphState::generalUserWalletsListManager)
+ userWalletsListManager.selectedUserWalletSync?.scanResponse
}
+ val cardProvider: () -> CardDTO? = { scanResponseProvider.invoke()?.card }
+
+ val buyService = makeBuyExchangeService(config)
+ val sellService = makeSellExchangeService(config)
+ val exchangeManager = CurrencyExchangeManager(
+ buyService = buyService,
+ sellService = sellService,
+ primaryRules = CardExchangeRules(cardProvider),
+ )
+ // TODO: for refactoring (after remove old design refactor CurrencyExchangeManager and use 1 instance)
+ store.inject(DaggerGraphState::appStateHolder).buyService = buyService
+ store.inject(DaggerGraphState::appStateHolder).sellService = sellService
+ store.inject(DaggerGraphState::appStateHolder).exchangeService = exchangeManager
+ store.dispatchOnMain(GlobalAction.ExchangeManager.Init.Success(exchangeManager))
+ store.dispatchOnMain(GlobalAction.ExchangeManager.Update)
}
}
is GlobalAction.ExchangeManager.Init.Success -> {}
@@ -161,45 +86,53 @@ private fun handleAction(action: Action, appState: () -> AppState?, dispatch: Di
}
scope.launch { exchangeManager.update() }
}
- is GlobalAction.ScanCard -> {
- scope.launch {
- tangemSdkManager.changeDisplayedCardIdNumbersCount(null)
- val result = tangemSdkManager.scanProduct(
- userTokensRepository = userTokensRepository,
- additionalBlockchainsToDerive = action.additionalBlockchainsToDerive,
- messageRes = action.messageResId,
- )
- withMainContext {
- store.dispatch(GlobalAction.ScanFailsCounter.ChooseBehavior(result))
- when (result) {
- is CompletionResult.Success -> {
- tangemSdkManager.changeDisplayedCardIdNumbersCount(result.data)
- action.onSuccess?.invoke(result.data)
- }
- is CompletionResult.Failure -> {
- action.onFailure?.invoke(result.error)
- }
- }
- }
- }
- }
- is GlobalAction.FetchUserCountry -> {
- scope.launch {
- // TODO("After adding DI") get dependencies by DI
- runCatching { store.state.featureRepositoryProvider.homeRepository.getUserCountryCode() }
- .onSuccess {
- store.dispatchOnMain(
- GlobalAction.FetchUserCountry.Success(countryCode = it.code.lowercase()),
- )
- }
- .onFailure {
- store.dispatchOnMain(
- GlobalAction.FetchUserCountry.Success(
- countryCode = Locale.getDefault().country.lowercase(),
- ),
- )
- }
- }
- }
}
+}
+
+private fun handleFailureChooseBehaviour(
+ result: CompletionResult.Failure,
+ analyticsSource: AnalyticsParam.ScreensSources,
+) {
+ if (result.error is TangemSdkError.UserCancelled) {
+ store.dispatch(GlobalAction.ScanFailsCounter.Increment)
+ if (store.state.globalState.scanCardFailsCounter >= 2) {
+ val scanFailsSource = when (analyticsSource) {
+ is AnalyticsParam.ScreensSources.SignIn -> StateDialog.ScanFailsSource.SIGN_IN
+ is AnalyticsParam.ScreensSources.Settings -> StateDialog.ScanFailsSource.SETTINGS
+ is AnalyticsParam.ScreensSources.Intro -> StateDialog.ScanFailsSource.INTRO
+ else -> StateDialog.ScanFailsSource.MAIN
+ }
+ store.dispatchDialogShow(StateDialog.ScanFailsDialog(scanFailsSource))
+ }
+ } else {
+ store.dispatch(GlobalAction.ScanFailsCounter.Reset)
+ }
+}
+
+private fun restoreAppCurrency() {
+ scope.launch {
+ val currency = store.inject(DaggerGraphState::appCurrencyRepository)
+ .getSelectedAppCurrency()
+ .firstOrNull()
+ ?: AppCurrency.Default
+
+ store.dispatchWithMain(GlobalAction.RestoreAppCurrency.Success(currency))
+ }
+}
+
+private fun makeSellExchangeService(environmentConfig: EnvironmentConfig): ExchangeService {
+ return MoonPayService(
+ apiKey = environmentConfig.moonPayApiKey,
+ secretKey = environmentConfig.moonPayApiSecretKey,
+ logEnabled = LogConfig.network.moonPayService,
+ )
+}
+
+private fun makeBuyExchangeService(environmentConfig: EnvironmentConfig): ExchangeService {
+ return MercuryoService(
+ environment = MercuryoEnvironment.prod(
+ widgetId = environmentConfig.mercuryoWidgetId,
+ secret = environmentConfig.mercuryoSecret,
+ ),
+ )
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt
index 7934a195f6..c8372a3d0d 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt
@@ -1,24 +1,19 @@
package com.tangem.tap.common.redux.global
-import com.tangem.domain.redux.domainStore
-import com.tangem.domain.redux.global.DomainGlobalAction
-import com.tangem.tap.common.extensions.replaceBy
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.features.onboarding.OnboardingManager
-import com.tangem.tap.preferencesStorage
-import com.tangem.tap.proxy.AppStateHolder
+import com.tangem.utils.extensions.replaceBy
import org.rekotlin.Action
@Suppress("LongMethod", "ComplexMethod")
-fun globalReducer(action: Action, state: AppState, appStateHolder: AppStateHolder): GlobalState {
+fun globalReducer(action: Action, state: AppState): GlobalState {
if (action !is GlobalAction) return state.globalState
val globalState = state.globalState
return when (action) {
is GlobalAction.Onboarding.Start -> {
- val usedCardsPrefStorage = preferencesStorage.usedCardsPrefStorage
- val onboardingManager = OnboardingManager(action.scanResponse, usedCardsPrefStorage)
+ val onboardingManager = OnboardingManager(action.scanResponse)
globalState.copy(onboardingState = OnboardingState(true, onboardingManager))
}
is GlobalAction.Onboarding.StartForUnfinishedBackup -> {
@@ -27,6 +22,11 @@ fun globalReducer(action: Action, state: AppState, appStateHolder: AppStateHolde
is GlobalAction.Onboarding.Stop -> {
globalState.copy(onboardingState = OnboardingState(false))
}
+ is GlobalAction.Onboarding.ShouldResetCardOnCreate -> {
+ globalState.copy(
+ onboardingState = globalState.onboardingState.copy(shouldResetOnCreate = action.shouldReset),
+ )
+ }
is GlobalAction.ScanFailsCounter.Increment -> {
globalState.copy(scanCardFailsCounter = globalState.scanCardFailsCounter + 1)
}
@@ -34,21 +34,14 @@ fun globalReducer(action: Action, state: AppState, appStateHolder: AppStateHolde
globalState.copy(scanCardFailsCounter = 0)
}
is GlobalAction.SaveScanResponse -> {
- appStateHolder.scanResponse = action.scanResponse
- domainStore.dispatch(DomainGlobalAction.SaveScanNoteResponse(action.scanResponse))
globalState.copy(scanResponse = action.scanResponse)
}
is GlobalAction.ChangeAppCurrency -> {
- appStateHolder.appFiatCurrency = action.appCurrency
globalState.copy(appCurrency = action.appCurrency)
}
is GlobalAction.RestoreAppCurrency.Success -> {
globalState.copy(appCurrency = action.appCurrency)
}
- is GlobalAction.SetConfigManager -> {
- globalState.copy(configManager = action.configManager)
- }
- is GlobalAction.SetWarningManager -> globalState.copy(warningManager = action.warningManager)
is GlobalAction.UpdateWalletSignedHashes -> {
val card = globalState.scanResponse?.card ?: return globalState
val wallet = card.wallets
@@ -67,9 +60,7 @@ fun globalReducer(action: Action, state: AppState, appStateHolder: AppStateHolde
)
globalState.copy(scanResponse = globalState.scanResponse.copy(card = newCardInstance))
}
- is GlobalAction.SetFeedbackManager -> {
- globalState.copy(feedbackManager = action.feedbackManager)
- }
+ is GlobalAction.IsSignWithRing -> globalState.copy(isLastSignWithRing = action.isSignWithRing)
is GlobalAction.ShowDialog -> {
globalState.copy(dialog = action.stateDialog)
}
@@ -79,11 +70,6 @@ fun globalReducer(action: Action, state: AppState, appStateHolder: AppStateHolde
is GlobalAction.ExchangeManager.Init.Success -> {
globalState.copy(exchangeManager = action.exchangeManager)
}
- is GlobalAction.SetIfCardVerifiedOnline ->
- globalState.copy(cardVerifiedOnline = action.verified)
- is GlobalAction.FetchUserCountry.Success -> globalState.copy(
- userCountryCode = action.countryCode,
- )
else -> globalState
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt
index b897f1b5dc..fb6bf4ae13 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt
@@ -1,31 +1,23 @@
package com.tangem.tap.common.redux.global
-import com.tangem.domain.common.ScanResponse
-import com.tangem.tap.common.entities.FiatCurrency
-import com.tangem.tap.common.feedback.FeedbackManager
-import com.tangem.tap.common.redux.StateDialog
-import com.tangem.tap.domain.PayIdManager
+import com.tangem.domain.appcurrency.model.AppCurrency
+import com.tangem.domain.models.scan.ScanResponse
+import com.tangem.domain.redux.StateDialog
import com.tangem.tap.domain.TapWalletManager
-import com.tangem.tap.domain.configurable.config.ConfigManager
-import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager
import com.tangem.tap.features.onboarding.OnboardingManager
import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager
import org.rekotlin.StateType
data class GlobalState(
+ @Deprecated("Use scan response from selected user wallet")
val scanResponse: ScanResponse? = null,
val onboardingState: OnboardingState = OnboardingState(),
- val cardVerifiedOnline: Boolean = false,
val tapWalletManager: TapWalletManager = TapWalletManager(),
- val payIdManager: PayIdManager = PayIdManager(),
- val configManager: ConfigManager? = null,
- val warningManager: WarningMessagesManager? = null,
- val feedbackManager: FeedbackManager? = null,
- val appCurrency: FiatCurrency = FiatCurrency.Default,
+ val appCurrency: AppCurrency = AppCurrency.Default,
val scanCardFailsCounter: Int = 0,
val dialog: StateDialog? = null,
val exchangeManager: CurrencyExchangeManager = CurrencyExchangeManager.dummy(),
- val userCountryCode: String? = null,
+ val isLastSignWithRing: Boolean = false,
) : StateType
typealias CryptoCurrencyName = String
@@ -33,4 +25,5 @@ typealias CryptoCurrencyName = String
data class OnboardingState(
val onboardingStarted: Boolean = false,
val onboardingManager: OnboardingManager? = null,
+ val shouldResetOnCreate: Boolean = false,
)
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/redux/legacy/LegacyMiddleware.kt b/app/src/main/java/com/tangem/tap/common/redux/legacy/LegacyMiddleware.kt
new file mode 100644
index 0000000000..71f04d42af
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/redux/legacy/LegacyMiddleware.kt
@@ -0,0 +1,61 @@
+package com.tangem.tap.common.redux.legacy
+
+import com.tangem.domain.redux.LegacyAction
+import com.tangem.tap.common.extensions.dispatchWithMain
+import com.tangem.tap.common.extensions.inject
+import com.tangem.tap.common.redux.AppState
+import com.tangem.tap.common.redux.global.GlobalAction
+import com.tangem.tap.features.details.redux.DetailsAction
+import com.tangem.tap.features.onboarding.products.wallet.redux.BackupStartedSource
+import com.tangem.tap.proxy.redux.DaggerGraphState
+import com.tangem.tap.scope
+import com.tangem.tap.store
+import com.tangem.utils.coroutines.JobHolder
+import com.tangem.utils.coroutines.saveIn
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import org.rekotlin.Middleware
+
+internal object LegacyMiddleware {
+ private val prepareDetailsScreenJobHolder = JobHolder()
+
+ val legacyMiddleware: Middleware = { _, _ ->
+ { next ->
+ { action ->
+ when (action) {
+ is LegacyAction.StartOnboardingProcess -> {
+ store.dispatch(
+ GlobalAction.Onboarding.Start(
+ scanResponse = action.scanResponse,
+ source = BackupStartedSource.CreateBackup,
+ canSkipBackup = action.canSkipBackup,
+ ),
+ )
+ }
+ is LegacyAction.PrepareDetailsScreen -> {
+ val userWalletsListManager = store.inject(DaggerGraphState::generalUserWalletsListManager)
+ val walletsRepository = store.inject(DaggerGraphState::walletsRepository)
+
+ userWalletsListManager.selectedUserWallet
+ .distinctUntilChanged()
+ .onEach { selectedUserWallet ->
+ store.dispatchWithMain(
+ DetailsAction.PrepareScreen(
+ scanResponse = selectedUserWallet.scanResponse,
+ shouldSaveUserWallets = walletsRepository.shouldSaveUserWalletsSync(),
+ ),
+ )
+ }
+ .flowOn(Dispatchers.IO)
+ .launchIn(scope)
+ .saveIn(prepareDetailsScreenJobHolder)
+ }
+ }
+ next(action)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/redux/navigation/FragmentShareTransition.kt b/app/src/main/java/com/tangem/tap/common/redux/navigation/FragmentShareTransition.kt
deleted file mode 100644
index ab7aa07259..0000000000
--- a/app/src/main/java/com/tangem/tap/common/redux/navigation/FragmentShareTransition.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.tangem.tap.common.redux.navigation
-
-import android.view.View
-import androidx.transition.TransitionSet
-import java.lang.ref.WeakReference
-
-/**
-[REDACTED_AUTHOR]
- */
-data class FragmentShareTransition(
- val shareElements: List,
- val enterTransitionSet: TransitionSet,
- val exitTransitionSet: TransitionSet,
-)
-
-/**
- * For ease of use, the name is used as transitionName\name into the FragmentTransaction.addSharedElement
- */
-class ShareElement(view: View, name: String? = null) {
-
- val wView: WeakReference
- val elementName: String
-
- init {
- name?.let { view.transitionName = it }
- elementName = view.transitionName
- ?: throw UnsupportedOperationException("ShareElement require the name")
- wView = WeakReference(view)
- }
-
- companion object {
- const val imvFrontCard = "imv_front_card"
- const val imvBackCard = "imv_back_card"
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationAction.kt b/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationAction.kt
deleted file mode 100644
index 71f3274e4c..0000000000
--- a/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationAction.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.tangem.tap.common.redux.navigation
-
-import android.net.Uri
-import android.os.Bundle
-import androidx.appcompat.app.AppCompatActivity
-import org.rekotlin.Action
-import java.lang.ref.WeakReference
-
-sealed class NavigationAction : Action {
- data class NavigateTo(
- val screen: AppScreen,
- val fragmentShareTransition: FragmentShareTransition? = null,
- val addToBackstack: Boolean = true,
- val bundle: Bundle? = null,
- ) : NavigationAction()
-
- data class PopBackTo(
- val screen: AppScreen? = null,
- val inclusive: Boolean = false,
- ) : NavigationAction()
-
- data class OpenUrl(val url: String) : NavigationAction()
-
- data class OpenDocument(val url: Uri) : NavigationAction()
-
- object OpenBiometricsSettings : NavigationAction()
-
- data class Share(val data: String) : NavigationAction()
-
- data class ActivityCreated(val activity: WeakReference) : NavigationAction()
- data class ActivityDestroyed(val activity: WeakReference) : NavigationAction()
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationMiddleware.kt b/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationMiddleware.kt
deleted file mode 100644
index bf5df6a9a9..0000000000
--- a/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationMiddleware.kt
+++ /dev/null
@@ -1,91 +0,0 @@
-package com.tangem.tap.common.redux.navigation
-
-import android.content.Intent
-import android.hardware.biometrics.BiometricManager
-import android.os.Build
-import android.provider.Settings
-import com.tangem.tap.activityResultCaller
-import com.tangem.tap.common.CustomTabsManager
-import com.tangem.tap.common.extensions.dispatchOnMain
-import com.tangem.tap.common.extensions.openFragment
-import com.tangem.tap.common.extensions.popBackTo
-import com.tangem.tap.common.extensions.shareText
-import com.tangem.tap.common.redux.AppState
-import com.tangem.tap.store
-import org.rekotlin.Middleware
-
-val navigationMiddleware: Middleware = { _, state ->
- { next ->
- { action ->
- if (action is NavigationAction) {
- val navState = state()?.navigationState
- when (action) {
- is NavigationAction.NavigateTo -> {
- navState?.activity?.get()?.openFragment(
- screen = action.screen,
- addToBackstack = action.addToBackstack,
- fgShareTransition = action.fragmentShareTransition,
- bundle = action.bundle,
- )
- }
- is NavigationAction.PopBackTo -> {
- if (navState?.backStack?.lastOrNull() != action.screen) {
- when (val screen = action.screen) {
- AppScreen.Home,
- AppScreen.Welcome,
- -> {
- if (navState?.backStack?.contains(screen) == false) {
- // Pop back to activity
- navState.activity?.get()?.popBackTo(screen = null, inclusive = true)
- store.dispatchOnMain(NavigationAction.NavigateTo(screen))
- } else {
- navState?.activity?.get()?.popBackTo(screen, action.inclusive)
- }
- }
- else -> {
- navState?.activity?.get()?.popBackTo(screen, action.inclusive)
- }
- }
- }
- }
- is NavigationAction.OpenUrl -> {
- navState?.activity?.get()?.let {
- CustomTabsManager().openUrl(action.url, it)
- }
- }
- is NavigationAction.OpenDocument -> {
- val intent = Intent(Intent.ACTION_VIEW)
- intent.data = action.url
- navState?.activity?.get()?.startActivity(intent)
- }
- is NavigationAction.OpenBiometricsSettings -> {
- val settingsAction = when {
- Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> {
- Settings.ACTION_BIOMETRIC_ENROLL
- }
- else -> {
- Settings.ACTION_SECURITY_SETTINGS
- }
- }
- val intent = Intent(settingsAction).apply {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
- putExtra(
- Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED,
- BiometricManager.Authenticators.BIOMETRIC_STRONG,
- )
- }
- }
- activityResultCaller.activityResultLauncher?.launch(intent)
- }
- is NavigationAction.Share -> {
- navState?.activity?.get()?.shareText(action.data)
- }
- is NavigationAction.ActivityCreated,
- is NavigationAction.ActivityDestroyed,
- -> Unit
- }
- }
- next(action)
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationReducer.kt b/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationReducer.kt
deleted file mode 100644
index 7febcfa59c..0000000000
--- a/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationReducer.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.tangem.tap.common.redux.navigation
-
-import com.tangem.tap.common.extensions.getPreviousScreen
-import com.tangem.tap.common.redux.AppState
-import org.rekotlin.Action
-
-object NavigationReducer {
- fun reduce(action: Action, state: AppState): NavigationState = internalReduce(action, state)
-}
-
-private fun internalReduce(action: Action, state: AppState): NavigationState {
- val navigationAction = action as? NavigationAction ?: return state.navigationState
- val navState = state.navigationState
-
- return when (navigationAction) {
- is NavigationAction.NavigateTo -> {
- navState.copy(backStack = navState.backStack + navigationAction.screen)
- }
- is NavigationAction.PopBackTo -> {
- if (navState.backStack.lastOrNull() == navigationAction.screen) return navState
-
- val screen = navigationAction.screen ?: navState.activity?.get()?.getPreviousScreen()
- val index = navState.backStack.lastIndexOf(screen) + 1
- state.navigationState.copy(backStack = navState.backStack.subList(0, index))
- }
- is NavigationAction.ActivityCreated -> navState.copy(activity = navigationAction.activity)
- is NavigationAction.ActivityDestroyed -> {
- when {
- // Destroy the activity if it invoked for the same activity. Prevents overwriting to null if there is a
- // new scan from the background [REDACTED_TASK_KEY]
- navState.activity?.get() == navigationAction.activity.get() -> navState.copy(activity = null)
- else -> navState
- }
- }
- else -> navState
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationState.kt b/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationState.kt
deleted file mode 100644
index 0b40b7bd8e..0000000000
--- a/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationState.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.tangem.tap.common.redux.navigation
-
-import androidx.appcompat.app.AppCompatActivity
-import org.rekotlin.StateType
-import java.lang.ref.WeakReference
-
-data class NavigationState(
- val backStack: List = emptyList(),
- val activity: WeakReference? = null,
-) : StateType
-
-enum class AppScreen(
- val isDialogFragment: Boolean = false,
-) {
- Home,
- Shop,
- Disclaimer,
- OnboardingNote, OnboardingWallet, OnboardingTwins, OnboardingOther,
- Wallet, WalletDetails,
- Send,
- Details, DetailsSecurity, CardSettings, AppSettings, ResetToFactory,
- AddTokens, AddCustomToken,
- WalletConnectSessions,
- QrScan,
- ReferralProgram,
- Swap,
- Welcome,
- SaveWallet(isDialogFragment = true),
- WalletSelector(isDialogFragment = true),
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/settings/IntentSettingsManager.kt b/app/src/main/java/com/tangem/tap/common/settings/IntentSettingsManager.kt
new file mode 100644
index 0000000000..ab6dd43f18
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/settings/IntentSettingsManager.kt
@@ -0,0 +1,48 @@
+package com.tangem.tap.common.settings
+
+import android.content.Context
+import android.content.Intent
+import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
+import android.hardware.biometrics.BiometricManager
+import android.net.Uri
+import android.os.Build
+import android.provider.Settings
+import com.tangem.core.navigation.settings.SettingsManager
+
+internal class IntentSettingsManager(val context: Context) : SettingsManager {
+
+ override fun openAppSettings() {
+ val intent = Intent(
+ Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
+ Uri.fromParts("package", context.packageName, null),
+ )
+
+ open(intent = intent)
+ }
+
+ override fun openBiometricSettings() {
+ val settingsAction = when {
+ Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> Settings.ACTION_BIOMETRIC_ENROLL
+ else -> Settings.ACTION_SECURITY_SETTINGS
+ }
+
+ val intent = Intent(settingsAction).apply {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ putExtra(
+ Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED,
+ BiometricManager.Authenticators.BIOMETRIC_STRONG,
+ )
+ }
+ }
+
+ open(intent = intent)
+ }
+
+ private fun open(intent: Intent) {
+ context.startActivity(
+ intent.apply {
+ flags = FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
+ },
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/share/IntentShareManager.kt b/app/src/main/java/com/tangem/tap/common/share/IntentShareManager.kt
new file mode 100644
index 0000000000..51b829de5f
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/share/IntentShareManager.kt
@@ -0,0 +1,22 @@
+package com.tangem.tap.common.share
+
+import android.content.Intent
+import com.tangem.core.navigation.share.ShareManager
+import com.tangem.tap.foregroundActivityObserver
+import com.tangem.tap.withForegroundActivity
+
+internal class IntentShareManager : ShareManager {
+
+ override fun shareText(text: String) {
+ foregroundActivityObserver.withForegroundActivity { activity ->
+ val sendIntent: Intent = Intent().apply {
+ action = Intent.ACTION_SEND
+ putExtra(Intent.EXTRA_TEXT, text)
+ type = "text/plain"
+ }
+ val shareIntent = Intent.createChooser(sendIntent, null)
+
+ activity.startActivity(shareIntent)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt b/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt
deleted file mode 100644
index 8366078322..0000000000
--- a/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt
+++ /dev/null
@@ -1,229 +0,0 @@
-package com.tangem.tap.common.shop
-
-import android.app.Application
-import android.content.Intent
-import com.google.android.gms.wallet.PaymentData
-import com.shopify.buy3.Storefront
-import com.tangem.core.analytics.Analytics
-import com.tangem.tap.common.analytics.converters.ShopOrderToEventConverter
-import com.tangem.tap.common.extensions.filterNotNull
-import com.tangem.tap.common.shop.data.ProductType
-import com.tangem.tap.common.shop.data.TangemProduct
-import com.tangem.tap.common.shop.data.TotalSum
-import com.tangem.tap.common.shop.googlepay.GooglePayService
-import com.tangem.tap.common.shop.shopify.ShopifyService
-import com.tangem.tap.common.shop.shopify.ShopifyShop
-import com.tangem.tap.common.shop.shopify.data.CheckoutItem
-import kotlinx.coroutines.async
-import kotlinx.coroutines.awaitAll
-import kotlinx.coroutines.coroutineScope
-import java.math.BigDecimal
-import java.util.*
-
-class TangemShopService(application: Application, shopifyShop: ShopifyShop) {
-
- private val shopifyService = ShopifyService(application, shopifyShop)
-
- private val checkouts = mutableMapOf()
- private val variants = mutableMapOf()
-
- private lateinit var googlePayService: GooglePayService
-
- suspend fun getProducts(): Result> {
- val result = shopifyService.getProducts()
-
- return result.mapCatching { product ->
- val availableVariants = product
- .flatMap { it.variants.edges.map { it.node } }
- .filter { SKUS_TO_DISPLAY.contains(it.sku) }
- .associateBy { ProductType.fromSku(it.sku) }
- .filterNotNull()
- variants.putAll(availableVariants)
-
- if (variants.size < SKUS_TO_DISPLAY.size) {
- return Result.failure(
- Exception(
- "Shopify: products are missing, " +
- "\nproducts available: ${variants.keys.map { it.sku }}",
- ),
- )
- }
-
- val twoCardsProduct = TangemProduct(
- type = ProductType.WALLET_2_CARDS,
- totalSum = TotalSum(
- finalValue = variants[ProductType.WALLET_2_CARDS]?.priceV2?.format(),
- beforeDiscount = variants[ProductType.WALLET_2_CARDS]?.compareAtPriceV2?.format(),
- ),
- )
- val threeCardsProduct = TangemProduct(
- type = ProductType.WALLET_3_CARDS,
- totalSum = TotalSum(
- finalValue = variants[ProductType.WALLET_3_CARDS]?.priceV2?.format(),
- beforeDiscount = variants[ProductType.WALLET_3_CARDS]?.compareAtPriceV2?.format(),
- ),
- )
- createCheckouts()
- return Result.success(listOf(twoCardsProduct, threeCardsProduct))
- }
- }
-
- private suspend fun createCheckouts() {
- variants.keys.map { coroutineScope { async { createCheckout(it) } } }.awaitAll()
- }
-
- private suspend fun createCheckout(productType: ProductType) {
- val checkoutItem = CheckoutItem(variants[productType]!!.id, 1)
- val result = shopifyService.createCheckout(listOf(checkoutItem))
- result.onSuccess { checkout ->
- checkouts[productType] = checkout
- }
- }
-
- suspend fun checkIfGooglePayAvailable(googlePayService: GooglePayService): Result {
- this.googlePayService = googlePayService
- return googlePayService.checkIfGooglePayAvailable()
- }
-
- fun buyWithGooglePay(productType: ProductType) {
- val totalPrice = checkouts[productType]!!.totalPriceV2.amount
- googlePayService.payWithGooglePay(
- totalPriceCents = totalPrice,
- currencyCode = checkouts[productType]!!.currencyCode.name,
- merchantID = shopifyService.shop.merchantID,
- )
- }
-
-// fun subscribeToGooglePayResult(
-// productType: ProductType,
-// resultCallback: (Result) -> Unit
-// ) {
-// googlePayService.responseCallback = { result ->
-// result.onFailure { }
-// result.onSuccess {
-// completeTokenizedPayment(it, productType)
-// }
-// }
-// }
-
- suspend fun handleGooglePayResult(
- resultCode: Int,
- data: Intent?,
- productType: ProductType,
- ): Result {
- val result = googlePayService.handleResponseFromGooglePay(resultCode, data)
- result.onSuccess {
- val finalizePaymentResult = completeTokenizedPayment(it, productType)
- finalizePaymentResult.onSuccess {
- return Result.success(Unit)
- }
- return Result.failure(finalizePaymentResult.exceptionOrNull()!!)
- }
- return Result.failure(result.exceptionOrNull()!!)
- }
-
- private suspend fun completeTokenizedPayment(
- paymentData: PaymentData,
- productType: ProductType,
- ): Result {
- val checkout = checkouts[productType]!!
- val googlePayResponse =
- googlePayService.parsePaymentData(paymentData)
- ?: return Result.failure(Exception("cannot parse GPay result"))
-
- val amount =
- Storefront.MoneyInput(checkout.totalPriceV2.amount, checkout.totalPriceV2.currencyCode)
- val idempotencyKey = UUID.randomUUID().toString()
- val addressGPay = googlePayResponse.billingAddress
-
- val address = Storefront.MailingAddressInput().apply {
- lastName = addressGPay.name
- address1 = addressGPay.address1
- address2 = addressGPay.address2 + addressGPay.address3
- province = addressGPay.administrativeArea
- zip = addressGPay.postalCode
- phone = addressGPay.phoneNumber
- }
-
- val payment = Storefront.TokenizedPaymentInputV3(
- amount,
- idempotencyKey,
- address,
- paymentData.toJson(),
- Storefront.PaymentTokenType.GOOGLE_PAY,
- )
- .setTest(true)
-
- return shopifyService.completeWithTokenizedPayment(
- payment = payment,
- checkoutID = checkout.id,
- )
- }
-
- suspend fun applyPromoCode(promoCode: String): Result> {
- val products = variants.keys
- .map { coroutineScope { async { applyPromoCode(promoCode, it) } } }
- .awaitAll()
- .map { result -> result.getOrElse { return Result.failure(it) } }
-
- return Result.success(products)
- }
-
- suspend fun applyPromoCode(promoCode: String, productType: ProductType): Result {
- val checkout = checkouts[productType] ?: return Result.failure(Exception("No checkout"))
-
- val result = if (promoCode.isBlank()) {
- shopifyService.removeDiscount(checkout.id)
- } else {
- shopifyService.applyDiscount(promoCode, checkout.id)
- }
-
- result.onSuccess {
- checkouts[productType] = it
- return Result.success(
- TangemProduct(
- productType,
- TotalSum(
- finalValue = it.totalPriceV2.format(),
- beforeDiscount = variants[productType]!!.compareAtPriceV2.format(),
- ),
- appliedDiscount = it.getAppliedDiscount(),
- ),
-
- )
- }
- return Result.failure(result.exceptionOrNull()!!)
- }
-
- fun getCheckoutUrl(productType: ProductType): String {
- return checkouts[productType]!!.webUrl
- }
-
- suspend fun waitForCheckout(productType: ProductType) {
- val result = shopifyService.checkout(true, checkouts[productType]!!.id)
- result.onSuccess { checkout ->
- if (checkout.order != null && checkout.lineItems != null) {
- val event = ShopOrderToEventConverter().convert(checkout to productType)
- Analytics.send(event)
- }
- }
- }
-
- companion object {
- const val TANGEM_WALLET_2_CARDS_SKU = "TG115X2-S"
- const val TANGEM_WALLET_3_CARDS_SKU = "TG115X3-S"
- val SKUS_TO_DISPLAY = listOf(TANGEM_WALLET_2_CARDS_SKU, TANGEM_WALLET_3_CARDS_SKU)
- }
-}
-
-private fun Storefront.MoneyV2.format(): String {
- val currencySymbol = Currency.getInstance(currencyCode.name).symbol
- val amountFormatted = BigDecimal(amount).setScale(2)
- return currencySymbol + amountFormatted
-}
-
-private fun Storefront.Checkout.getAppliedDiscount(): String? {
- val discountApplication =
- discountApplications.edges.firstOrNull()?.node as? Storefront.DiscountCodeApplication
- return discountApplication?.code
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/shop/data/ProductType.kt b/app/src/main/java/com/tangem/tap/common/shop/data/ProductType.kt
deleted file mode 100644
index d8db451147..0000000000
--- a/app/src/main/java/com/tangem/tap/common/shop/data/ProductType.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.tangem.tap.common.shop.data
-
-import com.tangem.tap.common.shop.TangemShopService
-
-enum class ProductType(val sku: String) {
- WALLET_2_CARDS(TangemShopService.TANGEM_WALLET_2_CARDS_SKU),
- WALLET_3_CARDS(TangemShopService.TANGEM_WALLET_3_CARDS_SKU);
-
- companion object {
- fun fromSku(sku: String): ProductType? {
- return when (sku) {
- WALLET_2_CARDS.sku -> WALLET_2_CARDS
- WALLET_3_CARDS.sku -> WALLET_3_CARDS
- else -> null
- }
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/shop/data/TangemProduct.kt b/app/src/main/java/com/tangem/tap/common/shop/data/TangemProduct.kt
deleted file mode 100644
index 022af2b4ea..0000000000
--- a/app/src/main/java/com/tangem/tap/common/shop/data/TangemProduct.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.tangem.tap.common.shop.data
-
-data class TangemProduct(
- val type: ProductType,
- val totalSum: TotalSum? = null,
- val appliedDiscount: String? = null
-)
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/shop/data/TotalSum.kt b/app/src/main/java/com/tangem/tap/common/shop/data/TotalSum.kt
deleted file mode 100644
index a9e920745f..0000000000
--- a/app/src/main/java/com/tangem/tap/common/shop/data/TotalSum.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.tangem.tap.common.shop.data
-
-data class TotalSum(
- val finalValue: String? = null,
- val beforeDiscount: String? = null,
-)
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/shop/googlepay/GooglePayService.kt b/app/src/main/java/com/tangem/tap/common/shop/googlepay/GooglePayService.kt
deleted file mode 100644
index 757b207741..0000000000
--- a/app/src/main/java/com/tangem/tap/common/shop/googlepay/GooglePayService.kt
+++ /dev/null
@@ -1,150 +0,0 @@
-package com.tangem.tap.common.shop.googlepay
-
-import android.app.Activity
-import android.app.Activity.RESULT_CANCELED
-import android.app.Activity.RESULT_OK
-import android.content.Intent
-import android.util.Log
-import com.google.android.gms.common.api.ApiException
-import com.google.android.gms.wallet.AutoResolveHelper
-import com.google.android.gms.wallet.IsReadyToPayRequest
-import com.google.android.gms.wallet.PaymentData
-import com.google.android.gms.wallet.PaymentDataRequest
-import com.google.android.gms.wallet.PaymentsClient
-import com.tangem.common.core.TangemSdkError
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.withContext
-import org.json.JSONException
-import org.json.JSONObject
-import timber.log.Timber
-import kotlin.coroutines.resume
-import kotlin.coroutines.suspendCoroutine
-
-class GooglePayService(private val paymentsClient: PaymentsClient, private val activity: Activity) {
-
-// var responseCallback: ((Result) -> Unit)? = null
-
- suspend fun checkIfGooglePayAvailable(): Result {
- val isReadyToPayJson = GooglePayUtil.isReadyToPayRequest() ?: return Result.success(false)
- val request = IsReadyToPayRequest.fromJson(isReadyToPayJson.toString())
-
- val task = paymentsClient.isReadyToPay(request)
- return withContext(Dispatchers.IO) {
- suspendCoroutine { continuation ->
- task.addOnCompleteListener { completedTask ->
- try {
- val result = completedTask.getResult(ApiException::class.java)
- continuation.resume(Result.success(true))
- } catch (exception: ApiException) {
- // Process error
- Timber.w("isReadyToPay failed: $exception")
- continuation.resume(Result.failure(exception))
- }
- }
- }
- }
- }
-
- fun payWithGooglePay(totalPriceCents: String, currencyCode: String, merchantID: String) {
- val paymentDataRequestJson = GooglePayUtil.getPaymentDataRequest(
- totalPriceCents,
- currencyCode = currencyCode,
- countryCode = "RU",
- merchantID = merchantID,
- )
- if (paymentDataRequestJson == null) {
- Timber.e("RequestPayment: can't fetch payment data request")
- return
- }
- val request = PaymentDataRequest.fromJson(paymentDataRequestJson.toString())
-
- AutoResolveHelper.resolveTask(
- paymentsClient.loadPaymentData(request),
- activity,
- LOAD_PAYMENT_DATA_REQUEST_CODE,
- )
- }
-
- fun handleResponseFromGooglePay(resultCode: Int, data: Intent?): Result {
- val result = when (resultCode) {
- RESULT_OK -> {
- val paymentData = data?.let { intent -> PaymentData.getFromIntent(intent) }
- if (paymentData == null) {
- Result.failure(Exception("No payment data"))
- } else {
- Result.success(paymentData)
- }
- }
- RESULT_CANCELED -> {
- Result.failure(TangemSdkError.UserCancelled())
- }
- AutoResolveHelper.RESULT_ERROR -> {
- val statusCode = AutoResolveHelper.getStatusFromIntent(data)?.statusCode
- if (statusCode == null) {
- Result.failure(Exception("Unknown Status"))
- } else {
- Result.failure(Exception("$statusCode"))
- }
- }
- else -> Result.failure(Exception("Unknown Status"))
- }
-// responseCallback?.invoke(result)
- return result
- }
-
- fun parsePaymentData(paymentData: PaymentData): GooglePayResponse? {
- val paymentInformation = paymentData.toJson()
-
- try {
- // Token will be null if PaymentDataRequest was not constructed using fromJson(String).
- val paymentMethodData =
- JSONObject(paymentInformation).getJSONObject("paymentMethodData")
- val addressJson = paymentMethodData.getJSONObject("info")
- .getJSONObject("billingAddress")
-
- val address = Address(
- name = addressJson.getString("name"),
- postalCode = addressJson.getString("postalCode"),
- countryCode = addressJson.getString("countryCode"),
- phoneNumber = addressJson.getString("phoneNumber"),
- address1 = addressJson.getString("address1"),
- address2 = addressJson.getString("address2"),
- address3 = addressJson.getString("address3"),
- locality = addressJson.getString("locality"),
- administrativeArea = addressJson.getString("administrativeArea"),
- sortingCode = addressJson.getString("sortingCode"),
- )
-
- val token = paymentMethodData
- .getJSONObject("tokenizationData")
- .getString("token")
-
- return GooglePayResponse(address, token)
- } catch (e: JSONException) {
- Log.e("handlePaymentSuccess", "Error: " + e.toString())
- }
- return null
- }
-
- companion object {
- const val LOAD_PAYMENT_DATA_REQUEST_CODE = 315
- }
-}
-
-data class GooglePayResponse(
- val billingAddress: Address,
- val token: String,
-)
-
-data class Address(
- val name: String,
- val postalCode: String,
- val countryCode: String,
- val phoneNumber: String,
- val address1: String,
- val address2: String,
- val address3: String,
- val locality: String,
- val administrativeArea: String,
- val sortingCode: String,
-)
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/shop/googlepay/GooglePayUtil.kt b/app/src/main/java/com/tangem/tap/common/shop/googlepay/GooglePayUtil.kt
deleted file mode 100644
index 82509e1180..0000000000
--- a/app/src/main/java/com/tangem/tap/common/shop/googlepay/GooglePayUtil.kt
+++ /dev/null
@@ -1,137 +0,0 @@
-package com.tangem.tap.common.shop.googlepay
-
-import android.app.Activity
-import com.google.android.gms.wallet.PaymentsClient
-import com.google.android.gms.wallet.Wallet
-import com.google.android.gms.wallet.WalletConstants
-import org.json.JSONArray
-import org.json.JSONException
-import org.json.JSONObject
-
-object GooglePayUtil {
- private val baseRequest = JSONObject().apply {
- put("apiVersion", 2)
- put("apiVersionMinor", 0)
- }
-
- @Suppress("MagicNumber")
- private val allowedCardNetworks = JSONArray(
- listOf(
- "AMEX",
- "DISCOVER",
- "INTERAC",
- "JCB",
- "MASTERCARD",
- "VISA",
- ),
- )
-
- private val allowedCardAuthMethods = JSONArray(
- listOf(
- "PAN_ONLY",
- "CRYPTOGRAM_3DS",
- ),
- )
-
- private val merchantInfo: JSONObject = JSONObject().put("merchantName", "Example Merchant")
-
- private fun gatewayTokenizationSpecification(merchantID: String): JSONObject {
- return JSONObject().apply {
- put("type", "PAYMENT_GATEWAY")
- put(
- "parameters",
- JSONObject(
- mapOf(
- "gateway" to "shopify",
- "gatewayMerchantId" to merchantID,
- ),
- ),
- )
- }
- }
-
- private fun baseCardPaymentMethod(): JSONObject {
- return JSONObject().apply {
- val parameters = JSONObject().apply {
- put("allowedAuthMethods", allowedCardAuthMethods)
- put("allowedCardNetworks", allowedCardNetworks)
- put("billingAddressRequired", true)
- put(
- "billingAddressParameters",
- JSONObject().apply {
- put("format", "FULL")
- },
- )
- }
-
- put("type", "CARD")
- put("parameters", parameters)
- }
- }
-
- private fun cardPaymentMethod(merchantID: String): JSONObject {
- val cardPaymentMethod = baseCardPaymentMethod()
- cardPaymentMethod.put("tokenizationSpecification", gatewayTokenizationSpecification(merchantID))
-
- return cardPaymentMethod
- }
-
- fun createPaymentsClient(activity: Activity): PaymentsClient {
- val walletOptions = Wallet.WalletOptions.Builder()
- .setEnvironment(PAYMENTS_ENVIRONMENT)
- .build()
-
- return Wallet.getPaymentsClient(activity, walletOptions)
- }
-
- fun isReadyToPayRequest(): JSONObject? {
- return try {
- baseRequest.apply {
- put("allowedPaymentMethods", JSONArray().put(baseCardPaymentMethod()))
- }
- } catch (e: JSONException) {
- null
- }
- }
-
- private fun getTransactionInfo(
- price: String,
- countryCode: String,
- currencyCode: String,
- ): JSONObject {
- return JSONObject().apply {
- put("totalPrice", price)
- put("totalPriceStatus", "FINAL")
- put("countryCode", countryCode)
- put("currencyCode", currencyCode)
- }
- }
-
- fun getPaymentDataRequest(
- price: String,
- countryCode: String,
- currencyCode: String,
- merchantID: String,
- ): JSONObject? {
- try {
- return baseRequest.apply {
- put("allowedPaymentMethods", JSONArray().put(cardPaymentMethod(merchantID)))
- put("transactionInfo", getTransactionInfo(price, countryCode, currencyCode))
- put("merchantInfo", merchantInfo)
-
- // An optional shipping address requirement is a top-level property of the
- // PaymentDataRequest JSON object.
- val shippingAddressParameters = JSONObject().apply {
- put("phoneNumberRequired", false)
-// put("allowedCountryCodes", JSONArray(listOf("US", "GB")))
- }
- put("shippingAddressParameters", shippingAddressParameters)
- put("shippingAddressRequired", true)
- }
- } catch (e: JSONException) {
- return null
- }
- }
-}
-
-const val PAYMENTS_ENVIRONMENT = WalletConstants.ENVIRONMENT_TEST
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/shop/shopify/ShopifyService.kt b/app/src/main/java/com/tangem/tap/common/shop/shopify/ShopifyService.kt
deleted file mode 100644
index f51fbf0c4e..0000000000
--- a/app/src/main/java/com/tangem/tap/common/shop/shopify/ShopifyService.kt
+++ /dev/null
@@ -1,295 +0,0 @@
-package com.tangem.tap.common.shop.shopify
-
-import android.app.Application
-import com.shopify.buy3.GraphCallResult
-import com.shopify.buy3.GraphClient
-import com.shopify.buy3.RetryHandler
-import com.shopify.buy3.Storefront.*
-import com.shopify.graphql.support.ID
-import com.shopify.graphql.support.Input
-import com.tangem.tap.common.shop.shopify.data.CheckoutItem
-import com.tangem.tap.common.shop.shopify.data.checkoutFieldsFragment
-import com.tangem.tap.common.shop.shopify.data.collectionFieldsFragment
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.withContext
-import java.util.concurrent.TimeUnit
-import kotlin.coroutines.resume
-import kotlin.coroutines.suspendCoroutine
-
-@Suppress("LargeClass")
-class ShopifyService(private val application: Application, val shop: ShopifyShop) {
- val client: GraphClient by lazy { initClient() }
-
- suspend fun getShopName(): Result {
- val query = query { rootQuery: QueryRootQuery ->
- rootQuery
- .shop { shopQuery: ShopQuery ->
- shopQuery
- .name()
- }
- }
- return when (val result = queryAsync(query)) {
- is GraphCallResult.Success -> {
- val name = result.response.data!!.shop.name
- Result.success(name)
- }
- is GraphCallResult.Failure -> {
- Result.failure(result.error)
- }
- }
- }
-
- @Suppress("MagicNumber")
- suspend fun getProducts(collectionTitleFilter: String? = null): Result> {
- val filter = collectionTitleFilter?.let { "title:\"$it\"" }
-
- val query = query { rootQuery: QueryRootQuery ->
- rootQuery.collections(
- { arg -> arg.first(250).query(filter) },
- CollectionConnectionQuery::collectionFieldsFragment,
- )
- }
- return when (val result = queryAsync(query)) {
- is GraphCallResult.Success -> {
- val products = result.response.data!!.collections.edges
- .map { it.node.products }
- .flatMap { it.edges }
- .map { it.node }
- Result.success(products)
- }
- is GraphCallResult.Failure -> {
- Result.failure(result.error)
- }
- }
- }
-
- suspend fun checkout(pollUntilOrder: Boolean, checkoutID: ID): Result {
- val query = query { rootQuery: QueryRootQuery ->
- rootQuery
- .node(checkoutID) { query ->
- query.onCheckout { checkoutQuery ->
- with(checkoutQuery) {
- checkoutFieldsFragment()
- }
- }
- }
- }
- val retryHandler = RetryHandler.build(
- delay = 1,
- timeUnit = TimeUnit.SECONDS,
- ) {
- this.retryWhen { result ->
- when (result) {
- is GraphCallResult.Success -> {
- val checkout = result.response.data?.node as? Checkout
- checkout?.order == null
- }
- is GraphCallResult.Failure -> false
- }
- }
- }
-
- val result = if (pollUntilOrder) queryAsync(query, retryHandler) else queryAsync(query)
- return when (result) {
- is GraphCallResult.Success -> {
- val checkout = result.response.data!!.node as? Checkout
- if (checkout != null) {
- Result.success(checkout)
- } else {
- Result.failure(ShopifyError.Unknown)
- }
- }
- is GraphCallResult.Failure -> {
- Result.failure(result.error)
- }
- }
- }
-
- suspend fun createCheckout(
- checkoutItems: List,
- checkoutID: ID? = null,
- ): Result {
- val storefrontLineItems: MutableList = checkoutItems
- .map { CheckoutLineItemInput(it.quantity, it.id) }.toMutableList()
-
- val query = if (checkoutID != null) {
- mutation { mutationQuery: MutationQuery ->
- mutationQuery
- .checkoutLineItemsReplace(
- storefrontLineItems,
- checkoutID,
- ) { payloadQuery: CheckoutLineItemsReplacePayloadQuery ->
- payloadQuery
- .checkout { checkoutQuery: CheckoutQuery ->
- checkoutQuery.checkoutFieldsFragment()
- }
- .userErrors { userErrorQuery: CheckoutUserErrorQuery ->
- userErrorQuery
- .field()
- .message()
- }
- }
- }
- } else {
- val input = CheckoutCreateInput()
- .setLineItemsInput(
- Input.value(storefrontLineItems),
- )
- mutation { mutationQuery: MutationQuery ->
- mutationQuery
- .checkoutCreate(
- input,
- ) { payloadQuery: CheckoutCreatePayloadQuery ->
- payloadQuery
- .checkout { checkoutQuery: CheckoutQuery ->
- checkoutQuery.checkoutFieldsFragment()
- }
- .checkoutUserErrors { userErrorQuery: CheckoutUserErrorQuery ->
- userErrorQuery
- .field()
- .message()
- }
- }
- }
- }
- return runCheckoutMutation(query)
- }
-
- suspend fun applyDiscount(discountCode: String, checkoutID: ID): Result {
- val query = mutation { mutationQuery: MutationQuery ->
- mutationQuery
- .checkoutDiscountCodeApplyV2(
- discountCode,
- checkoutID,
- ) { payloadQuery: CheckoutDiscountCodeApplyV2PayloadQuery ->
- payloadQuery
- .checkout { checkoutQuery: CheckoutQuery ->
- checkoutQuery.checkoutFieldsFragment()
- }
- .checkoutUserErrors { userErrorQuery: CheckoutUserErrorQuery ->
- userErrorQuery
- .field()
- .message()
- }
- }
- }
- return runCheckoutMutation(query)
- }
-
- suspend fun removeDiscount(checkoutID: ID): Result {
- val query = mutation { mutationQuery: MutationQuery ->
- mutationQuery
- .checkoutDiscountCodeRemove(
- checkoutID,
- ) { payloadQuery: CheckoutDiscountCodeRemovePayloadQuery ->
- payloadQuery
- .checkout { checkoutQuery: CheckoutQuery ->
- checkoutQuery.checkoutFieldsFragment()
- }
- .checkoutUserErrors { userErrorQuery: CheckoutUserErrorQuery ->
- userErrorQuery
- .field()
- .message()
- }
- }
- }
- return runCheckoutMutation(query)
- }
-
- suspend fun completeWithTokenizedPayment(
- payment: TokenizedPaymentInputV3,
- checkoutID: ID,
- ): Result {
- val query = mutation { mutationQuery: MutationQuery ->
- mutationQuery
- .checkoutCompleteWithTokenizedPaymentV3(
- checkoutID,
- payment,
- ) { payloadQuery: CheckoutCompleteWithTokenizedPaymentV3PayloadQuery ->
- payloadQuery
- .payment { paymentQuery: PaymentQuery ->
- paymentQuery
- .ready()
- .errorMessage()
- }
- .checkout { checkoutQuery: CheckoutQuery ->
- checkoutQuery
- .ready()
- }
- .checkoutUserErrors { userErrorQuery: CheckoutUserErrorQuery ->
- userErrorQuery
- .field()
- .message()
- }
- }
- }
- return runCheckoutMutation(query)
- }
-
- private suspend fun runCheckoutMutation(mutation: MutationQuery): Result {
- return when (val result = mutationQueryAsync(mutation)) {
- is GraphCallResult.Success -> {
- val checkout = result.response.data!!.checkoutCreate?.checkout
- ?: result.response.data!!.checkoutDiscountCodeApplyV2?.checkout
- ?: result.response.data!!.checkoutDiscountCodeRemove?.checkout
- ?: result.response.data!!.checkoutShippingAddressUpdateV2?.checkout
- ?: result.response.data!!.checkoutEmailUpdateV2?.checkout
- ?: result.response.data!!.checkoutShippingLineUpdate?.checkout
- ?: result.response.data!!.checkoutCompleteWithTokenizedPaymentV3.checkout
-
- Result.success(checkout)
- }
- is GraphCallResult.Failure -> Result.failure(result.error)
- }
- }
-
- private suspend fun queryAsync(
- query: QueryRootQuery,
- retryHandler: RetryHandler,
- ): GraphCallResult =
- withContext(Dispatchers.IO) {
- suspendCoroutine { continuation ->
- client.queryGraph(query).enqueue(retryHandler = retryHandler) { result ->
- continuation.resume(result)
- }
- }
- }
-
- private suspend fun queryAsync(
- query: QueryRootQuery,
- ): GraphCallResult =
- withContext(Dispatchers.IO) {
- suspendCoroutine { continuation ->
- client.queryGraph(query).enqueue { result ->
- continuation.resume(result)
- }
- }
- }
-
- private suspend fun mutationQueryAsync(query: MutationQuery): GraphCallResult =
- withContext(Dispatchers.IO) {
- suspendCoroutine { continuation ->
- client.mutateGraph(query).enqueue { result ->
- continuation.resume(result)
- }
- }
- }
-
- private fun initClient(): GraphClient {
- return GraphClient.build(
- application,
- shop.domain,
- shop.storefrontApiKey,
- ) {
-// httpCache(application.filesDir) {
-// cacheMaxSizeBytes = (1024 * 1024 * 10)
-// defaultCachePolicy =
-// HttpCachePolicy.Default.CACHE_FIRST.expireAfter(20, TimeUnit.MINUTES)
-// }
- }
- }
-}
-
-sealed class ShopifyError : Throwable() {
- object Unknown : ShopifyError()
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/shop/shopify/ShopifyShop.kt b/app/src/main/java/com/tangem/tap/common/shop/shopify/ShopifyShop.kt
deleted file mode 100644
index 776374e240..0000000000
--- a/app/src/main/java/com/tangem/tap/common/shop/shopify/ShopifyShop.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.tangem.tap.common.shop.shopify
-
-import com.squareup.moshi.Json
-import com.squareup.moshi.JsonClass
-
-@JsonClass(generateAdapter = true)
-data class ShopifyShop(
- val domain: String,
- @Json(name = "storefrontApiKeyAndroid")
- val storefrontApiKey: String,
- val merchantID: String,
-)
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/shop/shopify/data/Checkout.kt b/app/src/main/java/com/tangem/tap/common/shop/shopify/data/Checkout.kt
deleted file mode 100644
index 7565db2447..0000000000
--- a/app/src/main/java/com/tangem/tap/common/shop/shopify/data/Checkout.kt
+++ /dev/null
@@ -1,135 +0,0 @@
-package com.tangem.tap.common.shop.shopify.data
-
-import com.shopify.buy3.Storefront
-
-@Suppress("LongMethod", "MagicNumber")
-fun Storefront.CheckoutQuery.checkoutFieldsFragment() {
- ready()
- webUrl()
- currencyCode()
- lineItemsSubtotalPrice { it.amount() }
- totalPriceV2 {
- it.currencyCode()
- it.amount()
- }
- lineItems({ arg -> arg.first(250) }) {
- it.edges {
- it.node {
-// it.id()
- it.title()
- it.quantity()
- it.variant {
- it.priceV2 { it.amount() }
- }
- }
- }
- }
- shippingLine {
- it.handle()
- it.title()
- it.priceV2 { it.amount() }
- }
- availableShippingRates {
- it.ready()
- it.shippingRates {
- it.handle()
- it.title()
- it.priceV2 { it.amount() }
- }
- }
- shippingAddress {
- it.address1()
- it.address2()
- it.city()
-// .company()
- it.country()
-// .countryCodeV2()
- it.firstName()
-// .formatted()
-// .formattedArea()
-// .id()
- it.lastName()
-// .latitude()
-// .longitude()
-// .name()
- it.phone()
- it.province()
-// .provinceCode()
- it.zip()
- }
- discountApplications({ arg -> arg.first(250) }) {
- it.edges {
- it.node {
- it.onDiscountCodeApplication {
- it.code()
-// .applicable()
-// .allocationMethod()
-// .targetSelection()
-// .targetType()
- it.value {
- it.onMoneyV2 {
- it.amount()
- }
- it.onPricingPercentageValue {
- it.percentage()
- }
- }
- }
- }
- }
- }
- order {
- it.cancelReason()
- it.canceledAt()
- it.currencyCode()
-// .currentSubtotalPrice()
-// .currentTotalDuties()
-// .currentTotalPrice()
-// .currentTotalTax()
- it.customerLocale()
- it.customerUrl()
-// .discountApplications()
- it.edited()
- it.email()
- it.financialStatus()
- it.fulfillmentStatus()
-// .id()
-// .lineItems()
-// .metafield()
-// .metafields()
- it.name()
- it.orderNumber()
-// .originalTotalDuties()
-// .originalTotalPrice()
- it.phone()
- it.processedAt()
- it.shippingAddress {
- it.address1()
- it.address2()
- it.city()
- it.company()
- it.country()
- it.countryCodeV2()
- it.firstName()
- it.formatted()
- it.formattedArea()
-// .id()
- it.lastName()
- it.latitude()
- it.longitude()
- it.name()
- it.phone()
- it.province()
- it.provinceCode()
- it.zip()
- }
-// .shippingDiscountAllocations()
- it.statusUrl()
-// .subtotalPriceV2()
-// .successfulFulfillments()
-// .totalPriceV2()
-// .totalRefundedV2()
-// .totalShippingPriceV2()
-// .totalTaxV2()
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/shop/shopify/data/CheckoutItem.kt b/app/src/main/java/com/tangem/tap/common/shop/shopify/data/CheckoutItem.kt
deleted file mode 100644
index 5dc508df40..0000000000
--- a/app/src/main/java/com/tangem/tap/common/shop/shopify/data/CheckoutItem.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.tangem.tap.common.shop.shopify.data
-
-import com.shopify.graphql.support.ID
-
-data class CheckoutItem(
- val id: ID,
- val quantity: Int
-)
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/shop/shopify/data/Collection.kt b/app/src/main/java/com/tangem/tap/common/shop/shopify/data/Collection.kt
deleted file mode 100644
index 1527fc9558..0000000000
--- a/app/src/main/java/com/tangem/tap/common/shop/shopify/data/Collection.kt
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.tangem.tap.common.shop.shopify.data
-
-import com.shopify.buy3.Storefront
-
-@Suppress("MagicNumber")
-fun Storefront.CollectionConnectionQuery.collectionFieldsFragment() {
- edges { collectionEdgeQuery ->
- collectionEdgeQuery
- .node { collectionQuery ->
- collectionQuery
- .title()
- .products(
- { arg -> arg.first(250) },
- ) { productConnectionQuery ->
- productConnectionQuery
- .edges { productEdgeQuery ->
- productEdgeQuery
- .node { productQuery ->
- productQuery.title()
- .productType()
- .description()
- .variants({ arg -> arg.first(10) }) { variantConnectionQuery ->
- variantConnectionQuery.edges { variantQuery ->
- variantQuery.node {
- it.title()
- it.sku()
- it.currentlyNotInStock()
- it.priceV2 {
- it.amount()
- it.currencyCode()
- }
- it.compareAtPriceV2 {
- it.amount()
- it.currencyCode()
- }
- it.compareAtPriceV2 {
- it.amount()
- }
- it.product {
- it.title()
- .productType()
- .description()
- }
- }
- }
- }
- }
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/snackBar/MaxAmountSnackbar.kt b/app/src/main/java/com/tangem/tap/common/snackBar/MaxAmountSnackbar.kt
deleted file mode 100644
index d224143c98..0000000000
--- a/app/src/main/java/com/tangem/tap/common/snackBar/MaxAmountSnackbar.kt
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.tangem.tap.common.snackBar
-
-import android.content.Context
-import android.util.AttributeSet
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.FrameLayout
-import androidx.constraintlayout.widget.ConstraintLayout
-import androidx.coordinatorlayout.widget.CoordinatorLayout
-import com.google.android.material.snackbar.BaseTransientBottomBar
-import com.google.android.material.snackbar.ContentViewCallback
-import com.google.android.material.snackbar.Snackbar
-import com.tangem.wallet.R
-
-/**
-[REDACTED_AUTHOR]
- */
-class MaxAmountSnackbar(
- parent: ViewGroup,
- content: MaxAmountSnackbarView
-) : BaseTransientBottomBar(parent, content, content) {
-
- companion object {
-
- fun make(view: View, onClick: () -> Unit): MaxAmountSnackbar {
- val parent = view.findSuitableParent() ?: throw IllegalArgumentException(
- "No suitable parent found from the given view. Please provide a valid view."
- )
- val inflater = LayoutInflater.from(view.context)
- val customView = inflater.inflate(R.layout.view_snackbar_max_amount, parent, false) as MaxAmountSnackbarView
- customView.setOnClickListener { onClick() }
-
- return MaxAmountSnackbar(parent, customView).apply {
- duration = Snackbar.LENGTH_INDEFINITE
- }
- }
-
- private fun View?.findSuitableParent(): ViewGroup? {
- var view = this
- var fallback: ViewGroup? = null
- do {
- if (view is CoordinatorLayout) {
- return view
- } else if (view is FrameLayout) {
- if (view.id == android.R.id.content) {
- return view
- } else {
- fallback = view
- }
- }
-
- if (view != null) {
- val parent = view.parent
- view = if (parent is View) parent else null
- }
- } while (view != null)
- return fallback
- }
- }
-}
-
-class MaxAmountSnackbarView @JvmOverloads constructor(
- context: Context,
- attrs: AttributeSet? = null,
- defStyleAttr: Int = 0
-) : ConstraintLayout(context, attrs, defStyleAttr), ContentViewCallback {
-
- init {
- View.inflate(context, R.layout.view_snackbar_max_amount_content, this)
- clipToPadding = false
- }
-
- override fun animateContentIn(delay: Int, duration: Int) {
- }
-
- override fun animateContentOut(delay: Int, duration: Int) {
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/text/DecimalDigitsInputFilter.kt b/app/src/main/java/com/tangem/tap/common/text/DecimalDigitsInputFilter.kt
deleted file mode 100644
index 2201e794cc..0000000000
--- a/app/src/main/java/com/tangem/tap/common/text/DecimalDigitsInputFilter.kt
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.tangem.tap.common.text
-
-import android.text.InputFilter
-import android.text.Spanned
-import java.util.regex.Pattern
-
-/**
-[REDACTED_AUTHOR]
- */
-class DecimalDigitsInputFilter(
- digitsBeforeDecimal: Int,
- digitsAfterDecimal: Int,
- private val decimalSeparator: String,
-) : InputFilter {
- private val pattern: Pattern = Pattern.compile(
- "(([1-9]{1}[0-9]{0,${digitsBeforeDecimal - 1}})?||[0]{1})" +
- "((\\$decimalSeparator[0-9]{0,$digitsAfterDecimal})?)||(\\$decimalSeparator)?",
- )
-
- override fun filter(
- source: CharSequence,
- sourceStart: Int,
- sourceEnd: Int,
- destination: Spanned,
- destinationStart: Int,
- destinationEnd: Int,
- ): CharSequence? {
- val destString = destination.toString()
- val prefix = destString.substring(0, destinationStart)
- val suffix = destString.substring(destinationEnd, destString.length)
- val newDestination = prefix + suffix
-
- val resultPrefix = newDestination.substring(0, destinationStart)
- val resultSuffix = newDestination.substring(destinationStart, newDestination.length)
- val result = resultPrefix + source.toString() + resultSuffix
-
- return if (pattern.matcher(result).matches()) {
- null
- } else {
- val replacedWithAppropriateDecimalSeparator = setDecimalSeparator(result, decimalSeparator)
- if (pattern.matcher(replacedWithAppropriateDecimalSeparator).matches()) {
- decimalSeparator
- } else {
- ""
- }
- }
- }
-
- companion object {
- fun setDecimalSeparator(value: String, decimalSeparator: String): String {
- if (value.contains(decimalSeparator)) return value
-
- return if (decimalSeparator == ".") {
- value.replace(",", decimalSeparator)
- } else {
- value.replace(".", decimalSeparator)
- }
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/text/Truncate.kt b/app/src/main/java/com/tangem/tap/common/text/Truncate.kt
deleted file mode 100644
index 0aeb17d6d2..0000000000
--- a/app/src/main/java/com/tangem/tap/common/text/Truncate.kt
+++ /dev/null
@@ -1,136 +0,0 @@
-package com.tangem.tap.common.text
-
-import android.widget.TextView
-import com.tangem.tap.common.extensions.isEven
-
-/**
-[REDACTED_AUTHOR]
- */
-enum class TruncateType {
- START, MIDDLE, END
-}
-
-interface Truncate {
- fun apply(tv: TextView, text: String, with: String): String
-
- companion object {
- fun create(type: TruncateType): Truncate {
- return when (type) {
- TruncateType.START -> TruncateStart()
- TruncateType.MIDDLE -> TruncateMiddle()
- TruncateType.END -> TruncateEnd()
- }
- }
- }
-}
-
-abstract class BaseTruncate : Truncate {
- protected var hasBeenTruncated = false
-
- override fun apply(tv: TextView, text: String, with: String): String {
- val roughLength = getRoughFitLength(tv, text, with)
- val fittedText = preciseFitting(tv, roughTruncate(text, roughLength), with)
- return if (hasBeenTruncated) attachWith(fittedText, with) else fittedText
- }
-
- protected fun getRoughFitLength(tv: TextView, text: String, with: String): Int {
- val existingSpace = tv.measuredWidth - (tv.paddingStart + tv.paddingEnd)
- val textWillTakeSpace = tv.paint.measureText(text)
- val overSizeRatio: Float = textWillTakeSpace / existingSpace
-
- val maxLengthOfText = text.length / overSizeRatio
- if (text.length <= maxLengthOfText) return text.length
-
- return maxLengthOfText.toInt()
- }
-
- protected fun preciseFitting(tv: TextView, text: String, with: String): String {
- if (!hasBeenTruncated) return text
-
- val spaceForText = tv.measuredWidth - (tv.paddingStart + tv.paddingEnd)
-
- var fittedText = text
- while (tv.paint.measureText(fittedText + with) > spaceForText) {
- fittedText = preciseTruncate(fittedText)
- }
- return fittedText
- }
-
- protected abstract fun roughTruncate(text: String, residualLength: Int): String
- protected abstract fun preciseTruncate(text: String): String
- protected abstract fun attachWith(text: String, with: String): String
-}
-
-class TruncateStart : BaseTruncate() {
- override fun roughTruncate(text: String, residualLength: Int): String {
- if (text.length <= residualLength) return text
-
- hasBeenTruncated = true
- return text.substring(residualLength, text.length)
- }
-
- override fun preciseTruncate(text: String): String = text.substring(1, text.length)
-
- override fun attachWith(text: String, with: String): String = with + text
-}
-
-class TruncateMiddle : BaseTruncate() {
-
- override fun roughTruncate(text: String, residualLength: Int): String {
- if (text.length <= residualLength) return text
-
- hasBeenTruncated = true
- val halfOfResidualLength = residualLength / 2
- val leftSide = text.substring(0, halfOfResidualLength)
- val rightSide = text.substring(text.length - halfOfResidualLength, text.length)
-
- return leftSide + rightSide
- }
-
- override fun preciseTruncate(text: String): String {
- val middlePosition = text.length / 2
- return if (text.length.isEven()) {
- val leftSide = text.substring(0, middlePosition - 1)
- val rightSide = text.substring(middlePosition, text.length)
- leftSide + rightSide
- } else {
- val leftSide = text.substring(0, middlePosition)
- val rightSide = text.substring(middlePosition + 1, text.length)
- leftSide + rightSide
- }
- }
-
- override fun attachWith(text: String, with: String): String {
- val cuttingPosition = text.length / 2
- val leftSide = text.substring(0, cuttingPosition)
- val rightSide = text.substring(cuttingPosition, text.length)
- return leftSide + with + rightSide
- }
-}
-
-class TruncateEnd : BaseTruncate() {
- override fun roughTruncate(text: String, residualLength: Int): String {
- if (text.length <= residualLength) return text
-
- hasBeenTruncated = true
- return text.substring(0, residualLength)
- }
-
- override fun preciseTruncate(text: String): String = text.substring(0, text.length - 1)
-
- override fun attachWith(text: String, with: String): String = text + with
-}
-
-fun TextView.truncateWith(text: String, type: TruncateType, with: String = "..."): String {
- val truncate = Truncate.create(type)
- return truncate.apply(this, text, with)
-}
-
-fun TextView.truncateStartWith(text: String, with: String = "..."): String =
- this.truncateWith(text, TruncateType.START, with)
-
-fun TextView.truncateMiddleWith(text: String, with: String = "..."): String =
- this.truncateWith(text, TruncateType.MIDDLE, with)
-
-fun TextView.truncateEndWith(text: String, with: String = "..."): String =
- this.truncateWith(text, TruncateType.END, with)
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/toggleWidget/IndeterminateProgressButtonWidget.kt b/app/src/main/java/com/tangem/tap/common/toggleWidget/IndeterminateProgressButtonWidget.kt
deleted file mode 100644
index 56f80d5d78..0000000000
--- a/app/src/main/java/com/tangem/tap/common/toggleWidget/IndeterminateProgressButtonWidget.kt
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.tangem.tap.common.toggleWidget
-
-import android.graphics.drawable.Drawable
-import android.view.View
-import com.google.android.material.button.MaterialButton
-import com.tangem.tap.common.extensions.hide
-import com.tangem.tap.common.extensions.show
-import com.tangem.tap.features.wallet.redux.ProgressState
-
-/**
-[REDACTED_AUTHOR]
- */
-open class IndeterminateProgressButtonWidget(
- private val button: MaterialButton,
- private val progress: View,
- initialState: ProgressState = ProgressState.Done,
-) : ViewStateWidget {
-
- private var text: CharSequence = button.text
- private var icon: Drawable? = button.icon
- private var iconGravity: Int? = button.iconGravity
-
- init {
- if (initialState != ProgressState.Done) changeState(initialState)
- }
-
- var isEnabled: Boolean
- get() = button.isEnabled
- set(value) {
- button.isEnabled = value
- }
-
- override val mainView: View = button
-
- override fun changeState(state: WidgetState) {
- val progressState = state as? ProgressState ?: return
-
- when (progressState) {
- ProgressState.Done, ProgressState.Error -> switchToNone()
- ProgressState.Loading -> switchToProgress()
- else -> {}
- }
- }
-
- protected open fun switchToNone() {
- button.isClickable = true
- button.text = text
- button.icon = icon
- iconGravity?.let { button.iconGravity = it }
-
- progress.hide()
- }
-
- protected open fun switchToProgress() {
- button.isClickable = false
- button.text = ""
- button.icon = null
-
- progress.show()
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/toggleWidget/RefreshBalanceWidget.kt b/app/src/main/java/com/tangem/tap/common/toggleWidget/RefreshBalanceWidget.kt
index 6a5bd17f60..3996e28d5c 100644
--- a/app/src/main/java/com/tangem/tap/common/toggleWidget/RefreshBalanceWidget.kt
+++ b/app/src/main/java/com/tangem/tap/common/toggleWidget/RefreshBalanceWidget.kt
@@ -2,25 +2,16 @@ package com.tangem.tap.common.toggleWidget
import android.view.View
import android.view.ViewGroup
-import android.view.animation.AccelerateInterpolator
-import android.view.animation.AlphaAnimation
-import android.view.animation.Animation
-import android.view.animation.AnimationSet
-import android.view.animation.AnticipateOvershootInterpolator
-import android.view.animation.LinearInterpolator
-import android.view.animation.RotateAnimation
-import android.view.animation.ScaleAnimation
+import android.view.animation.*
import android.widget.ViewSwitcher
-import com.tangem.tap.features.wallet.redux.ProgressState
+import com.tangem.tap.common.entities.ProgressState
import com.tangem.wallet.R
/**
[REDACTED_AUTHOR]
*/
@Suppress("MagicNumber")
-class RefreshBalanceWidget(
- private val root: ViewGroup,
-) : ViewStateWidget {
+class RefreshBalanceWidget(root: ViewGroup) : ViewStateWidget {
var isShowing: Boolean? = null
private set
diff --git a/app/src/main/java/com/tangem/tap/common/ui/AddressInfoBottomSheetDialog.kt b/app/src/main/java/com/tangem/tap/common/ui/AddressInfoBottomSheetDialog.kt
new file mode 100644
index 0000000000..df54352380
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/ui/AddressInfoBottomSheetDialog.kt
@@ -0,0 +1,75 @@
+package com.tangem.tap.common.ui
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.widget.Toast
+import com.google.android.material.bottomsheet.BottomSheetBehavior
+import com.google.android.material.bottomsheet.BottomSheetDialog
+import com.tangem.core.analytics.Analytics
+import com.tangem.tap.common.analytics.events.Token
+import com.tangem.tap.common.extensions.*
+import com.tangem.tap.common.redux.AppDialog
+import com.tangem.tap.domain.model.WalletAddressData
+import com.tangem.tap.proxy.redux.DaggerGraphState
+import com.tangem.tap.store
+import com.tangem.wallet.R
+import com.tangem.wallet.databinding.DialogOnboardingAddressInfoBinding
+
+/**
+[REDACTED_AUTHOR]
+ */
+internal class AddressInfoBottomSheetDialog(
+ private val stateDialog: AppDialog.AddressInfoDialog,
+ context: Context,
+) : BottomSheetDialog(context) {
+
+ var binding: DialogOnboardingAddressInfoBinding? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = DialogOnboardingAddressInfoBinding
+ .inflate(LayoutInflater.from(context))
+ setContentView(binding!!.root)
+ behavior.state = BottomSheetBehavior.STATE_EXPANDED
+ setOnCancelListener {
+ store.dispatchDialogHide()
+ binding = null
+ }
+ }
+
+ override fun show() {
+ super.show()
+ Analytics.send(Token.Receive.ScreenOpened(stateDialog.currency.currencySymbol))
+ showData(data = stateDialog.addressData)
+ }
+
+ private fun showData(data: WalletAddressData) = with(binding!!) {
+ pseudoToolbar.imvClose.setOnClickListener {
+ dismissWithAnimation = true
+ cancel()
+ }
+ imvQrCode.setImageBitmap(data.shareUrl.toQrCode())
+ tvAddress.text = data.address
+ btnFlCopyAddress.setOnClickListener {
+ Analytics.send(Token.Receive.ButtonCopyAddress())
+
+ Toast
+ .makeText(context, R.string.wallet_notification_address_copied, Toast.LENGTH_SHORT)
+ .show()
+
+ store.inject(DaggerGraphState::clipboardManager).setText(text = data.address, isSensitive = true)
+ }
+ btnFlShare.setOnClickListener {
+ Analytics.send(Token.Receive.ButtonShareAddress())
+ store.dispatchShare(data.shareUrl)
+ }
+ val blockchain = stateDialog.currency.blockchain
+ tvReceiveMessage.text = tvReceiveMessage.getString(
+ id = R.string.address_qr_code_message_format,
+ blockchain.getCoinName(),
+ blockchain.currency,
+ blockchain.fullName,
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/ui/ScanFailsDialog.kt b/app/src/main/java/com/tangem/tap/common/ui/ScanFailsDialog.kt
new file mode 100644
index 0000000000..6096730a8e
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/ui/ScanFailsDialog.kt
@@ -0,0 +1,84 @@
+package com.tangem.tap.common.ui
+
+import android.content.Context
+import android.view.View
+import android.widget.TextView
+import androidx.appcompat.app.AlertDialog
+import androidx.core.view.isVisible
+import com.tangem.core.analytics.Analytics
+import com.tangem.core.analytics.models.AnalyticsParam
+import com.tangem.core.analytics.models.Basic
+import com.tangem.domain.feedback.models.FeedbackEmailType
+import com.tangem.domain.redux.StateDialog
+import com.tangem.tap.common.analytics.events.ScanFailsDialogAnalytics
+import com.tangem.tap.common.extensions.dispatchDialogHide
+import com.tangem.tap.common.extensions.dispatchOpenUrl
+import com.tangem.tap.common.extensions.inject
+import com.tangem.tap.features.home.LocaleRegionProvider
+import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE
+import com.tangem.tap.proxy.redux.DaggerGraphState
+import com.tangem.tap.scope
+import com.tangem.tap.store
+import com.tangem.wallet.R
+import kotlinx.coroutines.launch
+
+/**
+[REDACTED_AUTHOR]
+ */
+internal object ScanFailsDialog {
+
+ private const val HOW_TO_SCAN_RU_LINK = "https://tangem.com/ru/blog/post/scan-tangem-card/"
+ private const val HOW_TO_SCAN_LINK = "https://tangem.com/en/blog/post/scan-tangem-card/"
+
+ fun create(context: Context, source: StateDialog.ScanFailsSource, onTryAgain: (() -> Unit)? = null): AlertDialog {
+ return AlertDialog.Builder(context, R.style.CustomMaterialDialog).apply {
+ val customView = View.inflate(context, R.layout.dialog_scan_fails, null)
+ val sourceAnalytics = when (source) {
+ StateDialog.ScanFailsSource.MAIN -> AnalyticsParam.ScreensSources.Main
+ StateDialog.ScanFailsSource.SIGN_IN -> AnalyticsParam.ScreensSources.SignIn
+ StateDialog.ScanFailsSource.SETTINGS -> AnalyticsParam.ScreensSources.Settings
+ StateDialog.ScanFailsSource.INTRO -> AnalyticsParam.ScreensSources.Intro
+ }
+ val tryAgainBtn: TextView? = customView.findViewById(R.id.try_again_button)
+ if (onTryAgain != null) {
+ tryAgainBtn?.isVisible = true
+ tryAgainBtn?.setOnClickListener {
+ store.dispatchDialogHide()
+ Analytics.send(
+ ScanFailsDialogAnalytics(
+ button = ScanFailsDialogAnalytics.Buttons.TRY_AGAIN,
+ source = sourceAnalytics,
+ ),
+ )
+ onTryAgain()
+ }
+ } else {
+ tryAgainBtn?.isVisible = false
+ }
+ customView.findViewById(R.id.how_to_scan_button)?.setOnClickListener {
+ Analytics.send(
+ ScanFailsDialogAnalytics(
+ button = ScanFailsDialogAnalytics.Buttons.HOW_TO_SCAN,
+ source = sourceAnalytics,
+ ),
+ )
+ val locale = LocaleRegionProvider().getRegion()
+ val link = if (locale.lowercase() == RUSSIA_COUNTRY_CODE) HOW_TO_SCAN_RU_LINK else HOW_TO_SCAN_LINK
+ store.dispatchOpenUrl(link)
+ }
+ customView.findViewById(R.id.request_support_button)?.setOnClickListener {
+ Analytics.send(Basic.ButtonSupport(sourceAnalytics))
+
+ scope.launch {
+ store.inject(DaggerGraphState::sendFeedbackEmailUseCase)
+ .invoke(type = FeedbackEmailType.ScanningProblem)
+ }
+ }
+ customView.findViewById(R.id.cancel_button)?.setOnClickListener {
+ store.dispatchDialogHide()
+ }
+ setView(customView)
+ setOnDismissListener { store.dispatchDialogHide() }
+ }.create()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/ui/SimpleAlertDialog.kt b/app/src/main/java/com/tangem/tap/common/ui/SimpleAlertDialog.kt
index 365f235f11..3cd171d04a 100644
--- a/app/src/main/java/com/tangem/tap/common/ui/SimpleAlertDialog.kt
+++ b/app/src/main/java/com/tangem/tap/common/ui/SimpleAlertDialog.kt
@@ -2,6 +2,7 @@ package com.tangem.tap.common.ui
import android.content.Context
import androidx.appcompat.app.AlertDialog
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.store
import com.tangem.wallet.R
@@ -39,7 +40,7 @@ object SimpleCancelableAlertDialog {
secondaryButtonAction: () -> Unit = {},
context: Context,
): AlertDialog {
- return AlertDialog.Builder(context).apply {
+ return MaterialAlertDialogBuilder(context, R.style.CustomMaterialDialog).apply {
setTitle(titleRes?.let { context.getString(it) } ?: title)
setMessage(messageRes?.let { context.getString(it) } ?: message)
setPositiveButton(context.getText(primaryButtonRes)) { _, _ -> primaryButtonAction() }
diff --git a/app/src/main/java/com/tangem/tap/common/ui/SimpleOkDialog.kt b/app/src/main/java/com/tangem/tap/common/ui/SimpleOkDialog.kt
new file mode 100644
index 0000000000..e0eb7acf6f
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/ui/SimpleOkDialog.kt
@@ -0,0 +1,31 @@
+package com.tangem.tap.common.ui
+
+import android.content.Context
+import androidx.appcompat.app.AlertDialog
+import com.tangem.tap.common.extensions.dispatchDialogHide
+import com.tangem.tap.common.redux.AppDialog
+import com.tangem.tap.store
+import com.tangem.wallet.R
+
+/**
+[REDACTED_AUTHOR]
+ */
+object SimpleOkDialog {
+
+ fun create(dialog: AppDialog.SimpleOkDialogRes, context: Context): AlertDialog {
+ val message = if (dialog.args.isEmpty()) {
+ context.getString(dialog.messageId)
+ } else {
+ context.getString(dialog.messageId, *dialog.args.toTypedArray())
+ }
+ return AlertDialog.Builder(context).apply {
+ setTitle(context.getString(dialog.headerId))
+ setMessage(message)
+ setPositiveButton(R.string.common_ok) { _, _ -> }
+ setOnDismissListener {
+ store.dispatchDialogHide()
+ dialog.onOk?.invoke()
+ }
+ }.create()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/url/CustomTabsUrlOpener.kt b/app/src/main/java/com/tangem/tap/common/url/CustomTabsUrlOpener.kt
new file mode 100644
index 0000000000..965d6caacd
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/url/CustomTabsUrlOpener.kt
@@ -0,0 +1,74 @@
+package com.tangem.tap.common.url
+
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.net.Uri
+import androidx.browser.customtabs.CustomTabColorSchemeParams
+import androidx.browser.customtabs.CustomTabsClient
+import androidx.browser.customtabs.CustomTabsIntent
+import androidx.browser.customtabs.CustomTabsIntent.COLOR_SCHEME_DARK
+import androidx.browser.customtabs.CustomTabsIntent.COLOR_SCHEME_LIGHT
+import com.tangem.core.navigation.url.UrlOpener
+import com.tangem.tap.common.apptheme.MutableAppThemeModeHolder
+import com.tangem.tap.common.extensions.getColorCompat
+import com.tangem.tap.foregroundActivityObserver
+import com.tangem.tap.withForegroundActivity
+import com.tangem.wallet.R
+import timber.log.Timber
+
+internal class CustomTabsUrlOpener : UrlOpener {
+
+ override fun openUrl(url: String) {
+ foregroundActivityObserver.withForegroundActivity {
+ openUrl(url, context = it)
+ }
+ }
+
+ private fun openUrl(url: String, context: Context) {
+ if (url.isEmpty()) return
+ val customTabsIntent = CustomTabsIntent.Builder()
+ .setDefaultColorSchemeParams(
+ CustomTabColorSchemeParams.Builder()
+ .setNavigationBarColor(context.getColorCompat(R.color.toolbarColor))
+ .build(),
+ )
+ .setColorScheme(
+ if (MutableAppThemeModeHolder.isDarkThemeActive) COLOR_SCHEME_DARK else COLOR_SCHEME_LIGHT,
+ )
+ .build()
+
+ customTabsIntent.intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
+
+ val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
+ runCatching {
+ if (checkCustomTabsAvailability(context, browserIntent)) {
+ context.startActivity(browserIntent)
+ } else {
+ customTabsIntent.launchUrl(context, Uri.parse(url))
+ }
+ }.onFailure {
+ Timber.e(it.message)
+ }
+ }
+
+ /**
+ * Custom Tabs compatibility check. Returns flag whether custom tabs are supported
+ * @see "https://developer.chrome.com/docs/android/custom-tabs/howto-custom-tab-check"
+ */
+ private fun checkCustomTabsAvailability(context: Context, browserIntent: Intent): Boolean {
+ // Get all apps that can handle VIEW intents and Custom Tab service connections.
+ val resolveInfos = context.packageManager.queryIntentActivities(browserIntent, PackageManager.MATCH_ALL)
+
+ // Extract package names from ResolveInfo objects
+ val packageNames = mutableListOf()
+ for (info in resolveInfos) {
+ packageNames.add(info.activityInfo.packageName)
+ }
+
+ // Get a package that supports Custom Tabs
+ val packageName = CustomTabsClient.getPackageName(context, packageNames, true)
+
+ return packageName == null // Custom Tabs are not supported by any browser on the device
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/zendesk/ZendeskConfig.kt b/app/src/main/java/com/tangem/tap/common/zendesk/ZendeskConfig.kt
deleted file mode 100644
index 66569ee1b7..0000000000
--- a/app/src/main/java/com/tangem/tap/common/zendesk/ZendeskConfig.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.tangem.tap.common.zendesk
-
-import com.squareup.moshi.Json
-import com.squareup.moshi.JsonClass
-
-@JsonClass(generateAdapter = true)
-data class ZendeskConfig(
- @Json(name = "zendeskApiKey")
- val apiKey: String,
- @Json(name = "zendeskAppId")
- val appId: String,
- @Json(name = "zendeskClientId")
- val clientId: String,
- @Json(name = "zendeskAccountKey")
- val accountKey: String,
- @Json(name = "zendeskUrl")
- val url: String,
-)
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/core/navigation/email/AndroidEmailSender.kt b/app/src/main/java/com/tangem/tap/core/navigation/email/AndroidEmailSender.kt
new file mode 100644
index 0000000000..8d7beb3948
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/core/navigation/email/AndroidEmailSender.kt
@@ -0,0 +1,73 @@
+package com.tangem.tap.core.navigation.email
+
+import android.content.Intent
+import android.net.Uri
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.app.ShareCompat
+import androidx.core.content.ContextCompat
+import androidx.core.content.FileProvider
+import com.tangem.core.navigation.email.EmailSender
+import com.tangem.tap.foregroundActivityObserver
+import timber.log.Timber
+
+/**
+ * Implementation of email sender for Android
+ *
+[REDACTED_AUTHOR]
+ */
+internal class AndroidEmailSender : EmailSender {
+
+ override fun send(email: EmailSender.Email, onFail: ((Exception) -> Unit)?) {
+ val activity = foregroundActivityObserver.foregroundActivity
+
+ if (activity == null) {
+ Timber.e("Foreground activity not found")
+ return
+ }
+
+ val originalIntent = createEmailShareIntent(activity, email)
+ val emailFilterIntent = Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:"))
+
+ val packageManager = activity.packageManager
+ val originalIntentResults = packageManager.queryIntentActivities(originalIntent, 0)
+ val emailFilterIntentResults = packageManager.queryIntentActivities(emailFilterIntent, 0)
+
+ val targetedIntents = originalIntentResults
+ .filter { originalResult ->
+ emailFilterIntentResults.any {
+ originalResult.activityInfo.packageName == it.activityInfo.packageName
+ }
+ }
+ .map {
+ createEmailShareIntent(activity, email).apply { setPackage(it.activityInfo.packageName) }
+ }
+ .toMutableList()
+
+ try {
+ val chooserIntent = Intent.createChooser(targetedIntents.removeAt(0), "Send mail...").apply {
+ putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedIntents.toTypedArray())
+ }
+
+ ContextCompat.startActivity(activity, chooserIntent, null)
+ } catch (ex: Exception) {
+ Timber.e("Failed to send email: $ex")
+ }
+ }
+
+ private fun createEmailShareIntent(activity: AppCompatActivity, email: EmailSender.Email): Intent {
+ val builder = ShareCompat.IntentBuilder(activity)
+ .setType("message/rfc822")
+ .setEmailTo(arrayOf(email.address))
+ .setSubject(email.subject)
+ .setText(email.message)
+
+ email.attachment?.let {
+ builder.setStream(
+ FileProvider.getUriForFile(activity, "${activity.packageName}.provider", it),
+ )
+ }
+
+ return builder.intent
+ .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/data/DefaultCardSdkProvider.kt b/app/src/main/java/com/tangem/tap/data/DefaultCardSdkProvider.kt
new file mode 100644
index 0000000000..a1751aff85
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/data/DefaultCardSdkProvider.kt
@@ -0,0 +1,174 @@
+package com.tangem.tap.data
+
+import androidx.fragment.app.FragmentActivity
+import androidx.lifecycle.DefaultLifecycleObserver
+import androidx.lifecycle.LifecycleOwner
+import com.tangem.Log
+import com.tangem.TangemSdk
+import com.tangem.common.CardFilter
+import com.tangem.common.authentication.AuthenticationManager
+import com.tangem.common.card.FirmwareVersion
+import com.tangem.common.core.Config
+import com.tangem.common.services.secure.SecureStorage
+import com.tangem.core.analytics.api.AnalyticsEventHandler
+import com.tangem.crypto.bip39.Wordlist
+import com.tangem.data.card.sdk.CardSdkOwner
+import com.tangem.data.card.sdk.CardSdkProvider
+import com.tangem.sdk.DefaultSessionViewDelegate
+import com.tangem.sdk.extensions.*
+import com.tangem.sdk.nfc.AndroidNfcAvailabilityProvider
+import com.tangem.sdk.nfc.NfcManager
+import com.tangem.sdk.storage.create
+import com.tangem.tap.foregroundActivityObserver
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
+import kotlinx.coroutines.runBlocking
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/**
+ * Implementation of CardSDK instance provider
+ *
+[REDACTED_AUTHOR]
+ */
+@Singleton
+internal class DefaultCardSdkProvider @Inject constructor(
+ private val analyticsEventHandler: AnalyticsEventHandler,
+ private val dispatchers: CoroutineDispatcherProvider,
+) : CardSdkProvider, CardSdkOwner {
+
+ private val observer = Observer()
+
+ private var holder: Holder? = null
+
+ override val sdk: TangemSdk
+ get() = holder?.sdk ?: tryToRegisterWithForegroundActivity()
+
+ override fun register(activity: FragmentActivity) = runBlocking(dispatchers.mainImmediate) {
+ if (activity.isDestroyed || activity.isFinishing || activity.isChangingConfigurations) {
+ val message = "Tangem SDK owner registration skipped: activity is destroyed or finishing"
+ analyticsEventHandler.send(TangemSdkWarningEvent(message))
+ Log.info { message }
+ return@runBlocking
+ }
+
+ if (holder != null) {
+ unsubscribeAndCleanup()
+ }
+
+ initialize(activity)
+
+ activity.lifecycle.addObserver(observer)
+
+ Log.info { "Tangem SDK owner registered" }
+ }
+
+ private fun tryToRegisterWithForegroundActivity(): TangemSdk = runBlocking(dispatchers.mainImmediate) {
+ val warning = "Tangem SDK holder is null, trying to recreate it with foreground activity"
+ analyticsEventHandler.send(TangemSdkWarningEvent(warning))
+ Log.warning { warning }
+
+ val activity = foregroundActivityObserver.foregroundActivity
+
+ if (activity == null) {
+ val error = "Tangem SDK holder is null and foreground activity is null"
+ analyticsEventHandler.send(TangemSdkWarningEvent(error))
+ Log.error { error }
+ error(error)
+ }
+
+ register(activity)
+
+ val sdk = holder?.sdk
+
+ if (sdk == null) {
+ val error = "Tangem SDK is null after re-registering with foreground activity"
+ analyticsEventHandler.send(TangemSdkWarningEvent(error))
+ Log.error { error }
+ error(error)
+ }
+
+ return@runBlocking sdk
+ }
+
+ private fun initialize(activity: FragmentActivity) {
+ val secureStorage = SecureStorage.create(activity)
+ val nfcManager = TangemSdk.initNfcManager(activity)
+ val authenticationManager = TangemSdk.initAuthenticationManager(activity)
+ val keystoreManager = TangemSdk.initKeystoreManager(authenticationManager, secureStorage)
+
+ val viewDelegate = DefaultSessionViewDelegate(nfcManager, activity)
+ viewDelegate.sdkConfig = config
+
+ val androidNfcAvailabilityProvider = AndroidNfcAvailabilityProvider(activity)
+ val sdk = TangemSdk(
+ reader = nfcManager.reader,
+ viewDelegate = viewDelegate,
+ nfcAvailabilityProvider = androidNfcAvailabilityProvider,
+ secureStorage = secureStorage,
+ authenticationManager = authenticationManager,
+ keystoreManager = keystoreManager,
+ wordlist = Wordlist.getWordlist(activity),
+ config = config,
+ )
+
+ holder = Holder(
+ activity = activity,
+ nfcManager = nfcManager,
+ authenticationManager = authenticationManager,
+ sdk = sdk,
+ )
+
+ Log.info { "Tangem SDK initialized" }
+ }
+
+ private fun unsubscribeAndCleanup() {
+ val currentHolder = holder
+
+ if (currentHolder == null) {
+ Log.info { "Tangem SDK already unsubscribed and cleaned up" }
+ return
+ }
+
+ with(currentHolder) {
+ nfcManager.unsubscribe(activity)
+ authenticationManager.unsubscribe(activity)
+
+ activity.lifecycle.removeObserver(observer)
+ }
+
+ holder = null
+
+ Log.info { "Tangem SDK unsubscribed and cleaned up" }
+ }
+
+ inner class Observer : DefaultLifecycleObserver {
+
+ override fun onDestroy(owner: LifecycleOwner) {
+ Log.info { "Tangem SDK owner destroyed" }
+
+ unsubscribeAndCleanup()
+ }
+ }
+
+ data class Holder(
+ val activity: FragmentActivity,
+ val sdk: TangemSdk,
+ val nfcManager: NfcManager,
+ val authenticationManager: AuthenticationManager,
+ )
+
+ private companion object {
+
+ val config = Config(
+ linkedTerminal = true,
+ allowUntrustedCards = true,
+ filter = CardFilter(
+ allowedCardTypes = FirmwareVersion.FirmwareType.entries.toList(),
+ maxFirmwareVersion = FirmwareVersion(major = 6, minor = 33),
+ batchIdFilter = CardFilter.Companion.ItemFilter.Deny(
+ items = setOf("0027", "0030", "0031", "0035"),
+ ),
+ ),
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/data/DefaultVisaAuthTokenStorage.kt b/app/src/main/java/com/tangem/tap/data/DefaultVisaAuthTokenStorage.kt
new file mode 100644
index 0000000000..a6128ddfe6
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/data/DefaultVisaAuthTokenStorage.kt
@@ -0,0 +1,56 @@
+package com.tangem.tap.data
+
+import android.content.Context
+import com.squareup.moshi.Moshi
+import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
+import com.tangem.common.services.secure.SecureStorage
+import com.tangem.datasource.local.visa.VisaAuthTokenStorage
+import com.tangem.domain.visa.model.VisaAuthTokens
+import com.tangem.sdk.storage.AndroidSecureStorage
+import com.tangem.sdk.storage.createEncryptedSharedPreferences
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
+import dagger.hilt.android.qualifiers.ApplicationContext
+import kotlinx.coroutines.withContext
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+internal class DefaultVisaAuthTokenStorage @Inject constructor(
+ @ApplicationContext applicationContext: Context,
+ private val dispatcherProvider: CoroutineDispatcherProvider,
+) : VisaAuthTokenStorage {
+
+ private val secureStorage = AndroidSecureStorage(
+ preferences = SecureStorage.createEncryptedSharedPreferences(
+ context = applicationContext,
+ storageName = "visa_auth_storage",
+ ),
+ )
+
+ private val moshi = Moshi.Builder()
+ .add(KotlinJsonAdapterFactory())
+ .build()
+
+ private val tokensAdapter = moshi.adapter(VisaAuthTokens::class.java)
+
+ override suspend fun store(cardId: String, tokens: VisaAuthTokens) = withContext(dispatcherProvider.io) {
+ val json = tokensAdapter.toJson(tokens)
+
+ secureStorage.store(
+ json.encodeToByteArray(throwOnInvalidSequence = true),
+ createKey(cardId),
+ )
+ }
+
+ override suspend fun get(cardId: String): VisaAuthTokens? = withContext(dispatcherProvider.io) {
+ secureStorage.get(createKey(cardId))
+ ?.decodeToString(throwOnInvalidSequence = true)
+ ?.let(tokensAdapter::fromJson)
+ }
+
+ override fun remove(cardId: String) {
+ secureStorage.delete(createKey(cardId))
+ }
+
+ private fun createKey(cardId: String): String = "visa_auth_tokens_$cardId"
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/data/DefaultVisaOTPStorage.kt b/app/src/main/java/com/tangem/tap/data/DefaultVisaOTPStorage.kt
new file mode 100644
index 0000000000..f752d10dea
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/data/DefaultVisaOTPStorage.kt
@@ -0,0 +1,53 @@
+package com.tangem.tap.data
+
+import android.content.Context
+import com.tangem.common.extensions.toByteArray
+import com.tangem.common.extensions.toInt
+import com.tangem.common.services.secure.SecureStorage
+import com.tangem.datasource.local.visa.VisaOTPStorage
+import com.tangem.datasource.local.visa.VisaOtpData
+import com.tangem.sdk.storage.AndroidSecureStorage
+import com.tangem.sdk.storage.createEncryptedSharedPreferences
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
+import dagger.hilt.android.qualifiers.ApplicationContext
+import kotlinx.coroutines.withContext
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class DefaultVisaOTPStorage @Inject constructor(
+ @ApplicationContext applicationContext: Context,
+ private val dispatcherProvider: CoroutineDispatcherProvider,
+) : VisaOTPStorage {
+
+ private val secureStorage = AndroidSecureStorage(
+ preferences = SecureStorage.createEncryptedSharedPreferences(
+ context = applicationContext,
+ storageName = "visa_otp_storage",
+ ),
+ )
+
+ override suspend fun saveOTP(cardId: String, data: VisaOtpData) = withContext(dispatcherProvider.io) {
+ secureStorage.store(data.rootOTP, VISA_ROOT_OTP_KEY_PREFIX + cardId)
+ secureStorage.store(data.counter.toByteArray(), VISA_OTP_COUNTER_KEY_PREFIX + cardId)
+ }
+
+ override suspend fun getOTP(cardId: String): VisaOtpData? = withContext(dispatcherProvider.io) {
+ val rootOTP = secureStorage.get(VISA_ROOT_OTP_KEY_PREFIX + cardId) ?: return@withContext null
+ val counter = secureStorage.get(VISA_OTP_COUNTER_KEY_PREFIX + cardId)?.toInt() ?: return@withContext null
+ VisaOtpData(
+ rootOTP = rootOTP,
+ counter = counter,
+ )
+ }
+
+ override suspend fun removeOTP(cardId: String) = withContext(dispatcherProvider.io) {
+ secureStorage.delete(VISA_ROOT_OTP_KEY_PREFIX + cardId)
+ secureStorage.delete(VISA_OTP_COUNTER_KEY_PREFIX + cardId)
+ }
+
+ private companion object {
+ const val VISA_ROOT_OTP_KEY_PREFIX = "visa_root_otp_"
+ const val VISA_OTP_COUNTER_KEY_PREFIX = "visa_otp_counter_"
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/data/RuntimeUserWalletsStore.kt b/app/src/main/java/com/tangem/tap/data/RuntimeUserWalletsStore.kt
new file mode 100644
index 0000000000..1661cedb1d
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/data/RuntimeUserWalletsStore.kt
@@ -0,0 +1,40 @@
+package com.tangem.tap.data
+
+import com.tangem.common.CompletionResult
+import com.tangem.datasource.local.userwallet.UserWalletsStore
+import com.tangem.domain.wallets.legacy.UserWalletsListManager
+import com.tangem.domain.wallets.models.UserWallet
+import com.tangem.domain.wallets.models.UserWalletId
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.firstOrNull
+
+// FIXME: Workaround, remove it once the normal UserWalletsStore has been implemented
+// [REDACTED_JIRA]
+internal class RuntimeUserWalletsStore(
+ private val userWalletsListManager: UserWalletsListManager,
+) : UserWalletsStore {
+
+ override val selectedUserWalletOrNull: UserWallet?
+ get() = userWalletsListManager.selectedUserWalletSync
+
+ override val userWallets: Flow>
+ get() = userWalletsListManager.userWallets
+
+ override suspend fun getSyncOrNull(key: UserWalletId): UserWallet? {
+ return userWalletsListManager
+ .userWallets
+ .firstOrNull()
+ ?.singleOrNull { it.walletId == key }
+ }
+
+ override suspend fun getAllSyncOrNull(): List? {
+ return userWalletsListManager.userWallets.firstOrNull()
+ }
+
+ override suspend fun update(
+ userWalletId: UserWalletId,
+ update: suspend (UserWallet) -> UserWallet,
+ ): CompletionResult {
+ return userWalletsListManager.update(userWalletId, update)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/data/TangemBlockchainSDKLogger.kt b/app/src/main/java/com/tangem/tap/data/TangemBlockchainSDKLogger.kt
new file mode 100644
index 0000000000..f197705464
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/data/TangemBlockchainSDKLogger.kt
@@ -0,0 +1,20 @@
+package com.tangem.tap.data
+
+import com.tangem.blockchain.common.logging.BlockchainSDKLogger
+import com.tangem.datasource.local.logs.AppLogsStore
+
+/**
+ * BlockchainSDK logger implementation
+ *
+ * @property appLogsStore app logs store
+ *
+[REDACTED_AUTHOR]
+ */
+internal class TangemBlockchainSDKLogger(
+ private val appLogsStore: AppLogsStore,
+) : BlockchainSDKLogger {
+
+ override fun log(level: BlockchainSDKLogger.Level, message: String) {
+ appLogsStore.saveLogMessage(tag = "BlockchainSDK_${level.name}", message)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/data/TangemSdkWarningEvent.kt b/app/src/main/java/com/tangem/tap/data/TangemSdkWarningEvent.kt
new file mode 100644
index 0000000000..1393bfbf57
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/data/TangemSdkWarningEvent.kt
@@ -0,0 +1,9 @@
+package com.tangem.tap.data
+
+import com.tangem.core.analytics.models.AnalyticsEvent
+
+internal class TangemSdkWarningEvent(message: String) : AnalyticsEvent(
+ category = "Tangem SDK",
+ event = "Warning",
+ error = IllegalStateException(message),
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/ActivityModule.kt b/app/src/main/java/com/tangem/tap/di/ActivityModule.kt
new file mode 100644
index 0000000000..85d5a6630b
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/ActivityModule.kt
@@ -0,0 +1,96 @@
+package com.tangem.tap.di
+
+import com.tangem.blockchainsdk.utils.ExcludedBlockchains
+import com.tangem.datasource.exchangeservice.swap.ExpressServiceLoader
+import com.tangem.datasource.local.token.ExpressAssetsStore
+import com.tangem.domain.card.ScanCardUseCase
+import com.tangem.domain.card.repository.CardSdkConfigRepository
+import com.tangem.domain.exchange.RampStateManager
+import com.tangem.domain.tokens.GetNetworkCoinStatusUseCase
+import com.tangem.domain.tokens.GetPolkadotCheckHasImmortalUseCase
+import com.tangem.domain.tokens.GetPolkadotCheckHasResetUseCase
+import com.tangem.domain.tokens.repository.CurrenciesRepository
+import com.tangem.domain.tokens.repository.PolkadotAccountHealthCheckRepository
+import com.tangem.features.onramp.OnrampFeatureToggles
+import com.tangem.sdk.api.TangemSdkManager
+import com.tangem.tap.domain.scanCard.repository.DefaultScanCardRepository
+import com.tangem.tap.network.exchangeServices.DefaultRampManager
+import com.tangem.tap.proxy.AppStateHolder
+import com.tangem.utils.Provider
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.SupervisorJob
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object ActivityModule {
+
+ @Provides
+ @Singleton
+ fun provideScanCardUseCase(
+ tangemSdkManager: TangemSdkManager,
+ cardSdkConfigRepository: CardSdkConfigRepository,
+ ): ScanCardUseCase {
+ return ScanCardUseCase(
+ cardSdkConfigRepository = cardSdkConfigRepository,
+ scanCardRepository = DefaultScanCardRepository(
+ tangemSdkManager = tangemSdkManager,
+ ),
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideDefaultRampManager(
+ appStateHolder: AppStateHolder,
+ expressServiceLoader: ExpressServiceLoader,
+ currenciesRepository: CurrenciesRepository,
+ getNetworkCoinStatusUseCase: GetNetworkCoinStatusUseCase,
+ excludedBlockchains: ExcludedBlockchains,
+ dispatchers: CoroutineDispatcherProvider,
+ onrampFeatureToggles: OnrampFeatureToggles,
+ expressAssetsStore: ExpressAssetsStore,
+ ): RampStateManager {
+ return DefaultRampManager(
+ exchangeService = appStateHolder.exchangeService,
+ buyService = Provider { requireNotNull(appStateHolder.buyService) },
+ sellService = Provider { requireNotNull(appStateHolder.sellService) },
+ expressServiceLoader = expressServiceLoader,
+ currenciesRepository = currenciesRepository,
+ getNetworkCoinStatusUseCase = getNetworkCoinStatusUseCase,
+ excludedBlockchains = excludedBlockchains,
+ dispatchers = dispatchers,
+ onrampFeatureToggles = onrampFeatureToggles,
+ expressAssetsStore = expressAssetsStore,
+ )
+ }
+
+ @Provides
+ @Singleton
+ @DelayedWork
+ fun provideActivityDelayedWorkCoroutineScope(): CoroutineScope {
+ return CoroutineScope(SupervisorJob() + Dispatchers.IO)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetPolkadotCheckHasResetUseCase(
+ polkadotAccountHealthCheckRepository: PolkadotAccountHealthCheckRepository,
+ ): GetPolkadotCheckHasResetUseCase {
+ return GetPolkadotCheckHasResetUseCase(polkadotAccountHealthCheckRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetPolkadotCheckHasImmortalUseCase(
+ polkadotAccountHealthCheckRepository: PolkadotAccountHealthCheckRepository,
+ ): GetPolkadotCheckHasImmortalUseCase {
+ return GetPolkadotCheckHasImmortalUseCase(polkadotAccountHealthCheckRepository)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/AppStateHolderModule.kt b/app/src/main/java/com/tangem/tap/di/AppStateHolderModule.kt
new file mode 100644
index 0000000000..267fa733f1
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/AppStateHolderModule.kt
@@ -0,0 +1,18 @@
+package com.tangem.tap.di
+
+import com.tangem.domain.redux.ReduxStateHolder
+import com.tangem.tap.proxy.AppStateHolder
+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 AppStateHolderModule {
+
+ @Binds
+ @Singleton
+ fun bindsReduxStateHolder(appStateHolder: AppStateHolder): ReduxStateHolder
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/ClipboardManagerModule.kt b/app/src/main/java/com/tangem/tap/di/ClipboardManagerModule.kt
new file mode 100644
index 0000000000..052f1c4541
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/ClipboardManagerModule.kt
@@ -0,0 +1,30 @@
+package com.tangem.tap.di
+
+import android.content.Context
+import com.tangem.core.ui.clipboard.ClipboardManager
+import com.tangem.tap.common.clipboard.MockClipboardManager
+import com.tangem.tap.common.clipboard.DefaultClipboardManager
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+import android.content.ClipboardManager as AndroidClipboardManager
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal class ClipboardManagerModule {
+
+ @Provides
+ @Singleton
+ fun provideClipboardManager(@ApplicationContext context: Context): ClipboardManager {
+ val clipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE) as? AndroidClipboardManager
+
+ return if (clipboardManager != null) {
+ DefaultClipboardManager(clipboardManager = clipboardManager)
+ } else {
+ MockClipboardManager
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/HapticModule.kt b/app/src/main/java/com/tangem/tap/di/HapticModule.kt
new file mode 100644
index 0000000000..dc04a3ce72
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/HapticModule.kt
@@ -0,0 +1,40 @@
+package com.tangem.tap.di
+
+import android.content.Context
+import android.os.Build
+import android.os.Vibrator
+import android.os.VibratorManager
+import com.tangem.tap.common.haptic.DefaultVibratorHapticManager
+import com.tangem.core.ui.haptic.TangemHapticEffect
+import com.tangem.core.ui.haptic.VibratorHapticManager
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+class HapticModule {
+
+ @Provides
+ @Singleton
+ fun provideHapticManager(@ApplicationContext context: Context): VibratorHapticManager {
+ val vibrator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ val vibratorManager = context.getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
+ vibratorManager.defaultVibrator
+ } else {
+ context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
+ }
+
+ return if (vibrator.hasVibrator()) {
+ DefaultVibratorHapticManager(vibrator = vibrator)
+ } else {
+ // mock
+ object : VibratorHapticManager {
+ override fun performOneTime(effect: TangemHapticEffect.OneTime) = Unit
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/Qualifiers.kt b/app/src/main/java/com/tangem/tap/di/Qualifiers.kt
new file mode 100644
index 0000000000..94ba51a71e
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/Qualifiers.kt
@@ -0,0 +1,10 @@
+@file:Suppress("Filename")
+
+package com.tangem.tap.di
+
+import javax.inject.Qualifier
+
+@Deprecated("Use one in Core Utils")
+@Qualifier
+@Retention(AnnotationRetention.BINARY)
+annotation class DelayedWork
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/RootAppComponentContextModule.kt b/app/src/main/java/com/tangem/tap/di/RootAppComponentContextModule.kt
new file mode 100644
index 0000000000..b59094d579
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/RootAppComponentContextModule.kt
@@ -0,0 +1,40 @@
+package com.tangem.tap.di
+
+import android.content.Context
+import androidx.appcompat.app.AppCompatActivity
+import com.arkivanov.decompose.defaultComponentContext
+import com.tangem.core.decompose.context.AppComponentContext
+import com.tangem.core.decompose.context.DefaultAppComponentContext
+import com.tangem.core.decompose.di.DecomposeComponent
+import com.tangem.core.decompose.di.GlobalUiMessageSender
+import com.tangem.core.decompose.di.RootAppComponentContext
+import com.tangem.core.decompose.ui.UiMessageSender
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.components.ActivityComponent
+import dagger.hilt.android.qualifiers.ActivityContext
+import dagger.hilt.android.scopes.ActivityScoped
+
+@Module
+@InstallIn(ActivityComponent::class)
+internal object RootAppComponentContextModule {
+
+ @Provides
+ @ActivityScoped
+ @RootAppComponentContext
+ fun provideRootAppComponentContext(
+ @ActivityContext context: Context,
+ dispatchers: CoroutineDispatcherProvider,
+ componentBuilder: DecomposeComponent.Builder,
+ @GlobalUiMessageSender messageSender: UiMessageSender,
+ ): AppComponentContext {
+ return DefaultAppComponentContext(
+ componentContext = (context as AppCompatActivity).defaultComponentContext(),
+ dispatchers = dispatchers,
+ hiltComponentBuilder = componentBuilder,
+ messageSender = messageSender,
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/TangemSdkManagerModule.kt b/app/src/main/java/com/tangem/tap/di/TangemSdkManagerModule.kt
new file mode 100644
index 0000000000..d741fc1a41
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/TangemSdkManagerModule.kt
@@ -0,0 +1,44 @@
+package com.tangem.tap.di
+
+import android.content.Context
+import com.tangem.domain.card.BuildConfig
+import com.tangem.domain.card.repository.CardSdkConfigRepository
+import com.tangem.features.onboarding.v2.OnboardingV2FeatureToggles
+import com.tangem.sdk.api.TangemSdkManager
+import com.tangem.tap.domain.sdk.impl.DefaultTangemSdkManager
+import com.tangem.tap.domain.sdk.impl.MockTangemSdkManager
+import com.tangem.tap.domain.tasks.visa.VisaCardActivationTask
+import com.tangem.tap.domain.visa.VisaCardScanHandler
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal class TangemSdkManagerModule {
+
+ @Provides
+ @Singleton
+ fun provideTangemSdkManager(
+ @ApplicationContext context: Context,
+ cardSdkConfigRepository: CardSdkConfigRepository,
+ visaCardScanHandler: VisaCardScanHandler,
+ visaCardActivationTaskFactory: VisaCardActivationTask.Factory,
+ onboardingV2FeatureToggles: OnboardingV2FeatureToggles,
+ ): TangemSdkManager {
+ return if (BuildConfig.MOCK_DATA_SOURCE) {
+ MockTangemSdkManager(resources = context.resources)
+ } else {
+ DefaultTangemSdkManager(
+ cardSdkConfigRepository = cardSdkConfigRepository,
+ resources = context.resources,
+ visaCardScanHandler = visaCardScanHandler,
+ visaCardActivationTaskFactory = visaCardActivationTaskFactory,
+ onboardingV2FeatureToggles = onboardingV2FeatureToggles,
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/TangemSdkModule.kt b/app/src/main/java/com/tangem/tap/di/TangemSdkModule.kt
new file mode 100644
index 0000000000..b2f2f6d5c5
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/TangemSdkModule.kt
@@ -0,0 +1,17 @@
+package com.tangem.tap.di
+
+import com.tangem.sdk.api.BackupServiceHolder
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object TangemSdkModule {
+
+ @Provides
+ @Singleton
+ fun provideBackupServiceHolder(): BackupServiceHolder = BackupServiceHolder()
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/ThemeModule.kt b/app/src/main/java/com/tangem/tap/di/ThemeModule.kt
new file mode 100644
index 0000000000..e4b2deeb8d
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/ThemeModule.kt
@@ -0,0 +1,20 @@
+package com.tangem.tap.di
+
+import com.tangem.core.ui.theme.AppThemeModeHolder
+import com.tangem.tap.common.apptheme.MutableAppThemeModeHolder
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object ThemeModule {
+
+ @Provides
+ @Singleton
+ fun provideAppThemeModeHolder(): AppThemeModeHolder {
+ return MutableAppThemeModeHolder
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/UiDependenciesModule.kt b/app/src/main/java/com/tangem/tap/di/UiDependenciesModule.kt
new file mode 100644
index 0000000000..de5f7ef9e3
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/UiDependenciesModule.kt
@@ -0,0 +1,41 @@
+package com.tangem.tap.di
+
+import androidx.compose.material3.SnackbarHostState
+import com.tangem.core.decompose.di.GlobalUiMessageSender
+import com.tangem.core.decompose.ui.DefaultUiMessageSender
+import com.tangem.core.decompose.ui.UiMessageSender
+import com.tangem.core.ui.UiDependencies
+import com.tangem.core.ui.haptic.VibratorHapticManager
+import com.tangem.core.ui.message.EventMessageHandler
+import com.tangem.core.ui.theme.AppThemeModeHolder
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object UiDependenciesModule {
+
+ @Provides
+ @Singleton
+ fun provideUiDependencies(
+ vibratorHapticManager: VibratorHapticManager,
+ appThemeModeHolder: AppThemeModeHolder,
+ ): UiDependencies {
+ return object : UiDependencies {
+ override val vibratorHapticManager = vibratorHapticManager
+ override val appThemeModeHolder = appThemeModeHolder
+ override val globalSnackbarHostState: SnackbarHostState = SnackbarHostState()
+ override val eventMessageHandler: EventMessageHandler = EventMessageHandler()
+ }
+ }
+
+ @Provides
+ @Singleton
+ @GlobalUiMessageSender
+ fun provideUiMessageSender(uiDependencies: UiDependencies): UiMessageSender {
+ return DefaultUiMessageSender(uiDependencies.eventMessageHandler)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/UtilsModule.kt b/app/src/main/java/com/tangem/tap/di/UtilsModule.kt
new file mode 100644
index 0000000000..7fdf0263cc
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/UtilsModule.kt
@@ -0,0 +1,38 @@
+package com.tangem.tap.di
+
+import android.content.Context
+import com.tangem.core.navigation.finisher.AppFinisher
+import com.tangem.core.navigation.settings.SettingsManager
+import com.tangem.core.navigation.share.ShareManager
+import com.tangem.core.navigation.url.UrlOpener
+import com.tangem.tap.common.finisher.AndroidAppFinisher
+import com.tangem.tap.common.settings.IntentSettingsManager
+import com.tangem.tap.common.share.IntentShareManager
+import com.tangem.tap.common.url.CustomTabsUrlOpener
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object UtilsModule {
+
+ @Provides
+ @Singleton
+ fun provideShareManager(): ShareManager = IntentShareManager()
+
+ @Provides
+ @Singleton
+ fun provideUrlOpener(): UrlOpener = CustomTabsUrlOpener()
+
+ @Provides
+ @Singleton
+ fun provideAppFinisher(@ApplicationContext context: Context): AppFinisher = AndroidAppFinisher(context)
+
+ @Provides
+ @Singleton
+ fun provideSettingsManager(@ApplicationContext context: Context): SettingsManager = IntentSettingsManager(context)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/analytics/AnalyticsModule.kt b/app/src/main/java/com/tangem/tap/di/analytics/AnalyticsModule.kt
new file mode 100644
index 0000000000..60fea2b718
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/analytics/AnalyticsModule.kt
@@ -0,0 +1,32 @@
+package com.tangem.tap.di.analytics
+
+import com.tangem.core.analytics.AppInstanceIdProvider
+import com.tangem.core.analytics.utils.AnalyticsContextProxy
+import com.tangem.domain.analytics.ChangeCardAnalyticsContextUseCase
+import com.tangem.tap.common.analytics.DefaultAnalyticsContextProxy
+import com.tangem.tap.common.analytics.DefaultChangeCardAnalyticsContextUseCase
+import com.tangem.tap.common.analytics.handlers.firebase.FirebaseAppInstanceIdProvider
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object AnalyticsModule {
+
+ @Provides
+ @Singleton
+ fun provideChangeCardAnalyticsContextUseCase(): ChangeCardAnalyticsContextUseCase {
+ return DefaultChangeCardAnalyticsContextUseCase()
+ }
+
+ @Provides
+ @Singleton
+ fun provideAnalyticsContextProxy(): AnalyticsContextProxy = DefaultAnalyticsContextProxy()
+
+ @Provides
+ @Singleton
+ fun provideAppInstanceIdProvider(): AppInstanceIdProvider = FirebaseAppInstanceIdProvider()
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/core/ImageLoaderModule.kt b/app/src/main/java/com/tangem/tap/di/core/ImageLoaderModule.kt
new file mode 100644
index 0000000000..be0b4f9c20
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/core/ImageLoaderModule.kt
@@ -0,0 +1,22 @@
+package com.tangem.tap.di.core
+
+import android.content.Context
+import com.tangem.core.ui.coil.ImagePreloader
+import com.tangem.tap.common.images.DefaultImagePreloader
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object ImageLoaderModule {
+
+ @Provides
+ @Singleton
+ fun provideImageLoader(@ApplicationContext context: Context): ImagePreloader {
+ return DefaultImagePreloader(context)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/core/navigation/email/EmailSenderModule.kt b/app/src/main/java/com/tangem/tap/di/core/navigation/email/EmailSenderModule.kt
new file mode 100644
index 0000000000..b986cfe46d
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/core/navigation/email/EmailSenderModule.kt
@@ -0,0 +1,18 @@
+package com.tangem.tap.di.core.navigation.email
+
+import com.tangem.core.navigation.email.EmailSender
+import com.tangem.tap.core.navigation.email.AndroidEmailSender
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object EmailSenderModule {
+
+ @Provides
+ @Singleton
+ fun provideEmailSender(): EmailSender = AndroidEmailSender()
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/data/CardDataModule.kt b/app/src/main/java/com/tangem/tap/di/data/CardDataModule.kt
new file mode 100644
index 0000000000..34411415bf
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/data/CardDataModule.kt
@@ -0,0 +1,29 @@
+package com.tangem.tap.di.data
+
+import com.tangem.blockchainsdk.utils.ExcludedBlockchains
+import com.tangem.datasource.local.userwallet.UserWalletsStore
+import com.tangem.domain.card.repository.DerivationsRepository
+import com.tangem.sdk.api.TangemSdkManager
+import com.tangem.tap.domain.card.DefaultDerivationsRepository
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object CardDataModule {
+
+ @Singleton
+ @Provides
+ fun providesDerivationsRepository(
+ tangemSdkManager: TangemSdkManager,
+ userWalletsStore: UserWalletsStore,
+ excludedBlockchains: ExcludedBlockchains,
+ dispatchers: CoroutineDispatcherProvider,
+ ): DerivationsRepository {
+ return DefaultDerivationsRepository(tangemSdkManager, userWalletsStore, excludedBlockchains, dispatchers)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/data/CardSdkModule.kt b/app/src/main/java/com/tangem/tap/di/data/CardSdkModule.kt
new file mode 100644
index 0000000000..118bcb16a7
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/data/CardSdkModule.kt
@@ -0,0 +1,23 @@
+package com.tangem.tap.di.data
+
+import com.tangem.data.card.sdk.CardSdkOwner
+import com.tangem.data.card.sdk.CardSdkProvider
+import com.tangem.tap.data.DefaultCardSdkProvider
+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 CardSdkModule {
+
+ @Binds
+ @Singleton
+ fun provideCardSdkProvider(defaultCardSdkProvider: DefaultCardSdkProvider): CardSdkProvider
+
+ @Binds
+ @Singleton
+ fun providerCardSdkLifecycleObserver(defaultCardSdkProvider: DefaultCardSdkProvider): CardSdkOwner
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/data/TangemLoggingModule.kt b/app/src/main/java/com/tangem/tap/di/data/TangemLoggingModule.kt
new file mode 100644
index 0000000000..400f58d8b2
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/data/TangemLoggingModule.kt
@@ -0,0 +1,56 @@
+package com.tangem.tap.di.data
+
+import com.tangem.Log
+import com.tangem.LogFormat
+import com.tangem.TangemSdkLogger
+import com.tangem.blockchain.common.logging.BlockchainSDKLogger
+import com.tangem.datasource.local.logs.AppLogsStore
+import com.tangem.tap.common.log.TangemAppLoggerInitializer
+import com.tangem.tap.common.log.TangemCardSDKLogger
+import com.tangem.tap.data.TangemBlockchainSDKLogger
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object TangemLoggingModule {
+
+ @Provides
+ @Singleton
+ fun provideAppLoggerInitializer(appLogsStore: AppLogsStore): TangemAppLoggerInitializer {
+ return TangemAppLoggerInitializer(appLogsStore)
+ }
+
+ @Provides
+ @Singleton
+ fun provideCardSDKLogger(appLogsStore: AppLogsStore): TangemSdkLogger {
+ val logLevels = listOf(
+ Log.Level.ApduCommand,
+ Log.Level.Apdu,
+ Log.Level.Tlv,
+ Log.Level.Nfc,
+ Log.Level.Command,
+ Log.Level.Session,
+ Log.Level.View,
+ Log.Level.Network,
+ Log.Level.Error,
+ Log.Level.Biometric,
+ Log.Level.Info,
+ )
+
+ return TangemCardSDKLogger(
+ levels = logLevels,
+ messageFormatter = LogFormat.StairsFormatter(),
+ appLogsStore = appLogsStore,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideBlockchainSDKLogger(appLogsStore: AppLogsStore): BlockchainSDKLogger {
+ return TangemBlockchainSDKLogger(appLogsStore)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/data/UserWalletsStoreModule.kt b/app/src/main/java/com/tangem/tap/di/data/UserWalletsStoreModule.kt
new file mode 100644
index 0000000000..b2a04f9d52
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/data/UserWalletsStoreModule.kt
@@ -0,0 +1,21 @@
+package com.tangem.tap.di.data
+
+import com.tangem.datasource.local.userwallet.UserWalletsStore
+import com.tangem.domain.wallets.legacy.UserWalletsListManager
+import com.tangem.tap.data.RuntimeUserWalletsStore
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object UserWalletsStoreModule {
+
+ @Provides
+ @Singleton
+ fun provideUserWalletsStore(userWalletsListManager: UserWalletsListManager): UserWalletsStore {
+ return RuntimeUserWalletsStore(userWalletsListManager = userWalletsListManager)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/data/VisaStorageModule.kt b/app/src/main/java/com/tangem/tap/di/data/VisaStorageModule.kt
new file mode 100644
index 0000000000..c78909a676
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/data/VisaStorageModule.kt
@@ -0,0 +1,24 @@
+package com.tangem.tap.di.data
+
+import com.tangem.datasource.local.visa.VisaAuthTokenStorage
+import com.tangem.datasource.local.visa.VisaOTPStorage
+import com.tangem.tap.data.DefaultVisaAuthTokenStorage
+import com.tangem.tap.data.DefaultVisaOTPStorage
+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 VisaStorageModule {
+
+ @Binds
+ @Singleton
+ fun bindVisaStorage(impl: DefaultVisaAuthTokenStorage): VisaAuthTokenStorage
+
+ @Binds
+ @Singleton
+ fun bindVisaOTPStorage(impl: DefaultVisaOTPStorage): VisaOTPStorage
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/AnalyticsDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/AnalyticsDomainModule.kt
new file mode 100644
index 0000000000..dda9f2c253
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/AnalyticsDomainModule.kt
@@ -0,0 +1,18 @@
+package com.tangem.tap.di.domain
+
+import com.tangem.domain.analytics.CheckIsWalletToppedUpUseCase
+import com.tangem.domain.analytics.repository.AnalyticsRepository
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.components.ViewModelComponent
+
+@Module
+@InstallIn(ViewModelComponent::class)
+internal object AnalyticsDomainModule {
+
+ @Provides
+ fun provideCheckIsWalletToppedUpUseCase(analyticsRepository: AnalyticsRepository): CheckIsWalletToppedUpUseCase {
+ return CheckIsWalletToppedUpUseCase(analyticsRepository)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/AppCurrencyDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/AppCurrencyDomainModule.kt
new file mode 100644
index 0000000000..a85859ab25
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/AppCurrencyDomainModule.kt
@@ -0,0 +1,45 @@
+package com.tangem.tap.di.domain
+
+import com.tangem.domain.appcurrency.FetchAppCurrenciesUseCase
+import com.tangem.domain.appcurrency.GetAvailableCurrenciesUseCase
+import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
+import com.tangem.domain.appcurrency.SelectAppCurrencyUseCase
+import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object AppCurrencyDomainModule {
+
+ @Provides
+ @Singleton
+ fun provideGetSelectedAppCurrencyUseCase(
+ appCurrencyRepository: AppCurrencyRepository,
+ ): GetSelectedAppCurrencyUseCase {
+ return GetSelectedAppCurrencyUseCase(appCurrencyRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideSelectAppCurrencyUseCase(appCurrencyRepository: AppCurrencyRepository): SelectAppCurrencyUseCase {
+ return SelectAppCurrencyUseCase(appCurrencyRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetAvailableCurrenciesUseCase(
+ appCurrencyRepository: AppCurrencyRepository,
+ ): GetAvailableCurrenciesUseCase {
+ return GetAvailableCurrenciesUseCase(appCurrencyRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideFetchAppCurrenciesUseCase(appCurrencyRepository: AppCurrencyRepository): FetchAppCurrenciesUseCase {
+ return FetchAppCurrenciesUseCase(appCurrencyRepository)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/AppThemeDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/AppThemeDomainModule.kt
new file mode 100644
index 0000000000..4b6fc45a17
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/AppThemeDomainModule.kt
@@ -0,0 +1,24 @@
+package com.tangem.tap.di.domain
+
+import com.tangem.domain.apptheme.ChangeAppThemeModeUseCase
+import com.tangem.domain.apptheme.GetAppThemeModeUseCase
+import com.tangem.domain.apptheme.repository.AppThemeModeRepository
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object AppThemeDomainModule {
+
+ @Provides
+ fun provideGetAppThemeModeUpdatesUseCase(appThemeModeRepository: AppThemeModeRepository): GetAppThemeModeUseCase {
+ return GetAppThemeModeUseCase(appThemeModeRepository)
+ }
+
+ @Provides
+ fun provideChangeAppThemeModeUseCase(appThemeModeRepository: AppThemeModeRepository): ChangeAppThemeModeUseCase {
+ return ChangeAppThemeModeUseCase(appThemeModeRepository)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/CardDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/CardDomainModule.kt
new file mode 100644
index 0000000000..789f56e454
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/CardDomainModule.kt
@@ -0,0 +1,80 @@
+package com.tangem.tap.di.domain
+
+import com.tangem.domain.card.*
+import com.tangem.domain.card.repository.CardRepository
+import com.tangem.domain.card.repository.DerivationsRepository
+import com.tangem.domain.demo.DemoConfig
+import com.tangem.domain.demo.IsDemoCardUseCase
+import com.tangem.domain.walletmanager.WalletManagersFacade
+import com.tangem.domain.wallets.legacy.UserWalletsListManager
+import com.tangem.domain.wallets.usecase.IsNeedToBackupUseCase
+import com.tangem.sdk.api.TangemSdkManager
+import com.tangem.tap.domain.card.DefaultDeleteSavedAccessCodesUseCase
+import com.tangem.tap.domain.card.DefaultResetCardUseCase
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object CardDomainModule {
+
+ @Provides
+ @Singleton
+ fun provideSetCardWasScannedUseCase(cardRepository: CardRepository): SetCardWasScannedUseCase {
+ return SetCardWasScannedUseCase(cardRepository = cardRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideIsDemoCardUseCase(): IsDemoCardUseCase = IsDemoCardUseCase(config = DemoConfig())
+
+ @Provides
+ @Singleton
+ fun provideDerivePublicKeysUseCase(derivationsRepository: DerivationsRepository): DerivePublicKeysUseCase {
+ return DerivePublicKeysUseCase(derivationsRepository = derivationsRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideIsNeedToBackupUseCase(userWalletsListManager: UserWalletsListManager): IsNeedToBackupUseCase {
+ return IsNeedToBackupUseCase(userWalletsListManager = userWalletsListManager)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetExtendedPublicKeyForCurrencyUseCase(
+ derivationsRepository: DerivationsRepository,
+ walletManagersFacade: WalletManagersFacade,
+ ): GetExtendedPublicKeyForCurrencyUseCase {
+ return GetExtendedPublicKeyForCurrencyUseCase(derivationsRepository, walletManagersFacade)
+ }
+
+ @Provides
+ @Singleton
+ fun provideDeleteSavedAccessCodesUseCase(tangemSdkManager: TangemSdkManager): DeleteSavedAccessCodesUseCase {
+ return DefaultDeleteSavedAccessCodesUseCase(tangemSdkManager)
+ }
+
+ @Provides
+ @Singleton
+ fun provideResetCardUseCase(tangemSdkManager: TangemSdkManager): ResetCardUseCase {
+ return DefaultResetCardUseCase(tangemSdkManager)
+ }
+
+ @Provides
+ @Singleton
+ fun provideNetworkHasDerivationUseCase(): NetworkHasDerivationUseCase {
+ return NetworkHasDerivationUseCase()
+ }
+
+ @Provides
+ @Singleton
+ fun provideIsRequiredDerivePublicKeysUseCase(
+ derivationsRepository: DerivationsRepository,
+ ): HasMissedDerivationsUseCase {
+ return HasMissedDerivationsUseCase(derivationsRepository)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/CardLegacyDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/CardLegacyDomainModule.kt
new file mode 100644
index 0000000000..7be9d95b9a
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/CardLegacyDomainModule.kt
@@ -0,0 +1,37 @@
+package com.tangem.tap.di.domain
+
+import com.tangem.core.configtoggle.feature.FeatureTogglesManager
+import com.tangem.domain.card.ScanCardProcessor
+import com.tangem.domain.wallets.legacy.UserWalletsListManager
+import com.tangem.domain.wallets.usecase.GenerateWalletNameUseCase
+import com.tangem.tap.domain.scanCard.CardScanningFeatureToggles
+import com.tangem.tap.domain.scanCard.DefaultScanCardProcessor
+import com.tangem.tap.domain.scanCard.LegacyScanProcessor
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object CardLegacyDomainModule {
+
+ @Provides
+ @Singleton
+ fun provideCardScanningFeatureToggles(featureTogglesManager: FeatureTogglesManager): CardScanningFeatureToggles {
+ return CardScanningFeatureToggles(featureTogglesManager)
+ }
+
+ @Provides
+ @Singleton
+ fun provideScanCardProcessor(legacyScanProcessor: LegacyScanProcessor): ScanCardProcessor {
+ return DefaultScanCardProcessor(legacyScanProcessor = legacyScanProcessor)
+ }
+
+ @Provides
+ @Singleton
+ fun providesWalletNameGenerateUseCase(userWalletsListManager: UserWalletsListManager): GenerateWalletNameUseCase {
+ return GenerateWalletNameUseCase(userWalletsListManager)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/FeedbackDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/FeedbackDomainModule.kt
new file mode 100644
index 0000000000..b905aa7edc
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/FeedbackDomainModule.kt
@@ -0,0 +1,39 @@
+package com.tangem.tap.di.domain
+
+import android.content.Context
+import com.tangem.domain.feedback.GetCardInfoUseCase
+import com.tangem.domain.feedback.SaveBlockchainErrorUseCase
+import com.tangem.domain.feedback.SendFeedbackEmailUseCase
+import com.tangem.domain.feedback.repository.FeedbackRepository
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object FeedbackDomainModule {
+
+ @Provides
+ @Singleton
+ fun provideGetCardInfoUseCase(feedbackRepository: FeedbackRepository): GetCardInfoUseCase {
+ return GetCardInfoUseCase(feedbackRepository = feedbackRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetFeedbackEmailUseCase(
+ feedbackRepository: FeedbackRepository,
+ @ApplicationContext context: Context,
+ ): SendFeedbackEmailUseCase {
+ return SendFeedbackEmailUseCase(feedbackRepository = feedbackRepository, resources = context.resources)
+ }
+
+ @Provides
+ @Singleton
+ fun provideSaveBlockchainErrorUseCase(feedbackRepository: FeedbackRepository): SaveBlockchainErrorUseCase {
+ return SaveBlockchainErrorUseCase(feedbackRepository = feedbackRepository)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/ManageTokensDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/ManageTokensDomainModule.kt
new file mode 100644
index 0000000000..c3520a41cf
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/ManageTokensDomainModule.kt
@@ -0,0 +1,108 @@
+package com.tangem.tap.di.domain
+
+import com.tangem.domain.card.repository.DerivationsRepository
+import com.tangem.domain.managetokens.*
+import com.tangem.domain.managetokens.repository.CustomTokensRepository
+import com.tangem.domain.managetokens.repository.ManageTokensRepository
+import com.tangem.domain.staking.repositories.StakingRepository
+import com.tangem.domain.tokens.repository.CurrenciesRepository
+import com.tangem.domain.tokens.repository.NetworksRepository
+import com.tangem.domain.walletmanager.WalletManagersFacade
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object ManageTokensDomainModule {
+
+ @Provides
+ @Singleton
+ fun provideGetManageTokensUseCase(manageTokensRepository: ManageTokensRepository): GetManagedTokensUseCase {
+ return GetManagedTokensUseCase(manageTokensRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideValidateTokenFormatUseCase(customTokensRepository: CustomTokensRepository): ValidateTokenFormUseCase {
+ return ValidateTokenFormUseCase(customTokensRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideCreateCurrencyUseCase(customTokensRepository: CustomTokensRepository): CreateCurrencyUseCase {
+ return CreateCurrencyUseCase(customTokensRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideFindTokenUseCase(customTokensRepository: CustomTokensRepository): FindTokenUseCase {
+ return FindTokenUseCase(customTokensRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideCheckIsCurrencyNotAddedUseCase(
+ customTokensRepository: CustomTokensRepository,
+ ): CheckIsCurrencyNotAddedUseCase {
+ return CheckIsCurrencyNotAddedUseCase(customTokensRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideRemoveCustomManagedCryptoCurrencyUseCase(
+ customTokensRepository: CustomTokensRepository,
+ ): RemoveCustomManagedCryptoCurrencyUseCase {
+ return RemoveCustomManagedCryptoCurrencyUseCase(customTokensRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideSaveManagedTokensUseCase(
+ customTokensRepository: CustomTokensRepository,
+ walletManagersFacade: WalletManagersFacade,
+ currenciesRepository: CurrenciesRepository,
+ networksRepository: NetworksRepository,
+ derivationsRepository: DerivationsRepository,
+ stakingRepository: StakingRepository,
+ ): SaveManagedTokensUseCase {
+ return SaveManagedTokensUseCase(
+ customTokensRepository = customTokensRepository,
+ walletManagersFacade = walletManagersFacade,
+ currenciesRepository = currenciesRepository,
+ networksRepository = networksRepository,
+ derivationsRepository = derivationsRepository,
+ stakingRepository = stakingRepository,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetSupportedNetworksUseCase(
+ customTokensRepository: CustomTokensRepository,
+ ): GetSupportedNetworksUseCase {
+ return GetSupportedNetworksUseCase(customTokensRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideValidateDerivationPathUseCase(
+ customTokensRepository: CustomTokensRepository,
+ ): ValidateDerivationPathUseCase {
+ return ValidateDerivationPathUseCase(customTokensRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideCheckHasLinkedTokensUseCase(repository: ManageTokensRepository): CheckHasLinkedTokensUseCase {
+ return CheckHasLinkedTokensUseCase(repository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideCheckCurrencyUnsupportedUseCase(repository: ManageTokensRepository): CheckCurrencyUnsupportedUseCase {
+ return CheckCurrencyUnsupportedUseCase(repository)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/MarketsDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/MarketsDomainModule.kt
new file mode 100644
index 0000000000..4498836964
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/MarketsDomainModule.kt
@@ -0,0 +1,86 @@
+package com.tangem.tap.di.domain
+
+import com.tangem.blockchainsdk.utils.ExcludedBlockchains
+import com.tangem.domain.card.repository.DerivationsRepository
+import com.tangem.domain.markets.*
+import com.tangem.domain.markets.repositories.MarketsTokenRepository
+import com.tangem.domain.tokens.repository.CurrenciesRepository
+import com.tangem.domain.tokens.repository.NetworksRepository
+import com.tangem.domain.tokens.repository.QuotesRepository
+import com.tangem.domain.wallets.legacy.UserWalletsListManager
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+object MarketsDomainModule {
+
+ @Provides
+ @Singleton
+ fun provideGetMarketsTokenListFlowUseCase(
+ marketsTokenRepository: MarketsTokenRepository,
+ ): GetMarketsTokenListFlowUseCase {
+ return GetMarketsTokenListFlowUseCase(marketsTokenRepository = marketsTokenRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetTokenPriceChartUseCase(marketsTokenRepository: MarketsTokenRepository): GetTokenPriceChartUseCase {
+ return GetTokenPriceChartUseCase(marketsTokenRepository = marketsTokenRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetTokenMarketInfoUseCase(marketsTokenRepository: MarketsTokenRepository): GetTokenMarketInfoUseCase {
+ return GetTokenMarketInfoUseCase(marketsTokenRepository = marketsTokenRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideTokenFullQuotesUseCase(marketsTokenRepository: MarketsTokenRepository): GetTokenFullQuotesUseCase {
+ return GetTokenFullQuotesUseCase(marketsTokenRepository = marketsTokenRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetTokenQuotesUseCase(quotesRepository: QuotesRepository): GetCurrencyQuotesUseCase {
+ return GetCurrencyQuotesUseCase(quotesRepository = quotesRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideSaveMarketTokensUseCase(
+ derivationsRepository: DerivationsRepository,
+ marketsTokenRepository: MarketsTokenRepository,
+ currenciesRepository: CurrenciesRepository,
+ networksRepository: NetworksRepository,
+ ): SaveMarketTokensUseCase {
+ return SaveMarketTokensUseCase(
+ derivationsRepository = derivationsRepository,
+ marketsTokenRepository = marketsTokenRepository,
+ currenciesRepository = currenciesRepository,
+ networksRepository = networksRepository,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideFilterNetworksUseCase(
+ userWalletsListManager: UserWalletsListManager,
+ excludedBlockchains: ExcludedBlockchains,
+ ): FilterAvailableNetworksForWalletUseCase {
+ return FilterAvailableNetworksForWalletUseCase(
+ userWalletsListManager = userWalletsListManager,
+ excludedBlockchains = excludedBlockchains,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetTokenExchangesUseCase(marketsTokenRepository: MarketsTokenRepository): GetTokenExchangesUseCase {
+ return GetTokenExchangesUseCase(marketsTokenRepository = marketsTokenRepository)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/MnemonicModule.kt b/app/src/main/java/com/tangem/tap/di/domain/MnemonicModule.kt
new file mode 100644
index 0000000000..8f62a7e255
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/MnemonicModule.kt
@@ -0,0 +1,24 @@
+package com.tangem.tap.di.domain
+
+import android.content.Context
+import com.tangem.crypto.bip39.Wordlist
+import com.tangem.feature.onboarding.data.DefaultMnemonicRepository
+import com.tangem.feature.onboarding.data.MnemonicRepository
+import com.tangem.sdk.extensions.getWordlist
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+class MnemonicModule {
+
+ @Provides
+ @Singleton
+ fun provideMnemonicRepository(@ApplicationContext context: Context): MnemonicRepository {
+ return DefaultMnemonicRepository(Wordlist.getWordlist(context))
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/OnboardingDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/OnboardingDomainModule.kt
new file mode 100644
index 0000000000..2ec4dabe50
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/OnboardingDomainModule.kt
@@ -0,0 +1,31 @@
+package com.tangem.tap.di.domain
+
+import com.tangem.domain.onboarding.SaveTwinsOnboardingShownUseCase
+import com.tangem.domain.onboarding.WasTwinsOnboardingShownUseCase
+import com.tangem.domain.onboarding.repository.OnboardingRepository
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object OnboardingDomainModule {
+
+ @Provides
+ @Singleton
+ fun provideWasTwinsOnboardingShownUseCase(
+ onboardingRepository: OnboardingRepository,
+ ): WasTwinsOnboardingShownUseCase {
+ return WasTwinsOnboardingShownUseCase(onboardingRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideSaveTwinsOnboardingShownUseCase(
+ onboardingRepository: OnboardingRepository,
+ ): SaveTwinsOnboardingShownUseCase {
+ return SaveTwinsOnboardingShownUseCase(onboardingRepository)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/OnrampDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/OnrampDomainModule.kt
new file mode 100644
index 0000000000..87afb55912
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/OnrampDomainModule.kt
@@ -0,0 +1,245 @@
+package com.tangem.tap.di.domain
+
+import com.tangem.domain.onramp.*
+import com.tangem.domain.onramp.repositories.HotCryptoRepository
+import com.tangem.domain.onramp.repositories.OnrampErrorResolver
+import com.tangem.domain.onramp.repositories.OnrampRepository
+import com.tangem.domain.onramp.repositories.OnrampTransactionRepository
+import com.tangem.domain.settings.repositories.SettingsRepository
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Suppress("TooManyFunctions")
+@Module
+@InstallIn(SingletonComponent::class)
+internal object OnrampDomainModule {
+
+ @Provides
+ @Singleton
+ fun provideGetOnrampCurrenciesUseCase(
+ onrampRepository: OnrampRepository,
+ onrampErrorResolver: OnrampErrorResolver,
+ ): GetOnrampCurrenciesUseCase {
+ return GetOnrampCurrenciesUseCase(onrampRepository, onrampErrorResolver)
+ }
+
+ @Provides
+ @Singleton
+ fun provideOnrampSaveDefaultCurrencyUseCase(
+ onrampRepository: OnrampRepository,
+ onrampErrorResolver: OnrampErrorResolver,
+ ): OnrampSaveDefaultCurrencyUseCase {
+ return OnrampSaveDefaultCurrencyUseCase(onrampRepository, onrampErrorResolver)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetOnrampCountriesUseCase(
+ onrampRepository: OnrampRepository,
+ onrampErrorResolver: OnrampErrorResolver,
+ ): GetOnrampCountriesUseCase {
+ return GetOnrampCountriesUseCase(onrampRepository, onrampErrorResolver)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetOnrampCountryUseCase(
+ onrampRepository: OnrampRepository,
+ onrampErrorResolver: OnrampErrorResolver,
+ ): GetOnrampCountryUseCase {
+ return GetOnrampCountryUseCase(onrampRepository, onrampErrorResolver)
+ }
+
+ @Provides
+ @Singleton
+ fun provideOnrampSaveDefaultCountryUseCase(
+ onrampRepository: OnrampRepository,
+ onrampErrorResolver: OnrampErrorResolver,
+ ): OnrampSaveDefaultCountryUseCase {
+ return OnrampSaveDefaultCountryUseCase(onrampRepository, onrampErrorResolver)
+ }
+
+ @Provides
+ @Singleton
+ fun provideCheckOnrampAvailabilityUseCase(
+ onrampRepository: OnrampRepository,
+ onrampErrorResolver: OnrampErrorResolver,
+ ): CheckOnrampAvailabilityUseCase {
+ return CheckOnrampAvailabilityUseCase(onrampRepository, onrampErrorResolver)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetOnrampStatusUseCase(
+ onrampRepository: OnrampRepository,
+ onrampErrorResolver: OnrampErrorResolver,
+ ): GetOnrampStatusUseCase {
+ return GetOnrampStatusUseCase(
+ onrampRepository,
+ onrampErrorResolver,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetOnrampTransactionsUseCase(
+ onrampTransactionRepository: OnrampTransactionRepository,
+ onrampErrorResolver: OnrampErrorResolver,
+ ): GetOnrampTransactionsUseCase {
+ return GetOnrampTransactionsUseCase(onrampTransactionRepository, onrampErrorResolver)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetOnrampTransactionUseCase(
+ onrampTransactionRepository: OnrampTransactionRepository,
+ onrampErrorResolver: OnrampErrorResolver,
+ ): GetOnrampTransactionUseCase {
+ return GetOnrampTransactionUseCase(onrampTransactionRepository, onrampErrorResolver)
+ }
+
+ @Provides
+ @Singleton
+ fun provideOnrampRemoveTransactionUseCase(
+ onrampTransactionRepository: OnrampTransactionRepository,
+ onrampErrorResolver: OnrampErrorResolver,
+ ): OnrampRemoveTransactionUseCase {
+ return OnrampRemoveTransactionUseCase(onrampTransactionRepository, onrampErrorResolver)
+ }
+
+ @Provides
+ @Singleton
+ fun provideOnrampSaveTransactionUseCase(
+ onrampTransactionRepository: OnrampTransactionRepository,
+ onrampErrorResolver: OnrampErrorResolver,
+ ): OnrampSaveTransactionUseCase {
+ return OnrampSaveTransactionUseCase(onrampTransactionRepository, onrampErrorResolver)
+ }
+
+ @Provides
+ @Singleton
+ fun provideOnrampUpdateTransactionStatusUseCase(
+ onrampTransactionRepository: OnrampTransactionRepository,
+ onrampErrorResolver: OnrampErrorResolver,
+ ): OnrampUpdateTransactionStatusUseCase {
+ return OnrampUpdateTransactionStatusUseCase(onrampTransactionRepository, onrampErrorResolver)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetOnrampPaymentMethodsUseCase(
+ onrampRepository: OnrampRepository,
+ settingsRepository: SettingsRepository,
+ onrampErrorResolver: OnrampErrorResolver,
+ ): GetOnrampPaymentMethodsUseCase {
+ return GetOnrampPaymentMethodsUseCase(onrampRepository, settingsRepository, onrampErrorResolver)
+ }
+
+ @Provides
+ @Singleton
+ fun provideClearOnrampCacheUseCase(onrampRepository: OnrampRepository): ClearOnrampCacheUseCase {
+ return ClearOnrampCacheUseCase(onrampRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideOnrampFetchQuotesUseCase(
+ onrampRepository: OnrampRepository,
+ onrampErrorResolver: OnrampErrorResolver,
+ ): OnrampFetchQuotesUseCase {
+ return OnrampFetchQuotesUseCase(onrampRepository, onrampErrorResolver)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetOnrampQuotesUseCase(
+ settingsRepository: SettingsRepository,
+ onrampRepository: OnrampRepository,
+ onrampErrorResolver: OnrampErrorResolver,
+ ): GetOnrampQuotesUseCase {
+ return GetOnrampQuotesUseCase(
+ settingsRepository = settingsRepository,
+ repository = onrampRepository,
+ errorResolver = onrampErrorResolver,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetOnrampSelectedPaymentMethodUseCase(
+ onrampRepository: OnrampRepository,
+ onrampErrorResolver: OnrampErrorResolver,
+ ): GetOnrampSelectedPaymentMethodUseCase {
+ return GetOnrampSelectedPaymentMethodUseCase(onrampRepository, onrampErrorResolver)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetOnrampProviderWithQuoteUseCase(
+ onrampRepository: OnrampRepository,
+ onrampErrorResolver: OnrampErrorResolver,
+ ): GetOnrampProviderWithQuoteUseCase {
+ return GetOnrampProviderWithQuoteUseCase(onrampRepository, onrampErrorResolver)
+ }
+
+ @Provides
+ @Singleton
+ fun provideOnrampSaveSelectedPaymentMethod(
+ onrampRepository: OnrampRepository,
+ onrampErrorResolver: OnrampErrorResolver,
+ ): OnrampSaveSelectedPaymentMethod {
+ return OnrampSaveSelectedPaymentMethod(onrampRepository, onrampErrorResolver)
+ }
+
+ @Provides
+ @Singleton
+ fun provideOnrampFetchPairsUseCase(
+ onrampRepository: OnrampRepository,
+ onrampErrorResolver: OnrampErrorResolver,
+ ): OnrampFetchPairsUseCase {
+ return OnrampFetchPairsUseCase(onrampRepository, onrampErrorResolver)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetOnrampRedirectUrlUseCase(
+ onrampRepository: OnrampRepository,
+ transactionRepository: OnrampTransactionRepository,
+ onrampErrorResolver: OnrampErrorResolver,
+ ): GetOnrampRedirectUrlUseCase {
+ return GetOnrampRedirectUrlUseCase(onrampRepository, transactionRepository, onrampErrorResolver)
+ }
+
+ @Provides
+ @Singleton
+ fun provideFetchOnrampCurrenciesUseCase(
+ onrampRepository: OnrampRepository,
+ onrampErrorResolver: OnrampErrorResolver,
+ ): FetchOnrampCurrenciesUseCase {
+ return FetchOnrampCurrenciesUseCase(onrampRepository, onrampErrorResolver)
+ }
+
+ @Provides
+ @Singleton
+ fun provideFetchOnrampCountriesUseCase(
+ onrampRepository: OnrampRepository,
+ onrampErrorResolver: OnrampErrorResolver,
+ ): FetchOnrampCountriesUseCase {
+ return FetchOnrampCountriesUseCase(onrampRepository, onrampErrorResolver)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetHotCryptoTokensUseCase(hotCryptoRepository: HotCryptoRepository): GetHotCryptoUseCase {
+ return GetHotCryptoUseCase(hotCryptoRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideFetchHotCryptoUseCase(hotCryptoRepository: HotCryptoRepository): FetchHotCryptoUseCase {
+ return FetchHotCryptoUseCase(hotCryptoRepository)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/PromoDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/PromoDomainModule.kt
new file mode 100644
index 0000000000..9e969c71de
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/PromoDomainModule.kt
@@ -0,0 +1,39 @@
+package com.tangem.tap.di.domain
+
+import com.tangem.domain.promo.*
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object PromoDomainModule {
+
+ @Provides
+ @Singleton
+ fun provideShouldShowSwapPromoWalletUseCase(
+ promoSettingsRepository: PromoRepository,
+ ): ShouldShowSwapPromoWalletUseCase {
+ return ShouldShowSwapPromoWalletUseCase(promoSettingsRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideShouldShowSwapPromoTokenUseCase(promoRepository: PromoRepository): ShouldShowSwapPromoTokenUseCase {
+ return ShouldShowSwapPromoTokenUseCase(promoRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideShouldShowSwapStoriesUseCase(promoRepository: PromoRepository): ShouldShowStoriesUseCase {
+ return ShouldShowStoriesUseCase(promoRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetStoryContentUseCase(promoRepository: PromoRepository): GetStoryContentUseCase {
+ return GetStoryContentUseCase(promoRepository)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/QrScanningDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/QrScanningDomainModule.kt
new file mode 100644
index 0000000000..ec86de8c46
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/QrScanningDomainModule.kt
@@ -0,0 +1,34 @@
+package com.tangem.tap.di.domain
+
+import com.tangem.domain.qrscanning.repository.QrScanningEventsRepository
+import com.tangem.domain.qrscanning.usecases.EmitQrScannedEventUseCase
+import com.tangem.domain.qrscanning.usecases.ListenToQrScanningUseCase
+import com.tangem.domain.qrscanning.usecases.ParseQrCodeUseCase
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object QrScanningDomainModule {
+
+ @Provides
+ @Singleton
+ fun provideListenToQrScanUseCase(repository: QrScanningEventsRepository): ListenToQrScanningUseCase {
+ return ListenToQrScanningUseCase(repository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideEmitQrScannedEventUseCase(repository: QrScanningEventsRepository): EmitQrScannedEventUseCase {
+ return EmitQrScannedEventUseCase(repository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideParseQrCodeUseCase(repository: QrScanningEventsRepository): ParseQrCodeUseCase {
+ return ParseQrCodeUseCase(repository)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/SettingsDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/SettingsDomainModule.kt
new file mode 100644
index 0000000000..7dc5634128
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/SettingsDomainModule.kt
@@ -0,0 +1,230 @@
+package com.tangem.tap.di.domain
+
+import com.tangem.domain.balancehiding.DeviceFlipDetector
+import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
+import com.tangem.domain.balancehiding.ListenToFlipsUseCase
+import com.tangem.domain.balancehiding.UpdateBalanceHidingSettingsUseCase
+import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository
+import com.tangem.domain.settings.*
+import com.tangem.domain.settings.repositories.AppRatingRepository
+import com.tangem.domain.settings.repositories.PermissionRepository
+import com.tangem.domain.settings.repositories.SettingsRepository
+import com.tangem.domain.settings.usercountry.FetchUserCountryUseCase
+import com.tangem.domain.settings.usercountry.GetUserCountryUseCase
+import com.tangem.sdk.api.TangemSdkManager
+import com.tangem.tap.domain.settings.DefaultLegacySettingsRepository
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Suppress("TooManyFunctions")
+@Module
+@InstallIn(SingletonComponent::class)
+internal object SettingsDomainModule {
+
+ @Provides
+ @Singleton
+ fun providesIsReadyToShowRatingUseCase(appRatingRepository: AppRatingRepository): IsReadyToShowRateAppUseCase {
+ return IsReadyToShowRateAppUseCase(appRatingRepository = appRatingRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun providesRemindToRateAppLaterUseCase(appRatingRepository: AppRatingRepository): RemindToRateAppLaterUseCase {
+ return RemindToRateAppLaterUseCase(appRatingRepository = appRatingRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun providesNeverToSuggestRateAppUseCase(appRatingRepository: AppRatingRepository): NeverToSuggestRateAppUseCase {
+ return NeverToSuggestRateAppUseCase(appRatingRepository = appRatingRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun providesSetWalletWithFundsFoundUseCase(
+ appRatingRepository: AppRatingRepository,
+ ): SetWalletWithFundsFoundUseCase {
+ return SetWalletWithFundsFoundUseCase(appRatingRepository = appRatingRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun providesShouldShowSaveWalletScreenUseCase(
+ settingsRepository: SettingsRepository,
+ ): ShouldShowSaveWalletScreenUseCase {
+ return ShouldShowSaveWalletScreenUseCase(settingsRepository = settingsRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideShouldShowMarketsTooltipUseCase(
+ settingsRepository: SettingsRepository,
+ ): ShouldShowMarketsTooltipUseCase {
+ return ShouldShowMarketsTooltipUseCase(settingsRepository = settingsRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun providesCanUseBiometryUseCase(tangemSdkManager: TangemSdkManager): CanUseBiometryUseCase {
+ return CanUseBiometryUseCase(
+ legacySettingsRepository = DefaultLegacySettingsRepository(tangemSdkManager = tangemSdkManager),
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun providesGetBalanceHidingSettingsUseCase(
+ balanceHidingRepository: BalanceHidingRepository,
+ ): GetBalanceHidingSettingsUseCase {
+ return GetBalanceHidingSettingsUseCase(
+ balanceHidingRepository = balanceHidingRepository,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun providesListenUseCase(
+ flipDetector: DeviceFlipDetector,
+ balanceHidingRepository: BalanceHidingRepository,
+ ): ListenToFlipsUseCase {
+ return ListenToFlipsUseCase(
+ flipDetector = flipDetector,
+ balanceHidingRepository = balanceHidingRepository,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideUpdateHideBalancesSettingsUseCase(
+ balanceHidingRepository: BalanceHidingRepository,
+ ): UpdateBalanceHidingSettingsUseCase {
+ return UpdateBalanceHidingSettingsUseCase(balanceHidingRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideSetWalletsScrollPreviewIsShown(settingsRepository: SettingsRepository): NeverToShowWalletsScrollPreview {
+ return NeverToShowWalletsScrollPreview(settingsRepository = settingsRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideIsWalletsScrollPreviewEnabled(settingsRepository: SettingsRepository): IsWalletsScrollPreviewEnabled {
+ return IsWalletsScrollPreviewEnabled(settingsRepository = settingsRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideDeleteDeprecatedLogsUseCase(settingsRepository: SettingsRepository): DeleteDeprecatedLogsUseCase {
+ return DeleteDeprecatedLogsUseCase(settingsRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideIsSendTapHelpPreviewEnabledUseCase(
+ settingsRepository: SettingsRepository,
+ ): IsSendTapHelpEnabledUseCase {
+ return IsSendTapHelpEnabledUseCase(settingsRepository = settingsRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideNeverShowTapHelpUseCase(settingsRepository: SettingsRepository): NeverShowTapHelpUseCase {
+ return NeverShowTapHelpUseCase(settingsRepository = settingsRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideSetSaveWalletScreenShownUseCase(
+ settingsRepository: SettingsRepository,
+ ): SetSaveWalletScreenShownUseCase {
+ return SetSaveWalletScreenShownUseCase(settingsRepository = settingsRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideIncrementAppLaunchCounterUseCase(
+ settingsRepository: SettingsRepository,
+ ): IncrementAppLaunchCounterUseCase {
+ return IncrementAppLaunchCounterUseCase(settingsRepository = settingsRepository)
+ }
+
+ // region PushPermissionRepository
+ @Provides
+ @Singleton
+ fun provideShouldInitiallyAskPermissionUseCase(
+ permissionRepository: PermissionRepository,
+ ): ShouldInitiallyAskPermissionUseCase {
+ return ShouldInitiallyAskPermissionUseCase(repository = permissionRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideNeverToInitiallyAskPermissionUseCase(
+ permissionRepository: PermissionRepository,
+ ): NeverToInitiallyAskPermissionUseCase {
+ return NeverToInitiallyAskPermissionUseCase(repository = permissionRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideShouldAskPermissionUseCase(permissionRepository: PermissionRepository): ShouldAskPermissionUseCase {
+ return ShouldAskPermissionUseCase(repository = permissionRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideNeverRequestPermissionUseCase(
+ permissionRepository: PermissionRepository,
+ ): NeverRequestPermissionUseCase {
+ return NeverRequestPermissionUseCase(repository = permissionRepository)
+ }
+ // endregion
+
+ @Provides
+ @Singleton
+ fun provideFetchUserCountryCodeUseCase(settingsRepository: SettingsRepository): FetchUserCountryUseCase {
+ return FetchUserCountryUseCase(settingsRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetUserCountryCodeUseCase(settingsRepository: SettingsRepository): GetUserCountryUseCase {
+ return GetUserCountryUseCase(settingsRepository)
+ }
+
+ // region Google services availability
+ @Provides
+ @Singleton
+ fun provideSetGoogleServicesAvailabilityUseCase(
+ settingsRepository: SettingsRepository,
+ ): SetGoogleServicesAvailabilityUseCase {
+ return SetGoogleServicesAvailabilityUseCase(settingsRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideIsGoogleServicesAvailableUseCase(
+ settingsRepository: SettingsRepository,
+ ): IsGoogleServicesAvailableUseCase {
+ return IsGoogleServicesAvailableUseCase(settingsRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideSetGooglePayAvailabilityUseCase(
+ settingsRepository: SettingsRepository,
+ ): SetGooglePayAvailabilityUseCase {
+ return SetGooglePayAvailabilityUseCase(settingsRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideIsGooglePayAvailableUseCase(settingsRepository: SettingsRepository): IsGooglePayAvailableUseCase {
+ return IsGooglePayAvailableUseCase(settingsRepository)
+ }
+ // endregion
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/StakingDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/StakingDomainModule.kt
new file mode 100644
index 0000000000..db77c4ceba
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/StakingDomainModule.kt
@@ -0,0 +1,212 @@
+package com.tangem.tap.di.domain
+
+import com.tangem.domain.staking.*
+import com.tangem.domain.staking.repositories.*
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object StakingDomainModule {
+
+ @Provides
+ @Singleton
+ fun provideGetStakingAvailabilityUseCase(
+ stakingRepository: StakingRepository,
+ stakingErrorResolver: StakingErrorResolver,
+ ): GetStakingAvailabilityUseCase {
+ return GetStakingAvailabilityUseCase(
+ stakingRepository = stakingRepository,
+ stakingErrorResolver = stakingErrorResolver,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetStakingEntryInfoUseCase(
+ stakingRepository: StakingRepository,
+ stakingErrorResolver: StakingErrorResolver,
+ ): GetStakingEntryInfoUseCase {
+ return GetStakingEntryInfoUseCase(
+ stakingRepository = stakingRepository,
+ stakingErrorResolver = stakingErrorResolver,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetYieldUseCase(
+ stakingRepository: StakingRepository,
+ stakingErrorResolver: StakingErrorResolver,
+ ): GetYieldUseCase {
+ return GetYieldUseCase(
+ stakingRepository = stakingRepository,
+ stakingErrorResolver = stakingErrorResolver,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideFetchActionsUseCase(
+ stakingRepository: StakingRepository,
+ stakingActionRepository: StakingActionRepository,
+ stakingErrorResolver: StakingErrorResolver,
+ ): FetchActionsUseCase {
+ return FetchActionsUseCase(
+ stakingRepository = stakingRepository,
+ stakingActionRepository = stakingActionRepository,
+ stakingErrorResolver = stakingErrorResolver,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetActionsUseCase(
+ stakingActionRepository: StakingActionRepository,
+ stakingErrorResolver: StakingErrorResolver,
+ ): GetActionsUseCase {
+ return GetActionsUseCase(
+ stakingActionRepository = stakingActionRepository,
+ stakingErrorResolver = stakingErrorResolver,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetStakingTokensUseCase(
+ stakingRepository: StakingRepository,
+ stakingErrorResolver: StakingErrorResolver,
+ ): FetchStakingTokensUseCase {
+ return FetchStakingTokensUseCase(
+ stakingRepository = stakingRepository,
+ stakingErrorResolver = stakingErrorResolver,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideFetchStakingYieldBalanceUseCase(
+ stakingRepository: StakingRepository,
+ stakingErrorResolver: StakingErrorResolver,
+ ): FetchStakingYieldBalanceUseCase {
+ return FetchStakingYieldBalanceUseCase(
+ stakingRepository = stakingRepository,
+ stakingErrorResolver = stakingErrorResolver,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetStakingTransactionsUseCase(
+ stakingRepository: StakingRepository,
+ stakingErrorResolver: StakingErrorResolver,
+ ): GetStakingTransactionsUseCase {
+ return GetStakingTransactionsUseCase(
+ stakingRepository = stakingRepository,
+ stakingErrorResolver = stakingErrorResolver,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideGasEstimateUseCase(
+ stakingRepository: StakingRepository,
+ stakingErrorResolver: StakingErrorResolver,
+ ): EstimateGasUseCase {
+ return EstimateGasUseCase(
+ stakingRepository = stakingRepository,
+ stakingErrorResolver = stakingErrorResolver,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideSubmitHashUseCase(
+ stakingTransactionHashRepository: StakingTransactionHashRepository,
+ stakingErrorResolver: StakingErrorResolver,
+ ): SubmitHashUseCase {
+ return SubmitHashUseCase(
+ stakingTransactionHashRepository = stakingTransactionHashRepository,
+ stakingErrorResolver = stakingErrorResolver,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideSaveUnsubmittedHashUseCase(
+ stakingTransactionHashRepository: StakingTransactionHashRepository,
+ stakingErrorResolver: StakingErrorResolver,
+ ): SaveUnsubmittedHashUseCase {
+ return SaveUnsubmittedHashUseCase(
+ stakingTransactionHashRepository = stakingTransactionHashRepository,
+ stakingErrorResolver = stakingErrorResolver,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideInvalidatePendingTransactionsUseCase(
+ stakingErrorResolver: StakingErrorResolver,
+ ): InvalidatePendingTransactionsUseCase {
+ return InvalidatePendingTransactionsUseCase(
+ stakingErrorResolver = stakingErrorResolver,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideSendUnsubmittedHashesUseCase(
+ stakingTransactionHashRepository: StakingTransactionHashRepository,
+ stakingErrorResolver: StakingErrorResolver,
+ ): SendUnsubmittedHashesUseCase {
+ return SendUnsubmittedHashesUseCase(
+ stakingTransactionHashRepository = stakingTransactionHashRepository,
+ stakingErrorResolver = stakingErrorResolver,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideIsApproveNeededUseCase(
+ stakingRepository: StakingRepository,
+ stakingErrorResolver: StakingErrorResolver,
+ ): IsApproveNeededUseCase {
+ return IsApproveNeededUseCase(
+ stakingRepository = stakingRepository,
+ stakingErrorResolver = stakingErrorResolver,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetConstructedStakingTransactionUseCase(
+ stakingRepository: StakingRepository,
+ stakingErrorResolver: StakingErrorResolver,
+ ): GetConstructedStakingTransactionUseCase {
+ return GetConstructedStakingTransactionUseCase(
+ stakingRepository = stakingRepository,
+ stakingErrorResolver = stakingErrorResolver,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideIsAnyTokenStakedUseCase(
+ stakingRepository: StakingRepository,
+ stakingErrorResolver: StakingErrorResolver,
+ ): IsAnyTokenStakedUseCase {
+ return IsAnyTokenStakedUseCase(
+ stakingRepository = stakingRepository,
+ stakingErrorResolver = stakingErrorResolver,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetStakingIntegrationIdUseCase(stakingRepository: StakingRepository): GetStakingIntegrationIdUseCase {
+ return GetStakingIntegrationIdUseCase(stakingRepository)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/SwapDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/SwapDomainModule.kt
new file mode 100644
index 0000000000..e94429b646
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/SwapDomainModule.kt
@@ -0,0 +1,23 @@
+package com.tangem.tap.di.domain
+
+import com.tangem.feature.swap.domain.GetAvailablePairsUseCase
+import com.tangem.feature.swap.domain.api.SwapRepository
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+/**
+[REDACTED_AUTHOR]
+ */
+@Module
+@InstallIn(SingletonComponent::class)
+internal object SwapDomainModule {
+
+ @Provides
+ @Singleton
+ fun provideGetAvailablePairsUseCase(swapRepository: SwapRepository): GetAvailablePairsUseCase {
+ return GetAvailablePairsUseCase(swapRepository = swapRepository)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt
new file mode 100644
index 0000000000..b719015a7a
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt
@@ -0,0 +1,392 @@
+package com.tangem.tap.di.domain
+
+import com.tangem.core.configtoggle.feature.FeatureTogglesManager
+import com.tangem.domain.exchange.RampStateManager
+import com.tangem.domain.promo.PromoRepository
+import com.tangem.domain.staking.repositories.StakingRepository
+import com.tangem.domain.tokens.*
+import com.tangem.domain.tokens.operations.*
+import com.tangem.domain.tokens.repository.*
+import com.tangem.domain.walletmanager.WalletManagersFacade
+import com.tangem.features.swap.SwapFeatureToggles
+import com.tangem.tap.domain.tokens.DefaultTokensFeatureToggles
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+@Suppress("TooManyFunctions", "LargeClass")
+internal object TokensDomainModule {
+
+ @Provides
+ @Singleton
+ fun provideAddCryptoCurrenciesUseCase(
+ currenciesRepository: CurrenciesRepository,
+ networksRepository: NetworksRepository,
+ ): AddCryptoCurrenciesUseCase {
+ return AddCryptoCurrenciesUseCase(
+ currenciesRepository = currenciesRepository,
+ networksRepository = networksRepository,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideFetchTokenListUseCase(
+ currenciesRepository: CurrenciesRepository,
+ quotesRepository: QuotesRepository,
+ networksRepository: NetworksRepository,
+ stakingRepository: StakingRepository,
+ ): FetchTokenListUseCase {
+ return FetchTokenListUseCase(currenciesRepository, networksRepository, quotesRepository, stakingRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideFetchPendingTransactionsUseCase(
+ networksRepository: NetworksRepository,
+ ): FetchPendingTransactionsUseCase {
+ return FetchPendingTransactionsUseCase(networksRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideTokensFeatureToggles(featureTogglesManager: FeatureTogglesManager): TokensFeatureToggles {
+ return DefaultTokensFeatureToggles(featureTogglesManager = featureTogglesManager)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetTokenListUseCase(
+ currenciesRepository: CurrenciesRepository,
+ baseCurrenciesStatusesOperations: BaseCurrenciesStatusesOperations,
+ ): GetTokenListUseCase {
+ return GetTokenListUseCase(
+ currenciesRepository = currenciesRepository,
+ currenciesStatusesOperations = baseCurrenciesStatusesOperations,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideRemoveCurrencyUseCase(
+ currenciesRepository: CurrenciesRepository,
+ walletManagersFacade: WalletManagersFacade,
+ ): RemoveCurrencyUseCase {
+ return RemoveCurrencyUseCase(currenciesRepository, walletManagersFacade)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetCurrencyUseCase(
+ baseCurrencyStatusOperations: BaseCurrencyStatusOperations,
+ dispatchers: CoroutineDispatcherProvider,
+ ): GetCurrencyStatusUpdatesUseCase {
+ return GetCurrencyStatusUpdatesUseCase(
+ currencyStatusOperations = baseCurrencyStatusOperations,
+ dispatchers = dispatchers,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetAllWalletsCryptoCurrencyStatusesUseCase(
+ currenciesRepository: CurrenciesRepository,
+ currencyStatusOperations: BaseCurrencyStatusOperations,
+ dispatchers: CoroutineDispatcherProvider,
+ ): GetAllWalletsCryptoCurrencyStatusesUseCase {
+ return GetAllWalletsCryptoCurrencyStatusesUseCase(
+ currenciesRepository = currenciesRepository,
+ currencyStatusOperations = currencyStatusOperations,
+ dispatchers = dispatchers,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetCurrencyWarningsUseCase(
+ walletManagersFacade: WalletManagersFacade,
+ currenciesRepository: CurrenciesRepository,
+ networksRepository: NetworksRepository,
+ currencyChecksRepository: CurrencyChecksRepository,
+ dispatchers: CoroutineDispatcherProvider,
+ baseCurrencyStatusOperations: BaseCurrencyStatusOperations,
+ ): GetCurrencyWarningsUseCase {
+ return GetCurrencyWarningsUseCase(
+ walletManagersFacade = walletManagersFacade,
+ currenciesRepository = currenciesRepository,
+ networksRepository = networksRepository,
+ currencyChecksRepository = currencyChecksRepository,
+ dispatchers = dispatchers,
+ currencyStatusOperations = baseCurrencyStatusOperations,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetPrimaryCurrencyUseCase(
+ currencyStatusOperations: BaseCurrencyStatusOperations,
+ dispatchers: CoroutineDispatcherProvider,
+ ): GetPrimaryCurrencyStatusUpdatesUseCase {
+ return GetPrimaryCurrencyStatusUpdatesUseCase(
+ currencyStatusOperations = currencyStatusOperations,
+ dispatchers = dispatchers,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideFetchCurrencyStatusUseCase(
+ currenciesRepository: CurrenciesRepository,
+ quotesRepository: QuotesRepository,
+ networksRepository: NetworksRepository,
+ stakingRepository: StakingRepository,
+ ): FetchCurrencyStatusUseCase {
+ return FetchCurrencyStatusUseCase(currenciesRepository, networksRepository, quotesRepository, stakingRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideFetchCardTokenListUseCase(
+ currenciesRepository: CurrenciesRepository,
+ quotesRepository: QuotesRepository,
+ networksRepository: NetworksRepository,
+ stakingRepository: StakingRepository,
+ ): FetchCardTokenListUseCase {
+ return FetchCardTokenListUseCase(currenciesRepository, networksRepository, quotesRepository, stakingRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun providesGetCryptoCurrencyStatusSyncUseCase(
+ currencyStatusOperations: BaseCurrencyStatusOperations,
+ ): GetCryptoCurrencyStatusSyncUseCase {
+ return GetCryptoCurrencyStatusSyncUseCase(currencyStatusOperations)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetCryptoCurrencyUseCase(currenciesRepository: CurrenciesRepository): GetCryptoCurrencyUseCase {
+ return GetCryptoCurrencyUseCase(currenciesRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideToggleTokenListGroupingUseCase(
+ dispatchers: CoroutineDispatcherProvider,
+ ): ToggleTokenListGroupingUseCase {
+ return ToggleTokenListGroupingUseCase(dispatchers)
+ }
+
+ @Provides
+ @Singleton
+ fun provideToggleTokenListSortingUseCase(dispatchers: CoroutineDispatcherProvider): ToggleTokenListSortingUseCase {
+ return ToggleTokenListSortingUseCase(dispatchers)
+ }
+
+ @Provides
+ @Singleton
+ fun provideApplyTokenListSortingUseCase(
+ currenciesRepository: CurrenciesRepository,
+ dispatchers: CoroutineDispatcherProvider,
+ ): ApplyTokenListSortingUseCase {
+ return ApplyTokenListSortingUseCase(currenciesRepository, dispatchers)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetCryptoCurrencyActionsUseCase(
+ rampStateManager: RampStateManager,
+ walletManagersFacade: WalletManagersFacade,
+ currenciesRepository: CurrenciesRepository,
+ stakingRepository: StakingRepository,
+ promoRepository: PromoRepository,
+ swapFeatureToggles: SwapFeatureToggles,
+ dispatchers: CoroutineDispatcherProvider,
+ currencyStatusOperations: BaseCurrencyStatusOperations,
+ ): GetCryptoCurrencyActionsUseCase {
+ return GetCryptoCurrencyActionsUseCase(
+ rampManager = rampStateManager,
+ walletManagersFacade = walletManagersFacade,
+ currenciesRepository = currenciesRepository,
+ stakingRepository = stakingRepository,
+ promoRepository = promoRepository,
+ swapFeatureToggles = swapFeatureToggles,
+ dispatchers = dispatchers,
+ currencyStatusOperations = currencyStatusOperations,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetCurrencyStatusByNetworkUseCase(
+ currencyStatusOperations: BaseCurrencyStatusOperations,
+ dispatchers: CoroutineDispatcherProvider,
+ ): GetNetworkCoinStatusUseCase {
+ return GetNetworkCoinStatusUseCase(
+ currencyStatusOperations = currencyStatusOperations,
+ dispatchers = dispatchers,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetFeePaidCryptoCurrencyStatusSyncUseCase(
+ currenciesRepository: CurrenciesRepository,
+ currencyStatusOperations: BaseCurrencyStatusOperations,
+ ): GetFeePaidCryptoCurrencyStatusSyncUseCase {
+ return GetFeePaidCryptoCurrencyStatusSyncUseCase(
+ currenciesRepository = currenciesRepository,
+ currencyStatusOperations = currencyStatusOperations,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetMinimumTransactionAmountSyncUseCase(
+ currencyChecksRepository: CurrencyChecksRepository,
+ ): GetMinimumTransactionAmountSyncUseCase {
+ return GetMinimumTransactionAmountSyncUseCase(
+ currencyChecksRepository = currencyChecksRepository,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideIsCryptoCurrencyCoinCouldHideUseCase(
+ currenciesRepository: CurrenciesRepository,
+ ): IsCryptoCurrencyCoinCouldHideUseCase {
+ return IsCryptoCurrencyCoinCouldHideUseCase(
+ currenciesRepository = currenciesRepository,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideUpdateDelayedCurrencyStatusUseCase(
+ networksRepository: NetworksRepository,
+ ): UpdateDelayedNetworkStatusUseCase {
+ return UpdateDelayedNetworkStatusUseCase(
+ networksRepository = networksRepository,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetBalanceNotEnoughForFeeWarningUseCase(
+ currenciesRepository: CurrenciesRepository,
+ dispatchers: CoroutineDispatcherProvider,
+ ): GetBalanceNotEnoughForFeeWarningUseCase {
+ return GetBalanceNotEnoughForFeeWarningUseCase(currenciesRepository, dispatchers)
+ }
+
+ @Provides
+ @Singleton
+ fun provideIsAmountSubtractAvailableUseCase(
+ currenciesRepository: CurrenciesRepository,
+ dispatchers: CoroutineDispatcherProvider,
+ ): IsAmountSubtractAvailableUseCase {
+ return IsAmountSubtractAvailableUseCase(currenciesRepository, dispatchers)
+ }
+
+ @Provides
+ @Singleton
+ fun provideRunPolkadotAccountHealthCheckUseCase(
+ repository: PolkadotAccountHealthCheckRepository,
+ ): RunPolkadotAccountHealthCheckUseCase {
+ return RunPolkadotAccountHealthCheckUseCase(repository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetNetworkStatusesUseCase(networksRepository: NetworksRepository): GetNetworkAddressesUseCase {
+ return GetNetworkAddressesUseCase(
+ networksRepository = networksRepository,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetWalletTotalBalanceUseCase(
+ baseCurrenciesStatusesOperations: BaseCurrenciesStatusesOperations,
+ ): GetWalletTotalBalanceUseCase {
+ return GetWalletTotalBalanceUseCase(baseCurrenciesStatusesOperations)
+ }
+
+ @Provides
+ @Singleton
+ fun provideRefreshMultiCurrencyWalletQuotesUseCase(
+ currenciesRepository: CurrenciesRepository,
+ quotesRepository: QuotesRepository,
+ ): RefreshMultiCurrencyWalletQuotesUseCase {
+ return RefreshMultiCurrencyWalletQuotesUseCase(
+ currenciesRepository = currenciesRepository,
+ quotesRepository = quotesRepository,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetCurrencyCheckUseCase(
+ currencyChecksRepository: CurrencyChecksRepository,
+ dispatchers: CoroutineDispatcherProvider,
+ ): GetCurrencyCheckUseCase {
+ return GetCurrencyCheckUseCase(currencyChecksRepository, dispatchers)
+ }
+
+ @Provides
+ @Singleton
+ fun provideBaseCurrenciesStatusesOperations(
+ tokensFeatureToggles: TokensFeatureToggles,
+ currenciesRepository: CurrenciesRepository,
+ quotesRepository: QuotesRepository,
+ networksRepository: NetworksRepository,
+ stakingRepository: StakingRepository,
+ ): BaseCurrenciesStatusesOperations {
+ return if (tokensFeatureToggles.isBalancesCachingEnabled) {
+ CachedCurrenciesStatusesOperations(
+ currenciesRepository = currenciesRepository,
+ quotesRepository = quotesRepository,
+ networksRepository = networksRepository,
+ stakingRepository = stakingRepository,
+ )
+ } else {
+ LceCurrenciesStatusesOperations(
+ currenciesRepository = currenciesRepository,
+ quotesRepository = quotesRepository,
+ networksRepository = networksRepository,
+ stakingRepository = stakingRepository,
+ )
+ }
+ }
+
+ @Provides
+ @Singleton
+ fun provideBaseCurrencyStatusOperations(
+ tokensFeatureToggles: TokensFeatureToggles,
+ currenciesRepository: CurrenciesRepository,
+ quotesRepository: QuotesRepository,
+ networksRepository: NetworksRepository,
+ stakingRepository: StakingRepository,
+ ): BaseCurrencyStatusOperations {
+ return if (tokensFeatureToggles.isBalancesCachingEnabled) {
+ CachedCurrenciesStatusesOperations(
+ currenciesRepository = currenciesRepository,
+ quotesRepository = quotesRepository,
+ networksRepository = networksRepository,
+ stakingRepository = stakingRepository,
+ )
+ } else {
+ CurrenciesStatusesOperations(
+ currenciesRepository = currenciesRepository,
+ quotesRepository = quotesRepository,
+ networksRepository = networksRepository,
+ stakingRepository = stakingRepository,
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt
new file mode 100644
index 0000000000..507a284a76
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/TransactionDomainModule.kt
@@ -0,0 +1,139 @@
+package com.tangem.tap.di.domain
+
+import com.tangem.domain.card.repository.CardSdkConfigRepository
+import com.tangem.domain.demo.DemoConfig
+import com.tangem.domain.tokens.repository.CurrenciesRepository
+import com.tangem.domain.tokens.repository.NetworksRepository
+import com.tangem.domain.transaction.FeeRepository
+import com.tangem.domain.transaction.TransactionRepository
+import com.tangem.domain.transaction.usecase.*
+import com.tangem.domain.walletmanager.WalletManagersFacade
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object TransactionDomainModule {
+
+ @Provides
+ @Singleton
+ fun provideGetFeeUseCase(walletManagersFacade: WalletManagersFacade): GetFeeUseCase {
+ return GetFeeUseCase(
+ walletManagersFacade = walletManagersFacade,
+ demoConfig = DemoConfig(),
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideSendTransactionUseCase(
+ cardSdkConfigRepository: CardSdkConfigRepository,
+ transactionRepository: TransactionRepository,
+ walletManagersFacade: WalletManagersFacade,
+ ): SendTransactionUseCase {
+ return SendTransactionUseCase(
+ demoConfig = DemoConfig(),
+ cardSdkConfigRepository = cardSdkConfigRepository,
+ transactionRepository = transactionRepository,
+ walletManagersFacade = walletManagersFacade,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideAssociateAssetUseCase(
+ cardSdkConfigRepository: CardSdkConfigRepository,
+ walletManagersFacade: WalletManagersFacade,
+ currenciesRepository: CurrenciesRepository,
+ networksRepository: NetworksRepository,
+ ): AssociateAssetUseCase {
+ return AssociateAssetUseCase(
+ cardSdkConfigRepository = cardSdkConfigRepository,
+ walletManagersFacade = walletManagersFacade,
+ currenciesRepository = currenciesRepository,
+ networksRepository = networksRepository,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideRetryTransactionUseCase(
+ cardSdkConfigRepository: CardSdkConfigRepository,
+ walletManagersFacade: WalletManagersFacade,
+ ): RetryIncompleteTransactionUseCase {
+ return RetryIncompleteTransactionUseCase(
+ cardSdkConfigRepository = cardSdkConfigRepository,
+ walletManagersFacade = walletManagersFacade,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideDismissIncompleteTransactionUseCase(
+ walletManagersFacade: WalletManagersFacade,
+ ): DismissIncompleteTransactionUseCase {
+ return DismissIncompleteTransactionUseCase(
+ walletManagersFacade = walletManagersFacade,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideCreateTransactionUseCase(transactionRepository: TransactionRepository): CreateTransactionUseCase {
+ return CreateTransactionUseCase(transactionRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideCreateTransactionExtrasUseCase(
+ transactionRepository: TransactionRepository,
+ ): CreateTransactionDataExtrasUseCase {
+ return CreateTransactionDataExtrasUseCase(transactionRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideEstimateFeeUseCase(walletManagersFacade: WalletManagersFacade): EstimateFeeUseCase {
+ return EstimateFeeUseCase(
+ walletManagersFacade = walletManagersFacade,
+ demoConfig = DemoConfig(),
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun provideIsFeeApproximateUseCase(feeRepository: FeeRepository): IsFeeApproximateUseCase {
+ return IsFeeApproximateUseCase(feeRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideValidateTransactionUseCase(transactionRepository: TransactionRepository): ValidateTransactionUseCase {
+ return ValidateTransactionUseCase(transactionRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideIsUtxoConsolidationAvailableUseCase(
+ walletManagersFacade: WalletManagersFacade,
+ ): IsUtxoConsolidationAvailableUseCase {
+ return IsUtxoConsolidationAvailableUseCase(walletManagersFacade)
+ }
+
+ @Provides
+ @Singleton
+ fun provideCreateApproveTransactionUseCase(
+ transactionRepository: TransactionRepository,
+ ): CreateApprovalTransactionUseCase {
+ return CreateApprovalTransactionUseCase(transactionRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun provideGetAllowanceUseCase(transactionRepository: TransactionRepository): GetAllowanceUseCase {
+ return GetAllowanceUseCase(transactionRepository)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/TxHistoryDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/TxHistoryDomainModule.kt
new file mode 100644
index 0000000000..98eb94e42e
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/TxHistoryDomainModule.kt
@@ -0,0 +1,38 @@
+package com.tangem.tap.di.domain
+
+import com.tangem.domain.txhistory.repository.TxHistoryRepository
+import com.tangem.domain.txhistory.usecase.GetExplorerTransactionUrlUseCase
+import com.tangem.domain.txhistory.usecase.GetFixedTxHistoryItemsUseCase
+import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
+import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object TxHistoryDomainModule {
+
+ @Provides
+ fun provideGetTxHistoryItemsCountUseCase(txHistoryRepository: TxHistoryRepository): GetTxHistoryItemsCountUseCase {
+ return GetTxHistoryItemsCountUseCase(repository = txHistoryRepository)
+ }
+
+ @Provides
+ fun provideGetTxHistoryItemsUseCase(txHistoryRepository: TxHistoryRepository): GetTxHistoryItemsUseCase {
+ return GetTxHistoryItemsUseCase(repository = txHistoryRepository)
+ }
+
+ @Provides
+ fun providesGetExplorerTransactionUrlUseCase(
+ txHistoryRepository: TxHistoryRepository,
+ ): GetExplorerTransactionUrlUseCase {
+ return GetExplorerTransactionUrlUseCase(repository = txHistoryRepository)
+ }
+
+ @Provides
+ fun providesGetFixedTxHistoryItemsUseCase(txHistoryRepository: TxHistoryRepository): GetFixedTxHistoryItemsUseCase {
+ return GetFixedTxHistoryItemsUseCase(repository = txHistoryRepository)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/VisaDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/VisaDomainModule.kt
new file mode 100644
index 0000000000..de64fc496f
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/VisaDomainModule.kt
@@ -0,0 +1,39 @@
+package com.tangem.tap.di.domain
+
+import com.tangem.domain.visa.GetVisaCurrencyUseCase
+import com.tangem.domain.visa.GetVisaTxDetailsUseCase
+import com.tangem.domain.visa.GetVisaTxHistoryUseCase
+import com.tangem.domain.visa.SetVisaPinCodeUseCase
+import com.tangem.domain.visa.repository.VisaActivationRepository
+import com.tangem.domain.visa.repository.VisaRepository
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object VisaDomainModule {
+
+ @Provides
+ fun provideVisaCurrencyUseCase(visaRepository: VisaRepository): GetVisaCurrencyUseCase {
+ return GetVisaCurrencyUseCase(visaRepository)
+ }
+
+ @Provides
+ fun provideGetVisaTxHistoryUseCase(visaRepository: VisaRepository): GetVisaTxHistoryUseCase {
+ return GetVisaTxHistoryUseCase(visaRepository)
+ }
+
+ @Provides
+ fun provideGetVisaTxDetailsUseCase(visaRepository: VisaRepository): GetVisaTxDetailsUseCase {
+ return GetVisaTxDetailsUseCase(visaRepository)
+ }
+
+ @Provides
+ fun provideSetVisaPinCodeUseCase(
+ visaActivationRepositoryFactory: VisaActivationRepository.Factory,
+ ): SetVisaPinCodeUseCase {
+ return SetVisaPinCodeUseCase(visaActivationRepositoryFactory)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/WalletConnectDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/WalletConnectDomainModule.kt
new file mode 100644
index 0000000000..e542ddc5fd
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/WalletConnectDomainModule.kt
@@ -0,0 +1,22 @@
+package com.tangem.tap.di.domain
+
+import com.tangem.domain.walletconnect.CheckIsWalletConnectAvailableUseCase
+import com.tangem.domain.walletconnect.repository.WalletConnectRepository
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object WalletConnectDomainModule {
+
+ @Provides
+ @Singleton
+ fun providesCheckIsWalletConnectAvailableUseCase(
+ walletConnectRepository: WalletConnectRepository,
+ ): CheckIsWalletConnectAvailableUseCase {
+ return CheckIsWalletConnectAvailableUseCase(walletConnectRepository = walletConnectRepository)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/WalletManagersFacadeModule.kt b/app/src/main/java/com/tangem/tap/di/domain/WalletManagersFacadeModule.kt
new file mode 100644
index 0000000000..a54c6ecc0c
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/WalletManagersFacadeModule.kt
@@ -0,0 +1,37 @@
+package com.tangem.tap.di.domain
+
+import com.tangem.blockchainsdk.BlockchainSDKFactory
+import com.tangem.datasource.asset.loader.AssetLoader
+import com.tangem.datasource.local.userwallet.UserWalletsStore
+import com.tangem.datasource.local.walletmanager.WalletManagersStore
+import com.tangem.domain.walletmanager.DefaultWalletManagersFacade
+import com.tangem.domain.walletmanager.WalletManagersFacade
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object WalletManagersFacadeModule {
+
+ @Provides
+ @Singleton
+ fun provideWalletManagersFacade(
+ walletManagersStore: WalletManagersStore,
+ userWalletsStore: UserWalletsStore,
+ assetLoader: AssetLoader,
+ blockchainSDKFactory: BlockchainSDKFactory,
+ dispatchers: CoroutineDispatcherProvider,
+ ): WalletManagersFacade {
+ return DefaultWalletManagersFacade(
+ walletManagersStore = walletManagersStore,
+ userWalletsStore = userWalletsStore,
+ assetLoader = assetLoader,
+ dispatchers = dispatchers,
+ blockchainSDKFactory = blockchainSDKFactory,
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/domain/WalletsDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/WalletsDomainModule.kt
new file mode 100644
index 0000000000..49fdf2c1be
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/domain/WalletsDomainModule.kt
@@ -0,0 +1,168 @@
+package com.tangem.tap.di.domain
+
+import com.tangem.domain.redux.ReduxStateHolder
+import com.tangem.domain.transaction.WalletAddressServiceRepository
+import com.tangem.domain.transaction.usecase.ParseSharedAddressUseCase
+import com.tangem.domain.transaction.usecase.ValidateWalletAddressUseCase
+import com.tangem.domain.transaction.usecase.ValidateWalletMemoUseCase
+import com.tangem.domain.walletmanager.WalletManagersFacade
+import com.tangem.domain.wallets.legacy.UserWalletsListManager
+import com.tangem.domain.wallets.repository.WalletNamesMigrationRepository
+import com.tangem.domain.wallets.repository.WalletsRepository
+import com.tangem.domain.wallets.usecase.*
+import com.tangem.feature.wallet.presentation.wallet.domain.WalletNameMigrationUseCase
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object WalletsDomainModule {
+
+ @Provides
+ @Singleton
+ fun providesGetWalletsUseCase(userWalletsListManager: UserWalletsListManager): GetWalletsUseCase {
+ return GetWalletsUseCase(userWalletsListManager = userWalletsListManager)
+ }
+
+ @Provides
+ @Singleton
+ fun providesWalletNameMigrationUseCase(
+ userWalletsListManager: UserWalletsListManager,
+ walletNamesMigrationRepository: WalletNamesMigrationRepository,
+ ): WalletNameMigrationUseCase {
+ return WalletNameMigrationUseCase(
+ userWalletsListManager = userWalletsListManager,
+ walletNamesMigrationRepository = walletNamesMigrationRepository,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun providesGetUserWalletUseCase(userWalletsListManager: UserWalletsListManager): GetUserWalletUseCase {
+ return GetUserWalletUseCase(userWalletsListManager = userWalletsListManager)
+ }
+
+ @Provides
+ @Singleton
+ fun providesGetSelectedWalletSyncUseCase(
+ userWalletsListManager: UserWalletsListManager,
+ ): GetSelectedWalletSyncUseCase {
+ return GetSelectedWalletSyncUseCase(userWalletsListManager = userWalletsListManager)
+ }
+
+ @Provides
+ @Singleton
+ fun providesGetSelectedWalletUseCase(userWalletsListManager: UserWalletsListManager): GetSelectedWalletUseCase {
+ return GetSelectedWalletUseCase(userWalletsListManager = userWalletsListManager)
+ }
+
+ @Provides
+ @Singleton
+ fun providesSaveWalletUseCase(userWalletsListManager: UserWalletsListManager): SaveWalletUseCase {
+ return SaveWalletUseCase(userWalletsListManager = userWalletsListManager)
+ }
+
+ @Provides
+ @Singleton
+ fun providesGetExploreUrlUseCase(walletsManagersFacade: WalletManagersFacade): GetExploreUrlUseCase {
+ return GetExploreUrlUseCase(walletsManagersFacade = walletsManagersFacade)
+ }
+
+ @Provides
+ @Singleton
+ fun providesUnlockWalletUseCase(userWalletsListManager: UserWalletsListManager): UnlockWalletsUseCase {
+ return UnlockWalletsUseCase(userWalletsListManager = userWalletsListManager)
+ }
+
+ @Provides
+ @Singleton
+ fun providesSelectWalletUseCase(
+ userWalletsListManager: UserWalletsListManager,
+ reduxStateHolder: ReduxStateHolder,
+ ): SelectWalletUseCase {
+ return SelectWalletUseCase(userWalletsListManager = userWalletsListManager, reduxStateHolder = reduxStateHolder)
+ }
+
+ @Provides
+ @Singleton
+ fun providesUpdateWalletUseCase(userWalletsListManager: UserWalletsListManager): UpdateWalletUseCase {
+ return UpdateWalletUseCase(userWalletsListManager = userWalletsListManager)
+ }
+
+ @Provides
+ @Singleton
+ fun providesRenameWalletUseCase(
+ userWalletsListManager: UserWalletsListManager,
+ dispatchers: CoroutineDispatcherProvider,
+ ): RenameWalletUseCase {
+ return RenameWalletUseCase(userWalletsListManager = userWalletsListManager, dispatchers = dispatchers)
+ }
+
+ @Provides
+ @Singleton
+ fun providesGetWalletsSyncUseCase(userWalletsListManager: UserWalletsListManager): GetWalletNamesUseCase {
+ return GetWalletNamesUseCase(userWalletsListManager = userWalletsListManager)
+ }
+
+ @Provides
+ @Singleton
+ fun providesDeleteWalletUseCase(userWalletsListManager: UserWalletsListManager): DeleteWalletUseCase {
+ return DeleteWalletUseCase(userWalletsListManager = userWalletsListManager)
+ }
+
+ @Provides
+ @Singleton
+ fun providesShouldSaveUserWalletsSyncUseCase(
+ walletsRepository: WalletsRepository,
+ ): ShouldSaveUserWalletsSyncUseCase {
+ return ShouldSaveUserWalletsSyncUseCase(walletsRepository = walletsRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun providesShouldSaveUserWalletsUseCase(walletsRepository: WalletsRepository): ShouldSaveUserWalletsUseCase {
+ return ShouldSaveUserWalletsUseCase(walletsRepository = walletsRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun providesValidateWalletAddressUseCase(
+ walletAddressServiceRepository: WalletAddressServiceRepository,
+ walletManagersFacade: WalletManagersFacade,
+ ): ValidateWalletAddressUseCase {
+ return ValidateWalletAddressUseCase(
+ walletAddressServiceRepository = walletAddressServiceRepository,
+ walletManagersFacade = walletManagersFacade,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun providesValidateWalletMemoUseCase(
+ walletAddressServiceRepository: WalletAddressServiceRepository,
+ ): ValidateWalletMemoUseCase {
+ return ValidateWalletMemoUseCase(walletAddressServiceRepository = walletAddressServiceRepository)
+ }
+
+ @Provides
+ @Singleton
+ fun providesParseSharedAddressUseCase(
+ walletAddressServiceRepository: WalletAddressServiceRepository,
+ dispatchers: CoroutineDispatcherProvider,
+ ): ParseSharedAddressUseCase {
+ return ParseSharedAddressUseCase(
+ walletAddressServiceRepository = walletAddressServiceRepository,
+ dispatchers = dispatchers,
+ )
+ }
+
+ @Provides
+ @Singleton
+ fun providesSeedPhraseNotificationUseCase(walletsRepository: WalletsRepository): SeedPhraseNotificationUseCase {
+ return SeedPhraseNotificationUseCase(walletsRepository = walletsRepository)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/libs/blockchainsdk/TransactionSignerFactoryModule.kt b/app/src/main/java/com/tangem/tap/di/libs/blockchainsdk/TransactionSignerFactoryModule.kt
new file mode 100644
index 0000000000..d0997c9038
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/libs/blockchainsdk/TransactionSignerFactoryModule.kt
@@ -0,0 +1,23 @@
+package com.tangem.tap.di.libs.blockchainsdk
+
+import com.tangem.data.card.TransactionSignerFactory
+import com.tangem.tap.common.libs.blockchainsdk.DefaultTransactionSignerFactory
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+/**
+[REDACTED_AUTHOR]
+ */
+@Module
+@InstallIn(SingletonComponent::class)
+internal class TransactionSignerFactoryModule {
+
+ @Provides
+ @Singleton
+ fun provideTransactionSignerFactory(): TransactionSignerFactory {
+ return DefaultTransactionSignerFactory()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/routing/AppRouterModule.kt b/app/src/main/java/com/tangem/tap/di/routing/AppRouterModule.kt
new file mode 100644
index 0000000000..4f4aa7e79b
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/routing/AppRouterModule.kt
@@ -0,0 +1,26 @@
+package com.tangem.tap.di.routing
+
+import com.tangem.common.routing.AppRouter
+import com.tangem.tap.routing.ProxyAppRouter
+import com.tangem.tap.routing.configurator.AppRouterConfig
+import com.tangem.tap.routing.configurator.MutableAppRouterConfig
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal object AppRouterModule {
+
+ @Provides
+ @Singleton
+ fun provideAppRouter(config: AppRouterConfig, dispatchers: CoroutineDispatcherProvider): AppRouter =
+ ProxyAppRouter(config, dispatchers)
+
+ @Provides
+ @Singleton
+ fun provideAppRouterConfigurator(): AppRouterConfig = MutableAppRouterConfig()
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/di/routing/RoutingComponentModule.kt b/app/src/main/java/com/tangem/tap/di/routing/RoutingComponentModule.kt
new file mode 100644
index 0000000000..628d889d40
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/di/routing/RoutingComponentModule.kt
@@ -0,0 +1,18 @@
+package com.tangem.tap.di.routing
+
+import com.tangem.tap.routing.component.RoutingComponent
+import com.tangem.tap.routing.component.impl.DefaultRoutingComponent
+import dagger.Binds
+import dagger.Module
+import dagger.hilt.InstallIn
+import dagger.hilt.android.components.ActivityComponent
+import dagger.hilt.android.scopes.ActivityScoped
+
+@Module
+@InstallIn(ActivityComponent::class)
+internal interface RoutingComponentModule {
+
+ @Binds
+ @ActivityScoped
+ fun bindRoutingComponentFactory(factory: DefaultRoutingComponent.Factory): RoutingComponent.Factory
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/PayIdManager.kt b/app/src/main/java/com/tangem/tap/domain/PayIdManager.kt
deleted file mode 100644
index d66ac2ed73..0000000000
--- a/app/src/main/java/com/tangem/tap/domain/PayIdManager.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.tangem.tap.domain
-
-import com.tangem.blockchain.common.Blockchain
-import com.tangem.common.services.Result
-import com.tangem.tap.network.payid.PayIdVerifyService
-import com.tangem.tap.network.payid.VerifyPayIdResponse
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.withContext
-import java.util.*
-
-class PayIdManager {
-
- @Suppress("MagicNumber")
- suspend fun verifyPayId(
- payId: String,
- blockchain: Blockchain,
- ): Result = withContext(Dispatchers.IO) {
- val splitPayId = payId.split("\$")
- val user = splitPayId[0]
- val baseUrl = "https://${splitPayId[1]}/"
- return@withContext PayIdVerifyService(baseUrl).verifyAddress(user, blockchain.getPayIdNetwork())
- }
-
- private fun Blockchain.getPayIdNetwork(): String {
- return when (this) {
- Blockchain.XRP -> "XRPL"
- Blockchain.RSK -> "RSK"
- else -> this.currency
- }.lowercase(Locale.getDefault())
- }
-
- companion object {
- private val payIdRegExp = ("^[a-z0-9!#@%&*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#@%&*+/=?^_`{|}~-]+)*\\\$(?:(?:[a-z0-9]" +
- "(?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z-]*[a-z0-9])?|(?:[0-9]{1,3}\\.){3}[0-9]{1,3})\$").toRegex()
-
- val payIdSupported: EnumSet = EnumSet.of(
- Blockchain.XRP,
- Blockchain.Ethereum,
- Blockchain.Bitcoin,
- Blockchain.Litecoin,
- Blockchain.Stellar,
- Blockchain.Cardano,
- Blockchain.CardanoShelley,
- Blockchain.Ducatus,
- Blockchain.BitcoinCash,
- Blockchain.Binance,
- Blockchain.RSK,
- Blockchain.Tezos,
- )
-
- fun isPayId(value: String?): Boolean = value?.contains(payIdRegExp) ?: false
- }
-}
-
-fun Blockchain.isPayIdSupported(): Boolean {
- return PayIdManager.payIdSupported.contains(this)
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/RatesRepository.kt b/app/src/main/java/com/tangem/tap/domain/RatesRepository.kt
deleted file mode 100644
index 3d2a5764e2..0000000000
--- a/app/src/main/java/com/tangem/tap/domain/RatesRepository.kt
+++ /dev/null
@@ -1,74 +0,0 @@
-package com.tangem.tap.domain
-
-import com.tangem.common.services.Result
-import com.tangem.datasource.api.tangemTech.TangemTechApi
-import com.tangem.domain.common.ThrottlerWithValues
-import com.tangem.tap.features.wallet.models.Currency
-import com.tangem.utils.coroutines.CoroutineDispatcherProvider
-import kotlinx.coroutines.withContext
-import java.math.BigDecimal
-
-class RatesRepository(
- private val tangemTechApi: TangemTechApi,
- private val dispatchers: CoroutineDispatcherProvider,
-) {
- private val throttler = ThrottlerWithValues?>(60000)
-
- suspend fun loadFiatRate(currencyId: String, coinsList: List): Result =
- withContext(dispatchers.io) {
- // get and submit previous result of equivalents.
- val throttledResult = coinsList.filter { throttler.isStillThrottled(it) }.map {
- Pair(it, throttler.geValue(it))
- }
-
- val currenciesToUpdate = coinsList.filter { !throttler.isStillThrottled(it) }
- val coinIds = currenciesToUpdate.mapNotNull { it.coinId }.distinct()
- if (coinIds.isEmpty()) return@withContext handleFiatRatesResult(throttledResult.toMap())
-
- runCatching { tangemTechApi.getRates(currencyId.lowercase(), coinIds.joinToString(",")) }
- .onSuccess { response ->
- val ratesResultList: Map> = response.rates.mapValues {
- Result.Success(it.value.toBigDecimal())
- }
- val updatedCurrencies = throttledResult.toMap().toMutableMap()
- coinsList.forEach { currency ->
- ratesResultList[currency.coinId]?.let {
- updatedCurrencies[currency] = it
- throttler.updateThrottlingTo(currency)
- throttler.setValue(currency, it)
- }
- }
- return@withContext handleFiatRatesResult(updatedCurrencies)
- }
- .onFailure { Result.Failure(it) }
-
- error("Unreachable code because runCatching must return result")
- }
-
- private fun handleFiatRatesResult(rates: Map?>): Result.Success {
- val success = mutableMapOf()
- val failures = mutableMapOf()
-
- rates.mapNotNull { (currency, priceResult) ->
- when (priceResult) {
- is Result.Success -> success[currency] = priceResult.data
- is Result.Failure -> failures[currency] = priceResult.error
- else -> null
- }
- }
-
- return Result.Success(success to failures)
- }
-
- fun clear() {
- throttler.clear()
- }
-}
-
-typealias RatesResult = Pair, MutableMap>
-
-val RatesResult.loadedRates
- get() = this.first
-
-val RatesResult.failedRates
- get() = this.second
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt b/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt
deleted file mode 100644
index 288d399817..0000000000
--- a/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt
+++ /dev/null
@@ -1,252 +0,0 @@
-package com.tangem.tap.domain
-
-import android.content.Context
-import androidx.annotation.StringRes
-import com.tangem.Message
-import com.tangem.TangemSdk
-import com.tangem.blockchain.common.Blockchain
-import com.tangem.common.CardFilter
-import com.tangem.common.CompletionResult
-import com.tangem.common.SuccessResponse
-import com.tangem.common.UserCode
-import com.tangem.common.UserCodeType
-import com.tangem.common.biometric.BiometricManager
-import com.tangem.common.card.FirmwareVersion
-import com.tangem.common.core.CardIdDisplayFormat
-import com.tangem.common.core.CardSessionRunnable
-import com.tangem.common.core.Config
-import com.tangem.common.core.TangemSdkError
-import com.tangem.common.core.UserCodeRequestPolicy
-import com.tangem.common.extensions.ByteArrayKey
-import com.tangem.common.hdWallet.DerivationPath
-import com.tangem.common.map
-import com.tangem.common.usersCode.UserCodeRepository
-import com.tangem.core.analytics.Analytics
-import com.tangem.domain.common.CardDTO
-import com.tangem.domain.common.ScanResponse
-import com.tangem.operations.CommandResponse
-import com.tangem.operations.ScanTask
-import com.tangem.operations.derivation.DerivationTaskResponse
-import com.tangem.operations.derivation.DeriveMultipleWalletPublicKeysTask
-import com.tangem.operations.pins.CheckUserCodesCommand
-import com.tangem.operations.pins.CheckUserCodesResponse
-import com.tangem.operations.pins.SetUserCodeCommand
-import com.tangem.tap.common.analytics.events.Basic
-import com.tangem.tap.domain.tasks.CreateWalletAndRescanTask
-import com.tangem.tap.domain.tasks.product.CreateProductWalletTask
-import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse
-import com.tangem.tap.domain.tasks.product.ResetToFactorySettingsTask
-import com.tangem.tap.domain.tasks.product.ScanProductTask
-import com.tangem.tap.domain.tokens.UserTokensRepository
-import com.tangem.wallet.R
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.isActive
-import kotlinx.coroutines.withContext
-import kotlin.coroutines.resume
-import kotlin.coroutines.suspendCoroutine
-
-class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Context) {
-
- private val userCodeRepository by lazy {
- UserCodeRepository(
- biometricManager = tangemSdk.biometricManager,
- secureStorage = tangemSdk.secureStorage,
- )
- }
-
- val canUseBiometry: Boolean
- get() = tangemSdk.biometricManager.canAuthenticate || needEnrollBiometrics
-
- val needEnrollBiometrics: Boolean
- get() = tangemSdk.biometricManager.canEnrollBiometrics
-
- val biometricManager: BiometricManager
- get() = tangemSdk.biometricManager
-
- suspend fun scanProduct(
- userTokensRepository: UserTokensRepository,
- cardId: String? = null,
- additionalBlockchainsToDerive: Collection? = null,
- messageRes: Int? = null,
- ): CompletionResult {
- val message = Message(context.getString(messageRes ?: R.string.initial_message_scan_header))
- return runTaskAsyncReturnOnMain(
- runnable = ScanProductTask(
- card = null,
- userTokensRepository = userTokensRepository,
- additionalBlockchainsToDerive = additionalBlockchainsToDerive,
- ),
- cardId = cardId,
- initialMessage = message,
- ).also { sendScanResultsToAnalytics(it) }
- }
-
- suspend fun createProductWallet(
- scanResponse: ScanResponse,
- ): CompletionResult {
- return runTaskAsync(
- CreateProductWalletTask(scanResponse.cardTypesResolver),
- scanResponse.card.cardId,
- Message(context.getString(R.string.initial_message_create_wallet_body)),
- )
- }
-
- private fun sendScanResultsToAnalytics(
- result: CompletionResult,
- ) {
- if (result is CompletionResult.Failure) {
- (result.error as? TangemSdkError)?.let { error ->
- Analytics.send(Basic.ScanError(error))
- }
- }
- }
-
- suspend fun createWallet(cardId: String?): CompletionResult {
- return runTaskAsyncReturnOnMain(
- CreateWalletAndRescanTask(),
- cardId,
- initialMessage = Message(context.getString(R.string.initial_message_create_wallet_body)),
- )
- .map { CardDTO(it) }
- }
-
- suspend fun derivePublicKeys(
- cardId: String,
- derivations: Map>,
- ): CompletionResult {
- return runTaskAsyncReturnOnMain(DeriveMultipleWalletPublicKeysTask(derivations), cardId)
- }
-
- suspend fun resetToFactorySettings(cardId: String): CompletionResult {
- return runTaskAsyncReturnOnMain(
- runnable = ResetToFactorySettingsTask(),
- cardId = cardId,
- initialMessage = Message(context.getString(R.string.card_settings_reset_card_to_factory)),
- )
- .map { CardDTO(it) }
- }
-
- suspend fun saveAccessCode(accessCode: String, cardsIds: Set): CompletionResult {
- return userCodeRepository.save(
- cardsIds = cardsIds,
- userCode = UserCode(
- type = UserCodeType.AccessCode,
- stringValue = accessCode,
- ),
- )
- }
-
- suspend fun deleteSavedUserCodes(cardsIds: Set): CompletionResult {
- return userCodeRepository.delete(cardsIds.toSet())
- }
-
- suspend fun clearSavedUserCodes(): CompletionResult {
- return userCodeRepository.clear()
- }
-
- suspend fun setPasscode(cardId: String?): CompletionResult {
- return runTaskAsyncReturnOnMain(
- SetUserCodeCommand.changePasscode(null),
- cardId,
- initialMessage = Message(context.getString(R.string.initial_message_change_passcode_body)),
- )
- }
-
- suspend fun setAccessCode(cardId: String?): CompletionResult {
- return runTaskAsyncReturnOnMain(
- SetUserCodeCommand.changeAccessCode(null),
- cardId,
- initialMessage = Message(context.getString(R.string.initial_message_change_access_code_body)),
- )
- }
-
- suspend fun setLongTap(cardId: String?): CompletionResult {
- return runTaskAsyncReturnOnMain(
- SetUserCodeCommand.resetUserCodes(),
- cardId,
- initialMessage = Message(context.getString(R.string.initial_message_tap_header)),
- )
- }
-
- suspend fun checkUserCodes(cardId: String?): CompletionResult {
- return runTaskAsyncReturnOnMain(
- CheckUserCodesCommand(),
- cardId,
- initialMessage = Message(context.getString(R.string.initial_message_tap_header)),
- )
- }
-
- suspend fun scanCard(
- cardId: String? = null,
- allowRequestAccessCodeFromRepository: Boolean = false,
- ): CompletionResult {
- return runTaskAsyncReturnOnMain(
- runnable = ScanTask(allowRequestAccessCodeFromRepository),
- cardId = cardId,
- initialMessage = Message(context.getString(R.string.initial_message_tap_header)),
- )
- .map { CardDTO(it) }
- }
-
- suspend fun runTaskAsync(
- runnable: CardSessionRunnable,
- cardId: String? = null,
- initialMessage: Message? = null,
- accessCode: String? = null,
- ): CompletionResult =
- withContext(Dispatchers.Main) {
- suspendCoroutine { continuation ->
- tangemSdk.startSessionWithRunnable(runnable, cardId, initialMessage, accessCode) { result ->
- if (continuation.context.isActive) continuation.resume(result)
- }
- }
- }
-
- private suspend fun runTaskAsyncReturnOnMain(
- runnable: CardSessionRunnable,
- cardId: String? = null,
- initialMessage: Message? = null,
- ): CompletionResult {
- val result = runTaskAsync(runnable, cardId, initialMessage)
- return withContext(Dispatchers.Main) { result }
- }
-
- @Suppress("MagicNumber")
- fun changeDisplayedCardIdNumbersCount(scanResponse: ScanResponse?) {
- tangemSdk.config.cardIdDisplayFormat = when {
- scanResponse == null -> CardIdDisplayFormat.Full
- scanResponse.cardTypesResolver.isTangemTwins() -> CardIdDisplayFormat.LastLuhn(4)
- scanResponse.cardTypesResolver.isSaltPay() -> CardIdDisplayFormat.None
- else -> CardIdDisplayFormat.Full
- }
- }
-
- fun getString(@StringRes stringResId: Int, vararg formatArgs: Any?): String {
- return context.getString(stringResId, *formatArgs)
- }
-
- fun setAccessCodeRequestPolicy(
- useBiometricsForAccessCode: Boolean,
- ) {
- tangemSdk.config.userCodeRequestPolicy = if (useBiometricsForAccessCode) {
- UserCodeRequestPolicy.AlwaysWithBiometrics(codeType = UserCodeType.AccessCode)
- } else {
- UserCodeRequestPolicy.Default
- }
- }
-
- fun useBiometricsForAccessCode(): Boolean {
- val policy = tangemSdk.config.userCodeRequestPolicy
- return policy is UserCodeRequestPolicy.AlwaysWithBiometrics && policy.codeType == UserCodeType.AccessCode
- }
-
- companion object {
- val config = Config(
- linkedTerminal = true,
- allowUntrustedCards = true,
- filter = CardFilter(
- allowedCardTypes = FirmwareVersion.FirmwareType.values().toList(),
- ),
- )
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/TangemSigner.kt b/app/src/main/java/com/tangem/tap/domain/TangemSigner.kt
index 1979b1df8a..7f5f095079 100644
--- a/app/src/main/java/com/tangem/tap/domain/TangemSigner.kt
+++ b/app/src/main/java/com/tangem/tap/domain/TangemSigner.kt
@@ -5,57 +5,58 @@ import com.tangem.TangemSdk
import com.tangem.blockchain.common.TransactionSigner
import com.tangem.blockchain.common.Wallet
import com.tangem.common.CompletionResult
-import com.tangem.domain.common.CardDTO
+import com.tangem.domain.card.models.TwinKey
+import com.tangem.domain.models.scan.isRing
import com.tangem.tap.domain.tasks.SignHashesTask
+import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.resume
-import kotlin.coroutines.suspendCoroutine
class TangemSigner(
- private val card: CardDTO,
+ private val cardId: String?,
private val tangemSdk: TangemSdk,
private val initialMessage: Message,
- private val accessCode: String? = null,
+ private val twinKey: TwinKey?,
private val signerCallback: (TangemSignerResponse) -> Unit,
) : TransactionSigner {
override suspend fun sign(
hashes: List,
- publicKey: Wallet.PublicKey
+ publicKey: Wallet.PublicKey,
): CompletionResult> {
- return suspendCoroutine { continuation ->
- val cardId = if (card.backupStatus?.isActive == true) null else card.cardId
+ return suspendCancellableCoroutine { continuation ->
+ val task = SignHashesTask(hashes, publicKey, twinKey?.getPairKey(publicKey.seedKey))
- val task = SignHashesTask(hashes, publicKey)
tangemSdk.startSessionWithRunnable(
runnable = task,
cardId = cardId,
initialMessage = initialMessage,
- accessCode = accessCode,
) { result ->
when (result) {
is CompletionResult.Success -> {
signerCallback(
TangemSignerResponse(
- result.data.totalSignedHashes,
- result.data.remainingSignatures
- )
+ totalSignedHashes = result.data.totalSignedHashes,
+ remainingSignatures = result.data.remainingSignatures,
+ isRing = result.data.batchId?.let(::isRing) ?: false,
+ ),
)
- continuation.resume(CompletionResult.Success(result.data.signatures))
+ if (continuation.isActive) {
+ continuation.resume(CompletionResult.Success(result.data.signatures))
+ }
}
is CompletionResult.Failure ->
- continuation.resume(CompletionResult.Failure(result.error))
+ if (continuation.isActive) {
+ continuation.resume(CompletionResult.Failure(result.error))
+ }
}
}
}
}
- override suspend fun sign(
- hash: ByteArray,
- publicKey: Wallet.PublicKey
- ): CompletionResult {
+ override suspend fun sign(hash: ByteArray, publicKey: Wallet.PublicKey): CompletionResult {
val result = sign(
hashes = listOf(hash),
- publicKey = publicKey
+ publicKey = publicKey,
)
return when (result) {
@@ -68,4 +69,5 @@ class TangemSigner(
data class TangemSignerResponse(
val totalSignedHashes: Int?,
val remainingSignatures: Int?,
+ val isRing: Boolean,
)
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/TapErrors.kt b/app/src/main/java/com/tangem/tap/domain/TapErrors.kt
index b0ee231286..1fc37a0267 100644
--- a/app/src/main/java/com/tangem/tap/domain/TapErrors.kt
+++ b/app/src/main/java/com/tangem/tap/domain/TapErrors.kt
@@ -22,50 +22,21 @@ sealed class TapError(
object UnknownError : TapError(R.string.send_error_unknown)
open class CustomError(val customMessage: String) : TapError(R.string.common_custom_string, listOf(customMessage))
- object ScanCardError : TapError(R.string.scan_card_error)
- object UnknownBlockchain : TapError(R.string.wallet_error_unsupported_blockchain_subtitle)
+
object NoInternetConnection : TapError(R.string.wallet_notification_no_internet)
- object BlockchainInternalError : TapError(R.string.send_error_blockchain_internal)
- object AmountExceedsBalance : TapError(R.string.send_validation_amount_exceeds_balance)
- data class AmountLowerExistentialDeposit(
- override val args: List,
- ) : TapError(R.string.send_error_minimum_balance_format)
-
- object FeeExceedsBalance : TapError(R.string.send_validation_invalid_fee)
- object TotalExceedsBalance : TapError(R.string.send_validation_invalid_total)
- object InvalidAmountValue : TapError(R.string.send_validation_invalid_amount)
- object InvalidFeeValue : TapError(R.string.send_error_invalid_fee_value)
- data class DustAmount(override val args: List) : TapError(R.string.send_error_dust_amount_format)
- object DustChange : TapError(R.string.send_error_dust_change)
-
- data class UnsupportedState(
- val stateError: String,
- val customMessage: String = "Unsupported state:",
- ) : TapError(R.string.common_custom_string, listOf("$customMessage $stateError"))
sealed class WalletManager {
- object CreationError : CustomError("Can't create wallet manager")
class NoAccountError(amountToCreateAccount: String) : CustomError(amountToCreateAccount)
class InternalError(message: String) : CustomError(message)
object BlockchainIsUnreachableTryLater : TapError(R.string.wallet_balance_blockchain_unreachable_try_later)
}
-
- sealed class WalletConnect {
- object UnsupportedDapp : TapError(R.string.wallet_connect_error_unsupported_dapp)
- object UnsupportedLink : TapError(R.string.wallet_connect_error_failed_to_connect)
- }
-
- data class ValidateTransactionErrors(
- override val errorList: List,
- override val builder: (List) -> String,
- ) : TapError(-1), MultiMessageError
}
sealed class TapSdkError(override val messageResId: Int?) : TangemError(code = 50100) {
override var customMessage: String = code.toString()
object CardForDifferentApp : TapSdkError(R.string.alert_unsupported_card)
- object CardNotSupportedByRelease : TapSdkError(R.string.error_update_app)
+ object CardNotSupportedByRelease : TapSdkError(R.string.error_wrong_card_type)
}
fun TapErrors.assembleErrors(): MutableList?>> {
diff --git a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt
index dd13b37e8d..8225f9014c 100644
--- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt
+++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt
@@ -1,320 +1,51 @@
package com.tangem.tap.domain
-import com.tangem.blockchain.common.Blockchain
-import com.tangem.blockchain.common.BlockchainSdkConfig
import com.tangem.blockchain.common.Token
import com.tangem.blockchain.common.Wallet
-import com.tangem.blockchain.common.WalletManager
-import com.tangem.blockchain.common.WalletManagerFactory
-import com.tangem.common.doOnFailure
-import com.tangem.common.doOnSuccess
-import com.tangem.common.services.Result
-import com.tangem.domain.common.CardDTO
-import com.tangem.domain.common.ScanResponse
-import com.tangem.domain.common.TapWorkarounds.isTestCard
-import com.tangem.domain.common.ThrottlerWithValues
+import com.tangem.core.analytics.Analytics
import com.tangem.domain.common.extensions.withMainContext
-import com.tangem.operations.attestation.Attestation
-import com.tangem.tap.common.extensions.dispatchOnMain
-import com.tangem.tap.common.extensions.safeUpdate
+import com.tangem.domain.wallets.models.UserWallet
+import com.tangem.tap.common.extensions.setContext
import com.tangem.tap.common.redux.global.GlobalAction
-import com.tangem.tap.domain.configurable.config.ConfigManager
-import com.tangem.tap.domain.extensions.makePrimaryWalletManager
-import com.tangem.tap.domain.extensions.makeWalletManagersForApp
-import com.tangem.tap.domain.model.UserWallet
-import com.tangem.tap.domain.tokens.models.BlockchainNetwork
-import com.tangem.tap.domain.walletStores.WalletStoresError
-import com.tangem.tap.features.demo.isDemoCard
-import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction
-import com.tangem.tap.features.wallet.models.toBlockchainNetworks
-import com.tangem.tap.features.wallet.redux.WalletAction
-import com.tangem.tap.features.wallet.redux.middlewares.handleBasicAnalyticsEvent
-import com.tangem.tap.network.NetworkConnectivity
import com.tangem.tap.store
import com.tangem.tap.tangemSdkManager
-import com.tangem.tap.userTokensRepository
-import com.tangem.tap.walletStoresManager
import com.tangem.utils.coroutines.AppCoroutineDispatcherProvider
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.withContext
-import timber.log.Timber
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.launch
-class TapWalletManager {
- val walletManagerFactory: WalletManagerFactory
- by lazy { WalletManagerFactory(blockchainSdkConfig) }
+class TapWalletManager(
+ private val dispatchers: CoroutineDispatcherProvider = AppCoroutineDispatcherProvider(),
+) {
- // TODO("After adding DI") get dependencies by DI
- val rates: RatesRepository by lazy {
- RatesRepository(
- tangemTechApi = store.state.domainNetworks.tangemTechService.api,
- dispatchers = AppCoroutineDispatcherProvider(),
- )
- }
-
- private val blockchainSdkConfig by lazy {
- store.state.globalState.configManager?.config?.blockchainSdkConfig ?: BlockchainSdkConfig()
- }
-
- private val walletManagersThrottler =
- ThrottlerWithValues>(10000)
-
- suspend fun loadWalletData(walletManager: WalletManager) {
- val blockchainNetwork = BlockchainNetwork.fromWalletManager(walletManager)
- val result = if (walletManagersThrottler.isStillThrottled(blockchainNetwork)) {
- walletManagersThrottler.geValue(blockchainNetwork)!!
- } else {
- val safeUpdateResult = walletManager.safeUpdate()
- walletManagersThrottler.updateThrottlingTo(blockchainNetwork)
- walletManagersThrottler.setValue(blockchainNetwork, safeUpdateResult)
- safeUpdateResult
- }
- when (result) {
- is Result.Success -> {
- dispatchOnMain(WalletAction.LoadWallet.Success(result.data, blockchainNetwork))
- }
- is Result.Failure -> {
- when (result.error) {
- is TapError.WalletManager.NoAccountError -> {
- dispatchOnMain(
- WalletAction.LoadWallet.NoAccount(
- walletManager.wallet,
- blockchainNetwork,
- (result.error as TapError.WalletManager.NoAccountError).customMessage,
- ),
- )
- }
- else -> {
- dispatchOnMain(
- WalletAction.LoadWallet.Failure(
- walletManager.wallet,
- result.error.localizedMessage,
- ),
- )
- }
- }
- }
+ private var loadUserWalletDataJob: Job? = null
+ set(value) {
+ field?.cancel()
+ field = value
}
+
+ suspend fun onWalletSelected(userWallet: UserWallet) {
+ // If a previous job was running, it gets cancelled before the new one starts,
+ // ensuring that only one job is active at any given time.
+ loadUserWalletDataJob = CoroutineScope(dispatchers.io)
+ .launch { loadUserWalletData(userWallet) }
+ .also { it.join() }
}
- suspend fun onWalletSelected(userWallet: UserWallet, refresh: Boolean) {
+ private suspend fun loadUserWalletData(userWallet: UserWallet) {
+ Analytics.setContext(userWallet.scanResponse)
val scanResponse = userWallet.scanResponse
- val card = scanResponse.card
- val attestationFailed = card.attestation.status == Attestation.Status.Failed
tangemSdkManager.changeDisplayedCardIdNumbersCount(scanResponse)
- store.state.globalState.feedbackManager?.infoHolder?.setCardInfo(scanResponse)
- updateConfigManager(scanResponse)
withMainContext {
- store.dispatch(WalletAction.UserWalletChanged(userWallet))
+ // Order is important
store.dispatch(TwinCardsAction.IfTwinsPrepareState(scanResponse))
- store.dispatch(WalletConnectAction.ResetState)
store.dispatch(GlobalAction.SaveScanResponse(scanResponse))
- store.dispatch(WalletConnectAction.RestoreSessions(scanResponse))
- store.dispatch(GlobalAction.SetIfCardVerifiedOnline(!attestationFailed))
- store.dispatch(WalletAction.Warnings.CheckIfNeeded)
- }
-
- loadData(userWallet, refresh)
- }
-
- suspend fun loadData(userWallet: UserWallet, refresh: Boolean = false) {
- walletStoresManager.fetch(userWallet, refresh)
- .doOnSuccess {
- Timber.d("Wallet stores fetched for ${userWallet.walletId}")
- store.dispatchOnMain(WalletAction.LoadData.Success)
- handleBasicAnalyticsEvent()
- }
- .doOnFailure { error ->
- val errorAction = when (error) {
- is WalletStoresError -> when (error) {
- is WalletStoresError.FetchFiatRatesError,
- is WalletStoresError.UpdateWalletManagerError,
- -> WalletAction.LoadData.Failure(error = null)
- is WalletStoresError.WalletManagerNotCreated -> WalletAction.LoadData.Failure(
- error = TapError.WalletManager.CreationError,
- )
- is WalletStoresError.UnknownBlockchain -> WalletAction.LoadData.Failure(
- error = TapError.UnknownBlockchain,
- )
- is WalletStoresError.NoInternetConnection -> WalletAction.LoadData.Failure(
- error = TapError.NoInternetConnection,
- )
- }
- else -> WalletAction.LoadData.Failure(error = null)
- }
-
- Timber.e(error, "Wallet stores fetching failed for ${userWallet.walletId}")
-
- store.dispatchOnMain(errorAction)
- }
- }
-
- suspend fun onCardScanned(data: ScanResponse) {
- walletManagersThrottler.clear()
- store.state.globalState.feedbackManager?.infoHolder?.setCardInfo(data)
- updateConfigManager(data)
-
- withMainContext {
- store.dispatch(WalletAction.ResetState(data.card))
- store.dispatch(WalletConnectAction.ResetState)
- store.dispatch(GlobalAction.SaveScanResponse(data))
- store.dispatch(WalletAction.SetIfTestnetCard(data.card.isTestCard))
- store.dispatch(
- WalletAction.MultiWallet.SetIsMultiwalletAllowed(
- data.cardTypesResolver.isMultiwalletAllowed(),
- ),
- )
- store.dispatch(WalletConnectAction.RestoreSessions(data))
- store.dispatch(
- WalletAction.MultiWallet.ShowWalletBackupWarning(
- show = data.card.settings.isBackupAllowed &&
- data.card.backupStatus == CardDTO.BackupStatus.NoBackup,
- ),
- )
- loadData(data)
- }
- }
-
- fun updateConfigManager(data: ScanResponse) {
- val configManager = store.state.globalState.configManager
- val blockchain = data.cardTypesResolver.getBlockchain()
- if (data.cardTypesResolver.isStart2Coin()) {
- configManager?.turnOff(ConfigManager.isSendingToPayIdEnabled)
- configManager?.turnOff(ConfigManager.isTopUpEnabled)
- } else if (blockchain == Blockchain.Bitcoin ||
- data.walletData?.blockchain == Blockchain.Bitcoin.id
- ) {
- configManager?.resetToDefault(ConfigManager.isSendingToPayIdEnabled)
- configManager?.resetToDefault(ConfigManager.isTopUpEnabled)
- } else {
- configManager?.resetToDefault(ConfigManager.isSendingToPayIdEnabled)
- configManager?.resetToDefault(ConfigManager.isTopUpEnabled)
- }
- }
-
- suspend fun loadData(data: ScanResponse) {
- dispatchOnMain(WalletAction.LoadCardInfo(data.card))
- getActionIfUnknownBlockchainOrEmptyWallet(data)?.let {
- dispatchOnMain(it)
- return
- }
-
- if (data.cardTypesResolver.isMultiwalletAllowed()) {
- dispatchOnMain(WalletAction.MultiWallet.ScheduleCheckForMissingDerivation)
- loadMultiWalletData(data)
- } else {
- loadSingleWalletData(data)
- }
-
- dispatchOnMain(WalletAction.LoadWallet())
- }
-
- private suspend fun loadMultiWalletData(scanResponse: ScanResponse) {
- loadUserCurrencies(scanResponse, walletManagerFactory)
- }
-
- private fun checkIfDerivationsAreMissing(blockchainNetworks: List