Skip to content

Commit

Permalink
Merge branch 'mweb' of https://github.com/cake-tech/cake_wallet into …
Browse files Browse the repository at this point in the history
…mweb-bg-sync-2
  • Loading branch information
fossephate committed Sep 24, 2024
2 parents fe171c4 + 967e333 commit 4e6f0dd
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 88 deletions.
7 changes: 3 additions & 4 deletions cw_bitcoin/lib/electrum_balance.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,14 @@ class ElectrumBalance extends Balance {
}

@override
String get formattedSecondAvailableBalance => bitcoinAmountToString(amount: secondConfirmed ?? 0);
String get formattedSecondAvailableBalance => bitcoinAmountToString(amount: secondConfirmed);

@override
String get formattedSecondAdditionalBalance =>
bitcoinAmountToString(amount: secondUnconfirmed ?? 0);
String get formattedSecondAdditionalBalance => bitcoinAmountToString(amount: secondUnconfirmed);

@override
String get formattedFullAvailableBalance =>
bitcoinAmountToString(amount: confirmed + (secondConfirmed ?? 0) - frozen);
bitcoinAmountToString(amount: confirmed + secondConfirmed - frozen);

String toJSON() => json.encode({
'confirmed': confirmed,
Expand Down
8 changes: 1 addition & 7 deletions cw_bitcoin/lib/electrum_wallet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1380,13 +1380,7 @@ abstract class ElectrumWalletBase
List<Map<String, dynamic>> unspents = [];
List<BitcoinUnspent> updatedUnspentCoins = [];

try {
unspents = await electrumClient.getListUnspent(address.getScriptHash(network));
} catch (e, s) {
print(e);
print(s);
return [];
}
unspents = await electrumClient.getListUnspent(address.getScriptHash(network));

await Future.wait(unspents.map((unspent) async {
try {
Expand Down
120 changes: 63 additions & 57 deletions cw_bitcoin/lib/litecoin_wallet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
late final Bip32Slip10Secp256k1 mwebHd;
late final Box<MwebUtxo> mwebUtxosBox;
Timer? _syncTimer;
Timer? _stuckSyncTimer;
Timer? _feeRatesTimer;
StreamSubscription<Utxo>? _utxoStream;
late RpcClient _stub;
Expand Down Expand Up @@ -233,6 +232,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {

Future<void> waitForMwebAddresses() async {
// ensure that we have the full 1000 mweb addresses generated before continuing:
// should no longer be needed, but leaving here just in case
final mwebAddrs = (walletAddresses as LitecoinWalletAddresses).mwebAddrs;
while (mwebAddrs.length < 1000) {
print("waiting for mweb addresses to finish generating...");
Expand All @@ -243,31 +243,35 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
@action
@override
Future<void> startSync() async {
print("STARTING SYNC @@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
if (syncStatus is SyncronizingSyncStatus) {
return;
}
print("STARTING SYNC - MWEB ENABLED: $mwebEnabled");
syncStatus = SyncronizingSyncStatus();
await subscribeForUpdates();
try {
syncStatus = SyncronizingSyncStatus();
await subscribeForUpdates();

await updateFeeRates();
_feeRatesTimer?.cancel();
_feeRatesTimer =
Timer.periodic(const Duration(minutes: 1), (timer) async => await updateFeeRates());
await updateFeeRates();
_feeRatesTimer?.cancel();
_feeRatesTimer =
Timer.periodic(const Duration(minutes: 1), (timer) async => await updateFeeRates());

if (!mwebEnabled) {
try {
await updateAllUnspents();
await updateTransactions();
await updateBalance();
syncStatus = SyncedSyncStatus();
} catch (e, s) {
print(e);
print(s);
syncStatus = FailedSyncStatus();
if (!mwebEnabled) {
try {
await updateAllUnspents();
await updateTransactions();
await updateBalance();
syncStatus = SyncedSyncStatus();
} catch (e, s) {
print(e);
print(s);
syncStatus = FailedSyncStatus();
}
return;
}
return;
}

await waitForMwebAddresses();
try {
await waitForMwebAddresses();
await getStub();
await processMwebUtxos();
await updateTransactions();
Expand Down Expand Up @@ -296,11 +300,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
} else if (resp.mwebUtxosHeight < nodeHeight) {
syncStatus = SyncingSyncStatus(1, 0.999);
} else {
// prevent unnecessary reaction triggers:
if (syncStatus is! SyncedSyncStatus) {
syncStatus = SyncedSyncStatus();
}

if (resp.mwebUtxosHeight > walletInfo.restoreHeight) {
await walletInfo.updateRestoreHeight(resp.mwebUtxosHeight);
await checkMwebUtxosSpent();
Expand All @@ -315,27 +314,12 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
}
await transactionHistory.save();
}
return;
}
});

// setup a watch dog to restart the sync process if it gets stuck:
List<double> lastFewProgresses = [];
_stuckSyncTimer?.cancel();
_stuckSyncTimer = Timer.periodic(const Duration(seconds: 10), (timer) async {
if (syncStatus is! SyncingSyncStatus) return;
if (syncStatus.progress() > 0.98) return; // don't check if we're close to synced
lastFewProgresses.add(syncStatus.progress());
if (lastFewProgresses.length < 10) return;
// limit list size to 10:
while (lastFewProgresses.length > 10) {
lastFewProgresses.removeAt(0);
}
// if the progress is the same over the last 100 seconds, restart the sync:
if (lastFewProgresses.every((p) => p == lastFewProgresses.first)) {
print("mweb syncing is stuck, restarting...");
syncStatus = LostConnectionSyncStatus();
await stopSync();
// prevent unnecessary reaction triggers:
if (syncStatus is! SyncedSyncStatus) {
syncStatus = SyncedSyncStatus();
}
return;
}
});
}
Expand All @@ -346,7 +330,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
print("STOPPING SYNC");
_syncTimer?.cancel();
_utxoStream?.cancel();
_stuckSyncTimer?.cancel();
_feeRatesTimer?.cancel();
await CwMweb.stop();
await super.stopSync();
Expand Down Expand Up @@ -507,6 +490,11 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
throw Exception("failed to get utxos stream!");
}
_utxoStream = responseStream.listen((Utxo sUtxo) async {
// we're processing utxos, so our balance could still be innacurate:
if (syncStatus is! SyncronizingSyncStatus && syncStatus is! SyncingSyncStatus) {
syncStatus = SyncronizingSyncStatus();
}

final utxo = MwebUtxo(
address: sUtxo.address,
blockTime: sUtxo.blockTime,
Expand Down Expand Up @@ -541,21 +529,29 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
return;
}

while ((await Future.wait(transactionHistory.transactions.values
.where((tx) => tx.direction == TransactionDirection.outgoing && tx.isPending)
.map(checkPendingTransaction)))
.any((x) => x));
final pendingOutgoingTransactions = transactionHistory.transactions.values
.where((tx) => tx.direction == TransactionDirection.outgoing && tx.isPending);

// check if any of the pending outgoing transactions are now confirmed:
bool updatedAny = false;
for (final tx in pendingOutgoingTransactions) {
updatedAny = await checkPendingTransaction(tx) || updatedAny;
}

// get output ids of all the mweb utxos that have > 0 height:
final outputIds =
mwebUtxosBox.values.where((utxo) => utxo.height > 0).map((utxo) => utxo.outputId).toList();

final resp = await CwMweb.spent(SpentRequest(outputId: outputIds));
final spent = resp.outputId;
if (spent.isEmpty) return;
if (spent.isEmpty) {
return;
}

final status = await CwMweb.status(StatusRequest());
final height = await electrumClient.getCurrentBlockChainTip();
if (height == null || status.blockHeaderHeight != height) return;
if (status.mwebUtxosHeight != height) return;
if (status.mwebUtxosHeight != height) return; // we aren't synced

int amount = 0;
Set<String> inputAddresses = {};
Expand Down Expand Up @@ -597,32 +593,43 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {

transactionHistory.addOne(tx);
await transactionHistory.save();

if (updatedAny) {
await updateBalance();
}
}

// checks if a pending transaction is now confirmed, and updates the tx info accordingly:
Future<bool> checkPendingTransaction(ElectrumTransactionInfo tx) async {
if (!mwebEnabled) return false;
if (!tx.isPending) return false;

final outputId = <String>[], target = <String>{};
final isHash = RegExp(r'^[a-f0-9]{64}$').hasMatch;
final spendingOutputIds = tx.inputAddresses?.where(isHash) ?? [];
final payingToOutputIds = tx.outputAddresses?.where(isHash) ?? [];
outputId.addAll(spendingOutputIds);
outputId.addAll(payingToOutputIds);
target.addAll(spendingOutputIds);

for (final outputId in payingToOutputIds) {
final spendingTx = transactionHistory.transactions.values
.firstWhereOrNull((tx) => tx.inputAddresses?.contains(outputId) ?? false);
if (spendingTx != null && !spendingTx.isPending) {
target.add(outputId);
}
}

if (outputId.isEmpty) {
return false;
}

final resp = await CwMweb.spent(SpentRequest(outputId: outputId));
if (!setEquals(resp.outputId.toSet(), target)) return false;
if (!setEquals(resp.outputId.toSet(), target)) {
return false;
}

final status = await CwMweb.status(StatusRequest());
if (!tx.isPending) return false;
tx.height = status.mwebUtxosHeight;
tx.confirmations = 1;
tx.isPending = false;
Expand Down Expand Up @@ -915,7 +922,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
final addresses = <String>{};
transaction.inputAddresses?.forEach((id) async {
final utxo = mwebUtxosBox.get(id);
// await mwebUtxosBox.delete(id);
// await mwebUtxosBox.delete(id);// gets deleted in checkMwebUtxosSpent
if (utxo == null) return;
final addressRecord = walletAddresses.allAddresses
.firstWhere((addressRecord) => addressRecord.address == utxo.address);
Expand Down Expand Up @@ -948,7 +955,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
@override
Future<void> close() async {
_utxoStream?.cancel();
_stuckSyncTimer?.cancel();
_feeRatesTimer?.cancel();
_syncTimer?.cancel();
await stopSync();
Expand Down
2 changes: 1 addition & 1 deletion lib/src/screens/receive/widgets/address_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class AddressList extends StatelessWidget {
separatorBuilder: (context, _) => const HorizontalSectionDivider(),
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: min(addressListViewModel.items.length, 100),// TODO: don't show all 1000 mweb addresses
itemCount: addressListViewModel.items.length,
itemBuilder: (context, index) {
final item = addressListViewModel.items[index];
Widget cell = Container();
Expand Down
11 changes: 0 additions & 11 deletions lib/view_model/dashboard/balance_view_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -235,17 +235,6 @@ abstract class BalanceViewModelBase with Store {
return walletBalance.formattedAdditionalBalance;
}

@computed
String get secondAdditionalBalance {
final walletBalance = _walletBalance;

if (displayMode == BalanceDisplayMode.hiddenBalance) {
return '---';
}

return walletBalance.formattedSecondAdditionalBalance;
}

@computed
String get availableFiatBalance {
final walletBalance = _walletBalance;
Expand Down
11 changes: 10 additions & 1 deletion lib/view_model/send/send_view_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,16 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
PendingTransaction? pendingTransaction;

@computed
String get balance => wallet.balance[selectedCryptoCurrency]!.formattedFullAvailableBalance;
String get balance {
String fullFormattedBalance =
wallet.balance[selectedCryptoCurrency]!.formattedFullAvailableBalance;
String formattedAvailableBalance =
wallet.balance[selectedCryptoCurrency]!.formattedAvailableBalance;
if (fullFormattedBalance.isNotEmpty) {
return fullFormattedBalance;
}
return formattedAvailableBalance;
}

@computed
bool get isFiatDisabled => balanceViewModel.isFiatDisabled;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:math';

import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/core/wallet_change_listener_view_model.dart';
import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
Expand Down Expand Up @@ -217,8 +219,9 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
}) : _baseItems = <ListItem>[],
selectedCurrency = walletTypeToCryptoCurrency(appStore.wallet!.type),
_cryptoNumberFormat = NumberFormat(_cryptoNumberPattern),
hasAccounts =
appStore.wallet!.type == WalletType.monero || appStore.wallet!.type == WalletType.wownero || appStore.wallet!.type == WalletType.haven,
hasAccounts = appStore.wallet!.type == WalletType.monero ||
appStore.wallet!.type == WalletType.wownero ||
appStore.wallet!.type == WalletType.haven,
amount = '',
_settingsStore = appStore.settingsStore,
super(appStore: appStore) {
Expand All @@ -230,7 +233,9 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
_init();

selectedCurrency = walletTypeToCryptoCurrency(wallet.type);
hasAccounts = wallet.type == WalletType.monero || wallet.type == WalletType.wownero || wallet.type == WalletType.haven;
hasAccounts = wallet.type == WalletType.monero ||
wallet.type == WalletType.wownero ||
wallet.type == WalletType.haven;
}

static const String _cryptoNumberPattern = '0.00000000';
Expand Down Expand Up @@ -446,7 +451,7 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
address: wallet.walletAddresses.address,
));
}

if (wallet.type == WalletType.tron) {
final primaryAddress = tron!.getAddress(wallet);

Expand Down Expand Up @@ -519,16 +524,17 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo

@action
Future<void> setAddressType(dynamic option) async {
if (wallet.type == WalletType.bitcoin ||
wallet.type == WalletType.litecoin) {
if (wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin) {
await bitcoin!.setAddressType(wallet, option);
}
}

void _init() {
_baseItems = [];

if (wallet.type == WalletType.monero || wallet.type == WalletType.wownero || wallet.type == WalletType.haven) {
if (wallet.type == WalletType.monero ||
wallet.type == WalletType.wownero ||
wallet.type == WalletType.haven) {
_baseItems.add(WalletAccountListHeader());
}

Expand Down

0 comments on commit 4e6f0dd

Please sign in to comment.