cake_wallet/lib/view_model/wallet_creation_vm.dart
Matthew Fosse 50825a62c1
Mweb enhancements 3 (#1744)
* version 4.20.0

* update build numbers

* UI updates and script fix for ios bundle identifier

* disable mweb for desktop

* change hardcoded ltc server ip address
electrum connection enhancement

* MWEB enhancements 2.0 (#1735)

* additional logging and minor fixes

* additional logging and minor fixes

* addresses pt.1

* Allow Wallet Group Names to be the same as Wallet Names (#1730)

* fix: Issues with imaging

* fix: Allow group names to be the same as wallet names

* fix: Bug with wallet grouping when a wallet is minimized

* fix: Bug with wallet grouping when a wallet is minimized

* logs of fixes and experimental changes, close wallet before opening next

* save

* fix icon

* fixes

* [skip ci] updates

* [skip ci] updates

* updates

* minor optimizations

* fix for when switching between wallets

* [skip ci] updates

* [skip ci] updates

* Update cw_bitcoin/lib/litecoin_wallet.dart

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>

* Update cw_bitcoin/lib/litecoin_wallet.dart

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>

* mobx

* mostly logging

* stream fix pt.1 [skip ci]

* updates

* some fixes and enhancements

* [skip ci] minor

* potential partial fix for streamsink closed

* fix stream sink closed errors

* fix mweb logo colors

* save

* minor enhancements [skip ci]

* save

* experimental

* minor

* minor [skip ci]

---------

Co-authored-by: David Adegoke <64401859+Blazebrain@users.noreply.github.com>
Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>

* fix menu list removing from original list

* detach sync status from mwebsyncstatus

* minor

* keep sync status in sync where necessary

* minor

* wip

* appears to work?

* updates

* prevent mwebd from submitting non mweb transactions

* fix unspent coins info not persisting for mweb coins + other minor fixes

* [skip ci] minor

* Polish MWEB card UI

* make sure current chain tip is updated correctly [skip ci]

* [skip ci] review fixes

* [skip ci] detect mweb outputs more thoroughly (fix peg-in commit error)

* fix change address on send ui

* fix qr code scan issue

* get segwit address for pegout even if mweb is selected on the receive screen [skip ci]

* - Fix adding nodes twice
- Fix mempool API parsing error

* (potentially) fix duplicate tx history bug

* [skip ci] fix bc1 address

* don't show contacts prompt on pegin/out + potential unconfirmed balance fixes

* [skip ci] minor cleanup

* fix mweb input detection

* fix showing mweb address for non-mweb transactions

---------

Co-authored-by: OmarHatem <omarh.ismail1@gmail.com>
Co-authored-by: David Adegoke <64401859+Blazebrain@users.noreply.github.com>
Co-authored-by: tuxpizza <tuxsudo@tux.pizza>
2024-10-19 03:05:48 +03:00

240 lines
8.3 KiB
Dart

import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/core/execution_state.dart';
import 'package:cake_wallet/core/wallet_creation_service.dart';
import 'package:cake_wallet/di.dart';
import 'package:cake_wallet/entities/background_tasks.dart';
import 'package:cake_wallet/entities/generate_name.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/nano/nano.dart';
import 'package:cake_wallet/store/app_store.dart';
import 'package:cake_wallet/store/settings_store.dart';
import 'package:cake_wallet/view_model/restore/restore_mode.dart';
import 'package:cake_wallet/view_model/restore/restore_wallet.dart';
import 'package:cake_wallet/view_model/seed_settings_view_model.dart';
import 'package:cw_core/pathForWallet.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_credentials.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
import 'package:polyseed/polyseed.dart';
part 'wallet_creation_vm.g.dart';
class WalletCreationVM = WalletCreationVMBase with _$WalletCreationVM;
abstract class WalletCreationVMBase with Store {
WalletCreationVMBase(this._appStore, this._walletInfoSource, this.walletCreationService,
this.seedSettingsViewModel,
{required this.type, required this.isRecovery})
: state = InitialExecutionState(),
name = '';
@observable
bool _useTestnet = false;
@computed
bool get useTestnet => _useTestnet;
@observable
String name;
@observable
ExecutionState state;
@observable
String? walletPassword;
@observable
String? repeatedWalletPassword;
bool get hasWalletPassword => SettingsStoreBase.walletPasswordDirectInput;
WalletType type;
final bool isRecovery;
final WalletCreationService walletCreationService;
final Box<WalletInfo> _walletInfoSource;
final AppStore _appStore;
final SeedSettingsViewModel seedSettingsViewModel;
bool isPolyseed(String seed) =>
(type == WalletType.monero || type == WalletType.wownero) &&
(Polyseed.isValidSeed(seed) || (seed.split(" ").length == 14));
bool nameExists(String name) => walletCreationService.exists(name);
bool typeExists(WalletType type) => walletCreationService.typeExists(type);
Future<void> create({dynamic options, RestoredWallet? restoreWallet}) async {
final type = restoreWallet?.type ?? this.type;
try {
state = IsExecutingState();
if (name.isEmpty) {
name = await generateName();
}
if (hasWalletPassword && (walletPassword?.isEmpty ?? true)) {
throw Exception(S.current.wallet_password_is_empty);
}
if (hasWalletPassword && walletPassword != repeatedWalletPassword) {
throw Exception(S.current.repeated_password_is_incorrect);
}
walletCreationService.checkIfExists(name);
final dirPath = await pathForWalletDir(name: name, type: type);
final path = await pathForWallet(name: name, type: type);
final credentials = restoreWallet != null
? await getWalletCredentialsFromQRCredentials(restoreWallet)
: getCredentials(options);
final walletInfo = WalletInfo.external(
id: WalletBase.idFor(name, type),
name: name,
type: type,
isRecovery: isRecovery,
restoreHeight: credentials.height ?? 0,
date: DateTime.now(),
path: path,
dirPath: dirPath,
address: '',
showIntroCakePayCard: (!walletCreationService.typeExists(type)) && type != WalletType.haven,
derivationInfo: credentials.derivationInfo ?? getDefaultCreateDerivation(),
hardwareWalletType: credentials.hardwareWalletType,
parentAddress: credentials.parentAddress,
);
credentials.walletInfo = walletInfo;
final wallet = restoreWallet != null
? await processFromRestoredWallet(credentials, restoreWallet)
: await process(credentials);
walletInfo.address = wallet.walletAddresses.address;
await _walletInfoSource.add(walletInfo);
await _appStore.changeCurrentWallet(wallet);
getIt.get<BackgroundTasks>().registerSyncTask();
_appStore.authenticationStore.allowed();
state = ExecutedSuccessfullyState();
} catch (e, s) {
print("error: $e");
print("stack: $s");
state = FailureState(e.toString());
}
}
DerivationInfo? getDefaultCreateDerivation() {
final useBip39ForBitcoin = seedSettingsViewModel.bitcoinSeedType.type == DerivationType.bip39;
final useBip39ForNano = seedSettingsViewModel.nanoSeedType.type == DerivationType.bip39;
switch (type) {
case WalletType.nano:
if (useBip39ForNano) {
return DerivationInfo(derivationType: DerivationType.bip39);
}
return DerivationInfo(derivationType: DerivationType.nano);
case WalletType.bitcoin:
if (useBip39ForBitcoin) {
return DerivationInfo(
derivationType: DerivationType.bip39,
derivationPath: "m/84'/0'/0'",
description: "Standard BIP84 native segwit",
scriptType: "p2wpkh",
);
}
return bitcoin!.getElectrumDerivations()[DerivationType.electrum]!.first;
case WalletType.litecoin:
if (useBip39ForBitcoin) {
return DerivationInfo(
derivationType: DerivationType.bip39,
derivationPath: "m/84'/2'/0'",
description: "Default Litecoin",
scriptType: "p2wpkh",
);
}
return bitcoin!.getElectrumDerivations()[DerivationType.electrum]!.first;
default:
return null;
}
}
DerivationInfo? getCommonRestoreDerivation() {
final useElectrum = seedSettingsViewModel.bitcoinSeedType.type == DerivationType.electrum;
final useNanoStandard = seedSettingsViewModel.nanoSeedType.type == DerivationType.nano;
switch (this.type) {
case WalletType.nano:
if (useNanoStandard) {
return DerivationInfo(derivationType: DerivationType.nano);
}
return DerivationInfo(derivationType: DerivationType.bip39);
case WalletType.bitcoin:
if (useElectrum) {
return bitcoin!.getElectrumDerivations()[DerivationType.electrum]!.first;
}
return DerivationInfo(
derivationType: DerivationType.bip39,
derivationPath: "m/84'/0'/0'/0",
description: "Standard BIP84 native segwit",
scriptType: "p2wpkh",
);
case WalletType.litecoin:
if (useElectrum) {
return bitcoin!.getElectrumDerivations()[DerivationType.electrum]!.first;
}
return DerivationInfo(
derivationType: DerivationType.bip39,
derivationPath: "m/84'/2'/0'/0",
description: "Standard BIP84 native segwit (litecoin)",
scriptType: "p2wpkh",
);
default:
return null;
}
}
Future<List<DerivationInfo>> getDerivationInfoFromQRCredentials(
RestoredWallet restoreWallet) async {
var list = <DerivationInfo>[];
final walletType = restoreWallet.type;
var appStore = getIt.get<AppStore>();
var node = appStore.settingsStore.getCurrentNode(walletType);
switch (walletType) {
case WalletType.bitcoin:
case WalletType.litecoin:
final derivationList = await bitcoin!.getDerivationsFromMnemonic(
mnemonic: restoreWallet.mnemonicSeed!,
node: node,
passphrase: restoreWallet.passphrase,
);
if (derivationList.firstOrNull?.transactionsCount == 0 && derivationList.length > 1)
return [];
return derivationList;
case WalletType.nano:
return nanoUtil!.getDerivationsFromMnemonic(
mnemonic: restoreWallet.mnemonicSeed!,
node: node,
);
default:
break;
}
return list;
}
WalletCredentials getCredentials(dynamic options) => throw UnimplementedError();
Future<WalletBase> process(WalletCredentials credentials) => throw UnimplementedError();
Future<WalletCredentials> getWalletCredentialsFromQRCredentials(
RestoredWallet restoreWallet) async =>
throw UnimplementedError();
Future<WalletBase> processFromRestoredWallet(
WalletCredentials credentials, RestoredWallet restoreWallet) =>
throw UnimplementedError();
@action
void toggleUseTestnet(bool? value) {
_useTestnet = value ?? !_useTestnet;
}
}