drk: DAO list.

This commit is contained in:
parazyd
2023-01-10 15:08:58 +01:00
parent 48206a0eaa
commit f642524e81
3 changed files with 178 additions and 26 deletions

View File

@@ -249,8 +249,8 @@ enum DaoSubcmd {
/// List imported DAOs (or info about a specific one)
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
@@ -762,7 +762,17 @@ async fn main() -> Result<()> {
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!(),

View File

@@ -20,29 +20,37 @@ use anyhow::{anyhow, Result};
use darkfi::{rpc::jsonrpc::JsonRequest, wallet::walletdb::QueryType};
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_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 super::Drk;
use crate::DaoParams;
use crate::{dao::Dao, DaoParams};
impl Drk {
/// Import given DAO into the wallet
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
// 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?;
if (self.rpc_client.request(req).await).is_ok() {
return Err(anyhow!("DAO \"{}\" already imported in wallet.", dao_name))
// 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))
};
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);
@@ -81,4 +89,139 @@ impl Drk {
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(())
}
}

View File

@@ -595,21 +595,20 @@ impl Drk {
proposals_tree: &BridgeTree<MerkleNode, MERKLE_DEPTH>,
) -> Result<()> {
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 params = json!([
query,
QueryType::Blob as u8,
serialize(daos_tree),
QueryType::Blob as u8,
serialize(proposals_tree)
]);
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(proposals_tree)]);
let req = JsonRequest::new("wallet.exec_sql", params);
let _ = self.rpc_client.request(req).await?;
Ok(())