wallet + ui: external connection API token support, update translations
This commit is contained in:
parent
08c202519e
commit
cf834f86fc
6 changed files with 158 additions and 40 deletions
|
@ -21,7 +21,9 @@ wallets:
|
||||||
setup_conn_desc: Choose how your wallet connects to the network.
|
setup_conn_desc: Choose how your wallet connects to the network.
|
||||||
conn_method: Connection method
|
conn_method: Connection method
|
||||||
ext_conn: 'External connections:'
|
ext_conn: 'External connections:'
|
||||||
add_node_url: Add node URL
|
add_node: Add node
|
||||||
|
node_url: 'Node URL:'
|
||||||
|
node_secret: 'API Secret (optional):'
|
||||||
invalid_url: Entered URL is invalid
|
invalid_url: Entered URL is invalid
|
||||||
open: Open the wallet
|
open: Open the wallet
|
||||||
wrong_pass: Entered password is wrong
|
wrong_pass: Entered password is wrong
|
||||||
|
|
|
@ -21,7 +21,9 @@ wallets:
|
||||||
setup_conn_desc: Выберите способ подключения вашего кошелька к сети.
|
setup_conn_desc: Выберите способ подключения вашего кошелька к сети.
|
||||||
conn_method: Способ подключения
|
conn_method: Способ подключения
|
||||||
ext_conn: 'Внешние подключения:'
|
ext_conn: 'Внешние подключения:'
|
||||||
add_node_url: Добавить URL узла
|
add_node: Добавить узел
|
||||||
|
node_url: 'URL узла:'
|
||||||
|
node_secret: 'API токен (необязательно):'
|
||||||
invalid_url: Введенный URL-адрес недействителен
|
invalid_url: Введенный URL-адрес недействителен
|
||||||
open: Открыть кошелёк
|
open: Открыть кошелёк
|
||||||
wrong_pass: Введён неправильный пароль
|
wrong_pass: Введён неправильный пароль
|
||||||
|
|
|
@ -19,16 +19,21 @@ use crate::AppConfig;
|
||||||
use crate::gui::Colors;
|
use crate::gui::Colors;
|
||||||
use crate::gui::icons::{GLOBE, GLOBE_SIMPLE};
|
use crate::gui::icons::{GLOBE, GLOBE_SIMPLE};
|
||||||
use crate::gui::platform::PlatformCallbacks;
|
use crate::gui::platform::PlatformCallbacks;
|
||||||
use crate::gui::views::{Modal, View};
|
use crate::gui::views::{Modal, ModalPosition, View};
|
||||||
use crate::gui::views::wallets::setup::ConnectionMethod;
|
use crate::gui::views::wallets::setup::ConnectionMethod;
|
||||||
|
use crate::wallet::ExternalConnection;
|
||||||
|
|
||||||
/// Wallet node connection method setup content.
|
/// Wallet node connection method setup content.
|
||||||
pub struct ConnectionSetup {
|
pub struct ConnectionSetup {
|
||||||
/// Selected connection method.
|
/// Selected connection method.
|
||||||
method: ConnectionMethod,
|
method: ConnectionMethod,
|
||||||
|
|
||||||
|
/// Flag to check if modal was just opened.
|
||||||
|
first_modal_launch: bool,
|
||||||
/// External node connection URL value for [`Modal`].
|
/// External node connection URL value for [`Modal`].
|
||||||
ext_node_url_edit: String,
|
ext_node_url_edit: String,
|
||||||
|
/// External node connection API secret value for [`Modal`].
|
||||||
|
ext_node_secret_edit: String,
|
||||||
/// Flag to show URL format error.
|
/// Flag to show URL format error.
|
||||||
ext_node_url_error: bool,
|
ext_node_url_error: bool,
|
||||||
}
|
}
|
||||||
|
@ -37,7 +42,9 @@ impl Default for ConnectionSetup {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
method: ConnectionMethod::Integrated,
|
method: ConnectionMethod::Integrated,
|
||||||
|
first_modal_launch: true,
|
||||||
ext_node_url_edit: "".to_string(),
|
ext_node_url_edit: "".to_string(),
|
||||||
|
ext_node_secret_edit: "".to_string(),
|
||||||
ext_node_url_error: false
|
ext_node_url_error: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,25 +89,28 @@ impl ConnectionSetup {
|
||||||
ui.add_space(6.0);
|
ui.add_space(6.0);
|
||||||
|
|
||||||
// Show button to add new external node connection.
|
// Show button to add new external node connection.
|
||||||
let add_node_text = format!("{} {}", GLOBE_SIMPLE, t!("wallets.add_node_url"));
|
let add_node_text = format!("{} {}", GLOBE_SIMPLE, t!("wallets.add_node"));
|
||||||
View::button(ui, add_node_text, Colors::GOLD, || {
|
View::button(ui, add_node_text, Colors::GOLD, || {
|
||||||
// Setup values for Modal.
|
// Setup values for Modal.
|
||||||
|
self.first_modal_launch = true;
|
||||||
self.ext_node_url_edit = "".to_string();
|
self.ext_node_url_edit = "".to_string();
|
||||||
|
self.ext_node_secret_edit = "".to_string();
|
||||||
self.ext_node_url_error = false;
|
self.ext_node_url_error = false;
|
||||||
// Show modal.
|
// Show modal.
|
||||||
Modal::new(Self::ADD_CONNECTION_URL_MODAL)
|
Modal::new(Self::ADD_CONNECTION_URL_MODAL)
|
||||||
.title(t!("wallets.ext_conn"))
|
.position(ModalPosition::CenterTop)
|
||||||
|
.title(t!("wallets.add_node"))
|
||||||
.show();
|
.show();
|
||||||
cb.show_keyboard();
|
cb.show_keyboard();
|
||||||
});
|
});
|
||||||
ui.add_space(12.0);
|
ui.add_space(12.0);
|
||||||
|
|
||||||
// Show external nodes URLs selection.
|
// Show external nodes URLs selection.
|
||||||
for conn in AppConfig::external_nodes_urls() {
|
for conn in AppConfig::external_connections() {
|
||||||
View::radio_value(ui,
|
View::radio_value(ui,
|
||||||
&mut self.method,
|
&mut self.method,
|
||||||
ConnectionMethod::External(conn.clone()),
|
ConnectionMethod::External(conn.url.clone()),
|
||||||
conn);
|
conn.url);
|
||||||
ui.add_space(12.0);
|
ui.add_space(12.0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -111,15 +121,41 @@ impl ConnectionSetup {
|
||||||
pub fn modal_ui(&mut self, ui: &mut egui::Ui, modal: &Modal, cb: &dyn PlatformCallbacks) {
|
pub fn modal_ui(&mut self, ui: &mut egui::Ui, modal: &Modal, cb: &dyn PlatformCallbacks) {
|
||||||
ui.add_space(6.0);
|
ui.add_space(6.0);
|
||||||
ui.vertical_centered(|ui| {
|
ui.vertical_centered(|ui| {
|
||||||
// Draw external node URL text edit.
|
ui.label(RichText::new(t!("wallets.node_url"))
|
||||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.ext_node_url_edit)
|
.size(17.0)
|
||||||
.id(Id::from(modal.id))
|
.color(Colors::GRAY));
|
||||||
|
ui.add_space(8.0);
|
||||||
|
|
||||||
|
// Draw node URL text edit.
|
||||||
|
let url_edit_resp = egui::TextEdit::singleline(&mut self.ext_node_url_edit)
|
||||||
|
.id(Id::from(modal.id).with("node_url_edit"))
|
||||||
.font(TextStyle::Heading)
|
.font(TextStyle::Heading)
|
||||||
.desired_width(ui.available_width())
|
.desired_width(ui.available_width())
|
||||||
.cursor_at_end(true)
|
.cursor_at_end(true)
|
||||||
.ui(ui);
|
.ui(ui);
|
||||||
text_edit_resp.request_focus();
|
ui.add_space(8.0);
|
||||||
if text_edit_resp.clicked() {
|
if self.first_modal_launch {
|
||||||
|
self.first_modal_launch = false;
|
||||||
|
url_edit_resp.request_focus();
|
||||||
|
}
|
||||||
|
if url_edit_resp.clicked() {
|
||||||
|
cb.show_keyboard();
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.label(RichText::new(t!("wallets.node_secret"))
|
||||||
|
.size(17.0)
|
||||||
|
.color(Colors::GRAY));
|
||||||
|
ui.add_space(8.0);
|
||||||
|
|
||||||
|
// Draw node API secret text edit.
|
||||||
|
let secret_edit_resp = egui::TextEdit::singleline(&mut self.ext_node_secret_edit)
|
||||||
|
.id(Id::from(modal.id).with("node_secret_edit"))
|
||||||
|
.font(TextStyle::Heading)
|
||||||
|
.desired_width(ui.available_width())
|
||||||
|
.cursor_at_end(true)
|
||||||
|
.ui(ui);
|
||||||
|
ui.add_space(8.0);
|
||||||
|
if secret_edit_resp.clicked() {
|
||||||
cb.show_keyboard();
|
cb.show_keyboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,18 +174,6 @@ impl ConnectionSetup {
|
||||||
// Setup spacing between buttons.
|
// Setup spacing between buttons.
|
||||||
ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0);
|
ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0);
|
||||||
|
|
||||||
// Add button callback.
|
|
||||||
let on_add = || {
|
|
||||||
let error = Url::parse(self.ext_node_url_edit.as_str()).is_err();
|
|
||||||
self.ext_node_url_error = error;
|
|
||||||
if !error {
|
|
||||||
AppConfig::add_external_node_url(self.ext_node_url_edit.clone());
|
|
||||||
// Close modal.
|
|
||||||
cb.hide_keyboard();
|
|
||||||
modal.close();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ui.columns(2, |columns| {
|
ui.columns(2, |columns| {
|
||||||
columns[0].vertical_centered_justified(|ui| {
|
columns[0].vertical_centered_justified(|ui| {
|
||||||
View::button(ui, t!("modal.cancel"), Colors::WHITE, || {
|
View::button(ui, t!("modal.cancel"), Colors::WHITE, || {
|
||||||
|
@ -159,6 +183,35 @@ impl ConnectionSetup {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
columns[1].vertical_centered_justified(|ui| {
|
columns[1].vertical_centered_justified(|ui| {
|
||||||
|
// Add connection button callback.
|
||||||
|
let mut on_add = || {
|
||||||
|
let error = Url::parse(self.ext_node_url_edit.as_str()).is_err();
|
||||||
|
self.ext_node_url_error = error;
|
||||||
|
if !error {
|
||||||
|
// Save external connection.
|
||||||
|
let url = self.ext_node_url_edit.to_owned();
|
||||||
|
let secret = if self.ext_node_secret_edit.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(self.ext_node_secret_edit.to_owned())
|
||||||
|
};
|
||||||
|
let ext_conn = ExternalConnection::new(url.clone(), secret);
|
||||||
|
AppConfig::add_external_connection(ext_conn);
|
||||||
|
|
||||||
|
// Set added method as current.
|
||||||
|
self.method = ConnectionMethod::External(url);
|
||||||
|
|
||||||
|
// Close modal.
|
||||||
|
cb.hide_keyboard();
|
||||||
|
modal.close();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add connection on Enter button press.
|
||||||
|
View::on_enter_key(ui, || {
|
||||||
|
(on_add)();
|
||||||
|
});
|
||||||
|
|
||||||
View::button(ui, t!("modal.add"), Colors::WHITE, on_add);
|
View::button(ui, t!("modal.add"), Colors::WHITE, on_add);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -24,7 +24,7 @@ use serde::{Deserialize, Serialize};
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
|
|
||||||
use crate::node::NodeConfig;
|
use crate::node::NodeConfig;
|
||||||
use crate::wallet::Wallets;
|
use crate::wallet::{ExternalConnection, Wallets};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
/// Static settings state to be accessible globally.
|
/// Static settings state to be accessible globally.
|
||||||
|
@ -34,9 +34,6 @@ lazy_static! {
|
||||||
/// Application configuration file name.
|
/// Application configuration file name.
|
||||||
const APP_CONFIG_FILE_NAME: &'static str = "app.toml";
|
const APP_CONFIG_FILE_NAME: &'static str = "app.toml";
|
||||||
|
|
||||||
/// Default external node URL.
|
|
||||||
const DEFAULT_EXTERNAL_NODE_URL: &'static str = "https://grinnnode.live:3413";
|
|
||||||
|
|
||||||
/// Common application settings.
|
/// Common application settings.
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct AppConfig {
|
pub struct AppConfig {
|
||||||
|
@ -44,8 +41,8 @@ pub struct AppConfig {
|
||||||
pub auto_start_node: bool,
|
pub auto_start_node: bool,
|
||||||
/// Chain type for node and wallets.
|
/// Chain type for node and wallets.
|
||||||
chain_type: ChainTypes,
|
chain_type: ChainTypes,
|
||||||
/// URLs of external nodes for wallets.
|
/// URLs of external connections for wallets.
|
||||||
external_nodes_urls: Vec<String>
|
external_connections: Vec<ExternalConnection>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for AppConfig {
|
impl Default for AppConfig {
|
||||||
|
@ -53,8 +50,8 @@ impl Default for AppConfig {
|
||||||
Self {
|
Self {
|
||||||
auto_start_node: false,
|
auto_start_node: false,
|
||||||
chain_type: ChainTypes::default(),
|
chain_type: ChainTypes::default(),
|
||||||
external_nodes_urls: vec![
|
external_connections: vec![
|
||||||
DEFAULT_EXTERNAL_NODE_URL.to_string()
|
ExternalConnection::default()
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,19 +118,41 @@ impl AppConfig {
|
||||||
w_app_config.save();
|
w_app_config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get external nodes URLs.
|
/// Get external connections for the wallet.
|
||||||
pub fn external_nodes_urls() -> Vec<String> {
|
pub fn external_connections() -> Vec<ExternalConnection> {
|
||||||
let r_config = Settings::app_config_to_read();
|
let r_config = Settings::app_config_to_read();
|
||||||
r_config.external_nodes_urls.clone()
|
r_config.external_connections.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add external node URL.
|
/// Save external connection for the wallet in app config.
|
||||||
pub fn add_external_node_url(address: String) {
|
pub fn add_external_connection(conn: ExternalConnection) {
|
||||||
let mut w_config = Settings::app_config_to_update();
|
let mut w_config = Settings::app_config_to_update();
|
||||||
w_config.external_nodes_urls.insert(0, address);
|
let mut exists = false;
|
||||||
|
for mut c in w_config.external_connections.iter_mut() {
|
||||||
|
// Update connection if URL exists.
|
||||||
|
if c.url == conn.url {
|
||||||
|
c.secret = conn.secret.clone();
|
||||||
|
exists = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Create new connection if URL not exists.
|
||||||
|
if !exists {
|
||||||
|
w_config.external_connections.insert(0, conn);
|
||||||
|
}
|
||||||
w_config.save();
|
w_config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get external node connection secret from provided URL.
|
||||||
|
pub fn get_external_connection_secret(url: String) -> Option<String> {
|
||||||
|
let r_config = Settings::app_config_to_read();
|
||||||
|
for c in &r_config.external_connections {
|
||||||
|
if c.url == url {
|
||||||
|
return c.secret.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Main application directory name.
|
/// Main application directory name.
|
||||||
|
|
|
@ -22,3 +22,6 @@ pub use wallets::{Wallet, Wallets};
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
pub use config::*;
|
pub use config::*;
|
||||||
|
|
||||||
|
mod types;
|
||||||
|
pub use types::*;
|
39
src/wallet/types.rs
Normal file
39
src/wallet/types.rs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
// Copyright 2023 The Grim Developers
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
/// External node connection for the wallet.
|
||||||
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
|
pub struct ExternalConnection {
|
||||||
|
/// Node URL.
|
||||||
|
pub url: String,
|
||||||
|
/// Optional API secret key.
|
||||||
|
pub secret: Option<String>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExternalConnection {
|
||||||
|
/// Default external node URL.
|
||||||
|
const DEFAULT_EXTERNAL_NODE_URL: &'static str = "https://grinnnode.live:3413";
|
||||||
|
|
||||||
|
pub fn new(url: String, secret: Option<String>) -> Self {
|
||||||
|
Self { url, secret }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ExternalConnection {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { url: Self::DEFAULT_EXTERNAL_NODE_URL.to_string(), secret: None }
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue