mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-01-30 14:36:06 +00:00
updates
This commit is contained in:
parent
a2121ef73e
commit
964f66c74a
9 changed files with 229 additions and 61 deletions
|
@ -416,23 +416,19 @@ abstract class ElectrumWalletBase
|
|||
await _setInitialHeight();
|
||||
}
|
||||
|
||||
if (this is! LitecoinWallet) {
|
||||
await _subscribeForUpdates();
|
||||
await updateTransactions();
|
||||
await subscribeForUpdates();
|
||||
await updateTransactions();
|
||||
|
||||
await updateAllUnspents();
|
||||
await updateBalance();
|
||||
}
|
||||
await updateAllUnspents();
|
||||
await updateBalance();
|
||||
|
||||
await updateFeeRates();
|
||||
Timer.periodic(const Duration(minutes: 1), (timer) async => await updateFeeRates());
|
||||
|
||||
if (this is! LitecoinWallet) {
|
||||
if (alwaysScan == true) {
|
||||
_setListeners(walletInfo.restoreHeight);
|
||||
} else {
|
||||
syncStatus = SyncedSyncStatus();
|
||||
}
|
||||
if (alwaysScan == true) {
|
||||
_setListeners(walletInfo.restoreHeight);
|
||||
} else {
|
||||
syncStatus = SyncedSyncStatus();
|
||||
}
|
||||
} catch (e, stacktrace) {
|
||||
print(stacktrace);
|
||||
|
@ -1595,7 +1591,7 @@ abstract class ElectrumWalletBase
|
|||
matchedAddresses.toList(),
|
||||
addressRecord.isHidden,
|
||||
(address) async {
|
||||
await _subscribeForUpdates();
|
||||
await subscribeForUpdates();
|
||||
return _fetchAddressHistory(address, await getCurrentChainTip())
|
||||
.then((history) => history.isNotEmpty ? address.address : null);
|
||||
},
|
||||
|
@ -1684,7 +1680,7 @@ abstract class ElectrumWalletBase
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> _subscribeForUpdates() async {
|
||||
Future<void> subscribeForUpdates() async {
|
||||
final unsubscribedScriptHashes = walletAddresses.allAddresses.where(
|
||||
(address) => !_scripthashesUpdateSubject.containsKey(address.getScriptHash(network)),
|
||||
);
|
||||
|
|
|
@ -89,6 +89,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
StreamSubscription<Utxo>? _utxoStream;
|
||||
int mwebUtxosHeight = 0;
|
||||
late RpcClient _stub;
|
||||
late bool mwebEnabled = true;
|
||||
|
||||
static Future<LitecoinWallet> create(
|
||||
{required String mnemonic,
|
||||
|
@ -154,17 +155,26 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
@action
|
||||
@override
|
||||
Future<void> startSync() async {
|
||||
await super.startSync();
|
||||
if (!mwebEnabled) {
|
||||
syncStatus = SyncronizingSyncStatus();
|
||||
await subscribeForUpdates();
|
||||
await updateTransactions();
|
||||
syncStatus = SyncedSyncStatus();
|
||||
return;
|
||||
}
|
||||
|
||||
await subscribeForUpdates();
|
||||
await updateTransactions();
|
||||
await updateFeeRates();
|
||||
|
||||
Timer.periodic(const Duration(minutes: 1), (timer) async => await updateFeeRates());
|
||||
|
||||
_stub = await CwMweb.stub();
|
||||
_syncTimer?.cancel();
|
||||
_syncTimer = Timer.periodic(const Duration(milliseconds: 1500), (timer) async {
|
||||
if (syncStatus is FailedSyncStatus) return;
|
||||
final height = await electrumClient.getCurrentBlockChainTip() ?? 0;
|
||||
final resp = await _stub.status(StatusRequest());
|
||||
// print("height: $height");
|
||||
// print("resp.blockHeaderHeight: ${resp.blockHeaderHeight}");
|
||||
// print("resp.mwebHeaderHeight: ${resp.mwebHeaderHeight}");
|
||||
// print("resp.mwebUtxosHeight: ${resp.mwebUtxosHeight}");
|
||||
if (resp.blockHeaderHeight < height) {
|
||||
int h = resp.blockHeaderHeight;
|
||||
syncStatus = SyncingSyncStatus(height - h, h / height);
|
||||
|
@ -211,6 +221,21 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
mwebUtxosBox = await CakeHive.openBox<MwebUtxo>(boxName);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> renameWalletFiles(String newWalletName) async {
|
||||
// rename the hive box:
|
||||
final oldBoxName = "${walletInfo.name.replaceAll(" ", "_")}_${MwebUtxo.boxName}";
|
||||
final newBoxName = "${newWalletName.replaceAll(" ", "_")}_${MwebUtxo.boxName}";
|
||||
|
||||
final oldBox = await Hive.openBox<MwebUtxo>(oldBoxName);
|
||||
mwebUtxosBox = await CakeHive.openBox<MwebUtxo>(newBoxName);
|
||||
for (final key in oldBox.keys) {
|
||||
await mwebUtxosBox.put(key, oldBox.get(key)!);
|
||||
}
|
||||
|
||||
await super.renameWalletFiles(newWalletName);
|
||||
}
|
||||
|
||||
@action
|
||||
@override
|
||||
Future<void> rescan({
|
||||
|
@ -261,11 +286,15 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
);
|
||||
}
|
||||
|
||||
tx.height = utxo.height;
|
||||
tx.isPending = utxo.height == 0;
|
||||
tx.confirmations = confirmations;
|
||||
bool isNew = transactionHistory.transactions[tx.id] == null;
|
||||
|
||||
// don't update the confirmations if the tx is updated by electrum:
|
||||
if (tx.confirmations == 0 || utxo.height != 0) {
|
||||
tx.height = utxo.height;
|
||||
tx.isPending = utxo.height == 0;
|
||||
tx.confirmations = confirmations;
|
||||
}
|
||||
|
||||
if (!(tx.outputAddresses?.contains(utxo.address) ?? false)) {
|
||||
tx.outputAddresses?.add(utxo.address);
|
||||
isNew = true;
|
||||
|
@ -295,12 +324,10 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
int restoreHeight = walletInfo.restoreHeight;
|
||||
print("SCANNING FROM HEIGHT: $restoreHeight");
|
||||
final req = UtxosRequest(scanSecret: hex.decode(scanSecret), fromHeight: restoreHeight);
|
||||
bool initDone = false;
|
||||
|
||||
// process old utxos:
|
||||
for (final utxo in mwebUtxosBox.values) {
|
||||
if (utxo.address.isEmpty) {
|
||||
initDone = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -310,11 +337,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
|
||||
await handleIncoming(utxo, _stub);
|
||||
|
||||
// if (initDone) {
|
||||
// await updateUnspent();
|
||||
// await updateBalance();
|
||||
// }
|
||||
|
||||
if (utxo.height > walletInfo.restoreHeight) {
|
||||
walletInfo.updateRestoreHeight(utxo.height);
|
||||
}
|
||||
|
@ -459,36 +481,38 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
updatedUnspentCoins.addAll(await fetchUnspent(address));
|
||||
}));
|
||||
|
||||
// update mweb unspents:
|
||||
final mwebAddrs = (walletAddresses as LitecoinWalletAddresses).mwebAddrs;
|
||||
mwebUtxosBox.keys.forEach((dynamic oId) {
|
||||
final String outputId = oId as String;
|
||||
final utxo = mwebUtxosBox.get(outputId);
|
||||
if (utxo == null) {
|
||||
return;
|
||||
}
|
||||
if (utxo.address.isEmpty) {
|
||||
// not sure if a bug or a special case but we definitely ignore these
|
||||
return;
|
||||
}
|
||||
final addressRecord = walletAddresses.allAddresses
|
||||
.firstWhereOrNull((addressRecord) => addressRecord.address == utxo.address);
|
||||
if (mwebEnabled) {
|
||||
// update mweb unspents:
|
||||
final mwebAddrs = (walletAddresses as LitecoinWalletAddresses).mwebAddrs;
|
||||
mwebUtxosBox.keys.forEach((dynamic oId) {
|
||||
final String outputId = oId as String;
|
||||
final utxo = mwebUtxosBox.get(outputId);
|
||||
if (utxo == null) {
|
||||
return;
|
||||
}
|
||||
if (utxo.address.isEmpty) {
|
||||
// not sure if a bug or a special case but we definitely ignore these
|
||||
return;
|
||||
}
|
||||
final addressRecord = walletAddresses.allAddresses
|
||||
.firstWhereOrNull((addressRecord) => addressRecord.address == utxo.address);
|
||||
|
||||
if (addressRecord == null) {
|
||||
print("addressRecord is null! TODO: handle this case2");
|
||||
return;
|
||||
}
|
||||
final unspent = BitcoinUnspent(
|
||||
addressRecord,
|
||||
outputId,
|
||||
utxo.value.toInt(),
|
||||
mwebAddrs.indexOf(utxo.address),
|
||||
);
|
||||
if (unspent.vout == 0) {
|
||||
unspent.isChange = true;
|
||||
}
|
||||
updatedUnspentCoins.add(unspent);
|
||||
});
|
||||
if (addressRecord == null) {
|
||||
print("utxo contains an address that is not in the wallet: ${utxo.address}");
|
||||
return;
|
||||
}
|
||||
final unspent = BitcoinUnspent(
|
||||
addressRecord,
|
||||
outputId,
|
||||
utxo.value.toInt(),
|
||||
mwebAddrs.indexOf(utxo.address),
|
||||
);
|
||||
if (unspent.vout == 0) {
|
||||
unspent.isChange = true;
|
||||
}
|
||||
updatedUnspentCoins.add(unspent);
|
||||
});
|
||||
}
|
||||
|
||||
unspentCoins = updatedUnspentCoins;
|
||||
}
|
||||
|
@ -638,7 +662,12 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
@override
|
||||
Future<PendingTransaction> createTransaction(Object credentials) async {
|
||||
try {
|
||||
final tx = await super.createTransaction(credentials) as PendingBitcoinTransaction;
|
||||
var tx = await super.createTransaction(credentials) as PendingBitcoinTransaction;
|
||||
tx.isMweb = mwebEnabled;
|
||||
|
||||
if (!mwebEnabled) {
|
||||
return tx;
|
||||
}
|
||||
|
||||
final resp = await _stub.create(CreateRequest(
|
||||
rawTx: hex.decode(tx.hex),
|
||||
|
@ -708,4 +737,14 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
await mwebUtxosBox.close();
|
||||
_syncTimer?.cancel();
|
||||
}
|
||||
|
||||
void setMwebEnabled(bool enabled) {
|
||||
if (!mwebEnabled && enabled) {
|
||||
mwebEnabled = enabled;
|
||||
startSync();
|
||||
}
|
||||
mwebEnabled = enabled;
|
||||
}
|
||||
|
||||
bool get isMwebEnabled => mwebEnabled;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ class PendingBitcoinTransaction with PendingTransaction {
|
|||
required this.hasChange,
|
||||
this.isSendAll = false,
|
||||
this.hasTaprootInputs = false,
|
||||
this.isMweb = false,
|
||||
}) : _listeners = <void Function(ElectrumTransactionInfo transaction)>[];
|
||||
|
||||
final WalletType type;
|
||||
|
@ -35,6 +36,7 @@ class PendingBitcoinTransaction with PendingTransaction {
|
|||
final bool isSendAll;
|
||||
final bool hasChange;
|
||||
final bool hasTaprootInputs;
|
||||
bool isMweb;
|
||||
String? idOverride;
|
||||
String? hexOverride;
|
||||
List<String>? outputs;
|
||||
|
@ -103,7 +105,7 @@ class PendingBitcoinTransaction with PendingTransaction {
|
|||
|
||||
@override
|
||||
Future<void> commit() async {
|
||||
if (network is LitecoinNetwork) {
|
||||
if (isMweb) {
|
||||
await _ltcCommit();
|
||||
} else {
|
||||
await _commit();
|
||||
|
|
|
@ -582,4 +582,16 @@ class CWBitcoin extends Bitcoin {
|
|||
final bitcoinWallet = wallet as ElectrumWallet;
|
||||
await bitcoinWallet.updateFeeRates();
|
||||
}
|
||||
|
||||
@override
|
||||
void setMwebEnabled(Object wallet, bool enabled) {
|
||||
final litecoinWallet = wallet as LitecoinWallet;
|
||||
litecoinWallet.setMwebEnabled(enabled);
|
||||
}
|
||||
|
||||
@override
|
||||
bool getMwebEnabled(Object wallet) {
|
||||
final litecoinWallet = wallet as LitecoinWallet;
|
||||
return litecoinWallet.isMwebEnabled;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,8 @@ class PreferencesKey {
|
|||
static const customBitcoinFeeRate = 'custom_electrum_fee_rate';
|
||||
static const silentPaymentsCardDisplay = 'silentPaymentsCardDisplay';
|
||||
static const silentPaymentsAlwaysScan = 'silentPaymentsAlwaysScan';
|
||||
static const mwebCardDisplay = 'mwebCardDisplay';
|
||||
static const mwebEnabled = 'mwebEnabled';
|
||||
static const shouldShowReceiveWarning = 'should_show_receive_warning';
|
||||
static const shouldShowYatPopup = 'should_show_yat_popup';
|
||||
static const shouldShowRepWarning = 'should_show_rep_warning';
|
||||
|
|
|
@ -315,7 +315,73 @@ class CryptoBalanceWidget extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
),
|
||||
]
|
||||
],
|
||||
if (dashboardViewModel.showMwebCard) ...[
|
||||
SizedBox(height: 10),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 0, 16, 8),
|
||||
child: DashBoardRoundedCardWidget(
|
||||
customBorder: 30,
|
||||
title: "T: MWEB",
|
||||
subTitle: "T: Enable MWEB",
|
||||
hint: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () => launchUrl(
|
||||
Uri.parse(
|
||||
"https://guides.cakewallet.com/docs/cryptos/bitcoin/#silent-payments"),
|
||||
mode: LaunchMode.externalApplication,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"T: What is MWEB?",
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Theme.of(context)
|
||||
.extension<BalancePageTheme>()!
|
||||
.labelTextColor,
|
||||
height: 1,
|
||||
),
|
||||
softWrap: true,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
child: Icon(Icons.help_outline,
|
||||
size: 16,
|
||||
color: Theme.of(context)
|
||||
.extension<BalancePageTheme>()!
|
||||
.labelTextColor),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Observer(
|
||||
builder: (_) => StandardSwitch(
|
||||
value: dashboardViewModel.mwebEnabled,
|
||||
onTaped: () => _toggleMweb(context),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
onTap: () => _toggleMweb(context),
|
||||
icon: Icon(
|
||||
Icons.lock,
|
||||
color:
|
||||
Theme.of(context).extension<DashboardPageTheme>()!.pageTitleTextColor,
|
||||
size: 50,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
}),
|
||||
|
@ -355,6 +421,13 @@ class CryptoBalanceWidget extends StatelessWidget {
|
|||
|
||||
return dashboardViewModel.setSilentPaymentsScanning(newValue);
|
||||
}
|
||||
|
||||
|
||||
Future<void> _toggleMweb(BuildContext context) async {
|
||||
final isMwebEnabled = dashboardViewModel.mwebEnabled;
|
||||
final newValue = !isMwebEnabled;
|
||||
return dashboardViewModel.setMwebEnabled(newValue);
|
||||
}
|
||||
}
|
||||
|
||||
class BalanceRowWidget extends StatelessWidget {
|
||||
|
|
|
@ -110,6 +110,8 @@ abstract class SettingsStoreBase with Store {
|
|||
required this.customBitcoinFeeRate,
|
||||
required this.silentPaymentsCardDisplay,
|
||||
required this.silentPaymentsAlwaysScan,
|
||||
required this.mwebCardDisplay,
|
||||
required this.mwebEnabled,
|
||||
TransactionPriority? initialBitcoinTransactionPriority,
|
||||
TransactionPriority? initialMoneroTransactionPriority,
|
||||
TransactionPriority? initialWowneroTransactionPriority,
|
||||
|
@ -536,6 +538,14 @@ abstract class SettingsStoreBase with Store {
|
|||
(bool silentPaymentsAlwaysScan) => _sharedPreferences.setBool(
|
||||
PreferencesKey.silentPaymentsAlwaysScan, silentPaymentsAlwaysScan));
|
||||
|
||||
reaction(
|
||||
(_) => mwebCardDisplay,
|
||||
(bool mwebCardDisplay) =>
|
||||
_sharedPreferences.setBool(PreferencesKey.mwebCardDisplay, mwebCardDisplay));
|
||||
|
||||
reaction((_) => mwebEnabled,
|
||||
(bool mwebEnabled) => _sharedPreferences.setBool(PreferencesKey.mwebEnabled, mwebEnabled));
|
||||
|
||||
this.nodes.observe((change) {
|
||||
if (change.newValue != null && change.key != null) {
|
||||
_saveCurrentNode(change.newValue!, change.key!);
|
||||
|
@ -737,6 +747,12 @@ abstract class SettingsStoreBase with Store {
|
|||
@observable
|
||||
bool silentPaymentsAlwaysScan;
|
||||
|
||||
@observable
|
||||
bool mwebCardDisplay;
|
||||
|
||||
@observable
|
||||
bool mwebEnabled;
|
||||
|
||||
final SecureStorage _secureStorage;
|
||||
final SharedPreferences _sharedPreferences;
|
||||
final BackgroundTasks _backgroundTasks;
|
||||
|
@ -893,6 +909,8 @@ abstract class SettingsStoreBase with Store {
|
|||
sharedPreferences.getBool(PreferencesKey.silentPaymentsCardDisplay) ?? true;
|
||||
final silentPaymentsAlwaysScan =
|
||||
sharedPreferences.getBool(PreferencesKey.silentPaymentsAlwaysScan) ?? false;
|
||||
final mwebCardDisplay = sharedPreferences.getBool(PreferencesKey.mwebCardDisplay) ?? true;
|
||||
final mwebEnabled = sharedPreferences.getBool(PreferencesKey.mwebEnabled) ?? false;
|
||||
|
||||
// If no value
|
||||
if (pinLength == null || pinLength == 0) {
|
||||
|
@ -1145,6 +1163,8 @@ abstract class SettingsStoreBase with Store {
|
|||
customBitcoinFeeRate: customBitcoinFeeRate,
|
||||
silentPaymentsCardDisplay: silentPaymentsCardDisplay,
|
||||
silentPaymentsAlwaysScan: silentPaymentsAlwaysScan,
|
||||
mwebCardDisplay: mwebCardDisplay,
|
||||
mwebEnabled: mwebEnabled,
|
||||
initialMoneroTransactionPriority: moneroTransactionPriority,
|
||||
initialWowneroTransactionPriority: wowneroTransactionPriority,
|
||||
initialBitcoinTransactionPriority: bitcoinTransactionPriority,
|
||||
|
@ -1293,6 +1313,8 @@ abstract class SettingsStoreBase with Store {
|
|||
sharedPreferences.getBool(PreferencesKey.silentPaymentsCardDisplay) ?? true;
|
||||
silentPaymentsAlwaysScan =
|
||||
sharedPreferences.getBool(PreferencesKey.silentPaymentsAlwaysScan) ?? false;
|
||||
mwebCardDisplay = sharedPreferences.getBool(PreferencesKey.mwebCardDisplay) ?? true;
|
||||
mwebEnabled = sharedPreferences.getBool(PreferencesKey.mwebEnabled) ?? false;
|
||||
final nodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey);
|
||||
final bitcoinElectrumServerId =
|
||||
sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey);
|
||||
|
|
|
@ -329,6 +329,24 @@ abstract class DashboardViewModelBase with Store {
|
|||
}
|
||||
}
|
||||
|
||||
@computed
|
||||
bool get hasMweb => wallet.type == WalletType.litecoin;
|
||||
|
||||
@computed
|
||||
bool get showMwebCard => hasMweb && settingsStore.mwebCardDisplay;
|
||||
|
||||
@observable
|
||||
bool mwebEnabled = false;
|
||||
|
||||
@action
|
||||
void setMwebEnabled(bool active) {
|
||||
mwebEnabled = active;
|
||||
|
||||
if (hasMweb) {
|
||||
bitcoin!.setMwebEnabled(wallet, active);
|
||||
}
|
||||
}
|
||||
|
||||
BalanceViewModel balanceViewModel;
|
||||
|
||||
AppStore appStore;
|
||||
|
|
|
@ -115,6 +115,7 @@ import 'package:cw_bitcoin/bitcoin_amount_format.dart';
|
|||
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart';
|
||||
import 'package:cw_bitcoin/litecoin_wallet_service.dart';
|
||||
import 'package:cw_bitcoin/litecoin_wallet.dart';
|
||||
import 'package:cw_core/get_height_by_date.dart';
|
||||
import 'package:cw_bitcoin/script_hash.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_hardware_wallet_service.dart';
|
||||
|
@ -219,6 +220,9 @@ abstract class Bitcoin {
|
|||
|
||||
void setLedger(WalletBase wallet, Ledger ledger, LedgerDevice device);
|
||||
Future<List<HardwareAccountData>> getHardwareWalletAccounts(LedgerViewModel ledgerVM, {int index = 0, int limit = 5});
|
||||
|
||||
void setMwebEnabled(Object wallet, bool enabled);
|
||||
bool getMwebEnabled(Object wallet);
|
||||
}
|
||||
""";
|
||||
|
||||
|
|
Loading…
Reference in a new issue