mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-04-27 14:04:46 +00:00
testing branch don't merge
This commit is contained in:
parent
5b9baf541b
commit
bd93ba91f1
10 changed files with 312 additions and 131 deletions
cw_bitcoin/lib
electrum_derivations.dartelectrum_wallet.dartelectrum_wallet_addresses.dartlitecoin_wallet_addresses.dart
lib
bitcoin
core
src/screens/restore
utils
view_model
|
@ -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",
|
||||
),
|
||||
|
||||
],
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue