mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-23 20:19:25 +00:00
Merge branch 'main' of https://github.com/cake-tech/cake_wallet into CW-78-Ethereum
This commit is contained in:
commit
eff0369709
28 changed files with 753 additions and 627 deletions
1
.github/workflows/pr_test_build.yml
vendored
1
.github/workflows/pr_test_build.yml
vendored
|
@ -107,7 +107,6 @@ jobs:
|
||||||
echo "const moonPayApiKey = '${{ secrets.MOON_PAY_API_KEY }}';" >> lib/.secrets.g.dart
|
echo "const moonPayApiKey = '${{ secrets.MOON_PAY_API_KEY }}';" >> lib/.secrets.g.dart
|
||||||
echo "const moonPaySecretKey = '${{ secrets.MOON_PAY_SECRET_KEY }}';" >> lib/.secrets.g.dart
|
echo "const moonPaySecretKey = '${{ secrets.MOON_PAY_SECRET_KEY }}';" >> lib/.secrets.g.dart
|
||||||
echo "const sideShiftAffiliateId = '${{ secrets.SIDE_SHIFT_AFFILIATE_ID }}';" >> lib/.secrets.g.dart
|
echo "const sideShiftAffiliateId = '${{ secrets.SIDE_SHIFT_AFFILIATE_ID }}';" >> lib/.secrets.g.dart
|
||||||
echo "const sideShiftApiKey = '${{ secrets.SIDE_SHIFT_API_KEY }}';" >> lib/.secrets.g.dart
|
|
||||||
echo "const simpleSwapApiKey = '${{ secrets.SIMPLE_SWAP_API_KEY }}';" >> lib/.secrets.g.dart
|
echo "const simpleSwapApiKey = '${{ secrets.SIMPLE_SWAP_API_KEY }}';" >> lib/.secrets.g.dart
|
||||||
echo "const simpleSwapApiKeyDesktop = '${{ secrets.SIMPLE_SWAP_API_KEY_DESKTOP }}';" >> lib/.secrets.g.dart
|
echo "const simpleSwapApiKeyDesktop = '${{ secrets.SIMPLE_SWAP_API_KEY_DESKTOP }}';" >> lib/.secrets.g.dart
|
||||||
echo "const onramperApiKey = '${{ secrets.ONRAMPER_API_KEY }}';" >> lib/.secrets.g.dart
|
echo "const onramperApiKey = '${{ secrets.ONRAMPER_API_KEY }}';" >> lib/.secrets.g.dart
|
||||||
|
|
Before Width: | Height: | Size: 193 B After Width: | Height: | Size: 193 B |
|
@ -40,6 +40,7 @@ import 'package:cake_wallet/utils/payment_request.dart';
|
||||||
import 'package:cake_wallet/view_model/dashboard/desktop_sidebar_view_model.dart';
|
import 'package:cake_wallet/view_model/dashboard/desktop_sidebar_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/anon_invoice_page_view_model.dart';
|
import 'package:cake_wallet/view_model/anon_invoice_page_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/anonpay_details_view_model.dart';
|
import 'package:cake_wallet/view_model/anonpay_details_view_model.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/market_place_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/dashboard/receive_option_view_model.dart';
|
import 'package:cake_wallet/view_model/dashboard/receive_option_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/ionia/ionia_auth_view_model.dart';
|
import 'package:cake_wallet/view_model/ionia/ionia_auth_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/ionia/ionia_buy_card_view_model.dart';
|
import 'package:cake_wallet/view_model/ionia/ionia_buy_card_view_model.dart';
|
||||||
|
@ -876,6 +877,8 @@ Future setup({
|
||||||
|
|
||||||
getIt.registerFactory(() => IoniaGiftCardsListViewModel(ioniaService: getIt.get<IoniaService>()));
|
getIt.registerFactory(() => IoniaGiftCardsListViewModel(ioniaService: getIt.get<IoniaService>()));
|
||||||
|
|
||||||
|
getIt.registerFactory(()=> MarketPlaceViewModel(getIt.get<IoniaService>()));
|
||||||
|
|
||||||
getIt.registerFactory(() => IoniaAuthViewModel(ioniaService: getIt.get<IoniaService>()));
|
getIt.registerFactory(() => IoniaAuthViewModel(ioniaService: getIt.get<IoniaService>()));
|
||||||
|
|
||||||
getIt.registerFactoryParam<IoniaMerchPurchaseViewModel, double, IoniaMerchant>(
|
getIt.registerFactoryParam<IoniaMerchPurchaseViewModel, double, IoniaMerchant>(
|
||||||
|
@ -905,7 +908,7 @@ Future setup({
|
||||||
return IoniaVerifyIoniaOtp(getIt.get<IoniaAuthViewModel>(), email, isSignIn);
|
return IoniaVerifyIoniaOtp(getIt.get<IoniaAuthViewModel>(), email, isSignIn);
|
||||||
});
|
});
|
||||||
|
|
||||||
getIt.registerFactory(() => IoniaWelcomePage(getIt.get<IoniaGiftCardsListViewModel>()));
|
getIt.registerFactory(() => IoniaWelcomePage());
|
||||||
|
|
||||||
getIt.registerFactoryParam<IoniaBuyGiftCardPage, List, void>((List args, _) {
|
getIt.registerFactoryParam<IoniaBuyGiftCardPage, List, void>((List args, _) {
|
||||||
final merchant = args.first as IoniaMerchant;
|
final merchant = args.first as IoniaMerchant;
|
||||||
|
|
|
@ -55,11 +55,11 @@ class LanguageService {
|
||||||
'cs': 'czk',
|
'cs': 'czk',
|
||||||
'ur': 'pak',
|
'ur': 'pak',
|
||||||
'id': 'idn',
|
'id': 'idn',
|
||||||
'yo': 'yor',
|
'yo': 'nga',
|
||||||
'ha': 'hau'
|
'ha': 'hau'
|
||||||
};
|
};
|
||||||
|
|
||||||
static final list = <String, String> {};
|
static final list = <String, String>{};
|
||||||
|
|
||||||
static void loadLocaleList() {
|
static void loadLocaleList() {
|
||||||
supportedLocales.forEach((key, value) {
|
supportedLocales.forEach((key, value) {
|
||||||
|
|
|
@ -19,10 +19,10 @@ class SideShiftExchangeProvider extends ExchangeProvider {
|
||||||
|
|
||||||
static const affiliateId = secrets.sideShiftAffiliateId;
|
static const affiliateId = secrets.sideShiftAffiliateId;
|
||||||
static const apiBaseUrl = 'https://sideshift.ai/api';
|
static const apiBaseUrl = 'https://sideshift.ai/api';
|
||||||
static const rangePath = '/v1/pairs';
|
static const rangePath = '/v2/pair';
|
||||||
static const orderPath = '/v1/orders';
|
static const orderPath = '/v2/shifts';
|
||||||
static const quotePath = '/v1/quotes';
|
static const quotePath = '/v2/quotes';
|
||||||
static const permissionPath = '/v1/permissions';
|
static const permissionPath = '/v2/permissions';
|
||||||
|
|
||||||
static const List<CryptoCurrency> _notSupported = [
|
static const List<CryptoCurrency> _notSupported = [
|
||||||
CryptoCurrency.xhv,
|
CryptoCurrency.xhv,
|
||||||
|
@ -36,23 +36,22 @@ class SideShiftExchangeProvider extends ExchangeProvider {
|
||||||
CryptoCurrency.scrt,
|
CryptoCurrency.scrt,
|
||||||
CryptoCurrency.stx,
|
CryptoCurrency.stx,
|
||||||
CryptoCurrency.bttc,
|
CryptoCurrency.bttc,
|
||||||
|
CryptoCurrency.usdt,
|
||||||
|
CryptoCurrency.eos,
|
||||||
];
|
];
|
||||||
|
|
||||||
static List<ExchangePair> _supportedPairs() {
|
static List<ExchangePair> _supportedPairs() {
|
||||||
final supportedCurrencies = CryptoCurrency.all
|
final supportedCurrencies =
|
||||||
.where((element) => !_notSupported.contains(element))
|
CryptoCurrency.all.where((element) => !_notSupported.contains(element)).toList();
|
||||||
.toList();
|
|
||||||
|
|
||||||
return supportedCurrencies
|
return supportedCurrencies
|
||||||
.map((i) => supportedCurrencies
|
.map((i) => supportedCurrencies.map((k) => ExchangePair(from: i, to: k, reverse: true)))
|
||||||
.map((k) => ExchangePair(from: i, to: k, reverse: true)))
|
|
||||||
.expand((i) => i)
|
.expand((i) => i)
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ExchangeProviderDescription get description =>
|
ExchangeProviderDescription get description => ExchangeProviderDescription.sideShift;
|
||||||
ExchangeProviderDescription.sideShift;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<double> fetchRate(
|
Future<double> fetchRate(
|
||||||
|
@ -65,17 +64,18 @@ class SideShiftExchangeProvider extends ExchangeProvider {
|
||||||
if (amount == 0) {
|
if (amount == 0) {
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
final fromCurrency = _normalizeCryptoCurrency(from);
|
|
||||||
final toCurrency = _normalizeCryptoCurrency(to);
|
final fromCurrency = from.title.toLowerCase();
|
||||||
final url =
|
final toCurrency = to.title.toLowerCase();
|
||||||
apiBaseUrl + rangePath + '/' + fromCurrency + '/' + toCurrency;
|
final depositNetwork = _networkFor(from);
|
||||||
|
final settleNetwork = _networkFor(to);
|
||||||
|
|
||||||
|
final url = "$apiBaseUrl$rangePath/$fromCurrency-$depositNetwork/$toCurrency-$settleNetwork";
|
||||||
|
|
||||||
final uri = Uri.parse(url);
|
final uri = Uri.parse(url);
|
||||||
final response = await get(uri);
|
final response = await get(uri);
|
||||||
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
||||||
final rate = double.parse(responseJSON['rate'] as String);
|
final rate = double.parse(responseJSON['rate'] as String);
|
||||||
final max = double.parse(responseJSON['max'] as String);
|
|
||||||
|
|
||||||
if (amount > max) return 0.00;
|
|
||||||
|
|
||||||
return rate;
|
return rate;
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
|
@ -101,25 +101,38 @@ class SideShiftExchangeProvider extends ExchangeProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
||||||
final canCreateOrder = responseJSON['createOrder'] as bool;
|
final cancreateShift = responseJSON['createShift'] as bool;
|
||||||
final canCreateQuote = responseJSON['createQuote'] as bool;
|
return cancreateShift;
|
||||||
return canCreateOrder && canCreateQuote;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Trade> createTrade(
|
Future<Trade> createTrade({required TradeRequest request, required bool isFixedRateMode}) async {
|
||||||
{required TradeRequest request, required bool isFixedRateMode}) async {
|
|
||||||
final _request = request as SideShiftRequest;
|
final _request = request as SideShiftRequest;
|
||||||
final quoteId = await _createQuote(_request);
|
String url = '';
|
||||||
final url = apiBaseUrl + orderPath;
|
final depositCoin = request.depositMethod.title.toLowerCase();
|
||||||
final headers = {'Content-Type': 'application/json'};
|
final settleCoin = request.settleMethod.title.toLowerCase();
|
||||||
final body = {
|
final body = {
|
||||||
'type': 'fixed',
|
|
||||||
'quoteId': quoteId,
|
|
||||||
'affiliateId': affiliateId,
|
'affiliateId': affiliateId,
|
||||||
'settleAddress': _request.settleAddress,
|
'settleAddress': _request.settleAddress,
|
||||||
'refundAddress': _request.refundAddress
|
'refundAddress': _request.refundAddress,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (isFixedRateMode) {
|
||||||
|
final quoteId = await _createQuote(_request);
|
||||||
|
body['quoteId'] = quoteId;
|
||||||
|
|
||||||
|
url = apiBaseUrl + orderPath + '/fixed';
|
||||||
|
} else {
|
||||||
|
url = apiBaseUrl + orderPath + '/variable';
|
||||||
|
final depositNetwork = _networkFor(request.depositMethod);
|
||||||
|
final settleNetwork = _networkFor(request.settleMethod);
|
||||||
|
body["depositCoin"] = depositCoin;
|
||||||
|
body["settleCoin"] = settleCoin;
|
||||||
|
body["settleNetwork"] = settleNetwork;
|
||||||
|
body["depositNetwork"] = depositNetwork;
|
||||||
|
}
|
||||||
|
final headers = {'Content-Type': 'application/json'};
|
||||||
|
|
||||||
final uri = Uri.parse(url);
|
final uri = Uri.parse(url);
|
||||||
final response = await post(uri, headers: headers, body: json.encode(body));
|
final response = await post(uri, headers: headers, body: json.encode(body));
|
||||||
|
|
||||||
|
@ -136,8 +149,9 @@ class SideShiftExchangeProvider extends ExchangeProvider {
|
||||||
|
|
||||||
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
||||||
final id = responseJSON['id'] as String;
|
final id = responseJSON['id'] as String;
|
||||||
final inputAddress = responseJSON['depositAddress']['address'] as String;
|
final inputAddress = responseJSON['depositAddress'] as String;
|
||||||
final settleAddress = responseJSON['settleAddress']['address'] as String;
|
final settleAddress = responseJSON['settleAddress'] as String;
|
||||||
|
final depositAmount = responseJSON['depositAmount'] as String?;
|
||||||
|
|
||||||
return Trade(
|
return Trade(
|
||||||
id: id,
|
id: id,
|
||||||
|
@ -147,7 +161,7 @@ class SideShiftExchangeProvider extends ExchangeProvider {
|
||||||
inputAddress: inputAddress,
|
inputAddress: inputAddress,
|
||||||
refundAddress: settleAddress,
|
refundAddress: settleAddress,
|
||||||
state: TradeState.created,
|
state: TradeState.created,
|
||||||
amount: _request.depositAmount,
|
amount: depositAmount ?? _request.depositAmount,
|
||||||
payoutAddress: settleAddress,
|
payoutAddress: settleAddress,
|
||||||
createdAt: DateTime.now(),
|
createdAt: DateTime.now(),
|
||||||
);
|
);
|
||||||
|
@ -156,13 +170,17 @@ class SideShiftExchangeProvider extends ExchangeProvider {
|
||||||
Future<String> _createQuote(SideShiftRequest request) async {
|
Future<String> _createQuote(SideShiftRequest request) async {
|
||||||
final url = apiBaseUrl + quotePath;
|
final url = apiBaseUrl + quotePath;
|
||||||
final headers = {'Content-Type': 'application/json'};
|
final headers = {'Content-Type': 'application/json'};
|
||||||
final depositMethod = _normalizeCryptoCurrency(request.depositMethod);
|
final depositMethod = request.depositMethod.title.toLowerCase();
|
||||||
final settleMethod = _normalizeCryptoCurrency(request.settleMethod);
|
final settleMethod = request.settleMethod.title.toLowerCase();
|
||||||
|
final depositNetwork = _networkFor(request.depositMethod);
|
||||||
|
final settleNetwork = _networkFor(request.settleMethod);
|
||||||
final body = {
|
final body = {
|
||||||
'depositMethod': depositMethod,
|
'depositCoin': depositMethod,
|
||||||
'settleMethod': settleMethod,
|
'settleCoin': settleMethod,
|
||||||
'affiliateId': affiliateId,
|
'affiliateId': affiliateId,
|
||||||
'depositAmount': request.depositAmount,
|
'settleAmount': request.depositAmount,
|
||||||
|
'settleNetwork': settleNetwork,
|
||||||
|
'depositNetwork': depositNetwork,
|
||||||
};
|
};
|
||||||
final uri = Uri.parse(url);
|
final uri = Uri.parse(url);
|
||||||
final response = await post(uri, headers: headers, body: json.encode(body));
|
final response = await post(uri, headers: headers, body: json.encode(body));
|
||||||
|
@ -189,9 +207,15 @@ class SideShiftExchangeProvider extends ExchangeProvider {
|
||||||
{required CryptoCurrency from,
|
{required CryptoCurrency from,
|
||||||
required CryptoCurrency to,
|
required CryptoCurrency to,
|
||||||
required bool isFixedRateMode}) async {
|
required bool isFixedRateMode}) async {
|
||||||
final fromCurrency = _normalizeCryptoCurrency(from);
|
final fromCurrency = isFixedRateMode ? to : from;
|
||||||
final toCurrency = _normalizeCryptoCurrency(to);
|
final toCurrency = isFixedRateMode ? from : to;
|
||||||
final url = apiBaseUrl + rangePath + '/' + fromCurrency + '/' + toCurrency;
|
|
||||||
|
final fromNetwork = _networkFor(fromCurrency);
|
||||||
|
final toNetwork = _networkFor(toCurrency);
|
||||||
|
|
||||||
|
final url =
|
||||||
|
"$apiBaseUrl$rangePath/${fromCurrency.title.toLowerCase()}-$fromNetwork/${toCurrency.title.toLowerCase()}-$toNetwork";
|
||||||
|
|
||||||
final uri = Uri.parse(url);
|
final uri = Uri.parse(url);
|
||||||
final response = await get(uri);
|
final response = await get(uri);
|
||||||
|
|
||||||
|
@ -210,6 +234,14 @@ class SideShiftExchangeProvider extends ExchangeProvider {
|
||||||
final min = double.tryParse(responseJSON['min'] as String? ?? '');
|
final min = double.tryParse(responseJSON['min'] as String? ?? '');
|
||||||
final max = double.tryParse(responseJSON['max'] as String? ?? '');
|
final max = double.tryParse(responseJSON['max'] as String? ?? '');
|
||||||
|
|
||||||
|
if (isFixedRateMode) {
|
||||||
|
final currentRate = double.parse(responseJSON['rate'] as String);
|
||||||
|
return Limits(
|
||||||
|
min: min != null ? (min * currentRate) : null,
|
||||||
|
max: max != null ? (max * currentRate) : null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return Limits(min: min, max: max);
|
return Limits(min: min, max: max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,8 +259,7 @@ class SideShiftExchangeProvider extends ExchangeProvider {
|
||||||
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
||||||
final error = responseJSON['error']['message'] as String;
|
final error = responseJSON['error']['message'] as String;
|
||||||
|
|
||||||
throw TradeNotFoundException(id,
|
throw TradeNotFoundException(id, provider: description, description: error);
|
||||||
provider: description, description: error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.statusCode != 200) {
|
if (response.statusCode != 200) {
|
||||||
|
@ -236,24 +267,21 @@ class SideShiftExchangeProvider extends ExchangeProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
|
||||||
final fromCurrency = responseJSON['depositMethodId'] as String;
|
final fromCurrency = responseJSON['depositCoin'] as String;
|
||||||
final from = CryptoCurrency.fromString(fromCurrency);
|
final from = CryptoCurrency.fromString(fromCurrency);
|
||||||
final toCurrency = responseJSON['settleMethodId'] as String;
|
final toCurrency = responseJSON['settleCoin'] as String;
|
||||||
final to = CryptoCurrency.fromString(toCurrency);
|
final to = CryptoCurrency.fromString(toCurrency);
|
||||||
final inputAddress = responseJSON['depositAddress']['address'] as String;
|
final inputAddress = responseJSON['depositAddress'] as String;
|
||||||
final expectedSendAmount = responseJSON['depositAmount'].toString();
|
final expectedSendAmount = responseJSON['depositAmount'] as String?;
|
||||||
final deposits = responseJSON['deposits'] as List?;
|
final status = responseJSON['status'] as String?;
|
||||||
final settleAddress = responseJSON['settleAddress']['address'] as String;
|
final settleAddress = responseJSON['settleAddress'] as String;
|
||||||
TradeState? state;
|
TradeState? state;
|
||||||
String? status;
|
|
||||||
|
|
||||||
if (deposits?.isNotEmpty ?? false) {
|
|
||||||
status = deposits![0]['status'] as String?;
|
|
||||||
}
|
|
||||||
state = TradeState.deserialize(raw: status ?? 'created');
|
state = TradeState.deserialize(raw: status ?? 'created');
|
||||||
|
final isVariable = (responseJSON['type'] as String) == 'variable';
|
||||||
|
|
||||||
final expiredAtRaw = responseJSON['expiresAtISO'] as String;
|
final expiredAtRaw = responseJSON['expiresAt'] as String;
|
||||||
final expiredAt = DateTime.tryParse(expiredAtRaw)?.toLocal();
|
final expiredAt = isVariable ? null : DateTime.tryParse(expiredAtRaw)?.toLocal();
|
||||||
|
|
||||||
return Trade(
|
return Trade(
|
||||||
id: id,
|
id: id,
|
||||||
|
@ -261,11 +289,10 @@ class SideShiftExchangeProvider extends ExchangeProvider {
|
||||||
to: to,
|
to: to,
|
||||||
provider: description,
|
provider: description,
|
||||||
inputAddress: inputAddress,
|
inputAddress: inputAddress,
|
||||||
amount: expectedSendAmount,
|
amount: expectedSendAmount ?? '',
|
||||||
state: state,
|
state: state,
|
||||||
expiredAt: expiredAt,
|
expiredAt: expiredAt,
|
||||||
payoutAddress: settleAddress
|
payoutAddress: settleAddress);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -280,28 +307,25 @@ class SideShiftExchangeProvider extends ExchangeProvider {
|
||||||
@override
|
@override
|
||||||
String get title => 'SideShift';
|
String get title => 'SideShift';
|
||||||
|
|
||||||
static String _normalizeCryptoCurrency(CryptoCurrency currency) {
|
String _networkFor(CryptoCurrency currency) =>
|
||||||
switch (currency) {
|
currency.tag != null ? _normalizeTag(currency.tag!) : 'mainnet';
|
||||||
case CryptoCurrency.zaddr:
|
|
||||||
return 'zaddr';
|
String _normalizeTag(String tag) {
|
||||||
case CryptoCurrency.zec:
|
switch (tag) {
|
||||||
return 'zec';
|
case 'ETH':
|
||||||
case CryptoCurrency.bnb:
|
return 'ethereum';
|
||||||
return currency.tag!.toLowerCase();
|
case 'TRX':
|
||||||
case CryptoCurrency.usdterc20:
|
return 'tron';
|
||||||
return 'usdtErc20';
|
case 'LN':
|
||||||
case CryptoCurrency.usdttrc20:
|
return 'lightning';
|
||||||
return 'usdtTrc20';
|
case 'POLY':
|
||||||
case CryptoCurrency.usdcpoly:
|
|
||||||
return 'usdcpolygon';
|
|
||||||
case CryptoCurrency.usdcsol:
|
|
||||||
return 'usdcsol';
|
|
||||||
case CryptoCurrency.maticpoly:
|
|
||||||
return 'polygon';
|
return 'polygon';
|
||||||
case CryptoCurrency.btcln:
|
case 'ZEC':
|
||||||
return 'ln';
|
return 'zcash';
|
||||||
|
case 'AVAXC':
|
||||||
|
return 'avax';
|
||||||
default:
|
default:
|
||||||
return currency.title.toLowerCase();
|
return tag.toLowerCase();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||||
import 'package:cw_core/wallet_base.dart';
|
import 'package:cw_core/wallet_base.dart';
|
||||||
import 'package:cw_core/sync_status.dart';
|
import 'package:cw_core/sync_status.dart';
|
||||||
import 'package:cake_wallet/store/settings_store.dart';
|
import 'package:cake_wallet/store/settings_store.dart';
|
||||||
import 'package:connectivity/connectivity.dart';
|
|
||||||
|
|
||||||
Timer? _checkConnectionTimer;
|
Timer? _checkConnectionTimer;
|
||||||
|
|
||||||
void startCheckConnectionReaction(
|
void startCheckConnectionReaction(
|
||||||
|
|
|
@ -175,7 +175,6 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||||
fullscreenDialog: true);
|
fullscreenDialog: true);
|
||||||
} else if (isSingleCoin) {
|
} else if (isSingleCoin) {
|
||||||
return MaterialPageRoute<void>(
|
return MaterialPageRoute<void>(
|
||||||
fullscreenDialog: true,
|
|
||||||
builder: (_) => getIt.get<WalletRestorePage>(
|
builder: (_) => getIt.get<WalletRestorePage>(
|
||||||
param1: availableWalletTypes.first
|
param1: availableWalletTypes.first
|
||||||
));
|
));
|
||||||
|
@ -196,7 +195,6 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||||
|
|
||||||
case Routes.restoreWallet:
|
case Routes.restoreWallet:
|
||||||
return MaterialPageRoute<void>(
|
return MaterialPageRoute<void>(
|
||||||
fullscreenDialog: true,
|
|
||||||
builder: (_) => getIt.get<WalletRestorePage>(
|
builder: (_) => getIt.get<WalletRestorePage>(
|
||||||
param1: settings.arguments as WalletType));
|
param1: settings.arguments as WalletType));
|
||||||
|
|
||||||
|
@ -206,6 +204,7 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||||
|
|
||||||
case Routes.dashboard:
|
case Routes.dashboard:
|
||||||
return CupertinoPageRoute<void>(
|
return CupertinoPageRoute<void>(
|
||||||
|
settings: settings,
|
||||||
builder: (_) => getIt.get<DashboardPage>());
|
builder: (_) => getIt.get<DashboardPage>());
|
||||||
|
|
||||||
case Routes.send:
|
case Routes.send:
|
||||||
|
@ -468,7 +467,8 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||||
return CupertinoPageRoute<void>( builder: (_) => getIt.get<IoniaCreateAccountPage>());
|
return CupertinoPageRoute<void>( builder: (_) => getIt.get<IoniaCreateAccountPage>());
|
||||||
|
|
||||||
case Routes.ioniaManageCardsPage:
|
case Routes.ioniaManageCardsPage:
|
||||||
return CupertinoPageRoute<void>(builder: (_) => getIt.get<IoniaManageCardsPage>());
|
return CupertinoPageRoute<void>(
|
||||||
|
builder: (_) => getIt.get<IoniaManageCardsPage>());
|
||||||
|
|
||||||
case Routes.ioniaBuyGiftCardPage:
|
case Routes.ioniaBuyGiftCardPage:
|
||||||
final args = settings.arguments as List;
|
final args = settings.arguments as List;
|
||||||
|
@ -536,7 +536,6 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||||
case Routes.anonPayInvoicePage:
|
case Routes.anonPayInvoicePage:
|
||||||
final args = settings.arguments as List;
|
final args = settings.arguments as List;
|
||||||
return CupertinoPageRoute<void>(
|
return CupertinoPageRoute<void>(
|
||||||
fullscreenDialog: true,
|
|
||||||
builder: (_) => getIt.get<AnonPayInvoicePage>(param1: args));
|
builder: (_) => getIt.get<AnonPayInvoicePage>(param1: args));
|
||||||
|
|
||||||
case Routes.anonPayReceivePage:
|
case Routes.anonPayReceivePage:
|
||||||
|
|
|
@ -5,7 +5,7 @@ import 'package:cake_wallet/entities/main_actions.dart';
|
||||||
import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart';
|
import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart';
|
||||||
import 'package:cake_wallet/src/screens/dashboard/widgets/market_place_page.dart';
|
import 'package:cake_wallet/src/screens/dashboard/widgets/market_place_page.dart';
|
||||||
import 'package:cake_wallet/utils/version_comparator.dart';
|
import 'package:cake_wallet/utils/version_comparator.dart';
|
||||||
import 'package:cake_wallet/wallet_type_utils.dart';
|
import 'package:cake_wallet/view_model/dashboard/market_place_view_model.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/routes.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
import 'package:cake_wallet/src/screens/yat_emoji_id.dart';
|
import 'package:cake_wallet/src/screens/yat_emoji_id.dart';
|
||||||
|
@ -27,8 +27,6 @@ import 'package:mobx/mobx.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:smooth_page_indicator/smooth_page_indicator.dart';
|
import 'package:smooth_page_indicator/smooth_page_indicator.dart';
|
||||||
import 'package:cake_wallet/main.dart';
|
import 'package:cake_wallet/main.dart';
|
||||||
import 'package:cake_wallet/buy/moonpay/moonpay_buy_provider.dart';
|
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
|
||||||
import 'package:cake_wallet/src/screens/release_notes/release_notes_screen.dart';
|
import 'package:cake_wallet/src/screens/release_notes/release_notes_screen.dart';
|
||||||
|
|
||||||
class DashboardPage extends StatelessWidget {
|
class DashboardPage extends StatelessWidget {
|
||||||
|
@ -251,7 +249,12 @@ class _DashboardPageView extends BasePage {
|
||||||
if (dashboardViewModel.shouldShowMarketPlaceInDashboard) {
|
if (dashboardViewModel.shouldShowMarketPlaceInDashboard) {
|
||||||
pages.add(Semantics(
|
pages.add(Semantics(
|
||||||
label: 'Marketplace Page',
|
label: 'Marketplace Page',
|
||||||
child: MarketPlacePage(dashboardViewModel: dashboardViewModel)));
|
child: MarketPlacePage(
|
||||||
|
dashboardViewModel: dashboardViewModel,
|
||||||
|
marketPlaceViewModel: getIt.get<MarketPlaceViewModel>(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
pages.add(Semantics(label: 'Balance Page', child: balancePage));
|
pages.add(Semantics(label: 'Balance Page', child: balancePage));
|
||||||
pages.add(Semantics(
|
pages.add(Semantics(
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
|
import 'package:cake_wallet/di.dart';
|
||||||
import 'package:cake_wallet/entities/main_actions.dart';
|
import 'package:cake_wallet/entities/main_actions.dart';
|
||||||
import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_action_button.dart';
|
import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_action_button.dart';
|
||||||
import 'package:cake_wallet/src/screens/dashboard/widgets/market_place_page.dart';
|
import 'package:cake_wallet/src/screens/dashboard/widgets/market_place_page.dart';
|
||||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/market_place_view_model.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||||
|
|
||||||
|
@ -70,7 +72,10 @@ class DesktopDashboardActions extends StatelessWidget {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: MarketPlacePage(dashboardViewModel: dashboardViewModel),
|
child: MarketPlacePage(
|
||||||
|
dashboardViewModel: dashboardViewModel,
|
||||||
|
marketPlaceViewModel: getIt.get<MarketPlaceViewModel>(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
|
@ -273,7 +273,7 @@ class AddressPage extends BasePage {
|
||||||
reaction((_) => receiveOptionViewModel.selectedReceiveOption, (ReceivePageOption option) {
|
reaction((_) => receiveOptionViewModel.selectedReceiveOption, (ReceivePageOption option) {
|
||||||
switch (option) {
|
switch (option) {
|
||||||
case ReceivePageOption.anonPayInvoice:
|
case ReceivePageOption.anonPayInvoice:
|
||||||
Navigator.pushReplacementNamed(
|
Navigator.pushNamed(
|
||||||
context,
|
context,
|
||||||
Routes.anonPayInvoicePage,
|
Routes.anonPayInvoicePage,
|
||||||
arguments: [addressListViewModel.address.address, option],
|
arguments: [addressListViewModel.address.address, option],
|
||||||
|
@ -285,7 +285,7 @@ class AddressPage extends BasePage {
|
||||||
final onionUrl = sharedPreferences.getString(PreferencesKey.onionDonationLink);
|
final onionUrl = sharedPreferences.getString(PreferencesKey.onionDonationLink);
|
||||||
|
|
||||||
if (clearnetUrl != null && onionUrl != null) {
|
if (clearnetUrl != null && onionUrl != null) {
|
||||||
Navigator.pushReplacementNamed(
|
Navigator.pushNamed(
|
||||||
context,
|
context,
|
||||||
Routes.anonPayReceivePage,
|
Routes.anonPayReceivePage,
|
||||||
arguments: AnonpayDonationLinkInfo(
|
arguments: AnonpayDonationLinkInfo(
|
||||||
|
@ -295,7 +295,7 @@ class AddressPage extends BasePage {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
Navigator.pushReplacementNamed(
|
Navigator.pushNamed(
|
||||||
context,
|
context,
|
||||||
Routes.anonPayInvoicePage,
|
Routes.anonPayInvoicePage,
|
||||||
arguments: [addressListViewModel.address.address, option],
|
arguments: [addressListViewModel.address.address, option],
|
||||||
|
|
|
@ -3,16 +3,20 @@ import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||||
import 'package:cake_wallet/src/widgets/market_place_item.dart';
|
import 'package:cake_wallet/src/widgets/market_place_item.dart';
|
||||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/market_place_view_model.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
import 'package:cw_core/wallet_type.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class MarketPlacePage extends StatelessWidget {
|
class MarketPlacePage extends StatelessWidget {
|
||||||
|
MarketPlacePage({
|
||||||
MarketPlacePage({required this.dashboardViewModel});
|
required this.dashboardViewModel,
|
||||||
|
required this.marketPlaceViewModel,
|
||||||
|
});
|
||||||
|
|
||||||
final DashboardViewModel dashboardViewModel;
|
final DashboardViewModel dashboardViewModel;
|
||||||
|
final MarketPlaceViewModel marketPlaceViewModel;
|
||||||
final _scrollController = ScrollController();
|
final _scrollController = ScrollController();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -48,7 +52,7 @@ class MarketPlacePage extends StatelessWidget {
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
SizedBox(height: 20),
|
SizedBox(height: 20),
|
||||||
MarketPlaceItem(
|
MarketPlaceItem(
|
||||||
onTap: () =>_navigatorToGiftCardsPage(context),
|
onTap: () => _navigatorToGiftCardsPage(context),
|
||||||
title: S.of(context).cake_pay_title,
|
title: S.of(context).cake_pay_title,
|
||||||
subTitle: S.of(context).cake_pay_subtitle,
|
subTitle: S.of(context).cake_pay_subtitle,
|
||||||
),
|
),
|
||||||
|
@ -70,6 +74,7 @@ class MarketPlacePage extends StatelessWidget {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _navigatorToGiftCardsPage(BuildContext context) {
|
void _navigatorToGiftCardsPage(BuildContext context) {
|
||||||
final walletType = dashboardViewModel.type;
|
final walletType = dashboardViewModel.type;
|
||||||
|
|
||||||
|
@ -86,8 +91,13 @@ class MarketPlacePage extends StatelessWidget {
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
marketPlaceViewModel.isIoniaUserAuthenticated().then((value) {
|
||||||
|
if (value) {
|
||||||
|
Navigator.pushNamed(context, Routes.ioniaManageCardsPage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
Navigator.of(context).pushNamed(Routes.ioniaWelcomePage);
|
Navigator.of(context).pushNamed(Routes.ioniaWelcomePage);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,12 @@ class TransactionsPage extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return GestureDetector(
|
||||||
|
onLongPress: () => dashboardViewModel.balanceViewModel.isReversing =
|
||||||
|
!dashboardViewModel.balanceViewModel.isReversing,
|
||||||
|
onLongPressUp: () => dashboardViewModel.balanceViewModel.isReversing =
|
||||||
|
!dashboardViewModel.balanceViewModel.isReversing,
|
||||||
|
child: Container(
|
||||||
color: ResponsiveLayoutUtil.instance.isMobile(context)
|
color: ResponsiveLayoutUtil.instance.isMobile(context)
|
||||||
? null
|
? null
|
||||||
: Theme.of(context).colorScheme.background,
|
: Theme.of(context).colorScheme.background,
|
||||||
|
@ -51,34 +56,40 @@ class TransactionsPage extends StatelessWidget {
|
||||||
|
|
||||||
return Observer(
|
return Observer(
|
||||||
builder: (_) => TransactionRow(
|
builder: (_) => TransactionRow(
|
||||||
onTap: () => Navigator.of(context)
|
onTap: () => Navigator.of(context).pushNamed(
|
||||||
.pushNamed(Routes.transactionDetails, arguments: transaction),
|
Routes.transactionDetails,
|
||||||
|
arguments: transaction),
|
||||||
direction: transaction.direction,
|
direction: transaction.direction,
|
||||||
formattedDate: DateFormat('HH:mm').format(transaction.date),
|
formattedDate: DateFormat('HH:mm')
|
||||||
|
.format(transaction.date),
|
||||||
formattedAmount: item.formattedCryptoAmount,
|
formattedAmount: item.formattedCryptoAmount,
|
||||||
formattedFiatAmount:
|
formattedFiatAmount: dashboardViewModel
|
||||||
dashboardViewModel.balanceViewModel.isFiatDisabled
|
.balanceViewModel.isFiatDisabled
|
||||||
? ''
|
? ''
|
||||||
: item.formattedFiatAmount,
|
: item.formattedFiatAmount,
|
||||||
isPending: transaction.isPending,
|
isPending: transaction.isPending,
|
||||||
title: item.formattedTitle + item.formattedStatus));
|
title: item.formattedTitle +
|
||||||
|
item.formattedStatus));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item is AnonpayTransactionListItem) {
|
if (item is AnonpayTransactionListItem) {
|
||||||
final transactionInfo = item.transaction;
|
final transactionInfo = item.transaction;
|
||||||
|
|
||||||
return AnonpayTransactionRow(
|
return AnonpayTransactionRow(
|
||||||
onTap: () => Navigator.of(context)
|
onTap: () => Navigator.of(context).pushNamed(
|
||||||
.pushNamed(Routes.anonPayDetailsPage, arguments: transactionInfo),
|
Routes.anonPayDetailsPage,
|
||||||
|
arguments: transactionInfo),
|
||||||
currency: transactionInfo.fiatAmount != null
|
currency: transactionInfo.fiatAmount != null
|
||||||
? transactionInfo.fiatEquiv ?? ''
|
? transactionInfo.fiatEquiv ?? ''
|
||||||
: CryptoCurrency.fromFullName(transactionInfo.coinTo)
|
: CryptoCurrency.fromFullName(
|
||||||
|
transactionInfo.coinTo)
|
||||||
.name
|
.name
|
||||||
.toUpperCase(),
|
.toUpperCase(),
|
||||||
provider: transactionInfo.provider,
|
provider: transactionInfo.provider,
|
||||||
amount: transactionInfo.fiatAmount?.toString() ??
|
amount: transactionInfo.fiatAmount?.toString() ??
|
||||||
(transactionInfo.amountTo?.toString() ?? ''),
|
(transactionInfo.amountTo?.toString() ?? ''),
|
||||||
createdAt: DateFormat('HH:mm').format(transactionInfo.createdAt),
|
createdAt: DateFormat('HH:mm')
|
||||||
|
.format(transactionInfo.createdAt),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,13 +98,16 @@ class TransactionsPage extends StatelessWidget {
|
||||||
|
|
||||||
return Observer(
|
return Observer(
|
||||||
builder: (_) => TradeRow(
|
builder: (_) => TradeRow(
|
||||||
onTap: () => Navigator.of(context)
|
onTap: () => Navigator.of(context).pushNamed(
|
||||||
.pushNamed(Routes.tradeDetails, arguments: trade),
|
Routes.tradeDetails,
|
||||||
|
arguments: trade),
|
||||||
provider: trade.provider,
|
provider: trade.provider,
|
||||||
from: trade.from,
|
from: trade.from,
|
||||||
to: trade.to,
|
to: trade.to,
|
||||||
createdAtFormattedDate: trade.createdAt != null
|
createdAtFormattedDate:
|
||||||
? DateFormat('HH:mm').format(trade.createdAt!)
|
trade.createdAt != null
|
||||||
|
? DateFormat('HH:mm')
|
||||||
|
.format(trade.createdAt!)
|
||||||
: null,
|
: null,
|
||||||
formattedAmount: item.tradeFormattedAmount));
|
formattedAmount: item.tradeFormattedAmount));
|
||||||
}
|
}
|
||||||
|
@ -104,12 +118,13 @@ class TransactionsPage extends StatelessWidget {
|
||||||
return Observer(
|
return Observer(
|
||||||
builder: (_) => OrderRow(
|
builder: (_) => OrderRow(
|
||||||
onTap: () => Navigator.of(context)
|
onTap: () => Navigator.of(context)
|
||||||
.pushNamed(Routes.orderDetails, arguments: order),
|
.pushNamed(Routes.orderDetails,
|
||||||
|
arguments: order),
|
||||||
provider: order.provider,
|
provider: order.provider,
|
||||||
from: order.from!,
|
from: order.from!,
|
||||||
to: order.to!,
|
to: order.to!,
|
||||||
createdAtFormattedDate:
|
createdAtFormattedDate: DateFormat('HH:mm')
|
||||||
DateFormat('HH:mm').format(order.createdAt),
|
.format(order.createdAt),
|
||||||
formattedAmount: item.orderFormattedAmount,
|
formattedAmount: item.orderFormattedAmount,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -121,12 +136,16 @@ class TransactionsPage extends StatelessWidget {
|
||||||
S.of(context).placeholder_transactions,
|
S.of(context).placeholder_transactions,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Theme.of(context).primaryTextTheme!.labelSmall!.decorationColor!),
|
color: Theme.of(context)
|
||||||
|
.primaryTextTheme
|
||||||
|
.labelSmall!
|
||||||
|
.decorationColor!),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}))
|
}))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,14 +3,11 @@ import 'package:cake_wallet/routes.dart';
|
||||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||||
import 'package:cake_wallet/typography.dart';
|
import 'package:cake_wallet/typography.dart';
|
||||||
import 'package:cake_wallet/view_model/ionia/ionia_gift_cards_list_view_model.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/src/widgets/framework.dart';
|
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
|
||||||
|
|
||||||
class IoniaWelcomePage extends BasePage {
|
class IoniaWelcomePage extends BasePage {
|
||||||
IoniaWelcomePage(this._cardsListViewModel);
|
IoniaWelcomePage();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget middle(BuildContext context) {
|
Widget middle(BuildContext context) {
|
||||||
|
@ -25,15 +22,8 @@ class IoniaWelcomePage extends BasePage {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final IoniaGiftCardsListViewModel _cardsListViewModel;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget body(BuildContext context) {
|
Widget body(BuildContext context) {
|
||||||
reaction((_) => _cardsListViewModel.isLoggedIn, (bool state) {
|
|
||||||
if (state) {
|
|
||||||
Navigator.pushReplacementNamed(context, Routes.ioniaManageCardsPage);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(24.0),
|
padding: const EdgeInsets.all(24.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
|
@ -41,7 +31,7 @@ class IoniaWelcomePage extends BasePage {
|
||||||
children: [
|
children: [
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(height: 100),
|
SizedBox(height: 90),
|
||||||
Text(
|
Text(
|
||||||
S.of(context).about_cake_pay,
|
S.of(context).about_cake_pay,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
|
|
@ -17,7 +17,7 @@ import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||||
|
|
||||||
class IoniaManageCardsPage extends BasePage {
|
class IoniaManageCardsPage extends BasePage {
|
||||||
IoniaManageCardsPage(this._cardsListViewModel) {
|
IoniaManageCardsPage(this._cardsListViewModel): searchFocusNode = FocusNode() {
|
||||||
_searchController.addListener(() {
|
_searchController.addListener(() {
|
||||||
if (_searchController.text != _cardsListViewModel.searchString) {
|
if (_searchController.text != _cardsListViewModel.searchString) {
|
||||||
_searchDebounce.run(() {
|
_searchDebounce.run(() {
|
||||||
|
@ -29,6 +29,7 @@ class IoniaManageCardsPage extends BasePage {
|
||||||
_cardsListViewModel.getMerchants();
|
_cardsListViewModel.getMerchants();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
final FocusNode searchFocusNode;
|
||||||
final IoniaGiftCardsListViewModel _cardsListViewModel;
|
final IoniaGiftCardsListViewModel _cardsListViewModel;
|
||||||
|
|
||||||
final _searchDebounce = Debounce(Duration(milliseconds: 500));
|
final _searchDebounce = Debounce(Duration(milliseconds: 500));
|
||||||
|
@ -86,7 +87,14 @@ class IoniaManageCardsPage extends BasePage {
|
||||||
//highlightColor: Colors.transparent,
|
//highlightColor: Colors.transparent,
|
||||||
//splashColor: Colors.transparent,
|
//splashColor: Colors.transparent,
|
||||||
//padding: EdgeInsets.all(0),
|
//padding: EdgeInsets.all(0),
|
||||||
onPressed: () => Navigator.pop(context),
|
onPressed: (){
|
||||||
|
if (searchFocusNode.hasFocus) {
|
||||||
|
searchFocusNode.unfocus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
child: _backButton),
|
child: _backButton),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -149,6 +157,7 @@ class IoniaManageCardsPage extends BasePage {
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _SearchWidget(
|
child: _SearchWidget(
|
||||||
controller: _searchController,
|
controller: _searchController,
|
||||||
|
focusNode: searchFocusNode,
|
||||||
)),
|
)),
|
||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
filterButton
|
filterButton
|
||||||
|
@ -266,9 +275,10 @@ class _SearchWidget extends StatelessWidget {
|
||||||
const _SearchWidget({
|
const _SearchWidget({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.controller,
|
required this.controller,
|
||||||
|
required this.focusNode,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
final TextEditingController controller;
|
final TextEditingController controller;
|
||||||
|
final FocusNode focusNode;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final searchIcon = Padding(
|
final searchIcon = Padding(
|
||||||
|
@ -280,6 +290,7 @@ class _SearchWidget extends StatelessWidget {
|
||||||
);
|
);
|
||||||
|
|
||||||
return TextField(
|
return TextField(
|
||||||
|
focusNode: focusNode,
|
||||||
style: TextStyle(color: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!),
|
style: TextStyle(color: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!),
|
||||||
controller: controller,
|
controller: controller,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
|
|
|
@ -27,8 +27,7 @@ class AnonPayInvoicePage extends BasePage {
|
||||||
AnonPayInvoicePage(
|
AnonPayInvoicePage(
|
||||||
this.anonInvoicePageViewModel,
|
this.anonInvoicePageViewModel,
|
||||||
this.receiveOptionViewModel,
|
this.receiveOptionViewModel,
|
||||||
) : _amountFocusNode = FocusNode() {
|
) : _amountFocusNode = FocusNode() {}
|
||||||
}
|
|
||||||
|
|
||||||
final _nameController = TextEditingController();
|
final _nameController = TextEditingController();
|
||||||
final _emailController = TextEditingController();
|
final _emailController = TextEditingController();
|
||||||
|
@ -53,6 +52,11 @@ class AnonPayInvoicePage extends BasePage {
|
||||||
@override
|
@override
|
||||||
AppBarStyle get appBarStyle => AppBarStyle.transparent;
|
AppBarStyle get appBarStyle => AppBarStyle.transparent;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onClose(BuildContext context) {
|
||||||
|
Navigator.popUntil(context, ModalRoute.withName(Routes.dashboard));
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget middle(BuildContext context) =>
|
Widget middle(BuildContext context) =>
|
||||||
PresentReceiveOptionPicker(receiveOptionViewModel: receiveOptionViewModel);
|
PresentReceiveOptionPicker(receiveOptionViewModel: receiveOptionViewModel);
|
||||||
|
@ -65,11 +69,18 @@ class AnonPayInvoicePage extends BasePage {
|
||||||
anonInvoicePageViewModel.reset();
|
anonInvoicePageViewModel.reset();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Future<bool> _onNavigateBack(BuildContext context) async {
|
||||||
|
onClose(context);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget body(BuildContext context) {
|
Widget body(BuildContext context) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) => _setReactions(context));
|
WidgetsBinding.instance.addPostFrameCallback((_) => _setReactions(context));
|
||||||
|
|
||||||
return KeyboardActions(
|
return WillPopScope(
|
||||||
|
onWillPop: () => _onNavigateBack(context),
|
||||||
|
child: KeyboardActions(
|
||||||
disableScroll: true,
|
disableScroll: true,
|
||||||
config: KeyboardActionsConfig(
|
config: KeyboardActionsConfig(
|
||||||
keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
|
keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
|
||||||
|
@ -89,7 +100,8 @@ class AnonPayInvoicePage extends BasePage {
|
||||||
child: ScrollableWithBottomSection(
|
child: ScrollableWithBottomSection(
|
||||||
contentPadding: EdgeInsets.only(bottom: 24),
|
contentPadding: EdgeInsets.only(bottom: 24),
|
||||||
content: Container(
|
content: Container(
|
||||||
decoration: DeviceInfo.instance.isMobile ? BoxDecoration(
|
decoration: DeviceInfo.instance.isMobile
|
||||||
|
? BoxDecoration(
|
||||||
borderRadius: BorderRadius.only(
|
borderRadius: BorderRadius.only(
|
||||||
bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)),
|
bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)),
|
||||||
gradient: LinearGradient(
|
gradient: LinearGradient(
|
||||||
|
@ -100,7 +112,8 @@ class AnonPayInvoicePage extends BasePage {
|
||||||
begin: Alignment.topLeft,
|
begin: Alignment.topLeft,
|
||||||
end: Alignment.bottomRight,
|
end: Alignment.bottomRight,
|
||||||
),
|
),
|
||||||
) : null,
|
)
|
||||||
|
: null,
|
||||||
child: Observer(builder: (_) {
|
child: Observer(builder: (_) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: EdgeInsets.fromLTRB(24, 120, 24, 0),
|
padding: EdgeInsets.fromLTRB(24, 120, 24, 0),
|
||||||
|
@ -143,8 +156,9 @@ class AnonPayInvoicePage extends BasePage {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
LoadingPrimaryButton(
|
LoadingPrimaryButton(
|
||||||
text:
|
text: isInvoice
|
||||||
isInvoice ? S.of(context).create_invoice : S.of(context).create_donation_link,
|
? S.of(context).create_invoice
|
||||||
|
: S.of(context).create_donation_link,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
anonInvoicePageViewModel.setRequestParams(
|
anonInvoicePageViewModel.setRequestParams(
|
||||||
inputAmount: _amountController.text,
|
inputAmount: _amountController.text,
|
||||||
|
@ -175,6 +189,7 @@ class AnonPayInvoicePage extends BasePage {
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -266,6 +266,8 @@ class WalletRestorePage extends BasePage {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _confirmForm() {
|
void _confirmForm() {
|
||||||
|
// Dismissing all visible keyboard to provide context for navigation
|
||||||
|
FocusManager.instance.primaryFocus?.unfocus();
|
||||||
final formContext = walletRestoreViewModel.mode == WalletRestoreMode.seed
|
final formContext = walletRestoreViewModel.mode == WalletRestoreMode.seed
|
||||||
? walletRestoreFromSeedFormKey.currentContext
|
? walletRestoreFromSeedFormKey.currentContext
|
||||||
: walletRestoreFromKeysFormKey.currentContext;
|
: walletRestoreFromKeysFormKey.currentContext;
|
||||||
|
|
|
@ -145,7 +145,12 @@ class SendPage extends BasePage {
|
||||||
Widget body(BuildContext context) {
|
Widget body(BuildContext context) {
|
||||||
_setEffects(context);
|
_setEffects(context);
|
||||||
|
|
||||||
return Form(
|
return GestureDetector(
|
||||||
|
onLongPress: () => sendViewModel.balanceViewModel.isReversing =
|
||||||
|
!sendViewModel.balanceViewModel.isReversing,
|
||||||
|
onLongPressUp: () => sendViewModel.balanceViewModel.isReversing =
|
||||||
|
!sendViewModel.balanceViewModel.isReversing,
|
||||||
|
child: Form(
|
||||||
key: _formKey,
|
key: _formKey,
|
||||||
child: ScrollableWithBottomSection(
|
child: ScrollableWithBottomSection(
|
||||||
contentPadding: EdgeInsets.only(bottom: 24),
|
contentPadding: EdgeInsets.only(bottom: 24),
|
||||||
|
@ -174,8 +179,8 @@ class SendPage extends BasePage {
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
Padding(
|
Padding(
|
||||||
padding:
|
padding: EdgeInsets.only(
|
||||||
EdgeInsets.only(top: 10, left: 24, right: 24, bottom: 10),
|
top: 10, left: 24, right: 24, bottom: 10),
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 10,
|
height: 10,
|
||||||
child: Observer(
|
child: Observer(
|
||||||
|
@ -192,10 +197,12 @@ class SendPage extends BasePage {
|
||||||
dotWidth: 6.0,
|
dotWidth: 6.0,
|
||||||
dotHeight: 6.0,
|
dotHeight: 6.0,
|
||||||
dotColor: Theme.of(context)
|
dotColor: Theme.of(context)
|
||||||
.primaryTextTheme!.displaySmall!
|
.primaryTextTheme
|
||||||
|
!.displaySmall!
|
||||||
.backgroundColor!,
|
.backgroundColor!,
|
||||||
activeDotColor: Theme.of(context)
|
activeDotColor: Theme.of(context)
|
||||||
.primaryTextTheme!.displayMedium!
|
.primaryTextTheme
|
||||||
|
!.displayMedium!
|
||||||
.backgroundColor!),
|
.backgroundColor!),
|
||||||
)
|
)
|
||||||
: Offstage();
|
: Offstage();
|
||||||
|
@ -218,7 +225,8 @@ class SendPage extends BasePage {
|
||||||
return Row(
|
return Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
AddTemplateButton(
|
AddTemplateButton(
|
||||||
onTap: () => Navigator.of(context).pushNamed(Routes.sendTemplate),
|
onTap: () => Navigator.of(context)
|
||||||
|
.pushNamed(Routes.sendTemplate),
|
||||||
currentTemplatesLength: templates.length,
|
currentTemplatesLength: templates.length,
|
||||||
),
|
),
|
||||||
ListView.builder(
|
ListView.builder(
|
||||||
|
@ -231,35 +239,52 @@ class SendPage extends BasePage {
|
||||||
return TemplateTile(
|
return TemplateTile(
|
||||||
key: UniqueKey(),
|
key: UniqueKey(),
|
||||||
to: template.name,
|
to: template.name,
|
||||||
amount: template.isCurrencySelected ? template.amount : template.amountFiat,
|
amount: template.isCurrencySelected
|
||||||
from: template.isCurrencySelected ? template.cryptoCurrency : template.fiatCurrency,
|
? template.amount
|
||||||
|
: template.amountFiat,
|
||||||
|
from: template.isCurrencySelected
|
||||||
|
? template.cryptoCurrency
|
||||||
|
: template.fiatCurrency,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
final fiatFromTemplate = FiatCurrency.all.singleWhere((element) => element.title == template.fiatCurrency);
|
final fiatFromTemplate = FiatCurrency
|
||||||
|
.all
|
||||||
|
.singleWhere((element) =>
|
||||||
|
element.title ==
|
||||||
|
template.fiatCurrency);
|
||||||
final output = _defineCurrentOutput();
|
final output = _defineCurrentOutput();
|
||||||
output.address = template.address;
|
output.address = template.address;
|
||||||
if(template.isCurrencySelected){
|
if (template.isCurrencySelected) {
|
||||||
output.setCryptoAmount(template.amount);
|
output
|
||||||
}else{
|
.setCryptoAmount(template.amount);
|
||||||
sendViewModel.setFiatCurrency(fiatFromTemplate);
|
} else {
|
||||||
output.setFiatAmount(template.amountFiat);
|
sendViewModel.setFiatCurrency(
|
||||||
|
fiatFromTemplate);
|
||||||
|
output.setFiatAmount(
|
||||||
|
template.amountFiat);
|
||||||
}
|
}
|
||||||
output.resetParsedAddress();
|
output.resetParsedAddress();
|
||||||
await output.fetchParsedAddress(context);
|
await output
|
||||||
|
.fetchParsedAddress(context);
|
||||||
},
|
},
|
||||||
onRemove: () {
|
onRemove: () {
|
||||||
showPopUp<void>(
|
showPopUp<void>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (dialogContext) {
|
builder: (dialogContext) {
|
||||||
return AlertWithTwoActions(
|
return AlertWithTwoActions(
|
||||||
alertTitle: S.of(context).template,
|
alertTitle:
|
||||||
|
S.of(context).template,
|
||||||
alertContent: S
|
alertContent: S
|
||||||
.of(context)
|
.of(context)
|
||||||
.confirm_delete_template,
|
.confirm_delete_template,
|
||||||
rightButtonText: S.of(context).delete,
|
rightButtonText:
|
||||||
leftButtonText: S.of(context).cancel,
|
S.of(context).delete,
|
||||||
|
leftButtonText:
|
||||||
|
S.of(context).cancel,
|
||||||
actionRightButton: () {
|
actionRightButton: () {
|
||||||
Navigator.of(dialogContext).pop();
|
Navigator.of(dialogContext)
|
||||||
sendViewModel.sendTemplateViewModel
|
.pop();
|
||||||
|
sendViewModel
|
||||||
|
.sendTemplateViewModel
|
||||||
.removeTemplate(
|
.removeTemplate(
|
||||||
template: template);
|
template: template);
|
||||||
},
|
},
|
||||||
|
@ -286,19 +311,19 @@ class SendPage extends BasePage {
|
||||||
bottomSection: Column(
|
bottomSection: Column(
|
||||||
children: [
|
children: [
|
||||||
if (sendViewModel.hasCurrecyChanger)
|
if (sendViewModel.hasCurrecyChanger)
|
||||||
Observer(builder: (_) =>
|
Observer(
|
||||||
Padding(
|
builder: (_) => Padding(
|
||||||
padding: EdgeInsets.only(bottom: 12),
|
padding: EdgeInsets.only(bottom: 12),
|
||||||
child: PrimaryButton(
|
child: PrimaryButton(
|
||||||
onPressed: () => presentCurrencyPicker(context),
|
onPressed: () => presentCurrencyPicker(context),
|
||||||
text: 'Change your asset (${sendViewModel.selectedCryptoCurrency})',
|
text:
|
||||||
|
'Change your asset (${sendViewModel.selectedCryptoCurrency})',
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
textColor: Theme.of(context)
|
textColor: Theme.of(context)
|
||||||
.accentTextTheme!.displaySmall!
|
.accentTextTheme
|
||||||
|
!.displaySmall!
|
||||||
.decorationColor!,
|
.decorationColor!,
|
||||||
)
|
))),
|
||||||
)
|
|
||||||
),
|
|
||||||
if (sendViewModel.hasMultiRecipient)
|
if (sendViewModel.hasMultiRecipient)
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(bottom: 12),
|
padding: EdgeInsets.only(bottom: 12),
|
||||||
|
@ -306,24 +331,28 @@ class SendPage extends BasePage {
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
sendViewModel.addOutput();
|
sendViewModel.addOutput();
|
||||||
Future.delayed(const Duration(milliseconds: 250), () {
|
Future.delayed(const Duration(milliseconds: 250), () {
|
||||||
controller.jumpToPage(sendViewModel.outputs.length - 1);
|
controller
|
||||||
|
.jumpToPage(sendViewModel.outputs.length - 1);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
text: S.of(context).add_receiver,
|
text: S.of(context).add_receiver,
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
textColor: Theme.of(context)
|
textColor: Theme.of(context)
|
||||||
.accentTextTheme!.displaySmall!
|
.accentTextTheme
|
||||||
|
!.displaySmall!
|
||||||
.decorationColor!,
|
.decorationColor!,
|
||||||
isDottedBorder: true,
|
isDottedBorder: true,
|
||||||
borderColor: Theme.of(context)
|
borderColor: Theme.of(context)
|
||||||
.primaryTextTheme!.displaySmall!
|
.primaryTextTheme
|
||||||
|
!.displaySmall!
|
||||||
.decorationColor!,
|
.decorationColor!,
|
||||||
)),
|
)),
|
||||||
Observer(
|
Observer(
|
||||||
builder: (_) {
|
builder: (_) {
|
||||||
return LoadingPrimaryButton(
|
return LoadingPrimaryButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (_formKey.currentState != null && !_formKey.currentState!.validate()) {
|
if (_formKey.currentState != null &&
|
||||||
|
!_formKey.currentState!.validate()) {
|
||||||
if (sendViewModel.outputs.length > 1) {
|
if (sendViewModel.outputs.length > 1) {
|
||||||
showErrorValidationAlert(context);
|
showErrorValidationAlert(context);
|
||||||
}
|
}
|
||||||
|
@ -333,7 +362,8 @@ class SendPage extends BasePage {
|
||||||
|
|
||||||
final notValidItems = sendViewModel.outputs
|
final notValidItems = sendViewModel.outputs
|
||||||
.where((item) =>
|
.where((item) =>
|
||||||
item.address.isEmpty || item.cryptoAmount.isEmpty)
|
item.address.isEmpty ||
|
||||||
|
item.cryptoAmount.isEmpty)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
if (notValidItems.isNotEmpty ?? false) {
|
if (notValidItems.isNotEmpty ?? false) {
|
||||||
|
@ -342,10 +372,10 @@ class SendPage extends BasePage {
|
||||||
}
|
}
|
||||||
|
|
||||||
await sendViewModel.createTransaction();
|
await sendViewModel.createTransaction();
|
||||||
|
|
||||||
},
|
},
|
||||||
text: S.of(context).send,
|
text: S.of(context).send,
|
||||||
color: Theme.of(context).accentTextTheme!.bodyLarge!.color!,
|
color:
|
||||||
|
Theme.of(context).accentTextTheme!.bodyLarge!.color!,
|
||||||
textColor: Colors.white,
|
textColor: Colors.white,
|
||||||
isLoading: sendViewModel.state is IsExecutingState ||
|
isLoading: sendViewModel.state is IsExecutingState ||
|
||||||
sendViewModel.state is TransactionCommitting,
|
sendViewModel.state is TransactionCommitting,
|
||||||
|
@ -355,6 +385,7 @@ class SendPage extends BasePage {
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,10 +420,12 @@ class SendPage extends BasePage {
|
||||||
amount: S.of(context).send_amount,
|
amount: S.of(context).send_amount,
|
||||||
amountValue:
|
amountValue:
|
||||||
sendViewModel.pendingTransaction!.amountFormatted,
|
sendViewModel.pendingTransaction!.amountFormatted,
|
||||||
fiatAmountValue: sendViewModel.pendingTransactionFiatAmountFormatted,
|
fiatAmountValue:
|
||||||
|
sendViewModel.pendingTransactionFiatAmountFormatted,
|
||||||
fee: S.of(context).send_fee,
|
fee: S.of(context).send_fee,
|
||||||
feeValue: sendViewModel.pendingTransaction!.feeFormatted,
|
feeValue: sendViewModel.pendingTransaction!.feeFormatted,
|
||||||
feeFiatAmount: sendViewModel.pendingTransactionFeeFiatAmountFormatted,
|
feeFiatAmount: sendViewModel
|
||||||
|
.pendingTransactionFeeFiatAmountFormatted,
|
||||||
outputs: sendViewModel.outputs,
|
outputs: sendViewModel.outputs,
|
||||||
rightButtonText: S.of(context).ok,
|
rightButtonText: S.of(context).ok,
|
||||||
leftButtonText: S.of(context).cancel,
|
leftButtonText: S.of(context).cancel,
|
||||||
|
@ -413,7 +446,8 @@ class SendPage extends BasePage {
|
||||||
return AlertWithOneAction(
|
return AlertWithOneAction(
|
||||||
alertTitle: '',
|
alertTitle: '',
|
||||||
alertContent: S.of(context).send_success(
|
alertContent: S.of(context).send_success(
|
||||||
sendViewModel.selectedCryptoCurrency.toString()),
|
sendViewModel.selectedCryptoCurrency
|
||||||
|
.toString()),
|
||||||
buttonText: S.of(context).ok,
|
buttonText: S.of(context).ok,
|
||||||
buttonAction: () {
|
buttonAction: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
@ -466,10 +500,12 @@ class SendPage extends BasePage {
|
||||||
builder: (_) => Picker(
|
builder: (_) => Picker(
|
||||||
items: sendViewModel.currencies,
|
items: sendViewModel.currencies,
|
||||||
displayItem: (Object item) => item.toString(),
|
displayItem: (Object item) => item.toString(),
|
||||||
selectedAtIndex: sendViewModel.currencies.indexOf(sendViewModel.selectedCryptoCurrency),
|
selectedAtIndex: sendViewModel.currencies
|
||||||
|
.indexOf(sendViewModel.selectedCryptoCurrency),
|
||||||
title: S.of(context).please_select,
|
title: S.of(context).please_select,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
onItemSelected: (CryptoCurrency cur) => sendViewModel.selectedCryptoCurrency = cur,
|
onItemSelected: (CryptoCurrency cur) =>
|
||||||
|
sendViewModel.selectedCryptoCurrency = cur,
|
||||||
),
|
),
|
||||||
context: context);
|
context: context);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,26 +43,24 @@ class TotpAuthCodePageState extends State<TotpAuthCodePage> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
if(widget.totpArguments.onTotpAuthenticationFinished != null) {
|
||||||
_reaction ??= reaction((_) => widget.setup2FAViewModel.state, (ExecutionState state) {
|
_reaction ??= reaction((_) => widget.setup2FAViewModel.state, (ExecutionState state) {
|
||||||
if (state is ExecutedSuccessfullyState) {
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
if (state is ExecutedSuccessfullyState) {
|
||||||
widget.totpArguments.onTotpAuthenticationFinished!(true, this);
|
widget.totpArguments.onTotpAuthenticationFinished!(true, this);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state is FailureState) {
|
if (state is FailureState) {
|
||||||
print(state.error);
|
print(state.error);
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
widget.totpArguments.onTotpAuthenticationFinished!(false, this);
|
widget.totpArguments.onTotpAuthenticationFinished!(false, this);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state is AuthenticationBanned) {
|
if (state is AuthenticationBanned) {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
widget.totpArguments.onTotpAuthenticationFinished!(false, this);
|
widget.totpArguments.onTotpAuthenticationFinished!(false, this);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,12 +150,26 @@ class WalletListBodyState extends State<WalletListBody> {
|
||||||
|
|
||||||
return wallet.isCurrent
|
return wallet.isCurrent
|
||||||
? row
|
? row
|
||||||
: Slidable(
|
: Row(children: [
|
||||||
key: Key('${wallet.key}'),
|
Expanded(child: row),
|
||||||
startActionPane: _actionPane(wallet),
|
GestureDetector(
|
||||||
endActionPane: _actionPane(wallet),
|
onTap: () => _removeWallet(wallet),
|
||||||
child: row,
|
child: Container(
|
||||||
);
|
height: 40,
|
||||||
|
width: 44,
|
||||||
|
padding: EdgeInsets.only(right: 20),
|
||||||
|
child: Center(
|
||||||
|
child: Image.asset('assets/images/trash.png',
|
||||||
|
height: 16,
|
||||||
|
width: 16,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.primaryTextTheme
|
||||||
|
.titleLarge!
|
||||||
|
.color),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
]);
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -280,18 +294,4 @@ class WalletListBodyState extends State<WalletListBody> {
|
||||||
_progressBar = null;
|
_progressBar = null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ActionPane _actionPane(WalletListItem wallet) => ActionPane(
|
|
||||||
motion: const ScrollMotion(),
|
|
||||||
extentRatio: 0.3,
|
|
||||||
children: [
|
|
||||||
SlidableAction(
|
|
||||||
onPressed: (_) => _removeWallet(wallet),
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
foregroundColor: Colors.white,
|
|
||||||
icon: CupertinoIcons.delete,
|
|
||||||
label: S.of(context).delete,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
17
lib/view_model/dashboard/market_place_view_model.dart
Normal file
17
lib/view_model/dashboard/market_place_view_model.dart
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import 'package:cake_wallet/ionia/ionia_service.dart';
|
||||||
|
import 'package:mobx/mobx.dart';
|
||||||
|
|
||||||
|
part 'market_place_view_model.g.dart';
|
||||||
|
|
||||||
|
class MarketPlaceViewModel = MarketPlaceViewModelBase with _$MarketPlaceViewModel;
|
||||||
|
|
||||||
|
abstract class MarketPlaceViewModelBase with Store {
|
||||||
|
final IoniaService _ioniaService;
|
||||||
|
|
||||||
|
MarketPlaceViewModelBase(this._ioniaService);
|
||||||
|
|
||||||
|
|
||||||
|
Future<bool> isIoniaUserAuthenticated() async {
|
||||||
|
return await _ioniaService.isLogined();
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,7 +13,6 @@ import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart';
|
||||||
import 'package:cw_core/keyable.dart';
|
import 'package:cw_core/keyable.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
import 'package:cw_core/wallet_type.dart';
|
||||||
|
|
||||||
|
|
||||||
class TransactionListItem extends ActionListItem with Keyable {
|
class TransactionListItem extends ActionListItem with Keyable {
|
||||||
TransactionListItem(
|
TransactionListItem(
|
||||||
{required this.transaction,
|
{required this.transaction,
|
||||||
|
@ -28,7 +27,7 @@ class TransactionListItem extends ActionListItem with Keyable {
|
||||||
|
|
||||||
FiatCurrency get fiatCurrency => settingsStore.fiatCurrency;
|
FiatCurrency get fiatCurrency => settingsStore.fiatCurrency;
|
||||||
|
|
||||||
BalanceDisplayMode get displayMode => settingsStore.balanceDisplayMode;
|
BalanceDisplayMode get displayMode => balanceViewModel.displayMode;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
dynamic get keyIndex => transaction.id;
|
dynamic get keyIndex => transaction.id;
|
||||||
|
|
|
@ -114,6 +114,10 @@ abstract class ExchangeTradeViewModelBase with Store {
|
||||||
updatedTrade.createdAt = trade.createdAt;
|
updatedTrade.createdAt = trade.createdAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (updatedTrade.amount.isEmpty) {
|
||||||
|
updatedTrade.amount = trade.amount;
|
||||||
|
}
|
||||||
|
|
||||||
trade = updatedTrade;
|
trade = updatedTrade;
|
||||||
|
|
||||||
_updateItems();
|
_updateItems();
|
||||||
|
@ -123,7 +127,8 @@ abstract class ExchangeTradeViewModelBase with Store {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _updateItems() {
|
void _updateItems() {
|
||||||
final tagFrom = tradesStore.trade!.from.tag != null ? '${tradesStore.trade!.from.tag}' + ' ' : '';
|
final tagFrom =
|
||||||
|
tradesStore.trade!.from.tag != null ? '${tradesStore.trade!.from.tag}' + ' ' : '';
|
||||||
final tagTo = tradesStore.trade!.to.tag != null ? '${tradesStore.trade!.to.tag}' + ' ' : '';
|
final tagTo = tradesStore.trade!.to.tag != null ? '${tradesStore.trade!.to.tag}' + ' ' : '';
|
||||||
items.clear();
|
items.clear();
|
||||||
items.add(ExchangeTradeItem(
|
items.add(ExchangeTradeItem(
|
||||||
|
|
|
@ -443,7 +443,9 @@ abstract class ExchangeViewModelBase with Store {
|
||||||
request = SideShiftRequest(
|
request = SideShiftRequest(
|
||||||
depositMethod: depositCurrency,
|
depositMethod: depositCurrency,
|
||||||
settleMethod: receiveCurrency,
|
settleMethod: receiveCurrency,
|
||||||
depositAmount: depositAmount.replaceAll(',', '.'),
|
depositAmount: isFixedRateMode
|
||||||
|
? receiveAmount.replaceAll(',', '.')
|
||||||
|
: depositAmount.replaceAll(',', '.'),
|
||||||
settleAddress: receiveAddress,
|
settleAddress: receiveAddress,
|
||||||
refundAddress: depositAddress,
|
refundAddress: depositAddress,
|
||||||
);
|
);
|
||||||
|
|
|
@ -16,12 +16,10 @@ abstract class IoniaGiftCardsListViewModelBase with Store {
|
||||||
ioniaCategories = IoniaCategory.allCategories,
|
ioniaCategories = IoniaCategory.allCategories,
|
||||||
selectedIndices = ObservableList<IoniaCategory>.of([IoniaCategory.all]),
|
selectedIndices = ObservableList<IoniaCategory>.of([IoniaCategory.all]),
|
||||||
scrollOffsetFromTop = 0.0,
|
scrollOffsetFromTop = 0.0,
|
||||||
isLoggedIn = false,
|
|
||||||
merchantState = InitialIoniaMerchantLoadingState(),
|
merchantState = InitialIoniaMerchantLoadingState(),
|
||||||
createCardState = IoniaCreateCardState(),
|
createCardState = IoniaCreateCardState(),
|
||||||
searchString = '',
|
searchString = '',
|
||||||
ioniaMerchantList = <IoniaMerchant>[] {
|
ioniaMerchantList = <IoniaMerchant>[] {
|
||||||
_getAuthStatus().then((value) => isLoggedIn = value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final IoniaService ioniaService;
|
final IoniaService ioniaService;
|
||||||
|
@ -45,24 +43,17 @@ abstract class IoniaGiftCardsListViewModelBase with Store {
|
||||||
@observable
|
@observable
|
||||||
List<IoniaMerchant> ioniaMerchants;
|
List<IoniaMerchant> ioniaMerchants;
|
||||||
|
|
||||||
@observable
|
|
||||||
bool isLoggedIn;
|
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
List<IoniaCategory> ioniaCategories;
|
List<IoniaCategory> ioniaCategories;
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
ObservableList<IoniaCategory> selectedIndices;
|
ObservableList<IoniaCategory> selectedIndices;
|
||||||
|
|
||||||
Future<bool> _getAuthStatus() async {
|
|
||||||
return await ioniaService.isLogined();
|
|
||||||
}
|
|
||||||
|
|
||||||
@action
|
@action
|
||||||
Future<void> createCard() async {
|
Future<void> createCard() async {
|
||||||
try {
|
try {
|
||||||
createCardState = IoniaCreateCardLoading();
|
createCardState = IoniaCreateCardLoading();
|
||||||
final card = await ioniaService.createCard();
|
await ioniaService.createCard();
|
||||||
createCardState = IoniaCreateCardSuccess();
|
createCardState = IoniaCreateCardSuccess();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
createCardState = IoniaCreateCardFailure(error: e.toString());
|
createCardState = IoniaCreateCardFailure(error: e.toString());
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
import FlutterMacOS
|
import FlutterMacOS
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
import connectivity_macos
|
import connectivity_plus_macos
|
||||||
import cw_monero
|
import cw_monero
|
||||||
import device_info_plus
|
import device_info_plus
|
||||||
import devicelocale
|
import devicelocale
|
||||||
|
|
|
@ -56,8 +56,8 @@ dependencies:
|
||||||
# password: ^1.0.0
|
# password: ^1.0.0
|
||||||
basic_utils: ^4.3.0
|
basic_utils: ^4.3.0
|
||||||
get_it: ^7.2.0
|
get_it: ^7.2.0
|
||||||
connectivity: ^3.0.3
|
# connectivity: ^3.0.3
|
||||||
# connectivity_plus: ^2.3.5
|
connectivity_plus: ^2.3.5
|
||||||
keyboard_actions: ^4.0.1
|
keyboard_actions: ^4.0.1
|
||||||
another_flushbar: ^1.12.29
|
another_flushbar: ^1.12.29
|
||||||
archive: ^3.3.0
|
archive: ^3.3.0
|
||||||
|
|
|
@ -685,14 +685,14 @@
|
||||||
"arrive_in_this_address" : "${currency} ${tag}arrivera à cette adresse",
|
"arrive_in_this_address" : "${currency} ${tag}arrivera à cette adresse",
|
||||||
"do_not_send": "Ne pas envoyer",
|
"do_not_send": "Ne pas envoyer",
|
||||||
"error_dialog_content": "Oups, nous avons rencontré une erreur.\n\nMerci d'envoyer le rapport d'erreur à notre équipe d'assistance afin de nous permettre d'améliorer l'application.",
|
"error_dialog_content": "Oups, nous avons rencontré une erreur.\n\nMerci d'envoyer le rapport d'erreur à notre équipe d'assistance afin de nous permettre d'améliorer l'application.",
|
||||||
"scan_qr_code": "Scannez le code QR",
|
"scan_qr_code": "Scannez le QR code",
|
||||||
"cold_or_recover_wallet": "Ajoutez un cold wallet ou récupérez un paper wallet",
|
"cold_or_recover_wallet": "Ajoutez un portefeuille froid (cold wallet) ou récupérez un portefeuille papier (paper wallet)",
|
||||||
"please_wait": "S'il vous plaît, attendez",
|
"please_wait": "Merci de patienter",
|
||||||
"sweeping_wallet": "Portefeuille de balayage",
|
"sweeping_wallet": "Portefeuille (wallet) de consolidation",
|
||||||
"sweeping_wallet_alert": "Cela ne devrait pas prendre longtemps. NE QUITTEZ PAS CET ÉCRAN OU LES FONDS BALAYÉS POURRAIENT ÊTRE PERDUS",
|
"sweeping_wallet_alert": "Cette opération ne devrait pas prendre longtemps. NE QUITTEZ PAS CET ÉCRAN OU LES FONDS CONSOLIDÉS POURRAIENT ÊTRE PERDUS",
|
||||||
"decimal_places_error": "Trop de décimales",
|
"decimal_places_error": "Trop de décimales",
|
||||||
"edit_node": "Modifier le nœud",
|
"edit_node": "Modifier le nœud",
|
||||||
"frozen_balance": "Équilibre gelé",
|
"frozen_balance": "Solde gelé",
|
||||||
"invoice_details": "Détails de la facture",
|
"invoice_details": "Détails de la facture",
|
||||||
"donation_link_details": "Détails du lien de don",
|
"donation_link_details": "Détails du lien de don",
|
||||||
"anonpay_description": "Générez ${type}. Le destinataire peut ${method} avec n'importe quelle crypto-monnaie prise en charge, et vous recevrez des fonds dans ce portefeuille (wallet).",
|
"anonpay_description": "Générez ${type}. Le destinataire peut ${method} avec n'importe quelle crypto-monnaie prise en charge, et vous recevrez des fonds dans ce portefeuille (wallet).",
|
||||||
|
@ -709,22 +709,22 @@
|
||||||
"error_text_input_above_maximum_limit" : "Le montant est supérieur au maximum",
|
"error_text_input_above_maximum_limit" : "Le montant est supérieur au maximum",
|
||||||
"show_market_place" :"Afficher la place de marché",
|
"show_market_place" :"Afficher la place de marché",
|
||||||
"prevent_screenshots": "Empêcher les captures d'écran et l'enregistrement d'écran",
|
"prevent_screenshots": "Empêcher les captures d'écran et l'enregistrement d'écran",
|
||||||
"modify_2fa": "Modifier le gâteau 2FA",
|
"modify_2fa": "Modifier les paramètres Cake 2FA",
|
||||||
"disable_cake_2fa": "Désactiver le gâteau 2FA",
|
"disable_cake_2fa": "Désactiver Cake 2FA",
|
||||||
"question_to_disable_2fa":"Êtes-vous sûr de vouloir désactiver Cake 2FA ? Un code 2FA ne sera plus nécessaire pour accéder au portefeuille et à certaines fonctions.",
|
"question_to_disable_2fa":"Êtes-vous sûr de vouloir désactiver Cake 2FA ? Un code 2FA ne sera plus nécessaire pour accéder au portefeuille (wallet) et à certaines fonctions.",
|
||||||
"disable": "Désactiver",
|
"disable": "Désactiver",
|
||||||
"setup_2fa": "Gâteau d'installation 2FA",
|
"setup_2fa": "Paramétrer Cake 2FA",
|
||||||
"verify_with_2fa": "Vérifier avec Cake 2FA",
|
"verify_with_2fa": "Vérifier avec Cake 2FA",
|
||||||
"totp_code": "Code TOTP",
|
"totp_code": "Code TOTP",
|
||||||
"please_fill_totp": "Veuillez renseigner le code à 8 chiffres présent sur votre autre appareil",
|
"please_fill_totp": "Veuillez renseigner le code à 8 chiffres affiché sur votre autre appareil",
|
||||||
"totp_2fa_success": "Succès! Cake 2FA activé pour ce portefeuille. N'oubliez pas de sauvegarder votre graine mnémonique au cas où vous perdriez l'accès au portefeuille.",
|
"totp_2fa_success": "Succès! Cake 2FA est activé pour ce portefeuille. N'oubliez pas de sauvegarder votre phrase secrète (seed) au cas où vous perdriez l'accès au portefeuille (wallet).",
|
||||||
"totp_verification_success" :"Vérification réussie !",
|
"totp_verification_success" :"Vérification réussie !",
|
||||||
"totp_2fa_failure": "Code incorrect. Veuillez essayer un code différent ou générer une nouvelle clé secrète. Utilisez une application 2FA compatible qui prend en charge les codes à 8 chiffres et SHA512.",
|
"totp_2fa_failure": "Code incorrect. Veuillez essayer un code différent ou générer un nouveau secret TOTP. Utilisez une application 2FA compatible qui prend en charge les codes à 8 chiffres et SHA512.",
|
||||||
"enter_totp_code": "Veuillez entrer le code TOTP.",
|
"enter_totp_code": "Veuillez entrer le code TOTP.",
|
||||||
"add_secret_code":"Ajouter ce code secret à un autre appareil",
|
"add_secret_code":"Configurer un autre appareil à l'aide de ce secret TOTP",
|
||||||
"totp_secret_code":"Code secret TOTP",
|
"totp_secret_code":"Secret TOTP",
|
||||||
"important_note": "Note importante",
|
"important_note": "Note importante",
|
||||||
"setup_2fa_text": "Cake 2FA n'est PAS aussi sûr que le stockage à froid. 2FA protège contre les types d'attaques de base, comme votre ami fournissant votre empreinte digitale pendant que vous dormez.\n\n Cake 2FA ne protège PAS contre un appareil compromis par un attaquant sophistiqué.\n\n Si vous perdez l'accès à vos codes 2FA , VOUS PERDREZ L'ACCÈS À CE PORTEFEUILLE. Vous devrez restaurer votre portefeuille à partir de graines mnémotechniques. VOUS DEVEZ DONC SAUVEGARDER VOS SEMENCES MNEMONIQUES ! De plus, quelqu'un ayant accès à vos graines mnémoniques pourra voler vos fonds, en contournant Cake 2FA.\n\n Le personnel d'assistance de Cake ne pourra pas vous aider si vous perdez l'accès à vos graines mnémoniques, puisque Cake est un portefeuille non dépositaire.",
|
"setup_2fa_text": "Cake 2FA (Authentification à 2 Facteurs) n'est PAS aussi sûr que le stockage à froid. Cake 2FA protège contre les attaques basiques, comme un ami fournissant votre empreinte digitale pendant que vous dormez.\n\n Cake 2FA ne protège PAS contre un appareil compromis par un attaquant sophistiqué.\n\n Si vous perdez l'accès à vos codes 2FA , VOUS PERDREZ L'ACCÈS À CE PORTEFEUILLE (WALLET). Vous devrez restaurer votre portefeuille à partir de sa phrase secrète (seed). VOUS DEVEZ DONC SAUVEGARDER VOTRE PHRASE SECRÈTE ! De plus, quelqu'un ayant accès à votre phrase secrète pourra voler vos fonds, en contournant Cake 2FA.\n\n Le personnel d'assistance de Cake ne pourra pas vous aider si vous perdez l'accès à votre phrase secrète, puisque Cake est un portefeuille non dépositaire (non custodial).",
|
||||||
"setup_totp_recommended": "Configurer TOTP (recommandé)",
|
"setup_totp_recommended": "Configurer TOTP (recommandé)",
|
||||||
"disable_buy": "Désactiver l'action d'achat",
|
"disable_buy": "Désactiver l'action d'achat",
|
||||||
"disable_sell": "Désactiver l'action de vente"
|
"disable_sell": "Désactiver l'action de vente"
|
||||||
|
|
|
@ -20,7 +20,6 @@ class SecretKey {
|
||||||
SecretKey('moonPayApiKey', () => ''),
|
SecretKey('moonPayApiKey', () => ''),
|
||||||
SecretKey('moonPaySecretKey', () => ''),
|
SecretKey('moonPaySecretKey', () => ''),
|
||||||
SecretKey('sideShiftAffiliateId', () => ''),
|
SecretKey('sideShiftAffiliateId', () => ''),
|
||||||
SecretKey('sideShiftApiKey', () => ''),
|
|
||||||
SecretKey('simpleSwapApiKey', () => ''),
|
SecretKey('simpleSwapApiKey', () => ''),
|
||||||
SecretKey('simpleSwapApiKeyDesktop', () => ''),
|
SecretKey('simpleSwapApiKeyDesktop', () => ''),
|
||||||
SecretKey('anypayToken', () => ''),
|
SecretKey('anypayToken', () => ''),
|
||||||
|
|
Loading…
Reference in a new issue