| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- use std::sync::Arc;
- use async_std::sync::Mutex;
- use async_trait::async_trait;
- use log::debug;
- use pasta_curves::{group::ff::PrimeField, pallas};
- use std::str::FromStr;
- use serde_json::{json, Value};
- use darkfi::{
- crypto::keypair::PublicKey,
- rpc::{
- jsonrpc::{ErrorCode::*, JsonError, JsonRequest, JsonResponse, JsonResult},
- server::RequestHandler,
- },
- };
- use crate::{
- util::{parse_b58, GDRK_ID, XDRK_ID},
- Client,
- };
- pub struct JsonRpcInterface {
- client: Arc<Mutex<Client>>,
- }
- #[async_trait]
- impl RequestHandler for JsonRpcInterface {
- async fn handle_request(&self, req: JsonRequest) -> JsonResult {
- if !req.params.is_array() {
- return JsonError::new(InvalidParams, None, req.id).into()
- }
- let params = req.params.as_array().unwrap();
- debug!(target: "RPC", "--> {}", serde_json::to_string(&req).unwrap());
- match req.method.as_str() {
- Some("create") => return self.create_dao(req.id, params).await,
- Some("get_dao_addr") => return self.get_dao_addr(req.id, params).await,
- Some("get_votes") => return self.get_votes(req.id, params).await,
- Some("get_proposals") => return self.get_proposals(req.id, params).await,
- Some("dao_balance") => return self.dao_balance(req.id, params).await,
- Some("dao_bulla") => return self.dao_bulla(req.id, params).await,
- Some("user_balance") => return self.user_balance(req.id, params).await,
- Some("mint") => return self.mint_treasury(req.id, params).await,
- Some("keygen") => return self.keygen(req.id, params).await,
- Some("airdrop") => return self.airdrop_tokens(req.id, params).await,
- Some("propose") => return self.create_proposal(req.id, params).await,
- Some("vote") => return self.vote(req.id, params).await,
- Some("exec") => return self.execute(req.id, params).await,
- Some(_) | None => return JsonError::new(MethodNotFound, None, req.id).into(),
- }
- }
- }
- impl JsonRpcInterface {
- pub fn new(client: Client) -> Self {
- let client = Arc::new(Mutex::new(client));
- Self { client }
- }
- // --> {"method": "create", "params": []}
- // <-- {"result": "creating dao..."}
- async fn create_dao(&self, id: Value, params: &[Value]) -> JsonResult {
- let dao_proposer_limit = params[0].as_u64().unwrap();
- let dao_quorum = params[1].as_u64().unwrap();
- let dao_approval_ratio_quot = params[2].as_u64().unwrap();
- let dao_approval_ratio_base = params[3].as_u64().unwrap();
- let mut client = self.client.lock().await;
- let dao_bulla = client
- .create_dao(
- dao_proposer_limit,
- dao_quorum,
- dao_approval_ratio_quot,
- dao_approval_ratio_base,
- *GDRK_ID,
- )
- .unwrap();
- let bulla: String = bs58::encode(dao_bulla.to_repr()).into_string();
- JsonResponse::new(json!(bulla), id).into()
- }
- // --> {"method": "get_dao_addr", "params": []}
- // <-- {"result": "getting dao public addr..."}
- async fn get_dao_addr(&self, id: Value, params: &[Value]) -> JsonResult {
- let mut client = self.client.lock().await;
- let pubkey = client.dao_wallet.get_public_key();
- let addr: String = bs58::encode(pubkey.to_bytes()).into_string();
- JsonResponse::new(json!(addr), id).into()
- }
- // --> {"method": "get_dao_addr", "params": []}
- // <-- {"result": "getting dao public addr..."}
- async fn get_votes(&self, id: Value, params: &[Value]) -> JsonResult {
- let mut client = self.client.lock().await;
- let vote_notes = client.dao_wallet.get_votes();
- let mut vote_data = vec![];
- for note in vote_notes {
- let vote_option = note.vote.vote_option;
- let vote_value = note.vote_value;
- vote_data.push((vote_option, vote_value));
- }
- JsonResponse::new(json!(vote_data), id).into()
- }
- // --> {"method": "get_dao_addr", "params": []}
- // <-- {"result": "getting dao public addr..."}
- async fn get_proposals(&self, id: Value, params: &[Value]) -> JsonResult {
- let mut client = self.client.lock().await;
- let proposals = client.dao_wallet.get_proposals();
- let mut proposal_data = vec![];
- for proposal in proposals {
- let dest = proposal.dest;
- let amount = proposal.amount;
- let token_id = proposal.token_id;
- let token_id: String = bs58::encode(token_id.to_repr()).into_string();
- proposal_data.push((dest, amount, token_id));
- }
- JsonResponse::new(json!(proposal_data), id).into()
- }
- async fn dao_balance(&self, id: Value, params: &[Value]) -> JsonResult {
- let mut client = self.client.lock().await;
- let balance = client.dao_wallet.balances().unwrap();
- JsonResponse::new(json!(balance), id).into()
- }
- async fn dao_bulla(&self, id: Value, params: &[Value]) -> JsonResult {
- let mut client = self.client.lock().await;
- let dao_bullas = client.dao_wallet.bullas.clone();
- let mut bulla_vec = Vec::new();
- for bulla in dao_bullas {
- let dao_bulla: String = bs58::encode(bulla.0.to_repr()).into_string();
- bulla_vec.push(dao_bulla);
- }
- JsonResponse::new(json!(bulla_vec), id).into()
- }
- async fn user_balance(&self, id: Value, params: &[Value]) -> JsonResult {
- let mut client = self.client.lock().await;
- let nym = params[0].as_str().unwrap().to_string();
- let wallet = client.money_wallets.get(&nym).unwrap();
- let balance = wallet.balances().unwrap();
- JsonResponse::new(json!(balance), id).into()
- }
- // --> {"method": "mint_treasury", "params": []}
- // <-- {"result": "minting treasury..."}
- async fn mint_treasury(&self, id: Value, params: &[Value]) -> JsonResult {
- let mut client = self.client.lock().await;
- let token_supply = params[0].as_u64().unwrap();
- let addr = params[1].as_str().unwrap();
- let dao_addr = PublicKey::from_str(addr).unwrap();
- client.mint_treasury(*XDRK_ID, token_supply, dao_addr).unwrap();
- JsonResponse::new(json!("DAO treasury minted successfully."), id).into()
- }
- // Create a new wallet for governance tokens.
- async fn keygen(&self, id: Value, params: &[Value]) -> JsonResult {
- let mut client = self.client.lock().await;
- let nym = params[0].as_str().unwrap().to_string();
- client.new_money_wallet(nym.clone());
- let wallet = client.money_wallets.get(&nym).unwrap();
- let pubkey = wallet.get_public_key();
- let addr: String = bs58::encode(pubkey.to_bytes()).into_string();
- JsonResponse::new(json!(addr), id).into()
- }
- // --> {"method": "airdrop_tokens", "params": []}
- // <-- {"result": "airdropping tokens..."}
- async fn airdrop_tokens(&self, id: Value, params: &[Value]) -> JsonResult {
- let mut client = self.client.lock().await;
- let zk_bins = &client.zk_bins;
- let nym = params[0].as_str().unwrap().to_string();
- let value = params[1].as_u64().unwrap();
- client.airdrop_user(value, *GDRK_ID, nym.clone()).unwrap();
- JsonResponse::new(json!("Tokens airdropped successfully."), id).into()
- }
- // --> {"method": "create_proposal", "params": []}
- // <-- {"result": "creating proposal..."}
- async fn create_proposal(&self, id: Value, params: &[Value]) -> JsonResult {
- let mut client = self.client.lock().await;
- let sender = params[0].as_str().unwrap().to_string();
- let recipient = params[1].as_str().unwrap();
- let amount = params[2].as_u64().unwrap();
- let recv_addr = PublicKey::from_str(recipient).unwrap();
- let proposal_bulla = client.propose(recv_addr, *XDRK_ID, amount, sender).unwrap();
- let bulla: String = bs58::encode(proposal_bulla.to_repr()).into_string();
- JsonResponse::new(json!(bulla), id).into()
- }
- // --> {"method": "vote", "params": []}
- // <-- {"result": "voting..."}
- async fn vote(&self, id: Value, params: &[Value]) -> JsonResult {
- let mut client = self.client.lock().await;
- let nym = params[0].as_str().unwrap().to_string();
- let vote_str = params[1].as_str().unwrap();
- // This would be cleaner as a match statement,
- // but we need to sort out error handling first.
- let mut vote_bool = true;
- if vote_str == "yes" {}
- if vote_str == "no" {
- vote_bool = false
- }
- client.cast_vote(nym, vote_bool).unwrap();
- JsonResponse::new(json!("Vote cast successfully."), id).into()
- }
- // --> {"method": "execute", "params": []}
- // <-- {"result": "executing..."}
- async fn execute(&self, id: Value, params: &[Value]) -> JsonResult {
- let mut client = self.client.lock().await;
- let bulla_str = params[0].as_str().unwrap();
- let bulla: pallas::Base = parse_b58(bulla_str).unwrap();
- client.exec_proposal(bulla);
- JsonResponse::new(json!("Proposal executed successfully."), id).into()
- }
- }
|