Просмотр исходного кода

app/drk: make the balances_updated signal return the actual data so we avoid a double roundtrip calling get_balance, cache the balances so we avoid sending the signal on every sync update and simplify/flatten the code in src/main.rs updating the UI.

darkfi 1 день назад
Родитель
Сommit
bcdb969981
2 измененных файлов с 104 добавлено и 91 удалено
  1. 73 76
      bin/app/src/main.rs
  2. 31 15
      bin/app/src/plugin/drk.rs

+ 73 - 76
bin/app/src/main.rs

@@ -517,89 +517,77 @@ async fn load_plugins(
             use darkfi_money_contract::model::TokenId;
             use darkfi_money_contract::model::TokenId;
             use darkfi_serial::Encodable;
             use darkfi_serial::Encodable;
 
 
-            let update = async || {
+            let update = async |data: Vec<u8>| {
                 d!("drk balances_updated signal received");
                 d!("drk balances_updated signal received");
 
 
-                // Fetch and update main wallet tokens table
-                if let Ok(Some(response_data)) = drk_node2.call_method("get_balances", vec![]).await
-                {
+                let mut cur = std::io::Cursor::new(data);
+                if let Ok(balances) = Vec::<(String, TokenId, u64)>::decode(&mut cur) {
                     let atom = &mut renderer2.make_guard(gfxtag!("wallet - refresh tokens"));
                     let atom = &mut renderer2.make_guard(gfxtag!("wallet - refresh tokens"));
 
 
-                    let mut cur = std::io::Cursor::new(response_data);
-                    if let Ok(balances) = Vec::<(String, TokenId, u64)>::decode(&mut cur) {
-                        let token_rows: Vec<TokenRow> = balances
-                            .iter()
-                            .map(|(symbol, token_id, balance)| TokenRow {
-                                id: *token_id,
-                                symbol: symbol.clone(),
-                                balance: encode_base10(*balance, 8),
-                            })
-                            .collect();
-
-                        let mut data: Vec<u8> = vec![];
-                        for row in &token_rows {
-                            let _ = TokenRow::encode(row, &mut data);
-                        }
-
-                        if let Some(tokens_table) =
-                            sg_root2.lookup_node("/window/content/wallet/main_layer/tokens_table")
-                        {
-                            let _ = tokens_table.call_method("set_tokens", data.clone()).await;
-                        }
-
-                        if let Some(send_tokens_table) = sg_root2
-                            .lookup_node("/window/content/wallet/send_step1_layer/tokens_table")
-                        {
-                            let _ = send_tokens_table.call_method("set_tokens", data).await;
-                        }
-
-                        // Update main wallet balance
-                        if let Some(drk_row) =
-                            token_rows.iter().find(|row| row.id == *DARK_TOKEN_ID)
-                        {
-                            if let Some(balance_node) = sg_root2
-                                .lookup_node("/window/content/wallet/main_layer/wallet_balance")
-                            {
-                                balance_node
-                                    .set_property_str(
-                                        atom,
-                                        Role::App,
-                                        "text",
-                                        format!("DRK {}", drk_row.balance),
-                                    )
-                                    .unwrap();
-                            }
-                        }
-
-                        if let Some(tx_status_layer) =
-                            sg_root2.lookup_node("/window/content/wallet/tx_status_layer")
-                        {
-                            let tx_id = tx_status_layer.get_property_str("tx_id").unwrap();
-                            if !tx_id.is_empty() {
-                                let mut tx_id_data = vec![];
-                                tx_id.encode(&mut tx_id_data).unwrap();
-                                if let Ok(Some(data)) =
-                                    drk_node2.call_method("get_tx_status", tx_id_data).await
-                                {
-                                    let mut cur = std::io::Cursor::new(data);
-                                    let status_text = String::decode(&mut cur).unwrap();
-                                    if let Some(status_node) =
-                                        tx_status_layer.lookup_node("/status")
-                                    {
-                                        status_node
-                                            .set_property_str(atom, Role::App, "text", status_text)
-                                            .unwrap();
-                                    }
-                                }
-                            }
-                        }
+                    let token_rows: Vec<TokenRow> = balances
+                        .iter()
+                        .map(|(symbol, token_id, balance)| TokenRow {
+                            id: *token_id,
+                            symbol: symbol.clone(),
+                            balance: encode_base10(*balance, 8),
+                        })
+                        .collect();
+
+                    let mut rows_data: Vec<u8> = vec![];
+                    for row in &token_rows {
+                        let _ = TokenRow::encode(row, &mut rows_data);
+                    }
+
+                    let tokens_table = sg_root2
+                        .lookup_node("/window/content/wallet/main_layer/tokens_table")
+                        .unwrap();
+                    let send_tokens_table = sg_root2
+                        .lookup_node("/window/content/wallet/send_step1_layer/tokens_table")
+                        .unwrap();
+
+                    tokens_table.call_method("set_tokens", rows_data.clone()).await.unwrap();
+                    send_tokens_table.call_method("set_tokens", rows_data).await.unwrap();
+
+                    // Update main wallet balance
+                    if let Some(drk_row) = token_rows.iter().find(|row| row.id == *DARK_TOKEN_ID) {
+                        let balance_node = sg_root2
+                            .lookup_node("/window/content/wallet/main_layer/wallet_balance")
+                            .unwrap();
+                        balance_node
+                            .set_property_str(
+                                atom,
+                                Role::App,
+                                "text",
+                                format!("DRK {}", drk_row.balance),
+                            )
+                            .unwrap();
+                    }
+
+                    let tx_status_layer =
+                        sg_root2.lookup_node("/window/content/wallet/tx_status_layer").unwrap();
+                    let tx_id = tx_status_layer.get_property_str("tx_id").unwrap();
+                    if !tx_id.is_empty() {
+                        let mut tx_id_data = vec![];
+                        tx_id.encode(&mut tx_id_data).unwrap();
+                        let status_data = drk_node2
+                            .call_method("get_tx_status", tx_id_data)
+                            .await
+                            .unwrap()
+                            .unwrap();
+
+                        let mut cur = std::io::Cursor::new(status_data);
+                        let status_text = String::decode(&mut cur).unwrap();
+                        let status_node = tx_status_layer.lookup_node("/status").unwrap();
+                        status_node.set_property_str(atom, Role::App, "text", status_text).unwrap();
                     }
                     }
                 }
                 }
             };
             };
 
 
-            update().await;
-            while let Ok(_) = recv.recv().await {
-                update().await;
+            let response_data =
+                drk_node2.call_method("get_balances", vec![]).await.unwrap().unwrap();
+            update(response_data).await;
+            while let Ok(data) = recv.recv().await {
+                update(data).await;
             }
             }
         });
         });
 
 
