Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions lib/exchange/provider/near_Intents_exchange_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -271,17 +271,15 @@ class NearIntentsExchangeProvider extends ExchangeProvider {
throw Exception('Failed to parse to currency from assetId: $toAssetId');
}

final from = CryptoCurrency.safeParseCurrencyFromString(fromCurrency.$1,
tag: fromCurrency.$2);
final to = CryptoCurrency.safeParseCurrencyFromString(toCurrency.$1,
tag: toCurrency.$2);
final from = CryptoCurrency.safeParseCurrencyFromString(fromCurrency.$1, tag: fromCurrency.$2);
final to = CryptoCurrency.safeParseCurrencyFromString(toCurrency.$1, tag: toCurrency.$2);


final trade = Trade(
id: depositAddress,
// Using deposit address as trade ID
from: request.fromCurrency,
to: request.toCurrency,
to: request.fromCurrency,
provider: description,
providerName: title,
state: TradeState.created,
Expand Down Expand Up @@ -575,10 +573,17 @@ class NearIntentsExchangeProvider extends ExchangeProvider {
final token = supported.firstWhereOrNull((t) => t.assetId == assetId);

if (token == null) return null;
final title = token.symbol;

final title = token.symbol.toUpperCase()
.replaceAll(RegExp(r'\s*\([^)]*\)'), '');

final normalizedNetwork = _normalizeNearBlockchainToTag(token.blockchain);
final tag =
normalizedNetwork == title.toUpperCase() ? null : normalizedNetwork;

final isNativeAsset = assetId.contains(':native:coin');

final tag = isNativeAsset || normalizedNetwork == title
? null
: normalizedNetwork;

return (title, tag);
}
Expand Down
102 changes: 61 additions & 41 deletions lib/view_model/exchange/exchange_trade_view_model.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:async';

import 'package:cake_wallet/core/amount_parsing_proxy.dart';
import 'package:cake_wallet/core/execution_state.dart';
import 'package:cake_wallet/entities/calculate_fiat_amount.dart';
import 'package:cake_wallet/entities/fiat_currency.dart';
import 'package:cake_wallet/exchange/exchange_provider_description.dart';
Expand All @@ -24,6 +25,7 @@ import 'package:cake_wallet/reactions/wallet_connect.dart';
import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_item.dart';
import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart';
import 'package:cake_wallet/store/dashboard/trades_store.dart';
import 'package:cake_wallet/utils/exchange_provider_logger.dart';
import 'package:cake_wallet/utils/qr_util.dart';
import 'package:cake_wallet/utils/token_utilities.dart';
import 'package:cake_wallet/view_model/send/fees_view_model.dart';
Expand All @@ -48,7 +50,6 @@ abstract class ExchangeTradeViewModelBase with Store {
required this.feesViewModel,
required this.fiatConversionStore,
}) : trade = tradesStore.trade!,
isSendable = _checkIfCanSend(tradesStore, wallet),
isSwapsXYZCanSendFromExternal = _checkIfSwapsXYZCanSendFromExternal(tradesStore.trade!, wallet),
items = ObservableList<ExchangeTradeItem>() {
setUpOutput();
Expand Down Expand Up @@ -115,12 +116,10 @@ abstract class ExchangeTradeViewModelBase with Store {
@observable
Trade trade;

@observable
bool isSendable;


bool isSwapsXYZCanSendFromExternal;

bool get isSendable => checkIfCanSend(trade, wallet) == null;

/// Providers that should hide the "send from external" button
static const List<Type> _providersThatHideExternalSend = [
JupiterExchangeProvider,
Expand Down Expand Up @@ -212,7 +211,13 @@ abstract class ExchangeTradeViewModelBase with Store {

@action
Future<void> confirmSending() async {
if (!isSendable) return;
final canSendError = checkIfCanSend(trade, wallet);

if (canSendError != null) {
sendViewModel.state = FailureState(canSendError);
return;
}


final selected = trade.from;
if (selected == null) {
Expand Down Expand Up @@ -348,48 +353,63 @@ abstract class ExchangeTradeViewModelBase with Store {
);
}

static bool _checkIfCanSend(TradesStore tradesStore, WalletBase wallet) {
final trade = tradesStore.trade!;
final tradeFrom = trade.from;

bool _sameCurrency(CryptoCurrency? a, CryptoCurrency? b) =>
a != null && b != null && a.titleAndTagEqual(b);

bool _isEthToken() =>
wallet.currency == CryptoCurrency.eth && tradeFrom?.tag == CryptoCurrency.eth.title;
String? checkIfCanSend(Trade? trade, WalletBase wallet) {
try {

bool _isPolygonToken() =>
wallet.currency == CryptoCurrency.maticpoly &&
tradeFrom?.tag == CryptoCurrency.maticpoly.tag;
if (trade == null) throw Exception('Trade is null');

bool _isBaseToken() =>
wallet.currency == CryptoCurrency.baseEth && tradeFrom?.tag == CryptoCurrency.baseEth.tag;
final tradeFrom = trade.from;
if (tradeFrom == null) throw Exception('Trade from currency is null');

bool _isArbitrumToken() =>
wallet.currency == CryptoCurrency.arbEth &&
(tradeFrom?.tag == CryptoCurrency.arbEth.tag ||
tradeFrom?.title == CryptoCurrency.arbEth.tag); // This is to handle the CryptoCurrency.arb that doesn't have a tag but fully belongs to the Arbitrum chain
bool _sameCurrency(CryptoCurrency a, CryptoCurrency b) => a.titleAndTagEqual(b);

bool _isTronToken() =>
wallet.currency == CryptoCurrency.trx && tradeFrom?.tag == CryptoCurrency.trx.title;
bool _isTokenBelongingToWallet(CryptoCurrency cur) {
final chainTag = cur.tag ?? cur.title;
return wallet.currency == cur &&
tradeFrom.tag?.toUpperCase() == chainTag.toUpperCase();
}

bool _isSplToken() =>
wallet.currency == CryptoCurrency.sol && tradeFrom?.tag == CryptoCurrency.sol.title;
final canSend = _sameCurrency(tradeFrom, wallet.currency) ||
(_sameCurrency(tradeFrom, CryptoCurrency.btcln) &&
wallet.currency == CryptoCurrency.btc) ||
trade.provider == ExchangeProviderDescription.xmrto ||
_isTokenBelongingToWallet(CryptoCurrency.eth) ||
_isTokenBelongingToWallet(CryptoCurrency.maticpoly) ||
_isTokenBelongingToWallet(CryptoCurrency.baseEth) ||
_isTokenBelongingToWallet(CryptoCurrency.arbEth) ||
_isTokenBelongingToWallet(CryptoCurrency.trx) ||
_isTokenBelongingToWallet(CryptoCurrency.sol) ||
_isTokenBelongingToWallet(CryptoCurrency.bnb);

if (!canSend) {
throw Exception(
'Wallet currency ${wallet.currency.title} does not match trade from currency ${tradeFrom.title} or is not a supported token for this wallet.',
);
}

bool _isBscToken() =>
wallet.currency == CryptoCurrency.bnb && tradeFrom?.tag == CryptoCurrency.bnb.tag;
return null;
} catch (e, s) {
final trade = tradesStore.trade;

ExchangeProviderLogger.logError(
provider: trade?.provider,
function: '_checkIfCanSend',
error: e,
stackTrace: s,
requestData: {
'tradeId': trade?.id,
'tradeFrom': trade?.from?.title,
'tradeFromTag': trade?.from?.tag,
'tradeTo': trade?.to?.title,
'tradeToTag': trade?.to?.tag,
'walletName': wallet.name,
'walletCurrency': wallet.currency.title,
'walletCurrencyTag': wallet.currency.tag,
},
);

return _sameCurrency(tradeFrom, wallet.currency) ||
(_sameCurrency(tradeFrom, CryptoCurrency.btcln) &&
wallet.currency == CryptoCurrency.btc) ||
tradesStore.trade!.provider == ExchangeProviderDescription.xmrto ||
_isEthToken() ||
_isPolygonToken() ||
_isSplToken() ||
_isTronToken() ||
_isBaseToken() ||
_isArbitrumToken() ||
_isBscToken();
return e.toString();
}
}

static bool _checkIfSwapsXYZCanSendFromExternal(Trade trade, WalletBase wallet) {
Expand Down