diff --git a/app/src/main/java/com/flowfoundation/wallet/manager/config/AppConfig.kt b/app/src/main/java/com/flowfoundation/wallet/manager/config/AppConfig.kt index e49a5d71e..28551cfc8 100644 --- a/app/src/main/java/com/flowfoundation/wallet/manager/config/AppConfig.kt +++ b/app/src/main/java/com/flowfoundation/wallet/manager/config/AppConfig.kt @@ -39,6 +39,10 @@ object AppConfig { fun showTXWarning() = isDev() || isTesting() || (config().getFeatures().txWarning ?: false) + fun coverBridgeFee() = config().getFeatures().coverBridgeFee ?: false + + fun bridgeFeePayer() = if (isTestnet()) config().getBridgeFeePayer().testnet else config().getBridgeFeePayer().mainnet + fun addressRegistry(network: Int): Map { return when (network) { NETWORK_TESTNET -> flowAddressRegistry().testnet @@ -145,20 +149,32 @@ private data class Config( prod.payer } } + + fun getBridgeFeePayer(): Payer { + return if (isStagingVersion()) { + staging.bridgeFeePayer + } else { + prod.bridgeFeePayer + } + } } private data class Prod( @SerializedName("features") val features: Features, @SerializedName("payer") - val payer: Payer + val payer: Payer, + @SerializedName("bridgeFeePayer") + val bridgeFeePayer: Payer ) private data class Staging( @SerializedName("features") val features: Features, @SerializedName("payer") - val payer: Payer + val payer: Payer, + @SerializedName("bridgeFeePayer") + val bridgeFeePayer: Payer ) private data class Features( @@ -177,7 +193,9 @@ private data class Features( @SerializedName("nft_transfer") val nftTransfer: Boolean?, @SerializedName("tx_warning_prediction") - val txWarning: Boolean? + val txWarning: Boolean?, + @SerializedName("cover_bridge_fee") + val coverBridgeFee: Boolean?, ) private data class Payer( diff --git a/app/src/main/java/com/flowfoundation/wallet/manager/flowjvm/CadenceExecutor.kt b/app/src/main/java/com/flowfoundation/wallet/manager/flowjvm/CadenceExecutor.kt index 222290acf..08dc083b2 100644 --- a/app/src/main/java/com/flowfoundation/wallet/manager/flowjvm/CadenceExecutor.kt +++ b/app/src/main/java/com/flowfoundation/wallet/manager/flowjvm/CadenceExecutor.kt @@ -3,9 +3,11 @@ package com.flowfoundation.wallet.manager.flowjvm import com.flowfoundation.wallet.BuildConfig import com.flowfoundation.wallet.manager.coin.FlowCoin import com.flowfoundation.wallet.manager.coin.formatCadence +import com.flowfoundation.wallet.manager.config.AppConfig import com.flowfoundation.wallet.manager.config.NftCollection import com.flowfoundation.wallet.manager.flow.CadenceScriptBuilder import com.flowfoundation.wallet.manager.flow.FlowCadenceApi +import com.flowfoundation.wallet.manager.flowjvm.transaction.sendBridgeTransaction import com.flowfoundation.wallet.manager.flowjvm.transaction.sendTransaction import com.flowfoundation.wallet.manager.wallet.WalletManager import com.flowfoundation.wallet.mixpanel.MixpanelManager @@ -492,9 +494,16 @@ suspend fun cadenceBridgeNFTToEvm( nftId: String ): String? { logd(TAG, "cadenceBridgeNFTToEvm") - val transactionId = CadenceScript.CADENCE_BRIDGE_NFT_TO_EVM.transactionByMainWallet { - arg { string(nftIdentifier) } - arg { uint64(nftId) } + val transactionId = if (AppConfig.coverBridgeFee()) { + CadenceScript.CADENCE_BRIDGE_NFT_TO_EVM_WITH_PAYER.transactionWithBridgePayer { + arg { string(nftIdentifier) } + arg { uint64(nftId) } + } + } else { + CadenceScript.CADENCE_BRIDGE_NFT_TO_EVM.transactionByMainWallet { + arg { string(nftIdentifier) } + arg { uint64(nftId) } + } } logd(TAG, "cadenceBridgeNFTToEvm transactionId:$transactionId") return transactionId @@ -505,9 +514,16 @@ suspend fun cadenceBridgeNFTListToEvm( nftIdList: List ): String? { logd(TAG, "cadenceBridgeNFTListToEvm") - val transactionId = CadenceScript.CADENCE_BRIDGE_NFT_LIST_TO_EVM.transactionByMainWallet { - arg { string(nftIdentifier) } - arg { array(nftIdList.map { uint64(it) }) } + val transactionId = if (AppConfig.coverBridgeFee()) { + CadenceScript.CADENCE_BRIDGE_NFT_LIST_TO_EVM_WITH_PAYER.transactionWithBridgePayer { + arg { string(nftIdentifier) } + arg { array(nftIdList.map { uint64(it) }) } + } + } else { + CadenceScript.CADENCE_BRIDGE_NFT_LIST_TO_EVM.transactionByMainWallet { + arg { string(nftIdentifier) } + arg { array(nftIdList.map { uint64(it) }) } + } } logd(TAG, "cadenceBridgeNFTListToEvm transactionId:$transactionId") return transactionId @@ -518,9 +534,16 @@ suspend fun cadenceBridgeNFTListFromEvm( nftIdList: List ): String? { logd(TAG, "cadenceBridgeNFTListFromEvm") - val transactionId = CadenceScript.CADENCE_BRIDGE_NFT_LIST_FROM_EVM.transactionByMainWallet { - arg { string(nftIdentifier) } - arg { array(nftIdList.map { uint256(it) }) } + val transactionId = if (AppConfig.coverBridgeFee()) { + CadenceScript.CADENCE_BRIDGE_NFT_LIST_FROM_EVM_WITH_PAYER.transactionWithBridgePayer { + arg { string(nftIdentifier) } + arg { array(nftIdList.map { uint256(it) }) } + } + } else { + CadenceScript.CADENCE_BRIDGE_NFT_LIST_FROM_EVM.transactionByMainWallet { + arg { string(nftIdentifier) } + arg { array(nftIdList.map { uint256(it) }) } + } } logd(TAG, "cadenceBridgeNFTListFromEvm transactionId:$transactionId") return transactionId @@ -531,9 +554,16 @@ suspend fun cadenceBridgeNFTFromEvm( nftId: String ): String? { logd(TAG, "cadenceBridgeNFTFromEvm") - val transactionId = CadenceScript.CADENCE_BRIDGE_NFT_FROM_EVM.transactionByMainWallet { - arg { string(nftIdentifier) } - arg { uint256(nftId) } + val transactionId = if (AppConfig.coverBridgeFee()) { + CadenceScript.CADENCE_BRIDGE_NFT_FROM_EVM_WITH_PAYER.transactionWithBridgePayer { + arg { string(nftIdentifier) } + arg { uint256(nftId) } + } + } else { + CadenceScript.CADENCE_BRIDGE_NFT_FROM_EVM.transactionByMainWallet { + arg { string(nftIdentifier) } + arg { uint256(nftId) } + } } logd(TAG, "cadenceBridgeNFTFromEvm transactionId:$transactionId") return transactionId @@ -634,10 +664,18 @@ suspend fun cadenceBridgeNFTFromFlowToEVM( nftId: String, recipient: String ): String? { logd(TAG, "cadenceBridgeNFTFromFlowToEVM") - val transactionId = CadenceScript.CADENCE_BRIDGE_NFT_FROM_FLOW_TO_EVM.transactionByMainWallet { - arg { string(nftIdentifier) } - arg { uint64(nftId) } - arg { string(recipient) } + val transactionId = if (AppConfig.coverBridgeFee()) { + CadenceScript.CADENCE_BRIDGE_NFT_FROM_FLOW_TO_EVM_WITH_PAYER.transactionWithBridgePayer { + arg { string(nftIdentifier) } + arg { uint64(nftId) } + arg { address(recipient) } + } + } else { + CadenceScript.CADENCE_BRIDGE_NFT_FROM_FLOW_TO_EVM.transactionByMainWallet { + arg { string(nftIdentifier) } + arg { uint64(nftId) } + arg { string(recipient) } + } } logd(TAG, "cadenceBridgeNFTFromFlowToEVM transactionId:$transactionId") return transactionId @@ -648,10 +686,18 @@ suspend fun cadenceBridgeNFTFromEVMToFlow( nftId: String, recipient: String ): String? { logd(TAG, "cadenceBridgeNFTFromEVMToFlow") - val transactionId = CadenceScript.CADENCE_BRIDGE_NFT_FROM_EVM_TO_FLOW.transactionByMainWallet { - arg { string(nftIdentifier) } - arg { uint256(nftId) } - arg { address(recipient) } + val transactionId = if (AppConfig.coverBridgeFee()) { + CadenceScript.CADENCE_BRIDGE_NFT_FROM_EVM_TO_FLOW_WITH_PAYER.transactionWithBridgePayer { + arg { string(nftIdentifier) } + arg { uint256(nftId) } + arg { address(recipient) } + } + } else { + CadenceScript.CADENCE_BRIDGE_NFT_FROM_EVM_TO_FLOW.transactionByMainWallet { + arg { string(nftIdentifier) } + arg { uint256(nftId) } + arg { address(recipient) } + } } logd(TAG, "cadenceBridgeNFTFromEVMToFlow transactionId:$transactionId") return transactionId @@ -762,6 +808,23 @@ suspend fun String.transactionByMainWallet(arguments: CadenceArgumentsBuilder.() } } +suspend fun CadenceScript.transactionWithBridgePayer(arguments: CadenceArgumentsBuilder.() -> Unit): String? { + val walletAddress = WalletManager.wallet()?.walletAddress()?: return null + logd(TAG, "transactionBridge() walletAddress:$walletAddress") + val args = CadenceArgumentsBuilder().apply { arguments(this) } + return try { + sendBridgeTransaction { + args.build().forEach { arg(it) } + walletAddress(walletAddress) + script(this@transactionWithBridgePayer.getScript().addPlatformInfo()) + payer(AppConfig.bridgeFeePayer().address) + } + } catch (e: Exception) { + loge(e) + null + } +} + fun String.addPlatformInfo(): String { return this.replace("", "Android - ${BuildConfig.VERSION_NAME} - ${BuildConfig .VERSION_CODE} ${devPrefix()}") diff --git a/app/src/main/java/com/flowfoundation/wallet/manager/flowjvm/CadenceScript.kt b/app/src/main/java/com/flowfoundation/wallet/manager/flowjvm/CadenceScript.kt index b51f636a6..e0a639ca7 100644 --- a/app/src/main/java/com/flowfoundation/wallet/manager/flowjvm/CadenceScript.kt +++ b/app/src/main/java/com/flowfoundation/wallet/manager/flowjvm/CadenceScript.kt @@ -80,11 +80,17 @@ enum class CadenceScript(val scriptId: String, val type: CadenceScriptType) { CADENCE_BRIDGE_FT_FROM_EVM("bridgeTokensFromEvmV2", CadenceScriptType.BRIDGE), CADENCE_BRIDGE_FT_FROM_EVM_TO_FLOW("bridgeTokensFromEvmToFlowV3", CadenceScriptType.BRIDGE), CADENCE_BRIDGE_NFT_TO_EVM("bridgeNFTToEvmV2", CadenceScriptType.BRIDGE), + CADENCE_BRIDGE_NFT_TO_EVM_WITH_PAYER("bridgeNFTToEvmWithPayer", CadenceScriptType.BRIDGE), CADENCE_BRIDGE_NFT_FROM_EVM("bridgeNFTFromEvmV2", CadenceScriptType.BRIDGE), + CADENCE_BRIDGE_NFT_FROM_EVM_WITH_PAYER("bridgeNFTFromEvmWithPayer", CadenceScriptType.BRIDGE), CADENCE_BRIDGE_NFT_LIST_TO_EVM("batchBridgeNFTToEvmV2", CadenceScriptType.BRIDGE), + CADENCE_BRIDGE_NFT_LIST_TO_EVM_WITH_PAYER("batchBridgeNFTToEvmWithPayer", CadenceScriptType.BRIDGE), CADENCE_BRIDGE_NFT_LIST_FROM_EVM("batchBridgeNFTFromEvmV2", CadenceScriptType.BRIDGE), + CADENCE_BRIDGE_NFT_LIST_FROM_EVM_WITH_PAYER("batchBridgeNFTFromEvmWithPayer", CadenceScriptType.BRIDGE), CADENCE_BRIDGE_NFT_FROM_FLOW_TO_EVM("bridgeNFTToEvmAddressV2", CadenceScriptType.BRIDGE), + CADENCE_BRIDGE_NFT_FROM_FLOW_TO_EVM_WITH_PAYER("bridgeNFTToEvmAddressWithPayer", CadenceScriptType.BRIDGE), CADENCE_BRIDGE_NFT_FROM_EVM_TO_FLOW("bridgeNFTFromEvmToFlowV3", CadenceScriptType.BRIDGE), + CADENCE_BRIDGE_NFT_FROM_EVM_TO_FLOW_WITH_PAYER("bridgeNFTFromEvmToFlowWithPayer", CadenceScriptType.BRIDGE), // EVM CADENCE_CREATE_COA_ACCOUNT("createCoaEmpty", CadenceScriptType.EVM), diff --git a/app/src/main/java/com/flowfoundation/wallet/manager/flowjvm/transaction/Transaction.kt b/app/src/main/java/com/flowfoundation/wallet/manager/flowjvm/transaction/Transaction.kt index 2f6febff4..2b85f52ee 100644 --- a/app/src/main/java/com/flowfoundation/wallet/manager/flowjvm/transaction/Transaction.kt +++ b/app/src/main/java/com/flowfoundation/wallet/manager/flowjvm/transaction/Transaction.kt @@ -18,6 +18,8 @@ import com.flowfoundation.wallet.manager.flowjvm.toAsArgument import com.flowfoundation.wallet.manager.flowjvm.valueString import com.flowfoundation.wallet.manager.key.CryptoProviderManager import com.flowfoundation.wallet.mixpanel.MixpanelManager +import com.flowfoundation.wallet.network.BASE_HOST +import com.flowfoundation.wallet.network.functions.FUNCTION_SIGN_AS_BRIDGE_PAYER import com.flowfoundation.wallet.network.functions.FUNCTION_SIGN_AS_PAYER import com.flowfoundation.wallet.network.functions.executeHttpFunction import com.flowfoundation.wallet.utils.logd @@ -76,6 +78,44 @@ suspend fun sendTransaction( } } +suspend fun sendBridgeTransaction( + builder: TransactionBuilder.() -> Unit, +): String? { +// updateSecurityProvider() + val transactionBuilder = TransactionBuilder().apply { builder(this) } + + try { + logd(TAG, "sendBridgeTransaction prepare") + val voucher = prepare(transactionBuilder) + + logd(TAG, "sendBridgeTransaction build flow transaction") + var tx = voucher.toFlowTransactionWithBridgePayer() + tx = tx.addFreeBridgeFeeEnvelope() + + logd(TAG, "sendBridgeTransaction to flow chain") + val txID = FlowApi.get().sendTransaction(tx).bytes.bytesToHex() + logd(TAG, "transaction id:$${txID}") + vibrateTransaction() + MixpanelManager.cadenceTransactionSigned( + cadence = voucher.cadence.orEmpty(), txId = txID, authorizers = tx.authorizers.map { it.formatted }.toList(), + proposer = tx.proposalKey.address.formatted, + payer = tx.payerAddress.formatted, + isSuccess = true + ) + return txID + } catch (e: Exception) { + loge(e) + MixpanelManager.cadenceTransactionSigned( + cadence = transactionBuilder.script.orEmpty(), txId = "", + authorizers = emptyList(), + proposer = transactionBuilder.walletAddress?.toAddress().orEmpty(), + payer = transactionBuilder.payer ?: (if (isGasFree()) AppConfig.payer().address else transactionBuilder.walletAddress).orEmpty(), + isSuccess = false + ) + return null + } +} + suspend fun sendTransactionWithMultiSignature( builder: TransactionBuilder.() -> Unit, providers: List @@ -143,6 +183,19 @@ private suspend fun FlowTransaction.addFreeGasEnvelope(): FlowTransaction { ) } +private suspend fun FlowTransaction.addFreeBridgeFeeEnvelope(): FlowTransaction { + val response = executeHttpFunction(FUNCTION_SIGN_AS_BRIDGE_PAYER, buildBridgeFeePayerSignable(), BASE_HOST) + logd(TAG, "response:$response") + + val sign = Gson().fromJson(response, SignPayerResponse::class.java).envelopeSigs + + return addEnvelopeSignature( + FlowAddress(sign.address), + keyIndex = sign.keyId, + signature = FlowSignature(sign.sig) + ) +} + private suspend fun prepare(builder: TransactionBuilder): Voucher { logd(TAG, "prepare builder:$builder") val account = FlowApi.get().getAccountAtLatestBlock(FlowAddress(builder.walletAddress?.toAddress().orEmpty())) @@ -188,6 +241,43 @@ private suspend fun prepareWithMultiSignature( ) } +fun FlowTransaction.buildBridgeFeePayerSignable(): PayerSignable? { + val payerAccount = FlowApi.get().getAccountAtLatestBlock(payerAddress) ?: return null + val voucher = Voucher( + cadence = script.stringValue, + refBlock = referenceBlockId.base16Value, + computeLimit = gasLimit.toInt(), + arguments = arguments.map { it.toAsArgument() }, + proposalKey = ProposalKey( + address = proposalKey.address.base16Value.toAddress(), + keyId = proposalKey.keyIndex, + sequenceNum = proposalKey.sequenceNumber.toInt(), + ), + payer = payerAddress.base16Value.toAddress(), + authorizers = authorizers.map { it.base16Value.toAddress() }, + payloadSigs = payloadSignatures.map { + Singature( + address = it.address.base16Value.toAddress(), + keyId = it.keyIndex, + sig = it.signature.base16Value, + ) + }, + envelopeSigs = listOf( + Singature( + address = AppConfig.bridgeFeePayer().address.toAddress(), + keyId = payerAccount.keys.first().id, + ) + ), + ) + + return PayerSignable( + transaction = voucher, + message = PayerSignable.Message( + (DomainTag.TRANSACTION_DOMAIN_TAG + canonicalAuthorizationEnvelope).bytesToHex() + ) + ) +} + fun FlowTransaction.buildPayerSignable(): PayerSignable? { val payerAccount = FlowApi.get().getAccountAtLatestBlock(payerAddress) ?: return null val voucher = Voucher( @@ -319,6 +409,39 @@ fun Voucher.toFlowTransaction(): FlowTransaction { return tx } +fun Voucher.toFlowTransactionWithBridgePayer(): FlowTransaction { + val transaction = this + var tx = flowTransaction { + script { transaction.cadence.orEmpty() } + + arguments = transaction.arguments.orEmpty().map { it.toBytes() }.map { FlowArgument(it) }.toMutableList() + + referenceBlockId = FlowId(transaction.refBlock.orEmpty()) + + gasLimit = computeLimit ?: 9999 + + proposalKey { + address = FlowAddress(transaction.proposalKey.address.orEmpty()) + keyIndex = transaction.proposalKey.keyId ?: 0 + sequenceNumber = transaction.proposalKey.sequenceNum ?: 0 + } + + payerAddress = FlowAddress(transaction.payer.orEmpty()) + + authorizers(mutableListOf(FlowAddress(transaction.proposalKey.address.orEmpty()), payerAddress)) + } + + val cryptoProvider = CryptoProviderManager.getCurrentCryptoProvider() ?: return tx + + tx = tx.addPayloadSignature( + FlowAddress(proposalKey.address.orEmpty()), + keyIndex = proposalKey.keyId ?: 0, + cryptoProvider.getSigner(), + ) + + return tx +} + /** * fix: java.security.NoSuchAlgorithmException: no such algorithm: ECDSA for provider BC */ diff --git a/app/src/main/java/com/flowfoundation/wallet/network/NetworkConst.kt b/app/src/main/java/com/flowfoundation/wallet/network/NetworkConst.kt index e0473c06f..1538f3e76 100644 --- a/app/src/main/java/com/flowfoundation/wallet/network/NetworkConst.kt +++ b/app/src/main/java/com/flowfoundation/wallet/network/NetworkConst.kt @@ -16,6 +16,7 @@ import java.util.concurrent.TimeUnit val API_HOST = if (isDev()) "https://dev.lilico.app" else "https://api.lilico.app" +val BASE_HOST = if (isDev()) "https://web-dev.api.wallet.flow.com" else "https://lilico.app" fun retrofit( disableConverter: Boolean = false, @@ -46,11 +47,10 @@ fun retrofit( } fun retrofitApi(): Retrofit { - return retrofitWithHost(if (isDev()) "https://web-dev.api.wallet.flow.com" else "https://lilico.app", ignoreAuthorization = false) + return retrofitWithHost(BASE_HOST, ignoreAuthorization = false) } fun cadenceScriptApi(): Retrofit { - val host = if (isDev()) "https://web-dev.api.wallet.flow.com" else "https://lilico.app" val client = OkHttpClient.Builder().apply { addInterceptor(HeaderInterceptor(false)) addInterceptor(InstabugAPMOkhttpInterceptor()) @@ -69,7 +69,7 @@ fun cadenceScriptApi(): Retrofit { val builder = Retrofit.Builder() builder.addConverterFactory(GsonConverterFactory.create()) - return builder.baseUrl(host).client(client).build() + return builder.baseUrl(BASE_HOST).client(client).build() } fun retrofitWithHost(host: String, disableConverter: Boolean = false, ignoreAuthorization: Boolean = true): Retrofit { diff --git a/app/src/main/java/com/flowfoundation/wallet/network/functions/Functions.kt b/app/src/main/java/com/flowfoundation/wallet/network/functions/Functions.kt index 412137618..839a704a8 100644 --- a/app/src/main/java/com/flowfoundation/wallet/network/functions/Functions.kt +++ b/app/src/main/java/com/flowfoundation/wallet/network/functions/Functions.kt @@ -18,6 +18,7 @@ import kotlin.coroutines.resume private const val TAG = "FirebaseFunctions" const val FUNCTION_SIGN_AS_PAYER = "signAsPayer" +const val FUNCTION_SIGN_AS_BRIDGE_PAYER = "/api/signAsBridgeFeePayer" // https://us-central1-lilico-dev.cloudfunctions.net/moonPaySignature?url=https://buy-sandbox.moonpay.com?apiKey=pk_test_F0Y1SznEgbvGOWxFYJqStfjLeZ7XT&defaultCurrencyCode=FLOW&colorCode=%23FC814A&walletAddress=0x7d2b880d506db7cc const val FUNCTION_MOON_PAY_SIGN = "moonPaySignature" @@ -28,13 +29,13 @@ private val HOST = if (isDev()) "https://us-central1-lilico-dev.cloudfunctions.n /** * execute firebase function */ -suspend fun executeHttpFunction(functionName: String, data: Any? = null): String? { +suspend fun executeHttpFunction(functionName: String, data: Any? = null, host: String? = HOST): String? { logd(TAG, "executeFunction:$functionName") - return executeHttp(functionName, data) + return executeHttp(host ?: HOST, functionName, data) } -private suspend fun executeHttp(functionName: String, data: Any? = null) = suspendCancellableCoroutine { continuation -> +private suspend fun executeHttp(host: String, functionName: String, data: Any? = null) = suspendCancellableCoroutine { continuation -> val client = OkHttpClient.Builder().apply { callTimeout(10, TimeUnit.SECONDS) @@ -51,7 +52,7 @@ private suspend fun executeHttp(functionName: String, data: Any? = null) = suspe }.build() val body = if (data == null) data else (if (data is String) data else GsonBuilder().serializeNulls().create().toJson(data)) - val request = Request.Builder().url("$HOST$functionName") + val request = Request.Builder().url("$host$functionName") .post(body.orEmpty().toRequestBody("application/json; charset=utf-8".toMediaType())) .build() val response = client.newCall(request).execute() diff --git a/app/src/main/java/com/flowfoundation/wallet/page/nft/move/MoveNFTDialog.kt b/app/src/main/java/com/flowfoundation/wallet/page/nft/move/MoveNFTDialog.kt index 7e165850b..960c79510 100644 --- a/app/src/main/java/com/flowfoundation/wallet/page/nft/move/MoveNFTDialog.kt +++ b/app/src/main/java/com/flowfoundation/wallet/page/nft/move/MoveNFTDialog.kt @@ -12,6 +12,7 @@ import com.bumptech.glide.load.resource.bitmap.RoundedCorners import com.flowfoundation.wallet.R import com.flowfoundation.wallet.databinding.DialogMoveNftBinding import com.flowfoundation.wallet.manager.account.AccountInfoManager +import com.flowfoundation.wallet.manager.config.AppConfig import com.flowfoundation.wallet.manager.config.NftCollectionConfig import com.flowfoundation.wallet.manager.evm.EVMWalletManager import com.flowfoundation.wallet.manager.flowjvm.cadenceMoveNFTFromChildToParent @@ -30,6 +31,7 @@ import com.flowfoundation.wallet.page.nft.nftlist.utils.NftCache import com.flowfoundation.wallet.page.window.bubble.tools.pushBubbleStack import com.flowfoundation.wallet.utils.extensions.dp2px import com.flowfoundation.wallet.utils.extensions.res2String +import com.flowfoundation.wallet.utils.extensions.setVisible import com.flowfoundation.wallet.utils.ioScope import com.flowfoundation.wallet.utils.toast import com.flowfoundation.wallet.utils.uiScope @@ -192,6 +194,7 @@ class MoveNFTDialog : BottomSheetDialogFragment() { } + " FLOW" tvMoveFeeTips.text = (if (needMoveFee) R.string.move_fee_tips else R.string.no_move_fee_tips).res2String() + clMoveFee.setVisible(AppConfig.coverBridgeFee().not()) } } diff --git a/app/src/main/java/com/flowfoundation/wallet/page/nft/move/SelectNFTDialog.kt b/app/src/main/java/com/flowfoundation/wallet/page/nft/move/SelectNFTDialog.kt index c2d11b357..7a0d58f4d 100644 --- a/app/src/main/java/com/flowfoundation/wallet/page/nft/move/SelectNFTDialog.kt +++ b/app/src/main/java/com/flowfoundation/wallet/page/nft/move/SelectNFTDialog.kt @@ -16,6 +16,7 @@ import com.bumptech.glide.load.resource.bitmap.RoundedCorners import com.flowfoundation.wallet.R import com.flowfoundation.wallet.databinding.DialogSelectNftBinding import com.flowfoundation.wallet.manager.account.AccountInfoManager +import com.flowfoundation.wallet.manager.config.AppConfig import com.flowfoundation.wallet.manager.evm.EVMWalletManager import com.flowfoundation.wallet.manager.wallet.WalletManager import com.flowfoundation.wallet.page.nft.move.model.CollectionInfo @@ -396,6 +397,7 @@ class SelectNFTDialog: BottomSheetDialogFragment() { "0.00" } + " FLOW" tvMoveFeeTips.text = (if (needMoveFee) R.string.move_fee_tips else R.string.no_move_fee_tips).res2String() + clMoveFee.setVisible(AppConfig.coverBridgeFee().not()) } }