receive screen + node screen working

This commit is contained in:
fosse 2023-07-27 10:30:07 -04:00
parent 2670eb2868
commit 9ebf74fa01
14 changed files with 227 additions and 199 deletions

View file

@ -1,4 +1,2 @@
-
uri: rpc.nano.to
-
uri: eth.llamarpc.com
uri: rpc.nano.to

View file

@ -70,6 +70,8 @@ class Node extends HiveObject with Keyable {
return Uri.http(uriRaw, '');
case WalletType.ethereum:
return Uri.https(uriRaw, '');
case WalletType.nano:
return Uri.https(uriRaw, '');
default:
throw Exception('Unexpected type ${type.toString()} for Node uri');
}

View file

@ -25,8 +25,8 @@ class NanoBalance extends Balance {
// moneroParseAmount(amount: formattedCurrentBalance));
@override
String get formattedAvailableBalance => "error";
String get formattedAvailableBalance => "0";
@override
String get formattedAdditionalBalance => "error";
String get formattedAdditionalBalance => "0";
}

View file

@ -57,7 +57,7 @@ abstract class NanoWalletBase
late final String _privateKey;
late final String _publicAddress;
late final String _seed;
late final String _seedKey;
List<int> _priorityFees;
int? _gasPrice;
@ -74,14 +74,14 @@ abstract class NanoWalletBase
@observable
late ObservableMap<CryptoCurrency, NanoBalance> balance;
// initialize the different forms of private / public key we'll need:
Future<void> init() async {
final String type = (_derivationType == DerivationType.nano) ? "standard" : "hd";
_seed = bip39.mnemonicToEntropy(_mnemonic).toUpperCase();
_privateKey = await NanoUtil.uniSeedToPrivate(_mnemonic, 0, type);
_publicAddress = await NanoUtil.uniSeedToAddress(_mnemonic, 0, type);
_seedKey = bip39.mnemonicToEntropy(_mnemonic).toUpperCase();
_privateKey = await NanoUtil.uniSeedToPrivate(_seedKey, 0, type);
_publicAddress = await NanoUtil.uniSeedToAddress(_seedKey, 0, type);
this.walletInfo.address = _publicAddress;
await walletAddresses.init();
// await transactionHistory.init();
@ -166,8 +166,10 @@ abstract class NanoWalletBase
Future<String> makePath() async => pathForWallet(name: walletInfo.name, type: walletInfo.type);
String toJSON() => json.encode({
'seedKey': _seedKey,
'mnemonic': _mnemonic,
// 'balance': balance[currency]!.toJSON(),
'derivationType': _derivationType.toString()
});
static Future<NanoWallet> open({
@ -175,7 +177,26 @@ abstract class NanoWalletBase
required String password,
required WalletInfo walletInfo,
}) async {
throw UnimplementedError();
// TODO: finish
final path = await pathForWallet(name: name, type: walletInfo.type);
final jsonSource = await read(path: path, password: password);
final data = json.decode(jsonSource) as Map;
final mnemonic = data['mnemonic'] as String;
final balance = /*NanoBalance.fromJSON(data['balance'] as String) ?? */
NanoBalance(currentBalance: BigInt.zero, receivableBalance: BigInt.zero);
DerivationType derivationType = DerivationType.bip39;
if (data['derivationType'] == "nano") {
derivationType = DerivationType.nano;
}
return NanoWallet(
walletInfo: walletInfo,
password: password,
mnemonic: mnemonic,
initialBalance: balance,
derivationType: derivationType,
);
}
Future<void> _updateBalance() async {

View file

@ -37,20 +37,13 @@ class NanoWalletLoadingException implements Exception {
}
class NanoRestoreWalletFromKeysCredentials extends WalletCredentials {
NanoRestoreWalletFromKeysCredentials(
{required String name,
required String password,
required this.language,
required this.address,
required this.viewKey,
required this.spendKey,
int height = 0})
: super(name: name, password: password, height: height);
NanoRestoreWalletFromKeysCredentials({
required String name,
required String password,
required this.seedKey,
}) : super(name: name, password: password);
final String language;
final String address;
final String viewKey;
final String spendKey;
final String seedKey;
}
class NanoWalletService extends WalletService<NanoNewWalletCredentials,
@ -108,33 +101,36 @@ class NanoWalletService extends WalletService<NanoNewWalletCredentials,
// await walletInfoSource.put(currentWalletInfo.key, newWalletInfo);
}
@override
Future<NanoWallet> restoreFromKeys(NanoRestoreWalletFromKeysCredentials credentials) async {
print("a");
throw UnimplementedError();
// try {
// final path = await pathForWallet(name: credentials.name, type: getType());
// await monero_wallet_manager.restoreFromKeys(
// path: path,
// password: credentials.password!,
// language: credentials.language,
// restoreHeight: credentials.height!,
// address: credentials.address,
// viewKey: credentials.viewKey,
// spendKey: credentials.spendKey);
// final wallet = NanoWallet(walletInfo: credentials.walletInfo!);
// await wallet.init();
// return wallet;
// } catch (e) {
// // TODO: Implement Exception for wallet list service.
// print('NanoWalletsManager Error: $e');
// rethrow;
// }
Future<DerivationType> compareDerivationMethods({String? mnemonic, String? seedKey}) async {
// TODO:
return DerivationType.nano;
}
Future<DerivationType> compareDerivationMethods({String? mnemonic, String? seedKey}) async {
return DerivationType.nano;
@override
Future<NanoWallet> restoreFromKeys(NanoRestoreWalletFromKeysCredentials credentials) async {
throw UnimplementedError("restoreFromKeys");
DerivationType derivationType = DerivationType.bip39;
if (credentials.seedKey.length == 128) {
derivationType = DerivationType.bip39;
} else {
// we don't know for sure, but probably the nano standard:
derivationType = await compareDerivationMethods(seedKey: credentials.seedKey);
}
String? mnemonic;
final wallet = await NanoWallet(
password: credentials.password!,
mnemonic: mnemonic ?? "", // we can't derive the mnemonic from the key in all cases
walletInfo: credentials.walletInfo!,
derivationType: derivationType,
);
await wallet.init();
await wallet.save();
return wallet;
}
@override
@ -163,13 +159,7 @@ class NanoWalletService extends WalletService<NanoNewWalletCredentials,
derivationType: derivationType,
);
try {
await wallet.init();
} catch (e) {
print("test");
print(e);
rethrow;
}
await wallet.init();
await wallet.save();
return wallet;
}

View file

@ -44,37 +44,33 @@ Future defaultSettingsMigration(
// check current nodes for nullability regardless of the version
await checkCurrentNodes(nodes, sharedPreferences);
final isNewInstall = sharedPreferences
.getInt(PreferencesKey.currentDefaultSettingsMigrationVersion) == null;
await sharedPreferences.setBool(
PreferencesKey.isNewInstall, isNewInstall);
final isNewInstall =
sharedPreferences.getInt(PreferencesKey.currentDefaultSettingsMigrationVersion) == null;
await sharedPreferences.setBool(PreferencesKey.isNewInstall, isNewInstall);
final currentVersion = sharedPreferences
.getInt(PreferencesKey.currentDefaultSettingsMigrationVersion) ??
0;
if (currentVersion >= version) {
return;
}
final migrationVersionsLength = version - currentVersion;
final migrationVersions = List<int>.generate(
migrationVersionsLength, (i) => currentVersion + (i + 1));
final migrationVersions =
List<int>.generate(migrationVersionsLength, (i) => currentVersion + (i + 1));
await Future.forEach(migrationVersions, (int version) async {
try {
switch (version) {
case 1:
await sharedPreferences.setString(
PreferencesKey.currentFiatCurrencyKey,
FiatCurrency.usd.toString());
await sharedPreferences.setInt(
PreferencesKey.currentTransactionPriorityKeyLegacy,
PreferencesKey.currentFiatCurrencyKey, FiatCurrency.usd.toString());
await sharedPreferences.setInt(PreferencesKey.currentTransactionPriorityKeyLegacy,
monero!.getDefaultTransactionPriority().raw);
await sharedPreferences.setInt(
PreferencesKey.currentBalanceDisplayModeKey,
BalanceDisplayMode.availableBalance.raw);
PreferencesKey.currentBalanceDisplayModeKey, BalanceDisplayMode.availableBalance.raw);
await sharedPreferences.setBool('save_recipient_address', true);
await resetToDefault(nodes);
await changeMoneroCurrentNodeToDefault(
@ -83,14 +79,12 @@ Future defaultSettingsMigration(
sharedPreferences: sharedPreferences, nodes: nodes);
await changeLitecoinCurrentElectrumServerToDefault(
sharedPreferences: sharedPreferences, nodes: nodes);
await changeHavenCurrentNodeToDefault(
sharedPreferences: sharedPreferences, nodes: nodes);
await changeHavenCurrentNodeToDefault(sharedPreferences: sharedPreferences, nodes: nodes);
break;
case 2:
await replaceNodesMigration(nodes: nodes);
await replaceDefaultNode(
sharedPreferences: sharedPreferences, nodes: nodes);
await replaceDefaultNode(sharedPreferences: sharedPreferences, nodes: nodes);
break;
case 3:
@ -140,8 +134,7 @@ Future defaultSettingsMigration(
case 16:
await addHavenNodeList(nodes: nodes);
await changeHavenCurrentNodeToDefault(
sharedPreferences: sharedPreferences, nodes: nodes);
await changeHavenCurrentNodeToDefault(sharedPreferences: sharedPreferences, nodes: nodes);
await checkCurrentNodes(nodes, sharedPreferences);
break;
@ -164,6 +157,10 @@ Future defaultSettingsMigration(
await changeEthereumCurrentNodeToDefault(
sharedPreferences: sharedPreferences, nodes: nodes);
break;
case 22:
await addNanoNodeList(nodes: nodes);
await changeNanoCurrentNodeToDefault(sharedPreferences: sharedPreferences, nodes: nodes);
break;
default:
break;
@ -176,8 +173,7 @@ Future defaultSettingsMigration(
}
});
await sharedPreferences.setInt(
PreferencesKey.currentDefaultSettingsMigrationVersion, version);
await sharedPreferences.setInt(PreferencesKey.currentDefaultSettingsMigrationVersion, version);
}
Future<void> validateBitcoinSavedTransactionPriority(SharedPreferences sharedPreferences) async {
@ -187,8 +183,8 @@ Future<void> validateBitcoinSavedTransactionPriority(SharedPreferences sharedPre
final int? savedBitcoinPriority =
sharedPreferences.getInt(PreferencesKey.bitcoinTransactionPriority);
if (!bitcoin!.getTransactionPriorities().any((element) => element.raw == savedBitcoinPriority)) {
await sharedPreferences.setInt(
PreferencesKey.bitcoinTransactionPriority, bitcoin!.getMediumTransactionPriority().serialize());
await sharedPreferences.setInt(PreferencesKey.bitcoinTransactionPriority,
bitcoin!.getMediumTransactionPriority().serialize());
}
}
@ -205,10 +201,9 @@ Future<void> replaceNodesMigration({required Box<Node> nodes}) async {
final replaceNodes = <String, Node>{
'eu-node.cakewallet.io:18081':
Node(uri: 'xmr-node-eu.cakewallet.com:18081', type: WalletType.monero),
'node.cakewallet.io:18081': Node(
uri: 'xmr-node-usa-east.cakewallet.com:18081', type: WalletType.monero),
'node.xmr.ru:13666':
Node(uri: 'node.monero.net:18081', type: WalletType.monero)
'node.cakewallet.io:18081':
Node(uri: 'xmr-node-usa-east.cakewallet.com:18081', type: WalletType.monero),
'node.xmr.ru:13666': Node(uri: 'node.monero.net:18081', type: WalletType.monero)
};
nodes.values.forEach((Node node) async {
@ -224,8 +219,7 @@ Future<void> replaceNodesMigration({required Box<Node> nodes}) async {
}
Future<void> changeMoneroCurrentNodeToDefault(
{required SharedPreferences sharedPreferences,
required Box<Node> nodes}) async {
{required SharedPreferences sharedPreferences, required Box<Node> nodes}) async {
final node = getMoneroDefaultNode(nodes: nodes);
final nodeId = node?.key as int ?? 0; // 0 - England
@ -233,33 +227,30 @@ Future<void> changeMoneroCurrentNodeToDefault(
}
Node? getBitcoinDefaultElectrumServer({required Box<Node> nodes}) {
return nodes.values.firstWhereOrNull(
(Node node) => node.uriRaw == cakeWalletBitcoinElectrumUri)
?? nodes.values.firstWhereOrNull((node) => node.type == WalletType.bitcoin);
return nodes.values
.firstWhereOrNull((Node node) => node.uriRaw == cakeWalletBitcoinElectrumUri) ??
nodes.values.firstWhereOrNull((node) => node.type == WalletType.bitcoin);
}
Node? getLitecoinDefaultElectrumServer({required Box<Node> nodes}) {
return nodes.values.firstWhereOrNull(
(Node node) => node.uriRaw == cakeWalletLitecoinElectrumUri)
?? nodes.values.firstWhereOrNull((node) => node.type == WalletType.litecoin);
return nodes.values
.firstWhereOrNull((Node node) => node.uriRaw == cakeWalletLitecoinElectrumUri) ??
nodes.values.firstWhereOrNull((node) => node.type == WalletType.litecoin);
}
Node? getHavenDefaultNode({required Box<Node> nodes}) {
return nodes.values.firstWhereOrNull(
(Node node) => node.uriRaw == havenDefaultNodeUri)
?? nodes.values.firstWhereOrNull((node) => node.type == WalletType.haven);
return nodes.values.firstWhereOrNull((Node node) => node.uriRaw == havenDefaultNodeUri) ??
nodes.values.firstWhereOrNull((node) => node.type == WalletType.haven);
}
Node? getEthereumDefaultNode({required Box<Node> nodes}) {
return nodes.values.firstWhereOrNull(
(Node node) => node.uriRaw == ethereumDefaultNodeUri)
?? nodes.values.firstWhereOrNull((node) => node.type == WalletType.ethereum);
return nodes.values.firstWhereOrNull((Node node) => node.uriRaw == ethereumDefaultNodeUri) ??
nodes.values.firstWhereOrNull((node) => node.type == WalletType.ethereum);
}
Node? getNanoDefaultNode({required Box<Node> nodes}) {
return nodes.values.firstWhereOrNull(
(Node node) => node.uriRaw == nanoDefaultNodeUri)
?? nodes.values.firstWhereOrNull((node) => node.type == WalletType.ethereum);
return nodes.values.firstWhereOrNull((Node node) => node.uriRaw == nanoDefaultNodeUri) ??
nodes.values.firstWhereOrNull((node) => node.type == WalletType.ethereum);
}
Node getMoneroDefaultNode({required Box<Node> nodes}) {
@ -275,16 +266,14 @@ Node getMoneroDefaultNode({required Box<Node> nodes}) {
}
try {
return nodes.values
.firstWhere((Node node) => node.uriRaw == nodeUri);
} catch(_) {
return nodes.values.firstWhere((Node node) => node.uriRaw == nodeUri);
} catch (_) {
return nodes.values.first;
}
}
Future<void> changeBitcoinCurrentElectrumServerToDefault(
{required SharedPreferences sharedPreferences,
required Box<Node> nodes}) async {
{required SharedPreferences sharedPreferences, required Box<Node> nodes}) async {
final server = getBitcoinDefaultElectrumServer(nodes: nodes);
final serverId = server?.key as int ?? 0;
@ -292,8 +281,7 @@ Future<void> changeBitcoinCurrentElectrumServerToDefault(
}
Future<void> changeLitecoinCurrentElectrumServerToDefault(
{required SharedPreferences sharedPreferences,
required Box<Node> nodes}) async {
{required SharedPreferences sharedPreferences, required Box<Node> nodes}) async {
final server = getLitecoinDefaultElectrumServer(nodes: nodes);
final serverId = server?.key as int ?? 0;
@ -301,8 +289,7 @@ Future<void> changeLitecoinCurrentElectrumServerToDefault(
}
Future<void> changeHavenCurrentNodeToDefault(
{required SharedPreferences sharedPreferences,
required Box<Node> nodes}) async {
{required SharedPreferences sharedPreferences, required Box<Node> nodes}) async {
final node = getHavenDefaultNode(nodes: nodes);
final nodeId = node?.key as int ?? 0;
@ -310,25 +297,21 @@ Future<void> changeHavenCurrentNodeToDefault(
}
Future<void> replaceDefaultNode(
{required SharedPreferences sharedPreferences,
required Box<Node> nodes}) async {
{required SharedPreferences sharedPreferences, required Box<Node> nodes}) async {
const nodesForReplace = <String>[
'xmr-node-uk.cakewallet.com:18081',
'eu-node.cakewallet.io:18081',
'node.cakewallet.io:18081'
];
final currentNodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey);
final currentNode =
nodes.values.firstWhereOrNull((Node node) => node.key == currentNodeId);
final needToReplace =
currentNode == null ? true : nodesForReplace.contains(currentNode.uriRaw);
final currentNode = nodes.values.firstWhereOrNull((Node node) => node.key == currentNodeId);
final needToReplace = currentNode == null ? true : nodesForReplace.contains(currentNode.uriRaw);
if (!needToReplace) {
return;
}
await changeMoneroCurrentNodeToDefault(
sharedPreferences: sharedPreferences, nodes: nodes);
await changeMoneroCurrentNodeToDefault(sharedPreferences: sharedPreferences, nodes: nodes);
}
Future<void> updateNodeTypes({required Box<Node> nodes}) async {
@ -367,14 +350,11 @@ Future<void> addHavenNodeList({required Box<Node> nodes}) async {
}
}
Future<void> addAddressesForMoneroWallets(
Box<WalletInfo> walletInfoSource) async {
final moneroWalletsInfo =
walletInfoSource.values.where((info) => info.type == WalletType.monero);
Future<void> addAddressesForMoneroWallets(Box<WalletInfo> walletInfoSource) async {
final moneroWalletsInfo = walletInfoSource.values.where((info) => info.type == WalletType.monero);
moneroWalletsInfo.forEach((info) async {
try {
final walletPath =
await pathForWallet(name: info.name, type: WalletType.monero);
final walletPath = await pathForWallet(name: info.name, type: WalletType.monero);
final addressFilePath = '$walletPath.address.txt';
final addressFile = File(addressFilePath);
@ -395,8 +375,7 @@ Future<void> updateDisplayModes(SharedPreferences sharedPreferences) async {
final currentBalanceDisplayMode =
sharedPreferences.getInt(PreferencesKey.currentBalanceDisplayModeKey) ?? -1;
final balanceDisplayMode = currentBalanceDisplayMode < 2 ? 3 : 2;
await sharedPreferences.setInt(
PreferencesKey.currentBalanceDisplayModeKey, balanceDisplayMode);
await sharedPreferences.setInt(PreferencesKey.currentBalanceDisplayModeKey, balanceDisplayMode);
}
Future<void> generateBackupPassword(FlutterSecureStorage secureStorage) async {
@ -410,10 +389,9 @@ Future<void> generateBackupPassword(FlutterSecureStorage secureStorage) async {
await secureStorage.write(key: key, value: password);
}
Future<void> changeTransactionPriorityAndFeeRateKeys(
SharedPreferences sharedPreferences) async {
final legacyTransactionPriority = sharedPreferences
.getInt(PreferencesKey.currentTransactionPriorityKeyLegacy)!;
Future<void> changeTransactionPriorityAndFeeRateKeys(SharedPreferences sharedPreferences) async {
final legacyTransactionPriority =
sharedPreferences.getInt(PreferencesKey.currentTransactionPriorityKeyLegacy)!;
await sharedPreferences.setInt(
PreferencesKey.moneroTransactionPriority, legacyTransactionPriority);
await sharedPreferences.setInt(PreferencesKey.bitcoinTransactionPriority,
@ -423,10 +401,8 @@ Future<void> changeTransactionPriorityAndFeeRateKeys(
Future<void> changeDefaultMoneroNode(
Box<Node> nodeSource, SharedPreferences sharedPreferences) async {
const cakeWalletMoneroNodeUriPattern = '.cakewallet.com';
final currentMoneroNodeId =
sharedPreferences.getInt(PreferencesKey.currentNodeIdKey);
final currentMoneroNode =
nodeSource.values.firstWhere((node) => node.key == currentMoneroNodeId);
final currentMoneroNodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey);
final currentMoneroNode = nodeSource.values.firstWhere((node) => node.key == currentMoneroNodeId);
final needToReplaceCurrentMoneroNode =
currentMoneroNode.uri.toString().contains(cakeWalletMoneroNodeUriPattern);
@ -437,78 +413,64 @@ Future<void> changeDefaultMoneroNode(
}
});
final newCakeWalletNode =
Node(uri: newCakeWalletMoneroUri, type: WalletType.monero);
final newCakeWalletNode = Node(uri: newCakeWalletMoneroUri, type: WalletType.monero);
await nodeSource.add(newCakeWalletNode);
if (needToReplaceCurrentMoneroNode) {
await sharedPreferences.setInt(
PreferencesKey.currentNodeIdKey, newCakeWalletNode.key as int);
await sharedPreferences.setInt(PreferencesKey.currentNodeIdKey, newCakeWalletNode.key as int);
}
}
Future<void> checkCurrentNodes(
Box<Node> nodeSource, SharedPreferences sharedPreferences) async {
final currentMoneroNodeId =
sharedPreferences.getInt(PreferencesKey.currentNodeIdKey);
Future<void> checkCurrentNodes(Box<Node> nodeSource, SharedPreferences sharedPreferences) async {
final currentMoneroNodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey);
final currentBitcoinElectrumSeverId =
sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey);
final currentLitecoinElectrumSeverId = sharedPreferences
.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey);
final currentHavenNodeId = sharedPreferences
.getInt(PreferencesKey.currentHavenNodeIdKey);
final currentEthereumNodeId = sharedPreferences
.getInt(PreferencesKey.currentEthereumNodeIdKey);
final currentMoneroNode = nodeSource.values.firstWhereOrNull(
(node) => node.key == currentMoneroNodeId);
final currentBitcoinElectrumServer = nodeSource.values.firstWhereOrNull(
(node) => node.key == currentBitcoinElectrumSeverId);
final currentLitecoinElectrumServer = nodeSource.values.firstWhereOrNull(
(node) => node.key == currentLitecoinElectrumSeverId);
final currentHavenNodeServer = nodeSource.values.firstWhereOrNull(
(node) => node.key == currentHavenNodeId);
final currentEthereumNodeServer = nodeSource.values.firstWhereOrNull(
(node) => node.key == currentEthereumNodeId);
final currentLitecoinElectrumSeverId =
sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey);
final currentHavenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey);
final currentEthereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey);
final currentMoneroNode =
nodeSource.values.firstWhereOrNull((node) => node.key == currentMoneroNodeId);
final currentBitcoinElectrumServer =
nodeSource.values.firstWhereOrNull((node) => node.key == currentBitcoinElectrumSeverId);
final currentLitecoinElectrumServer =
nodeSource.values.firstWhereOrNull((node) => node.key == currentLitecoinElectrumSeverId);
final currentHavenNodeServer =
nodeSource.values.firstWhereOrNull((node) => node.key == currentHavenNodeId);
final currentEthereumNodeServer =
nodeSource.values.firstWhereOrNull((node) => node.key == currentEthereumNodeId);
if (currentMoneroNode == null) {
final newCakeWalletNode =
Node(uri: newCakeWalletMoneroUri, type: WalletType.monero);
final newCakeWalletNode = Node(uri: newCakeWalletMoneroUri, type: WalletType.monero);
await nodeSource.add(newCakeWalletNode);
await sharedPreferences.setInt(
PreferencesKey.currentNodeIdKey, newCakeWalletNode.key as int);
await sharedPreferences.setInt(PreferencesKey.currentNodeIdKey, newCakeWalletNode.key as int);
}
if (currentBitcoinElectrumServer == null) {
final cakeWalletElectrum =
Node(uri: cakeWalletBitcoinElectrumUri, type: WalletType.bitcoin);
final cakeWalletElectrum = Node(uri: cakeWalletBitcoinElectrumUri, type: WalletType.bitcoin);
await nodeSource.add(cakeWalletElectrum);
await sharedPreferences.setInt(
PreferencesKey.currentBitcoinElectrumSererIdKey,
cakeWalletElectrum.key as int);
PreferencesKey.currentBitcoinElectrumSererIdKey, cakeWalletElectrum.key as int);
}
if (currentLitecoinElectrumServer == null) {
final cakeWalletElectrum =
Node(uri: cakeWalletLitecoinElectrumUri, type: WalletType.litecoin);
final cakeWalletElectrum = Node(uri: cakeWalletLitecoinElectrumUri, type: WalletType.litecoin);
await nodeSource.add(cakeWalletElectrum);
await sharedPreferences.setInt(
PreferencesKey.currentLitecoinElectrumSererIdKey,
cakeWalletElectrum.key as int);
PreferencesKey.currentLitecoinElectrumSererIdKey, cakeWalletElectrum.key as int);
}
if (currentHavenNodeServer == null) {
final node = Node(uri: havenDefaultNodeUri, type: WalletType.haven);
await nodeSource.add(node);
await sharedPreferences.setInt(
PreferencesKey.currentHavenNodeIdKey, node.key as int);
await sharedPreferences.setInt(PreferencesKey.currentHavenNodeIdKey, node.key as int);
}
if (currentEthereumNodeServer == null) {
final node = Node(uri: ethereumDefaultNodeUri, type: WalletType.ethereum);
await nodeSource.add(node);
await sharedPreferences.setInt(
PreferencesKey.currentEthereumNodeIdKey, node.key as int);
await sharedPreferences.setInt(PreferencesKey.currentEthereumNodeIdKey, node.key as int);
}
}
@ -516,31 +478,27 @@ Future<void> resetBitcoinElectrumServer(
Box<Node> nodeSource, SharedPreferences sharedPreferences) async {
final currentElectrumSeverId =
sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey);
final oldElectrumServer = nodeSource.values.firstWhereOrNull(
(node) => node.uri.toString().contains('electrumx.cakewallet.com'));
var cakeWalletNode = nodeSource.values.firstWhereOrNull(
(node) => node.uriRaw.toString() == cakeWalletBitcoinElectrumUri);
final oldElectrumServer = nodeSource.values
.firstWhereOrNull((node) => node.uri.toString().contains('electrumx.cakewallet.com'));
var cakeWalletNode = nodeSource.values
.firstWhereOrNull((node) => node.uriRaw.toString() == cakeWalletBitcoinElectrumUri);
if (cakeWalletNode == null) {
cakeWalletNode =
Node(uri: cakeWalletBitcoinElectrumUri, type: WalletType.bitcoin);
cakeWalletNode = Node(uri: cakeWalletBitcoinElectrumUri, type: WalletType.bitcoin);
await nodeSource.add(cakeWalletNode);
}
if (currentElectrumSeverId == oldElectrumServer?.key) {
await sharedPreferences.setInt(
PreferencesKey.currentBitcoinElectrumSererIdKey,
cakeWalletNode.key as int);
PreferencesKey.currentBitcoinElectrumSererIdKey, cakeWalletNode.key as int);
}
await oldElectrumServer?.delete();
}
Future<void> changeDefaultHavenNode(
Box<Node> nodeSource) async {
Future<void> changeDefaultHavenNode(Box<Node> nodeSource) async {
const previousHavenDefaultNodeUri = 'vault.havenprotocol.org:443';
final havenNodes = nodeSource.values.where(
(node) => node.uriRaw == previousHavenDefaultNodeUri);
final havenNodes = nodeSource.values.where((node) => node.uriRaw == previousHavenDefaultNodeUri);
havenNodes.forEach((node) async {
node.uriRaw = havenDefaultNodeUri;
await node.save();
@ -553,8 +511,8 @@ Future<void> migrateExchangeStatus(SharedPreferences sharedPreferences) async {
return;
}
await sharedPreferences.setInt(PreferencesKey.exchangeStatusKey, isExchangeDisabled
? ExchangeApiMode.disabled.raw : ExchangeApiMode.enabled.raw);
await sharedPreferences.setInt(PreferencesKey.exchangeStatusKey,
isExchangeDisabled ? ExchangeApiMode.disabled.raw : ExchangeApiMode.enabled.raw);
await sharedPreferences.remove(PreferencesKey.disableExchangeKey);
}
@ -569,10 +527,26 @@ Future<void> addEthereumNodeList({required Box<Node> nodes}) async {
}
Future<void> changeEthereumCurrentNodeToDefault(
{required SharedPreferences sharedPreferences,
required Box<Node> nodes}) async {
{required SharedPreferences sharedPreferences, required Box<Node> nodes}) async {
final node = getEthereumDefaultNode(nodes: nodes);
final nodeId = node?.key as int? ?? 0;
await sharedPreferences.setInt(PreferencesKey.currentEthereumNodeIdKey, nodeId);
}
Future<void> addNanoNodeList({required Box<Node> nodes}) async {
final nodeList = await loadDefaultNanoNodes();
for (var node in nodeList) {
if (nodes.values.firstWhereOrNull((element) => element.uriRaw == node.uriRaw) == null) {
await nodes.add(node);
}
}
}
Future<void> changeNanoCurrentNodeToDefault(
{required SharedPreferences sharedPreferences, required Box<Node> nodes}) async {
final node = getNanoDefaultNode(nodes: nodes);
final nodeId = node?.key as int? ?? 0;
await sharedPreferences.setInt(PreferencesKey.currentNanoNodeIdKey, nodeId);
}

View file

@ -21,13 +21,12 @@ Future<List<Node>> loadDefaultNodes() async {
}
Future<List<Node>> loadBitcoinElectrumServerList() async {
final serverListRaw =
await rootBundle.loadString('assets/bitcoin_electrum_server_list.yml');
final serverListRaw = await rootBundle.loadString('assets/bitcoin_electrum_server_list.yml');
final loadedServerList = loadYaml(serverListRaw) as YamlList;
final serverList = <Node>[];
for (final raw in loadedServerList) {
if (raw is Map) {
if (raw is Map) {
final node = Node.fromMap(Map<String, Object>.from(raw));
node.type = WalletType.bitcoin;
serverList.add(node);
@ -38,8 +37,7 @@ Future<List<Node>> loadBitcoinElectrumServerList() async {
}
Future<List<Node>> loadLitecoinElectrumServerList() async {
final serverListRaw =
await rootBundle.loadString('assets/litecoin_electrum_server_list.yml');
final serverListRaw = await rootBundle.loadString('assets/litecoin_electrum_server_list.yml');
final loadedServerList = loadYaml(serverListRaw) as YamlList;
final serverList = <Node>[];
@ -66,7 +64,7 @@ Future<List<Node>> loadDefaultHavenNodes() async {
nodes.add(node);
}
}
return nodes;
}
@ -94,7 +92,7 @@ Future<List<Node>> loadDefaultNanoNodes() async {
for (final raw in loadedNodes) {
if (raw is Map) {
final node = Node.fromMap(Map<String, Object>.from(raw));
node.type = WalletType.ethereum;
node.type = WalletType.nano;
nodes.add(node);
}
}
@ -107,12 +105,13 @@ Future resetToDefault(Box<Node> nodeSource) async {
final bitcoinElectrumServerList = await loadBitcoinElectrumServerList();
final litecoinElectrumServerList = await loadLitecoinElectrumServerList();
final havenNodes = await loadDefaultHavenNodes();
final ethereumNodes = await loadDefaultEthereumNodes();
final nanoNodes = await loadDefaultNanoNodes();
final nodes =
moneroNodes +
final nodes = moneroNodes +
bitcoinElectrumServerList +
litecoinElectrumServerList +
havenNodes +
ethereumNodes +
nanoNodes;
await nodeSource.clear();

View file

@ -6,6 +6,7 @@ class PreferencesKey {
static const currentLitecoinElectrumSererIdKey = 'current_node_id_ltc';
static const currentHavenNodeIdKey = 'current_node_id_xhv';
static const currentEthereumNodeIdKey = 'current_node_id_eth';
static const currentNanoNodeIdKey = 'current_node_id_nano';
static const currentFiatCurrencyKey = 'current_fiat_currency';
static const currentTransactionPriorityKeyLegacy = 'current_fee_priority';
static const currentBalanceDisplayModeKey = 'current_balance_display_mode';

View file

@ -141,7 +141,7 @@ Future<void> main() async {
transactionDescriptions: transactionDescriptions,
secureStorage: secureStorage,
anonpayInvoiceInfo: anonpayInvoiceInfo,
initialMigrationVersion: 21);
initialMigrationVersion: 22);
runApp(App());
}, (error, stackTrace) async {
ExceptionHandler.onError(FlutterErrorDetails(exception: error, stack: stackTrace));

View file

@ -47,6 +47,7 @@ class WalletListBodyState extends State<WalletListBody> {
final nonWalletTypeIcon = Image.asset('assets/images/close.png', height: 24, width: 24);
final havenIcon = Image.asset('assets/images/haven_logo.png', height: 24, width: 24);
final ethereumIcon = Image.asset('assets/images/eth_icon.png', height: 24, width: 24);
final nanoIcon = Image.asset('assets/images/nano_icon.png', height: 24, width: 24);
final scrollController = ScrollController();
final double tileHeight = 60;
Flushbar<void>? _progressBar;
@ -205,6 +206,8 @@ class WalletListBodyState extends State<WalletListBody> {
return havenIcon;
case WalletType.ethereum:
return ethereumIcon;
case WalletType.nano:
return nanoIcon;
default:
return nonWalletTypeIcon;
}

View file

@ -431,11 +431,13 @@ abstract class SettingsStoreBase with Store {
sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey);
final havenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey);
final ethereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey);
final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey);
final moneroNode = nodeSource.get(nodeId);
final bitcoinElectrumServer = nodeSource.get(bitcoinElectrumServerId);
final litecoinElectrumServer = nodeSource.get(litecoinElectrumServerId);
final havenNode = nodeSource.get(havenNodeId);
final ethereumNode = nodeSource.get(ethereumNodeId);
final nanoNode = nodeSource.get(nanoNodeId);
final packageInfo = await PackageInfo.fromPlatform();
final deviceName = await _getDeviceName() ?? '';
final shouldShowYatPopup = sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? true;
@ -462,6 +464,10 @@ abstract class SettingsStoreBase with Store {
nodes[WalletType.ethereum] = ethereumNode;
}
if (nanoNode != null) {
nodes[WalletType.nano] = nanoNode;
}
return SettingsStore(
sharedPreferences: sharedPreferences,
initialShouldShowMarketPlaceInDashboard: shouldShowMarketPlaceInDashboard,
@ -577,11 +583,13 @@ abstract class SettingsStoreBase with Store {
sharedPreferences.getInt(PreferencesKey.currentLitecoinElectrumSererIdKey);
final havenNodeId = sharedPreferences.getInt(PreferencesKey.currentHavenNodeIdKey);
final ethereumNodeId = sharedPreferences.getInt(PreferencesKey.currentEthereumNodeIdKey);
final nanoNodeId = sharedPreferences.getInt(PreferencesKey.currentNanoNodeIdKey);
final moneroNode = nodeSource.get(nodeId);
final bitcoinElectrumServer = nodeSource.get(bitcoinElectrumServerId);
final litecoinElectrumServer = nodeSource.get(litecoinElectrumServerId);
final havenNode = nodeSource.get(havenNodeId);
final ethereumNode = nodeSource.get(ethereumNodeId);
final nanoNode = nodeSource.get(nanoNodeId);
if (moneroNode != null) {
nodes[WalletType.monero] = moneroNode;
@ -602,6 +610,10 @@ abstract class SettingsStoreBase with Store {
if (ethereumNode != null) {
nodes[WalletType.ethereum] = ethereumNode;
}
if (nanoNode != null) {
nodes[WalletType.nano] = nanoNode;
}
}
Future<void> _saveCurrentNode(Node node, WalletType walletType) async {
@ -623,6 +635,9 @@ abstract class SettingsStoreBase with Store {
case WalletType.ethereum:
await _sharedPreferences.setInt(PreferencesKey.currentEthereumNodeIdKey, node.key as int);
break;
case WalletType.nano:
await _sharedPreferences.setInt(PreferencesKey.currentNanoNodeIdKey, node.key as int);
break;
default:
break;
}

View file

@ -63,6 +63,9 @@ abstract class NodeListViewModelBase with Store {
case WalletType.haven:
node = getHavenDefaultNode(nodes: _nodeSource)!;
break;
case WalletType.ethereum:
node = getEthereumDefaultNode(nodes: _nodeSource)!;
break;
case WalletType.nano:
node = getNanoDefaultNode(nodes: _nodeSource)!;
break;

View file

@ -110,6 +110,23 @@ class EthereumURI extends PaymentURI {
}
}
class NanoURI extends PaymentURI {
NanoURI({required String amount, required String address})
: super(amount: amount, address: address);
@override
String toString() {
print(address);
var base = 'nano:' + address;
if (amount.isNotEmpty) {
base += '?amount=${amount.replaceAll(',', '.')}';
}
return base;
}
}
abstract class WalletAddressListViewModelBase with Store {
WalletAddressListViewModelBase({
required AppStore appStore,
@ -172,6 +189,10 @@ abstract class WalletAddressListViewModelBase with Store {
return EthereumURI(amount: amount, address: address.address);
}
if (_wallet.type == WalletType.nano) {
return NanoURI(amount: amount, address: address.address);
}
throw Exception('Unexpected type: ${type.toString()}');
}

View file

@ -119,6 +119,7 @@ flutter:
- assets/bitcoin_electrum_server_list.yml
- assets/litecoin_electrum_server_list.yml
- assets/ethereum_server_list.yml
- assets/nano_node_list.yml
- assets/text/
- assets/faq/
- assets/animation/