CW-224-Allow-Monero-proxy-in-node-settings (#966)

* update setupNodeSync func

* minor fixes

* localization

* add request node with proxy

* formatting
This commit is contained in:
Serhii 2023-08-02 14:48:52 +03:00 committed by GitHub
parent fcf4fbdc14
commit d5c0012964
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
38 changed files with 180 additions and 27 deletions

View file

@ -18,6 +18,7 @@ class Node extends HiveObject with Keyable {
this.password,
this.useSSL,
this.trusted = false,
this.socksProxyAddress,
String? uri,
WalletType? type,}) {
if (uri != null) {
@ -33,7 +34,8 @@ class Node extends HiveObject with Keyable {
login = map['login'] as String?,
password = map['password'] as String?,
useSSL = map['useSSL'] as bool?,
trusted = map['trusted'] as bool? ?? false;
trusted = map['trusted'] as bool? ?? false,
socksProxyAddress = map['socksProxyPort'] as String?;
static const typeId = 1;
static const boxName = 'Nodes';
@ -56,8 +58,13 @@ class Node extends HiveObject with Keyable {
@HiveField(5, defaultValue: false)
bool trusted;
@HiveField(6)
String? socksProxyAddress;
bool get isSSL => useSSL ?? false;
bool get useSocksProxy => socksProxyAddress == null ? false : socksProxyAddress!.isNotEmpty;
Uri get uri {
switch (type) {
case WalletType.monero:
@ -81,7 +88,8 @@ class Node extends HiveObject with Keyable {
other.password == password &&
other.typeRaw == typeRaw &&
other.useSSL == useSSL &&
other.trusted == trusted);
other.trusted == trusted &&
other.socksProxyAddress == socksProxyAddress);
@override
int get hashCode =>
@ -90,7 +98,8 @@ class Node extends HiveObject with Keyable {
password.hashCode ^
typeRaw.hashCode ^
useSSL.hashCode ^
trusted.hashCode;
trusted.hashCode ^
socksProxyAddress.hashCode;
@override
dynamic get keyIndex {
@ -108,7 +117,7 @@ class Node extends HiveObject with Keyable {
try {
switch (type) {
case WalletType.monero:
return requestMoneroNode();
return useSocksProxy ? requestNodeWithProxy(socksProxyAddress ?? '') : requestMoneroNode();
case WalletType.bitcoin:
return requestElectrumServer();
case WalletType.litecoin:
@ -159,6 +168,22 @@ class Node extends HiveObject with Keyable {
}
}
Future<bool> requestNodeWithProxy(String proxy) async {
if (proxy.isEmpty || !proxy.contains(':')) {
return false;
}
final proxyAddress = proxy.split(':')[0];
final proxyPort = int.parse(proxy.split(':')[1]);
try {
final socket = await Socket.connect(proxyAddress, proxyPort, timeout: Duration(seconds: 5));
socket.destroy();
return true;
} catch (_) {
return false;
}
}
Future<bool> requestElectrumServer() async {
try {
await SecureSocket.connect(uri.host, uri.port,

View file

@ -39,7 +39,7 @@ typedef get_node_height = Int64 Function();
typedef is_connected = Int8 Function();
typedef setup_node = Int8 Function(
Pointer<Utf8>, Pointer<Utf8>?, Pointer<Utf8>?, Int8, Int8, Pointer<Utf8>);
Pointer<Utf8>, Pointer<Utf8>?, Pointer<Utf8>?, Int8, Int8, Pointer<Utf8>?, Pointer<Utf8>);
typedef start_refresh = Void Function();

View file

@ -39,7 +39,7 @@ typedef GetNodeHeight = int Function();
typedef IsConnected = int Function();
typedef SetupNode = int Function(
Pointer<Utf8>, Pointer<Utf8>?, Pointer<Utf8>?, int, int, Pointer<Utf8>);
Pointer<Utf8>, Pointer<Utf8>?, Pointer<Utf8>?, int, int, Pointer<Utf8>?, Pointer<Utf8>);
typedef StartRefresh = void Function();

View file

@ -154,9 +154,11 @@ bool setupNodeSync(
String? login,
String? password,
bool useSSL = false,
bool isLightWallet = false}) {
bool isLightWallet = false,
String? socksProxyAddress}) {
final addressPointer = address.toNativeUtf8();
Pointer<Utf8>? loginPointer;
Pointer<Utf8>? socksProxyAddressPointer;
Pointer<Utf8>? passwordPointer;
if (login != null) {
@ -167,6 +169,10 @@ bool setupNodeSync(
passwordPointer = password.toNativeUtf8();
}
if (socksProxyAddress != null) {
socksProxyAddressPointer = socksProxyAddress.toNativeUtf8();
}
final errorMessagePointer = ''.toNativeUtf8();
final isSetupNode = setupNodeNative(
addressPointer,
@ -174,6 +180,7 @@ bool setupNodeSync(
passwordPointer,
_boolToInt(useSSL),
_boolToInt(isLightWallet),
socksProxyAddressPointer,
errorMessagePointer) !=
0;
@ -323,13 +330,15 @@ bool _setupNodeSync(Map args) {
final password = (args['password'] ?? '') as String;
final useSSL = args['useSSL'] as bool;
final isLightWallet = args['isLightWallet'] as bool;
final socksProxyAddress = (args['socksProxyAddress'] ?? '') as String;
return setupNodeSync(
address: address,
login: login,
password: password,
useSSL: useSSL,
isLightWallet: isLightWallet);
isLightWallet: isLightWallet,
socksProxyAddress: socksProxyAddress);
}
bool _isConnected(Object _) => isConnectedSync();
@ -343,13 +352,15 @@ Future<void> setupNode(
String? login,
String? password,
bool useSSL = false,
String? socksProxyAddress,
bool isLightWallet = false}) =>
compute<Map<String, Object?>, void>(_setupNodeSync, {
'address': address,
'login': login,
'password': password,
'useSSL': useSSL,
'isLightWallet': isLightWallet
'isLightWallet': isLightWallet,
'socksProxyAddress': socksProxyAddress
});
Future<void> store() => compute<int, void>(_storeSync, 0);

View file

@ -125,7 +125,8 @@ abstract class HavenWalletBase extends WalletBase<MoneroBalance,
login: node.login,
password: node.password,
useSSL: node.useSSL ?? false,
isLightWallet: false); // FIXME: hardcoded value
isLightWallet: false, // FIXME: hardcoded value
socksProxyAddress: node.socksProxyAddress);
haven_wallet.setTrustedDaemon(node.trusted);
syncStatus = ConnectedSyncStatus();

View file

@ -3,6 +3,7 @@
#include <chrono>
#include <functional>
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <mutex>
#include "thread"
@ -405,13 +406,14 @@ extern "C"
return is_connected;
}
bool setup_node(char *address, char *login, char *password, bool use_ssl, bool is_light_wallet, char *error)
bool setup_node(char *address, char *login, char *password, bool use_ssl, bool is_light_wallet, char *socksProxyAddress, char *error)
{
nice(19);
Monero::Wallet *wallet = get_current_wallet();
std::string _login = "";
std::string _password = "";
std::string _socksProxyAddress = "";
if (login != nullptr)
{
@ -423,7 +425,12 @@ extern "C"
_password = std::string(password);
}
bool inited = wallet->init(std::string(address), 0, _login, _password, use_ssl, is_light_wallet);
if (socksProxyAddress != nullptr)
{
_socksProxyAddress = std::string(socksProxyAddress);
}
bool inited = wallet->init(std::string(address), 0, _login, _password, use_ssl, is_light_wallet, _socksProxyAddress);
if (!inited)
{

View file

@ -35,7 +35,7 @@ typedef get_node_height = Int64 Function();
typedef is_connected = Int8 Function();
typedef setup_node = Int8 Function(
Pointer<Utf8>, Pointer<Utf8>?, Pointer<Utf8>?, Int8, Int8, Pointer<Utf8>);
Pointer<Utf8>, Pointer<Utf8>?, Pointer<Utf8>?, Int8, Int8, Pointer<Utf8>?, Pointer<Utf8>);
typedef start_refresh = Void Function();

View file

@ -35,7 +35,7 @@ typedef GetNodeHeight = int Function();
typedef IsConnected = int Function();
typedef SetupNode = int Function(
Pointer<Utf8>, Pointer<Utf8>?, Pointer<Utf8>?, int, int, Pointer<Utf8>);
Pointer<Utf8>, Pointer<Utf8>?, Pointer<Utf8>?, int, int, Pointer<Utf8>?, Pointer<Utf8>);
typedef StartRefresh = void Function();

View file

@ -158,9 +158,11 @@ bool setupNodeSync(
String? login,
String? password,
bool useSSL = false,
bool isLightWallet = false}) {
bool isLightWallet = false,
String? socksProxyAddress}) {
final addressPointer = address.toNativeUtf8();
Pointer<Utf8>? loginPointer;
Pointer<Utf8>? socksProxyAddressPointer;
Pointer<Utf8>? passwordPointer;
if (login != null) {
@ -171,6 +173,10 @@ bool setupNodeSync(
passwordPointer = password.toNativeUtf8();
}
if (socksProxyAddress != null) {
socksProxyAddressPointer = socksProxyAddress.toNativeUtf8();
}
final errorMessagePointer = ''.toNativeUtf8();
final isSetupNode = setupNodeNative(
addressPointer,
@ -178,6 +184,7 @@ bool setupNodeSync(
passwordPointer,
_boolToInt(useSSL),
_boolToInt(isLightWallet),
socksProxyAddressPointer,
errorMessagePointer) !=
0;
@ -328,13 +335,15 @@ bool _setupNodeSync(Map<String, Object?> args) {
final password = (args['password'] ?? '') as String;
final useSSL = args['useSSL'] as bool;
final isLightWallet = args['isLightWallet'] as bool;
final socksProxyAddress = (args['socksProxyAddress'] ?? '') as String;
return setupNodeSync(
address: address,
login: login,
password: password,
useSSL: useSSL,
isLightWallet: isLightWallet);
isLightWallet: isLightWallet,
socksProxyAddress: socksProxyAddress);
}
bool _isConnected(Object _) => isConnectedSync();
@ -348,13 +357,15 @@ Future<void> setupNode(
String? login,
String? password,
bool useSSL = false,
String? socksProxyAddress,
bool isLightWallet = false}) =>
compute<Map<String, Object?>, void>(_setupNodeSync, {
'address': address,
'login': login ,
'password': password,
'useSSL': useSSL,
'isLightWallet': isLightWallet
'isLightWallet': isLightWallet,
'socksProxyAddress': socksProxyAddress
});
Future<void> store() => compute<int, void>(_storeSync, 0);

View file

@ -138,7 +138,8 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
login: node.login,
password: node.password,
useSSL: node.isSSL,
isLightWallet: false); // FIXME: hardcoded value
isLightWallet: false, // FIXME: hardcoded value
socksProxyAddress: node.socksProxyAddress);
monero_wallet.setTrustedDaemon(node.trusted);
syncStatus = ConnectedSyncStatus();

View file

@ -0,0 +1,10 @@
import 'package:cake_wallet/core/validator.dart';
import 'package:cake_wallet/generated/i18n.dart';
class SocksProxyNodeAddressValidator extends TextValidator {
SocksProxyNodeAddressValidator()
: super(
errorMessage: S.current.error_text_node_proxy_address,
pattern:
'^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]+\$');
}

View file

@ -1,5 +1,6 @@
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';
@ -17,7 +18,8 @@ class NodeForm extends StatelessWidget {
}) : _addressController = TextEditingController(text: editingNode?.uri.host.toString()),
_portController = TextEditingController(text: editingNode?.uri.port.toString()),
_loginController = TextEditingController(text: editingNode?.login),
_passwordController = TextEditingController(text: editingNode?.password) {
_passwordController = TextEditingController(text: editingNode?.password),
_socksAddressController = TextEditingController(text: editingNode?.socksProxyAddress){
if (editingNode != null) {
nodeViewModel
..setAddress((editingNode!.uri.host.toString()))
@ -25,7 +27,9 @@ class NodeForm extends StatelessWidget {
..setPassword((editingNode!.password ?? ''))
..setLogin((editingNode!.login ?? ''))
..setSSL((editingNode!.isSSL))
..setTrusted((editingNode!.trusted));
..setTrusted((editingNode!.trusted))
..setSocksProxy((editingNode!.useSocksProxy))
..setSocksProxyAddress((editingNode!.socksProxyAddress ?? ''));
}
if (nodeViewModel.hasAuthCredentials) {
reaction((_) => nodeViewModel.login, (String login) {
@ -45,6 +49,7 @@ class NodeForm extends StatelessWidget {
_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 NodeCreateOrEditViewModel nodeViewModel;
@ -55,6 +60,7 @@ class NodeForm extends StatelessWidget {
final TextEditingController _portController;
final TextEditingController _loginController;
final TextEditingController _passwordController;
final TextEditingController _socksAddressController;
@override
Widget build(BuildContext context) {
@ -138,6 +144,43 @@ class NodeForm extends StatelessWidget {
],
),
),
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(),
))
],
),
]
],
)),
]
],
),

