diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index a73e2c107..2f7cabe60 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -120,7 +120,7 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen static const eos = CryptoCurrency(title: 'EOS', fullName: 'EOS', raw: 7, name: 'eos', iconPath: 'assets/images/eos_icon.png'); static const eth = CryptoCurrency(title: 'ETH', fullName: 'Ethereum', raw: 8, name: 'eth', iconPath: 'assets/images/eth_icon.png'); static const ltc = CryptoCurrency(title: 'LTC', fullName: 'Litecoin', raw: 9, name: 'ltc', iconPath: 'assets/images/litecoin-ltc_icon.png'); - static const nano = CryptoCurrency(title: 'XNO', raw: 10, name: 'nano', iconPath: 'assets/images/nano.png'); + static const nano = CryptoCurrency(title: 'XNO', raw: 10, name: 'nano', iconPath: 'assets/images/nano_icon.png'); static const trx = CryptoCurrency(title: 'TRX', fullName: 'TRON', raw: 11, name: 'trx', iconPath: 'assets/images/trx_icon.png'); static const usdt = CryptoCurrency(title: 'USDT', tag: 'OMNI', fullName: 'USDT Tether', raw: 12, name: 'usdt', iconPath: 'assets/images/usdt_icon.png'); static const usdterc20 = CryptoCurrency(title: 'USDT', tag: 'ETH', fullName: 'USDT Tether', raw: 13, name: 'usdterc20', iconPath: 'assets/images/usdterc20_icon.png'); @@ -199,7 +199,7 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen static const zrx = CryptoCurrency(title: 'ZRX', tag: 'ETH', fullName: '0x Protocol', raw: 83, name: 'zrx', iconPath: 'assets/images/zrx_icon.png'); static const dydx = CryptoCurrency(title: 'DYDX', tag: 'ETH', fullName: 'dYdX', raw: 84, name: 'dydx', iconPath: 'assets/images/dydx_icon.png'); static const steth = CryptoCurrency(title: 'STETH', tag: 'ETH', fullName: 'Lido Staked Ethereum', raw: 85, name: 'steth', iconPath: 'assets/images/steth_icon.png'); - static const banano = CryptoCurrency(title: 'BAN', raw: 86, name: 'banano', iconPath: 'assets/images/nano.png'); + static const banano = CryptoCurrency(title: 'BAN', raw: 86, name: 'banano', iconPath: 'assets/images/nano_icon.png'); static final Map<int, CryptoCurrency> _rawCurrencyMap = diff --git a/cw_nano/lib/nano_client.dart b/cw_nano/lib/nano_client.dart index 74481f9ff..52abcd1b2 100644 --- a/cw_nano/lib/nano_client.dart +++ b/cw_nano/lib/nano_client.dart @@ -31,7 +31,7 @@ class NanoClient { return false; } } - + Future<NanoBalance> getBalance(String address) async { final response = await http.post( _node!.uri, @@ -51,6 +51,27 @@ class NanoClient { return NanoBalance(currentBalance: cur, receivableBalance: rec); } + Future<dynamic> getAccountInfo(String address) async { + try { + final response = await http.post( + _node!.uri, + headers: {"Content-Type": "application/json"}, + body: jsonEncode( + { + "action": "account_info", + "representative": "true", + "account": address, + }, + ), + ); + final data = await jsonDecode(response.body); + return data; + } catch (e) { + print("error while getting account info"); + rethrow; + } + } + Future<String> requestWork(String hash) async { return http .post( @@ -325,7 +346,7 @@ class NanoClient { if (receivableData["blocks"] == "" || receivableData["blocks"] == null) { return 0; } - + dynamic blocks; if (receivableData["blocks"] is List<dynamic>) { var listBlocks = receivableData["blocks"] as List<dynamic>; diff --git a/cw_nano/lib/nano_wallet.dart b/cw_nano/lib/nano_wallet.dart index c25f0042b..978da9268 100644 --- a/cw_nano/lib/nano_wallet.dart +++ b/cw_nano/lib/nano_wallet.dart @@ -62,6 +62,7 @@ abstract class NanoWalletBase late final String _privateKey; late final String _publicAddress; late final String _seedKey; + String? _representativeAddress; Timer? _receiveTimer; late NanoClient _client; @@ -120,6 +121,7 @@ abstract class NanoWalletBase try { await _updateBalance(); + await _updateRep(); await _receiveAll(); } catch (e) {} @@ -339,6 +341,15 @@ abstract class NanoWalletBase await save(); } + Future<void> _updateRep() async { + try { + final accountInfo = await _client.getAccountInfo(_publicAddress); + _representativeAddress = accountInfo["representative"] as String; + } catch (e) { + throw Exception("Failed to get representative address $e"); + } + } + Future<void>? updateBalance() async => await _updateBalance(); void _onNewTransaction(FilterEvent event) { diff --git a/lib/router.dart b/lib/router.dart index 8a42e7b04..f4120371e 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -12,6 +12,7 @@ import 'package:cake_wallet/src/screens/buy/webview_page.dart'; import 'package:cake_wallet/src/screens/buy/pre_order_page.dart'; import 'package:cake_wallet/src/screens/dashboard/edit_token_page.dart'; import 'package:cake_wallet/src/screens/dashboard/home_settings_page.dart'; +import 'package:cake_wallet/src/screens/nano/nano_change_rep_page.dart'; import 'package:cake_wallet/src/screens/restore/sweeping_wallet_page.dart'; import 'package:cake_wallet/src/screens/receive/anonpay_invoice_page.dart'; import 'package:cake_wallet/src/screens/receive/anonpay_receive_page.dart'; @@ -111,36 +112,34 @@ Route<dynamic> createRoute(RouteSettings settings) { case Routes.newWalletFromWelcome: return CupertinoPageRoute<void>( - builder: (_) => getIt.get<SetupPinCodePage>( - param1: (PinCodeState<PinCodeWidget> context, dynamic _) { - if (availableWalletTypes.length == 1) { - Navigator.of(context.context).pushNamed(Routes.newWallet, arguments: availableWalletTypes.first); - } else { - Navigator.of(context.context).pushNamed(Routes.newWalletType); - } - }), + builder: (_) => + getIt.get<SetupPinCodePage>(param1: (PinCodeState<PinCodeWidget> context, dynamic _) { + if (availableWalletTypes.length == 1) { + Navigator.of(context.context) + .pushNamed(Routes.newWallet, arguments: availableWalletTypes.first); + } else { + Navigator.of(context.context).pushNamed(Routes.newWalletType); + } + }), fullscreenDialog: true); case Routes.newWalletType: return CupertinoPageRoute<void>( builder: (_) => getIt.get<NewWalletTypePage>( param1: (BuildContext context, WalletType type) => - Navigator.of(context) - .pushNamed(Routes.newWallet, arguments: type))); + Navigator.of(context).pushNamed(Routes.newWallet, arguments: type))); case Routes.newWallet: final type = settings.arguments as WalletType; final walletNewVM = getIt.get<WalletNewVM>(param1: type); - return CupertinoPageRoute<void>( - builder: (_) => NewWalletPage(walletNewVM)); + return CupertinoPageRoute<void>(builder: (_) => NewWalletPage(walletNewVM)); case Routes.setupPin: Function(PinCodeState<PinCodeWidget>, String)? callback; if (settings.arguments is Function(PinCodeState<PinCodeWidget>, String)) { - callback = - settings.arguments as Function(PinCodeState<PinCodeWidget>, String); + callback = settings.arguments as Function(PinCodeState<PinCodeWidget>, String); } return CupertinoPageRoute<void>( @@ -150,8 +149,7 @@ Route<dynamic> createRoute(RouteSettings settings) { return CupertinoPageRoute<void>( builder: (_) => getIt.get<NewWalletTypePage>( param1: (BuildContext context, WalletType type) => - Navigator.of(context) - .pushNamed(Routes.restoreWallet, arguments: type), + Navigator.of(context).pushNamed(Routes.restoreWallet, arguments: type), param2: false)); case Routes.restoreOptions: @@ -166,66 +164,57 @@ Route<dynamic> createRoute(RouteSettings settings) { if (isNewInstall) { return CupertinoPageRoute<void>( builder: (_) => getIt.get<SetupPinCodePage>( - param1: (PinCodeState<PinCodeWidget> context, dynamic _) { + param1: (PinCodeState<PinCodeWidget> context, dynamic _) { if (isSingleCoin) { return Navigator.of(context.context) .pushNamed(Routes.restoreWallet, arguments: availableWalletTypes.first); } - return Navigator.pushNamed( - context.context, Routes.restoreWalletType); + return Navigator.pushNamed(context.context, Routes.restoreWalletType); }), fullscreenDialog: true); } else if (isSingleCoin) { return MaterialPageRoute<void>( - builder: (_) => getIt.get<WalletRestorePage>( - param1: availableWalletTypes.first - )); + builder: (_) => getIt.get<WalletRestorePage>(param1: availableWalletTypes.first)); } else { return CupertinoPageRoute<void>( builder: (_) => getIt.get<NewWalletTypePage>( param1: (BuildContext context, WalletType type) => - Navigator.of(context) - .pushNamed(Routes.restoreWallet, arguments: type), + Navigator.of(context).pushNamed(Routes.restoreWallet, arguments: type), param2: false)); } case Routes.seed: return MaterialPageRoute<void>( fullscreenDialog: true, - builder: (_) => - getIt.get<WalletSeedPage>(param1: settings.arguments as bool)); + builder: (_) => getIt.get<WalletSeedPage>(param1: settings.arguments as bool)); case Routes.restoreWallet: return MaterialPageRoute<void>( - builder: (_) => getIt.get<WalletRestorePage>( - param1: settings.arguments as WalletType)); + builder: (_) => getIt.get<WalletRestorePage>(param1: settings.arguments as WalletType)); case Routes.sweepingWalletPage: - return CupertinoPageRoute<void>( - builder: (_) => getIt.get<SweepingWalletPage>()); + return CupertinoPageRoute<void>(builder: (_) => getIt.get<SweepingWalletPage>()); case Routes.dashboard: return CupertinoPageRoute<void>( - settings: settings, - builder: (_) => getIt.get<DashboardPage>()); + settings: settings, builder: (_) => getIt.get<DashboardPage>()); case Routes.send: final initialPaymentRequest = settings.arguments as PaymentRequest?; return CupertinoPageRoute<void>( - fullscreenDialog: true, builder: (_) => getIt.get<SendPage>( - param1: initialPaymentRequest, - )); + fullscreenDialog: true, + builder: (_) => getIt.get<SendPage>( + param1: initialPaymentRequest, + )); case Routes.sendTemplate: return CupertinoPageRoute<void>( - fullscreenDialog: true, - builder: (_) => getIt.get<SendTemplatePage>()); + fullscreenDialog: true, builder: (_) => getIt.get<SendTemplatePage>()); case Routes.receive: - return CupertinoPageRoute<void>( - builder: (_) => getIt.get<ReceivePage>()); + return CupertinoPageRoute<void>(builder: (_) => getIt.get<ReceivePage>()); case Routes.addressPage: return CupertinoPageRoute<void>( @@ -234,20 +223,21 @@ Route<dynamic> createRoute(RouteSettings settings) { case Routes.transactionDetails: return CupertinoPageRoute<void>( fullscreenDialog: true, - builder: (_) => getIt.get<TransactionDetailsPage>( - param1: settings.arguments as TransactionInfo)); + builder: (_) => + getIt.get<TransactionDetailsPage>(param1: settings.arguments as TransactionInfo)); case Routes.newSubaddress: return CupertinoPageRoute<void>( - builder: (_) => - getIt.get<AddressEditOrCreatePage>(param1: settings.arguments)); + builder: (_) => getIt.get<AddressEditOrCreatePage>(param1: settings.arguments)); case Routes.disclaimer: return CupertinoPageRoute<void>(builder: (_) => DisclaimerPage()); case Routes.readDisclaimer: - return CupertinoPageRoute<void>( - builder: (_) => DisclaimerPage(isReadOnly: true)); + return CupertinoPageRoute<void>(builder: (_) => DisclaimerPage(isReadOnly: true)); + + case Routes.changeRep: + return CupertinoPageRoute<void>(builder: (_) => NanoChangeRepPage()); case Routes.seedLanguage: final args = settings.arguments as List<dynamic>; @@ -256,8 +246,8 @@ Route<dynamic> createRoute(RouteSettings settings) { return CupertinoPageRoute<void>(builder: (_) { return SeedLanguage( - onConfirm: (context, lang) => Navigator.of(context) - .popAndPushNamed(redirectRoute, arguments: [type, lang])); + onConfirm: (context, lang) => + Navigator.of(context).popAndPushNamed(redirectRoute, arguments: [type, lang])); }); case Routes.walletList: @@ -267,15 +257,13 @@ Route<dynamic> createRoute(RouteSettings settings) { case Routes.walletEdit: return MaterialPageRoute<void>( fullscreenDialog: true, - builder: (_) => getIt.get<WalletEditPage>( - param1: settings.arguments as List<dynamic>)); + builder: (_) => getIt.get<WalletEditPage>(param1: settings.arguments as List<dynamic>)); case Routes.auth: return MaterialPageRoute<void>( fullscreenDialog: true, builder: (_) => getIt.get<AuthPage>( - param1: settings.arguments as OnAuthenticationFinished, - param2: true)); + param1: settings.arguments as OnAuthenticationFinished, param2: true)); case Routes.totpAuthCodePage: final args = settings.arguments as TotpAuthArgumentsModel; @@ -290,9 +278,9 @@ Route<dynamic> createRoute(RouteSettings settings) { return CupertinoPageRoute<void>( builder: (context) => WillPopScope( child: getIt.get<AuthPage>(instanceName: 'login'), - onWillPop: () async => - // FIX-ME: Additional check does it works correctly - (await SystemChannels.platform.invokeMethod<bool>('SystemNavigator.pop') ?? + onWillPop: () async => + // FIX-ME: Additional check does it works correctly + (await SystemChannels.platform.invokeMethod<bool>('SystemNavigator.pop') ?? false), ), fullscreenDialog: true); @@ -302,43 +290,34 @@ Route<dynamic> createRoute(RouteSettings settings) { fullscreenDialog: true, builder: (_) => WillPopScope( child: getIt.get<AuthPage>( - param1: settings.arguments as OnAuthenticationFinished, - param2: false), + param1: settings.arguments as OnAuthenticationFinished, param2: false), onWillPop: () async => false)); case Routes.connectionSync: return CupertinoPageRoute<void>( - fullscreenDialog: true, - builder: (_) => getIt.get<ConnectionSyncPage>()); + fullscreenDialog: true, builder: (_) => getIt.get<ConnectionSyncPage>()); case Routes.securityBackupPage: return CupertinoPageRoute<void>( - fullscreenDialog: true, - builder: (_) => getIt.get<SecurityBackupPage>()); + fullscreenDialog: true, builder: (_) => getIt.get<SecurityBackupPage>()); - case Routes.privacyPage: + case Routes.privacyPage: return CupertinoPageRoute<void>( - fullscreenDialog: true, - builder: (_) => getIt.get<PrivacyPage>()); + fullscreenDialog: true, builder: (_) => getIt.get<PrivacyPage>()); - case Routes.displaySettingsPage: + case Routes.displaySettingsPage: return CupertinoPageRoute<void>( - fullscreenDialog: true, - builder: (_) => getIt.get<DisplaySettingsPage>()); + fullscreenDialog: true, builder: (_) => getIt.get<DisplaySettingsPage>()); case Routes.otherSettingsPage: return CupertinoPageRoute<void>( - fullscreenDialog: true, - builder: (_) => getIt.get<OtherSettingsPage>()); + fullscreenDialog: true, builder: (_) => getIt.get<OtherSettingsPage>()); case Routes.newNode: final args = settings.arguments as Map<String, dynamic>?; return CupertinoPageRoute<void>( builder: (_) => getIt.get<NodeCreateOrEditPage>( - param1: args?['editingNode'] as Node?, - param2: args?['isSelected'] as bool?)); - - + param1: args?['editingNode'] as Node?, param2: args?['isSelected'] as bool?)); case Routes.accountCreation: return CupertinoPageRoute<String>( @@ -347,8 +326,7 @@ Route<dynamic> createRoute(RouteSettings settings) { case Routes.addressBook: return MaterialPageRoute<void>( - fullscreenDialog: true, - builder: (_) => getIt.get<ContactListPage>()); + fullscreenDialog: true, builder: (_) => getIt.get<ContactListPage>()); case Routes.pickerAddressBook: final selectedCurrency = settings.arguments as CryptoCurrency?; @@ -357,49 +335,39 @@ Route<dynamic> createRoute(RouteSettings settings) { case Routes.addressBookAddContact: return CupertinoPageRoute<void>( - builder: (_) => getIt.get<ContactPage>( - param1: settings.arguments as ContactRecord?)); + builder: (_) => getIt.get<ContactPage>(param1: settings.arguments as ContactRecord?)); case Routes.showKeys: return MaterialPageRoute<void>( builder: (_) => getIt.get<WalletKeysPage>(), fullscreenDialog: true); case Routes.exchangeTrade: - return CupertinoPageRoute<void>( - builder: (_) => getIt.get<ExchangeTradePage>()); + return CupertinoPageRoute<void>(builder: (_) => getIt.get<ExchangeTradePage>()); case Routes.exchangeConfirm: - return MaterialPageRoute<void>( - builder: (_) => getIt.get<ExchangeConfirmPage>()); + return MaterialPageRoute<void>(builder: (_) => getIt.get<ExchangeConfirmPage>()); case Routes.tradeDetails: return MaterialPageRoute<void>( fullscreenDialog: true, - builder: (_) => - getIt.get<TradeDetailsPage>(param1: settings.arguments as Trade)); + builder: (_) => getIt.get<TradeDetailsPage>(param1: settings.arguments as Trade)); case Routes.orderDetails: return MaterialPageRoute<void>( - builder: (_) => - getIt.get<OrderDetailsPage>(param1: settings.arguments as Order)); + builder: (_) => getIt.get<OrderDetailsPage>(param1: settings.arguments as Order)); case Routes.preOrder: - return MaterialPageRoute<void>( - builder: (_) => - getIt.get<PreOrderPage>()); + return MaterialPageRoute<void>(builder: (_) => getIt.get<PreOrderPage>()); case Routes.buyWebView: final args = settings.arguments as List; return MaterialPageRoute<void>( - fullscreenDialog: true, - builder: (_) => - getIt.get<BuyWebViewPage>(param1: args)); + fullscreenDialog: true, builder: (_) => getIt.get<BuyWebViewPage>(param1: args)); case Routes.restoreWalletFromSeedDetails: final args = settings.arguments as List; - final walletRestorationFromSeedVM = - getIt.get<WalletRestorationFromSeedVM>(param1: args); + final walletRestorationFromSeedVM = getIt.get<WalletRestorationFromSeedVM>(param1: args); return CupertinoPageRoute<void>( fullscreenDialog: true, @@ -408,12 +376,10 @@ Route<dynamic> createRoute(RouteSettings settings) { case Routes.exchange: return CupertinoPageRoute<void>( - fullscreenDialog: true, - builder: (_) => getIt.get<ExchangePage>()); + fullscreenDialog: true, builder: (_) => getIt.get<ExchangePage>()); case Routes.exchangeTemplate: - return CupertinoPageRoute<void>( - builder: (_) => getIt.get<ExchangeTemplatePage>()); + return CupertinoPageRoute<void>(builder: (_) => getIt.get<ExchangeTemplatePage>()); case Routes.rescan: return MaterialPageRoute<void>(builder: (_) => getIt.get<RescanPage>()); @@ -423,43 +389,35 @@ Route<dynamic> createRoute(RouteSettings settings) { case Routes.preSeed: return MaterialPageRoute<void>( - builder: (_) => - getIt.get<PreSeedPage>(param1: settings.arguments as WalletType)); + builder: (_) => getIt.get<PreSeedPage>(param1: settings.arguments as WalletType)); case Routes.backup: return CupertinoPageRoute<void>( fullscreenDialog: true, builder: (_) => getIt.get<BackupPage>()); case Routes.editBackupPassword: - return CupertinoPageRoute<void>( - builder: (_) => getIt.get<EditBackupPasswordPage>()); + return CupertinoPageRoute<void>(builder: (_) => getIt.get<EditBackupPasswordPage>()); case Routes.restoreFromBackup: return CupertinoPageRoute<void>( - fullscreenDialog: true, - builder: (_) => getIt.get<RestoreFromBackupPage>()); + fullscreenDialog: true, builder: (_) => getIt.get<RestoreFromBackupPage>()); case Routes.support: return CupertinoPageRoute<void>( - fullscreenDialog: true, - builder: (_) => getIt.get<SupportPage>()); + fullscreenDialog: true, builder: (_) => getIt.get<SupportPage>()); case Routes.unspentCoinsList: - return MaterialPageRoute<void>( - builder: (_) => getIt.get<UnspentCoinsListPage>()); + return MaterialPageRoute<void>(builder: (_) => getIt.get<UnspentCoinsListPage>()); case Routes.unspentCoinsDetails: final args = settings.arguments as List; return MaterialPageRoute<void>( - builder: (_) => - getIt.get<UnspentCoinsDetailsPage>( - param1: args)); + builder: (_) => getIt.get<UnspentCoinsDetailsPage>(param1: args)); case Routes.fullscreenQR: return MaterialPageRoute<void>( - builder: (_) => - getIt.get<FullscreenQRPage>( + builder: (_) => getIt.get<FullscreenQRPage>( param1: settings.arguments as QrViewData, )); @@ -470,26 +428,27 @@ Route<dynamic> createRoute(RouteSettings settings) { ); case Routes.ioniaLoginPage: - return CupertinoPageRoute<void>( builder: (_) => getIt.get<IoniaLoginPage>()); + return CupertinoPageRoute<void>(builder: (_) => getIt.get<IoniaLoginPage>()); case Routes.ioniaCreateAccountPage: - return CupertinoPageRoute<void>( builder: (_) => getIt.get<IoniaCreateAccountPage>()); + return CupertinoPageRoute<void>(builder: (_) => getIt.get<IoniaCreateAccountPage>()); case Routes.ioniaManageCardsPage: - return CupertinoPageRoute<void>( - builder: (_) => getIt.get<IoniaManageCardsPage>()); + return CupertinoPageRoute<void>(builder: (_) => getIt.get<IoniaManageCardsPage>()); case Routes.ioniaBuyGiftCardPage: final args = settings.arguments as List; - return CupertinoPageRoute<void>(builder: (_) => getIt.get<IoniaBuyGiftCardPage>(param1: args)); + return CupertinoPageRoute<void>( + builder: (_) => getIt.get<IoniaBuyGiftCardPage>(param1: args)); case Routes.ioniaBuyGiftCardDetailPage: final args = settings.arguments as List; - return CupertinoPageRoute<void>(builder: (_) => getIt.get<IoniaBuyGiftCardDetailPage>(param1: args)); + return CupertinoPageRoute<void>( + builder: (_) => getIt.get<IoniaBuyGiftCardDetailPage>(param1: args)); case Routes.ioniaVerifyIoniaOtpPage: final args = settings.arguments as List; - return CupertinoPageRoute<void>(builder: (_) =>getIt.get<IoniaVerifyIoniaOtp>(param1: args)); + return CupertinoPageRoute<void>(builder: (_) => getIt.get<IoniaVerifyIoniaOtp>(param1: args)); case Routes.ioniaDebitCardPage: return CupertinoPageRoute<void>(builder: (_) => getIt.get<IoniaDebitCardPage>()); @@ -505,57 +464,60 @@ Route<dynamic> createRoute(RouteSettings settings) { case Routes.ioniaCustomTipPage: final args = settings.arguments as List; - return CupertinoPageRoute<void>(builder: (_) =>getIt.get<IoniaCustomTipPage>(param1: args)); + return CupertinoPageRoute<void>(builder: (_) => getIt.get<IoniaCustomTipPage>(param1: args)); case Routes.ioniaGiftCardDetailPage: final args = settings.arguments as List; - return CupertinoPageRoute<void>(builder: (_) => getIt.get<IoniaGiftCardDetailPage>(param1: args.first)); + return CupertinoPageRoute<void>( + builder: (_) => getIt.get<IoniaGiftCardDetailPage>(param1: args.first)); case Routes.ioniaCustomRedeemPage: final args = settings.arguments as List; - return CupertinoPageRoute<void>(builder: (_) => getIt.get<IoniaCustomRedeemPage>(param1: args)); + return CupertinoPageRoute<void>( + builder: (_) => getIt.get<IoniaCustomRedeemPage>(param1: args)); case Routes.ioniaMoreOptionsPage: final args = settings.arguments as List; - return CupertinoPageRoute<void>(builder: (_) => getIt.get<IoniaMoreOptionsPage>(param1: args)); + return CupertinoPageRoute<void>( + builder: (_) => getIt.get<IoniaMoreOptionsPage>(param1: args)); case Routes.ioniaPaymentStatusPage: final args = settings.arguments as List; final paymentInfo = args.first as IoniaAnyPayPaymentInfo; final commitedInfo = args[1] as AnyPayPaymentCommittedInfo; - return CupertinoPageRoute<void>(builder: (_) => getIt.get<IoniaPaymentStatusPage>( - param1: paymentInfo, - param2: commitedInfo)); + return CupertinoPageRoute<void>( + builder: (_) => + getIt.get<IoniaPaymentStatusPage>(param1: paymentInfo, param2: commitedInfo)); case Routes.webViewPage: final args = settings.arguments as List; final title = args.first as String; final url = args[1] as Uri; - return CupertinoPageRoute<void>(builder: (_) => getIt.get<WebViewPage>( - param1: title, - param2: url)); + return CupertinoPageRoute<void>( + builder: (_) => getIt.get<WebViewPage>(param1: title, param2: url)); case Routes.advancedPrivacySettings: final type = settings.arguments as WalletType; return CupertinoPageRoute<void>( builder: (_) => AdvancedPrivacySettingsPage( - getIt.get<AdvancedPrivacySettingsViewModel>(param1: type), - getIt.get<NodeCreateOrEditViewModel>(param1: type), - )); + getIt.get<AdvancedPrivacySettingsViewModel>(param1: type), + getIt.get<NodeCreateOrEditViewModel>(param1: type), + )); case Routes.anonPayInvoicePage: final args = settings.arguments as List; - return CupertinoPageRoute<void>( - builder: (_) => getIt.get<AnonPayInvoicePage>(param1: args)); + return CupertinoPageRoute<void>(builder: (_) => getIt.get<AnonPayInvoicePage>(param1: args)); case Routes.anonPayReceivePage: - final anonInvoiceViewData = settings.arguments as AnonpayInfoBase; - return CupertinoPageRoute<void>(builder: (_) => getIt.get<AnonPayReceivePage>(param1: anonInvoiceViewData)); + final anonInvoiceViewData = settings.arguments as AnonpayInfoBase; + return CupertinoPageRoute<void>( + builder: (_) => getIt.get<AnonPayReceivePage>(param1: anonInvoiceViewData)); case Routes.anonPayDetailsPage: final anonInvoiceViewData = settings.arguments as AnonpayInvoiceInfo; - return CupertinoPageRoute<void>(builder: (_) => getIt.get<AnonpayDetailsPage>(param1: anonInvoiceViewData)); + return CupertinoPageRoute<void>( + builder: (_) => getIt.get<AnonpayDetailsPage>(param1: anonInvoiceViewData)); case Routes.desktop_actions: return PageRouteBuilder( @@ -564,12 +526,10 @@ Route<dynamic> createRoute(RouteSettings settings) { ); case Routes.desktop_settings_page: - return CupertinoPageRoute<void>( - builder: (_) => DesktopSettingsPage()); + return CupertinoPageRoute<void>(builder: (_) => DesktopSettingsPage()); case Routes.empty_no_route: - return MaterialPageRoute<void>( - builder: (_) => SizedBox.shrink()); + return MaterialPageRoute<void>(builder: (_) => SizedBox.shrink()); case Routes.transactionsPage: return CupertinoPageRoute<void>( @@ -608,7 +568,6 @@ Route<dynamic> createRoute(RouteSettings settings) { default: return MaterialPageRoute<void>( builder: (_) => Scaffold( - body: Center( - child: Text(S.current.router_no_route(settings.name ?? 'No route'))))); + body: Center(child: Text(S.current.router_no_route(settings.name ?? 'No route'))))); } } diff --git a/lib/routes.dart b/lib/routes.dart index c6489d08c..6ca8e7bd8 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -14,6 +14,7 @@ class Routes { static const walletEdit = '/walletEdit'; static const disclaimer = '/disclaimer'; static const readDisclaimer = '/read_disclaimer'; + static const changeRep = '/change_representative'; static const seedLanguage = '/seed_language'; static const walletList = '/view_model.wallet_list'; static const auth = '/auth'; diff --git a/lib/src/screens/nano/nano_change_rep_page.dart b/lib/src/screens/nano/nano_change_rep_page.dart new file mode 100644 index 000000000..72ecdd2d4 --- /dev/null +++ b/lib/src/screens/nano/nano_change_rep_page.dart @@ -0,0 +1,128 @@ +import 'package:cake_wallet/core/address_validator.dart'; +import 'package:cake_wallet/core/execution_state.dart'; +import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/src/screens/nodes/widgets/node_form.dart'; +import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; +import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; +import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/node.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:mobx/mobx.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/widgets/primary_button.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; +import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; + +class NanoChangeRepPage extends BasePage { + NanoChangeRepPage() + : _formKey = GlobalKey<FormState>(), + _addressController = TextEditingController() { + // reaction((_) => nodeCreateOrEditViewModel.address, (String address) { + // if (address != _addressController.text) { + // _addressController.text = address; + // } + // }); + + // reaction((_) => nodeCreateOrEditViewModel.port, (String port) { + // if (port != _portController.text) { + // _portController.text = port; + // } + // }); + + // if (nodeCreateOrEditViewModel.hasAuthCredentials) { + // reaction((_) => nodeCreateOrEditViewModel.login, (String login) { + // if (login != _loginController.text) { + // _loginController.text = login; + // } + // }); + + // reaction((_) => nodeCreateOrEditViewModel.password, (String password) { + // if (password != _passwordController.text) { + // _passwordController.text = password; + // } + // }); + // } + + // _addressController.addListener( + // () => repViewModel.address = _addressController.text); + // _portController.addListener( + // () => nodeCreateOrEditViewModel.port = _portController.text); + // _loginController.addListener( + // () => nodeCreateOrEditViewModel.login = _loginController.text); + // _passwordController.addListener( + // () => nodeCreateOrEditViewModel.password = _passwordController.text); + } + + final GlobalKey<FormState> _formKey; + final TextEditingController _addressController; + + // final CryptoCurrency type; + + @override + String get title => S.current.change_rep; + + @override + Widget body(BuildContext context) { + return Container( + padding: EdgeInsets.only(left: 24, right: 24), + child: ScrollableWithBottomSection( + contentPadding: EdgeInsets.only(bottom: 24.0), + content: Container( + child: Column( + children: <Widget>[ + Row( + children: <Widget>[ + Expanded( + child: BaseTextFormField( + controller: _addressController, + hintText: S.of(context).node_address, + validator: AddressValidator(type: CryptoCurrency.nano), + ), + ) + ], + ), + ], + ), + ), + bottomSectionPadding: EdgeInsets.only(bottom: 24), + bottomSection: Observer( + builder: (_) => Row( + mainAxisAlignment: MainAxisAlignment.center, + children: <Widget>[ + Flexible( + child: Container( + padding: EdgeInsets.only(right: 8.0), + child: LoadingPrimaryButton( + onPressed: () async { + final confirmed = await showPopUp<bool>( + context: context, + builder: (BuildContext context) { + return AlertWithTwoActions( + alertTitle: S.of(context).remove_node, + alertContent: S.of(context).remove_node_message, + rightButtonText: S.of(context).change, + leftButtonText: S.of(context).cancel, + actionRightButton: () => Navigator.pop(context, true), + actionLeftButton: () => Navigator.pop(context, false)); + }) ?? + false; + + if (confirmed) { + // await editingNode!.delete(); + Navigator.of(context).pop(); + } + }, + text: S.of(context).change, + color: Theme.of(context).accentTextTheme.bodyLarge!.color!, + textColor: Colors.white, + ), + )), + ], + )), + )); + } +} diff --git a/lib/src/screens/nano/rep_form.dart b/lib/src/screens/nano/rep_form.dart new file mode 100644 index 000000000..bde3088a7 --- /dev/null +++ b/lib/src/screens/nano/rep_form.dart @@ -0,0 +1,57 @@ +import 'package:cake_wallet/core/address_validator.dart'; +import 'package:cake_wallet/core/node_address_validator.dart'; +import 'package:cake_wallet/core/node_port_validator.dart'; +import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; +import 'package:cake_wallet/src/widgets/standard_checkbox.dart'; +import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/node.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:mobx/mobx.dart'; + +class RepForm extends StatelessWidget { + RepForm({ + required this.repViewModel, + required this.formKey, + required this.type, + this.editingNode, + }) : _addressController = TextEditingController(text: editingNode?.password) { + if (editingNode != null) { + repViewModel..setAddress((editingNode!.password!)); + } + + _addressController.addListener(() => repViewModel.address = _addressController.text); + } + + final NodeCreateOrEditViewModel repViewModel; + final GlobalKey<FormState> formKey; + final Node? editingNode; + final CryptoCurrency type; + + final TextEditingController _addressController; + + @override + Widget build(BuildContext context) { + return Form( + key: formKey, + child: Column( + children: <Widget>[ + Row( + children: <Widget>[ + Expanded( + child: BaseTextFormField( + controller: _addressController, + hintText: S.of(context).node_address, + validator: AddressValidator(type: type), + ), + ) + ], + ), + SizedBox(height: 10.0), + ], + ), + ); + } +} diff --git a/lib/src/screens/settings/other_settings_page.dart b/lib/src/screens/settings/other_settings_page.dart index e055e2e8e..14dc5d4c8 100644 --- a/lib/src/screens/settings/other_settings_page.dart +++ b/lib/src/screens/settings/other_settings_page.dart @@ -31,9 +31,16 @@ class OtherSettingsPage extends BasePage { selectedItem: _otherSettingsViewModel.transactionPriority, onItemSelected: _otherSettingsViewModel.onDisplayPrioritySelected, ), + if (_otherSettingsViewModel.changeRepresentativeEnabled) + SettingsCellWithArrow( + title: S.current.change, + handler: (BuildContext context) => + Navigator.of(context).pushNamed(Routes.changeRep), + ), SettingsCellWithArrow( title: S.current.settings_terms_and_conditions, - handler: (BuildContext context) => Navigator.of(context).pushNamed(Routes.readDisclaimer), + handler: (BuildContext context) => + Navigator.of(context).pushNamed(Routes.readDisclaimer), ), StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)), Spacer(), diff --git a/lib/view_model/settings/other_settings_view_model.dart b/lib/view_model/settings/other_settings_view_model.dart index c57af50d9..1aec2dc31 100644 --- a/lib/view_model/settings/other_settings_view_model.dart +++ b/lib/view_model/settings/other_settings_view_model.dart @@ -48,6 +48,15 @@ abstract class OtherSettingsViewModelBase with Store { return priority; } + @computed + bool get changeRepresentativeEnabled { + if (_wallet.type == WalletType.nano || _wallet.type == WalletType.banano) { + return true; + } + + return false; + } + String getDisplayPriority(dynamic priority) { final _priority = priority as TransactionPriority;