rpc.rs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. use std::sync::Arc;
  2. use async_std::sync::Mutex;
  3. use async_trait::async_trait;
  4. use log::debug;
  5. use pasta_curves::{group::ff::PrimeField, pallas};
  6. use std::str::FromStr;
  7. use serde_json::{json, Value};
  8. use darkfi::{
  9. crypto::keypair::PublicKey,
  10. rpc::{
  11. jsonrpc::{ErrorCode::*, JsonError, JsonRequest, JsonResponse, JsonResult},
  12. server::RequestHandler,
  13. },
  14. };
  15. use crate::{
  16. util::{parse_b58, GDRK_ID, XDRK_ID},
  17. Client,
  18. };
  19. pub struct JsonRpcInterface {
  20. client: Arc<Mutex<Client>>,
  21. }
  22. #[async_trait]
  23. impl RequestHandler for JsonRpcInterface {
  24. async fn handle_request(&self, req: JsonRequest) -> JsonResult {
  25. if !req.params.is_array() {
  26. return JsonError::new(InvalidParams, None, req.id).into()
  27. }
  28. let params = req.params.as_array().unwrap();
  29. debug!(target: "RPC", "--> {}", serde_json::to_string(&req).unwrap());
  30. match req.method.as_str() {
  31. Some("create") => return self.create_dao(req.id, params).await,
  32. Some("get_dao_addr") => return self.get_dao_addr(req.id, params).await,
  33. Some("get_votes") => return self.get_votes(req.id, params).await,
  34. Some("get_proposals") => return self.get_proposals(req.id, params).await,
  35. Some("dao_balance") => return self.dao_balance(req.id, params).await,
  36. Some("dao_bulla") => return self.dao_bulla(req.id, params).await,
  37. Some("user_balance") => return self.user_balance(req.id, params).await,
  38. Some("mint") => return self.mint_treasury(req.id, params).await,
  39. Some("keygen") => return self.keygen(req.id, params).await,
  40. Some("airdrop") => return self.airdrop_tokens(req.id, params).await,
  41. Some("propose") => return self.create_proposal(req.id, params).await,
  42. Some("vote") => return self.vote(req.id, params).await,
  43. Some("exec") => return self.execute(req.id, params).await,
  44. Some(_) | None => return JsonError::new(MethodNotFound, None, req.id).into(),
  45. }
  46. }
  47. }
  48. impl JsonRpcInterface {
  49. pub fn new(client: Client) -> Self {
  50. let client = Arc::new(Mutex::new(client));
  51. Self { client }
  52. }
  53. // --> {"method": "create", "params": []}
  54. // <-- {"result": "creating dao..."}
  55. async fn create_dao(&self, id: Value, params: &[Value]) -> JsonResult {
  56. let dao_proposer_limit = params[0].as_u64().unwrap();
  57. let dao_quorum = params[1].as_u64().unwrap();
  58. let dao_approval_ratio_quot = params[2].as_u64().unwrap();
  59. let dao_approval_ratio_base = params[3].as_u64().unwrap();
  60. let mut client = self.client.lock().await;
  61. let dao_bulla = client
  62. .create_dao(
  63. dao_proposer_limit,
  64. dao_quorum,
  65. dao_approval_ratio_quot,
  66. dao_approval_ratio_base,
  67. *GDRK_ID,
  68. )
  69. .unwrap();
  70. let bulla: String = bs58::encode(dao_bulla.to_repr()).into_string();
  71. JsonResponse::new(json!(bulla), id).into()
  72. }
  73. // --> {"method": "get_dao_addr", "params": []}
  74. // <-- {"result": "getting dao public addr..."}
  75. async fn get_dao_addr(&self, id: Value, params: &[Value]) -> JsonResult {
  76. let mut client = self.client.lock().await;
  77. let pubkey = client.dao_wallet.get_public_key();
  78. let addr: String = bs58::encode(pubkey.to_bytes()).into_string();
  79. JsonResponse::new(json!(addr), id).into()
  80. }
  81. // --> {"method": "get_dao_addr", "params": []}
  82. // <-- {"result": "getting dao public addr..."}
  83. async fn get_votes(&self, id: Value, params: &[Value]) -> JsonResult {
  84. let mut client = self.client.lock().await;
  85. let vote_notes = client.dao_wallet.get_votes();
  86. let mut vote_data = vec![];
  87. for note in vote_notes {
  88. let vote_option = note.vote.vote_option;
  89. let vote_value = note.vote_value;
  90. vote_data.push((vote_option, vote_value));
  91. }
  92. JsonResponse::new(json!(vote_data), id).into()
  93. }
  94. // --> {"method": "get_dao_addr", "params": []}
  95. // <-- {"result": "getting dao public addr..."}
  96. async fn get_proposals(&self, id: Value, params: &[Value]) -> JsonResult {
  97. let mut client = self.client.lock().await;
  98. let proposals = client.dao_wallet.get_proposals();
  99. let mut proposal_data = vec![];
  100. for proposal in proposals {
  101. let dest = proposal.dest;
  102. let amount = proposal.amount;
  103. let token_id = proposal.token_id;
  104. let token_id: String = bs58::encode(token_id.to_repr()).into_string();
  105. proposal_data.push((dest, amount, token_id));
  106. }
  107. JsonResponse::new(json!(proposal_data), id).into()
  108. }
  109. async fn dao_balance(&self, id: Value, params: &[Value]) -> JsonResult {
  110. let mut client = self.client.lock().await;
  111. let balance = client.dao_wallet.balances().unwrap();
  112. JsonResponse::new(json!(balance), id).into()
  113. }
  114. async fn dao_bulla(&self, id: Value, params: &[Value]) -> JsonResult {
  115. let mut client = self.client.lock().await;
  116. let dao_bullas = client.dao_wallet.bullas.clone();
  117. let mut bulla_vec = Vec::new();
  118. for bulla in dao_bullas {
  119. let dao_bulla: String = bs58::encode(bulla.0.to_repr()).into_string();
  120. bulla_vec.push(dao_bulla);
  121. }
  122. JsonResponse::new(json!(bulla_vec), id).into()
  123. }
  124. async fn user_balance(&self, id: Value, params: &[Value]) -> JsonResult {
  125. let mut client = self.client.lock().await;
  126. let nym = params[0].as_str().unwrap().to_string();
  127. let wallet = client.money_wallets.get(&nym).unwrap();
  128. let balance = wallet.balances().unwrap();
  129. JsonResponse::new(json!(balance), id).into()
  130. }
  131. // --> {"method": "mint_treasury", "params": []}
  132. // <-- {"result": "minting treasury..."}
  133. async fn mint_treasury(&self, id: Value, params: &[Value]) -> JsonResult {
  134. let mut client = self.client.lock().await;
  135. let token_supply = params[0].as_u64().unwrap();
  136. let addr = params[1].as_str().unwrap();
  137. let dao_addr = PublicKey::from_str(addr).unwrap();
  138. client.mint_treasury(*XDRK_ID, token_supply, dao_addr).unwrap();
  139. JsonResponse::new(json!("DAO treasury minted successfully."), id).into()
  140. }
  141. // Create a new wallet for governance tokens.
  142. async fn keygen(&self, id: Value, params: &[Value]) -> JsonResult {
  143. let mut client = self.client.lock().await;
  144. let nym = params[0].as_str().unwrap().to_string();
  145. client.new_money_wallet(nym.clone());
  146. let wallet = client.money_wallets.get(&nym).unwrap();
  147. let pubkey = wallet.get_public_key();
  148. let addr: String = bs58::encode(pubkey.to_bytes()).into_string();
  149. JsonResponse::new(json!(addr), id).into()
  150. }
  151. // --> {"method": "airdrop_tokens", "params": []}
  152. // <-- {"result": "airdropping tokens..."}
  153. async fn airdrop_tokens(&self, id: Value, params: &[Value]) -> JsonResult {
  154. let mut client = self.client.lock().await;
  155. let zk_bins = &client.zk_bins;
  156. let nym = params[0].as_str().unwrap().to_string();
  157. let value = params[1].as_u64().unwrap();
  158. client.airdrop_user(value, *GDRK_ID, nym.clone()).unwrap();
  159. JsonResponse::new(json!("Tokens airdropped successfully."), id).into()
  160. }
  161. // --> {"method": "create_proposal", "params": []}
  162. // <-- {"result": "creating proposal..."}
  163. async fn create_proposal(&self, id: Value, params: &[Value]) -> JsonResult {
  164. let mut client = self.client.lock().await;
  165. let sender = params[0].as_str().unwrap().to_string();
  166. let recipient = params[1].as_str().unwrap();
  167. let amount = params[2].as_u64().unwrap();
  168. let recv_addr = PublicKey::from_str(recipient).unwrap();
  169. let proposal_bulla = client.propose(recv_addr, *XDRK_ID, amount, sender).unwrap();
  170. let bulla: String = bs58::encode(proposal_bulla.to_repr()).into_string();
  171. JsonResponse::new(json!(bulla), id).into()
  172. }
  173. // --> {"method": "vote", "params": []}
  174. // <-- {"result": "voting..."}
  175. async fn vote(&self, id: Value, params: &[Value]) -> JsonResult {
  176. let mut client = self.client.lock().await;
  177. let nym = params[0].as_str().unwrap().to_string();
  178. let vote_str = params[1].as_str().unwrap();
  179. // This would be cleaner as a match statement,
  180. // but we need to sort out error handling first.
  181. let mut vote_bool = true;
  182. if vote_str == "yes" {}
  183. if vote_str == "no" {
  184. vote_bool = false
  185. }
  186. client.cast_vote(nym, vote_bool).unwrap();
  187. JsonResponse::new(json!("Vote cast successfully."), id).into()
  188. }
  189. // --> {"method": "execute", "params": []}
  190. // <-- {"result": "executing..."}
  191. async fn execute(&self, id: Value, params: &[Value]) -> JsonResult {
  192. let mut client = self.client.lock().await;
  193. let bulla_str = params[0].as_str().unwrap();
  194. let bulla: pallas::Base = parse_b58(bulla_str).unwrap();
  195. client.exec_proposal(bulla);
  196. JsonResponse::new(json!("Proposal executed successfully."), id).into()
  197. }
  198. }