debatably better refactoring of derivationInfo, migration needed

This commit is contained in:
fosse 2023-10-09 14:08:14 -04:00
parent d4c8a1d8f6
commit ae97e50bf4
15 changed files with 127 additions and 106 deletions

View file

@ -38,7 +38,6 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
initialBalance: initialBalance,
seedBytes: seedBytes,
currency: CryptoCurrency.btc) {
// in a standard BIP44 wallet, mainHd derivation path = m/84'/0'/0'/0 (account 0, index unspecified here)
// the sideHd derivation path = m/84'/0'/0'/1 (account 1, index unspecified here)
walletAddresses = BitcoinWalletAddresses(walletInfo,
@ -47,9 +46,11 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
initialRegularAddressIndex: initialRegularAddressIndex,
initialChangeAddressIndex: initialChangeAddressIndex,
mainHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType)
.derivePath(walletInfo.derivationPath!),
sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath(
walletInfo.derivationPath!.substring(0, walletInfo.derivationPath!.length - 1) + "1"),
.derivePath(walletInfo.derivationInfo!.derivationPath!),
sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath(walletInfo
.derivationInfo!.derivationPath!
.substring(0, walletInfo.derivationInfo!.derivationPath!.length - 1) +
"1"),
networkType: networkType);
}
@ -64,14 +65,14 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
int initialChangeAddressIndex = 0}) async {
late Uint8List seedBytes;
switch (walletInfo.derivationType) {
case DerivationType.electrum2:
seedBytes = await mnemonicToSeedBytes(mnemonic);
break;
switch (walletInfo.derivationInfo?.derivationType) {
case DerivationType.bip39:
default:
seedBytes = await bip39.mnemonicToSeed(mnemonic);
break;
case DerivationType.electrum2:
default:
seedBytes = await mnemonicToSeedBytes(mnemonic);
break;
}
return BitcoinWallet(
@ -94,20 +95,17 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
}) async {
final snp = await ElectrumWallletSnapshot.load(name, walletInfo.type, password);
walletInfo.derivationType = snp.derivationType;
walletInfo.derivationPath = snp.derivationPath;
walletInfo.derivationInfo ??= DerivationInfo(
derivationType: snp.derivationType ?? DerivationType.electrum2,
derivationPath: snp.derivationPath,
);
// set the default if not present:
if (walletInfo.derivationPath == null) {
walletInfo.derivationPath = "m/0'/1";
}
if (walletInfo.derivationType == null) {
walletInfo.derivationType = DerivationType.electrum2;
}
walletInfo.derivationInfo!.derivationPath = snp.derivationPath ?? "m/0'/1";
late Uint8List seedBytes;
switch (walletInfo.derivationType) {
switch (walletInfo.derivationInfo!.derivationType) {
case DerivationType.electrum2:
seedBytes = await mnemonicToSeedBytes(snp.mnemonic);
break;
@ -128,4 +126,4 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
initialRegularAddressIndex: snp.regularAddressIndex,
initialChangeAddressIndex: snp.changeAddressIndex);
}
}
}

View file

@ -2,8 +2,11 @@ import 'package:cw_core/wallet_credentials.dart';
import 'package:cw_core/wallet_info.dart';
class BitcoinNewWalletCredentials extends WalletCredentials {
BitcoinNewWalletCredentials({required String name, WalletInfo? walletInfo})
BitcoinNewWalletCredentials(
{required String name, WalletInfo? walletInfo, this.derivationType, this.derivationPath})
: super(name: name, walletInfo: walletInfo);
DerivationType? derivationType;
String? derivationPath;
}
class BitcoinRestoreWalletFromSeedCredentials extends WalletCredentials {
@ -11,16 +14,17 @@ class BitcoinRestoreWalletFromSeedCredentials extends WalletCredentials {
required String name,
required String password,
required this.mnemonic,
WalletInfo? walletInfo,
DerivationType? derivationType,
String? derivationPath,
WalletInfo? walletInfo,
}) : super(
name: name,
password: password,
walletInfo: walletInfo,
derivationType: derivationType,
derivationPath: derivationPath,
);
name: name,
password: password,
walletInfo: walletInfo,
derivationInfo: DerivationInfo(
derivationType: derivationType,
derivationPath: derivationPath,
));
final String mnemonic;
}
@ -31,4 +35,4 @@ class BitcoinRestoreWalletFromWIFCredentials extends WalletCredentials {
: super(name: name, password: password, walletInfo: walletInfo);
final String wif;
}
}

View file

