feat: zano hf + bip39 (#3359)

* feat: bip39 zano hf

* fix: correct monero_c hash

* lockfile [skip ci]

* fix: zano: proper bip32
fix: zano respect 24 word setting
fix: rename / delete

* fix: nonBip39WalletTypes

* fix: zano wallet rename

* fix: passphrase store zano

---------

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
cyan
2026-08-28 15:49:51 +08:00
committed by GitHub
co-authored by Omar Hatem
parent 14167a85e8
commit 905db64f77
27 changed files with 1074 additions and 106 deletions
+1 -1
View File
@@ -86,6 +86,7 @@ class WalletCreationService {
case WalletType.dogecoin:
case WalletType.nano:
case WalletType.zcash:
case WalletType.zano:
case WalletType.decred:
return true;
case WalletType.monero:
@@ -93,7 +94,6 @@ class WalletCreationService {
case WalletType.none:
case WalletType.haven:
case WalletType.banano:
case WalletType.zano:
return false;
}
}
+1 -1
View File
@@ -1341,7 +1341,7 @@ Future<void> setup({
case WalletType.wownero:
return wownero!.createWowneroWalletService(_unspentCoinsInfoSource);
case WalletType.zano:
return zano!.createZanoWalletService();
return zano!.createZanoWalletService(SettingsStoreBase.walletPasswordDirectInput);
case WalletType.decred:
return decred!.createDecredWalletService(
_unspentCoinsInfoSource, SettingsStoreBase.walletPasswordDirectInput);
+1 -1
View File
@@ -17,11 +17,11 @@ bool isBIP39Wallet(WalletType walletType) {
case WalletType.monero:
case WalletType.dogecoin:
case WalletType.zcash:
case WalletType.zano:
case WalletType.decred:
return true;
case WalletType.wownero:
case WalletType.haven:
case WalletType.zano:
case WalletType.none:
return false;
}
@@ -286,7 +286,12 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
'wallet_restore_from_seed_blockheight_textfield_key',
),
onHeightOrDateEntered: widget.onHeightOrDateEntered,
hasDatePicker: [WalletType.monero, WalletType.wownero, WalletType.zcash].contains(
hasDatePicker: [
WalletType.monero,
WalletType.wownero,
WalletType.zcash,
WalletType.zano,
].contains(
widget.type,
),
walletType: widget.type,
@@ -13,6 +13,7 @@ import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/restore/restore_mode.dart';
import 'package:cake_wallet/view_model/seed_settings_view_model.dart';
import 'package:cake_wallet/view_model/wallet_restore_view_model.dart';
import 'package:cake_wallet/zano/zano.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:flutter/material.dart';
@@ -606,7 +607,13 @@ class _WalletRestorePageBodyState extends State<_WalletRestorePageBody>
final seedWords = seedPhrase.split(' ');
if (seedWords.length == 14 && walletRestoreViewModel.type == WalletType.wownero) return true;
if (seedWords.length == 26 && walletRestoreViewModel.type == WalletType.zano) return true;
if (walletRestoreViewModel.type == WalletType.zano) {
if (seedWords.length == 26) return true;
if ([12, 24].contains(seedWords.length) && zano!.isBip39Seed(seedPhrase.trim())) {
return true;
}
return false;
}
if (seedWords.length == 12 && walletRestoreViewModel.type == WalletType.monero) {
return walletRestoreFromSeedFormKey.currentState?.blockchainHeightKey.currentState
@@ -2,6 +2,7 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/src/widgets/standard_switch.dart';
import 'package:cake_wallet/utils/date_picker.dart';
import 'package:cake_wallet/wownero/wownero.dart';
import 'package:cake_wallet/zano/zano.dart';
import 'package:cake_wallet/zcash/zcash.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:flutter/material.dart';
@@ -200,6 +201,8 @@ class BlockchainHeightState extends State<BlockchainHeightWidget> {
height = wownero!.getHeightByDate(date: date);
} else if (widget.walletType == WalletType.zcash) {
height = await zcash!.getHeightByDate(date);
} else if (widget.walletType == WalletType.zano) {
height = zano!.getHeightByDate(date: date);
} else {
throw Exception("unknown currency in BlockchainHeightWidget");
}
@@ -59,6 +59,7 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
case WalletType.solana:
case WalletType.tron:
case WalletType.zcash:
case WalletType.zano:
case WalletType.decred:
return true;
@@ -74,7 +75,6 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
case WalletType.wownero:
case WalletType.none:
case WalletType.haven:
case WalletType.zano:
return false;
}
}
@@ -128,8 +128,9 @@ abstract class WalletGroupsDisplayViewModelBase with Store {
bool isNonSeedWallet = wallet.isNonSeedWallet;
bool isNotMoneroBip39Wallet =
wallet.type == WalletType.monero && di.derivationType != DerivationType.bip39;
bool isNotBip39CoinWallet =
(wallet.type == WalletType.monero || wallet.type == WalletType.zano) &&
di.derivationType != DerivationType.bip39;
bool isNotDecredBip39Wallet = wallet.type == WalletType.decred &&
di.derivationType != DerivationType.bip39 &&
@@ -142,7 +143,7 @@ abstract class WalletGroupsDisplayViewModelBase with Store {
isElectrumDerivationType ||
isSameTypeAsSelectedWallet ||
isNonSeedWallet ||
isNotMoneroBip39Wallet ||
isNotBip39CoinWallet ||
isNotDecredBip39Wallet;
}
+1
View File
@@ -139,6 +139,7 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
name: name,
password: walletPassword,
passphrase: passphrase,
mnemonic: newWalletArguments!.mnemonic,
);
case WalletType.zcash:
return zcash!.createZcashNewWalletCredentials(
+21 -3
View File
@@ -83,8 +83,13 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
late final bool hasSeedLanguageSelector =
[WalletType.monero, WalletType.haven, WalletType.wownero].contains(type);
late final bool hasBlockchainHeightSelector =
[WalletType.monero, WalletType.haven, WalletType.wownero, WalletType.zcash].contains(type);
late final bool hasBlockchainHeightSelector = [
WalletType.monero,
WalletType.haven,
WalletType.wownero,
WalletType.zcash,
WalletType.zano,
].contains(type);
late final bool hasRestoreFromPrivateKey = [
WalletType.ethereum,
@@ -204,13 +209,15 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
height: height,
);
case WalletType.zano:
return zano!.createZanoRestoreWalletFromSeedCredentials(
final credentials = zano!.createZanoRestoreWalletFromSeedCredentials(
name: name,
password: password,
height: height,
passphrase: passphrase ?? '',
mnemonic: seed,
);
credentials.derivationInfo = derivationInfo;
return credentials;
case WalletType.decred:
return decred!.createDecredRestoreWalletFromSeedCredentials(
name: name,
@@ -363,6 +370,17 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
seedKey: seedKey,
node: node,
);
case WalletType.zano:
final mnemonic = (credentials['seed'] as String?)?.trim() ?? '';
if (mnemonic.isEmpty) break;
if (zano!.isBip39Seed(mnemonic)) {
return [
DerivationInfo(derivationType: DerivationType.bip39),
];
}
return [
DerivationInfo(derivationType: DerivationType.unknown),
];
default:
break;
}
+21 -6
View File
@@ -46,7 +46,7 @@ class CWZano extends Zano {
@override
List<String> getWordList(String language) {
assert(language.toLowerCase() == LanguageList.english.toLowerCase());
return EnglishMnemonics.words;
return [...zano_bip39.bip39EnglishWords, ...EnglishMnemonics.words];
}
@override
@@ -61,9 +61,18 @@ class CWZano extends Zano {
}
@override
WalletCredentials createZanoNewWalletCredentials(
{required String name, required String? password, required String? passphrase}) {
return ZanoNewWalletCredentials(name: name, password: password, passphrase: passphrase);
WalletCredentials createZanoNewWalletCredentials({
required String name,
required String? password,
required String? passphrase,
String? mnemonic,
}) {
return ZanoNewWalletCredentials(
name: name,
password: password,
passphrase: passphrase,
mnemonic: mnemonic,
);
}
@override
@@ -122,8 +131,8 @@ class CWZano extends Zano {
// }
@override
WalletService createZanoWalletService() {
return ZanoWalletService();
WalletService createZanoWalletService(bool isDirect) {
return ZanoWalletService(isDirect);
}
@override
@@ -146,6 +155,12 @@ class CWZano extends Zano {
@override
bool validateAddress(String address) => ZanoUtils.validateAddress(address);
@override
bool isBip39Seed(String mnemonic) => zano_bip39.isBip39Seed(mnemonic);
@override
int getHeightByDate({required DateTime date}) => ZanoUtils.heightByDate(date);
@override
Map<String, List<int>> debugCallLength() {
return api.debugCallLength();