|
@@ -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(())
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|