@ -46,13 +46,13 @@ class BitcoinWalletService extends WalletService<BitcoinNewWalletCredentials,
@override
Future<BitcoinWallet> create(BitcoinNewWalletCredentials credentials) async {
// default derivation type/path for bitcoin wallets:
if (credentials.walletInfo!.derivationType == null) {
credentials.walletInfo!.derivationType = DerivationType.electrum2;
}
if (credentials.walletInfo!.derivationPath == null) {
credentials.walletInfo!.derivationPath = "m/0'/1";
}
// set default if not present:
DerivationType derivationType = credentials.derivationType ?? DerivationType.electrum2;
String derivationPath = credentials.derivationPath ?? "m/0'/1";
// only set if not in the walletInfo already:
credentials.walletInfo!.derivationInfo ??=
DerivationInfo(derivationType: derivationType, derivationPath: derivationPath);
final wallet = await BitcoinWalletBase.create(
mnemonic: await generateElectrumMnemonic(strength: 132),
password: credentials.password!,

View file

@ -13,4 +13,5 @@ const ADDRESS_INFO_TYPE_ID = 11;
const ERC20_TOKEN_TYPE_ID = 12;
const NANO_ACCOUNT_TYPE_ID = 13;
const POW_NODE_TYPE_ID = 14;
const DERIVATION_TYPE_TYPE_ID = 15;
const DERIVATION_TYPE_TYPE_ID = 15;
const DERIVATION_INFO_TYPE_ID = 16;

View file

@ -6,14 +6,12 @@ abstract class WalletCredentials {
this.height,
this.walletInfo,
this.password,
this.derivationType,
this.derivationPath,
this.derivationInfo,
});
final String name;
final int? height;
String? password;
DerivationType? derivationType;
String? derivationPath;
WalletInfo? walletInfo;
DerivationInfo? derivationInfo;
}

View file

@ -21,10 +21,10 @@ enum DerivationType {
@HiveField(5)
electrum2,
}
class DerivationInfo {
@HiveType(typeId: DerivationInfo.typeId)
class DerivationInfo extends HiveObject {
DerivationInfo({
required this.derivationType,
this.derivationType,
this.derivationPath,
this.balance = "",
this.address = "",
@ -33,10 +33,12 @@ class DerivationInfo {
this.description,
});
static const typeId = DERIVATION_INFO_TYPE_ID;
String balance;
String address;
int height;
final DerivationType derivationType;
DerivationType? derivationType;
String? derivationPath;
final String? script_type;
final String? description;
@ -57,8 +59,7 @@ class WalletInfo extends HiveObject {
this.yatEid,
this.yatLastUsedAddressRaw,
this.showIntroCakePayCard,
this.derivationType,
this.derivationPath)
this.derivationInfo)
: _yatLastUsedAddressController = StreamController<String>.broadcast();
factory WalletInfo.external({
@ -74,8 +75,7 @@ class WalletInfo extends HiveObject {
bool? showIntroCakePayCard,
String yatEid = '',
String yatLastUsedAddressRaw = '',
DerivationType? derivationType,
String? derivationPath,
DerivationInfo? derivationInfo,
}) {
return WalletInfo(
id,
@ -90,8 +90,7 @@ class WalletInfo extends HiveObject {
yatEid,
yatLastUsedAddressRaw,
showIntroCakePayCard,
derivationType,
derivationPath);
derivationInfo);
}
static const typeId = WALLET_INFO_TYPE_ID;
@ -143,10 +142,7 @@ class WalletInfo extends HiveObject {
List<String>? usedAddresses;
@HiveField(16)
DerivationType? derivationType;
@HiveField(17)
String? derivationPath;
DerivationInfo? derivationInfo;
String get yatLastUsedAddress => yatLastUsedAddressRaw ?? '';

View file

@ -42,7 +42,7 @@ abstract class NanoWalletBase
}) : syncStatus = NotConnectedSyncStatus(),
_password = password,
_mnemonic = mnemonic,
_derivationType = walletInfo.derivationType!,
_derivationType = walletInfo.derivationInfo!.derivationType!,
_isTransactionUpdating = false,
_client = NanoClient(),
walletAddresses = NanoWalletAddresses(walletInfo),
@ -354,7 +354,7 @@ abstract class NanoWalletBase
derivationType = DerivationType.nano;
}
walletInfo.derivationType = derivationType;
walletInfo.derivationInfo ??= DerivationInfo(derivationType: derivationType);
return NanoWallet(
walletInfo: walletInfo,

View file

@ -2,8 +2,15 @@ import 'package:cw_core/wallet_credentials.dart';
import 'package:cw_core/wallet_info.dart';
class NanoNewWalletCredentials extends WalletCredentials {
NanoNewWalletCredentials({required String name, String? password})
: super(name: name, password: password);
NanoNewWalletCredentials({
required String name,
String? password,
DerivationType? derivationType,
}) : super(
name: name,
password: password,
derivationInfo: DerivationInfo(derivationType: derivationType),
);
}
class NanoRestoreWalletFromSeedCredentials extends WalletCredentials {
@ -14,11 +21,13 @@ class NanoRestoreWalletFromSeedCredentials extends WalletCredentials {
String? password,
DerivationType? derivationType,
}) : super(
name: name,
password: password,
height: height,
derivationType: derivationType,
);
name: name,
password: password,
height: height,
derivationInfo: DerivationInfo(
derivationType: derivationType,
height: height,
));
final String mnemonic;
}
@ -38,4 +47,4 @@ class NanoRestoreWalletFromKeysCredentials extends WalletCredentials {
final String seedKey;
final DerivationType? derivationType;
}
}

View file

@ -28,11 +28,12 @@ class NanoWalletService extends WalletService<NanoNewWalletCredentials,
@override
Future<WalletBase> create(NanoNewWalletCredentials credentials) async {
// nano standard:
DerivationType derivationType = DerivationType.nano;
String seedKey = NanoSeeds.generateSeed();
String mnemonic = NanoUtil.seedToMnemonic(seedKey);
credentials.walletInfo!.derivationType = derivationType;
// set default if not present:
DerivationType derivationType = credentials.derivationInfo?.derivationType ?? DerivationType.nano;
credentials.walletInfo!.derivationInfo ??= DerivationInfo(derivationType: derivationType);
final wallet = NanoWallet(
walletInfo: credentials.walletInfo!,
@ -88,7 +89,7 @@ class NanoWalletService extends WalletService<NanoNewWalletCredentials,
}
DerivationType derivationType = credentials.derivationType ?? DerivationType.nano;
credentials.walletInfo!.derivationType = derivationType;
credentials.walletInfo!.derivationInfo ??= DerivationInfo(derivationType: derivationType);
String? mnemonic;
@ -127,9 +128,10 @@ class NanoWalletService extends WalletService<NanoNewWalletCredentials,
}
}
DerivationType derivationType = credentials.derivationType ?? DerivationType.nano;
DerivationType derivationType =
credentials.walletInfo?.derivationInfo?.derivationType ?? DerivationType.nano;
credentials.walletInfo!.derivationType = derivationType;
credentials.walletInfo!.derivationInfo ??= DerivationInfo(derivationType: derivationType);
final wallet = await NanoWallet(
password: credentials.password!,

View file

@ -100,6 +100,10 @@ Future<void> initializeAppConfigs() async {
if (!Hive.isAdapterRegistered(DERIVATION_TYPE_TYPE_ID)) {
CakeHive.registerAdapter(DerivationTypeAdapter());
}
if (!Hive.isAdapterRegistered(DERIVATION_INFO_TYPE_ID)) {
CakeHive.registerAdapter(DerivationInfoAdapter());
}
if (!CakeHive.isAdapterRegistered(WALLET_TYPE_TYPE_ID)) {
CakeHive.registerAdapter(WalletTypeAdapter());

View file

@ -96,6 +96,7 @@ class CWNano extends Nano {
NanoNewWalletCredentials(
name: name,
password: password,
derivationType: DerivationType.nano,
);
@override

View file

@ -110,8 +110,9 @@ class WalletRestorePage extends BasePage {
final GlobalKey<WalletRestoreFromSeedFormState> walletRestoreFromSeedFormKey;
final GlobalKey<WalletRestoreFromKeysFromState> walletRestoreFromKeysFormKey;
final FocusNode _blockHeightFocusNode;
DerivationType derivationType = DerivationType.unknown;
String? derivationPath = null;
// DerivationType derivationType = DerivationType.unknown;
// String? derivationPath = null;
DerivationInfo? derivationInfo;
@override
Widget body(BuildContext context) {
@ -294,8 +295,7 @@ class WalletRestorePage extends BasePage {
}
}
credentials['derivationType'] = this.derivationType;
credentials['derivationPath'] = this.derivationPath;
credentials['derivationInfo'] = this.derivationInfo;
credentials['walletType'] = walletRestoreViewModel.type;
return credentials;
}
@ -330,10 +330,12 @@ class WalletRestorePage extends BasePage {
List<DerivationType> derivationTypes =
await walletRestoreViewModel.getDerivationTypes(_credentials());
DerivationInfo? dInfo;
if (derivationTypes[0] == DerivationType.unknown || derivationTypes.length > 1) {
if (derivationTypes.length > 1) {
// push screen to choose the derivation type:
List<DerivationInfo> derivations = await walletRestoreViewModel.getDerivationInfo(_credentials());
List<DerivationInfo> derivations =
await walletRestoreViewModel.getDerivationInfo(_credentials());
int derivationsWithHistory = 0;
int derivationWithHistoryIndex = 0;
@ -343,34 +345,25 @@ class WalletRestorePage extends BasePage {
derivationWithHistoryIndex = i;
}
}
DerivationInfo? derivationInfo;
if (derivationsWithHistory > 1) {
derivationInfo = await Navigator.of(context).pushNamed(Routes.restoreWalletChooseDerivation,
dInfo = await Navigator.of(context).pushNamed(Routes.restoreWalletChooseDerivation,
arguments: derivations) as DerivationInfo?;
} else if (derivationsWithHistory == 1) {
derivationInfo = derivations[derivationWithHistoryIndex];
} else if (derivationsWithHistory == 0) {
// default derivation:
derivationInfo = DerivationInfo(
derivationType: derivationTypes[0],
derivationPath: "m/0'/1",
height: 0,
);
dInfo = derivations[derivationWithHistoryIndex];
}
if (derivationInfo == null) {
if (dInfo == null) {
walletRestoreViewModel.state = InitialExecutionState();
return;
}
this.derivationType = derivationInfo.derivationType;
this.derivationPath = derivationInfo.derivationPath;
} else {
// electrum derivation:
this.derivationType = derivationTypes[0];
this.derivationPath = "m/0'/1";
this.derivationInfo = dInfo;
}
// get the default derivation for this wallet type:
if (this.derivationInfo == null) {
this.derivationInfo = walletRestoreViewModel.getDefaultDerivation();
}
walletRestoreViewModel.state = InitialExecutionState();

View file

@ -65,8 +65,7 @@ abstract class WalletCreationVMBase with Store {
dirPath: dirPath,
address: '',
showIntroCakePayCard: (!walletCreationService.typeExists(type)) && type != WalletType.haven,
derivationPath: credentials.derivationPath,
derivationType: credentials.derivationType,
derivationInfo: credentials.derivationInfo,
);
credentials.walletInfo = walletInfo;
final wallet = restoreWallet != null

View file

@ -35,21 +35,20 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
WalletCredentials getCredentials(dynamic options) {
switch (type) {
case WalletType.monero:
return monero!.createMoneroNewWalletCredentials(
name: name, language: options as String);
return monero!.createMoneroNewWalletCredentials(name: name, language: options as String);
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);
return haven!.createHavenNewWalletCredentials(name: name, language: options as String);
case WalletType.ethereum:
return ethereum!.createEthereumNewWalletCredentials(name: name);
case WalletType.nano:
return nano!.createNanoNewWalletCredentials(name: name);
default:
throw Exception('Unexpected type: ${type.toString()}');;
throw Exception('Unexpected type: ${type.toString()}');
;
}
}

View file

@ -70,8 +70,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
final password = generateWalletPassword();
final height = options['height'] as int? ?? 0;
name = options['name'] as String;
DerivationType? derivationType = options["derivationType"] as DerivationType?;
String? derivationPath = options["derivationPath"] as String?;
DerivationInfo? derivationInfo = options["derivationInfo"] as DerivationInfo?;
if (mode == WalletRestoreMode.seed) {
final seed = options['seed'] as String;
@ -84,8 +83,8 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
name: name,
mnemonic: seed,
password: password,
derivationType: derivationType,
derivationPath: derivationPath,
derivationType: derivationInfo?.derivationType,
derivationPath: derivationInfo?.derivationPath,
);
case WalletType.litecoin:
return bitcoin!.createBitcoinRestoreWalletFromSeedCredentials(
@ -101,7 +100,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
name: name,
mnemonic: seed,
password: password,
derivationType: derivationType,
derivationType: derivationInfo?.derivationType,
);
default:
break;
@ -223,6 +222,8 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
privateKey: seedKey,
node: node,
);
case WalletType.litecoin:
return [DerivationType.electrum2];
default:
break;
}
@ -231,6 +232,22 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
return [DerivationType.def];
}
DerivationInfo getDefaultDerivation() {
switch (type) {
case WalletType.nano:
return DerivationInfo(
derivationType: DerivationType.nano,
);
case WalletType.bitcoin:
case WalletType.litecoin:
default:
return DerivationInfo(
derivationType: DerivationType.electrum2,
derivationPath: "m/0'/1",
);
}
}
@override
Future<WalletBase> process(WalletCredentials credentials) async {
if (mode == WalletRestoreMode.keys) {