mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-23 12:09:43 +00:00
stuff that should've stayed deleted
This commit is contained in:
parent
25ef8cbe67
commit
1c210274d3
8 changed files with 114 additions and 781 deletions
|
@ -1,91 +0,0 @@
|
|||
import 'package:cw_nano/api/structs/subaddress_row.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cw_nano/api/subaddress_list.dart' as subaddress_list;
|
||||
import 'package:cw_core/subaddress.dart';
|
||||
|
||||
part 'nano_subaddress_list.g.dart';
|
||||
|
||||
class NanoSubaddressList = NanoSubaddressListBase
|
||||
with _$NanoSubaddressList;
|
||||
|
||||
abstract class NanoSubaddressListBase with Store {
|
||||
NanoSubaddressListBase()
|
||||
: _isRefreshing = false,
|
||||
_isUpdating = false,
|
||||
subaddresses = ObservableList<Subaddress>();
|
||||
|
||||
@observable
|
||||
ObservableList<Subaddress> subaddresses;
|
||||
|
||||
bool _isRefreshing;
|
||||
bool _isUpdating;
|
||||
|
||||
void update({required int accountIndex}) {
|
||||
if (_isUpdating) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
_isUpdating = true;
|
||||
refresh(accountIndex: accountIndex);
|
||||
subaddresses.clear();
|
||||
subaddresses.addAll(getAll());
|
||||
_isUpdating = false;
|
||||
} catch (e) {
|
||||
_isUpdating = false;
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
List<Subaddress> getAll() {
|
||||
var subaddresses = subaddress_list.getAllSubaddresses();
|
||||
|
||||
if (subaddresses.length > 2) {
|
||||
final primary = subaddresses.first;
|
||||
final rest = subaddresses.sublist(1).reversed;
|
||||
subaddresses = [primary] + rest.toList();
|
||||
}
|
||||
|
||||
return [];
|
||||
|
||||
// return subaddresses
|
||||
// .map((subaddressRow) => Subaddress(
|
||||
// id: subaddressRow.getId(),
|
||||
// address: subaddressRow.getAddress(),
|
||||
// label: subaddressRow.getId() == 0 &&
|
||||
// subaddressRow.getLabel().toLowerCase() == 'Primary account'.toLowerCase()
|
||||
// ? 'Primary address'
|
||||
// : subaddressRow.getLabel()))
|
||||
// .toList();
|
||||
}
|
||||
|
||||
Future<void> addSubaddress({required int accountIndex, required String label}) async {
|
||||
await subaddress_list.addSubaddress(
|
||||
accountIndex: accountIndex, label: label);
|
||||
update(accountIndex: accountIndex);
|
||||
}
|
||||
|
||||
Future<void> setLabelSubaddress(
|
||||
{required int accountIndex, required int addressIndex, required String label}) async {
|
||||
await subaddress_list.setLabelForSubaddress(
|
||||
accountIndex: accountIndex, addressIndex: addressIndex, label: label);
|
||||
update(accountIndex: accountIndex);
|
||||
}
|
||||
|
||||
void refresh({required int accountIndex}) {
|
||||
if (_isRefreshing) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
_isRefreshing = true;
|
||||
subaddress_list.refreshSubaddresses(accountIndex: accountIndex);
|
||||
_isRefreshing = false;
|
||||
} on PlatformException catch (e) {
|
||||
_isRefreshing = false;
|
||||
print(e);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,23 +1,38 @@
|
|||
|
||||
import 'package:cw_core/cake_hive.dart';
|
||||
import 'package:cw_core/nano_account.dart';
|
||||
import 'package:cw_nano/nano_mnemonic.dart';
|
||||
import 'package:cw_nano/nano_wallet.dart';
|
||||
import 'package:cw_nano/nano_wallet_service.dart';
|
||||
import 'package:cake_wallet/view_model/send/output.dart';
|
||||
import 'package:cw_core/account.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cw_core/node.dart';
|
||||
import 'package:cw_core/wallet_credentials.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/transaction_info.dart';
|
||||
import 'package:cw_core/transaction_history.dart';
|
||||
import 'package:cw_core/wallet_service.dart';
|
||||
import 'package:cw_core/output_info.dart';
|
||||
import 'package:cw_core/nano_account_info_response.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:cake_wallet/view_model/send/output.dart';
|
||||
|
||||
import 'package:cw_nano/nano_client.dart';
|
||||
import 'package:cw_nano/nano_mnemonic.dart';
|
||||
import 'package:cw_nano/nano_wallet.dart';
|
||||
import 'package:cw_nano/nano_wallet_service.dart';
|
||||
import 'package:cw_nano/nano_transaction_info.dart';
|
||||
import 'package:cw_nano/nano_transaction_credentials.dart';
|
||||
import 'package:cw_nano/nano_wallet_creation_credentials.dart';
|
||||
// needed for nano_util:
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
import 'package:convert/convert.dart';
|
||||
import "package:ed25519_hd_key/ed25519_hd_key.dart";
|
||||
import 'package:libcrypto/libcrypto.dart';
|
||||
import 'package:nanodart/nanodart.dart' as ND;
|
||||
import 'package:decimal/decimal.dart';
|
||||
|
||||
part 'cw_nano.dart';
|
||||
|
||||
Nano? nano = CWNano();
|
||||
NanoUtil? nanoUtil = CWNanoUtil();
|
||||
|
||||
abstract class Nano {
|
||||
NanoAccountList getAccountList(Object wallet);
|
||||
|
@ -28,8 +43,6 @@ abstract class Nano {
|
|||
|
||||
WalletService createNanoWalletService(Box<WalletInfo> walletInfoSource);
|
||||
|
||||
TransactionHistoryBase getTransactionHistory(Object wallet);
|
||||
|
||||
WalletCredentials createNanoNewWalletCredentials({
|
||||
required String name,
|
||||
String password,
|
||||
|
@ -49,13 +62,12 @@ abstract class Nano {
|
|||
DerivationType? derivationType,
|
||||
});
|
||||
|
||||
String getTransactionAddress(Object wallet, int accountIndex, int addressIndex);
|
||||
|
||||
void onStartup();
|
||||
|
||||
List<String> getNanoWordList(String language);
|
||||
Map<String, String> getKeys(Object wallet);
|
||||
Object createNanoTransactionCredentials(List<Output> outputs);
|
||||
Future<void> changeRep(Object wallet, String address);
|
||||
Future<void> updateTransactions(Object wallet);
|
||||
BigInt getTransactionAmountRaw(TransactionInfo transactionInfo);
|
||||
}
|
||||
|
||||
abstract class NanoAccountList {
|
||||
|
@ -66,4 +78,46 @@ abstract class NanoAccountList {
|
|||
Future<void> addAccount(Object wallet, {required String label});
|
||||
Future<void> setLabelAccount(Object wallet, {required int accountIndex, required String label});
|
||||
}
|
||||
|
||||
abstract class NanoUtil {
|
||||
String seedToPrivate(String seed, int index);
|
||||
String seedToAddress(String seed, int index);
|
||||
String seedToMnemonic(String seed);
|
||||
Future<String> mnemonicToSeed(String mnemonic);
|
||||
String privateKeyToPublic(String privateKey);
|
||||
String addressToPublicKey(String publicAddress);
|
||||
String privateKeyToAddress(String privateKey);
|
||||
String publicKeyToAddress(String publicKey);
|
||||
bool isValidSeed(String seed);
|
||||
Future<String> hdMnemonicListToSeed(List<String> words);
|
||||
Future<String> hdSeedToPrivate(String seed, int index);
|
||||
Future<String> hdSeedToAddress(String seed, int index);
|
||||
Future<String> uniSeedToAddress(String seed, int index, String type);
|
||||
Future<String> uniSeedToPrivate(String seed, int index, String type);
|
||||
bool isValidBip39Seed(String seed);
|
||||
static const int maxDecimalDigits = 6; // Max digits after decimal
|
||||
BigInt rawPerNano = BigInt.parse("1000000000000000000000000000000");
|
||||
BigInt rawPerNyano = BigInt.parse("1000000000000000000000000");
|
||||
BigInt rawPerBanano = BigInt.parse("100000000000000000000000000000");
|
||||
BigInt rawPerXMR = BigInt.parse("1000000000000");
|
||||
BigInt convertXMRtoNano = BigInt.parse("1000000000000000000");
|
||||
Decimal getRawAsDecimal(String? raw, BigInt? rawPerCur);
|
||||
String truncateDecimal(Decimal input, {int digits = maxDecimalDigits});
|
||||
String getRawAsUsableString(String? raw, BigInt rawPerCur);
|
||||
String getRawAccuracy(String? raw, BigInt rawPerCur);
|
||||
String getAmountAsRaw(String amount, BigInt rawPerCur);
|
||||
|
||||
// derivationInfo:
|
||||
Future<AccountInfoResponse?> getInfoFromSeedOrMnemonic(
|
||||
DerivationType derivationType, {
|
||||
String? seedKey,
|
||||
String? mnemonic,
|
||||
required Node node,
|
||||
});
|
||||
Future<List<DerivationType>> compareDerivationMethods({
|
||||
String? mnemonic,
|
||||
String? privateKey,
|
||||
required Node node,
|
||||
});
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
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),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -15,7 +15,8 @@ import 'package:cake_wallet/src/screens/base_page.dart';
|
|||
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
||||
|
||||
class PowNodeCreateOrEditPage extends BasePage {
|
||||
PowNodeCreateOrEditPage({required this.nodeCreateOrEditViewModel,this.editingNode, this.isSelected})
|
||||
PowNodeCreateOrEditPage(
|
||||
{required this.nodeCreateOrEditViewModel, this.editingNode, this.isSelected})
|
||||
: _formKey = GlobalKey<FormState>(),
|
||||
_addressController = TextEditingController(),
|
||||
_portController = TextEditingController(),
|
||||
|
@ -47,14 +48,12 @@ class PowNodeCreateOrEditPage extends BasePage {
|
|||
});
|
||||
}
|
||||
|
||||
_addressController.addListener(
|
||||
() => nodeCreateOrEditViewModel.address = _addressController.text);
|
||||
_portController.addListener(
|
||||
() => nodeCreateOrEditViewModel.port = _portController.text);
|
||||
_loginController.addListener(
|
||||
() => nodeCreateOrEditViewModel.login = _loginController.text);
|
||||
_passwordController.addListener(
|
||||
() => nodeCreateOrEditViewModel.password = _passwordController.text);
|
||||
_addressController
|
||||
.addListener(() => nodeCreateOrEditViewModel.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;
|
||||
|
@ -78,45 +77,42 @@ class PowNodeCreateOrEditPage extends BasePage {
|
|||
'assets/images/qr_code_icon.png',
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
final NodeCreateOrEditViewModel nodeCreateOrEditViewModel;
|
||||
final Node? editingNode;
|
||||
final bool? isSelected;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
|
||||
reaction((_) => nodeCreateOrEditViewModel.connectionState,
|
||||
(ExecutionState state) {
|
||||
if (state is ExecutedSuccessfullyState) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) =>
|
||||
AlertWithOneAction(
|
||||
alertTitle: S.of(context).new_node_testing,
|
||||
alertContent: state.payload as bool
|
||||
? S.of(context).node_connection_successful
|
||||
: S.of(context).node_connection_failed,
|
||||
buttonText: S.of(context).ok,
|
||||
buttonAction: () => Navigator.of(context).pop()));
|
||||
});
|
||||
}
|
||||
|
||||
if (state is FailureState) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithOneAction(
|
||||
alertTitle: S.of(context).error,
|
||||
alertContent: state.error,
|
||||
buttonText: S.of(context).ok,
|
||||
buttonAction: () => Navigator.of(context).pop());
|
||||
});
|
||||
});
|
||||
}
|
||||
reaction((_) => nodeCreateOrEditViewModel.connectionState, (ExecutionState state) {
|
||||
if (state is ExecutedSuccessfullyState) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) => AlertWithOneAction(
|
||||
alertTitle: S.of(context).new_node_testing,
|
||||
alertContent: state.payload as bool
|
||||
? S.of(context).node_connection_successful
|
||||
: S.of(context).node_connection_failed,
|
||||
buttonText: S.of(context).ok,
|
||||
buttonAction: () => Navigator.of(context).pop()));
|
||||
});
|
||||
}
|
||||
|
||||
if (state is FailureState) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithOneAction(
|
||||
alertTitle: S.of(context).error,
|
||||
alertContent: state.error,
|
||||
buttonText: S.of(context).ok,
|
||||
buttonAction: () => Navigator.of(context).pop());
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return Container(
|
||||
padding: EdgeInsets.only(left: 24, right: 24),
|
||||
|
@ -141,19 +137,12 @@ class PowNodeCreateOrEditPage extends BasePage {
|
|||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithTwoActions(
|
||||
alertTitle:
|
||||
S.of(context).remove_node,
|
||||
alertContent: S
|
||||
.of(context)
|
||||
.remove_node_message,
|
||||
rightButtonText:
|
||||
S.of(context).remove,
|
||||
leftButtonText:
|
||||
S.of(context).cancel,
|
||||
actionRightButton: () =>
|
||||
Navigator.pop(context, true),
|
||||
actionLeftButton: () =>
|
||||
Navigator.pop(context, false));
|
||||
alertTitle: S.of(context).remove_node,
|
||||
alertContent: S.of(context).remove_node_message,
|
||||
rightButtonText: S.of(context).remove,
|
||||
leftButtonText: S.of(context).cancel,
|
||||
actionRightButton: () => Navigator.pop(context, true),
|
||||
actionLeftButton: () => Navigator.pop(context, false));
|
||||
}) ??
|
||||
false;
|
||||
|
||||
|
@ -163,8 +152,7 @@ class PowNodeCreateOrEditPage extends BasePage {
|
|||
}
|
||||
},
|
||||
text: S.of(context).delete,
|
||||
isDisabled: !nodeCreateOrEditViewModel.isReady ||
|
||||
(isSelected ?? false),
|
||||
isDisabled: !nodeCreateOrEditViewModel.isReady || (isSelected ?? false),
|
||||
color: Palette.red,
|
||||
textColor: Colors.white),
|
||||
)),
|
||||
|
@ -173,7 +161,8 @@ class PowNodeCreateOrEditPage extends BasePage {
|
|||
padding: EdgeInsets.only(left: 8.0),
|
||||
child: PrimaryButton(
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState != null && !_formKey.currentState!.validate()) {
|
||||
if (_formKey.currentState != null &&
|
||||
!_formKey.currentState!.validate()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -184,9 +173,8 @@ class PowNodeCreateOrEditPage extends BasePage {
|
|||
text: S.of(context).save,
|
||||
color: Theme.of(context).primaryColor,
|
||||
textColor: Colors.white,
|
||||
isDisabled: (!nodeCreateOrEditViewModel.isReady)||
|
||||
(nodeCreateOrEditViewModel
|
||||
.connectionState is IsExecutingState),
|
||||
isDisabled: (!nodeCreateOrEditViewModel.isReady) ||
|
||||
(nodeCreateOrEditViewModel.connectionState is IsExecutingState),
|
||||
),
|
||||
)),
|
||||
],
|
||||
|
|
|
@ -1,201 +0,0 @@
|
|||
import 'package:cake_wallet/core/node_address_validator.dart';
|
||||
import 'package:cake_wallet/core/node_port_validator.dart';
|
||||
import 'package:cake_wallet/core/socks_proxy_node_address_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:cake_wallet/view_model/node_list/pow_node_create_or_edit_view_model.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 PowNodeForm extends StatelessWidget {
|
||||
PowNodeForm({
|
||||
required this.nodeViewModel,
|
||||
required this.formKey,
|
||||
this.editingNode,
|
||||
}) : _addressController = TextEditingController(text: editingNode?.uri.host.toString()),
|
||||
_portController = TextEditingController(text: editingNode?.uri.port.toString()),
|
||||
_loginController = TextEditingController(text: editingNode?.login),
|
||||
_passwordController = TextEditingController(text: editingNode?.password),
|
||||
_socksAddressController = TextEditingController(text: editingNode?.socksProxyAddress){
|
||||
if (editingNode != null) {
|
||||
nodeViewModel
|
||||
..setAddress((editingNode!.uri.host.toString()))
|
||||
..setPort((editingNode!.uri.port.toString()))
|
||||
..setPassword((editingNode!.password ?? ''))
|
||||
..setLogin((editingNode!.login ?? ''))
|
||||
..setSSL((editingNode!.isSSL))
|
||||
..setTrusted((editingNode!.trusted))
|
||||
..setSocksProxy((editingNode!.useSocksProxy))
|
||||
..setSocksProxyAddress((editingNode!.socksProxyAddress ?? ''));
|
||||
}
|
||||
if (nodeViewModel.hasAuthCredentials) {
|
||||
reaction((_) => nodeViewModel.login, (String login) {
|
||||
if (login != _loginController.text) {
|
||||
_loginController.text = login;
|
||||
}
|
||||
});
|
||||
|
||||
reaction((_) => nodeViewModel.password, (String password) {
|
||||
if (password != _passwordController.text) {
|
||||
_passwordController.text = password;
|
||||
}
|
||||
});
|
||||
}
|
||||
reaction((_) => nodeViewModel.address, (String address) {
|
||||
if (address != _addressController.text) {
|
||||
_addressController.text = address;
|
||||
}
|
||||
});
|
||||
|
||||
reaction((_) => nodeViewModel.port, (String port) {
|
||||
if (port != _portController.text) {
|
||||
_portController.text = port;
|
||||
}
|
||||
});
|
||||
|
||||
_addressController.addListener(() => nodeViewModel.address = _addressController.text);
|
||||
_portController.addListener(() => nodeViewModel.port = _portController.text);
|
||||
_loginController.addListener(() => nodeViewModel.login = _loginController.text);
|
||||
_passwordController.addListener(() => nodeViewModel.password = _passwordController.text);
|
||||
_socksAddressController.addListener(() => nodeViewModel.socksProxyAddress = _socksAddressController.text);
|
||||
}
|
||||
|
||||
final PowNodeCreateOrEditViewModel nodeViewModel;
|
||||
final GlobalKey<FormState> formKey;
|
||||
final Node? editingNode;
|
||||
|
||||
final TextEditingController _addressController;
|
||||
final TextEditingController _portController;
|
||||
final TextEditingController _loginController;
|
||||
final TextEditingController _passwordController;
|
||||
final TextEditingController _socksAddressController;
|
||||
|
||||
@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: NodeAddressValidator(),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10.0),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: BaseTextFormField(
|
||||
controller: _portController,
|
||||
hintText: S.of(context).node_port,
|
||||
keyboardType: TextInputType.numberWithOptions(signed: false, decimal: false),
|
||||
validator: NodePortValidator(),
|
||||
))
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10.0),
|
||||
if (nodeViewModel.hasAuthCredentials) ...[
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: BaseTextFormField(
|
||||
controller: _loginController,
|
||||
hintText: S.of(context).login,
|
||||
))
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10.0),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: BaseTextFormField(
|
||||
controller: _passwordController,
|
||||
hintText: S.of(context).password,
|
||||
))
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 20),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Observer(
|
||||
builder: (_) => StandardCheckbox(
|
||||
value: nodeViewModel.useSSL,
|
||||
onChanged: (value) => nodeViewModel.useSSL = value,
|
||||
caption: S.of(context).use_ssl,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 20),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Observer(
|
||||
builder: (_) => StandardCheckbox(
|
||||
value: nodeViewModel.trusted,
|
||||
onChanged: (value) => nodeViewModel.trusted = value,
|
||||
caption: S.of(context).trusted,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Observer(
|
||||
builder: (_) => Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 20),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
StandardCheckbox(
|
||||
value: nodeViewModel.useSocksProxy,
|
||||
onChanged: (value) {
|
||||
if (!value) {
|
||||
_socksAddressController.text = '';
|
||||
}
|
||||
nodeViewModel.useSocksProxy = value;
|
||||
},
|
||||
caption: 'SOCKS Proxy',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (nodeViewModel.useSocksProxy) ...[
|
||||
SizedBox(height: 10.0),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: BaseTextFormField(
|
||||
controller: _socksAddressController,
|
||||
hintText: '[<ip>:]<port>',
|
||||
validator: SocksProxyNodeAddressValidator(),
|
||||
))
|
||||
],
|
||||
),
|
||||
]
|
||||
],
|
||||
)),
|
||||
]
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/nodes/widgets/node_indicator.dart';
|
||||
import 'package:cake_wallet/src/widgets/standard_list.dart';
|
||||
import 'package:cake_wallet/themes/extensions/filter_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/receive_page_theme.dart';
|
||||
import 'package:cw_core/node.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class PowNodeListRow extends StandardListRow {
|
||||
PowNodeListRow(
|
||||
{required String title,
|
||||
required this.node,
|
||||
required void Function(BuildContext context) onTap,
|
||||
required bool isSelected})
|
||||
: super(title: title, onTap: onTap, isSelected: isSelected);
|
||||
|
||||
final Node node;
|
||||
|
||||
@override
|
||||
Widget buildLeading(BuildContext context) {
|
||||
return FutureBuilder(
|
||||
future: node.requestNode(),
|
||||
builder: (context, snapshot) {
|
||||
switch (snapshot.connectionState) {
|
||||
case ConnectionState.done:
|
||||
return NodeIndicator(isLive: (snapshot.data as bool?) ?? false);
|
||||
default:
|
||||
return NodeIndicator(isLive: false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget buildTrailing(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () => Navigator.of(context)
|
||||
.pushNamed(Routes.newNode, arguments: {'editingNode': node, 'isSelected': isSelected}),
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Theme.of(context).extension<ReceivePageTheme>()!.iconsBackgroundColor),
|
||||
child: Icon(Icons.edit,
|
||||
size: 14, color: Theme.of(context).extension<ReceivePageTheme>()!.iconsColor)));
|
||||
}
|
||||
}
|
||||
|
||||
class PowNodeHeaderListRow extends StandardListRow {
|
||||
PowNodeHeaderListRow({required String title, required void Function(BuildContext context) onTap})
|
||||
: super(title: title, onTap: onTap, isSelected: false);
|
||||
|
||||
@override
|
||||
Widget buildTrailing(BuildContext context) {
|
||||
return SizedBox(
|
||||
width: 20,
|
||||
child: Icon(Icons.add,
|
||||
color: Theme.of(context).extension<FilterTheme>()!.titlesColor, size: 24.0),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/screens/nodes/widgets/pow_node_list_row.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||
import 'package:cake_wallet/src/widgets/standard_list.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/node_list/pow_node_list_view_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
|
||||
class ManagePowNodesPage extends BasePage {
|
||||
ManagePowNodesPage(this.nodeListViewModel);
|
||||
|
||||
final PowNodeListViewModel nodeListViewModel;
|
||||
|
||||
@override
|
||||
String get title => S.current.manage_pow_nodes;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: Column(
|
||||
children: [
|
||||
Semantics(
|
||||
button: true,
|
||||
child: PowNodeHeaderListRow(
|
||||
title: S.of(context).add_new_node,
|
||||
onTap: (_) async => await Navigator.of(context).pushNamed(Routes.newPowNode),
|
||||
),
|
||||
),
|
||||
const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
|
||||
SizedBox(height: 20),
|
||||
Observer(
|
||||
builder: (BuildContext context) {
|
||||
int nodesLength = nodeListViewModel.nodes.length;
|
||||
return Flexible(
|
||||
child: SectionStandardList(
|
||||
sectionCount: 1,
|
||||
dividerPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||
itemCounter: (int sectionIndex) {
|
||||
return nodesLength;
|
||||
},
|
||||
itemBuilder: (_, index) {
|
||||
return Observer(
|
||||
builder: (context) {
|
||||
final node = nodeListViewModel.nodes[index];
|
||||
final isSelected = node.keyIndex == nodeListViewModel.currentNode.keyIndex;
|
||||
final nodeListRow = PowNodeListRow(
|
||||
title: node.uriRaw,
|
||||
node: node,
|
||||
isSelected: isSelected,
|
||||
onTap: (_) async {
|
||||
if (isSelected) {
|
||||
return;
|
||||
}
|
||||
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithTwoActions(
|
||||
alertTitle: S.of(context).change_current_node_title,
|
||||
alertContent: nodeListViewModel.getAlertContent(node.uriRaw),
|
||||
leftButtonText: S.of(context).cancel,
|
||||
rightButtonText: S.of(context).change,
|
||||
actionLeftButton: () => Navigator.of(context).pop(),
|
||||
actionRightButton: () async {
|
||||
await nodeListViewModel.setAsCurrent(node);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
return nodeListRow;
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,211 +0,0 @@
|
|||
import 'package:cake_wallet/core/execution_state.dart';
|
||||
import 'package:cake_wallet/entities/qr_scanner.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cw_core/node.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
|
||||
part 'pow_node_create_or_edit_view_model.g.dart';
|
||||
|
||||
class PowNodeCreateOrEditViewModel = PowNodeCreateOrEditViewModelBase
|
||||
with _$PowNodeCreateOrEditViewModel;
|
||||
|
||||
abstract class PowNodeCreateOrEditViewModelBase with Store {
|
||||
PowNodeCreateOrEditViewModelBase(
|
||||
this._nodeSource, this._walletType, this._settingsStore)
|
||||
: state = InitialExecutionState(),
|
||||
connectionState = InitialExecutionState(),
|
||||
useSSL = false,
|
||||
address = '',
|
||||
port = '',
|
||||
login = '',
|
||||
password = '',
|
||||
trusted = false,
|
||||
useSocksProxy = false,
|
||||
socksProxyAddress = '';
|
||||
|
||||
@observable
|
||||
ExecutionState state;
|
||||
|
||||
@observable
|
||||
String address;
|
||||
|
||||
@observable
|
||||
String port;
|
||||
|
||||
@observable
|
||||
String login;
|
||||
|
||||
@observable
|
||||
String password;
|
||||
|
||||
@observable
|
||||
ExecutionState connectionState;
|
||||
|
||||
@observable
|
||||
bool useSSL;
|
||||
|
||||
@observable
|
||||
bool trusted;
|
||||
|
||||
@observable
|
||||
bool useSocksProxy;
|
||||
|
||||
@observable
|
||||
String socksProxyAddress;
|
||||
|
||||
@computed
|
||||
bool get isReady => address.isNotEmpty && port.isNotEmpty;
|
||||
|
||||
bool get hasAuthCredentials =>
|
||||
_walletType == WalletType.monero || _walletType == WalletType.haven;
|
||||
|
||||
String get uri {
|
||||
var uri = address;
|
||||
|
||||
if (port.isNotEmpty) {
|
||||
uri += ':' + port;
|
||||
}
|
||||
|
||||
return uri;
|
||||
}
|
||||
|
||||
final WalletType _walletType;
|
||||
final Box<Node> _nodeSource;
|
||||
final SettingsStore _settingsStore;
|
||||
|
||||
@action
|
||||
void reset() {
|
||||
address = '';
|
||||
port = '';
|
||||
login = '';
|
||||
password = '';
|
||||
useSSL = false;
|
||||
trusted = false;
|
||||
useSocksProxy = false;
|
||||
socksProxyAddress = '';
|
||||
}
|
||||
|
||||
@action
|
||||
void setPort(String val) => port = val;
|
||||
|
||||
@action
|
||||
void setAddress(String val) => address = val;
|
||||
|
||||
@action
|
||||
void setLogin(String val) => login = val;
|
||||
|
||||
@action
|
||||
void setPassword(String val) => password = val;
|
||||
|
||||
@action
|
||||
void setSSL(bool val) => useSSL = val;
|
||||
|
||||
@action
|
||||
void setTrusted(bool val) => trusted = val;
|
||||
|
||||
@action
|
||||
void setSocksProxy(bool val) => useSocksProxy = val;
|
||||
|
||||
@action
|
||||
void setSocksProxyAddress(String val) => socksProxyAddress = val;
|
||||
|
||||
@action
|
||||
Future<void> save({Node? editingNode, bool saveAsCurrent = false}) async {
|
||||
final node = Node(
|
||||
uri: uri,
|
||||
type: _walletType,
|
||||
login: login,
|
||||
password: password,
|
||||
useSSL: useSSL,
|
||||
trusted: trusted,
|
||||
socksProxyAddress: socksProxyAddress);
|
||||
try {
|
||||
state = IsExecutingState();
|
||||
if (editingNode != null) {
|
||||
await _nodeSource.put(editingNode.key, node);
|
||||
} else if (_existingNode(node) != null) {
|
||||
setAsCurrent(_existingNode(node)!);
|
||||
} else {
|
||||
await _nodeSource.add(node);
|
||||
setAsCurrent(_nodeSource.values.last);
|
||||
}
|
||||
if (saveAsCurrent) {
|
||||
setAsCurrent(node);
|
||||
}
|
||||
|
||||
state = ExecutedSuccessfullyState();
|
||||
} catch (e) {
|
||||
state = FailureState(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
Future<void> connect() async {
|
||||
final node = Node(
|
||||
uri: uri,
|
||||
type: _walletType,
|
||||
login: login,
|
||||
password: password,
|
||||
useSSL: useSSL,
|
||||
trusted: trusted,
|
||||
socksProxyAddress: socksProxyAddress);
|
||||
try {
|
||||
connectionState = IsExecutingState();
|
||||
final isAlive = await node.requestNode();
|
||||
connectionState = ExecutedSuccessfullyState(payload: isAlive);
|
||||
} catch (e) {
|
||||
connectionState = FailureState(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
Node? _existingNode(Node node) {
|
||||
final nodes = _nodeSource.values.toList();
|
||||
nodes.forEach((item) {
|
||||
item.login ??= '';
|
||||
item.password ??= '';
|
||||
item.useSSL ??= false;
|
||||
});
|
||||
return nodes.firstWhereOrNull((item) => item == node);
|
||||
}
|
||||
|
||||
@action
|
||||
void setAsCurrent(Node node) => _settingsStore.powNodes[_walletType] = node;
|
||||
|
||||
@action
|
||||
Future<void> scanQRCodeForNewNode() async {
|
||||
try {
|
||||
String code = await presentQRScanner();
|
||||
|
||||
if (code.isEmpty) {
|
||||
throw Exception('Unexpected scan QR code value: value is empty');
|
||||
}
|
||||
|
||||
final uri = Uri.tryParse(code);
|
||||
|
||||
if (uri == null) {
|
||||
throw Exception('Unexpected scan QR code value: Value is invalid');
|
||||
}
|
||||
|
||||
final userInfo = uri.userInfo.split(':');
|
||||
|
||||
if (userInfo.length < 2) {
|
||||
throw Exception('Unexpected scan QR code value: Value is invalid');
|
||||
}
|
||||
|
||||
final rpcUser = userInfo[0];
|
||||
final rpcPassword = userInfo[1];
|
||||
final ipAddress = uri.host;
|
||||
final port = uri.port.toString();
|
||||
|
||||
setAddress(ipAddress);
|
||||
setPassword(rpcPassword);
|
||||
setLogin(rpcUser);
|
||||
setPort(port);
|
||||
} on Exception catch (e) {
|
||||
connectionState = FailureState(e.toString());
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue