parazyd 3 лет назад
Родитель
Сommit
f642524e81
3 измененных файлов с 178 добавлено и 26 удалено
  1. 13 3
      bin/drk/src/main.rs
  2. 155 12
      bin/drk/src/rpc_dao.rs
  3. 10 11
      bin/drk/src/rpc_wallet.rs

+ 13 - 3
bin/drk/src/main.rs

@@ -249,8 +249,8 @@ enum DaoSubcmd {
 
 
     /// List imported DAOs (or info about a specific one)
     /// List imported DAOs (or info about a specific one)
     List {
     List {
-        /// Named identifier for the DAO (optional)
-        dao_name: Option<String>,
+        /// Numeric identifier for the DAO (optional)
+        dao_id: Option<u64>,
     },
     },
 
 
     /// Mint an imported DAO on-chain
     /// Mint an imported DAO on-chain
@@ -762,7 +762,17 @@ async fn main() -> Result<()> {
                 Ok(())
                 Ok(())
             }
             }
 
 
-            DaoSubcmd::List { dao_name } => todo!(),
+            DaoSubcmd::List { dao_id } => {
+                let rpc_client = RpcClient::new(args.endpoint.clone())
+                    .await
+                    .with_context(|| "Could not connect to darkfid RPC endpoint")?;
+
+                let drk = Drk { rpc_client };
+
+                drk.dao_list(dao_id).await.with_context(|| "Failed to list DAO")?;
+
+                Ok(())
+            }
 
 
             DaoSubcmd::Mint { dao_name } => todo!(),
             DaoSubcmd::Mint { dao_name } => todo!(),
 
 

+ 155 - 12
bin/drk/src/rpc_dao.rs

@@ -20,29 +20,37 @@ use anyhow::{anyhow, Result};
 use darkfi::{rpc::jsonrpc::JsonRequest, wallet::walletdb::QueryType};
 use darkfi::{rpc::jsonrpc::JsonRequest, wallet::walletdb::QueryType};
 use darkfi_dao_contract::dao_client::{
 use darkfi_dao_contract::dao_client::{
     DAO_DAOS_COL_APPROVAL_RATIO_BASE, DAO_DAOS_COL_APPROVAL_RATIO_QUOT, DAO_DAOS_COL_BULLA_BLIND,
     DAO_DAOS_COL_APPROVAL_RATIO_BASE, DAO_DAOS_COL_APPROVAL_RATIO_QUOT, DAO_DAOS_COL_BULLA_BLIND,
-    DAO_DAOS_COL_DAO_ID, DAO_DAOS_COL_GOV_TOKEN_ID, DAO_DAOS_COL_NAME, DAO_DAOS_COL_PROPOSER_LIMIT,
-    DAO_DAOS_COL_QUORUM, DAO_DAOS_COL_SECRET, DAO_DAOS_TABLE,
+    DAO_DAOS_COL_CALL_INDEX, DAO_DAOS_COL_DAO_ID, DAO_DAOS_COL_GOV_TOKEN_ID,
+    DAO_DAOS_COL_LEAF_POSITION, DAO_DAOS_COL_NAME, DAO_DAOS_COL_PROPOSER_LIMIT,
+    DAO_DAOS_COL_QUORUM, DAO_DAOS_COL_SECRET, DAO_DAOS_COL_TX_HASH, DAO_DAOS_TABLE,
 };
 };
-use darkfi_serial::serialize;
+use darkfi_serial::{deserialize, serialize};
 use serde_json::json;
 use serde_json::json;
 
 
 use super::Drk;
 use super::Drk;
-use crate::DaoParams;
+use crate::{dao::Dao, DaoParams};
 
 
 impl Drk {
 impl Drk {
     /// Import given DAO into the wallet
     /// Import given DAO into the wallet
     pub async fn dao_import(&self, dao_name: String, dao_params: DaoParams) -> Result<()> {
     pub async fn dao_import(&self, dao_name: String, dao_params: DaoParams) -> Result<()> {
         // First let's check if we've imported this DAO before. We use the name
         // First let's check if we've imported this DAO before. We use the name
         // as the identifier.
         // as the identifier.
-        let query = format!(
-            "SELECT {} FROM {} WHERE {} = {}",
-            DAO_DAOS_COL_DAO_ID, DAO_DAOS_TABLE, DAO_DAOS_COL_NAME, dao_name
-        );
-        let params = json!([query, QueryType::Integer as u8, DAO_DAOS_COL_DAO_ID]);
-        let req = JsonRequest::new("wallet.query_row_single", params);
+        let query = format!("SELECT {} FROM {}", DAO_DAOS_COL_NAME, DAO_DAOS_TABLE);
+        let params = json!([query, QueryType::Blob as u8, DAO_DAOS_COL_NAME]);
+        let req = JsonRequest::new("wallet.query_row_multi", params);
+        let rep = self.rpc_client.request(req).await?;
+
+        // The returned thing should be an array of found rows.
+        let Some(rows) = rep.as_array() else {
+            return Err(anyhow!("Unexpected response from darkfid: {}", rep))
+        };
 
 
-        if (self.rpc_client.request(req).await).is_ok() {
-            return Err(anyhow!("DAO \"{}\" already imported in wallet.", dao_name))
+        for row in rows {
+            let name_bytes: Vec<u8> = serde_json::from_value(row[0].clone())?;
+            let name: String = deserialize(&name_bytes)?;
+            if name == dao_name {
+                return Err(anyhow!("DAO \"{}\" already imported in wallet", dao_name))
+            }
         }
         }
 
 
         eprintln!("Importing \"{}\" DAO into wallet", dao_name);
         eprintln!("Importing \"{}\" DAO into wallet", dao_name);
@@ -81,4 +89,139 @@ impl Drk {
 
 
         Ok(())
         Ok(())
     }
     }
+
+    async fn dao_list_single(&self, dao_id: u64) -> Result<()> {
+        let query =
+            format!("SELECT * FROM {} WHERE {} = {}", DAO_DAOS_TABLE, DAO_DAOS_COL_DAO_ID, dao_id);
+
+        let params = json!([
+            query,
+            QueryType::Integer as u8,
+            DAO_DAOS_COL_DAO_ID,
+            QueryType::Blob as u8,
+            DAO_DAOS_COL_NAME,
+            QueryType::Integer as u8,
+            DAO_DAOS_COL_PROPOSER_LIMIT,
+            QueryType::Integer as u8,
+            DAO_DAOS_COL_QUORUM,
+            QueryType::Integer as u8,
+            DAO_DAOS_COL_APPROVAL_RATIO_BASE,
+            QueryType::Integer as u8,
+            DAO_DAOS_COL_APPROVAL_RATIO_QUOT,
+            QueryType::Blob as u8,
+            DAO_DAOS_COL_GOV_TOKEN_ID,
+            QueryType::Blob as u8,
+            DAO_DAOS_COL_SECRET,
+            QueryType::Blob as u8,
+            DAO_DAOS_COL_BULLA_BLIND,
+            QueryType::OptionBlob as u8,
+            DAO_DAOS_COL_LEAF_POSITION,
+            QueryType::OptionBlob as u8,
+            DAO_DAOS_COL_TX_HASH,
+            QueryType::OptionInteger as u8,
+            DAO_DAOS_COL_CALL_INDEX,
+        ]);
+
+        let req = JsonRequest::new("wallet.query_row_single", params);
+        let rep = self.rpc_client.request(req).await?;
+
+        let Some(row) = rep.as_array() else {
+            return Err(anyhow!("Unexpected response from darkfid: {}", rep));
+        };
+
+        let dao_id: u64 = serde_json::from_value(row[0].clone())?;
+
+        let name_bytes: Vec<u8> = serde_json::from_value(row[1].clone())?;
+        let name = deserialize(&name_bytes)?;
+        let proposer_limit = serde_json::from_value(row[2].clone())?;
+        let quorum = serde_json::from_value(row[3].clone())?;
+        let approval_ratio_base = serde_json::from_value(row[4].clone())?;
+        let approval_ratio_quot = serde_json::from_value(row[5].clone())?;
+        let gov_token_bytes: Vec<u8> = serde_json::from_value(row[6].clone())?;
+        let gov_token_id = deserialize(&gov_token_bytes)?;
+        let secret_bytes: Vec<u8> = serde_json::from_value(row[7].clone())?;
+        let secret_key = deserialize(&secret_bytes)?;
+        let bulla_blind_bytes: Vec<u8> = serde_json::from_value(row[8].clone())?;
+        let bulla_blind = deserialize(&bulla_blind_bytes)?;
+
+        let leaf_position_bytes: Vec<u8> = serde_json::from_value(row[9].clone())?;
+        let tx_hash_bytes: Vec<u8> = serde_json::from_value(row[10].clone())?;
+        let call_index = serde_json::from_value(row[11].clone())?;
+
+        let leaf_position = if leaf_position_bytes.is_empty() {
+            None
+        } else {
+            Some(deserialize(&leaf_position_bytes)?)
+        };
+
+        let tx_hash =
+            if tx_hash_bytes.is_empty() { None } else { Some(deserialize(&tx_hash_bytes)?) };
+
+        let dao = Dao {
+            name,
+            proposer_limit,
+            quorum,
+            approval_ratio_base,
+            approval_ratio_quot,
+            gov_token_id,
+            secret_key,
+            bulla_blind,
+            leaf_position,
+            tx_hash,
+            call_index,
+        };
+
+        println!("DAO Parameters:");
+        println!("Name: {}", dao.name);
+        println!("Proposer limit: {}", dao.proposer_limit);
+        println!("Quorum: {}", dao.quorum);
+        println!(
+            "Approval ratio: {}",
+            dao.approval_ratio_base as f64 / dao.approval_ratio_quot as f64
+        );
+        println!("Governance token ID: {}", dao.gov_token_id);
+        println!("Secret key: {}", dao.secret_key);
+        println!("Bulla blind: {:?}", dao.bulla_blind);
+        println!("Leaf position: {:?}", dao.leaf_position);
+        println!("Tx hash: {:?}", dao.tx_hash);
+        println!("Call idx: {:?}", dao.call_index);
+
+        Ok(())
+    }
+
+    /// List DAO(s) imported in the wallet
+    pub async fn dao_list(&self, dao_id: Option<u64>) -> Result<()> {
+        if dao_id.is_some() {
+            return self.dao_list_single(dao_id.unwrap()).await
+        }
+
+        let query = format!(
+            "SELECT {}, {} FROM {}",
+            DAO_DAOS_COL_DAO_ID, DAO_DAOS_COL_NAME, DAO_DAOS_TABLE
+        );
+
+        let params = json!([
+            query,
+            QueryType::Integer as u8,
+            DAO_DAOS_COL_DAO_ID,
+            QueryType::Blob as u8,
+            DAO_DAOS_COL_NAME
+        ]);
+
+        let req = JsonRequest::new("wallet.query_row_multi", params);
+        let rep = self.rpc_client.request(req).await?;
+
+        let Some(rows) = rep.as_array() else {
+            return Err(anyhow!("Unexpected response from darkfid: {}", rep))
+        };
+
+        for row in rows {
+            let dao_id: u64 = serde_json::from_value(row[0].clone())?;
+            let dao_name_bytes: Vec<u8> = serde_json::from_value(row[1].clone())?;
+            let dao_name: String = deserialize(&dao_name_bytes)?;
+            println!("[{}] {}", dao_id, dao_name);
+        }
+
+        Ok(())
+    }
 }
 }

+ 10 - 11
bin/drk/src/rpc_wallet.rs

@@ -595,21 +595,20 @@ impl Drk {
         proposals_tree: &BridgeTree<MerkleNode, MERKLE_DEPTH>,
         proposals_tree: &BridgeTree<MerkleNode, MERKLE_DEPTH>,
     ) -> Result<()> {
     ) -> Result<()> {
         let query = format!(
         let query = format!(
-            "DELETE FROM {}; INSERT INTO {} ({}) VALUES (?1);",
-            DAO_TREES_TABLE, DAO_TREES_TABLE, DAO_TREES_COL_DAOS_TREE
+            "DELETE FROM {}; INSERT INTO {} ({}, {}) VALUES (?1, ?2);",
+            DAO_TREES_TABLE, DAO_TREES_TABLE, DAO_TREES_COL_DAOS_TREE, DAO_TREES_COL_PROPOSALS_TREE
         );
         );
 
 
-        let params = json!([query, QueryType::Blob as u8, serialize(daos_tree)]);
-        let req = JsonRequest::new("wallet.exec_sql", params);
-        let _ = self.rpc_client.request(req).await?;
-
-        let query = format!(
-            "DELETE FROM {}; INSERT INTO {} ({}) VALUES (?1);",
-            DAO_TREES_TABLE, DAO_TREES_TABLE, DAO_TREES_COL_PROPOSALS_TREE
-        );
+        let params = json!([
+            query,
+            QueryType::Blob as u8,
+            serialize(daos_tree),
+            QueryType::Blob as u8,
+            serialize(proposals_tree)
+        ]);
 
 
-        let params = json!([query, QueryType::Blob as u8, serialize(proposals_tree)]);
         let req = JsonRequest::new("wallet.exec_sql", params);
         let req = JsonRequest::new("wallet.exec_sql", params);
+
         let _ = self.rpc_client.request(req).await?;
         let _ = self.rpc_client.request(req).await?;
 
 
         Ok(())
         Ok(())