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

View file

@ -66,54 +66,68 @@ class ElectrumClient {
socket!.listen((Uint8List event) { socket!.listen((Uint8List event) {
try { try {
final msg = utf8.decode(event.toList()); final msg = utf8.decode(event.toList());
final response = final messagesList = msg.split("\n");
json.decode(msg) as Map<String, dynamic>; for (var message in messagesList) {
_handleResponse(response); if (message.isEmpty) {
} on FormatException catch (e) { continue;
final msg = e.message.toLowerCase(); }
_parseResponse(message);
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 = '';
} }
} catch (e) { } catch (e) {
print(e.toString()); print(e.toString());
} }
}, onError: (Object error) { }, onError: (Object error) {
print(error.toString()); print(error.toString());
unterminatedString = '';
_setIsConnected(false); _setIsConnected(false);
}, onDone: () { }, onDone: () {
unterminatedString = '';
_setIsConnected(false); _setIsConnected(false);
}); });
keepAlive(); 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() { void keepAlive() {
_aliveTimer?.cancel(); _aliveTimer?.cancel();
_aliveTimer = Timer.periodic(aliveTimerDuration, (_) async => ping()); _aliveTimer = Timer.periodic(aliveTimerDuration, (_) async => ping());
@ -217,7 +231,7 @@ class ElectrumClient {
Future<Map<String, dynamic>> getTransactionRaw( Future<Map<String, dynamic>> getTransactionRaw(
{required String hash}) async => {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) { .then((dynamic result) {
if (result is Map<String, dynamic>) { if (result is Map<String, dynamic>) {
return result; return result;
@ -228,7 +242,7 @@ class ElectrumClient {
Future<String> getTransactionHex( Future<String> getTransactionHex(
{required String hash}) async => {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) { .then((dynamic result) {
if (result is String) { if (result is String) {
return result; return result;

View file

@ -86,5 +86,4 @@ abstract class ElectrumTransactionHistoryBase
void _update(ElectrumTransactionInfo transaction) => void _update(ElectrumTransactionInfo transaction) =>
transactions[transaction.id] = 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:cw_core/wallet_base.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
class LitecoinWalletService extends WalletService< class LitecoinWalletService extends WalletService<BitcoinNewWalletCredentials,
BitcoinNewWalletCredentials, BitcoinRestoreWalletFromSeedCredentials, BitcoinRestoreWalletFromWIFCredentials> {
BitcoinRestoreWalletFromSeedCredentials,
BitcoinRestoreWalletFromWIFCredentials> {
LitecoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource, this.isDirect); LitecoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource, this.isDirect);
final Box<WalletInfo> walletInfoSource; final Box<WalletInfo> walletInfoSource;
@ -46,10 +44,12 @@ class LitecoinWalletService extends WalletService<
@override @override
Future<LitecoinWallet> openWallet(String name, String password) async { Future<LitecoinWallet> openWallet(String name, String password) async {
final walletInfo = walletInfoSource.values.firstWhereOrNull( final walletInfo = walletInfoSource.values
(info) => info.id == WalletBase.idFor(name, getType()))!; .firstWhereOrNull((info) => info.id == WalletBase.idFor(name, getType()))!;
final wallet = await LitecoinWalletBase.open( final wallet = await LitecoinWalletBase.open(
password: password, name: name, walletInfo: walletInfo, password: password,
name: name,
walletInfo: walletInfo,
unspentCoinsInfo: unspentCoinsInfoSource, unspentCoinsInfo: unspentCoinsInfoSource,
encryptionFileUtils: encryptionFileUtilsFor(isDirect)); encryptionFileUtils: encryptionFileUtilsFor(isDirect));
await wallet.init(); await wallet.init();
@ -58,22 +58,23 @@ class LitecoinWalletService extends WalletService<
@override @override
Future<void> remove(String wallet) async { Future<void> remove(String wallet) async {
File(await pathForWalletDir(name: wallet, type: getType())) File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true);
.delete(recursive: true); final walletInfo = walletInfoSource.values
final walletInfo = walletInfoSource.values.firstWhereOrNull( .firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!;
(info) => info.id == WalletBase.idFor(wallet, getType()))!;
await walletInfoSource.delete(walletInfo.key); await walletInfoSource.delete(walletInfo.key);
} }
@override @override
Future<void> rename(String currentName, String password, String newName) async { Future<void> rename(String currentName, String password, String newName) async {
final currentWalletInfo = walletInfoSource.values.firstWhereOrNull( final currentWalletInfo = walletInfoSource.values
(info) => info.id == WalletBase.idFor(currentName, getType()))!; .firstWhereOrNull((info) => info.id == WalletBase.idFor(currentName, getType()))!;
final currentWallet = await LitecoinWalletBase.open( final currentWallet = await LitecoinWalletBase.open(
password: password, password: password,
name: currentName, name: currentName,
walletInfo: currentWalletInfo, walletInfo: currentWalletInfo,
unspentCoinsInfo: unspentCoinsInfoSource); unspentCoinsInfo: unspentCoinsInfoSource,
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
);
await currentWallet.renameWalletFiles(newName); 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 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 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 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 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 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'); 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:cw_core/monero_wallet_utils.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:cw_monero/api/wallet_manager.dart' as monero_wallet_manager; 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/api/exceptions/wallet_opening_exception.dart';
import 'package:cw_monero/monero_wallet.dart'; import 'package:cw_monero/monero_wallet.dart';
import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_credentials.dart';
@ -161,7 +160,7 @@ class MoneroWalletService extends WalletService<
String currentName, String password, String newName) async { String currentName, String password, String newName) async {
final currentWalletInfo = walletInfoSource.values.firstWhere( final currentWalletInfo = walletInfoSource.values.firstWhere(
(info) => info.id == WalletBase.idFor(currentName, getType())); (info) => info.id == WalletBase.idFor(currentName, getType()));
final currentWallet = MoneroWallet(walletInfo: currentWalletInfo); final currentWallet = MoneroWallet(walletInfo: currentWalletInfo, password: password);
await currentWallet.renameWalletFiles(newName); await currentWallet.renameWalletFiles(newName);

View file

@ -1,4 +1,7 @@
import 'dart:convert'; 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:crypto/crypto.dart';
import 'package:cake_wallet/buy/buy_exception.dart'; import 'package:cake_wallet/buy/buy_exception.dart';
import 'package:http/http.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'; import 'package:cw_core/crypto_currency.dart';
class MoonPaySellProvider { class MoonPaySellProvider {
MoonPaySellProvider({this.isTest = false}) MoonPaySellProvider({this.isTest = false}) : baseUrl = isTest ? _baseTestUrl : _baseProductUrl;
: 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 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 bool isTest;
final String baseUrl; 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( final originalUri = Uri.https(
baseUrl, '', <String, dynamic>{ baseUrl,
'apiKey': _apiKey, '',
'defaultBaseCurrencyCode': currency.toString().toLowerCase(), <String, dynamic>{
'refundWalletAddress': refundWalletAddress 'apiKey': _apiKey,
}); 'defaultBaseCurrencyCode': currency.toString().toLowerCase(),
'refundWalletAddress': refundWalletAddress
}..addAll(customParams));
final messageBytes = utf8.encode('?${originalUri.query}'); final messageBytes = utf8.encode('?${originalUri.query}');
final key = utf8.encode(_secretKey); final key = utf8.encode(_secretKey);
final hmac = Hmac(sha256, key); final hmac = Hmac(sha256, key);
@ -68,8 +96,7 @@ class MoonPayBuyProvider extends BuyProvider {
@override @override
BuyProviderDescription get description => BuyProviderDescription.moonPay; BuyProviderDescription get description => BuyProviderDescription.moonPay;
String get currencyCode => String get currencyCode => walletTypeToCryptoCurrency(walletType).title.toLowerCase();
walletTypeToCryptoCurrency(walletType).title.toLowerCase();
@override @override
String get trackUrl => baseUrl + '/transaction_receipt?transactionId='; String get trackUrl => baseUrl + '/transaction_receipt?transactionId=';
@ -78,16 +105,24 @@ class MoonPayBuyProvider extends BuyProvider {
@override @override
Future<String> requestUrl(String amount, String sourceCurrency) async { Future<String> requestUrl(String amount, String sourceCurrency) async {
final enabledPaymentMethods = final enabledPaymentMethods = 'credit_debit_card%2Capple_pay%2Cgoogle_pay%2Csamsung_pay'
'credit_debit_card%2Capple_pay%2Cgoogle_pay%2Csamsung_pay'
'%2Csepa_bank_transfer%2Cgbp_bank_transfer%2Cgbp_open_banking_payment'; '%2Csepa_bank_transfer%2Cgbp_bank_transfer%2Cgbp_open_banking_payment';
final suffix = '?apiKey=' + _apiKey + '&currencyCode=' + final suffix = '?apiKey=' +
currencyCode + '&enabledPaymentMethods=' + enabledPaymentMethods + _apiKey +
'&walletAddress=' + walletAddress + '&currencyCode=' +
'&baseCurrencyCode=' + sourceCurrency.toLowerCase() + currencyCode +
'&baseCurrencyAmount=' + amount + '&lockAmount=true' + '&enabledPaymentMethods=' +
'&showAllCurrencies=false' + '&showWalletAddressForm=false'; enabledPaymentMethods +
'&walletAddress=' +
walletAddress +
'&baseCurrencyCode=' +
sourceCurrency.toLowerCase() +
'&baseCurrencyAmount=' +
amount +
'&lockAmount=true' +
'&showAllCurrencies=false' +
'&showWalletAddressForm=false';
final originalUrl = baseUrl + suffix; final originalUrl = baseUrl + suffix;
@ -96,25 +131,28 @@ class MoonPayBuyProvider extends BuyProvider {
final hmac = Hmac(sha256, key); final hmac = Hmac(sha256, key);
final digest = hmac.convert(messageBytes); final digest = hmac.convert(messageBytes);
final signature = base64.encode(digest.bytes); final signature = base64.encode(digest.bytes);
final urlWithSignature = originalUrl + final urlWithSignature = originalUrl + '&signature=${Uri.encodeComponent(signature)}';
'&signature=${Uri.encodeComponent(signature)}';
return isTestEnvironment ? originalUrl : urlWithSignature; return isTestEnvironment ? originalUrl : urlWithSignature;
} }
@override @override
Future<BuyAmount> calculateAmount(String amount, String sourceCurrency) async { Future<BuyAmount> calculateAmount(String amount, String sourceCurrency) async {
final url = _apiUrl + _currenciesSuffix + '/$currencyCode' + final url = _apiUrl +
_quoteSuffix + '/?apiKey=' + _apiKey + _currenciesSuffix +
'&baseCurrencyAmount=' + amount + '/$currencyCode' +
'&baseCurrencyCode=' + sourceCurrency.toLowerCase(); _quoteSuffix +
'/?apiKey=' +
_apiKey +
'&baseCurrencyAmount=' +
amount +
'&baseCurrencyCode=' +
sourceCurrency.toLowerCase();
final uri = Uri.parse(url); final uri = Uri.parse(url);
final response = await get(uri); final response = await get(uri);
if (response.statusCode != 200) { if (response.statusCode != 200) {
throw BuyException( throw BuyException(description: description, text: 'Quote is not found!');
description: description,
text: 'Quote is not found!');
} }
final responseJSON = json.decode(response.body) as Map<String, dynamic>; 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; final minSourceAmount = responseJSON['baseCurrency']['minAmount'] as int;
return BuyAmount( return BuyAmount(
sourceAmount: sourceAmount, sourceAmount: sourceAmount, destAmount: destAmount, minAmount: minSourceAmount);
destAmount: destAmount,
minAmount: minSourceAmount);
} }
@override @override
Future<Order> findOrderById(String id) async { Future<Order> findOrderById(String id) async {
final url = _apiUrl + _transactionsSuffix + '/$id' + final url = _apiUrl + _transactionsSuffix + '/$id' + '?apiKey=' + _apiKey;
'?apiKey=' + _apiKey;
final uri = Uri.parse(url); final uri = Uri.parse(url);
final response = await get(uri); final response = await get(uri);
if (response.statusCode != 200) { if (response.statusCode != 200) {
throw BuyException( throw BuyException(description: description, text: 'Transaction $id is not found!');
description: description,
text: 'Transaction $id is not found!');
} }
final responseJSON = json.decode(response.body) as Map<String, dynamic>; final responseJSON = json.decode(response.body) as Map<String, dynamic>;
@ -156,8 +189,7 @@ class MoonPayBuyProvider extends BuyProvider {
createdAt: createdAt, createdAt: createdAt,
amount: amount.toString(), amount: amount.toString(),
receiveAddress: walletAddress, receiveAddress: walletAddress,
walletId: walletId walletId: walletId);
);
} }
static Future<bool> onEnabled() async { static Future<bool> onEnabled() async {
@ -176,4 +208,4 @@ class MoonPayBuyProvider extends BuyProvider {
return isBuyEnable; return isBuyEnable;
} }
} }

View file

@ -7,21 +7,19 @@ import 'package:cw_core/wallet_type.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
class WalletLoadingService { class WalletLoadingService {
WalletLoadingService( WalletLoadingService(this.sharedPreferences, this.keyService, this.walletServiceFactory);
this.sharedPreferences, this.keyService, this.walletServiceFactory);
final SharedPreferences sharedPreferences; final SharedPreferences sharedPreferences;
final KeyService keyService; final KeyService keyService;
final WalletService Function(WalletType type) walletServiceFactory; final WalletService Function(WalletType type) walletServiceFactory;
Future<void> renameWallet( Future<void> renameWallet(WalletType type, String name, String newName,
WalletType type, String name, String newName, {String? password}) async { {String? password}) async {
final walletService = walletServiceFactory.call(type); final walletService = walletServiceFactory.call(type);
final walletPassword = password ?? (await keyService.getWalletPassword(walletName: name)); final walletPassword = password ?? (await keyService.getWalletPassword(walletName: name));
// Save the current wallet's password to the new wallet name's key // Save the current wallet's password to the new wallet name's key
await keyService.saveWalletPassword( await keyService.saveWalletPassword(walletName: newName, password: walletPassword);
walletName: newName, password: walletPassword);
// Delete previous wallet name from keyService to keep only new wallet's name // Delete previous wallet name from keyService to keep only new wallet's name
// otherwise keeps duplicate (old and new names) // otherwise keeps duplicate (old and new names)
await keyService.deleteWalletPassword(walletName: name); await keyService.deleteWalletPassword(walletName: name);
@ -29,10 +27,10 @@ class WalletLoadingService {
await walletService.rename(name, walletPassword, newName); await walletService.rename(name, walletPassword, newName);
} }
Future<WalletBase> load(WalletType type, String name, {String? password}) async { Future<WalletBase> load(WalletType type, String name, {String? password}) async {
final walletService = walletServiceFactory.call(type); final walletService = walletServiceFactory.call(type);
final walletPassword = password ?? (await keyService.getWalletPassword(walletName: name)); final walletPassword = password ?? (await keyService.getWalletPassword(walletName: name));
final wallet = await walletService.openWallet(name, walletPassword); final wallet = await walletService.openWallet(name, walletPassword);
if (type == WalletType.monero) { if (type == WalletType.monero) {
await updateMoneroWalletPassword(wallet); await updateMoneroWalletPassword(wallet);
@ -53,12 +51,10 @@ class WalletLoadingService {
// Save new generated password with backup key for case where // Save new generated password with backup key for case where
// wallet will change password, but it will fail to update in secure storage // wallet will change password, but it will fail to update in secure storage
final bakWalletName = '#__${wallet.name}_bak__#'; final bakWalletName = '#__${wallet.name}_bak__#';
await keyService.saveWalletPassword( await keyService.saveWalletPassword(walletName: bakWalletName, password: password);
walletName: bakWalletName, password: password);
await wallet.changePassword(password); await wallet.changePassword(password);
await keyService.saveWalletPassword( await keyService.saveWalletPassword(walletName: wallet.name, password: password);
walletName: wallet.name, password: password);
isPasswordUpdated = true; isPasswordUpdated = true;
await sharedPreferences.setBool(key, isPasswordUpdated); 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/buy/onramper/onramper_buy_provider.dart';
import 'package:cake_wallet/core/yat_service.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_api.dart';
import 'package:cake_wallet/anonpay/anonpay_info_base.dart'; import 'package:cake_wallet/anonpay/anonpay_info_base.dart';
import 'package:cake_wallet/anonpay/anonpay_invoice_info.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/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/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/entities/receive_page_option.dart';
import 'package:cake_wallet/ionia/ionia_anypay.dart'; import 'package:cake_wallet/ionia/ionia_anypay.dart';
import 'package:cake_wallet/ionia/ionia_gift_card.dart'; import 'package:cake_wallet/ionia/ionia_gift_card.dart';
import 'package:cake_wallet/ionia/ionia_tip.dart'; import 'package:cake_wallet/ionia/ionia_tip.dart';
import 'package:cake_wallet/routes.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/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/desktop_widgets/desktop_wallet_selection_dropdown.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/transactions_page.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_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_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_invoice_page.dart';
import 'package:cake_wallet/src/screens/receive/anonpay_receive_page.dart'; import 'package:cake_wallet/src/screens/receive/anonpay_receive_page.dart';
import 'package:cake_wallet/src/screens/settings/display_settings_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.dart';
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_enter_code_page.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/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/utils/device_info.dart';
import 'package:cake_wallet/store/anonpay/anonpay_transactions_store.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/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/receive_option_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_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_loadable_view_model.dart';
import 'package:cake_wallet/view_model/wallet_unlock_verifiable_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:cw_core/unspent_coins_info.dart';
import 'package:cake_wallet/core/backup_service.dart'; import 'package:cake_wallet/core/backup_service.dart';
import 'package:cw_core/wallet_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_restore_view_model.dart';
import 'package:cake_wallet/view_model/wallet_seed_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:cake_wallet/view_model/exchange/exchange_view_model.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:get_it/get_it.dart'; import 'package:get_it/get_it.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
@ -709,15 +697,13 @@ Future setup({
wallet: getIt.get<AppStore>().wallet!, 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( getIt.registerFactory<PayfuraBuyProvider>(() => PayfuraBuyProvider(
settingsStore: getIt.get<AppStore>().settingsStore, settingsStore: getIt.get<AppStore>().settingsStore,
wallet: getIt.get<AppStore>().wallet!, wallet: getIt.get<AppStore>().wallet!,
)); ));
getIt.registerFactory(() => PayFuraPage(getIt.get<PayfuraBuyProvider>()));
getIt.registerFactory(() => ExchangeViewModel( getIt.registerFactory(() => ExchangeViewModel(
getIt.get<AppStore>().wallet!, getIt.get<AppStore>().wallet!,
_tradesSource, _tradesSource,

View file

@ -48,10 +48,11 @@ class MainActions {
case WalletType.bitcoin: case WalletType.bitcoin:
case WalletType.litecoin: case WalletType.litecoin:
if (viewModel.isEnabledBuyAction) { if (viewModel.isEnabledBuyAction) {
final uri = getIt.get<OnRamperBuyProvider>().requestUrl();
if (DeviceInfo.instance.isMobile) { if (DeviceInfo.instance.isMobile) {
Navigator.of(context).pushNamed(Routes.onramperPage); Navigator.of(context)
.pushNamed(Routes.webViewPage, arguments: [S.of(context).buy, uri]);
} else { } else {
final uri = getIt.get<OnRamperBuyProvider>().requestUrl();
await launchUrl(uri); await launchUrl(uri);
} }
} }
@ -118,14 +119,22 @@ class MainActions {
switch (walletType) { switch (walletType) {
case WalletType.bitcoin: case WalletType.bitcoin:
case WalletType.litecoin:
if (viewModel.isEnabledSellAction) { if (viewModel.isEnabledSellAction) {
final moonPaySellProvider = MoonPaySellProvider(); final moonPaySellProvider = MoonPaySellProvider();
final uri = await moonPaySellProvider.requestUrl( final uri = await moonPaySellProvider.requestUrl(
currency: viewModel.wallet.currency, currency: viewModel.wallet.currency,
refundWalletAddress: viewModel.wallet.walletAddresses.address, 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; break;
default: default:
await showPopUp<void>( 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/exception_handler.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:cw_core/root_dir.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/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.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/backup_page.dart';
import 'package:cake_wallet/src/screens/backup/edit_backup_password_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/buy_webview_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/buy/payfura_page.dart';
import 'package:cake_wallet/src/screens/buy/pre_order_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/restore/sweeping_wallet_page.dart';
import 'package:cake_wallet/src/screens/receive/anonpay_invoice_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/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/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/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:cake_wallet/wallet_type_utils.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -564,11 +562,13 @@ Route<dynamic> createRoute(RouteSettings settings) {
param1: paymentInfo, param1: paymentInfo,
param2: commitedInfo)); param2: commitedInfo));
case Routes.onramperPage: case Routes.webViewPage:
return CupertinoPageRoute<void>(builder: (_) => getIt.get<OnRamperPage>()); final args = settings.arguments as List;
final title = args.first as String;
case Routes.payfuraPage: final url = args[1] as Uri;
return CupertinoPageRoute<void>(builder: (_) => getIt.get<PayFuraPage>()); return CupertinoPageRoute<void>(builder: (_) => getIt.get<WebViewPage>(
param1: title,
param2: url));
case Routes.advancedPrivacySettings: case Routes.advancedPrivacySettings:
final type = settings.arguments as WalletType; final type = settings.arguments as WalletType;

View file

@ -71,7 +71,7 @@ class Routes {
static const ioniaPaymentStatusPage = '/ionia_payment_status_page'; static const ioniaPaymentStatusPage = '/ionia_payment_status_page';
static const ioniaMoreOptionsPage = '/ionia_more_options_page'; static const ioniaMoreOptionsPage = '/ionia_more_options_page';
static const ioniaCustomRedeemPage = '/ionia_custom_redeem_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 connectionSync = '/connection_sync_page';
static const securityBackupPage = '/security_and_backup_page'; static const securityBackupPage = '/security_and_backup_page';
static const privacyPage = '/privacy_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:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
class OnRamperPage extends BasePage { class WebViewPage extends BasePage {
OnRamperPage(this._onRamperBuyProvider); WebViewPage(this._title, this._url);
final OnRamperBuyProvider _onRamperBuyProvider; final String _title;
final Uri _url;
@override @override
String get title => S.current.buy; String get title => _title;
@override @override
Widget body(BuildContext context) { Widget body(BuildContext context) {
return OnRamperPageBody(_onRamperBuyProvider); return WebViewPageBody(_url);
} }
} }
class OnRamperPageBody extends StatefulWidget { class WebViewPageBody extends StatefulWidget {
OnRamperPageBody(this.onRamperBuyProvider); WebViewPageBody(this.uri);
final OnRamperBuyProvider onRamperBuyProvider; final Uri uri;
Uri get uri => onRamperBuyProvider.requestUrl();
@override @override
OnRamperPageBodyState createState() => OnRamperPageBodyState(); WebViewPageBodyState createState() => WebViewPageBodyState();
} }
class OnRamperPageBodyState extends State<OnRamperPageBody> { class WebViewPageBodyState extends State<WebViewPageBody> {
OnRamperPageBodyState(); WebViewPageBodyState();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View file

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

View file

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

View file

@ -45,9 +45,11 @@ class TransactionsPage extends StatelessWidget {
return Padding( return Padding(
padding: const EdgeInsets.fromLTRB(24, 0, 24, 8), padding: const EdgeInsets.fromLTRB(24, 0, 24, 8),
child: DashBoardRoundedCardWidget( child: DashBoardRoundedCardWidget(
onTap: () => Navigator.of(context).pushNamed( onTap: () => Navigator.of(context).pushNamed(Routes.webViewPage, arguments: [
Routes.webViewPage, '',
arguments: ['', Uri.parse('https://guides.cakewallet.com/docs/bugs-service-status/why_are_my_funds_not_appearing/')]), Uri.parse(
'https://guides.cakewallet.com/docs/bugs-service-status/why_are_my_funds_not_appearing/')
]),
title: S.of(context).syncing_wallet_alert_title, title: S.of(context).syncing_wallet_alert_title,
subTitle: S.of(context).syncing_wallet_alert_content, subTitle: S.of(context).syncing_wallet_alert_content,
), ),
@ -60,96 +62,97 @@ class TransactionsPage extends StatelessWidget {
Expanded(child: Observer(builder: (_) { Expanded(child: Observer(builder: (_) {
final items = dashboardViewModel.items; final items = dashboardViewModel.items;
return items.isNotEmpty return items.isNotEmpty
? ListView.builder( ? ListView.builder(
itemCount: items.length, itemCount: items.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final item = items[index]; final item = items[index];
if (item is DateSectionItem) { if (item is DateSectionItem) {
return DateSectionRaw(date: item.date); return DateSectionRaw(date: item.date);
} }
if (item is TransactionListItem) { if (item is TransactionListItem) {
final transaction = item.transaction; final transaction = item.transaction;
return Observer( return Observer(
builder: (_) => TransactionRow( 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(
onTap: () => Navigator.of(context) onTap: () => Navigator.of(context)
.pushNamed(Routes.orderDetails, arguments: order), .pushNamed(Routes.transactionDetails, arguments: transaction),
provider: order.provider, direction: transaction.direction,
from: order.from!, formattedDate: DateFormat('HH:mm').format(transaction.date),
to: order.to!, formattedAmount: item.formattedCryptoAmount,
createdAtFormattedDate: formattedFiatAmount:
DateFormat('HH:mm').format(order.createdAt), dashboardViewModel.balanceViewModel.isFiatDisabled
formattedAmount: item.orderFormattedAmount, ? ''
)); : item.formattedFiatAmount,
} isPending: transaction.isPending,
title: item.formattedTitle + item.formattedStatus));
}
return Container(color: Colors.transparent, height: 1); if (item is AnonpayTransactionListItem) {
}) final transactionInfo = item.transaction;
: Center(
child: Text( return AnonpayTransactionRow(
S.of(context).placeholder_transactions, onTap: () => Navigator.of(context)
style: TextStyle( .pushNamed(Routes.anonPayDetailsPage, arguments: transactionInfo),
fontSize: 14, currency: transactionInfo.fiatAmount != null
color: Theme.of(context).primaryTextTheme!.labelSmall!.decorationColor!), ? 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 final _closeButton = currentTheme.type == ThemeType.dark
? closeButtonImageDarkTheme : closeButtonImage; ? closeButtonImageDarkTheme : closeButtonImage;
bool isMobileView = ResponsiveLayoutUtil.instance.isMobile(context); bool isMobileView = ResponsiveLayoutUtil.instance.isMobile;
return MergeSemantics( return MergeSemantics(
child: SizedBox( child: SizedBox(
@ -733,7 +733,7 @@ class ExchangePage extends BasePage {
}, },
)); ));
if (ResponsiveLayoutUtil.instance.isMobile(context)) { if (ResponsiveLayoutUtil.instance.isMobile) {
return MobileExchangeCardsSection( return MobileExchangeCardsSection(
firstExchangeCard: firstExchangeCard, firstExchangeCard: firstExchangeCard,
secondExchangeCard: secondExchangeCard, secondExchangeCard: secondExchangeCard,

View file

@ -40,6 +40,7 @@ class AnonPayInvoicePage extends BasePage {
final _formKey = GlobalKey<FormState>(); final _formKey = GlobalKey<FormState>();
bool effectsInstalled = false; bool effectsInstalled = false;
@override @override
Color get titleColor => Colors.white; Color get titleColor => Colors.white;
@ -82,34 +83,33 @@ class AnonPayInvoicePage extends BasePage {
disableScroll: true, disableScroll: true,
config: KeyboardActionsConfig( config: KeyboardActionsConfig(
keyboardActionsPlatform: KeyboardActionsPlatform.IOS, keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
keyboardBarColor: Theme.of(context) keyboardBarColor: Theme.of(context).accentTextTheme!.bodyLarge!.backgroundColor!,
.accentTextTheme! nextFocus: false,
.bodyLarge! actions: [
.backgroundColor!, KeyboardActionsItem(
nextFocus: false, focusNode: _amountFocusNode,
actions: [ toolbarButtons: [(_) => KeyboardDoneButton()],
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,
), ),
) : 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: (_) { child: Observer(builder: (_) {
return Padding( return Padding(
padding: EdgeInsets.fromLTRB(24, 120, 24, 0), padding: EdgeInsets.fromLTRB(24, 120, 24, 0),
@ -142,12 +142,10 @@ class AnonPayInvoicePage extends BasePage {
: S.of(context).anonpay_description("a donation link", "donate"), : S.of(context).anonpay_description("a donation link", "donate"),
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
color: Theme.of(context) color:
.primaryTextTheme! Theme.of(context).primaryTextTheme!.displayLarge!.decorationColor!,
.displayLarge! fontWeight: FontWeight.w500,
.decorationColor!, fontSize: 12),
fontWeight: FontWeight.w500,
fontSize: 12),
), ),
), ),
), ),
@ -173,10 +171,7 @@ class AnonPayInvoicePage extends BasePage {
anonInvoicePageViewModel.generateDonationLink(); anonInvoicePageViewModel.generateDonationLink();
} }
}, },
color: Theme.of(context) color: Theme.of(context).accentTextTheme!.bodyLarge!.color!,
.accentTextTheme!
.bodyLarge!
.color!,
textColor: Colors.white, textColor: Colors.white,
isLoading: anonInvoicePageViewModel.state is IsExecutingState, isLoading: anonInvoicePageViewModel.state is IsExecutingState,
), ),

View file

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

View file

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

View file

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

View file

@ -1,5 +1,5 @@
import 'dart:io'; 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 } 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/auth_service.dart';
import 'package:cake_wallet/core/wallet_loading_service.dart'; import 'package:cake_wallet/core/wallet_loading_service.dart';
import 'package:cw_core/wallet_base.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:hive/hive.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/store/app_store.dart';

View file

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

View file

@ -1,7 +1,7 @@
PODS: PODS:
- connectivity_macos (0.0.1): - connectivity_plus_macos (0.0.1):
- FlutterMacOS - FlutterMacOS
- Reachability - ReachabilitySwift
- cw_monero (0.0.1): - cw_monero (0.0.1):
- cw_monero/Boost (= 0.0.1) - cw_monero/Boost (= 0.0.1)
- cw_monero/Monero (= 0.0.1) - cw_monero/Monero (= 0.0.1)
@ -28,7 +28,7 @@ PODS:
- FlutterMacOS (1.0.0) - FlutterMacOS (1.0.0)
- in_app_review (0.2.0): - in_app_review (0.2.0):
- FlutterMacOS - FlutterMacOS
- package_info_plus (0.0.1): - package_info (0.0.1):
- FlutterMacOS - FlutterMacOS
- path_provider_foundation (0.0.1): - path_provider_foundation (0.0.1):
- Flutter - Flutter
@ -37,7 +37,7 @@ PODS:
- FlutterMacOS - FlutterMacOS
- platform_device_id_macos (0.0.1): - platform_device_id_macos (0.0.1):
- FlutterMacOS - FlutterMacOS
- Reachability (3.2) - ReachabilitySwift (5.0.0)
- share_plus_macos (0.0.1): - share_plus_macos (0.0.1):
- FlutterMacOS - FlutterMacOS
- shared_preferences_foundation (0.0.1): - shared_preferences_foundation (0.0.1):
@ -49,14 +49,14 @@ PODS:
- FlutterMacOS - FlutterMacOS
DEPENDENCIES: 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`) - cw_monero (from `Flutter/ephemeral/.symlinks/plugins/cw_monero/macos`)
- device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`) - device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`)
- devicelocale (from `Flutter/ephemeral/.symlinks/plugins/devicelocale/macos`) - devicelocale (from `Flutter/ephemeral/.symlinks/plugins/devicelocale/macos`)
- flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`) - flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`)
- FlutterMacOS (from `Flutter/ephemeral`) - FlutterMacOS (from `Flutter/ephemeral`)
- in_app_review (from `Flutter/ephemeral/.symlinks/plugins/in_app_review/macos`) - 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`) - 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 (from `Flutter/ephemeral/.symlinks/plugins/platform_device_id/macos`)
- platform_device_id_macos (from `Flutter/ephemeral/.symlinks/plugins/platform_device_id_macos/macos`) - platform_device_id_macos (from `Flutter/ephemeral/.symlinks/plugins/platform_device_id_macos/macos`)
@ -67,11 +67,11 @@ DEPENDENCIES:
SPEC REPOS: SPEC REPOS:
trunk: trunk:
- Reachability - ReachabilitySwift
EXTERNAL SOURCES: EXTERNAL SOURCES:
connectivity_macos: connectivity_plus_macos:
:path: Flutter/ephemeral/.symlinks/plugins/connectivity_macos/macos :path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus_macos/macos
cw_monero: cw_monero:
:path: Flutter/ephemeral/.symlinks/plugins/cw_monero/macos :path: Flutter/ephemeral/.symlinks/plugins/cw_monero/macos
device_info_plus: device_info_plus:
@ -84,8 +84,8 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral :path: Flutter/ephemeral
in_app_review: in_app_review:
:path: Flutter/ephemeral/.symlinks/plugins/in_app_review/macos :path: Flutter/ephemeral/.symlinks/plugins/in_app_review/macos
package_info_plus: package_info:
:path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos :path: Flutter/ephemeral/.symlinks/plugins/package_info/macos
path_provider_foundation: path_provider_foundation:
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/macos
platform_device_id: platform_device_id:
@ -102,23 +102,23 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/wakelock_macos/macos :path: Flutter/ephemeral/.symlinks/plugins/wakelock_macos/macos
SPEC CHECKSUMS: SPEC CHECKSUMS:
connectivity_macos: 5dae6ee11d320fac7c05f0d08bd08fc32b5514d9 connectivity_plus_macos: f6e86fd000e971d361e54b5afcadc8c8fa773308
cw_monero: ec03de55a19c4a2b174ea687e0f4202edc716fa4 cw_monero: ec03de55a19c4a2b174ea687e0f4202edc716fa4
device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f
devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225 devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225
flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
in_app_review: a850789fad746e89bce03d4aeee8078b45a53fd0 in_app_review: a850789fad746e89bce03d4aeee8078b45a53fd0
package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce package_info: 6eba2fd8d3371dda2d85c8db6fe97488f24b74b2
path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9 path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
platform_device_id: 3e414428f45df149bbbfb623e2c0ca27c545b763 platform_device_id: 3e414428f45df149bbbfb623e2c0ca27c545b763
platform_device_id_macos: f763bb55f088be804d61b96eb4710b8ab6598e94 platform_device_id_macos: f763bb55f088be804d61b96eb4710b8ab6598e94
Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96 ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4 share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126 shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
url_launcher_macos: 5335912b679c073563f29d89d33d10d459f95451 url_launcher_macos: 5335912b679c073563f29d89d33d10d459f95451
wakelock_macos: bc3f2a9bd8d2e6c89fee1e1822e7ddac3bd004a9 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_timeout": "نفذ الوقت",
"trade_state_created": "تم الأنشاء", "trade_state_created": "تم الأنشاء",
"trade_state_finished": "تم", "trade_state_finished": "تم",
"invalid_password": "رمز مرور خاطئ",
"unlock": "الغاء القفل",
"enter_wallet_password": "أدخل كلمة مرور المحفظة",
"repeate_wallet_password": "كرر كلمة مرور المحفظة",
"wallet_password_is_empty": "كلمة مرور المحفظة فارغة. يجب ألا تكون كلمة مرور المحفظة فارغة",
"repeated_password_is_incorrect": "كلمة المرور المتكررة غير صحيحة. يرجى إعادة كلمة مرور المحفظة مرة أخرى.",
"change_language": "تغيير اللغة", "change_language": "تغيير اللغة",
"change_language_to": "هل تريد تغيير اللغة إلى ${language}؟", "change_language_to": "هل تريد تغيير اللغة إلى ${language}؟",
"paste": "لصق", "paste": "لصق",

View file

@ -321,6 +321,12 @@
"trade_state_timeout": "Време за изчакване", "trade_state_timeout": "Време за изчакване",
"trade_state_created": "Създадено", "trade_state_created": "Създадено",
"trade_state_finished": "Завършено", "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": "Смяна на езика",
"change_language_to": "Смяна на езика на ${language}?", "change_language_to": "Смяна на езика на ${language}?",
"paste": "Поставяне", "paste": "Поставяне",

View file

@ -321,6 +321,12 @@
"trade_state_timeout": "lokacin da ya ƙare", "trade_state_timeout": "lokacin da ya ƙare",
"trade_state_created": "an halicci", "trade_state_created": "an halicci",
"trade_state_finished": "an kammala", "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": "canja harshen",
"change_language_to": "canja harshen zuwa ${language}?", "change_language_to": "canja harshen zuwa ${language}?",
"paste": "Manna", "paste": "Manna",
@ -619,4 +625,3 @@
"share": "Raba", "share": "Raba",
"slidable": "Mai iya zamewa" "slidable": "Mai iya zamewa"
} }

View file

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