mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-26 06:08:40 +01:00
feat: Add memo support for swap (#3229)
* feat: Add memo support for swap * fix: Error on swap page select receiver bottomsheet when picking receiveing currency that's not a wallet type * feat: exclude providers that do not support memo when receive currency needs it, also show passed memo in confirmation and trade history sheets * fix: overflow for destination tag on swap confirmation * Update lib/view_model/exchange/exchange_view_model.dart [skip ci] * Update lib/exchange/provider/trocador_exchange_provider.dart [skip ci] --------- Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
co-authored by
Omar Hatem
parent
d10f2f2a60
commit
1d652c76aa
@@ -51,6 +51,9 @@ class ChainflipExchangeProvider extends ExchangeProvider {
|
||||
@override
|
||||
bool get supportsFixedRate => false;
|
||||
|
||||
@override
|
||||
bool get supportsMemoOrDestinationTag => false;
|
||||
|
||||
@override
|
||||
ExchangeProviderDescription get description =>
|
||||
ExchangeProviderDescription.chainflip;
|
||||
|
||||
@@ -189,6 +189,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
|
||||
if (!isFixedRateMode) 'fromAmount': request.fromAmount,
|
||||
if (isFixedRateMode) 'toAmount': request.toAmount,
|
||||
'address': request.toAddress,
|
||||
if (request.toAddressExtraId.isNotEmpty) 'extraId': request.toAddressExtraId,
|
||||
'flow': _getFlow(isFixedRateMode),
|
||||
'type': type,
|
||||
'refundAddress': request.refundAddress,
|
||||
@@ -248,6 +249,7 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
|
||||
state: TradeState.created,
|
||||
payoutAddress: payoutAddress,
|
||||
isSendAll: isSendAll,
|
||||
toAddressExtraId: request.toAddressExtraId,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ abstract class ExchangeProvider {
|
||||
|
||||
bool get supportsOnionAddress => false;
|
||||
|
||||
bool get supportsMemoOrDestinationTag => true;
|
||||
|
||||
@override
|
||||
String toString() => title;
|
||||
|
||||
|
||||
@@ -198,6 +198,8 @@ class ExolixExchangeProvider extends ExchangeProvider {
|
||||
'networkFrom': _networkFor(request.fromCurrency),
|
||||
'networkTo': _networkFor(request.toCurrency),
|
||||
'withdrawalAddress': await _normalizeAddress(request.toAddress),
|
||||
if (request.toAddressExtraId.isNotEmpty)
|
||||
'withdrawalExtraId': request.toAddressExtraId,
|
||||
'refundAddress': await _normalizeAddress(request.refundAddress),
|
||||
'rateType': _getRateType(isFixedRateMode),
|
||||
'apiToken': apiKey,
|
||||
@@ -315,6 +317,7 @@ class ExolixExchangeProvider extends ExchangeProvider {
|
||||
state: TradeState.created,
|
||||
payoutAddress: payoutAddress,
|
||||
isSendAll: isSendAll,
|
||||
toAddressExtraId: request.toAddressExtraId,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,9 @@ class JupiterExchangeProvider extends ExchangeProvider {
|
||||
@override
|
||||
bool get supportsFixedRate => false; // Jupiter doesn't support fixed rate
|
||||
|
||||
@override
|
||||
bool get supportsMemoOrDestinationTag => false;
|
||||
|
||||
@override
|
||||
ExchangeProviderDescription get description => ExchangeProviderDescription.jupiter;
|
||||
|
||||
|
||||
@@ -174,7 +174,7 @@ class LetsExchangeExchangeProvider extends ExchangeProvider {
|
||||
if (!isFixedRateMode) 'deposit_amount': request.fromAmount.toString(),
|
||||
'withdrawal': withdrawalAddress,
|
||||
if (isFixedRateMode) 'withdrawal_amount': request.toAmount.toString(),
|
||||
'withdrawal_extra_id': '',
|
||||
'withdrawal_extra_id': request.toAddressExtraId,
|
||||
'return': returnAddress,
|
||||
'rate_id': rateId,
|
||||
if (networkFrom != null) 'network_from': networkFrom,
|
||||
@@ -302,6 +302,7 @@ class LetsExchangeExchangeProvider extends ExchangeProvider {
|
||||
expiredAt: expiredAt,
|
||||
extraId: extraId,
|
||||
isSendAll: isSendAll,
|
||||
toAddressExtraId: request.toAddressExtraId,
|
||||
);
|
||||
} catch (e, s) {
|
||||
ExchangeProviderLogger.logError(
|
||||
|
||||
@@ -88,6 +88,9 @@ class NearIntentsExchangeProvider extends ExchangeProvider {
|
||||
@override
|
||||
bool get supportsFixedRate => true;
|
||||
|
||||
@override
|
||||
bool get supportsMemoOrDestinationTag => false;
|
||||
|
||||
@override
|
||||
ExchangeProviderDescription get description =>
|
||||
ExchangeProviderDescription.nearIntents;
|
||||
|
||||
@@ -216,6 +216,7 @@ class SideShiftExchangeProvider extends ExchangeProvider {
|
||||
final body = {
|
||||
'affiliateId': affiliateId,
|
||||
'settleAddress': request.toAddress,
|
||||
if (request.toAddressExtraId.isNotEmpty) 'settleMemo': request.toAddressExtraId,
|
||||
'refundAddress': request.refundAddress,
|
||||
};
|
||||
|
||||
@@ -336,6 +337,7 @@ class SideShiftExchangeProvider extends ExchangeProvider {
|
||||
createdAt: DateTime.now(),
|
||||
isSendAll: isSendAll,
|
||||
extraId: depositMemo,
|
||||
toAddressExtraId: request.toAddressExtraId,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -180,7 +180,8 @@ class SimpleSwapExchangeProvider extends ExchangeProvider {
|
||||
"amount": request.fromAmount,
|
||||
"fixed": isFixedRateMode,
|
||||
"user_refund_address": _normalizeAddress(request.refundAddress),
|
||||
"address_to": _normalizeAddress(request.toAddress)
|
||||
"address_to": _normalizeAddress(request.toAddress),
|
||||
if (request.toAddressExtraId.isNotEmpty) "extra_id_to": request.toAddressExtraId,
|
||||
};
|
||||
final uri = Uri.https(apiAuthority, createExchangePath, params);
|
||||
|
||||
@@ -289,6 +290,7 @@ class SimpleSwapExchangeProvider extends ExchangeProvider {
|
||||
payoutAddress: payoutAddress,
|
||||
createdAt: DateTime.now(),
|
||||
isSendAll: isSendAll,
|
||||
toAddressExtraId: request.toAddressExtraId,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -186,6 +186,7 @@ class StealthExExchangeProvider extends ExchangeProvider {
|
||||
'amount':
|
||||
isFixedRateMode ? double.parse(request.toAmount) : double.parse(request.fromAmount),
|
||||
'address': _normalizeAddress(request.toAddress),
|
||||
if (request.toAddressExtraId.isNotEmpty) 'extra_id': request.toAddressExtraId,
|
||||
'refund_address': _normalizeAddress(request.refundAddress),
|
||||
'additional_fee_percent': _additionalFeePercent,
|
||||
};
|
||||
@@ -299,6 +300,7 @@ class StealthExExchangeProvider extends ExchangeProvider {
|
||||
expiredAt: expiredAt,
|
||||
extraId: extraId,
|
||||
isSendAll: isSendAll,
|
||||
toAddressExtraId: request.toAddressExtraId,
|
||||
);
|
||||
} catch (e, s) {
|
||||
ExchangeProviderLogger.logError(
|
||||
|
||||
@@ -54,6 +54,9 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
|
||||
@override
|
||||
bool get supportsFixedRate => false;
|
||||
|
||||
@override
|
||||
bool get supportsMemoOrDestinationTag => false;
|
||||
|
||||
@override
|
||||
ExchangeProviderDescription get description =>
|
||||
ExchangeProviderDescription.swapsXyz;
|
||||
|
||||
@@ -37,6 +37,9 @@ class SwapTradeExchangeProvider extends ExchangeProvider {
|
||||
@override
|
||||
bool get supportsFixedRate => false;
|
||||
|
||||
@override
|
||||
bool get supportsMemoOrDestinationTag => false;
|
||||
|
||||
@override
|
||||
ExchangeProviderDescription get description => ExchangeProviderDescription.swapTrade;
|
||||
|
||||
|
||||
@@ -36,6 +36,9 @@ class ThorChainExchangeProvider extends ExchangeProvider {
|
||||
@override
|
||||
bool get supportsFixedRate => false;
|
||||
|
||||
@override
|
||||
bool get supportsMemoOrDestinationTag => false;
|
||||
|
||||
@override
|
||||
ExchangeProviderDescription get description => ExchangeProviderDescription.thorChain;
|
||||
|
||||
|
||||
@@ -235,6 +235,7 @@ class TrocadorExchangeProvider extends ExchangeProvider {
|
||||
if (!isFixedRateMode) 'amount_from': request.fromAmount,
|
||||
if (isFixedRateMode) 'amount_to': request.toAmount,
|
||||
'address': request.toAddress,
|
||||
if (request.toAddressExtraId.isNotEmpty) 'address_memo': request.toAddressExtraId,
|
||||
'refund': request.refundAddress,
|
||||
'refund_memo': '0',
|
||||
};
|
||||
@@ -392,6 +393,7 @@ class TrocadorExchangeProvider extends ExchangeProvider {
|
||||
payoutAddress: payoutAddress,
|
||||
isSendAll: isSendAll,
|
||||
extraId: addressProviderMemo,
|
||||
toAddressExtraId: request.toAddressExtraId,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -321,6 +321,7 @@ class XOSwapExchangeProvider extends ExchangeProvider {
|
||||
'fromAddress': request.refundAddress,
|
||||
'toAmount': request.toAmount,
|
||||
'toAddress': request.toAddress,
|
||||
if (request.toAddressExtraId.isNotEmpty) 'toAddressTag': request.toAddressExtraId,
|
||||
'pairId': pairId,
|
||||
};
|
||||
|
||||
@@ -424,6 +425,7 @@ class XOSwapExchangeProvider extends ExchangeProvider {
|
||||
payoutAddress: payoutAddress,
|
||||
extraId: extraId,
|
||||
isSendAll: isSendAll,
|
||||
toAddressExtraId: request.toAddressExtraId,
|
||||
);
|
||||
} catch (e, s) {
|
||||
ExchangeProviderLogger.logError(
|
||||
|
||||
@@ -27,6 +27,7 @@ class Trade {
|
||||
this.refundAddress,
|
||||
this.walletId,
|
||||
this.payoutAddress,
|
||||
this.toAddressExtraId,
|
||||
this.password,
|
||||
this.providerId,
|
||||
this.providerName,
|
||||
@@ -86,6 +87,9 @@ class Trade {
|
||||
String? refundAddress;
|
||||
String? walletId;
|
||||
String? payoutAddress;
|
||||
|
||||
// holds the receive address memo or destination tag that was passed for this trade
|
||||
String? toAddressExtraId;
|
||||
String? password;
|
||||
String? providerId;
|
||||
String? providerName;
|
||||
@@ -221,6 +225,7 @@ class Trade {
|
||||
'refundAddress': refundAddress,
|
||||
'walletId': walletId,
|
||||
'payoutAddress': payoutAddress,
|
||||
'toAddressExtraId': toAddressExtraId,
|
||||
'password': password,
|
||||
'providerId': providerId,
|
||||
'providerName': providerName,
|
||||
@@ -264,6 +269,7 @@ class Trade {
|
||||
refundAddress: row['refundAddress'] as String?,
|
||||
walletId: row['walletId'] as String?,
|
||||
payoutAddress: row['payoutAddress'] as String?,
|
||||
toAddressExtraId: row['toAddressExtraId'] as String?,
|
||||
password: row['password'] as String?,
|
||||
providerId: row['providerId'] as String?,
|
||||
providerName: row['providerName'] as String?,
|
||||
|
||||
@@ -8,6 +8,7 @@ class TradeRequest {
|
||||
required this.refundAddress,
|
||||
required this.fromAmount,
|
||||
this.toAmount = '',
|
||||
this.toAddressExtraId = '',
|
||||
this.isFixedRate = false});
|
||||
|
||||
final CryptoCurrency fromCurrency;
|
||||
@@ -16,5 +17,6 @@ class TradeRequest {
|
||||
final String refundAddress;
|
||||
final String fromAmount;
|
||||
final String toAmount;
|
||||
final String toAddressExtraId;
|
||||
final bool isFixedRate;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import 'package:cake_wallet/new-ui/widgets/keyboard_hide_overlay.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/modern_button.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/send_page/fiat_amount_bar.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/send_page/send_memo_input.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/send_page/send_syncing_indicator.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/swap_page/provider_selector_page.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/swap_page/refund_address_modal.dart';
|
||||
@@ -37,6 +38,7 @@ import 'package:cake_wallet/view_model/exchange/exchange_trade_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/exchange/exchange_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_switcher_view_model.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_core/currencies_with_memo.dart';
|
||||
import 'package:cw_core/currency.dart';
|
||||
import 'package:cw_core/sync_status.dart';
|
||||
import 'package:cw_core/utils/print_verbose.dart';
|
||||
@@ -837,12 +839,43 @@ class SwapAmountBoxState extends State<SwapAmountBox> {
|
||||
final amountController = TextEditingController();
|
||||
final fiatAmountController = TextEditingController();
|
||||
final amountFocusNode = FocusNode();
|
||||
final memoController = TextEditingController();
|
||||
ReactionDisposer? _memoReactionDisposer;
|
||||
VoidCallback? _memoListener;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_selectedCurrency = widget.initialCurrency;
|
||||
|
||||
super.initState();
|
||||
|
||||
if (widget.isReceiverCard) {
|
||||
memoController.text = widget.exchangeViewModel.receiveAddressExtraId;
|
||||
|
||||
_memoListener = () {
|
||||
if (widget.exchangeViewModel.receiveAddressExtraId != memoController.text) {
|
||||
widget.exchangeViewModel.receiveAddressExtraId = memoController.text;
|
||||
}
|
||||
};
|
||||
memoController.addListener(_memoListener!);
|
||||
|
||||
_memoReactionDisposer =
|
||||
reaction((_) => widget.exchangeViewModel.receiveAddressExtraId, (String value) {
|
||||
if (memoController.text != value) {
|
||||
memoController.text = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
if (_memoListener != null) {
|
||||
memoController.removeListener(_memoListener!);
|
||||
}
|
||||
_memoReactionDisposer?.call();
|
||||
memoController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
late Currency _selectedCurrency;
|
||||
@@ -1128,7 +1161,29 @@ class SwapAmountBoxState extends State<SwapAmountBox> {
|
||||
],
|
||||
);
|
||||
},
|
||||
)
|
||||
),
|
||||
if (widget.isReceiverCard)
|
||||
Observer(builder: (_) {
|
||||
final selected = widget.exchangeViewModel.receiveCurrency;
|
||||
final labelType = memoLabelTypeFor(selected);
|
||||
if (labelType == null) return const SizedBox.shrink();
|
||||
|
||||
final isDestinationTag = labelType == MemoLabelType.destinationTag;
|
||||
final hint = isDestinationTag
|
||||
? S.of(context).destination_tag_optional
|
||||
: S.of(context).memo_optional;
|
||||
final disclaimer = isDestinationTag
|
||||
? S.of(context).destination_tag_swap_disclaimer
|
||||
: S.of(context).memo_swap_disclaimer;
|
||||
|
||||
return NewSendMemoInput(
|
||||
memoController: memoController,
|
||||
maxMemoLength: isDestinationTag ? 20 : 256,
|
||||
memoLength: memoController.text.length,
|
||||
hintText: hint,
|
||||
disclaimerText: disclaimer,
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -8,11 +8,15 @@ class NewSendMemoInput extends StatelessWidget {
|
||||
{super.key,
|
||||
required this.memoController,
|
||||
required this.maxMemoLength,
|
||||
required this.memoLength});
|
||||
required this.memoLength,
|
||||
this.hintText,
|
||||
this.disclaimerText});
|
||||
|
||||
final TextEditingController memoController;
|
||||
final int maxMemoLength;
|
||||
final int memoLength;
|
||||
final String? hintText;
|
||||
final String? disclaimerText;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -30,8 +34,8 @@ class NewSendMemoInput extends StatelessWidget {
|
||||
child: TextField(
|
||||
maxLength: maxMemoLength,
|
||||
controller: memoController,
|
||||
decoration:
|
||||
InputDecoration(hintText: S.of(context).memo_optional, counterText: ""),
|
||||
decoration: InputDecoration(
|
||||
hintText: hintText ?? S.of(context).memo_optional, counterText: ""),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
@@ -52,9 +56,12 @@ class NewSendMemoInput extends StatelessWidget {
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(S.of(context).memo_disclaimer,
|
||||
style: TextStyle(
|
||||
fontSize: 12, color: Theme.of(context).colorScheme.onSurfaceVariant)),
|
||||
Expanded(
|
||||
child: Text(disclaimerText ?? S.of(context).memo_disclaimer,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant)),
|
||||
),
|
||||
Text("${memoController.text.length} / ${maxMemoLength}",
|
||||
style: TextStyle(fontSize: 12, color: Theme.of(context).colorScheme.primary))
|
||||
],
|
||||
|
||||
@@ -14,6 +14,7 @@ import 'package:cake_wallet/src/widgets/new_list_row/new_list_section.dart';
|
||||
import 'package:cake_wallet/view_model/exchange/exchange_trade_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/exchange/exchange_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/send/send_view_model_state.dart';
|
||||
import 'package:cw_core/currencies_with_memo.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
@@ -191,7 +192,19 @@ class SwapTransactionDetails extends StatelessWidget {
|
||||
showArrow: false,
|
||||
trailingText: exchangeViewModel.receiveAddressDisplayName ??
|
||||
middleTruncate(
|
||||
exchangeTradeViewModel.trade.payoutAddress ?? "", 8, 8))
|
||||
exchangeTradeViewModel.trade.payoutAddress ?? "", 8, 8)),
|
||||
if ((exchangeTradeViewModel.trade.toAddressExtraId ?? '').isNotEmpty)
|
||||
ListItemRegularRow(
|
||||
keyValue: "receive memo",
|
||||
showArrow: false,
|
||||
label: memoLabelTypeFor(exchangeViewModel.receiveCurrency) ==
|
||||
MemoLabelType.destinationTag
|
||||
? S.of(context).destination_tag
|
||||
: S.of(context).memo,
|
||||
trailingText: middleTruncate(
|
||||
exchangeTradeViewModel.trade.toAddressExtraId ?? "", 8, 8),
|
||||
copyableText: exchangeTradeViewModel.trade.toAddressExtraId,
|
||||
),
|
||||
],
|
||||
"${S.of(context).swap_id} (${S.of(context).tap_to_copy})": [
|
||||
ListItemRegularRow(
|
||||
|
||||
@@ -57,6 +57,7 @@ import 'package:cake_wallet/view_model/send/fees_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_list_view_model.dart';
|
||||
import 'package:cw_core/crypto_amount_format.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_core/currencies_with_memo.dart';
|
||||
import 'package:cw_core/erc20_token.dart';
|
||||
import 'package:cw_core/spl_token.dart';
|
||||
import 'package:cw_core/sync_status.dart';
|
||||
@@ -124,12 +125,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
_useTorOnly = _settingsStore.exchangeStatus == ExchangeApiMode.torOnly;
|
||||
_setProviders();
|
||||
const excludeDepositCurrencies = [CryptoCurrency.btt];
|
||||
const excludeReceiveCurrencies = [
|
||||
CryptoCurrency.xlm,
|
||||
CryptoCurrency.xrp,
|
||||
CryptoCurrency.bnb,
|
||||
CryptoCurrency.btt
|
||||
];
|
||||
const excludeReceiveCurrencies = [CryptoCurrency.btt];
|
||||
_initialPairBasedOnWallet();
|
||||
|
||||
unspentCoinsListViewModel.initialSetup().then((_) {
|
||||
@@ -391,6 +387,9 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
@observable
|
||||
String receiveAddress;
|
||||
|
||||
@observable
|
||||
String receiveAddressExtraId = '';
|
||||
|
||||
@observable
|
||||
String? receiveAddressDisplayName;
|
||||
|
||||
@@ -436,13 +435,18 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
|
||||
@computed
|
||||
Future<List<WalletInfo>> get receiveWallets async {
|
||||
WalletType? type;
|
||||
type = cryptoCurrencyOrTokenToWalletType(receiveCurrency);
|
||||
if (type == null) {
|
||||
type = cryptoCurrencyOrTokenToWalletType(CryptoCurrency.fromString(receiveCurrency.tag ?? ""));
|
||||
}
|
||||
try {
|
||||
WalletType? type;
|
||||
type = cryptoCurrencyOrTokenToWalletType(receiveCurrency);
|
||||
if (type == null) {
|
||||
type =
|
||||
cryptoCurrencyOrTokenToWalletType(CryptoCurrency.fromString(receiveCurrency.tag ?? ""));
|
||||
}
|
||||
|
||||
return await WalletInfo.selectList("type = ?", [type!.index]);
|
||||
return await WalletInfo.selectList("type = ?", [type!.index]);
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<WalletInfoAddressInfo>> addressesForAccountsWallet(WalletInfo wallet) async {
|
||||
@@ -761,6 +765,9 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
currency == receiveCurrency)) {
|
||||
receiveAddress = "";
|
||||
}
|
||||
if (currency != receiveCurrency) {
|
||||
receiveAddressExtraId = "";
|
||||
}
|
||||
|
||||
receiveCurrency = currency;
|
||||
isFixedRateMode = false;
|
||||
@@ -884,6 +891,9 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
(provider.description == ExchangeProviderDescription.swapsXyz ||
|
||||
provider.description == ExchangeProviderDescription.nearIntents);
|
||||
|
||||
bool _excludeProviderForReceiveExtraId(ExchangeProvider provider) =>
|
||||
memoLabelTypeFor(receiveCurrency) != null && !provider.supportsMemoOrDestinationTag;
|
||||
|
||||
Future<void> calculateBestRate() async {
|
||||
if (depositCurrency == receiveCurrency) {
|
||||
bestRate = 0.0;
|
||||
@@ -895,6 +905,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
|
||||
final validProvidersForAmount = _tradeAvailableProviders.where((provider) {
|
||||
if (_excludeProviderForSwapAll(provider)) return false;
|
||||
if (_excludeProviderForReceiveExtraId(provider)) return false;
|
||||
|
||||
final limits = _providerLimits[provider];
|
||||
|
||||
@@ -972,6 +983,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
try {
|
||||
final futures = selectedProviders
|
||||
.where((provider) => providerList.contains(provider))
|
||||
.where((provider) => !_excludeProviderForReceiveExtraId(provider))
|
||||
.map((provider) async {
|
||||
final limits = await provider
|
||||
.fetchLimits(
|
||||
@@ -1050,6 +1062,13 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
}
|
||||
}
|
||||
|
||||
if (forcedProvider != null && _excludeProviderForReceiveExtraId(forcedProvider!)) {
|
||||
tradeState = TradeIsCreatedFailure(
|
||||
title: S.current.trade_not_created,
|
||||
error: S.current.none_of_selected_providers_can_exchange);
|
||||
return;
|
||||
}
|
||||
|
||||
Map<double, ExchangeProvider> providers;
|
||||
if (forcedProvider != null) {
|
||||
providers = {forcedProviderRate: forcedProvider!};
|
||||
@@ -1138,6 +1157,10 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
if (isFixedRateMode && provider.supportsFixedRate == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_excludeProviderForReceiveExtraId(provider)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip Swaps.xyz when sending from external
|
||||
if (isSendFromExternal &&
|
||||
@@ -1160,6 +1183,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
toAmount: _receiveAmount.replaceAll(',', '.'),
|
||||
refundAddress: depositAddress,
|
||||
toAddress: receiveAddress,
|
||||
toAddressExtraId: receiveAddressExtraId.trim(),
|
||||
isFixedRate: isFixedRateMode,
|
||||
);
|
||||
|
||||
@@ -1260,6 +1284,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
depositCurrency == wallet.currency ? wallet.walletAddresses.addressForExchange : '';
|
||||
receiveAddress =
|
||||
receiveCurrency == wallet.currency ? wallet.walletAddresses.addressForExchange : '';
|
||||
receiveAddressExtraId = '';
|
||||
isDepositAddressEnabled = !(depositCurrency == wallet.currency);
|
||||
isFixedRateMode = false;
|
||||
_onPairChange();
|
||||
|
||||
@@ -26,6 +26,7 @@ import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.d
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:cake_wallet/utils/date_formatter.dart';
|
||||
import 'package:cake_wallet/utils/show_bar.dart';
|
||||
import 'package:cw_core/currencies_with_memo.dart';
|
||||
import 'package:cw_core/utils/print_verbose.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
@@ -182,6 +183,18 @@ abstract class TradeDetailsViewModelBase with Store {
|
||||
));
|
||||
}
|
||||
|
||||
final destinationMemo = trade.toAddressExtraId;
|
||||
final destinationCurrency = trade.to;
|
||||
if (destinationMemo != null &&
|
||||
destinationMemo.isNotEmpty &&
|
||||
destinationCurrency != null) {
|
||||
final isDestinationTag =
|
||||
memoLabelTypeFor(destinationCurrency) == MemoLabelType.destinationTag;
|
||||
items.add(StandartListItem(
|
||||
title: isDestinationTag ? S.current.destination_tag : S.current.memo,
|
||||
value: destinationMemo));
|
||||
}
|
||||
|
||||
items.add(StandartListItem(
|
||||
title: S.current.trade_details_provider, value: trade.provider.toString()));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user