mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-04-27 18:24:45 +00:00
Mweb fixes (#1972)
* quick fix [still investigating] * cleaner quick fix * cleaner quick fix * log fix * save to downloads would require an additional permission * change address handling updates [skip ci] * should change address not updating * change address handling updates * remove unnecessary code + don't reset change address index to 0
This commit is contained in:
parent
9673b7c026
commit
199ada3fa9
7 changed files with 55 additions and 60 deletions
|
@ -2,6 +2,7 @@ import 'package:bitcoin_base/bitcoin_base.dart';
|
|||
import 'package:blockchain_utils/bip/bip/bip32/bip32.dart';
|
||||
import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
|
||||
import 'package:cw_bitcoin/utils.dart';
|
||||
import 'package:cw_core/unspent_coin_type.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
|
@ -26,7 +27,10 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S
|
|||
|
||||
@override
|
||||
String getAddress(
|
||||
{required int index, required Bip32Slip10Secp256k1 hd, BitcoinAddressType? addressType}) {
|
||||
{required int index,
|
||||
required Bip32Slip10Secp256k1 hd,
|
||||
BitcoinAddressType? addressType,
|
||||
UnspentCoinType coinTypeToSpendFrom = UnspentCoinType.any}) {
|
||||
if (addressType == P2pkhAddressType.p2pkh)
|
||||
return generateP2PKHAddress(hd: hd, index: index, network: network);
|
||||
|
||||
|
|
|
@ -842,6 +842,7 @@ abstract class ElectrumWalletBase
|
|||
final changeAddress = await walletAddresses.getChangeAddress(
|
||||
inputs: utxoDetails.availableInputs,
|
||||
outputs: updatedOutputs,
|
||||
coinTypeToSpendFrom: coinTypeToSpendFrom,
|
||||
);
|
||||
final address = RegexUtils.addressTypeFromStr(changeAddress.address, network);
|
||||
updatedOutputs.add(BitcoinOutput(
|
||||
|
|
|
@ -4,6 +4,7 @@ import 'package:bitcoin_base/bitcoin_base.dart';
|
|||
import 'package:blockchain_utils/blockchain_utils.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
||||
import 'package:cw_bitcoin/electrum_wallet.dart';
|
||||
import 'package:cw_core/unspent_coin_type.dart';
|
||||
import 'package:cw_core/utils/print_verbose.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_unspent.dart';
|
||||
import 'package:cw_core/wallet_addresses.dart';
|
||||
|
@ -47,7 +48,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 +187,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 +274,10 @@ 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,
|
||||
UnspentCoinType coinTypeToSpendFrom = UnspentCoinType.any}) async {
|
||||
updateChangeAddresses();
|
||||
|
||||
if (changeAddresses.isEmpty) {
|
||||
|
|
|
@ -9,6 +9,7 @@ import 'package:crypto/crypto.dart';
|
|||
import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart';
|
||||
import 'package:cw_core/cake_hive.dart';
|
||||
import 'package:cw_core/mweb_utxo.dart';
|
||||
import 'package:cw_core/unspent_coin_type.dart';
|
||||
import 'package:cw_core/utils/print_verbose.dart';
|
||||
import 'package:cw_core/node.dart';
|
||||
import 'package:cw_mweb/mwebd.pbgrpc.dart';
|
||||
|
@ -394,7 +395,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
// if the confirmations haven't changed, skip updating:
|
||||
if (tx.confirmations == confirmations) continue;
|
||||
|
||||
|
||||
// if an outgoing tx is now confirmed, delete the utxo from the box (delete the unspent coin):
|
||||
if (confirmations >= 2 &&
|
||||
tx.direction == TransactionDirection.outgoing &&
|
||||
|
@ -966,10 +966,19 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
List<ECPrivateInfo>? inputPrivKeyInfos,
|
||||
List<Outpoint>? vinOutpoints,
|
||||
}) async {
|
||||
final spendsMweb = utxos.any((utxo) => utxo.utxo.scriptType == SegwitAddresType.mweb);
|
||||
final paysToMweb = outputs
|
||||
bool spendsMweb = utxos.any((utxo) => utxo.utxo.scriptType == SegwitAddresType.mweb);
|
||||
bool paysToMweb = outputs
|
||||
.any((output) => output.toOutput.scriptPubKey.getAddressType() == SegwitAddresType.mweb);
|
||||
if (!spendsMweb && !paysToMweb) {
|
||||
|
||||
bool isRegular = !spendsMweb && !paysToMweb;
|
||||
bool isMweb = spendsMweb || paysToMweb;
|
||||
|
||||
if (isMweb && !mwebEnabled) {
|
||||
throw Exception("MWEB is not enabled! can't calculate fee without starting the mweb server!");
|
||||
// TODO: likely the change address is mweb and just not updated
|
||||
}
|
||||
|
||||
if (isRegular) {
|
||||
return await super.calcFee(
|
||||
utxos: utxos,
|
||||
outputs: outputs,
|
||||
|
@ -981,10 +990,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
);
|
||||
}
|
||||
|
||||
if (!mwebEnabled) {
|
||||
throw Exception("MWEB is not enabled! can't calculate fee without starting the mweb server!");
|
||||
}
|
||||
|
||||
if (outputs.length == 1 && outputs[0].toOutput.amount == BigInt.zero) {
|
||||
outputs = [
|
||||
BitcoinScriptOutput(
|
||||
|
@ -1055,7 +1060,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
|
||||
if (!mwebEnabled) {
|
||||
tx.changeAddressOverride =
|
||||
(await (walletAddresses as LitecoinWalletAddresses).getChangeAddress(isPegIn: false))
|
||||
(await (walletAddresses as LitecoinWalletAddresses).getChangeAddress(coinTypeToSpendFrom: UnspentCoinType.nonMweb))
|
||||
.address;
|
||||
return tx;
|
||||
}
|
||||
|
@ -1103,13 +1108,15 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
}
|
||||
}
|
||||
|
||||
// could probably be simplified but left for clarity:
|
||||
bool isPegIn = !hasMwebInput && hasMwebOutput;
|
||||
bool isPegOut = hasMwebInput && hasRegularOutput;
|
||||
bool isRegular = !hasMwebInput && !hasMwebOutput;
|
||||
bool shouldNotUseMwebChange = isPegIn || isRegular || !hasMwebInput;
|
||||
tx.changeAddressOverride = (await (walletAddresses as LitecoinWalletAddresses)
|
||||
.getChangeAddress(isPegIn: isPegIn || isRegular))
|
||||
.getChangeAddress(coinTypeToSpendFrom: shouldNotUseMwebChange ? UnspentCoinType.nonMweb : UnspentCoinType.any))
|
||||
.address;
|
||||
if (!hasMwebInput && !hasMwebOutput) {
|
||||
if (isRegular) {
|
||||
tx.isMweb = false;
|
||||
return tx;
|
||||
}
|
||||
|
@ -1212,7 +1219,9 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
}
|
||||
|
||||
Future<void> setMwebEnabled(bool enabled) async {
|
||||
if (mwebEnabled == enabled) {
|
||||
if (mwebEnabled == enabled &&
|
||||
alwaysScan == enabled &&
|
||||
(walletAddresses as LitecoinWalletAddresses).mwebEnabled == enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import 'package:cw_bitcoin/bitcoin_unspent.dart';
|
|||
import 'package:cw_bitcoin/electrum_wallet.dart';
|
||||
import 'package:cw_bitcoin/utils.dart';
|
||||
import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
|
||||
import 'package:cw_core/unspent_coin_type.dart';
|
||||
import 'package:cw_core/utils/print_verbose.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_mweb/cw_mweb.dart';
|
||||
|
@ -148,10 +149,12 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
|
|||
@action
|
||||
@override
|
||||
Future<BitcoinAddressRecord> getChangeAddress(
|
||||
{List<BitcoinUnspent>? inputs, List<BitcoinOutput>? outputs, bool isPegIn = false}) async {
|
||||
{List<BitcoinUnspent>? inputs,
|
||||
List<BitcoinOutput>? outputs,
|
||||
UnspentCoinType coinTypeToSpendFrom = UnspentCoinType.any}) async {
|
||||
// use regular change address on peg in, otherwise use mweb for change address:
|
||||
|
||||
if (!mwebEnabled || isPegIn) {
|
||||
if (!mwebEnabled || coinTypeToSpendFrom == UnspentCoinType.nonMweb) {
|
||||
return super.getChangeAddress();
|
||||
}
|
||||
|
||||
|
@ -178,19 +181,17 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
|
|||
});
|
||||
|
||||
bool isPegIn = !comesFromMweb && outputsToMweb;
|
||||
bool isNonMweb = !comesFromMweb && !outputsToMweb;
|
||||
|
||||
if (isPegIn && mwebEnabled) {
|
||||
return super.getChangeAddress();
|
||||
}
|
||||
|
||||
// use regular change address if it's not an mweb tx:
|
||||
if (!comesFromMweb && !outputsToMweb) {
|
||||
// use regular change address if it's not an mweb tx or if it's a peg in:
|
||||
if (isPegIn || isNonMweb) {
|
||||
return super.getChangeAddress();
|
||||
}
|
||||
}
|
||||
|
||||
if (mwebEnabled) {
|
||||
await ensureMwebAddressUpToIndexExists(1);
|
||||
updateChangeAddresses();
|
||||
return BitcoinAddressRecord(
|
||||
mwebAddrs[0],
|
||||
index: 0,
|
||||
|
|
|
@ -77,15 +77,12 @@ class MwebLogsPage extends BasePage {
|
|||
return AlertWithTwoActions(
|
||||
alertTitle: S.of(context).export_backup,
|
||||
alertContent: S.of(context).select_destination,
|
||||
rightButtonText: S.of(context).save_to_downloads,
|
||||
leftButtonText: S.of(context).share,
|
||||
actionRightButton: () async {
|
||||
const downloadDirPath = "/storage/emulated/0/Download";
|
||||
final filePath = downloadDirPath + "/debug.log";
|
||||
await mwebSettingsViewModelBase.saveLogsLocally(filePath);
|
||||
rightButtonText: S.of(context).save,
|
||||
leftButtonText: S.of(context).cancel,
|
||||
actionLeftButton: () async {
|
||||
Navigator.of(dialogContext).pop();
|
||||
},
|
||||
actionLeftButton: () async {
|
||||
actionRightButton: () async {
|
||||
Navigator.of(dialogContext).pop();
|
||||
try {
|
||||
await share(context);
|
||||
|
@ -101,11 +98,8 @@ class MwebLogsPage extends BasePage {
|
|||
}
|
||||
|
||||
Future<void> share(BuildContext context) async {
|
||||
final filePath = (await getAppDir()).path + "/debug.log";
|
||||
bool success = await mwebSettingsViewModelBase.saveLogsLocally(filePath);
|
||||
if (!success) return;
|
||||
await ShareUtil.shareFile(filePath: filePath, fileName: "debug.log", context: context);
|
||||
await mwebSettingsViewModelBase.removeLogsLocally(filePath);
|
||||
final inAppPath = "${(await getApplicationSupportDirectory()).path}/logs/debug.log";
|
||||
await ShareUtil.shareFile(filePath: inAppPath, fileName: "debug.log", context: context);
|
||||
}
|
||||
|
||||
Future<void> _saveFile() async {
|
||||
|
|
|
@ -3,6 +3,8 @@ import 'dart:io';
|
|||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cake_wallet/utils/exception_handler.dart';
|
||||
import 'package:cw_core/root_dir.dart';
|
||||
import 'package:cw_core/utils/print_verbose.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
@ -47,25 +49,6 @@ abstract class MwebSettingsViewModelBase with Store {
|
|||
_settingsStore.mwebAlwaysScan = value;
|
||||
}
|
||||
|
||||
Future<bool> saveLogsLocally(String filePath) async {
|
||||
try {
|
||||
final appSupportPath = (await getApplicationSupportDirectory()).path;
|
||||
final logsFile = File("$appSupportPath/logs/debug.log");
|
||||
if (!logsFile.existsSync()) {
|
||||
throw Exception('Logs file does not exist');
|
||||
}
|
||||
await logsFile.copy(filePath);
|
||||
return true;
|
||||
} catch (e, s) {
|
||||
ExceptionHandler.onError(FlutterErrorDetails(
|
||||
exception: e,
|
||||
stack: s,
|
||||
library: "Export Logs",
|
||||
));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> getAbbreviatedLogs() async {
|
||||
final appSupportPath = (await getApplicationSupportDirectory()).path;
|
||||
final logsFile = File("$appSupportPath/logs/debug.log");
|
||||
|
|
Loading…
Reference in a new issue