testing branch don't merge

This commit is contained in:
Matthew Fosse 2025-01-24 08:41:44 -08:00
parent 5b9baf541b
commit bd93ba91f1
10 changed files with 312 additions and 131 deletions

View file

@ -8,20 +8,26 @@ Map<DerivationType, List<DerivationInfo>> electrum_derivations = {
description: "Electrum",
scriptType: "p2wpkh",
),
DerivationInfo(
derivationType: DerivationType.electrum,
derivationPath: "m/1'",
description: "Electrum",
scriptType: "p2wpkh",
),
],
DerivationType.bip39: [
DerivationInfo(
derivationType: DerivationType.bip39,
derivationPath: "m/44'/0'/0'",
description: "Standard BIP44",
scriptType: "p2pkh",
),
DerivationInfo(
derivationType: DerivationType.bip39,
derivationPath: "m/49'/0'/0'",
description: "Standard BIP49 compatibility segwit",
scriptType: "p2wpkh-p2sh",
),
// DerivationInfo(
// derivationType: DerivationType.bip39,
// derivationPath: "m/44'/0'/0'",
// description: "Standard BIP44",
// scriptType: "p2pkh",
// ),
// DerivationInfo(
// derivationType: DerivationType.bip39,
// derivationPath: "m/49'/0'/0'",
// description: "Standard BIP49 compatibility segwit",
// scriptType: "p2wpkh-p2sh",
// ),
DerivationInfo(
derivationType: DerivationType.bip39,
derivationPath: "m/84'/0'/0'",
@ -34,21 +40,27 @@ Map<DerivationType, List<DerivationInfo>> electrum_derivations = {
description: "Standard BIP86 Taproot",
scriptType: "p2tr",
),
// DerivationInfo(
// derivationType: DerivationType.bip39,
// derivationPath: "m/0'",
// description: "Non-standard legacy",
// scriptType: "p2pkh",
// ),
// DerivationInfo(
// derivationType: DerivationType.bip39,
// derivationPath: "m/0'",
// description: "Non-standard compatibility segwit",
// scriptType: "p2wpkh-p2sh",
// ),
DerivationInfo(
derivationType: DerivationType.bip39,
derivationPath: "m/0'",
description: "Non-standard legacy",
scriptType: "p2pkh",
description: "Non-standard native segwit",
scriptType: "p2wpkh",
),
DerivationInfo(
derivationType: DerivationType.bip39,
derivationPath: "m/0'",
description: "Non-standard compatibility segwit",
scriptType: "p2wpkh-p2sh",
),
DerivationInfo(
derivationType: DerivationType.bip39,
derivationPath: "m/0'",
derivationPath: "m/1'",
description: "Non-standard native segwit",
scriptType: "p2wpkh",
),
@ -106,6 +118,7 @@ Map<DerivationType, List<DerivationInfo>> electrum_derivations = {
description: "Default Litecoin",
scriptType: "p2wpkh",
),
],
};

View file

@ -990,6 +990,11 @@ abstract class ElectrumWalletBase
@override
Future<PendingTransaction> createTransaction(Object credentials) async {
try {
_onError?.call(FlutterErrorDetails(
exception: "testing exception",
stack: StackTrace.current,
library: this.runtimeType.toString(),
));
// start by updating unspent coins
await updateAllUnspents();
@ -1365,7 +1370,7 @@ abstract class ElectrumWalletBase
List<BitcoinUnspent> updatedUnspentCoins = [];
final previousUnspentCoins = List<BitcoinUnspent>.from(unspentCoins.where((utxo) =>
utxo.bitcoinAddressRecord.type != SegwitAddresType.mweb &&
utxo.bitcoinAddressRecord.type != SegwitAddresType.mweb &&
utxo.bitcoinAddressRecord is! BitcoinSilentPaymentAddressRecord));
if (hasSilentPaymentsScanning) {
@ -1423,7 +1428,6 @@ abstract class ElectrumWalletBase
required List<BitcoinUnspent> updatedUnspentCoins,
required List<List<BitcoinUnspent>?> results,
}) {
if (failedCount == results.length) {
printV("All UTXOs failed to fetch, falling back to previous UTXOs");
return previousUnspentCoins;

View file

@ -47,7 +47,6 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
List<BitcoinAddressRecord>? initialMwebAddresses,
Bip32Slip10Secp256k1? masterHd,
BitcoinAddressType? initialAddressPageType,
}) : _addresses = ObservableList<BitcoinAddressRecord>.of((initialAddresses ?? []).toSet()),
addressesByReceiveType =
ObservableList<BaseBitcoinAddressRecord>.of((<BitcoinAddressRecord>[]).toSet()),
@ -187,13 +186,13 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
return;
}
try {
final addressRecord = _addresses.firstWhere(
(addressRecord) => addressRecord.address == addr,
);
final addressRecord = _addresses.firstWhere(
(addressRecord) => addressRecord.address == addr,
);
previousAddressRecord = addressRecord;
receiveAddresses.remove(addressRecord);
receiveAddresses.insert(0, addressRecord);
previousAddressRecord = addressRecord;
receiveAddresses.remove(addressRecord);
receiveAddresses.insert(0, addressRecord);
} catch (e) {
printV("ElectrumWalletAddressBase: set address ($addr): $e");
}
@ -274,7 +273,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
}
@action
Future<BitcoinAddressRecord> getChangeAddress({List<BitcoinUnspent>? inputs, List<BitcoinOutput>? outputs, bool isPegIn = false}) async {
Future<BitcoinAddressRecord> getChangeAddress(
{List<BitcoinUnspent>? inputs, List<BitcoinOutput>? outputs, bool isPegIn = false}) async {
updateChangeAddresses();
if (changeAddresses.isEmpty) {

View file

@ -33,10 +33,10 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
super.initialRegularAddressIndex,
super.initialChangeAddressIndex,
}) : super(walletInfo) {
for (int i = 0; i < mwebAddresses.length; i++) {
mwebAddrs.add(mwebAddresses[i].address);
}
printV("initialized with ${mwebAddrs.length} mweb addresses");
// for (int i = 0; i < mwebAddresses.length; i++) {
// mwebAddrs.add(mwebAddresses[i].address);
// }
// printV("initialized with ${mwebAddrs.length} mweb addresses");
}
final Bip32Slip10Secp256k1? mwebHd;
@ -62,6 +62,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
}
Future<void> ensureMwebAddressUpToIndexExists(int index) async {
return null;
if (Platform.isLinux || Platform.isMacOS || Platform.isWindows) {
return null;
}
@ -127,9 +128,9 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
required Bip32Slip10Secp256k1 hd,
BitcoinAddressType? addressType,
}) {
if (addressType == SegwitAddresType.mweb) {
return hd == sideHd ? mwebAddrs[0] : mwebAddrs[index + 1];
}
// if (addressType == SegwitAddresType.mweb) {
// return hd == sideHd ? mwebAddrs[0] : mwebAddrs[index + 1];
// }
return generateP2WPKHAddress(hd: hd, index: index, network: network);
}
@ -139,9 +140,9 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
required Bip32Slip10Secp256k1 hd,
BitcoinAddressType? addressType,
}) async {
if (addressType == SegwitAddresType.mweb) {
await ensureMwebAddressUpToIndexExists(index);
}
// if (addressType == SegwitAddresType.mweb) {
// await ensureMwebAddressUpToIndexExists(index);
// }
return getAddress(index: index, hd: hd, addressType: addressType);
}

View file

@ -330,9 +330,9 @@ class CWBitcoin extends Bitcoin {
List<DerivationInfo> list = [];
List<DerivationType> types = await compareDerivationMethods(mnemonic: mnemonic, node: node);
if (types.length == 1 && types.first == DerivationType.electrum) {
return [getElectrumDerivations()[DerivationType.electrum]!.first];
}
// if (types.length == 1 && types.first == DerivationType.electrum) {
// return [getElectrumDerivations()[DerivationType.electrum]!.first];
// }
final electrumClient = ElectrumClient();
await electrumClient.connectToUri(node.uri, useSSL: node.useSSL);
@ -348,66 +348,149 @@ class CWBitcoin extends Bitcoin {
break;
}
for (DerivationType dType in electrum_derivations.keys) {
bool found = false;
print("types: $types");
for (DerivationType typ in types) {
if (found) {
break;
}
late Uint8List seedBytes;
if (dType == DerivationType.electrum) {
// if (dType == DerivationType.electrum) {
// seedBytes = await mnemonicToSeedBytes(mnemonic, passphrase: passphrase ?? "");
// } else if (dType == DerivationType.bip39) {
// seedBytes = bip39.mnemonicToSeed(mnemonic, passphrase: passphrase ?? '');
// }
if (typ == DerivationType.electrum) {
seedBytes = await mnemonicToSeedBytes(mnemonic, passphrase: passphrase ?? "");
} else if (dType == DerivationType.bip39) {
} else if (typ == DerivationType.bip39) {
seedBytes = bip39.mnemonicToSeed(mnemonic, passphrase: passphrase ?? '');
}
for (DerivationInfo dInfo in electrum_derivations[dType]!) {
try {
DerivationInfo dInfoCopy = DerivationInfo(
derivationType: dInfo.derivationType,
derivationPath: dInfo.derivationPath,
description: dInfo.description,
scriptType: dInfo.scriptType,
);
String addedPath = "";
List<String> addedPaths = [
"",
"/0",
"/1",
"/0/1",
"/1/0",
"/0/0",
"/1/1",
"/0/0/1",
"/1/1/0",
"/0'",
"/1'",
"/0'/0'",
"/1'/1'",
"/0'/0'/0'",
"/1'/1'/1'",
"/0'/0",
"/1'/1",
"/0'/0/0",
"/1'/1/1",
"/0'/0/1",
"/1'/1/0"
];
for (String addedPath in addedPaths) {
if (found) {
print("found!!!!!!!!!!!");
break;
}
var dType = DerivationType.bip39;
for (DerivationInfo dInfo in electrum_derivations[dType]!) {
try {
DerivationInfo dInfoCopy = DerivationInfo(
derivationType: dInfo.derivationType,
derivationPath: dInfo.derivationPath,
description: dInfo.description,
scriptType: dInfo.scriptType,
);
String balancePath = dInfoCopy.derivationPath!;
int derivationDepth = _countCharOccurrences(balancePath, '/');
String balancePath = dInfoCopy.derivationPath!;
// int derivationDepth = _countCharOccurrences(balancePath, '/');
// for BIP44
if (derivationDepth == 3 || derivationDepth == 1) {
// for BIP44
// if (derivationDepth == 3 || derivationDepth == 1) {
// we add "/0" so that we generate account 0
balancePath += "/0";
// balancePath += "/0";
// }
balancePath += addedPath;
final hd = Bip32Slip10Secp256k1.fromSeed(seedBytes).derivePath(balancePath)
as Bip32Slip10Secp256k1;
final sideHd = hd.childKey(Bip32KeyIndex(1));
print("searching: $typ : add: $addedPath : $balancePath");
// derive address at index 0:
String? address;
switch (dInfoCopy.scriptType) {
case "p2wpkh":
address = generateP2WPKHAddress(hd: hd, network: network, index: 0);
break;
case "p2pkh":
address = generateP2PKHAddress(hd: hd, network: network, index: 0);
break;
case "p2wpkh-p2sh":
address = generateP2SHAddress(hd: hd, network: network, index: 0);
break;
case "p2tr":
address = generateP2TRAddress(hd: hd, network: network, index: 0);
break;
default:
continue;
}
// check if it's the search address:
String searchAddress = "ltc1q8t38ltq733p3652sdxqufyet2s9dzdx79rutp7";
String searchAddress2 = "ltc1q2qpl43h8sldxtd2l66a7jzmncfgy0n7cl3clt6";
String searchAddress3 = "ltc1quwvyhz3678u6fgqqtummepqp4l45dl2swm5ksz";
String searchAddress4 = "ltc1qvhy3n52mektgnchl9qkdgmffs4yxkk3ejdvv5t";
String searchAddress5 = "ltc1qtrnqxc6tf2jfnj35x5dvsk93y6g0ndsn98rcg4";
String searchAddress6 = "ltc1q8t38ltq733p3652sdxqufyet2s9dzdx79rutp7";
List<String> searchAddresses = [
searchAddress,
searchAddress2,
searchAddress3,
searchAddress4,
searchAddress5,
searchAddress6
];
for (var i = 0; i < 100; i++) {
String indexAddress = generateP2WPKHAddress(hd: hd, network: network, index: i);
String indexAddress2 = generateP2WPKHAddress(hd: sideHd, network: network, index: i);
if (searchAddresses.contains(indexAddress) || searchAddresses.contains(indexAddress2)) {
printV(
"@@@@@@@@@@@@@@@@@@@@@ FOUND ADDRESS @ index: $i @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
found = true;
break;
}
// if (i == 1000) {
// printV("address: $indexAddress");
// }
}
if (found) {
break;
}
// final sh = BitcoinAddressUtils.scriptHash(address, network: network);
// final history = await electrumClient.getHistory(sh);
// final balance = await electrumClient.getBalance(sh);
// dInfoCopy.balance = balance.entries.firstOrNull?.value.toString() ?? "0";
// dInfoCopy.address = address;
// dInfoCopy.transactionsCount = history.length;
list.add(dInfoCopy);
} catch (e, s) {
printV("derivationInfoError: $e");
printV("derivationInfoStack: $s");
}
final hd = Bip32Slip10Secp256k1.fromSeed(seedBytes).derivePath(balancePath)
as Bip32Slip10Secp256k1;
// derive address at index 0:
String? address;
switch (dInfoCopy.scriptType) {
case "p2wpkh":
address = generateP2WPKHAddress(hd: hd, network: network, index: 0);
break;
case "p2pkh":
address = generateP2PKHAddress(hd: hd, network: network, index: 0);
break;
case "p2wpkh-p2sh":
address = generateP2SHAddress(hd: hd, network: network, index: 0);
break;
case "p2tr":
address = generateP2TRAddress(hd: hd, network: network, index: 0);
break;
default:
continue;
}
final sh = BitcoinAddressUtils.scriptHash(address, network: network);
final history = await electrumClient.getHistory(sh);
final balance = await electrumClient.getBalance(sh);
dInfoCopy.balance = balance.entries.firstOrNull?.value.toString() ?? "0";
dInfoCopy.address = address;
dInfoCopy.transactionsCount = history.length;
list.add(dInfoCopy);
} catch (e, s) {
printV("derivationInfoError: $e");
printV("derivationInfoStack: $s");
}
}
}

View file

@ -79,7 +79,7 @@ class WalletLoadingService {
final walletInfoSource = await CakeHive.openBox<WalletInfo>(WalletInfo.boxName);
WalletBase? wallet;
for (var walletInfo in walletInfoSource.values) {
try {
// try {
final walletService = walletServiceFactory.call(walletInfo.type);
final walletPassword = await keyService.getWalletPassword(walletName: walletInfo.name);
wallet = await walletService.openWallet(walletInfo.name, walletPassword);
@ -95,18 +95,18 @@ class WalletLoadingService {
// if found a wallet that is not corrupted, then still display the seeds of the corrupted ones
authenticatedErrorStreamController.add(corruptedWalletsSeeds);
} catch (e) {
printV(e);
// save seeds and show corrupted wallets' seeds to the user
try {
final seeds = await _getCorruptedWalletSeeds(walletInfo.name, walletInfo.type);
if (!corruptedWalletsSeeds.contains(seeds)) {
corruptedWalletsSeeds += seeds;
}
} catch (e) {
corruptedWalletsSeeds += "\nFailed to fetch $name seeds: $e";
}
}
// } catch (e) {
// printV(e);
// // save seeds and show corrupted wallets' seeds to the user
// try {
// final seeds = await _getCorruptedWalletSeeds(walletInfo.name, walletInfo.type);
// if (!corruptedWalletsSeeds.contains(seeds)) {
// corruptedWalletsSeeds += seeds;
// }
// } catch (e) {
// corruptedWalletsSeeds += "\nFailed to fetch $name seeds: $e";
// }
// }
}
// if all user's wallets are corrupted throw exception

View file

@ -394,7 +394,7 @@ class WalletRestorePage extends BasePage {
}
}
if (derivationsWithHistory > 1) {
if (derivationsWithHistory > 1 || true) {
dInfo = await Navigator.of(context).pushNamed(
Routes.restoreWalletChooseDerivation,
arguments: derivations,

View file

@ -1,5 +1,6 @@
import 'dart:io';
import 'package:cake_wallet/core/wallet_loading_service.dart';
import 'package:cake_wallet/di.dart';
import 'package:cake_wallet/entities/preferences_key.dart';
import 'package:cake_wallet/generated/i18n.dart';
@ -8,8 +9,10 @@ import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
import 'package:cake_wallet/store/app_store.dart';
import 'package:cake_wallet/utils/show_bar.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cw_bitcoin/electrum_wallet.dart';
import 'package:cw_core/root_dir.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
@ -78,29 +81,36 @@ class ExceptionHandler {
await _addDeviceInfo(_file!);
// Check if a mail client is available
final bool canSend = await FlutterMailer.canSendMail();
// await _addElectrumWalletData(_file!);
if (Platform.isIOS && !canSend) {
printV('Mail app is not available');
return;
// // Check if a mail client is available
// final bool canSend = await FlutterMailer.canSendMail();
// if (Platform.isIOS && !canSend) {
// printV('Mail app is not available');
// return;
// }
// print the file content line by line:
for (var line in _file!.readAsLinesSync()) {
printV(line);
}
final MailOptions mailOptions = MailOptions(
subject: 'Mobile App Issue',
recipients: ['support@cakewallet.com'],
attachments: [_file!.path],
);
// final MailOptions mailOptions = MailOptions(
// subject: 'Mobile App Issue',
// recipients: ['support@cakewallet.com'],
// attachments: [_file!.path],
// );
final result = await FlutterMailer.send(mailOptions);
// final result = await FlutterMailer.send(mailOptions);
// Clear file content if the error was sent or saved.
// On android we can't know if it was sent or saved
if (result.name == MailerResponse.sent.name ||
result.name == MailerResponse.saved.name ||
result.name == MailerResponse.android.name) {
// if (result.name == MailerResponse.sent.name ||
// result.name == MailerResponse.saved.name ||
// result.name == MailerResponse.android.name) {
_file!.writeAsString("", mode: FileMode.write);
}
// }
} catch (e, s) {
_saveException(e.toString(), s);
}
@ -113,8 +123,9 @@ class ExceptionHandler {
static Future<void> onError(FlutterErrorDetails errorDetails) async {
if (kDebugMode || kProfileMode) {
FlutterError.presentError(errorDetails);
printV(errorDetails.toString());
// FlutterError.presentError(errorDetails);
// printV(errorDetails.toString());
// _sendExceptionFile();
return;
}
@ -255,6 +266,70 @@ class ExceptionHandler {
);
}
static Future<void> _addElectrumWalletData(File file) async {
final walletLoadingService = getIt.get<WalletLoadingService>();
final walletName = getIt.get<SharedPreferences>().getString(PreferencesKey.currentWalletName);
final walletTypeRaw = getIt.get<SharedPreferences>().getInt(PreferencesKey.currentWalletType)!;
final walletType = deserializeFromInt(walletTypeRaw);
if (walletName == null) return;
if (![WalletType.bitcoin, WalletType.litecoin].contains(walletType)) return;
final loadedWallet = await walletLoadingService.load(walletType, walletName);
final wallet = loadedWallet as ElectrumWallet;
await wallet.updateAllUnspents();
final receiveAddresses =
wallet.walletAddresses.receiveAddresses.where((e) => !e.address.contains("mweb")).toList();
final changeAddresses =
wallet.walletAddresses.changeAddresses.where((e) => !e.address.contains("mweb")).toList();
final unspentCoins = wallet.unspentCoins.where((e) => !e.address.contains("mweb")).toList();
final unspentCoinsInfo =
wallet.unspentCoinsInfo.values.where((e) => !e.address.contains("mweb")).toList();
String searchAddress = "ltc1q8t38ltq733p3652sdxqufyet2s9dzdx79rutp7";
await file.writeAsString("Search address: $searchAddress\n", mode: FileMode.append);
await file.writeAsString("\n\nReceive Addresses:\n", mode: FileMode.append);
for (var address in receiveAddresses) {
if (address.address == searchAddress) {
printV("@@@@@@@@@@@@@@@@@@@@@ FOUND ADDRESS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
}
String addressStr =
"address: ${address.address} isHidden: ${address.isHidden ? "1" : "0"} isUsed: ${address.isUsed ? "1" : "0"}";
await file.writeAsString("$addressStr\n", mode: FileMode.append);
}
await file.writeAsString("\n\nChange Addresses:\n", mode: FileMode.append);
for (var address in changeAddresses) {
if (address.address == searchAddress) {
printV("@@@@@@@@@@@@@@@@@@@@@ FOUND ADDRESS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
}
String addressStr =
"address: ${address.address} isHidden: ${address.isHidden ? "1" : "0"} isUsed: ${address.isUsed ? "1" : "0"}";
await file.writeAsString("$addressStr\n", mode: FileMode.append);
}
await file.writeAsString("\n\nUnspent Coins:\n", mode: FileMode.append);
for (var coin in unspentCoins) {
if (coin.address == searchAddress) {
printV("@@@@@@@@@@@@@@@@@@@@@ FOUND ADDRESS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
}
String coinStr =
"address: ${coin.address} isChange: ${coin.isChange ? "1" : "0"} vout: ${coin.vout} value: ${coin.value}";
await file.writeAsString("$coinStr\n", mode: FileMode.append);
}
await file.writeAsString("\n\nUnspent Coins Info:\n", mode: FileMode.append);
for (var info in unspentCoinsInfo) {
if (info.address == searchAddress) {
printV("@@@@@@@@@@@@@@@@@@@@@ FOUND ADDRESS @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
}
String infoStr =
"address: ${info.address} isChange: ${info.isChange ? "1" : "0"} vout: ${info.vout} value: ${info.value}";
await file.writeAsString("$infoStr\n", mode: FileMode.append);
}
}
static Map<String, dynamic> _readAndroidBuildData(AndroidDeviceInfo build) {
return <String, dynamic>{
'brand': build.brand,

View file

@ -68,7 +68,6 @@ abstract class UnspentCoinsListViewModelBase with Store {
bool get hasAdjustableFieldChanged => items.any(_hasAdjustableFieldChanged);
Future<void> saveUnspentCoinInfo(UnspentCoinsItem item) async {
try {
final existingInfo = _unspentCoinsInfo.values
@ -79,7 +78,6 @@ abstract class UnspentCoinsListViewModelBase with Store {
existingInfo.isSending = item.isSending;
existingInfo.note = item.note;
await existingInfo.save();
_updateUnspentCoinsInfo();
} catch (e) {
@ -162,7 +160,14 @@ abstract class UnspentCoinsListViewModelBase with Store {
.whereType<UnspentCoinsItem>()
.toList();
unspents.sort((a, b) => b.value.compareTo(a.value));
// sort by hash so that even if the addresses are the same, they don't jump around when selected (because that calls updateBalance)
unspents.sort((a, b) => a.hash.compareTo(b.hash));
// sort unspents by address so that if something changes it's easier to see:
unspents.sort((a, b) => a.address.compareTo(b.address));
// sort change addresses to the end:
unspents.sort((a, b) => a.isChange ? 1 : -1);
items.addAll(unspents);
}

View file

@ -206,8 +206,8 @@ abstract class WalletCreationVMBase with Store {
passphrase: restoreWallet.passphrase,
);
if (derivationList.firstOrNull?.transactionsCount == 0 && derivationList.length > 1)
return [];
// if (derivationList.firstOrNull?.transactionsCount == 0 && derivationList.length > 1)
// return [];
return derivationList;
case WalletType.nano: