diff --git a/README.md b/README.md new file mode 100644 index 000000000..c9452327f --- /dev/null +++ b/README.md @@ -0,0 +1,215 @@ +# Dash Evo Tool + +**Dash Evo Tool** is a graphical user interface for easily interacting with Dash Evolution. The current version enables the following actions: + +- Registering a DPNS username +- Viewing active DPNS username contests +- Voting on active DPNS username contests +- Decoding and viewing state transitions + +The tool supports both Mainnet and Testnet networks. + +## Table of Contents + +- [Prerequisites](#prerequisites) + - [Rust Installation](#rust-installation) + - [Dash Core Wallet Setup](#dash-core-wallet-setup) +- [Installation](#installation) +- [Getting Started](#getting-started) + - [Start the App](#start-the-app) + - [Connect to a Network](#connect-to-a-network) +- [Usage](#usage) + - [Register a DPNS Username](#register-a-dpns-username) + - [Vote on an Active DPNS Contest](#vote-on-an-active-dpns-contest) + - [View Decoded State Transition](#view-decoded-state-transition) +- [Switching Networks](#switching-networks) +- [Contributing](#contributing) +- [License](#license) +- [Support](#support) +- [Security Note](#security-note) + +## Prerequisites + +Before you begin, ensure you have met the following requirements: + +### Rust Installation + +- **Rust**: Install Rust using [rustup](https://rustup.rs/): + + ``` + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + ``` + +- Update Rust to the latest version: + + ``` + rustup update + ``` + +### Dash Core Wallet Setup + +- **Dash Core Wallet**: Download and install from [dash.org/wallets](https://www.dash.org/wallets/). + +- **Synchronize Wallet**: Ensure the wallet is fully synced with the network you intend to use (Mainnet or Testnet). + +## Installation + +To install Dash Evo Tool: + +1. **Clone the repository**: + + ``` + git clone https://github.com/dashpay/dash-evo-tool.git + ``` + +2. **Navigate to the project directory**: + + ``` + cd dash-evo-tool + ``` + +3. **Build the project**: + + ``` + cargo build --release + ``` + +## Getting Started + +### Create `.env` File + +Create a new file in the root of the dash-evo-tool directory named `.env` and copy the contents of `.env.example` into it. No changes to the file are necessary in this version. + +### Start the App + +Run the application using: + +``` +cargo run +``` + +### Connect to a Network + +1. **Open Network Chooser**: In the app, navigate to the **Network Chooser** screen. + +2. **Select Network**: Choose **Mainnet** or **Testnet**. + +3. **Start Connection**: Click **Start** next to the selected network. + + - If Dash Core Wallet is running and synced, the status will show **Online**. + - If not, the app attempts to start Dash Core Wallet automatically. + +## Usage + +### Register a DPNS Username + +1. **Load User Identity**: + + - Go to the **Identity** screen. + - Click **Load Identity** at the top right. + - Fill in your user identity details: + - **Identity ID** (Hex or Base58) + - **Identity Type** should be "User" + - **Alias** (optional alias for use within Dash Evo Tool) + - **Private Keys** (only the authentication key that will be used to register the name is required for registering a username. Other keys can be added later.) + - Click **Submit**. + +2. **Register Username**: + + - Navigate to the **DPNS** screen. + - Click **Register Username** at the top right. + - Select the Identity you'd like to register the username for. + - Enter your desired username. + - Click **Register Name** + +### Vote on an Active DPNS Contest + +1. **Load HPMN Identity**: + + - Go to the **Identity** screen. + - Fill in your Masternode or HPMN (High Performance Masternode) identity details: + - For **Testnet**, you can click "Fill Random HPMN" or "Fill Random Masternode". + - For **Mainnet**, ensure you have valid Masternode or HPMN credentials. + - Click **Submit**. + +2. **Vote on Contest**: + + - Navigate to the **DPNS** screen. + - If no contests appear, click **Refresh**. If still no contests appear, there are probably no active contests. + - Locate the active contest you wish to vote on. + - Click the button for the option you'd like to vote for within the contest's row (Lock, Abstain, or an Identity ID). + - Choose the Masternode or HPMN identity to vote with or select **All** to vote with all loaded Masternodes and HPMNs. + - Confirm your vote. + +### View Decoded State Transition + +1. **Open State Transition Viewer**: + + - Navigate to the **State Transition Viewer** screen. + +2. **Decode State Transition**: + + - Paste a hex or base58 encoded state transition into the input box at the top. + - View the decoded details displayed below. + +## Switching Networks + +1. **Open Network Chooser**: + + - Go to the **Network Chooser** screen. + +2. **Select Network**: + + - Choose the network you'd like to interact with (**Mainnet** or **Testnet**). + +3. **Check Wallet Status**: + + - If Dash Core Wallet is already running on that network, the status column will show **Online**. + - If not, click **Start** to launch Dash Core Wallet on the selected network. + +4. **Wait for Sync**: + + - Ensure Dash Core Wallet is fully synchronized before proceeding. + +## Contributing + +Contributions are welcome! + +- **Fork the Repository**: Click the **Fork** button on the GitHub repository page. + +- **Create a Branch**: + + ``` + git checkout -b feature/YourFeatureName + ``` + +- **Commit Changes**: Make your changes and commit them with descriptive messages. + + ``` + git commit -m "Add feature: YourFeatureName" + ``` + +- **Push to Branch**: + + ``` + git push origin feature/YourFeatureName + ``` + +- **Submit Pull Request**: Open a pull request on GitHub and describe your changes. + +- **Follow Guidelines**: Please ensure your code adheres to the project's coding standards and passes all tests. + +## License + +This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. + +## Support + +For assistance: + +- **Issues**: Open an issue on [GitHub Issues](https://github.com/dashpay/dash-evo-tool/issues). +- **Community**: Join the Dash community forums or Discord server for discussions. + +## Security Note + +Keep your private keys and identity information secure. Do not share them with untrusted parties or applications. diff --git a/src/database/wallet.rs b/src/database/wallet.rs index 8d4e1c98f..f7f57de7d 100644 --- a/src/database/wallet.rs +++ b/src/database/wallet.rs @@ -3,7 +3,7 @@ use crate::model::wallet::{AddressInfo, DerivationPathReference, DerivationPathT use dash_sdk::dashcore_rpc::dashcore::Address; use dash_sdk::dpp::dashcore::bip32::DerivationPath; use dash_sdk::dpp::dashcore::hashes::Hash; -use dash_sdk::dpp::dashcore::{consensus, Network, OutPoint, Script, ScriptBuf, TxOut, Txid}; +use dash_sdk::dpp::dashcore::{Network, OutPoint, ScriptBuf, TxOut, Txid}; use rusqlite::params; use std::collections::BTreeMap; use std::str::FromStr; diff --git a/src/main.rs b/src/main.rs index c7b0e4708..1a3fed494 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] + mod app; mod config; mod database; diff --git a/src/model/qualified_identity.rs b/src/model/qualified_identity.rs index 1db7414f1..1e2f9b6d2 100644 --- a/src/model/qualified_identity.rs +++ b/src/model/qualified_identity.rs @@ -251,7 +251,7 @@ impl QualifiedIdentity { let mut keys = vec![]; // Check the main identity's public keys - for ((public_key, _)) in self.encrypted_private_keys.values() { + for (public_key, _) in self.encrypted_private_keys.values() { if public_key.purpose() == Purpose::TRANSFER { keys.push(public_key); } diff --git a/src/model/wallet/utxos.rs b/src/model/wallet/utxos.rs index b6f341a50..4efbe3384 100644 --- a/src/model/wallet/utxos.rs +++ b/src/model/wallet/utxos.rs @@ -1,8 +1,7 @@ use crate::model::wallet::Wallet; use dash_sdk::dashcore_rpc::{Client, RpcApi}; -use dash_sdk::dpp::dashcore::{Address, OutPoint, PublicKey, TxOut}; +use dash_sdk::dpp::dashcore::{Address, OutPoint, TxOut}; use std::collections::{BTreeMap, HashMap}; -use tracing::info; impl Wallet { pub fn take_unspent_utxos_for( diff --git a/src/platform/contested_names/mod.rs b/src/platform/contested_names/mod.rs index 439ea59c2..53dd3cb05 100644 --- a/src/platform/contested_names/mod.rs +++ b/src/platform/contested_names/mod.rs @@ -33,7 +33,7 @@ impl AppContext { .await .map(|_| BackendTaskSuccessResult::None), ContestedResourceTask::QueryDPNSVoteContenders(name) => self - .query_dpns_vote_contenders(name, sdk, sender) + .query_dpns_vote_contenders(name, sdk) .await .map(|_| BackendTaskSuccessResult::None), ContestedResourceTask::VoteOnDPNSName(name, vote_choice, voters) => { diff --git a/src/platform/contested_names/query_dpns_contested_resources.rs b/src/platform/contested_names/query_dpns_contested_resources.rs index e300d7d70..e1bd847bf 100644 --- a/src/platform/contested_names/query_dpns_contested_resources.rs +++ b/src/platform/contested_names/query_dpns_contested_resources.rs @@ -78,7 +78,7 @@ impl AppContext { // Acquire a permit from the semaphore let _permit: OwnedSemaphorePermit = semaphore.acquire_owned().await.unwrap(); - match self_ref.query_dpns_ending_times(sdk, sender.clone()).await { + match self_ref.query_dpns_ending_times(sdk).await { Ok(_) => { // Send a refresh message if the query succeeded sender @@ -112,10 +112,7 @@ impl AppContext { let _permit: OwnedSemaphorePermit = semaphore.acquire_owned().await.unwrap(); // Perform the query - match self_ref - .query_dpns_vote_contenders(&name, sdk, sender.clone()) - .await - { + match self_ref.query_dpns_vote_contenders(&name, sdk).await { Ok(_) => { // Send a refresh message if the query succeeded sender diff --git a/src/platform/contested_names/query_dpns_vote_contenders.rs b/src/platform/contested_names/query_dpns_vote_contenders.rs index d4a618bff..16bff52ad 100644 --- a/src/platform/contested_names/query_dpns_vote_contenders.rs +++ b/src/platform/contested_names/query_dpns_vote_contenders.rs @@ -1,4 +1,3 @@ -use crate::app::TaskResult; use crate::context::AppContext; use dash_sdk::dpp::data_contract::accessors::v0::DataContractV0Getters; use dash_sdk::dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; @@ -10,14 +9,12 @@ use dash_sdk::drive::query::vote_poll_vote_state_query::{ }; use dash_sdk::platform::FetchMany; use dash_sdk::Sdk; -use tokio::sync::mpsc; impl AppContext { pub(super) async fn query_dpns_vote_contenders( &self, name: &String, sdk: Sdk, - sender: mpsc::Sender, ) -> Result<(), String> { let data_contract = self.dpns_contract.as_ref(); let document_type = data_contract diff --git a/src/platform/contested_names/query_ending_times.rs b/src/platform/contested_names/query_ending_times.rs index 6576ecd63..3be7d002b 100644 --- a/src/platform/contested_names/query_ending_times.rs +++ b/src/platform/contested_names/query_ending_times.rs @@ -8,16 +8,10 @@ use dash_sdk::platform::FetchMany; use std::collections::BTreeMap; use std::sync::Arc; -use crate::app::TaskResult; use dash_sdk::Sdk; -use tokio::sync::mpsc; impl AppContext { - pub(super) async fn query_dpns_ending_times( - self: &Arc, - sdk: Sdk, - sender: mpsc::Sender, - ) -> Result<(), String> { + pub(super) async fn query_dpns_ending_times(self: &Arc, sdk: Sdk) -> Result<(), String> { let now: DateTime = Utc::now(); let start_time_dt = now - Duration::weeks(2); let end_time_dt = now + Duration::weeks(2); diff --git a/src/platform/identity/add_key_to_identity.rs b/src/platform/identity/add_key_to_identity.rs index cd795d922..12029f013 100644 --- a/src/platform/identity/add_key_to_identity.rs +++ b/src/platform/identity/add_key_to_identity.rs @@ -12,7 +12,7 @@ use dash_sdk::dpp::state_transition::proof_result::StateTransitionProofResult; use dash_sdk::platform::transition::broadcast::BroadcastStateTransition; use dash_sdk::platform::{Fetch, Identity, IdentityPublicKey}; use dash_sdk::Sdk; -use futures::TryFutureExt; + impl AppContext { pub(super) async fn add_key_to_identity( &self, diff --git a/src/platform/identity/register_identity.rs b/src/platform/identity/register_identity.rs index f006dd9c2..e66f0ed81 100644 --- a/src/platform/identity/register_identity.rs +++ b/src/platform/identity/register_identity.rs @@ -6,18 +6,13 @@ use dash_sdk::dapi_grpc::core::v0::{ BroadcastTransactionRequest, GetBlockchainStatusRequest, GetTransactionRequest, GetTransactionResponse, }; -use dash_sdk::dashcore_rpc::dashcore::PrivateKey; -use dash_sdk::dashcore_rpc::RpcApi; use dash_sdk::dpp::dashcore::psbt::serialize::Serialize; use dash_sdk::dpp::dashcore::{Address, Transaction}; use dash_sdk::dpp::prelude::AssetLockProof; use dash_sdk::platform::transition::put_identity::PutIdentity; use dash_sdk::platform::Identity; -use dash_sdk::{RequestSettings, Sdk}; -use rand::prelude::StdRng; -use std::collections::BTreeMap; +use dash_sdk::RequestSettings; use std::time::Duration; -use tokio::sync::MutexGuard; impl AppContext { pub(crate) async fn broadcast_and_retrieve_asset_lock( @@ -108,7 +103,7 @@ impl AppContext { input: IdentityRegistrationInfo, ) -> Result<(), String> { let IdentityRegistrationInfo { - alias_input, + alias_input: _, amount, keys, identity_index, diff --git a/src/ui/components/contract_chooser_panel.rs b/src/ui/components/contract_chooser_panel.rs index 55e7052a9..10eb1896c 100644 --- a/src/ui/components/contract_chooser_panel.rs +++ b/src/ui/components/contract_chooser_panel.rs @@ -10,7 +10,7 @@ pub fn add_contract_chooser_panel( current_search_term: &mut String, app_context: &Arc, ) -> AppAction { - let mut action = AppAction::None; + let action = AppAction::None; // Fetch contracts from the app context let contracts = app_context.get_contracts(None, None).unwrap_or_else(|e| { diff --git a/src/ui/components/left_panel.rs b/src/ui/components/left_panel.rs index bd171d24d..53c36a7ef 100644 --- a/src/ui/components/left_panel.rs +++ b/src/ui/components/left_panel.rs @@ -1,10 +1,8 @@ use crate::app::AppAction; -use crate::context::AppContext; use crate::ui::RootScreenType; use eframe::epaint::{Color32, Margin}; use egui::{Context, Frame, ImageButton, SidePanel, TextureHandle}; use rust_embed::RustEmbed; -use std::sync::Arc; #[derive(RustEmbed)] #[folder = "icons/"] // Adjust the folder path if necessary @@ -35,11 +33,7 @@ fn load_icon(ctx: &Context, path: &str) -> Option { } } -pub fn add_left_panel( - ctx: &Context, - app_context: &Arc, - selected_screen: RootScreenType, -) -> AppAction { +pub fn add_left_panel(ctx: &Context, selected_screen: RootScreenType) -> AppAction { let mut action = AppAction::None; // Define the button details directly in this function diff --git a/src/ui/document_query_screen.rs b/src/ui/document_query_screen.rs index c94349df1..3063a00d5 100644 --- a/src/ui/document_query_screen.rs +++ b/src/ui/document_query_screen.rs @@ -177,11 +177,7 @@ impl ScreenLike for DocumentQueryScreen { vec![], ); - action |= add_left_panel( - ctx, - &self.app_context, - RootScreenType::RootScreenDocumentQuery, - ); + action |= add_left_panel(ctx, RootScreenType::RootScreenDocumentQuery); action |= add_contract_chooser_panel(ctx, &mut self.contract_search_term, &self.app_context); diff --git a/src/ui/dpns_contested_names_screen.rs b/src/ui/dpns_contested_names_screen.rs index 9ac873555..5abba1a83 100644 --- a/src/ui/dpns_contested_names_screen.rs +++ b/src/ui/dpns_contested_names_screen.rs @@ -483,11 +483,7 @@ impl ScreenLike for DPNSContestedNamesScreen { right_buttons, ); - action |= add_left_panel( - ctx, - &self.app_context, - RootScreenType::RootScreenDPNSContestedNames, - ); + action |= add_left_panel(ctx, RootScreenType::RootScreenDPNSContestedNames); // Render the UI with the cloned contested_names vector egui::CentralPanel::default().show(ctx, |ui| { diff --git a/src/ui/identities/add_new_identity_screen.rs b/src/ui/identities/add_new_identity_screen.rs index a03bb7223..517be0d42 100644 --- a/src/ui/identities/add_new_identity_screen.rs +++ b/src/ui/identities/add_new_identity_screen.rs @@ -157,7 +157,7 @@ impl AddNewIdentityScreen { { Ok(new_balance) => { // Update wallet balance if it has changed. - if let Some(mut wallet_guard) = selected_wallet.as_ref() { + if let Some(wallet_guard) = selected_wallet.as_ref() { let mut wallet = wallet_guard.write().unwrap(); wallet .update_address_balance( diff --git a/src/ui/identities/identities_screen.rs b/src/ui/identities/identities_screen.rs index 5f29ec0d0..1f73327e6 100644 --- a/src/ui/identities/identities_screen.rs +++ b/src/ui/identities/identities_screen.rs @@ -354,7 +354,7 @@ impl ScreenLike for IdentitiesScreen { right_buttons, ); - action |= add_left_panel(ctx, &self.app_context, RootScreenType::RootScreenIdentities); + action |= add_left_panel(ctx, RootScreenType::RootScreenIdentities); let identities = self.identities.lock().unwrap(); diff --git a/src/ui/identities/register_dpns_name_screen.rs b/src/ui/identities/register_dpns_name_screen.rs index fcc2a231b..52f04d1c8 100644 --- a/src/ui/identities/register_dpns_name_screen.rs +++ b/src/ui/identities/register_dpns_name_screen.rs @@ -13,7 +13,6 @@ use dash_sdk::dpp::identity::{Purpose, SecurityLevel, TimestampMillis}; use dash_sdk::dpp::platform_value::string_encoding::Encoding; use dash_sdk::platform::IdentityPublicKey; use eframe::egui::Context; -use futures::StreamExt; use std::sync::Arc; use std::time::{SystemTime, UNIX_EPOCH}; diff --git a/src/ui/key_info_screen.rs b/src/ui/key_info_screen.rs index 01fd841a4..21344fc34 100644 --- a/src/ui/key_info_screen.rs +++ b/src/ui/key_info_screen.rs @@ -6,7 +6,6 @@ use crate::ui::ScreenLike; use dash_sdk::dpp::dashcore::address::Payload; use dash_sdk::dpp::dashcore::hashes::Hash; use dash_sdk::dpp::dashcore::{Address, PubkeyHash, ScriptHash}; -use dash_sdk::dpp::identity::accessors::IdentityGettersV0; use dash_sdk::dpp::identity::hash::IdentityPublicKeyHashMethodsV0; use dash_sdk::dpp::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV0; use dash_sdk::dpp::identity::KeyType; diff --git a/src/ui/network_chooser_screen.rs b/src/ui/network_chooser_screen.rs index 7f063a790..8f5c79c92 100644 --- a/src/ui/network_chooser_screen.rs +++ b/src/ui/network_chooser_screen.rs @@ -259,11 +259,7 @@ impl ScreenLike for NetworkChooserScreen { action |= AppAction::BackendTask(BackendTask::CoreTask(CoreTask::GetBestChainLock)); } - action |= add_left_panel( - ctx, - self.current_app_context(), - RootScreenType::RootScreenNetworkChooser, - ); + action |= add_left_panel(ctx, RootScreenType::RootScreenNetworkChooser); egui::CentralPanel::default().show(ctx, |ui| { action |= self.render_network_table(ui); diff --git a/src/ui/transfers/mod.rs b/src/ui/transfers/mod.rs index 2368df578..a67d4ea8a 100644 --- a/src/ui/transfers/mod.rs +++ b/src/ui/transfers/mod.rs @@ -13,7 +13,6 @@ use dash_sdk::dpp::identity::identity_public_key::accessors::v0::IdentityPublicK use dash_sdk::dpp::identity::{KeyType, Purpose, SecurityLevel}; use dash_sdk::platform::IdentityPublicKey; use eframe::egui::{self, Context, Ui}; -use std::convert::identity; use std::str::FromStr; use std::sync::Arc; @@ -181,7 +180,7 @@ impl TransferScreen { } impl ScreenLike for TransferScreen { - fn display_message(&mut self, message: &str, message_type: MessageType) { + fn display_message(&mut self, message: &str, _message_type: MessageType) { self.error_message = Some(message.to_string()); } diff --git a/src/ui/transition_visualizer_screen.rs b/src/ui/transition_visualizer_screen.rs index 03aac3106..e3acb5fc8 100644 --- a/src/ui/transition_visualizer_screen.rs +++ b/src/ui/transition_visualizer_screen.rs @@ -113,11 +113,7 @@ impl ScreenLike for TransitionVisualizerScreen { vec![], ); - action |= add_left_panel( - ctx, - &self.app_context, - RootScreenType::RootScreenTransitionVisualizerScreen, - ); + action |= add_left_panel(ctx, RootScreenType::RootScreenTransitionVisualizerScreen); egui::CentralPanel::default().show(ctx, |ui| { self.show_input_field(ui);