Updated on 2026-08-14
This commit is contained in:
parent
92c95095cc
commit
fbfd7476fa
20 changed files with 430 additions and 66 deletions
|
|
@ -148,4 +148,32 @@ internal object YieldSupplyDomainModule {
|
|||
currenciesRepository = currenciesRepository,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideYieldSupplyGetCurrentFeeUseCase(
|
||||
feeRepository: FeeRepository,
|
||||
quotesRepository: QuotesRepository,
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
): YieldSupplyGetCurrentFeeUseCase {
|
||||
return YieldSupplyGetCurrentFeeUseCase(
|
||||
feeRepository = feeRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
currenciesRepository = currenciesRepository,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideYieldSupplyGetMaxFeeUseCase(
|
||||
yieldSupplyRepository: YieldSupplyRepository,
|
||||
quotesRepository: QuotesRepository,
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
): YieldSupplyGetMaxFeeUseCase {
|
||||
return YieldSupplyGetMaxFeeUseCase(
|
||||
yieldSupplyRepository = yieldSupplyRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
currenciesRepository = currenciesRepository,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -41,32 +41,44 @@ internal class YieldSupply(
|
|||
private fun createDevEnvironment(): ApiEnvironmentConfig = ApiEnvironmentConfig(
|
||||
environment = ApiEnvironment.DEV,
|
||||
baseUrl = "[REDACTED_ENV_URL]",
|
||||
headers = createHeaders(),
|
||||
headers = createHeaders(ApiEnvironment.DEV),
|
||||
)
|
||||
|
||||
private fun createStageEnvironment(): ApiEnvironmentConfig = ApiEnvironmentConfig(
|
||||
environment = ApiEnvironment.STAGE,
|
||||
baseUrl = "[REDACTED_ENV_URL]",
|
||||
headers = createHeaders(),
|
||||
headers = createHeaders(ApiEnvironment.STAGE),
|
||||
)
|
||||
|
||||
private fun createMockedEnvironment(): ApiEnvironmentConfig = ApiEnvironmentConfig(
|
||||
environment = ApiEnvironment.MOCK,
|
||||
baseUrl = "[REDACTED_ENV_URL]",
|
||||
headers = createHeaders(),
|
||||
headers = createHeaders(ApiEnvironment.MOCK),
|
||||
)
|
||||
|
||||
private fun createProdEnvironment(): ApiEnvironmentConfig = ApiEnvironmentConfig(
|
||||
environment = ApiEnvironment.PROD,
|
||||
baseUrl = "https://yield.tangem.org/",
|
||||
headers = createHeaders(),
|
||||
headers = createHeaders(ApiEnvironment.PROD),
|
||||
)
|
||||
|
||||
private fun createHeaders() = buildMap {
|
||||
private fun createHeaders(apiEnvironment: ApiEnvironment) = buildMap {
|
||||
put(key = "api-key", value = ProviderSuspend {
|
||||
environmentConfigStorage.getConfigSync().yieldModuleApiKey.orEmpty()
|
||||
getApiKey(apiEnvironment)
|
||||
})
|
||||
putAll(from = RequestHeader.AppVersionPlatformHeaders(appVersionProvider, appInfoProvider).values)
|
||||
putAll(from = RequestHeader.AuthenticationHeader(authProvider).values)
|
||||
}
|
||||
|
||||
private fun getApiKey(apiEnvironment: ApiEnvironment): String {
|
||||
return when (apiEnvironment) {
|
||||
ApiEnvironment.MOCK,
|
||||
ApiEnvironment.DEV,
|
||||
ApiEnvironment.DEV_2,
|
||||
ApiEnvironment.DEV_3,
|
||||
ApiEnvironment.STAGE,
|
||||
-> environmentConfigStorage.getConfigSync().yieldModuleApiKeyDev
|
||||
ApiEnvironment.PROD -> environmentConfigStorage.getConfigSync().yieldModuleApiKey
|
||||
} ?: error("No tangem tech api config provided")
|
||||
}
|
||||
}
|
||||
|
|
@ -21,4 +21,5 @@ data class EnvironmentConfig(
|
|||
val tangemApiKeyDev: String? = null,
|
||||
val tangemApiKeyStage: String? = null,
|
||||
val yieldModuleApiKey: String? = null,
|
||||
val yieldModuleApiKeyDev: String? = null,
|
||||
)
|
||||
|
|
@ -30,6 +30,7 @@ internal object EnvironmentConfigConverter : Converter<EnvironmentConfigModel, E
|
|||
tangemApiKeyDev = value.tangemApiKeyDev,
|
||||
tangemApiKeyStage = value.tangemApiKeyStage,
|
||||
yieldModuleApiKey = value.yieldModuleApiKey,
|
||||
yieldModuleApiKeyDev = value.yieldModuleApiKeyDev,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -45,6 +45,7 @@ class EnvironmentConfigModel(
|
|||
@Json(name = "tangemApiKeyStage") val tangemApiKeyStage: String?,
|
||||
@Json(name = "etherscanApiKey") val etherScanApiKey: String?,
|
||||
@Json(name = "yieldModuleApiKey") val yieldModuleApiKey: String?,
|
||||
@Json(name = "yieldModuleApiKeyDev") val yieldModuleApiKeyDev: String?,
|
||||
@Json(name = "blinkApiKey") val blinkApiKey: String?,
|
||||
@Json(name = "tatumApiKey") val tatumApiKey: String?,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ internal class MockEnvironmentConfigStorage : EnvironmentConfigStorage {
|
|||
tangemApiKeyDev = TANGEM_API_KEY_DEV,
|
||||
tangemApiKeyStage = TANGEM_API_KEY_STAGE,
|
||||
yieldModuleApiKey = YIELD_MODULE_KEY,
|
||||
yieldModuleApiKeyDev = YIELD_MODULE_KEY_DEV,
|
||||
)
|
||||
|
||||
override suspend fun initialize() = environmentConfig
|
||||
|
|
@ -34,5 +35,6 @@ internal class MockEnvironmentConfigStorage : EnvironmentConfigStorage {
|
|||
const val TANGEM_API_KEY_DEV = "tangem_api_key_dev"
|
||||
const val TANGEM_API_KEY_STAGE = "tangem_api_key_stage"
|
||||
const val YIELD_MODULE_KEY = "yield_module_api_key"
|
||||
const val YIELD_MODULE_KEY_DEV = "yield_module_api_key_dev"
|
||||
}
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@
|
|||
<string name="account_archived_recover_error_message">すでにアクティブアカウントの上限(20件)に達しています。復元するには、1つをアーカイブしてください。</string>
|
||||
<string name="account_archived_recover_error_title">アカウントを復元できません</string>
|
||||
<string name="account_archived_title">アーカイブ済み</string>
|
||||
<string name="account_could_not_archive">アカウントをアーカイブできませんでした。しばらくしてからもう一度お試しください。</string>
|
||||
<string name="account_could_not_create">アカウントを作成できませんでした。しばらくしてからもう一度お試しください。</string>
|
||||
<string name="account_create_success_message">アカウントを作成しました</string>
|
||||
<string name="account_details_archive">アカウントをアーカイブする</string>
|
||||
|
|
@ -249,10 +250,12 @@
|
|||
<string name="common_fee_selector_option_slow">遅い</string>
|
||||
<string name="common_fee_selector_title">速度と料金</string>
|
||||
<string name="common_finish">終了</string>
|
||||
<string name="common_forget">忘れる</string>
|
||||
<string name="common_free">無料</string>
|
||||
<string name="common_from">送信元</string>
|
||||
<string name="common_generate_addresses">アドレスを同期する</string>
|
||||
<string name="common_get_started">はじめる</string>
|
||||
<string name="common_get_token">トークンを取得</string>
|
||||
<string name="common_go_to_provider">プロバイダーへ移動</string>
|
||||
<string name="common_go_to_token">トークンへ移動</string>
|
||||
<string name="common_got_it">わかりました</string>
|
||||
|
|
@ -526,14 +529,20 @@
|
|||
<string name="hw_activation_need_warning_description">アクセスコードでアプリを保護して、設定を完了してください。</string>
|
||||
<string name="hw_backup_alert_description">そうした場合は、最初からやり直す必要があります。</string>
|
||||
<string name="hw_backup_alert_title">本当にアクティベーション処理を終了してもよろしいですか?</string>
|
||||
<string name="hw_backup_banner_description">暗号資産をオフラインで厳重保管。カードサイズで、金庫以上の安心を。</string>
|
||||
<string name="hw_backup_close_description">実行すると、最初からやり直す必要があります。</string>
|
||||
<string name="hw_backup_google_drive_description">Googleドライブのバックアップから既存のウォレットを復元する</string>
|
||||
<string name="hw_backup_google_drive_title">Googleドライブのバックアップ</string>
|
||||
<string name="hw_backup_hardware_create_description">さらに強固なセキュリティのために、新しいウォレットを作成して資産を移動しましょう。</string>
|
||||
<string name="hw_backup_hardware_create_title">新しいウォレットを作成</string>
|
||||
<string name="hw_backup_hardware_description">Tangemの高性能ハードウェアウォレットで、セキュリティをさらに強化しましょう。</string>
|
||||
<string name="hw_backup_hardware_title">ハードウェアウォレット</string>
|
||||
<string name="hw_backup_hardware_upgrade_description">現在のウォレットをTangemウォレットに移します。</string>
|
||||
<string name="hw_backup_hardware_upgrade_title">現在のウォレットをアップグレードする</string>
|
||||
<string name="hw_backup_need_action">バックアップへ移動</string>
|
||||
<string name="hw_backup_need_description">アクセスコードを作成する前にウォレットをバックアップしてください。</string>
|
||||
<string name="hw_backup_need_title">まずバックアップを完了する</string>
|
||||
<string name="hw_backup_section_other_title">その他の方法</string>
|
||||
<string name="hw_backup_seed_description">秘密鍵をオフラインで安全に保存する物理デバイス。</string>
|
||||
<string name="hw_backup_seed_title">リカバリーフレーズ</string>
|
||||
<string name="hw_create_keys_title">鍵はアプリに保存されます</string>
|
||||
|
|
@ -603,6 +612,7 @@
|
|||
<string name="manage_tokens_unavailable_description">選択したトークンは現在、暗号資産ウォレット内でのアクションには利用できません。しかし、心配しないでください。賛成票を投じることで関心を表明できます。</string>
|
||||
<string name="manage_tokens_unavailable_vote">賛成票を投じる</string>
|
||||
<string name="manage_tokens_wallet_support_only_one_network_title">ウォレットは複数のネットワークをサポートしていません。</string>
|
||||
<string name="markets_about_coin_header">コインについて</string>
|
||||
<string name="markets_add_to_my_portfolio_description">このアセットを購入・交換・受け取るには、ポートフォリオに追加してください。</string>
|
||||
<string name="markets_add_to_my_portfolio_unavailable_description">このアセットは現在ウォレットで利用できません</string>
|
||||
<string name="markets_add_to_my_portfolio_unavailable_for_wallet_description">このアセットはこのウォレットでは使用できません。</string>
|
||||
|
|
@ -638,6 +648,7 @@
|
|||
<string name="markets_sort_by_trending_title">トレンド</string>
|
||||
<string name="markets_staking_banner_description_placeholder">ステーキングは暗号資産で報酬を受け取る最も簡単な方法です。 %s</string>
|
||||
<string name="markets_staking_banner_title">最大%s APYを獲得</string>
|
||||
<string name="markets_token_added">トークンを追加しました</string>
|
||||
<string name="markets_token_details_about_token_title">%sについて</string>
|
||||
<plurals name="markets_token_details_amount_exchanges">
|
||||
<item quantity="other">%d取引所</item>
|
||||
|
|
@ -895,7 +906,7 @@
|
|||
<item quantity="other">最大%d日</item>
|
||||
</plurals>
|
||||
<string name="onramp_timing_minutes">%s分</string>
|
||||
<string name="onramp_title_available_from">下記より利用可能</string>
|
||||
<string name="onramp_title_available_from">利用可能:</string>
|
||||
<string name="onramp_title_you_get">以下が手に入ります。</string>
|
||||
<string name="onramp_tos_external_providers">サービスは外部プロバイダーによって提供されます。 \nTangemは責任を負いません。</string>
|
||||
<string name="onramp_transaction_status_footer_text">この画面を閉じて、トークンの詳細画面で取引状況を確認できます。</string>
|
||||
|
|
@ -1275,7 +1286,20 @@
|
|||
<string name="swapping_to_title">受け取る</string>
|
||||
<string name="swapping_token_list_title">トークンを選択</string>
|
||||
<string name="swapping_token_not_available">利用不可</string>
|
||||
<string name="tangem_pay_deposit">入金</string>
|
||||
<string name="tangem_pay_dispute">異議申し立て</string>
|
||||
<string name="tangem_pay_explore_transaction">取引を表示</string>
|
||||
<string name="tangem_pay_fee_subtitle">サービス手数料</string>
|
||||
<string name="tangem_pay_fee_title">手数料</string>
|
||||
<string name="tangem_pay_status_completed">完了</string>
|
||||
<string name="tangem_pay_status_declined">拒否</string>
|
||||
<string name="tangem_pay_status_pending">保留中</string>
|
||||
<string name="tangem_pay_transaction_declined_notification_text">銀行がこの取引リクエストを拒否しました。</string>
|
||||
<string name="tangem_pay_transaction_fee_notification_text">この手数料は、送金処理にかかるコストをカバーするためのものです。</string>
|
||||
<string name="tangem_pay_withdrawal">出金</string>
|
||||
<string name="tangempay_card_details_change_pin">PINを変更する</string>
|
||||
<string name="tangempay_card_details_error_text">データの読み込みに失敗しました。しばらくしてからもう一度お試しください。</string>
|
||||
<string name="tangempay_card_details_freeze_card">カードの一時停止</string>
|
||||
<string name="tangempay_card_details_hide_text">非表示</string>
|
||||
<string name="tangempay_card_details_receive_error_description">技術的な問題が検出されました。しばらくしてからもう一度お試しいただくか、サポートにお問い合わせください。</string>
|
||||
<string name="tangempay_card_details_receive_error_title">現在、受け取りは利用できません</string>
|
||||
|
|
@ -1310,6 +1334,7 @@
|
|||
<string name="token_button_unavailability_reason_pending_transaction_send">ネットワーク%s内の保留中の取引が完了すると、送金が可能になります。</string>
|
||||
<string name="token_button_unavailability_reason_sell_unavailable">%sの売却は、現在のプロバイダーではサポートされていませんが、より多くのオプションを追加できるよう取り組んでいます。</string>
|
||||
<string name="token_button_unavailability_reason_staking_unavailable">%sのステーキングは、現在のプロバイダーではサポートされていませんが、より多くのオプションを追加できるよう取り組んでいます。</string>
|
||||
<string name="token_button_unavailability_reason_yield_supply_approval">ここにテキストを入力</string>
|
||||
<string name="token_details_generate_xpub">XPUBを生成する</string>
|
||||
<string name="token_details_hide_alert_hide">非表示</string>
|
||||
<string name="token_details_hide_alert_message">このトークンをメイン画面から非表示にします。トークンの管理ページからいつでも再度追加できます。</string>
|
||||
|
|
@ -1729,10 +1754,10 @@
|
|||
<string name="yield_module_fee_policy_sheet_description">今後の%sの入金はすべて、取引手数料が差し引かれて自動的にAaveに供給されます。</string>
|
||||
<string name="yield_module_fee_policy_sheet_max_fee_note">ネットワーク手数料が上限手数料を超えた場合、手数料が下がるまで取引は成立しません。この制限は後で変更できます。</string>
|
||||
<string name="yield_module_fee_policy_sheet_max_fee_title">最大手数料</string>
|
||||
<string name="yield_module_fee_policy_sheet_min_amount_note">取引手数料は、預入額の4%未満である必要があります。Tangemは、この条件を満たす十分な残高が貯まった時点で、Aaveへの資金移動を行います。</string>
|
||||
<string name="yield_module_fee_policy_sheet_min_amount_note">取引手数料は入金額の4%未満である必要があります。残高がこの条件を満たすのに十分な金額になった場合にのみ、TangemはAaveに資金を送ります。</string>
|
||||
<string name="yield_module_fee_policy_sheet_min_amount_title">最低入金額</string>
|
||||
<string name="yield_module_fee_policy_sheet_title">手数料ポリシー</string>
|
||||
<string name="yield_module_fee_policy_tangem_service_fee_title">Tangemはまた、得られた利回りに対して3%のサービス手数料を差し引きます。</string>
|
||||
<string name="yield_module_fee_policy_tangem_service_fee_title">Tangemはまた、得られた利回りに対して3%のサービス手数料を差し引きます。</string>
|
||||
<string name="yield_module_high_fee_error">ネットワーク手数料が現在高すぎます。設定した上限を下回るまで待機しています。</string>
|
||||
<string name="yield_module_historical_returns">過去のリターン</string>
|
||||
<string name="yield_module_main_view_approve_notification_description">ここに説明を入力してください。1〜3行が理想的です。[プレースホルダー]</string>
|
||||
|
|
@ -1748,7 +1773,7 @@
|
|||
<string name="yield_module_promo_screen_self_custodial_title">分散型・自己管理型</string>
|
||||
<string name="yield_module_promo_screen_terms_disclaimer">サービスを利用することにより、プロバイダー\n %1$sおよび%2$sに同意したことになります</string>
|
||||
<string name="yield_module_promo_screen_title">年間%s%%の収益</string>
|
||||
<string name="yield_module_promo_screen_variable_rate_info">Aave • 変動金利</string>
|
||||
<string name="yield_module_promo_screen_variable_rate_info">Aave %1$s%% • 変動金利</string>
|
||||
<string name="yield_module_provider">Aave</string>
|
||||
<string name="yield_module_rate_info_sheet_chart_average">平均%s</string>
|
||||
<string name="yield_module_rate_info_sheet_chart_title">昨年のリターン</string>
|
||||
|
|
|
|||
|
|
@ -542,8 +542,12 @@
|
|||
<string name="hw_backup_close_description">If you do, you\'ll need to start over.</string>
|
||||
<string name="hw_backup_google_drive_description">Recover existing wallet via Google Drive backup</string>
|
||||
<string name="hw_backup_google_drive_title">Google Drive backup</string>
|
||||
<string name="hw_backup_hardware_create_description">Create a new secure wallet and transfer your funds for extra protection.</string>
|
||||
<string name="hw_backup_hardware_create_title">Create new wallet</string>
|
||||
<string name="hw_backup_hardware_description">Level up your security with the superior Tangem hardware wallet.</string>
|
||||
<string name="hw_backup_hardware_title">Hardware Wallet</string>
|
||||
<string name="hw_backup_hardware_upgrade_description">Move your current wallet into Tangem Wallet.</string>
|
||||
<string name="hw_backup_hardware_upgrade_title">Upgrade current wallet</string>
|
||||
<string name="hw_backup_need_action">Go to backup</string>
|
||||
<string name="hw_backup_need_description">Please back up your wallet before creating an access code.</string>
|
||||
<string name="hw_backup_need_title">Finalize backup first</string>
|
||||
|
|
@ -1813,6 +1817,8 @@
|
|||
<string name="yield_module_earn_badge">APY %1$s%%</string>
|
||||
<string name="yield_module_earn_sheet_available_title">Available</string>
|
||||
<string name="yield_module_earn_sheet_current_apy_title">Current APY</string>
|
||||
<string name="yield_module_earn_sheet_fee_description">When topping up for lending, a network fee will be deducted from the amount — never more than %1$s</string>
|
||||
<string name="yield_module_earn_sheet_high_fee_description">The network fee is currently too high to execute lending. Funds will be supplied once it drops to %1$s or below. </string>
|
||||
<string name="yield_module_earn_sheet_my_funds_title">My funds</string>
|
||||
<string name="yield_module_earn_sheet_provider_description">Your %1$s is now deposited in Aave and earning interest. You hold a%2$s token, which represents your balance and grows over time. When you top up, funds go to Aave to earn interest, minus a transaction fee.</string>
|
||||
<string name="yield_module_earn_sheet_title">Earn</string>
|
||||
|
|
@ -1824,7 +1830,7 @@
|
|||
<string name="yield_module_fee_policy_sheet_description">All future %s top-ups will be supplied to Aave automatically, with the transaction fee deducted.</string>
|
||||
<string name="yield_module_fee_policy_sheet_max_fee_note">If network fees rise above maximum fee, the transaction won’t go through until they decrease. You can change this limit later.</string>
|
||||
<string name="yield_module_fee_policy_sheet_max_fee_title">Maximum fee</string>
|
||||
<string name="yield_module_fee_policy_sheet_min_amount_note">The transaction fee must stay below 4% of your deposit. Tangem will transfer funds to Aave only once your balance is large enough to meet this condition. </string>
|
||||
<string name="yield_module_fee_policy_sheet_min_amount_note">The transaction fee must stay below 4% of your deposit. Tangem will transfer funds to Aave only once your balance is large enough to meet this condition.</string>
|
||||
<string name="yield_module_fee_policy_sheet_min_amount_title">Minimal top-up</string>
|
||||
<string name="yield_module_fee_policy_sheet_title">Fee policy</string>
|
||||
<string name="yield_module_fee_policy_tangem_service_fee_title">Tangem also takes a 3% service fee on the yield earned.</string>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
package com.tangem.domain.yield.supply
|
||||
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import java.math.BigInteger
|
||||
|
||||
fun Fee.fixFee(cryptoCurrency: CryptoCurrency, gasLimit: BigInteger): Fee = when (this) {
|
||||
is Fee.Ethereum.Legacy -> copy(
|
||||
gasLimit = gasLimit,
|
||||
amount = amount.copy(
|
||||
value = gasPrice.multiply(gasLimit)
|
||||
.toBigDecimal().movePointLeft(cryptoCurrency.decimals),
|
||||
),
|
||||
)
|
||||
is Fee.Ethereum.EIP1559 -> copy(
|
||||
gasLimit = gasLimit,
|
||||
amount = amount.copy(
|
||||
value = maxFeePerGas.multiply(gasLimit)
|
||||
.toBigDecimal().movePointLeft(cryptoCurrency.decimals),
|
||||
),
|
||||
)
|
||||
else -> this
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package com.tangem.domain.yield.supply
|
||||
|
||||
object YieldSupplyConst {
|
||||
val YIELD_SUPPLY_EVM_CONSTANT_GAS_LIMIT = 350_000.toBigInteger()
|
||||
}
|
||||
|
|
@ -3,17 +3,16 @@ package com.tangem.domain.yield.supply.usecase
|
|||
import arrow.core.Either
|
||||
import com.tangem.blockchain.blockchains.ethereum.EthereumTransactionExtras
|
||||
import com.tangem.blockchain.common.TransactionData
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.blockchain.yieldsupply.providers.ethereum.yield.EthereumYieldSupplyEnterCallData
|
||||
import com.tangem.domain.blockaid.BlockAidGasEstimate
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.yield.supply.fixFee
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.transaction.FeeRepository
|
||||
import com.tangem.domain.transaction.error.FeeErrorResolver
|
||||
import com.tangem.domain.transaction.error.GetFeeError
|
||||
import com.tangem.utils.extensions.isSingleItem
|
||||
import timber.log.Timber
|
||||
import java.math.BigInteger
|
||||
|
||||
class YieldSupplyEstimateEnterFeeUseCase(
|
||||
private val feeRepository: FeeRepository,
|
||||
|
|
@ -107,24 +106,6 @@ class YieldSupplyEstimateEnterFeeUseCase(
|
|||
return withCalculatedFees + withEstimatedFees
|
||||
}
|
||||
|
||||
private fun Fee.fixFee(cryptoCurrency: CryptoCurrency, gasLimit: BigInteger) = when (this) {
|
||||
is Fee.Ethereum.Legacy -> copy(
|
||||
gasLimit = gasLimit,
|
||||
amount = amount.copy(
|
||||
value = gasPrice.multiply(gasLimit)
|
||||
.toBigDecimal().movePointLeft(cryptoCurrency.decimals),
|
||||
),
|
||||
)
|
||||
is Fee.Ethereum.EIP1559 -> copy(
|
||||
gasLimit = gasLimit,
|
||||
amount = amount.copy(
|
||||
value = maxFeePerGas.multiply(gasLimit)
|
||||
.toBigDecimal().movePointLeft(cryptoCurrency.decimals),
|
||||
),
|
||||
)
|
||||
else -> this
|
||||
}
|
||||
|
||||
private companion object {
|
||||
// Using constant gas limit to avoid fee calculation errors when contract address is not deployed yet
|
||||
val ETHEREUM_CONSTANT_GAS_LIMIT = 500_000.toBigInteger()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
package com.tangem.domain.yield.supply.usecase
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.Either.Companion.catch
|
||||
import com.tangem.domain.yield.supply.fixFee
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.quote.QuoteStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.quotes.QuotesRepository
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.transaction.FeeRepository
|
||||
import com.tangem.domain.yield.supply.YieldSupplyConst.YIELD_SUPPLY_EVM_CONSTANT_GAS_LIMIT
|
||||
import java.math.BigDecimal
|
||||
import java.math.RoundingMode
|
||||
|
||||
/**
|
||||
* Calculates current fee for Yield Supply enter transaction expressed in token units.
|
||||
*/
|
||||
class YieldSupplyGetCurrentFeeUseCase(
|
||||
private val feeRepository: FeeRepository,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(
|
||||
userWallet: UserWallet,
|
||||
cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
): Either<Throwable, BigDecimal> = catch {
|
||||
val feeWithoutGas = feeRepository.getEthereumFeeWithoutGas(userWallet, cryptoCurrencyStatus.currency)
|
||||
|
||||
val fiatRate = cryptoCurrencyStatus.value.fiatRate ?: error("Fiat rate is missing")
|
||||
require(fiatRate > BigDecimal.ZERO) { "Fiat rate for token must be > 0" }
|
||||
|
||||
val nativeCryptoCurrency = currenciesRepository.getNetworkCoin(
|
||||
userWalletId = userWallet.walletId,
|
||||
networkId = cryptoCurrencyStatus.currency.network.id,
|
||||
derivationPath = cryptoCurrencyStatus.currency.network.derivationPath,
|
||||
)
|
||||
|
||||
val quotes =
|
||||
quotesRepository.getMultiQuoteSyncOrNull(setOfNotNull(nativeCryptoCurrency.id.rawCurrencyId))
|
||||
?: error("Quotes for native coin are unavailable")
|
||||
|
||||
val quotesStatus = quotes.firstOrNull() ?: error("Empty quotes list for native coin")
|
||||
|
||||
val nativeFiatRate = (quotesStatus.value as? QuoteStatus.Data)?.fiatRate
|
||||
?: error("Native fiat rate is missing")
|
||||
require(nativeFiatRate > BigDecimal.ZERO) { "Native fiat rate must be > 0" }
|
||||
|
||||
val nativeGas = feeWithoutGas.fixFee(
|
||||
nativeCryptoCurrency,
|
||||
YIELD_SUPPLY_EVM_CONSTANT_GAS_LIMIT,
|
||||
)
|
||||
|
||||
val rateRatio = nativeFiatRate.divide(
|
||||
fiatRate,
|
||||
cryptoCurrencyStatus.currency.decimals,
|
||||
RoundingMode.HALF_UP,
|
||||
)
|
||||
|
||||
val tokenValue = rateRatio.multiply(nativeGas.amount.value)
|
||||
|
||||
tokenValue.stripTrailingZeros()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
package com.tangem.domain.yield.supply.usecase
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.Either.Companion.catch
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.quote.QuoteStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.quotes.QuotesRepository
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.yield.supply.YieldSupplyRepository
|
||||
import java.math.BigDecimal
|
||||
import java.math.RoundingMode
|
||||
|
||||
/**
|
||||
* Calculates max allowed network fee for Yield Supply enter transaction expressed in token units.
|
||||
*
|
||||
* Uses YieldMarketToken.maxFeeNative (native coin units) and converts it to token units with the
|
||||
* same conversion logic as [YieldSupplyGetCurrentFeeUseCase]: based on fiat rate ratio
|
||||
* (nativeFiatRate / tokenFiatRate).
|
||||
*/
|
||||
class YieldSupplyGetMaxFeeUseCase(
|
||||
private val yieldSupplyRepository: YieldSupplyRepository,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(
|
||||
userWallet: UserWallet,
|
||||
cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
): Either<Throwable, BigDecimal> = catch {
|
||||
val token = cryptoCurrencyStatus.currency as? CryptoCurrency.Token
|
||||
?: error("CryptoCurrency must be token for max fee calculation")
|
||||
|
||||
val fiatRate = cryptoCurrencyStatus.value.fiatRate ?: error("Fiat rate is missing")
|
||||
require(fiatRate > BigDecimal.ZERO) { "Fiat rate for token must be > 0" }
|
||||
|
||||
val nativeCryptoCurrency = currenciesRepository.getNetworkCoin(
|
||||
userWalletId = userWallet.walletId,
|
||||
networkId = cryptoCurrencyStatus.currency.network.id,
|
||||
derivationPath = cryptoCurrencyStatus.currency.network.derivationPath,
|
||||
)
|
||||
|
||||
val quotes =
|
||||
quotesRepository.getMultiQuoteSyncOrNull(setOfNotNull(nativeCryptoCurrency.id.rawCurrencyId))
|
||||
?: error("Quotes for native coin are unavailable")
|
||||
|
||||
val quotesStatus = quotes.firstOrNull() ?: error("Empty quotes list for native coin")
|
||||
|
||||
val nativeFiatRate = (quotesStatus.value as? QuoteStatus.Data)?.fiatRate
|
||||
?: error("Native fiat rate is missing")
|
||||
require(nativeFiatRate > BigDecimal.ZERO) { "Native fiat rate must be > 0" }
|
||||
|
||||
val marketToken = yieldSupplyRepository.getTokenStatus(token)
|
||||
val maxFeeNative = marketToken.maxFeeNative.toBigDecimal()
|
||||
|
||||
val rateRatio = nativeFiatRate.divide(
|
||||
fiatRate,
|
||||
cryptoCurrencyStatus.currency.decimals,
|
||||
RoundingMode.HALF_UP,
|
||||
)
|
||||
|
||||
val tokenValue = rateRatio.multiply(maxFeeNative)
|
||||
|
||||
tokenValue.stripTrailingZeros()
|
||||
}
|
||||
}
|
||||
|
|
@ -2,16 +2,15 @@ package com.tangem.domain.yield.supply.usecase
|
|||
|
||||
import arrow.core.Either
|
||||
import arrow.core.Either.Companion.catch
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.yield.supply.fixFee
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.quote.QuoteStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.quotes.QuotesRepository
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.transaction.FeeRepository
|
||||
import com.tangem.domain.yield.supply.YieldSupplyConst.YIELD_SUPPLY_EVM_CONSTANT_GAS_LIMIT
|
||||
import java.math.BigDecimal
|
||||
import java.math.BigInteger
|
||||
import java.math.RoundingMode
|
||||
|
||||
class YieldSupplyMinAmountUseCase(
|
||||
|
|
@ -45,7 +44,10 @@ class YieldSupplyMinAmountUseCase(
|
|||
?: error("Native fiat rate is missing")
|
||||
require(nativeFiatRate > BigDecimal.ZERO) { "Native fiat rate must be > 0" }
|
||||
|
||||
val nativeGas = feeWithoutGas.fixFee(nativeCryptoCurrency, ETHEREUM_CONSTANT_GAS_LIMIT)
|
||||
val nativeGas = feeWithoutGas.fixFee(
|
||||
nativeCryptoCurrency,
|
||||
YIELD_SUPPLY_EVM_CONSTANT_GAS_LIMIT,
|
||||
)
|
||||
|
||||
val rateRatio = nativeFiatRate.divide(
|
||||
fiatRate,
|
||||
|
|
@ -62,27 +64,8 @@ class YieldSupplyMinAmountUseCase(
|
|||
.stripTrailingZeros()
|
||||
}
|
||||
|
||||
private fun Fee.fixFee(cryptoCurrency: CryptoCurrency, gasLimit: BigInteger) = when (this) {
|
||||
is Fee.Ethereum.Legacy -> copy(
|
||||
gasLimit = gasLimit,
|
||||
amount = amount.copy(
|
||||
value = gasPrice.multiply(gasLimit)
|
||||
.toBigDecimal().movePointLeft(cryptoCurrency.decimals),
|
||||
),
|
||||
)
|
||||
is Fee.Ethereum.EIP1559 -> copy(
|
||||
gasLimit = gasLimit,
|
||||
amount = amount.copy(
|
||||
value = maxFeePerGas.multiply(gasLimit)
|
||||
.toBigDecimal().movePointLeft(cryptoCurrency.decimals),
|
||||
),
|
||||
)
|
||||
else -> this
|
||||
}
|
||||
|
||||
private companion object {
|
||||
val FEE_BUFFER_MULTIPLIER: BigDecimal = BigDecimal("1.25")
|
||||
val MAX_FEE_PERCENT: BigDecimal = BigDecimal("0.04")
|
||||
val ETHEREUM_CONSTANT_GAS_LIMIT = 350_000.toBigInteger()
|
||||
}
|
||||
}
|
||||
|
|
@ -2,24 +2,38 @@ package com.tangem.features.yield.supply.impl.common.formatter
|
|||
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.format.bigdecimal.approximateAmount
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.utils.StringsSigns
|
||||
import com.tangem.utils.StringsSigns.DOT
|
||||
import java.math.BigDecimal
|
||||
|
||||
internal class YieldSupplyMinAmountFormatter(
|
||||
internal class YieldSupplyAmountFormatter(
|
||||
private val feeCryptoCurrency: CryptoCurrency,
|
||||
private val appCurrency: AppCurrency,
|
||||
) {
|
||||
|
||||
operator fun invoke(feeValue: BigDecimal, fiatRate: BigDecimal?): TextReference {
|
||||
operator fun invoke(feeValue: BigDecimal, fiatRate: BigDecimal?, showCrypto: Boolean = true): TextReference {
|
||||
val cryptoFee = feeValue.format { crypto(feeCryptoCurrency) }
|
||||
val fiatFeeValue = fiatRate?.let(feeValue::multiply)
|
||||
val fiatFee = fiatFeeValue.format { fiat(appCurrency.code, appCurrency.symbol) }
|
||||
val fiatFee = if (showCrypto) {
|
||||
fiatFeeValue.format {
|
||||
fiat(appCurrency.code, appCurrency.symbol)
|
||||
.approximateAmount()
|
||||
}
|
||||
} else {
|
||||
fiatFeeValue.format {
|
||||
fiat(appCurrency.code, appCurrency.symbol)
|
||||
}
|
||||
}
|
||||
|
||||
return stringReference(cryptoFee + " ${StringsSigns.DOT} " + fiatFee)
|
||||
return if (showCrypto) {
|
||||
stringReference("$cryptoFee $DOT $fiatFee")
|
||||
} else {
|
||||
stringReference(fiatFee)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.SpacerWMax
|
||||
import com.tangem.core.ui.components.TextShimmer
|
||||
|
|
@ -46,6 +47,7 @@ internal fun YieldSupplyFeeRow(title: TextReference, value: TextReference?) {
|
|||
text = targetValue.resolveReference(),
|
||||
style = TangemTheme.typography.body1,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
textAlign = TextAlign.End,
|
||||
)
|
||||
} else {
|
||||
TextShimmer(
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ internal data class YieldSupplyActiveContentUM(
|
|||
val subtitle: TextReference,
|
||||
val subtitleLink: TextReference,
|
||||
val notificationUM: NotificationUM?,
|
||||
val apy: TextReference? = null,
|
||||
val minAmount: TextReference?,
|
||||
val currentFee: TextReference?,
|
||||
val feeDescription: TextReference?,
|
||||
val apy: TextReference? = null,
|
||||
val isHighFee: Boolean = false,
|
||||
)
|
||||
|
|
@ -12,6 +12,7 @@ import com.tangem.core.ui.extensions.resourceReference
|
|||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
|
|
@ -19,9 +20,11 @@ import com.tangem.domain.models.currency.CryptoCurrency
|
|||
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetProtocolBalanceUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetTokenStatusUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyMinAmountUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetCurrentFeeUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetMaxFeeUseCase
|
||||
import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics
|
||||
import com.tangem.features.yield.supply.impl.R
|
||||
import com.tangem.features.yield.supply.impl.common.formatter.YieldSupplyMinAmountFormatter
|
||||
import com.tangem.features.yield.supply.impl.common.formatter.YieldSupplyAmountFormatter
|
||||
import com.tangem.features.yield.supply.impl.subcomponents.active.YieldSupplyActiveComponent
|
||||
import com.tangem.features.yield.supply.impl.subcomponents.active.entity.YieldSupplyActiveContentUM
|
||||
import com.tangem.utils.StringsSigns.DASH_SIGN
|
||||
|
|
@ -40,6 +43,8 @@ internal class YieldSupplyActiveModel @Inject constructor(
|
|||
private val yieldSupplyGetProtocolBalanceUseCase: YieldSupplyGetProtocolBalanceUseCase,
|
||||
private val yieldSupplyGetTokenStatusUseCase: YieldSupplyGetTokenStatusUseCase,
|
||||
private val yieldSupplyMinAmountUseCase: YieldSupplyMinAmountUseCase,
|
||||
private val yieldSupplyGetCurrentFeeUseCase: YieldSupplyGetCurrentFeeUseCase,
|
||||
private val yieldSupplyGetMaxFeeUseCase: YieldSupplyGetMaxFeeUseCase,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
) : Model() {
|
||||
|
||||
|
|
@ -62,6 +67,9 @@ internal class YieldSupplyActiveModel @Inject constructor(
|
|||
subtitleLink = resourceReference(R.string.common_read_more),
|
||||
notificationUM = null,
|
||||
minAmount = null,
|
||||
currentFee = null,
|
||||
feeDescription = null,
|
||||
isHighFee = false,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -115,6 +123,7 @@ internal class YieldSupplyActiveModel @Inject constructor(
|
|||
|
||||
loadApy()
|
||||
loadMinAmount()
|
||||
loadFees()
|
||||
|
||||
uiState.update {
|
||||
it.copy(
|
||||
|
|
@ -154,10 +163,14 @@ internal class YieldSupplyActiveModel @Inject constructor(
|
|||
params.userWallet,
|
||||
cryptoCurrencyStatusFlow.value,
|
||||
).onRight { minAmount ->
|
||||
val minAmountTextReference = YieldSupplyMinAmountFormatter(
|
||||
val minAmountTextReference = YieldSupplyAmountFormatter(
|
||||
cryptoCurrencyStatusFlow.value.currency,
|
||||
appCurrency,
|
||||
).invoke(minAmount, cryptoCurrencyStatusFlow.value.value.fiatRate)
|
||||
).invoke(
|
||||
feeValue = minAmount,
|
||||
fiatRate = cryptoCurrencyStatusFlow.value.value.fiatRate,
|
||||
showCrypto = false,
|
||||
)
|
||||
uiState.update {
|
||||
it.copy(minAmount = minAmountTextReference)
|
||||
}
|
||||
|
|
@ -169,6 +182,51 @@ internal class YieldSupplyActiveModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun loadFees() {
|
||||
modelScope.launch(dispatchers.default) {
|
||||
val cryptoStatus = cryptoCurrencyStatusFlow.value
|
||||
|
||||
val currentFee = yieldSupplyGetCurrentFeeUseCase(
|
||||
userWallet = params.userWallet,
|
||||
cryptoCurrencyStatus = cryptoStatus,
|
||||
).getOrNull()
|
||||
|
||||
val maxFee = yieldSupplyGetMaxFeeUseCase(
|
||||
userWallet = params.userWallet,
|
||||
cryptoCurrencyStatus = cryptoStatus,
|
||||
).getOrNull()
|
||||
|
||||
val currentFeeText = currentFee?.let {
|
||||
YieldSupplyAmountFormatter(
|
||||
cryptoStatus.currency,
|
||||
appCurrency,
|
||||
).invoke(
|
||||
feeValue = it,
|
||||
fiatRate = cryptoStatus.value.fiatRate,
|
||||
showCrypto = false,
|
||||
)
|
||||
}
|
||||
|
||||
val isHighFee = if (currentFee != null && maxFee != null) currentFee > maxFee else false
|
||||
|
||||
val maxFiatFee = cryptoStatus.value.fiatRate?.multiply(maxFee)
|
||||
.format { fiat(appCurrency.code, appCurrency.symbol) }
|
||||
val feeDescription = if (isHighFee) {
|
||||
resourceReference(R.string.yield_module_earn_sheet_high_fee_description, wrappedList(maxFiatFee))
|
||||
} else {
|
||||
resourceReference(R.string.yield_module_earn_sheet_fee_description, wrappedList(maxFiatFee))
|
||||
}
|
||||
|
||||
uiState.update {
|
||||
it.copy(
|
||||
currentFee = currentFeeText ?: stringReference(DASH_SIGN),
|
||||
isHighFee = isHighFee,
|
||||
feeDescription = feeDescription,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val AAVEV3_PREFIX = "a"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import androidx.compose.ui.graphics.vector.ImageVector
|
|||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.text.LinkAnnotation
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.withLink
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
|
|
@ -70,6 +71,22 @@ internal fun YieldSupplyActiveContent(
|
|||
}
|
||||
|
||||
YieldSupplyActiveMyFunds(state = state, isBalanceHidden = isBalanceHidden)
|
||||
|
||||
AnimatedVisibility(state.feeDescription != null) {
|
||||
Text(
|
||||
modifier = Modifier.padding(horizontal = 12.dp),
|
||||
text = state.feeDescription?.resolveReference().orEmpty(),
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
}
|
||||
|
||||
Text(
|
||||
modifier = Modifier.padding(horizontal = 12.dp),
|
||||
text = stringResourceSafe(R.string.yield_module_fee_policy_sheet_min_amount_note),
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -99,7 +116,9 @@ private fun CurrentApy(apy: TextReference?, modifier: Modifier = Modifier) {
|
|||
painterResource(R.drawable.ic_arrow_up_8),
|
||||
tint = TangemTheme.colors.text.accent,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.padding(end = 6.dp).size(12.dp),
|
||||
modifier = Modifier
|
||||
.padding(end = 6.dp)
|
||||
.size(12.dp),
|
||||
)
|
||||
Text(
|
||||
modifier = modifier,
|
||||
|
|
@ -113,6 +132,7 @@ private fun CurrentApy(apy: TextReference?, modifier: Modifier = Modifier) {
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("LongMethod")
|
||||
@Composable
|
||||
private fun YieldSupplyActiveMyFunds(state: YieldSupplyActiveContentUM, isBalanceHidden: Boolean) {
|
||||
Column(
|
||||
|
|
@ -173,6 +193,15 @@ private fun YieldSupplyActiveMyFunds(state: YieldSupplyActiveContentUM, isBalanc
|
|||
info = state.minAmount,
|
||||
isBalanceHidden = false,
|
||||
)
|
||||
HorizontalDivider(
|
||||
thickness = 0.5.dp,
|
||||
color = TangemTheme.colors.stroke.primary,
|
||||
)
|
||||
HighComissionInfoRow(
|
||||
title = resourceReference(R.string.common_network_fee_title),
|
||||
info = state.currentFee,
|
||||
isHighComission = state.isHighFee,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -220,6 +249,7 @@ private fun InfoRow(title: TextReference, isBalanceHidden: Boolean, info: TextRe
|
|||
text = currentInfo.orMaskWithStars(isBalanceHidden).resolveReference(),
|
||||
style = TangemTheme.typography.body1,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
textAlign = TextAlign.End,
|
||||
)
|
||||
} else {
|
||||
TextShimmer(
|
||||
|
|
@ -231,6 +261,57 @@ private fun InfoRow(title: TextReference, isBalanceHidden: Boolean, info: TextRe
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun HighComissionInfoRow(title: TextReference, info: TextReference?, isHighComission: Boolean) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||
modifier = Modifier.padding(horizontal = 4.dp, vertical = 12.dp),
|
||||
) {
|
||||
Text(
|
||||
text = title.resolveReference(),
|
||||
style = TangemTheme.typography.body1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
SpacerWMax()
|
||||
|
||||
AnimatedContent(info) { currentInfo ->
|
||||
if (currentInfo != null) {
|
||||
if (isHighComission) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(6.dp),
|
||||
) {
|
||||
Icon(
|
||||
painterResource(R.drawable.ic_token_info_24),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(20.dp),
|
||||
tint = TangemTheme.colors.text.warning,
|
||||
)
|
||||
Text(
|
||||
text = currentInfo.resolveReference(),
|
||||
style = TangemTheme.typography.body1,
|
||||
color = TangemTheme.colors.text.warning,
|
||||
textAlign = TextAlign.End,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Text(
|
||||
text = currentInfo.resolveReference(),
|
||||
style = TangemTheme.typography.body1,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
textAlign = TextAlign.End,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
TextShimmer(
|
||||
text = title.resolveReference(),
|
||||
style = TangemTheme.typography.body1,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// region Preview
|
||||
@Composable
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
|
|
@ -262,6 +343,12 @@ private class YieldSupplyActiveBottomSheetPreviewProvider : PreviewParameterProv
|
|||
notificationUM = NotificationUM.Error.InvalidAmount,
|
||||
apy = stringReference("5,14%"),
|
||||
minAmount = stringReference("50 USDT"),
|
||||
isHighFee = true,
|
||||
feeDescription = stringReference(
|
||||
"The network fee is currently too high to execute lending." +
|
||||
"Funds will be supplied once it drops to \$12 or below. ",
|
||||
),
|
||||
currentFee = stringReference("30 USDT"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import com.tangem.domain.appcurrency.model.AppCurrency
|
|||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM
|
||||
import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyFeeUM
|
||||
import com.tangem.features.yield.supply.impl.common.formatter.YieldSupplyMinAmountFormatter
|
||||
import com.tangem.features.yield.supply.impl.common.formatter.YieldSupplyAmountFormatter
|
||||
import com.tangem.utils.StringsSigns.DOT
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
|
@ -49,7 +49,7 @@ internal class YieldSupplyStartEarningFeeContentTransformer(
|
|||
}
|
||||
val maxFiatFee = maxFiatFeeValue.format { fiat(appCurrency.code, appCurrency.symbol) }
|
||||
|
||||
val minAmountTextReference = YieldSupplyMinAmountFormatter(
|
||||
val minAmountTextReference = YieldSupplyAmountFormatter(
|
||||
cryptoCurrency,
|
||||
appCurrency,
|
||||
).invoke(minAmount, cryptoCurrencyStatus.value.fiatRate)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue