diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 7bfef59df1..0000000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 99b43a1293..4d9c559847 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -31,6 +31,9 @@ android { minifyEnabled false applicationIdSuffix ".dev" signingConfig signingConfigs.debug + firebaseCrashlytics { + mappingFileUploadEnabled false + } } debug_beta { initWith debug @@ -67,7 +70,7 @@ dependencies { implementation 'com.google.android.material:material:1.2.1' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.10' - implementation 'com.tangem:blockchain:1.83.0' + implementation 'com.tangem:blockchain:1.96.0' implementation 'com.tangem:core:1.68.0' implementation 'com.tangem:sdk:1.68.0' diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png index 4c55d07eb3..8e9c7d9162 100644 Binary files a/app/src/main/ic_launcher-playstore.png and b/app/src/main/ic_launcher-playstore.png differ diff --git a/app/src/main/java/com/tangem/tap/domain/PayIdManager.kt b/app/src/main/java/com/tangem/tap/domain/PayIdManager.kt index 591473e9cb..3773bd41b7 100644 --- a/app/src/main/java/com/tangem/tap/domain/PayIdManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/PayIdManager.kt @@ -73,6 +73,7 @@ class PayIdManager { Blockchain.BitcoinCash, Blockchain.Binance, Blockchain.RSK, + Blockchain.Tezos ) fun isPayId(value: String?): Boolean = value?.contains(payIdRegExp) ?: false diff --git a/app/src/main/java/com/tangem/tap/domain/TapErrors.kt b/app/src/main/java/com/tangem/tap/domain/TapErrors.kt index 6e5388a40d..35229ce2e6 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapErrors.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapErrors.kt @@ -6,7 +6,7 @@ import com.tangem.wallet.R interface TapErrors -interface ArgError{ +interface ArgError { val args: List? } @@ -21,6 +21,7 @@ sealed class TapError( ) : Throwable(), TapErrors, ArgError { object UnknownError : TapError(R.string.send_error_unknown) + data class CustomError(val customMessage: String) : TapError(R.string.common_custom_string, listOf(customMessage)) object PayIdAlreadyCreated : TapError(R.string.wallet_create_payid_error_already_created) object PayIdCreatingError : TapError(R.string.wallet_create_payid_error_message) object PayIdEmptyField : TapError(R.string.wallet_create_payid_empty) 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 c6e77e8a9f..cea0ea99b2 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -12,7 +12,6 @@ import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.domain.extensions.amountToCreateAccount import com.tangem.tap.domain.extensions.isNoAccountError import com.tangem.tap.domain.tasks.ScanNoteResponse -import com.tangem.tap.features.wallet.redux.PayIdState import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.network.NetworkConnectivity import com.tangem.tap.network.coinmarketcap.CoinMarketCapService @@ -25,6 +24,7 @@ import java.math.BigDecimal class TapWalletManager { private val payIdManager = PayIdManager() private val coinMarketCapService = CoinMarketCapService() + private var tapWorkarounds: TapWorkarounds? = null suspend fun loadWalletData() { val walletManager = store.state.globalState.scanNoteResponse?.walletManager @@ -78,6 +78,7 @@ class TapWalletManager { } suspend fun onCardScanned(data: ScanNoteResponse) { + tapWorkarounds = TapWorkarounds(data.card) withContext(Dispatchers.Main) { store.dispatch(WalletAction.ResetState) store.dispatch(GlobalAction.SaveScanNoteResponse(data)) @@ -142,7 +143,6 @@ class TapWalletManager { private suspend fun loadPayIdIfNeeded(): Result? { val scanNoteResponse = store.state.globalState.scanNoteResponse if (!TapConfig.usePayId || - store.state.walletState.payIdData.payIdState == PayIdState.Disabled || scanNoteResponse?.walletManager?.wallet?.blockchain?.isPayIdSupported() == false) { return null } @@ -160,7 +160,11 @@ class TapWalletManager { is Result.Success -> { val payId = result.data if (payId == null) { - store.dispatch(WalletAction.LoadPayId.NotCreated) + if (tapWorkarounds?.isPayIdCreationEnabled() == false) { + store.dispatch(WalletAction.DisablePayId) + } else { + store.dispatch(WalletAction.LoadPayId.NotCreated) + } } else { store.dispatch(WalletAction.LoadPayId.Success(payId)) } diff --git a/app/src/main/java/com/tangem/tap/domain/TapWorkarounds.kt b/app/src/main/java/com/tangem/tap/domain/TapWorkarounds.kt new file mode 100644 index 0000000000..7764650537 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/domain/TapWorkarounds.kt @@ -0,0 +1,17 @@ +package com.tangem.tap.domain + +import com.tangem.commands.Card + +class TapWorkarounds(val card: Card) { + + private val isStart2Coin: Boolean = card.cardData?.issuerName == START_2_COIN_ISSUER + + fun isPayIdCreationEnabled(): Boolean { + if (isStart2Coin) return false + return true + } + + companion object { + const val START_2_COIN_ISSUER = "start2coin" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/extensions/BlockchainExtensions.kt b/app/src/main/java/com/tangem/tap/domain/extensions/BlockchainExtensions.kt index b9866e5359..00ad0c17ea 100644 --- a/app/src/main/java/com/tangem/tap/domain/extensions/BlockchainExtensions.kt +++ b/app/src/main/java/com/tangem/tap/domain/extensions/BlockchainExtensions.kt @@ -3,6 +3,7 @@ package com.tangem.tap.domain.extensions import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Token import org.stellar.sdk.requests.ErrorResponse +import java.math.BigDecimal fun Blockchain.isNoAccountError(exception: Throwable): Boolean { @@ -17,10 +18,14 @@ fun Blockchain.isNoAccountError(exception: Throwable): Boolean { fun Blockchain.amountToCreateAccount(token: Token? = null): Double? { return when (this) { - Blockchain.Stellar -> if (token?.symbol == NODL) 1.5 else 1.toDouble() + Blockchain.Stellar -> if (token?.symbol == NODL) 1.5 else 1.toDouble() Blockchain.XRP -> 20.toDouble() else -> null } } +fun Blockchain.minimalAmount(): BigDecimal { + return 1.toBigDecimal().movePointLeft(decimals()) +} + private const val NODL = "NODL" \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/SendScreenAction.kt b/app/src/main/java/com/tangem/tap/features/send/redux/SendScreenAction.kt index b0ed6c6bf4..e78fb3a81a 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/SendScreenAction.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/SendScreenAction.kt @@ -2,6 +2,7 @@ package com.tangem.tap.features.send.redux import com.tangem.Message import com.tangem.blockchain.common.Amount +import com.tangem.tangem_sdk_new.ui.animation.VoidCallback import com.tangem.tap.common.redux.ErrorAction import com.tangem.tap.common.redux.ToastNotificationAction import com.tangem.tap.domain.TapError @@ -114,4 +115,13 @@ sealed class SendAction : SendScreenAction { } data class SendError(override val error: TapError) : SendAction(), ErrorAction + + sealed class Dialog : SendAction() { + data class ShowTezosWarningDialog( + val reduceCallback: VoidCallback, + val sendAllCallback: VoidCallback, + val reduceAmount: BigDecimal, + ) : Dialog() + object Hide : Dialog() + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/AmountMiddleware.kt b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/AmountMiddleware.kt index 389822d53a..08dc775fba 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/AmountMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/AmountMiddleware.kt @@ -1,6 +1,7 @@ package com.tangem.tap.features.send.redux.middlewares import com.tangem.blockchain.common.Amount +import com.tangem.blockchain.common.TransactionError import com.tangem.common.extensions.isZero import com.tangem.tap.common.redux.AppState import com.tangem.tap.features.send.redux.* @@ -59,6 +60,7 @@ class AmountMiddleware { val amountToSend = Amount(typedAmount, sendState.getTotalAmountToSend(inputCrypto)) val transactionErrors = walletManager.validateTransaction(amountToSend, sendState.feeState.currentFee) + transactionErrors.remove(TransactionError.TezosSendAll) if (transactionErrors.isEmpty()) { dispatch(AmountAction.SetAmountError(null)) } else { 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 aad00d6912..03e3ba943c 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,11 +9,9 @@ import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.domain.TapError -import com.tangem.tap.features.send.redux.AddressPayIdActionUi -import com.tangem.tap.features.send.redux.AmountActionUi +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.SendAction -import com.tangem.tap.features.send.redux.SendActionUi import com.tangem.tap.features.send.redux.states.SendButtonState import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.scope @@ -55,12 +53,35 @@ private fun verifyAndSendTransaction( val amountToSend = Amount(typedAmount, sendState.getTotalAmountToSend()) - val verifyResult = walletManager.validateTransaction(amountToSend, feeAmount) - if (verifyResult.isNotEmpty()) { - dispatch(SendAction.SendError(createValidateTransactionError(verifyResult, walletManager))) - return + val transactionErrors = walletManager.validateTransaction(amountToSend, feeAmount) + val hadTezosError = transactionErrors.remove(TransactionError.TezosSendAll) + when { + hadTezosError -> { + val reduceAmount = walletManager.wallet.blockchain.minimalAmount() + dispatch(SendAction.Dialog.ShowTezosWarningDialog(reduceCallback = { + dispatch(AmountAction.SetAmount(typedAmount.value!!.minus(reduceAmount), false)) + dispatch(AmountActionUi.CheckAmountToSend) + }, sendAllCallback = { + sendTransaction(action, walletManager, amountToSend, feeAmount, recipientAddress, dispatch) + }, reduceAmount)) + } + transactionErrors.isNotEmpty() -> { + dispatch(SendAction.SendError(createValidateTransactionError(transactionErrors, walletManager))) + } + else -> { + sendTransaction(action, walletManager, amountToSend, feeAmount, recipientAddress, dispatch) + } } +} +private fun sendTransaction( + action: SendActionUi.SendAmountToRecipient, + walletManager: WalletManager, + amountToSend: Amount, + feeAmount: Amount, + recipientAddress: String, + dispatch: (Action) -> Unit +) { dispatch(SendAction.ChangeSendButtonState(SendButtonState.PROGRESS)) val txData = walletManager.createTransaction(amountToSend, feeAmount, recipientAddress) scope.launch { @@ -89,7 +110,8 @@ private fun verifyAndSendTransaction( } } is Throwable -> { - val message = (result.error as Throwable).message + val throwable = result.error as Throwable + val message = throwable.message when { message == null -> { dispatch(SendAction.SendError(TapError.UnknownError)) @@ -98,8 +120,9 @@ private fun verifyAndSendTransaction( // user was cancelled the operation by closing the Sdk bottom sheet } else -> { - Timber.e(result.error) - dispatch(SendAction.SendError(TapError.BlockchainInternalError)) + Timber.e(throwable) + FirebaseCrashlytics.getInstance().recordException(throwable) + dispatch(SendAction.SendError(TapError.CustomError(message))) } } } @@ -109,7 +132,6 @@ private fun verifyAndSendTransaction( dispatch(SendAction.ChangeSendButtonState(SendButtonState.ENABLED)) } } - } fun extractErrorsForAmountField(errors: EnumSet): EnumSet { 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 d09cb9b695..e7454abcc1 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 @@ -41,6 +41,8 @@ private class SendReducer : SendInternalReducer { override fun handle(action: SendScreenAction, sendState: SendState): SendState { val result = when (action) { is SendAction.ChangeSendButtonState -> sendState.copy(sendButtonState = action.state) + is SendAction.Dialog.ShowTezosWarningDialog -> sendState.copy(dialog = action) + is SendAction.Dialog.Hide -> sendState.copy(dialog = null) else -> return sendState } 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 8dcb140ce5..68954619a6 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 @@ -8,6 +8,7 @@ import com.tangem.tap.common.CurrencyConverter import com.tangem.tap.common.entities.TapCurrency import com.tangem.tap.common.text.DecimalDigitsInputFilter import com.tangem.tap.domain.TapError +import com.tangem.tap.features.send.redux.SendAction import com.tangem.tap.store import org.rekotlin.StateType import java.math.BigDecimal @@ -35,7 +36,8 @@ data class SendState( val amountState: AmountState = AmountState(), val feeState: FeeState = FeeState(), val receiptState: ReceiptState = ReceiptState(), - val sendButtonState: SendButtonState = SendButtonState.DISABLED + val sendButtonState: SendButtonState = SendButtonState.DISABLED, + val dialog: SendAction.Dialog? = null ) : SendScreenState { override val stateId: StateId = StateId.SEND_SCREEN diff --git a/app/src/main/java/com/tangem/tap/features/send/ui/dialogs/TezosWarningDialog.kt b/app/src/main/java/com/tangem/tap/features/send/ui/dialogs/TezosWarningDialog.kt new file mode 100644 index 0000000000..45b092ea8c --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/send/ui/dialogs/TezosWarningDialog.kt @@ -0,0 +1,29 @@ +package com.tangem.tap.features.send.ui.dialogs + +import android.content.Context +import androidx.appcompat.app.AlertDialog +import com.tangem.tap.features.send.redux.SendAction +import com.tangem.tap.store +import com.tangem.wallet.R + +class TezosWarningDialog(context: Context) : AlertDialog(context) { + + companion object { + fun create(context: Context, showDialogData: SendAction.Dialog.ShowTezosWarningDialog): AlertDialog { + val reduceAmount = showDialogData.reduceAmount.toPlainString() + return Builder(context).apply { + setTitle(context.getString(R.string.common_warning)) + setMessage(context.getString(R.string.xtz_withdrawal_message_warning, reduceAmount)) + setNegativeButton(R.string.xtz_withdrawal_message_ignore) { _, _ -> + showDialogData.sendAllCallback() + } + setPositiveButton(context.getString(R.string.xtz_withdrawal_message_reduce, reduceAmount)) { _, _ -> + showDialogData.reduceCallback() + } + setOnDismissListener { + store.dispatch(SendAction.Dialog.Hide) + } + }.create() + } + } +} \ No newline at end of file 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 a88d5ca461..0e266fcc54 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 @@ -1,5 +1,6 @@ package com.tangem.tap.features.send.ui.stateSubscribers +import android.app.Dialog import android.content.Context import android.text.SpannableStringBuilder import android.view.ViewGroup @@ -16,10 +17,12 @@ import com.tangem.tap.domain.assembleErrors import com.tangem.tap.features.send.BaseStoreFragment import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.Error import com.tangem.tap.features.send.redux.FeeAction +import com.tangem.tap.features.send.redux.SendAction import com.tangem.tap.features.send.redux.reducers.ReceiptReducer import com.tangem.tap.features.send.redux.states.* import com.tangem.tap.features.send.ui.FeeUiHelper import com.tangem.tap.features.send.ui.SendFragment +import com.tangem.tap.features.send.ui.dialogs.TezosWarningDialog import com.tangem.tap.store import com.tangem.wallet.R import kotlinx.android.synthetic.main.btn_expand_collapse.* @@ -37,6 +40,8 @@ import kotlinx.android.synthetic.main.layout_send_receipt.* */ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber(fragment) { + private var dialog: Dialog? = null + override fun updateWithNewState(fg: BaseStoreFragment, state: SendState) { val lastChangedStates = state.lastChangedStates.toList() state.lastChangedStates.clear() @@ -54,6 +59,19 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber private fun handleSendScreen(fg: BaseStoreFragment, state: SendState) { val sendFragment = (fg as? SendFragment) ?: return + when (state.dialog) { + is SendAction.Dialog.ShowTezosWarningDialog -> { + if (dialog == null) { + dialog = TezosWarningDialog.create(fg.requireContext(), state.dialog) + dialog?.show() + } + } + else -> { + dialog?.dismiss() + dialog = null + } + } + when (state.sendButtonState) { SendButtonState.ENABLED -> { fg.btnSend.isEnabled = true @@ -235,10 +253,10 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber totalLayout.tvTotalValue.update("${roughOrEmpty(receipt.totalFiat)} ${receipt.symbols.fiat}") val willSent = getString( - R.string.send_total_subtitle_asset_format, - receipt.symbols.token ?: "", receipt.willSentToken, - receipt.symbols.crypto, receipt.willSentFeeCoin - ) + R.string.send_total_subtitle_asset_format, + receipt.symbols.token ?: "", receipt.willSentToken, + receipt.symbols.crypto, receipt.willSentFeeCoin + ) totalLayout.tvWillBeSentValue.update(willSent) } ReceiptLayoutType.TOKEN_CRYPTO -> { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/models/PendingTransaction.kt b/app/src/main/java/com/tangem/tap/features/wallet/models/PendingTransaction.kt index afa8bd8e17..6c56a9be65 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/models/PendingTransaction.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/models/PendingTransaction.kt @@ -11,15 +11,21 @@ data class PendingTransaction( val type: PendingTransactionType ) -enum class PendingTransactionType { Incoming, Outcoming } +enum class PendingTransactionType { Incoming, Outgoing, Unknown } fun TransactionData.toPendingTransaction(walletAddress: String): PendingTransaction? { if (this.status == TransactionStatus.Confirmed) return null - val type: PendingTransactionType = if (this.sourceAddress == walletAddress) { - PendingTransactionType.Outcoming - } else { - PendingTransactionType.Incoming + val type: PendingTransactionType = when { +// this.sourceAddress == walletAddress -> { +// PendingTransactionType.Outgoing +// } +// this.destinationAddress == walletAddress -> { +// PendingTransactionType.Incoming +// } + else -> { + PendingTransactionType.Unknown + } } val address = if (this.sourceAddress == walletAddress) { this.destinationAddress 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 3bbbda0d1c..1a573776e6 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 @@ -50,6 +50,8 @@ sealed class WalletAction : Action { object Failure : WalletAction() } + object DisablePayId: WalletAction() + data class LoadArtwork(val card: Card, val artworkId: String?) : WalletAction() { data class Success(val artwork: Artwork) : WalletAction() object Failure : WalletAction() diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletReducer.kt index 9e1930ca1e..b8f66e0aeb 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletReducer.kt @@ -176,6 +176,9 @@ private fun internalReduce(action: Action, state: AppState): WalletState { is WalletAction.LoadPayId.NotCreated -> newState = newState.copy( payIdData = PayIdData(PayIdState.NotCreated, null) ) + is WalletAction.DisablePayId -> newState = newState.copy( + payIdData = PayIdData(PayIdState.Disabled, null) + ) is WalletAction.CreatePayId, is WalletAction.CreatePayId.Failure -> newState = newState.copy( walletDialog = WalletDialog.CreatePayIdDialog(CreatingPayIdState.EnterPayId) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/PendingTransactionsAdapter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/PendingTransactionsAdapter.kt index 66b0a11d9c..f6290b5eb9 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/PendingTransactionsAdapter.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/PendingTransactionsAdapter.kt @@ -42,15 +42,18 @@ class PendingTransactionsAdapter fun bind(transaction: PendingTransaction) { val transactionDescriptionRes = when (transaction.type) { PendingTransactionType.Incoming -> R.string.wallet_pending_tx_receiving - PendingTransactionType.Outcoming -> R.string.wallet_pending_tx_sending + PendingTransactionType.Outgoing -> R.string.wallet_pending_tx_sending + PendingTransactionType.Unknown -> return } val transactionAddressRes = when (transaction.type) { PendingTransactionType.Incoming -> R.string.wallet_pending_tx_receiving_address_format - PendingTransactionType.Outcoming -> R.string.wallet_pending_tx_sending_address_format + PendingTransactionType.Outgoing -> R.string.wallet_pending_tx_sending_address_format + PendingTransactionType.Unknown -> return } val image = when (transaction.type) { PendingTransactionType.Incoming -> R.drawable.ic_arrow_left - PendingTransactionType.Outcoming -> R.drawable.ic_arrow_right_20 + PendingTransactionType.Outgoing -> R.drawable.ic_arrow_right_20 + PendingTransactionType.Unknown -> return } view.tv_pending_transaction.text = view.context.getString(transactionDescriptionRes) diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png index fcfe9eb999..f26b7cd005 100644 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png index 7beabf9cb2..ad4b07ff80 100644 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png and b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png index 9813f49bae..bb2457e1ff 100644 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png index b7261f96cb..d7b8e985cc 100644 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png index c5a309d2de..7fccb8a69b 100644 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png and b/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png index f1224045f5..2a7e2a1395 100644 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png index 680ac6dc76..4f205d64ab 100644 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png index 7f67a0a7ec..3c3b30ca7e 100644 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png index 409667b7aa..dc8fb9c530 100644 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index 6b1e6b7a5c..ffebc72291 100644 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png index 1b20e8280d..97a83eb92a 100644 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png index 7a69bf581f..9d876c01e3 100644 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 91e1896930..613405d26a 100644 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png index aa96fb42fe..fbe488e03a 100644 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png index 486e640d78..405be1cf56 100644 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8142ff23cc..9af2597610 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -9,6 +9,7 @@ Done Cancel Accept + %s Camera access denied You have not given access to your camera, please adjust your privacy settings diff --git a/app/src/main/res/values/strings_untranslated.xml b/app/src/main/res/values/strings_untranslated.xml new file mode 100644 index 0000000000..ee920115aa --- /dev/null +++ b/app/src/main/res/values/strings_untranslated.xml @@ -0,0 +1,7 @@ + + + To avoid paying an increased commission the next time you top up your wallet, reduce the amount by %s XTZ + Reduce by %s XTZ + No, send all + + diff --git a/blockchain-demo/.gitignore b/blockchain-demo/.gitignore deleted file mode 100644 index 796b96d1c4..0000000000 --- a/blockchain-demo/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/blockchain-demo/build.gradle b/blockchain-demo/build.gradle deleted file mode 100644 index 934f45b26c..0000000000 --- a/blockchain-demo/build.gradle +++ /dev/null @@ -1,64 +0,0 @@ -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' -apply plugin: 'kotlin-kapt' - -android { - compileSdkVersion 29 - buildToolsVersion "29.0.2" - - - defaultConfig { - applicationId "com.example.blockchain_demo" - minSdkVersion 21 - targetSdkVersion 29 - versionCode 1 - versionName "1.0" - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - kotlinOptions { - jvmTarget = '1.8' - } - - packagingOptions { - exclude 'lib/x86_64/darwin/libscrypt.dylib' - exclude 'lib/x86_64/freebsd/libscrypt.so' - exclude 'lib/x86_64/linux/libscrypt.so' - } - - viewBinding { - enabled = true - } -} - -dependencies { - implementation project(':blockchain') - - implementation 'com.tangem:core:0.10.4' - implementation 'com.tangem:sdk:0.10.4' - - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$versions.kotlin" - implementation 'androidx.appcompat:appcompat:1.1.0' - implementation 'androidx.core:core-ktx:1.2.0' - implementation 'androidx.constraintlayout:constraintlayout:1.1.3' - implementation 'com.google.android.material:material:1.1.0' - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3' - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.3.3" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3" - testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test.ext:junit:1.1.1' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' -} diff --git a/blockchain-demo/proguard-rules.pro b/blockchain-demo/proguard-rules.pro deleted file mode 100644 index f1b424510d..0000000000 --- a/blockchain-demo/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile diff --git a/blockchain-demo/src/androidTest/java/com/tangem/blockchain_demo/ExampleInstrumentedTest.kt b/blockchain-demo/src/androidTest/java/com/tangem/blockchain_demo/ExampleInstrumentedTest.kt deleted file mode 100644 index 2a03ebc11f..0000000000 --- a/blockchain-demo/src/androidTest/java/com/tangem/blockchain_demo/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.tangem.blockchain_demo - -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.platform.app.InstrumentationRegistry -import org.junit.Assert.assertEquals -import org.junit.Test -import org.junit.runner.RunWith - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("com.example.blockchain_demo", appContext.packageName) - } -} \ No newline at end of file diff --git a/blockchain-demo/src/main/AndroidManifest.xml b/blockchain-demo/src/main/AndroidManifest.xml deleted file mode 100644 index 9d092d68db..0000000000 --- a/blockchain-demo/src/main/AndroidManifest.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/blockchain-demo/src/main/java/com/tangem/blockchain_demo/BlockchainDemoActivity.kt b/blockchain-demo/src/main/java/com/tangem/blockchain_demo/BlockchainDemoActivity.kt deleted file mode 100644 index 038c0ea66c..0000000000 --- a/blockchain-demo/src/main/java/com/tangem/blockchain_demo/BlockchainDemoActivity.kt +++ /dev/null @@ -1,183 +0,0 @@ -package com.tangem.blockchain_demo - -import android.os.Bundle -import android.text.Editable -import android.widget.Toast -import androidx.appcompat.app.AppCompatActivity -import com.tangem.TangemSdk -import com.tangem.TangemSdkError -import com.tangem.blockchain.common.* -import com.tangem.blockchain.extensions.Result -import com.tangem.blockchain.extensions.Signer -import com.tangem.blockchain.extensions.SimpleResult -import com.tangem.blockchain_demo.databinding.ActivityBlockchainDemoBinding -import com.tangem.commands.Card -import com.tangem.common.CompletionResult -import com.tangem.tangem_sdk_new.extensions.init -import kotlinx.coroutines.* -import java.math.BigDecimal -import kotlin.coroutines.CoroutineContext - -class BlockchainDemoActivity : AppCompatActivity() { - - private lateinit var tangemSdk: TangemSdk - private lateinit var signer: TransactionSigner - private lateinit var card: Card - private lateinit var walletManager: WalletManager - private var issuerDataCounter: Int = 1 - - private lateinit var fee: BigDecimal - - private lateinit var binding: ActivityBlockchainDemoBinding - - private val parentJob = Job() - private val exceptionHandler = CoroutineExceptionHandler { _, throwable -> - handleError(throwable.localizedMessage) - } - private val coroutineContext: CoroutineContext - get() = parentJob + Dispatchers.IO + exceptionHandler - private val scope = CoroutineScope(coroutineContext) - - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - binding = ActivityBlockchainDemoBinding.inflate(layoutInflater) - val view = binding.root - setContentView(view) - - tangemSdk = TangemSdk.init(this) - signer = Signer(tangemSdk) - - binding.btnScan.setOnClickListener { scan() } - - binding.btnCheckFee.setOnClickListener { requestFee() } - - binding.btnSend.setOnClickListener { send() } - } - - - private fun scan() { - tangemSdk.scanCard { result -> - when (result) { - is CompletionResult.Success -> { - walletManager = WalletManagerFactory.makeWalletManager(result.data)!! - getInfo() - } - is CompletionResult.Failure -> { - if (result.error !is TangemSdkError.UserCancelled) { - handleError(result.error.toString()) - } - } - } - } - } - - private fun getInfo() { - scope.launch { - walletManager.update() - withContext(Dispatchers.Main) { - binding.tvBalance.text = - "${walletManager.wallet.amounts[AmountType.Coin]?.value?.toPlainString() - ?: "error"} ${walletManager.wallet.blockchain.currency}" - val token = walletManager.wallet.amounts[AmountType.Token] - if (token != null) { - binding.tvBalance.text = token.value?.toPlainString() + " " + token.currencySymbol - binding.etSumToSend.text = Editable.Factory.getInstance().newEditable( - token.value?.toPlainString() ?: "" - ) - } else { - binding.etSumToSend.text = - Editable.Factory.getInstance().newEditable( - walletManager.wallet.amounts[AmountType.Coin]?.value?.toPlainString() - ) - } - binding.btnCheckFee.isEnabled = true - } - } - } - - private fun requestFee() { - if (binding.etReceiverAddress.text.isBlank()) { - Toast.makeText(this, "Please enter receiver address", Toast.LENGTH_LONG).show() - return - } else if (binding.etSumToSend.text.isBlank()) { - Toast.makeText(this, "Choose sum to send", Toast.LENGTH_LONG).show() - return - } - - scope.launch { - val feeResult = (walletManager as TransactionSender).getFee( - walletManager.wallet.amounts[AmountType.Token] - ?: walletManager.wallet.amounts[AmountType.Coin]!!, - binding.etReceiverAddress.text.toString()) - withContext(Dispatchers.Main) { - when (feeResult) { - is Result.Failure -> { - handleError(feeResult.error?.localizedMessage ?: "Error") - } - is Result.Success -> { - binding.btnSend.isEnabled = true - val fees = feeResult.data - if (fees.size == 1) { - binding.tvFee.text = fees[0].value.toString() - fee = fees[0].value ?: BigDecimal(0) - } else { - binding.tvFee.text = fees[0].value.toString() + "\n" + - fees[1].value.toString() + "\n" + - fees[2].value.toString() - fee = fees[1].value ?: BigDecimal(0) - - } - } - } - } - } - } - - private fun send() { - scope.launch { - val result = (walletManager as TransactionSender).send( - formTransactionData(), - signer) - withContext(Dispatchers.Main) { - when (result) { - is SimpleResult.Failure -> { - handleError(result.error?.localizedMessage ?: "Error") - } - is SimpleResult.Success -> { - binding.tvFee.text = "Success" - } - } - } - } - } - - private fun formTransactionData(): TransactionData { - val amount = if (walletManager.wallet.amounts[AmountType.Token] != null) { - walletManager.wallet.amounts[AmountType.Token]!!.copy( - value = binding.etSumToSend.text.toString().toBigDecimal() - ) - } else { - walletManager.wallet.amounts[AmountType.Coin]!!.copy( - value = binding.etSumToSend.text.toString().toBigDecimal() - fee - ) - } - return TransactionData( - amount, - walletManager.wallet.amounts[AmountType.Coin]!!.copy(value = fee), - walletManager.wallet.amounts[AmountType.Coin]!!.address!!, - binding.etReceiverAddress.text.toString(), - contractAddress = walletManager.wallet.amounts[AmountType.Token]?.address - ) - } - - private fun handleError(error: String?) { - Toast.makeText(this, error, Toast.LENGTH_LONG).show() - } - - override fun onDestroy() { - super.onDestroy() - scope.cancel() - } -} \ No newline at end of file diff --git a/blockchain-demo/src/main/res/drawable-v24/ic_launcher_foreground.xml b/blockchain-demo/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index 1f6bb29060..0000000000 --- a/blockchain-demo/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/blockchain-demo/src/main/res/drawable/ic_launcher_background.xml b/blockchain-demo/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 0d025f9bf6..0000000000 --- a/blockchain-demo/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/blockchain-demo/src/main/res/layout/activity_blockchain_demo.xml b/blockchain-demo/src/main/res/layout/activity_blockchain_demo.xml deleted file mode 100644 index faa8ad1d9e..0000000000 --- a/blockchain-demo/src/main/res/layout/activity_blockchain_demo.xml +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - - - - - - - -