diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/express/TangemExpressApi.kt b/core/datasource/src/main/java/com/tangem/datasource/api/express/TangemExpressApi.kt index 3a4c3d9e84..d4e2600da3 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/express/TangemExpressApi.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/express/TangemExpressApi.kt @@ -67,6 +67,7 @@ interface TangemExpressApi { @Query("refundAddress") refundAddress: String?, // for cex only @Query("refundExtraId") refundExtraId: String?, // for cex only @Query("partnerOperationType") partnerOperationType: String?, // swap/ swap-and-send + @Query("toExtraId") toExtraId: String?, // swap-and-send memo ): ApiResponse @GET("exchange-status") diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeProvider.kt b/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeProvider.kt index 4712dadadc..a8ed2fd5dc 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeProvider.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/express/models/response/ExchangeProvider.kt @@ -35,6 +35,9 @@ data class ExchangeProvider( @Json(name = "exchangeOnlyWithinSingleAddress") val isExchangeOnlyWithinSingleAddress: Boolean = false, + + @Json(name = "isExtraIdSupported") + val isExtraIdSupported: Boolean = false, ) @JsonClass(generateAdapter = false) diff --git a/data/express/src/main/java/com/tangem/data/express/converter/ExpressProviderConverter.kt b/data/express/src/main/java/com/tangem/data/express/converter/ExpressProviderConverter.kt index 09a2f55b15..94d78677bb 100644 --- a/data/express/src/main/java/com/tangem/data/express/converter/ExpressProviderConverter.kt +++ b/data/express/src/main/java/com/tangem/data/express/converter/ExpressProviderConverter.kt @@ -20,6 +20,7 @@ internal class ExpressProviderConverter : Converter // Search available to swap currency cryptoCurrencyList.any { currencyStatus -> - // Allowed only on networks without tx extras (e.i. memo and destination tag) - val isExtrasSupported = currencyStatus.network.transactionExtrasType.isTxExtrasSupported() - currencyStatus.id == pair.to.currency.id && !isExtrasSupported + currencyStatus.id == pair.to.currency.id } } - .map { pair -> SwapCryptoCurrency(groupingCurrency(pair), pair.providers) } + .map { pair -> + val toCurrency = groupingCurrency(pair) + val isTxExtrasSupported = toCurrency.currency.network.transactionExtrasType.isTxExtrasSupported() + val filteredProviders = if (isTxExtrasSupported) { + pair.providers.filter { it.isExtraIdSupported } + } else { + pair.providers + } + SwapCryptoCurrency(toCurrency, filteredProviders) + } + .filter { it.providers.isNotEmpty() } .toList() val unavailableCryptoCurrencies = diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/common/ConfirmData.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/common/ConfirmData.kt index 5ce32201dc..b825e3f9e7 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/common/ConfirmData.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/common/ConfirmData.kt @@ -13,6 +13,7 @@ internal data class ConfirmData( val reduceAmountBy: BigDecimal, val isIgnoreReduce: Boolean, val enteredDestination: String?, + val enteredMemo: String?, val fee: Fee?, val feeError: GetFeeError?, val fromCryptoCurrencyStatus: CryptoCurrencyStatus?, diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/model/SendWithSwapConfirmModel.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/model/SendWithSwapConfirmModel.kt index 50666b4e1b..4c22e6b47c 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/model/SendWithSwapConfirmModel.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/model/SendWithSwapConfirmModel.kt @@ -142,6 +142,7 @@ internal class SendWithSwapConfirmModel @Inject constructor( reduceAmountBy = amountState?.reduceAmountBy.takeIf { isQuoteContent }.orZero(), isIgnoreReduce = amountState?.isIgnoreReduce == true, enteredDestination = destinationUM?.addressTextField?.actualAddress, + enteredMemo = destinationUM?.memoTextField?.value, fee = feeSelectorUM?.selectedFeeItem?.fee.takeIf { isQuoteContent }, feeError = (uiState.value.feeSelectorUM as? FeeSelectorUM.Error)?.error.takeIf { isQuoteContent }, fromCryptoCurrencyStatus = amountUM?.swapDirection?.withSwapDirection( diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/model/SwapTransactionSender.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/model/SwapTransactionSender.kt index 50a94cdb36..7a166639ff 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/model/SwapTransactionSender.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/model/SwapTransactionSender.kt @@ -104,6 +104,7 @@ internal class SwapTransactionSender @AssistedInject constructor( fromAmount = fromAmount.toStringWithRightOffset(fromStatus.currency.decimals), toCryptoCurrency = toStatus.currency, toAddress = destination, + toExtraId = confirmData.enteredMemo, expressProvider = provider, rateType = rateType, expressOperationType = expressOperationType, diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/success/ui/SendWithSwapSuccessContent.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/success/ui/SendWithSwapSuccessContent.kt index 44ca767ac2..5657f00361 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/success/ui/SendWithSwapSuccessContent.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/success/ui/SendWithSwapSuccessContent.kt @@ -125,7 +125,10 @@ private fun SuccessContent(sendWithSwapUM: SendWithSwapUM, modifier: Modifier = .clip(TangemTheme.shapes.roundedCornersXMedium) .background(TangemTheme.colors.background.action), ) - DestinationBlock(destinationUM.addressTextField) + DestinationBlock( + address = destinationUM.addressTextField, + memo = destinationUM.memoTextField, + ) FeeBlock(feeSelectorUM = feeSelectorUM) Spacer(Modifier.height(16.dp)) } @@ -247,7 +250,11 @@ private fun FeeBlock(feeSelectorUM: FeeSelectorUM.Content) { } @Composable -private fun DestinationBlock(address: DestinationTextFieldUM.RecipientAddress, modifier: Modifier = Modifier) { +private fun DestinationBlock( + address: DestinationTextFieldUM.RecipientAddress, + memo: DestinationTextFieldUM.RecipientMemo?, + modifier: Modifier = Modifier, +) { Column( modifier = modifier .fillMaxWidth() @@ -279,6 +286,14 @@ private fun DestinationBlock(address: DestinationTextFieldUM.RecipientAddress, m .background(TangemTheme.colors.background.tertiary), ) } + if (memo != null && memo.value.isNotBlank()) { + Text( + text = stringResourceSafe(R.string.send_memo, memo.value), + style = TangemTheme.typography.caption2, + color = TangemTheme.colors.text.tertiary, + modifier = Modifier.padding(top = TangemTheme.dimens.spacing8), + ) + } } } @@ -304,7 +319,17 @@ private fun SendWithSwapSuccessContent_Preview() { isValuePasted = false, blockchainAddress = "0x391316d97a07027a0702c8A002c8A0C25d8470", ), - memoTextField = null, + memoTextField = DestinationTextFieldUM.RecipientMemo( + value = "123123123", + keyboardOptions = KeyboardOptions(), + placeholder = TextReference.EMPTY, + label = resourceReference(R.string.send_recipient), + isError = false, + error = null, + isValuePasted = false, + isEnabled = true, + disabledText = TextReference.EMPTY, + ), recent = persistentListOf(), wallets = persistentListOf(), networkName = "Polygon", diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt index e6be947657..d207e7992b 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt @@ -286,6 +286,7 @@ internal class DefaultSwapRepository( expressOperationType: ExpressOperationType, refundAddress: String?, // for cex only refundExtraId: String?, // for cex only + toExtraId: String?, // for networks with memo only ): Either { return withContext(coroutineDispatcher.io) { try { @@ -311,6 +312,7 @@ internal class DefaultSwapRepository( userWallet = userWallet, appPreferencesStore = appPreferencesStore, ), + toExtraId = toExtraId, ).getOrThrow() if (dataSignatureVerifier.verifySignature(response.signature, response.txDetailsJson)) { val txDetails = parseTxDetails(response.txDetailsJson) diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/SwapPairInfoConverter.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/SwapPairInfoConverter.kt index a64fc2cf07..1080578a05 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/converters/SwapPairInfoConverter.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/converters/SwapPairInfoConverter.kt @@ -48,6 +48,7 @@ class SwapPairInfoConverter : Converter // TODO: Add target error handling, remove either ([REDACTED_JIRA]) diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/domain/SwapPairLeast.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/domain/SwapPairLeast.kt index bf97fe58d9..f65dd60a98 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/domain/SwapPairLeast.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/domain/SwapPairLeast.kt @@ -53,6 +53,8 @@ data class SwapProvider( val isRecommended: Boolean = false, @Json(name = "slippage") val slippage: BigDecimal?, + @Json(name = "isExtraIdSupported") + val isExtraIdSupported: Boolean = false, ) @JsonClass(generateAdapter = false)