Skip to content

Commit

Permalink
Feature/vip codes2 (#2189)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexanderPavlenko authored Jul 3, 2024
2 parents 28e732a + e2acdf9 commit 6c107ca
Show file tree
Hide file tree
Showing 26 changed files with 527 additions and 347 deletions.
Binary file added mbw/src/main/assets/token-logos/usdt_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 0 additions & 12 deletions mbw/src/main/java/com/mycelium/bequant/remote/model/User.kt

This file was deleted.

16 changes: 16 additions & 0 deletions mbw/src/main/java/com/mycelium/bequant/remote/model/UserStatus.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.mycelium.bequant.remote.model

enum class UserStatus {
VIP,
REGULAR;

fun isVIP() = this == VIP

companion object {
fun fromName(name: String?) = when (name) {
VIP.name -> VIP
REGULAR.name -> REGULAR
else -> null
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.mycelium.bequant.remote.repositories

import com.mycelium.wallet.external.changelly2.remote.UserRepository

object Api {
val accountRepository by lazy { AccountApiRepository() }
Expand Down
28 changes: 14 additions & 14 deletions mbw/src/main/java/com/mycelium/wallet/activity/modern/ModernMain.kt
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ import com.mycelium.wallet.event.*
import com.mycelium.wallet.external.changelly.ChangellyConstants
import com.mycelium.wallet.external.changelly2.ExchangeFragment
import com.mycelium.wallet.external.changelly2.HistoryFragment
import com.mycelium.wallet.external.changelly2.remote.UserRepository
import com.mycelium.wallet.external.changelly2.remote.Api
import com.mycelium.wallet.external.mediaflow.NewsConstants
import com.mycelium.wallet.fio.FioRequestNotificator
import com.mycelium.wallet.modularisation.ModularisationVersionHelper
Expand All @@ -65,6 +65,7 @@ import com.mycelium.wapi.wallet.manager.State
import com.squareup.otto.Subscribe
import info.guardianproject.netcipher.proxy.OrbotHelper
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import java.util.*
import java.util.concurrent.TimeUnit

Expand All @@ -76,7 +77,7 @@ class ModernMain : AppCompatActivity(), BackHandler {
private var mNewsTab: TabLayout.Tab? = null
private var mAccountsTab: TabLayout.Tab? = null
private var mTransactionsTab: TabLayout.Tab? = null
// private var mVipTab: TabLayout.Tab? = null
private var mVipTab: TabLayout.Tab? = null
private var mRecommendationsTab: TabLayout.Tab? = null
private var mFioRequestsTab: TabLayout.Tab? = null
private var refreshItem: MenuItem? = null
Expand All @@ -92,7 +93,7 @@ class ModernMain : AppCompatActivity(), BackHandler {

lateinit var binding: ModernMainBinding

private val userRepository = UserRepository()
private val userRepository = Api.statusRepository

public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand Down Expand Up @@ -124,8 +125,8 @@ class ModernMain : AppCompatActivity(), BackHandler {
mTabsAdapter!!.addTab(mBalanceTab!!, BalanceMasterFragment::class.java, null, TAB_BALANCE)
mTransactionsTab = binding.pagerTabs.newTab().setText(getString(R.string.tab_transactions))
mTabsAdapter!!.addTab(mTransactionsTab!!, TransactionHistoryFragment::class.java, null, TAB_HISTORY)
// mVipTab = binding.pagerTabs.newTab().setText(getString(R.string.tab_vip))
// mTabsAdapter!!.addTab(mVipTab!!, VipFragment::class.java, null, TAB_VIP)
mVipTab = binding.pagerTabs.newTab().setText(getString(R.string.tab_vip))
mTabsAdapter!!.addTab(mVipTab!!, VipFragment::class.java, null, TAB_VIP)

if (getPartnersLocalized()?.isActive() == true) {
mRecommendationsTab =
Expand Down Expand Up @@ -167,15 +168,14 @@ class ModernMain : AppCompatActivity(), BackHandler {
lifecycleScope.launchWhenResumed {
ChangeLog.showIfNewVersion(this@ModernMain, supportFragmentManager)
}
// lifecycleScope.launchWhenStarted {
// userRepository.identify()
// userRepository.userFlow.collect { user ->
// val icon =
// if (user.status.isVIP()) R.drawable.action_bar_logo_vip
// else R.drawable.action_bar_logo
// supportActionBar?.setIcon(icon)
// }
// }
lifecycleScope.launch {
userRepository.statusFlow.collect { status ->
val icon =
if (status.isVIP()) R.drawable.action_bar_logo_vip
else R.drawable.action_bar_logo
supportActionBar?.setIcon(icon)
}
}
}

fun selectTab(tabTag: String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import androidx.appcompat.app.AlertDialog
import androidx.core.view.isVisible
import androidx.core.widget.doOnTextChanged
import androidx.fragment.app.Fragment
Expand Down Expand Up @@ -49,7 +50,7 @@ class VipFragment : Fragment() {
binding.vipProgress.isVisible = state.progress
updateButtons(state)
handleError(state.error)
handleSuccess(state.success)
handleSuccess(state.isVip)
}
}

Expand All @@ -70,39 +71,59 @@ class VipFragment : Fragment() {

private fun updateButtons(state: VipViewModel.State) {
binding.vipApplyButton.apply {
isEnabled = state.text.isNotEmpty() && !state.progress && !state.error
isEnabled = state.text.isNotEmpty() && !state.progress && state.error == null
text = if (state.progress) "" else getString(R.string.apply_vip_code)
setOnClickListener { viewModel.applyCode() }
}
}

private fun handleError(error: Boolean) = binding.apply {
if (error) {
errorText.isVisible = true
vipCodeInput.setBackgroundResource(R.drawable.bg_input_text_filled_error)
} else {
errorText.isVisible = false
vipCodeInput.setBackgroundResource(R.drawable.bg_input_text_filled)
private fun handleError(error: VipViewModel.ErrorType?) = binding.apply {
when (error) {
null -> {
errorText.isVisible = false
vipCodeInput.setBackgroundResource(R.drawable.bg_input_text_filled)
}

VipViewModel.ErrorType.BAD_REQUEST -> {
errorText.isVisible = true
vipCodeInput.setBackgroundResource(R.drawable.bg_input_text_filled_error)
}

else -> {
hideKeyBoard()
showViperUnexpectedErrorDialog()
}
}
}

private fun handleSuccess(success: Boolean) {
if (!success) return
binding.apply {
vipApplyButton.isVisible = false
vipInputGroup.isVisible = false
vipSuccessGroup.isVisible = true
vipTitle.setText(R.string.vip_title_success)
vipCodeInput.apply {
hint = null
text = null
isFocusable = false
clearFocus()
vipApplyButton.isVisible = !success
vipInputGroup.isVisible = !success
vipSuccessGroup.isVisible = success
vipTitle.setText(if (success) R.string.vip_title_success else R.string.vip_title)
if (success) {
vipCodeInput.apply {
hint = null
text = null
clearFocus()
}
hideKeyBoard()
} else {
vipCodeInput.hint = getString(R.string.vip_code_hint)
}
hideKeyBoard()
}
}

private fun showViperUnexpectedErrorDialog() {
AlertDialog.Builder(requireContext())
.setTitle(getString(R.string.vip_unexpected_alert_title))
.setMessage(getString(R.string.vip_unexpected_alert_message))
.setPositiveButton(R.string.button_ok, null)
.setOnDismissListener { viewModel.resetState() }
.show()
}

private fun hideKeyBoard() {
val imm = context?.getSystemService(Activity.INPUT_METHOD_SERVICE) as? InputMethodManager
imm?.hideSoftInputFromWindow(requireView().windowToken, 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,17 @@ import com.mycelium.wallet.update
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import retrofit2.HttpException

class VipViewModel : ViewModel() {

private val userRepository = Api.userRepository
private val userRepository = Api.statusRepository

data class State(
val success: Boolean = false,
val error: Boolean = false,
val isVip: Boolean = false,
val error: ErrorType? = null,
val progress: Boolean = true,
val text: String = "",
)
Expand All @@ -26,47 +27,42 @@ class VipViewModel : ViewModel() {

init {
viewModelScope.launch {
val initialUser = userRepository.userFlow.first()
_stateFlow.update { state ->
state.copy(
progress = false,
success = initialUser.status.isVIP(),
)
userRepository.statusFlow.collect { status ->
val isVip = status.isVIP()
_stateFlow.update { state -> state.copy(progress = false, isVip = isVip) }
}
}
}

fun updateVipText(text: String) {
_stateFlow.update { state -> state.copy(text = text, success = false, error = false) }
_stateFlow.update { s -> s.copy(text = text, error = null) }
}

private val exceptionHandler = CoroutineExceptionHandler { _, _ ->
_stateFlow.update { state ->
state.copy(
progress = false,
success = false,
error = true,
)
private val exceptionHandler = CoroutineExceptionHandler { _, e ->
var errorType = ErrorType.UNEXPECTED
if (e is HttpException) {
if (e.code() == 404 || e.code() == 409 || e.code() == 401) {
errorType = ErrorType.BAD_REQUEST
}
}
_stateFlow.update { s -> s.copy(progress = false, error = errorType, isVip = false) }
}

fun applyCode() {
viewModelScope.launch(exceptionHandler) {
_stateFlow.update { state ->
state.copy(
progress = true,
success = false,
error = false,
)
}
_stateFlow.update { s -> s.copy(progress = true, error = null, isVip = false) }
val status = userRepository.applyVIPCode(_stateFlow.value.text)
_stateFlow.update { state ->
state.copy(
progress = false,
success = status.isVIP(),
error = !status.isVIP(),
)
}
val error = if (status.isVIP()) null else ErrorType.BAD_REQUEST
_stateFlow.update { s -> s.copy(progress = false, error = error) }
}
}

fun resetState() {
_stateFlow.update { s -> s.copy(progress = false, error = null, isVip = false) }
}

enum class ErrorType {
UNEXPECTED,
BAD_REQUEST,
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package com.mycelium.wallet.external.changelly

import com.mycelium.wallet.external.changelly.model.*
import org.jetbrains.annotations.TestOnly
import com.mycelium.wallet.external.changelly.model.ChangellyCurrency
import com.mycelium.wallet.external.changelly.model.ChangellyGetExchangeAmountResponse
import com.mycelium.wallet.external.changelly.model.ChangellyListResponse
import com.mycelium.wallet.external.changelly.model.ChangellyResponse
import com.mycelium.wallet.external.changelly.model.ChangellyTransaction
import com.mycelium.wallet.external.changelly.model.ChangellyTransactionOffer
import com.mycelium.wallet.external.changelly.model.FixRate
import retrofit2.Call
import retrofit2.Response
import retrofit2.http.POST
Expand Down Expand Up @@ -56,7 +61,17 @@ interface ChangellyAPIService {
@Query("from") from: String,
@Query("to") to: String,
@Query("amountFrom") amount: BigDecimal = BigDecimal.ONE,
): Response<ChangellyListResponse<FixRateForAmount>>
): Response<ChangellyListResponse<FixRate>>

@Deprecated(
"To get the fixed rate, you need to use getFixRateForAmount, but the transaction amount must be within limits",
ReplaceWith("getFixRateForAmount")
)
@POST("getFixRate")
suspend fun getFixRate(
@Query("from") from: String,
@Query("to") to: String,
): Response<ChangellyListResponse<FixRate>>

@POST("createFixTransaction")
suspend fun createFixTransaction(
Expand All @@ -66,24 +81,17 @@ interface ChangellyAPIService {
@Query("address") address: String,
@Query("rateId") rateId: String,
@Query("refundAddress") refundAddress: String,
): Response<ChangellyResponse<ChangellyTransactionOffer>>
): ChangellyResponse<ChangellyTransactionOffer>

@POST("getTransactions")
suspend fun getTransaction(
@Query("id") id: String
): Response<ChangellyResponse<List<ChangellyTransaction>>>
): ChangellyResponse<List<ChangellyTransaction>>

@POST("getTransactions")
suspend fun getTransactions(
@Query("id") id: List<String>,
): Response<ChangellyResponse<List<ChangellyTransaction>>>


@TestOnly
@POST("getFixRate")
suspend fun getFixRate(@Query("from") from: String,
@Query("to") to: String): Response<ChangellyResponse<FixRateForAmount>>

): ChangellyResponse<List<ChangellyTransaction>>

companion object {
const val BCH = "BCH"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ private void createOffer() {
amount = getIntent().getDoubleExtra(ChangellyAPIService.AMOUNT, 0);
currency = getIntent().getStringExtra(ChangellyAPIService.FROM);
receivingAddress = getIntent().getStringExtra(ChangellyAPIService.DESTADDRESS);
ChangellyRetrofitFactory.INSTANCE.getApi()
ChangellyRetrofitFactory.INSTANCE.getChangellyApi()
.createTransaction(currency, BTC, amount, receivingAddress)
.enqueue(new GetOfferCallback(amount));
progressDialog = new ProgressDialog(this);
Expand Down
Loading

0 comments on commit 6c107ca

Please sign in to comment.