mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-22 11:39:22 +00:00
Nano rep page + derivation fixes (#1655)
Some checks are pending
Cache Dependencies / test (push) Waiting to run
Some checks are pending
Cache Dependencies / test (push) Waiting to run
* minor nano derivation fixes * rep page fixes * ignore non-critical receive block errors * really be sure the derivation type is set during wallet creation
This commit is contained in:
parent
576dd49766
commit
783f1a2349
4 changed files with 80 additions and 59 deletions
|
@ -466,21 +466,25 @@ class NanoClient {
|
||||||
|
|
||||||
blocks = blocks as Map<String, dynamic>;
|
blocks = blocks as Map<String, dynamic>;
|
||||||
|
|
||||||
// confirm all receivable blocks:
|
try {
|
||||||
for (final blockHash in blocks.keys) {
|
// confirm all receivable blocks:
|
||||||
final block = blocks[blockHash];
|
for (final blockHash in blocks.keys) {
|
||||||
final String amountRaw = block["amount"] as String;
|
final block = blocks[blockHash];
|
||||||
await receiveBlock(
|
final String amountRaw = block["amount"] as String;
|
||||||
blockHash: blockHash,
|
await receiveBlock(
|
||||||
amountRaw: amountRaw,
|
blockHash: blockHash,
|
||||||
privateKey: privateKey,
|
amountRaw: amountRaw,
|
||||||
destinationAddress: destinationAddress,
|
privateKey: privateKey,
|
||||||
);
|
destinationAddress: destinationAddress,
|
||||||
// a bit of a hack:
|
);
|
||||||
await Future<void>.delayed(const Duration(seconds: 2));
|
// a bit of a hack:
|
||||||
|
await Future<void>.delayed(const Duration(seconds: 2));
|
||||||
|
}
|
||||||
|
return blocks.keys.length;
|
||||||
|
} catch (_) {
|
||||||
|
// we failed to confirm all receivable blocks for w/e reason (PoW / node outage / etc)
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return blocks.keys.length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop() {}
|
void stop() {}
|
||||||
|
|
|
@ -14,8 +14,11 @@ import 'package:bip39/bip39.dart' as bip39;
|
||||||
import 'package:nanodart/nanodart.dart';
|
import 'package:nanodart/nanodart.dart';
|
||||||
import 'package:nanoutil/nanoutil.dart';
|
import 'package:nanoutil/nanoutil.dart';
|
||||||
|
|
||||||
class NanoWalletService extends WalletService<NanoNewWalletCredentials,
|
class NanoWalletService extends WalletService<
|
||||||
NanoRestoreWalletFromSeedCredentials, NanoRestoreWalletFromKeysCredentials, NanoNewWalletCredentials> {
|
NanoNewWalletCredentials,
|
||||||
|
NanoRestoreWalletFromSeedCredentials,
|
||||||
|
NanoRestoreWalletFromKeysCredentials,
|
||||||
|
NanoNewWalletCredentials> {
|
||||||
NanoWalletService(this.walletInfoSource, this.isDirect);
|
NanoWalletService(this.walletInfoSource, this.isDirect);
|
||||||
|
|
||||||
final Box<WalletInfo> walletInfoSource;
|
final Box<WalletInfo> walletInfoSource;
|
||||||
|
@ -33,8 +36,12 @@ class NanoWalletService extends WalletService<NanoNewWalletCredentials,
|
||||||
String seedKey = NanoSeeds.generateSeed();
|
String seedKey = NanoSeeds.generateSeed();
|
||||||
String mnemonic = NanoDerivations.standardSeedToMnemonic(seedKey);
|
String mnemonic = NanoDerivations.standardSeedToMnemonic(seedKey);
|
||||||
|
|
||||||
// ensure default if not present:
|
// should never happen but just in case:
|
||||||
credentials.walletInfo!.derivationInfo ??= DerivationInfo(derivationType: DerivationType.nano);
|
if (credentials.walletInfo!.derivationInfo == null) {
|
||||||
|
credentials.walletInfo!.derivationInfo = DerivationInfo(derivationType: DerivationType.nano);
|
||||||
|
} else if (credentials.walletInfo!.derivationInfo!.derivationType == null) {
|
||||||
|
credentials.walletInfo!.derivationInfo!.derivationType = DerivationType.nano;
|
||||||
|
}
|
||||||
|
|
||||||
final wallet = NanoWallet(
|
final wallet = NanoWallet(
|
||||||
walletInfo: credentials.walletInfo!,
|
walletInfo: credentials.walletInfo!,
|
||||||
|
@ -86,7 +93,8 @@ class NanoWalletService extends WalletService<NanoNewWalletCredentials,
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<NanoWallet> restoreFromKeys(NanoRestoreWalletFromKeysCredentials credentials, {bool? isTestnet}) async {
|
Future<NanoWallet> restoreFromKeys(NanoRestoreWalletFromKeysCredentials credentials,
|
||||||
|
{bool? isTestnet}) async {
|
||||||
if (credentials.seedKey.contains(' ')) {
|
if (credentials.seedKey.contains(' ')) {
|
||||||
throw Exception("Invalid key!");
|
throw Exception("Invalid key!");
|
||||||
} else {
|
} else {
|
||||||
|
@ -106,6 +114,13 @@ class NanoWalletService extends WalletService<NanoNewWalletCredentials,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// should never happen but just in case:
|
||||||
|
if (credentials.walletInfo!.derivationInfo == null) {
|
||||||
|
credentials.walletInfo!.derivationInfo = DerivationInfo(derivationType: DerivationType.nano);
|
||||||
|
} else if (credentials.walletInfo!.derivationInfo!.derivationType == null) {
|
||||||
|
credentials.walletInfo!.derivationInfo!.derivationType = DerivationType.nano;
|
||||||
|
}
|
||||||
|
|
||||||
final wallet = await NanoWallet(
|
final wallet = await NanoWallet(
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
mnemonic: mnemonic ?? credentials.seedKey,
|
mnemonic: mnemonic ?? credentials.seedKey,
|
||||||
|
@ -119,11 +134,13 @@ class NanoWalletService extends WalletService<NanoNewWalletCredentials,
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<NanoWallet> restoreFromHardwareWallet(NanoNewWalletCredentials credentials) {
|
Future<NanoWallet> restoreFromHardwareWallet(NanoNewWalletCredentials credentials) {
|
||||||
throw UnimplementedError("Restoring a Nano wallet from a hardware wallet is not yet supported!");
|
throw UnimplementedError(
|
||||||
|
"Restoring a Nano wallet from a hardware wallet is not yet supported!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<NanoWallet> restoreFromSeed(NanoRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async {
|
Future<NanoWallet> restoreFromSeed(NanoRestoreWalletFromSeedCredentials credentials,
|
||||||
|
{bool? isTestnet}) async {
|
||||||
if (credentials.mnemonic.contains(' ')) {
|
if (credentials.mnemonic.contains(' ')) {
|
||||||
if (!bip39.validateMnemonic(credentials.mnemonic)) {
|
if (!bip39.validateMnemonic(credentials.mnemonic)) {
|
||||||
throw nm.NanoMnemonicIsIncorrectException();
|
throw nm.NanoMnemonicIsIncorrectException();
|
||||||
|
|
|
@ -40,13 +40,11 @@ class NanoChangeRepPage extends BasePage {
|
||||||
(node) => node.account == currentRepAccount,
|
(node) => node.account == currentRepAccount,
|
||||||
orElse: () => N2Node(
|
orElse: () => N2Node(
|
||||||
account: currentRepAccount,
|
account: currentRepAccount,
|
||||||
alias: currentRepAccount,
|
|
||||||
score: 0,
|
score: 0,
|
||||||
uptime: "???",
|
uptime: "???",
|
||||||
weight: 0,
|
weight: 0,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
return currentNode;
|
return currentNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,9 +55,7 @@ class NanoChangeRepPage extends BasePage {
|
||||||
child: FutureBuilder(
|
child: FutureBuilder(
|
||||||
future: nano!.getN2Reps(_wallet),
|
future: nano!.getN2Reps(_wallet),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.data == null) {
|
final reps = snapshot.data ?? [];
|
||||||
return SizedBox();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
padding: EdgeInsets.only(left: 24, right: 24),
|
padding: EdgeInsets.only(left: 24, right: 24),
|
||||||
|
@ -101,29 +97,35 @@ class NanoChangeRepPage extends BasePage {
|
||||||
),
|
),
|
||||||
_buildSingleRepresentative(
|
_buildSingleRepresentative(
|
||||||
context,
|
context,
|
||||||
getCurrentRepNode(snapshot.data as List<N2Node>),
|
getCurrentRepNode(reps),
|
||||||
isList: false,
|
isList: false,
|
||||||
|
divider: false,
|
||||||
),
|
),
|
||||||
Divider(height: 20),
|
if (reps.isNotEmpty) ...[
|
||||||
Container(
|
Divider(height: 20),
|
||||||
margin: EdgeInsets.only(top: 12),
|
Container(
|
||||||
child: Text(
|
margin: EdgeInsets.only(top: 12),
|
||||||
S.current.nano_pick_new_rep,
|
child: Text(
|
||||||
style: TextStyle(
|
S.current.nano_pick_new_rep,
|
||||||
fontSize: 16,
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w700,
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Divider(height: 20),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
contentPadding: EdgeInsets.only(bottom: 24),
|
contentPadding: EdgeInsets.only(bottom: 24),
|
||||||
content: Container(
|
content: Container(
|
||||||
child: Column(
|
child: reps.isNotEmpty
|
||||||
children: _getRepresentativeWidgets(context, snapshot.data as List<N2Node>),
|
? Column(
|
||||||
),
|
children: _getRepresentativeWidgets(context, reps),
|
||||||
|
)
|
||||||
|
: SizedBox(),
|
||||||
),
|
),
|
||||||
bottomSectionPadding: EdgeInsets.only(bottom: 24),
|
bottomSectionPadding: EdgeInsets.only(bottom: 24),
|
||||||
bottomSection: Observer(
|
bottomSection: Observer(
|
||||||
|
@ -207,19 +209,22 @@ class NanoChangeRepPage extends BasePage {
|
||||||
final List<Widget> ret = [];
|
final List<Widget> ret = [];
|
||||||
for (final N2Node node in list) {
|
for (final N2Node node in list) {
|
||||||
if (node.alias != null && node.alias!.trim().isNotEmpty) {
|
if (node.alias != null && node.alias!.trim().isNotEmpty) {
|
||||||
ret.add(_buildSingleRepresentative(context, node));
|
bool divider = node != list.first;
|
||||||
|
ret.add(_buildSingleRepresentative(context, node, divider: divider, isList: true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildSingleRepresentative(BuildContext context, N2Node rep, {bool isList = true}) {
|
Widget _buildSingleRepresentative(
|
||||||
|
BuildContext context,
|
||||||
|
N2Node rep, {
|
||||||
|
bool isList = true,
|
||||||
|
bool divider = false,
|
||||||
|
}) {
|
||||||
return Column(
|
return Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
if (isList)
|
if (divider) Divider(height: 2),
|
||||||
Divider(
|
|
||||||
height: 2,
|
|
||||||
),
|
|
||||||
TextButton(
|
TextButton(
|
||||||
style: TextButton.styleFrom(
|
style: TextButton.styleFrom(
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
|
@ -244,11 +249,11 @@ class NanoChangeRepPage extends BasePage {
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text(
|
Text(
|
||||||
_sanitizeAlias(rep.alias),
|
rep.alias ?? rep.account!,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
|
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
fontSize: 18,
|
fontSize: rep.alias == null ? 14 : 18,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
|
@ -337,11 +342,4 @@ class NanoChangeRepPage extends BasePage {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
String _sanitizeAlias(String? alias) {
|
|
||||||
if (alias != null) {
|
|
||||||
return alias.replaceAll(RegExp(r'[^a-zA-Z_.!?_;:-]'), '');
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,8 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
||||||
type == WalletType.tron,
|
type == WalletType.tron,
|
||||||
isButtonEnabled = false,
|
isButtonEnabled = false,
|
||||||
mode = WalletRestoreMode.seed,
|
mode = WalletRestoreMode.seed,
|
||||||
super(appStore, walletInfoSource, walletCreationService, seedSettingsViewModel, type: type, isRecovery: true) {
|
super(appStore, walletInfoSource, walletCreationService, seedSettingsViewModel,
|
||||||
|
type: type, isRecovery: true) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case WalletType.monero:
|
case WalletType.monero:
|
||||||
availableModes = WalletRestoreMode.values;
|
availableModes = WalletRestoreMode.values;
|
||||||
|
@ -194,10 +195,11 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
||||||
|
|
||||||
case WalletType.nano:
|
case WalletType.nano:
|
||||||
return nano!.createNanoRestoreWalletFromKeysCredentials(
|
return nano!.createNanoRestoreWalletFromKeysCredentials(
|
||||||
name: name,
|
name: name,
|
||||||
password: password,
|
password: password,
|
||||||
seedKey: options['private_key'] as String,
|
seedKey: options['private_key'] as String,
|
||||||
derivationType: options["derivationType"] as DerivationType);
|
derivationType: derivationInfo!.derivationType!,
|
||||||
|
);
|
||||||
case WalletType.polygon:
|
case WalletType.polygon:
|
||||||
return polygon!.createPolygonRestoreWalletFromPrivateKey(
|
return polygon!.createPolygonRestoreWalletFromPrivateKey(
|
||||||
name: name,
|
name: name,
|
||||||
|
|
Loading…
Reference in a new issue