View file

@ -19,7 +19,9 @@ abstract class NodeCreateOrEditViewModelBase with Store {
port = '',
login = '',
password = '',
trusted = false;
trusted = false,
useSocksProxy = false,
socksProxyAddress = '';
@observable
ExecutionState state;
@ -45,6 +47,12 @@ abstract class NodeCreateOrEditViewModelBase with Store {
@observable
bool trusted;
@observable
bool useSocksProxy;
@observable
String socksProxyAddress;
@computed
bool get isReady => address.isNotEmpty && port.isNotEmpty;
@ -73,6 +81,8 @@ abstract class NodeCreateOrEditViewModelBase with Store {
password = '';
useSSL = false;
trusted = false;
useSocksProxy = false;
socksProxyAddress = '';
}
@action
@ -93,6 +103,12 @@ abstract class NodeCreateOrEditViewModelBase with Store {
@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(
@ -101,7 +117,8 @@ abstract class NodeCreateOrEditViewModelBase with Store {
login: login,
password: password,
useSSL: useSSL,
trusted: trusted);
trusted: trusted,
socksProxyAddress: socksProxyAddress);
try {
state = IsExecutingState();
if (editingNode != null) {
@ -130,7 +147,8 @@ abstract class NodeCreateOrEditViewModelBase with Store {
login: login,
password: password,
useSSL: useSSL,
trusted: trusted);
trusted: trusted,
socksProxyAddress: socksProxyAddress);
try {
connectionState = IsExecutingState();
final isAlive = await node.requestNode();

View file

@ -250,8 +250,8 @@
"transaction_details_recipient_address": "عناوين المستلم",
"wallet_list_title": "محفظة Monero",
"wallet_list_create_new_wallet": "إنشاء محفظة جديدة",
"wallet_list_edit_wallet" : "تحرير المحفظة",
"wallet_list_wallet_name" : "اسم المحفظة",
"wallet_list_edit_wallet" : "تحرير المحفظة",
"wallet_list_wallet_name" : "اسم المحفظة",
"wallet_list_restore_wallet": "استعادة المحفظة",
"wallet_list_load_wallet": "تحميل المحفظة",
"wallet_list_loading_wallet": "جار تحميل محفظة ${wallet_name}",
@ -269,6 +269,7 @@
"error_text_address": "يجب أن يتوافق عنوان المحفظة مع نوع\nالعملة المشفرة",
"error_text_node_address": "الرجاء إدخال عنوان IPv4",
"error_text_node_port": "منفذ العقدة يمكن أن يحتوي فقط على أرقام بين 0 و 65535",
"error_text_node_proxy_address": "الرجاء إدخال <عنوان IPv4>: <port> ، على سبيل المثال 127.0.0.1:9050",
"error_text_payment_id": "يمكن أن يحتوي معرّف الدفع فقط من 16 إلى 64 حرفًا hex",
"error_text_xmr": "لا يمكن أن تتجاوز قيمة XMR الرصيد المتاح.\nيجب أن يكون عدد الكسور أقل من أو يساوي 12",
"error_text_fiat": "لا يمكن أن تتجاوز قيمة المبلغ الرصيد المتاح.\nيجب أن يكون عدد الكسور أقل أو يساوي 2",

View file

@ -269,6 +269,7 @@
"error_text_address": "Адресът на портфейла трябва да отговаря \n на вида криптовалута",
"error_text_node_address": "Моля, въведете iPv4 адрес",
"error_text_node_port": "Node port-ът е цяло число между 0 и 65535",
"error_text_node_proxy_address": "Моля, въведете <IPv4 адрес>:<порт>, например 127.0.0.1:9050",
"error_text_payment_id": "Payment ID-то може да съдържа само между 16 и 64 шестнайсетични символа",
"error_text_xmr": "XMR сумата не може да надхвърля наличния баланс.\nБроят на цифрите след десетичната запетая може да бъде най-много 12",
"error_text_fiat": "Сумата не може да надвишава наличния баланс.\nThe number of fraction digits must be less or equal to 2",

View file

@ -269,6 +269,7 @@
"error_text_address": "Adresa peněženky musí odpovídat typu\nkryptoměny",
"error_text_node_address": "prosím zadejte IPv4 adresu",
"error_text_node_port": "Port uzlu musí být číslo mezi 0 a 65535",
"error_text_node_proxy_address": "Zadejte prosím <adresa IPv4>:<port>, například 127.0.0.1:9050",
"error_text_payment_id": "ID platby se musí skládat z 16 až 64 hexadecimálních znaků",
"error_text_xmr": "Hodnota XMR nemůže překročit dostupný zůstatek.\nPočet desetinných míst musí být menší, nebo roven 12",
"error_text_fiat": "Částka nemůže překročit dostupný zůstatek.\nPočet desetinných míst musí být menší, nebo roven 2",

View file

@ -269,6 +269,7 @@
"error_text_address": "Die Walletadresse muss dem Typ der Kryptowährung\nentsprechen",
"error_text_node_address": "Bitte geben Sie eine iPv4-Adresse ein",
"error_text_node_port": "Der Knotenport darf nur Nummern zwischen 0 und 65535 enthalten",
"error_text_node_proxy_address": "Bitte geben Sie <IPv4-Adresse>:<Port> ein, zum Beispiel 127.0.0.1:9050",
"error_text_payment_id": "Die Zahlungs-ID darf nur 16 bis 64 hexadezimale Zeichen enthalten",
"error_text_xmr": "Der XMR-Wert darf das verfügbare Guthaben nicht überschreiten.\nDie Anzahl der Nachkommastellen muss kleiner oder gleich 12 sein",
"error_text_fiat": "Der Wert des Betrags darf den verfügbaren Kontostand nicht überschreiten.\nDie Anzahl der Nachkommastellen muss kleiner oder gleich 2 sein",

View file

@ -269,6 +269,7 @@
"error_text_address": "Wallet address must correspond to the type\nof cryptocurrency",
"error_text_node_address": "Please enter a iPv4 address",
"error_text_node_port": "Node port can only contain numbers between 0 and 65535",
"error_text_node_proxy_address": "Please enter <IPv4 address>:<port>, for example 127.0.0.1:9050",
"error_text_payment_id": "Payment ID can only contain from 16 to 64 chars in hex",
"error_text_xmr": "XMR value can't exceed available balance.\nThe number of fraction digits must be less or equal to 12",
"error_text_fiat": "Value of amount can't exceed available balance.\nThe number of fraction digits must be less or equal to 2",

View file

@ -269,6 +269,7 @@
"error_text_address": "La dirección de la billetera debe corresponder al tipo \nde criptomoneda",
"error_text_node_address": "Por favor, introduzca una dirección iPv4",
"error_text_node_port": "El puerto de nodo solo puede contener números entre 0 y 65535",
"error_text_node_proxy_address": "Ingrese <dirección IPv4>:<puerto>, por ejemplo 127.0.0.1:9050",
"error_text_payment_id": "La ID de pago solo puede contener de 16 a 64 caracteres en hexadecimal",
"error_text_xmr": "El valor XMR no puede exceder el saldo disponible.\nTEl número de dígitos de fracción debe ser menor o igual a 12",
"error_text_fiat": "El valor de la cantidad no puede exceder el saldo disponible.\nEl número de dígitos de fracción debe ser menor o igual a 2",

View file

@ -269,6 +269,7 @@
"error_text_address": "L'adresse du portefeuille (wallet) doit correspondre au type de\ncryptomonnaie",
"error_text_node_address": "Merci d'entrer une adresse IPv4",
"error_text_node_port": "Le port d'un nœud doit être un nombre compris entre 0 et 65535",
"error_text_node_proxy_address": "Veuillez saisir <adresse IPv4> :<port>, par exemple 127.0.0.1:9050",
"error_text_payment_id": "Un ID de paiement ne peut être constitué que de 16 à 64 caractères hexadécimaux",
"error_text_xmr": "La valeur de XMR dépasse le solde disponible.\nLa partie décimale doit comporter au plus 12 chiffres",
"error_text_fiat": "La valeur du montant ne peut dépasser le solde disponible.\nLa partie décimale doit comporter au plus 2 chiffres",

View file

@ -269,6 +269,7 @@
"error_text_address": "Adireshin hujja ya kamata ya dace da irin\nna cryptocurrency",
"error_text_node_address": "Da fatan a shigar da iPv4 adireshin",
"error_text_node_port": "Node tashar jiragen ruwa zai iya ƙunsar lambobi tsakanin 0 zuwa 65535 kawai",
"error_text_node_proxy_address": "Da fatan za a shigar da <IPv4 address>:<port>, misali 127.0.0.1:9050",
"error_text_payment_id": "ID na biyan kudi kawai zai iya ɗaukar daga 16 zuwa 64 haruffa a cikin hex",
"error_text_xmr": "XMR adadin ba zai iya wuce available balance.\nAdadin haruffan gaba zai kamata ya zama ko ƙasa daga na 12",
"error_text_fiat": "Adadin kudin ba zai iya wuce available balance.\nAdadin haruffan gaba zai kamata ya zama ko ƙasa daga na 2",

View file

@ -269,6 +269,7 @@
"error_text_address": "वॉलेट पता प्रकार के अनुरूप होना चाहिए\nक्रिप्टोकरेंसी का",
"error_text_node_address": "कृपया एक IPv4 पता दर्ज करें",
"error_text_node_port": "नोड पोर्ट में केवल 0 और 65535 के बीच संख्याएँ हो सकती हैं",
"error_text_node_proxy_address": "कृपया <IPv4 पता> दर्ज करें: <पोर्ट>, उदाहरण के लिए 127.0.0.1:9050",
"error_text_payment_id": "पेमेंट आईडी केवल हेक्स में 16 से 64 चार्ट तक हो सकती है",
"error_text_xmr": "एक्सएमआर मूल्य उपलब्ध शेष राशि से अधिक नहीं हो सकता.\nअंश अंकों की संख्या 12 से कम या इसके बराबर होनी चाहिए",
"error_text_fiat": "राशि का मूल्य उपलब्ध शेष राशि से अधिक नहीं हो सकता.\nअंश अंकों की संख्या कम या 2 के बराबर होनी चाहिए",

View file

@ -269,6 +269,7 @@
"error_text_address": "Adresa novčanika mora odgovarati\nvrsti kriptovalute",
"error_text_node_address": "Molimo unesite iPv4 adresu",
"error_text_node_port": "Node port smije sadržavati samo brojeve između 0 i 65535",
"error_text_node_proxy_address": "Unesite <IPv4 adresa>:<port>, na primjer 127.0.0.1:9050",
"error_text_payment_id": "ID plaćanja smije sadržavati samo od 16 do 64 znakova hex vrijednosti",
"error_text_xmr": "XMR vrijednost ne smije biti veća od raspoloživog iznosa.\nBroj decimala smije biti 12 ili manji.",
"error_text_fiat": "Vrijednost iznosa ne smije biti veća od raspoloživog iznosa.\nBroj decimala smije biti 2 ili manji.",

View file

@ -269,6 +269,7 @@
"error_text_address": "Alamat dompet harus sesuai dengan tipe\nmata uang kripto",
"error_text_node_address": "Silakan masukkan alamat iPv4",
"error_text_node_port": "Port node hanya dapat berisi angka antara 0 dan 65535",
"error_text_node_proxy_address": "Masukkan <alamat IPv4>:<port>, misalnya 127.0.0.1:9050",
"error_text_payment_id": "ID pembayaran hanya dapat berisi dari 16 hingga 64 karakter dalam hex",
"error_text_xmr": "Nilai XMR tidak boleh melebihi saldo yang tersedia.\nJumlah digit pecahan harus kurang atau sama dengan 12",
"error_text_fiat": "Nilai jumlah tidak boleh melebihi saldo yang tersedia.\nJumlah digit pecahan harus kurang atau sama dengan 2",

View file

@ -269,6 +269,7 @@
"error_text_address": "L'indirizzo del Portafoglio deve corrispondere alla tipologia\ndi criptovaluta",
"error_text_node_address": "Gentilmente inserisci un indirizzo iPv4",
"error_text_node_port": "La porta del nodo può contenere solo numeri compresi tra 0 e 65535",
"error_text_node_proxy_address": "Inserisci <indirizzo IPv4>:<porta>, ad esempio 127.0.0.1:9050",
"error_text_payment_id": "L'ID del pagamento può contenere solo da 16 a 64 caratteri in esadecimale",
"error_text_xmr": "Il valore in XMR non può eccedere il saldo disponibile.\nIl numero delle cifre decimali deve essere inferiore o uguale a 12",
"error_text_fiat": "L'ammontare non può eccedere il saldo dispoinibile.\nIl numero di cifre decimali deve essere inferiore o uguale a 2",

View file

@ -269,6 +269,7 @@
"error_text_address": "ウォレットアドレスは、\n暗号通貨",
"error_text_node_address": "iPv4アドレスを入力してください",
"error_text_node_port": "ードポートには、0〜65535の数字のみを含めることができます",
"error_text_node_proxy_address": "<IPv4 アドレス>:<ポート> を入力してください (例: 127.0.0.1:9050)",
"error_text_payment_id": "支払いIDには、16進数で16〜64文字しか含めることができません",
"error_text_xmr": "XMR値は利用可能な残高を超えることはできません.\n小数桁数は12以下でなければなりません",
"error_text_fiat": "金額は利用可能な残高を超えることはできません.\n小数桁の数は2以下でなければなりません",

View file

@ -269,6 +269,7 @@
"error_text_address": "지갑 주소는 유형과 일치해야합니다\n암호 화폐",
"error_text_node_address": "iPv4 주소를 입력하십시오",
"error_text_node_port": "노드 포트는 0에서 65535 사이의 숫자 만 포함 할 수 있습니다",
"error_text_node_proxy_address": "<IPv4 주소>:<포트>를 입력하십시오(예: 127.0.0.1:9050).",
"error_text_payment_id": "지불 ID는 16 ~ 64 자의 16 진 문자 만 포함 할 수 있습니다",
"error_text_xmr": "XMR 값은 사용 가능한 잔액을 초과 할 수 없습니다.\n소수 자릿수는 12 이하 여야합니다",
"error_text_fiat": "금액은 사용 가능한 잔액을 초과 할 수 없습니다.\n소수 자릿수는 2보다 작거나 같아야합니다",

View file

@ -269,6 +269,7 @@
"error_text_address": "Wallet လိပ်စာသည် အမျိုးအစား\no cryptocurrency နှင့် ကိုက်ညီရပါမည်။",
"error_text_node_address": "ကျေးဇူးပြု၍ iPv4 လိပ်စာကို ထည့်ပါ။",
"error_text_node_port": "နော်ဒီဆိပ်ကမ်း တွင် 0 နှင့် 65535 အကြား နံပါတ်များသာ ပါဝင်နိုင်သည်။",
"error_text_node_proxy_address": "ကျေးဇူးပြု၍ <IPv4 လိပ်စာ>:<port>၊ ဥပမာ 127.0.0.1:9050 ထည့်ပါ",
"error_text_payment_id": "ငွေပေးချေမှု ID တွင် hex တွင် စာလုံး 16 လုံးမှ 64 လုံးသာ ပါဝင်နိုင်သည်။",
"error_text_xmr": "XMR တန်ဖိုးသည် ရနိုင်သောလက်ကျန်ကို ကျော်လွန်၍မရပါ။\nအပိုင်းကိန်းဂဏန်းများ သည် 12 နှင့် လျော့နည်းရမည်",
"error_text_fiat": "ပမာဏ၏တန်ဖိုးသည် ရနိုင်သောလက်ကျန်ကို မကျော်လွန်နိုင်ပါ။\nအပိုင်းကိန်းဂဏန်းအရေအတွက်သည် 2 နှင့် လျော့နည်းရမည်",

View file

@ -269,6 +269,7 @@
"error_text_address": "Portemonnee-adres moet overeenkomen met het type\nvan cryptocurrency",
"error_text_node_address": "Voer een iPv4-adres in",
"error_text_node_port": "Knooppuntpoort kan alleen nummers tussen 0 en 65535 bevatten",
"error_text_node_proxy_address": "Voer <IPv4-adres>:<poort> in, bijvoorbeeld 127.0.0.1:9050",
"error_text_payment_id": "Betalings-ID kan alleen 16 tot 64 tekens bevatten in hexadecimale volgorde",
"error_text_xmr": "XMR-waarde kan het beschikbare saldo niet overschrijden.\nHet aantal breukcijfers moet kleiner zijn dan of gelijk zijn aan 12",
"error_text_fiat": "Waarde van bedrag kan het beschikbare saldo niet overschrijden.\nHet aantal breukcijfers moet kleiner zijn dan of gelijk zijn aan 2",

View file

@ -269,6 +269,7 @@
"error_text_address": "Adres musi odpowiadać typowi kryptowaluty",
"error_text_node_address": "Wpisz adres iPv4",
"error_text_node_port": "Port węzła może zawierać tylko liczby od 0 do 65535",
"error_text_node_proxy_address": "Wprowadź <adres IPv4>:<port>, na przykład 127.0.0.1:9050",
"error_text_payment_id": "ID może zawierać od 16 do 64 znaków w formacie szesnastkowym",
"error_text_xmr": "Wartość XMR nie może przekraczać dostępnego salda.\nLiczba cyfr ułamkowych musi być mniejsza lub równa 12",
"error_text_fiat": "Wartość kwoty nie może przekroczyć dostępnego salda.\nLiczba cyfr ułamkowych musi być mniejsza lub równa 2",

View file

@ -269,6 +269,7 @@
"error_text_address": "O endereço da carteira deve corresponder à\ncriptomoeda selecionada",
"error_text_node_address": "Digite um endereço iPv4",
"error_text_node_port": "A porta do nó deve conter apenas números entre 0 e 65535",
"error_text_node_proxy_address": "Insira <endereço IPv4>:<porta>, por exemplo 127.0.0.1:9050",
"error_text_payment_id": "O ID de pagamento pode conter apenas de 16 a 64 caracteres em hexadecimal",
"error_text_xmr": "A quantia em XMR não pode exceder o saldo disponível.\nTO número de dígitos decimais deve ser menor ou igual a 12",
"error_text_fiat": "O valor do valor não pode exceder o saldo disponível.\nO número de dígitos decimais deve ser menor ou igual a 2",

View file

@ -269,6 +269,8 @@
"error_text_address": "Адрес кошелька должен соответствовать типу\nкриптовалюты",
"error_text_node_address": "Пожалуйста, введите iPv4 адрес",
"error_text_node_port": "Порт ноды может содержать только цифры от 0 до 65535",
"error_text_node_proxy_address": "Введите <IPv4-адрес>:<порт>, например 127.0.0.1:9050.",
"error_text_payment_id": "Идентификатор платежа может содержать от 16 до 64 символов в hex",
"error_text_xmr": "Значение XMR не может превышать доступный баланс.\nКоличество цифр после запятой должно быть меньше или равно 12",
"error_text_fiat": "Значение суммы не может превышать доступный баланс.\nКоличество цифр после запятой должно быть меньше или равно 2",

View file

@ -269,6 +269,7 @@
"error_text_address": "ที่อยู่กระเป๋าจะต้องสอดคล้องกับประเภท\nของเหรียญคริปโตเนียม",
"error_text_node_address": "โปรดป้อนที่อยู่ iPv4",
"error_text_node_port": "พอร์ตโหนดสามารถมีตัวเลขเท่านั้นระหว่าง 0 ถึง 65535",
"error_text_node_proxy_address": "โปรดป้อน <ที่อยู่ IPv4>:<พอร์ต> เช่น 127.0.0.1:9050",
"error_text_payment_id": "Payment ID สามารถมีขนาดระหว่าง 16 ถึง 64 ตัวอักษรตามแบบ hex",
"error_text_xmr": "มูลค่า XMR ไม่สามารถเกินยอดคงเหลือได้\nจำนวนสตริงทศนิยมต้องน้อยกว่าหรือเท่ากับ 12",
"error_text_fiat": "มูลค่าของจำนวนเงินไม่สามารถเกินยอดคงเหลือได้\nจำนวนสตริงทศนิยมต้องน้อยกว่าหรือเท่ากับ 2",

View file

@ -269,6 +269,7 @@
"error_text_address": "Cüzdan adresi kripto para biriminin\ntürüne karşılık gelmelidir",
"error_text_node_address": "Lütfen iPv4 adresi girin",
"error_text_node_port": "Düğüm port'u yalnızca 0 ve 65535 arasında rakam içerebilir",
"error_text_node_proxy_address": "Lütfen <IPv4 adresi>:<bağlantı noktası> girin, örneğin 127.0.0.1:9050",
"error_text_payment_id": "Ödeme ID'si yalnızca onaltılık (hex) olarak 16 veya 64 karakter içerebilir",
"error_text_xmr": "XMR miktarı kullanılabilir bakiyeyi aşamaz.\nKesir basamaklarının sayısı 12'ye eşit veya daha az olmalıdır",
"error_text_fiat": "Tutarın değeri, mevcut bakiyeyi aşamaz.\nKesir basamaklarının sayısı 2'ye eşit veya daha az olmalıdır",

View file

@ -269,6 +269,7 @@
"error_text_address": "Адреса гаманця повинна відповідати типу\nкриптовалюти",
"error_text_node_address": "Будь ласка, введіть iPv4 адресу",
"error_text_node_port": "Порт вузла може містити тільки цифри від 0 до 65535",
"error_text_node_proxy_address": "Будь ласка, введіть <IPv4-адреса>:<порт>, наприклад 127.0.0.1:9050",
"error_text_payment_id": "Ідентифікатор платежу може містити від 16 до 64 символів в hex",
"error_text_xmr": "Значення XMR не може перевищувати доступний баланс.\nКількість цифр після коми повинно бути меншим або дорівнювати 12",
"error_text_fiat": "Значення суми не може перевищувати доступний баланс.\nКількість цифр після коми повинно бути меншим або дорівнювати 2",

View file

@ -269,6 +269,7 @@
"error_text_address": "والیٹ کا پتہ cryptocurrency کی قسم\\nکے مطابق ہونا چاہیے۔",
"error_text_node_address": "براہ کرم ایک iPv4 پتہ درج کریں۔",
"error_text_node_port": "نوڈ پورٹ میں صرف 0 اور 65535 کے درمیان نمبر ہوسکتے ہیں۔",
"error_text_node_proxy_address": "براہ کرم <IPv4 ایڈریس>:<port> درج کریں، مثال کے طور پر 127.0.0.1:9050",
"error_text_payment_id": "ادائیگی کی ID ہیکس میں صرف 16 سے 64 حروف پر مشتمل ہو سکتی ہے۔",
"error_text_xmr": "XMR قدر دستیاب بیلنس سے زیادہ نہیں ہو سکتی۔\\nفرکشن ہندسوں کی تعداد 12 سے کم یا اس کے برابر ہونی چاہیے۔",
"error_text_fiat": "رقم کی قدر دستیاب بیلنس سے زیادہ نہیں ہو سکتی۔\\nفرکشن ہندسوں کی تعداد 2 کے برابر یا کم ہونی چاہیے۔",

View file

@ -250,8 +250,8 @@
"transaction_details_recipient_address": "Àwọn àdírẹ́sì olùgbà",
"wallet_list_title": "Àpamọ́wọ́ Monero",
"wallet_list_create_new_wallet": "Ṣe àpamọ́wọ́ títun",
"wallet_list_edit_wallet" : "Ṣatunkọ apamọwọ",
"wallet_list_wallet_name" : "Orukọ apamọwọ",
"wallet_list_edit_wallet" : "Ṣatunkọ apamọwọ",
"wallet_list_wallet_name" : "Orukọ apamọwọ",
"wallet_list_restore_wallet": "Restore àpamọ́wọ́",
"wallet_list_load_wallet": "Load àpamọ́wọ́",
"wallet_list_loading_wallet": "Ń ṣí àpamọ́wọ́ ${wallet_name}",
@ -269,6 +269,7 @@
"error_text_address": "Àdírẹ́sì àpamọ́wọ́ gbọ́dọ̀ báramu irú owó",
"error_text_node_address": "Ẹ jọ̀wọ́ tẹ̀ àdírẹ́sì iPv4",
"error_text_node_port": "Ojú ìkànpọ̀ apẹka lè ni nìkan nínú òǹkà l'áàárín òdo àti márùn-úndínlógojí lé ní ẹ̀ẹ́dẹgbẹ̀ta lé ní ọ̀kẹ́ mẹ́ta lé ní ẹ̀ẹ́dẹ́gbàta",
"error_text_node_proxy_address": "Jọwọ tẹ <IPv4 adirẹsi>:<port>, fun apẹẹrẹ 127.0.0.1:9050",
"error_text_payment_id": "Iye ẹyọ ọ̀rọ̀ nínú àmì ìdánimọ̀ àránṣẹ́ gbọ́dọ̀ wà l'áàárín aárùndínlógún dé ẹẹ́rinlélọ́gọ́ta.",
"error_text_xmr": "Iye XMR kò lè tóbi ju ìyókù.\nIye díjíìtì léyìn ẹsẹ kò gbọ́dọ̀ tóbi ju eéjìlá.",
"error_text_fiat": "Iye àránṣẹ́ kò tóbi ju ìyókù owó.\nIye díjíìtì léyìn ẹsẹ kò gbọ́dọ̀ tóbi ju eéjì.",

View file

@ -269,6 +269,7 @@
"error_text_address": "钱包地址必须与类型对应\n加密货币",
"error_text_node_address": "请输入一个IPv4地址",
"error_text_node_port": "节点端口只能包含0到65535之间的数字",
"error_text_node_proxy_address": "请输入<IPv4地址>:<端口>例如127.0.0.1:9050",
"error_text_payment_id": "付款ID只能包含16到64个字符十六进制",
"error_text_xmr": "XMR值不能超过可用余额.\n小数位数必须小于或等于12",
"error_text_fiat": "金额不能超过可用余额.\n小数位数必须小于或等于2",