Updated on 2026-08-14
This commit is contained in:
commit
b645b447e9
37 changed files with 392 additions and 414 deletions
|
|
@ -93,7 +93,7 @@ dependencies {
|
|||
implementation 'com.google.android.play:core-ktx:1.8.1'
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
||||
|
||||
implementation 'com.tangem:blockchain:develop-88'
|
||||
implementation 'com.tangem:blockchain:develop-90'
|
||||
// implementation 'com.tangem:blockchain:0.0.1'
|
||||
implementation 'com.tangem.tangem-sdk-kotlin:core:develop-154'
|
||||
implementation 'com.tangem.tangem-sdk-kotlin:android:develop-154'
|
||||
|
|
@ -118,8 +118,9 @@ dependencies {
|
|||
// Camera
|
||||
implementation 'com.otaliastudios:cameraview:2.6.3'
|
||||
|
||||
// Image Loading - Picasso
|
||||
implementation 'com.squareup.picasso:picasso:2.71828'
|
||||
// Image Loading
|
||||
implementation 'io.coil-kt:coil:2.1.0'
|
||||
implementation 'io.coil-kt:coil-compose:2.1.0'
|
||||
|
||||
// Firebase
|
||||
implementation platform('com.google.firebase:firebase-bom:26.0.0')
|
||||
|
|
@ -172,9 +173,6 @@ dependencies {
|
|||
|
||||
implementation "com.github.skydoves:androidveil:1.1.2"
|
||||
|
||||
implementation("io.coil-kt:coil:2.0.0-rc01")
|
||||
implementation("io.coil-kt:coil-compose:2.0.0-rc01")
|
||||
|
||||
implementation 'com.github.kirich1409:viewbindingpropertydelegate-noreflection:1.5.6'
|
||||
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 64ae04d2086e5a605dd4da3cba4af32a60d46c79
|
||||
Subproject commit f50133547b5e19fb7ad32e64370573d60f6791fd
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
package com.tangem.tap
|
||||
|
||||
import android.app.Application
|
||||
import coil.ImageLoader
|
||||
import coil.ImageLoaderFactory
|
||||
import com.appsflyer.AppsFlyerLib
|
||||
import com.google.firebase.ktx.Firebase
|
||||
import com.google.firebase.remoteconfig.ktx.remoteConfig
|
||||
|
|
@ -10,7 +12,7 @@ import com.tangem.blockchain.network.BlockchainSdkRetrofitBuilder
|
|||
import com.tangem.domain.DomainLayer
|
||||
import com.tangem.network.common.MoshiConverter
|
||||
import com.tangem.tap.common.analytics.GlobalAnalyticsHandler
|
||||
import com.tangem.tap.common.images.PicassoHelper
|
||||
import com.tangem.tap.common.images.createCoilImageLoader
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.appReducer
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
|
|
@ -43,7 +45,7 @@ lateinit var currenciesRepository: CurrenciesRepository
|
|||
lateinit var walletConnectRepository: WalletConnectRepository
|
||||
lateinit var shopService: TangemShopService
|
||||
|
||||
class TapApplication : Application() {
|
||||
class TapApplication : Application(), ImageLoaderFactory {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
|
|
@ -61,7 +63,6 @@ class TapApplication : Application() {
|
|||
|
||||
NetworkConnectivity.createInstance(store, this)
|
||||
preferencesStorage = PreferencesStorage(this)
|
||||
PicassoHelper.initPicassoWithCaching(this)
|
||||
currenciesRepository = CurrenciesRepository(
|
||||
this, store.state.domainNetworks.tangemTechService
|
||||
)
|
||||
|
|
@ -75,6 +76,10 @@ class TapApplication : Application() {
|
|||
initAppsFlyer()
|
||||
}
|
||||
|
||||
override fun newImageLoader(): ImageLoader {
|
||||
return createCoilImageLoader(context = this)
|
||||
}
|
||||
|
||||
private fun loadConfigs() {
|
||||
val moshi = MoshiConverter.defaultMoshi()
|
||||
val localLoader = FeaturesLocalLoader(this, moshi)
|
||||
|
|
@ -108,11 +113,6 @@ class TapApplication : Application() {
|
|||
}
|
||||
|
||||
data class LogConfig(
|
||||
// disables both [internal, http]
|
||||
val picasso: Boolean = BuildConfig.DEBUG,
|
||||
val picassoInternal: Boolean = true,
|
||||
val picassoHttp: Boolean = true,
|
||||
|
||||
val coil: Boolean = BuildConfig.DEBUG,
|
||||
val storeAction: Boolean = BuildConfig.DEBUG,
|
||||
|
||||
)
|
||||
|
|
@ -62,6 +62,7 @@ fun Blockchain.getNetworkName(): String {
|
|||
Blockchain.Ethereum, Blockchain.EthereumTestnet -> "ERC20"
|
||||
Blockchain.BSC, Blockchain.BSCTestnet -> "BEP20"
|
||||
Blockchain.Binance, Blockchain.BinanceTestnet -> "BEP2"
|
||||
Blockchain.Tron, Blockchain.TronTestnet -> "TRC20"
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,135 +0,0 @@
|
|||
package com.tangem.tap.common.extensions
|
||||
|
||||
import android.graphics.*
|
||||
import android.widget.TextView
|
||||
import androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
import com.squareup.picasso.Callback
|
||||
import com.squareup.picasso.Picasso
|
||||
import com.squareup.picasso.Transformation
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.IconsUtil
|
||||
import com.tangem.blockchain.common.Token
|
||||
import com.tangem.domain.common.extensions.toNetworkId
|
||||
import com.tangem.tap.domain.extensions.getCustomIconUrl
|
||||
import com.tangem.tap.domain.tokens.getIconUrl
|
||||
import com.tangem.wallet.R
|
||||
|
||||
fun Picasso.loadCurrenciesIcon(
|
||||
imageView: ImageFilterView,
|
||||
textView: TextView,
|
||||
token: Token? = null,
|
||||
blockchain: Blockchain,
|
||||
) {
|
||||
|
||||
val url: String? = if (token != null) {
|
||||
token.id?.let { getIconUrl(it) } ?: token.getCustomIconUrl()
|
||||
?: IconsUtil.getTokenIconUri(blockchain, token)?.toString()
|
||||
} else {
|
||||
getIconUrl(blockchain.toNetworkId())
|
||||
}
|
||||
|
||||
imageView.setImageDrawable(null)
|
||||
imageView.colorFilter = null
|
||||
textView.text = null
|
||||
|
||||
when {
|
||||
token?.symbol == QCX -> {
|
||||
this.load(R.drawable.ic_qcx)?.into(imageView)
|
||||
}
|
||||
token?.symbol == VOYR -> {
|
||||
this.load(R.drawable.ic_voyr)?.into(imageView)
|
||||
}
|
||||
url != null -> {
|
||||
if (token != null) {
|
||||
setTokenImage(imageView, textView, token, blockchain)
|
||||
}
|
||||
this.load(url)
|
||||
.transform(RoundedCornersTransform())
|
||||
.noPlaceholder()
|
||||
?.into(imageView,
|
||||
object : Callback {
|
||||
override fun onError(e: Exception?) {
|
||||
setOfflineCurrencyImage(imageView, textView, token, blockchain)
|
||||
}
|
||||
|
||||
override fun onSuccess() {
|
||||
if (token != null) {
|
||||
imageView.colorFilter = null
|
||||
textView.text = null
|
||||
}
|
||||
if (blockchain.isTestnet()) imageView.saturation = 0f
|
||||
}
|
||||
})
|
||||
}
|
||||
else -> {
|
||||
setOfflineCurrencyImage(imageView, textView, token, blockchain)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private const val QCX = "QCX"
|
||||
private const val VOYR = "VOYRME"
|
||||
|
||||
private fun setOfflineCurrencyImage(
|
||||
imageView: ImageFilterView,
|
||||
textView: TextView,
|
||||
token: Token?,
|
||||
blockchain: Blockchain,
|
||||
) {
|
||||
when (token) {
|
||||
null -> setBlockchainImage(imageView, textView, blockchain)
|
||||
else -> setTokenImage(imageView, textView, token, blockchain)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setBlockchainImage(
|
||||
imageView: ImageFilterView,
|
||||
textView: TextView,
|
||||
blockchain: Blockchain,
|
||||
) {
|
||||
imageView.setImageResource(blockchain.getRoundIconRes())
|
||||
imageView.colorFilter = null
|
||||
if (blockchain.isTestnet()) imageView.saturation = 0f
|
||||
textView.text = null
|
||||
}
|
||||
|
||||
private fun setTokenImage(
|
||||
imageView: ImageFilterView,
|
||||
textView: TextView,
|
||||
token: Token,
|
||||
tokenBlockchain: Blockchain
|
||||
) {
|
||||
imageView.setImageResource(R.drawable.shape_circle)
|
||||
if (tokenBlockchain.isTestnet()) {
|
||||
imageView.saturation = 0f
|
||||
} else {
|
||||
imageView.setColorFilter(token.getColor())
|
||||
}
|
||||
textView.text = token.symbol.take(1)
|
||||
}
|
||||
|
||||
private class RoundedCornersTransform : Transformation {
|
||||
|
||||
override fun transform(source: Bitmap): Bitmap {
|
||||
val size = source.width.coerceAtMost(source.height)
|
||||
val x = (source.width - size) / 2
|
||||
val y = (source.height - size) / 2
|
||||
val squaredBitmap = Bitmap.createBitmap(source, x, y, size, size)
|
||||
if (squaredBitmap != source) source.recycle()
|
||||
|
||||
val paint = Paint().apply {
|
||||
shader = BitmapShader(squaredBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
|
||||
isAntiAlias = true
|
||||
}
|
||||
|
||||
val rectF = RectF(0f, 0f, source.width.toFloat(), source.height.toFloat())
|
||||
val radius = size / 8f
|
||||
val bitmap = Bitmap.createBitmap(size, size, source.config)
|
||||
Canvas(bitmap).drawRoundRect(rectF, radius, radius, paint)
|
||||
squaredBitmap.recycle()
|
||||
|
||||
return bitmap
|
||||
}
|
||||
|
||||
override fun key(): String = "rounded_corners"
|
||||
}
|
||||
|
|
@ -53,8 +53,7 @@ fun BigDecimal.toFiatString(
|
|||
fiatCurrencyName: String,
|
||||
formatWithSpaces: Boolean = false
|
||||
): String {
|
||||
var fiatValue = rateValue.multiply(this)
|
||||
fiatValue = fiatValue.setScale(2, RoundingMode.HALF_UP)
|
||||
val fiatValue = rateValue.multiply(this)
|
||||
return fiatValue.toFormattedFiatValue(fiatCurrencyName, formatWithSpaces)
|
||||
}
|
||||
|
||||
|
|
@ -67,7 +66,8 @@ fun BigDecimal.toFormattedFiatValue(
|
|||
fiatCurrencyName: String,
|
||||
formatWithSpaces: Boolean = false
|
||||
): String {
|
||||
val fiatValue = if (formatWithSpaces) this.formatWithSpaces() else this
|
||||
val fiatValue = this.setScale(2, RoundingMode.HALF_UP)
|
||||
.let { if (formatWithSpaces) it.formatWithSpaces() else it }
|
||||
return " ${fiatValue} $fiatCurrencyName"
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
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
|
||||
import com.tangem.wallet.R
|
||||
|
|
@ -9,8 +11,13 @@ import com.tangem.wallet.R
|
|||
fun Token.getColor(): Int {
|
||||
return try {
|
||||
("#" + this.contractAddress.subSequence(2..7).toString())
|
||||
.toColorInt()
|
||||
.toColorInt()
|
||||
} catch (exception: Exception) {
|
||||
R.color.lightGray4
|
||||
}
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
fun Token.getTextColor(): Int {
|
||||
return if (this.getColor().luminance > 0.5) Color.BLACK else Color.WHITE
|
||||
}
|
||||
50
app/src/main/java/com/tangem/tap/common/images/Coil.kt
Normal file
50
app/src/main/java/com/tangem/tap/common/images/Coil.kt
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
package com.tangem.tap.common.images
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import coil.ImageLoader
|
||||
import coil.util.Logger
|
||||
import com.tangem.tap.logConfig
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import timber.log.Timber
|
||||
|
||||
private const val COIL_LOG_TAG = "COIL"
|
||||
|
||||
fun createCoilImageLoader(
|
||||
context: Context
|
||||
): ImageLoader {
|
||||
return ImageLoader.Builder(context)
|
||||
.apply {
|
||||
if (!logConfig.coil) return@apply
|
||||
|
||||
logger(CoilTimberLogger())
|
||||
okHttpClient {
|
||||
OkHttpClient.Builder()
|
||||
.addNetworkInterceptor(
|
||||
HttpLoggingInterceptor { message ->
|
||||
Timber.tag(COIL_LOG_TAG).d(message)
|
||||
}
|
||||
.apply {
|
||||
level = HttpLoggingInterceptor.Level.BODY
|
||||
}
|
||||
)
|
||||
.build()
|
||||
|
||||
}
|
||||
}
|
||||
.build()
|
||||
}
|
||||
|
||||
|
||||
private class CoilTimberLogger : Logger {
|
||||
|
||||
override var level: Int = Log.DEBUG
|
||||
|
||||
override fun log(tag: String, priority: Int, message: String?, throwable: Throwable?) {
|
||||
with(Timber.tag(COIL_LOG_TAG)) {
|
||||
throwable?.let { e -> e(e, message) }
|
||||
message?.let { msg -> d(msg) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
package com.tangem.tap.common.images
|
||||
|
||||
import android.app.Application
|
||||
import com.squareup.picasso.OkHttp3Downloader
|
||||
import com.squareup.picasso.Picasso
|
||||
import com.tangem.tap.logConfig
|
||||
import com.tangem.wallet.BuildConfig
|
||||
import okhttp3.Cache
|
||||
import okhttp3.CacheControl
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class PicassoHelper {
|
||||
companion object {
|
||||
private const val KEEP_CACHE_MAX_DAYS = 7
|
||||
|
||||
fun initPicassoWithCaching(application: Application) {
|
||||
val picasso = Picasso.Builder(application)
|
||||
.downloader(OkHttp3Downloader(getOkHttpForPicasso(application)))
|
||||
.build()
|
||||
picasso.isLoggingEnabled = logIsEnabled()
|
||||
picasso.setIndicatorsEnabled(BuildConfig.DEBUG)
|
||||
Picasso.setSingletonInstance(picasso)
|
||||
}
|
||||
|
||||
private fun getOkHttpForPicasso(application: Application): OkHttpClient {
|
||||
return OkHttpClient.Builder().apply {
|
||||
cache(Cache(File(application.filesDir, "artworks"), Long.MAX_VALUE))
|
||||
callTimeout(15000, TimeUnit.MILLISECONDS)
|
||||
|
||||
if (logIsEnabled()) {
|
||||
addDebugInterceptors(this)
|
||||
}
|
||||
|
||||
addInterceptor { chain ->
|
||||
val cacheControl = CacheControl.Builder()
|
||||
.maxStale(KEEP_CACHE_MAX_DAYS, TimeUnit.DAYS)
|
||||
.build()
|
||||
val origRequest = chain.request()
|
||||
val neverExpireRequest = origRequest.newBuilder()
|
||||
.cacheControl(cacheControl)
|
||||
.build()
|
||||
chain.proceed(neverExpireRequest)
|
||||
}
|
||||
}.build()
|
||||
|
||||
}
|
||||
|
||||
private fun addDebugInterceptors(okHttpBuilder: OkHttpClient.Builder) {
|
||||
val picassoInterceptor = HttpLoggingInterceptor(PicassoOkHttpLogger()).apply {
|
||||
level = HttpLoggingInterceptor.Level.BODY
|
||||
}
|
||||
okHttpBuilder.addInterceptor(picassoInterceptor)
|
||||
}
|
||||
|
||||
private fun logIsEnabled(): Boolean = BuildConfig.DEBUG && logConfig.picasso
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private class PicassoOkHttpLogger : HttpLoggingInterceptor.Logger {
|
||||
override fun log(message: String) {
|
||||
Timber.d(message)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
package com.tangem.tap.domain
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import com.squareup.picasso.Picasso
|
||||
import com.squareup.picasso.Target
|
||||
import com.tangem.common.services.Result
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class UrlBitmapLoader {
|
||||
private val mainHandler = Handler(Looper.getMainLooper())
|
||||
|
||||
fun loadBitmap(url: String, callback: (Result<Bitmap>) -> Unit) {
|
||||
val target = DownloadTarget(callback)
|
||||
protectedFromGarbageCollectorTargets.add(target)
|
||||
mainHandler.post { Picasso.get().load(url).into(target) }
|
||||
}
|
||||
|
||||
fun loadBitmap(url: String, target: DownloadTarget) {
|
||||
protectedFromGarbageCollectorTargets.add(target)
|
||||
Picasso.get().load(url).into(target)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private val protectedFromGarbageCollectorTargets = mutableListOf<Target>()
|
||||
|
||||
// It adds the ability to trigger multiple downloads with a unique callback.
|
||||
open class DownloadTarget(
|
||||
val callback: (Result<Bitmap>) -> Unit,
|
||||
) : Target {
|
||||
|
||||
override fun onBitmapLoaded(bitmap: Bitmap, from: Picasso.LoadedFrom) {
|
||||
callback(Result.Success(bitmap))
|
||||
protectedFromGarbageCollectorTargets.remove(this)
|
||||
}
|
||||
|
||||
override fun onBitmapFailed(e: Exception?, errorDrawable: Drawable?) {
|
||||
callback.invoke(Result.Failure(e ?: Exception("Unknown exception")))
|
||||
protectedFromGarbageCollectorTargets.remove(this)
|
||||
}
|
||||
|
||||
override fun onPrepareLoad(placeHolderDrawable: Drawable?) {
|
||||
}
|
||||
}
|
||||
|
|
@ -112,31 +112,44 @@ private class CreateWalletTangemWallet : ProductCommandProcessor<CreateProductWa
|
|||
this.card = card
|
||||
val curves = card.getCurvesForNonCreatedWallets()
|
||||
|
||||
if (curves.isEmpty()) {
|
||||
val createWalletResponses = card.wallets.map { CreateWalletResponse(card.cardId, it) }
|
||||
proceedWithCreatedWallets(createWalletResponses, session, callback)
|
||||
return
|
||||
}
|
||||
|
||||
CreateWalletsTask(curves).run(session) { result ->
|
||||
when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
val createWalletResponses = result.data.createWalletResponses
|
||||
when {
|
||||
card.settings.isBackupAllowed -> {
|
||||
linkPrimaryCard(createWalletResponses, session, callback)
|
||||
}
|
||||
card.settings.isHDWalletAllowed -> {
|
||||
deriveKeys(createWalletResponses, session, callback)
|
||||
}
|
||||
else -> {
|
||||
callback(
|
||||
CompletionResult.Success(
|
||||
CreateProductWalletTaskResponse(card = session.environment.card!!)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
proceedWithCreatedWallets(result.data.createWalletResponses, session, callback)
|
||||
}
|
||||
is CompletionResult.Failure -> callback(CompletionResult.Failure(result.error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun proceedWithCreatedWallets(
|
||||
createWalletResponses: List<CreateWalletResponse>,
|
||||
session: CardSession,
|
||||
callback: (result: CompletionResult<CreateProductWalletTaskResponse>) -> Unit,
|
||||
) {
|
||||
when {
|
||||
card.settings.isBackupAllowed -> {
|
||||
linkPrimaryCard(createWalletResponses, session, callback)
|
||||
}
|
||||
card.settings.isHDWalletAllowed -> {
|
||||
deriveKeys(createWalletResponses, session, callback)
|
||||
}
|
||||
else -> {
|
||||
callback(
|
||||
CompletionResult.Success(
|
||||
CreateProductWalletTaskResponse(card = session.environment.card!!)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun linkPrimaryCard(
|
||||
createWalletResponse: List<CreateWalletResponse>,
|
||||
session: CardSession,
|
||||
|
|
|
|||
|
|
@ -185,8 +185,9 @@ class CurrenciesRepository(
|
|||
tokens.map {
|
||||
async {
|
||||
tangemNetworkService.getTokens(
|
||||
it.contractAddress,
|
||||
it.blockchainDao.toBlockchain().toNetworkId()
|
||||
contractAddress = it.contractAddress,
|
||||
networkId = it.blockchainDao.toBlockchain().toNetworkId(),
|
||||
active = true,
|
||||
)
|
||||
}
|
||||
}.map { it.await() }
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ class LoadAvailableCoinsService(
|
|||
val networkIds = supportedBlockchains.toSet().map { it.toNetworkId() }
|
||||
return networkService.getListOfCoins(
|
||||
networkIds = networkIds,
|
||||
active = true,
|
||||
offset = offset,
|
||||
limit = LOAD_PER_PAGE,
|
||||
searchText = searchInput
|
||||
|
|
|
|||
|
|
@ -5,11 +5,15 @@ import android.content.Context
|
|||
import com.squareup.moshi.JsonAdapter
|
||||
import com.squareup.moshi.JsonClass
|
||||
import com.squareup.moshi.Types
|
||||
import com.tangem.common.extensions.hexToBytes
|
||||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.network.common.MoshiConverter
|
||||
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectSession
|
||||
import com.tangem.tap.features.details.redux.walletconnect.WalletForSession
|
||||
import com.trustwallet.walletconnect.models.WCPeerMeta
|
||||
import com.trustwallet.walletconnect.models.session.WCSession
|
||||
import timber.log.Timber
|
||||
import java.nio.charset.Charset
|
||||
|
||||
class WalletConnectRepository(val context: Application) {
|
||||
private val moshi = MoshiConverter.defaultMoshi()
|
||||
|
|
@ -35,17 +39,29 @@ class WalletConnectRepository(val context: Application) {
|
|||
fun loadSavedSessions(): List<WalletConnectSession> {
|
||||
return try {
|
||||
val json = context.readFileText(FILE_NAME_PREFIX_SESSIONS)
|
||||
.hexToUtf8()
|
||||
walletConnectAdapter.fromJson(json)!!.map { it.toSession() }
|
||||
} catch (exception: Exception) {
|
||||
Timber.e(exception)
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveSessions(sessions: List<WalletConnectSession>) {
|
||||
val json = walletConnectAdapter.toJson(sessions.map { SessionDao.fromSession(it) })
|
||||
.utf8ToHex() // convert to hex to solve problems with saving text with emojis
|
||||
Timber.e("WC sessions, saving following json: $json")
|
||||
context.rewriteFile(json, FILE_NAME_PREFIX_SESSIONS)
|
||||
}
|
||||
|
||||
private fun String.utf8ToHex(): String {
|
||||
return this.toByteArray().toHexString()
|
||||
}
|
||||
|
||||
private fun String.hexToUtf8(): String {
|
||||
return this.hexToBytes().toString(Charset.defaultCharset())
|
||||
}
|
||||
|
||||
private fun Context.readFileText(fileName: String): String =
|
||||
this.openFileInput(fileName).bufferedReader().readText()
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import androidx.annotation.LayoutRes
|
|||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.transition.TransitionManager
|
||||
import com.squareup.picasso.Picasso
|
||||
import coil.load
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.tangem_sdk_new.extensions.fadeIn
|
||||
import com.tangem.tangem_sdk_new.extensions.fadeOut
|
||||
|
|
@ -67,11 +67,11 @@ class OnboardingNoteFragment : BaseOnboardingFragment<OnboardingNoteState>() {
|
|||
override fun newState(state: OnboardingNoteState) {
|
||||
if (activity == null || view == null) return
|
||||
|
||||
Picasso.get()
|
||||
.load(state.cardArtworkUrl)
|
||||
.error(R.drawable.card_placeholder_black)
|
||||
.placeholder(R.drawable.card_placeholder_black)
|
||||
?.into(binding.onboardingTopContainer.imvFrontCard)
|
||||
binding.onboardingTopContainer.imvFrontCard.load(state.cardArtworkUrl) {
|
||||
placeholder(R.drawable.card_placeholder_black)
|
||||
error(R.drawable.card_placeholder_black)
|
||||
fallback(R.drawable.card_placeholder_black)
|
||||
}
|
||||
|
||||
pbBinding.pbState.max = state.steps.size - 1
|
||||
pbBinding.pbState.progress = state.progress
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import androidx.annotation.LayoutRes
|
|||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.transition.TransitionManager
|
||||
import com.squareup.picasso.Picasso
|
||||
import coil.load
|
||||
import com.tangem.tap.common.extensions.getDrawableCompat
|
||||
import com.tangem.tap.common.redux.navigation.ShareElement
|
||||
import com.tangem.tap.common.transitions.InternalNoteLayoutTransition
|
||||
|
|
@ -54,11 +54,11 @@ class OnboardingOtherCardsFragment : BaseOnboardingFragment<OnboardingOtherCards
|
|||
if (activity == null || view == null) return
|
||||
if (state.currentStep == OnboardingOtherCardsStep.None) return
|
||||
|
||||
Picasso.get()
|
||||
.load(state.cardArtworkUrl)
|
||||
.error(R.drawable.card_placeholder_black)
|
||||
.placeholder(R.drawable.card_placeholder_black)
|
||||
?.into(binding.onboardingTopContainer.imvFrontCard)
|
||||
binding.onboardingTopContainer.imvFrontCard.load(state.cardArtworkUrl) {
|
||||
placeholder(R.drawable.card_placeholder_black)
|
||||
error(R.drawable.card_placeholder_black)
|
||||
fallback(R.drawable.card_placeholder_black)
|
||||
}
|
||||
|
||||
pbBinding.pbState.max = state.steps.size - 1
|
||||
pbBinding.pbState.progress = state.progress
|
||||
|
|
|
|||
|
|
@ -9,13 +9,18 @@ import androidx.constraintlayout.widget.ConstraintSet
|
|||
import androidx.core.view.isVisible
|
||||
import androidx.transition.TransitionInflater
|
||||
import androidx.transition.TransitionManager
|
||||
import com.squareup.picasso.Picasso
|
||||
import coil.load
|
||||
import com.tangem.Message
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.common.extensions.VoidCallback
|
||||
import com.tangem.domain.common.TwinCardNumber
|
||||
import com.tangem.tangem_sdk_new.ui.widget.leapfrogWidget.LeapfrogWidget
|
||||
import com.tangem.tap.common.extensions.*
|
||||
import com.tangem.tap.common.extensions.beginDelayedTransition
|
||||
import com.tangem.tap.common.extensions.getDrawableCompat
|
||||
import com.tangem.tap.common.extensions.hide
|
||||
import com.tangem.tap.common.extensions.readAssetAsString
|
||||
import com.tangem.tap.common.extensions.show
|
||||
import com.tangem.tap.common.extensions.stripZeroPlainString
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.common.redux.navigation.ShareElement
|
||||
|
|
@ -75,24 +80,28 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
|
|||
resources.getValue(R.dimen.device_scale_factor_for_twins_welcome, typedValue, true)
|
||||
val deviceScaleFactorForWelcomeState = typedValue.float
|
||||
|
||||
twinsWidget = TwinsCardWidget(LeapfrogWidget(binding.onboardingTopContainer.cardsContainer), deviceScaleFactorForWelcomeState) {
|
||||
twinsWidget = TwinsCardWidget(
|
||||
LeapfrogWidget(binding.onboardingTopContainer.cardsContainer),
|
||||
deviceScaleFactorForWelcomeState
|
||||
) {
|
||||
285f * deviceScaleFactorForWelcomeState
|
||||
}
|
||||
btnRefreshBalanceWidget = RefreshBalanceWidget(binding.onboardingTopContainer.onboardingMainContainer)
|
||||
btnRefreshBalanceWidget =
|
||||
RefreshBalanceWidget(binding.onboardingTopContainer.onboardingMainContainer)
|
||||
|
||||
binding.toolbar.title = getText(R.string.twins_recreate_toolbar)
|
||||
|
||||
Picasso.get()
|
||||
.load(Artwork.TWIN_CARD_1)
|
||||
.error(R.drawable.card_placeholder_black)
|
||||
.placeholder(R.drawable.card_placeholder_black)
|
||||
?.into(binding.onboardingTopContainer.imvTwinFrontCard)
|
||||
binding.onboardingTopContainer.imvTwinFrontCard.load(Artwork.TWIN_CARD_1) {
|
||||
placeholder(R.drawable.card_placeholder_black)
|
||||
error(R.drawable.card_placeholder_black)
|
||||
fallback(R.drawable.card_placeholder_black)
|
||||
}
|
||||
|
||||
Picasso.get()
|
||||
.load(Artwork.TWIN_CARD_2)
|
||||
.error(R.drawable.card_placeholder_white)
|
||||
.placeholder(R.drawable.card_placeholder_white)
|
||||
?.into(binding.onboardingTopContainer.imvTwinBackCard)
|
||||
binding.onboardingTopContainer.imvTwinBackCard.load(Artwork.TWIN_CARD_2) {
|
||||
placeholder(R.drawable.card_placeholder_white)
|
||||
error(R.drawable.card_placeholder_white)
|
||||
fallback(R.drawable.card_placeholder_white)
|
||||
}
|
||||
}
|
||||
|
||||
private fun reconfigureLayoutForTwins(containerBinding: LayoutOnboardingContainerTopBinding) =
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ import androidx.fragment.app.Fragment
|
|||
import androidx.transition.TransitionInflater
|
||||
import androidx.transition.TransitionManager
|
||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import coil.load
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import com.squareup.picasso.Picasso
|
||||
import com.tangem.common.CardIdFormatter
|
||||
import com.tangem.common.core.CardIdDisplayFormat
|
||||
import com.tangem.tangem_sdk_new.ui.widget.leapfrogWidget.LeapfrogWidget
|
||||
|
|
@ -22,7 +22,12 @@ import com.tangem.tap.common.extensions.hide
|
|||
import com.tangem.tap.common.extensions.show
|
||||
import com.tangem.tap.features.FragmentOnBackPressedHandler
|
||||
import com.tangem.tap.features.addBackPressHandler
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.*
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupAction
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupState
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.BackupStep
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletAction
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletState
|
||||
import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWalletStep
|
||||
import com.tangem.tap.features.onboarding.products.wallet.ui.dialogs.AccessCodeDialog
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
|
|
@ -124,11 +129,11 @@ class OnboardingWalletFragment : Fragment(R.layout.fragment_onboarding_wallet),
|
|||
}
|
||||
|
||||
private fun loadImageIntoImageView(url: String?, view: ImageView) {
|
||||
Picasso.get()
|
||||
.load(url)
|
||||
.error(R.drawable.card_placeholder_black)
|
||||
.placeholder(R.drawable.card_placeholder_black)
|
||||
?.into(view)
|
||||
view.load(url) {
|
||||
placeholder(R.drawable.card_placeholder_black)
|
||||
error(R.drawable.card_placeholder_black)
|
||||
fallback(R.drawable.card_placeholder_black)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupCreateWalletState() = with(binding) {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import com.tangem.tap.common.extensions.stripZeroPlainString
|
|||
import com.tangem.tap.features.send.redux.ReceiptAction.RefreshReceipt
|
||||
import com.tangem.tap.features.send.redux.SendScreenAction
|
||||
import com.tangem.tap.features.send.redux.states.*
|
||||
import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN
|
||||
import com.tangem.tap.store
|
||||
import java.math.BigDecimal
|
||||
|
||||
|
|
@ -15,10 +16,6 @@ import java.math.BigDecimal
|
|||
*/
|
||||
class ReceiptReducer : SendInternalReducer {
|
||||
|
||||
companion object {
|
||||
const val EMPTY = "-"
|
||||
}
|
||||
|
||||
private lateinit var sendState: SendState
|
||||
private lateinit var amountState: AmountState
|
||||
private lateinit var feeState: FeeState
|
||||
|
|
@ -137,9 +134,9 @@ class ReceiptReducer : SendInternalReducer {
|
|||
)
|
||||
} else {
|
||||
ReceiptTokenFiat(
|
||||
amountFiat = EMPTY,
|
||||
feeFiat = EMPTY,
|
||||
totalFiat = EMPTY,
|
||||
amountFiat = UNKNOWN_AMOUNT_SIGN,
|
||||
feeFiat = UNKNOWN_AMOUNT_SIGN,
|
||||
totalFiat = UNKNOWN_AMOUNT_SIGN,
|
||||
willSentToken = tokensToSend.stripZeroPlainString(),
|
||||
willSentFeeCoin = feeCoin.stripZeroPlainString(),
|
||||
symbols = symbols
|
||||
|
|
@ -169,7 +166,7 @@ class ReceiptReducer : SendInternalReducer {
|
|||
ReceiptTokenCrypto(
|
||||
amountToken = tokensToSend.stripZeroPlainString(),
|
||||
feeCoin = feeCoin.stripZeroPlainString().addPrecisionSign(),
|
||||
totalFiat = EMPTY,
|
||||
totalFiat = UNKNOWN_AMOUNT_SIGN,
|
||||
symbols = symbols
|
||||
)
|
||||
}
|
||||
|
|
@ -206,7 +203,7 @@ class ReceiptReducer : SendInternalReducer {
|
|||
return when {
|
||||
!isToken && sendState.coinIsConvertible() -> sendState.coinConverter!!.toFiatWithPrecision(value).stripZeroPlainString()
|
||||
isToken && sendState.tokenIsConvertible() -> sendState.tokenConverter!!.toFiatWithPrecision(value).stripZeroPlainString()
|
||||
else -> EMPTY
|
||||
else -> UNKNOWN_AMOUNT_SIGN
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,12 +17,13 @@ import com.tangem.tap.features.BaseStoreFragment
|
|||
import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.Error
|
||||
import com.tangem.tap.features.send.redux.FeeAction
|
||||
import com.tangem.tap.features.send.redux.SendAction
|
||||
import com.tangem.tap.features.send.redux.reducers.ReceiptReducer
|
||||
import com.tangem.tap.features.send.redux.states.*
|
||||
import com.tangem.tap.features.send.ui.FeeUiHelper
|
||||
import com.tangem.tap.features.send.ui.SendFragment
|
||||
import com.tangem.tap.features.send.ui.dialogs.SendTransactionFailsDialog
|
||||
import com.tangem.tap.features.send.ui.dialogs.TezosWarningDialog
|
||||
import com.tangem.tap.features.wallet.redux.WalletState.Companion.ROUGH_SIGN
|
||||
import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN
|
||||
import com.tangem.tap.features.wallet.ui.adapters.WarningMessagesAdapter
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
|
|
@ -257,12 +258,12 @@ class SendStateSubscriber(fragment: BaseStoreFragment) :
|
|||
val mainLayout = clReceiptContainer as ViewGroup
|
||||
val totalLayout = llTotalContainer.llTotal as ViewGroup
|
||||
val totalTokenLayout = llTotalContainer.flTotalTokenCrypto as ViewGroup
|
||||
fun getString(id: Int, vararg formatStrings: String): String =
|
||||
mainLayout.context.getString(id, *formatStrings)
|
||||
|
||||
val rough = getString(R.string.sign_rough)
|
||||
fun roughOrEmpty(value: String): String =
|
||||
if (value == ReceiptReducer.EMPTY) value else "$rough $value"
|
||||
fun getString(id: Int, vararg formatStrings: String): String = mainLayout.getString(id, *formatStrings)
|
||||
|
||||
fun roughOrEmpty(value: String): String {
|
||||
return if (value == UNKNOWN_AMOUNT_SIGN) value else "$ROUGH_SIGN $value"
|
||||
}
|
||||
|
||||
when (state.visibleTypeOfReceipt) {
|
||||
ReceiptLayoutType.FIAT -> {
|
||||
|
|
|
|||
|
|
@ -301,6 +301,11 @@ data class WalletState(
|
|||
)
|
||||
} else this
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val UNKNOWN_AMOUNT_SIGN = "—"
|
||||
const val ROUGH_SIGN = "≈"
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface WalletDialog : StateDialog {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import com.tangem.tap.features.wallet.models.filterByToken
|
|||
import com.tangem.tap.features.wallet.models.getPendingTransactions
|
||||
import com.tangem.tap.features.wallet.models.removeUnknownTransactions
|
||||
import com.tangem.tap.features.wallet.redux.*
|
||||
import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN
|
||||
import com.tangem.tap.features.wallet.ui.BalanceStatus
|
||||
import com.tangem.tap.features.wallet.ui.BalanceWidgetData
|
||||
import com.tangem.tap.features.wallet.ui.TokenData
|
||||
|
|
@ -127,9 +128,8 @@ class MultiWalletReducer {
|
|||
action.amount.decimals, action.amount.currencySymbol
|
||||
),
|
||||
fiatAmountFormatted = tokenWalletData.fiatRate?.let {
|
||||
action.amount.value
|
||||
?.toFiatString(it, store.state.globalState.appCurrency.symbol)
|
||||
},
|
||||
action.amount.value?.toFiatString(it, store.state.globalState.appCurrency.symbol)
|
||||
} ?: UNKNOWN_AMOUNT_SIGN,
|
||||
blockchainAmount = wallet.amounts[AmountType.Coin]?.value ?: BigDecimal.ZERO
|
||||
),
|
||||
pendingTransactions = pendingTransactions.removeUnknownTransactions(),
|
||||
|
|
|
|||
|
|
@ -14,11 +14,11 @@ import com.tangem.tap.features.wallet.models.filterByToken
|
|||
import com.tangem.tap.features.wallet.models.getPendingTransactions
|
||||
import com.tangem.tap.features.wallet.models.removeUnknownTransactions
|
||||
import com.tangem.tap.features.wallet.redux.*
|
||||
import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN
|
||||
import com.tangem.tap.features.wallet.ui.BalanceStatus
|
||||
import com.tangem.tap.features.wallet.ui.BalanceWidgetData
|
||||
import com.tangem.tap.features.wallet.ui.TokenData
|
||||
import com.tangem.tap.store
|
||||
import java.math.RoundingMode
|
||||
|
||||
class OnWalletLoadedReducer {
|
||||
|
||||
|
|
@ -55,6 +55,8 @@ class OnWalletLoadedReducer {
|
|||
}
|
||||
|
||||
val fiatAmount = walletData.fiatRate?.let { coinAmountValue?.toFiatValue(it) }
|
||||
val fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(fiatCurrency.symbol) ?: UNKNOWN_AMOUNT_SIGN
|
||||
|
||||
val newWalletData = walletData.copy(
|
||||
currencyData = walletData.currencyData.copy(
|
||||
status = balanceStatus,
|
||||
|
|
@ -64,7 +66,7 @@ class OnWalletLoadedReducer {
|
|||
amount = coinAmountValue,
|
||||
amountFormatted = formattedAmount,
|
||||
fiatAmount = fiatAmount,
|
||||
fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(fiatCurrency.symbol)
|
||||
fiatAmountFormatted = fiatAmountFormatted,
|
||||
),
|
||||
pendingTransactions = pendingTransactions.removeUnknownTransactions(),
|
||||
mainButton = WalletMainButton.SendButton(isCoinSendButtonEnabled),
|
||||
|
|
@ -82,8 +84,9 @@ class OnWalletLoadedReducer {
|
|||
else -> BalanceStatus.VerifiedOnline
|
||||
}
|
||||
val tokenAmountValue = wallet.getTokenAmount(token)?.value
|
||||
val tokenFiatAmount =
|
||||
tokenWalletData?.fiatRate?.let { rate -> tokenAmountValue?.toFiatValue(rate) }
|
||||
val tokenFiatAmount = tokenWalletData?.fiatRate?.let { tokenAmountValue?.toFiatValue(it) }
|
||||
val tokenFiatAmountFormatted = tokenFiatAmount?.toFormattedFiatValue(fiatCurrency.symbol)
|
||||
?: UNKNOWN_AMOUNT_SIGN
|
||||
|
||||
val isTokenSendButtonEnabled = newWalletData.shouldEnableTokenSendButton()
|
||||
&& pendingTransactions.isEmpty()
|
||||
|
|
@ -97,7 +100,7 @@ class OnWalletLoadedReducer {
|
|||
token.symbol
|
||||
),
|
||||
fiatAmount = tokenFiatAmount,
|
||||
fiatAmountFormatted = tokenFiatAmount?.toFormattedFiatValue(fiatCurrency.symbol)
|
||||
fiatAmountFormatted = tokenFiatAmountFormatted,
|
||||
),
|
||||
pendingTransactions = tokenPendingTransactions.removeUnknownTransactions(),
|
||||
mainButton = WalletMainButton.SendButton(isTokenSendButtonEnabled),
|
||||
|
|
@ -141,9 +144,8 @@ class OnWalletLoadedReducer {
|
|||
wallet.blockchain.decimals(),
|
||||
wallet.blockchain.currency
|
||||
)
|
||||
val fiatRate = walletState.primaryWallet?.fiatRate
|
||||
val fiatAmountRaw = fiatRate?.multiply(amount)?.setScale(2, RoundingMode.DOWN)
|
||||
val fiatAmount = fiatRate?.let { amount?.toFiatString(it, fiatCurrencyName) }
|
||||
val fiatAmount = walletState.primaryWallet?.fiatRate?.let { amount?.toFiatValue(it) }
|
||||
val fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(fiatCurrencyName) ?: UNKNOWN_AMOUNT_SIGN
|
||||
|
||||
val pendingTransactions = wallet.getPendingTransactions()
|
||||
val sendButtonEnabled = amount?.isZero() == false && pendingTransactions.isEmpty()
|
||||
|
|
@ -160,8 +162,8 @@ class OnWalletLoadedReducer {
|
|||
blockchainAmount = amount,
|
||||
amount = amount,
|
||||
amountFormatted = formattedAmount,
|
||||
fiatAmountFormatted = fiatAmount,
|
||||
fiatAmount = fiatAmountRaw
|
||||
fiatAmount = fiatAmount,
|
||||
fiatAmountFormatted = fiatAmountFormatted
|
||||
),
|
||||
pendingTransactions = pendingTransactions.removeUnknownTransactions(),
|
||||
mainButton = WalletMainButton.SendButton(sendButtonEnabled),
|
||||
|
|
|
|||
|
|
@ -217,8 +217,8 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
|
|||
currency = walletBlockchain.currency,
|
||||
),
|
||||
fiatAmount = fiatAmount,
|
||||
fiatAmountFormatted = fiatAmount.toFiatRateString(
|
||||
fiatCurrencyName = store.state.globalState.appCurrency.symbol
|
||||
fiatAmountFormatted = fiatAmount.toFormattedFiatValue(
|
||||
fiatCurrencyName = state.globalState.appCurrency.symbol
|
||||
),
|
||||
amountToCreateAccount = action.amountToCreateAccount,
|
||||
)
|
||||
|
|
@ -439,7 +439,7 @@ private fun setMultiWalletFiatRate(
|
|||
wallet?.getTokenAmount(currency.token)?.value?.toFiatValue(rate)
|
||||
}
|
||||
if (currencyData.status == BalanceStatus.NoAccount && fiatAmount == null) {
|
||||
fiatAmount = BigDecimal.ZERO
|
||||
fiatAmount = BigDecimal.ZERO.setScale(2)
|
||||
}
|
||||
val fiatAmountFormatted = fiatAmount?.toFormattedFiatValue(appCurrency.symbol)
|
||||
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ data class BalanceWidgetData(
|
|||
val blockchainAmount: BigDecimal? = BigDecimal.ZERO,
|
||||
val amount: BigDecimal? = null,
|
||||
val amountFormatted: String? = null,
|
||||
val fiatAmountFormatted: String? = null,
|
||||
val fiatAmount: BigDecimal? = null,
|
||||
val fiatAmountFormatted: String? = null,
|
||||
val token: TokenData? = null,
|
||||
val amountToCreateAccount: String? = null,
|
||||
val errorMessage: String? = null
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import androidx.fragment.app.Fragment
|
|||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.transition.TransitionInflater
|
||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import com.squareup.picasso.Picasso
|
||||
import com.tangem.tangem_sdk_new.extensions.dpToPx
|
||||
import com.tangem.tap.common.SnackbarHandler
|
||||
import com.tangem.tap.common.TestActions
|
||||
import com.tangem.tap.common.extensions.*
|
||||
|
|
@ -22,8 +22,10 @@ import com.tangem.tap.features.onboarding.getQRReceiveMessage
|
|||
import com.tangem.tap.features.wallet.models.Currency
|
||||
import com.tangem.tap.features.wallet.models.PendingTransaction
|
||||
import com.tangem.tap.features.wallet.redux.*
|
||||
import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN
|
||||
import com.tangem.tap.features.wallet.ui.adapters.PendingTransactionsAdapter
|
||||
import com.tangem.tap.features.wallet.ui.adapters.WalletDetailWarningMessagesAdapter
|
||||
import com.tangem.tap.features.wallet.ui.images.loadCurrencyIcon
|
||||
import com.tangem.tap.features.wallet.ui.test.TestWalletDetails
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
|
|
@ -127,11 +129,11 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
|
|||
|
||||
handleCurrencyIcon(selectedWallet)
|
||||
handleWarnings(selectedWallet)
|
||||
updateViewMeasurements()
|
||||
|
||||
binding.srlWalletDetails.setOnRefreshListener {
|
||||
if (selectedWallet.currencyData.status != BalanceStatus.Loading) {
|
||||
store.dispatch(
|
||||
WalletAction.LoadWallet(
|
||||
store.dispatch(WalletAction.LoadWallet(
|
||||
blockchain = BlockchainNetwork(
|
||||
selectedWallet.currency.blockchain,
|
||||
selectedWallet.currency.derivationPath,
|
||||
|
|
@ -147,13 +149,27 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
|
|||
}
|
||||
}
|
||||
|
||||
private fun updateViewMeasurements() {
|
||||
val tvFiatAmount = binding.lWalletDetails.lBalance.tvFiatAmount
|
||||
val paddingStart = when (tvFiatAmount.text) {
|
||||
UNKNOWN_AMOUNT_SIGN -> 16f
|
||||
else -> 12f
|
||||
}
|
||||
tvFiatAmount.setPadding(
|
||||
tvFiatAmount.dpToPx(paddingStart).toInt(),
|
||||
tvFiatAmount.paddingTop,
|
||||
tvFiatAmount.paddingEnd,
|
||||
tvFiatAmount.paddingBottom,
|
||||
)
|
||||
}
|
||||
|
||||
private fun setupCurrency(currencyData: BalanceWidgetData, currency: Currency) = with(binding) {
|
||||
tvCurrencyTitle.text = currencyData.currency
|
||||
if (currency is Currency.Token) {
|
||||
binding.tvCurrencySubtitle.text = currency.blockchain.tokenDisplayName()
|
||||
binding.tvCurrencySubtitle.show()
|
||||
tvCurrencySubtitle.text = currency.blockchain.tokenDisplayName()
|
||||
tvCurrencySubtitle.show()
|
||||
} else {
|
||||
binding.tvCurrencySubtitle.hide()
|
||||
tvCurrencySubtitle.hide()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -185,9 +201,9 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details),
|
|||
}
|
||||
|
||||
private fun handleCurrencyIcon(wallet: WalletData) = with(binding.lWalletDetails.lBalance) {
|
||||
Picasso.get().loadCurrenciesIcon(
|
||||
imageView = ivCurrency,
|
||||
textView = tvTokenLetter,
|
||||
loadCurrencyIcon(
|
||||
currencyImageView = ivCurrency,
|
||||
currencyTextView = tvTokenLetter,
|
||||
blockchain = wallet.currency.blockchain,
|
||||
token = (wallet.currency as? Currency.Token)?.token
|
||||
)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.transition.TransitionInflater
|
||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import com.squareup.picasso.Picasso
|
||||
import coil.load
|
||||
import com.tangem.tap.MainActivity
|
||||
import com.tangem.tap.common.extensions.show
|
||||
import com.tangem.tap.common.recyclerView.SpaceItemDecoration
|
||||
|
|
@ -165,11 +165,11 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
|
|||
}
|
||||
|
||||
private fun setupCardImage(cardImage: Artwork?) {
|
||||
Picasso.get()
|
||||
.load(cardImage?.artworkId)
|
||||
.placeholder(R.drawable.card_placeholder_black)
|
||||
?.error(R.drawable.card_placeholder_black)
|
||||
?.into(binding.ivCard)
|
||||
binding.ivCard.load(cardImage?.artworkId) {
|
||||
placeholder(R.drawable.card_placeholder_black)
|
||||
error(R.drawable.card_placeholder_black)
|
||||
fallback(R.drawable.card_placeholder_black)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
|
|
|
|||
|
|
@ -6,18 +6,17 @@ import androidx.core.view.isVisible
|
|||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.squareup.picasso.Picasso
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.Token
|
||||
import com.tangem.domain.common.TapWorkarounds.derivationStyle
|
||||
import com.tangem.tap.common.extensions.getString
|
||||
import com.tangem.tap.common.extensions.hide
|
||||
import com.tangem.tap.common.extensions.loadCurrenciesIcon
|
||||
import com.tangem.tap.common.extensions.show
|
||||
import com.tangem.tap.features.wallet.models.Currency
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.features.wallet.redux.WalletData
|
||||
import com.tangem.tap.features.wallet.ui.BalanceStatus
|
||||
import com.tangem.tap.features.wallet.ui.images.loadCurrencyIcon
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
import com.tangem.wallet.databinding.ItemCurrencyWalletBinding
|
||||
|
|
@ -98,16 +97,16 @@ class WalletAdapter
|
|||
lContent.root.show()
|
||||
}
|
||||
|
||||
Picasso.get().loadCurrenciesIcon(
|
||||
imageView = ivCurrency,
|
||||
textView = tvTokenLetter,
|
||||
loadCurrencyIcon(
|
||||
currencyImageView = ivCurrency,
|
||||
currencyTextView = tvTokenLetter,
|
||||
token = (wallet.currency as? Currency.Token)?.token,
|
||||
blockchain = wallet.currency.blockchain,
|
||||
)
|
||||
|
||||
lContent.tvCurrency.text = wallet.currencyData.currency
|
||||
lContent.tvAmountFiat.text = wallet.currencyData.fiatAmountFormatted ?: "—"
|
||||
lContent.tvAmount.text = wallet.currencyData.amountFormatted ?: "—"
|
||||
lContent.tvAmountFiat.text = wallet.currencyData.fiatAmountFormatted
|
||||
lContent.tvAmount.text = wallet.currencyData.amountFormatted
|
||||
|
||||
lContent.tvStatus.isVisible = statusMessage != null
|
||||
lContent.tvStatus.text = statusMessage
|
||||
|
|
|
|||
|
|
@ -0,0 +1,109 @@
|
|||
package com.tangem.tap.features.wallet.ui.images
|
||||
|
||||
import android.graphics.PorterDuff
|
||||
import android.graphics.PorterDuffColorFilter
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
import coil.imageLoader
|
||||
import coil.load
|
||||
import coil.request.ImageRequest
|
||||
import coil.transform.RoundedCornersTransformation
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.IconsUtil
|
||||
import com.tangem.blockchain.common.Token
|
||||
import com.tangem.domain.common.extensions.toNetworkId
|
||||
import com.tangem.tap.common.extensions.getColor
|
||||
import com.tangem.tap.common.extensions.getRoundIconRes
|
||||
import com.tangem.tap.common.extensions.getTextColor
|
||||
import com.tangem.tap.domain.extensions.getCustomIconUrl
|
||||
import com.tangem.tap.domain.tokens.getIconUrl
|
||||
import com.tangem.wallet.R
|
||||
|
||||
private const val QCX = "QCX"
|
||||
private const val VOYR = "VOYRME"
|
||||
|
||||
fun loadCurrencyIcon(
|
||||
currencyImageView: ImageFilterView,
|
||||
currencyTextView: TextView,
|
||||
token: Token?,
|
||||
blockchain: Blockchain,
|
||||
) {
|
||||
when {
|
||||
token == null -> currencyImageView.loadIcon(
|
||||
iconUrl = getIconUrl(blockchain.toNetworkId()),
|
||||
placeholderRes = blockchain.getRoundIconRes(),
|
||||
onStart = {
|
||||
if (blockchain.isTestnet()) {
|
||||
currencyImageView.saturation = 0f
|
||||
} else {
|
||||
currencyImageView.colorFilter = null
|
||||
}
|
||||
}
|
||||
)
|
||||
token.symbol == QCX -> currencyImageView.load(R.drawable.ic_qcx)
|
||||
token.symbol == VOYR -> currencyImageView.load(R.drawable.ic_voyr)
|
||||
else -> currencyImageView.loadIcon(
|
||||
iconUrl = getTokenIconUrl(token, blockchain),
|
||||
placeholderRes = R.drawable.shape_circle,
|
||||
onStart = {
|
||||
currencyTextView.text = token.symbol.take(1)
|
||||
currencyTextView.setTextColor(token.getTextColor())
|
||||
|
||||
if (blockchain.isTestnet()) {
|
||||
currencyImageView.saturation = 0f
|
||||
}
|
||||
},
|
||||
onError = {
|
||||
currencyImageView.colorFilter = PorterDuffColorFilter(
|
||||
/* color = */
|
||||
token.getColor(),
|
||||
/* mode = */
|
||||
PorterDuff.Mode.SRC_ATOP,
|
||||
)
|
||||
},
|
||||
onSuccess = {
|
||||
if (!blockchain.isTestnet()) {
|
||||
currencyImageView.colorFilter = null
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun ImageView.loadIcon(
|
||||
iconUrl: String?,
|
||||
placeholderRes: Int,
|
||||
crossinline onStart: () -> Unit = {},
|
||||
crossinline onSuccess: () -> Unit = {},
|
||||
crossinline onError: () -> Unit = {},
|
||||
) {
|
||||
ImageRequest.Builder(context)
|
||||
.data(iconUrl)
|
||||
.placeholder(placeholderRes)
|
||||
.error(placeholderRes)
|
||||
.fallback(placeholderRes)
|
||||
.transformations(
|
||||
RoundedCornersTransformation(
|
||||
topLeft = 32f,
|
||||
topRight = 32f,
|
||||
bottomLeft = 32f,
|
||||
bottomRight = 32f
|
||||
)
|
||||
)
|
||||
.listener(
|
||||
onStart = { onStart() },
|
||||
onSuccess = { _, _ -> onSuccess() },
|
||||
onError = { _, _ -> onError() }
|
||||
)
|
||||
.target(imageView = this)
|
||||
.build()
|
||||
.also(context.imageLoader::enqueue)
|
||||
}
|
||||
|
||||
private fun getTokenIconUrl(token: Token, blockchain: Blockchain): String? {
|
||||
return token.id?.let(::getIconUrl)
|
||||
?: token.getCustomIconUrl()
|
||||
?: IconsUtil.getTokenIconUri(blockchain, token)
|
||||
?.toString()
|
||||
}
|
||||
|
|
@ -35,7 +35,8 @@
|
|||
android:visibility="gone"
|
||||
app:drawableStartCompat="@drawable/ic_ok"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_currency" />
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_currency"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_status_error"
|
||||
|
|
@ -89,10 +90,10 @@
|
|||
app:layout_constraintTop_toBottomOf="@id/tv_currency" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_amount"
|
||||
android:id="@+id/tv_fiat_amount"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:ellipsize="end"
|
||||
android:gravity="end|bottom"
|
||||
android:maxLines="1"
|
||||
|
|
@ -100,27 +101,32 @@
|
|||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
app:autoSizeMaxTextSize="20sp"
|
||||
app:autoSizeMinTextSize="12sp"
|
||||
app:autoSizeMinTextSize="10sp"
|
||||
app:autoSizeStepGranularity="1sp"
|
||||
app:autoSizeTextType="uniform"
|
||||
app:layout_constraintBottom_toBottomOf="@id/tv_currency"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_weight="1"
|
||||
app:layout_constraintStart_toEndOf="@id/tv_currency"
|
||||
tools:text="0.43 BTC" />
|
||||
tools:text="3.58 USD" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_fiat_amount"
|
||||
android:layout_width="wrap_content"
|
||||
android:id="@+id/tv_amount"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:gravity="end|bottom"
|
||||
android:maxLines="1"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:textColor="@color/darkGray2"
|
||||
android:textSize="14sp"
|
||||
app:autoSizeMaxTextSize="14sp"
|
||||
app:autoSizeMinTextSize="8sp"
|
||||
app:autoSizeStepGranularity="1sp"
|
||||
app:autoSizeTextType="uniform"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_amount"
|
||||
tools:text="USD 3 588" />
|
||||
app:layout_constraintStart_toEndOf="@+id/tv_status_verified"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_fiat_amount"
|
||||
tools:text="123.12387628 XTZ" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_placeholder"
|
||||
|
|
@ -132,8 +138,7 @@
|
|||
android:textSize="14sp"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_amount"
|
||||
tools:text="USD 3 588" />
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_fiat_amount" />
|
||||
|
||||
|
||||
<View
|
||||
|
|
@ -179,8 +184,7 @@
|
|||
app:layout_constraintHorizontal_bias="1"
|
||||
app:layout_constraintStart_toEndOf="@id/tv_base_currency"
|
||||
app:layout_constraintTop_toBottomOf="@id/v_divider"
|
||||
tools:text="0.00434143 ETH"
|
||||
/>
|
||||
tools:text="0.00434143 ETH" />
|
||||
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/group_base_currency"
|
||||
|
|
|
|||
|
|
@ -7,13 +7,12 @@
|
|||
android:layout_height="120dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_amount"
|
||||
android:id="@+id/tv_fiat_amount"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:textColor="@color/darkGray6"
|
||||
|
|
@ -23,10 +22,10 @@
|
|||
app:layout_constraintHorizontal_weight="1"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="2000.43 USD" />
|
||||
tools:text="496304.28 RUB" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_fiat_amount"
|
||||
android:id="@+id/tv_amount"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
|
|
@ -37,8 +36,8 @@
|
|||
app:layout_constraintEnd_toStartOf="@id/iv_currency"
|
||||
app:layout_constraintHorizontal_weight="1"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_amount"
|
||||
tools:text="3.588 ETH" />
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_fiat_amount"
|
||||
tools:text="0.43 BTC" />
|
||||
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
android:id="@+id/iv_currency"
|
||||
|
|
@ -73,7 +72,7 @@
|
|||
android:paddingEnd="16dp"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_fiat_amount"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_amount"
|
||||
tools:text="@string/wallet_balance_verified" />
|
||||
|
||||
<TextView
|
||||
|
|
@ -87,17 +86,17 @@
|
|||
android:paddingTop="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:textSize="14sp"
|
||||
android:visibility="visible"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toStartOf="@+id/iv_currency"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_fiat_amount"
|
||||
tools:text="@string/lorem_ipsum" />
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_amount"
|
||||
tools:text="Some error" />
|
||||
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/group_balance"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:visibility="visible"
|
||||
app:constraint_referenced_ids="tv_amount, tv_fiat_amount, tv_status" />
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -331,7 +331,7 @@
|
|||
<string name="token_symbol_address_format">%1s (%2s)</string>
|
||||
<string name="alert_signed_hashes_message">Эта карта не является векселем на предъявителя. В настоящее время мы не можем сопоставить количество подписей на карте с информацией в блокчейне. Это нормально, но в редких случаях может означать, что предыдущий владелец скрывает автономную подпись, что является проблемой безопасности.\n\nНе принимайте эту карту в качестве физического платежа от кого-то, кому Вы не доверяете.\n\nВо всех остальных отношениях - это совершенно безопасно.\n\nTangem — единственный аппаратный кошелек, предлагающий защиту от подсчета подписей.</string>
|
||||
<string name="wallet_connect">WalletConnect</string>
|
||||
<string name="wallet_connect_create_tx_message">Запрос на создание транзакции для %2s\n%3s\n\nСумма: %4s\nКомиссия: %5s\nВсего: %6s\nБаланс: %7s</string>
|
||||
<string name="wallet_connect_create_tx_message">Карта %1s\nЗапрос на создание транзакции для %2s\n%3s\n\nСумма: %4s\nКомиссия: %5s\nВсего: %6s\nБаланс: %7s</string>
|
||||
<string name="wallet_connect_request_session_start">Запрос на запуск сеанса для карты с идентификатором %1s\nдля %2s\n\nURL: %3s</string>
|
||||
<string name="wallet_connect_sessions_title">Сессии WalletConnect</string>
|
||||
<string name="wallet_connect_session_opened">Сеанс WalletConnect открыт с %s</string>
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
<resources>
|
||||
|
||||
<string name="sign_rough">≈</string>
|
||||
|
||||
</resources>
|
||||
|
|
@ -141,7 +141,7 @@
|
|||
<string name="wallet_connect_card_number" translatable="false">Card: %s</string>
|
||||
<string name="wallet_connect_scan_card_message" translatable="false">Tap card to bind to wallet connect</string>
|
||||
|
||||
<string name="wallet_connect_create_tx_message" translatable="false">Card: %1s
|
||||
<string name="wallet_connect_create_tx_message" translatable="false">Card: %1s\n
|
||||
Request to create transaction for %2s
|
||||
\n%3s
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ dependencies {
|
|||
implementation implementation(project(path: ':network'))
|
||||
implementation implementation(project(path: ':common'))
|
||||
|
||||
implementation 'com.tangem:blockchain:develop-88'
|
||||
implementation 'com.tangem:blockchain:develop-90'
|
||||
// implementation 'com.tangem:blockchain:0.0.1'
|
||||
implementation 'com.tangem.tangem-sdk-kotlin:core:develop-154'
|
||||
implementation 'com.tangem.tangem-sdk-kotlin:android:develop-154'
|
||||
|
|
|
|||
|
|
@ -16,11 +16,13 @@ suspend fun TangemTechService.getTokens(
|
|||
|
||||
suspend fun TangemTechService.getListOfCoins(
|
||||
networkIds: List<String>,
|
||||
active: Boolean? = null,
|
||||
searchText: String? = null,
|
||||
offset: Int? = null,
|
||||
limit: Int? = null
|
||||
): Result<CoinsResponse> = coins(
|
||||
networkIds = networkIds.joinToString(","),
|
||||
active = active,
|
||||
searchText = searchText,
|
||||
offset = offset,
|
||||
limit = limit
|
||||
|
|
|
|||
|
|
@ -13,4 +13,4 @@ org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryErro
|
|||
org.gradle.parallel=true
|
||||
org.gradle.daemon=true
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
android.enableJetifier=true
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue