Old state (#999)

* Fix Bitcoin transactions not showing (#978)

* handle multiple responses coming in a single event

* Add timeout for getting transaction info, to allow other transactions to be returned in case of any failure or network issue

* Handle other cases of receiving multiple messages in the same response

* Fix shib and storj (#997)

* Merge main branch

* Add missing files

---------

Co-authored-by: Justin Ehrenhofer <justin.ehrenhofer@gmail.com>
This commit is contained in:
Omar Hatem 2023-07-14 01:48:47 +03:00 committed by GitHub
parent f51f0a1d1f
commit 62007975e1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 399 additions and 339 deletions

BIN
assets/images/shib_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

View file

@ -13,10 +13,8 @@ import 'package:cw_core/wallet_type.dart';
import 'package:hive/hive.dart';
import 'package:collection/collection.dart';
class BitcoinWalletService extends WalletService<
BitcoinNewWalletCredentials,
BitcoinRestoreWalletFromSeedCredentials,
BitcoinRestoreWalletFromWIFCredentials> {
class BitcoinWalletService extends WalletService<BitcoinNewWalletCredentials,
BitcoinRestoreWalletFromSeedCredentials, BitcoinRestoreWalletFromWIFCredentials> {
BitcoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource, this.isDirect);
final Box<WalletInfo> walletInfoSource;
@ -45,10 +43,12 @@ class BitcoinWalletService extends WalletService<
@override
Future<BitcoinWallet> openWallet(String name, String password) async {
final walletInfo = walletInfoSource.values.firstWhereOrNull(
(info) => info.id == WalletBase.idFor(name, getType()))!;
final walletInfo = walletInfoSource.values
.firstWhereOrNull((info) => info.id == WalletBase.idFor(name, getType()))!;
final wallet = await BitcoinWalletBase.open(
password: password, name: name, walletInfo: walletInfo,
password: password,
name: name,
walletInfo: walletInfo,
unspentCoinsInfo: unspentCoinsInfoSource,
encryptionFileUtils: encryptionFileUtilsFor(isDirect));
await wallet.init();
@ -57,22 +57,23 @@ class BitcoinWalletService extends WalletService<
@override
Future<void> remove(String wallet) async {
File(await pathForWalletDir(name: wallet, type: getType()))
.delete(recursive: true);
final walletInfo = walletInfoSource.values.firstWhereOrNull(
(info) => info.id == WalletBase.idFor(wallet, getType()))!;
File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true);
final walletInfo = walletInfoSource.values
.firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!;
await walletInfoSource.delete(walletInfo.key);
}
@override
Future<void> rename(String currentName, String password, String newName) async {
final currentWalletInfo = walletInfoSource.values.firstWhereOrNull(
(info) => info.id == WalletBase.idFor(currentName, getType()))!;
final currentWalletInfo = walletInfoSource.values
.firstWhereOrNull((info) => info.id == WalletBase.idFor(currentName, getType()))!;
final currentWallet = await BitcoinWalletBase.open(
password: password,
name: currentName,
walletInfo: currentWalletInfo,
unspentCoinsInfo: unspentCoinsInfoSource);
password: password,
name: currentName,
walletInfo: currentWalletInfo,
unspentCoinsInfo: unspentCoinsInfoSource,
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
);
await currentWallet.renameWalletFiles(newName);
@ -84,13 +85,11 @@ class BitcoinWalletService extends WalletService<
}
@override
Future<BitcoinWallet> restoreFromKeys(
BitcoinRestoreWalletFromWIFCredentials credentials) async =>
Future<BitcoinWallet> restoreFromKeys(BitcoinRestoreWalletFromWIFCredentials credentials) async =>
throw UnimplementedError();
@override
Future<BitcoinWallet> restoreFromSeed(
BitcoinRestoreWalletFromSeedCredentials credentials) async {
Future<BitcoinWallet> restoreFromSeed(BitcoinRestoreWalletFromSeedCredentials credentials) async {
if (!validateMnemonic(credentials.mnemonic)) {
throw BitcoinMnemonicIsIncorrectException();
}

View file

@ -66,54 +66,68 @@ class ElectrumClient {
socket!.listen((Uint8List event) {
try {
final msg = utf8.decode(event.toList());
final response =
json.decode(msg) as Map<String, dynamic>;
_handleResponse(response);
} on FormatException catch (e) {
final msg = e.message.toLowerCase();
if (e.source is String) {
unterminatedString += e.source as String;
}
if (msg.contains("not a subtype of type")) {
unterminatedString += e.source as String;
return;
}
if (isJSONStringCorrect(unterminatedString)) {
final response =
json.decode(unterminatedString) as Map<String, dynamic>;
_handleResponse(response);
unterminatedString = '';
}
} on TypeError catch (e) {
if (!e.toString().contains('Map<String, Object>') && !e.toString().contains('Map<String, dynamic>')) {
return;
}
final source = utf8.decode(event.toList());
unterminatedString += source;
if (isJSONStringCorrect(unterminatedString)) {
final response =
json.decode(unterminatedString) as Map<String, dynamic>;
_handleResponse(response);
// unterminatedString = null;
unterminatedString = '';
final messagesList = msg.split("\n");
for (var message in messagesList) {
if (message.isEmpty) {
continue;
}
_parseResponse(message);
}
} catch (e) {
print(e.toString());
}
}, onError: (Object error) {
print(error.toString());
unterminatedString = '';
_setIsConnected(false);
}, onDone: () {
unterminatedString = '';
_setIsConnected(false);
});
keepAlive();
}
void _parseResponse(String message) {
try {
final response = json.decode(message) as Map<String, dynamic>;
_handleResponse(response);
} on FormatException catch (e) {
final msg = e.message.toLowerCase();
if (e.source is String) {
unterminatedString += e.source as String;
}
if (msg.contains("not a subtype of type")) {
unterminatedString += e.source as String;
return;
}
if (isJSONStringCorrect(unterminatedString)) {
final response =
json.decode(unterminatedString) as Map<String, dynamic>;
_handleResponse(response);
unterminatedString = '';
}
} on TypeError catch (e) {
if (!e.toString().contains('Map<String, Object>') && !e.toString().contains('Map<String, dynamic>')) {
return;
}
unterminatedString += message;
if (isJSONStringCorrect(unterminatedString)) {
final response =
json.decode(unterminatedString) as Map<String, dynamic>;
_handleResponse(response);
// unterminatedString = null;
unterminatedString = '';
}
} catch (e) {
print(e.toString());
}
}
void keepAlive() {
_aliveTimer?.cancel();
_aliveTimer = Timer.periodic(aliveTimerDuration, (_) async => ping());
@ -217,7 +231,7 @@ class ElectrumClient {
Future<Map<String, dynamic>> getTransactionRaw(
{required String hash}) async =>
call(method: 'blockchain.transaction.get', params: [hash, true])
callWithTimeout(method: 'blockchain.transaction.get', params: [hash, true], timeout: 10000)
.then((dynamic result) {
if (result is Map<String, dynamic>) {
return result;
@ -228,7 +242,7 @@ class ElectrumClient {
Future<String> getTransactionHex(
{required String hash}) async =>
call(method: 'blockchain.transaction.get', params: [hash, false])
callWithTimeout(method: 'blockchain.transaction.get', params: [hash, false], timeout: 10000)
.then((dynamic result) {
if (result is String) {
return result;

View file

@ -86,5 +86,4 @@ abstract class ElectrumTransactionHistoryBase
void _update(ElectrumTransactionInfo transaction) =>
transactions[transaction.id] = transaction;
}

View file

@ -13,10 +13,8 @@ import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:collection/collection.dart';
class LitecoinWalletService extends WalletService<
BitcoinNewWalletCredentials,
BitcoinRestoreWalletFromSeedCredentials,
BitcoinRestoreWalletFromWIFCredentials> {
class LitecoinWalletService extends WalletService<BitcoinNewWalletCredentials,
BitcoinRestoreWalletFromSeedCredentials, BitcoinRestoreWalletFromWIFCredentials> {
LitecoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource, this.isDirect);
final Box<WalletInfo> walletInfoSource;
@ -46,10 +44,12 @@ class LitecoinWalletService extends WalletService<
@override
Future<LitecoinWallet> openWallet(String name, String password) async {
final walletInfo = walletInfoSource.values.firstWhereOrNull(
(info) => info.id == WalletBase.idFor(name, getType()))!;
final walletInfo = walletInfoSource.values
.firstWhereOrNull((info) => info.id == WalletBase.idFor(name, getType()))!;
final wallet = await LitecoinWalletBase.open(
password: password, name: name, walletInfo: walletInfo,
password: password,
name: name,
walletInfo: walletInfo,
unspentCoinsInfo: unspentCoinsInfoSource,
encryptionFileUtils: encryptionFileUtilsFor(isDirect));
await wallet.init();
@ -58,22 +58,23 @@ class LitecoinWalletService extends WalletService<
@override
Future<void> remove(String wallet) async {
File(await pathForWalletDir(name: wallet, type: getType()))
.delete(recursive: true);
final walletInfo = walletInfoSource.values.firstWhereOrNull(
(info) => info.id == WalletBase.idFor(wallet, getType()))!;
File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true);
final walletInfo = walletInfoSource.values
.firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!;
await walletInfoSource.delete(walletInfo.key);
}
@override
Future<void> rename(String currentName, String password, String newName) async {
final currentWalletInfo = walletInfoSource.values.firstWhereOrNull(
(info) => info.id == WalletBase.idFor(currentName, getType()))!;
final currentWalletInfo = walletInfoSource.values
.firstWhereOrNull((info) => info.id == WalletBase.idFor(currentName, getType()))!;
final currentWallet = await LitecoinWalletBase.open(
password: password,
name: currentName,
walletInfo: currentWalletInfo,
unspentCoinsInfo: unspentCoinsInfoSource);
password: password,
name: currentName,
walletInfo: currentWalletInfo,
unspentCoinsInfo: unspentCoinsInfoSource,
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
);
await currentWallet.renameWalletFiles(newName);

View file

@ -191,7 +191,7 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
static const nexo = CryptoCurrency(title: 'NEXO', tag: 'ETH', fullName: 'Nexo', raw: 76, name: 'nexo', iconPath: 'assets/images/nexo_icon.png');
static const cake = CryptoCurrency(title: 'CAKE', tag: 'BSC', fullName: 'PancakeSwap', raw: 77, name: 'cake', iconPath: 'assets/images/cake_icon.png');
static const pepe = CryptoCurrency(title: 'PEPE', tag: 'ETH', fullName: 'Pepe', raw: 78, name: 'pepe', iconPath: 'assets/images/pepe_icon.png');
static const storj = CryptoCurrency(title: 'STORJ', tag: 'ETH', fullName: 'Storj', raw: 79, name: 'storj', iconPath: 'assets/images/stroj_icon.png');
static const storj = CryptoCurrency(title: 'STORJ', tag: 'ETH', fullName: 'Storj', raw: 79, name: 'storj', iconPath: 'assets/images/storj_icon.png');
static const tusd = CryptoCurrency(title: 'TUSD', tag: 'ETH', fullName: 'TrueUSD', raw: 80, name: 'tusd', iconPath: 'assets/images/tusd_icon.png');
static const wbtc = CryptoCurrency(title: 'WBTC', tag: 'ETH', fullName: 'Wrapped Bitcoin', raw: 81, name: 'wbtc', iconPath: 'assets/images/wbtc_icon.png');
static const weth = CryptoCurrency(title: 'WETH', tag: 'ETH', fullName: 'Wrapped Ethereum', raw: 82, name: 'weth', iconPath: 'assets/images/weth_icon.png');

View file

@ -3,7 +3,6 @@ import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/monero_wallet_utils.dart';
import 'package:hive/hive.dart';
import 'package:cw_monero/api/wallet_manager.dart' as monero_wallet_manager;
import 'package:cw_monero/api/wallet.dart' as monero_wallet;
import 'package:cw_monero/api/exceptions/wallet_opening_exception.dart';
import 'package:cw_monero/monero_wallet.dart';
import 'package:cw_core/wallet_credentials.dart';
@ -161,7 +160,7 @@ class MoneroWalletService extends WalletService<
String currentName, String password, String newName) async {
final currentWalletInfo = walletInfoSource.values.firstWhere(
(info) => info.id == WalletBase.idFor(currentName, getType()));
final currentWallet = MoneroWallet(walletInfo: currentWalletInfo);
final currentWallet = MoneroWallet(walletInfo: currentWalletInfo, password: password);
await currentWallet.renameWalletFiles(newName);

View file

@ -1,4 +1,7 @@
import 'dart:convert';
import 'package:cake_wallet/palette.dart';
import 'package:cake_wallet/store/settings_store.dart';
import 'package:cake_wallet/themes/theme_base.dart';
import 'package:crypto/crypto.dart';
import 'package:cake_wallet/buy/buy_exception.dart';
import 'package:http/http.dart';
@ -13,23 +16,48 @@ import 'package:cake_wallet/.secrets.g.dart' as secrets;
import 'package:cw_core/crypto_currency.dart';
class MoonPaySellProvider {
MoonPaySellProvider({this.isTest = false})
: baseUrl = isTest ? _baseTestUrl : _baseProductUrl;
MoonPaySellProvider({this.isTest = false}) : baseUrl = isTest ? _baseTestUrl : _baseProductUrl;
static const _baseTestUrl = 'sell-staging.moonpay.com';
static const _baseTestUrl = 'sell-sandbox.moonpay.com';
static const _baseProductUrl = 'sell.moonpay.com';
static String get _apiKey => secrets.moonPayApiKey;
static String get _secretKey => secrets.moonPaySecretKey;
static String themeToMoonPayTheme(ThemeBase theme) {
switch (theme.type) {
case ThemeType.bright:
return 'light';
case ThemeType.light:
return 'light';
case ThemeType.dark:
return 'dark';
}
}
static String get _apiKey => secrets.moonPayApiKey;
static String get _secretKey => secrets.moonPaySecretKey;
final bool isTest;
final String baseUrl;
Future<Uri> requestUrl({required CryptoCurrency currency, required String refundWalletAddress}) async {
Future<Uri> requestUrl(
{required CryptoCurrency currency,
required String refundWalletAddress,
required SettingsStore settingsStore}) async {
final customParams = {
'theme': themeToMoonPayTheme(settingsStore.currentTheme),
'language': settingsStore.languageCode,
'colorCode': settingsStore.currentTheme.type == ThemeType.dark
? '#${Palette.blueCraiola.value.toRadixString(16).substring(2, 8)}'
: '#${Palette.moderateSlateBlue.value.toRadixString(16).substring(2, 8)}',
};
final originalUri = Uri.https(
baseUrl, '', <String, dynamic>{
'apiKey': _apiKey,
'defaultBaseCurrencyCode': currency.toString().toLowerCase(),
'refundWalletAddress': refundWalletAddress
});
baseUrl,
'',
<String, dynamic>{
'apiKey': _apiKey,
'defaultBaseCurrencyCode': currency.toString().toLowerCase(),
'refundWalletAddress': refundWalletAddress
}..addAll(customParams));
final messageBytes = utf8.encode('?${originalUri.query}');
final key = utf8.encode(_secretKey);
final hmac = Hmac(sha256, key);
@ -68,8 +96,7 @@ class MoonPayBuyProvider extends BuyProvider {
@override
BuyProviderDescription get description => BuyProviderDescription.moonPay;
String get currencyCode =>
walletTypeToCryptoCurrency(walletType).title.toLowerCase();
String get currencyCode => walletTypeToCryptoCurrency(walletType).title.toLowerCase();
@override
String get trackUrl => baseUrl + '/transaction_receipt?transactionId=';
@ -78,16 +105,24 @@ class MoonPayBuyProvider extends BuyProvider {
@override
Future<String> requestUrl(String amount, String sourceCurrency) async {
final enabledPaymentMethods =
'credit_debit_card%2Capple_pay%2Cgoogle_pay%2Csamsung_pay'
final enabledPaymentMethods = 'credit_debit_card%2Capple_pay%2Cgoogle_pay%2Csamsung_pay'
'%2Csepa_bank_transfer%2Cgbp_bank_transfer%2Cgbp_open_banking_payment';
final suffix = '?apiKey=' + _apiKey + '&currencyCode=' +
currencyCode + '&enabledPaymentMethods=' + enabledPaymentMethods +
'&walletAddress=' + walletAddress +
'&baseCurrencyCode=' + sourceCurrency.toLowerCase() +
'&baseCurrencyAmount=' + amount + '&lockAmount=true' +
'&showAllCurrencies=false' + '&showWalletAddressForm=false';
final suffix = '?apiKey=' +
_apiKey +
'&currencyCode=' +
currencyCode +
'&enabledPaymentMethods=' +
enabledPaymentMethods +
'&walletAddress=' +
walletAddress +
'&baseCurrencyCode=' +
sourceCurrency.toLowerCase() +
'&baseCurrencyAmount=' +
amount +
'&lockAmount=true' +
'&showAllCurrencies=false' +
'&showWalletAddressForm=false';
final originalUrl = baseUrl + suffix;
@ -96,25 +131,28 @@ class MoonPayBuyProvider extends BuyProvider {
final hmac = Hmac(sha256, key);
final digest = hmac.convert(messageBytes);
final signature = base64.encode(digest.bytes);
final urlWithSignature = originalUrl +
'&signature=${Uri.encodeComponent(signature)}';
final urlWithSignature = originalUrl + '&signature=${Uri.encodeComponent(signature)}';
return isTestEnvironment ? originalUrl : urlWithSignature;
}
@override
Future<BuyAmount> calculateAmount(String amount, String sourceCurrency) async {
final url = _apiUrl + _currenciesSuffix + '/$currencyCode' +
_quoteSuffix + '/?apiKey=' + _apiKey +
'&baseCurrencyAmount=' + amount +
'&baseCurrencyCode=' + sourceCurrency.toLowerCase();
final url = _apiUrl +
_currenciesSuffix +
'/$currencyCode' +
_quoteSuffix +
'/?apiKey=' +
_apiKey +
'&baseCurrencyAmount=' +
amount +
'&baseCurrencyCode=' +
sourceCurrency.toLowerCase();
final uri = Uri.parse(url);
final response = await get(uri);
if (response.statusCode != 200) {
throw BuyException(
description: description,
text: 'Quote is not found!');
throw BuyException(description: description, text: 'Quote is not found!');
}
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
@ -123,22 +161,17 @@ class MoonPayBuyProvider extends BuyProvider {
final minSourceAmount = responseJSON['baseCurrency']['minAmount'] as int;
return BuyAmount(
sourceAmount: sourceAmount,
destAmount: destAmount,
minAmount: minSourceAmount);
sourceAmount: sourceAmount, destAmount: destAmount, minAmount: minSourceAmount);
}
@override
Future<Order> findOrderById(String id) async {
final url = _apiUrl + _transactionsSuffix + '/$id' +
'?apiKey=' + _apiKey;
final url = _apiUrl + _transactionsSuffix + '/$id' + '?apiKey=' + _apiKey;
final uri = Uri.parse(url);
final response = await get(uri);
if (response.statusCode != 200) {
throw BuyException(
description: description,
text: 'Transaction $id is not found!');
throw BuyException(description: description, text: 'Transaction $id is not found!');
}
final responseJSON = json.decode(response.body) as Map<String, dynamic>;
@ -156,8 +189,7 @@ class MoonPayBuyProvider extends BuyProvider {
createdAt: createdAt,
amount: amount.toString(),
receiveAddress: walletAddress,
walletId: walletId
);
walletId: walletId);
}
static Future<bool> onEnabled() async {
@ -176,4 +208,4 @@ class MoonPayBuyProvider extends BuyProvider {
return isBuyEnable;
}
}
}

View file

@ -7,21 +7,19 @@ import 'package:cw_core/wallet_type.dart';
import 'package:shared_preferences/shared_preferences.dart';
class WalletLoadingService {
WalletLoadingService(
this.sharedPreferences, this.keyService, this.walletServiceFactory);
WalletLoadingService(this.sharedPreferences, this.keyService, this.walletServiceFactory);
final SharedPreferences sharedPreferences;
final KeyService keyService;
final WalletService Function(WalletType type) walletServiceFactory;
Future<void> renameWallet(
WalletType type, String name, String newName, {String? password}) async {
Future<void> renameWallet(WalletType type, String name, String newName,
{String? password}) async {
final walletService = walletServiceFactory.call(type);
final walletPassword = password ?? (await keyService.getWalletPassword(walletName: name));
// Save the current wallet's password to the new wallet name's key
await keyService.saveWalletPassword(
walletName: newName, password: walletPassword);
await keyService.saveWalletPassword(walletName: newName, password: walletPassword);
// Delete previous wallet name from keyService to keep only new wallet's name
// otherwise keeps duplicate (old and new names)
await keyService.deleteWalletPassword(walletName: name);
@ -29,10 +27,10 @@ class WalletLoadingService {
await walletService.rename(name, walletPassword, newName);
}
Future<WalletBase> load(WalletType type, String name, {String? password}) async {
final walletService = walletServiceFactory.call(type);
final walletPassword = password ?? (await keyService.getWalletPassword(walletName: name));
final wallet = await walletService.openWallet(name, walletPassword);
Future<WalletBase> load(WalletType type, String name, {String? password}) async {
final walletService = walletServiceFactory.call(type);
final walletPassword = password ?? (await keyService.getWalletPassword(walletName: name));
final wallet = await walletService.openWallet(name, walletPassword);
if (type == WalletType.monero) {
await updateMoneroWalletPassword(wallet);
@ -53,12 +51,10 @@ class WalletLoadingService {
// Save new generated password with backup key for case where
// wallet will change password, but it will fail to update in secure storage
final bakWalletName = '#__${wallet.name}_bak__#';
await keyService.saveWalletPassword(
walletName: bakWalletName, password: password);
await keyService.saveWalletPassword(walletName: bakWalletName, password: password);
await wallet.changePassword(password);
await keyService.saveWalletPassword(
walletName: wallet.name, password: password);
await keyService.saveWalletPassword(walletName: wallet.name, password: password);
isPasswordUpdated = true;
await sharedPreferences.setBool(key, isPasswordUpdated);
}
}
}

View file

@ -1,4 +1,3 @@
import 'dart:io';
import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart';
import 'package:cake_wallet/core/yat_service.dart';
@ -7,25 +6,19 @@ import 'package:cake_wallet/entities/preferences_key.dart';
import 'package:cake_wallet/anonpay/anonpay_api.dart';
import 'package:cake_wallet/anonpay/anonpay_info_base.dart';
import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart';
import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart';
import 'package:cake_wallet/buy/payfura/payfura_buy_provider.dart';
import 'package:cake_wallet/core/yat_service.dart';
import 'package:cake_wallet/entities/exchange_api_mode.dart';
import 'package:cake_wallet/entities/parse_address_from_domain.dart';
import 'package:cake_wallet/entities/receive_page_option.dart';
import 'package:cake_wallet/ionia/ionia_anypay.dart';
import 'package:cake_wallet/ionia/ionia_gift_card.dart';
import 'package:cake_wallet/ionia/ionia_tip.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/anonpay_details/anonpay_details_page.dart';
import 'package:cake_wallet/src/screens/buy/onramper_page.dart';
import 'package:cake_wallet/src/screens/buy/webview_page.dart';
import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/transactions_page.dart';
import 'package:cake_wallet/src/screens/buy/payfura_page.dart';
import 'package:cake_wallet/src/screens/dashboard/desktop_dashboard_page.dart';
import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart';
import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/transactions_page.dart';
import 'package:cake_wallet/src/screens/receive/anonpay_invoice_page.dart';
import 'package:cake_wallet/src/screens/receive/anonpay_receive_page.dart';
import 'package:cake_wallet/src/screens/settings/display_settings_page.dart';
@ -45,11 +38,8 @@ import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart';
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart';
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_enter_code_page.dart';
import 'package:cake_wallet/src/screens/wallet/wallet_edit_page.dart';
import 'package:cake_wallet/themes/theme_list.dart';
import 'package:cake_wallet/utils/device_info.dart';
import 'package:cake_wallet/store/anonpay/anonpay_transactions_store.dart';
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/anon_invoice_page_view_model.dart';
import 'package:cake_wallet/view_model/anonpay_details_view_model.dart';
import 'package:cake_wallet/view_model/dashboard/receive_option_view_model.dart';
@ -83,7 +73,6 @@ import 'package:cake_wallet/view_model/wallet_list/wallet_edit_view_model.dart';
import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart';
import 'package:cake_wallet/view_model/wallet_unlock_loadable_view_model.dart';
import 'package:cake_wallet/view_model/wallet_unlock_verifiable_view_model.dart';
import 'package:cake_wallet/view_model/wallet_unlock_view_model.dart';
import 'package:cw_core/unspent_coins_info.dart';
import 'package:cake_wallet/core/backup_service.dart';
import 'package:cw_core/wallet_service.dart';
@ -176,7 +165,6 @@ import 'package:cake_wallet/view_model/wallet_list/wallet_list_view_model.dart';
import 'package:cake_wallet/view_model/wallet_restore_view_model.dart';
import 'package:cake_wallet/view_model/wallet_seed_view_model.dart';
import 'package:cake_wallet/view_model/exchange/exchange_view_model.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:get_it/get_it.dart';
import 'package:hive/hive.dart';
@ -709,15 +697,13 @@ Future setup({
wallet: getIt.get<AppStore>().wallet!,
));
getIt.registerFactory(() => OnRamperPage(getIt.get<OnRamperBuyProvider>()));
getIt.registerFactoryParam<WebViewPage, String, Uri>((title, uri) => WebViewPage(title, uri));
getIt.registerFactory<PayfuraBuyProvider>(() => PayfuraBuyProvider(
settingsStore: getIt.get<AppStore>().settingsStore,
wallet: getIt.get<AppStore>().wallet!,
));
getIt.registerFactory(() => PayFuraPage(getIt.get<PayfuraBuyProvider>()));
getIt.registerFactory(() => ExchangeViewModel(
getIt.get<AppStore>().wallet!,
_tradesSource,

View file

@ -48,10 +48,11 @@ class MainActions {
case WalletType.bitcoin:
case WalletType.litecoin:
if (viewModel.isEnabledBuyAction) {
final uri = getIt.get<OnRamperBuyProvider>().requestUrl();
if (DeviceInfo.instance.isMobile) {
Navigator.of(context).pushNamed(Routes.onramperPage);
Navigator.of(context)
.pushNamed(Routes.webViewPage, arguments: [S.of(context).buy, uri]);
} else {
final uri = getIt.get<OnRamperBuyProvider>().requestUrl();
await launchUrl(uri);
}
}
@ -118,14 +119,22 @@ class MainActions {
switch (walletType) {
case WalletType.bitcoin:
case WalletType.litecoin:
if (viewModel.isEnabledSellAction) {
final moonPaySellProvider = MoonPaySellProvider();
final uri = await moonPaySellProvider.requestUrl(
currency: viewModel.wallet.currency,
refundWalletAddress: viewModel.wallet.walletAddresses.address,
settingsStore: viewModel.settingsStore,
);
await launchUrl(uri);
if (DeviceInfo.instance.isMobile) {
Navigator.of(context).pushNamed(Routes.webViewPage,
arguments: [S.of(context).sell, uri]);
} else {
await launchUrl(uri);
}
}
break;
default:
await showPopUp<void>(

View file

@ -8,6 +8,7 @@ import 'package:cake_wallet/store/yat/yat_store.dart';
import 'package:cake_wallet/utils/exception_handler.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:cw_core/root_dir.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

View file

@ -8,8 +8,7 @@ import 'package:cake_wallet/src/screens/anonpay_details/anonpay_details_page.dar
import 'package:cake_wallet/src/screens/backup/backup_page.dart';
import 'package:cake_wallet/src/screens/backup/edit_backup_password_page.dart';
import 'package:cake_wallet/src/screens/buy/buy_webview_page.dart';
import 'package:cake_wallet/src/screens/buy/onramper_page.dart';
import 'package:cake_wallet/src/screens/buy/payfura_page.dart';
import 'package:cake_wallet/src/screens/buy/webview_page.dart';
import 'package:cake_wallet/src/screens/buy/pre_order_page.dart';
import 'package:cake_wallet/src/screens/restore/sweeping_wallet_page.dart';
import 'package:cake_wallet/src/screens/receive/anonpay_invoice_page.dart';
@ -48,7 +47,6 @@ import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart';
import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart';
import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart';
import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart';
import 'package:cake_wallet/wallet_type_utils.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
@ -564,11 +562,13 @@ Route<dynamic> createRoute(RouteSettings settings) {
param1: paymentInfo,
param2: commitedInfo));
case Routes.onramperPage:
return CupertinoPageRoute<void>(builder: (_) => getIt.get<OnRamperPage>());
case Routes.payfuraPage:
return CupertinoPageRoute<void>(builder: (_) => getIt.get<PayFuraPage>());
case Routes.webViewPage:
final args = settings.arguments as List;
final title = args.first as String;
final url = args[1] as Uri;
return CupertinoPageRoute<void>(builder: (_) => getIt.get<WebViewPage>(
param1: title,
param2: url));
case Routes.advancedPrivacySettings:
final type = settings.arguments as WalletType;

View file

@ -71,7 +71,7 @@ class Routes {
static const ioniaPaymentStatusPage = '/ionia_payment_status_page';
static const ioniaMoreOptionsPage = '/ionia_more_options_page';
static const ioniaCustomRedeemPage = '/ionia_custom_redeem_page';
static const onramperPage = '/onramper';
static const webViewPage = '/web_view_page';
static const connectionSync = '/connection_sync_page';
static const securityBackupPage = '/security_and_backup_page';
static const privacyPage = '/privacy_page';

View file

@ -5,33 +5,32 @@ import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:permission_handler/permission_handler.dart';
class OnRamperPage extends BasePage {
OnRamperPage(this._onRamperBuyProvider);
class WebViewPage extends BasePage {
WebViewPage(this._title, this._url);
final OnRamperBuyProvider _onRamperBuyProvider;
final String _title;
final Uri _url;
@override
String get title => S.current.buy;
String get title => _title;
@override
Widget body(BuildContext context) {
return OnRamperPageBody(_onRamperBuyProvider);
return WebViewPageBody(_url);
}
}
class OnRamperPageBody extends StatefulWidget {
OnRamperPageBody(this.onRamperBuyProvider);
class WebViewPageBody extends StatefulWidget {
WebViewPageBody(this.uri);
final OnRamperBuyProvider onRamperBuyProvider;
Uri get uri => onRamperBuyProvider.requestUrl();
final Uri uri;
@override
OnRamperPageBodyState createState() => OnRamperPageBodyState();
WebViewPageBodyState createState() => WebViewPageBodyState();
}
class OnRamperPageBodyState extends State<OnRamperPageBody> {
OnRamperPageBodyState();
class WebViewPageBodyState extends State<WebViewPageBody> {
WebViewPageBodyState();
@override
Widget build(BuildContext context) {

View file

@ -73,7 +73,7 @@ class AddressPage extends BasePage {
? closeButtonImageDarkTheme
: closeButtonImage;
bool isMobileView = ResponsiveLayoutUtil.instance.isMobile(context);
bool isMobileView = ResponsiveLayoutUtil.instance.isMobile;
return MergeSemantics(
child: SizedBox(

View file

@ -1,6 +1,5 @@
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
import 'package:cake_wallet/store/settings_store.dart';
import 'package:cake_wallet/src/widgets/dashboard_card_widget.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
@ -85,7 +84,7 @@ class MarketPlacePage extends StatelessWidget {
switch (walletType) {
case WalletType.haven:
showPopUp<void>(
showPopUp<void>(
context: context,
builder: (BuildContext context) {
return AlertWithOneAction(

View file

@ -45,9 +45,11 @@ class TransactionsPage extends StatelessWidget {
return Padding(
padding: const EdgeInsets.fromLTRB(24, 0, 24, 8),
child: DashBoardRoundedCardWidget(
onTap: () => Navigator.of(context).pushNamed(
Routes.webViewPage,
arguments: ['', Uri.parse('https://guides.cakewallet.com/docs/bugs-service-status/why_are_my_funds_not_appearing/')]),
onTap: () => Navigator.of(context).pushNamed(Routes.webViewPage, arguments: [
'',
Uri.parse(
'https://guides.cakewallet.com/docs/bugs-service-status/why_are_my_funds_not_appearing/')
]),
title: S.of(context).syncing_wallet_alert_title,
subTitle: S.of(context).syncing_wallet_alert_content,
),
@ -60,96 +62,97 @@ class TransactionsPage extends StatelessWidget {
Expanded(child: Observer(builder: (_) {
final items = dashboardViewModel.items;
return items.isNotEmpty
? ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
final item = items[index];
return items.isNotEmpty
? ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
final item = items[index];
if (item is DateSectionItem) {
return DateSectionRaw(date: item.date);
}
if (item is DateSectionItem) {
return DateSectionRaw(date: item.date);
}
if (item is TransactionListItem) {
final transaction = item.transaction;
if (item is TransactionListItem) {
final transaction = item.transaction;
return Observer(
builder: (_) => TransactionRow(
onTap: () => Navigator.of(context)
.pushNamed(Routes.transactionDetails, arguments: transaction),
direction: transaction.direction,
formattedDate: DateFormat('HH:mm').format(transaction.date),
formattedAmount: item.formattedCryptoAmount,
formattedFiatAmount:
dashboardViewModel.balanceViewModel.isFiatDisabled
? ''
: item.formattedFiatAmount,
isPending: transaction.isPending,
title: item.formattedTitle + item.formattedStatus));
}
if (item is AnonpayTransactionListItem) {
final transactionInfo = item.transaction;
return AnonpayTransactionRow(
onTap: () => Navigator.of(context)
.pushNamed(Routes.anonPayDetailsPage, arguments: transactionInfo),
currency: transactionInfo.fiatAmount != null
? transactionInfo.fiatEquiv ?? ''
: CryptoCurrency.fromFullName(transactionInfo.coinTo)
.name
.toUpperCase(),
provider: transactionInfo.provider,
amount: transactionInfo.fiatAmount?.toString() ??
(transactionInfo.amountTo?.toString() ?? ''),
createdAt: DateFormat('HH:mm').format(transactionInfo.createdAt),
);
}
if (item is TradeListItem) {
final trade = item.trade;
return Observer(
builder: (_) => TradeRow(
onTap: () => Navigator.of(context)
.pushNamed(Routes.tradeDetails, arguments: trade),
provider: trade.provider,
from: trade.from,
to: trade.to,
createdAtFormattedDate: trade.createdAt != null
? DateFormat('HH:mm').format(trade.createdAt!)
: null,
formattedAmount: item.tradeFormattedAmount));
}
if (item is OrderListItem) {
final order = item.order;
return Observer(
builder: (_) => OrderRow(
return Observer(
builder: (_) => TransactionRow(
onTap: () => Navigator.of(context)
.pushNamed(Routes.orderDetails, arguments: order),
provider: order.provider,
from: order.from!,
to: order.to!,
createdAtFormattedDate:
DateFormat('HH:mm').format(order.createdAt),
formattedAmount: item.orderFormattedAmount,
));
}
.pushNamed(Routes.transactionDetails, arguments: transaction),
direction: transaction.direction,
formattedDate: DateFormat('HH:mm').format(transaction.date),
formattedAmount: item.formattedCryptoAmount,
formattedFiatAmount:
dashboardViewModel.balanceViewModel.isFiatDisabled
? ''
: item.formattedFiatAmount,
isPending: transaction.isPending,
title: item.formattedTitle + item.formattedStatus));
}
return Container(color: Colors.transparent, height: 1);
})
: Center(
child: Text(
S.of(context).placeholder_transactions,
style: TextStyle(
fontSize: 14,
color: Theme.of(context).primaryTextTheme!.labelSmall!.decorationColor!),
),
);
}))
],
if (item is AnonpayTransactionListItem) {
final transactionInfo = item.transaction;
return AnonpayTransactionRow(
onTap: () => Navigator.of(context)
.pushNamed(Routes.anonPayDetailsPage, arguments: transactionInfo),
currency: transactionInfo.fiatAmount != null
? transactionInfo.fiatEquiv ?? ''
: CryptoCurrency.fromFullName(transactionInfo.coinTo)
.name
.toUpperCase(),
provider: transactionInfo.provider,
amount: transactionInfo.fiatAmount?.toString() ??
(transactionInfo.amountTo?.toString() ?? ''),
createdAt: DateFormat('HH:mm').format(transactionInfo.createdAt),
);
}
if (item is TradeListItem) {
final trade = item.trade;
return Observer(
builder: (_) => TradeRow(
onTap: () => Navigator.of(context)
.pushNamed(Routes.tradeDetails, arguments: trade),
provider: trade.provider,
from: trade.from,
to: trade.to,
createdAtFormattedDate: trade.createdAt != null
? DateFormat('HH:mm').format(trade.createdAt!)
: null,
formattedAmount: item.tradeFormattedAmount));
}
if (item is OrderListItem) {
final order = item.order;
return Observer(
builder: (_) => OrderRow(
onTap: () => Navigator.of(context)
.pushNamed(Routes.orderDetails, arguments: order),
provider: order.provider,
from: order.from!,
to: order.to!,
createdAtFormattedDate:
DateFormat('HH:mm').format(order.createdAt),
formattedAmount: item.orderFormattedAmount,
));
}
return Container(color: Colors.transparent, height: 1);
})
: Center(
child: Text(
S.of(context).placeholder_transactions,
style: TextStyle(
fontSize: 14,
color: Theme.of(context).primaryTextTheme.labelSmall!.decorationColor!),
),
);
}))
],
),
),
);
}

View file

@ -117,7 +117,7 @@ class ExchangePage extends BasePage {
final _closeButton = currentTheme.type == ThemeType.dark
? closeButtonImageDarkTheme : closeButtonImage;
bool isMobileView = ResponsiveLayoutUtil.instance.isMobile(context);
bool isMobileView = ResponsiveLayoutUtil.instance.isMobile;
return MergeSemantics(
child: SizedBox(
@ -733,7 +733,7 @@ class ExchangePage extends BasePage {
},
));
if (ResponsiveLayoutUtil.instance.isMobile(context)) {
if (ResponsiveLayoutUtil.instance.isMobile) {
return MobileExchangeCardsSection(
firstExchangeCard: firstExchangeCard,
secondExchangeCard: secondExchangeCard,

View file

@ -40,6 +40,7 @@ class AnonPayInvoicePage extends BasePage {
final _formKey = GlobalKey<FormState>();
bool effectsInstalled = false;
@override
Color get titleColor => Colors.white;
@ -82,34 +83,33 @@ class AnonPayInvoicePage extends BasePage {
disableScroll: true,
config: KeyboardActionsConfig(
keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
keyboardBarColor: Theme.of(context)
.accentTextTheme!
.bodyLarge!
.backgroundColor!,
nextFocus: false,
actions: [
KeyboardActionsItem(
focusNode: _amountFocusNode,
toolbarButtons: [(_) => KeyboardDoneButton()],
),
]),
child: Container(
color: Theme.of(context).colorScheme.background,
child: ScrollableWithBottomSection(
contentPadding: EdgeInsets.only(bottom: 24),
content: Container(
decoration: ResponsiveLayoutUtil.instance.isMobile ? BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)),
gradient: LinearGradient(
colors: [
Theme.of(context).primaryTextTheme!.titleSmall!.color!,
Theme.of(context).primaryTextTheme!.titleSmall!.decorationColor!,
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
keyboardBarColor: Theme.of(context).accentTextTheme!.bodyLarge!.backgroundColor!,
nextFocus: false,
actions: [
KeyboardActionsItem(
focusNode: _amountFocusNode,
toolbarButtons: [(_) => KeyboardDoneButton()],
),
) : null,
]),
child: Container(
color: Theme.of(context).colorScheme.background,
child: ScrollableWithBottomSection(
contentPadding: EdgeInsets.only(bottom: 24),
content: Container(
decoration: ResponsiveLayoutUtil.instance.isMobile
? BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)),
gradient: LinearGradient(
colors: [
Theme.of(context).primaryTextTheme!.titleSmall!.color!,
Theme.of(context).primaryTextTheme!.titleSmall!.decorationColor!,
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
)
: null,
child: Observer(builder: (_) {
return Padding(
padding: EdgeInsets.fromLTRB(24, 120, 24, 0),
@ -142,12 +142,10 @@ class AnonPayInvoicePage extends BasePage {
: S.of(context).anonpay_description("a donation link", "donate"),
textAlign: TextAlign.center,
style: TextStyle(
color: Theme.of(context)
.primaryTextTheme!
.displayLarge!
.decorationColor!,
fontWeight: FontWeight.w500,
fontSize: 12),
color:
Theme.of(context).primaryTextTheme!.displayLarge!.decorationColor!,
fontWeight: FontWeight.w500,
fontSize: 12),
),
),
),
@ -173,10 +171,7 @@ class AnonPayInvoicePage extends BasePage {
anonInvoicePageViewModel.generateDonationLink();
}
},
color: Theme.of(context)
.accentTextTheme!
.bodyLarge!
.color!,
color: Theme.of(context).accentTextTheme!.bodyLarge!.color!,
textColor: Colors.white,
isLoading: anonInvoicePageViewModel.state is IsExecutingState,
),

View file

@ -62,7 +62,7 @@ class SendPage extends BasePage {
final _closeButton = currentTheme.type == ThemeType.dark
? closeButtonImageDarkTheme : closeButtonImage;
bool isMobileView = ResponsiveLayoutUtil.instance.isMobile(context);
bool isMobileView = ResponsiveLayoutUtil.instance.isMobile;
return MergeSemantics(
child: SizedBox(
@ -94,7 +94,7 @@ class SendPage extends BasePage {
double _sendCardHeight(BuildContext context) {
final double initialHeight = sendViewModel.isElectrumWallet ? 490 : 465;
if (!ResponsiveLayoutUtil.instance.isMobile(context)) {
if (!ResponsiveLayoutUtil.instance.isMobile) {
return initialHeight - 66;
}
return initialHeight;

View file

@ -122,7 +122,7 @@ class SendCardState extends State<SendCard>
color: Colors.transparent,
)),
Container(
decoration: ResponsiveLayoutUtil.instance.isMobile(context) ? BoxDecoration(
decoration: ResponsiveLayoutUtil.instance.isMobile ? BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(24),
bottomRight: Radius.circular(24)),
@ -137,9 +137,9 @@ class SendCardState extends State<SendCard>
child: Padding(
padding: EdgeInsets.fromLTRB(
24,
ResponsiveLayoutUtil.instance.isMobile(context) ? 100 : 55,
ResponsiveLayoutUtil.instance.isMobile ? 100 : 55,
24,
ResponsiveLayoutUtil.instance.isMobile(context) ? 32 : 0,
ResponsiveLayoutUtil.instance.isMobile ? 32 : 0,
),
child: SingleChildScrollView(
child: Observer(builder: (_) => Column(

View file

@ -26,7 +26,7 @@ class AddTemplateButton extends StatelessWidget {
child: Container(
height: 34,
padding: EdgeInsets.symmetric(
horizontal: ResponsiveLayoutUtil.instance.isMobile(context) ? 10 : 30),
horizontal: ResponsiveLayoutUtil.instance.isMobile ? 10 : 30),
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20)),

View file

@ -1,5 +1,5 @@
import 'dart:io';
import 'package:package_info/package_info.dart';
import 'package:package_info_plus/package_info_plus.dart';
enum DistributionType { googleplay, github, appstore, fdroid }

View 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();
}
}

View file

@ -1,10 +1,6 @@
import 'package:cake_wallet/core/auth_service.dart';
import 'package:cake_wallet/core/wallet_loading_service.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/balance.dart';
import 'package:cw_core/transaction_history.dart';
import 'package:cw_core/transaction_info.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
import 'package:cake_wallet/store/app_store.dart';

View file

@ -9,7 +9,6 @@ import connectivity_macos
import cw_monero
import device_info_plus
import devicelocale
import flutter_secure_storage_macos
import in_app_review
import package_info_plus
import path_provider_foundation
@ -25,7 +24,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
CwMoneroPlugin.register(with: registry.registrar(forPlugin: "CwMoneroPlugin"))
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin"))
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin"))
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))

View file

@ -1,7 +1,7 @@
PODS:
- connectivity_macos (0.0.1):
- connectivity_plus_macos (0.0.1):
- FlutterMacOS
- Reachability
- ReachabilitySwift
- cw_monero (0.0.1):
- cw_monero/Boost (= 0.0.1)
- cw_monero/Monero (= 0.0.1)
@ -28,7 +28,7 @@ PODS:
- FlutterMacOS (1.0.0)
- in_app_review (0.2.0):
- FlutterMacOS
- package_info_plus (0.0.1):
- package_info (0.0.1):
- FlutterMacOS
- path_provider_foundation (0.0.1):
- Flutter
@ -37,7 +37,7 @@ PODS:
- FlutterMacOS
- platform_device_id_macos (0.0.1):
- FlutterMacOS
- Reachability (3.2)
- ReachabilitySwift (5.0.0)
- share_plus_macos (0.0.1):
- FlutterMacOS
- shared_preferences_foundation (0.0.1):
@ -49,14 +49,14 @@ PODS:
- FlutterMacOS
DEPENDENCIES:
- connectivity_macos (from `Flutter/ephemeral/.symlinks/plugins/connectivity_macos/macos`)
- connectivity_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus_macos/macos`)
- cw_monero (from `Flutter/ephemeral/.symlinks/plugins/cw_monero/macos`)
- device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`)
- devicelocale (from `Flutter/ephemeral/.symlinks/plugins/devicelocale/macos`)
- flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`)
- FlutterMacOS (from `Flutter/ephemeral`)
- in_app_review (from `Flutter/ephemeral/.symlinks/plugins/in_app_review/macos`)
- package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
- package_info (from `Flutter/ephemeral/.symlinks/plugins/package_info/macos`)
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos`)
- platform_device_id (from `Flutter/ephemeral/.symlinks/plugins/platform_device_id/macos`)
- platform_device_id_macos (from `Flutter/ephemeral/.symlinks/plugins/platform_device_id_macos/macos`)
@ -67,11 +67,11 @@ DEPENDENCIES:
SPEC REPOS:
trunk:
- Reachability
- ReachabilitySwift
EXTERNAL SOURCES:
connectivity_macos:
:path: Flutter/ephemeral/.symlinks/plugins/connectivity_macos/macos
connectivity_plus_macos:
:path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus_macos/macos
cw_monero:
:path: Flutter/ephemeral/.symlinks/plugins/cw_monero/macos
device_info_plus:
@ -84,8 +84,8 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral
in_app_review:
:path: Flutter/ephemeral/.symlinks/plugins/in_app_review/macos
package_info_plus:
:path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos
package_info:
:path: Flutter/ephemeral/.symlinks/plugins/package_info/macos
path_provider_foundation:
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos
platform_device_id:
@ -102,23 +102,23 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/wakelock_macos/macos
SPEC CHECKSUMS:
connectivity_macos: 5dae6ee11d320fac7c05f0d08bd08fc32b5514d9
connectivity_plus_macos: f6e86fd000e971d361e54b5afcadc8c8fa773308
cw_monero: ec03de55a19c4a2b174ea687e0f4202edc716fa4
device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f
devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225
flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
in_app_review: a850789fad746e89bce03d4aeee8078b45a53fd0
package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce
path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9
package_info: 6eba2fd8d3371dda2d85c8db6fe97488f24b74b2
path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
platform_device_id: 3e414428f45df149bbbfb623e2c0ca27c545b763
platform_device_id_macos: f763bb55f088be804d61b96eb4710b8ab6598e94
Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
url_launcher_macos: 5335912b679c073563f29d89d33d10d459f95451
wakelock_macos: bc3f2a9bd8d2e6c89fee1e1822e7ddac3bd004a9
PODFILE CHECKSUM: 505596d150d38022472859d890f709281982e016
PODFILE CHECKSUM: 5107934592df7813b33d744aebc8ddc6b5a5445f
COCOAPODS: 1.11.2
COCOAPODS: 1.12.1

View file

@ -321,6 +321,12 @@
"trade_state_timeout": "نفذ الوقت",
"trade_state_created": "تم الأنشاء",
"trade_state_finished": "تم",
"invalid_password": "رمز مرور خاطئ",
"unlock": "الغاء القفل",
"enter_wallet_password": "أدخل كلمة مرور المحفظة",
"repeate_wallet_password": "كرر كلمة مرور المحفظة",
"wallet_password_is_empty": "كلمة مرور المحفظة فارغة. يجب ألا تكون كلمة مرور المحفظة فارغة",
"repeated_password_is_incorrect": "كلمة المرور المتكررة غير صحيحة. يرجى إعادة كلمة مرور المحفظة مرة أخرى.",
"change_language": "تغيير اللغة",
"change_language_to": "هل تريد تغيير اللغة إلى ${language}؟",
"paste": "لصق",

View file

@ -321,6 +321,12 @@
"trade_state_timeout": "Време за изчакване",
"trade_state_created": "Създадено",
"trade_state_finished": "Завършено",
"invalid_password" : "Невалидна парола",
"unlock" : "Отключи",
"enter_wallet_password" : "Въведете паролата на портфейла",
"repeate_wallet_password" : "Повторете паролата на портфейла",
"wallet_password_is_empty" : "Паролата за Wallet е празна. Паролата за Wallet не трябва да е празна",
"repeated_password_is_incorrect" : "Повтарящата се парола е неправилна. Моля, повторете отново паролата за портфейла.",
"change_language": "Смяна на езика",
"change_language_to": "Смяна на езика на ${language}?",
"paste": "Поставяне",

View file

@ -321,6 +321,12 @@
"trade_state_timeout": "lokacin da ya ƙare",
"trade_state_created": "an halicci",
"trade_state_finished": "an kammala",
"invalid_password" : "Mot de passe incorrect",
"unlock" : "Ouvrir",
"enter_wallet_password" : "Entrez le mot de passe du portefeuille",
"repeate_wallet_password" : "Répétez le mot de passe du portefeuille",
"wallet_password_is_empty" : "Le mot de passe du portefeuille est vide. Le mot de passe du portefeuille ne doit pas être vide",
"repeated_password_is_incorrect" : "Le mot de passe répété est incorrect. Veuillez répéter le mot de passe du portefeuille.",
"change_language": "canja harshen",
"change_language_to": "canja harshen zuwa ${language}?",
"paste": "Manna",
@ -619,4 +625,3 @@
"share": "Raba",
"slidable": "Mai iya zamewa"
}

View file

@ -250,8 +250,8 @@
"transaction_details_recipient_address": "Àwọn àdírẹ́sì olùgbà",
"wallet_list_title": "Àpamọ́wọ́ Monero",
"wallet_list_create_new_wallet": "Ṣe àpamọ́wọ́ títun",
"wallet_list_edit_wallet" : "Ṣatunkọ apamọwọ",
"wallet_list_wallet_name" : "Orukọ apamọwọ",
"wallet_list_edit_wallet" : "Ṣatunkọ apamọwọ",
"wallet_list_wallet_name" : "Orukọ apamọwọ",
"wallet_list_restore_wallet": "Restore àpamọ́wọ́",
"wallet_list_load_wallet": "Load àpamọ́wọ́",
"wallet_list_loading_wallet": "Ń ṣí àpamọ́wọ́ ${wallet_name}",