rpc_tx.rs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. use std::str::FromStr;
  2. use log::{error, warn};
  3. use serde_json::{json, Value};
  4. use darkfi::{
  5. crypto::{address::Address, keypair::PublicKey, token_id::generate_id},
  6. rpc::jsonrpc::{
  7. ErrorCode::{InternalError, InvalidParams},
  8. JsonError, JsonResponse, JsonResult,
  9. },
  10. util::{decode_base10, serial::serialize, NetworkName},
  11. };
  12. use super::Darkfid;
  13. use crate::{server_error, RpcError};
  14. impl Darkfid {
  15. // RPCAPI:
  16. // Transfer a given amount of some token to the given address.
  17. // Returns a transaction ID upon success.
  18. // --> {"jsonrpc": "2.0", "method": "tx.transfer", "params": ["darkfi" "gdrk", "1DarkFi...", 12.0], "id": 1}
  19. // <-- {"jsonrpc": "2.0", "result": "txID...", "id": 1}
  20. pub async fn transfer(&self, id: Value, params: &[Value]) -> JsonResult {
  21. if params.len() != 4 ||
  22. !params[0].is_string() ||
  23. !params[1].is_string() ||
  24. !params[2].is_string() ||
  25. !params[3].is_f64()
  26. {
  27. return JsonError::new(InvalidParams, None, id).into()
  28. }
  29. let network = params[0].as_str().unwrap();
  30. let token = params[1].as_str().unwrap();
  31. let address = params[2].as_str().unwrap();
  32. let amount = params[3].as_f64().unwrap();
  33. if !(*self.synced.lock().await) {
  34. error!("transfer(): Blockchain is not yet synced");
  35. return server_error(RpcError::NotYetSynced, id)
  36. }
  37. let address = match Address::from_str(address) {
  38. Ok(v) => v,
  39. Err(e) => {
  40. error!("transfer(): Failed parsing address from string: {}", e);
  41. return server_error(RpcError::InvalidAddressParam, id)
  42. }
  43. };
  44. let pubkey = match PublicKey::try_from(address) {
  45. Ok(v) => v,
  46. Err(e) => {
  47. error!("transfer(): Failed parsing PublicKey from Address: {}", e);
  48. return server_error(RpcError::ParseError, id)
  49. }
  50. };
  51. let amount = amount.to_string();
  52. let amount = match decode_base10(&amount, 8, true) {
  53. Ok(v) => v,
  54. Err(e) => {
  55. error!("transfer(): Failed parsing amount from string: {}", e);
  56. return server_error(RpcError::InvalidAmountParam, id)
  57. }
  58. };
  59. let amount: u64 = match amount.try_into() {
  60. Ok(v) => v,
  61. Err(e) => {
  62. error!("transfer(): Failed converting biguint to u64: {}", e);
  63. return JsonError::new(InternalError, None, id).into()
  64. }
  65. };
  66. let network = match NetworkName::from_str(network) {
  67. Ok(v) => v,
  68. Err(e) => {
  69. error!("transfer(): Failed parsing NetworkName: {}", e);
  70. return server_error(RpcError::NetworkNameError, id)
  71. }
  72. };
  73. let token_id =
  74. if let Some(tok) = self.client.tokenlist.by_net[&network].get(token.to_uppercase()) {
  75. tok.drk_address
  76. } else {
  77. match generate_id(&network, token) {
  78. Ok(v) => v,
  79. Err(e) => {
  80. error!("transfer(): Failed generate_id(): {}", e);
  81. return JsonError::new(InternalError, None, id).into()
  82. }
  83. }
  84. };
  85. let tx = match self
  86. .client
  87. .build_transaction(
  88. pubkey,
  89. amount,
  90. token_id,
  91. false,
  92. self.validator_state.read().await.state_machine.clone(),
  93. )
  94. .await
  95. {
  96. Ok(v) => v,
  97. Err(e) => {
  98. error!("transfer(): Failed building transaction: {}", e);
  99. return server_error(RpcError::TxBuildFail, id)
  100. }
  101. };
  102. if let Some(sync_p2p) = &self.sync_p2p {
  103. match sync_p2p.broadcast(tx.clone()).await {
  104. Ok(()) => {}
  105. Err(e) => {
  106. error!("transfer(): Failed broadcasting transaction: {}", e);
  107. return server_error(RpcError::TxBroadcastFail, id)
  108. }
  109. }
  110. } else {
  111. warn!("No sync P2P network, not broadcasting transaction.");
  112. }
  113. let tx_hash = blake3::hash(&serialize(&tx)).to_hex().as_str().to_string();
  114. JsonResponse::new(json!(tx_hash), id).into()
  115. }
  116. }