mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-09 14:48:08 -05:00
drk2: Dao functionality added
This commit is contained in:
@@ -120,16 +120,16 @@ pub fn generate_completions(shell: &str) -> Result<()> {
|
||||
let addresses =
|
||||
Arg::with_name("addresses").long("addresses").help("Print all the addresses in the wallet");
|
||||
|
||||
let default_address = Arg::with_name("default_address")
|
||||
.long("default_address")
|
||||
let default_address = Arg::with_name("default-address")
|
||||
.long("default-address")
|
||||
.takes_value(true)
|
||||
.help("Set the default address in the wallet");
|
||||
|
||||
let secrets =
|
||||
Arg::with_name("secrets").long("secrets").help("Print all the secret keys from the wallet");
|
||||
|
||||
let import_secrets = Arg::with_name("import_secrets")
|
||||
.long("import_secrets")
|
||||
let import_secrets = Arg::with_name("import-secrets")
|
||||
.long("import-secrets")
|
||||
.help("Import secret keys from stdin into the wallet, separated by newlines");
|
||||
|
||||
let tree = Arg::with_name("tree").long("tree").help("Print the Merkle tree in the wallet");
|
||||
@@ -166,15 +166,15 @@ pub fn generate_completions(shell: &str) -> Result<()> {
|
||||
.args(&vec![amount, token, recipient]);
|
||||
|
||||
// Otc
|
||||
let value_pair = Arg::with_name("value_pair")
|
||||
let value_pair = Arg::with_name("value-pair")
|
||||
.short("v")
|
||||
.long("value_pair")
|
||||
.long("value-pair")
|
||||
.takes_value(true)
|
||||
.help("Value pair to send:recv (11.55:99.42)");
|
||||
|
||||
let token_pair = Arg::with_name("token_pair")
|
||||
let token_pair = Arg::with_name("token-pair")
|
||||
.short("t")
|
||||
.long("token_pair")
|
||||
.long("token-pair")
|
||||
.takes_value(true)
|
||||
.help("Token pair to send:recv (f00:b4r)");
|
||||
|
||||
@@ -210,7 +210,88 @@ pub fn generate_completions(shell: &str) -> Result<()> {
|
||||
find coins sent to us and fill our wallet with the necessary metadata.",
|
||||
);
|
||||
|
||||
// TODO: DAO
|
||||
// DAO
|
||||
let proposer_limit = Arg::with_name("proposer-limit")
|
||||
.help("The minimum amount of governance tokens needed to open a proposal for this DAO");
|
||||
|
||||
let quorum = Arg::with_name("quorum")
|
||||
.help("Minimal threshold of participating total tokens needed for a proposal to pass");
|
||||
|
||||
let approval_ratio = Arg::with_name("approval-ratio")
|
||||
.help("The ratio of winning votes/total votes needed for a proposal to pass (2 decimals)");
|
||||
|
||||
let gov_token_id = Arg::with_name("gov-token-id").help("DAO's governance token ID");
|
||||
|
||||
let create = SubCommand::with_name("create").about("Create DAO parameters").args(&vec![
|
||||
proposer_limit,
|
||||
quorum,
|
||||
approval_ratio,
|
||||
gov_token_id,
|
||||
]);
|
||||
|
||||
let view = SubCommand::with_name("view").about("View DAO data from stdin");
|
||||
|
||||
let dao_name = Arg::with_name("dao-name").help("Named identifier for the DAO");
|
||||
|
||||
let import =
|
||||
SubCommand::with_name("import").about("Import DAO data from stdin").args(&vec![dao_name]);
|
||||
|
||||
let dao_alias = Arg::with_name("dao-alias").help("Numeric identifier for the DAO (optional)");
|
||||
|
||||
let list = SubCommand::with_name("list")
|
||||
.about("List imported DAOs (or info about a specific one)")
|
||||
.args(&vec![dao_alias]);
|
||||
|
||||
let dao_alias = Arg::with_name("dao-alias").help("Name or numeric identifier for the DAO");
|
||||
|
||||
let balance = SubCommand::with_name("balance")
|
||||
.about("Show the balance of a DAO")
|
||||
.args(&vec![dao_alias.clone()]);
|
||||
|
||||
let mint = SubCommand::with_name("mint")
|
||||
.about("Mint an imported DAO on-chain")
|
||||
.args(&vec![dao_alias.clone()]);
|
||||
|
||||
let recipient =
|
||||
Arg::with_name("recipient").help("Pubkey to send tokens to with proposal success");
|
||||
|
||||
let amount = Arg::with_name("amount").help("Amount to send from DAO with proposal success");
|
||||
|
||||
let token = Arg::with_name("token").help("Token ID to send from DAO with proposal success");
|
||||
|
||||
let propose = SubCommand::with_name("propose")
|
||||
.about("Create a proposal for a DAO")
|
||||
.args(&vec![dao_alias.clone(), recipient, amount, token]);
|
||||
|
||||
let proposals = SubCommand::with_name("proposals")
|
||||
.about("List DAO proposals")
|
||||
.args(&vec![dao_alias.clone()]);
|
||||
|
||||
let proposal_id = Arg::with_name("proposal-id").help("Numeric identifier for the proposal");
|
||||
|
||||
let proposal = SubCommand::with_name("proposal")
|
||||
.about("View a DAO proposal data")
|
||||
.args(&vec![dao_alias.clone(), proposal_id.clone()]);
|
||||
|
||||
let vote = Arg::with_name("vote").help("Vote (0 for NO, 1 for YES)");
|
||||
|
||||
let vote_weight =
|
||||
Arg::with_name("vote-weight").help("Vote weight (amount of governance tokens)");
|
||||
|
||||
let vote = SubCommand::with_name("vote").about("Vote on a given proposal").args(&vec![
|
||||
dao_alias.clone(),
|
||||
proposal_id.clone(),
|
||||
vote,
|
||||
vote_weight,
|
||||
]);
|
||||
|
||||
let exec = SubCommand::with_name("exec")
|
||||
.about("Execute a DAO proposal")
|
||||
.args(&vec![dao_alias, proposal_id]);
|
||||
|
||||
let dao = SubCommand::with_name("dao").about("DAO functionalities").subcommands(vec![
|
||||
create, view, import, list, balance, mint, propose, proposals, proposal, vote, exec,
|
||||
]);
|
||||
|
||||
// Scan
|
||||
let reset = Arg::with_name("reset")
|
||||
@@ -354,6 +435,7 @@ pub fn generate_completions(shell: &str) -> Result<()> {
|
||||
inspect,
|
||||
broadcast,
|
||||
subscribe,
|
||||
dao,
|
||||
scan,
|
||||
explorer,
|
||||
alias,
|
||||
|
||||
1054
bin/drk2/src/dao.rs
1054
bin/drk2/src/dao.rs
File diff suppressed because it is too large
Load Diff
@@ -35,7 +35,11 @@ use darkfi::{
|
||||
async_daemonize, cli_desc,
|
||||
rpc::{client::RpcClient, jsonrpc::JsonRequest, util::JsonValue},
|
||||
tx::Transaction,
|
||||
util::{parse::encode_base10, path::expand_path},
|
||||
util::{
|
||||
parse::{decode_base10, encode_base10},
|
||||
path::expand_path,
|
||||
},
|
||||
zk::halo2::Field,
|
||||
Result,
|
||||
};
|
||||
use darkfi_money_contract::model::Coin;
|
||||
@@ -71,6 +75,7 @@ use money::BALANCE_BASE10_DECIMALS;
|
||||
|
||||
/// Wallet functionality related to Dao
|
||||
mod dao;
|
||||
use dao::DaoParams;
|
||||
|
||||
/// Wallet functionality related to transactions history
|
||||
mod txs_history;
|
||||
@@ -82,6 +87,8 @@ use walletdb::{WalletDb, WalletPtr};
|
||||
const CONFIG_FILE: &str = "drk_config.toml";
|
||||
const CONFIG_FILE_CONTENTS: &str = include_str!("../drk_config.toml");
|
||||
|
||||
// Dev Note: when adding/modifying args here,
|
||||
// don't forget to update cli_util::generate_completions()
|
||||
#[derive(Clone, Debug, Deserialize, StructOpt, StructOptToml)]
|
||||
#[serde(default)]
|
||||
#[structopt(name = "drk", about = cli_desc!())]
|
||||
@@ -115,6 +122,8 @@ struct Args {
|
||||
verbose: u8,
|
||||
}
|
||||
|
||||
// Dev Note: when adding/modifying commands here,
|
||||
// don't forget to update cli_util::generate_completions()
|
||||
#[derive(Clone, Debug, Deserialize, StructOpt)]
|
||||
enum Subcmd {
|
||||
/// Fun
|
||||
@@ -209,7 +218,13 @@ enum Subcmd {
|
||||
/// find coins sent to us and fill our wallet with the necessary metadata.
|
||||
Subscribe,
|
||||
|
||||
// TODO: DAO
|
||||
/// DAO functionalities
|
||||
Dao {
|
||||
#[structopt(subcommand)]
|
||||
/// Sub command to execute
|
||||
command: DaoSubcmd,
|
||||
},
|
||||
|
||||
/// Scan the blockchain and parse relevant transactions
|
||||
Scan {
|
||||
#[structopt(long)]
|
||||
@@ -270,6 +285,102 @@ enum OtcSubcmd {
|
||||
Sign,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, StructOpt)]
|
||||
enum DaoSubcmd {
|
||||
/// Create DAO parameters
|
||||
Create {
|
||||
/// The minimum amount of governance tokens needed to open a proposal for this DAO
|
||||
proposer_limit: String,
|
||||
/// Minimal threshold of participating total tokens needed for a proposal to pass
|
||||
quorum: String,
|
||||
/// The ratio of winning votes/total votes needed for a proposal to pass (2 decimals)
|
||||
approval_ratio: f64,
|
||||
/// DAO's governance token ID
|
||||
gov_token_id: String,
|
||||
},
|
||||
|
||||
/// View DAO data from stdin
|
||||
View,
|
||||
|
||||
/// Import DAO data from stdin
|
||||
Import {
|
||||
/// Named identifier for the DAO
|
||||
dao_name: String,
|
||||
},
|
||||
|
||||
/// List imported DAOs (or info about a specific one)
|
||||
List {
|
||||
/// Numeric identifier for the DAO (optional)
|
||||
dao_alias: Option<String>,
|
||||
},
|
||||
|
||||
/// Show the balance of a DAO
|
||||
Balance {
|
||||
/// Name or numeric identifier for the DAO
|
||||
dao_alias: String,
|
||||
},
|
||||
|
||||
/// Mint an imported DAO on-chain
|
||||
Mint {
|
||||
/// Name or numeric identifier for the DAO
|
||||
dao_alias: String,
|
||||
},
|
||||
|
||||
/// Create a proposal for a DAO
|
||||
Propose {
|
||||
/// Name or numeric identifier for the DAO
|
||||
dao_alias: String,
|
||||
|
||||
/// Pubkey to send tokens to with proposal success
|
||||
recipient: String,
|
||||
|
||||
/// Amount to send from DAO with proposal success
|
||||
amount: String,
|
||||
|
||||
/// Token ID to send from DAO with proposal success
|
||||
token: String,
|
||||
},
|
||||
|
||||
/// List DAO proposals
|
||||
Proposals {
|
||||
/// Name or numeric identifier for the DAO
|
||||
dao_alias: String,
|
||||
},
|
||||
|
||||
/// View a DAO proposal data
|
||||
Proposal {
|
||||
/// Name or numeric identifier for the DAO
|
||||
dao_alias: String,
|
||||
|
||||
/// Numeric identifier for the proposal
|
||||
proposal_id: u64,
|
||||
},
|
||||
|
||||
/// Vote on a given proposal
|
||||
Vote {
|
||||
/// Name or numeric identifier for the DAO
|
||||
dao_alias: String,
|
||||
|
||||
/// Numeric identifier for the proposal
|
||||
proposal_id: u64,
|
||||
|
||||
/// Vote (0 for NO, 1 for YES)
|
||||
vote: u8,
|
||||
|
||||
/// Vote weight (amount of governance tokens)
|
||||
vote_weight: String,
|
||||
},
|
||||
|
||||
/// Execute a DAO proposal
|
||||
Exec {
|
||||
/// Name or numeric identifier for the DAO
|
||||
dao_alias: String,
|
||||
|
||||
/// Numeric identifier for the proposal
|
||||
proposal_id: u64,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, StructOpt)]
|
||||
enum ExplorerSubcmd {
|
||||
/// Fetch a blockchain transaction by hash
|
||||
@@ -800,6 +911,280 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
Subcmd::Dao { command } => match command {
|
||||
DaoSubcmd::Create { proposer_limit, quorum, approval_ratio, gov_token_id } => {
|
||||
if let Err(e) = f64::from_str(&proposer_limit) {
|
||||
eprintln!("Invalid proposer limit: {e:?}");
|
||||
exit(2);
|
||||
}
|
||||
if let Err(e) = f64::from_str(&quorum) {
|
||||
eprintln!("Invalid quorum: {e:?}");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
let proposer_limit = decode_base10(&proposer_limit, BALANCE_BASE10_DECIMALS, true)?;
|
||||
let quorum = decode_base10(&quorum, BALANCE_BASE10_DECIMALS, true)?;
|
||||
|
||||
if approval_ratio > 1.0 {
|
||||
eprintln!("Error: Approval ratio cannot be >1.0");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
let approval_ratio_base = 100_u64;
|
||||
let approval_ratio_quot = (approval_ratio * approval_ratio_base as f64) as u64;
|
||||
|
||||
let drk = Drk::new(args.wallet_path, args.wallet_pass, args.endpoint, ex).await?;
|
||||
let gov_token_id = match drk.get_token(gov_token_id).await {
|
||||
Ok(g) => g,
|
||||
Err(e) => {
|
||||
eprintln!("Invalid Token ID: {e:?}");
|
||||
exit(2);
|
||||
}
|
||||
};
|
||||
|
||||
let secret_key = SecretKey::random(&mut OsRng);
|
||||
let bulla_blind = pallas::Base::random(&mut OsRng);
|
||||
|
||||
let dao_params = DaoParams {
|
||||
proposer_limit,
|
||||
quorum,
|
||||
approval_ratio_base,
|
||||
approval_ratio_quot,
|
||||
gov_token_id,
|
||||
secret_key,
|
||||
bulla_blind,
|
||||
};
|
||||
|
||||
let encoded = bs58::encode(&serialize(&dao_params)).into_string();
|
||||
eprintln!("{encoded}");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
DaoSubcmd::View => {
|
||||
let mut buf = String::new();
|
||||
stdin().read_to_string(&mut buf)?;
|
||||
let bytes = bs58::decode(&buf.trim()).into_vec()?;
|
||||
let dao_params: DaoParams = deserialize(&bytes)?;
|
||||
eprintln!("{dao_params}");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
DaoSubcmd::Import { dao_name } => {
|
||||
let mut buf = String::new();
|
||||
stdin().read_to_string(&mut buf)?;
|
||||
let bytes = bs58::decode(&buf.trim()).into_vec()?;
|
||||
let dao_params: DaoParams = deserialize(&bytes)?;
|
||||
|
||||
let drk = Drk::new(args.wallet_path, args.wallet_pass, args.endpoint, ex).await?;
|
||||
|
||||
if let Err(e) = drk.import_dao(dao_name, dao_params).await {
|
||||
eprintln!("Failed to import DAO: {e:?}");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
DaoSubcmd::List { dao_alias } => {
|
||||
let drk = Drk::new(args.wallet_path, args.wallet_pass, args.endpoint, ex).await?;
|
||||
// We cannot use .map() since get_dao_id() uses ?
|
||||
let dao_id = match dao_alias {
|
||||
Some(alias) => Some(drk.get_dao_id(&alias).await?),
|
||||
None => None,
|
||||
};
|
||||
|
||||
if let Err(e) = drk.dao_list(dao_id).await {
|
||||
eprintln!("Failed to list DAO: {e:?}");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
DaoSubcmd::Balance { dao_alias } => {
|
||||
let drk = Drk::new(args.wallet_path, args.wallet_pass, args.endpoint, ex).await?;
|
||||
let dao_id = drk.get_dao_id(&dao_alias).await?;
|
||||
|
||||
let balmap = match drk.dao_balance(dao_id).await {
|
||||
Ok(b) => b,
|
||||
Err(e) => {
|
||||
eprintln!("Failed to fetch DAO balance: {e:?}");
|
||||
exit(2);
|
||||
}
|
||||
};
|
||||
|
||||
let aliases_map = match drk.get_aliases_mapped_by_token().await {
|
||||
Ok(a) => a,
|
||||
Err(e) => {
|
||||
eprintln!("Failed to fetch wallet aliases: {e:?}");
|
||||
exit(2);
|
||||
}
|
||||
};
|
||||
|
||||
// Create a prettytable with the new data:
|
||||
let mut table = Table::new();
|
||||
table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
|
||||
table.set_titles(row!["Token ID", "Aliases", "Balance"]);
|
||||
for (token_id, balance) in balmap.iter() {
|
||||
let aliases = match aliases_map.get(token_id) {
|
||||
Some(a) => a,
|
||||
None => "-",
|
||||
};
|
||||
|
||||
table.add_row(row![
|
||||
token_id,
|
||||
aliases,
|
||||
encode_base10(*balance, BALANCE_BASE10_DECIMALS)
|
||||
]);
|
||||
}
|
||||
|
||||
if table.is_empty() {
|
||||
eprintln!("No unspent balances found");
|
||||
} else {
|
||||
eprintln!("{table}");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
DaoSubcmd::Mint { dao_alias } => {
|
||||
let drk = Drk::new(args.wallet_path, args.wallet_pass, args.endpoint, ex).await?;
|
||||
let dao_id = drk.get_dao_id(&dao_alias).await?;
|
||||
|
||||
let tx = match drk.dao_mint(dao_id).await {
|
||||
Ok(tx) => tx,
|
||||
Err(e) => {
|
||||
eprintln!("Failed to mint DAO: {e:?}");
|
||||
exit(2);
|
||||
}
|
||||
};
|
||||
eprintln!("{}", bs58::encode(&serialize(&tx)).into_string());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
DaoSubcmd::Propose { dao_alias, recipient, amount, token } => {
|
||||
if let Err(e) = f64::from_str(&amount) {
|
||||
eprintln!("Invalid amount: {e:?}");
|
||||
exit(2);
|
||||
}
|
||||
let amount = decode_base10(&amount, BALANCE_BASE10_DECIMALS, true)?;
|
||||
let rcpt = match PublicKey::from_str(&recipient) {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
eprintln!("Invalid recipient: {e:?}");
|
||||
exit(2);
|
||||
}
|
||||
};
|
||||
|
||||
let drk = Drk::new(args.wallet_path, args.wallet_pass, args.endpoint, ex).await?;
|
||||
let dao_id = drk.get_dao_id(&dao_alias).await?;
|
||||
let token_id = match drk.get_token(token).await {
|
||||
Ok(t) => t,
|
||||
Err(e) => {
|
||||
eprintln!("Invalid token alias: {e:?}");
|
||||
exit(2);
|
||||
}
|
||||
};
|
||||
|
||||
let tx = match drk.dao_propose(dao_id, rcpt, amount, token_id).await {
|
||||
Ok(tx) => tx,
|
||||
Err(e) => {
|
||||
eprintln!("Failed to create DAO proposal: {e:?}");
|
||||
exit(2);
|
||||
}
|
||||
};
|
||||
eprintln!("{}", bs58::encode(&serialize(&tx)).into_string());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
DaoSubcmd::Proposals { dao_alias } => {
|
||||
let drk = Drk::new(args.wallet_path, args.wallet_pass, args.endpoint, ex).await?;
|
||||
let dao_id = drk.get_dao_id(&dao_alias).await?;
|
||||
|
||||
let proposals = drk.get_dao_proposals(dao_id).await?;
|
||||
|
||||
for proposal in proposals {
|
||||
eprintln!("[{}] {:?}", proposal.id, proposal.bulla());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
DaoSubcmd::Proposal { dao_alias, proposal_id } => {
|
||||
let drk = Drk::new(args.wallet_path, args.wallet_pass, args.endpoint, ex).await?;
|
||||
let dao_id = drk.get_dao_id(&dao_alias).await?;
|
||||
|
||||
let proposals = drk.get_dao_proposals(dao_id).await?;
|
||||
let Some(proposal) = proposals.iter().find(|x| x.id == proposal_id) else {
|
||||
eprintln!("No such DAO proposal found");
|
||||
exit(2);
|
||||
};
|
||||
|
||||
eprintln!("{proposal}");
|
||||
|
||||
let votes = drk.get_dao_proposal_votes(proposal_id).await?;
|
||||
eprintln!("votes:");
|
||||
for vote in votes {
|
||||
let option = if vote.vote_option { "yes" } else { "no " };
|
||||
eprintln!(" {option} {}", vote.all_vote_value);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
DaoSubcmd::Vote { dao_alias, proposal_id, vote, vote_weight } => {
|
||||
let drk = Drk::new(args.wallet_path, args.wallet_pass, args.endpoint, ex).await?;
|
||||
let dao_id = drk.get_dao_id(&dao_alias).await?;
|
||||
|
||||
if let Err(e) = f64::from_str(&vote_weight) {
|
||||
eprintln!("Invalid vote weight: {e:?}");
|
||||
exit(2);
|
||||
}
|
||||
let weight = decode_base10(&vote_weight, BALANCE_BASE10_DECIMALS, true)?;
|
||||
|
||||
if vote > 1 {
|
||||
eprintln!("Vote can be either 0 (NO) or 1 (YES)");
|
||||
exit(2);
|
||||
}
|
||||
let vote = vote != 0;
|
||||
|
||||
let tx = match drk.dao_vote(dao_id, proposal_id, vote, weight).await {
|
||||
Ok(tx) => tx,
|
||||
Err(e) => {
|
||||
eprintln!("Failed to create DAO Vote transaction: {e:?}");
|
||||
exit(2);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Write our_vote in the proposal sql.
|
||||
|
||||
eprintln!("{}", bs58::encode(&serialize(&tx)).into_string());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
DaoSubcmd::Exec { dao_alias, proposal_id } => {
|
||||
let drk = Drk::new(args.wallet_path, args.wallet_pass, args.endpoint, ex).await?;
|
||||
let dao_id = drk.get_dao_id(&dao_alias).await?;
|
||||
let dao = drk.get_dao_by_id(dao_id).await?;
|
||||
let proposal = drk.get_dao_proposal_by_id(proposal_id).await?;
|
||||
assert!(proposal.dao_bulla == dao.bulla());
|
||||
|
||||
let tx = match drk.dao_exec(dao, proposal).await {
|
||||
Ok(tx) => tx,
|
||||
Err(e) => {
|
||||
eprintln!("Failed to execute DAO proposal: {e:?}");
|
||||
exit(2);
|
||||
}
|
||||
};
|
||||
eprintln!("{}", bs58::encode(&serialize(&tx)).into_string());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
},
|
||||
|
||||
Subcmd::Inspect => {
|
||||
let mut buf = String::new();
|
||||
stdin().read_to_string(&mut buf)?;
|
||||
@@ -863,15 +1248,13 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
|
||||
if list {
|
||||
eprintln!("List requested.");
|
||||
// TODO: implement
|
||||
|
||||
return Ok(())
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
if let Some(c) = checkpoint {
|
||||
eprintln!("Checkpoint requested: {c}");
|
||||
// TODO: implement
|
||||
|
||||
return Ok(())
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
if let Err(e) = drk.scan_blocks(false).await {
|
||||
|
||||
Reference in New Issue
Block a user