diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 97e4157f97..c2d4929889 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -81,9 +81,33 @@
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/com/tangem/tap/common/CustomTabsManager.kt b/app/src/main/java/com/tangem/tap/common/CustomTabsManager.kt
new file mode 100644
index 0000000000..a30af0f5d6
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/common/CustomTabsManager.kt
@@ -0,0 +1,21 @@
+package com.tangem.tap.common
+
+import android.content.Context
+import android.net.Uri
+import androidx.browser.customtabs.CustomTabColorSchemeParams
+import androidx.browser.customtabs.CustomTabsIntent
+import com.tangem.tap.common.extensions.getColorCompat
+import com.tangem.wallet.R
+
+class CustomTabsManager {
+ fun openUrl(url: String, context: Context) {
+ val customTabsIntent = CustomTabsIntent.Builder()
+ .setDefaultColorSchemeParams(
+ CustomTabColorSchemeParams.Builder()
+ .setNavigationBarColor(context.getColorCompat(R.color.toolbarColor))
+ .build()
+ )
+ .build()
+ customTabsIntent.launchUrl(context, Uri.parse(url))
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/IntentHandler.kt b/app/src/main/java/com/tangem/tap/common/IntentHandler.kt
index f30a481c98..a804d20624 100644
--- a/app/src/main/java/com/tangem/tap/common/IntentHandler.kt
+++ b/app/src/main/java/com/tangem/tap/common/IntentHandler.kt
@@ -5,16 +5,20 @@ import android.nfc.NfcAdapter
import android.nfc.Tag
import com.tangem.tap.common.redux.navigation.AppScreen
import com.tangem.tap.common.redux.navigation.NavigationAction
+import com.tangem.tap.domain.topup.TradeCryptoHelper
import com.tangem.tap.domain.walletconnect.WalletConnectManager
import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction
import com.tangem.tap.features.home.redux.HomeAction
+import com.tangem.tap.features.wallet.redux.WalletAction
import com.tangem.tap.store
+import timber.log.Timber
class IntentHandler {
fun handleIntent(intent: Intent?) {
handleBackgroundScan(intent)
handleWalletConnectLink(intent)
+ handleSellCurrencyCallback(intent)
}
private fun handleBackgroundScan(intent: Intent?) {
@@ -38,4 +42,26 @@ class IntentHandler {
}
}
+ private fun handleSellCurrencyCallback(intent: Intent?) {
+ val transactionID =
+ intent?.data?.getQueryParameter(TradeCryptoHelper.TRANSACTION_ID_PARAM) ?: return
+ val currency =
+ intent.data?.getQueryParameter(TradeCryptoHelper.CURRENCY_CODE_PARAM) ?: return
+ val amount =
+ intent.data?.getQueryParameter(TradeCryptoHelper.CURRENCY_AMOUNT_PARAM) ?: return
+ val destinationAddress =
+ intent.data?.getQueryParameter(TradeCryptoHelper.DEPOSIT_WALLET_ADDRESS_PARAM)
+ ?: return
+
+ Timber.d("MoonPay Sell: $amount $currency to $destinationAddress")
+
+ store.dispatch(WalletAction.TradeCryptoAction.SendCrypto(
+ currencyId = currency,
+ amount = amount,
+ destinationAddress = destinationAddress,
+ transactionId = transactionID
+ ))
+ }
+
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/extensions/UI.kt b/app/src/main/java/com/tangem/tap/common/extensions/UI.kt
index b43c49b307..d29b032ef3 100644
--- a/app/src/main/java/com/tangem/tap/common/extensions/UI.kt
+++ b/app/src/main/java/com/tangem/tap/common/extensions/UI.kt
@@ -30,6 +30,11 @@ fun Fragment.getColor(@ColorRes colorRes: Int): Int {
return ContextCompat.getColor(requireContext(), colorRes)
}
+@ColorInt
+fun Context.getColorCompat(@ColorRes colorRes: Int): Int {
+ return ContextCompat.getColor(this, colorRes)
+}
+
fun View.getString(@StringRes id: Int): String {
return context.getString(id)
}
diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt
index 419fa5737d..bb32bfa7b4 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt
@@ -9,6 +9,7 @@ import com.tangem.tap.domain.tasks.ScanNoteResponse
import com.tangem.tap.features.details.redux.SecurityOption
import com.tangem.tap.features.feedback.EmailData
import com.tangem.tap.features.feedback.FeedbackManager
+import com.tangem.tap.network.moonpay.MoonPayUserStatus
import org.rekotlin.Action
sealed class GlobalAction : Action {
@@ -43,4 +44,8 @@ sealed class GlobalAction : Action {
data class ShowDialog(val stateDialog: StateDialog) : GlobalAction()
object HideDialog : GlobalAction()
+
+ object GetMoonPayUserStatus : GlobalAction() {
+ data class Success(val moonPayUserStatus: MoonPayUserStatus) : GlobalAction()
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMidlleware.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMidlleware.kt
index 2f79a5bbcc..e499b320c2 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMidlleware.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMidlleware.kt
@@ -1,14 +1,19 @@
package com.tangem.tap.common.redux.global
import com.tangem.TangemSdkError
+import com.tangem.commands.common.network.Result
import com.tangem.common.CompletionResult
+import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager
import com.tangem.tap.features.home.redux.HomeAction
import com.tangem.tap.features.send.redux.SendAction
import com.tangem.tap.features.wallet.redux.WalletAction
+import com.tangem.tap.network.moonpay.MoonpayService
import com.tangem.tap.preferencesStorage
+import com.tangem.tap.scope
import com.tangem.tap.store
+import kotlinx.coroutines.launch
import org.rekotlin.Middleware
val globalMiddleware: Middleware = { dispatch, appState ->
@@ -60,6 +65,19 @@ val globalMiddleware: Middleware = { dispatch, appState ->
store.state.globalState.feedbackManager?.infoHolder
?.setWalletsInfo(action.walletManagers)
}
+ is GlobalAction.GetMoonPayUserStatus -> {
+ val apiKey = appState()?.globalState?.configManager?.config?.moonPayApiKey
+ if (apiKey != null) {
+ scope.launch {
+ val userStatusResponse = MoonpayService().getUserStatus(apiKey)
+ if (userStatusResponse is Result.Success) {
+ store.dispatchOnMain(
+ GlobalAction.GetMoonPayUserStatus.Success(userStatusResponse.data)
+ )
+ }
+ }
+ }
+ }
}
nextDispatch(action)
}
diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt
index b7208034f7..7dbbe6f40e 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt
@@ -73,6 +73,9 @@ fun globalReducer(action: Action, state: AppState): GlobalState {
is GlobalAction.HideDialog -> {
globalState.copy(dialog = null)
}
+ is GlobalAction.GetMoonPayUserStatus.Success -> {
+ globalState.copy(moonPayUserStatus = action.moonPayUserStatus)
+ }
else -> globalState
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt
index c7e173310b..77b02d5e8c 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt
@@ -9,6 +9,7 @@ import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager
import com.tangem.tap.domain.tasks.ScanNoteResponse
import com.tangem.tap.features.feedback.FeedbackManager
import com.tangem.tap.network.coinmarketcap.CoinMarketCapService
+import com.tangem.tap.network.moonpay.MoonPayUserStatus
import org.rekotlin.StateType
data class GlobalState(
@@ -22,7 +23,8 @@ data class GlobalState(
val feedbackManager: FeedbackManager? = null,
val appCurrency: FiatCurrencyName = DEFAULT_FIAT_CURRENCY,
val scanCardFailsCounter: Int = 0,
- val dialog: StateDialog? = null
+ val dialog: StateDialog? = null,
+ val moonPayUserStatus: MoonPayUserStatus? = null
) : StateType
typealias CryptoCurrencyName = String
diff --git a/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationAction.kt b/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationAction.kt
index 5cbdb915f6..6da57dfec8 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationAction.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationAction.kt
@@ -10,6 +10,8 @@ sealed class NavigationAction : Action {
data class PopBackTo(val screen: AppScreen? = null) : NavigationAction()
+ data class OpenUrl(val url: String) : NavigationAction()
+
data class ActivityCreated(val activity: WeakReference) : NavigationAction()
object ActivityDestroyed : NavigationAction()
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationMiddleware.kt b/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationMiddleware.kt
index 8c4d5e9fea..43c8ed406e 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationMiddleware.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationMiddleware.kt
@@ -1,25 +1,30 @@
package com.tangem.tap.common.redux.navigation
+import com.tangem.tap.common.CustomTabsManager
import com.tangem.tap.common.extensions.openFragment
import com.tangem.tap.common.extensions.popBackTo
import com.tangem.tap.common.redux.AppState
-import com.tangem.tap.store
import org.rekotlin.Middleware
val navigationMiddleware: Middleware = { dispatch, state ->
{ next ->
{ action ->
if (action is NavigationAction) {
- val navState = store.state.navigationState
+ val navState = state()?.navigationState
when (action) {
is NavigationAction.NavigateTo -> {
- navState.activity?.get()?.openFragment(action.screen, action.addToBackstack)
+ navState?.activity?.get()?.openFragment(action.screen, action.addToBackstack)
}
is NavigationAction.PopBackTo -> {
if (action.screen == AppScreen.Home) {
- navState.activity?.get()?.popBackTo(null, true)
+ navState?.activity?.get()?.popBackTo(null, true)
} else {
- navState.activity?.get()?.popBackTo(action.screen)
+ navState?.activity?.get()?.popBackTo(action.screen)
+ }
+ }
+ is NavigationAction.OpenUrl -> {
+ navState?.activity?.get()?.let {
+ CustomTabsManager().openUrl(action.url, it)
}
}
}
diff --git a/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationReducer.kt b/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationReducer.kt
index a4ce784435..80cd5e3260 100644
--- a/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationReducer.kt
+++ b/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationReducer.kt
@@ -27,5 +27,6 @@ private fun internalReduce(action: Action, state: AppState): NavigationState {
}
is NavigationAction.ActivityCreated -> navState.copy(activity = navigationAction.activity)
is NavigationAction.ActivityDestroyed -> navState.copy(activity = null)
+ else -> navState
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt
index 9ae9105a46..992ddbc606 100644
--- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt
+++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt
@@ -174,7 +174,11 @@ class TapWalletManager {
}
}
store.dispatch(WalletAction.SetArtworkId(data.verifyResponse?.artworkInfo?.id))
- store.dispatch(WalletAction.LoadWallet(config.isTopUpEnabled))
+ val moonPayUserStatus = store.state.globalState.moonPayUserStatus
+ store.dispatch(WalletAction.LoadWallet(
+ allowToBuy = config.isTopUpEnabled && moonPayUserStatus?.isBuyAllowed == true,
+ allowToSell = config.isTopUpEnabled && moonPayUserStatus?.isSellAllowed == true,
+ ))
store.dispatch(WalletAction.LoadArtwork(data.card, artworkId))
store.dispatch(WalletAction.LoadFiatRate())
}
@@ -245,7 +249,11 @@ class TapWalletManager {
return@withContext
}
val config = store.state.globalState.configManager?.config ?: return@withContext
- store.dispatch(WalletAction.LoadWallet(config.isTopUpEnabled))
+ val moonpayUserStatus = store.state.globalState.moonPayUserStatus
+ store.dispatch(WalletAction.LoadWallet(
+ allowToBuy = config.isTopUpEnabled && moonpayUserStatus?.isBuyAllowed == true,
+ allowToSell = config.isTopUpEnabled && moonpayUserStatus?.isSellAllowed == true,
+ ))
store.dispatch(WalletAction.LoadFiatRate())
}
}
diff --git a/app/src/main/java/com/tangem/tap/domain/TapWorkarounds.kt b/app/src/main/java/com/tangem/tap/domain/TapWorkarounds.kt
index 0c1a379a3c..6a6723cd83 100644
--- a/app/src/main/java/com/tangem/tap/domain/TapWorkarounds.kt
+++ b/app/src/main/java/com/tangem/tap/domain/TapWorkarounds.kt
@@ -20,7 +20,7 @@ object TapWorkarounds {
val cardData = this.cardData ?: return false
val productMask = cardData.productMask
val excludedBatch = excludedBatches.contains(cardData.batchId)
- val excludedIssuerName = excludedIssuers.contains(cardData.issuerName?.toUpperCase(Locale.US))
+ val excludedIssuerName = excludedIssuers.contains(cardData.issuerName?.uppercase(Locale.ROOT))
val excludedProductMask = (productMask != null && // product mask is on cards v2.30 and later
!productMask.contains(Product.Note) && !productMask.contains(Product.TwinCard))
return excludedBatch || excludedIssuerName || excludedProductMask
diff --git a/app/src/main/java/com/tangem/tap/domain/topup/TopUpHelper.kt b/app/src/main/java/com/tangem/tap/domain/topup/TopUpHelper.kt
deleted file mode 100644
index 2ab6b843c8..0000000000
--- a/app/src/main/java/com/tangem/tap/domain/topup/TopUpHelper.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.tangem.tap.domain.topup
-
-import android.net.Uri
-import android.util.Base64
-import com.tangem.blockchain.common.Blockchain
-import com.tangem.tap.common.redux.global.CryptoCurrencyName
-import javax.crypto.Mac
-import javax.crypto.spec.SecretKeySpec
-
-class TopUpHelper {
-
- companion object {
-// const val REDIRECT_URL = "https://success.tangem.com"
-
- private const val BASE_URL = "https://buy.moonpay.io"
- private const val API_KEY_PATH = "?apiKey="
- private const val CURRENCY_PATH = "¤cyCode="
- private const val WALLET_ADDRESS_PATH = "&walletAddress="
-
- // private const val REDIRECT_URL_PATH = "&redirectUrl="
- private const val SIGNATURE_PATH = "&signature="
-
- fun getUrl(
- blockchain: Blockchain?,
- cryptoCurrencyName: CryptoCurrencyName,
- walletAddress: String,
- apiKey: String,
- secretKey: String,
- ): String {
- if (blockchain?.isTestnet() == true) {
- return blockchain.getTestnetTopUpUrl() ?: ""
- }
- val originalQuery = API_KEY_PATH + apiKey.urlEncode() +
- CURRENCY_PATH + cryptoCurrencyName.urlEncode() +
- WALLET_ADDRESS_PATH + walletAddress.urlEncode()
-// REDIRECT_URL_PATH + REDIRECT_URL.urlEncode()
- val signature = createSignature(originalQuery, secretKey)
-
- return BASE_URL + originalQuery + SIGNATURE_PATH + signature.urlEncode()
- }
-
- private fun String.urlEncode(): String {
- return Uri.encode(this)
- }
-
-
- private fun createSignature(data: String, key: String): String {
- val sha256Hmac = Mac.getInstance("HmacSHA256")
- val secretKey = SecretKeySpec(key.toByteArray(), "HmacSHA256")
- sha256Hmac.init(secretKey)
- val sha256encoded = sha256Hmac.doFinal(data.toByteArray())
- return Base64.encodeToString(sha256encoded, Base64.NO_WRAP)
- }
- }
-}
diff --git a/app/src/main/java/com/tangem/tap/domain/topup/TradeCryptoHelper.kt b/app/src/main/java/com/tangem/tap/domain/topup/TradeCryptoHelper.kt
new file mode 100644
index 0000000000..f16a2591b2
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/domain/topup/TradeCryptoHelper.kt
@@ -0,0 +1,102 @@
+package com.tangem.tap.domain.topup
+
+import android.net.Uri
+import android.util.Base64
+import com.tangem.blockchain.common.Blockchain
+import com.tangem.tap.common.redux.global.CryptoCurrencyName
+import javax.crypto.Mac
+import javax.crypto.spec.SecretKeySpec
+
+class TradeCryptoHelper {
+
+ companion object {
+
+ const val TRANSACTION_ID_PARAM = "transactionId"
+ const val CURRENCY_CODE_PARAM = "baseCurrencyCode"
+ const val CURRENCY_AMOUNT_PARAM = "baseCurrencyAmount"
+ const val DEPOSIT_WALLET_ADDRESS_PARAM = "depositWalletAddress"
+
+ private const val REDIRECT_URL_BUY = "tangem://success.tangem.com"
+ private const val REDIRECT_URL_SELL_REQUEST = "tangem://sell-request.tangem.com"
+
+ private const val BASE_URL_BUY =
+ "https://buy.moonpay.io"
+// "https://buy-staging.moonpay.io" // TESTNET
+ private const val BASE_URL_SELL =
+ "https://sell.moonpay.com"
+// "https://sell-staging.moonpay.com" // TESTNET
+
+ private const val API_KEY_PATH = "?apiKey="
+ private const val CURRENCY_PATH = "¤cyCode="
+ private const val WALLET_ADDRESS_PATH = "&walletAddress="
+
+ private const val REFUND_WALLET_ADDRESS_PATH = "&refundWalletAddress="
+ private const val BASE_CURRENCY_PATH = "&baseCurrencyCode="
+
+ private const val REDIRECT_URL_PATH = "&redirectURL="
+ private const val SIGNATURE_PATH = "&signature="
+
+ private const val TRANSACTION_RECEIPT_PATH = "transaction_receipt?transactionId="
+
+ val AVAILABLE_TO_BUY: Set = setOf(
+ "ZRX", "AAVE", "ALGO", "AXS", "BAT", "BNB", "BUSD", "BTC", "BCH", "BTT", "ADA", "CELO", "CUSD", "LINK", "CHZ", "COMP", "ATOM", "DAI", "DASH", "MANA", "DGB", "DOGE", "EGLD",
+ "ENJ", "EOS", "ETC", "ETH", "KETH", "RINKETH", "FIL", "HBAR", "MIOTA", "KAVA", "KLAY", "LBC", "LTC", "LUNA", "MKR", "OM", "MATIC", "NANO", "NEAR", "XEM", "NEO", "NIM", "OKB",
+ "OMG", "ONG", "ONT", "DOT", "QTUM", "RVN", "RFUEL", "KEY", "SRM", "SOL", "XLM", "STMX", "SNX", "KRT", "UST", "USDT", "XTZ", "RUNE", "SAND", "TOMO", "AVA", "TRX", "TUSD", "UNI",
+ "USDC", "UTK", "VET", "WAXP", "WBTC", "XRP", "ZEC", "ZIL"
+ )
+
+ val AVAILABLE_TO_SELL: Set = setOf("BTC", "ETH", "BCH")
+
+ fun getUrl(
+ action: Action,
+ blockchain: Blockchain?,
+ cryptoCurrencyName: CryptoCurrencyName,
+ walletAddress: String,
+ apiKey: String,
+ secretKey: String,
+ ): String {
+ val originalQuery: String
+ val baseUrl: String
+ when (action) {
+ Action.Buy -> {
+ if (blockchain?.isTestnet() == true) {
+ return blockchain.getTestnetTopUpUrl() ?: ""
+ }
+ baseUrl = BASE_URL_BUY
+ originalQuery = API_KEY_PATH + apiKey.urlEncode() +
+ CURRENCY_PATH + cryptoCurrencyName.urlEncode() +
+ WALLET_ADDRESS_PATH + walletAddress.urlEncode() +
+ REDIRECT_URL_PATH + REDIRECT_URL_BUY.urlEncode()
+ }
+ Action.Sell -> {
+ baseUrl = BASE_URL_SELL
+ originalQuery = API_KEY_PATH + apiKey.urlEncode() +
+ BASE_CURRENCY_PATH + cryptoCurrencyName.urlEncode() +
+ REFUND_WALLET_ADDRESS_PATH + walletAddress.urlEncode() +
+ REDIRECT_URL_PATH + REDIRECT_URL_SELL_REQUEST.urlEncode()
+ }
+ }
+ val signature = createSignature(originalQuery, secretKey)
+ return baseUrl + originalQuery + SIGNATURE_PATH + signature.urlEncode()
+
+ }
+
+ fun getSellCryptoReceiptUrl(transactionId: String): String {
+ return BASE_URL_SELL + TRANSACTION_RECEIPT_PATH + transactionId
+ }
+
+ private fun String.urlEncode(): String {
+ return Uri.encode(this)
+ }
+
+ private fun createSignature(data: String, key: String): String {
+ val sha256Hmac = Mac.getInstance("HmacSHA256")
+ val secretKey = SecretKeySpec(key.toByteArray(), "HmacSHA256")
+ sha256Hmac.init(secretKey)
+ val sha256encoded = sha256Hmac.doFinal(data.toByteArray())
+ return Base64.encodeToString(sha256encoded, Base64.NO_WRAP)
+ }
+ }
+
+ enum class Action { Buy, Sell }
+}
diff --git a/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt b/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt
index c93543613e..29cd04dc73 100644
--- a/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt
+++ b/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt
@@ -5,6 +5,7 @@ import android.os.Bundle
import android.view.View
import androidx.fragment.app.Fragment
import androidx.transition.TransitionInflater
+import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.common.redux.global.StateDialog
import com.tangem.tap.features.home.redux.HomeAction
import com.tangem.tap.features.home.redux.HomeDialog
@@ -66,6 +67,8 @@ class HomeFragment : Fragment(R.layout.fragment_home), StoreSubscriber) : SendAction()
}
+
+ data class SendSpecificTransaction(
+ val sendAmount: String,
+ val destinationAddress: String,
+ val transactionId: String
+ ) : SendAction()
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt
index 9ca7c9ce1c..d24bfa3949 100644
--- a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt
+++ b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt
@@ -9,6 +9,7 @@ import com.tangem.blockchain.extensions.SimpleResult
import com.tangem.commands.common.card.Card
import com.tangem.tap.common.analytics.AnalyticsEvent
import com.tangem.tap.common.analytics.FirebaseAnalyticsHandler
+import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.extensions.stripZeroPlainString
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.global.GlobalAction
@@ -20,6 +21,8 @@ import com.tangem.tap.domain.configurable.warningMessage.WarningMessage
import com.tangem.tap.domain.extensions.minimalAmount
import com.tangem.tap.features.send.redux.*
import com.tangem.tap.features.send.redux.FeeAction.RequestFee
+import com.tangem.tap.features.send.redux.states.ExternalTransactionData
+import com.tangem.tap.features.send.redux.states.MainCurrencyType
import com.tangem.tap.features.send.redux.states.SendButtonState
import com.tangem.tap.features.send.redux.states.TransactionExtrasState
import com.tangem.tap.features.wallet.redux.WalletAction
@@ -49,6 +52,18 @@ val sendMiddleware: Middleware = { dispatch, appState ->
verifyAndSendTransaction(action, appState(), dispatch)
is PrepareSendScreen -> setIfSendingToPayIdEnabled(appState(), dispatch)
is SendAction.Warnings.Update -> updateWarnings(dispatch)
+ is SendActionUi.CheckIfTransactionDataWasProvided -> {
+ val transactionData = appState()?.sendState?.externalTransactionData
+ if (transactionData != null) {
+ store.dispatchOnMain(AddressPayIdVerifyAction.AddressVerification.SetWalletAddress(
+ transactionData.destinationAddress, false
+ ))
+ store.dispatchOnMain(AmountActionUi.SetMainCurrency(MainCurrencyType.CRYPTO))
+ store.dispatchOnMain(AmountActionUi.HandleUserInput(transactionData.amount))
+ store.dispatchOnMain(AmountAction.SetAmount(transactionData.amount.toBigDecimal(),
+ false))
+ }
+ }
}
nextDispatch(action)
}
@@ -76,8 +91,11 @@ private fun verifyAndSendTransaction(
dispatch(AmountAction.SetAmount(typedAmount.value!!.minus(reduceAmount), false))
dispatch(AmountActionUi.CheckAmountToSend)
}, sendAllCallback = {
- sendTransaction(action, walletManager, amountToSend, feeAmount, destinationAddress,
- sendState.transactionExtrasState, card, dispatch)
+ sendTransaction(
+ action, walletManager, amountToSend, feeAmount, destinationAddress,
+ sendState.transactionExtrasState, card, sendState.externalTransactionData,
+ dispatch
+ )
}, reduceAmount))
}
transactionErrors.isNotEmpty() -> {
@@ -85,7 +103,7 @@ private fun verifyAndSendTransaction(
}
else -> {
sendTransaction(action, walletManager, amountToSend, feeAmount, destinationAddress,
- sendState.transactionExtrasState, card, dispatch)
+ sendState.transactionExtrasState, card, sendState.externalTransactionData, dispatch)
}
}
}
@@ -98,6 +116,7 @@ private fun sendTransaction(
destinationAddress: String,
transactionExtras: TransactionExtrasState,
card: Card,
+ externalTransactionData: ExternalTransactionData?,
dispatch: (Action) -> Unit,
) {
dispatch(SendAction.ChangeSendButtonState(SendButtonState.PROGRESS))
@@ -134,7 +153,12 @@ private fun sendTransaction(
blockchain = walletManager.wallet.blockchain
)
dispatch(SendAction.SendSuccess)
- dispatch(NavigationAction.PopBackTo())
+
+ if (externalTransactionData != null) {
+ dispatch(WalletAction.TradeCryptoAction.FinishSelling(externalTransactionData.transactionId))
+ } else {
+ dispatch(NavigationAction.PopBackTo())
+ }
scope.launch(Dispatchers.IO) {
withContext(Dispatchers.Main) {
dispatch(WalletAction.UpdateWallet(walletManager.wallet.blockchain))
diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/SendScreenReducer.kt b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/SendScreenReducer.kt
index 8cad24d39c..58b36afe00 100644
--- a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/SendScreenReducer.kt
+++ b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/SendScreenReducer.kt
@@ -3,6 +3,7 @@ package com.tangem.tap.features.send.redux.reducers
import com.tangem.blockchain.common.AmountType
import com.tangem.tap.common.CurrencyConverter
import com.tangem.tap.features.send.redux.*
+import com.tangem.tap.features.send.redux.states.ExternalTransactionData
import com.tangem.tap.features.send.redux.states.IdStateHolder
import com.tangem.tap.features.send.redux.states.SendState
import org.rekotlin.Action
@@ -45,11 +46,31 @@ private class SendReducer : SendInternalReducer {
is SendAction.Dialog.SendTransactionFails -> sendState.copy(dialog = action)
is SendAction.Dialog.Hide -> sendState.copy(dialog = null)
is SendAction.Warnings.Set -> sendState.copy(sendWarningsList = action.warningList)
+ is SendAction.SendSpecificTransaction ->
+ handleSendSpecificTransactionAction(action, sendState)
else -> return sendState
}
return updateLastState(result, result)
}
+
+ private fun handleSendSpecificTransactionAction(
+ action: SendAction.SendSpecificTransaction, state: SendState
+ ): SendState {
+ return state.copy(
+ externalTransactionData =
+ ExternalTransactionData(action.sendAmount, action.destinationAddress, action.transactionId),
+ feeState = state.feeState.copy(
+ includeFeeSwitcherIsEnabled = false
+ ),
+ amountState = state.amountState.copy(
+ inputIsEnabled = false
+ ),
+ addressPayIdState = state.addressPayIdState.copy(
+ inputIsEnabled = false
+ ),
+ )
+ }
}
private class EmptyReducer : SendInternalReducer {
diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt b/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt
index d17531a84a..4f2e4e1a6d 100644
--- a/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt
+++ b/app/src/main/java/com/tangem/tap/features/send/redux/states/AddressPayIdState.kt
@@ -12,7 +12,8 @@ data class AddressPayIdState(
val error: AddressPayIdVerifyAction.Error? = null,
val truncateHandler: ((String) -> String)? = null,
val sendingToPayIdEnabled: Boolean = false,
- val pasteIsEnabled: Boolean = false
+ val pasteIsEnabled: Boolean = false,
+ val inputIsEnabled: Boolean = true
) : SendScreenState {
override val stateId: StateId = StateId.ADDRESS_PAY_ID
diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/states/SendState.kt b/app/src/main/java/com/tangem/tap/features/send/redux/states/SendState.kt
index 41d2fd79c5..eed6fa793c 100644
--- a/app/src/main/java/com/tangem/tap/features/send/redux/states/SendState.kt
+++ b/app/src/main/java/com/tangem/tap/features/send/redux/states/SendState.kt
@@ -40,7 +40,8 @@ data class SendState(
val receiptState: ReceiptState = ReceiptState(),
val sendWarningsList: List = listOf(),
val sendButtonState: SendButtonState = SendButtonState.DISABLED,
- val dialog: StateDialog? = null
+ val dialog: StateDialog? = null,
+ val externalTransactionData: ExternalTransactionData? = null
) : SendScreenState {
override val stateId: StateId = StateId.SEND_SCREEN
@@ -131,7 +132,8 @@ data class AmountState(
val cursorAtTheSamePosition: Boolean = true,
val maxLengthOfAmount: Int = 2,
val decimalSeparator: String = ".",
- val error: TapError? = null
+ val error: TapError? = null,
+ val inputIsEnabled: Boolean = true,
) : SendScreenState {
override val stateId: StateId = StateId.AMOUNT
@@ -166,4 +168,12 @@ data class MainCurrency(
val type: MainCurrencyType,
val currencySymbol: String,
val isEnabled: Boolean = true
+)
+
+data class ExternalTransactionData(
+ val amount: String,
+ val destinationAddress: String,
+ val transactionId: String,
+ val canAmountBeModified: Boolean = false,
+ val canDestinationAddressBeModified: Boolean = false
)
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/send/ui/SendFragment.kt b/app/src/main/java/com/tangem/tap/features/send/ui/SendFragment.kt
index 2b2b682294..9736cc16e0 100644
--- a/app/src/main/java/com/tangem/tap/features/send/ui/SendFragment.kt
+++ b/app/src/main/java/com/tangem/tap/features/send/ui/SendFragment.kt
@@ -71,6 +71,7 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
setupAmountLayout()
setupFeeLayout()
setupWarningMessages()
+ store.dispatch(SendActionUi.CheckIfTransactionDataWasProvided)
}
private fun initSendButtonStates() {
@@ -250,7 +251,7 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
val sp = requireContext().getSharedPreferences("SendScreen", Context.MODE_PRIVATE)
val mainCurrency = sp.getString("mainCurrency", TapCurrency.DEFAULT_FIAT_CURRENCY)
val foundType = MainCurrencyType.values()
- .firstOrNull { it.name.toLowerCase() == mainCurrency!!.toLowerCase() }
+ .firstOrNull { it.name.equals(mainCurrency!!, ignoreCase = true) }
?: MainCurrencyType.CRYPTO
return foundType
}
diff --git a/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt b/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt
index 933b1580d7..05c7af7d18 100644
--- a/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt
+++ b/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt
@@ -156,6 +156,12 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
val til = fg.tilAddressOrPayId
val parsedError = parseError(til.context, state.error)
+ til.isEnabled = state.inputIsEnabled
+ fg.imvPaste.show(state.inputIsEnabled)
+ fg.imvQrCode.show(state.inputIsEnabled)
+ fg.flPaste.show(state.inputIsEnabled)
+ fg.flQrCode.show(state.inputIsEnabled)
+
val hintResId = if (state.sendingToPayIdEnabled) {
R.string.send_destination_hint_address_payid
} else {
@@ -198,6 +204,14 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber
state.mainCurrency.currencySymbol,
state.viewBalanceValue)
fg.tvBalance.update(balanceText)
+
+ fg.tilAmountToSend.isEnabled = state.inputIsEnabled
+
+ val imageRes = if (state.inputIsEnabled) R.drawable.ic_arrows_up_down else 0
+ fg.tvAmountCurrency.setCompoundDrawablesWithIntrinsicBounds(0, 0, imageRes, 0)
+ val textColor = if (state.inputIsEnabled) R.color.blue else R.color.textGray
+ fg.tvAmountCurrency.setTextColor(fg.getColor(textColor))
+
}
private fun handleFeeState(fg: BaseStoreFragment, state: FeeState) {
diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt
index 43617cb446..cff630a1a8 100644
--- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt
+++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt
@@ -25,7 +25,11 @@ sealed class WalletAction : Action {
}
- data class LoadWallet(val allowTopUp: Boolean? = null, val blockchain: Blockchain? = null) : WalletAction() {
+ data class LoadWallet(
+ val allowToSell: Boolean? = null, val allowToBuy: Boolean? = null,
+ val blockchain: Blockchain? = null,
+ ) :
+ WalletAction() {
data class Success(val wallet: Wallet) : WalletAction()
data class NoAccount(val wallet: Wallet, val amountToCreateAccount: String) : WalletAction()
data class Failure(val wallet: Wallet, val errorMessage: String? = null) : WalletAction()
@@ -39,13 +43,16 @@ sealed class WalletAction : Action {
data class AddWalletManagers(val walletManagers: List) : MultiWallet() {
constructor(walletManager: WalletManager) : this(listOf(walletManager))
}
+
data class AddBlockchain(val blockchain: Blockchain) : MultiWallet()
data class AddBlockchains(val blockchains: List) : MultiWallet()
data class AddTokens(val tokens: List) : MultiWallet()
data class AddToken(val token: Token) : MultiWallet()
data class SaveCurrencies(val cardCurrencies: CardCurrencies) : MultiWallet()
object FindTokensInUse : MultiWallet()
- data class FindBlockchainsInUse(val card: Card, val factory: WalletManagerFactory) : MultiWallet()
+ data class FindBlockchainsInUse(val card: Card, val factory: WalletManagerFactory) :
+ MultiWallet()
+
data class TokenLoaded(val amount: Amount, val token: Token) : MultiWallet()
data class SelectWallet(val walletData: WalletData?) : MultiWallet()
data class RemoveWallet(val walletData: WalletData) : MultiWallet()
@@ -69,6 +76,7 @@ sealed class WalletAction : Action {
object SetNeverToShow : Warnings()
object RemindLater : Warnings()
}
+
class CheckRemainingSignatures(val remainingSignatures: Int?) : Warnings()
}
@@ -79,7 +87,7 @@ sealed class WalletAction : Action {
}
data class LoadFiatRate(
- val wallet: Wallet? = null, val currency: Currency? = null
+ val wallet: Wallet? = null, val currency: Currency? = null,
) : WalletAction() {
data class Success(val fiatRate: Pair) : WalletAction()
object Failure : WalletAction()
@@ -114,6 +122,7 @@ sealed class WalletAction : Action {
object QrCode : WalletAction()
object ScanFails : WalletAction()
object SignedHashesMultiWalletDialog : WalletAction()
+ object ChooseTradeActionDialog : WalletAction()
}
object HideDialog : WalletAction()
@@ -123,8 +132,16 @@ sealed class WalletAction : Action {
object CreateWallet : WalletAction()
object EmptyWallet : WalletAction()
- sealed class TopUpAction : WalletAction() {
- data class TopUp(val context: Context, val toolbarColor: Int) : TopUpAction()
+ sealed class TradeCryptoAction : WalletAction() {
+ object Buy : TradeCryptoAction()
+ object Sell : TradeCryptoAction()
+ data class FinishSelling(val transactionId: String) : TradeCryptoAction()
+ data class SendCrypto(
+ val currencyId: String,
+ val amount: String,
+ val destinationAddress: String,
+ val transactionId: String
+ ) : TradeCryptoAction()
}
data class ChangeSelectedAddress(val type: AddressType) : WalletAction()
@@ -133,8 +150,8 @@ sealed class WalletAction : Action {
object ShowOnboarding : TwinsAction()
object SetOnboardingShown : TwinsAction()
data class SetTwinCard(
- val secondCardId: String, val number: TwinCardNumber,
- val isCreatingTwinCardsAllowed: Boolean,
+ val secondCardId: String, val number: TwinCardNumber,
+ val isCreatingTwinCardsAllowed: Boolean,
) : TwinsAction()
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt
index afa3936fb4..d08f8caecf 100644
--- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt
+++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt
@@ -9,6 +9,7 @@ import com.tangem.tap.common.redux.global.CryptoCurrencyName
import com.tangem.tap.common.redux.global.StateDialog
import com.tangem.tap.domain.configurable.warningMessage.WarningMessage
import com.tangem.tap.domain.extensions.toSendableAmounts
+import com.tangem.tap.domain.topup.TradeCryptoHelper
import com.tangem.tap.domain.twins.TwinCardNumber
import com.tangem.tap.features.wallet.models.PendingTransaction
import com.tangem.tap.features.wallet.models.toPendingTransactions
@@ -34,6 +35,7 @@ data class WalletState(
val primaryBlockchain: Blockchain? = null,
val primaryToken: Token? = null,
val isTestnet: Boolean = false,
+ val tradeCryptoAllowed: TradeCryptoAvailability = TradeCryptoAvailability()
) : StateType {
val primaryWallet = if (wallets.isNotEmpty()) wallets[0] else null
@@ -141,6 +143,7 @@ sealed class WalletDialog: StateDialog {
data class SelectAmountToSendDialog(val amounts: List?) : WalletDialog()
object ScanFailsDialog : WalletDialog()
object SignedHashesMultiWalletDialog : WalletDialog()
+ object ChooseTradeActionDialog : WalletDialog()
}
enum class ProgressState { Loading, Done, Error }
@@ -180,10 +183,15 @@ data class Artwork(
}
}
-data class TopUpState(
- val allowed: Boolean = true,
- val url: String? = null,
- val redirectUrl: String? = null
+data class TradeCryptoState(
+ val sellingAllowed: Boolean = false,
+ val buyingAllowed: Boolean = false,
+)
+
+data class TradeCryptoAvailability(
+ val sellingAllowed: Boolean = false,
+ val buyingAllowed: Boolean = false,
+ val availableToSell: Set = TradeCryptoHelper.AVAILABLE_TO_SELL,
)
data class TwinCardsState(
@@ -194,17 +202,17 @@ data class TwinCardsState(
)
data class WalletData(
- val pendingTransactions: List = emptyList(),
- val hashesCountVerified: Boolean? = null,
- val walletAddresses: WalletAddresses? = null,
- val currencyData: BalanceWidgetData = BalanceWidgetData(),
- val updatingWallet: Boolean = false,
- val topUpState: TopUpState = TopUpState(),
- val allowToSend: Boolean = true,
- val fiatRateString: String? = null,
- val fiatRate: BigDecimal? = null,
- val mainButton: WalletMainButton = WalletMainButton.SendButton(false),
- val currency: Currency? = null
+ val pendingTransactions: List = emptyList(),
+ val hashesCountVerified: Boolean? = null,
+ val walletAddresses: WalletAddresses? = null,
+ val currencyData: BalanceWidgetData = BalanceWidgetData(),
+ val updatingWallet: Boolean = false,
+ val tradeCryptoState: TradeCryptoState = TradeCryptoState(),
+ val allowToSend: Boolean = true,
+ val fiatRateString: String? = null,
+ val fiatRate: BigDecimal? = null,
+ val mainButton: WalletMainButton = WalletMainButton.SendButton(false),
+ val currency: Currency? = null
) {
fun shouldShowMultipleAddress(): Boolean {
val listOfAddresses = walletAddresses?.list ?: return false
diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TopUpMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TopUpMiddleware.kt
deleted file mode 100644
index 98b63904ba..0000000000
--- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TopUpMiddleware.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.tangem.tap.features.wallet.redux.middlewares
-
-import android.net.Uri
-import androidx.browser.customtabs.CustomTabsIntent
-import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager
-import com.tangem.tap.domain.topup.TopUpHelper
-import com.tangem.tap.domain.topup.TopUpManager
-import com.tangem.tap.features.wallet.redux.Currency
-import com.tangem.tap.features.wallet.redux.WalletAction
-import com.tangem.tap.scope
-import com.tangem.tap.store
-import kotlinx.coroutines.launch
-
-
-class TopUpMiddleware {
- fun handle(action: WalletAction.TopUpAction) {
- when (action) {
- is WalletAction.TopUpAction.TopUp -> {
- val selectedWalletData = store.state.walletState.getSelectedWalletData()
- val config = store.state.globalState.configManager?.config ?: return
- val addresses = selectedWalletData?.walletAddresses ?: return
- if (addresses.list.isEmpty()) return
-
- val defaultAddress = addresses.list[0].address
- val currency = selectedWalletData.currency
-
- if (currency is Currency.Token && currency.blockchain.isTestnet()) {
- val walletManager = store.state.walletState.getWalletManager(currency.token)
- if (walletManager !is EthereumWalletManager) return
-
- scope.launch {
- TopUpManager().topUpTestErc20Tokens(
- walletManager = walletManager, token = currency.token
- )
- }
- } else {
- val url = TopUpHelper.getUrl(
- currency?.blockchain,
- selectedWalletData.currencyData.currencySymbol!!,
- defaultAddress,
- config.moonPayApiKey,
- config.moonPayApiSecretKey
- )
-
- val customTabsIntent = CustomTabsIntent.Builder()
- .setToolbarColor(action.toolbarColor)
- .build()
- customTabsIntent.launchUrl(action.context, Uri.parse(url))
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt
new file mode 100644
index 0000000000..2b2087dd25
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt
@@ -0,0 +1,94 @@
+package com.tangem.tap.features.wallet.redux.middlewares
+
+import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager
+import com.tangem.blockchain.common.AmountType
+import com.tangem.tap.common.extensions.dispatchOnMain
+import com.tangem.tap.common.redux.navigation.AppScreen
+import com.tangem.tap.common.redux.navigation.NavigationAction
+import com.tangem.tap.domain.topup.TopUpManager
+import com.tangem.tap.domain.topup.TradeCryptoHelper
+import com.tangem.tap.features.send.redux.PrepareSendScreen
+import com.tangem.tap.features.send.redux.SendAction
+import com.tangem.tap.features.wallet.redux.Currency
+import com.tangem.tap.features.wallet.redux.WalletAction
+import com.tangem.tap.scope
+import com.tangem.tap.store
+import kotlinx.coroutines.launch
+import timber.log.Timber
+
+
+class TradeCryptoMiddleware {
+ fun handle(action: WalletAction.TradeCryptoAction) {
+ when (action) {
+ is WalletAction.TradeCryptoAction.Buy -> startExchange(action)
+ is WalletAction.TradeCryptoAction.Sell -> startExchange(action)
+ is WalletAction.TradeCryptoAction.SendCrypto -> preconfigureAndOpenSendScreen(action)
+ is WalletAction.TradeCryptoAction.FinishSelling -> openReceiptUrl(action.transactionId)
+ }
+ }
+
+ private fun startExchange(action: WalletAction.TradeCryptoAction) {
+ val selectedWalletData = store.state.walletState.getSelectedWalletData()
+ val config = store.state.globalState.configManager?.config ?: return
+ val addresses = selectedWalletData?.walletAddresses ?: return
+ if (addresses.list.isEmpty()) return
+
+ val defaultAddress = addresses.list[0].address
+ val currency = selectedWalletData.currency
+ val currencySymbol = selectedWalletData.currency?.currencySymbol ?: return
+
+ val exchangeAction = if (action is WalletAction.TradeCryptoAction.Buy) {
+ TradeCryptoHelper.Action.Buy
+ } else {
+ TradeCryptoHelper.Action.Sell
+ }
+
+ if (exchangeAction == TradeCryptoHelper.Action.Buy &&
+ currency is Currency.Token && currency.blockchain.isTestnet()
+ ) {
+ val walletManager = store.state.walletState.getWalletManager(currency.token)
+ if (walletManager !is EthereumWalletManager) return
+
+ scope.launch {
+ TopUpManager().topUpTestErc20Tokens(
+ walletManager = walletManager, token = currency.token
+ )
+ }
+ return
+ }
+
+ val url = TradeCryptoHelper.getUrl(
+ exchangeAction,
+ currency?.blockchain,
+ currencySymbol,
+ defaultAddress,
+ config.moonPayApiKey,
+ config.moonPayApiSecretKey
+ )
+ Timber.d("Moonpay $exchangeAction URL: $url")
+ store.dispatchOnMain(NavigationAction.OpenUrl(url))
+ }
+
+ private fun preconfigureAndOpenSendScreen(action: WalletAction.TradeCryptoAction.SendCrypto) {
+ val selectedWalletData = store.state.walletState.getSelectedWalletData() ?: return
+ val walletManager =
+ store.state.walletState.getWalletManager(selectedWalletData.currency)
+ store.dispatchOnMain(PrepareSendScreen(
+ coinAmount = walletManager?.wallet?.amounts?.get(AmountType.Coin),
+ coinRate = selectedWalletData.fiatRate,
+ walletManager = walletManager
+ ))
+ store.dispatchOnMain(SendAction.SendSpecificTransaction(
+ sendAmount = action.amount,
+ destinationAddress = action.destinationAddress,
+ transactionId = action.transactionId
+ ))
+ store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.Send))
+ }
+
+ private fun openReceiptUrl(transactionId: String) {
+ store.dispatchOnMain(NavigationAction.PopBackTo())
+ val url = TradeCryptoHelper.getSellCryptoReceiptUrl(transactionId)
+ store.dispatchOnMain(NavigationAction.OpenUrl(url))
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt
index a03fbe9c16..8dc207048b 100644
--- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt
+++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt
@@ -28,7 +28,7 @@ import org.rekotlin.Action
import org.rekotlin.Middleware
class WalletMiddleware {
- private val topUpMiddleware = TopUpMiddleware()
+ private val tradeCryptoMiddleware = TradeCryptoMiddleware()
private val twinsMiddleware = TwinsMiddleware()
private val warningsMiddleware = WarningsMiddleware()
private val multiWalletMiddleware = MultiWalletMiddleware()
@@ -39,7 +39,7 @@ class WalletMiddleware {
val globalState = state()?.globalState
val walletState = state()?.walletState
when (action) {
- is WalletAction.TopUpAction -> topUpMiddleware.handle(action)
+ is WalletAction.TradeCryptoAction -> tradeCryptoMiddleware.handle(action)
is WalletAction.TwinsAction -> twinsMiddleware.handle(action)
is WalletAction.Warnings -> warningsMiddleware.handle(action, globalState)
is WalletAction.MultiWallet ->
diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt
index 52a557ead6..030c2e2ab6 100644
--- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt
+++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt
@@ -1,7 +1,6 @@
package com.tangem.tap.features.wallet.redux.reducers
import com.tangem.blockchain.common.AmountType
-import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.Token
import com.tangem.common.extensions.isZero
import com.tangem.tap.common.extensions.toFiatString
@@ -38,8 +37,12 @@ class MultiWalletReducer {
),
walletAddresses = createAddressList(wallet),
mainButton = WalletMainButton.SendButton(false),
- topUpState = TopUpState(allowed = false),
- currency = Currency.Blockchain(blockchain)
+ currency = Currency.Blockchain(blockchain),
+ tradeCryptoState = TradeCryptoState(
+ sellingAllowed = state.tradeCryptoAllowed.sellingAllowed &&
+ state.tradeCryptoAllowed.availableToSell.contains(blockchain.currency),
+ buyingAllowed = state.tradeCryptoAllowed.buyingAllowed
+ )
)
}
@@ -63,8 +66,12 @@ class MultiWalletReducer {
),
walletAddresses = createAddressList(wallet),
mainButton = WalletMainButton.SendButton(false),
- topUpState = TopUpState(allowed = false),
- currency = Currency.Blockchain(action.blockchain)
+ currency = Currency.Blockchain(action.blockchain),
+ tradeCryptoState = TradeCryptoState(
+ sellingAllowed = state.tradeCryptoAllowed.sellingAllowed &&
+ state.tradeCryptoAllowed.availableToSell.contains(action.blockchain.currency),
+ buyingAllowed = state.tradeCryptoAllowed.buyingAllowed
+ )
)
val newState = state.copy(wallets = state.replaceWalletInWallets(walletData))
if (wallet != null && wallet.amounts[AmountType.Coin]?.value != null) {
@@ -165,7 +172,11 @@ fun Token.toWallet(state: WalletState): WalletData? {
),
walletAddresses = walletAddresses,
mainButton = WalletMainButton.SendButton(false),
- topUpState = TopUpState(allowed = false),
- currency = Currency.Token(this)
+ currency = Currency.Token(this),
+ tradeCryptoState = TradeCryptoState(
+ sellingAllowed = state.tradeCryptoAllowed.sellingAllowed &&
+ state.tradeCryptoAllowed.availableToSell.contains(this.symbol),
+ buyingAllowed = state.tradeCryptoAllowed.buyingAllowed
+ )
)
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt
index b39e928706..3298b8a9cc 100644
--- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt
+++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/WalletReducer.kt
@@ -50,7 +50,6 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
WalletData(
currencyData = BalanceWidgetData(BalanceStatus.EmptyCard),
mainButton = WalletMainButton.CreateWalletButton(creatingWalletAllowed),
- topUpState = TopUpState(false)
)
)
)
@@ -78,7 +77,6 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
wallets = listOf(
WalletData(
currencyData = BalanceWidgetData(BalanceStatus.UnknownBlockchain),
- topUpState = TopUpState(false)
)
)
)
@@ -95,6 +93,7 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
is WalletAction.LoadWallet -> {
if (action.blockchain == null) {
val wallets = newState.wallets.map { wallet ->
+
wallet.copy(
currencyData = wallet.currencyData.copy(
status = BalanceStatus.Loading,
@@ -102,15 +101,22 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
currencySymbol = wallet.currencyData.currencySymbol,
),
mainButton = WalletMainButton.SendButton(false),
- topUpState = TopUpState(
- allowed = action.allowTopUp
- ?: wallet.topUpState.allowed
+ tradeCryptoState = TradeCryptoState(
+ sellingAllowed = action.allowToSell ?: wallet.tradeCryptoState.sellingAllowed &&
+ state.walletState.tradeCryptoAllowed.availableToSell.contains(wallet.currencyData.currencySymbol),
+ buyingAllowed = action.allowToBuy
+ ?: wallet.tradeCryptoState.buyingAllowed
)
)
}
+ val tradeCryptoAllowed = TradeCryptoAvailability(
+ sellingAllowed = action.allowToSell ?: false,
+ buyingAllowed = action.allowToBuy ?: false
+ )
newState = newState.copy(
state = ProgressState.Loading,
- wallets = wallets
+ wallets = wallets,
+ tradeCryptoAllowed = tradeCryptoAllowed
)
} else {
val walletManager = newState.getWalletManager(action.blockchain) ?: return newState
@@ -126,8 +132,11 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
currencySymbol = wallet.currencyData.currencySymbol,
),
mainButton = WalletMainButton.SendButton(false),
- topUpState = TopUpState(
- allowed = action.allowTopUp ?: wallet.topUpState.allowed
+ tradeCryptoState = TradeCryptoState(
+ sellingAllowed = action.allowToSell ?: wallet.tradeCryptoState.sellingAllowed &&
+ state.walletState.tradeCryptoAllowed.availableToSell.contains(wallet.currencyData.currencySymbol),
+ buyingAllowed = action.allowToBuy
+ ?: wallet.tradeCryptoState.buyingAllowed
)
)
}
@@ -172,7 +181,6 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
status = BalanceStatus.Unreachable,
errorMessage = message
),
- topUpState = TopUpState(false)
)
val tokenWallets = action.wallet.getTokens()
.mapNotNull { newState.getWalletData(it) }
@@ -242,6 +250,9 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
is WalletAction.ShowDialog.SignedHashesMultiWalletDialog -> {
newState = newState.copy(walletDialog = WalletDialog.SignedHashesMultiWalletDialog)
}
+ is WalletAction.ShowDialog.ChooseTradeActionDialog -> {
+ newState = newState.copy(walletDialog = WalletDialog.ChooseTradeActionDialog)
+ }
is WalletAction.HideDialog -> {
newState = newState.copy(walletDialog = null)
}
@@ -251,7 +262,7 @@ private fun internalReduce(action: Action, state: AppState): WalletState {
)
}
is WalletAction.Send.Cancel -> newState = newState.copy(walletDialog = null)
- is WalletAction.TopUpAction -> return newState
+ is WalletAction.TradeCryptoAction -> return newState
is WalletAction.ChangeSelectedAddress -> {
val selectedWalletData = newState.getWalletData(newState.selectedWallet)
diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt
index 63a7a78812..c2ff298244 100644
--- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt
+++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt
@@ -86,11 +86,9 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), StoreS
btn_share.setOnClickListener { store.dispatch(WalletAction.ShowDialog.QrCode) }
- btn_top_up.setOnClickListener {
- store.dispatch(
- WalletAction.TopUpAction.TopUp(requireContext(), R.color.backgroundLightGray)
- )
- }
+ btn_top_up.setOnClickListener { store.dispatch(WalletAction.TradeCryptoAction.Buy) }
+
+ btn_sell.setOnClickListener { store.dispatch(WalletAction.TradeCryptoAction.Sell) }
}
override fun newState(state: WalletState) {
@@ -131,8 +129,9 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), StoreS
srl_wallet_details.setOnRefreshListener {
if (selectedWallet.currencyData.status != BalanceStatus.Loading) {
store.dispatch(WalletAction.LoadWallet(
- selectedWallet.topUpState.allowed,
- selectedWallet.currency?.blockchain
+ allowToBuy = selectedWallet.tradeCryptoState.buyingAllowed,
+ allowToSell = selectedWallet.tradeCryptoState.sellingAllowed,
+ blockchain = selectedWallet.currency?.blockchain
))
}
}
@@ -140,6 +139,9 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), StoreS
if (selectedWallet.currencyData.status != BalanceStatus.Loading) {
srl_wallet_details.isRefreshing = false
}
+
+ btn_top_up.isEnabled = selectedWallet.tradeCryptoState.buyingAllowed
+ btn_sell.show(selectedWallet.tradeCryptoState.sellingAllowed)
}
private fun handleCurrencyIcon(wallet: WalletData) {
diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/ChooseTradeActionDialog.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/ChooseTradeActionDialog.kt
new file mode 100644
index 0000000000..95ff1f65ea
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/ChooseTradeActionDialog.kt
@@ -0,0 +1,32 @@
+package com.tangem.tap.features.wallet.ui.dialogs
+
+import android.content.Context
+import com.google.android.material.bottomsheet.BottomSheetDialog
+import com.tangem.tap.features.wallet.redux.WalletAction
+import com.tangem.tap.store
+import com.tangem.wallet.R
+import kotlinx.android.synthetic.main.dialog_wallet_trade.*
+
+class ChooseTradeActionDialog(context: Context) : BottomSheetDialog(context) {
+
+ init {
+ this.setContentView(R.layout.dialog_wallet_trade)
+ }
+
+ override fun show() {
+ super.show()
+
+ this.setOnDismissListener {
+ store.dispatch(WalletAction.HideDialog)
+ }
+
+ dialog_btn_buy.setOnClickListener {
+ store.dispatch(WalletAction.TradeCryptoAction.Buy)
+ dismiss()
+ }
+ dialog_btn_sell.setOnClickListener {
+ store.dispatch(WalletAction.TradeCryptoAction.Sell)
+ dismiss()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt
index ce0623ac86..14883f5233 100644
--- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt
+++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SingleWalletView.kt
@@ -16,10 +16,7 @@ import com.tangem.tap.features.wallet.ui.BalanceWidget
import com.tangem.tap.features.wallet.ui.MultipleAddressUiHelper
import com.tangem.tap.features.wallet.ui.WalletFragment
import com.tangem.tap.features.wallet.ui.adapters.PendingTransactionsAdapter
-import com.tangem.tap.features.wallet.ui.dialogs.AmountToSendDialog
-import com.tangem.tap.features.wallet.ui.dialogs.QrDialog
-import com.tangem.tap.features.wallet.ui.dialogs.ScanFailsDialog
-import com.tangem.tap.features.wallet.ui.dialogs.SignedHashesWarningDialog
+import com.tangem.tap.features.wallet.ui.dialogs.*
import com.tangem.tap.store
import com.tangem.wallet.R
import kotlinx.android.synthetic.main.card_balance.*
@@ -124,12 +121,17 @@ class SingleWalletView : WalletView {
setupButtonsType(state, fragment)
- val btnConfirm = if (state.topUpState.allowed) {
+ val btnConfirm = if (state.tradeCryptoState.sellingAllowed ||
+ state.tradeCryptoState.buyingAllowed
+ ) {
btn_confirm_short
} else {
btn_confirm_long
}
- val btnScan = if (state.topUpState.allowed) {
+
+ val btnScan = if (state.tradeCryptoState.sellingAllowed ||
+ state.tradeCryptoState.buyingAllowed
+ ) {
btn_scan_short
} else {
btn_scan_long
@@ -149,14 +151,26 @@ class SingleWalletView : WalletView {
btn_show_qr.setOnClickListener { store.dispatch(WalletAction.ShowDialog.QrCode) }
btn_top_up.setOnClickListener {
- store.dispatch(
- WalletAction.TopUpAction.TopUp(fragment.requireContext(), R.color.backgroundLightGray)
- )
+ tradeCryptoAction(state.tradeCryptoState)
}
}
+ private fun tradeCryptoAction(tradeCryptoState: TradeCryptoState) {
+ val allowedToBuy = tradeCryptoState.buyingAllowed
+ val allowedToSell = tradeCryptoState.sellingAllowed
+ val action = when {
+ allowedToBuy && !allowedToSell -> WalletAction.TradeCryptoAction.Buy
+ !allowedToBuy && allowedToSell -> WalletAction.TradeCryptoAction.Sell
+ allowedToBuy && allowedToSell -> WalletAction.ShowDialog.ChooseTradeActionDialog
+ else -> null
+ }
+ if (action != null) store.dispatch(action)
+ }
+
private fun setupButtonsType(state: WalletData, fragment: WalletFragment) = with(fragment) {
- if (state.topUpState.allowed) {
+ if (state.tradeCryptoState.sellingAllowed ||
+ state.tradeCryptoState.buyingAllowed
+ ) {
l_buttons_long.hide()
l_buttons_short.show()
} else {
@@ -244,6 +258,9 @@ class SingleWalletView : WalletView {
dialog = SignedHashesWarningDialog.create(context).apply { show() }
}
}
+ is WalletDialog.ChooseTradeActionDialog -> {
+ if (dialog == null) dialog = ChooseTradeActionDialog(context).apply { show() }
+ }
null -> {
dialog?.dismiss()
dialog = null
diff --git a/app/src/main/java/com/tangem/tap/network/moonpay/MoonpayApi.kt b/app/src/main/java/com/tangem/tap/network/moonpay/MoonpayApi.kt
new file mode 100644
index 0000000000..f3e062abf3
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/network/moonpay/MoonpayApi.kt
@@ -0,0 +1,16 @@
+package com.tangem.tap.network.moonpay
+
+import retrofit2.http.GET
+import retrofit2.http.Query
+
+interface MoonpayApi {
+ @GET( MOOONPAY_IP_ADDRESS_REQUEST_URL)
+ suspend fun getUserStatus(
+ @Query("apiKey") moonpayApiKey: String
+ ): MoonPayUserStatus
+
+ companion object {
+ const val MOOONPAY_BASE_URL = "https://api.moonpay.com/v4/"
+ const val MOOONPAY_IP_ADDRESS_REQUEST_URL = "ip_address/"
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/network/moonpay/MoonpayService.kt b/app/src/main/java/com/tangem/tap/network/moonpay/MoonpayService.kt
new file mode 100644
index 0000000000..c20d22863e
--- /dev/null
+++ b/app/src/main/java/com/tangem/tap/network/moonpay/MoonpayService.kt
@@ -0,0 +1,24 @@
+package com.tangem.tap.network.moonpay
+
+import com.squareup.moshi.JsonClass
+import com.tangem.commands.common.network.Result
+import com.tangem.commands.common.network.performRequest
+import com.tangem.tap.network.createRetrofitInstance
+
+class MoonpayService {
+
+ private val moonpayApi: MoonpayApi by lazy {
+ createRetrofitInstance(MoonpayApi.MOOONPAY_BASE_URL)
+ .create(MoonpayApi::class.java)
+ }
+
+ suspend fun getUserStatus(moonpayApiKey: String): Result {
+ return performRequest { moonpayApi.getUserStatus(moonpayApiKey) }
+ }
+}
+
+@JsonClass(generateAdapter = true)
+data class MoonPayUserStatus(
+ val isBuyAllowed: Boolean,
+ val isSellAllowed: Boolean
+)
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_arrows_up_down_short_btn.xml b/app/src/main/res/drawable/ic_arrows_up_down_short_btn.xml
new file mode 100644
index 0000000000..51b285c947
--- /dev/null
+++ b/app/src/main/res/drawable/ic_arrows_up_down_short_btn.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_wallet_trade.xml b/app/src/main/res/layout/dialog_wallet_trade.xml
new file mode 100644
index 0000000000..062d0286d1
--- /dev/null
+++ b/app/src/main/res/layout/dialog_wallet_trade.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_topup.xml b/app/src/main/res/layout/fragment_topup.xml
index 8069c307f0..01182c0c4c 100644
--- a/app/src/main/res/layout/fragment_topup.xml
+++ b/app/src/main/res/layout/fragment_topup.xml
@@ -11,7 +11,7 @@
android:layout_height="?attr/actionBarSize"
app:layout_constraintTop_toTopOf="parent"
app:navigationIcon="@drawable/ic_close"
- app:title="@string/wallet_button_topup" />
+ app:title="@string/wallet_button_buy" />
diff --git a/app/src/main/res/layout/fragment_wallet_details.xml b/app/src/main/res/layout/fragment_wallet_details.xml
index 8270cd53ac..7b61f56d8d 100644
--- a/app/src/main/res/layout/fragment_wallet_details.xml
+++ b/app/src/main/res/layout/fragment_wallet_details.xml
@@ -83,12 +83,12 @@
android:id="@+id/rv_pending_transaction"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
android:layout_marginBottom="8dp"
android:nestedScrollingEnabled="false"
android:overScrollMode="never"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
- android:layout_marginTop="16dp"
app:layout_constraintTop_toBottomOf="@id/barrier_currency_title" />
+ android:textColor="@android:color/white"
+ android:textSize="14sp" />
-
+
+
+
+
+ app:layout_constraintHorizontal_chainStyle="packed"
+ app:layout_constraintStart_toEndOf="@id/btn_top_up"
+ app:layout_constraintEnd_toStartOf="@id/btn_confirm"
+ app:layout_constraintTop_toBottomOf="@id/barrier"
+ app:layout_constraintVertical_bias="1" />
diff --git a/app/src/main/res/layout/layout_send_address_payid.xml b/app/src/main/res/layout/layout_send_address_payid.xml
index 00a5617a9d..2b0f046335 100644
--- a/app/src/main/res/layout/layout_send_address_payid.xml
+++ b/app/src/main/res/layout/layout_send_address_payid.xml
@@ -32,6 +32,7 @@
android:id="@+id/etAddressOrPayId"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:background="@color/backgroundLightGray"
android:ellipsize="middle"
android:inputType="textNoSuggestions"
android:paddingStart="0dp"
@@ -150,6 +151,7 @@
android:id="@+id/etMemo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:background="@color/backgroundLightGray"
android:ellipsize="middle"
android:paddingStart="0dp"
android:paddingEnd="0dp"
@@ -180,6 +182,7 @@
android:id="@+id/etDestinationTag"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:background="@color/backgroundLightGray"
android:ellipsize="end"
android:inputType="number"
android:paddingStart="0dp"
diff --git a/app/src/main/res/layout/layout_send_amount.xml b/app/src/main/res/layout/layout_send_amount.xml
index e2b5441fa2..b2e8700482 100644
--- a/app/src/main/res/layout/layout_send_amount.xml
+++ b/app/src/main/res/layout/layout_send_amount.xml
@@ -51,6 +51,7 @@
android:id="@+id/etAmountToSend"
android:layout_width="match_parent"
android:layout_height="82dp"
+ android:background="@color/backgroundLightGray"
android:fontFamily="sans-serif-light"
android:inputType="numberDecimal"
android:paddingStart="0dp"
diff --git a/app/src/main/res/layout/layout_wallet_short_buttons.xml b/app/src/main/res/layout/layout_wallet_short_buttons.xml
index 072306c7b7..be494ee95b 100644
--- a/app/src/main/res/layout/layout_wallet_short_buttons.xml
+++ b/app/src/main/res/layout/layout_wallet_short_buttons.xml
@@ -28,10 +28,10 @@
android:layout_marginStart="8dp"
android:layout_marginTop="30dp"
android:layout_marginBottom="33dp"
- android:drawableTop="@drawable/ic_arrow_up_short_btn"
+ android:drawableTop="@drawable/ic_arrows_up_down_short_btn"
android:gravity="bottom|center_horizontal"
android:paddingTop="1dp"
- android:text="@string/wallet_button_topup"
+ android:text="@string/wallet_button_trade"
app:drawableTint="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/btn_confirm_short"
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index de5579c26b..509d2b72be 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -5,6 +5,8 @@
#0022D4
#1ACE80
+ @color/backgroundLightGray
+
@color/accent
#661ACE80
@color/darkGray6
diff --git a/app/src/main/res/values/strings_untranslated.xml b/app/src/main/res/values/strings_untranslated.xml
index 062a7439ae..01bdb3d5d6 100644
--- a/app/src/main/res/values/strings_untranslated.xml
+++ b/app/src/main/res/values/strings_untranslated.xml
@@ -1,5 +1,7 @@
- Top Up
+ Buy
+ Sell
+ Trade
Default
Compatibility
Legacy
@@ -161,4 +163,7 @@ this wallet.
Failed to establish WalletConnect session: timeout error. Please, try again later.
This is a Testnet card. Don\'t accept it as a payment. This card must only be used for testing and development purposes.
+
+
+ Do you want to buy or sell crypto?