Merge remote-tracking branch 'origin/main' into CW-453-silent-payments

This commit is contained in:
Rafael Saes 2024-05-09 07:37:58 -03:00
commit b7c942ac4e
70 changed files with 472 additions and 332 deletions

1
.gitignore vendored
View file

@ -156,6 +156,7 @@ assets/images/app_logo.png
macos/Runner/Info.plist macos/Runner/Info.plist
macos/Runner/DebugProfile.entitlements macos/Runner/DebugProfile.entitlements
macos/Runner/Release.entitlements macos/Runner/Release.entitlements
lib/core/secure_storage.dart
macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png

View file

@ -1 +1,4 @@
Bitcoin Bug fixes and enhancements Hardware wallets support for Bitcoin, Ethereum and Polygon
Add Tron wallet
Security enhancements
Bug fixes and generic enhancements

View file

@ -1,8 +1,8 @@
- -
uri: api.trongrid.io uri: tron-rpc.publicnode.com:443
is_default: true is_default: true
useSSL: true useSSL: true
- -
uri: tron-rpc.publicnode.com:443 uri: api.trongrid.io
is_default: false is_default: false
useSSL: true useSSL: true

View file

@ -524,7 +524,7 @@ abstract class SolanaWalletBase
_transactionsUpdateTimer!.cancel(); _transactionsUpdateTimer!.cancel();
} }
_transactionsUpdateTimer = Timer.periodic(const Duration(seconds: 20), (_) { _transactionsUpdateTimer = Timer.periodic(const Duration(seconds: 30), (_) {
_updateBalance(); _updateBalance();
_updateNativeSOLTransactions(); _updateNativeSOLTransactions();
_updateSPLTokenTransactions(); _updateSPLTokenTransactions();

View file

@ -22,14 +22,14 @@ class DefaultTronTokens {
symbol: "BTC", symbol: "BTC",
contractAddress: "TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9", contractAddress: "TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9",
decimal: 8, decimal: 8,
enabled: true, enabled: false,
), ),
TronToken( TronToken(
name: "Ethereum", name: "Ethereum",
symbol: "ETH", symbol: "ETH",
contractAddress: "TRFe3hT5oYhjSZ6f3ji5FJ7YCfrkWnHRvh", contractAddress: "TRFe3hT5oYhjSZ6f3ji5FJ7YCfrkWnHRvh",
decimal: 18, decimal: 18,
enabled: true, enabled: false,
), ),
TronToken( TronToken(
name: "Wrapped BTC", name: "Wrapped BTC",

View file

@ -19,7 +19,7 @@ class TronHTTPProvider implements TronServiceProvider {
Future<Map<String, dynamic>> get(TronRequestDetails params, [Duration? timeout]) async { Future<Map<String, dynamic>> get(TronRequestDetails params, [Duration? timeout]) async {
final response = await client.get(Uri.parse(params.url(url)), headers: { final response = await client.get(Uri.parse(params.url(url)), headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'TRON-PRO-API-KEY': secrets.tronGridApiKey, if (url.contains("trongrid")) 'TRON-PRO-API-KEY': secrets.tronGridApiKey,
}).timeout(timeout ?? defaultRequestTimeout); }).timeout(timeout ?? defaultRequestTimeout);
final data = json.decode(response.body) as Map<String, dynamic>; final data = json.decode(response.body) as Map<String, dynamic>;
return data; return data;
@ -31,7 +31,7 @@ class TronHTTPProvider implements TronServiceProvider {
.post(Uri.parse(params.url(url)), .post(Uri.parse(params.url(url)),
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'TRON-PRO-API-KEY': secrets.tronGridApiKey, if (url.contains("trongrid")) 'TRON-PRO-API-KEY': secrets.tronGridApiKey,
}, },
body: params.toRequestBody()) body: params.toRequestBody())
.timeout(timeout ?? defaultRequestTimeout); .timeout(timeout ?? defaultRequestTimeout);

View file

@ -31,7 +31,6 @@ import 'package:cw_tron/tron_wallet_addresses.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
import 'package:on_chain/on_chain.dart'; import 'package:on_chain/on_chain.dart';
import 'package:shared_preferences/shared_preferences.dart';
part 'tron_wallet.g.dart'; part 'tron_wallet.g.dart';
@ -61,8 +60,6 @@ abstract class TronWalletBase
if (!CakeHive.isAdapterRegistered(TronToken.typeId)) { if (!CakeHive.isAdapterRegistered(TronToken.typeId)) {
CakeHive.registerAdapter(TronTokenAdapter()); CakeHive.registerAdapter(TronTokenAdapter());
} }
sharedPrefs.complete(SharedPreferences.getInstance());
} }
final String? _mnemonic; final String? _mnemonic;
@ -81,7 +78,7 @@ abstract class TronWalletBase
late String _tronAddress; late String _tronAddress;
late TronClient _client; late final TronClient _client;
Timer? _transactionsUpdateTimer; Timer? _transactionsUpdateTimer;
@ -102,8 +99,6 @@ abstract class TronWalletBase
@observable @observable
late ObservableMap<CryptoCurrency, TronBalance> balance; late ObservableMap<CryptoCurrency, TronBalance> balance;
Completer<SharedPreferences> sharedPrefs = Completer();
Future<void> init() async { Future<void> init() async {
await initTronTokensBox(); await initTronTokensBox();
@ -464,6 +459,7 @@ abstract class TronWalletBase
} }
} }
@override
Future<void>? updateBalance() async => await _updateBalance(); Future<void>? updateBalance() async => await _updateBalance();
List<TronToken> get tronTokenCurrencies => tronTokensBox.values.toList(); List<TronToken> get tronTokenCurrencies => tronTokensBox.values.toList();
@ -543,7 +539,7 @@ abstract class TronWalletBase
_transactionsUpdateTimer!.cancel(); _transactionsUpdateTimer!.cancel();
} }
_transactionsUpdateTimer = Timer.periodic(const Duration(seconds: 20), (_) async { _transactionsUpdateTimer = Timer.periodic(const Duration(seconds: 30), (_) async {
_updateBalance(); _updateBalance();
await fetchTransactions(); await fetchTransactions();
fetchTrc20ExcludedTransactions(); fetchTrc20ExcludedTransactions();
@ -557,4 +553,14 @@ abstract class TronWalletBase
String getTronBase58AddressFromHex(String hexAddress) { String getTronBase58AddressFromHex(String hexAddress) {
return TronAddress(hexAddress).toAddress(); return TronAddress(hexAddress).toAddress();
} }
void updateScanProviderUsageState(bool isEnabled) {
if (isEnabled) {
fetchTransactions();
fetchTrc20ExcludedTransactions();
_setTransactionUpdateTimer();
} else {
_transactionsUpdateTimer?.cancel();
}
}
} }

View file

@ -21,6 +21,6 @@
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.0</string> <string>1.0</string>
<key>MinimumOSVersion</key> <key>MinimumOSVersion</key>
<string>11.0</string> <string>12.0</string>
</dict> </dict>
</plist> </plist>

View file

@ -109,6 +109,8 @@ PODS:
- flutter_inappwebview_ios/Core (0.0.1): - flutter_inappwebview_ios/Core (0.0.1):
- Flutter - Flutter
- OrderedSet (~> 5.0) - OrderedSet (~> 5.0)
- flutter_local_authentication (1.2.0):
- Flutter
- flutter_mailer (0.0.1): - flutter_mailer (0.0.1):
- Flutter - Flutter
- flutter_secure_storage (6.0.0): - flutter_secure_storage (6.0.0):
@ -118,8 +120,6 @@ PODS:
- Toast - Toast
- in_app_review (0.2.0): - in_app_review (0.2.0):
- Flutter - Flutter
- local_auth_ios (0.0.1):
- Flutter
- MTBBarcodeScanner (5.0.11) - MTBBarcodeScanner (5.0.11)
- OrderedSet (5.0.0) - OrderedSet (5.0.0)
- package_info (0.0.1): - package_info (0.0.1):
@ -175,11 +175,11 @@ DEPENDENCIES:
- file_picker (from `.symlinks/plugins/file_picker/ios`) - file_picker (from `.symlinks/plugins/file_picker/ios`)
- Flutter (from `Flutter`) - Flutter (from `Flutter`)
- flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`) - flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`)
- flutter_local_authentication (from `.symlinks/plugins/flutter_local_authentication/ios`)
- flutter_mailer (from `.symlinks/plugins/flutter_mailer/ios`) - flutter_mailer (from `.symlinks/plugins/flutter_mailer/ios`)
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
- in_app_review (from `.symlinks/plugins/in_app_review/ios`) - in_app_review (from `.symlinks/plugins/in_app_review/ios`)
- local_auth_ios (from `.symlinks/plugins/local_auth_ios/ios`)
- package_info (from `.symlinks/plugins/package_info/ios`) - package_info (from `.symlinks/plugins/package_info/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
@ -233,6 +233,8 @@ EXTERNAL SOURCES:
:path: Flutter :path: Flutter
flutter_inappwebview_ios: flutter_inappwebview_ios:
:path: ".symlinks/plugins/flutter_inappwebview_ios/ios" :path: ".symlinks/plugins/flutter_inappwebview_ios/ios"
flutter_local_authentication:
:path: ".symlinks/plugins/flutter_local_authentication/ios"
flutter_mailer: flutter_mailer:
:path: ".symlinks/plugins/flutter_mailer/ios" :path: ".symlinks/plugins/flutter_mailer/ios"
flutter_secure_storage: flutter_secure_storage:
@ -241,8 +243,6 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/fluttertoast/ios" :path: ".symlinks/plugins/fluttertoast/ios"
in_app_review: in_app_review:
:path: ".symlinks/plugins/in_app_review/ios" :path: ".symlinks/plugins/in_app_review/ios"
local_auth_ios:
:path: ".symlinks/plugins/local_auth_ios/ios"
package_info: package_info:
:path: ".symlinks/plugins/package_info/ios" :path: ".symlinks/plugins/package_info/ios"
package_info_plus: package_info_plus:
@ -282,18 +282,18 @@ SPEC CHECKSUMS:
DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac
DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179 DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179
file_picker: 15fd9539e4eb735dc54bae8c0534a7a9511a03de file_picker: 15fd9539e4eb735dc54bae8c0534a7a9511a03de
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_inappwebview_ios: 97215cf7d4677db55df76782dbd2930c5e1c1ea0 flutter_inappwebview_ios: 97215cf7d4677db55df76782dbd2930c5e1c1ea0
flutter_local_authentication: 1172a4dd88f6306dadce067454e2c4caf07977bb
flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83 flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
fluttertoast: 48c57db1b71b0ce9e6bba9f31c940ff4b001293c fluttertoast: 48c57db1b71b0ce9e6bba9f31c940ff4b001293c
in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d
local_auth_ios: 1ba1475238daa33a6ffa2a29242558437be435ac
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62 package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85 package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6 permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6
Protobuf: 8e9074797a13c484a79959fdb819ef4ae6da7dbe Protobuf: 8e9074797a13c484a79959fdb819ef4ae6da7dbe
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
@ -301,13 +301,13 @@ SPEC CHECKSUMS:
SDWebImage: a3ba0b8faac7228c3c8eadd1a55c9c9fe5e16457 SDWebImage: a3ba0b8faac7228c3c8eadd1a55c9c9fe5e16457
sensitive_clipboard: d4866e5d176581536c27bb1618642ee83adca986 sensitive_clipboard: d4866e5d176581536c27bb1618642ee83adca986
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68 share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695 shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
SwiftProtobuf: 407a385e97fd206c4fbe880cc84123989167e0d1 SwiftProtobuf: 407a385e97fd206c4fbe880cc84123989167e0d1
SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f
Toast: ec33c32b8688982cecc6348adeae667c1b9938da Toast: ec33c32b8688982cecc6348adeae667c1b9938da
uni_links: d97da20c7701486ba192624d99bffaaffcfc298a uni_links: d97da20c7701486ba192624d99bffaaffcfc298a
UnstoppableDomainsResolution: c3c67f4d0a5e2437cb00d4bd50c2e00d6e743841 UnstoppableDomainsResolution: c3c67f4d0a5e2437cb00d4bd50c2e00d6e743841
url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812 url_launcher_ios: 6116280ddcfe98ab8820085d8d76ae7449447586
wakelock_plus: 8b09852c8876491e4b6d179e17dfe2a0b5f60d47 wakelock_plus: 8b09852c8876491e4b6d179e17dfe2a0b5f60d47
workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6 workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6

View file

@ -1,5 +1,4 @@
import 'dart:async'; import 'dart:async';
import 'dart:io';
import 'package:cake_wallet/core/secure_storage.dart'; import 'package:cake_wallet/core/secure_storage.dart';
import 'package:cake_wallet/core/totp_request_details.dart'; import 'package:cake_wallet/core/totp_request_details.dart';
@ -7,7 +6,6 @@ import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/auth/auth_page.dart'; import 'package:cake_wallet/src/screens/auth/auth_page.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/preferences_key.dart';
import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:cake_wallet/entities/secret_store_key.dart';
@ -35,14 +33,14 @@ class AuthService with Store {
Routes.restoreOptions, Routes.restoreOptions,
]; ];
final FlutterSecureStorage secureStorage; final SecureStorage secureStorage;
final SharedPreferences sharedPreferences; final SharedPreferences sharedPreferences;
final SettingsStore settingsStore; final SettingsStore settingsStore;
Future<void> setPassword(String password) async { Future<void> setPassword(String password) async {
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
final encodedPassword = encodedPinCode(pin: password); final encodedPassword = encodedPinCode(pin: password);
await writeSecureStorage(secureStorage, key: key, value: encodedPassword); await secureStorage.write(key: key, value: encodedPassword);
} }
Future<bool> canAuthenticate() async { Future<bool> canAuthenticate() async {
@ -61,7 +59,7 @@ class AuthService with Store {
Future<bool> authenticate(String pin) async { Future<bool> authenticate(String pin) async {
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
final encodedPin = await readSecureStorage(secureStorage, key); final encodedPin = await secureStorage.read(key: key);
final decodedPin = decodedPinCode(pin: encodedPin!); final decodedPin = decodedPinCode(pin: encodedPin!);
return decodedPin == pin; return decodedPin == pin;
@ -69,11 +67,7 @@ class AuthService with Store {
void saveLastAuthTime() { void saveLastAuthTime() {
int timestamp = DateTime.now().millisecondsSinceEpoch; int timestamp = DateTime.now().millisecondsSinceEpoch;
writeSecureStorage( secureStorage.write(key: SecureKey.lastAuthTimeMilliseconds, value: timestamp.toString());
secureStorage,
key: SecureKey.lastAuthTimeMilliseconds,
value: timestamp.toString(),
);
} }
Future<bool> requireAuth() async { Future<bool> requireAuth() async {

View file

@ -7,7 +7,6 @@ import 'package:cake_wallet/utils/device_info.dart';
import 'package:cw_core/wallet_type.dart'; import 'package:cw_core/wallet_type.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:cryptography/cryptography.dart'; import 'package:cryptography/cryptography.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
@ -25,7 +24,7 @@ import 'package:cake_backup/backup.dart' as cake_backup;
class BackupService { class BackupService {
BackupService( BackupService(
this._flutterSecureStorage, this._walletInfoSource, this._keyService, this._sharedPreferences) this._secureStorage, this._walletInfoSource, this._keyService, this._sharedPreferences)
: _cipher = Cryptography.instance.chacha20Poly1305Aead(), : _cipher = Cryptography.instance.chacha20Poly1305Aead(),
_correctWallets = <WalletInfo>[]; _correctWallets = <WalletInfo>[];
@ -35,7 +34,7 @@ class BackupService {
static const _v2 = 2; static const _v2 = 2;
final Cipher _cipher; final Cipher _cipher;
final FlutterSecureStorage _flutterSecureStorage; final SecureStorage _secureStorage;
final SharedPreferences _sharedPreferences; final SharedPreferences _sharedPreferences;
final Box<WalletInfo> _walletInfoSource; final Box<WalletInfo> _walletInfoSource;
final KeyService _keyService; final KeyService _keyService;
@ -374,15 +373,14 @@ class BackupService {
final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword); final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
final backupPassword = keychainJSON[backupPasswordKey] as String; final backupPassword = keychainJSON[backupPasswordKey] as String;
await writeSecureStorage(_flutterSecureStorage, key: backupPasswordKey, value: backupPassword); await _secureStorage.write(key: backupPasswordKey, value: backupPassword);
keychainWalletsInfo.forEach((dynamic rawInfo) async { keychainWalletsInfo.forEach((dynamic rawInfo) async {
final info = rawInfo as Map<String, dynamic>; final info = rawInfo as Map<String, dynamic>;
await importWalletKeychainInfo(info); await importWalletKeychainInfo(info);
}); });
await writeSecureStorage(_flutterSecureStorage, await _secureStorage.write(key: pinCodeKey, value: encodedPinCode(pin: decodedPin));
key: pinCodeKey, value: encodedPinCode(pin: decodedPin));
keychainDumpFile.deleteSync(); keychainDumpFile.deleteSync();
} }
@ -401,15 +399,14 @@ class BackupService {
final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword); final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
final backupPassword = keychainJSON[backupPasswordKey] as String; final backupPassword = keychainJSON[backupPasswordKey] as String;
await writeSecureStorage(_flutterSecureStorage, key: backupPasswordKey, value: backupPassword); await _secureStorage.write(key: backupPasswordKey, value: backupPassword);
keychainWalletsInfo.forEach((dynamic rawInfo) async { keychainWalletsInfo.forEach((dynamic rawInfo) async {
final info = rawInfo as Map<String, dynamic>; final info = rawInfo as Map<String, dynamic>;
await importWalletKeychainInfo(info); await importWalletKeychainInfo(info);
}); });
await writeSecureStorage(_flutterSecureStorage, await _secureStorage.write(key: pinCodeKey, value: encodedPinCode(pin: decodedPin));
key: pinCodeKey, value: encodedPinCode(pin: decodedPin));
keychainDumpFile.deleteSync(); keychainDumpFile.deleteSync();
} }
@ -429,7 +426,7 @@ class BackupService {
Future<Uint8List> _exportKeychainDumpV2(String password, Future<Uint8List> _exportKeychainDumpV2(String password,
{String keychainSalt = secrets.backupKeychainSalt}) async { {String keychainSalt = secrets.backupKeychainSalt}) async {
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
final encodedPin = await _flutterSecureStorage.read(key: key); final encodedPin = await _secureStorage.read(key: key);
final decodedPin = decodedPinCode(pin: encodedPin!); final decodedPin = decodedPinCode(pin: encodedPin!);
final wallets = await Future.wait(_walletInfoSource.values.map((walletInfo) async { final wallets = await Future.wait(_walletInfoSource.values.map((walletInfo) async {
return { return {
@ -439,7 +436,7 @@ class BackupService {
}; };
})); }));
final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword); final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
final backupPassword = await _flutterSecureStorage.read(key: backupPasswordKey); final backupPassword = await _secureStorage.read(key: backupPasswordKey);
final data = utf8.encode( final data = utf8.encode(
json.encode({'pin': decodedPin, 'wallets': wallets, backupPasswordKey: backupPassword})); json.encode({'pin': decodedPin, 'wallets': wallets, backupPasswordKey: backupPassword}));
final encrypted = await _encryptV2(Uint8List.fromList(data), '$keychainSalt$password'); final encrypted = await _encryptV2(Uint8List.fromList(data), '$keychainSalt$password');

View file

@ -1,31 +1,30 @@
import 'package:cake_wallet/core/secure_storage.dart'; import 'package:cake_wallet/core/secure_storage.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:cake_wallet/entities/secret_store_key.dart';
import 'package:cake_wallet/entities/encrypt.dart'; import 'package:cake_wallet/entities/encrypt.dart';
class KeyService { class KeyService {
KeyService(this._secureStorage); KeyService(this._secureStorage);
final FlutterSecureStorage _secureStorage; final SecureStorage _secureStorage;
Future<String> getWalletPassword({required String walletName}) async { Future<String> getWalletPassword({required String walletName}) async {
final key = generateStoreKeyFor( final key =
key: SecretStoreKey.moneroWalletPassword, walletName: walletName); generateStoreKeyFor(key: SecretStoreKey.moneroWalletPassword, walletName: walletName);
final encodedPassword = await readSecureStorage(_secureStorage, key); final encodedPassword = await _secureStorage.read(key: key);
return decodeWalletPassword(password: encodedPassword!); return decodeWalletPassword(password: encodedPassword!);
} }
Future<void> saveWalletPassword({required String walletName, required String password}) async { Future<void> saveWalletPassword({required String walletName, required String password}) async {
final key = generateStoreKeyFor( final key =
key: SecretStoreKey.moneroWalletPassword, walletName: walletName); generateStoreKeyFor(key: SecretStoreKey.moneroWalletPassword, walletName: walletName);
final encodedPassword = encodeWalletPassword(password: password); final encodedPassword = encodeWalletPassword(password: password);
await writeSecureStorage(_secureStorage, key: key, value: encodedPassword); await _secureStorage.write(key: key, value: encodedPassword);
} }
Future<void> deleteWalletPassword({required String walletName}) async { Future<void> deleteWalletPassword({required String walletName}) async {
final key = generateStoreKeyFor( final key =
key: SecretStoreKey.moneroWalletPassword, walletName: walletName); generateStoreKeyFor(key: SecretStoreKey.moneroWalletPassword, walletName: walletName);
await _secureStorage.delete(key: key); await _secureStorage.delete(key: key);
} }

View file

@ -1,38 +0,0 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
// For now, we can create a utility function to handle this.
//
// However, we could look into abstracting the entire FlutterSecureStorage package
// so the app doesn't depend on the package directly but an absraction.
// It'll make these kind of modifications to read/write come from a single point.
Future<String?> readSecureStorage(FlutterSecureStorage secureStorage, String key) async {
String? result;
const maxWait = Duration(seconds: 3);
const checkInterval = Duration(milliseconds: 200);
DateTime start = DateTime.now();
while (result == null && DateTime.now().difference(start) < maxWait) {
result = await secureStorage.read(key: key);
if (result != null) {
break;
}
await Future.delayed(checkInterval);
}
return result;
}
Future<void> writeSecureStorage(FlutterSecureStorage secureStorage,
{required String key, required String value}) async {
// delete the value before writing on macOS because of a weird bug
// https://github.com/mogol/flutter_secure_storage/issues/581
if (Platform.isMacOS) {
await secureStorage.delete(key: key);
}
await secureStorage.write(key: key, value: value);
}

View file

@ -1,8 +1,8 @@
import 'package:cake_wallet/core/secure_storage.dart';
import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/di.dart';
import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/store/settings_store.dart';
import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_info.dart';
import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/preferences_key.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:cake_wallet/core/key_service.dart'; import 'package:cake_wallet/core/key_service.dart';
@ -25,7 +25,7 @@ class WalletCreationService {
} }
WalletType type; WalletType type;
final FlutterSecureStorage secureStorage; final SecureStorage secureStorage;
final SharedPreferences sharedPreferences; final SharedPreferences sharedPreferences;
final SettingsStore settingsStore; final SettingsStore settingsStore;
final KeyService keyService; final KeyService keyService;

View file

@ -234,6 +234,32 @@ import 'package:get_it/get_it.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:cake_wallet/core/secure_storage.dart';
import 'package:cake_wallet/core/wallet_creation_service.dart';
import 'package:cake_wallet/store/app_store.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:cake_wallet/view_model/wallet_new_vm.dart';
import 'package:cake_wallet/store/authentication_store.dart';
import 'package:cake_wallet/store/dashboard/trades_store.dart';
import 'package:cake_wallet/store/dashboard/trade_filter_store.dart';
import 'package:cake_wallet/store/dashboard/transaction_filter_store.dart';
import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart';
import 'package:cake_wallet/store/templates/send_template_store.dart';
import 'package:cake_wallet/store/templates/exchange_template_store.dart';
import 'package:cake_wallet/entities/template.dart';
import 'package:cake_wallet/exchange/exchange_template.dart';
import 'package:cake_wallet/.secrets.g.dart' as secrets;
import 'package:cake_wallet/src/screens/dashboard/pages/address_page.dart';
import 'package:cake_wallet/anypay/anypay_api.dart';
import 'package:cake_wallet/view_model/ionia/ionia_gift_card_details_view_model.dart';
import 'package:cake_wallet/src/screens/ionia/cards/ionia_payment_status_page.dart';
import 'package:cake_wallet/view_model/ionia/ionia_payment_status_view_model.dart';
import 'package:cake_wallet/anypay/any_pay_payment_committed_info.dart';
import 'package:cake_wallet/ionia/ionia_any_pay_payment_info.dart';
import 'package:cake_wallet/src/screens/receive/fullscreen_qr_page.dart';
import 'package:cake_wallet/core/wallet_loading_service.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cake_wallet/entities/qr_view_data.dart';
import 'buy/dfx/dfx_buy_provider.dart'; import 'buy/dfx/dfx_buy_provider.dart';
import 'core/totp_request_details.dart'; import 'core/totp_request_details.dart';
@ -266,7 +292,7 @@ Future<void> setup({
required Box<Order> ordersSource, required Box<Order> ordersSource,
required Box<UnspentCoinsInfo> unspentCoinsInfoSource, required Box<UnspentCoinsInfo> unspentCoinsInfoSource,
required Box<AnonpayInvoiceInfo> anonpayInvoiceInfoSource, required Box<AnonpayInvoiceInfo> anonpayInvoiceInfoSource,
required FlutterSecureStorage secureStorage, required SecureStorage secureStorage,
required GlobalKey<NavigatorState> navigatorKey, required GlobalKey<NavigatorState> navigatorKey,
}) async { }) async {
_walletInfoSource = walletInfoSource; _walletInfoSource = walletInfoSource;
@ -283,7 +309,7 @@ Future<void> setup({
if (!_isSetupFinished) { if (!_isSetupFinished) {
getIt.registerSingletonAsync<SharedPreferences>(() => SharedPreferences.getInstance()); getIt.registerSingletonAsync<SharedPreferences>(() => SharedPreferences.getInstance());
getIt.registerSingleton<FlutterSecureStorage>(secureStorage); getIt.registerSingleton<SecureStorage>(secureStorage);
} }
if (!_isSetupFinished) { if (!_isSetupFinished) {
getIt.registerFactory(() => BackgroundTasks()); getIt.registerFactory(() => BackgroundTasks());
@ -331,22 +357,22 @@ Future<void> setup({
getIt.registerSingleton<ExchangeTemplateStore>( getIt.registerSingleton<ExchangeTemplateStore>(
ExchangeTemplateStore(templateSource: _exchangeTemplates)); ExchangeTemplateStore(templateSource: _exchangeTemplates));
getIt.registerSingleton<YatStore>( getIt.registerSingleton<YatStore>(
YatStore(appStore: getIt.get<AppStore>(), secureStorage: getIt.get<FlutterSecureStorage>()) YatStore(appStore: getIt.get<AppStore>(), secureStorage: getIt.get<SecureStorage>())
..init()); ..init());
getIt.registerSingleton<AnonpayTransactionsStore>( getIt.registerSingleton<AnonpayTransactionsStore>(
AnonpayTransactionsStore(anonpayInvoiceInfoSource: _anonpayInvoiceInfoSource)); AnonpayTransactionsStore(anonpayInvoiceInfoSource: _anonpayInvoiceInfoSource));
final secretStore = await SecretStoreBase.load(getIt.get<FlutterSecureStorage>()); final secretStore = await SecretStoreBase.load(getIt.get<SecureStorage>());
getIt.registerSingleton<SecretStore>(secretStore); getIt.registerSingleton<SecretStore>(secretStore);
getIt.registerFactory<KeyService>(() => KeyService(getIt.get<FlutterSecureStorage>())); getIt.registerFactory<KeyService>(() => KeyService(getIt.get<SecureStorage>()));
getIt.registerFactoryParam<WalletCreationService, WalletType, void>((type, _) => getIt.registerFactoryParam<WalletCreationService, WalletType, void>((type, _) =>
WalletCreationService( WalletCreationService(
initialType: type, initialType: type,
keyService: getIt.get<KeyService>(), keyService: getIt.get<KeyService>(),
secureStorage: getIt.get<FlutterSecureStorage>(), secureStorage: getIt.get<SecureStorage>(),
sharedPreferences: getIt.get<SharedPreferences>(), sharedPreferences: getIt.get<SharedPreferences>(),
settingsStore: getIt.get<SettingsStore>(), settingsStore: getIt.get<SettingsStore>(),
walletInfoSource: _walletInfoSource)); walletInfoSource: _walletInfoSource));
@ -401,7 +427,7 @@ Future<void> setup({
getIt.registerFactory<AuthService>( getIt.registerFactory<AuthService>(
() => AuthService( () => AuthService(
secureStorage: getIt.get<FlutterSecureStorage>(), secureStorage: getIt.get<SecureStorage>(),
sharedPreferences: getIt.get<SharedPreferences>(), sharedPreferences: getIt.get<SharedPreferences>(),
settingsStore: getIt.get<SettingsStore>(), settingsStore: getIt.get<SettingsStore>(),
), ),
@ -979,16 +1005,16 @@ Future<void> setup({
trades: _tradesSource, trades: _tradesSource,
settingsStore: getIt.get<SettingsStore>())); settingsStore: getIt.get<SettingsStore>()));
getIt.registerFactory(() => BackupService(getIt.get<FlutterSecureStorage>(), _walletInfoSource, getIt.registerFactory(() => BackupService(getIt.get<SecureStorage>(), _walletInfoSource,
getIt.get<KeyService>(), getIt.get<SharedPreferences>())); getIt.get<KeyService>(), getIt.get<SharedPreferences>()));
getIt.registerFactory(() => BackupViewModel( getIt.registerFactory(() => BackupViewModel(
getIt.get<FlutterSecureStorage>(), getIt.get<SecretStore>(), getIt.get<BackupService>())); getIt.get<SecureStorage>(), getIt.get<SecretStore>(), getIt.get<BackupService>()));
getIt.registerFactory(() => BackupPage(getIt.get<BackupViewModel>())); getIt.registerFactory(() => BackupPage(getIt.get<BackupViewModel>()));
getIt.registerFactory(() => getIt.registerFactory(() =>
EditBackupPasswordViewModel(getIt.get<FlutterSecureStorage>(), getIt.get<SecretStore>())); EditBackupPasswordViewModel(getIt.get<SecureStorage>(), getIt.get<SecretStore>()));
getIt.registerFactory(() => EditBackupPasswordPage(getIt.get<EditBackupPasswordViewModel>())); getIt.registerFactory(() => EditBackupPasswordPage(getIt.get<EditBackupPasswordViewModel>()));
@ -1037,7 +1063,7 @@ Future<void> setup({
getIt.registerFactory(() => SupportPage(getIt.get<SupportViewModel>())); getIt.registerFactory(() => SupportPage(getIt.get<SupportViewModel>()));
getIt.registerFactory(() => SupportChatPage(getIt.get<SupportViewModel>(), getIt.registerFactory(() => SupportChatPage(getIt.get<SupportViewModel>(),
secureStorage: getIt.get<FlutterSecureStorage>())); secureStorage: getIt.get<SecureStorage>()));
getIt.registerFactory(() => SupportOtherLinksPage(getIt.get<SupportViewModel>())); getIt.registerFactory(() => SupportOtherLinksPage(getIt.get<SupportViewModel>()));
@ -1079,7 +1105,7 @@ Future<void> setup({
getIt.registerFactory(() => AnyPayApi()); getIt.registerFactory(() => AnyPayApi());
getIt.registerFactory<IoniaService>( getIt.registerFactory<IoniaService>(
() => IoniaService(getIt.get<FlutterSecureStorage>(), getIt.get<IoniaApi>())); () => IoniaService(getIt.get<SecureStorage>(), getIt.get<IoniaApi>()));
getIt.registerFactory<IoniaAnyPay>(() => IoniaAnyPay( getIt.registerFactory<IoniaAnyPay>(() => IoniaAnyPay(
getIt.get<IoniaService>(), getIt.get<AnyPayApi>(), getIt.get<AppStore>().wallet!)); getIt.get<IoniaService>(), getIt.get<AnyPayApi>(), getIt.get<AppStore>().wallet!));

View file

@ -1,10 +1,10 @@
import 'dart:io' show Directory, File, Platform; import 'dart:io' show Directory, File, Platform;
import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/core/secure_storage.dart';
import 'package:cake_wallet/entities/exchange_api_mode.dart'; import 'package:cake_wallet/entities/exchange_api_mode.dart';
import 'package:cake_wallet/entities/fiat_api_mode.dart'; import 'package:cake_wallet/entities/fiat_api_mode.dart';
import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/pathForWallet.dart';
import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:cake_wallet/entities/secret_store_key.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
@ -37,12 +37,13 @@ const nanoDefaultNodeUri = 'rpc.nano.to';
const nanoDefaultPowNodeUri = 'rpc.nano.to'; const nanoDefaultPowNodeUri = 'rpc.nano.to';
const solanaDefaultNodeUri = 'rpc.ankr.com'; const solanaDefaultNodeUri = 'rpc.ankr.com';
const tronDefaultNodeUri = 'api.trongrid.io'; const tronDefaultNodeUri = 'api.trongrid.io';
const tronDefaultNodeUri = 'tron-rpc.publicnode.com:443';
const newCakeWalletBitcoinUri = '198.58.111.154:50001'; const newCakeWalletBitcoinUri = '198.58.111.154:50001';
Future<void> defaultSettingsMigration( Future<void> defaultSettingsMigration(
{required int version, {required int version,
required SharedPreferences sharedPreferences, required SharedPreferences sharedPreferences,
required FlutterSecureStorage secureStorage, required SecureStorage secureStorage,
required Box<Node> nodes, required Box<Node> nodes,
required Box<Node> powNodes, required Box<Node> powNodes,
required Box<WalletInfo> walletInfoSource, required Box<WalletInfo> walletInfoSource,
@ -485,7 +486,7 @@ Node? getTronDefaultNode({required Box<Node> nodes}) {
Future<void> insecureStorageMigration({ Future<void> insecureStorageMigration({
required SharedPreferences sharedPreferences, required SharedPreferences sharedPreferences,
required FlutterSecureStorage secureStorage, required SecureStorage secureStorage,
}) async { }) async {
bool? allowBiometricalAuthentication = bool? allowBiometricalAuthentication =
sharedPreferences.getBool(SecureKey.allowBiometricalAuthenticationKey); sharedPreferences.getBool(SecureKey.allowBiometricalAuthenticationKey);
@ -559,7 +560,7 @@ Future<void> insecureStorageMigration({
} }
} }
Future<void> rewriteSecureStoragePin({required FlutterSecureStorage secureStorage}) async { Future<void> rewriteSecureStoragePin({required SecureStorage secureStorage}) async {
// the bug only affects ios/mac: // the bug only affects ios/mac:
if (!Platform.isIOS && !Platform.isMacOS) { if (!Platform.isIOS && !Platform.isMacOS) {
return; return;
@ -585,8 +586,9 @@ Future<void> rewriteSecureStoragePin({required FlutterSecureStorage secureStorag
await secureStorage.write( await secureStorage.write(
key: keyForPinCode, key: keyForPinCode,
value: encodedPin, value: encodedPin,
iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock), // TODO: find a way to add those with the generated secure storage
mOptions: MacOsOptions(accessibility: KeychainAccessibility.first_unlock), // iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock),
// mOptions: MacOsOptions(accessibility: KeychainAccessibility.first_unlock),
); );
} }
@ -720,7 +722,7 @@ Future<void> updateDisplayModes(SharedPreferences sharedPreferences) async {
await sharedPreferences.setInt(PreferencesKey.currentBalanceDisplayModeKey, balanceDisplayMode); await sharedPreferences.setInt(PreferencesKey.currentBalanceDisplayModeKey, balanceDisplayMode);
} }
Future<void> generateBackupPassword(FlutterSecureStorage secureStorage) async { Future<void> generateBackupPassword(SecureStorage secureStorage) async {
final key = generateStoreKeyFor(key: SecretStoreKey.backupPassword); final key = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
if ((await secureStorage.read(key: key))?.isNotEmpty ?? false) { if ((await secureStorage.read(key: key))?.isNotEmpty ?? false) {

View file

@ -2,7 +2,6 @@ import 'dart:io';
import 'dart:convert'; import 'dart:convert';
import 'package:cake_wallet/core/secure_storage.dart'; import 'package:cake_wallet/core/secure_storage.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
@ -11,8 +10,7 @@ import 'package:cake_wallet/entities/contact.dart';
import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/crypto_currency.dart';
import 'package:cake_wallet/entities/encrypt.dart'; import 'package:cake_wallet/entities/encrypt.dart';
import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/entities/fiat_currency.dart';
import 'package:cake_wallet/entities/ios_legacy_helper.dart' import 'package:cake_wallet/entities/ios_legacy_helper.dart' as ios_legacy_helper;
as ios_legacy_helper;
import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/preferences_key.dart';
import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:cake_wallet/entities/secret_store_key.dart';
import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_info.dart';
@ -30,8 +28,8 @@ Future<void> migrate_android_v1() async {
await android_migrate_wallets(appDocDir: appDocDir); await android_migrate_wallets(appDocDir: appDocDir);
} }
Future<void> ios_migrate_v1(Box<WalletInfo> walletInfoSource, Future<void> ios_migrate_v1(
Box<Trade> tradeSource, Box<Contact> contactSource) async { Box<WalletInfo> walletInfoSource, Box<Trade> tradeSource, Box<Contact> contactSource) async {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
if (prefs.getBool('ios_migration_v1_completed') ?? false) { if (prefs.getBool('ios_migration_v1_completed') ?? false) {
@ -67,10 +65,7 @@ Future<void> ios_migrate_user_defaults() async {
if (activeCurrency != null) { if (activeCurrency != null) {
final convertedCurrency = convertFiatLegacy(activeCurrency); final convertedCurrency = convertFiatLegacy(activeCurrency);
if (convertedCurrency != null) { await prefs.setString('current_fiat_currency', convertedCurrency.serialize());
await prefs.setString(
'current_fiat_currency', convertedCurrency.serialize());
}
} }
//translate fee priority //translate fee priority
@ -81,23 +76,20 @@ Future<void> ios_migrate_user_defaults() async {
} }
//translate current balance mode //translate current balance mode
final currentBalanceMode = final currentBalanceMode = await ios_legacy_helper.getInt('display_balance_mode');
await ios_legacy_helper.getInt('display_balance_mode');
if (currentBalanceMode != null) { if (currentBalanceMode != null) {
await prefs.setInt('current_balance_display_mode', currentBalanceMode); await prefs.setInt('current_balance_display_mode', currentBalanceMode);
} }
//translate should save recipient address //translate should save recipient address
final shouldSave = final shouldSave = await ios_legacy_helper.getBool('should_save_recipient_address');
await ios_legacy_helper.getBool('should_save_recipient_address');
if (shouldSave != null) { if (shouldSave != null) {
await prefs.setBool('save_recipient_address', shouldSave); await prefs.setBool('save_recipient_address', shouldSave);
} }
//translate biometric //translate biometric
final biometricOn = final biometricOn = await ios_legacy_helper.getBool('biometric_authentication_on');
await ios_legacy_helper.getBool('biometric_authentication_on');
if (biometricOn != null) { if (biometricOn != null) {
await prefs.setBool('allow_biometrical_authentication', biometricOn); await prefs.setBool('allow_biometrical_authentication', biometricOn);
@ -137,9 +129,8 @@ Future<void> ios_migrate_pin() async {
return; return;
} }
final flutterSecureStorage = FlutterSecureStorage(); final flutterSecureStorage = secureStorageShared;
final pinPassword = await flutterSecureStorage.read( final pinPassword = await flutterSecureStorage.readNoIOptions(key: 'pin_password');
key: 'pin_password', iOptions: IOSOptions());
// No pin // No pin
if (pinPassword == null) { if (pinPassword == null) {
await prefs.setBool('ios_migration_pin_completed', true); await prefs.setBool('ios_migration_pin_completed', true);
@ -148,7 +139,7 @@ Future<void> ios_migrate_pin() async {
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
final encodedPassword = encodedPinCode(pin: pinPassword); final encodedPassword = encodedPinCode(pin: pinPassword);
await writeSecureStorage(flutterSecureStorage, key: key, value: encodedPassword); await flutterSecureStorage.write(key: key, value: encodedPassword);
await prefs.setBool('ios_migration_pin_completed', true); await prefs.setBool('ios_migration_pin_completed', true);
} }
@ -161,7 +152,7 @@ Future<void> ios_migrate_wallet_passwords() async {
} }
final appDocDir = await getApplicationDocumentsDirectory(); final appDocDir = await getApplicationDocumentsDirectory();
final flutterSecureStorage = FlutterSecureStorage(); final flutterSecureStorage = secureStorageShared;
final keyService = KeyService(flutterSecureStorage); final keyService = KeyService(flutterSecureStorage);
final walletsDir = Directory('${appDocDir.path}/wallets'); final walletsDir = Directory('${appDocDir.path}/wallets');
final moneroWalletsDir = Directory('${walletsDir.path}/monero'); final moneroWalletsDir = Directory('${walletsDir.path}/monero');
@ -176,10 +167,8 @@ Future<void> ios_migrate_wallet_passwords() async {
if (item is Directory) { if (item is Directory) {
final name = item.path.split('/').last; final name = item.path.split('/').last;
final oldKey = 'wallet_monero_' + name + '_password'; final oldKey = 'wallet_monero_' + name + '_password';
final password = await flutterSecureStorage.read( final password = await flutterSecureStorage.readNoIOptions(key: oldKey);
key: oldKey, iOptions: IOSOptions()); await keyService.saveWalletPassword(walletName: name, password: password!);
await keyService.saveWalletPassword(
walletName: name, password: password!);
} }
} catch (e) { } catch (e) {
print(e.toString()); print(e.toString());
@ -311,17 +300,13 @@ Future<void> ios_migrate_wallet_info(Box<WalletInfo> walletsInfoSource) async {
return null; return null;
} }
final config = json.decode(configFile.readAsStringSync()) final config = json.decode(configFile.readAsStringSync()) as Map<String, dynamic>;
as Map<String, dynamic>; final isRecovery = config['isRecovery'] as bool? ?? false;
final isRecovery = config['isRecovery'] as bool ?? false;
final dateAsDouble = config['date'] as double; final dateAsDouble = config['date'] as double;
final timestamp = dateAsDouble.toInt() * 1000; final timestamp = dateAsDouble.toInt() * 1000;
final date = DateTime.fromMillisecondsSinceEpoch(timestamp); final date = DateTime.fromMillisecondsSinceEpoch(timestamp);
final id = walletTypeToString(WalletType.monero).toLowerCase() + final id = walletTypeToString(WalletType.monero).toLowerCase() + '_' + name;
'_' + final exist = walletsInfoSource.values.firstWhereOrNull((el) => el.id == id) != null;
name;
final exist = walletsInfoSource.values
.firstWhereOrNull((el) => el.id == id) != null;
if (exist) { if (exist) {
return null; return null;
@ -373,12 +358,10 @@ Future<void> ios_migrate_trades_list(Box<Trade> tradeSource) async {
} }
final content = file.readAsBytesSync(); final content = file.readAsBytesSync();
final flutterSecureStorage = FlutterSecureStorage(); final flutterSecureStorage = secureStorageShared;
final masterPassword = await flutterSecureStorage.read( final masterPassword = await flutterSecureStorage.readNoIOptions(key: 'master_password');
key: 'master_password', iOptions: IOSOptions());
final key = masterPassword!.replaceAll('-', ''); final key = masterPassword!.replaceAll('-', '');
final decoded = final decoded = await ios_legacy_helper.decrypt(content, key: key, salt: secrets.salt);
await ios_legacy_helper.decrypt(content, key: key, salt: secrets.salt);
final decodedJson = json.decode(decoded) as List<dynamic>; final decodedJson = json.decode(decoded) as List<dynamic>;
final trades = decodedJson.map((dynamic el) { final trades = decodedJson.map((dynamic el) {
final elAsMap = el as Map<String, dynamic>; final elAsMap = el as Map<String, dynamic>;
@ -441,8 +424,7 @@ Future<void> ios_migrate_address_book(Box<Contact> contactSource) async {
final address = _item["address"] as String; final address = _item["address"] as String;
final name = _item["name"] as String; final name = _item["name"] as String;
return Contact( return Contact(address: address, name: name, type: CryptoCurrency.fromString(type));
address: address, name: name, type: CryptoCurrency.fromString(type));
}); });
await contactSource.addAll(contacts); await contactSource.addAll(contacts);

View file

@ -1,9 +1,8 @@
import 'package:cake_wallet/core/secure_storage.dart'; import 'package:cake_wallet/core/secure_storage.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:cw_core/cake_hive.dart'; import 'package:cw_core/cake_hive.dart';
Future<List<int>> getEncryptionKey( Future<List<int>> getEncryptionKey(
{required String forKey, required FlutterSecureStorage secureStorage}) async { {required String forKey, required SecureStorage secureStorage}) async {
final stringifiedKey = await secureStorage.read(key: 'transactionDescriptionsBoxKey'); final stringifiedKey = await secureStorage.read(key: 'transactionDescriptionsBoxKey');
List<int> key; List<int> key;
@ -11,7 +10,7 @@ Future<List<int>> getEncryptionKey(
key = CakeHive.generateSecureKey(); key = CakeHive.generateSecureKey();
final keyStringified = key.join(','); final keyStringified = key.join(',');
String storageKey = 'transactionDescriptionsBoxKey'; String storageKey = 'transactionDescriptionsBoxKey';
await writeSecureStorage(secureStorage, key: storageKey, value: keyStringified); await secureStorage.write(key: storageKey, value: keyStringified);
} else { } else {
key = stringifiedKey.split(',').map((i) => int.parse(i)).toList(); key = stringifiedKey.split(',').map((i) => int.parse(i)).toList();
} }

View file

@ -56,13 +56,14 @@ class PreferencesKey {
static const pinNativeTokenAtTop = 'pin_native_token_at_top'; static const pinNativeTokenAtTop = 'pin_native_token_at_top';
static const useEtherscan = 'use_etherscan'; static const useEtherscan = 'use_etherscan';
static const usePolygonScan = 'use_polygonscan'; static const usePolygonScan = 'use_polygonscan';
static const useTronGrid = 'use_trongrid';
static const defaultNanoRep = 'default_nano_representative'; static const defaultNanoRep = 'default_nano_representative';
static const defaultBananoRep = 'default_banano_representative'; static const defaultBananoRep = 'default_banano_representative';
static const lookupsTwitter = 'looks_up_twitter'; static const lookupsTwitter = 'looks_up_twitter';
static const lookupsMastodon = 'looks_up_mastodon'; static const lookupsMastodon = 'looks_up_mastodon';
static const lookupsYatService = 'looks_up_mastodon'; static const lookupsYatService = 'looks_up_yat';
static const lookupsUnstoppableDomains = 'looks_up_mastodon'; static const lookupsUnstoppableDomains = 'looks_up_unstoppable_domain';
static const lookupsOpenAlias = 'looks_up_mastodon'; static const lookupsOpenAlias = 'looks_up_open_alias';
static const lookupsENS = 'looks_up_ens'; static const lookupsENS = 'looks_up_ens';
static String moneroWalletUpdateV1Key(String name) => static String moneroWalletUpdateV1Key(String name) =>

View file

@ -1,4 +1,4 @@
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:cake_wallet/core/secure_storage.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
enum SecretStoreKey { moneroWalletPassword, pinCodePassword, backupPassword } enum SecretStoreKey { moneroWalletPassword, pinCodePassword, backupPassword }
@ -66,7 +66,7 @@ class SecureKey {
static const lastAuthTimeMilliseconds = 'last_auth_time_milliseconds'; static const lastAuthTimeMilliseconds = 'last_auth_time_milliseconds';
static Future<int?> getInt({ static Future<int?> getInt({
required FlutterSecureStorage secureStorage, required SecureStorage secureStorage,
required SharedPreferences sharedPreferences, required SharedPreferences sharedPreferences,
required String key, required String key,
}) async { }) async {
@ -76,7 +76,7 @@ class SecureKey {
} }
static Future<bool?> getBool({ static Future<bool?> getBool({
required FlutterSecureStorage secureStorage, required SecureStorage secureStorage,
required SharedPreferences sharedPreferences, required SharedPreferences sharedPreferences,
required String key, required String key,
}) async { }) async {
@ -91,7 +91,7 @@ class SecureKey {
} }
static Future<String?> getString({ static Future<String?> getString({
required FlutterSecureStorage secureStorage, required SecureStorage secureStorage,
required SharedPreferences sharedPreferences, required SharedPreferences sharedPreferences,
required String key, required String key,
}) async { }) async {

View file

@ -19,15 +19,15 @@ class ThorChainExchangeProvider extends ExchangeProvider {
...(CryptoCurrency.all ...(CryptoCurrency.all
.where((element) => ![ .where((element) => ![
CryptoCurrency.btc, CryptoCurrency.btc,
CryptoCurrency.eth, // CryptoCurrency.eth,
CryptoCurrency.ltc, CryptoCurrency.ltc,
CryptoCurrency.bch, CryptoCurrency.bch,
CryptoCurrency.aave, // CryptoCurrency.aave,
CryptoCurrency.dai, // CryptoCurrency.dai,
CryptoCurrency.gusd, // CryptoCurrency.gusd,
CryptoCurrency.usdc, // CryptoCurrency.usdc,
CryptoCurrency.usdterc20, // CryptoCurrency.usdterc20,
CryptoCurrency.wbtc, // CryptoCurrency.wbtc, // TODO: temporarily commented until https://github.com/cake-tech/cake_wallet/pull/1436 is merged
].contains(element)) ].contains(element))
.toList()) .toList())
]; ];

View file

@ -1,7 +1,7 @@
import 'package:cake_wallet/core/secure_storage.dart';
import 'package:cake_wallet/ionia/ionia_merchant.dart'; import 'package:cake_wallet/ionia/ionia_merchant.dart';
import 'package:cake_wallet/ionia/ionia_order.dart'; import 'package:cake_wallet/ionia/ionia_order.dart';
import 'package:cake_wallet/ionia/ionia_virtual_card.dart'; import 'package:cake_wallet/ionia/ionia_virtual_card.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:cake_wallet/.secrets.g.dart' as secrets; import 'package:cake_wallet/.secrets.g.dart' as secrets;
import 'package:cake_wallet/ionia/ionia_api.dart'; import 'package:cake_wallet/ionia/ionia_api.dart';
import 'package:cake_wallet/ionia/ionia_gift_card.dart'; import 'package:cake_wallet/ionia/ionia_gift_card.dart';
@ -16,7 +16,7 @@ class IoniaService {
static String get clientId => secrets.ioniaClientId; static String get clientId => secrets.ioniaClientId;
final FlutterSecureStorage secureStorage; final SecureStorage secureStorage;
final IoniaApi ioniaApi; final IoniaApi ioniaApi;
// Create user // Create user

View file

@ -1,6 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart'; import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart';
import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/core/auth_service.dart';
import 'package:cake_wallet/core/secure_storage.dart';
import 'package:cake_wallet/entities/language_service.dart'; import 'package:cake_wallet/entities/language_service.dart';
import 'package:cake_wallet/buy/order.dart'; import 'package:cake_wallet/buy/order.dart';
import 'package:cake_wallet/locales/locale.dart'; import 'package:cake_wallet/locales/locale.dart';
@ -18,7 +19,6 @@ import 'package:hive/hive.dart';
import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/di.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/themes/theme_base.dart';
import 'package:cake_wallet/router.dart' as Router; import 'package:cake_wallet/router.dart' as Router;
@ -138,9 +138,8 @@ Future<void> initializeAppConfigs() async {
CakeHive.registerAdapter(AnonpayInvoiceInfoAdapter()); CakeHive.registerAdapter(AnonpayInvoiceInfoAdapter());
} }
final secureStorage = FlutterSecureStorage( final secureStorage = secureStorageShared;
iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock),
);
final transactionDescriptionsBoxKey = final transactionDescriptionsBoxKey =
await getEncryptionKey(secureStorage: secureStorage, forKey: TransactionDescription.boxKey); await getEncryptionKey(secureStorage: secureStorage, forKey: TransactionDescription.boxKey);
final tradesBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Trade.boxKey); final tradesBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Trade.boxKey);
@ -191,7 +190,7 @@ Future<void> initialSetup(
required Box<Template> templates, required Box<Template> templates,
required Box<ExchangeTemplate> exchangeTemplates, required Box<ExchangeTemplate> exchangeTemplates,
required Box<TransactionDescription> transactionDescriptions, required Box<TransactionDescription> transactionDescriptions,
required FlutterSecureStorage secureStorage, required SecureStorage secureStorage,
required Box<AnonpayInvoiceInfo> anonpayInvoiceInfo, required Box<AnonpayInvoiceInfo> anonpayInvoiceInfo,
required Box<UnspentCoinsInfo> unspentCoinsInfoSource, required Box<UnspentCoinsInfo> unspentCoinsInfoSource,
int initialMigrationVersion = 15}) async { int initialMigrationVersion = 15}) async {

View file

@ -7,6 +7,7 @@ import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.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/src/widgets/option_tile.dart'; import 'package:cake_wallet/src/widgets/option_tile.dart';
import 'package:cake_wallet/themes/extensions/option_tile_theme.dart'; import 'package:cake_wallet/themes/extensions/option_tile_theme.dart';
import 'package:cake_wallet/utils/device_info.dart';
import 'package:cake_wallet/utils/permission_handler.dart'; import 'package:cake_wallet/utils/permission_handler.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/utils/show_pop_up.dart';
@ -56,17 +57,18 @@ class RestoreOptionsPage extends BasePage {
description: S.of(context).restore_description_from_backup, description: S.of(context).restore_description_from_backup,
), ),
), ),
Padding( if (DeviceInfo.instance.isMobile)
padding: EdgeInsets.only(top: 24), Padding(
child: OptionTile( padding: EdgeInsets.only(top: 24),
onPressed: () => Navigator.pushNamed( child: OptionTile(
context, Routes.restoreWalletFromHardwareWallet, onPressed: () => Navigator.pushNamed(
arguments: isNewInstall), context, Routes.restoreWalletFromHardwareWallet,
image: imageLedger, arguments: isNewInstall),
title: S.of(context).restore_title_from_hardware_wallet, image: imageLedger,
description: S.of(context).restore_description_from_hardware_wallet, title: S.of(context).restore_title_from_hardware_wallet,
description: S.of(context).restore_description_from_hardware_wallet,
),
), ),
),
Padding( Padding(
padding: EdgeInsets.only(top: 24), padding: EdgeInsets.only(top: 24),
child: OptionTile( child: OptionTile(

View file

@ -103,6 +103,14 @@ class PrivacyPage extends BasePage {
_privacySettingsViewModel.setUsePolygonScan(value); _privacySettingsViewModel.setUsePolygonScan(value);
}, },
), ),
if (_privacySettingsViewModel.canUseTronGrid)
SettingsSwitcherCell(
title: S.current.trongrid_history,
value: _privacySettingsViewModel.useTronGrid,
onValueChange: (BuildContext _, bool value) {
_privacySettingsViewModel.setUseTronGrid(value);
},
),
SettingsCellWithArrow( SettingsCellWithArrow(
title: S.current.domain_looks_up, title: S.current.domain_looks_up,
handler: (context) => Navigator.of(context).pushNamed(Routes.domainLookupsPage), handler: (context) => Navigator.of(context).pushNamed(Routes.domainLookupsPage),

View file

@ -1,16 +1,16 @@
import 'package:cake_wallet/core/secure_storage.dart';
import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/screens/support_chat/widgets/chatwoot_widget.dart'; import 'package:cake_wallet/src/screens/support_chat/widgets/chatwoot_widget.dart';
import 'package:cake_wallet/view_model/support_view_model.dart'; import 'package:cake_wallet/view_model/support_view_model.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
class SupportChatPage extends BasePage { class SupportChatPage extends BasePage {
SupportChatPage(this.supportViewModel, {required this.secureStorage}); SupportChatPage(this.supportViewModel, {required this.secureStorage});
final SupportViewModel supportViewModel; final SupportViewModel supportViewModel;
final FlutterSecureStorage secureStorage; final SecureStorage secureStorage;
@override @override
String get title => S.current.settings_support; String get title => S.current.settings_support;

View file

@ -3,14 +3,13 @@ import 'dart:convert';
import 'package:cake_wallet/core/secure_storage.dart'; import 'package:cake_wallet/core/secure_storage.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
const COOKIE_KEY = 'chatwootCookie'; const COOKIE_KEY = 'chatwootCookie';
class ChatwootWidget extends StatefulWidget { class ChatwootWidget extends StatefulWidget {
ChatwootWidget(this.secureStorage, {required this.supportUrl}); ChatwootWidget(this.secureStorage, {required this.supportUrl});
final FlutterSecureStorage secureStorage; final SecureStorage secureStorage;
final String supportUrl; final String supportUrl;
@override @override
@ -59,6 +58,6 @@ class ChatwootWidgetState extends State<ChatwootWidget> {
} }
Future<void> storeCookie(String value) async { Future<void> storeCookie(String value) async {
await writeSecureStorage(widget.secureStorage, key: COOKIE_KEY, value: value); await widget.secureStorage.write(key: COOKIE_KEY, value: value);
} }
} }

View file

@ -1,6 +1,5 @@
import 'package:cake_wallet/core/secure_storage.dart';
import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:cake_wallet/entities/secret_store_key.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
part 'secret_store.g.dart'; part 'secret_store.g.dart';
@ -8,7 +7,7 @@ part 'secret_store.g.dart';
class SecretStore = SecretStoreBase with _$SecretStore; class SecretStore = SecretStoreBase with _$SecretStore;
abstract class SecretStoreBase with Store { abstract class SecretStoreBase with Store {
static Future<SecretStore> load(FlutterSecureStorage storage) async { static Future<SecretStore> load(SecureStorage storage) async {
final secretStore = SecretStore(); final secretStore = SecretStore();
final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword); final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
final backupPassword = await storage.read(key: backupPasswordKey); final backupPassword = await storage.read(key: backupPasswordKey);

View file

@ -26,7 +26,6 @@ import 'package:cake_wallet/themes/theme_base.dart';
import 'package:cake_wallet/themes/theme_list.dart'; import 'package:cake_wallet/themes/theme_list.dart';
import 'package:device_info_plus/device_info_plus.dart'; import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
import 'package:package_info/package_info.dart'; import 'package:package_info/package_info.dart';
@ -48,7 +47,7 @@ class SettingsStore = SettingsStoreBase with _$SettingsStore;
abstract class SettingsStoreBase with Store { abstract class SettingsStoreBase with Store {
SettingsStoreBase( SettingsStoreBase(
{required FlutterSecureStorage secureStorage, {required SecureStorage secureStorage,
required BackgroundTasks backgroundTasks, required BackgroundTasks backgroundTasks,
required SharedPreferences sharedPreferences, required SharedPreferences sharedPreferences,
required bool initialShouldShowMarketPlaceInDashboard, required bool initialShouldShowMarketPlaceInDashboard,
@ -99,6 +98,7 @@ abstract class SettingsStoreBase with Store {
required this.pinNativeTokenAtTop, required this.pinNativeTokenAtTop,
required this.useEtherscan, required this.useEtherscan,
required this.usePolygonScan, required this.usePolygonScan,
required this.useTronGrid,
required this.defaultNanoRep, required this.defaultNanoRep,
required this.defaultBananoRep, required this.defaultBananoRep,
required this.lookupsTwitter, required this.lookupsTwitter,
@ -397,6 +397,9 @@ abstract class SettingsStoreBase with Store {
(bool usePolygonScan) => (bool usePolygonScan) =>
_sharedPreferences.setBool(PreferencesKey.usePolygonScan, usePolygonScan)); _sharedPreferences.setBool(PreferencesKey.usePolygonScan, usePolygonScan));
reaction((_) => useTronGrid,
(bool useTronGrid) => _sharedPreferences.setBool(PreferencesKey.useTronGrid, useTronGrid));
reaction((_) => defaultNanoRep, reaction((_) => defaultNanoRep,
(String nanoRep) => _sharedPreferences.setString(PreferencesKey.defaultNanoRep, nanoRep)); (String nanoRep) => _sharedPreferences.setString(PreferencesKey.defaultNanoRep, nanoRep));
@ -435,83 +438,79 @@ abstract class SettingsStoreBase with Store {
// secure storage keys: // secure storage keys:
reaction( reaction(
(_) => allowBiometricalAuthentication, (_) => allowBiometricalAuthentication,
(bool biometricalAuthentication) => writeSecureStorage(secureStorage, (bool biometricalAuthentication) => secureStorage.write(
key: SecureKey.allowBiometricalAuthenticationKey, key: SecureKey.allowBiometricalAuthenticationKey,
value: biometricalAuthentication.toString())); value: biometricalAuthentication.toString()));
reaction( reaction(
(_) => selectedCake2FAPreset, (_) => selectedCake2FAPreset,
(Cake2FAPresetsOptions selectedCake2FAPreset) => writeSecureStorage(secureStorage, (Cake2FAPresetsOptions selectedCake2FAPreset) => secureStorage.write(
key: SecureKey.selectedCake2FAPreset, key: SecureKey.selectedCake2FAPreset,
value: selectedCake2FAPreset.serialize().toString())); value: selectedCake2FAPreset.serialize().toString()));
reaction( reaction(
(_) => shouldRequireTOTP2FAForAccessingWallet, (_) => shouldRequireTOTP2FAForAccessingWallet,
(bool requireTOTP2FAForAccessingWallet) => writeSecureStorage(secureStorage, (bool requireTOTP2FAForAccessingWallet) => secureStorage.write(
key: SecureKey.shouldRequireTOTP2FAForAccessingWallet, key: SecureKey.shouldRequireTOTP2FAForAccessingWallet,
value: requireTOTP2FAForAccessingWallet.toString())); value: requireTOTP2FAForAccessingWallet.toString()));
reaction( reaction(
(_) => shouldRequireTOTP2FAForSendsToContact, (_) => shouldRequireTOTP2FAForSendsToContact,
(bool requireTOTP2FAForSendsToContact) => writeSecureStorage(secureStorage, (bool requireTOTP2FAForSendsToContact) => secureStorage.write(
key: SecureKey.shouldRequireTOTP2FAForSendsToContact, key: SecureKey.shouldRequireTOTP2FAForSendsToContact,
value: requireTOTP2FAForSendsToContact.toString())); value: requireTOTP2FAForSendsToContact.toString()));
reaction( reaction(
(_) => shouldRequireTOTP2FAForSendsToNonContact, (_) => shouldRequireTOTP2FAForSendsToNonContact,
(bool requireTOTP2FAForSendsToNonContact) => writeSecureStorage(secureStorage, (bool requireTOTP2FAForSendsToNonContact) => secureStorage.write(
key: SecureKey.shouldRequireTOTP2FAForSendsToNonContact, key: SecureKey.shouldRequireTOTP2FAForSendsToNonContact,
value: requireTOTP2FAForSendsToNonContact.toString())); value: requireTOTP2FAForSendsToNonContact.toString()));
reaction( reaction(
(_) => shouldRequireTOTP2FAForSendsToInternalWallets, (_) => shouldRequireTOTP2FAForSendsToInternalWallets,
(bool requireTOTP2FAForSendsToInternalWallets) => writeSecureStorage(secureStorage, (bool requireTOTP2FAForSendsToInternalWallets) => secureStorage.write(
key: SecureKey.shouldRequireTOTP2FAForSendsToInternalWallets, key: SecureKey.shouldRequireTOTP2FAForSendsToInternalWallets,
value: requireTOTP2FAForSendsToInternalWallets.toString())); value: requireTOTP2FAForSendsToInternalWallets.toString()));
reaction( reaction(
(_) => shouldRequireTOTP2FAForExchangesToInternalWallets, (_) => shouldRequireTOTP2FAForExchangesToInternalWallets,
(bool requireTOTP2FAForExchangesToInternalWallets) => writeSecureStorage(secureStorage, (bool requireTOTP2FAForExchangesToInternalWallets) => secureStorage.write(
key: SecureKey.shouldRequireTOTP2FAForExchangesToInternalWallets, key: SecureKey.shouldRequireTOTP2FAForExchangesToInternalWallets,
value: requireTOTP2FAForExchangesToInternalWallets.toString())); value: requireTOTP2FAForExchangesToInternalWallets.toString()));
reaction( reaction(
(_) => shouldRequireTOTP2FAForExchangesToExternalWallets, (_) => shouldRequireTOTP2FAForExchangesToExternalWallets,
(bool requireTOTP2FAForExchangesToExternalWallets) => writeSecureStorage(secureStorage, (bool requireTOTP2FAForExchangesToExternalWallets) => secureStorage.write(
key: SecureKey.shouldRequireTOTP2FAForExchangesToExternalWallets, key: SecureKey.shouldRequireTOTP2FAForExchangesToExternalWallets,
value: requireTOTP2FAForExchangesToExternalWallets.toString())); value: requireTOTP2FAForExchangesToExternalWallets.toString()));
reaction( reaction(
(_) => shouldRequireTOTP2FAForAddingContacts, (_) => shouldRequireTOTP2FAForAddingContacts,
(bool requireTOTP2FAForAddingContacts) => writeSecureStorage(secureStorage, (bool requireTOTP2FAForAddingContacts) => secureStorage.write(
key: SecureKey.shouldRequireTOTP2FAForAddingContacts, key: SecureKey.shouldRequireTOTP2FAForAddingContacts,
value: requireTOTP2FAForAddingContacts.toString())); value: requireTOTP2FAForAddingContacts.toString()));
reaction( reaction(
(_) => shouldRequireTOTP2FAForCreatingNewWallets, (_) => shouldRequireTOTP2FAForCreatingNewWallets,
(bool requireTOTP2FAForCreatingNewWallets) => writeSecureStorage(secureStorage, (bool requireTOTP2FAForCreatingNewWallets) => secureStorage.write(
key: SecureKey.shouldRequireTOTP2FAForCreatingNewWallets, key: SecureKey.shouldRequireTOTP2FAForCreatingNewWallets,
value: requireTOTP2FAForCreatingNewWallets.toString())); value: requireTOTP2FAForCreatingNewWallets.toString()));
reaction( reaction(
(_) => shouldRequireTOTP2FAForAllSecurityAndBackupSettings, (_) => shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
(bool requireTOTP2FAForAllSecurityAndBackupSettings) => writeSecureStorage(secureStorage, (bool requireTOTP2FAForAllSecurityAndBackupSettings) => secureStorage.write(
key: SecureKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings, key: SecureKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
value: requireTOTP2FAForAllSecurityAndBackupSettings.toString())); value: requireTOTP2FAForAllSecurityAndBackupSettings.toString()));
reaction( reaction((_) => useTOTP2FA,
(_) => useTOTP2FA, (bool use) => secureStorage.write(key: SecureKey.useTOTP2FA, value: use.toString()));
(bool use) =>
writeSecureStorage(secureStorage, key: SecureKey.useTOTP2FA, value: use.toString()));
reaction( reaction((_) => totpSecretKey,
(_) => totpSecretKey, (String totpKey) => secureStorage.write(key: SecureKey.totpSecretKey, value: totpKey));
(String totpKey) =>
writeSecureStorage(secureStorage, key: SecureKey.totpSecretKey, value: totpKey));
reaction( reaction(
(_) => pinTimeOutDuration, (_) => pinTimeOutDuration,
(PinCodeRequiredDuration pinCodeInterval) => writeSecureStorage(secureStorage, (PinCodeRequiredDuration pinCodeInterval) => secureStorage.write(
key: SecureKey.pinTimeOutDuration, value: pinCodeInterval.value.toString())); key: SecureKey.pinTimeOutDuration, value: pinCodeInterval.value.toString()));
reaction( reaction(
@ -674,6 +673,9 @@ abstract class SettingsStoreBase with Store {
@observable @observable
bool usePolygonScan; bool usePolygonScan;
@observable
bool useTronGrid;
@observable @observable
String defaultNanoRep; String defaultNanoRep;
@ -711,7 +713,7 @@ abstract class SettingsStoreBase with Store {
@observable @observable
int customBitcoinFeeRate; int customBitcoinFeeRate;
final FlutterSecureStorage _secureStorage; final SecureStorage _secureStorage;
final SharedPreferences _sharedPreferences; final SharedPreferences _sharedPreferences;
final BackgroundTasks _backgroundTasks; final BackgroundTasks _backgroundTasks;
@ -754,7 +756,7 @@ abstract class SettingsStoreBase with Store {
BalanceDisplayMode initialBalanceDisplayMode = BalanceDisplayMode.availableBalance, BalanceDisplayMode initialBalanceDisplayMode = BalanceDisplayMode.availableBalance,
ThemeBase? initialTheme}) async { ThemeBase? initialTheme}) async {
final sharedPreferences = await getIt.getAsync<SharedPreferences>(); final sharedPreferences = await getIt.getAsync<SharedPreferences>();
final secureStorage = await getIt.get<FlutterSecureStorage>(); final secureStorage = await getIt.get<SecureStorage>();
final backgroundTasks = getIt.get<BackgroundTasks>(); final backgroundTasks = getIt.get<BackgroundTasks>();
final currentFiatCurrency = FiatCurrency.deserialize( final currentFiatCurrency = FiatCurrency.deserialize(
raw: sharedPreferences.getString(PreferencesKey.currentFiatCurrencyKey)!); raw: sharedPreferences.getString(PreferencesKey.currentFiatCurrencyKey)!);
@ -846,6 +848,7 @@ abstract class SettingsStoreBase with Store {
: defaultSeedPhraseLength; : defaultSeedPhraseLength;
final useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true; final useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true;
final usePolygonScan = sharedPreferences.getBool(PreferencesKey.usePolygonScan) ?? true; final usePolygonScan = sharedPreferences.getBool(PreferencesKey.usePolygonScan) ?? true;
final useTronGrid = sharedPreferences.getBool(PreferencesKey.useTronGrid) ?? true;
final defaultNanoRep = sharedPreferences.getString(PreferencesKey.defaultNanoRep) ?? ""; final defaultNanoRep = sharedPreferences.getString(PreferencesKey.defaultNanoRep) ?? "";
final defaultBananoRep = sharedPreferences.getString(PreferencesKey.defaultBananoRep) ?? ""; final defaultBananoRep = sharedPreferences.getString(PreferencesKey.defaultBananoRep) ?? "";
final lookupsTwitter = sharedPreferences.getBool(PreferencesKey.lookupsTwitter) ?? true; final lookupsTwitter = sharedPreferences.getBool(PreferencesKey.lookupsTwitter) ?? true;
@ -1090,6 +1093,7 @@ abstract class SettingsStoreBase with Store {
pinNativeTokenAtTop: pinNativeTokenAtTop, pinNativeTokenAtTop: pinNativeTokenAtTop,
useEtherscan: useEtherscan, useEtherscan: useEtherscan,
usePolygonScan: usePolygonScan, usePolygonScan: usePolygonScan,
useTronGrid: useTronGrid,
defaultNanoRep: defaultNanoRep, defaultNanoRep: defaultNanoRep,
defaultBananoRep: defaultBananoRep, defaultBananoRep: defaultBananoRep,
lookupsTwitter: lookupsTwitter, lookupsTwitter: lookupsTwitter,
@ -1227,6 +1231,7 @@ abstract class SettingsStoreBase with Store {
pinNativeTokenAtTop = sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop) ?? true; pinNativeTokenAtTop = sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop) ?? true;
useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true; useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true;
usePolygonScan = sharedPreferences.getBool(PreferencesKey.usePolygonScan) ?? true; usePolygonScan = sharedPreferences.getBool(PreferencesKey.usePolygonScan) ?? true;
useTronGrid = sharedPreferences.getBool(PreferencesKey.useTronGrid) ?? true;
defaultNanoRep = sharedPreferences.getString(PreferencesKey.defaultNanoRep) ?? ""; defaultNanoRep = sharedPreferences.getString(PreferencesKey.defaultNanoRep) ?? "";
defaultBananoRep = sharedPreferences.getString(PreferencesKey.defaultBananoRep) ?? ""; defaultBananoRep = sharedPreferences.getString(PreferencesKey.defaultBananoRep) ?? "";
lookupsTwitter = sharedPreferences.getBool(PreferencesKey.lookupsTwitter) ?? true; lookupsTwitter = sharedPreferences.getBool(PreferencesKey.lookupsTwitter) ?? true;

View file

@ -1,3 +1,4 @@
import 'package:cake_wallet/core/secure_storage.dart';
import 'package:cw_core/transaction_history.dart'; import 'package:cw_core/transaction_history.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/balance.dart';
@ -10,7 +11,6 @@ import 'dart:convert';
import 'package:cake_wallet/store/yat/yat_exception.dart'; import 'package:cake_wallet/store/yat/yat_exception.dart';
import 'package:http/http.dart'; import 'package:http/http.dart';
import 'dart:async'; import 'dart:async';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
part 'yat_store.g.dart'; part 'yat_store.g.dart';
@ -193,7 +193,7 @@ abstract class YatStoreBase with Store {
AppStore appStore; AppStore appStore;
FlutterSecureStorage secureStorage; SecureStorage secureStorage;
@observable @observable
String emoji; String emoji;

View file

@ -111,4 +111,9 @@ class CWTron extends Tron {
@override @override
String? getTronTRC20EstimatedFee(WalletBase wallet) => (wallet as TronWallet).trc20EstimatedFee; String? getTronTRC20EstimatedFee(WalletBase wallet) => (wallet as TronWallet).trc20EstimatedFee;
@override
void updateTronGridUsageState(WalletBase wallet, bool isEnabled) {
(wallet as TronWallet).updateScanProviderUsageState(isEnabled);
}
} }

View file

@ -1,10 +1,9 @@
import 'dart:io'; import 'dart:io';
import 'package:cake_wallet/core/backup_service.dart'; import 'package:cake_wallet/core/backup_service.dart';
import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/core/execution_state.dart';
import 'package:cake_wallet/core/secure_storage.dart';
import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:cake_wallet/entities/secret_store_key.dart';
import 'package:cake_wallet/store/secret_store.dart'; import 'package:cake_wallet/store/secret_store.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:cake_wallet/wallet_type_utils.dart'; import 'package:cake_wallet/wallet_type_utils.dart';
@ -34,7 +33,7 @@ abstract class BackupViewModelBase with Store {
}, fireImmediately: true); }, fireImmediately: true);
} }
final FlutterSecureStorage secureStorage; final SecureStorage secureStorage;
final SecretStore secretStore; final SecretStore secretStore;
final BackupService backupService; final BackupService backupService;

View file

@ -1,6 +1,5 @@
import 'package:cake_wallet/core/secure_storage.dart'; import 'package:cake_wallet/core/secure_storage.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:cake_wallet/entities/secret_store_key.dart'; import 'package:cake_wallet/entities/secret_store_key.dart';
import 'package:cake_wallet/store/secret_store.dart'; import 'package:cake_wallet/store/secret_store.dart';
@ -14,7 +13,7 @@ abstract class EditBackupPasswordViewModelBase with Store {
: backupPassword = secretStore.read(generateStoreKeyFor(key: SecretStoreKey.backupPassword)), : backupPassword = secretStore.read(generateStoreKeyFor(key: SecretStoreKey.backupPassword)),
_originalPassword = ''; _originalPassword = '';
final FlutterSecureStorage secureStorage; final SecureStorage secureStorage;
final SecretStore secretStore; final SecretStore secretStore;
@observable @observable
@ -38,7 +37,7 @@ abstract class EditBackupPasswordViewModelBase with Store {
@action @action
Future<void> save() async { Future<void> save() async {
final key = generateStoreKeyFor(key: SecretStoreKey.backupPassword); final key = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
await writeSecureStorage(secureStorage, key: key, value: backupPassword); await secureStorage.write(key: key, value: backupPassword);
secretStore.write(key: key, value: backupPassword); secretStore.write(key: key, value: backupPassword);
} }
} }

View file

@ -2,27 +2,34 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/ethereum/ethereum.dart';
import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/polygon/polygon.dart';
import 'package:cake_wallet/utils/device_info.dart';
import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_type.dart'; import 'package:cw_core/wallet_type.dart';
import 'package:ledger_flutter/ledger_flutter.dart'; import 'package:ledger_flutter/ledger_flutter.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
class LedgerViewModel { class LedgerViewModel {
final Ledger ledger = Ledger( late final Ledger ledger;
options: LedgerOptions(
scanMode: ScanMode.balanced,
maxScanDuration: const Duration(minutes: 5),
),
onPermissionRequest: (_) async {
Map<Permission, PermissionStatus> statuses = await [
Permission.bluetoothScan,
Permission.bluetoothConnect,
Permission.bluetoothAdvertise,
].request();
return statuses.values.where((status) => status.isDenied).isEmpty; LedgerViewModel() {
}, if (DeviceInfo.instance.isMobile) {
); ledger = Ledger(
options: LedgerOptions(
scanMode: ScanMode.balanced,
maxScanDuration: const Duration(minutes: 5),
),
onPermissionRequest: (_) async {
Map<Permission, PermissionStatus> statuses = await [
Permission.bluetoothScan,
Permission.bluetoothConnect,
Permission.bluetoothAdvertise,
].request();
return statuses.values.where((status) => status.isDenied).isEmpty;
},
);
}
}
Future<void> connectLedger(LedgerDevice device) async { Future<void> connectLedger(LedgerDevice device) async {
await ledger.connect(device); await ledger.connect(device);

View file

@ -7,19 +7,14 @@ import 'package:cake_wallet/store/settings_store.dart';
import 'package:cake_wallet/utils/payment_request.dart'; import 'package:cake_wallet/utils/payment_request.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart'; import 'package:fluttertoast/fluttertoast.dart';
import 'package:mobx/mobx.dart';
part 'link_view_model.g.dart'; class LinkViewModel {
LinkViewModel({
class LinkViewModel = LinkViewModelBase with _$LinkViewModel;
abstract class LinkViewModelBase with Store {
LinkViewModelBase({
required this.settingsStore, required this.settingsStore,
required this.appStore, required this.appStore,
required this.authenticationStore, required this.authenticationStore,
required this.navigatorKey, required this.navigatorKey,
}) {} });
final SettingsStore settingsStore; final SettingsStore settingsStore;
final AppStore appStore; final AppStore appStore;

View file

@ -3,6 +3,7 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart';
import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/ethereum/ethereum.dart';
import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/polygon/polygon.dart';
import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/store/settings_store.dart';
import 'package:cake_wallet/tron/tron.dart';
import 'package:cw_core/balance.dart'; import 'package:cw_core/balance.dart';
import 'package:cw_core/transaction_history.dart'; import 'package:cw_core/transaction_history.dart';
import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/transaction_info.dart';
@ -70,6 +71,9 @@ abstract class PrivacySettingsViewModelBase with Store {
@computed @computed
bool get usePolygonScan => _settingsStore.usePolygonScan; bool get usePolygonScan => _settingsStore.usePolygonScan;
@computed
bool get useTronGrid => _settingsStore.useTronGrid;
@computed @computed
bool get lookupTwitter => _settingsStore.lookupsTwitter; bool get lookupTwitter => _settingsStore.lookupsTwitter;
@ -92,6 +96,8 @@ abstract class PrivacySettingsViewModelBase with Store {
bool get canUsePolygonScan => _wallet.type == WalletType.polygon; bool get canUsePolygonScan => _wallet.type == WalletType.polygon;
bool get canUseTronGrid => _wallet.type == WalletType.tron;
@action @action
void setShouldSaveRecipientAddress(bool value) => void setShouldSaveRecipientAddress(bool value) =>
_settingsStore.shouldSaveRecipientAddress = value; _settingsStore.shouldSaveRecipientAddress = value;
@ -143,4 +149,10 @@ abstract class PrivacySettingsViewModelBase with Store {
_settingsStore.usePolygonScan = value; _settingsStore.usePolygonScan = value;
polygon!.updatePolygonScanUsageState(_wallet, value); polygon!.updatePolygonScanUsageState(_wallet, value);
} }
@action
void setUseTronGrid(bool value) {
_settingsStore.useTronGrid = value;
tron!.updateTronGridUsageState(_wallet, value);
}
} }

View file

@ -122,10 +122,10 @@ SPEC CHECKSUMS:
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
package_info: 6eba2fd8d3371dda2d85c8db6fe97488f24b74b2 package_info: 6eba2fd8d3371dda2d85c8db6fe97488f24b74b2
package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4 share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4
shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695 shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95 url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95
wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269 wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269

View file

@ -207,7 +207,7 @@
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastSwiftUpdateCheck = 0920; LastSwiftUpdateCheck = 0920;
LastUpgradeCheck = 1300; LastUpgradeCheck = 1510;
ORGANIZATIONNAME = ""; ORGANIZATIONNAME = "";
TargetAttributes = { TargetAttributes = {
33CC10EC2044A3C60003C045 = { 33CC10EC2044A3C60003C045 = {

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1300" LastUpgradeVersion = "1510"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
@ -15,7 +15,7 @@
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045" BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "Cake Wallet.app" BuildableName = "Monero.com.app"
BlueprintName = "Runner" BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj"> ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference> </BuildableReference>
@ -31,7 +31,7 @@
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045" BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "Cake Wallet.app" BuildableName = "Monero.com.app"
BlueprintName = "Runner" BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj"> ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference> </BuildableReference>
@ -54,7 +54,7 @@
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045" BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "Cake Wallet.app" BuildableName = "Monero.com.app"
BlueprintName = "Runner" BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj"> ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference> </BuildableReference>
@ -71,7 +71,7 @@
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "33CC10EC2044A3C60003C045" BlueprintIdentifier = "33CC10EC2044A3C60003C045"
BuildableName = "Cake Wallet.app" BuildableName = "Monero.com.app"
BlueprintName = "Runner" BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj"> ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference> </BuildableReference>

View file

@ -11,12 +11,6 @@ dependencies:
ref: cake-4.0.2 ref: cake-4.0.2
version: 4.0.2 version: 4.0.2
shared_preferences: ^2.0.15 shared_preferences: ^2.0.15
flutter_secure_storage:
git:
url: https://github.com/cake-tech/flutter_secure_storage.git
path: flutter_secure_storage
ref: cake-8.0.0
version: 8.0.0
# provider: ^6.0.3 # provider: ^6.0.3
rxdart: ^0.27.4 rxdart: ^0.27.4
yaml: ^3.1.1 yaml: ^3.1.1

View file

@ -371,10 +371,10 @@
"moonpay_alert_text": "يجب أن تكون قيمة المبلغ أكبر من أو تساوي ${minAmount} ${fiatCurrency}", "moonpay_alert_text": "يجب أن تكون قيمة المبلغ أكبر من أو تساوي ${minAmount} ${fiatCurrency}",
"more_options": "المزيد من الخيارات", "more_options": "المزيد من الخيارات",
"name": "ﻢﺳﺍ", "name": "ﻢﺳﺍ",
"nano_gpt_thanks_message": "شكرا لاستخدام nanogpt! تذكر أن تعود إلى المتصفح بعد اكتمال معاملتك!",
"nanogpt_subtitle": "جميع النماذج الأحدث (GPT-4 ، Claude). \\ nno اشتراك ، ادفع مع Crypto.",
"nano_current_rep": "الممثل الحالي", "nano_current_rep": "الممثل الحالي",
"nano_gpt_thanks_message": "شكرا لاستخدام nanogpt! تذكر أن تعود إلى المتصفح بعد اكتمال معاملتك!",
"nano_pick_new_rep": "اختر ممثلًا جديدًا", "nano_pick_new_rep": "اختر ممثلًا جديدًا",
"nanogpt_subtitle": "جميع النماذج الأحدث (GPT-4 ، Claude). \\ nno اشتراك ، ادفع مع Crypto.",
"narrow": "ضيق", "narrow": "ضيق",
"new_first_wallet_text": "حافظ بسهولة على أمان العملة المشفرة", "new_first_wallet_text": "حافظ بسهولة على أمان العملة المشفرة",
"new_node_testing": "تجربة العقدة الجديدة", "new_node_testing": "تجربة العقدة الجديدة",
@ -761,6 +761,7 @@
"transaction_sent_notice": "إذا لم تستمر الشاشة بعد دقيقة واحدة ، فتحقق من مستكشف البلوك والبريد الإلكتروني.", "transaction_sent_notice": "إذا لم تستمر الشاشة بعد دقيقة واحدة ، فتحقق من مستكشف البلوك والبريد الإلكتروني.",
"transactions": "المعاملات", "transactions": "المعاملات",
"transactions_by_date": "المعاملات حسب التاريخ", "transactions_by_date": "المعاملات حسب التاريخ",
"trongrid_history": "تاريخ ترونغريد",
"trusted": "موثوق به", "trusted": "موثوق به",
"tx_commit_exception_no_dust_on_change": "يتم رفض المعاملة مع هذا المبلغ. باستخدام هذه العملات المعدنية ، يمكنك إرسال ${min} دون تغيير أو ${max} الذي يعيد التغيير.", "tx_commit_exception_no_dust_on_change": "يتم رفض المعاملة مع هذا المبلغ. باستخدام هذه العملات المعدنية ، يمكنك إرسال ${min} دون تغيير أو ${max} الذي يعيد التغيير.",
"tx_commit_failed": "فشل ارتكاب المعاملة. يرجى الاتصال بالدعم.", "tx_commit_failed": "فشل ارتكاب المعاملة. يرجى الاتصال بالدعم.",

View file

@ -371,10 +371,10 @@
"moonpay_alert_text": "Сумата трябва да бъде най-малко ${minAmount} ${fiatCurrency}", "moonpay_alert_text": "Сумата трябва да бъде най-малко ${minAmount} ${fiatCurrency}",
"more_options": "Още настройки", "more_options": "Още настройки",
"name": "Име", "name": "Име",
"nano_gpt_thanks_message": "Благодаря, че използвахте Nanogpt! Не забравяйте да се върнете обратно към браузъра, след като транзакцията ви приключи!",
"nanogpt_subtitle": "Всички най-нови модели (GPT-4, Claude). \\ Nno абонамент, платете с Crypto.",
"nano_current_rep": "Настоящ представител", "nano_current_rep": "Настоящ представител",
"nano_gpt_thanks_message": "Благодаря, че използвахте Nanogpt! Не забравяйте да се върнете обратно към браузъра, след като транзакцията ви приключи!",
"nano_pick_new_rep": "Изберете нов представител", "nano_pick_new_rep": "Изберете нов представител",
"nanogpt_subtitle": "Всички най-нови модели (GPT-4, Claude). \\ Nno абонамент, платете с Crypto.",
"narrow": "Тесен", "narrow": "Тесен",
"new_first_wallet_text": "Лесно пазете криптовалутата си в безопасност", "new_first_wallet_text": "Лесно пазете криптовалутата си в безопасност",
"new_node_testing": "Тестване на нов node", "new_node_testing": "Тестване на нов node",
@ -761,6 +761,7 @@
"transaction_sent_notice": "Ако процесът продължи повече от 1 минута, проверете някой block explorer и своя имейл.", "transaction_sent_notice": "Ако процесът продължи повече от 1 минута, проверете някой block explorer и своя имейл.",
"transactions": "Транзакции", "transactions": "Транзакции",
"transactions_by_date": "Транзакции по дата", "transactions_by_date": "Транзакции по дата",
"trongrid_history": "Trongrid History",
"trusted": "Надежден", "trusted": "Надежден",
"tx_commit_exception_no_dust_on_change": "Сделката се отхвърля с тази сума. С тези монети можете да изпратите ${min} без промяна или ${max}, която връща промяна.", "tx_commit_exception_no_dust_on_change": "Сделката се отхвърля с тази сума. С тези монети можете да изпратите ${min} без промяна или ${max}, която връща промяна.",
"tx_commit_failed": "Компетацията на транзакцията не успя. Моля, свържете се с поддръжката.", "tx_commit_failed": "Компетацията на транзакцията не успя. Моля, свържете се с поддръжката.",

View file

@ -371,10 +371,10 @@
"moonpay_alert_text": "Částka musí být větší nebo rovna ${minAmount} ${fiatCurrency}", "moonpay_alert_text": "Částka musí být větší nebo rovna ${minAmount} ${fiatCurrency}",
"more_options": "Více možností", "more_options": "Více možností",
"name": "název", "name": "název",
"nano_gpt_thanks_message": "Děkujeme za používání Nanogpt! Nezapomeňte se po dokončení transakce vydat zpět do prohlížeče!",
"nanogpt_subtitle": "Všechny nejnovější modely (GPT-4, Claude). \\ Nno předplatné, plaťte krypto.",
"nano_current_rep": "Současný zástupce", "nano_current_rep": "Současný zástupce",
"nano_gpt_thanks_message": "Děkujeme za používání Nanogpt! Nezapomeňte se po dokončení transakce vydat zpět do prohlížeče!",
"nano_pick_new_rep": "Vyberte nového zástupce", "nano_pick_new_rep": "Vyberte nového zástupce",
"nanogpt_subtitle": "Všechny nejnovější modely (GPT-4, Claude). \\ Nno předplatné, plaťte krypto.",
"narrow": "Úzký", "narrow": "Úzký",
"new_first_wallet_text": "Snadno udržujte svou kryptoměnu v bezpečí", "new_first_wallet_text": "Snadno udržujte svou kryptoměnu v bezpečí",
"new_node_testing": "Testování nového uzlu", "new_node_testing": "Testování nového uzlu",
@ -761,6 +761,7 @@
"transaction_sent_notice": "Pokud proces nepokročí během 1 minuty, zkontrolujte block explorer a svůj e-mail.", "transaction_sent_notice": "Pokud proces nepokročí během 1 minuty, zkontrolujte block explorer a svůj e-mail.",
"transactions": "Transakce", "transactions": "Transakce",
"transactions_by_date": "Transakce podle data", "transactions_by_date": "Transakce podle data",
"trongrid_history": "Trongridní historie",
"trusted": "Důvěřovat", "trusted": "Důvěřovat",
"tx_commit_exception_no_dust_on_change": "Transakce je zamítnuta s touto částkou. S těmito mincemi můžete odeslat ${min} bez změny nebo ${max}, které se vrátí změna.", "tx_commit_exception_no_dust_on_change": "Transakce je zamítnuta s touto částkou. S těmito mincemi můžete odeslat ${min} bez změny nebo ${max}, které se vrátí změna.",
"tx_commit_failed": "Transakce COMPORT selhala. Kontaktujte prosím podporu.", "tx_commit_failed": "Transakce COMPORT selhala. Kontaktujte prosím podporu.",

View file

@ -371,10 +371,10 @@
"moonpay_alert_text": "Der Wert des Betrags muss größer oder gleich ${minAmount} ${fiatCurrency} sein", "moonpay_alert_text": "Der Wert des Betrags muss größer oder gleich ${minAmount} ${fiatCurrency} sein",
"more_options": "Weitere Optionen", "more_options": "Weitere Optionen",
"name": "Name", "name": "Name",
"nano_gpt_thanks_message": "Danke, dass du Nanogpt benutzt hast! Denken Sie daran, nach Abschluss Ihrer Transaktion zurück zum Browser zu gehen!",
"nanogpt_subtitle": "Alle neuesten Modelle (GPT-4, Claude).",
"nano_current_rep": "Aktueller Vertreter", "nano_current_rep": "Aktueller Vertreter",
"nano_gpt_thanks_message": "Danke, dass du Nanogpt benutzt hast! Denken Sie daran, nach Abschluss Ihrer Transaktion zurück zum Browser zu gehen!",
"nano_pick_new_rep": "Wählen Sie einen neuen Vertreter aus", "nano_pick_new_rep": "Wählen Sie einen neuen Vertreter aus",
"nanogpt_subtitle": "Alle neuesten Modelle (GPT-4, Claude).",
"narrow": "Eng", "narrow": "Eng",
"new_first_wallet_text": "Bewahren Sie Ihre Kryptowährung einfach sicher auf", "new_first_wallet_text": "Bewahren Sie Ihre Kryptowährung einfach sicher auf",
"new_node_testing": "Neuen Knoten testen", "new_node_testing": "Neuen Knoten testen",
@ -762,6 +762,7 @@
"transaction_sent_notice": "Wenn der Bildschirm nach 1 Minute nicht weitergeht, überprüfen Sie einen Block-Explorer und Ihre E-Mail.", "transaction_sent_notice": "Wenn der Bildschirm nach 1 Minute nicht weitergeht, überprüfen Sie einen Block-Explorer und Ihre E-Mail.",
"transactions": "Transaktionen", "transactions": "Transaktionen",
"transactions_by_date": "Transaktionen nach Datum", "transactions_by_date": "Transaktionen nach Datum",
"trongrid_history": "Tronglidgeschichte",
"trusted": "Vertrauenswürdige", "trusted": "Vertrauenswürdige",
"tx_commit_exception_no_dust_on_change": "Die Transaktion wird diesen Betrag abgelehnt. Mit diesen Münzen können Sie ${min} ohne Veränderung oder ${max} senden, die Änderungen zurückgeben.", "tx_commit_exception_no_dust_on_change": "Die Transaktion wird diesen Betrag abgelehnt. Mit diesen Münzen können Sie ${min} ohne Veränderung oder ${max} senden, die Änderungen zurückgeben.",
"tx_commit_failed": "Transaktionsausschüsse ist fehlgeschlagen. Bitte wenden Sie sich an Support.", "tx_commit_failed": "Transaktionsausschüsse ist fehlgeschlagen. Bitte wenden Sie sich an Support.",

View file

@ -371,10 +371,10 @@
"moonpay_alert_text": "Value of the amount must be more or equal to ${minAmount} ${fiatCurrency}", "moonpay_alert_text": "Value of the amount must be more or equal to ${minAmount} ${fiatCurrency}",
"more_options": "More Options", "more_options": "More Options",
"name": "Name", "name": "Name",
"nano_gpt_thanks_message": "Thanks for using NanoGPT! Remember to head back to the browser after your transaction completes!",
"nanogpt_subtitle": "All the newest models (GPT-4, Claude).\\nNo subscription, pay with crypto.",
"nano_current_rep": "Current Representative", "nano_current_rep": "Current Representative",
"nano_gpt_thanks_message": "Thanks for using NanoGPT! Remember to head back to the browser after your transaction completes!",
"nano_pick_new_rep": "Pick a new representative", "nano_pick_new_rep": "Pick a new representative",
"nanogpt_subtitle": "All the newest models (GPT-4, Claude).\\nNo subscription, pay with crypto.",
"narrow": "Narrow", "narrow": "Narrow",
"new_first_wallet_text": "Keep your crypto safe, piece of cake", "new_first_wallet_text": "Keep your crypto safe, piece of cake",
"new_node_testing": "New node testing", "new_node_testing": "New node testing",
@ -761,6 +761,7 @@
"transaction_sent_notice": "If the screen doesnt proceed after 1 minute, check a block explorer and your email.", "transaction_sent_notice": "If the screen doesnt proceed after 1 minute, check a block explorer and your email.",
"transactions": "Transactions", "transactions": "Transactions",
"transactions_by_date": "Transactions by date", "transactions_by_date": "Transactions by date",
"trongrid_history": "TronGrid history",
"trusted": "Trusted", "trusted": "Trusted",
"tx_commit_exception_no_dust_on_change": "The transaction is rejected with this amount. With these coins you can send ${min} without change or ${max} that returns change.", "tx_commit_exception_no_dust_on_change": "The transaction is rejected with this amount. With these coins you can send ${min} without change or ${max} that returns change.",
"tx_commit_failed": "Transaction commit failed. Please contact support.", "tx_commit_failed": "Transaction commit failed. Please contact support.",

View file

@ -371,10 +371,10 @@
"moonpay_alert_text": "El valor de la cantidad debe ser mayor o igual a ${minAmount} ${fiatCurrency}", "moonpay_alert_text": "El valor de la cantidad debe ser mayor o igual a ${minAmount} ${fiatCurrency}",
"more_options": "Más Opciones", "more_options": "Más Opciones",
"name": "Nombre", "name": "Nombre",
"nano_gpt_thanks_message": "¡Gracias por usar nanogpt! ¡Recuerde regresar al navegador después de que se complete su transacción!",
"nanogpt_subtitle": "Todos los modelos más nuevos (GPT-4, Claude). \\ Nno suscripción, pague con cripto.",
"nano_current_rep": "Representante actual", "nano_current_rep": "Representante actual",
"nano_gpt_thanks_message": "¡Gracias por usar nanogpt! ¡Recuerde regresar al navegador después de que se complete su transacción!",
"nano_pick_new_rep": "Elija un nuevo representante", "nano_pick_new_rep": "Elija un nuevo representante",
"nanogpt_subtitle": "Todos los modelos más nuevos (GPT-4, Claude). \\ Nno suscripción, pague con cripto.",
"narrow": "Angosto", "narrow": "Angosto",
"new_first_wallet_text": "Mantenga fácilmente su criptomoneda segura", "new_first_wallet_text": "Mantenga fácilmente su criptomoneda segura",
"new_node_testing": "Prueba de nuevos nodos", "new_node_testing": "Prueba de nuevos nodos",
@ -762,6 +762,7 @@
"transaction_sent_notice": "Si la pantalla no continúa después de 1 minuto, revisa un explorador de bloques y tu correo electrónico.", "transaction_sent_notice": "Si la pantalla no continúa después de 1 minuto, revisa un explorador de bloques y tu correo electrónico.",
"transactions": "Actas", "transactions": "Actas",
"transactions_by_date": "Transacciones por fecha", "transactions_by_date": "Transacciones por fecha",
"trongrid_history": "Historia trongrid",
"trusted": "de confianza", "trusted": "de confianza",
"tx_commit_exception_no_dust_on_change": "La transacción se rechaza con esta cantidad. Con estas monedas puede enviar ${min} sin cambios o ${max} que devuelve el cambio.", "tx_commit_exception_no_dust_on_change": "La transacción se rechaza con esta cantidad. Con estas monedas puede enviar ${min} sin cambios o ${max} que devuelve el cambio.",
"tx_commit_failed": "La confirmación de transacción falló. Póngase en contacto con el soporte.", "tx_commit_failed": "La confirmación de transacción falló. Póngase en contacto con el soporte.",

View file

@ -371,10 +371,10 @@
"moonpay_alert_text": "Le montant doit être au moins égal à ${minAmount} ${fiatCurrency}", "moonpay_alert_text": "Le montant doit être au moins égal à ${minAmount} ${fiatCurrency}",
"more_options": "Plus d'options", "more_options": "Plus d'options",
"name": "Nom", "name": "Nom",
"nano_gpt_thanks_message": "Merci d'avoir utilisé Nanogpt! N'oubliez pas de retourner au navigateur une fois votre transaction terminée!",
"nanogpt_subtitle": "Tous les modèles les plus récents (GPT-4, Claude). \\ NNO abonnement, payez avec crypto.",
"nano_current_rep": "Représentant actuel", "nano_current_rep": "Représentant actuel",
"nano_gpt_thanks_message": "Merci d'avoir utilisé Nanogpt! N'oubliez pas de retourner au navigateur une fois votre transaction terminée!",
"nano_pick_new_rep": "Choisissez un nouveau représentant", "nano_pick_new_rep": "Choisissez un nouveau représentant",
"nanogpt_subtitle": "Tous les modèles les plus récents (GPT-4, Claude). \\ NNO abonnement, payez avec crypto.",
"narrow": "Étroit", "narrow": "Étroit",
"new_first_wallet_text": "Gardez facilement votre crypto-monnaie en sécurité", "new_first_wallet_text": "Gardez facilement votre crypto-monnaie en sécurité",
"new_node_testing": "Test du nouveau nœud", "new_node_testing": "Test du nouveau nœud",
@ -761,6 +761,7 @@
"transaction_sent_notice": "Si l'écran ne continue pas après 1 minute, vérifiez un explorateur de blocs et votre e-mail.", "transaction_sent_notice": "Si l'écran ne continue pas après 1 minute, vérifiez un explorateur de blocs et votre e-mail.",
"transactions": "Transactions", "transactions": "Transactions",
"transactions_by_date": "Transactions par date", "transactions_by_date": "Transactions par date",
"trongrid_history": "Histoire de la trongride",
"trusted": "de confiance", "trusted": "de confiance",
"tx_commit_exception_no_dust_on_change": "La transaction est rejetée avec ce montant. Avec ces pièces, vous pouvez envoyer ${min} sans changement ou ${max} qui renvoie le changement.", "tx_commit_exception_no_dust_on_change": "La transaction est rejetée avec ce montant. Avec ces pièces, vous pouvez envoyer ${min} sans changement ou ${max} qui renvoie le changement.",
"tx_commit_failed": "La validation de la transaction a échoué. Veuillez contacter l'assistance.", "tx_commit_failed": "La validation de la transaction a échoué. Veuillez contacter l'assistance.",

View file

@ -371,10 +371,10 @@
"moonpay_alert_text": "Darajar adadin dole ne ya zama fiye ko daidai da ${minAmount} ${fiatCurrency}", "moonpay_alert_text": "Darajar adadin dole ne ya zama fiye ko daidai da ${minAmount} ${fiatCurrency}",
"more_options": "Ƙarin Zaɓuɓɓuka", "more_options": "Ƙarin Zaɓuɓɓuka",
"name": "Suna", "name": "Suna",
"nano_gpt_thanks_message": "Na gode da amfani da Nanogpt! Ka tuna da komawa zuwa mai bincike bayan ma'amalar ka ta cika!",
"nanogpt_subtitle": "Duk sabbin samfuran (GPT-4, CLODE). \\ NNO biyan kuɗi, biya tare da crypto.",
"nano_current_rep": "Wakilin Yanzu", "nano_current_rep": "Wakilin Yanzu",
"nano_gpt_thanks_message": "Na gode da amfani da Nanogpt! Ka tuna da komawa zuwa mai bincike bayan ma'amalar ka ta cika!",
"nano_pick_new_rep": "Dauki sabon wakili", "nano_pick_new_rep": "Dauki sabon wakili",
"nanogpt_subtitle": "Duk sabbin samfuran (GPT-4, CLODE). \\ NNO biyan kuɗi, biya tare da crypto.",
"narrow": "kunkuntar", "narrow": "kunkuntar",
"new_first_wallet_text": "A sauƙaƙe kiyaye kuzarin ku", "new_first_wallet_text": "A sauƙaƙe kiyaye kuzarin ku",
"new_node_testing": "Sabbin gwajin kumburi", "new_node_testing": "Sabbin gwajin kumburi",
@ -763,6 +763,7 @@
"transaction_sent_notice": "Idan allon bai ci gaba ba bayan minti 1, duba mai binciken toshewa da imel ɗin ku.", "transaction_sent_notice": "Idan allon bai ci gaba ba bayan minti 1, duba mai binciken toshewa da imel ɗin ku.",
"transactions": "Ma'amaloli", "transactions": "Ma'amaloli",
"transactions_by_date": "Ma'amaloli ta kwanan wata", "transactions_by_date": "Ma'amaloli ta kwanan wata",
"trongrid_history": "Tarihin Trongrid",
"trusted": "Amintacce", "trusted": "Amintacce",
"tx_commit_exception_no_dust_on_change": "An ƙi ma'amala da wannan adadin. Tare da waɗannan tsabar kudi Zaka iya aika ${min}, ba tare da canji ba ko ${max} wanda ya dawo canzawa.", "tx_commit_exception_no_dust_on_change": "An ƙi ma'amala da wannan adadin. Tare da waɗannan tsabar kudi Zaka iya aika ${min}, ba tare da canji ba ko ${max} wanda ya dawo canzawa.",
"tx_commit_failed": "Ma'amala ya kasa. Da fatan za a tuntuɓi goyan baya.", "tx_commit_failed": "Ma'amala ya kasa. Da fatan za a tuntuɓi goyan baya.",

View file

@ -371,10 +371,10 @@
"moonpay_alert_text": "राशि का मूल्य अधिक है या करने के लिए बराबर होना चाहिए ${minAmount} ${fiatCurrency}", "moonpay_alert_text": "राशि का मूल्य अधिक है या करने के लिए बराबर होना चाहिए ${minAmount} ${fiatCurrency}",
"more_options": "और विकल्प", "more_options": "और विकल्प",
"name": "नाम", "name": "नाम",
"nano_gpt_thanks_message": "Nanogpt का उपयोग करने के लिए धन्यवाद! अपने लेन -देन के पूरा होने के बाद ब्राउज़र पर वापस जाना याद रखें!",
"nanogpt_subtitle": "सभी नवीनतम मॉडल (GPT-4, क्लाउड)। \\ nno सदस्यता, क्रिप्टो के साथ भुगतान करें।",
"nano_current_rep": "वर्तमान प्रतिनिधि", "nano_current_rep": "वर्तमान प्रतिनिधि",
"nano_gpt_thanks_message": "Nanogpt का उपयोग करने के लिए धन्यवाद! अपने लेन -देन के पूरा होने के बाद ब्राउज़र पर वापस जाना याद रखें!",
"nano_pick_new_rep": "एक नया प्रतिनिधि चुनें", "nano_pick_new_rep": "एक नया प्रतिनिधि चुनें",
"nanogpt_subtitle": "सभी नवीनतम मॉडल (GPT-4, क्लाउड)। \\ nno सदस्यता, क्रिप्टो के साथ भुगतान करें।",
"narrow": "सँकरा", "narrow": "सँकरा",
"new_first_wallet_text": "आसानी से अपनी क्रिप्टोक्यूरेंसी को सुरक्षित रखें", "new_first_wallet_text": "आसानी से अपनी क्रिप्टोक्यूरेंसी को सुरक्षित रखें",
"new_node_testing": "नई नोड परीक्षण", "new_node_testing": "नई नोड परीक्षण",
@ -763,6 +763,7 @@
"transaction_sent_notice": "अगर 1 मिनट के बाद भी स्क्रीन आगे नहीं बढ़ती है, तो ब्लॉक एक्सप्लोरर और अपना ईमेल देखें।", "transaction_sent_notice": "अगर 1 मिनट के बाद भी स्क्रीन आगे नहीं बढ़ती है, तो ब्लॉक एक्सप्लोरर और अपना ईमेल देखें।",
"transactions": "लेन-देन", "transactions": "लेन-देन",
"transactions_by_date": "तारीख से लेन-देन", "transactions_by_date": "तारीख से लेन-देन",
"trongrid_history": "ट्रॉन्ग्रिड का इतिहास",
"trusted": "भरोसा", "trusted": "भरोसा",
"tx_commit_exception_no_dust_on_change": "लेनदेन को इस राशि से खारिज कर दिया जाता है। इन सिक्कों के साथ आप चेंज या ${min} के बिना ${max} को भेज सकते हैं जो परिवर्तन लौटाता है।", "tx_commit_exception_no_dust_on_change": "लेनदेन को इस राशि से खारिज कर दिया जाता है। इन सिक्कों के साथ आप चेंज या ${min} के बिना ${max} को भेज सकते हैं जो परिवर्तन लौटाता है।",
"tx_commit_failed": "लेन -देन प्रतिबद्ध विफल। कृपया संपर्क समर्थन करें।", "tx_commit_failed": "लेन -देन प्रतिबद्ध विफल। कृपया संपर्क समर्थन करें।",

View file

@ -371,10 +371,10 @@
"moonpay_alert_text": "Vrijednost iznosa mora biti veća ili jednaka ${minAmount} ${fiatCurrency}", "moonpay_alert_text": "Vrijednost iznosa mora biti veća ili jednaka ${minAmount} ${fiatCurrency}",
"more_options": "Više opcija", "more_options": "Više opcija",
"name": "Ime", "name": "Ime",
"nano_gpt_thanks_message": "Hvala što ste koristili nanogpt! Ne zaboravite da se vratite u preglednik nakon što vam se transakcija završi!",
"nanogpt_subtitle": "Svi najnoviji modeli (GPT-4, Claude). \\ NNO pretplata, plaćajte kripto.",
"nano_current_rep": "Trenutni predstavnik", "nano_current_rep": "Trenutni predstavnik",
"nano_gpt_thanks_message": "Hvala što ste koristili nanogpt! Ne zaboravite da se vratite u preglednik nakon što vam se transakcija završi!",
"nano_pick_new_rep": "Odaberite novog predstavnika", "nano_pick_new_rep": "Odaberite novog predstavnika",
"nanogpt_subtitle": "Svi najnoviji modeli (GPT-4, Claude). \\ NNO pretplata, plaćajte kripto.",
"narrow": "Usko", "narrow": "Usko",
"new_first_wallet_text": "Jednostavno čuvajte svoju kripto valutu", "new_first_wallet_text": "Jednostavno čuvajte svoju kripto valutu",
"new_node_testing": "Provjera novog nodea", "new_node_testing": "Provjera novog nodea",
@ -761,6 +761,7 @@
"transaction_sent_notice": "Ako se zaslon ne nastavi nakon 1 minute, provjerite block explorer i svoju e-poštu.", "transaction_sent_notice": "Ako se zaslon ne nastavi nakon 1 minute, provjerite block explorer i svoju e-poštu.",
"transactions": "Transakcije", "transactions": "Transakcije",
"transactions_by_date": "Transakcije prema datumu", "transactions_by_date": "Transakcije prema datumu",
"trongrid_history": "Povijest Trongrida",
"trusted": "vjerovao", "trusted": "vjerovao",
"tx_commit_exception_no_dust_on_change": "Transakcija se odbija s tim iznosom. Pomoću ovih kovanica možete poslati ${min} bez promjene ili ${max} koja vraća promjenu.", "tx_commit_exception_no_dust_on_change": "Transakcija se odbija s tim iznosom. Pomoću ovih kovanica možete poslati ${min} bez promjene ili ${max} koja vraća promjenu.",
"tx_commit_failed": "Obveza transakcije nije uspjela. Molimo kontaktirajte podršku.", "tx_commit_failed": "Obveza transakcije nije uspjela. Molimo kontaktirajte podršku.",

View file

@ -371,10 +371,10 @@
"moonpay_alert_text": "Nilai jumlah harus lebih atau sama dengan ${minAmount} ${fiatCurrency}", "moonpay_alert_text": "Nilai jumlah harus lebih atau sama dengan ${minAmount} ${fiatCurrency}",
"more_options": "Opsi Lainnya", "more_options": "Opsi Lainnya",
"name": "Nama", "name": "Nama",
"nano_gpt_thanks_message": "Terima kasih telah menggunakan Nanogpt! Ingatlah untuk kembali ke browser setelah transaksi Anda selesai!",
"nanogpt_subtitle": "Semua model terbaru (GPT-4, Claude). \\ Nno langganan, bayar dengan crypto.",
"nano_current_rep": "Perwakilan saat ini", "nano_current_rep": "Perwakilan saat ini",
"nano_gpt_thanks_message": "Terima kasih telah menggunakan Nanogpt! Ingatlah untuk kembali ke browser setelah transaksi Anda selesai!",
"nano_pick_new_rep": "Pilih perwakilan baru", "nano_pick_new_rep": "Pilih perwakilan baru",
"nanogpt_subtitle": "Semua model terbaru (GPT-4, Claude). \\ Nno langganan, bayar dengan crypto.",
"narrow": "Sempit", "narrow": "Sempit",
"new_first_wallet_text": "Dengan mudah menjaga cryptocurrency Anda aman", "new_first_wallet_text": "Dengan mudah menjaga cryptocurrency Anda aman",
"new_node_testing": "Pengujian node baru", "new_node_testing": "Pengujian node baru",
@ -764,6 +764,7 @@
"transaction_sent_notice": "Jika layar tidak bergerak setelah 1 menit, periksa block explorer dan email Anda.", "transaction_sent_notice": "Jika layar tidak bergerak setelah 1 menit, periksa block explorer dan email Anda.",
"transactions": "Transaksi", "transactions": "Transaksi",
"transactions_by_date": "Transaksi berdasarkan tanggal", "transactions_by_date": "Transaksi berdasarkan tanggal",
"trongrid_history": "Sejarah Trongrid",
"trusted": "Dipercayai", "trusted": "Dipercayai",
"tx_commit_exception_no_dust_on_change": "Transaksi ditolak dengan jumlah ini. Dengan koin ini Anda dapat mengirim ${min} tanpa perubahan atau ${max} yang mengembalikan perubahan.", "tx_commit_exception_no_dust_on_change": "Transaksi ditolak dengan jumlah ini. Dengan koin ini Anda dapat mengirim ${min} tanpa perubahan atau ${max} yang mengembalikan perubahan.",
"tx_commit_failed": "Transaksi Gagal. Silakan hubungi Dukungan.", "tx_commit_failed": "Transaksi Gagal. Silakan hubungi Dukungan.",

View file

@ -372,10 +372,10 @@
"moonpay_alert_text": "Il valore dell'importo deve essere maggiore o uguale a ${minAmount} ${fiatCurrency}", "moonpay_alert_text": "Il valore dell'importo deve essere maggiore o uguale a ${minAmount} ${fiatCurrency}",
"more_options": "Altre opzioni", "more_options": "Altre opzioni",
"name": "Nome", "name": "Nome",
"nano_gpt_thanks_message": "Grazie per aver usato il nanogpt! Ricorda di tornare al browser dopo il completamento della transazione!",
"nanogpt_subtitle": "Tutti i modelli più recenti (GPT-4, Claude). Abbonamento nno, paga con cripto.",
"nano_current_rep": "Rappresentante attuale", "nano_current_rep": "Rappresentante attuale",
"nano_gpt_thanks_message": "Grazie per aver usato il nanogpt! Ricorda di tornare al browser dopo il completamento della transazione!",
"nano_pick_new_rep": "Scegli un nuovo rappresentante", "nano_pick_new_rep": "Scegli un nuovo rappresentante",
"nanogpt_subtitle": "Tutti i modelli più recenti (GPT-4, Claude). Abbonamento nno, paga con cripto.",
"narrow": "Stretto", "narrow": "Stretto",
"new_first_wallet_text": "Mantieni facilmente la tua criptovaluta al sicuro", "new_first_wallet_text": "Mantieni facilmente la tua criptovaluta al sicuro",
"new_node_testing": "Test novo nodo", "new_node_testing": "Test novo nodo",
@ -763,6 +763,7 @@
"transaction_sent_notice": "Se lo schermo non procede dopo 1 minuto, controlla un block explorer e la tua email.", "transaction_sent_notice": "Se lo schermo non procede dopo 1 minuto, controlla un block explorer e la tua email.",
"transactions": "Transazioni", "transactions": "Transazioni",
"transactions_by_date": "Transazioni per data", "transactions_by_date": "Transazioni per data",
"trongrid_history": "Storia del trongride",
"trusted": "di fiducia", "trusted": "di fiducia",
"tx_commit_exception_no_dust_on_change": "La transazione viene respinta con questo importo. Con queste monete è possibile inviare ${min} senza modifiche o ${max} che restituisce il cambiamento.", "tx_commit_exception_no_dust_on_change": "La transazione viene respinta con questo importo. Con queste monete è possibile inviare ${min} senza modifiche o ${max} che restituisce il cambiamento.",
"tx_commit_failed": "Commit di transazione non riuscita. Si prega di contattare il supporto.", "tx_commit_failed": "Commit di transazione non riuscita. Si prega di contattare il supporto.",

View file

@ -372,10 +372,10 @@
"moonpay_alert_text": "金額の値は以上でなければなりません ${minAmount} ${fiatCurrency}", "moonpay_alert_text": "金額の値は以上でなければなりません ${minAmount} ${fiatCurrency}",
"more_options": "その他のオプション", "more_options": "その他のオプション",
"name": "名前", "name": "名前",
"nano_gpt_thanks_message": "NanoGptを使用してくれてありがとうトランザクションが完了したら、ブラウザに戻ることを忘れないでください",
"nanogpt_subtitle": "すべての最新モデルGPT-4、Claude。\\ nnoサブスクリプション、暗号で支払います。",
"nano_current_rep": "現在の代表", "nano_current_rep": "現在の代表",
"nano_gpt_thanks_message": "NanoGptを使用してくれてありがとうトランザクションが完了したら、ブラウザに戻ることを忘れないでください",
"nano_pick_new_rep": "新しい代表者を選びます", "nano_pick_new_rep": "新しい代表者を選びます",
"nanogpt_subtitle": "すべての最新モデルGPT-4、Claude。\\ nnoサブスクリプション、暗号で支払います。",
"narrow": "狭い", "narrow": "狭い",
"new_first_wallet_text": "暗号通貨を簡単に安全に保ちます", "new_first_wallet_text": "暗号通貨を簡単に安全に保ちます",
"new_node_testing": "新しいノードのテスト", "new_node_testing": "新しいノードのテスト",
@ -762,6 +762,7 @@
"transaction_sent_notice": "1分経っても画面が進まない場合は、ブロックエクスプローラーとメールアドレスを確認してください。", "transaction_sent_notice": "1分経っても画面が進まない場合は、ブロックエクスプローラーとメールアドレスを確認してください。",
"transactions": "取引", "transactions": "取引",
"transactions_by_date": "日付ごとの取引", "transactions_by_date": "日付ごとの取引",
"trongrid_history": "トロンリッドの歴史",
"trusted": "信頼できる", "trusted": "信頼できる",
"tx_commit_exception_no_dust_on_change": "この金額ではトランザクションは拒否されます。 これらのコインを使用すると、おつりなしの ${min} またはおつりを返す ${max} を送信できます。", "tx_commit_exception_no_dust_on_change": "この金額ではトランザクションは拒否されます。 これらのコインを使用すると、おつりなしの ${min} またはおつりを返す ${max} を送信できます。",
"tx_commit_failed": "トランザクションコミットは失敗しました。サポートに連絡してください。", "tx_commit_failed": "トランザクションコミットは失敗しました。サポートに連絡してください。",

View file

@ -371,10 +371,10 @@
"moonpay_alert_text": "금액은 다음보다 크거나 같아야합니다 ${minAmount} ${fiatCurrency}", "moonpay_alert_text": "금액은 다음보다 크거나 같아야합니다 ${minAmount} ${fiatCurrency}",
"more_options": "추가 옵션", "more_options": "추가 옵션",
"name": "이름", "name": "이름",
"nano_gpt_thanks_message": "Nanogpt를 사용해 주셔서 감사합니다! 거래가 완료된 후 브라우저로 돌아가는 것을 잊지 마십시오!",
"nanogpt_subtitle": "모든 최신 모델 (GPT-4, Claude). \\ nno 구독, Crypto로 지불하십시오.",
"nano_current_rep": "현재 대표", "nano_current_rep": "현재 대표",
"nano_gpt_thanks_message": "Nanogpt를 사용해 주셔서 감사합니다! 거래가 완료된 후 브라우저로 돌아가는 것을 잊지 마십시오!",
"nano_pick_new_rep": "새로운 담당자를 선택하십시오", "nano_pick_new_rep": "새로운 담당자를 선택하십시오",
"nanogpt_subtitle": "모든 최신 모델 (GPT-4, Claude). \\ nno 구독, Crypto로 지불하십시오.",
"narrow": "좁은", "narrow": "좁은",
"new_first_wallet_text": "cryptocurrency를 쉽게 안전하게 유지하십시오", "new_first_wallet_text": "cryptocurrency를 쉽게 안전하게 유지하십시오",
"new_node_testing": "새로운 노드 테스트", "new_node_testing": "새로운 노드 테스트",
@ -762,6 +762,7 @@
"transaction_sent_notice": "1분 후에도 화면이 진행되지 않으면 블록 익스플로러와 이메일을 확인하세요.", "transaction_sent_notice": "1분 후에도 화면이 진행되지 않으면 블록 익스플로러와 이메일을 확인하세요.",
"transactions": "업무", "transactions": "업무",
"transactions_by_date": "날짜 별 거래", "transactions_by_date": "날짜 별 거래",
"trongrid_history": "트롱 트리드 역사",
"trusted": "신뢰할 수 있는", "trusted": "신뢰할 수 있는",
"tx_commit_exception_no_dust_on_change": "이 금액으로 거래가 거부되었습니다. 이 코인을 사용하면 거스름돈 없이 ${min}를 보내거나 거스름돈을 반환하는 ${max}를 보낼 수 있습니다.", "tx_commit_exception_no_dust_on_change": "이 금액으로 거래가 거부되었습니다. 이 코인을 사용하면 거스름돈 없이 ${min}를 보내거나 거스름돈을 반환하는 ${max}를 보낼 수 있습니다.",
"tx_commit_failed": "거래 커밋이 실패했습니다. 지원에 연락하십시오.", "tx_commit_failed": "거래 커밋이 실패했습니다. 지원에 연락하십시오.",

View file

@ -371,10 +371,10 @@
"moonpay_alert_text": "ပမာဏ၏တန်ဖိုးသည် ${minAmount} ${fiatCurrency} နှင့် ပိုနေရမည်", "moonpay_alert_text": "ပမာဏ၏တန်ဖိုးသည် ${minAmount} ${fiatCurrency} နှင့် ပိုနေရမည်",
"more_options": "နောက်ထပ် ရွေးချယ်စရာများ", "more_options": "နောက်ထပ် ရွေးချယ်စရာများ",
"name": "နာမည်", "name": "နာမည်",
"nano_gpt_thanks_message": "nanogpt ကိုသုံးပြီးကျေးဇူးတင်ပါတယ် သင်၏ငွေပေးငွေယူပြီးနောက် browser သို့ပြန်သွားရန်သတိရပါ။",
"nanogpt_subtitle": "အားလုံးနောက်ဆုံးပေါ်မော်ဒယ်များ (GPT-4, Claude) ။ \\ nno subscription, crypto နှင့်အတူပေးဆောင်။",
"nano_current_rep": "လက်ရှိကိုယ်စားလှယ်", "nano_current_rep": "လက်ရှိကိုယ်စားလှယ်",
"nano_gpt_thanks_message": "nanogpt ကိုသုံးပြီးကျေးဇူးတင်ပါတယ် သင်၏ငွေပေးငွေယူပြီးနောက် browser သို့ပြန်သွားရန်သတိရပါ။",
"nano_pick_new_rep": "အသစ်တစ်ခုကိုရွေးပါ", "nano_pick_new_rep": "အသစ်တစ်ခုကိုရွေးပါ",
"nanogpt_subtitle": "အားလုံးနောက်ဆုံးပေါ်မော်ဒယ်များ (GPT-4, Claude) ။ \\ nno subscription, crypto နှင့်အတူပေးဆောင်။",
"narrow": "ကျဉ်းသော", "narrow": "ကျဉ်းသော",
"new_first_wallet_text": "သင့်ရဲ့ cryptocurrencrencres ကိုအလွယ်တကူလုံခြုံစွာထားရှိပါ", "new_first_wallet_text": "သင့်ရဲ့ cryptocurrencrencres ကိုအလွယ်တကူလုံခြုံစွာထားရှိပါ",
"new_node_testing": "နှာခေါင်း အသစ်စမ်းသပ်ခြင်း။", "new_node_testing": "နှာခေါင်း အသစ်စမ်းသပ်ခြင်း။",
@ -761,6 +761,7 @@
"transaction_sent_notice": "မျက်နှာပြင်သည် ၁ မိနစ်အကြာတွင် ဆက်လက်မလုပ်ဆောင်ပါက၊ ပိတ်ဆို့ရှာဖွေသူနှင့် သင့်အီးမေးလ်ကို စစ်ဆေးပါ။", "transaction_sent_notice": "မျက်နှာပြင်သည် ၁ မိနစ်အကြာတွင် ဆက်လက်မလုပ်ဆောင်ပါက၊ ပိတ်ဆို့ရှာဖွေသူနှင့် သင့်အီးမေးလ်ကို စစ်ဆေးပါ။",
"transactions": "ငွေပေးငွေယူ", "transactions": "ငွေပေးငွေယူ",
"transactions_by_date": "ရက်စွဲအလိုက် ငွေလွှဲမှုများ", "transactions_by_date": "ရက်စွဲအလိုက် ငွေလွှဲမှုများ",
"trongrid_history": "Trongrid သမိုင်း",
"trusted": "ယုံတယ်။", "trusted": "ယုံတယ်။",
"tx_commit_exception_no_dust_on_change": "အဆိုပါငွေပေးငွေယူကဒီပမာဏနှင့်အတူပယ်ချခံရသည်။ ဤဒင်္ဂါးပြားများနှင့်အတူပြောင်းလဲမှုကိုပြန်လည်ပြောင်းလဲခြင်းသို့မဟုတ် ${min} မပါဘဲ ${max} ပေးပို့နိုင်သည်။", "tx_commit_exception_no_dust_on_change": "အဆိုပါငွေပေးငွေယူကဒီပမာဏနှင့်အတူပယ်ချခံရသည်။ ဤဒင်္ဂါးပြားများနှင့်အတူပြောင်းလဲမှုကိုပြန်လည်ပြောင်းလဲခြင်းသို့မဟုတ် ${min} မပါဘဲ ${max} ပေးပို့နိုင်သည်။",
"tx_commit_failed": "ငွေပေးငွေယူကျူးလွန်မှုပျက်ကွက်။ ကျေးဇူးပြုပြီးပံ့ပိုးမှုဆက်သွယ်ပါ။", "tx_commit_failed": "ငွေပေးငွေယူကျူးလွန်မှုပျက်ကွက်။ ကျေးဇူးပြုပြီးပံ့ပိုးမှုဆက်သွယ်ပါ။",

View file

@ -371,10 +371,10 @@
"moonpay_alert_text": "Waarde van het bedrag moet meer of gelijk zijn aan ${minAmount} ${fiatCurrency}", "moonpay_alert_text": "Waarde van het bedrag moet meer of gelijk zijn aan ${minAmount} ${fiatCurrency}",
"more_options": "Meer opties", "more_options": "Meer opties",
"name": "Naam", "name": "Naam",
"nano_gpt_thanks_message": "Bedankt voor het gebruik van Nanogpt! Vergeet niet om terug te gaan naar de browser nadat uw transactie is voltooid!",
"nanogpt_subtitle": "Alle nieuwste modellen (GPT-4, Claude). \\ Nno-abonnement, betalen met crypto.",
"nano_current_rep": "Huidige vertegenwoordiger", "nano_current_rep": "Huidige vertegenwoordiger",
"nano_gpt_thanks_message": "Bedankt voor het gebruik van Nanogpt! Vergeet niet om terug te gaan naar de browser nadat uw transactie is voltooid!",
"nano_pick_new_rep": "Kies een nieuwe vertegenwoordiger", "nano_pick_new_rep": "Kies een nieuwe vertegenwoordiger",
"nanogpt_subtitle": "Alle nieuwste modellen (GPT-4, Claude). \\ Nno-abonnement, betalen met crypto.",
"narrow": "Smal", "narrow": "Smal",
"new_first_wallet_text": "Houd uw cryptocurrency gemakkelijk veilig", "new_first_wallet_text": "Houd uw cryptocurrency gemakkelijk veilig",
"new_node_testing": "Nieuwe knooppunttest", "new_node_testing": "Nieuwe knooppunttest",
@ -761,6 +761,7 @@
"transaction_sent_notice": "Als het scherm na 1 minuut niet verder gaat, controleer dan een blokverkenner en je e-mail.", "transaction_sent_notice": "Als het scherm na 1 minuut niet verder gaat, controleer dan een blokverkenner en je e-mail.",
"transactions": "Transacties", "transactions": "Transacties",
"transactions_by_date": "Transacties op datum", "transactions_by_date": "Transacties op datum",
"trongrid_history": "Trongrid geschiedenis",
"trusted": "vertrouwd", "trusted": "vertrouwd",
"tx_commit_exception_no_dust_on_change": "De transactie wordt afgewezen met dit bedrag. Met deze munten kunt u ${min} verzenden zonder verandering of ${max} die wijziging retourneert.", "tx_commit_exception_no_dust_on_change": "De transactie wordt afgewezen met dit bedrag. Met deze munten kunt u ${min} verzenden zonder verandering of ${max} die wijziging retourneert.",
"tx_commit_failed": "Transactiebewissing is mislukt. Neem contact op met de ondersteuning.", "tx_commit_failed": "Transactiebewissing is mislukt. Neem contact op met de ondersteuning.",

View file

@ -371,10 +371,10 @@
"moonpay_alert_text": "Wartość kwoty musi być większa lub równa ${minAmount} ${fiatCurrency}", "moonpay_alert_text": "Wartość kwoty musi być większa lub równa ${minAmount} ${fiatCurrency}",
"more_options": "Więcej opcji", "more_options": "Więcej opcji",
"name": "Nazwa", "name": "Nazwa",
"nano_gpt_thanks_message": "Dzięki za użycie Nanogpt! Pamiętaj, aby wrócić do przeglądarki po zakończeniu transakcji!",
"nanogpt_subtitle": "Wszystkie najnowsze modele (GPT-4, Claude). \\ Nno subskrypcja, płacą za pomocą kryptografii.",
"nano_current_rep": "Obecny przedstawiciel", "nano_current_rep": "Obecny przedstawiciel",
"nano_gpt_thanks_message": "Dzięki za użycie Nanogpt! Pamiętaj, aby wrócić do przeglądarki po zakończeniu transakcji!",
"nano_pick_new_rep": "Wybierz nowego przedstawiciela", "nano_pick_new_rep": "Wybierz nowego przedstawiciela",
"nanogpt_subtitle": "Wszystkie najnowsze modele (GPT-4, Claude). \\ Nno subskrypcja, płacą za pomocą kryptografii.",
"narrow": "Wąski", "narrow": "Wąski",
"new_first_wallet_text": "Łatwo zapewnić bezpieczeństwo kryptowalut", "new_first_wallet_text": "Łatwo zapewnić bezpieczeństwo kryptowalut",
"new_node_testing": "Testowanie nowych węzłów", "new_node_testing": "Testowanie nowych węzłów",
@ -761,6 +761,7 @@
"transaction_sent_notice": "Jeśli ekran nie zmieni się po 1 minucie, sprawdź eksplorator bloków i swój e-mail.", "transaction_sent_notice": "Jeśli ekran nie zmieni się po 1 minucie, sprawdź eksplorator bloków i swój e-mail.",
"transactions": "Transakcje", "transactions": "Transakcje",
"transactions_by_date": "Transakcje według daty", "transactions_by_date": "Transakcje według daty",
"trongrid_history": "Historia Trongrida",
"trusted": "Zaufany", "trusted": "Zaufany",
"tx_commit_exception_no_dust_on_change": "Transakcja jest odrzucana z tą kwotą. Za pomocą tych monet możesz wysłać ${min} bez zmiany lub ${max}, które zwraca zmianę.", "tx_commit_exception_no_dust_on_change": "Transakcja jest odrzucana z tą kwotą. Za pomocą tych monet możesz wysłać ${min} bez zmiany lub ${max}, które zwraca zmianę.",
"tx_commit_failed": "Zatwierdzenie transakcji nie powiodło się. Skontaktuj się z obsługą.", "tx_commit_failed": "Zatwierdzenie transakcji nie powiodło się. Skontaktuj się z obsługą.",

View file

@ -372,10 +372,10 @@
"moonpay_alert_text": "O valor do montante deve ser maior ou igual a ${minAmount} ${fiatCurrency}", "moonpay_alert_text": "O valor do montante deve ser maior ou igual a ${minAmount} ${fiatCurrency}",
"more_options": "Mais opções", "more_options": "Mais opções",
"name": "Nome", "name": "Nome",
"nano_gpt_thanks_message": "Obrigado por usar o Nanogpt! Lembre -se de voltar para o navegador após a conclusão da transação!",
"nanogpt_subtitle": "Todos os modelos mais recentes (GPT-4, Claude). \\ Nno assinatura, pagam com criptografia.",
"nano_current_rep": "Representante atual", "nano_current_rep": "Representante atual",
"nano_gpt_thanks_message": "Obrigado por usar o Nanogpt! Lembre -se de voltar para o navegador após a conclusão da transação!",
"nano_pick_new_rep": "Escolha um novo representante", "nano_pick_new_rep": "Escolha um novo representante",
"nanogpt_subtitle": "Todos os modelos mais recentes (GPT-4, Claude). \\ Nno assinatura, pagam com criptografia.",
"narrow": "Estreito", "narrow": "Estreito",
"new_first_wallet_text": "Mantenha sua criptomoeda facilmente segura", "new_first_wallet_text": "Mantenha sua criptomoeda facilmente segura",
"new_node_testing": "Teste de novo nó", "new_node_testing": "Teste de novo nó",
@ -763,6 +763,7 @@
"transaction_sent_notice": "Se a tela não prosseguir após 1 minuto, verifique um explorador de blocos e seu e-mail.", "transaction_sent_notice": "Se a tela não prosseguir após 1 minuto, verifique um explorador de blocos e seu e-mail.",
"transactions": "Transações", "transactions": "Transações",
"transactions_by_date": "Transações por data", "transactions_by_date": "Transações por data",
"trongrid_history": "História de Trongrid",
"trusted": "confiável", "trusted": "confiável",
"tx_commit_exception_no_dust_on_change": "A transação é rejeitada com esse valor. Com essas moedas, você pode enviar ${min} sem alteração ou ${max} que retorna alterações.", "tx_commit_exception_no_dust_on_change": "A transação é rejeitada com esse valor. Com essas moedas, você pode enviar ${min} sem alteração ou ${max} que retorna alterações.",
"tx_commit_failed": "A confirmação da transação falhou. Entre em contato com o suporte.", "tx_commit_failed": "A confirmação da transação falhou. Entre em contato com o suporte.",

View file

@ -371,10 +371,10 @@
"moonpay_alert_text": "Сумма должна быть больше или равна ${minAmount} ${fiatCurrency}", "moonpay_alert_text": "Сумма должна быть больше или равна ${minAmount} ${fiatCurrency}",
"more_options": "Дополнительные параметры", "more_options": "Дополнительные параметры",
"name": "Имя", "name": "Имя",
"nano_gpt_thanks_message": "Спасибо за использование Nanogpt! Не забудьте вернуться в браузер после завершения транзакции!",
"nanogpt_subtitle": "Все новейшие модели (GPT-4, Claude). \\ Nno Подписка, платите с крипто.",
"nano_current_rep": "Нынешний представитель", "nano_current_rep": "Нынешний представитель",
"nano_gpt_thanks_message": "Спасибо за использование Nanogpt! Не забудьте вернуться в браузер после завершения транзакции!",
"nano_pick_new_rep": "Выберите нового представителя", "nano_pick_new_rep": "Выберите нового представителя",
"nanogpt_subtitle": "Все новейшие модели (GPT-4, Claude). \\ Nno Подписка, платите с крипто.",
"narrow": "Узкий", "narrow": "Узкий",
"new_first_wallet_text": "Легко сохранить свою криптовалюту в безопасности", "new_first_wallet_text": "Легко сохранить свою криптовалюту в безопасности",
"new_node_testing": "Тестирование новой ноды", "new_node_testing": "Тестирование новой ноды",
@ -762,6 +762,7 @@
"transaction_sent_notice": "Если экран не отображается через 1 минуту, проверьте обозреватель блоков и свою электронную почту.", "transaction_sent_notice": "Если экран не отображается через 1 минуту, проверьте обозреватель блоков и свою электронную почту.",
"transactions": "Транзакции", "transactions": "Транзакции",
"transactions_by_date": "Сортировать по дате", "transactions_by_date": "Сортировать по дате",
"trongrid_history": "История Тронгрида",
"trusted": "доверенный", "trusted": "доверенный",
"tx_commit_exception_no_dust_on_change": "Транзакция отклоняется с этой суммой. С этими монетами вы можете отправлять ${min} без изменения или ${max}, которые возвращают изменение.", "tx_commit_exception_no_dust_on_change": "Транзакция отклоняется с этой суммой. С этими монетами вы можете отправлять ${min} без изменения или ${max}, которые возвращают изменение.",
"tx_commit_failed": "Комплект транзакции не удался. Пожалуйста, свяжитесь с поддержкой.", "tx_commit_failed": "Комплект транзакции не удался. Пожалуйста, свяжитесь с поддержкой.",

View file

@ -371,10 +371,10 @@
"moonpay_alert_text": "มูลค่าของจำนวนต้องมากกว่าหรือเท่ากับ ${minAmount} ${fiatCurrency}", "moonpay_alert_text": "มูลค่าของจำนวนต้องมากกว่าหรือเท่ากับ ${minAmount} ${fiatCurrency}",
"more_options": "ตัวเลือกเพิ่มเติม", "more_options": "ตัวเลือกเพิ่มเติม",
"name": "ชื่อ", "name": "ชื่อ",
"nano_gpt_thanks_message": "ขอบคุณที่ใช้ Nanogpt! อย่าลืมกลับไปที่เบราว์เซอร์หลังจากการทำธุรกรรมของคุณเสร็จสิ้น!",
"nanogpt_subtitle": "รุ่นใหม่ล่าสุดทั้งหมด (GPT-4, Claude). การสมัครสมาชิก \\ nno, จ่ายด้วย crypto",
"nano_current_rep": "ตัวแทนปัจจุบัน", "nano_current_rep": "ตัวแทนปัจจุบัน",
"nano_gpt_thanks_message": "ขอบคุณที่ใช้ Nanogpt! อย่าลืมกลับไปที่เบราว์เซอร์หลังจากการทำธุรกรรมของคุณเสร็จสิ้น!",
"nano_pick_new_rep": "เลือกตัวแทนใหม่", "nano_pick_new_rep": "เลือกตัวแทนใหม่",
"nanogpt_subtitle": "รุ่นใหม่ล่าสุดทั้งหมด (GPT-4, Claude). การสมัครสมาชิก \\ nno, จ่ายด้วย crypto",
"narrow": "แคบ", "narrow": "แคบ",
"new_first_wallet_text": "ทำให้สกุลเงินดิจิตอลของคุณปลอดภัยได้อย่างง่ายดาย", "new_first_wallet_text": "ทำให้สกุลเงินดิจิตอลของคุณปลอดภัยได้อย่างง่ายดาย",
"new_node_testing": "การทดสอบโหนดใหม่", "new_node_testing": "การทดสอบโหนดใหม่",
@ -761,6 +761,7 @@
"transaction_sent_notice": "ถ้าหน้าจอไม่ขึ้นหลังจาก 1 นาทีแล้ว ให้ตรวจสอบ block explorer และอีเมลของคุณ", "transaction_sent_notice": "ถ้าหน้าจอไม่ขึ้นหลังจาก 1 นาทีแล้ว ให้ตรวจสอบ block explorer และอีเมลของคุณ",
"transactions": "ธุรกรรม", "transactions": "ธุรกรรม",
"transactions_by_date": "ธุรกรรมตามวันที่", "transactions_by_date": "ธุรกรรมตามวันที่",
"trongrid_history": "ประวัติศาสตร์ Trongrid",
"trusted": "มั่นคง", "trusted": "มั่นคง",
"tx_commit_exception_no_dust_on_change": "ธุรกรรมถูกปฏิเสธด้วยจำนวนเงินนี้ ด้วยเหรียญเหล่านี้คุณสามารถส่ง ${min} โดยไม่ต้องเปลี่ยนแปลงหรือ ${max} ที่ส่งคืนการเปลี่ยนแปลง", "tx_commit_exception_no_dust_on_change": "ธุรกรรมถูกปฏิเสธด้วยจำนวนเงินนี้ ด้วยเหรียญเหล่านี้คุณสามารถส่ง ${min} โดยไม่ต้องเปลี่ยนแปลงหรือ ${max} ที่ส่งคืนการเปลี่ยนแปลง",
"tx_commit_failed": "การทำธุรกรรมล้มเหลว กรุณาติดต่อฝ่ายสนับสนุน", "tx_commit_failed": "การทำธุรกรรมล้มเหลว กรุณาติดต่อฝ่ายสนับสนุน",

View file

@ -371,10 +371,10 @@
"moonpay_alert_text": "Ang halaga ng halaga ay dapat na higit pa o katumbas ng ${minAmount} ${fiatCurrency}", "moonpay_alert_text": "Ang halaga ng halaga ay dapat na higit pa o katumbas ng ${minAmount} ${fiatCurrency}",
"more_options": "Higit pang mga pagpipilian", "more_options": "Higit pang mga pagpipilian",
"name": "Pangalan", "name": "Pangalan",
"nano_gpt_thanks_message": "Salamat sa paggamit ng nanogpt! Tandaan na bumalik sa browser matapos makumpleto ang iyong transaksyon!",
"nanogpt_subtitle": "Ang lahat ng mga pinakabagong modelo (GPT-4, Claude). \\ Nno subscription, magbayad gamit ang crypto.",
"nano_current_rep": "Kasalukuyang kinatawan", "nano_current_rep": "Kasalukuyang kinatawan",
"nano_gpt_thanks_message": "Salamat sa paggamit ng nanogpt! Tandaan na bumalik sa browser matapos makumpleto ang iyong transaksyon!",
"nano_pick_new_rep": "Pumili ng isang bagong kinatawan", "nano_pick_new_rep": "Pumili ng isang bagong kinatawan",
"nanogpt_subtitle": "Ang lahat ng mga pinakabagong modelo (GPT-4, Claude). \\ Nno subscription, magbayad gamit ang crypto.",
"narrow": "Makitid", "narrow": "Makitid",
"new_first_wallet_text": "Panatilihing ligtas ang iyong crypto, piraso ng cake", "new_first_wallet_text": "Panatilihing ligtas ang iyong crypto, piraso ng cake",
"new_node_testing": "Bagong pagsubok sa node", "new_node_testing": "Bagong pagsubok sa node",
@ -761,6 +761,7 @@
"transaction_sent_notice": "Kung ang screen ay hindi magpatuloy pagkatapos ng 1 minuto, suriin ang isang block explorer at ang iyong email.", "transaction_sent_notice": "Kung ang screen ay hindi magpatuloy pagkatapos ng 1 minuto, suriin ang isang block explorer at ang iyong email.",
"transactions": "Mga Transaksyon", "transactions": "Mga Transaksyon",
"transactions_by_date": "Mga Transaksyon ayon sa Petsa", "transactions_by_date": "Mga Transaksyon ayon sa Petsa",
"trongrid_history": "Kasaysayan ng Trongrid",
"trusted": "Pinagkakatiwalaan", "trusted": "Pinagkakatiwalaan",
"tx_commit_exception_no_dust_on_change": "Ang transaksyon ay tinanggihan sa halagang ito. Sa mga barya na ito maaari kang magpadala ng ${min} nang walang pagbabago o ${max} na nagbabalik ng pagbabago.", "tx_commit_exception_no_dust_on_change": "Ang transaksyon ay tinanggihan sa halagang ito. Sa mga barya na ito maaari kang magpadala ng ${min} nang walang pagbabago o ${max} na nagbabalik ng pagbabago.",
"tx_commit_failed": "Nabigo ang transaksyon sa transaksyon. Mangyaring makipag -ugnay sa suporta.", "tx_commit_failed": "Nabigo ang transaksyon sa transaksyon. Mangyaring makipag -ugnay sa suporta.",

View file

@ -371,10 +371,10 @@
"moonpay_alert_text": "Tutar ${minAmount} ${fiatCurrency} miktarına eşit veya daha fazla olmalıdır", "moonpay_alert_text": "Tutar ${minAmount} ${fiatCurrency} miktarına eşit veya daha fazla olmalıdır",
"more_options": "Daha Fazla Seçenek", "more_options": "Daha Fazla Seçenek",
"name": "İsim", "name": "İsim",
"nano_gpt_thanks_message": "Nanogpt kullandığınız için teşekkürler! İşleminiz tamamlandıktan sonra tarayıcıya geri dönmeyi unutmayın!",
"nanogpt_subtitle": "En yeni modeller (GPT-4, Claude). \\ Nno aboneliği, kripto ile ödeme yapın.",
"nano_current_rep": "Mevcut temsilci", "nano_current_rep": "Mevcut temsilci",
"nano_gpt_thanks_message": "Nanogpt kullandığınız için teşekkürler! İşleminiz tamamlandıktan sonra tarayıcıya geri dönmeyi unutmayın!",
"nano_pick_new_rep": "Yeni bir temsilci seçin", "nano_pick_new_rep": "Yeni bir temsilci seçin",
"nanogpt_subtitle": "En yeni modeller (GPT-4, Claude). \\ Nno aboneliği, kripto ile ödeme yapın.",
"narrow": "Dar", "narrow": "Dar",
"new_first_wallet_text": "Kripto para biriminizi kolayca güvende tutun", "new_first_wallet_text": "Kripto para biriminizi kolayca güvende tutun",
"new_node_testing": "Yeni düğüm test ediliyor", "new_node_testing": "Yeni düğüm test ediliyor",
@ -761,6 +761,7 @@
"transaction_sent_notice": "Ekran 1 dakika sonra ilerlemezse, blok gezgininden ve e-postanızdan kontrol edin.", "transaction_sent_notice": "Ekran 1 dakika sonra ilerlemezse, blok gezgininden ve e-postanızdan kontrol edin.",
"transactions": "İşlemler", "transactions": "İşlemler",
"transactions_by_date": "Tarihe göre transferler", "transactions_by_date": "Tarihe göre transferler",
"trongrid_history": "Trongrid tarihi",
"trusted": "Güvenilir", "trusted": "Güvenilir",
"tx_commit_exception_no_dust_on_change": "İşlem bu miktarla reddedilir. Bu madeni paralarla değişiklik yapmadan ${min} veya değişikliği döndüren ${max} gönderebilirsiniz.", "tx_commit_exception_no_dust_on_change": "İşlem bu miktarla reddedilir. Bu madeni paralarla değişiklik yapmadan ${min} veya değişikliği döndüren ${max} gönderebilirsiniz.",
"tx_commit_failed": "İşlem taahhüdü başarısız oldu. Lütfen Destek ile iletişime geçin.", "tx_commit_failed": "İşlem taahhüdü başarısız oldu. Lütfen Destek ile iletişime geçin.",

View file

@ -371,10 +371,10 @@
"moonpay_alert_text": "Значення суми має бути більшим або дорівнювати ${minAmount} ${fiatCurrency}", "moonpay_alert_text": "Значення суми має бути більшим або дорівнювати ${minAmount} ${fiatCurrency}",
"more_options": "Більше параметрів", "more_options": "Більше параметрів",
"name": "Ім'я", "name": "Ім'я",
"nano_gpt_thanks_message": "Дякуємо за використання наногпта! Не забудьте повернутися до браузера після завершення транзакції!",
"nanogpt_subtitle": "Усі найновіші моделі (GPT-4, Claude). \\ Nno підписка, оплата криптовалютою.",
"nano_current_rep": "Поточний представник", "nano_current_rep": "Поточний представник",
"nano_gpt_thanks_message": "Дякуємо за використання наногпта! Не забудьте повернутися до браузера після завершення транзакції!",
"nano_pick_new_rep": "Виберіть нового представника", "nano_pick_new_rep": "Виберіть нового представника",
"nanogpt_subtitle": "Усі найновіші моделі (GPT-4, Claude). \\ Nno підписка, оплата криптовалютою.",
"narrow": "вузькі", "narrow": "вузькі",
"new_first_wallet_text": "Легко зберігайте свою криптовалюту в безпеці", "new_first_wallet_text": "Легко зберігайте свою криптовалюту в безпеці",
"new_node_testing": "Тестування нового вузла", "new_node_testing": "Тестування нового вузла",
@ -762,6 +762,7 @@
"transaction_sent_notice": "Якщо екран не відображається через 1 хвилину, перевірте провідник блоків і свою електронну пошту.", "transaction_sent_notice": "Якщо екран не відображається через 1 хвилину, перевірте провідник блоків і свою електронну пошту.",
"transactions": "Транзакції", "transactions": "Транзакції",
"transactions_by_date": "Сортувати по даті", "transactions_by_date": "Сортувати по даті",
"trongrid_history": "Тронгрідська історія",
"trusted": "довіряють", "trusted": "довіряють",
"tx_commit_exception_no_dust_on_change": "Транзакція відхилена цією сумою. За допомогою цих монет ви можете надіслати ${min} без змін або ${max}, що повертає зміни.", "tx_commit_exception_no_dust_on_change": "Транзакція відхилена цією сумою. За допомогою цих монет ви можете надіслати ${min} без змін або ${max}, що повертає зміни.",
"tx_commit_failed": "Транзакційна комісія не вдалося. Будь ласка, зв'яжіться з підтримкою.", "tx_commit_failed": "Транзакційна комісія не вдалося. Будь ласка, зв'яжіться з підтримкою.",

View file

@ -371,10 +371,10 @@
"moonpay_alert_text": "رقم کی قدر ${minAmount} ${fiatCurrency} کے برابر یا زیادہ ہونی چاہیے۔", "moonpay_alert_text": "رقم کی قدر ${minAmount} ${fiatCurrency} کے برابر یا زیادہ ہونی چاہیے۔",
"more_options": "مزید زرائے", "more_options": "مزید زرائے",
"name": "ﻡﺎﻧ", "name": "ﻡﺎﻧ",
"nano_gpt_thanks_message": "نانوگپٹ استعمال کرنے کا شکریہ! اپنے لین دین کی تکمیل کے بعد براؤزر کی طرف واپس جانا یاد رکھیں!",
"nanogpt_subtitle": "تمام تازہ ترین ماڈل (GPT-4 ، کلاڈ)۔ n n no سبسکرپشن ، کریپٹو کے ساتھ ادائیگی کریں۔",
"nano_current_rep": "موجودہ نمائندہ", "nano_current_rep": "موجودہ نمائندہ",
"nano_gpt_thanks_message": "نانوگپٹ استعمال کرنے کا شکریہ! اپنے لین دین کی تکمیل کے بعد براؤزر کی طرف واپس جانا یاد رکھیں!",
"nano_pick_new_rep": "ایک نیا نمائندہ منتخب کریں", "nano_pick_new_rep": "ایک نیا نمائندہ منتخب کریں",
"nanogpt_subtitle": "تمام تازہ ترین ماڈل (GPT-4 ، کلاڈ)۔ n n no سبسکرپشن ، کریپٹو کے ساتھ ادائیگی کریں۔",
"narrow": "تنگ", "narrow": "تنگ",
"new_first_wallet_text": "آسانی سے اپنے cryptocurrency محفوظ رکھیں", "new_first_wallet_text": "آسانی سے اپنے cryptocurrency محفوظ رکھیں",
"new_node_testing": "نیا نوڈ ٹیسٹنگ", "new_node_testing": "نیا نوڈ ٹیسٹنگ",
@ -763,6 +763,7 @@
"transaction_sent_notice": "اگر اسکرین 1 منٹ کے بعد آگے نہیں بڑھتی ہے، تو بلاک ایکسپلورر اور اپنا ای میل چیک کریں۔", "transaction_sent_notice": "اگر اسکرین 1 منٹ کے بعد آگے نہیں بڑھتی ہے، تو بلاک ایکسپلورر اور اپنا ای میل چیک کریں۔",
"transactions": "لین دین", "transactions": "لین دین",
"transactions_by_date": "تاریخ کے لحاظ سے لین دین", "transactions_by_date": "تاریخ کے لحاظ سے لین دین",
"trongrid_history": "ٹرانگریڈ ہسٹری",
"trusted": "قابل اعتماد", "trusted": "قابل اعتماد",
"tx_commit_exception_no_dust_on_change": "اس رقم سے لین دین کو مسترد کردیا گیا ہے۔ ان سککوں کے ذریعہ آپ بغیر کسی تبدیلی کے ${min} یا ${max} بھیج سکتے ہیں جو لوٹتے ہیں۔", "tx_commit_exception_no_dust_on_change": "اس رقم سے لین دین کو مسترد کردیا گیا ہے۔ ان سککوں کے ذریعہ آپ بغیر کسی تبدیلی کے ${min} یا ${max} بھیج سکتے ہیں جو لوٹتے ہیں۔",
"tx_commit_failed": "ٹرانزیکشن کمٹ ناکام ہوگیا۔ براہ کرم سپورٹ سے رابطہ کریں۔", "tx_commit_failed": "ٹرانزیکشن کمٹ ناکام ہوگیا۔ براہ کرم سپورٹ سے رابطہ کریں۔",

View file

@ -372,10 +372,10 @@
"moonpay_alert_text": "Iye owó kò gbọ́dọ̀ kéré ju ${minAmount} ${fiatCurrency}", "moonpay_alert_text": "Iye owó kò gbọ́dọ̀ kéré ju ${minAmount} ${fiatCurrency}",
"more_options": "Ìyàn àfikún", "more_options": "Ìyàn àfikún",
"name": "Oruko", "name": "Oruko",
"nano_gpt_thanks_message": "O ṣeun fun lilo Nonnogt! Ranti lati tẹle pada si ẹrọ lilọ kiri ayelujara lẹhin iṣowo rẹ pari!",
"nanogpt_subtitle": "Gbogbo awọn awoṣe tuntun (GPT-4, Claude). \\ Nno alabapin kan, sanwo pẹlu Crypto.",
"nano_current_rep": "Aṣoju lọwọlọwọ", "nano_current_rep": "Aṣoju lọwọlọwọ",
"nano_gpt_thanks_message": "O ṣeun fun lilo Nonnogt! Ranti lati tẹle pada si ẹrọ lilọ kiri ayelujara lẹhin iṣowo rẹ pari!",
"nano_pick_new_rep": "Mu aṣoju tuntun kan", "nano_pick_new_rep": "Mu aṣoju tuntun kan",
"nanogpt_subtitle": "Gbogbo awọn awoṣe tuntun (GPT-4, Claude). \\ Nno alabapin kan, sanwo pẹlu Crypto.",
"narrow": "Taara", "narrow": "Taara",
"new_first_wallet_text": "Ni rọọrun jẹ ki o jẹ ki o jẹ ki o jẹ ki a mu", "new_first_wallet_text": "Ni rọọrun jẹ ki o jẹ ki o jẹ ki o jẹ ki a mu",
"new_node_testing": "A ń dán apẹka títun wò", "new_node_testing": "A ń dán apẹka títun wò",
@ -762,6 +762,7 @@
"transaction_sent_notice": "Tí aṣàfihàn kò bá tẹ̀síwájú l'áàárín ìṣẹ́jú kan, ẹ tọ́ olùṣèwádìí àkójọpọ̀ àti ímeèlì yín wò.", "transaction_sent_notice": "Tí aṣàfihàn kò bá tẹ̀síwájú l'áàárín ìṣẹ́jú kan, ẹ tọ́ olùṣèwádìí àkójọpọ̀ àti ímeèlì yín wò.",
"transactions": "Àwọn àránṣẹ́", "transactions": "Àwọn àránṣẹ́",
"transactions_by_date": "Àwọn àránṣẹ́ t'á ti fi aago ṣa", "transactions_by_date": "Àwọn àránṣẹ́ t'á ti fi aago ṣa",
"trongrid_history": "Itan Trongrid",
"trusted": "A ti fọkàn ẹ̀ tán", "trusted": "A ti fọkàn ẹ̀ tán",
"tx_commit_exception_no_dust_on_change": "Iṣowo naa ti kọ pẹlu iye yii. Pẹlu awọn owó wọnyi o le firanṣẹ ${min} laisi ayipada tabi ${max} ni iyipada iyipada.", "tx_commit_exception_no_dust_on_change": "Iṣowo naa ti kọ pẹlu iye yii. Pẹlu awọn owó wọnyi o le firanṣẹ ${min} laisi ayipada tabi ${max} ni iyipada iyipada.",
"tx_commit_failed": "Idunadura iṣowo kuna. Jọwọ kan si atilẹyin.", "tx_commit_failed": "Idunadura iṣowo kuna. Jọwọ kan si atilẹyin.",

View file

@ -371,10 +371,10 @@
"moonpay_alert_text": "金额的价值必须大于或等于 ${minAmount} ${fiatCurrency}", "moonpay_alert_text": "金额的价值必须大于或等于 ${minAmount} ${fiatCurrency}",
"more_options": "更多选项", "more_options": "更多选项",
"name": "姓名", "name": "姓名",
"nano_gpt_thanks_message": "感谢您使用Nanogpt事务完成后请记住回到浏览器",
"nanogpt_subtitle": "所有最新型号GPT-4Claude。\\ nno订阅用加密货币付款。",
"nano_current_rep": "当前代表", "nano_current_rep": "当前代表",
"nano_gpt_thanks_message": "感谢您使用Nanogpt事务完成后请记住回到浏览器",
"nano_pick_new_rep": "选择新代表", "nano_pick_new_rep": "选择新代表",
"nanogpt_subtitle": "所有最新型号GPT-4Claude。\\ nno订阅用加密货币付款。",
"narrow": "狭窄的", "narrow": "狭窄的",
"new_first_wallet_text": "轻松确保您的加密货币安全", "new_first_wallet_text": "轻松确保您的加密货币安全",
"new_node_testing": "新节点测试", "new_node_testing": "新节点测试",
@ -761,6 +761,7 @@
"transaction_sent_notice": "如果屏幕在 1 分钟后没有继续,请检查区块浏览器和您的电子邮件。", "transaction_sent_notice": "如果屏幕在 1 分钟后没有继续,请检查区块浏览器和您的电子邮件。",
"transactions": "交易情况", "transactions": "交易情况",
"transactions_by_date": "按日期交易", "transactions_by_date": "按日期交易",
"trongrid_history": "Trongrid历史",
"trusted": "值得信赖", "trusted": "值得信赖",
"tx_commit_exception_no_dust_on_change": "交易被此金额拒绝。使用这些硬币,您可以发送${min}无需更改或返回${max}的变化。", "tx_commit_exception_no_dust_on_change": "交易被此金额拒绝。使用这些硬币,您可以发送${min}无需更改或返回${max}的变化。",
"tx_commit_failed": "交易承诺失败。请联系支持。", "tx_commit_failed": "交易承诺失败。请联系支持。",

View file

@ -15,15 +15,15 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN)
APP_ANDROID_TYPE=$1 APP_ANDROID_TYPE=$1
MONERO_COM_NAME="Monero.com" MONERO_COM_NAME="Monero.com"
MONERO_COM_VERSION="1.12.3" MONERO_COM_VERSION="1.13.0"
MONERO_COM_BUILD_NUMBER=84 MONERO_COM_BUILD_NUMBER=85
MONERO_COM_BUNDLE_ID="com.monero.app" MONERO_COM_BUNDLE_ID="com.monero.app"
MONERO_COM_PACKAGE="com.monero.app" MONERO_COM_PACKAGE="com.monero.app"
MONERO_COM_SCHEME="monero.com" MONERO_COM_SCHEME="monero.com"
CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="4.15.6" CAKEWALLET_VERSION="4.16.0"
CAKEWALLET_BUILD_NUMBER=207 CAKEWALLET_BUILD_NUMBER=208
CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet" CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet"
CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet" CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet"
CAKEWALLET_SCHEME="cakewallet" CAKEWALLET_SCHEME="cakewallet"

View file

@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN)
APP_IOS_TYPE=$1 APP_IOS_TYPE=$1
MONERO_COM_NAME="Monero.com" MONERO_COM_NAME="Monero.com"
MONERO_COM_VERSION="1.12.3" MONERO_COM_VERSION="1.13.0"
MONERO_COM_BUILD_NUMBER=82 MONERO_COM_BUILD_NUMBER=83
MONERO_COM_BUNDLE_ID="com.cakewallet.monero" MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="4.15.6" CAKEWALLET_VERSION="4.16.0"
CAKEWALLET_BUILD_NUMBER=232 CAKEWALLET_BUILD_NUMBER=234
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
HAVEN_NAME="Haven" HAVEN_NAME="Haven"

View file

@ -16,13 +16,13 @@ if [ -n "$1" ]; then
fi fi
MONERO_COM_NAME="Monero.com" MONERO_COM_NAME="Monero.com"
MONERO_COM_VERSION="1.2.3" MONERO_COM_VERSION="1.3.0"
MONERO_COM_BUILD_NUMBER=16 MONERO_COM_BUILD_NUMBER=17
MONERO_COM_BUNDLE_ID="com.cakewallet.monero" MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
CAKEWALLET_NAME="Cake Wallet" CAKEWALLET_NAME="Cake Wallet"
CAKEWALLET_VERSION="1.8.6" CAKEWALLET_VERSION="1.9.0"
CAKEWALLET_BUILD_NUMBER=67 CAKEWALLET_BUILD_NUMBER=69
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet" CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then

View file

@ -10,6 +10,7 @@ const polygonOutputPath = 'lib/polygon/polygon.dart';
const solanaOutputPath = 'lib/solana/solana.dart'; const solanaOutputPath = 'lib/solana/solana.dart';
const tronOutputPath = 'lib/tron/tron.dart'; const tronOutputPath = 'lib/tron/tron.dart';
const walletTypesPath = 'lib/wallet_types.g.dart'; const walletTypesPath = 'lib/wallet_types.g.dart';
const secureStoragePath = 'lib/core/secure_storage.dart';
const pubspecDefaultPath = 'pubspec_default.yaml'; const pubspecDefaultPath = 'pubspec_default.yaml';
const pubspecOutputPath = 'pubspec.yaml'; const pubspecOutputPath = 'pubspec.yaml';
@ -25,6 +26,7 @@ Future<void> main(List<String> args) async {
final hasPolygon = args.contains('${prefix}polygon'); final hasPolygon = args.contains('${prefix}polygon');
final hasSolana = args.contains('${prefix}solana'); final hasSolana = args.contains('${prefix}solana');
final hasTron = args.contains('${prefix}tron'); final hasTron = args.contains('${prefix}tron');
final excludeFlutterSecureStorage = args.contains('${prefix}excludeFlutterSecureStorage');
await generateBitcoin(hasBitcoin); await generateBitcoin(hasBitcoin);
await generateMonero(hasMonero); await generateMonero(hasMonero);
@ -45,6 +47,7 @@ Future<void> main(List<String> args) async {
hasNano: hasNano, hasNano: hasNano,
hasBanano: hasBanano, hasBanano: hasBanano,
hasBitcoinCash: hasBitcoinCash, hasBitcoinCash: hasBitcoinCash,
hasFlutterSecureStorage: !excludeFlutterSecureStorage,
hasPolygon: hasPolygon, hasPolygon: hasPolygon,
hasSolana: hasSolana, hasSolana: hasSolana,
hasTron: hasTron, hasTron: hasTron,
@ -61,6 +64,7 @@ Future<void> main(List<String> args) async {
hasSolana: hasSolana, hasSolana: hasSolana,
hasTron: hasTron, hasTron: hasTron,
); );
await injectSecureStorage(!excludeFlutterSecureStorage);
} }
Future<void> generateBitcoin(bool hasImplementation) async { Future<void> generateBitcoin(bool hasImplementation) async {
@ -1130,6 +1134,8 @@ abstract class Tron {
String? getTronNativeEstimatedFee(WalletBase wallet); String? getTronNativeEstimatedFee(WalletBase wallet);
String? getTronTRC20EstimatedFee(WalletBase wallet); String? getTronTRC20EstimatedFee(WalletBase wallet);
void updateTronGridUsageState(WalletBase wallet, bool isEnabled);
} }
"""; """;
@ -1158,6 +1164,7 @@ Future<void> generatePubspec(
required bool hasNano, required bool hasNano,
required bool hasBanano, required bool hasBanano,
required bool hasBitcoinCash, required bool hasBitcoinCash,
required bool hasFlutterSecureStorage,
required bool hasPolygon, required bool hasPolygon,
required bool hasSolana, required bool hasSolana,
required bool hasTron}) async { required bool hasTron}) async {
@ -1181,6 +1188,14 @@ Future<void> generatePubspec(
cw_shared_external: cw_shared_external:
path: ./cw_shared_external path: ./cw_shared_external
"""; """;
const flutterSecureStorage = """
flutter_secure_storage:
git:
url: https://github.com/cake-tech/flutter_secure_storage.git
path: flutter_secure_storage
ref: cake-9.0.0
version: 9.0.0
""";
const cwEthereum = """ const cwEthereum = """
cw_ethereum: cw_ethereum:
path: ./cw_ethereum path: ./cw_ethereum
@ -1262,6 +1277,10 @@ Future<void> generatePubspec(
output += '\n$cwHaven'; output += '\n$cwHaven';
} }
if (hasFlutterSecureStorage) {
output += '\n$flutterSecureStorage\n';
}
if (hasEthereum || hasPolygon) { if (hasEthereum || hasPolygon) {
output += '\n$cwEVM'; output += '\n$cwEVM';
} }
@ -1346,3 +1365,103 @@ Future<void> generateWalletTypes(
outputContent += '];\n'; outputContent += '];\n';
await walletTypesFile.writeAsString(outputContent); await walletTypesFile.writeAsString(outputContent);
} }
Future<void> injectSecureStorage(bool hasFlutterSecureStorage) async {
const flutterSecureStorageHeader = """
import 'dart:async';
import 'dart:io';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
""";
const abstractSecureStorage = """
abstract class SecureStorage {
Future<String?> read({required String key});
Future<void> write({required String key, required String? value});
Future<void> delete({required String key});
// Legacy
Future<String?> readNoIOptions({required String key});
}""";
const defaultSecureStorage = """
class DefaultSecureStorage extends SecureStorage {
DefaultSecureStorage._(this._secureStorage);
factory DefaultSecureStorage() => _instance;
static final _instance = DefaultSecureStorage._(FlutterSecureStorage(
iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock),
));
final FlutterSecureStorage _secureStorage;
@override
Future<String?> read({required String key}) async => await _readInternal(key, false);
@override
Future<void> write({required String key, required String? value}) async {
// delete the value before writing on macOS because of a weird bug
// https://github.com/mogol/flutter_secure_storage/issues/581
if (Platform.isMacOS) {
await _secureStorage.delete(key: key);
}
await _secureStorage.write(key: key, value: value);
}
@override
Future<void> delete({required String key}) async => _secureStorage.delete(key: key);
@override
Future<String?> readNoIOptions({required String key}) async => await _readInternal(key, true);
Future<String?> _readInternal(String key, bool useNoIOptions) async {
String? result;
const maxWait = Duration(seconds: 3);
const checkInterval = Duration(milliseconds: 200);
DateTime start = DateTime.now();
while (result == null && DateTime.now().difference(start) < maxWait) {
result = await _secureStorage.read(
key: key,
iOptions: useNoIOptions ? IOSOptions() : null,
);
if (result != null) {
break;
}
await Future.delayed(checkInterval);
}
return result;
}
}""";
const fakeSecureStorage = """
class FakeSecureStorage extends SecureStorage {
@override
Future<String?> read({required String key}) async => null;
@override
Future<void> write({required String key, required String? value}) async {}
@override
Future<void> delete({required String key}) async {}
@override
Future<String?> readNoIOptions({required String key}) async => null;
}""";
final outputFile = File(secureStoragePath);
final header = hasFlutterSecureStorage
? '${flutterSecureStorageHeader}\n\nfinal SecureStorage secureStorageShared = DefaultSecureStorage();\n'
: 'final SecureStorage secureStorageShared = FakeSecureStorage();\n';
var output = '';
if (outputFile.existsSync()) {
await outputFile.delete();
}
output += '${header}\n${abstractSecureStorage}\n\n';
if (hasFlutterSecureStorage) {
output += '${defaultSecureStorage}\n';
} else {
output += '${fakeSecureStorage}\n';
}
await outputFile.writeAsString(output);
}