@@ -872,7 +860,16 @@ pub fn create_drk(name: &str) -> SceneNode {
     )
     )
     .unwrap();
     .unwrap();
 
 
-    node.add_signal("balances_updated", "Balances changed", vec![]).unwrap();
+    node.add_signal(
+        "balances_updated",
+        "Balances changed",
+        vec![
+            ("symbol", "Token symbol", CallArgType::Str),
+            ("token_id", "Token ID", CallArgType::Hash),
+            ("balance", "Token balance", CallArgType::Uint64),
+        ],
+    )
+    .unwrap();
 
 
     node.add_signal(
     node.add_signal(
         "tx_updated",
         "tx_updated",

+ 31 - 15
bin/app/src/plugin/drk.rs

@@ -25,11 +25,11 @@ use darkfi_money_contract::model::TokenId;
 use darkfi_sdk::crypto::keypair::{Address, Network, PublicKey, StandardAddress};
 use darkfi_sdk::crypto::keypair::{Address, Network, PublicKey, StandardAddress};
 use darkfi_serial::{serialize, Decodable, Encodable};
 use darkfi_serial::{serialize, Decodable, Encodable};
 use drk::{rpc::subscribe_blocks, Drk};
 use drk::{rpc::subscribe_blocks, Drk};
+use parking_lot::Mutex as SyncMutex;
 use smol::{channel::unbounded, lock::RwLock};
 use smol::{channel::unbounded, lock::RwLock};
 use std::{
 use std::{
     io::Cursor,
     io::Cursor,
     sync::{Arc, OnceLock, Weak},
     sync::{Arc, OnceLock, Weak},
-    time::Instant,
 };
 };
 use url::Url;
 use url::Url;
 
 
@@ -42,8 +42,7 @@ use crate::{
 
 
 // TODO: should be configurable at runtime
 // TODO: should be configurable at runtime
 //const DARKFID_ENDPOINT: &str = "tcp://127.0.0.1:18345";
 //const DARKFID_ENDPOINT: &str = "tcp://127.0.0.1:18345";
-const DARKFID_ENDPOINT: &str = "tcp://192.168.1.38:18345";
-//const DARKFID_ENDPOINT: &str = "tcp+tls://node0.testnet.dark.fi:18345";
+const DARKFID_ENDPOINT: &str = "tcp+tls://node0.testnet.dark.fi:18345";
 const DARKFID_RETRY_TIME: u64 = 20;
 const DARKFID_RETRY_TIME: u64 = 20;
 
 
 #[cfg(target_os = "android")]
 #[cfg(target_os = "android")]
@@ -127,6 +126,7 @@ pub struct DrkPlugin {
 
 
     drk: Arc<RwLock<Drk>>,
     drk: Arc<RwLock<Drk>>,
     build_tx_channel: smol::channel::Sender<BuildTxRequest>,
     build_tx_channel: smol::channel::Sender<BuildTxRequest>,
+    last_balances: SyncMutex<Option<Vec<(String, TokenId, u64)>>>,
 }
 }
 
 
 impl DrkPlugin {
 impl DrkPlugin {
@@ -209,6 +209,7 @@ impl DrkPlugin {
             drk: drk.into_ptr(),
             drk: drk.into_ptr(),
             build_tx_channel: build_tx_tx,
             build_tx_channel: build_tx_tx,
             scan_progress_pub: Publisher::new(),
             scan_progress_pub: Publisher::new(),
+            last_balances: SyncMutex::new(None),
         });
         });
 
 
         // Start background task to process build_tx requests from channel
         // Start background task to process build_tx requests from channel
@@ -324,11 +325,34 @@ impl DrkPlugin {
         Ok(result)
         Ok(result)
     }
     }
 
 
-    /// Emit balances_updated signal
+    /// Emit balances_updated signal with the balances encoded in the payload.
+    /// Only emits when the encoded balances differ from the last emitted ones.
     async fn emit_balances_updated(&self) {
     async fn emit_balances_updated(&self) {
-        if let Some(node) = self.node.upgrade() {
-            let _ = node.trigger("balances_updated", vec![]).await;
+        let Some(node) = self.node.upgrade() else { return };
+
+        let balances = match self.get_balances().await {
+            Ok(b) => b,
+            Err(e) => {
+                e!("Failed to get balances for balances_updated signal: {e}");
+                return
+            }
+        };
+
+        let mut data = vec![];
+        if let Err(e) = balances.encode(&mut data) {
+            e!("Failed to encode balances for balances_updated signal: {e}");
+            return
+        }
+
+        let mut last = self.last_balances.lock();
+        if let Some(last) = &*last {
+            if *last == balances {
+                return
+            }
         }
         }
+        *last = Some(balances);
+
+        let _ = node.trigger("balances_updated", data).await;
     }
     }
 
 
     /// Emit tx_updated signal
     /// Emit tx_updated signal
@@ -747,19 +771,11 @@ impl DrkPlugin {
 
 
         let self2 = self.clone();
         let self2 = self.clone();
         let subscribe_recv_task = ex.spawn(async move {
         let subscribe_recv_task = ex.spawn(async move {
-            let mut last_emit: Option<Instant> = None;
             loop {
             loop {
                 let recv = shell_receiver.recv().await;
                 let recv = shell_receiver.recv().await;
 
 
                 if let Ok(lines) = recv {
                 if let Ok(lines) = recv {
-                    let should_emit = match last_emit {
-                        None => true,
-                        Some(last) => last.elapsed().as_millis() >= 500,
-                    };
-                    if should_emit {
-                        last_emit = Some(Instant::now());
-                        self2.emit_balances_updated().await;
-                    }
+                    self2.emit_balances_updated().await;
 
 
                     for line in lines.iter() {
                     for line in lines.iter() {
                         i!(line);
                         i!(line);