mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-21 06:18:42 +02:00
Merge branch 'main' into CW-529-Modify-2FA-introduction-screens
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||
import 'package:cake_wallet/utils/device_info.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class DFXBuyProvider {
|
||||
DFXBuyProvider({required WalletBase wallet}) : this._wallet = wallet;
|
||||
|
||||
final WalletBase _wallet;
|
||||
|
||||
static const _baseUrl = 'api.dfx.swiss';
|
||||
static const _authPath = '/v1/auth/signMessage';
|
||||
static const _signUpPath = '/v1/auth/signUp';
|
||||
static const _signInPath = '/v1/auth/signIn';
|
||||
static const walletName = 'CakeWallet';
|
||||
|
||||
String get assetOut {
|
||||
switch (_wallet.type) {
|
||||
case WalletType.bitcoin:
|
||||
return 'BTC';
|
||||
case WalletType.bitcoinCash:
|
||||
return 'BCH';
|
||||
case WalletType.litecoin:
|
||||
return 'LTC';
|
||||
case WalletType.monero:
|
||||
return 'XMR';
|
||||
case WalletType.ethereum:
|
||||
return 'ETH';
|
||||
default:
|
||||
throw Exception("WalletType is not available for DFX ${_wallet.type}");
|
||||
}
|
||||
}
|
||||
|
||||
String get blockchain {
|
||||
switch (_wallet.type) {
|
||||
case WalletType.bitcoin:
|
||||
case WalletType.bitcoinCash:
|
||||
case WalletType.litecoin:
|
||||
return 'Bitcoin';
|
||||
case WalletType.monero:
|
||||
return 'Monero';
|
||||
case WalletType.ethereum:
|
||||
return 'Ethereum';
|
||||
default:
|
||||
throw Exception("WalletType is not available for DFX ${_wallet.type}");
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> getSignMessage() async {
|
||||
final walletAddress = _wallet.walletAddresses.address;
|
||||
final uri = Uri.https(_baseUrl, _authPath, {'address': walletAddress});
|
||||
|
||||
var response = await http.get(uri, headers: {'accept': 'application/json'});
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final responseBody = jsonDecode(response.body);
|
||||
return responseBody['message'] as String;
|
||||
} else {
|
||||
throw Exception(
|
||||
'Failed to get sign message. Status: ${response.statusCode} ${response.body}');
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> signUp() async {
|
||||
final signMessage = getSignature(await getSignMessage());
|
||||
final walletAddress = _wallet.walletAddresses.address;
|
||||
|
||||
final requestBody = jsonEncode({
|
||||
'wallet': walletName,
|
||||
'address': walletAddress,
|
||||
'signature': signMessage,
|
||||
});
|
||||
|
||||
final uri = Uri.https(_baseUrl, _signUpPath);
|
||||
var response = await http.post(uri,
|
||||
headers: {'Content-Type': 'application/json'}, body: requestBody);
|
||||
|
||||
if (response.statusCode == 201) {
|
||||
final responseBody = jsonDecode(response.body);
|
||||
return responseBody['accessToken'] as String;
|
||||
} else {
|
||||
throw Exception(
|
||||
'Failed to sign up. Status: ${response.statusCode} ${response.body}');
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> signIn() async {
|
||||
final signMessage = getSignature(await getSignMessage());
|
||||
final walletAddress = _wallet.walletAddresses.address;
|
||||
|
||||
final requestBody = jsonEncode({
|
||||
'address': walletAddress,
|
||||
'signature': signMessage,
|
||||
});
|
||||
|
||||
final uri = Uri.https(_baseUrl, _signInPath);
|
||||
var response = await http.post(uri,
|
||||
headers: {'Content-Type': 'application/json'}, body: requestBody);
|
||||
|
||||
if (response.statusCode == 201) {
|
||||
final responseBody = jsonDecode(response.body);
|
||||
return responseBody['accessToken'] as String;
|
||||
} else {
|
||||
throw Exception(
|
||||
'Failed to sign in. Status: ${response.statusCode} ${response.body}');
|
||||
}
|
||||
}
|
||||
|
||||
String getSignature(String message) {
|
||||
switch (_wallet.type) {
|
||||
case WalletType.ethereum:
|
||||
return _wallet.signMessage(message);
|
||||
case WalletType.monero:
|
||||
case WalletType.litecoin:
|
||||
case WalletType.bitcoin:
|
||||
case WalletType.bitcoinCash:
|
||||
return _wallet.signMessage(message,
|
||||
address: _wallet.walletAddresses.address);
|
||||
default:
|
||||
throw Exception("WalletType is not available for DFX ${_wallet.type}");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> launchProvider(BuildContext context) async {
|
||||
try {
|
||||
final assetOut = this.assetOut;
|
||||
final blockchain = this.blockchain;
|
||||
|
||||
String accessToken;
|
||||
|
||||
try {
|
||||
accessToken = await signUp();
|
||||
} on Exception catch (e) {
|
||||
if (e.toString().contains('409')) {
|
||||
accessToken = await signIn();
|
||||
} else {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
final uri = Uri.https('services.dfx.swiss', '/buy', {
|
||||
'session': accessToken,
|
||||
'lang': 'en',
|
||||
'asset-out': assetOut,
|
||||
'blockchain': blockchain,
|
||||
'asset-in': 'EUR',
|
||||
});
|
||||
|
||||
if (await canLaunchUrl(uri)) {
|
||||
if (DeviceInfo.instance.isMobile) {
|
||||
Navigator.of(context).pushNamed(Routes.webViewPage,
|
||||
arguments: [S.of(context).buy, uri]);
|
||||
} else {
|
||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||
}
|
||||
} else {
|
||||
throw Exception('Could not launch URL');
|
||||
}
|
||||
} catch (e) {
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithOneAction(
|
||||
alertTitle: "DFX Connect",
|
||||
alertContent: S.of(context).buy_provider_unavailable + ': $e',
|
||||
buttonText: S.of(context).ok,
|
||||
buttonAction: () => Navigator.of(context).pop());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -271,6 +271,8 @@ class AddressValidator extends TextValidator {
|
||||
'|([^0-9a-zA-Z]|^)ltc[a-zA-Z0-9]{26,45}([^0-9a-zA-Z]|\$)';
|
||||
case CryptoCurrency.eth:
|
||||
return '0x[0-9a-zA-Z]{42}';
|
||||
case CryptoCurrency.maticpoly:
|
||||
return '0x[0-9a-zA-Z]{42}';
|
||||
case CryptoCurrency.nano:
|
||||
return 'nano_[0-9a-zA-Z]{60}';
|
||||
case CryptoCurrency.banano:
|
||||
|
||||
@@ -436,6 +436,7 @@ class BackupService {
|
||||
final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
|
||||
final backupPassword = keychainJSON[backupPasswordKey] as String;
|
||||
|
||||
await _flutterSecureStorage.delete(key: backupPasswordKey);
|
||||
await _flutterSecureStorage.write(key: backupPasswordKey, value: backupPassword);
|
||||
|
||||
keychainWalletsInfo.forEach((dynamic rawInfo) async {
|
||||
@@ -443,6 +444,7 @@ class BackupService {
|
||||
await importWalletKeychainInfo(info);
|
||||
});
|
||||
|
||||
await _flutterSecureStorage.delete(key: pinCodeKey);
|
||||
await _flutterSecureStorage.write(key: pinCodeKey, value: encodedPinCode(pin: decodedPin));
|
||||
|
||||
keychainDumpFile.deleteSync();
|
||||
@@ -462,6 +464,7 @@ class BackupService {
|
||||
final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
|
||||
final backupPassword = keychainJSON[backupPasswordKey] as String;
|
||||
|
||||
await _flutterSecureStorage.delete(key: backupPasswordKey);
|
||||
await _flutterSecureStorage.write(key: backupPasswordKey, value: backupPassword);
|
||||
|
||||
keychainWalletsInfo.forEach((dynamic rawInfo) async {
|
||||
@@ -469,6 +472,7 @@ class BackupService {
|
||||
await importWalletKeychainInfo(info);
|
||||
});
|
||||
|
||||
await _flutterSecureStorage.delete(key: pinCodeKey);
|
||||
await _flutterSecureStorage.write(key: pinCodeKey, value: encodedPinCode(pin: decodedPin));
|
||||
|
||||
keychainDumpFile.deleteSync();
|
||||
|
||||
@@ -16,7 +16,7 @@ Future<double> _fetchPrice(Map<String, dynamic> args) async {
|
||||
|
||||
final Map<String, String> queryParams = {
|
||||
'interval_count': '1',
|
||||
'base': crypto,
|
||||
'base': crypto.split(".").first,
|
||||
'quote': fiat,
|
||||
'key': secrets.fiatApiKey,
|
||||
};
|
||||
|
||||
@@ -19,6 +19,7 @@ class KeyService {
|
||||
key: SecretStoreKey.moneroWalletPassword, walletName: walletName);
|
||||
final encodedPassword = encodeWalletPassword(password: password);
|
||||
|
||||
await _secureStorage.delete(key: key);
|
||||
await _secureStorage.write(key: key, value: encodedPassword);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:cake_wallet/haven/haven.dart';
|
||||
import 'package:cake_wallet/core/validator.dart';
|
||||
import 'package:cake_wallet/entities/mnemonic_item.dart';
|
||||
import 'package:cake_wallet/polygon/polygon.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cake_wallet/monero/monero.dart';
|
||||
import 'package:cake_wallet/nano/nano.dart';
|
||||
@@ -34,6 +35,8 @@ class SeedValidator extends Validator<MnemonicItem> {
|
||||
case WalletType.nano:
|
||||
case WalletType.banano:
|
||||
return nano!.getNanoWordList(language);
|
||||
case WalletType.polygon:
|
||||
return polygon!.getPolygonWordList(language);
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import 'package:cake_wallet/core/wallet_connect/eth_transaction_model.dart';
|
||||
import 'package:cake_wallet/core/wallet_connect/evm_chain_id.dart';
|
||||
import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_connect/widgets/message_display_widget.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:cake_wallet/core/wallet_connect/models/chain_key_model.dart';
|
||||
@@ -14,7 +15,6 @@ import 'package:cake_wallet/src/screens/wallet_connect/widgets/connection_widget
|
||||
import 'package:cake_wallet/src/screens/wallet_connect/widgets/modals/web3_request_modal.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_connect/utils/string_parsing.dart';
|
||||
import 'package:convert/convert.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:eth_sig_util/eth_sig_util.dart';
|
||||
import 'package:eth_sig_util/util/utils.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
@@ -46,13 +46,12 @@ class EvmChainServiceImpl implements ChainService {
|
||||
required this.wcKeyService,
|
||||
required this.bottomSheetService,
|
||||
required this.wallet,
|
||||
Web3Client? ethClient,
|
||||
}) : ethClient = ethClient ??
|
||||
Web3Client? web3Client,
|
||||
}) : ethClient = web3Client ??
|
||||
Web3Client(
|
||||
appStore.settingsStore.getCurrentNode(WalletType.ethereum).uri.toString(),
|
||||
appStore.settingsStore.getCurrentNode(appStore.wallet!.type).uri.toString(),
|
||||
http.Client(),
|
||||
) {
|
||||
|
||||
for (final String event in getEvents()) {
|
||||
wallet.registerEventEmitter(chainId: getChainId(), event: event);
|
||||
}
|
||||
@@ -138,7 +137,8 @@ class EvmChainServiceImpl implements ChainService {
|
||||
|
||||
try {
|
||||
// Load the private key
|
||||
final List<ChainKeyModel> keys = wcKeyService.getKeysForChain(getChainId());
|
||||
final List<ChainKeyModel> keys = wcKeyService
|
||||
.getKeysForChain(getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type));
|
||||
|
||||
final Credentials credentials = EthPrivateKey.fromHex(keys[0].privateKey);
|
||||
|
||||
@@ -176,13 +176,15 @@ class EvmChainServiceImpl implements ChainService {
|
||||
|
||||
try {
|
||||
// Load the private key
|
||||
final List<ChainKeyModel> keys = wcKeyService.getKeysForChain(getChainId());
|
||||
final List<ChainKeyModel> keys = wcKeyService
|
||||
.getKeysForChain(getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type));
|
||||
|
||||
final EthPrivateKey credentials = EthPrivateKey.fromHex(keys[0].privateKey);
|
||||
|
||||
final String signature = hex.encode(
|
||||
credentials.signPersonalMessageToUint8List(
|
||||
Uint8List.fromList(utf8.encode(message)),
|
||||
chainId: getChainIdBasedOnWalletType(appStore.wallet!.type),
|
||||
),
|
||||
);
|
||||
log(signature);
|
||||
@@ -212,7 +214,8 @@ class EvmChainServiceImpl implements ChainService {
|
||||
}
|
||||
|
||||
// Load the private key
|
||||
final List<ChainKeyModel> keys = wcKeyService.getKeysForChain(getChainId());
|
||||
final List<ChainKeyModel> keys = wcKeyService
|
||||
.getKeysForChain(getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type));
|
||||
|
||||
final Credentials credentials = EthPrivateKey.fromHex(keys[0].privateKey);
|
||||
|
||||
@@ -232,7 +235,11 @@ class EvmChainServiceImpl implements ChainService {
|
||||
);
|
||||
|
||||
try {
|
||||
final result = await ethClient.sendTransaction(credentials, transaction);
|
||||
final result = await ethClient.sendTransaction(
|
||||
credentials,
|
||||
transaction,
|
||||
chainId: getChainIdBasedOnWalletType(appStore.wallet!.type),
|
||||
);
|
||||
|
||||
log('Result: $result');
|
||||
|
||||
@@ -267,7 +274,8 @@ class EvmChainServiceImpl implements ChainService {
|
||||
return authError;
|
||||
}
|
||||
|
||||
final List<ChainKeyModel> keys = wcKeyService.getKeysForChain(getChainId());
|
||||
final List<ChainKeyModel> keys = wcKeyService
|
||||
.getKeysForChain(getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type));
|
||||
|
||||
return EthSigUtil.signTypedData(
|
||||
privateKey: keys[0].privateKey,
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:cake_wallet/core/wallet_connect/models/chain_key_model.dart';
|
||||
import 'package:cake_wallet/polygon/polygon.dart';
|
||||
import 'package:cw_core/balance.dart';
|
||||
import 'package:cw_core/transaction_history.dart';
|
||||
import 'package:cw_core/transaction_info.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
|
||||
abstract class WalletConnectKeyService {
|
||||
/// Returns a list of all the keys.
|
||||
@@ -32,16 +34,36 @@ class KeyServiceImpl implements WalletConnectKeyService {
|
||||
'eip155:42161',
|
||||
'eip155:80001',
|
||||
],
|
||||
privateKey: ethereum!.getPrivateKey(wallet),
|
||||
publicKey: ethereum!.getPublicKey(wallet),
|
||||
privateKey: _getPrivateKeyForWallet(wallet),
|
||||
publicKey: _getPublicKeyForWallet(wallet),
|
||||
),
|
||||
|
||||
];
|
||||
|
||||
late final WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> wallet;
|
||||
|
||||
late final List<ChainKeyModel> _keys;
|
||||
|
||||
static String _getPrivateKeyForWallet(WalletBase wallet) {
|
||||
switch (wallet.type) {
|
||||
case WalletType.ethereum:
|
||||
return ethereum!.getPrivateKey(wallet);
|
||||
case WalletType.polygon:
|
||||
return polygon!.getPrivateKey(wallet);
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
static String _getPublicKeyForWallet(WalletBase wallet) {
|
||||
switch (wallet.type) {
|
||||
case WalletType.ethereum:
|
||||
return ethereum!.getPublicKey(wallet);
|
||||
case WalletType.polygon:
|
||||
return polygon!.getPublicKey(wallet);
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@override
|
||||
List<String> getChains() {
|
||||
final List<String> chainIds = [];
|
||||
|
||||
@@ -9,6 +9,7 @@ import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/core/wallet_connect/models/auth_request_model.dart';
|
||||
import 'package:cake_wallet/core/wallet_connect/models/chain_key_model.dart';
|
||||
import 'package:cake_wallet/core/wallet_connect/models/session_request_model.dart';
|
||||
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_connect/widgets/connection_request_widget.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_connect/widgets/message_display_widget.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_connect/widgets/modals/web3_request_modal.dart';
|
||||
@@ -164,8 +165,10 @@ abstract class Web3WalletServiceBase with Store {
|
||||
|
||||
void _onSessionProposal(SessionProposalEvent? args) async {
|
||||
if (args != null) {
|
||||
final chaindIdNamespace = getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type);
|
||||
final Widget modalWidget = Web3RequestModal(
|
||||
child: ConnectionRequestWidget(
|
||||
chaindIdNamespace: chaindIdNamespace,
|
||||
wallet: _web3Wallet,
|
||||
sessionProposal: SessionRequestModel(request: args.params),
|
||||
),
|
||||
@@ -232,12 +235,13 @@ abstract class Web3WalletServiceBase with Store {
|
||||
@action
|
||||
Future<void> _onAuthRequest(AuthRequest? args) async {
|
||||
if (args != null) {
|
||||
List<ChainKeyModel> chainKeys = walletKeyService.getKeysForChain('eip155:1');
|
||||
final chaindIdNamespace = getChainNameSpaceAndIdBasedOnWalletType(appStore.wallet!.type);
|
||||
List<ChainKeyModel> chainKeys = walletKeyService.getKeysForChain(chaindIdNamespace);
|
||||
// Create the message to be signed
|
||||
final String iss = 'did:pkh:eip155:1:${chainKeys.first.publicKey}';
|
||||
|
||||
final String iss = 'did:pkh:$chaindIdNamespace:${chainKeys.first.publicKey}';
|
||||
final Widget modalWidget = Web3RequestModal(
|
||||
child: ConnectionRequestWidget(
|
||||
chaindIdNamespace: chaindIdNamespace,
|
||||
wallet: _web3Wallet,
|
||||
authRequest: AuthRequestModel(iss: iss, request: args),
|
||||
),
|
||||
|
||||
+16
-5
@@ -18,6 +18,8 @@ import 'package:cake_wallet/nano/nano.dart';
|
||||
import 'package:cake_wallet/ionia/ionia_anypay.dart';
|
||||
import 'package:cake_wallet/ionia/ionia_gift_card.dart';
|
||||
import 'package:cake_wallet/ionia/ionia_tip.dart';
|
||||
import 'package:cake_wallet/polygon/polygon.dart';
|
||||
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/anonpay_details/anonpay_details_page.dart';
|
||||
import 'package:cake_wallet/src/screens/buy/buy_options_page.dart';
|
||||
@@ -88,6 +90,7 @@ import 'package:cake_wallet/view_model/ionia/ionia_purchase_merch_view_model.dar
|
||||
import 'package:cake_wallet/view_model/nano_account_list/nano_account_edit_or_create_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/nano_account_list/nano_account_list_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/node_list/pow_node_list_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/seed_type_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/set_up_2fa_viewmodel.dart';
|
||||
import 'package:cake_wallet/view_model/restore/restore_from_qr_vm.dart';
|
||||
import 'package:cake_wallet/view_model/settings/display_settings_view_model.dart';
|
||||
@@ -225,6 +228,7 @@ 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 'core/totp_request_details.dart';
|
||||
import 'src/screens/settings/desktop_settings/desktop_settings_page.dart';
|
||||
|
||||
@@ -720,6 +724,8 @@ Future<void> setup({
|
||||
|
||||
getIt.registerFactory(() => WalletSeedViewModel(getIt.get<AppStore>().wallet!));
|
||||
|
||||
getIt.registerFactory<SeedTypeViewModel>(() => SeedTypeViewModel(getIt.get<AppStore>()));
|
||||
|
||||
getIt.registerFactoryParam<WalletSeedPage, bool, void>((bool isWalletCreated, _) =>
|
||||
WalletSeedPage(getIt.get<WalletSeedViewModel>(), isNewWalletCreated: isWalletCreated));
|
||||
|
||||
@@ -754,7 +760,7 @@ Future<void> setup({
|
||||
final wallet = getIt.get<AppStore>().wallet;
|
||||
return ConnectionSyncPage(
|
||||
getIt.get<DashboardViewModel>(),
|
||||
wallet?.type == WalletType.ethereum ? getIt.get<Web3WalletService>() : null,
|
||||
isEVMCompatibleChain(wallet!.type) ? getIt.get<Web3WalletService>() : null,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -797,6 +803,9 @@ Future<void> setup({
|
||||
getIt.registerFactory<RobinhoodBuyProvider>(
|
||||
() => RobinhoodBuyProvider(wallet: getIt.get<AppStore>().wallet!));
|
||||
|
||||
getIt.registerFactory<DFXBuyProvider>(
|
||||
() => DFXBuyProvider(wallet: getIt.get<AppStore>().wallet!));
|
||||
|
||||
getIt.registerFactory<OnRamperBuyProvider>(() => OnRamperBuyProvider(
|
||||
settingsStore: getIt.get<AppStore>().settingsStore,
|
||||
wallet: getIt.get<AppStore>().wallet!,
|
||||
@@ -848,9 +857,11 @@ Future<void> setup({
|
||||
return ethereum!.createEthereumWalletService(_walletInfoSource);
|
||||
case WalletType.bitcoinCash:
|
||||
return bitcoinCash!
|
||||
.createBitcoinCashWalletService(_walletInfoSource, _unspentCoinsInfoSource!);
|
||||
.createBitcoinCashWalletService(_walletInfoSource, _unspentCoinsInfoSource);
|
||||
case WalletType.nano:
|
||||
return nano!.createNanoWalletService(_walletInfoSource);
|
||||
case WalletType.polygon:
|
||||
return polygon!.createPolygonWalletService(_walletInfoSource);
|
||||
default:
|
||||
throw Exception('Unexpected token: ${param1.toString()} for generating of WalletService');
|
||||
}
|
||||
@@ -875,8 +886,8 @@ Future<void> setup({
|
||||
getIt.get<AppStore>(), getIt.get<WalletCreationService>(param1: type), _walletInfoSource,
|
||||
type: type));
|
||||
|
||||
getIt.registerFactoryParam<WalletRestorePage, WalletType, void>(
|
||||
(type, _) => WalletRestorePage(getIt.get<WalletRestoreViewModel>(param1: type)));
|
||||
getIt.registerFactoryParam<WalletRestorePage, WalletType, void>((type, _) => WalletRestorePage(
|
||||
getIt.get<WalletRestoreViewModel>(param1: type), getIt.get<SeedTypeViewModel>()));
|
||||
|
||||
getIt.registerFactoryParam<WalletRestoreChooseDerivationViewModel, List<DerivationInfo>, void>(
|
||||
(derivations, _) => WalletRestoreChooseDerivationViewModel(derivationInfos: derivations));
|
||||
@@ -940,7 +951,7 @@ Future<void> setup({
|
||||
|
||||
getIt.registerFactory(() => BuyAmountViewModel());
|
||||
|
||||
getIt.registerFactory(() => BuyOptionsPage());
|
||||
getIt.registerFactory(() => BuyOptionsPage(getIt.get<DashboardViewModel>()));
|
||||
|
||||
getIt.registerFactory(() {
|
||||
final wallet = getIt.get<AppStore>().wallet;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
|
||||
enum BuyProviderType {
|
||||
AskEachTime,
|
||||
Robinhood,
|
||||
Onramper;
|
||||
Onramper,
|
||||
DFX;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
@@ -14,6 +16,42 @@ enum BuyProviderType {
|
||||
return "Robinhood";
|
||||
case BuyProviderType.Onramper:
|
||||
return "Onramper";
|
||||
case BuyProviderType.DFX:
|
||||
return "DFX";
|
||||
}
|
||||
}
|
||||
|
||||
static List<BuyProviderType> getAvailableProviders(WalletType walletType) {
|
||||
switch (walletType) {
|
||||
case WalletType.nano:
|
||||
case WalletType.banano:
|
||||
return [
|
||||
BuyProviderType.AskEachTime,
|
||||
BuyProviderType.Onramper
|
||||
];
|
||||
case WalletType.monero:
|
||||
return [
|
||||
BuyProviderType.AskEachTime,
|
||||
BuyProviderType.Onramper,
|
||||
BuyProviderType.DFX
|
||||
];
|
||||
case WalletType.bitcoin:
|
||||
case WalletType.ethereum:
|
||||
return [
|
||||
BuyProviderType.AskEachTime,
|
||||
BuyProviderType.Onramper,
|
||||
BuyProviderType.DFX,
|
||||
BuyProviderType.Robinhood
|
||||
];
|
||||
case WalletType.litecoin:
|
||||
case WalletType.bitcoinCash:
|
||||
return [
|
||||
BuyProviderType.AskEachTime,
|
||||
BuyProviderType.Onramper,
|
||||
BuyProviderType.Robinhood
|
||||
];
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'dart:io' show Directory, File, Platform;
|
||||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||
import 'package:cake_wallet/entities/encrypt.dart';
|
||||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||
import 'package:cw_core/pathForWallet.dart';
|
||||
import 'package:cake_wallet/entities/secret_store_key.dart';
|
||||
@@ -26,6 +27,7 @@ const cakeWalletBitcoinElectrumUri = 'electrum.cakewallet.com:50002';
|
||||
const cakeWalletLitecoinElectrumUri = 'ltc-electrum.cakewallet.com:50002';
|
||||
const havenDefaultNodeUri = 'nodes.havenprotocol.org:443';
|
||||
const ethereumDefaultNodeUri = 'ethereum.publicnode.com';
|
||||
const polygonDefaultNodeUri = 'polygon-bor.publicnode.com';
|
||||
const cakeWalletBitcoinCashDefaultNodeUri = 'bitcoincash.stackwallet.com:50002';
|
||||
const nanoDefaultNodeUri = 'rpc.nano.to';
|
||||
const nanoDefaultPowNodeUri = 'rpc.nano.to';
|
||||
@@ -64,6 +66,8 @@ Future<void> defaultSettingsMigration(
|
||||
final migrationVersions =
|
||||
List<int>.generate(migrationVersionsLength, (i) => currentVersion + (i + 1));
|
||||
|
||||
/// When you add a new case, increase the initialMigrationVersion parameter in the main.dart file.
|
||||
/// This ensures that this switch case runs the newly added case.
|
||||
await Future.forEach(migrationVersions, (int version) async {
|
||||
try {
|
||||
switch (version) {
|
||||
@@ -82,8 +86,7 @@ Future<void> defaultSettingsMigration(
|
||||
sharedPreferences: sharedPreferences, nodes: nodes);
|
||||
await changeLitecoinCurrentElectrumServerToDefault(
|
||||
sharedPreferences: sharedPreferences, nodes: nodes);
|
||||
await changeHavenCurrentNodeToDefault(
|
||||
sharedPreferences: sharedPreferences, nodes: nodes);
|
||||
await changeHavenCurrentNodeToDefault(sharedPreferences: sharedPreferences, nodes: nodes);
|
||||
await changeBitcoinCashCurrentNodeToDefault(
|
||||
sharedPreferences: sharedPreferences, nodes: nodes);
|
||||
|
||||
@@ -175,6 +178,14 @@ Future<void> defaultSettingsMigration(
|
||||
await changeBitcoinCurrentElectrumServerToDefault(
|
||||
sharedPreferences: sharedPreferences, nodes: nodes);
|
||||
break;
|
||||
case 24:
|
||||
await addPolygonNodeList(nodes: nodes);
|
||||
await changePolygonCurrentNodeToDefault(
|
||||
sharedPreferences: sharedPreferences, nodes: nodes);
|
||||
break;
|
||||
case 25:
|
||||
await rewriteSecureStoragePin(secureStorage: secureStorage);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
@@ -329,6 +340,11 @@ Node? getEthereumDefaultNode({required Box<Node> nodes}) {
|
||||
nodes.values.firstWhereOrNull((node) => node.type == WalletType.ethereum);
|
||||
}
|
||||
|
||||
Node? getPolygonDefaultNode({required Box<Node> nodes}) {
|
||||
return nodes.values.firstWhereOrNull((Node node) => node.uriRaw == polygonDefaultNodeUri) ??
|
||||
nodes.values.firstWhereOrNull((node) => node.type == WalletType.polygon);
|
||||
}
|
||||
|
||||
Node? getNanoDefaultNode({required Box<Node> nodes}) {
|
||||
return nodes.values.firstWhereOrNull((Node node) => node.uriRaw == nanoDefaultNodeUri) ??
|
||||
nodes.values.firstWhereOrNull((node) => node.type == WalletType.nano);
|
||||
@@ -340,9 +356,9 @@ Node? getNanoDefaultPowNode({required Box<Node> nodes}) {
|
||||
}
|
||||
|
||||
Node? getBitcoinCashDefaultElectrumServer({required Box<Node> nodes}) {
|
||||
return nodes.values.firstWhereOrNull(
|
||||
(Node node) => node.uriRaw == cakeWalletBitcoinCashDefaultNodeUri)
|
||||
?? nodes.values.firstWhereOrNull((node) => node.type == WalletType.bitcoinCash);
|
||||
return nodes.values
|
||||
.firstWhereOrNull((Node node) => node.uriRaw == cakeWalletBitcoinCashDefaultNodeUri) ??
|
||||
nodes.values.firstWhereOrNull((node) => node.type == WalletType.bitcoinCash);
|
||||
}
|
||||
|
||||
Node getMoneroDefaultNode({required Box<Node> nodes}) {
|
||||
@@ -364,6 +380,37 @@ Node getMoneroDefaultNode({required Box<Node> nodes}) {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> rewriteSecureStoragePin({required FlutterSecureStorage secureStorage}) async {
|
||||
// the bug only affects ios/mac:
|
||||
if (!Platform.isIOS && !Platform.isMacOS) {
|
||||
return;
|
||||
}
|
||||
|
||||
// first, get the encoded pin:
|
||||
final keyForPinCode = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
|
||||
String? encodedPin;
|
||||
try {
|
||||
encodedPin = await secureStorage.read(key: keyForPinCode);
|
||||
} catch (e) {
|
||||
// either we don't have a pin, or we can't read it (maybe even because of the bug!)
|
||||
// the only option here is to abort the migration or we risk losing the pin and locking the user out
|
||||
return;
|
||||
}
|
||||
|
||||
if (encodedPin == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ensure we overwrite by deleting the old key first:
|
||||
await secureStorage.delete(key: keyForPinCode);
|
||||
await secureStorage.write(
|
||||
key: keyForPinCode,
|
||||
value: encodedPin,
|
||||
iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock),
|
||||
mOptions: MacOsOptions(accessibility: KeychainAccessibility.first_unlock),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> changeBitcoinCurrentElectrumServerToDefault(
|
||||
{required SharedPreferences sharedPreferences, required Box<Node> nodes}) async {
|
||||
final server = getBitcoinDefaultElectrumServer(nodes: nodes);
|
||||
@@ -381,8 +428,7 @@ Future<void> changeLitecoinCurrentElectrumServerToDefault(
|
||||
}
|
||||
|
||||
Future<void> changeBitcoinCashCurrentNodeToDefault(
|
||||
{required SharedPreferences sharedPreferences,
|
||||
required Box<Node> nodes}) async {
|
||||
{required SharedPreferences sharedPreferences, required Box<Node> nodes}) async {
|
||||
final server = getBitcoinCashDefaultElectrumServer(nodes: nodes);
|
||||
final serverId = server?.key as int ?? 0;
|
||||
|
||||
@@ -496,6 +542,7 @@ Future<void> generateBackupPassword(FlutterSecureStorage secureStorage) async {
|
||||
}
|
||||
|
||||
final password = encrypt.Key.fromSecureRandom(32).base16;
|
||||
await secureStorage.delete(key: key);
|
||||
await secureStorage.write(key: key, value: password);
|
||||
}
|
||||
|
||||
@@ -537,34 +584,33 @@ Future<void> checkCurrentNodes(
|
||||
final currentMoneroNodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey);
|
||||
final currentBitcoinElectrumSeverId =
|
||||
sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey);
|
||||
final currentLitecoinElectrumSeverId = sharedPreferences
|
||||
.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey);
|
||||
final currentHavenNodeId = sharedPreferences
|
||||
.getInt(PreferencesKey.currentHavenNodeIdKey);
|
||||
final currentEthereumNodeId = sharedPreferences
|
||||
.getInt(PreferencesKey.currentEthereumNodeIdKey);
|
||||
final currentNanoNodeId = sharedPreferences
|
||||
.getInt(PreferencesKey.currentNanoNodeIdKey);
|
||||
final currentNanoPowNodeId = sharedPreferences
|
||||
.getInt(PreferencesKey.currentNanoPowNodeIdKey);
|
||||
final currentBitcoinCashNodeId = sharedPreferences
|
||||
.getInt(PreferencesKey.currentBitcoinCashNodeIdKey);
|
||||
final currentMoneroNode = nodeSource.values.firstWhereOrNull(
|
||||
(node) => node.key == currentMoneroNodeId);
|
||||
final currentBitcoinElectrumServer = nodeSource.values.firstWhereOrNull(
|
||||
(node) => node.key == currentBitcoinElectrumSeverId);
|
||||
final currentLitecoinElectrumServer = nodeSource.values.firstWhereOrNull(
|
||||
(node) => node.key == currentLitecoinElectrumSeverId);
|
||||
final currentHavenNodeServer = nodeSource.values.firstWhereOrNull(
|
||||
(node) => node.key == currentHavenNodeId);
|
||||
final currentEthereumNodeServer = nodeSource.values.firstWhereOrNull(
|
||||
(node) => node.key == currentEthereumNodeId);
|
||||
final currentLitecoinElectrumSeverId =
|
||||
sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey);
|
||||
final currentHavenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey);
|
||||
final currentEthereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey);
|
||||
final currentPolygonNodeId = sharedPreferences.getInt(PreferencesKey.currentPolygonNodeIdKey);
|
||||
final currentNanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey);
|
||||
final currentNanoPowNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoPowNodeIdKey);
|
||||
final currentBitcoinCashNodeId =
|
||||
sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey);
|
||||
final currentMoneroNode =
|
||||
nodeSource.values.firstWhereOrNull((node) => node.key == currentMoneroNodeId);
|
||||
final currentBitcoinElectrumServer =
|
||||
nodeSource.values.firstWhereOrNull((node) => node.key == currentBitcoinElectrumSeverId);
|
||||
final currentLitecoinElectrumServer =
|
||||
nodeSource.values.firstWhereOrNull((node) => node.key == currentLitecoinElectrumSeverId);
|
||||
final currentHavenNodeServer =
|
||||
nodeSource.values.firstWhereOrNull((node) => node.key == currentHavenNodeId);
|
||||
final currentEthereumNodeServer =
|
||||
nodeSource.values.firstWhereOrNull((node) => node.key == currentEthereumNodeId);
|
||||
final currentPolygonNodeServer =
|
||||
nodeSource.values.firstWhereOrNull((node) => node.key == currentPolygonNodeId);
|
||||
final currentNanoNodeServer =
|
||||
nodeSource.values.firstWhereOrNull((node) => node.key == currentNanoNodeId);
|
||||
nodeSource.values.firstWhereOrNull((node) => node.key == currentNanoNodeId);
|
||||
final currentNanoPowNodeServer =
|
||||
powNodeSource.values.firstWhereOrNull((node) => node.key == currentNanoPowNodeId);
|
||||
final currentBitcoinCashNodeServer = nodeSource.values.firstWhereOrNull(
|
||||
(node) => node.key == currentBitcoinCashNodeId);
|
||||
powNodeSource.values.firstWhereOrNull((node) => node.key == currentNanoPowNodeId);
|
||||
final currentBitcoinCashNodeServer =
|
||||
nodeSource.values.firstWhereOrNull((node) => node.key == currentBitcoinCashNodeId);
|
||||
if (currentMoneroNode == null) {
|
||||
final newCakeWalletNode = Node(uri: newCakeWalletMoneroUri, type: WalletType.monero);
|
||||
await nodeSource.add(newCakeWalletNode);
|
||||
@@ -616,8 +662,13 @@ Future<void> checkCurrentNodes(
|
||||
if (currentBitcoinCashNodeServer == null) {
|
||||
final node = Node(uri: cakeWalletBitcoinCashDefaultNodeUri, type: WalletType.bitcoinCash);
|
||||
await nodeSource.add(node);
|
||||
await sharedPreferences.setInt(
|
||||
PreferencesKey.currentBitcoinCashNodeIdKey, node.key as int);
|
||||
await sharedPreferences.setInt(PreferencesKey.currentBitcoinCashNodeIdKey, node.key as int);
|
||||
}
|
||||
|
||||
if (currentPolygonNodeServer == null) {
|
||||
final node = Node(uri: polygonDefaultNodeUri, type: WalletType.polygon);
|
||||
await nodeSource.add(node);
|
||||
await sharedPreferences.setInt(PreferencesKey.currentPolygonNodeIdKey, node.key as int);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -713,3 +764,20 @@ Future<void> changeNanoCurrentPowNodeToDefault(
|
||||
final nodeId = node?.key as int? ?? 0;
|
||||
await sharedPreferences.setInt(PreferencesKey.currentNanoPowNodeIdKey, nodeId);
|
||||
}
|
||||
|
||||
Future<void> addPolygonNodeList({required Box<Node> nodes}) async {
|
||||
final nodeList = await loadDefaultPolygonNodes();
|
||||
for (var node in nodeList) {
|
||||
if (nodes.values.firstWhereOrNull((element) => element.uriRaw == node.uriRaw) == null) {
|
||||
await nodes.add(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> changePolygonCurrentNodeToDefault(
|
||||
{required SharedPreferences sharedPreferences, required Box<Node> nodes}) async {
|
||||
final node = getPolygonDefaultNode(nodes: nodes);
|
||||
final nodeId = node?.key as int? ?? 0;
|
||||
|
||||
await sharedPreferences.setInt(PreferencesKey.currentPolygonNodeIdKey, nodeId);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:cake_wallet/polygon/polygon.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:ens_dart/ens_dart.dart';
|
||||
@@ -12,6 +13,10 @@ class EnsRecord {
|
||||
if (wallet != null && wallet.type == WalletType.ethereum) {
|
||||
_client = ethereum!.getWeb3Client(wallet);
|
||||
}
|
||||
|
||||
if (wallet != null && wallet.type == WalletType.polygon) {
|
||||
_client = polygon!.getWeb3Client(wallet);
|
||||
}
|
||||
|
||||
if (_client == null) {
|
||||
_client = Web3Client("https://ethereum.publicnode.com", Client());
|
||||
@@ -31,6 +36,7 @@ class EnsRecord {
|
||||
case WalletType.haven:
|
||||
return await ens.withName(name).getCoinAddress(CoinType.XHV);
|
||||
case WalletType.ethereum:
|
||||
case WalletType.polygon:
|
||||
default:
|
||||
return (await ens.withName(name).getAddress()).hex;
|
||||
}
|
||||
|
||||
@@ -147,6 +147,7 @@ Future<void> ios_migrate_pin() async {
|
||||
|
||||
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
|
||||
final encodedPassword = encodedPinCode(pin: pinPassword);
|
||||
await flutterSecureStorage.delete(key: key);
|
||||
await flutterSecureStorage.write(key: key, value: encodedPassword);
|
||||
await prefs.setBool('ios_migration_pin_completed', true);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,9 @@ Future<List<int>> getEncryptionKey(
|
||||
if (stringifiedKey == null) {
|
||||
key = CakeHive.generateSecureKey();
|
||||
final keyStringified = key.join(',');
|
||||
await secureStorage.write(key: 'transactionDescriptionsBoxKey', value: keyStringified);
|
||||
String storageKey = 'transactionDescriptionsBoxKey';
|
||||
await secureStorage.delete(key: storageKey);
|
||||
await secureStorage.write(key: storageKey, value: keyStringified);
|
||||
} else {
|
||||
key = stringifiedKey.split(',').map((i) => int.parse(i)).toList();
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:cake_wallet/buy/dfx/dfx_buy_provider.dart';
|
||||
import 'package:cake_wallet/buy/moonpay/moonpay_buy_provider.dart';
|
||||
import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart';
|
||||
import 'package:cake_wallet/buy/robinhood/robinhood_buy_provider.dart';
|
||||
@@ -19,7 +20,8 @@ class MainActions {
|
||||
|
||||
final bool Function(DashboardViewModel viewModel)? isEnabled;
|
||||
final bool Function(DashboardViewModel viewModel)? canShow;
|
||||
final Future<void> Function(BuildContext context, DashboardViewModel viewModel) onTap;
|
||||
final Future<void> Function(
|
||||
BuildContext context, DashboardViewModel viewModel) onTap;
|
||||
|
||||
MainActions._({
|
||||
required this.name,
|
||||
@@ -43,47 +45,54 @@ class MainActions {
|
||||
isEnabled: (viewModel) => viewModel.isEnabledBuyAction,
|
||||
canShow: (viewModel) => viewModel.hasBuyAction,
|
||||
onTap: (BuildContext context, DashboardViewModel viewModel) async {
|
||||
if (!viewModel.isEnabledBuyAction) {
|
||||
await _showErrorDialog(context, S.of(context).unsupported_asset);
|
||||
return;
|
||||
}
|
||||
|
||||
final defaultBuyProvider = viewModel.defaultBuyProvider;
|
||||
final walletType = viewModel.type;
|
||||
|
||||
if (!viewModel.isEnabledBuyAction) return;
|
||||
|
||||
switch (walletType) {
|
||||
case WalletType.bitcoin:
|
||||
case WalletType.litecoin:
|
||||
case WalletType.ethereum:
|
||||
case WalletType.bitcoinCash:
|
||||
switch (defaultBuyProvider) {
|
||||
case BuyProviderType.AskEachTime:
|
||||
Navigator.pushNamed(context, Routes.buy);
|
||||
break;
|
||||
case BuyProviderType.Onramper:
|
||||
await getIt.get<OnRamperBuyProvider>().launchProvider(context);
|
||||
break;
|
||||
case BuyProviderType.Robinhood:
|
||||
await getIt.get<RobinhoodBuyProvider>().launchProvider(context);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case WalletType.nano:
|
||||
case WalletType.banano:
|
||||
case WalletType.monero:
|
||||
await getIt.get<OnRamperBuyProvider>().launchProvider(context);
|
||||
break;
|
||||
default:
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithOneAction(
|
||||
alertTitle: S.of(context).buy,
|
||||
alertContent: S.of(context).unsupported_asset,
|
||||
buttonText: S.of(context).ok,
|
||||
buttonAction: () => Navigator.of(context).pop());
|
||||
});
|
||||
try {
|
||||
await _launchProviderByType(context, defaultBuyProvider);
|
||||
} catch (e) {
|
||||
await _showErrorDialog(context, e.toString());
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
static Future<void> _launchProviderByType(BuildContext context, BuyProviderType providerType) async {
|
||||
switch (providerType) {
|
||||
case BuyProviderType.AskEachTime:
|
||||
Navigator.pushNamed(context, Routes.buy);
|
||||
break;
|
||||
case BuyProviderType.Onramper:
|
||||
await getIt.get<OnRamperBuyProvider>().launchProvider(context);
|
||||
break;
|
||||
case BuyProviderType.Robinhood:
|
||||
await getIt.get<RobinhoodBuyProvider>().launchProvider(context);
|
||||
break;
|
||||
case BuyProviderType.DFX:
|
||||
await getIt.get<DFXBuyProvider>().launchProvider(context);
|
||||
break;
|
||||
default:
|
||||
throw UnsupportedError('Unsupported buy provider type');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static Future<void> _showErrorDialog(BuildContext context, String errorMessage) async {
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithOneAction(
|
||||
alertTitle: S.of(context).buy,
|
||||
alertContent: errorMessage,
|
||||
buttonText: S.of(context).ok,
|
||||
buttonAction: () => Navigator.of(context).pop(),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
static MainActions receiveAction = MainActions._(
|
||||
name: (context) => S.of(context).receive,
|
||||
image: 'assets/images/received.png',
|
||||
@@ -124,6 +133,7 @@ class MainActions {
|
||||
case WalletType.bitcoin:
|
||||
case WalletType.litecoin:
|
||||
case WalletType.ethereum:
|
||||
case WalletType.polygon:
|
||||
case WalletType.bitcoinCash:
|
||||
if (viewModel.isEnabledSellAction) {
|
||||
final moonPaySellProvider = MoonPaySellProvider();
|
||||
|
||||
@@ -133,6 +133,22 @@ Future<List<Node>> loadDefaultNanoPowNodes() async {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
Future<List<Node>> loadDefaultPolygonNodes() async {
|
||||
final nodesRaw = await rootBundle.loadString('assets/polygon_node_list.yml');
|
||||
final loadedNodes = loadYaml(nodesRaw) as YamlList;
|
||||
final nodes = <Node>[];
|
||||
|
||||
for (final raw in loadedNodes) {
|
||||
if (raw is Map) {
|
||||
final node = Node.fromMap(Map<String, Object>.from(raw));
|
||||
node.type = WalletType.polygon;
|
||||
nodes.add(node);
|
||||
}
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
Future<void> resetToDefault(Box<Node> nodeSource) async {
|
||||
final moneroNodes = await loadDefaultNodes();
|
||||
final bitcoinElectrumServerList = await loadBitcoinElectrumServerList();
|
||||
@@ -141,6 +157,8 @@ Future<void> resetToDefault(Box<Node> nodeSource) async {
|
||||
final havenNodes = await loadDefaultHavenNodes();
|
||||
final ethereumNodes = await loadDefaultEthereumNodes();
|
||||
final nanoNodes = await loadDefaultNanoNodes();
|
||||
final polygonNodes = await loadDefaultPolygonNodes();
|
||||
|
||||
|
||||
final nodes = moneroNodes +
|
||||
bitcoinElectrumServerList +
|
||||
@@ -148,7 +166,8 @@ Future<void> resetToDefault(Box<Node> nodeSource) async {
|
||||
havenNodes +
|
||||
ethereumNodes +
|
||||
bitcoinCashElectrumServerList +
|
||||
nanoNodes;
|
||||
nanoNodes +
|
||||
polygonNodes;
|
||||
|
||||
await nodeSource.clear();
|
||||
await nodeSource.addAll(nodes);
|
||||
|
||||
@@ -6,6 +6,7 @@ class PreferencesKey {
|
||||
static const currentLitecoinElectrumSererIdKey = 'current_node_id_ltc';
|
||||
static const currentHavenNodeIdKey = 'current_node_id_xhv';
|
||||
static const currentEthereumNodeIdKey = 'current_node_id_eth';
|
||||
static const currentPolygonNodeIdKey = 'current_node_id_matic';
|
||||
static const currentNanoNodeIdKey = 'current_node_id_nano';
|
||||
static const currentNanoPowNodeIdKey = 'current_node_id_nano_pow';
|
||||
static const currentBananoNodeIdKey = 'current_node_id_banano';
|
||||
@@ -37,6 +38,7 @@ class PreferencesKey {
|
||||
static const havenTransactionPriority = 'current_fee_priority_haven';
|
||||
static const litecoinTransactionPriority = 'current_fee_priority_litecoin';
|
||||
static const ethereumTransactionPriority = 'current_fee_priority_ethereum';
|
||||
static const polygonTransactionPriority = 'current_fee_priority_polygon';
|
||||
static const bitcoinCashTransactionPriority = 'current_fee_priority_bitcoin_cash';
|
||||
static const shouldShowReceiveWarning = 'should_show_receive_warning';
|
||||
static const shouldShowYatPopup = 'should_show_yat_popup';
|
||||
@@ -50,6 +52,7 @@ class PreferencesKey {
|
||||
static const sortBalanceBy = 'sort_balance_by';
|
||||
static const pinNativeTokenAtTop = 'pin_native_token_at_top';
|
||||
static const useEtherscan = 'use_etherscan';
|
||||
static const usePolygonScan = 'use_polygonscan';
|
||||
static const defaultNanoRep = 'default_nano_representative';
|
||||
static const defaultBananoRep = 'default_banano_representative';
|
||||
static const lookupsTwitter = 'looks_up_twitter';
|
||||
@@ -64,6 +67,7 @@ class PreferencesKey {
|
||||
|
||||
static const exchangeProvidersSelection = 'exchange-providers-selection';
|
||||
static const autoGenerateSubaddressStatusKey = 'auto_generate_subaddress_status';
|
||||
static const moneroSeedType = 'monero_seed_type';
|
||||
static const clearnetDonationLink = 'clearnet_donation_link';
|
||||
static const onionDonationLink = 'onion_donation_link';
|
||||
static const lastSeenAppVersion = 'last_seen_app_version';
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
|
||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:cake_wallet/haven/haven.dart';
|
||||
import 'package:cake_wallet/monero/monero.dart';
|
||||
import 'package:cake_wallet/polygon/polygon.dart';
|
||||
import 'package:cw_core/transaction_priority.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
|
||||
@@ -24,6 +25,8 @@ List<TransactionPriority> priorityForWalletType(WalletType type) {
|
||||
case WalletType.nano:
|
||||
case WalletType.banano:
|
||||
return [];
|
||||
case WalletType.polygon:
|
||||
return polygon!.getTransactionPriorities();
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cw_core/enumerable_item.dart';
|
||||
|
||||
class SeedType extends EnumerableItem<int> with Serializable<int> {
|
||||
const SeedType({required String title, required int raw}) : super(title: title, raw: raw);
|
||||
|
||||
static const all = [SeedType.legacy, SeedType.polyseed];
|
||||
|
||||
static const defaultSeedType = polyseed;
|
||||
|
||||
static const legacy = SeedType(raw: 0, title: 'Legacy (25 words)');
|
||||
static const polyseed = SeedType(raw: 1, title: 'Polyseed (16 words)');
|
||||
|
||||
static SeedType deserialize({required int raw}) {
|
||||
switch (raw) {
|
||||
case 0:
|
||||
return legacy;
|
||||
case 1:
|
||||
return polyseed;
|
||||
default:
|
||||
throw Exception('Unexpected token: $raw for SeedType deserialize');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
switch (this) {
|
||||
case SeedType.legacy:
|
||||
return S.current.seedtype_legacy;
|
||||
case SeedType.polyseed:
|
||||
return S.current.seedtype_polyseed;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -163,7 +163,7 @@ Future<void> initializeAppConfigs() async {
|
||||
transactionDescriptions: transactionDescriptions,
|
||||
secureStorage: secureStorage,
|
||||
anonpayInvoiceInfo: anonpayInvoiceInfo,
|
||||
initialMigrationVersion: 23);
|
||||
initialMigrationVersion: 25);
|
||||
}
|
||||
|
||||
Future<void> initialSetup(
|
||||
|
||||
@@ -166,6 +166,10 @@ class CWMonero extends Monero {
|
||||
|
||||
@override
|
||||
List<String> getMoneroWordList(String language) {
|
||||
if (language.startsWith("POLYSEED_")) {
|
||||
final lang = language.replaceAll("POLYSEED_", "");
|
||||
return PolyseedLang.getByEnglishName(lang).words;
|
||||
}
|
||||
switch (language.toLowerCase()) {
|
||||
case 'english':
|
||||
return EnglishMnemonics.words;
|
||||
@@ -223,8 +227,10 @@ class CWMonero extends Monero {
|
||||
WalletCredentials createMoneroNewWalletCredentials({
|
||||
required String name,
|
||||
required String language,
|
||||
required bool isPolyseed,
|
||||
String? password}) =>
|
||||
MoneroNewWalletCredentials(name: name, password: password, language: language);
|
||||
MoneroNewWalletCredentials(
|
||||
name: name, password: password, language: language, isPolyseed: isPolyseed);
|
||||
|
||||
@override
|
||||
Map<String, String> getKeys(Object wallet) {
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
part of 'polygon.dart';
|
||||
|
||||
class CWPolygon extends Polygon {
|
||||
@override
|
||||
List<String> getPolygonWordList(String language) => EthereumMnemonics.englishWordlist;
|
||||
|
||||
WalletService createPolygonWalletService(Box<WalletInfo> walletInfoSource) =>
|
||||
PolygonWalletService(walletInfoSource);
|
||||
|
||||
@override
|
||||
WalletCredentials createPolygonNewWalletCredentials({
|
||||
required String name,
|
||||
WalletInfo? walletInfo,
|
||||
}) =>
|
||||
PolygonNewWalletCredentials(name: name, walletInfo: walletInfo);
|
||||
|
||||
@override
|
||||
WalletCredentials createPolygonRestoreWalletFromSeedCredentials({
|
||||
required String name,
|
||||
required String mnemonic,
|
||||
required String password,
|
||||
}) =>
|
||||
PolygonRestoreWalletFromSeedCredentials(name: name, password: password, mnemonic: mnemonic);
|
||||
|
||||
@override
|
||||
WalletCredentials createPolygonRestoreWalletFromPrivateKey({
|
||||
required String name,
|
||||
required String privateKey,
|
||||
required String password,
|
||||
}) =>
|
||||
PolygonRestoreWalletFromPrivateKey(name: name, password: password, privateKey: privateKey);
|
||||
|
||||
@override
|
||||
String getAddress(WalletBase wallet) => (wallet as PolygonWallet).walletAddresses.address;
|
||||
|
||||
@override
|
||||
String getPrivateKey(WalletBase wallet) {
|
||||
final privateKeyHolder = (wallet as PolygonWallet).polygonPrivateKey;
|
||||
String stringKey = bytesToHex(privateKeyHolder.privateKey);
|
||||
return stringKey;
|
||||
}
|
||||
|
||||
@override
|
||||
String getPublicKey(WalletBase wallet) {
|
||||
final privateKeyInUnitInt = (wallet as PolygonWallet).polygonPrivateKey;
|
||||
final publicKey = privateKeyInUnitInt.address.hex;
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
@override
|
||||
TransactionPriority getDefaultTransactionPriority() => PolygonTransactionPriority.medium;
|
||||
|
||||
@override
|
||||
TransactionPriority getPolygonTransactionPrioritySlow() => PolygonTransactionPriority.slow;
|
||||
|
||||
@override
|
||||
List<TransactionPriority> getTransactionPriorities() => PolygonTransactionPriority.all;
|
||||
|
||||
@override
|
||||
TransactionPriority deserializePolygonTransactionPriority(int raw) =>
|
||||
PolygonTransactionPriority.deserialize(raw: raw);
|
||||
|
||||
Object createPolygonTransactionCredentials(
|
||||
List<Output> outputs, {
|
||||
required TransactionPriority priority,
|
||||
required CryptoCurrency currency,
|
||||
int? feeRate,
|
||||
}) =>
|
||||
PolygonTransactionCredentials(
|
||||
outputs
|
||||
.map((out) => OutputInfo(
|
||||
fiatAmount: out.fiatAmount,
|
||||
cryptoAmount: out.cryptoAmount,
|
||||
address: out.address,
|
||||
note: out.note,
|
||||
sendAll: out.sendAll,
|
||||
extractedAddress: out.extractedAddress,
|
||||
isParsedAddress: out.isParsedAddress,
|
||||
formattedCryptoAmount: out.formattedCryptoAmount))
|
||||
.toList(),
|
||||
priority: priority as PolygonTransactionPriority,
|
||||
currency: currency,
|
||||
feeRate: feeRate,
|
||||
);
|
||||
|
||||
Object createPolygonTransactionCredentialsRaw(
|
||||
List<OutputInfo> outputs, {
|
||||
TransactionPriority? priority,
|
||||
required CryptoCurrency currency,
|
||||
required int feeRate,
|
||||
}) =>
|
||||
PolygonTransactionCredentials(
|
||||
outputs,
|
||||
priority: priority as PolygonTransactionPriority?,
|
||||
currency: currency,
|
||||
feeRate: feeRate,
|
||||
);
|
||||
|
||||
@override
|
||||
int formatterPolygonParseAmount(String amount) => PolygonFormatter.parsePolygonAmount(amount);
|
||||
|
||||
@override
|
||||
double formatterPolygonAmountToDouble(
|
||||
{TransactionInfo? transaction, BigInt? amount, int exponent = 18}) {
|
||||
assert(transaction != null || amount != null);
|
||||
|
||||
if (transaction != null) {
|
||||
transaction as PolygonTransactionInfo;
|
||||
return transaction.ethAmount / BigInt.from(10).pow(transaction.exponent);
|
||||
} else {
|
||||
return (amount!) / BigInt.from(10).pow(exponent);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
List<Erc20Token> getERC20Currencies(WalletBase wallet) {
|
||||
final polygonWallet = wallet as PolygonWallet;
|
||||
return polygonWallet.erc20Currencies;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> addErc20Token(WalletBase wallet, Erc20Token token) async =>
|
||||
await (wallet as PolygonWallet).addErc20Token(token);
|
||||
|
||||
@override
|
||||
Future<void> deleteErc20Token(WalletBase wallet, Erc20Token token) async =>
|
||||
await (wallet as PolygonWallet).deleteErc20Token(token);
|
||||
|
||||
@override
|
||||
Future<Erc20Token?> getErc20Token(WalletBase wallet, String contractAddress) async {
|
||||
final polygonWallet = wallet as PolygonWallet;
|
||||
return await polygonWallet.getErc20Token(contractAddress);
|
||||
}
|
||||
|
||||
@override
|
||||
CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction) {
|
||||
transaction as PolygonTransactionInfo;
|
||||
if (transaction.tokenSymbol == CryptoCurrency.maticpoly.title) {
|
||||
return CryptoCurrency.maticpoly;
|
||||
}
|
||||
|
||||
wallet as PolygonWallet;
|
||||
return wallet.erc20Currencies.firstWhere(
|
||||
(element) => transaction.tokenSymbol.toLowerCase() == element.symbol.toLowerCase());
|
||||
}
|
||||
|
||||
@override
|
||||
void updatePolygonScanUsageState(WalletBase wallet, bool isEnabled) {
|
||||
(wallet as PolygonWallet).updatePolygonScanUsageState(isEnabled);
|
||||
}
|
||||
|
||||
@override
|
||||
Web3Client? getWeb3Client(WalletBase wallet) {
|
||||
return (wallet as PolygonWallet).getWeb3Client();
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,11 @@ import 'package:cake_wallet/core/fiat_conversion_service.dart';
|
||||
import 'package:cake_wallet/entities/fiat_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/update_haven_rate.dart';
|
||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:cake_wallet/polygon/polygon.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cw_core/erc20_token.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
@@ -33,10 +35,18 @@ Future<void> startFiatRateUpdate(
|
||||
torOnly: settingsStore.fiatApiMode == FiatApiMode.torOnly);
|
||||
}
|
||||
|
||||
Iterable<Erc20Token>? currencies;
|
||||
if (appStore.wallet!.type == WalletType.ethereum) {
|
||||
final currencies =
|
||||
ethereum!.getERC20Currencies(appStore.wallet!).where((element) => element.enabled);
|
||||
currencies =
|
||||
ethereum!.getERC20Currencies(appStore.wallet!).where((element) => element.enabled);
|
||||
}
|
||||
|
||||
if (appStore.wallet!.type == WalletType.polygon) {
|
||||
currencies =
|
||||
polygon!.getERC20Currencies(appStore.wallet!).where((element) => element.enabled);
|
||||
}
|
||||
|
||||
if (currencies != null) {
|
||||
for (final currency in currencies) {
|
||||
() async {
|
||||
fiatConversionStore.prices[currency] = await FiatConversionService.fetchPrice(
|
||||
|
||||
@@ -2,7 +2,8 @@ import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
|
||||
import 'package:cake_wallet/entities/fiat_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/update_haven_rate.dart';
|
||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:cake_wallet/nano/nano.dart';
|
||||
import 'package:cake_wallet/polygon/polygon.dart';
|
||||
import 'package:cw_core/erc20_token.dart';
|
||||
import 'package:cw_core/transaction_history.dart';
|
||||
import 'package:cw_core/balance.dart';
|
||||
import 'package:cw_core/transaction_info.dart';
|
||||
@@ -107,10 +108,17 @@ void startCurrentWalletChangeReaction(
|
||||
fiat: settingsStore.fiatCurrency,
|
||||
torOnly: settingsStore.fiatApiMode == FiatApiMode.torOnly);
|
||||
|
||||
Iterable<Erc20Token>? currencies;
|
||||
if (wallet.type == WalletType.ethereum) {
|
||||
final currencies =
|
||||
currencies =
|
||||
ethereum!.getERC20Currencies(appStore.wallet!).where((element) => element.enabled);
|
||||
}
|
||||
if (wallet.type == WalletType.polygon) {
|
||||
currencies =
|
||||
polygon!.getERC20Currencies(appStore.wallet!).where((element) => element.enabled);
|
||||
}
|
||||
|
||||
if (currencies != null) {
|
||||
for (final currency in currencies) {
|
||||
() async {
|
||||
fiatConversionStore.prices[currency] = await FiatConversionService.fetchPrice(
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import 'package:cake_wallet/core/wallet_connect/evm_chain_id.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
|
||||
bool isEVMCompatibleChain(WalletType walletType) {
|
||||
switch (walletType) {
|
||||
case WalletType.polygon:
|
||||
case WalletType.ethereum:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
String getChainNameSpaceAndIdBasedOnWalletType(WalletType walletType) {
|
||||
switch (walletType) {
|
||||
case WalletType.ethereum:
|
||||
return EVMChainId.ethereum.chain();
|
||||
case WalletType.polygon:
|
||||
return EVMChainId.polygon.chain();
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
int getChainIdBasedOnWalletType(WalletType walletType) {
|
||||
switch (walletType) {
|
||||
case WalletType.polygon:
|
||||
return 137;
|
||||
|
||||
// For now, we return eth chain Id as the default, we'll modify as we add more wallets
|
||||
case WalletType.ethereum:
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
String getChainNameBasedOnWalletType(WalletType walletType) {
|
||||
switch (walletType) {
|
||||
case WalletType.ethereum:
|
||||
return 'eth';
|
||||
case WalletType.polygon:
|
||||
return 'polygon';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
+6
-16
@@ -62,6 +62,7 @@ import 'package:cake_wallet/view_model/dashboard/nft_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart';
|
||||
import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/seed_type_view_model.dart';
|
||||
import 'package:cake_wallet/wallet_type_utils.dart';
|
||||
import 'package:cw_core/nano_account.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
@@ -87,7 +88,6 @@ import 'package:cake_wallet/src/screens/setup_pin_code/setup_pin_code.dart';
|
||||
import 'package:cake_wallet/src/screens/restore/restore_options_page.dart';
|
||||
import 'package:cake_wallet/src/screens/send/send_page.dart';
|
||||
import 'package:cake_wallet/src/screens/disclaimer/disclaimer_page.dart';
|
||||
import 'package:cake_wallet/src/screens/seed_language/seed_language_page.dart';
|
||||
import 'package:cake_wallet/src/screens/transaction_details/transaction_details_page.dart';
|
||||
import 'package:cake_wallet/src/screens/monero_accounts/monero_account_edit_or_create_page.dart';
|
||||
import 'package:cake_wallet/src/screens/contact/contact_list_page.dart';
|
||||
@@ -147,8 +147,9 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||
case Routes.newWallet:
|
||||
final type = settings.arguments as WalletType;
|
||||
final walletNewVM = getIt.get<WalletNewVM>(param1: type);
|
||||
final seedTypeViewModel = getIt.get<SeedTypeViewModel>();
|
||||
|
||||
return CupertinoPageRoute<void>(builder: (_) => NewWalletPage(walletNewVM));
|
||||
return CupertinoPageRoute<void>(builder: (_) => NewWalletPage(walletNewVM, seedTypeViewModel));
|
||||
|
||||
case Routes.setupPin:
|
||||
Function(PinCodeState<PinCodeWidget>, String)? callback;
|
||||
@@ -264,17 +265,6 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||
case Routes.changeRep:
|
||||
return CupertinoPageRoute<void>(builder: (_) => getIt.get<NanoChangeRepPage>());
|
||||
|
||||
case Routes.seedLanguage:
|
||||
final args = settings.arguments as List<dynamic>;
|
||||
final type = args.first as WalletType;
|
||||
final redirectRoute = args[1] as String;
|
||||
|
||||
return CupertinoPageRoute<void>(builder: (_) {
|
||||
return SeedLanguage(
|
||||
onConfirm: (context, lang) =>
|
||||
Navigator.of(context).popAndPushNamed(redirectRoute, arguments: [type, lang]));
|
||||
});
|
||||
|
||||
case Routes.walletList:
|
||||
return MaterialPageRoute<void>(
|
||||
fullscreenDialog: true, builder: (_) => getIt.get<WalletListPage>());
|
||||
@@ -543,9 +533,9 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||
|
||||
return CupertinoPageRoute<void>(
|
||||
builder: (_) => AdvancedPrivacySettingsPage(
|
||||
getIt.get<AdvancedPrivacySettingsViewModel>(param1: type),
|
||||
getIt.get<NodeCreateOrEditViewModel>(param1: type, param2: false),
|
||||
));
|
||||
getIt.get<AdvancedPrivacySettingsViewModel>(param1: type),
|
||||
getIt.get<NodeCreateOrEditViewModel>(param1: type, param2: false),
|
||||
getIt.get<SeedTypeViewModel>()));
|
||||
|
||||
case Routes.anonPayInvoicePage:
|
||||
final args = settings.arguments as List;
|
||||
|
||||
@@ -18,7 +18,6 @@ class Routes {
|
||||
static const disclaimer = '/disclaimer';
|
||||
static const readDisclaimer = '/read_disclaimer';
|
||||
static const changeRep = '/change_representative';
|
||||
static const seedLanguage = '/seed_language';
|
||||
static const walletList = '/view_model.wallet_list';
|
||||
static const auth = '/auth';
|
||||
static const newNode = '/new_node_list';
|
||||
|
||||
@@ -1,18 +1,26 @@
|
||||
import 'package:cake_wallet/buy/dfx/dfx_buy_provider.dart';
|
||||
import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart';
|
||||
import 'package:cake_wallet/buy/robinhood/robinhood_buy_provider.dart';
|
||||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/entities/buy_provider_types.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.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/transaction_trade_theme.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class BuyOptionsPage extends BasePage {
|
||||
BuyOptionsPage(this.dashboardViewModel);
|
||||
|
||||
final DashboardViewModel dashboardViewModel;
|
||||
final iconDarkRobinhood = 'assets/images/robinhood_dark.png';
|
||||
final iconLightRobinhood = 'assets/images/robinhood_light.png';
|
||||
final iconDarkOnramper = 'assets/images/onramper_dark.png';
|
||||
final iconLightOnramper = 'assets/images/onramper_light.png';
|
||||
final iconDarkDFX = 'assets/images/dfx_dark.png';
|
||||
final iconLightDFX = 'assets/images/dfx_light.png';
|
||||
|
||||
@override
|
||||
String get title => S.current.buy;
|
||||
@@ -22,11 +30,19 @@ class BuyOptionsPage extends BasePage {
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
final isLightMode = Theme.of(context).extension<OptionTileTheme>()?.useDarkImage ?? false;
|
||||
final iconRobinhood =
|
||||
Image.asset(isLightMode ? iconLightRobinhood : iconDarkRobinhood, height: 40, width: 40);
|
||||
final iconOnramper =
|
||||
Image.asset(isLightMode ? iconLightOnramper : iconDarkOnramper, height: 40, width: 40);
|
||||
final isLightMode =
|
||||
Theme.of(context).extension<OptionTileTheme>()?.useDarkImage ?? false;
|
||||
final iconRobinhood = Image.asset(
|
||||
isLightMode ? iconLightRobinhood : iconDarkRobinhood,
|
||||
height: 40,
|
||||
width: 40);
|
||||
final iconOnramper = Image.asset(
|
||||
isLightMode ? iconLightOnramper : iconDarkOnramper,
|
||||
height: 40,
|
||||
width: 40);
|
||||
final iconDFX = Image.asset(isLightMode ? iconLightDFX : iconDarkDFX,
|
||||
height: 40, width: 40);
|
||||
final availableProviders = dashboardViewModel.availableProviders;
|
||||
|
||||
return Container(
|
||||
child: Center(
|
||||
@@ -34,26 +50,42 @@ class BuyOptionsPage extends BasePage {
|
||||
constraints: BoxConstraints(maxWidth: 330),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: OptionTile(
|
||||
image: iconOnramper,
|
||||
title: "Onramper",
|
||||
description: S.of(context).onramper_option_description,
|
||||
onPressed: () async =>
|
||||
await getIt.get<OnRamperBuyProvider>().launchProvider(context),
|
||||
if (availableProviders.contains(BuyProviderType.Onramper))
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: OptionTile(
|
||||
image: iconOnramper,
|
||||
title: "Onramper",
|
||||
description: S.of(context).onramper_option_description,
|
||||
onPressed: () async => await getIt
|
||||
.get<OnRamperBuyProvider>()
|
||||
.launchProvider(context),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: OptionTile(
|
||||
image: iconRobinhood,
|
||||
title: "Robinhood Connect",
|
||||
description: S.of(context).robinhood_option_description,
|
||||
onPressed: () async =>
|
||||
await getIt.get<RobinhoodBuyProvider>().launchProvider(context),
|
||||
if (availableProviders.contains(BuyProviderType.Robinhood))
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: OptionTile(
|
||||
image: iconRobinhood,
|
||||
title: "Robinhood Connect",
|
||||
description: S.of(context).robinhood_option_description,
|
||||
onPressed: () async => await getIt
|
||||
.get<RobinhoodBuyProvider>()
|
||||
.launchProvider(context),
|
||||
),
|
||||
),
|
||||
if (availableProviders.contains(BuyProviderType.DFX))
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: OptionTile(
|
||||
image: iconDFX,
|
||||
title: "DFX Connect",
|
||||
description: S.of(context).dfx_option_description,
|
||||
onPressed: () async => await getIt
|
||||
.get<DFXBuyProvider>()
|
||||
.launchProvider(context),
|
||||
),
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(24, 24, 24, 32),
|
||||
@@ -63,7 +95,9 @@ class BuyOptionsPage extends BasePage {
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor,
|
||||
color: Theme.of(context)
|
||||
.extension<TransactionTradeTheme>()!
|
||||
.detailsTitlesColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -191,7 +191,10 @@ class _DashboardPageView extends BasePage {
|
||||
radius: 6.0,
|
||||
dotWidth: 6.0,
|
||||
dotHeight: 6.0,
|
||||
dotColor: Theme.of(context).indicatorColor,
|
||||
dotColor: Theme.of(context)
|
||||
.extension<DashboardPageTheme>()!
|
||||
.indicatorDotTheme
|
||||
.indicatorColor,
|
||||
activeDotColor: Theme.of(context)
|
||||
.extension<DashboardPageTheme>()!
|
||||
.indicatorDotTheme
|
||||
|
||||
@@ -33,6 +33,7 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
|
||||
final litecoinIcon = Image.asset('assets/images/litecoin_icon.png', height: 24, width: 24);
|
||||
final havenIcon = Image.asset('assets/images/haven_logo.png', height: 24, width: 24);
|
||||
final ethereumIcon = Image.asset('assets/images/eth_icon.png', height: 24, width: 24);
|
||||
final polygonIcon = Image.asset('assets/images/matic_icon.png', height: 24, width: 24);
|
||||
final bitcoinCashIcon = Image.asset('assets/images/bch_icon.png', height: 24, width: 24);
|
||||
final nanoIcon = Image.asset('assets/images/nano_icon.png', height: 24, width: 24);
|
||||
final bananoIcon = Image.asset('assets/images/nano_icon.png', height: 24, width: 24);
|
||||
@@ -150,6 +151,8 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
|
||||
return nanoIcon;
|
||||
case WalletType.banano:
|
||||
return bananoIcon;
|
||||
case WalletType.polygon:
|
||||
return polygonIcon;
|
||||
default:
|
||||
return nonWalletTypeIcon;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:auto_size_text/auto_size_text.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/pages/nft_listing_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/home_screen_account_widget.dart';
|
||||
@@ -13,7 +14,6 @@ import 'package:cake_wallet/utils/feature_flag.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/nft_view_model.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
|
||||
@@ -32,12 +32,12 @@ class BalancePage extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return Observer(
|
||||
builder: (context) {
|
||||
final isEthereumWallet = dashboardViewModel.type == WalletType.ethereum;
|
||||
final isEVMCompatible = isEVMCompatibleChain(dashboardViewModel.type);
|
||||
return DefaultTabController(
|
||||
length: isEthereumWallet ? 2 : 1,
|
||||
length: isEVMCompatible ? 2 : 1,
|
||||
child: Column(
|
||||
children: [
|
||||
if (isEthereumWallet)
|
||||
if (isEVMCompatible)
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Padding(
|
||||
@@ -66,7 +66,7 @@ class BalancePage extends StatelessWidget {
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
children: [
|
||||
CryptoBalanceWidget(dashboardViewModel: dashboardViewModel),
|
||||
if (isEthereumWallet) NFTListingPage(nftViewModel: nftViewModel)
|
||||
if (isEVMCompatible) NFTListingPage(nftViewModel: nftViewModel)
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -32,7 +32,8 @@ class MenuWidgetState extends State<MenuWidget> {
|
||||
this.ethereumIcon = Image.asset('assets/images/eth_icon.png'),
|
||||
this.nanoIcon = Image.asset('assets/images/nano_icon.png'),
|
||||
this.bananoIcon = Image.asset('assets/images/nano_icon.png'),
|
||||
this.bitcoinCashIcon = Image.asset('assets/images/bch_icon.png');
|
||||
this.bitcoinCashIcon = Image.asset('assets/images/bch_icon.png'),
|
||||
this.polygonIcon = Image.asset('assets/images/matic_icon.png');
|
||||
|
||||
|
||||
final largeScreen = 731;
|
||||
@@ -54,6 +55,8 @@ class MenuWidgetState extends State<MenuWidget> {
|
||||
Image bitcoinCashIcon;
|
||||
Image nanoIcon;
|
||||
Image bananoIcon;
|
||||
Image polygonIcon;
|
||||
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -219,6 +222,8 @@ class MenuWidgetState extends State<MenuWidget> {
|
||||
return nanoIcon;
|
||||
case WalletType.banano:
|
||||
return bananoIcon;
|
||||
case WalletType.polygon:
|
||||
return polygonIcon;
|
||||
default:
|
||||
throw Exception('No icon for ${type.toString()}');
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/fiat_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/seed_phrase_length.dart';
|
||||
import 'package:cake_wallet/entities/seed_type.dart';
|
||||
import 'package:cake_wallet/src/screens/nodes/widgets/node_form.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_choices_cell.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart';
|
||||
@@ -8,6 +9,7 @@ import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.
|
||||
import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart';
|
||||
import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/seed_type_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/settings/choices_list_item.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -17,25 +19,30 @@ import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
||||
|
||||
class AdvancedPrivacySettingsPage extends BasePage {
|
||||
AdvancedPrivacySettingsPage(this.advancedPrivacySettingsViewModel, this.nodeViewModel);
|
||||
AdvancedPrivacySettingsPage(
|
||||
this.advancedPrivacySettingsViewModel, this.nodeViewModel, this.seedTypeViewModel);
|
||||
|
||||
final AdvancedPrivacySettingsViewModel advancedPrivacySettingsViewModel;
|
||||
final NodeCreateOrEditViewModel nodeViewModel;
|
||||
final SeedTypeViewModel seedTypeViewModel;
|
||||
|
||||
@override
|
||||
String get title => S.current.privacy_settings;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) =>
|
||||
AdvancedPrivacySettingsBody(advancedPrivacySettingsViewModel, nodeViewModel);
|
||||
Widget body(BuildContext context) => AdvancedPrivacySettingsBody(
|
||||
advancedPrivacySettingsViewModel, nodeViewModel, seedTypeViewModel);
|
||||
}
|
||||
|
||||
class AdvancedPrivacySettingsBody extends StatefulWidget {
|
||||
const AdvancedPrivacySettingsBody(this.privacySettingsViewModel, this.nodeViewModel, {Key? key})
|
||||
const AdvancedPrivacySettingsBody(
|
||||
this.privacySettingsViewModel, this.nodeViewModel, this.seedTypeViewModel,
|
||||
{Key? key})
|
||||
: super(key: key);
|
||||
|
||||
final AdvancedPrivacySettingsViewModel privacySettingsViewModel;
|
||||
final NodeCreateOrEditViewModel nodeViewModel;
|
||||
final SeedTypeViewModel seedTypeViewModel;
|
||||
|
||||
@override
|
||||
_AdvancedPrivacySettingsBodyState createState() => _AdvancedPrivacySettingsBodyState();
|
||||
@@ -58,7 +65,7 @@ class _AdvancedPrivacySettingsBodyState extends State<AdvancedPrivacySettingsBod
|
||||
Observer(builder: (_) {
|
||||
return SettingsChoicesCell(
|
||||
ChoicesListItem<FiatApiMode>(
|
||||
title: S.current.disable_fiat,
|
||||
title: S.current.fiat_api,
|
||||
items: FiatApiMode.all,
|
||||
selectedItem: widget.privacySettingsViewModel.fiatApiMode,
|
||||
onItemSelected: (FiatApiMode mode) =>
|
||||
@@ -97,16 +104,27 @@ class _AdvancedPrivacySettingsBodyState extends State<AdvancedPrivacySettingsBod
|
||||
);
|
||||
}),
|
||||
if (widget.privacySettingsViewModel.hasSeedPhraseLengthOption)
|
||||
Observer(builder: (_) {
|
||||
return SettingsPickerCell<SeedPhraseLength>(
|
||||
title: S.current.seed_phrase_length,
|
||||
items: SeedPhraseLength.values,
|
||||
selectedItem: widget.privacySettingsViewModel.seedPhraseLength,
|
||||
onItemSelected: (SeedPhraseLength length) {
|
||||
widget.privacySettingsViewModel.setSeedPhraseLength(length);
|
||||
},
|
||||
);
|
||||
}),
|
||||
Observer(builder: (_) {
|
||||
return SettingsPickerCell<SeedPhraseLength>(
|
||||
title: S.current.seed_phrase_length,
|
||||
items: SeedPhraseLength.values,
|
||||
selectedItem: widget.privacySettingsViewModel.seedPhraseLength,
|
||||
onItemSelected: (SeedPhraseLength length) {
|
||||
widget.privacySettingsViewModel.setSeedPhraseLength(length);
|
||||
},
|
||||
);
|
||||
}),
|
||||
if (widget.privacySettingsViewModel.hasSeedTypeOption)
|
||||
Observer(builder: (_) {
|
||||
return SettingsChoicesCell(
|
||||
ChoicesListItem<SeedType>(
|
||||
title: S.current.seedtype,
|
||||
items: SeedType.all,
|
||||
selectedItem: widget.seedTypeViewModel.moneroSeedType,
|
||||
onItemSelected: widget.seedTypeViewModel.setMoneroSeedType,
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
bottomSectionPadding: EdgeInsets.all(24),
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import 'package:cake_wallet/entities/generate_name.dart';
|
||||
import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart';
|
||||
import 'package:cake_wallet/src/widgets/picker.dart';
|
||||
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
|
||||
import 'package:cake_wallet/main.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/seed_type_view_model.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -14,17 +17,19 @@ import 'package:cake_wallet/src/widgets/seed_language_selector.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
||||
import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_picker.dart';
|
||||
import 'package:cake_wallet/src/widgets/seed_language_picker.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||
import 'package:cake_wallet/core/execution_state.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_new_vm.dart';
|
||||
import 'package:cake_wallet/themes/extensions/new_wallet_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
|
||||
import 'package:cake_wallet/entities/seed_type.dart';
|
||||
|
||||
class NewWalletPage extends BasePage {
|
||||
NewWalletPage(this._walletNewVM);
|
||||
NewWalletPage(this._walletNewVM, this._seedTypeViewModel);
|
||||
|
||||
final WalletNewVM _walletNewVM;
|
||||
final SeedTypeViewModel _seedTypeViewModel;
|
||||
|
||||
final walletNameImage = Image.asset('assets/images/wallet_name.png');
|
||||
|
||||
@@ -35,14 +40,15 @@ class NewWalletPage extends BasePage {
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) => WalletNameForm(
|
||||
_walletNewVM, currentTheme.type == ThemeType.dark ? walletNameImage : walletNameLightImage);
|
||||
_walletNewVM, currentTheme.type == ThemeType.dark ? walletNameImage : walletNameLightImage, _seedTypeViewModel);
|
||||
}
|
||||
|
||||
class WalletNameForm extends StatefulWidget {
|
||||
WalletNameForm(this._walletNewVM, this.walletImage);
|
||||
WalletNameForm(this._walletNewVM, this.walletImage, this._seedTypeViewModel);
|
||||
|
||||
final WalletNewVM _walletNewVM;
|
||||
final Image walletImage;
|
||||
final SeedTypeViewModel _seedTypeViewModel;
|
||||
|
||||
@override
|
||||
_WalletNameFormState createState() => _WalletNameFormState(_walletNewVM);
|
||||
@@ -84,6 +90,8 @@ class _WalletNameFormState extends State<WalletNameForm> {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
_setSeedType(SeedType.defaultSeedType);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@@ -125,15 +133,20 @@ class _WalletNameFormState extends State<WalletNameForm> {
|
||||
hintStyle: TextStyle(
|
||||
fontSize: 18.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context).extension<NewWalletTheme>()!.hintTextColor),
|
||||
color:
|
||||
Theme.of(context).extension<NewWalletTheme>()!.hintTextColor),
|
||||
hintText: S.of(context).wallet_name,
|
||||
focusedBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(context).extension<NewWalletTheme>()!.underlineColor,
|
||||
color: Theme.of(context)
|
||||
.extension<NewWalletTheme>()!
|
||||
.underlineColor,
|
||||
width: 1.0)),
|
||||
enabledBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(context).extension<NewWalletTheme>()!.underlineColor,
|
||||
color: Theme.of(context)
|
||||
.extension<NewWalletTheme>()!
|
||||
.underlineColor,
|
||||
width: 1.0),
|
||||
),
|
||||
suffixIcon: Semantics(
|
||||
@@ -160,7 +173,9 @@ class _WalletNameFormState extends State<WalletNameForm> {
|
||||
height: 34,
|
||||
child: Image.asset(
|
||||
'assets/images/refresh_icon.png',
|
||||
color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonIconColor,
|
||||
color: Theme.of(context)
|
||||
.extension<SendPageTheme>()!
|
||||
.textFieldButtonIconColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -172,22 +187,40 @@ class _WalletNameFormState extends State<WalletNameForm> {
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
if (_walletNewVM.hasLanguageSelector) ...[
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 40),
|
||||
child: Text(
|
||||
S.of(context).seed_language_choose,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor),
|
||||
if (_walletNewVM.hasSeedType) ...[
|
||||
Observer(
|
||||
builder: (BuildContext build) => Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: SelectButton(
|
||||
text: widget._seedTypeViewModel.moneroSeedType.title,
|
||||
onTap: () async {
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (_) => Picker(
|
||||
items: SeedType.all,
|
||||
selectedAtIndex: isPolyseed ? 1 : 0,
|
||||
onItemSelected: _setSeedType,
|
||||
isSeparated: false,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
Observer(
|
||||
builder: (BuildContext build) => Padding(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: SeedLanguageSelector(
|
||||
key: _languageSelectorKey,
|
||||
initialSelected: defaultSeedLanguage,
|
||||
seedType: _walletNewVM.hasSeedType
|
||||
? widget._seedTypeViewModel.moneroSeedType
|
||||
: SeedType.legacy,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: SeedLanguageSelector(
|
||||
key: _languageSelectorKey, initialSelected: defaultSeedLanguage),
|
||||
)
|
||||
]
|
||||
],
|
||||
@@ -215,7 +248,7 @@ class _WalletNameFormState extends State<WalletNameForm> {
|
||||
Navigator.of(context)
|
||||
.pushNamed(Routes.advancedPrivacySettings, arguments: _walletNewVM.type);
|
||||
},
|
||||
child: Text(S.of(context).advanced_privacy_settings),
|
||||
child: Text(S.of(context).advanced_settings),
|
||||
),
|
||||
],
|
||||
)),
|
||||
@@ -239,8 +272,15 @@ class _WalletNameFormState extends State<WalletNameForm> {
|
||||
} else {
|
||||
_walletNewVM.create(
|
||||
options: _walletNewVM.hasLanguageSelector
|
||||
? _languageSelectorKey.currentState!.selected
|
||||
? [_languageSelectorKey.currentState!.selected, isPolyseed]
|
||||
: null);
|
||||
}
|
||||
}
|
||||
|
||||
bool get isPolyseed => widget._seedTypeViewModel.moneroSeedType == SeedType.polyseed;
|
||||
|
||||
void _setSeedType(SeedType item) {
|
||||
widget._seedTypeViewModel.setMoneroSeedType(item);
|
||||
_languageSelectorKey.currentState?.selected = defaultSeedLanguage; // Reset Seed language
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_core/currency.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
@@ -23,6 +24,13 @@ class CurrencyInputField extends StatelessWidget {
|
||||
final TextEditingController controller;
|
||||
final bool isLight;
|
||||
|
||||
String get _currencyName {
|
||||
if (selectedCurrency is CryptoCurrency) {
|
||||
return (selectedCurrency as CryptoCurrency).title.toUpperCase();
|
||||
}
|
||||
return selectedCurrency.name.toUpperCase();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final arrowBottomPurple = Image.asset(
|
||||
@@ -74,7 +82,7 @@ class CurrencyInputField extends StatelessWidget {
|
||||
child: arrowBottomPurple,
|
||||
),
|
||||
Text(
|
||||
selectedCurrency.name.toUpperCase(),
|
||||
_currencyName,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 16,
|
||||
@@ -83,7 +91,7 @@ class CurrencyInputField extends StatelessWidget {
|
||||
),
|
||||
if (selectedCurrency.tag != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 3.0),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 3.0),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor,
|
||||
|
||||
@@ -133,7 +133,7 @@ class WalletRestoreFromKeysFromState extends State<WalletRestoreFromKeysFrom> {
|
||||
widget.walletRestoreViewModel.type == WalletType.banano;
|
||||
return AddressTextField(
|
||||
controller: privateKeyController,
|
||||
placeholder: nanoBased ? S.of(context).seed_key : S.of(context).private_key,
|
||||
placeholder: nanoBased ? S.of(context).seed_hex_form : S.of(context).private_key,
|
||||
options: [AddressTextFieldOption.paste],
|
||||
buttonColor: Theme.of(context).hintColor,
|
||||
onPushPasteButton: (_) {
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
import 'package:cake_wallet/core/wallet_name_validator.dart';
|
||||
import 'package:cake_wallet/entities/generate_name.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_restore_view_model.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_picker.dart';
|
||||
import 'package:cake_wallet/src/widgets/seed_widget.dart';
|
||||
import 'package:cake_wallet/entities/seed_type.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||
import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart';
|
||||
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/core/wallet_name_validator.dart';
|
||||
import 'package:cake_wallet/src/widgets/picker.dart';
|
||||
import 'package:cake_wallet/src/widgets/seed_language_picker.dart';
|
||||
import 'package:cake_wallet/src/widgets/seed_widget.dart';
|
||||
import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/seed_type_view_model.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:polyseed/polyseed.dart';
|
||||
|
||||
class WalletRestoreFromSeedForm extends StatefulWidget {
|
||||
WalletRestoreFromSeedForm(
|
||||
@@ -19,6 +21,7 @@ class WalletRestoreFromSeedForm extends StatefulWidget {
|
||||
required this.displayLanguageSelector,
|
||||
required this.displayBlockHeightSelector,
|
||||
required this.type,
|
||||
required this.seedTypeViewModel,
|
||||
this.blockHeightFocusNode,
|
||||
this.onHeightOrDateEntered,
|
||||
this.onSeedChange,
|
||||
@@ -28,14 +31,14 @@ class WalletRestoreFromSeedForm extends StatefulWidget {
|
||||
final WalletType type;
|
||||
final bool displayLanguageSelector;
|
||||
final bool displayBlockHeightSelector;
|
||||
final SeedTypeViewModel seedTypeViewModel;
|
||||
final FocusNode? blockHeightFocusNode;
|
||||
final Function(bool)? onHeightOrDateEntered;
|
||||
final void Function(String)? onSeedChange;
|
||||
final void Function(String)? onLanguageChange;
|
||||
|
||||
@override
|
||||
WalletRestoreFromSeedFormState createState() =>
|
||||
WalletRestoreFromSeedFormState('English');
|
||||
WalletRestoreFromSeedFormState createState() => WalletRestoreFromSeedFormState('English');
|
||||
}
|
||||
|
||||
class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
|
||||
@@ -44,104 +47,189 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
|
||||
blockchainHeightKey = GlobalKey<BlockchainHeightState>(),
|
||||
formKey = GlobalKey<FormState>(),
|
||||
languageController = TextEditingController(),
|
||||
nameTextEditingController = TextEditingController();
|
||||
nameTextEditingController = TextEditingController(),
|
||||
seedTypeController = TextEditingController();
|
||||
|
||||
final GlobalKey<SeedWidgetState> seedWidgetStateKey;
|
||||
final GlobalKey<BlockchainHeightState> blockchainHeightKey;
|
||||
final TextEditingController languageController;
|
||||
final TextEditingController nameTextEditingController;
|
||||
final TextEditingController seedTypeController;
|
||||
final GlobalKey<FormState> formKey;
|
||||
late ReactionDisposer moneroSeedTypeReaction;
|
||||
String language;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_setSeedType(widget.seedTypeViewModel.moneroSeedType);
|
||||
_setLanguageLabel(language);
|
||||
moneroSeedTypeReaction =
|
||||
reaction((_) => widget.seedTypeViewModel.moneroSeedType, (SeedType item) {
|
||||
_setSeedType(item);
|
||||
_changeLanguage('English');
|
||||
});
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
moneroSeedTypeReaction();
|
||||
}
|
||||
|
||||
void onSeedChange(String seed) {
|
||||
if (widget.type == WalletType.monero && Polyseed.isValidSeed(seed)) {
|
||||
final lang = PolyseedLang.getByPhrase(seed);
|
||||
|
||||
_changeSeedType(SeedType.polyseed);
|
||||
_changeLanguage(lang.nameEnglish);
|
||||
}
|
||||
widget.onSeedChange?.call(seed);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.only(left: 24, right: 24),
|
||||
child: Column(children: [
|
||||
Form(
|
||||
key: formKey,
|
||||
child: Stack(
|
||||
alignment: Alignment.centerRight,
|
||||
children: [
|
||||
BaseTextFormField(
|
||||
controller: nameTextEditingController,
|
||||
hintText: S.of(context).wallet_name,
|
||||
suffixIcon: IconButton(
|
||||
onPressed: () async {
|
||||
final rName = await generateName();
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
key: formKey,
|
||||
child: Stack(
|
||||
alignment: Alignment.centerRight,
|
||||
children: [
|
||||
BaseTextFormField(
|
||||
controller: nameTextEditingController,
|
||||
hintText: S.of(context).wallet_name,
|
||||
suffixIcon: IconButton(
|
||||
onPressed: () async {
|
||||
final rName = await generateName();
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
|
||||
setState(() {
|
||||
nameTextEditingController.text = rName;
|
||||
nameTextEditingController.selection =
|
||||
TextSelection.fromPosition(TextPosition(
|
||||
offset: nameTextEditingController.text.length));
|
||||
});
|
||||
},
|
||||
icon: Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(6.0),
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
width: 34,
|
||||
height: 34,
|
||||
child: Image.asset(
|
||||
'assets/images/refresh_icon.png',
|
||||
color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonIconColor,
|
||||
setState(() {
|
||||
nameTextEditingController.text = rName;
|
||||
nameTextEditingController.selection = TextSelection.fromPosition(
|
||||
TextPosition(offset: nameTextEditingController.text.length));
|
||||
});
|
||||
},
|
||||
icon: Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(6.0),
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
width: 34,
|
||||
height: 34,
|
||||
child: Image.asset(
|
||||
'assets/images/refresh_icon.png',
|
||||
color: Theme.of(context)
|
||||
.extension<SendPageTheme>()!
|
||||
.textFieldButtonIconColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
validator: WalletNameValidator(),
|
||||
),
|
||||
),
|
||||
validator: WalletNameValidator(),
|
||||
),
|
||||
],
|
||||
)),
|
||||
],
|
||||
)),
|
||||
Container(height: 20),
|
||||
SeedWidget(
|
||||
key: seedWidgetStateKey,
|
||||
language: language,
|
||||
type: widget.type,
|
||||
onSeedChange: widget.onSeedChange),
|
||||
onSeedChange: onSeedChange),
|
||||
if (widget.type == WalletType.monero)
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (_) => Picker(
|
||||
items: SeedType.all,
|
||||
selectedAtIndex: isPolyseed ? 1 : 0,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
onItemSelected: _changeSeedType,
|
||||
isSeparated: false,
|
||||
));
|
||||
},
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
padding: EdgeInsets.only(top: 20.0),
|
||||
child: IgnorePointer(
|
||||
child: BaseTextFormField(
|
||||
controller: seedTypeController,
|
||||
enableInteractiveSelection: false,
|
||||
readOnly: true,
|
||||
suffixIcon: expandIcon,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.displayLanguageSelector)
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (_) => SeedLanguagePicker(
|
||||
selected: language, onItemSelected: _changeLanguage));
|
||||
selected: language,
|
||||
onItemSelected: _changeLanguage,
|
||||
seedType: isPolyseed ? SeedType.polyseed : SeedType.legacy,
|
||||
));
|
||||
},
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
padding: EdgeInsets.only(top: 20.0),
|
||||
child: IgnorePointer(
|
||||
child: BaseTextFormField(
|
||||
controller: languageController,
|
||||
enableInteractiveSelection: false,
|
||||
readOnly: true)))),
|
||||
if (widget.displayBlockHeightSelector)
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
padding: EdgeInsets.only(top: 20.0),
|
||||
child: IgnorePointer(
|
||||
child: BaseTextFormField(
|
||||
controller: languageController,
|
||||
enableInteractiveSelection: false,
|
||||
readOnly: true,
|
||||
suffixIcon: expandIcon,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (!isPolyseed && widget.displayBlockHeightSelector)
|
||||
BlockchainHeightWidget(
|
||||
focusNode: widget.blockHeightFocusNode,
|
||||
key: blockchainHeightKey,
|
||||
onHeightOrDateEntered: widget.onHeightOrDateEntered,
|
||||
hasDatePicker: widget.type == WalletType.monero)
|
||||
hasDatePicker: widget.type == WalletType.monero),
|
||||
]));
|
||||
}
|
||||
|
||||
bool get isPolyseed => widget.seedTypeViewModel.moneroSeedType == SeedType.polyseed;
|
||||
|
||||
Widget get expandIcon => Container(
|
||||
padding: EdgeInsets.all(18),
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: Image.asset(
|
||||
'assets/images/arrow_bottom_purple_icon.png',
|
||||
height: 8,
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
);
|
||||
|
||||
void _changeLanguage(String language) {
|
||||
final setLang = isPolyseed ? "POLYSEED_$language" : language;
|
||||
setState(() {
|
||||
this.language = language;
|
||||
seedWidgetStateKey.currentState!.changeSeedLanguage(language);
|
||||
_setLanguageLabel(language);
|
||||
widget.onLanguageChange?.call(language);
|
||||
this.language = setLang;
|
||||
seedWidgetStateKey.currentState!.changeSeedLanguage(setLang);
|
||||
_setLanguageLabel(setLang);
|
||||
widget.onLanguageChange?.call(setLang);
|
||||
});
|
||||
}
|
||||
|
||||
void _setLanguageLabel(String language) =>
|
||||
languageController.text = '$language (Seed language)';
|
||||
languageController.text = '${language.replaceAll("POLYSEED_", "")} (Seed language)';
|
||||
|
||||
void _changeSeedType(SeedType item) {
|
||||
_setSeedType(item);
|
||||
_changeLanguage('English');
|
||||
widget.seedTypeViewModel.setMoneroSeedType(item);
|
||||
}
|
||||
|
||||
void _setSeedType(SeedType item) {
|
||||
seedTypeController.text = item.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,34 @@
|
||||
import 'package:cake_wallet/core/execution_state.dart';
|
||||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/nano/nano.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/screens/restore/wallet_restore_from_keys_form.dart';
|
||||
import 'package:cake_wallet/src/screens/restore/wallet_restore_from_seed_form.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||
import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:cake_wallet/themes/extensions/keyboard_theme.dart';
|
||||
import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
|
||||
import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart';
|
||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/restore/restore_mode.dart';
|
||||
import 'package:cake_wallet/view_model/seed_type_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_restore_view_model.dart';
|
||||
import 'package:cw_core/nano_account_info_response.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:keyboard_actions/keyboard_actions.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:polyseed/polyseed.dart';
|
||||
import 'package:smooth_page_indicator/smooth_page_indicator.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/core/execution_state.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_restore_view_model.dart';
|
||||
import 'package:cake_wallet/src/screens/restore/wallet_restore_from_keys_form.dart';
|
||||
import 'package:cake_wallet/src/screens/restore/wallet_restore_from_seed_form.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/restore/restore_mode.dart';
|
||||
import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart';
|
||||
|
||||
class WalletRestorePage extends BasePage {
|
||||
WalletRestorePage(this.walletRestoreViewModel)
|
||||
WalletRestorePage(this.walletRestoreViewModel, this.seedTypeViewModel)
|
||||
: walletRestoreFromSeedFormKey = GlobalKey<WalletRestoreFromSeedFormState>(),
|
||||
walletRestoreFromKeysFormKey = GlobalKey<WalletRestoreFromKeysFromState>(),
|
||||
_pages = [],
|
||||
@@ -36,6 +38,7 @@ class WalletRestorePage extends BasePage {
|
||||
switch (mode) {
|
||||
case WalletRestoreMode.seed:
|
||||
_pages.add(WalletRestoreFromSeedForm(
|
||||
seedTypeViewModel: seedTypeViewModel,
|
||||
displayBlockHeightSelector:
|
||||
walletRestoreViewModel.hasBlockchainHeightLanguageSelector,
|
||||
displayLanguageSelector: walletRestoreViewModel.hasSeedLanguageSelector,
|
||||
@@ -48,27 +51,13 @@ class WalletRestorePage extends BasePage {
|
||||
}
|
||||
},
|
||||
onSeedChange: (String seed) {
|
||||
if (walletRestoreViewModel.hasBlockchainHeightLanguageSelector) {
|
||||
final hasHeight = walletRestoreFromSeedFormKey.currentState!.blockchainHeightKey
|
||||
.currentState!.restoreHeightController.text.isNotEmpty;
|
||||
if (hasHeight) {
|
||||
walletRestoreViewModel.isButtonEnabled = _isValidSeed();
|
||||
}
|
||||
} else {
|
||||
walletRestoreViewModel.isButtonEnabled = _isValidSeed();
|
||||
}
|
||||
final isPolyseed =
|
||||
walletRestoreViewModel.type == WalletType.monero && Polyseed.isValidSeed(seed);
|
||||
_validateOnChange(isPolyseed: isPolyseed);
|
||||
},
|
||||
onLanguageChange: (_) {
|
||||
if (walletRestoreViewModel.hasBlockchainHeightLanguageSelector) {
|
||||
final hasHeight = walletRestoreFromSeedFormKey.currentState!.blockchainHeightKey
|
||||
.currentState!.restoreHeightController.text.isNotEmpty;
|
||||
|
||||
if (hasHeight) {
|
||||
walletRestoreViewModel.isButtonEnabled = _isValidSeed();
|
||||
}
|
||||
} else {
|
||||
walletRestoreViewModel.isButtonEnabled = _isValidSeed();
|
||||
}
|
||||
onLanguageChange: (String language) {
|
||||
final isPolyseed = language.startsWith("POLYSEED_");
|
||||
_validateOnChange(isPolyseed: isPolyseed);
|
||||
}));
|
||||
break;
|
||||
case WalletRestoreMode.keys:
|
||||
@@ -104,6 +93,7 @@ class WalletRestorePage extends BasePage {
|
||||
));
|
||||
|
||||
final WalletRestoreViewModel walletRestoreViewModel;
|
||||
final SeedTypeViewModel seedTypeViewModel;
|
||||
final PageController _controller;
|
||||
final List<Widget> _pages;
|
||||
final GlobalKey<WalletRestoreFromSeedFormState> walletRestoreFromSeedFormKey;
|
||||
@@ -163,7 +153,8 @@ class WalletRestorePage extends BasePage {
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
child: Center(
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint),
|
||||
constraints:
|
||||
BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
@@ -219,10 +210,10 @@ class WalletRestorePage extends BasePage {
|
||||
const SizedBox(height: 25),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.of(context)
|
||||
.pushNamed(Routes.advancedPrivacySettings, arguments: walletRestoreViewModel.type);
|
||||
Navigator.of(context).pushNamed(Routes.advancedPrivacySettings,
|
||||
arguments: walletRestoreViewModel.type);
|
||||
},
|
||||
child: Text(S.of(context).advanced_privacy_settings),
|
||||
child: Text(S.of(context).advanced_settings),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -235,9 +226,26 @@ class WalletRestorePage extends BasePage {
|
||||
);
|
||||
}
|
||||
|
||||
void _validateOnChange({bool isPolyseed = false}) {
|
||||
if (!isPolyseed && walletRestoreViewModel.hasBlockchainHeightLanguageSelector) {
|
||||
final hasHeight = walletRestoreFromSeedFormKey
|
||||
.currentState?.blockchainHeightKey.currentState?.restoreHeightController.text.isNotEmpty;
|
||||
|
||||
if (hasHeight == true) {
|
||||
walletRestoreViewModel.isButtonEnabled = _isValidSeed();
|
||||
}
|
||||
} else {
|
||||
walletRestoreViewModel.isButtonEnabled = _isValidSeed();
|
||||
}
|
||||
}
|
||||
|
||||
bool _isValidSeed() {
|
||||
final seedWords =
|
||||
walletRestoreFromSeedFormKey.currentState!.seedWidgetStateKey.currentState!.text.split(' ');
|
||||
final seedPhrase =
|
||||
walletRestoreFromSeedFormKey.currentState!.seedWidgetStateKey.currentState!.text;
|
||||
if (walletRestoreViewModel.type == WalletType.monero && Polyseed.isValidSeed(seedPhrase))
|
||||
return true;
|
||||
|
||||
final seedWords = seedPhrase.split(' ');
|
||||
|
||||
if ((walletRestoreViewModel.type == WalletType.monero ||
|
||||
walletRestoreViewModel.type == WalletType.haven) &&
|
||||
@@ -282,7 +290,8 @@ class WalletRestorePage extends BasePage {
|
||||
|
||||
if (walletRestoreViewModel.hasBlockchainHeightLanguageSelector) {
|
||||
credentials['height'] =
|
||||
walletRestoreFromSeedFormKey.currentState!.blockchainHeightKey.currentState!.height;
|
||||
walletRestoreFromSeedFormKey.currentState!.blockchainHeightKey.currentState?.height ??
|
||||
-1;
|
||||
}
|
||||
|
||||
credentials['name'] =
|
||||
|
||||
@@ -2,9 +2,9 @@ import 'dart:async';
|
||||
import 'package:cake_wallet/core/auth_service.dart';
|
||||
import 'package:cake_wallet/core/totp_request_details.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||
import 'package:cake_wallet/utils/device_info.dart';
|
||||
import 'package:cake_wallet/utils/payment_request.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/auth/auth_page.dart';
|
||||
@@ -169,7 +169,7 @@ class RootState extends State<Root> with WidgetsBindingObserver {
|
||||
);
|
||||
launchUri = null;
|
||||
} else if (isWalletConnectLink) {
|
||||
if (widget.appStore.wallet!.type == WalletType.ethereum) {
|
||||
if (isEVMCompatibleChain(widget.appStore.wallet!.type)) {
|
||||
widget.navigatorKey.currentState?.pushNamed(
|
||||
Routes.walletConnectConnectionsListing,
|
||||
arguments: launchUri,
|
||||
@@ -179,7 +179,7 @@ class RootState extends State<Root> with WidgetsBindingObserver {
|
||||
_nonETHWalletErrorToast(S.current.switchToETHWallet);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
launchUri = null;
|
||||
return WillPopScope(
|
||||
onWillPop: () async => false,
|
||||
@@ -205,7 +205,7 @@ class RootState extends State<Root> with WidgetsBindingObserver {
|
||||
|
||||
String? _getRouteToGo() {
|
||||
if (isWalletConnectLink) {
|
||||
if (widget.appStore.wallet!.type != WalletType.ethereum) {
|
||||
if (isEVMCompatibleChain(widget.appStore.wallet!.type)) {
|
||||
_nonETHWalletErrorToast(S.current.switchToETHWallet);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
|
||||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:cake_wallet/src/widgets/seed_language_selector.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
||||
import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_picker.dart';
|
||||
|
||||
class SeedLanguage extends BasePage {
|
||||
SeedLanguage({required this.onConfirm});
|
||||
|
||||
final Function(BuildContext, String) onConfirm;
|
||||
|
||||
final walletNameImage = Image.asset('assets/images/wallet_name.png');
|
||||
final walletNameLightImage =
|
||||
Image.asset('assets/images/wallet_name_light.png');
|
||||
|
||||
@override
|
||||
String get title => S.current.wallet_list_restore_wallet;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) =>
|
||||
SeedLanguageForm(
|
||||
onConfirm: onConfirm,
|
||||
walletImage: currentTheme.type == ThemeType.dark
|
||||
? walletNameImage : walletNameLightImage);
|
||||
}
|
||||
|
||||
class SeedLanguageForm extends StatefulWidget {
|
||||
SeedLanguageForm({required this.onConfirm, required this.walletImage});
|
||||
|
||||
final Function(BuildContext, String) onConfirm;
|
||||
final Image walletImage;
|
||||
|
||||
@override
|
||||
SeedLanguageFormState createState() => SeedLanguageFormState();
|
||||
}
|
||||
|
||||
class SeedLanguageFormState extends State<SeedLanguageForm> {
|
||||
static const aspectRatioImage = 1.22;
|
||||
final _languageSelectorKey = GlobalKey<SeedLanguageSelectorState>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: ScrollableWithBottomSection(
|
||||
contentPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
|
||||
content:
|
||||
Column(crossAxisAlignment: CrossAxisAlignment.center, children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 12, right: 12),
|
||||
child: AspectRatio(
|
||||
aspectRatio: aspectRatioImage,
|
||||
child: FittedBox(child: widget.walletImage,
|
||||
fit: BoxFit.fill)),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 40),
|
||||
child: Text(
|
||||
S.of(context).seed_language_choose,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
color:
|
||||
Theme.of(context).extension<CakeTextTheme>()!.titleColor),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: SeedLanguageSelector(
|
||||
key: _languageSelectorKey,
|
||||
initialSelected: defaultSeedLanguage),
|
||||
)
|
||||
]),
|
||||
bottomSectionPadding:
|
||||
EdgeInsets.only(left: 24, right: 24, bottom: 24),
|
||||
bottomSection: Observer(
|
||||
builder: (context) {
|
||||
return PrimaryButton(
|
||||
onPressed: () => widget.onConfirm(
|
||||
context, _languageSelectorKey.currentState!.selected),
|
||||
text: S.of(context).seed_language_next,
|
||||
color: Colors.green,
|
||||
textColor: Colors.white);
|
||||
},
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/src/widgets/picker.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
|
||||
List<Image> flagImages = [
|
||||
Image.asset('assets/images/flags/usa.png'),
|
||||
Image.asset('assets/images/flags/chn.png'),
|
||||
Image.asset('assets/images/flags/nld.png'),
|
||||
Image.asset('assets/images/flags/deu.png'),
|
||||
Image.asset('assets/images/flags/jpn.png'),
|
||||
Image.asset('assets/images/flags/prt.png'),
|
||||
Image.asset('assets/images/flags/rus.png'),
|
||||
Image.asset('assets/images/flags/esp.png'),
|
||||
Image.asset('assets/images/flags/fra.png'),
|
||||
Image.asset('assets/images/flags/ita.png'),
|
||||
];
|
||||
|
||||
const List<String> languageCodes = [
|
||||
'Eng',
|
||||
'Chi',
|
||||
'Ned',
|
||||
'Ger',
|
||||
'Jap',
|
||||
'Por',
|
||||
'Rus',
|
||||
'Esp',
|
||||
'Fre',
|
||||
'Ita',
|
||||
];
|
||||
|
||||
const defaultSeedLanguage = 'English';
|
||||
|
||||
const List<String> seedLanguages = [
|
||||
defaultSeedLanguage,
|
||||
'Chinese (simplified)',
|
||||
'Dutch',
|
||||
'German',
|
||||
'Japanese',
|
||||
'Portuguese',
|
||||
'Russian',
|
||||
'Spanish',
|
||||
'French',
|
||||
'Italian',
|
||||
];
|
||||
|
||||
enum Places { topLeft, topRight, bottomLeft, bottomRight, inside }
|
||||
|
||||
class SeedLanguagePicker extends StatefulWidget {
|
||||
SeedLanguagePicker({Key? key, this.selected = defaultSeedLanguage, required this.onItemSelected})
|
||||
: super(key: key);
|
||||
|
||||
final String selected;
|
||||
final Function(String) onItemSelected;
|
||||
|
||||
@override
|
||||
SeedLanguagePickerState createState() =>
|
||||
SeedLanguagePickerState(selected: selected, onItemSelected: onItemSelected);
|
||||
}
|
||||
|
||||
class SeedLanguagePickerState extends State<SeedLanguagePicker> {
|
||||
SeedLanguagePickerState({required this.selected, required this.onItemSelected});
|
||||
|
||||
final String selected;
|
||||
final Function(String) onItemSelected;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Picker(
|
||||
selectedAtIndex: seedLanguages.indexOf(selected),
|
||||
items: seedLanguages,
|
||||
images: flagImages,
|
||||
isGridView: true,
|
||||
title: S.of(context).seed_choose,
|
||||
hintText: S.of(context).seed_choose,
|
||||
matchingCriteria: (String language, String searchText) {
|
||||
return language.toLowerCase().contains(searchText);
|
||||
},
|
||||
onItemSelected: onItemSelected,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart';
|
||||
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart';
|
||||
@@ -8,7 +9,6 @@ import 'package:cake_wallet/utils/feature_flag.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/settings/sync_mode.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
@@ -85,7 +85,7 @@ class ConnectionSyncPage extends BasePage {
|
||||
);
|
||||
},
|
||||
),
|
||||
if (dashboardViewModel.wallet.type == WalletType.ethereum) ...[
|
||||
if (isEVMCompatibleChain(dashboardViewModel.wallet.type)) ...[
|
||||
WalletConnectTile(
|
||||
onTap: () => Navigator.of(context).pushNamed(Routes.walletConnectConnectionsListing),
|
||||
),
|
||||
@@ -101,6 +101,7 @@ class ConnectionSyncPage extends BasePage {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Future<void> _presentReconnectAlert(BuildContext context) async {
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import 'package:cake_wallet/buy/buy_provider.dart';
|
||||
import 'package:cake_wallet/entities/buy_provider_types.dart';
|
||||
import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
@@ -42,9 +40,10 @@ class OtherSettingsPage extends BasePage {
|
||||
handler: (BuildContext context) =>
|
||||
Navigator.of(context).pushNamed(Routes.changeRep),
|
||||
),
|
||||
if(_otherSettingsViewModel.isEnabledBuyAction)
|
||||
SettingsPickerCell(
|
||||
title: S.current.default_buy_provider,
|
||||
items: BuyProviderType.values,
|
||||
items: _otherSettingsViewModel.availableBuyProviders,
|
||||
displayItem: _otherSettingsViewModel.getBuyProviderType,
|
||||
selectedItem: _otherSettingsViewModel.buyProviderType,
|
||||
onItemSelected: _otherSettingsViewModel.onBuyProviderTypeSelected,
|
||||
|
||||
@@ -87,6 +87,14 @@ class PrivacyPage extends BasePage {
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setUseEtherscan(value);
|
||||
}),
|
||||
if (_privacySettingsViewModel.canUsePolygonScan)
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.polygonscan_history,
|
||||
value: _privacySettingsViewModel.usePolygonScan,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setUsePolygonScan(value);
|
||||
},
|
||||
),
|
||||
SettingsCellWithArrow(
|
||||
title: S.current.domain_looks_up,
|
||||
handler: (context) => Navigator.of(context).pushNamed(Routes.domainLookupsPage),
|
||||
|
||||
@@ -4,7 +4,7 @@ import 'dart:io';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tor/tor.dart';
|
||||
// import 'package:tor/tor.dart';
|
||||
|
||||
class TorPage extends BasePage {
|
||||
final AppStore appStore;
|
||||
@@ -40,44 +40,44 @@ class _TorPageBodyState extends State<TorPageBody> {
|
||||
connecting = true; // Update flag
|
||||
});
|
||||
|
||||
await Tor.init();
|
||||
|
||||
// Start the proxy
|
||||
await Tor.instance.start();
|
||||
|
||||
// Toggle started flag.
|
||||
setState(() {
|
||||
torEnabled = Tor.instance.enabled; // Update flag
|
||||
connecting = false;
|
||||
});
|
||||
|
||||
final node = widget.appStore.settingsStore.getCurrentNode(widget.appStore.wallet!.type);
|
||||
if (node.socksProxyAddress?.isEmpty ?? true) {
|
||||
node.socksProxyAddress = "${InternetAddress.loopbackIPv4.address}:${Tor.instance.port}";
|
||||
}
|
||||
widget.appStore.wallet!.connectToNode(node: node);
|
||||
// await Tor.init();
|
||||
//
|
||||
// // Start the proxy
|
||||
// await Tor.instance.start();
|
||||
//
|
||||
// // Toggle started flag.
|
||||
// setState(() {
|
||||
// torEnabled = Tor.instance.enabled; // Update flag
|
||||
// connecting = false;
|
||||
// });
|
||||
//
|
||||
// final node = widget.appStore.settingsStore.getCurrentNode(widget.appStore.wallet!.type);
|
||||
// if (node.socksProxyAddress?.isEmpty ?? true) {
|
||||
// node.socksProxyAddress = "${InternetAddress.loopbackIPv4.address}:${Tor.instance.port}";
|
||||
// }
|
||||
// widget.appStore.wallet!.connectToNode(node: node);
|
||||
|
||||
print('Done awaiting; tor should be running');
|
||||
}
|
||||
|
||||
Future<void> endTor() async {
|
||||
// Start the proxy
|
||||
Tor.instance.disable();
|
||||
|
||||
// Toggle started flag.
|
||||
setState(() {
|
||||
torEnabled = Tor.instance.enabled; // Update flag
|
||||
});
|
||||
|
||||
print('Done awaiting; tor should be stopped');
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
torEnabled = Tor.instance.enabled;
|
||||
// // Start the proxy
|
||||
// Tor.instance.disable();
|
||||
//
|
||||
// // Toggle started flag.
|
||||
// setState(() {
|
||||
// torEnabled = Tor.instance.enabled; // Update flag
|
||||
// });
|
||||
//
|
||||
// print('Done awaiting; tor should be stopped');
|
||||
}
|
||||
//
|
||||
// @override
|
||||
// void initState() {
|
||||
// super.initState();
|
||||
//
|
||||
// torEnabled = Tor.instance.enabled;
|
||||
// }
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
|
||||
@@ -57,6 +57,8 @@ class ChatwootWidgetState extends State<ChatwootWidget> {
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<void> storeCookie(String value) async =>
|
||||
await widget.secureStorage.write(key: COOKIE_KEY, value: value);
|
||||
Future<void> storeCookie(String value) async {
|
||||
await widget.secureStorage.delete(key: COOKIE_KEY);
|
||||
await widget.secureStorage.write(key: COOKIE_KEY, value: value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@ class WalletConnectConnectionsView extends StatelessWidget {
|
||||
|
||||
final actualLinkList = launchUri.query.split("uri=");
|
||||
|
||||
if (actualLinkList.length <= 1) return;
|
||||
|
||||
final query = actualLinkList[1];
|
||||
|
||||
final uri = Uri.decodeComponent(query);
|
||||
|
||||
@@ -14,12 +14,14 @@ import 'connection_widget.dart';
|
||||
class ConnectionRequestWidget extends StatefulWidget {
|
||||
const ConnectionRequestWidget({
|
||||
required this.wallet,
|
||||
required this.chaindIdNamespace,
|
||||
this.authRequest,
|
||||
this.sessionProposal,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
final Web3Wallet wallet;
|
||||
final String chaindIdNamespace;
|
||||
final AuthRequestModel? authRequest;
|
||||
final SessionRequestModel? sessionProposal;
|
||||
|
||||
@@ -52,23 +54,26 @@ class _ConnectionRequestWidgetState extends State<ConnectionRequestWidget> {
|
||||
|
||||
return _ConnectionMetadataDisplayWidget(
|
||||
metadata: metadata,
|
||||
wallet: widget.wallet,
|
||||
authRequest: widget.authRequest,
|
||||
sessionProposal: widget.sessionProposal,
|
||||
wallet: widget.wallet,
|
||||
chaindIdNamespace: widget.chaindIdNamespace,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ConnectionMetadataDisplayWidget extends StatelessWidget {
|
||||
const _ConnectionMetadataDisplayWidget({
|
||||
required this.metadata,
|
||||
required this.wallet,
|
||||
this.authRequest,
|
||||
required this.metadata,
|
||||
required this.sessionProposal,
|
||||
required this.chaindIdNamespace,
|
||||
this.authRequest,
|
||||
});
|
||||
|
||||
final ConnectionMetadata? metadata;
|
||||
final Web3Wallet wallet;
|
||||
final String chaindIdNamespace;
|
||||
final AuthRequestModel? authRequest;
|
||||
final SessionRequestModel? sessionProposal;
|
||||
|
||||
@@ -114,7 +119,11 @@ class _ConnectionMetadataDisplayWidget extends StatelessWidget {
|
||||
const SizedBox(height: 8),
|
||||
Visibility(
|
||||
visible: authRequest != null,
|
||||
child: _AuthRequestWidget(wallet: wallet, authRequest: authRequest),
|
||||
child: _AuthRequestWidget(
|
||||
wallet: wallet,
|
||||
authRequest: authRequest,
|
||||
chaindIdNamespace: chaindIdNamespace,
|
||||
),
|
||||
|
||||
//If authRequest is null, sessionProposal is not null.
|
||||
replacement: _SessionProposalWidget(sessionProposal: sessionProposal!),
|
||||
@@ -126,16 +135,21 @@ class _ConnectionMetadataDisplayWidget extends StatelessWidget {
|
||||
}
|
||||
|
||||
class _AuthRequestWidget extends StatelessWidget {
|
||||
const _AuthRequestWidget({required this.wallet, this.authRequest});
|
||||
const _AuthRequestWidget({
|
||||
required this.wallet,
|
||||
required this.chaindIdNamespace,
|
||||
this.authRequest,
|
||||
});
|
||||
|
||||
final Web3Wallet wallet;
|
||||
final String chaindIdNamespace;
|
||||
final AuthRequestModel? authRequest;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final model = ConnectionModel(
|
||||
text: wallet.formatAuthMessage(
|
||||
iss: 'did:pkh:eip155:1:${authRequest!.iss}',
|
||||
iss: 'did:pkh:$chaindIdNamespace:${authRequest!.iss}',
|
||||
cacaoPayload: CacaoRequestPayload.fromPayloadParams(
|
||||
authRequest!.request.payloadParams,
|
||||
),
|
||||
|
||||
@@ -49,6 +49,7 @@ class WalletListBodyState extends State<WalletListBody> {
|
||||
final ethereumIcon = Image.asset('assets/images/eth_icon.png', height: 24, width: 24);
|
||||
final bitcoinCashIcon = Image.asset('assets/images/bch_icon.png', height: 24, width: 24);
|
||||
final nanoIcon = Image.asset('assets/images/nano_icon.png', height: 24, width: 24);
|
||||
final polygonIcon = Image.asset('assets/images/matic_icon.png', height: 24, width: 24);
|
||||
final scrollController = ScrollController();
|
||||
final double tileHeight = 60;
|
||||
Flushbar<void>? _progressBar;
|
||||
@@ -256,6 +257,8 @@ class WalletListBodyState extends State<WalletListBody> {
|
||||
return bitcoinCashIcon;
|
||||
case WalletType.nano:
|
||||
return nanoIcon;
|
||||
case WalletType.polygon:
|
||||
return polygonIcon;
|
||||
default:
|
||||
return nonWalletTypeIcon;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/src/widgets/picker.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
|
||||
import 'package:cake_wallet/entities/seed_type.dart';
|
||||
|
||||
class SeedLanguagePickerOption {
|
||||
SeedLanguagePickerOption(this.name, this.nameLocalized, this.image, this.supportedSeedTypes);
|
||||
|
||||
final String name;
|
||||
final String nameLocalized;
|
||||
final Image image;
|
||||
final List<SeedType> supportedSeedTypes;
|
||||
}
|
||||
|
||||
final List<SeedLanguagePickerOption> seedLanguages = [
|
||||
SeedLanguagePickerOption('English', S.current.seed_language_english,
|
||||
Image.asset('assets/images/flags/usa.png'), [SeedType.legacy, SeedType.polyseed]),
|
||||
SeedLanguagePickerOption('Chinese (simplified)', S.current.seed_language_chinese,
|
||||
Image.asset('assets/images/flags/chn.png'), [SeedType.legacy, SeedType.polyseed]),
|
||||
SeedLanguagePickerOption('Chinese (Traditional)', S.current.seed_language_chinese_traditional,
|
||||
Image.asset('assets/images/flags/chn.png'), [SeedType.polyseed]),
|
||||
SeedLanguagePickerOption('Dutch', S.current.seed_language_dutch,
|
||||
Image.asset('assets/images/flags/nld.png'), [SeedType.legacy]),
|
||||
SeedLanguagePickerOption('German', S.current.seed_language_german,
|
||||
Image.asset('assets/images/flags/deu.png'), [SeedType.legacy]),
|
||||
SeedLanguagePickerOption('Japanese', S.current.seed_language_japanese,
|
||||
Image.asset('assets/images/flags/jpn.png'), [SeedType.legacy, SeedType.polyseed]),
|
||||
SeedLanguagePickerOption('Korean', S.current.seed_language_korean,
|
||||
Image.asset('assets/images/flags/kor.png'), [SeedType.polyseed]),
|
||||
SeedLanguagePickerOption('Portuguese', S.current.seed_language_portuguese,
|
||||
Image.asset('assets/images/flags/prt.png'), [SeedType.legacy, SeedType.polyseed]),
|
||||
SeedLanguagePickerOption('Russian', S.current.seed_language_russian,
|
||||
Image.asset('assets/images/flags/rus.png'), [SeedType.legacy]),
|
||||
SeedLanguagePickerOption('Czech', S.current.seed_language_czech,
|
||||
Image.asset('assets/images/flags/czk.png'), [SeedType.polyseed]),
|
||||
SeedLanguagePickerOption('Spanish', S.current.seed_language_spanish,
|
||||
Image.asset('assets/images/flags/esp.png'), [SeedType.legacy, SeedType.polyseed]),
|
||||
SeedLanguagePickerOption('French', S.current.seed_language_french,
|
||||
Image.asset('assets/images/flags/fra.png'), [SeedType.legacy, SeedType.polyseed]),
|
||||
SeedLanguagePickerOption('Italian', S.current.seed_language_italian,
|
||||
Image.asset('assets/images/flags/ita.png'), [SeedType.legacy, SeedType.polyseed]),
|
||||
];
|
||||
|
||||
const defaultSeedLanguage = 'English';
|
||||
|
||||
enum Places { topLeft, topRight, bottomLeft, bottomRight, inside }
|
||||
|
||||
class SeedLanguagePicker extends StatefulWidget {
|
||||
SeedLanguagePicker(
|
||||
{Key? key,
|
||||
this.selected = defaultSeedLanguage,
|
||||
this.seedType = SeedType.defaultSeedType,
|
||||
required this.onItemSelected})
|
||||
: super(key: key);
|
||||
|
||||
final SeedType seedType;
|
||||
final String selected;
|
||||
final Function(String) onItemSelected;
|
||||
|
||||
@override
|
||||
SeedLanguagePickerState createState() => SeedLanguagePickerState(
|
||||
selected: selected, onItemSelected: onItemSelected, seedType: seedType);
|
||||
}
|
||||
|
||||
class SeedLanguagePickerState extends State<SeedLanguagePicker> {
|
||||
SeedLanguagePickerState(
|
||||
{required this.selected, required this.onItemSelected, required this.seedType});
|
||||
|
||||
final SeedType seedType;
|
||||
final String selected;
|
||||
final Function(String) onItemSelected;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final availableSeedLanguages = seedLanguages
|
||||
.where((SeedLanguagePickerOption e) => e.supportedSeedTypes.contains(seedType));
|
||||
|
||||
return Picker(
|
||||
selectedAtIndex: availableSeedLanguages.map((e) => e.name).toList().indexOf(selected),
|
||||
items: availableSeedLanguages.map((e) => e.name).toList(),
|
||||
images: availableSeedLanguages.map((e) => e.image).toList(),
|
||||
isGridView: true,
|
||||
title: S.of(context).seed_choose,
|
||||
hintText: S.of(context).seed_choose,
|
||||
matchingCriteria: (String language, String searchText) {
|
||||
return language.toLowerCase().contains(searchText);
|
||||
},
|
||||
onItemSelected: onItemSelected,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,49 +1,42 @@
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/entities/seed_type.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart';
|
||||
import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_picker.dart';
|
||||
import 'package:cake_wallet/src/widgets/seed_language_picker.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SeedLanguageSelector extends StatefulWidget {
|
||||
SeedLanguageSelector({Key? key, required this.initialSelected})
|
||||
SeedLanguageSelector(
|
||||
{Key? key, required this.initialSelected, this.seedType = SeedType.defaultSeedType})
|
||||
: super(key: key);
|
||||
|
||||
final String initialSelected;
|
||||
final SeedType seedType;
|
||||
|
||||
@override
|
||||
SeedLanguageSelectorState createState() =>
|
||||
SeedLanguageSelectorState(selected: initialSelected);
|
||||
SeedLanguageSelectorState createState() => SeedLanguageSelectorState(selected: initialSelected);
|
||||
}
|
||||
|
||||
class SeedLanguageSelectorState extends State<SeedLanguageSelector> {
|
||||
SeedLanguageSelectorState({required this.selected});
|
||||
|
||||
final seedLocales = [
|
||||
S.current.seed_language_english,
|
||||
S.current.seed_language_chinese,
|
||||
S.current.seed_language_dutch,
|
||||
S.current.seed_language_german,
|
||||
S.current.seed_language_japanese,
|
||||
S.current.seed_language_portuguese,
|
||||
S.current.seed_language_russian,
|
||||
S.current.seed_language_spanish,
|
||||
S.current.seed_language_french,
|
||||
S.current.seed_language_italian,
|
||||
];
|
||||
String selected;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SelectButton(
|
||||
image: null,
|
||||
text: seedLocales[seedLanguages.indexOf(selected)],
|
||||
text:
|
||||
"${seedLanguages.firstWhere((e) => e.name == selected).nameLocalized} (${S.of(context).seed_language})",
|
||||
onTap: () async {
|
||||
await showPopUp<String>(
|
||||
context: context,
|
||||
builder: (_) => SeedLanguagePicker(
|
||||
selected: this.selected,
|
||||
onItemSelected: (String selected) =>
|
||||
setState(() => this.selected = selected)));
|
||||
context: context,
|
||||
builder: (_) => SeedLanguagePicker(
|
||||
selected: this.selected,
|
||||
seedType: widget.seedType,
|
||||
onItemSelected: (String selected) => setState(() => this.selected = selected),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'package:cake_wallet/core/wallet_connect/web3wallet_service.dart';
|
||||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||
import 'package:cake_wallet/utils/exception_handler.dart';
|
||||
import 'package:cw_core/transaction_info.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cw_core/balance.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
@@ -44,7 +44,7 @@ abstract class AppStoreBase with Store {
|
||||
this.wallet = wallet;
|
||||
this.wallet!.setExceptionHandler(ExceptionHandler.onError);
|
||||
|
||||
if (wallet.type == WalletType.ethereum) {
|
||||
if (isEVMCompatibleChain(wallet.type)) {
|
||||
getIt.get<Web3WalletService>().init();
|
||||
}
|
||||
}
|
||||
|
||||
+177
-95
@@ -10,7 +10,9 @@ import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/pin_code_required_duration.dart';
|
||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:cake_wallet/entities/seed_phrase_length.dart';
|
||||
import 'package:cake_wallet/entities/seed_type.dart';
|
||||
import 'package:cake_wallet/entities/sort_balance_types.dart';
|
||||
import 'package:cake_wallet/polygon/polygon.dart';
|
||||
import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
|
||||
import 'package:cake_wallet/view_model/settings/sync_mode.dart';
|
||||
import 'package:cake_wallet/utils/device_info.dart';
|
||||
@@ -34,7 +36,6 @@ import 'package:cake_wallet/monero/monero.dart';
|
||||
import 'package:cake_wallet/entities/action_list_display_mode.dart';
|
||||
import 'package:cake_wallet/entities/fiat_api_mode.dart';
|
||||
import 'package:cw_core/set_app_secure_native.dart';
|
||||
|
||||
part 'settings_store.g.dart';
|
||||
|
||||
class SettingsStore = SettingsStoreBase with _$SettingsStore;
|
||||
@@ -48,6 +49,7 @@ abstract class SettingsStoreBase with Store {
|
||||
required BalanceDisplayMode initialBalanceDisplayMode,
|
||||
required bool initialSaveRecipientAddress,
|
||||
required AutoGenerateSubaddressStatus initialAutoGenerateSubaddressStatus,
|
||||
required SeedType initialMoneroSeedType,
|
||||
required bool initialAppSecure,
|
||||
required bool initialDisableBuy,
|
||||
required bool initialDisableSell,
|
||||
@@ -86,6 +88,7 @@ abstract class SettingsStoreBase with Store {
|
||||
required this.sortBalanceBy,
|
||||
required this.pinNativeTokenAtTop,
|
||||
required this.useEtherscan,
|
||||
required this.usePolygonScan,
|
||||
required this.defaultNanoRep,
|
||||
required this.defaultBananoRep,
|
||||
required this.lookupsTwitter,
|
||||
@@ -99,6 +102,7 @@ abstract class SettingsStoreBase with Store {
|
||||
TransactionPriority? initialHavenTransactionPriority,
|
||||
TransactionPriority? initialLitecoinTransactionPriority,
|
||||
TransactionPriority? initialEthereumTransactionPriority,
|
||||
TransactionPriority? initialPolygonTransactionPriority,
|
||||
TransactionPriority? initialBitcoinCashTransactionPriority})
|
||||
: nodes = ObservableMap<WalletType, Node>.of(nodes),
|
||||
powNodes = ObservableMap<WalletType, Node>.of(powNodes),
|
||||
@@ -108,6 +112,7 @@ abstract class SettingsStoreBase with Store {
|
||||
balanceDisplayMode = initialBalanceDisplayMode,
|
||||
shouldSaveRecipientAddress = initialSaveRecipientAddress,
|
||||
autoGenerateSubaddressStatus = initialAutoGenerateSubaddressStatus,
|
||||
moneroSeedType = initialMoneroSeedType,
|
||||
fiatApiMode = initialFiatMode,
|
||||
allowBiometricalAuthentication = initialAllowBiometricalAuthentication,
|
||||
selectedCake2FAPreset = initialCake2FAPresetOptions,
|
||||
@@ -117,7 +122,6 @@ abstract class SettingsStoreBase with Store {
|
||||
isAppSecure = initialAppSecure,
|
||||
disableBuy = initialDisableBuy,
|
||||
disableSell = initialDisableSell,
|
||||
defaultBuyProvider = initialDefaultBuyProvider,
|
||||
shouldShowMarketPlaceInDashboard = initialShouldShowMarketPlaceInDashboard,
|
||||
exchangeStatus = initialExchangeStatus,
|
||||
currentTheme = initialTheme,
|
||||
@@ -162,12 +166,22 @@ abstract class SettingsStoreBase with Store {
|
||||
priority[WalletType.ethereum] = initialEthereumTransactionPriority;
|
||||
}
|
||||
|
||||
if (initialPolygonTransactionPriority != null) {
|
||||
priority[WalletType.polygon] = initialPolygonTransactionPriority;
|
||||
}
|
||||
|
||||
if (initialBitcoinCashTransactionPriority != null) {
|
||||
priority[WalletType.bitcoinCash] = initialBitcoinCashTransactionPriority;
|
||||
}
|
||||
|
||||
initializeTrocadorProviderStates();
|
||||
|
||||
WalletType.values.forEach((walletType) {
|
||||
final key = 'defaultBuyProvider_${walletType.toString()}';
|
||||
final providerIndex = sharedPreferences.getInt(key);
|
||||
defaultBuyProviders[walletType] = providerIndex != null ? BuyProviderType.values[providerIndex] : BuyProviderType.AskEachTime;
|
||||
});
|
||||
|
||||
reaction(
|
||||
(_) => fiatCurrency,
|
||||
(FiatCurrency fiatCurrency) => sharedPreferences.setString(
|
||||
@@ -199,6 +213,9 @@ abstract class SettingsStoreBase with Store {
|
||||
case WalletType.bitcoinCash:
|
||||
key = PreferencesKey.bitcoinCashTransactionPriority;
|
||||
break;
|
||||
case WalletType.polygon:
|
||||
key = PreferencesKey.polygonTransactionPriority;
|
||||
break;
|
||||
default:
|
||||
key = null;
|
||||
}
|
||||
@@ -231,15 +248,25 @@ abstract class SettingsStoreBase with Store {
|
||||
sharedPreferences.setBool(PreferencesKey.disableSellKey, disableSell));
|
||||
|
||||
reaction(
|
||||
(_) => defaultBuyProvider,
|
||||
(BuyProviderType defaultBuyProvider) =>
|
||||
sharedPreferences.setInt(PreferencesKey.defaultBuyProvider, defaultBuyProvider.index));
|
||||
(_) => defaultBuyProviders.asObservable(),
|
||||
(ObservableMap<WalletType, BuyProviderType> providers) {
|
||||
providers.forEach((walletType, provider) {
|
||||
final key = 'defaultBuyProvider_${walletType.toString()}';
|
||||
sharedPreferences.setInt(key, provider.index);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
reaction(
|
||||
(_) => autoGenerateSubaddressStatus,
|
||||
(AutoGenerateSubaddressStatus autoGenerateSubaddressStatus) => sharedPreferences.setInt(
|
||||
PreferencesKey.autoGenerateSubaddressStatusKey, autoGenerateSubaddressStatus.value));
|
||||
|
||||
reaction(
|
||||
(_) => moneroSeedType,
|
||||
(SeedType moneroSeedType) =>
|
||||
sharedPreferences.setInt(PreferencesKey.moneroSeedType, moneroSeedType.raw));
|
||||
|
||||
reaction(
|
||||
(_) => fiatApiMode,
|
||||
(FiatApiMode mode) =>
|
||||
@@ -315,6 +342,7 @@ abstract class SettingsStoreBase with Store {
|
||||
|
||||
reaction((_) => totpSecretKey,
|
||||
(String totpKey) => sharedPreferences.setString(PreferencesKey.totpSecretKey, totpKey));
|
||||
|
||||
reaction(
|
||||
(_) => numberOfFailedTokenTrials,
|
||||
(int failedTokenTrail) =>
|
||||
@@ -334,9 +362,9 @@ abstract class SettingsStoreBase with Store {
|
||||
sharedPreferences.setString(PreferencesKey.currentLanguageCode, languageCode));
|
||||
|
||||
reaction(
|
||||
(_) => seedPhraseLength,
|
||||
(SeedPhraseLength seedPhraseWordCount) =>
|
||||
sharedPreferences.setInt(PreferencesKey.currentSeedPhraseLength, seedPhraseWordCount.value));
|
||||
(_) => seedPhraseLength,
|
||||
(SeedPhraseLength seedPhraseWordCount) => sharedPreferences.setInt(
|
||||
PreferencesKey.currentSeedPhraseLength, seedPhraseWordCount.value));
|
||||
|
||||
reaction(
|
||||
(_) => pinTimeOutDuration,
|
||||
@@ -380,6 +408,11 @@ abstract class SettingsStoreBase with Store {
|
||||
(bool useEtherscan) =>
|
||||
_sharedPreferences.setBool(PreferencesKey.useEtherscan, useEtherscan));
|
||||
|
||||
reaction(
|
||||
(_) => usePolygonScan,
|
||||
(bool usePolygonScan) =>
|
||||
_sharedPreferences.setBool(PreferencesKey.usePolygonScan, usePolygonScan));
|
||||
|
||||
reaction((_) => defaultNanoRep,
|
||||
(String nanoRep) => _sharedPreferences.setString(PreferencesKey.defaultNanoRep, nanoRep));
|
||||
|
||||
@@ -388,34 +421,32 @@ abstract class SettingsStoreBase with Store {
|
||||
(String bananoRep) =>
|
||||
_sharedPreferences.setString(PreferencesKey.defaultBananoRep, bananoRep));
|
||||
reaction(
|
||||
(_) => lookupsTwitter,
|
||||
(bool looksUpTwitter) =>
|
||||
(_) => lookupsTwitter,
|
||||
(bool looksUpTwitter) =>
|
||||
_sharedPreferences.setBool(PreferencesKey.lookupsTwitter, looksUpTwitter));
|
||||
|
||||
reaction(
|
||||
(_) => lookupsMastodon,
|
||||
(bool looksUpMastodon) =>
|
||||
(_) => lookupsMastodon,
|
||||
(bool looksUpMastodon) =>
|
||||
_sharedPreferences.setBool(PreferencesKey.lookupsMastodon, looksUpMastodon));
|
||||
|
||||
reaction(
|
||||
(_) => lookupsYatService,
|
||||
(bool looksUpYatService) =>
|
||||
(_) => lookupsYatService,
|
||||
(bool looksUpYatService) =>
|
||||
_sharedPreferences.setBool(PreferencesKey.lookupsYatService, looksUpYatService));
|
||||
|
||||
reaction(
|
||||
(_) => lookupsUnstoppableDomains,
|
||||
(bool looksUpUnstoppableDomains) =>
|
||||
_sharedPreferences.setBool(PreferencesKey.lookupsUnstoppableDomains, looksUpUnstoppableDomains));
|
||||
(_) => lookupsUnstoppableDomains,
|
||||
(bool looksUpUnstoppableDomains) => _sharedPreferences.setBool(
|
||||
PreferencesKey.lookupsUnstoppableDomains, looksUpUnstoppableDomains));
|
||||
|
||||
reaction(
|
||||
(_) => lookupsOpenAlias,
|
||||
(bool looksUpOpenAlias) =>
|
||||
(_) => lookupsOpenAlias,
|
||||
(bool looksUpOpenAlias) =>
|
||||
_sharedPreferences.setBool(PreferencesKey.lookupsOpenAlias, looksUpOpenAlias));
|
||||
|
||||
reaction(
|
||||
(_) => lookupsENS,
|
||||
(bool looksUpENS) =>
|
||||
_sharedPreferences.setBool(PreferencesKey.lookupsENS, looksUpENS));
|
||||
reaction((_) => lookupsENS,
|
||||
(bool looksUpENS) => _sharedPreferences.setBool(PreferencesKey.lookupsENS, looksUpENS));
|
||||
|
||||
this.nodes.observe((change) {
|
||||
if (change.newValue != null && change.key != null) {
|
||||
@@ -435,6 +466,7 @@ abstract class SettingsStoreBase with Store {
|
||||
static const defaultPinCodeTimeOutDuration = PinCodeRequiredDuration.tenminutes;
|
||||
static const defaultAutoGenerateSubaddressStatus = AutoGenerateSubaddressStatus.initialized;
|
||||
static const defaultSeedPhraseLength = SeedPhraseLength.twelveWords;
|
||||
static const defaultMoneroSeedType = SeedType.defaultSeedType;
|
||||
|
||||
@observable
|
||||
FiatCurrency fiatCurrency;
|
||||
@@ -460,6 +492,9 @@ abstract class SettingsStoreBase with Store {
|
||||
@observable
|
||||
AutoGenerateSubaddressStatus autoGenerateSubaddressStatus;
|
||||
|
||||
@observable
|
||||
SeedType moneroSeedType;
|
||||
|
||||
@observable
|
||||
bool isAppSecure;
|
||||
|
||||
@@ -469,9 +504,6 @@ abstract class SettingsStoreBase with Store {
|
||||
@observable
|
||||
bool disableSell;
|
||||
|
||||
@observable
|
||||
BuyProviderType defaultBuyProvider;
|
||||
|
||||
@observable
|
||||
bool allowBiometricalAuthentication;
|
||||
|
||||
@@ -541,6 +573,9 @@ abstract class SettingsStoreBase with Store {
|
||||
@observable
|
||||
ObservableMap<String, bool> trocadorProviderStates = ObservableMap<String, bool>();
|
||||
|
||||
@observable
|
||||
ObservableMap<WalletType, BuyProviderType> defaultBuyProviders = ObservableMap<WalletType, BuyProviderType>();
|
||||
|
||||
@observable
|
||||
SortBalanceBy sortBalanceBy;
|
||||
|
||||
@@ -550,6 +585,9 @@ abstract class SettingsStoreBase with Store {
|
||||
@observable
|
||||
bool useEtherscan;
|
||||
|
||||
@observable
|
||||
bool usePolygonScan;
|
||||
|
||||
@observable
|
||||
String defaultNanoRep;
|
||||
|
||||
@@ -639,6 +677,7 @@ abstract class SettingsStoreBase with Store {
|
||||
TransactionPriority? havenTransactionPriority;
|
||||
TransactionPriority? litecoinTransactionPriority;
|
||||
TransactionPriority? ethereumTransactionPriority;
|
||||
TransactionPriority? polygonTransactionPriority;
|
||||
TransactionPriority? bitcoinCashTransactionPriority;
|
||||
|
||||
if (sharedPreferences.getInt(PreferencesKey.havenTransactionPriority) != null) {
|
||||
@@ -650,9 +689,13 @@ abstract class SettingsStoreBase with Store {
|
||||
sharedPreferences.getInt(PreferencesKey.litecoinTransactionPriority)!);
|
||||
}
|
||||
if (sharedPreferences.getInt(PreferencesKey.ethereumTransactionPriority) != null) {
|
||||
ethereumTransactionPriority = bitcoin?.deserializeLitecoinTransactionPriority(
|
||||
ethereumTransactionPriority = ethereum?.deserializeEthereumTransactionPriority(
|
||||
sharedPreferences.getInt(PreferencesKey.ethereumTransactionPriority)!);
|
||||
}
|
||||
if (sharedPreferences.getInt(PreferencesKey.polygonTransactionPriority) != null) {
|
||||
polygonTransactionPriority = polygon?.deserializePolygonTransactionPriority(
|
||||
sharedPreferences.getInt(PreferencesKey.polygonTransactionPriority)!);
|
||||
}
|
||||
if (sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority) != null) {
|
||||
bitcoinCashTransactionPriority = bitcoinCash?.deserializeBitcoinCashTransactionPriority(
|
||||
sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority)!);
|
||||
@@ -664,6 +707,7 @@ abstract class SettingsStoreBase with Store {
|
||||
litecoinTransactionPriority ??= bitcoin?.getLitecoinTransactionPriorityMedium();
|
||||
ethereumTransactionPriority ??= ethereum?.getDefaultTransactionPriority();
|
||||
bitcoinCashTransactionPriority ??= bitcoinCash?.getDefaultTransactionPriority();
|
||||
polygonTransactionPriority ??= polygon?.getDefaultTransactionPriority();
|
||||
|
||||
final currentBalanceDisplayMode = BalanceDisplayMode.deserialize(
|
||||
raw: sharedPreferences.getInt(PreferencesKey.currentBalanceDisplayModeKey)!);
|
||||
@@ -737,12 +781,14 @@ abstract class SettingsStoreBase with Store {
|
||||
final pinNativeTokenAtTop =
|
||||
sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop) ?? true;
|
||||
final useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true;
|
||||
final usePolygonScan = sharedPreferences.getBool(PreferencesKey.usePolygonScan) ?? true;
|
||||
final defaultNanoRep = sharedPreferences.getString(PreferencesKey.defaultNanoRep) ?? "";
|
||||
final defaultBananoRep = sharedPreferences.getString(PreferencesKey.defaultBananoRep) ?? "";
|
||||
final lookupsTwitter = sharedPreferences.getBool(PreferencesKey.lookupsTwitter) ?? true;
|
||||
final lookupsMastodon = sharedPreferences.getBool(PreferencesKey.lookupsMastodon) ?? true;
|
||||
final lookupsYatService = sharedPreferences.getBool(PreferencesKey.lookupsYatService) ?? true;
|
||||
final lookupsUnstoppableDomains = sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains) ?? true;
|
||||
final lookupsUnstoppableDomains =
|
||||
sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains) ?? true;
|
||||
final lookupsOpenAlias = sharedPreferences.getBool(PreferencesKey.lookupsOpenAlias) ?? true;
|
||||
final lookupsENS = sharedPreferences.getBool(PreferencesKey.lookupsENS) ?? true;
|
||||
|
||||
@@ -762,6 +808,7 @@ abstract class SettingsStoreBase with Store {
|
||||
sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey);
|
||||
final havenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey);
|
||||
final ethereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey);
|
||||
final polygonNodeId = sharedPreferences.getInt(PreferencesKey.currentPolygonNodeIdKey);
|
||||
final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey);
|
||||
final nanoPowNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoPowNodeIdKey);
|
||||
final moneroNode = nodeSource.get(nodeId);
|
||||
@@ -769,18 +816,27 @@ abstract class SettingsStoreBase with Store {
|
||||
final litecoinElectrumServer = nodeSource.get(litecoinElectrumServerId);
|
||||
final havenNode = nodeSource.get(havenNodeId);
|
||||
final ethereumNode = nodeSource.get(ethereumNodeId);
|
||||
final polygonNode = nodeSource.get(polygonNodeId);
|
||||
final bitcoinCashElectrumServer = nodeSource.get(bitcoinCashElectrumServerId);
|
||||
final nanoNode = nodeSource.get(nanoNodeId);
|
||||
final nanoPowNode = powNodeSource.get(nanoPowNodeId);
|
||||
final packageInfo = await PackageInfo.fromPlatform();
|
||||
final deviceName = await _getDeviceName() ?? '';
|
||||
final shouldShowYatPopup = sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? true;
|
||||
|
||||
final generateSubaddresses =
|
||||
sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey);
|
||||
|
||||
final autoGenerateSubaddressStatus = generateSubaddresses != null
|
||||
? AutoGenerateSubaddressStatus.deserialize(raw: generateSubaddresses)
|
||||
: defaultAutoGenerateSubaddressStatus;
|
||||
|
||||
final _moneroSeedType = sharedPreferences.getInt(PreferencesKey.moneroSeedType);
|
||||
|
||||
final moneroSeedType = _moneroSeedType != null
|
||||
? SeedType.deserialize(raw: _moneroSeedType)
|
||||
: defaultMoneroSeedType;
|
||||
|
||||
final nodes = <WalletType, Node>{};
|
||||
final powNodes = <WalletType, Node>{};
|
||||
|
||||
@@ -804,6 +860,10 @@ abstract class SettingsStoreBase with Store {
|
||||
nodes[WalletType.ethereum] = ethereumNode;
|
||||
}
|
||||
|
||||
if (polygonNode != null) {
|
||||
nodes[WalletType.polygon] = polygonNode;
|
||||
}
|
||||
|
||||
if (bitcoinCashElectrumServer != null) {
|
||||
nodes[WalletType.bitcoinCash] = bitcoinCashElectrumServer;
|
||||
}
|
||||
@@ -817,74 +877,77 @@ abstract class SettingsStoreBase with Store {
|
||||
}
|
||||
|
||||
final savedSyncMode = SyncMode.all.firstWhere((element) {
|
||||
return element.type.index == (sharedPreferences.getInt(PreferencesKey.syncModeKey) ?? 1);
|
||||
return element.type.index == (sharedPreferences.getInt(PreferencesKey.syncModeKey) ?? 0);
|
||||
});
|
||||
final savedSyncAll = sharedPreferences.getBool(PreferencesKey.syncAllKey) ?? true;
|
||||
|
||||
return SettingsStore(
|
||||
sharedPreferences: sharedPreferences,
|
||||
initialShouldShowMarketPlaceInDashboard: shouldShowMarketPlaceInDashboard,
|
||||
nodes: nodes,
|
||||
powNodes: powNodes,
|
||||
appVersion: packageInfo.version,
|
||||
deviceName: deviceName,
|
||||
isBitcoinBuyEnabled: isBitcoinBuyEnabled,
|
||||
initialFiatCurrency: currentFiatCurrency,
|
||||
initialBalanceDisplayMode: currentBalanceDisplayMode,
|
||||
initialSaveRecipientAddress: shouldSaveRecipientAddress,
|
||||
initialAutoGenerateSubaddressStatus: autoGenerateSubaddressStatus,
|
||||
initialAppSecure: isAppSecure,
|
||||
initialDisableBuy: disableBuy,
|
||||
initialDisableSell: disableSell,
|
||||
initialDefaultBuyProvider: defaultBuyProvider,
|
||||
initialFiatMode: currentFiatApiMode,
|
||||
initialAllowBiometricalAuthentication: allowBiometricalAuthentication,
|
||||
initialCake2FAPresetOptions: selectedCake2FAPreset,
|
||||
initialUseTOTP2FA: useTOTP2FA,
|
||||
initialTotpSecretKey: totpSecretKey,
|
||||
initialFailedTokenTrial: tokenTrialNumber,
|
||||
initialExchangeStatus: exchangeStatus,
|
||||
initialTheme: savedTheme,
|
||||
actionlistDisplayMode: actionListDisplayMode,
|
||||
initialPinLength: pinLength,
|
||||
pinTimeOutDuration: pinCodeTimeOutDuration,
|
||||
seedPhraseLength: seedPhraseWordCount,
|
||||
initialLanguageCode: savedLanguageCode,
|
||||
sortBalanceBy: sortBalanceBy,
|
||||
pinNativeTokenAtTop: pinNativeTokenAtTop,
|
||||
useEtherscan: useEtherscan,
|
||||
defaultNanoRep: defaultNanoRep,
|
||||
defaultBananoRep: defaultBananoRep,
|
||||
lookupsTwitter: lookupsTwitter,
|
||||
lookupsMastodon: lookupsMastodon,
|
||||
lookupsYatService: lookupsYatService,
|
||||
lookupsUnstoppableDomains: lookupsUnstoppableDomains,
|
||||
lookupsOpenAlias: lookupsOpenAlias,
|
||||
lookupsENS: lookupsENS,
|
||||
initialMoneroTransactionPriority: moneroTransactionPriority,
|
||||
initialBitcoinTransactionPriority: bitcoinTransactionPriority,
|
||||
initialHavenTransactionPriority: havenTransactionPriority,
|
||||
initialLitecoinTransactionPriority: litecoinTransactionPriority,
|
||||
initialBitcoinCashTransactionPriority: bitcoinCashTransactionPriority,
|
||||
initialShouldRequireTOTP2FAForAccessingWallet: shouldRequireTOTP2FAForAccessingWallet,
|
||||
initialShouldRequireTOTP2FAForSendsToContact: shouldRequireTOTP2FAForSendsToContact,
|
||||
initialShouldRequireTOTP2FAForSendsToNonContact: shouldRequireTOTP2FAForSendsToNonContact,
|
||||
initialShouldRequireTOTP2FAForSendsToInternalWallets:
|
||||
shouldRequireTOTP2FAForSendsToInternalWallets,
|
||||
initialShouldRequireTOTP2FAForExchangesToInternalWallets:
|
||||
shouldRequireTOTP2FAForExchangesToInternalWallets,
|
||||
return SettingsStore(
|
||||
sharedPreferences: sharedPreferences,
|
||||
initialShouldShowMarketPlaceInDashboard: shouldShowMarketPlaceInDashboard,
|
||||
nodes: nodes,
|
||||
powNodes: powNodes,
|
||||
appVersion: packageInfo.version,
|
||||
deviceName: deviceName,
|
||||
isBitcoinBuyEnabled: isBitcoinBuyEnabled,
|
||||
initialFiatCurrency: currentFiatCurrency,
|
||||
initialBalanceDisplayMode: currentBalanceDisplayMode,
|
||||
initialSaveRecipientAddress: shouldSaveRecipientAddress,
|
||||
initialAutoGenerateSubaddressStatus: autoGenerateSubaddressStatus,
|
||||
initialMoneroSeedType: moneroSeedType,
|
||||
initialAppSecure: isAppSecure,
|
||||
initialDisableBuy: disableBuy,
|
||||
initialDisableSell: disableSell,
|
||||
initialDefaultBuyProvider: defaultBuyProvider,
|
||||
initialFiatMode: currentFiatApiMode,
|
||||
initialAllowBiometricalAuthentication: allowBiometricalAuthentication,
|
||||
initialCake2FAPresetOptions: selectedCake2FAPreset,
|
||||
initialUseTOTP2FA: useTOTP2FA,
|
||||
initialTotpSecretKey: totpSecretKey,
|
||||
initialFailedTokenTrial: tokenTrialNumber,
|
||||
initialExchangeStatus: exchangeStatus,
|
||||
initialTheme: savedTheme,
|
||||
actionlistDisplayMode: actionListDisplayMode,
|
||||
initialPinLength: pinLength,
|
||||
pinTimeOutDuration: pinCodeTimeOutDuration,
|
||||
seedPhraseLength: seedPhraseWordCount,
|
||||
initialLanguageCode: savedLanguageCode,
|
||||
sortBalanceBy: sortBalanceBy,
|
||||
pinNativeTokenAtTop: pinNativeTokenAtTop,
|
||||
useEtherscan: useEtherscan,
|
||||
usePolygonScan: usePolygonScan,
|
||||
defaultNanoRep: defaultNanoRep,
|
||||
defaultBananoRep: defaultBananoRep,
|
||||
lookupsTwitter: lookupsTwitter,
|
||||
lookupsMastodon: lookupsMastodon,
|
||||
lookupsYatService: lookupsYatService,
|
||||
lookupsUnstoppableDomains: lookupsUnstoppableDomains,
|
||||
lookupsOpenAlias: lookupsOpenAlias,
|
||||
lookupsENS: lookupsENS,
|
||||
initialMoneroTransactionPriority: moneroTransactionPriority,
|
||||
initialBitcoinTransactionPriority: bitcoinTransactionPriority,
|
||||
initialHavenTransactionPriority: havenTransactionPriority,
|
||||
initialLitecoinTransactionPriority: litecoinTransactionPriority,
|
||||
initialBitcoinCashTransactionPriority: bitcoinCashTransactionPriority,
|
||||
initialShouldRequireTOTP2FAForAccessingWallet: shouldRequireTOTP2FAForAccessingWallet,
|
||||
initialShouldRequireTOTP2FAForSendsToContact: shouldRequireTOTP2FAForSendsToContact,
|
||||
initialShouldRequireTOTP2FAForSendsToNonContact: shouldRequireTOTP2FAForSendsToNonContact,
|
||||
initialShouldRequireTOTP2FAForSendsToInternalWallets:
|
||||
shouldRequireTOTP2FAForSendsToInternalWallets,
|
||||
initialShouldRequireTOTP2FAForExchangesToInternalWallets:
|
||||
shouldRequireTOTP2FAForExchangesToInternalWallets,
|
||||
initialShouldRequireTOTP2FAForExchangesToExternalWallets:
|
||||
shouldRequireTOTP2FAForExchangesToExternalWallets,
|
||||
initialShouldRequireTOTP2FAForAddingContacts: shouldRequireTOTP2FAForAddingContacts,
|
||||
initialShouldRequireTOTP2FAForCreatingNewWallets: shouldRequireTOTP2FAForCreatingNewWallets,
|
||||
initialShouldRequireTOTP2FAForAllSecurityAndBackupSettings:
|
||||
shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
|
||||
initialEthereumTransactionPriority: ethereumTransactionPriority,
|
||||
backgroundTasks: backgroundTasks,
|
||||
initialSyncMode: savedSyncMode,
|
||||
initialSyncAll: savedSyncAll,
|
||||
shouldShowYatPopup: shouldShowYatPopup);
|
||||
}
|
||||
initialShouldRequireTOTP2FAForAddingContacts: shouldRequireTOTP2FAForAddingContacts,
|
||||
initialShouldRequireTOTP2FAForCreatingNewWallets: shouldRequireTOTP2FAForCreatingNewWallets,
|
||||
initialShouldRequireTOTP2FAForAllSecurityAndBackupSettings:
|
||||
shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
|
||||
initialEthereumTransactionPriority: ethereumTransactionPriority,
|
||||
initialPolygonTransactionPriority: polygonTransactionPriority,
|
||||
backgroundTasks: backgroundTasks,
|
||||
initialSyncMode: savedSyncMode,
|
||||
initialSyncAll: savedSyncAll,
|
||||
shouldShowYatPopup: shouldShowYatPopup);
|
||||
}
|
||||
|
||||
Future<void> reload({required Box<Node> nodeSource}) async {
|
||||
final sharedPreferences = await getIt.getAsync<SharedPreferences>();
|
||||
@@ -914,6 +977,11 @@ abstract class SettingsStoreBase with Store {
|
||||
sharedPreferences.getInt(PreferencesKey.ethereumTransactionPriority)!) ??
|
||||
priority[WalletType.ethereum]!;
|
||||
}
|
||||
if (sharedPreferences.getInt(PreferencesKey.polygonTransactionPriority) != null) {
|
||||
priority[WalletType.polygon] = polygon?.deserializePolygonTransactionPriority(
|
||||
sharedPreferences.getInt(PreferencesKey.polygonTransactionPriority)!) ??
|
||||
priority[WalletType.polygon]!;
|
||||
}
|
||||
if (sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority) != null) {
|
||||
priority[WalletType.bitcoinCash] = bitcoinCash?.deserializeBitcoinCashTransactionPriority(
|
||||
sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority)!) ??
|
||||
@@ -927,6 +995,12 @@ abstract class SettingsStoreBase with Store {
|
||||
? AutoGenerateSubaddressStatus.deserialize(raw: generateSubaddresses)
|
||||
: defaultAutoGenerateSubaddressStatus;
|
||||
|
||||
final _moneroSeedType = sharedPreferences.getInt(PreferencesKey.moneroSeedType);
|
||||
|
||||
moneroSeedType = _moneroSeedType != null
|
||||
? SeedType.deserialize(raw: _moneroSeedType)
|
||||
: defaultMoneroSeedType;
|
||||
|
||||
balanceDisplayMode = BalanceDisplayMode.deserialize(
|
||||
raw: sharedPreferences.getInt(PreferencesKey.currentBalanceDisplayModeKey)!);
|
||||
shouldSaveRecipientAddress =
|
||||
@@ -939,8 +1013,6 @@ abstract class SettingsStoreBase with Store {
|
||||
isAppSecure = sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? isAppSecure;
|
||||
disableBuy = sharedPreferences.getBool(PreferencesKey.disableBuyKey) ?? disableBuy;
|
||||
disableSell = sharedPreferences.getBool(PreferencesKey.disableSellKey) ?? disableSell;
|
||||
defaultBuyProvider =
|
||||
BuyProviderType.values[sharedPreferences.getInt(PreferencesKey.defaultBuyProvider) ?? 0];
|
||||
allowBiometricalAuthentication =
|
||||
sharedPreferences.getBool(PreferencesKey.allowBiometricalAuthenticationKey) ??
|
||||
allowBiometricalAuthentication;
|
||||
@@ -1001,12 +1073,14 @@ abstract class SettingsStoreBase with Store {
|
||||
.values[sharedPreferences.getInt(PreferencesKey.sortBalanceBy) ?? sortBalanceBy.index];
|
||||
pinNativeTokenAtTop = sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop) ?? true;
|
||||
useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true;
|
||||
usePolygonScan = sharedPreferences.getBool(PreferencesKey.usePolygonScan) ?? true;
|
||||
defaultNanoRep = sharedPreferences.getString(PreferencesKey.defaultNanoRep) ?? "";
|
||||
defaultBananoRep = sharedPreferences.getString(PreferencesKey.defaultBananoRep) ?? "";
|
||||
lookupsTwitter = sharedPreferences.getBool(PreferencesKey.lookupsTwitter) ?? true;
|
||||
lookupsMastodon = sharedPreferences.getBool(PreferencesKey.lookupsMastodon) ?? true;
|
||||
lookupsYatService = sharedPreferences.getBool(PreferencesKey.lookupsYatService) ?? true;
|
||||
lookupsUnstoppableDomains = sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains) ?? true;
|
||||
lookupsUnstoppableDomains =
|
||||
sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains) ?? true;
|
||||
lookupsOpenAlias = sharedPreferences.getBool(PreferencesKey.lookupsOpenAlias) ?? true;
|
||||
lookupsENS = sharedPreferences.getBool(PreferencesKey.lookupsENS) ?? true;
|
||||
|
||||
@@ -1019,6 +1093,7 @@ abstract class SettingsStoreBase with Store {
|
||||
sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey);
|
||||
final havenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey);
|
||||
final ethereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey);
|
||||
final polygonNodeId = sharedPreferences.getInt(PreferencesKey.currentPolygonNodeIdKey);
|
||||
final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey);
|
||||
final nanoPowNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey);
|
||||
final moneroNode = nodeSource.get(nodeId);
|
||||
@@ -1026,6 +1101,7 @@ abstract class SettingsStoreBase with Store {
|
||||
final litecoinElectrumServer = nodeSource.get(litecoinElectrumServerId);
|
||||
final havenNode = nodeSource.get(havenNodeId);
|
||||
final ethereumNode = nodeSource.get(ethereumNodeId);
|
||||
final polygonNode = nodeSource.get(polygonNodeId);
|
||||
final bitcoinCashNode = nodeSource.get(bitcoinCashElectrumServerId);
|
||||
final nanoNode = nodeSource.get(nanoNodeId);
|
||||
|
||||
@@ -1049,6 +1125,10 @@ abstract class SettingsStoreBase with Store {
|
||||
nodes[WalletType.ethereum] = ethereumNode;
|
||||
}
|
||||
|
||||
if (polygonNode != null) {
|
||||
nodes[WalletType.polygon] = polygonNode;
|
||||
}
|
||||
|
||||
if (bitcoinCashNode != null) {
|
||||
nodes[WalletType.bitcoinCash] = bitcoinCashNode;
|
||||
}
|
||||
@@ -1084,6 +1164,9 @@ abstract class SettingsStoreBase with Store {
|
||||
case WalletType.nano:
|
||||
await _sharedPreferences.setInt(PreferencesKey.currentNanoNodeIdKey, node.key as int);
|
||||
break;
|
||||
case WalletType.polygon:
|
||||
await _sharedPreferences.setInt(PreferencesKey.currentPolygonNodeIdKey, node.key as int);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1115,7 +1198,6 @@ abstract class SettingsStoreBase with Store {
|
||||
trocadorProviderStates[providerName] = state;
|
||||
}
|
||||
|
||||
|
||||
static Future<String?> _getDeviceName() async {
|
||||
String? deviceName = '';
|
||||
final deviceInfoPlugin = DeviceInfoPlugin();
|
||||
|
||||
@@ -29,6 +29,8 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
|
||||
bool get hasSeedPhraseLengthOption =>
|
||||
type == WalletType.bitcoinCash || type == WalletType.ethereum;
|
||||
|
||||
bool get hasSeedTypeOption => type == WalletType.monero;
|
||||
|
||||
@computed
|
||||
bool get addCustomNode => _addCustomNode;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:cake_wallet/entities/fiat_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/sort_balance_types.dart';
|
||||
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||
import 'package:cw_core/transaction_history.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/balance.dart';
|
||||
@@ -81,7 +82,7 @@ abstract class BalanceViewModelBase with Store {
|
||||
bool get isFiatDisabled => settingsStore.fiatApiMode == FiatApiMode.disabled;
|
||||
|
||||
@computed
|
||||
bool get isHomeScreenSettingsEnabled => wallet.type == WalletType.ethereum;
|
||||
bool get isHomeScreenSettingsEnabled => isEVMCompatibleChain(wallet.type);
|
||||
|
||||
@computed
|
||||
bool get hasAccounts => wallet.type == WalletType.monero;
|
||||
@@ -123,6 +124,7 @@ abstract class BalanceViewModelBase with Store {
|
||||
case WalletType.monero:
|
||||
case WalletType.haven:
|
||||
case WalletType.ethereum:
|
||||
case WalletType.polygon:
|
||||
return S.current.xmr_available_balance;
|
||||
default:
|
||||
return S.current.confirmed;
|
||||
@@ -135,6 +137,7 @@ abstract class BalanceViewModelBase with Store {
|
||||
case WalletType.monero:
|
||||
case WalletType.haven:
|
||||
case WalletType.ethereum:
|
||||
case WalletType.polygon:
|
||||
return S.current.xmr_full_balance;
|
||||
default:
|
||||
return S.current.unconfirmed;
|
||||
@@ -272,7 +275,8 @@ abstract class BalanceViewModelBase with Store {
|
||||
}
|
||||
|
||||
@computed
|
||||
bool get hasAdditionalBalance => wallet.type != WalletType.ethereum;
|
||||
bool get hasAdditionalBalance => !isEVMCompatibleChain(wallet.type);
|
||||
|
||||
|
||||
@computed
|
||||
List<BalanceRecord> get formattedBalances {
|
||||
|
||||
@@ -282,10 +282,14 @@ abstract class DashboardViewModelBase with Store {
|
||||
|
||||
Map<String, List<FilterItem>> filterItems;
|
||||
|
||||
BuyProviderType get defaultBuyProvider => settingsStore.defaultBuyProvider;
|
||||
BuyProviderType get defaultBuyProvider =>
|
||||
settingsStore.defaultBuyProviders[wallet.type] ??
|
||||
BuyProviderType.AskEachTime;
|
||||
|
||||
bool get isBuyEnabled => settingsStore.isBitcoinBuyEnabled;
|
||||
|
||||
List<BuyProviderType> get availableProviders => BuyProviderType.getAvailableProviders(wallet.type);
|
||||
|
||||
bool get shouldShowYatPopup => settingsStore.shouldShowYatPopup;
|
||||
|
||||
@action
|
||||
|
||||
@@ -2,10 +2,12 @@ import 'package:cake_wallet/core/fiat_conversion_service.dart';
|
||||
import 'package:cake_wallet/entities/fiat_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/sort_balance_types.dart';
|
||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:cake_wallet/polygon/polygon.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_core/erc20_token.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
part 'home_settings_view_model.g.dart';
|
||||
@@ -42,18 +44,41 @@ abstract class HomeSettingsViewModelBase with Store {
|
||||
void setPinNativeToken(bool value) => _settingsStore.pinNativeTokenAtTop = value;
|
||||
|
||||
Future<void> addErc20Token(Erc20Token token) async {
|
||||
await ethereum!.addErc20Token(_balanceViewModel.wallet, token);
|
||||
if (_balanceViewModel.wallet.type == WalletType.ethereum) {
|
||||
await ethereum!.addErc20Token(_balanceViewModel.wallet, token);
|
||||
}
|
||||
|
||||
if (_balanceViewModel.wallet.type == WalletType.polygon) {
|
||||
await polygon!.addErc20Token(_balanceViewModel.wallet, token);
|
||||
}
|
||||
|
||||
_updateTokensList();
|
||||
_updateFiatPrices(token);
|
||||
}
|
||||
|
||||
Future<void> deleteErc20Token(Erc20Token token) async {
|
||||
await ethereum!.deleteErc20Token(_balanceViewModel.wallet, token);
|
||||
if (_balanceViewModel.wallet.type == WalletType.ethereum) {
|
||||
await ethereum!.deleteErc20Token(_balanceViewModel.wallet, token);
|
||||
}
|
||||
|
||||
if (_balanceViewModel.wallet.type == WalletType.polygon) {
|
||||
await polygon!.deleteErc20Token(_balanceViewModel.wallet, token);
|
||||
}
|
||||
|
||||
_updateTokensList();
|
||||
}
|
||||
|
||||
Future<Erc20Token?> getErc20Token(String contractAddress) async =>
|
||||
await ethereum!.getErc20Token(_balanceViewModel.wallet, contractAddress);
|
||||
Future<Erc20Token?> getErc20Token(String contractAddress) async {
|
||||
if (_balanceViewModel.wallet.type == WalletType.ethereum) {
|
||||
return await ethereum!.getErc20Token(_balanceViewModel.wallet, contractAddress);
|
||||
}
|
||||
|
||||
if (_balanceViewModel.wallet.type == WalletType.polygon) {
|
||||
return await polygon!.getErc20Token(_balanceViewModel.wallet, contractAddress);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
CryptoCurrency get nativeToken => _balanceViewModel.wallet.currency;
|
||||
|
||||
@@ -69,7 +94,12 @@ abstract class HomeSettingsViewModelBase with Store {
|
||||
|
||||
void changeTokenAvailability(Erc20Token token, bool value) async {
|
||||
token.enabled = value;
|
||||
ethereum!.addErc20Token(_balanceViewModel.wallet, token);
|
||||
if (_balanceViewModel.wallet.type == WalletType.ethereum) {
|
||||
ethereum!.addErc20Token(_balanceViewModel.wallet, token);
|
||||
}
|
||||
if (_balanceViewModel.wallet.type == WalletType.polygon) {
|
||||
polygon!.addErc20Token(_balanceViewModel.wallet, token);
|
||||
}
|
||||
_refreshTokensList();
|
||||
}
|
||||
|
||||
@@ -83,7 +113,8 @@ abstract class HomeSettingsViewModelBase with Store {
|
||||
return -1;
|
||||
} else if (e2.enabled && !e1.enabled) {
|
||||
return 1;
|
||||
} else if (!e1.enabled && !e2.enabled) { // if both are disabled then sort alphabetically
|
||||
} else if (!e1.enabled && !e2.enabled) {
|
||||
// if both are disabled then sort alphabetically
|
||||
return e1.name.compareTo(e2.name);
|
||||
}
|
||||
|
||||
@@ -92,11 +123,21 @@ abstract class HomeSettingsViewModelBase with Store {
|
||||
|
||||
tokens.clear();
|
||||
|
||||
tokens.addAll(ethereum!
|
||||
.getERC20Currencies(_balanceViewModel.wallet)
|
||||
.where((element) => _matchesSearchText(element))
|
||||
.toList()
|
||||
..sort(_sortFunc));
|
||||
if (_balanceViewModel.wallet.type == WalletType.ethereum) {
|
||||
tokens.addAll(ethereum!
|
||||
.getERC20Currencies(_balanceViewModel.wallet)
|
||||
.where((element) => _matchesSearchText(element))
|
||||
.toList()
|
||||
..sort(_sortFunc));
|
||||
}
|
||||
|
||||
if (_balanceViewModel.wallet.type == WalletType.polygon) {
|
||||
tokens.addAll(polygon!
|
||||
.getERC20Currencies(_balanceViewModel.wallet)
|
||||
.where((element) => _matchesSearchText(element))
|
||||
.toList()
|
||||
..sort(_sortFunc));
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:cake_wallet/core/wallet_connect/wc_bottom_sheet_service.dart';
|
||||
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_connect/widgets/message_display_widget.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:mobx/mobx.dart';
|
||||
@@ -38,21 +38,26 @@ abstract class NFTViewModelBase with Store {
|
||||
|
||||
@action
|
||||
Future<void> getNFTAssetByWallet() async {
|
||||
if (!isEVMCompatibleChain(appStore.wallet!.type)) return;
|
||||
|
||||
final walletAddress = appStore.wallet!.walletInfo.address;
|
||||
log('Fetching wallet NFTs for $walletAddress');
|
||||
|
||||
final chainName = getChainNameBasedOnWalletType(appStore.wallet!.type);
|
||||
// the [chain] refers to the chain network that the nft is on
|
||||
// the [format] refers to the number format type of the responses
|
||||
// the [normalizedMetadata] field is a boolean that determines if
|
||||
// the response would include a json string of the NFT Metadata that can be decoded
|
||||
// and used within the wallet
|
||||
// the [excludeSpam] field is a boolean that determines if spam nfts be excluded from the response.
|
||||
final uri = Uri.https(
|
||||
'deep-index.moralis.io',
|
||||
'/api/v2.2/$walletAddress/nft',
|
||||
{
|
||||
"chain": "eth",
|
||||
"chain": chainName,
|
||||
"format": "decimal",
|
||||
"media_items": "false",
|
||||
"exclude_spam": "true",
|
||||
"normalizeMetadata": "true",
|
||||
},
|
||||
);
|
||||
@@ -91,7 +96,7 @@ abstract class NFTViewModelBase with Store {
|
||||
|
||||
@action
|
||||
Future<void> importNFT(String tokenAddress, String tokenId) async {
|
||||
|
||||
final chainName = getChainNameBasedOnWalletType(appStore.wallet!.type);
|
||||
// the [chain] refers to the chain network that the nft is on
|
||||
// the [format] refers to the number format type of the responses
|
||||
// the [normalizedMetadata] field is a boolean that determines if
|
||||
@@ -101,7 +106,7 @@ abstract class NFTViewModelBase with Store {
|
||||
'deep-index.moralis.io',
|
||||
'/api/v2.2/nft/$tokenAddress/$tokenId',
|
||||
{
|
||||
"chain": "eth",
|
||||
"chain": chainName,
|
||||
"format": "decimal",
|
||||
"media_items": "false",
|
||||
"normalizeMetadata": "true",
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:cake_wallet/entities/fiat_currency.dart';
|
||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/nano/nano.dart';
|
||||
import 'package:cake_wallet/polygon/polygon.dart';
|
||||
import 'package:cw_core/transaction_direction.dart';
|
||||
import 'package:cw_core/transaction_info.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
@@ -91,6 +92,13 @@ class TransactionListItem extends ActionListItem with Keyable {
|
||||
cryptoAmount: ethereum!.formatterEthereumAmountToDouble(transaction: transaction),
|
||||
price: price);
|
||||
break;
|
||||
case WalletType.polygon:
|
||||
final asset = polygon!.assetOfTransaction(balanceViewModel.wallet, transaction);
|
||||
final price = balanceViewModel.fiatConvertationStore.prices[asset];
|
||||
amount = calculateFiatAmountRaw(
|
||||
cryptoAmount: polygon!.formatterPolygonAmountToDouble(transaction: transaction),
|
||||
price: price);
|
||||
break;
|
||||
case WalletType.nano:
|
||||
amount = calculateFiatAmountRaw(
|
||||
cryptoAmount: double.parse(nanoUtil!.getRawAsDecimalString(
|
||||
|
||||
@@ -37,6 +37,7 @@ abstract class EditBackupPasswordViewModelBase with Store {
|
||||
@action
|
||||
Future<void> save() async {
|
||||
final key = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
|
||||
await secureStorage.delete(key: key);
|
||||
await secureStorage.write(key: key, value: backupPassword);
|
||||
secretStore.write(key: key, value: backupPassword);
|
||||
}
|
||||
|
||||
@@ -28,10 +28,7 @@ abstract class ExchangeTradeViewModelBase with Store {
|
||||
required this.tradesStore,
|
||||
required this.sendViewModel})
|
||||
: trade = tradesStore.trade!,
|
||||
isSendable = tradesStore.trade!.from == wallet.currency ||
|
||||
tradesStore.trade!.provider == ExchangeProviderDescription.xmrto ||
|
||||
(wallet.currency == CryptoCurrency.eth &&
|
||||
tradesStore.trade!.from.tag == CryptoCurrency.eth.title),
|
||||
isSendable = _checkIfCanSend(tradesStore, wallet),
|
||||
items = ObservableList<ExchangeTradeItem>() {
|
||||
switch (trade.provider) {
|
||||
case ExchangeProviderDescription.changeNow:
|
||||
@@ -155,4 +152,19 @@ abstract class ExchangeTradeViewModelBase with Store {
|
||||
isCopied: true),
|
||||
]);
|
||||
}
|
||||
|
||||
static bool _checkIfCanSend(TradesStore tradesStore, WalletBase wallet) {
|
||||
bool _isEthToken() =>
|
||||
wallet.currency == CryptoCurrency.eth &&
|
||||
tradesStore.trade!.from.tag == CryptoCurrency.eth.title;
|
||||
|
||||
bool _isPolygonToken() =>
|
||||
wallet.currency == CryptoCurrency.maticpoly &&
|
||||
tradesStore.trade!.from.tag == CryptoCurrency.maticpoly.tag;
|
||||
|
||||
return tradesStore.trade!.from == wallet.currency ||
|
||||
tradesStore.trade!.provider == ExchangeProviderDescription.xmrto ||
|
||||
_isEthToken() ||
|
||||
_isPolygonToken();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import 'package:cake_wallet/exchange/trade.dart';
|
||||
import 'package:cake_wallet/exchange/trade_request.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/monero/monero.dart';
|
||||
import 'package:cake_wallet/polygon/polygon.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:cake_wallet/store/dashboard/trades_store.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
@@ -287,6 +288,8 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
return transactionPriority == ethereum!.getEthereumTransactionPrioritySlow();
|
||||
case WalletType.bitcoinCash:
|
||||
return transactionPriority == bitcoinCash!.getBitcoinCashTransactionPrioritySlow();
|
||||
case WalletType.polygon:
|
||||
return transactionPriority == polygon!.getPolygonTransactionPrioritySlow();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -626,6 +629,10 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
depositCurrency = CryptoCurrency.nano;
|
||||
receiveCurrency = CryptoCurrency.xmr;
|
||||
break;
|
||||
case WalletType.polygon:
|
||||
depositCurrency = CryptoCurrency.maticpoly;
|
||||
receiveCurrency = CryptoCurrency.xmr;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -713,6 +720,9 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
case WalletType.bitcoinCash:
|
||||
_settingsStore.priority[wallet.type] = bitcoinCash!.getDefaultTransactionPriority();
|
||||
break;
|
||||
case WalletType.polygon:
|
||||
_settingsStore.priority[wallet.type] = polygon!.getDefaultTransactionPriority();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -72,6 +72,9 @@ abstract class NodeListViewModelBase with Store {
|
||||
case WalletType.nano:
|
||||
node = getNanoDefaultNode(nodes: _nodeSource)!;
|
||||
break;
|
||||
case WalletType.polygon:
|
||||
node = getPolygonDefaultNode(nodes: _nodeSource)!;
|
||||
break;
|
||||
default:
|
||||
throw Exception('Unexpected wallet type: ${_appStore.wallet!.type}');
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
|
||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:cake_wallet/nano/nano.dart';
|
||||
import 'package:cake_wallet/polygon/polygon.dart';
|
||||
import 'package:cake_wallet/view_model/restore/restore_mode.dart';
|
||||
import 'package:cake_wallet/view_model/restore/restore_wallet.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
@@ -71,6 +72,9 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store
|
||||
case WalletType.ethereum:
|
||||
return ethereum!.createEthereumRestoreWalletFromPrivateKey(
|
||||
name: name, password: password, privateKey: restoreWallet.privateKey!);
|
||||
case WalletType.polygon:
|
||||
return polygon!.createPolygonRestoreWalletFromPrivateKey(
|
||||
name: name, password: password, privateKey: restoreWallet.privateKey!);
|
||||
default:
|
||||
throw Exception('Unexpected type: ${restoreWallet.type.toString()}');
|
||||
}
|
||||
@@ -95,6 +99,9 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store
|
||||
case WalletType.nano:
|
||||
return nano!.createNanoRestoreWalletFromSeedCredentials(
|
||||
name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password);
|
||||
case WalletType.polygon:
|
||||
return polygon!.createPolygonRestoreWalletFromSeedCredentials(
|
||||
name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password);
|
||||
default:
|
||||
throw Exception('Unexpected type: ${type.toString()}');
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ class RestoredWallet {
|
||||
factory RestoredWallet.fromSeed(Map<String, dynamic> json) {
|
||||
final height = json['height'] as String?;
|
||||
final mnemonic_seed = json['mnemonic_seed'] as String?;
|
||||
final seed = json['seed'] as String?;
|
||||
final seed = json['seed'] as String? ?? json['hexSeed'] as String?;
|
||||
return RestoredWallet(
|
||||
restoreMode: json['mode'] as WalletRestoreMode,
|
||||
type: json['type'] as WalletType,
|
||||
|
||||
@@ -10,6 +10,7 @@ import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:polyseed/polyseed.dart';
|
||||
|
||||
class WalletRestoreFromQRCode {
|
||||
WalletRestoreFromQRCode();
|
||||
@@ -25,6 +26,7 @@ class WalletRestoreFromQRCode {
|
||||
'litecoin-wallet': WalletType.litecoin,
|
||||
'litecoin_wallet': WalletType.litecoin,
|
||||
'ethereum-wallet': WalletType.ethereum,
|
||||
'polygon-wallet': WalletType.polygon,
|
||||
'nano-wallet': WalletType.nano,
|
||||
'nano_wallet': WalletType.nano,
|
||||
'bitcoincash': WalletType.bitcoinCash,
|
||||
@@ -51,7 +53,7 @@ class WalletRestoreFromQRCode {
|
||||
RegExp _getPattern(int wordCount) =>
|
||||
RegExp(r'(?<=\W|^)((?:\w+\s+){' + (wordCount - 1).toString() + r'}\w+)(?=\W|$)');
|
||||
|
||||
List<int> patternCounts = walletType == WalletType.monero ? [25, 14, 13] : [24, 18, 12];
|
||||
List<int> patternCounts = walletType == WalletType.monero ? [25, 16, 14, 13] : [24, 18, 12];
|
||||
|
||||
for (final count in patternCounts) {
|
||||
final pattern = _getPattern(count);
|
||||
@@ -123,12 +125,17 @@ class WalletRestoreFromQRCode {
|
||||
}
|
||||
|
||||
if (credentials['seed'] != null) {
|
||||
final seedValue = credentials['seed'];
|
||||
final seedValue = credentials['seed'] as String;
|
||||
final words = SeedValidator.getWordList(type: type, language: 'english');
|
||||
|
||||
if (type == WalletType.monero && Polyseed.isValidSeed(seedValue)) {
|
||||
return WalletRestoreMode.seed;
|
||||
}
|
||||
|
||||
seedValue.split(' ').forEach((element) {
|
||||
if (!words.contains(element)) {
|
||||
throw Exception(
|
||||
'Unexpected restore mode: mnemonic_seed is invalid or does\'t match wallet type');
|
||||
"Unexpected restore mode: mnemonic_seed is invalid or doesn't match wallet type");
|
||||
}
|
||||
});
|
||||
return WalletRestoreMode.seed;
|
||||
@@ -151,6 +158,23 @@ class WalletRestoreFromQRCode {
|
||||
return WalletRestoreMode.keys;
|
||||
}
|
||||
|
||||
if (type == WalletType.polygon && credentials.containsKey('private_key')) {
|
||||
final privateKey = credentials['private_key'] as String;
|
||||
if (privateKey.isEmpty) {
|
||||
throw Exception('Unexpected restore mode: private_key');
|
||||
}
|
||||
return WalletRestoreMode.keys;
|
||||
}
|
||||
|
||||
if ((type == WalletType.nano || type == WalletType.banano) &&
|
||||
credentials.containsKey('hexSeed')) {
|
||||
final hexSeed = credentials['hexSeed'] as String;
|
||||
if (hexSeed.isEmpty) {
|
||||
throw Exception('Unexpected restore mode: hexSeed');
|
||||
}
|
||||
return WalletRestoreMode.seed;
|
||||
}
|
||||
|
||||
throw Exception('Unexpected restore mode: restore params are invalid');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import 'package:cake_wallet/entities/seed_type.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
part 'seed_type_view_model.g.dart';
|
||||
|
||||
class SeedTypeViewModel = SeedTypeViewModelBase with _$SeedTypeViewModel;
|
||||
|
||||
abstract class SeedTypeViewModelBase with Store {
|
||||
SeedTypeViewModelBase(this._appStore);
|
||||
|
||||
@computed
|
||||
SeedType get moneroSeedType => _appStore.settingsStore.moneroSeedType;
|
||||
|
||||
@action
|
||||
void setMoneroSeedType(SeedType seedType) => _appStore.settingsStore.moneroSeedType = seedType;
|
||||
|
||||
final AppStore _appStore;
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import 'package:cake_wallet/entities/parse_address_from_domain.dart';
|
||||
import 'package:cake_wallet/entities/parsed_address.dart';
|
||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:cake_wallet/haven/haven.dart';
|
||||
import 'package:cake_wallet/polygon/polygon.dart';
|
||||
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||
import 'package:cake_wallet/src/screens/send/widgets/extract_address_from_parsed.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -27,7 +29,8 @@ const String cryptoNumberPattern = '0.0';
|
||||
class Output = OutputBase with _$Output;
|
||||
|
||||
abstract class OutputBase with Store {
|
||||
OutputBase(this._wallet, this._settingsStore, this._fiatConversationStore, this.cryptoCurrencyHandler)
|
||||
OutputBase(
|
||||
this._wallet, this._settingsStore, this._fiatConversationStore, this.cryptoCurrencyHandler)
|
||||
: _cryptoNumberFormat = NumberFormat(cryptoNumberPattern),
|
||||
key = UniqueKey(),
|
||||
sendAll = false,
|
||||
@@ -65,8 +68,7 @@ abstract class OutputBase with Store {
|
||||
|
||||
@computed
|
||||
bool get isParsedAddress =>
|
||||
parsedAddress.parseFrom != ParseFrom.notParsed &&
|
||||
parsedAddress.name.isNotEmpty;
|
||||
parsedAddress.parseFrom != ParseFrom.notParsed && parsedAddress.name.isNotEmpty;
|
||||
|
||||
@computed
|
||||
int get formattedCryptoAmount {
|
||||
@@ -83,8 +85,7 @@ abstract class OutputBase with Store {
|
||||
case WalletType.bitcoin:
|
||||
case WalletType.litecoin:
|
||||
case WalletType.bitcoinCash:
|
||||
_amount =
|
||||
bitcoin!.formatterStringDoubleToBitcoinAmount(_cryptoAmount);
|
||||
_amount = bitcoin!.formatterStringDoubleToBitcoinAmount(_cryptoAmount);
|
||||
break;
|
||||
case WalletType.haven:
|
||||
_amount = haven!.formatterMoneroParseAmount(amount: _cryptoAmount);
|
||||
@@ -92,6 +93,9 @@ abstract class OutputBase with Store {
|
||||
case WalletType.ethereum:
|
||||
_amount = ethereum!.formatterEthereumParseAmount(_cryptoAmount);
|
||||
break;
|
||||
case WalletType.polygon:
|
||||
_amount = polygon!.formatterPolygonParseAmount(_cryptoAmount);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -130,6 +134,10 @@ abstract class OutputBase with Store {
|
||||
if (_wallet.type == WalletType.ethereum) {
|
||||
return ethereum!.formatterEthereumAmountToDouble(amount: BigInt.from(fee));
|
||||
}
|
||||
|
||||
if (_wallet.type == WalletType.polygon) {
|
||||
return polygon!.formatterPolygonAmountToDouble(amount: BigInt.from(fee));
|
||||
}
|
||||
} catch (e) {
|
||||
print(e.toString());
|
||||
}
|
||||
@@ -140,10 +148,11 @@ abstract class OutputBase with Store {
|
||||
@computed
|
||||
String get estimatedFeeFiatAmount {
|
||||
try {
|
||||
final currency = _wallet.type == WalletType.ethereum ? _wallet.currency : cryptoCurrencyHandler();
|
||||
final currency = isEVMCompatibleChain(_wallet.type)
|
||||
? _wallet.currency
|
||||
: cryptoCurrencyHandler();
|
||||
final fiat = calculateFiatAmountRaw(
|
||||
price: _fiatConversationStore.prices[currency]!,
|
||||
cryptoAmount: estimatedFee);
|
||||
price: _fiatConversationStore.prices[currency]!, cryptoAmount: estimatedFee);
|
||||
return fiat;
|
||||
} catch (_) {
|
||||
return '0.00';
|
||||
@@ -240,6 +249,7 @@ abstract class OutputBase with Store {
|
||||
maximumFractionDigits = 12;
|
||||
break;
|
||||
case WalletType.ethereum:
|
||||
case WalletType.polygon:
|
||||
maximumFractionDigits = 12;
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -50,7 +50,9 @@ abstract class SendTemplateViewModelBase with Store {
|
||||
TemplateValidator get templateValidator => TemplateValidator();
|
||||
|
||||
bool get hasMultiRecipient =>
|
||||
_wallet.type != WalletType.haven && _wallet.type != WalletType.ethereum;
|
||||
_wallet.type != WalletType.haven &&
|
||||
_wallet.type != WalletType.ethereum &&
|
||||
_wallet.type != WalletType.polygon;
|
||||
|
||||
@computed
|
||||
CryptoCurrency get cryptoCurrency => _wallet.currency;
|
||||
|
||||
@@ -5,6 +5,8 @@ import 'package:cake_wallet/nano/nano.dart';
|
||||
import 'package:cake_wallet/core/wallet_change_listener_view_model.dart';
|
||||
import 'package:cake_wallet/entities/contact_record.dart';
|
||||
import 'package:cake_wallet/entities/wallet_contact.dart';
|
||||
import 'package:cake_wallet/polygon/polygon.dart';
|
||||
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart';
|
||||
@@ -42,7 +44,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
||||
void onWalletChange(wallet) {
|
||||
currencies = wallet.balance.keys.toList();
|
||||
selectedCryptoCurrency = wallet.currency;
|
||||
hasMultipleTokens = wallet.type == WalletType.ethereum;
|
||||
hasMultipleTokens = isEVMCompatibleChain(wallet.type);
|
||||
}
|
||||
|
||||
SendViewModelBase(
|
||||
@@ -55,7 +57,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
||||
) : state = InitialExecutionState(),
|
||||
currencies = appStore.wallet!.balance.keys.toList(),
|
||||
selectedCryptoCurrency = appStore.wallet!.currency,
|
||||
hasMultipleTokens = appStore.wallet!.type == WalletType.ethereum,
|
||||
hasMultipleTokens = isEVMCompatibleChain(appStore.wallet!.type),
|
||||
outputs = ObservableList<Output>(),
|
||||
_settingsStore = appStore.settingsStore,
|
||||
fiatFromSettings = appStore.settingsStore.fiatCurrency,
|
||||
@@ -119,7 +121,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
||||
try {
|
||||
if (pendingTransaction != null) {
|
||||
final currency =
|
||||
walletType == WalletType.ethereum ? wallet.currency : selectedCryptoCurrency;
|
||||
isEVMCompatibleChain(walletType) ? wallet.currency : selectedCryptoCurrency;
|
||||
final fiat = calculateFiatAmount(
|
||||
price: _fiatConversationStore.prices[currency]!,
|
||||
cryptoAmount: pendingTransaction!.feeFormatted);
|
||||
@@ -372,6 +374,9 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
||||
priority: priority!, currency: selectedCryptoCurrency);
|
||||
case WalletType.nano:
|
||||
return nano!.createNanoTransactionCredentials(outputs);
|
||||
case WalletType.polygon:
|
||||
return polygon!.createPolygonTransactionCredentials(outputs,
|
||||
priority: priority!, currency: selectedCryptoCurrency);
|
||||
default:
|
||||
throw Exception('Unexpected wallet type: ${wallet.type}');
|
||||
}
|
||||
@@ -412,11 +417,15 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
||||
WalletType walletType,
|
||||
CryptoCurrency currency,
|
||||
) {
|
||||
if (walletType == WalletType.ethereum || walletType == WalletType.haven) {
|
||||
if (walletType == WalletType.ethereum ||
|
||||
walletType == WalletType.polygon ||
|
||||
walletType == WalletType.haven) {
|
||||
if (error.contains('gas required exceeds allowance') ||
|
||||
error.contains('insufficient funds for')) {
|
||||
return S.current.do_not_have_enough_gas_asset(currency.toString());
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
return error;
|
||||
|
||||
@@ -13,14 +13,15 @@ import 'package:package_info/package_info.dart';
|
||||
|
||||
part 'other_settings_view_model.g.dart';
|
||||
|
||||
class OtherSettingsViewModel = OtherSettingsViewModelBase with _$OtherSettingsViewModel;
|
||||
class OtherSettingsViewModel = OtherSettingsViewModelBase
|
||||
with _$OtherSettingsViewModel;
|
||||
|
||||
abstract class OtherSettingsViewModelBase with Store {
|
||||
OtherSettingsViewModelBase(this._settingsStore, this._wallet)
|
||||
: walletType = _wallet.type,
|
||||
currentVersion = '' {
|
||||
PackageInfo.fromPlatform()
|
||||
.then((PackageInfo packageInfo) => currentVersion = packageInfo.version);
|
||||
PackageInfo.fromPlatform().then(
|
||||
(PackageInfo packageInfo) => currentVersion = packageInfo.version);
|
||||
|
||||
final priority = _settingsStore.priority[_wallet.type];
|
||||
final priorities = priorityForWalletType(_wallet.type);
|
||||
@@ -31,7 +32,8 @@ abstract class OtherSettingsViewModelBase with Store {
|
||||
}
|
||||
|
||||
final WalletType walletType;
|
||||
final WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> _wallet;
|
||||
final WalletBase<Balance, TransactionHistoryBase<TransactionInfo>,
|
||||
TransactionInfo> _wallet;
|
||||
|
||||
@observable
|
||||
String currentVersion;
|
||||
@@ -50,15 +52,19 @@ abstract class OtherSettingsViewModelBase with Store {
|
||||
}
|
||||
|
||||
@computed
|
||||
bool get changeRepresentativeEnabled {
|
||||
if (_wallet.type == WalletType.nano || _wallet.type == WalletType.banano) {
|
||||
return true;
|
||||
}
|
||||
bool get changeRepresentativeEnabled =>
|
||||
_wallet.type == WalletType.nano || _wallet.type == WalletType.banano;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
BuyProviderType get buyProviderType { return _settingsStore.defaultBuyProvider; }
|
||||
@computed
|
||||
bool get isEnabledBuyAction =>
|
||||
!_settingsStore.disableBuy && _wallet.type != WalletType.haven;
|
||||
|
||||
List<BuyProviderType> get availableBuyProviders =>
|
||||
BuyProviderType.getAvailableProviders(walletType);
|
||||
|
||||
BuyProviderType get buyProviderType =>
|
||||
_settingsStore.defaultBuyProviders[walletType] ??
|
||||
BuyProviderType.AskEachTime;
|
||||
|
||||
String getDisplayPriority(dynamic priority) {
|
||||
final _priority = priority as TransactionPriority;
|
||||
@@ -73,7 +79,7 @@ abstract class OtherSettingsViewModelBase with Store {
|
||||
return priority.toString();
|
||||
}
|
||||
|
||||
String getBuyProviderType (dynamic buyProviderType) {
|
||||
String getBuyProviderType(dynamic buyProviderType) {
|
||||
final _buyProviderType = buyProviderType as BuyProviderType;
|
||||
|
||||
return _buyProviderType.toString();
|
||||
@@ -83,6 +89,5 @@ abstract class OtherSettingsViewModelBase with Store {
|
||||
_settingsStore.priority[_wallet.type] = priority;
|
||||
|
||||
void onBuyProviderTypeSelected(BuyProviderType buyProviderType) =>
|
||||
_settingsStore.defaultBuyProvider = buyProviderType;
|
||||
|
||||
_settingsStore.defaultBuyProviders[walletType] = buyProviderType;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
|
||||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:cake_wallet/polygon/polygon.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cw_core/balance.dart';
|
||||
import 'package:cw_core/transaction_history.dart';
|
||||
@@ -12,8 +13,7 @@ import 'package:cake_wallet/entities/fiat_api_mode.dart';
|
||||
|
||||
part 'privacy_settings_view_model.g.dart';
|
||||
|
||||
class
|
||||
PrivacySettingsViewModel = PrivacySettingsViewModelBase with _$PrivacySettingsViewModel;
|
||||
class PrivacySettingsViewModel = PrivacySettingsViewModelBase with _$PrivacySettingsViewModel;
|
||||
|
||||
abstract class PrivacySettingsViewModelBase with Store {
|
||||
PrivacySettingsViewModelBase(this._settingsStore, this._wallet);
|
||||
@@ -58,6 +58,9 @@ abstract class PrivacySettingsViewModelBase with Store {
|
||||
@computed
|
||||
bool get useEtherscan => _settingsStore.useEtherscan;
|
||||
|
||||
@computed
|
||||
bool get usePolygonScan => _settingsStore.usePolygonScan;
|
||||
|
||||
@computed
|
||||
bool get lookupTwitter => _settingsStore.lookupsTwitter;
|
||||
|
||||
@@ -78,6 +81,8 @@ abstract class PrivacySettingsViewModelBase with Store {
|
||||
|
||||
bool get canUseEtherscan => _wallet.type == WalletType.ethereum;
|
||||
|
||||
bool get canUsePolygonScan => _wallet.type == WalletType.polygon;
|
||||
|
||||
@action
|
||||
void setShouldSaveRecipientAddress(bool value) =>
|
||||
_settingsStore.shouldSaveRecipientAddress = value;
|
||||
@@ -120,4 +125,10 @@ abstract class PrivacySettingsViewModelBase with Store {
|
||||
_settingsStore.useEtherscan = value;
|
||||
ethereum!.updateEtherscanUsageState(_wallet, value);
|
||||
}
|
||||
|
||||
@action
|
||||
void setUsePolygonScan(bool value) {
|
||||
_settingsStore.usePolygonScan = value;
|
||||
polygon!.updatePolygonScanUsageState(_wallet, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,9 @@ abstract class TransactionDetailsViewModelBase with Store {
|
||||
case WalletType.nano:
|
||||
_addNanoListItems(tx, dateFormat);
|
||||
break;
|
||||
case WalletType.polygon:
|
||||
_addPolygonListItems(tx, dateFormat);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -125,7 +128,9 @@ abstract class TransactionDetailsViewModelBase with Store {
|
||||
case WalletType.nano:
|
||||
return 'https://nanolooker.com/block/${txId}';
|
||||
case WalletType.banano:
|
||||
return 'https://bananolooker.com/block/${txId}';
|
||||
return 'https://bananolooker.com/block/${txId}';
|
||||
case WalletType.polygon:
|
||||
return 'https://polygonscan.com/tx/${txId}';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
@@ -148,6 +153,8 @@ abstract class TransactionDetailsViewModelBase with Store {
|
||||
return S.current.view_transaction_on + 'nanolooker.com';
|
||||
case WalletType.banano:
|
||||
return S.current.view_transaction_on + 'bananolooker.com';
|
||||
case WalletType.polygon:
|
||||
return S.current.view_transaction_on + 'polygonscan.com';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
@@ -237,7 +244,6 @@ abstract class TransactionDetailsViewModelBase with Store {
|
||||
items.addAll(_items);
|
||||
}
|
||||
|
||||
|
||||
void _addNanoListItems(TransactionInfo tx, DateFormat dateFormat) {
|
||||
final _items = [
|
||||
StandartListItem(title: S.current.transaction_details_transaction_id, value: tx.id),
|
||||
@@ -250,4 +256,21 @@ abstract class TransactionDetailsViewModelBase with Store {
|
||||
|
||||
items.addAll(_items);
|
||||
}
|
||||
|
||||
void _addPolygonListItems(TransactionInfo tx, DateFormat dateFormat) {
|
||||
final _items = [
|
||||
StandartListItem(title: S.current.transaction_details_transaction_id, value: tx.id),
|
||||
StandartListItem(
|
||||
title: S.current.transaction_details_date, value: dateFormat.format(tx.date)),
|
||||
StandartListItem(title: S.current.confirmations, value: tx.confirmations.toString()),
|
||||
StandartListItem(title: S.current.transaction_details_height, value: '${tx.height}'),
|
||||
StandartListItem(title: S.current.transaction_details_amount, value: tx.amountFormatted()),
|
||||
if (tx.feeFormatted()?.isNotEmpty ?? false)
|
||||
StandartListItem(title: S.current.transaction_details_fee, value: tx.feeFormatted()!),
|
||||
if (showRecipientAddress && tx.to != null)
|
||||
StandartListItem(title: S.current.transaction_details_recipient_address, value: tx.to!),
|
||||
];
|
||||
|
||||
items.addAll(_items);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:cake_wallet/core/wallet_change_listener_view_model.dart';
|
||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:cake_wallet/entities/fiat_currency.dart';
|
||||
import 'package:cake_wallet/polygon/polygon.dart';
|
||||
import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart';
|
||||
import 'package:cake_wallet/store/yat/yat_store.dart';
|
||||
import 'package:cw_core/currency.dart';
|
||||
@@ -139,6 +140,22 @@ class NanoURI extends PaymentURI {
|
||||
}
|
||||
}
|
||||
|
||||
class PolygonURI extends PaymentURI {
|
||||
PolygonURI({required String amount, required String address})
|
||||
: super(amount: amount, address: address);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
var base = 'polygon:' + address;
|
||||
|
||||
if (amount.isNotEmpty) {
|
||||
base += '?amount=${amount.replaceAll(',', '.')}';
|
||||
}
|
||||
|
||||
return base;
|
||||
}
|
||||
}
|
||||
|
||||
abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewModel with Store {
|
||||
WalletAddressListViewModelBase({
|
||||
required AppStore appStore,
|
||||
@@ -216,6 +233,10 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
|
||||
return NanoURI(amount: amount, address: address.address);
|
||||
}
|
||||
|
||||
if (wallet.type == WalletType.polygon) {
|
||||
return PolygonURI(amount: amount, address: address.address);
|
||||
}
|
||||
|
||||
throw Exception('Unexpected type: ${type.toString()}');
|
||||
}
|
||||
|
||||
@@ -272,6 +293,12 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
|
||||
addressList.add(WalletAddressListItem(isPrimary: true, name: null, address: primaryAddress));
|
||||
}
|
||||
|
||||
if (wallet.type == WalletType.polygon) {
|
||||
final primaryAddress = polygon!.getAddress(wallet);
|
||||
|
||||
addressList.add(WalletAddressListItem(isPrimary: true, name: null, address: primaryAddress));
|
||||
}
|
||||
|
||||
return addressList;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:cw_core/transaction_direction.dart';
|
||||
import 'package:cw_core/transaction_info.dart';
|
||||
@@ -9,6 +10,7 @@ import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.d
|
||||
import 'package:cake_wallet/monero/monero.dart';
|
||||
import 'package:cake_wallet/haven/haven.dart';
|
||||
import 'package:cw_monero/api/wallet.dart' as monero_wallet;
|
||||
import 'package:polyseed/polyseed.dart';
|
||||
|
||||
part 'wallet_keys_view_model.g.dart';
|
||||
|
||||
@@ -19,7 +21,8 @@ abstract class WalletKeysViewModelBase with Store {
|
||||
: title = _appStore.wallet!.type == WalletType.bitcoin ||
|
||||
_appStore.wallet!.type == WalletType.litecoin ||
|
||||
_appStore.wallet!.type == WalletType.bitcoinCash ||
|
||||
_appStore.wallet!.type == WalletType.ethereum
|
||||
_appStore.wallet!.type == WalletType.ethereum ||
|
||||
_appStore.wallet!.type == WalletType.polygon
|
||||
? S.current.wallet_seed
|
||||
: S.current.wallet_keys,
|
||||
_restoreHeight = _appStore.wallet!.walletInfo.restoreHeight,
|
||||
@@ -72,6 +75,15 @@ abstract class WalletKeysViewModelBase with Store {
|
||||
StandartListItem(title: S.current.view_key_private, value: keys['privateViewKey']!),
|
||||
StandartListItem(title: S.current.wallet_seed, value: _appStore.wallet!.seed!),
|
||||
]);
|
||||
|
||||
if (_appStore.wallet?.seed != null && Polyseed.isValidSeed(_appStore.wallet!.seed!)) {
|
||||
final lang = PolyseedLang.getByPhrase(_appStore.wallet!.seed!);
|
||||
final legacyLang = _getLegacySeedLang(lang);
|
||||
final legacySeed =
|
||||
Polyseed.decode(_appStore.wallet!.seed!, lang, PolyseedCoin.POLYSEED_MONERO)
|
||||
.toLegacySeed(legacyLang);
|
||||
items.add(StandartListItem(title: S.current.wallet_seed_legacy, value: legacySeed));
|
||||
}
|
||||
}
|
||||
|
||||
if (_appStore.wallet!.type == WalletType.haven) {
|
||||
@@ -98,7 +110,7 @@ abstract class WalletKeysViewModelBase with Store {
|
||||
]);
|
||||
}
|
||||
|
||||
if (_appStore.wallet!.type == WalletType.ethereum) {
|
||||
if (isEVMCompatibleChain(_appStore.wallet!.type)) {
|
||||
items.addAll([
|
||||
if (_appStore.wallet!.privateKey != null)
|
||||
StandartListItem(title: S.current.private_key, value: _appStore.wallet!.privateKey!),
|
||||
@@ -107,19 +119,18 @@ abstract class WalletKeysViewModelBase with Store {
|
||||
]);
|
||||
}
|
||||
|
||||
if (_appStore.wallet!.type == WalletType.nano || _appStore.wallet!.type == WalletType.banano) {
|
||||
bool nanoBased =
|
||||
_appStore.wallet!.type == WalletType.nano || _appStore.wallet!.type == WalletType.banano;
|
||||
|
||||
// we don't necessarily have the seed phrase for nano / banano:
|
||||
if (_appStore.wallet!.seed != null) {
|
||||
items.addAll([
|
||||
StandartListItem(title: S.current.wallet_seed, value: _appStore.wallet!.seed!),
|
||||
]);
|
||||
}
|
||||
|
||||
// we always have the hex version of the seed:
|
||||
if (nanoBased) {
|
||||
// we always have the hex version of the seed and private key:
|
||||
items.addAll([
|
||||
if (_appStore.wallet!.seed != null)
|
||||
StandartListItem(title: S.current.wallet_seed, value: _appStore.wallet!.seed!),
|
||||
if (_appStore.wallet!.hexSeed != null)
|
||||
StandartListItem(title: S.current.seed_hex_form, value: _appStore.wallet!.hexSeed!),
|
||||
if (_appStore.wallet!.privateKey != null)
|
||||
StandartListItem(title: S.current.spend_key_private, value: _appStore.wallet!.privateKey!),
|
||||
StandartListItem(title: S.current.private_key, value: _appStore.wallet!.privateKey!),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -152,6 +163,8 @@ abstract class WalletKeysViewModelBase with Store {
|
||||
return 'nano-wallet';
|
||||
case WalletType.banano:
|
||||
return 'banano-wallet';
|
||||
case WalletType.polygon:
|
||||
return 'polygon-wallet';
|
||||
default:
|
||||
throw Exception('Unexpected wallet type: ${_appStore.wallet!.toString()}');
|
||||
}
|
||||
@@ -172,7 +185,10 @@ abstract class WalletKeysViewModelBase with Store {
|
||||
final restoreHeightResult = await restoreHeight;
|
||||
return {
|
||||
if (_appStore.wallet!.seed != null) 'seed': _appStore.wallet!.seed!,
|
||||
if (_appStore.wallet!.privateKey != null) 'private_key': _appStore.wallet!.privateKey!,
|
||||
if (_appStore.wallet!.seed == null && _appStore.wallet!.hexSeed != null)
|
||||
'hexSeed': _appStore.wallet!.hexSeed!,
|
||||
if (_appStore.wallet!.seed == null && _appStore.wallet!.privateKey != null)
|
||||
'private_key': _appStore.wallet!.privateKey!,
|
||||
if (restoreHeightResult != null) ...{'height': restoreHeightResult}
|
||||
};
|
||||
}
|
||||
@@ -201,4 +217,23 @@ abstract class WalletKeysViewModelBase with Store {
|
||||
}
|
||||
|
||||
String getRoundedRestoreHeight(int height) => ((height / 1000).floor() * 1000).toString();
|
||||
|
||||
LegacySeedLang _getLegacySeedLang(PolyseedLang lang) {
|
||||
switch (lang.nameEnglish) {
|
||||
case "Spanish":
|
||||
return LegacySeedLang.getByEnglishName("Spanish");
|
||||
case "French":
|
||||
return LegacySeedLang.getByEnglishName("French");
|
||||
case "Italian":
|
||||
return LegacySeedLang.getByEnglishName("Italian");
|
||||
case "Japanese":
|
||||
return LegacySeedLang.getByEnglishName("Japanese");
|
||||
case "Portuguese":
|
||||
return LegacySeedLang.getByEnglishName("Portuguese");
|
||||
case "Chinese (Simplified)":
|
||||
return LegacySeedLang.getByEnglishName("Chinese (simplified)");
|
||||
default:
|
||||
return LegacySeedLang.getByEnglishName("English");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import 'package:cake_wallet/view_model/restore/restore_wallet.dart';
|
||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
@@ -17,6 +15,8 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||
import 'package:cake_wallet/haven/haven.dart';
|
||||
import 'advanced_privacy_settings_view_model.dart';
|
||||
|
||||
import '../polygon/polygon.dart';
|
||||
|
||||
part 'wallet_new_vm.g.dart';
|
||||
|
||||
class WalletNewVM = WalletNewVMBase with _$WalletNewVM;
|
||||
@@ -47,25 +47,30 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
|
||||
}
|
||||
}
|
||||
|
||||
bool get hasSeedType => type == WalletType.monero;
|
||||
|
||||
@override
|
||||
WalletCredentials getCredentials(dynamic options) {
|
||||
WalletCredentials getCredentials(dynamic _options) {
|
||||
final options = _options as List<dynamic>?;
|
||||
switch (type) {
|
||||
case WalletType.monero:
|
||||
return monero!.createMoneroNewWalletCredentials(
|
||||
name: name, language: options as String);
|
||||
name: name, language: options!.first as String, isPolyseed: options.last as bool);
|
||||
case WalletType.bitcoin:
|
||||
return bitcoin!.createBitcoinNewWalletCredentials(name: name);
|
||||
case WalletType.litecoin:
|
||||
return bitcoin!.createBitcoinNewWalletCredentials(name: name);
|
||||
case WalletType.haven:
|
||||
return haven!.createHavenNewWalletCredentials(
|
||||
name: name, language: options as String);
|
||||
name: name, language: options!.first as String);
|
||||
case WalletType.ethereum:
|
||||
return ethereum!.createEthereumNewWalletCredentials(name: name);
|
||||
case WalletType.bitcoinCash:
|
||||
return bitcoinCash!.createBitcoinCashNewWalletCredentials(name: name);
|
||||
case WalletType.nano:
|
||||
return nano!.createNanoNewWalletCredentials(name: name);
|
||||
case WalletType.polygon:
|
||||
return polygon!.createPolygonNewWalletCredentials(name: name);
|
||||
default:
|
||||
throw Exception('Unexpected type: ${type.toString()}');
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/nano/nano.dart';
|
||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
|
||||
import 'package:cake_wallet/polygon/polygon.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
@@ -28,7 +29,10 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
||||
: hasSeedLanguageSelector = type == WalletType.monero || type == WalletType.haven,
|
||||
hasBlockchainHeightLanguageSelector = type == WalletType.monero || type == WalletType.haven,
|
||||
hasRestoreFromPrivateKey =
|
||||
type == WalletType.ethereum || type == WalletType.nano || type == WalletType.banano,
|
||||
type == WalletType.ethereum ||
|
||||
type == WalletType.polygon ||
|
||||
type == WalletType.nano ||
|
||||
type == WalletType.banano,
|
||||
isButtonEnabled = false,
|
||||
mode = WalletRestoreMode.seed,
|
||||
super(appStore, walletInfoSource, walletCreationService, type: type, isRecovery: true) {
|
||||
@@ -36,6 +40,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
||||
case WalletType.monero:
|
||||
case WalletType.haven:
|
||||
case WalletType.ethereum:
|
||||
case WalletType.polygon:
|
||||
availableModes = WalletRestoreMode.values;
|
||||
break;
|
||||
case WalletType.nano:
|
||||
@@ -107,6 +112,12 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
||||
mnemonic: seed,
|
||||
password: password,
|
||||
derivationType: derivationType);
|
||||
case WalletType.polygon:
|
||||
return polygon!.createPolygonRestoreWalletFromSeedCredentials(
|
||||
name: name,
|
||||
mnemonic: seed,
|
||||
password: password,
|
||||
);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -153,6 +164,12 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
||||
password: password,
|
||||
seedKey: options['private_key'] as String,
|
||||
derivationType: options["derivationType"] as DerivationType);
|
||||
case WalletType.polygon:
|
||||
return polygon!.createPolygonRestoreWalletFromPrivateKey(
|
||||
name: name,
|
||||
password: password,
|
||||
privateKey: options['private_key'] as String,
|
||||
);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user