1use crate::jsonrpc::client::HTTPClient;
2use std::sync::Arc;
3use std::time::Duration;
4
5mod get;
6mod send;
7
8#[derive(Clone)]
10pub struct Contact {
11 pub jsonrpc_client: Arc<Box<HTTPClient>>,
12 pub timeout: Duration,
13}
14
15impl Contact {
16 pub fn new(url: &str, timeout: Duration) -> Self {
17 let mut url = url;
18 if !url.ends_with('/') {
19 url = url.trim_end_matches('/');
20 }
21 Self {
22 jsonrpc_client: Arc::new(Box::new(HTTPClient::new(&url))),
23 timeout,
24 }
25 }
26}
27
28#[cfg(test)]
29mod tests {
30 use super::*;
31 use crate::jsonrpc::error::JsonRpcError;
32 use actix::Arbiter;
33 use actix::System;
34 use deep_space::address::Address;
35 use deep_space::coin::Coin;
36 use deep_space::private_key::PrivateKey;
37 use rand::Rng;
38
39 #[test]
46 #[ignore]
47 fn test_endpoints() {
48 env_logger::init();
49 let key = PrivateKey::from_phrase("destroy lock crane champion nest hurt chicken leopard field album describe glimpse chimney sort kind peanut worry dilemma anchor dismiss fox there judge arm", "").unwrap();
50 let token_name = "footoken".to_string();
51
52 let res = System::run(move || {
53 let contact = Contact::new(
54 "http://testnet1-rpc.althea.net:1317",
55 Duration::from_secs(30),
56 );
57 Arbiter::spawn(async move {
58 let res = contact.get_syncing_status().await;
59 if res.is_err() {
60 println!("{:?}", res);
61 System::current().stop_with_code(1);
62 }
63
64 let res = test_rpc_calls(contact, key, token_name).await;
65 if res.is_err() {
66 println!("{:?}", res);
67 System::current().stop_with_code(1);
68 }
69
70 System::current().stop();
71 });
72 });
73
74 if let Err(e) = res {
75 panic!(format!("{:?}", e))
76 }
77 }
78
79 pub async fn test_rpc_calls(
80 contact: Contact,
81 key: PrivateKey,
82 test_token_name: String,
83 ) -> Result<(), String> {
84 let fee = Coin {
85 denom: test_token_name.clone(),
86 amount: 1u32.into(),
87 };
88 let address = key
89 .to_public_key()
90 .expect("Failed to convert to pubkey!")
91 .to_address();
92
93 test_basic_calls(&contact, key, test_token_name, fee.clone(), address).await?;
94
95 Ok(())
96 }
97
98 async fn test_basic_calls(
99 contact: &Contact,
100 key: PrivateKey,
101 test_token_name: String,
102 fee: Coin,
103 address: Address,
104 ) -> Result<(), String> {
105 let res = contact.get_latest_block().await;
112 if res.is_err() {
113 return Err(format!("Failed to get latest block {:?}", res));
114 }
115
116 let res = contact.get_account_info(address).await;
117 match res {
118 Ok(_) => {}
119 Err(JsonRpcError::NoToken) => {}
120 Err(e) => return Err(format!("Failed to get account info {:?}", e)),
121 }
122
123 let res = contact.get_balances(address).await;
124 if res.is_err() {
125 return Err(format!("Failed to get balances {:?}", res));
126 }
127
128 let mut rng = rand::thread_rng();
129 let secret: [u8; 32] = rng.gen();
130 let cosmos_key = PrivateKey::from_secret(&secret);
131 let cosmos_address = cosmos_key.to_public_key().unwrap().to_address();
132
133 let res = contact
134 .create_and_send_transaction(
135 Coin {
136 denom: test_token_name.clone(),
137 amount: 5u32.into(),
138 },
139 fee.clone(),
140 cosmos_address,
141 key,
142 None,
143 None,
144 None,
145 )
146 .await;
147 if res.is_err() {
148 return Err(format!("Failed to send tx {:?}", res));
149 }
150
151 let new_balances = contact.get_balances(cosmos_address).await.unwrap();
152 assert!(!new_balances.result.is_empty());
153 info!("new balances are {:?}", new_balances);
154
155 Ok(())
156 }
157}