fix: zcash address for exchange (#3491)

* fix: zcash address for exchange

* fix: honour the restore height the user entered

- Make Zcash rescan work in both directions by resetting sync from the new birth height
- Keep the entered height when restoring a wallet from keys
- Tolerate grouping separators in typed restore heights

---------

Co-authored-by: Vik Sharma <vik@cakewallet.com>
This commit is contained in:
cyan
2026-08-11 03:15:59 +02:00
committed by GitHub
co-authored by Vik Sharma
parent 8ed08fb10e
commit 3b16f2fb7c
5 changed files with 71 additions and 2 deletions
+44 -1
View File
@@ -1021,7 +1021,50 @@ abstract class ZcashWalletBase
@override
@action
Future<void> rescan({required final int height}) async {
await zkool_sync.rewindSync(height: height, account: accountId, c: c);
syncStatus = StartingScanSyncStatus(height);
try {
await zkool_sync.cancelSync();
isSyncing = false;
await runWithCoin(
accountId: accountId,
func: (final coin) async {
await zkool_account.updateAccount(
update: zkool_account.AccountUpdate(
coin: coin.coin,
id: accountId,
birth: height,
folder: 0,
),
c: coin,
);
final accounts = await zkool_account.listAccounts(c: coin);
final updated =
accounts.where((final a) => a.id == accountId).firstOrNull;
if (updated == null) {
throw Exception('account $accountId not found after update');
}
if (updated.birth != height) {
throw Exception(
'birth height did not persist: wanted $height, '
'database still has ${updated.birth}',
);
}
await zkool_account.resetSync(id: accountId, c: coin);
},
);
lastKnownRestoreHeight = height;
await save();
syncStatus = ConnectedSyncStatus();
unawaited(startSync());
} catch (e) {
printV('Zcash rescan failed: $e');
syncStatus = FailedSyncStatus(error: e.toString());
}
// try {
// syncStatus = StartingScanSyncStatus(height);
// printV("rescanning from: $height");
@@ -220,6 +220,13 @@ abstract class ZcashWalletAddressesBase extends WalletAddresses with Store {
};
await _syncRotationHiddenAddresses();
await _applyAddressForCurrentType();
await _persistAddressForExchange();
}
Future<void> _persistAddressForExchange() async {
final addr = addressForExchange;
if (isPlaceholderAddress(addr)) return;
await walletInfo.setAddresses({addr: 'transparent'});
}
Future<void> _applyAddressForCurrentType() async {
@@ -253,6 +260,7 @@ abstract class ZcashWalletAddressesBase extends WalletAddresses with Store {
walletInfo.address = address;
}
await walletInfo.setAddresses({});
await _persistAddressForExchange();
await walletInfo.setAddressInfos(addressInfos);
await walletInfo.setUsedAddresses(usedAddresses.toList());
await walletInfo.setHiddenAddresses(hiddenAddresses.toList());
@@ -215,6 +215,10 @@ class WalletRestorePage extends BasePage {
walletRestoreFromKeysFormKey.currentState!.privateKeyController.text;
credentials['name'] =
walletRestoreFromKeysFormKey.currentState!.nameTextEditingController.text;
if (walletRestoreViewModel.hasBlockchainHeightSelector) {
credentials['height'] =
walletRestoreFromKeysFormKey.currentState!.blockchainHeightKey.currentState?.height;
}
} else {
credentials['name'] =
walletRestoreFromKeysFormKey.currentState!.nameTextEditingController.text;
@@ -65,7 +65,8 @@ class BlockchainHeightState extends State<BlockchainHeightWidget> {
try {
final int _height;
if (restoreHeightController.text.isNotEmpty) {
_height = int.tryParse(restoreHeightController.text) ?? 0;
final digits = restoreHeightController.text.replaceAll(RegExp(r'[^0-9]'), '');
_height = int.tryParse(digits) ?? 0;
} else {
_height = 0;
}
@@ -1185,6 +1185,19 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
}
}
if (receiveCurrency == CryptoCurrency.zec &&
selectedAddressBookWallet?.type == WalletType.zcash) {
if (wallet.type == WalletType.zcash && wallet.name == selectedAddressBookWallet!.name) {
receiveAddress = wallet.walletAddresses.addressForExchange;
} else {
receiveAddress = (await selectedAddressBookWallet!.getAddresses())
.entries
.firstWhereOrNull((e) => e.value == 'transparent')
?.key ??
receiveAddress;
}
}
// parse Lightning address to bolt11 invoice
if (receiveAddress.contains("@")) {
receiveAddress = await getBolt11FromLightingAddress(receiveAddress) ?? receiveAddress;